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