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