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