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