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