Bash-4.3 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 passed 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_pushed_input_available ())
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 (RL_ISSTATE (RL_STATE_MACRODEF))
912     _rl_add_macro_char (c);
913
914 #if defined (HANDLE_SIGNALS)
915   if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
916     _rl_restore_tty_signals ();
917 #endif
918
919   return (_rl_insert_char (count, c));  
920 }
921
922 #if defined (READLINE_CALLBACKS)
923 static int
924 _rl_insert_next_callback (data)
925      _rl_callback_generic_arg *data;
926 {
927   int count;
928
929   count = data->count;
930
931   /* Deregister function, let rl_callback_read_char deallocate data */
932   _rl_callback_func = 0;
933   _rl_want_redisplay = 1;
934  
935   return _rl_insert_next (count);
936 }
937 #endif
938   
939 int
940 rl_quoted_insert (count, key)
941      int count, key;
942 {
943   /* Let's see...should the callback interface futz with signal handling? */
944 #if defined (HANDLE_SIGNALS)
945   if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
946     _rl_disable_tty_signals ();
947 #endif
948
949 #if defined (READLINE_CALLBACKS)
950   if (RL_ISSTATE (RL_STATE_CALLBACK))
951     {
952       _rl_callback_data = _rl_callback_data_alloc (count);
953       _rl_callback_func = _rl_insert_next_callback;
954       return (0);
955     }
956 #endif
957       
958   return _rl_insert_next (count);
959 }
960
961 /* Insert a tab character. */
962 int
963 rl_tab_insert (count, key)
964      int count, key;
965 {
966   return (_rl_insert_char (count, '\t'));
967 }
968
969 /* What to do when a NEWLINE is pressed.  We accept the whole line.
970    KEY is the key that invoked this command.  I guess it could have
971    meaning in the future. */
972 int
973 rl_newline (count, key)
974      int count, key;
975 {
976   rl_done = 1;
977
978   if (_rl_history_preserve_point)
979     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
980
981   RL_SETSTATE(RL_STATE_DONE);
982
983 #if defined (VI_MODE)
984   if (rl_editing_mode == vi_mode)
985     {
986       _rl_vi_done_inserting ();
987       if (_rl_vi_textmod_command (_rl_vi_last_command) == 0)    /* XXX */
988         _rl_vi_reset_last ();
989     }
990 #endif /* VI_MODE */
991
992   /* If we've been asked to erase empty lines, suppress the final update,
993      since _rl_update_final calls rl_crlf(). */
994   if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
995     return 0;
996
997   if (_rl_echoing_p)
998     _rl_update_final ();
999   return 0;
1000 }
1001
1002 /* What to do for some uppercase characters, like meta characters,
1003    and some characters appearing in emacs_ctlx_keymap.  This function
1004    is just a stub, you bind keys to it and the code in _rl_dispatch ()
1005    is special cased. */
1006 int
1007 rl_do_lowercase_version (ignore1, ignore2)
1008      int ignore1, ignore2;
1009 {
1010   return 0;
1011 }
1012
1013 /* This is different from what vi does, so the code's not shared.  Emacs
1014    rubout in overwrite mode has one oddity:  it replaces a control
1015    character that's displayed as two characters (^X) with two spaces. */
1016 int
1017 _rl_overwrite_rubout (count, key)
1018      int count, key;
1019 {
1020   int opoint;
1021   int i, l;
1022
1023   if (rl_point == 0)
1024     {
1025       rl_ding ();
1026       return 1;
1027     }
1028
1029   opoint = rl_point;
1030
1031   /* L == number of spaces to insert */
1032   for (i = l = 0; i < count; i++)
1033     {
1034       rl_backward_char (1, key);
1035       l += rl_character_len (rl_line_buffer[rl_point], rl_point);       /* not exactly right */
1036     }
1037
1038   rl_begin_undo_group ();
1039
1040   if (count > 1 || rl_explicit_arg)
1041     rl_kill_text (opoint, rl_point);
1042   else
1043     rl_delete_text (opoint, rl_point);
1044
1045   /* Emacs puts point at the beginning of the sequence of spaces. */
1046   if (rl_point < rl_end)
1047     {
1048       opoint = rl_point;
1049       _rl_insert_char (l, ' ');
1050       rl_point = opoint;
1051     }
1052
1053   rl_end_undo_group ();
1054
1055   return 0;
1056 }
1057   
1058 /* Rubout the character behind point. */
1059 int
1060 rl_rubout (count, key)
1061      int count, key;
1062 {
1063   if (count < 0)
1064     return (rl_delete (-count, key));
1065
1066   if (!rl_point)
1067     {
1068       rl_ding ();
1069       return -1;
1070     }
1071
1072   if (rl_insert_mode == RL_IM_OVERWRITE)
1073     return (_rl_overwrite_rubout (count, key));
1074
1075   return (_rl_rubout_char (count, key));
1076 }
1077
1078 int
1079 _rl_rubout_char (count, key)
1080      int count, key;
1081 {
1082   int orig_point;
1083   unsigned char c;
1084
1085   /* Duplicated code because this is called from other parts of the library. */
1086   if (count < 0)
1087     return (rl_delete (-count, key));
1088
1089   if (rl_point == 0)
1090     {
1091       rl_ding ();
1092       return -1;
1093     }
1094
1095   orig_point = rl_point;
1096   if (count > 1 || rl_explicit_arg)
1097     {
1098       rl_backward_char (count, key);
1099       rl_kill_text (orig_point, rl_point);
1100     }
1101   else if (MB_CUR_MAX == 1 || rl_byte_oriented)
1102     {
1103       c = rl_line_buffer[--rl_point];
1104       rl_delete_text (rl_point, orig_point);
1105       /* The erase-at-end-of-line hack is of questionable merit now. */
1106       if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
1107         {
1108           int l;
1109           l = rl_character_len (c, rl_point);
1110           _rl_erase_at_end_of_line (l);
1111         }
1112     }
1113   else
1114     {
1115       rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1116       rl_delete_text (rl_point, orig_point);
1117     }
1118
1119   return 0;
1120 }
1121
1122 /* Delete the character under the cursor.  Given a numeric argument,
1123    kill that many characters instead. */
1124 int
1125 rl_delete (count, key)
1126      int count, key;
1127 {
1128   int xpoint;
1129
1130   if (count < 0)
1131     return (_rl_rubout_char (-count, key));
1132
1133   if (rl_point == rl_end)
1134     {
1135       rl_ding ();
1136       return -1;
1137     }
1138
1139   if (count > 1 || rl_explicit_arg)
1140     {
1141       xpoint = rl_point;
1142       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1143         rl_forward_char (count, key);
1144       else
1145         rl_forward_byte (count, key);
1146
1147       rl_kill_text (xpoint, rl_point);
1148       rl_point = xpoint;
1149     }
1150   else
1151     {
1152       xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
1153       rl_delete_text (rl_point, xpoint);
1154     }
1155   return 0;
1156 }
1157
1158 /* Delete the character under the cursor, unless the insertion
1159    point is at the end of the line, in which case the character
1160    behind the cursor is deleted.  COUNT is obeyed and may be used
1161    to delete forward or backward that many characters. */      
1162 int
1163 rl_rubout_or_delete (count, key)
1164      int count, key;
1165 {
1166   if (rl_end != 0 && rl_point == rl_end)
1167     return (_rl_rubout_char (count, key));
1168   else
1169     return (rl_delete (count, key));
1170 }  
1171
1172 /* Delete all spaces and tabs around point. */
1173 int
1174 rl_delete_horizontal_space (count, ignore)
1175      int count, ignore;
1176 {
1177   int start;
1178
1179   while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
1180     rl_point--;
1181
1182   start = rl_point;
1183
1184   while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1185     rl_point++;
1186
1187   if (start != rl_point)
1188     {
1189       rl_delete_text (start, rl_point);
1190       rl_point = start;
1191     }
1192
1193   if (rl_point < 0)
1194     rl_point = 0;
1195
1196   return 0;
1197 }
1198
1199 /* Like the tcsh editing function delete-char-or-list.  The eof character
1200    is caught before this is invoked, so this really does the same thing as
1201    delete-char-or-list-or-eof, as long as it's bound to the eof character. */
1202 int
1203 rl_delete_or_show_completions (count, key)
1204      int count, key;
1205 {
1206   if (rl_end != 0 && rl_point == rl_end)
1207     return (rl_possible_completions (count, key));
1208   else
1209     return (rl_delete (count, key));
1210 }
1211
1212 #ifndef RL_COMMENT_BEGIN_DEFAULT
1213 #define RL_COMMENT_BEGIN_DEFAULT "#"
1214 #endif
1215
1216 /* Turn the current line into a comment in shell history.
1217    A K*rn shell style function. */
1218 int
1219 rl_insert_comment (count, key)
1220      int count, key;
1221 {
1222   char *rl_comment_text;
1223   int rl_comment_len;
1224
1225   rl_beg_of_line (1, key);
1226   rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
1227
1228   if (rl_explicit_arg == 0)
1229     rl_insert_text (rl_comment_text);
1230   else
1231     {
1232       rl_comment_len = strlen (rl_comment_text);
1233       if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
1234         rl_delete_text (rl_point, rl_point + rl_comment_len);
1235       else
1236         rl_insert_text (rl_comment_text);
1237     }
1238
1239   (*rl_redisplay_function) ();
1240   rl_newline (1, '\n');
1241
1242   return (0);
1243 }
1244
1245 /* **************************************************************** */
1246 /*                                                                  */
1247 /*                      Changing Case                               */
1248 /*                                                                  */
1249 /* **************************************************************** */
1250
1251 /* The three kinds of things that we know how to do. */
1252 #define UpCase 1
1253 #define DownCase 2
1254 #define CapCase 3
1255
1256 /* Uppercase the word at point. */
1257 int
1258 rl_upcase_word (count, key)
1259      int count, key;
1260 {
1261   return (rl_change_case (count, UpCase));
1262 }
1263
1264 /* Lowercase the word at point. */
1265 int
1266 rl_downcase_word (count, key)
1267      int count, key;
1268 {
1269   return (rl_change_case (count, DownCase));
1270 }
1271
1272 /* Upcase the first letter, downcase the rest. */
1273 int
1274 rl_capitalize_word (count, key)
1275      int count, key;
1276 {
1277  return (rl_change_case (count, CapCase));
1278 }
1279
1280 /* The meaty function.
1281    Change the case of COUNT words, performing OP on them.
1282    OP is one of UpCase, DownCase, or CapCase.
1283    If a negative argument is given, leave point where it started,
1284    otherwise, leave it where it moves to. */
1285 static int
1286 rl_change_case (count, op)
1287      int count, op;
1288 {
1289   int start, next, end;
1290   int inword, c, nc, nop;
1291 #if defined (HANDLE_MULTIBYTE)
1292   wchar_t wc, nwc;
1293   char mb[MB_LEN_MAX+1];
1294   int mlen;
1295   size_t m;
1296   mbstate_t mps;
1297 #endif
1298
1299   start = rl_point;
1300   rl_forward_word (count, 0);
1301   end = rl_point;
1302
1303   if (op != UpCase && op != DownCase && op != CapCase)
1304     {
1305       rl_ding ();
1306       return -1;
1307     }
1308
1309   if (count < 0)
1310     SWAP (start, end);
1311
1312 #if defined (HANDLE_MULTIBYTE)
1313   memset (&mps, 0, sizeof (mbstate_t));
1314 #endif
1315
1316   /* We are going to modify some text, so let's prepare to undo it. */
1317   rl_modifying (start, end);
1318
1319   inword = 0;
1320   while (start < end)
1321     {
1322       c = _rl_char_value (rl_line_buffer, start);
1323       /*  This assumes that the upper and lower case versions are the same width. */
1324       next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO);
1325
1326       if (_rl_walphabetic (c) == 0)
1327         {
1328           inword = 0;
1329           start = next;
1330           continue;
1331         }
1332
1333       if (op == CapCase)
1334         {
1335           nop = inword ? DownCase : UpCase;
1336           inword = 1;
1337         }
1338       else
1339         nop = op;
1340       if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c))
1341         {
1342           nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c);
1343           rl_line_buffer[start] = nc;
1344         }
1345 #if defined (HANDLE_MULTIBYTE)
1346       else
1347         {
1348           m = mbrtowc (&wc, rl_line_buffer + start, end - start, &mps);
1349           if (MB_INVALIDCH (m))
1350             wc = (wchar_t)rl_line_buffer[start];
1351           else if (MB_NULLWCH (m))
1352             wc = L'\0';
1353           nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
1354           if  (nwc != wc)       /*  just skip unchanged characters */
1355             {
1356               mlen = wcrtomb (mb, nwc, &mps);
1357               if (mlen > 0)
1358                 mb[mlen] = '\0';
1359               /* Assume the same width */
1360               strncpy (rl_line_buffer + start, mb, mlen);
1361             }
1362         }
1363 #endif
1364
1365       start = next;
1366     }
1367
1368   rl_point = end;
1369   return 0;
1370 }
1371
1372 /* **************************************************************** */
1373 /*                                                                  */
1374 /*                      Transposition                               */
1375 /*                                                                  */
1376 /* **************************************************************** */
1377
1378 /* Transpose the words at point.  If point is at the end of the line,
1379    transpose the two words before point. */
1380 int
1381 rl_transpose_words (count, key)
1382      int count, key;
1383 {
1384   char *word1, *word2;
1385   int w1_beg, w1_end, w2_beg, w2_end;
1386   int orig_point = rl_point;
1387
1388   if (!count)
1389     return 0;
1390
1391   /* Find the two words. */
1392   rl_forward_word (count, key);
1393   w2_end = rl_point;
1394   rl_backward_word (1, key);
1395   w2_beg = rl_point;
1396   rl_backward_word (count, key);
1397   w1_beg = rl_point;
1398   rl_forward_word (1, key);
1399   w1_end = rl_point;
1400
1401   /* Do some check to make sure that there really are two words. */
1402   if ((w1_beg == w2_beg) || (w2_beg < w1_end))
1403     {
1404       rl_ding ();
1405       rl_point = orig_point;
1406       return -1;
1407     }
1408
1409   /* Get the text of the words. */
1410   word1 = rl_copy_text (w1_beg, w1_end);
1411   word2 = rl_copy_text (w2_beg, w2_end);
1412
1413   /* We are about to do many insertions and deletions.  Remember them
1414      as one operation. */
1415   rl_begin_undo_group ();
1416
1417   /* Do the stuff at word2 first, so that we don't have to worry
1418      about word1 moving. */
1419   rl_point = w2_beg;
1420   rl_delete_text (w2_beg, w2_end);
1421   rl_insert_text (word1);
1422
1423   rl_point = w1_beg;
1424   rl_delete_text (w1_beg, w1_end);
1425   rl_insert_text (word2);
1426
1427   /* This is exactly correct since the text before this point has not
1428      changed in length. */
1429   rl_point = w2_end;
1430
1431   /* I think that does it. */
1432   rl_end_undo_group ();
1433   xfree (word1);
1434   xfree (word2);
1435
1436   return 0;
1437 }
1438
1439 /* Transpose the characters at point.  If point is at the end of the line,
1440    then transpose the characters before point. */
1441 int
1442 rl_transpose_chars (count, key)
1443      int count, key;
1444 {
1445 #if defined (HANDLE_MULTIBYTE)
1446   char *dummy;
1447   int i;
1448 #else
1449   char dummy[2];
1450 #endif
1451   int char_length, prev_point;
1452
1453   if (count == 0)
1454     return 0;
1455
1456   if (!rl_point || rl_end < 2)
1457     {
1458       rl_ding ();
1459       return -1;
1460     }
1461
1462   rl_begin_undo_group ();
1463
1464   if (rl_point == rl_end)
1465     {
1466       rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1467       count = 1;
1468     }
1469
1470   prev_point = rl_point;
1471   rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1472
1473 #if defined (HANDLE_MULTIBYTE)
1474   char_length = prev_point - rl_point;
1475   dummy = (char *)xmalloc (char_length + 1);
1476   for (i = 0; i < char_length; i++)
1477     dummy[i] = rl_line_buffer[rl_point + i];
1478   dummy[i] = '\0';
1479 #else
1480   dummy[0] = rl_line_buffer[rl_point];
1481   dummy[char_length = 1] = '\0';
1482 #endif
1483
1484   rl_delete_text (rl_point, rl_point + char_length);
1485
1486   rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1487
1488   _rl_fix_point (0);
1489   rl_insert_text (dummy);
1490   rl_end_undo_group ();
1491
1492 #if defined (HANDLE_MULTIBYTE)
1493   xfree (dummy);
1494 #endif
1495
1496   return 0;
1497 }
1498
1499 /* **************************************************************** */
1500 /*                                                                  */
1501 /*                      Character Searching                         */
1502 /*                                                                  */
1503 /* **************************************************************** */
1504
1505 int
1506 #if defined (HANDLE_MULTIBYTE)
1507 _rl_char_search_internal (count, dir, smbchar, len)
1508      int count, dir;
1509      char *smbchar;
1510      int len;
1511 #else
1512 _rl_char_search_internal (count, dir, schar)
1513      int count, dir, schar;
1514 #endif
1515 {
1516   int pos, inc;
1517 #if defined (HANDLE_MULTIBYTE)
1518   int prepos;
1519 #endif
1520
1521   if (dir == 0)
1522     return -1;
1523
1524   pos = rl_point;
1525   inc = (dir < 0) ? -1 : 1;
1526   while (count)
1527     {
1528       if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
1529         {
1530           rl_ding ();
1531           return -1;
1532         }
1533
1534 #if defined (HANDLE_MULTIBYTE)
1535       pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
1536                       : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1537 #else
1538       pos += inc;
1539 #endif
1540       do
1541         {
1542 #if defined (HANDLE_MULTIBYTE)
1543           if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
1544 #else
1545           if (rl_line_buffer[pos] == schar)
1546 #endif
1547             {
1548               count--;
1549               if (dir < 0)
1550                 rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
1551                                         : pos;
1552               else
1553                 rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
1554                                         : pos;
1555               break;
1556             }
1557 #if defined (HANDLE_MULTIBYTE)
1558           prepos = pos;
1559 #endif
1560         }
1561 #if defined (HANDLE_MULTIBYTE)
1562       while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
1563                        : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
1564 #else
1565       while ((dir < 0) ? pos-- : ++pos < rl_end);
1566 #endif
1567     }
1568   return (0);
1569 }
1570
1571 /* Search COUNT times for a character read from the current input stream.
1572    FDIR is the direction to search if COUNT is non-negative; otherwise
1573    the search goes in BDIR.  So much is dependent on HANDLE_MULTIBYTE
1574    that there are two separate versions of this function. */
1575 #if defined (HANDLE_MULTIBYTE)
1576 static int
1577 _rl_char_search (count, fdir, bdir)
1578      int count, fdir, bdir;
1579 {
1580   char mbchar[MB_LEN_MAX];
1581   int mb_len;
1582
1583   mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
1584
1585   if (mb_len <= 0)
1586     return -1;
1587
1588   if (count < 0)
1589     return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
1590   else
1591     return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
1592 }
1593 #else /* !HANDLE_MULTIBYTE */
1594 static int
1595 _rl_char_search (count, fdir, bdir)
1596      int count, fdir, bdir;
1597 {
1598   int c;
1599
1600   RL_SETSTATE(RL_STATE_MOREINPUT);
1601   c = rl_read_key ();
1602   RL_UNSETSTATE(RL_STATE_MOREINPUT);
1603
1604   if (c < 0)
1605     return -1;
1606
1607   if (count < 0)
1608     return (_rl_char_search_internal (-count, bdir, c));
1609   else
1610     return (_rl_char_search_internal (count, fdir, c));
1611 }
1612 #endif /* !HANDLE_MULTIBYTE */
1613
1614 #if defined (READLINE_CALLBACKS)
1615 static int
1616 _rl_char_search_callback (data)
1617      _rl_callback_generic_arg *data;
1618 {
1619   _rl_callback_func = 0;
1620   _rl_want_redisplay = 1;
1621
1622   return (_rl_char_search (data->count, data->i1, data->i2));
1623 }
1624 #endif
1625
1626 int
1627 rl_char_search (count, key)
1628      int count, key;
1629 {
1630 #if defined (READLINE_CALLBACKS)
1631   if (RL_ISSTATE (RL_STATE_CALLBACK))
1632     {
1633       _rl_callback_data = _rl_callback_data_alloc (count);
1634       _rl_callback_data->i1 = FFIND;
1635       _rl_callback_data->i2 = BFIND;
1636       _rl_callback_func = _rl_char_search_callback;
1637       return (0);
1638     }
1639 #endif
1640   
1641   return (_rl_char_search (count, FFIND, BFIND));
1642 }
1643
1644 int
1645 rl_backward_char_search (count, key)
1646      int count, key;
1647 {
1648 #if defined (READLINE_CALLBACKS)
1649   if (RL_ISSTATE (RL_STATE_CALLBACK))
1650     {
1651       _rl_callback_data = _rl_callback_data_alloc (count);
1652       _rl_callback_data->i1 = BFIND;
1653       _rl_callback_data->i2 = FFIND;
1654       _rl_callback_func = _rl_char_search_callback;
1655       return (0);
1656     }
1657 #endif
1658
1659   return (_rl_char_search (count, BFIND, FFIND));
1660 }
1661
1662 /* **************************************************************** */
1663 /*                                                                  */
1664 /*                 The Mark and the Region.                         */
1665 /*                                                                  */
1666 /* **************************************************************** */
1667
1668 /* Set the mark at POSITION. */
1669 int
1670 _rl_set_mark_at_pos (position)
1671      int position;
1672 {
1673   if (position > rl_end)
1674     return -1;
1675
1676   rl_mark = position;
1677   return 0;
1678 }
1679
1680 /* A bindable command to set the mark. */
1681 int
1682 rl_set_mark (count, key)
1683      int count, key;
1684 {
1685   return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
1686 }
1687
1688 /* Exchange the position of mark and point. */
1689 int
1690 rl_exchange_point_and_mark (count, key)
1691      int count, key;
1692 {
1693   if (rl_mark > rl_end)
1694     rl_mark = -1;
1695
1696   if (rl_mark == -1)
1697     {
1698       rl_ding ();
1699       return -1;
1700     }
1701   else
1702     SWAP (rl_point, rl_mark);
1703
1704   return 0;
1705 }