Import GNU Readline 8.1
[deliverable/binutils-gdb.git] / readline / readline / text.c
CommitLineData
9255ee31
EZ
1/* text.c -- text handling commands for readline. */
2
b4f26d54 3/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
9255ee31 4
cc88a640
JK
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.
9255ee31 7
cc88a640
JK
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
9255ee31
EZ
11 (at your option) any later version.
12
cc88a640
JK
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
9255ee31
EZ
16 GNU General Public License for more details.
17
cc88a640
JK
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
9255ee31
EZ
22#define READLINE_LIBRARY
23
24#if defined (HAVE_CONFIG_H)
25# include <config.h>
26#endif
27
28#if defined (HAVE_UNISTD_H)
29# include <unistd.h>
30#endif /* HAVE_UNISTD_H */
31
32#if defined (HAVE_STDLIB_H)
33# include <stdlib.h>
34#else
35# include "ansi_stdlib.h"
36#endif /* HAVE_STDLIB_H */
37
38#if defined (HAVE_LOCALE_H)
39# include <locale.h>
40#endif
41
42#include <stdio.h>
43
44/* System-specific feature definitions and include files. */
45#include "rldefs.h"
46#include "rlmbutil.h"
47
48#if defined (__EMX__)
49# define INCL_DOSPROCESS
50# include <os2.h>
51#endif /* __EMX__ */
52
53/* Some standard library routines. */
54#include "readline.h"
55#include "history.h"
56
57#include "rlprivate.h"
58#include "rlshell.h"
59#include "xmalloc.h"
60
61/* Forward declarations. */
62static int rl_change_case PARAMS((int, int));
63static int _rl_char_search PARAMS((int, int, int));
64
5bdf8622
DJ
65#if defined (READLINE_CALLBACKS)
66static int _rl_insert_next_callback PARAMS((_rl_callback_generic_arg *));
67static int _rl_char_search_callback PARAMS((_rl_callback_generic_arg *));
68#endif
69
cc88a640
JK
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
775e241e
TT
74int _rl_optimize_typeahead = 1; /* rl_insert tries to read typeahead */
75
9255ee31
EZ
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. */
85int
cb41b9e7 86rl_insert_text (const char *string)
9255ee31
EZ
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. */
122int
cb41b9e7 123rl_delete_text (int from, int to)
9255ee31
EZ
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
cc88a640 153 xfree (text);
9255ee31
EZ
154
155 rl_end -= diff;
156 rl_line_buffer[rl_end] = '\0';
b4f26d54 157 _rl_fix_mark ();
9255ee31
EZ
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
173void
cb41b9e7 174_rl_fix_point (int fix_mark_too)
9255ee31
EZ
175{
176 _RL_FIX_POINT (rl_point);
177 if (fix_mark_too)
178 _RL_FIX_POINT (rl_mark);
179}
b4f26d54
TT
180
181void
182_rl_fix_mark (void)
183{
184 _RL_FIX_POINT (rl_mark);
185}
9255ee31
EZ
186#undef _RL_FIX_POINT
187
5bdf8622
DJ
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); */
9255ee31 191int
cb41b9e7 192_rl_replace_text (const char *text, int start, int end)
9255ee31
EZ
193{
194 int n;
195
cc88a640 196 n = 0;
9255ee31 197 rl_begin_undo_group ();
cc88a640
JK
198 if (start <= end)
199 rl_delete_text (start, end + 1);
9255ee31 200 rl_point = start;
cc88a640
JK
201 if (*text)
202 n = rl_insert_text (text);
9255ee31
EZ
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. */
210void
cb41b9e7 211rl_replace_line (const char *text, int clear_undo)
9255ee31
EZ
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.
775e241e 245 The first is a count: the numeric arg passed to this command.
9255ee31
EZ
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. */
261int
cb41b9e7 262rl_forward_byte (int count, int key)
9255ee31
EZ
263{
264 if (count < 0)
265 return (rl_backward_byte (-count, key));
266
267 if (count > 0)
268 {
cc88a640
JK
269 int end, lend;
270
271 end = rl_point + count;
9255ee31 272#if defined (VI_MODE)
cc88a640 273 lend = rl_end > 0 ? rl_end - (VI_COMMAND_MODE()) : rl_end;
9255ee31 274#else
cc88a640 275 lend = rl_end;
9255ee31
EZ
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
cc88a640 293int
cb41b9e7 294_rl_forward_char_internal (int count)
cc88a640
JK
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)
cb41b9e7 307 rl_end = 0;
cc88a640
JK
308#else
309 point = rl_point + count;
cb41b9e7
TT
310#endif
311
cc88a640
JK
312 if (point > rl_end)
313 point = rl_end;
cb41b9e7
TT
314 return (point);
315}
316
317int
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;
cc88a640
JK
337#endif
338
cb41b9e7
TT
339 if (point < 0)
340 point = 0;
cc88a640
JK
341 return (point);
342}
343
9255ee31
EZ
344#if defined (HANDLE_MULTIBYTE)
345/* Move forward COUNT characters. */
346int
cb41b9e7 347rl_forward_char (int count, int key)
9255ee31
EZ
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 {
cc88a640
JK
359 if (rl_point == rl_end && EMACS_MODE())
360 {
361 rl_ding ();
362 return 0;
363 }
9255ee31 364
cc88a640 365 point = _rl_forward_char_internal (count);
9255ee31
EZ
366
367 if (rl_point == point)
368 rl_ding ();
369
370 rl_point = point;
9255ee31
EZ
371 }
372
373 return 0;
374}
375#else /* !HANDLE_MULTIBYTE */
376int
cb41b9e7 377rl_forward_char (int count, int key)
9255ee31
EZ
378{
379 return (rl_forward_byte (count, key));
380}
381#endif /* !HANDLE_MULTIBYTE */
382
383/* Backwards compatibility. */
384int
cb41b9e7 385rl_forward (int count, int key)
9255ee31
EZ
386{
387 return (rl_forward_char (count, key));
388}
389
390/* Move backward COUNT bytes. */
391int
cb41b9e7 392rl_backward_byte (int count, int key)
9255ee31
EZ
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. */
416int
cb41b9e7 417rl_backward_char (int count, int key)
9255ee31
EZ
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
448int
cb41b9e7 449rl_backward_char (int count, int key)
9255ee31
EZ
450{
451 return (rl_backward_byte (count, key));
452}
453#endif
454
455/* Backwards compatibility. */
456int
cb41b9e7 457rl_backward (int count, int key)
9255ee31
EZ
458{
459 return (rl_backward_char (count, key));
460}
461
462/* Move to the beginning of the line. */
463int
cb41b9e7 464rl_beg_of_line (int count, int key)
9255ee31
EZ
465{
466 rl_point = 0;
467 return 0;
468}
469
470/* Move to the end of the line. */
471int
cb41b9e7 472rl_end_of_line (int count, int key)
9255ee31
EZ
473{
474 rl_point = rl_end;
475 return 0;
476}
477
5bdf8622 478/* Move forward a word. We do what Emacs does. Handles multibyte chars. */
9255ee31 479int
cb41b9e7 480rl_forward_word (int count, int key)
9255ee31
EZ
481{
482 int c;
483
484 if (count < 0)
485 return (rl_backward_word (-count, key));
486
487 while (count)
488 {
b4f26d54
TT
489 if (rl_point > rl_end)
490 rl_point = rl_end;
9255ee31
EZ
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. */
5bdf8622
DJ
496 c = _rl_char_value (rl_line_buffer, rl_point);
497
498 if (_rl_walphabetic (c) == 0)
9255ee31 499 {
5bdf8622
DJ
500 rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
501 while (rl_point < rl_end)
9255ee31 502 {
5bdf8622
DJ
503 c = _rl_char_value (rl_line_buffer, rl_point);
504 if (_rl_walphabetic (c))
9255ee31 505 break;
5bdf8622 506 rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
9255ee31
EZ
507 }
508 }
509
b4f26d54
TT
510 if (rl_point > rl_end)
511 rl_point = rl_end;
9255ee31
EZ
512 if (rl_point == rl_end)
513 return 0;
514
5bdf8622
DJ
515 rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
516 while (rl_point < rl_end)
9255ee31 517 {
5bdf8622
DJ
518 c = _rl_char_value (rl_line_buffer, rl_point);
519 if (_rl_walphabetic (c) == 0)
9255ee31 520 break;
5bdf8622 521 rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
9255ee31 522 }
5bdf8622 523
9255ee31
EZ
524 --count;
525 }
526
527 return 0;
528}
529
5bdf8622 530/* Move backward a word. We do what Emacs does. Handles multibyte chars. */
9255ee31 531int
cb41b9e7 532rl_backward_word (int count, int key)
9255ee31 533{
5bdf8622 534 int c, p;
9255ee31
EZ
535
536 if (count < 0)
537 return (rl_forward_word (-count, key));
538
539 while (count)
540 {
5bdf8622 541 if (rl_point == 0)
9255ee31
EZ
542 return 0;
543
544 /* Like rl_forward_word (), except that we look at the characters
545 just before point. */
546
5bdf8622
DJ
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)
9255ee31 551 {
5bdf8622
DJ
552 rl_point = p;
553 while (rl_point > 0)
9255ee31 554 {
5bdf8622
DJ
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))
9255ee31 558 break;
5bdf8622 559 rl_point = p;
9255ee31
EZ
560 }
561 }
562
563 while (rl_point)
564 {
5bdf8622
DJ
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)
9255ee31
EZ
568 break;
569 else
5bdf8622 570 rl_point = p;
9255ee31
EZ
571 }
572
573 --count;
574 }
575
576 return 0;
577}
578
579/* Clear the current line. Numeric argument to C-l does this. */
580int
cb41b9e7 581rl_refresh_line (int ignore1, int ignore2)
9255ee31 582{
b4f26d54 583 _rl_refresh_line ();
9255ee31 584 rl_display_fixed = 1;
9255ee31
EZ
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. */
591int
cb41b9e7 592rl_clear_screen (int count, int key)
9255ee31
EZ
593{
594 if (rl_explicit_arg)
595 {
596 rl_refresh_line (count, key);
597 return 0;
598 }
599
b4f26d54
TT
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
608int
609rl_clear_display (int count, int key)
610{
611 _rl_clear_screen (1); /* calls termcap function to clear screen and scrollback buffer */
9255ee31
EZ
612 rl_forced_update_display ();
613 rl_display_fixed = 1;
614
615 return 0;
616}
617
cc88a640 618int
cb41b9e7
TT
619rl_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
627int
628rl_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
636int
637rl_skip_csi_sequence (int count, int key)
cc88a640
JK
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
775e241e 647 return (ch < 0);
cc88a640
JK
648}
649
9255ee31 650int
cb41b9e7 651rl_arrow_keys (int count, int key)
9255ee31
EZ
652{
653 int ch;
654
655 RL_SETSTATE(RL_STATE_MOREINPUT);
656 ch = rl_read_key ();
657 RL_UNSETSTATE(RL_STATE_MOREINPUT);
775e241e
TT
658 if (ch < 0)
659 return (1);
9255ee31
EZ
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
699static char pending_bytes[MB_LEN_MAX];
700static int pending_bytes_length = 0;
701static 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. */
707int
cb41b9e7 708_rl_insert_char (int count, int c)
9255ee31
EZ
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 }
cb41b9e7
TT
730 else if (_rl_utf8locale && (c & 0x80) == 0)
731 {
732 incoming[0] = c;
733 incoming[1] = '\0';
734 incoming_length = 1;
735 }
9255ee31
EZ
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 }
cb41b9e7
TT
780 else if (ret == 1)
781 {
782 incoming[0] = pending_bytes[0];
783 incoming[incoming_length = 1] = '\0';
784 pending_bytes_length = 0;
785 }
9255ee31
EZ
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. */
cc88a640 799 if (count > 1 && count <= TEXT_COUNT_MAX)
9255ee31
EZ
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 {
cb41b9e7
TT
808 if (incoming_length == 1)
809 string[i++] = *incoming;
810 else
811 {
812 strncpy (string + i, incoming, incoming_length);
813 i += incoming_length;
814 }
9255ee31
EZ
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);
cc88a640 827 xfree (string);
9255ee31
EZ
828
829 return 0;
830 }
831
cc88a640 832 if (count > TEXT_COUNT_MAX)
9255ee31
EZ
833 {
834 int decreaser;
835#if defined (HANDLE_MULTIBYTE)
cc88a640 836 string_size = incoming_length * TEXT_COUNT_MAX;
9255ee31
EZ
837 string = (char *)xmalloc (1 + string_size);
838
839 i = 0;
840 while (i < string_size)
841 {
cb41b9e7
TT
842 if (incoming_length == 1)
843 string[i++] = *incoming;
844 else
845 {
846 strncpy (string + i, incoming, incoming_length);
847 i += incoming_length;
848 }
9255ee31
EZ
849 }
850
851 while (count)
852 {
cc88a640 853 decreaser = (count > TEXT_COUNT_MAX) ? TEXT_COUNT_MAX : count;
9255ee31
EZ
854 string[decreaser*incoming_length] = '\0';
855 rl_insert_text (string);
856 count -= decreaser;
857 }
858
cc88a640 859 xfree (string);
9255ee31
EZ
860 incoming_length = 0;
861 stored_count = 0;
862#else /* !HANDLE_MULTIBYTE */
cc88a640 863 char str[TEXT_COUNT_MAX+1];
9255ee31 864
cc88a640 865 for (i = 0; i < TEXT_COUNT_MAX; i++)
9255ee31
EZ
866 str[i] = c;
867
868 while (count)
869 {
cc88a640 870 decreaser = (count > TEXT_COUNT_MAX ? TEXT_COUNT_MAX : count);
9255ee31
EZ
871 str[decreaser] = '\0';
872 rl_insert_text (str);
873 count -= decreaser;
874 }
875#endif /* !HANDLE_MULTIBYTE */
876
877 return 0;
878 }
879
9255ee31
EZ
880 if (MB_CUR_MAX == 1 || rl_byte_oriented)
881 {
9255ee31
EZ
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
cc88a640
JK
885 them all. Don't do this if we're current reading input from
886 a macro. */
775e241e 887 if ((RL_ISSTATE (RL_STATE_MACROINPUT) == 0) && _rl_pushed_input_available ())
9255ee31
EZ
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 }
9255ee31 898 }
5bdf8622 899#if defined (HANDLE_MULTIBYTE)
9255ee31
EZ
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. */
913int
cb41b9e7 914_rl_overwrite_char (int count, int c)
9255ee31
EZ
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
5bdf8622
DJ
926 rl_begin_undo_group ();
927
9255ee31
EZ
928 for (i = 0; i < count; i++)
929 {
9255ee31
EZ
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
5bdf8622
DJ
937 if (rl_point < rl_end)
938 rl_delete (1, c);
9255ee31
EZ
939 }
940
5bdf8622
DJ
941 rl_end_undo_group ();
942
9255ee31
EZ
943 return 0;
944}
945
946int
cb41b9e7 947rl_insert (int count, int c)
9255ee31 948{
775e241e
TT
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 &&
cb41b9e7 957 rl_num_chars_to_read == 0 &&
775e241e
TT
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;
9255ee31
EZ
993}
994
995/* Insert the next typed character verbatim. */
5bdf8622 996static int
cb41b9e7 997_rl_insert_next (int count)
9255ee31
EZ
998{
999 int c;
1000
9255ee31
EZ
1001 RL_SETSTATE(RL_STATE_MOREINPUT);
1002 c = rl_read_key ();
1003 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1004
cc88a640 1005 if (c < 0)
775e241e
TT
1006 return 1;
1007
1008 if (RL_ISSTATE (RL_STATE_MACRODEF))
1009 _rl_add_macro_char (c);
cc88a640 1010
9255ee31 1011#if defined (HANDLE_SIGNALS)
5bdf8622
DJ
1012 if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
1013 _rl_restore_tty_signals ();
9255ee31
EZ
1014#endif
1015
1016 return (_rl_insert_char (count, c));
1017}
1018
5bdf8622
DJ
1019#if defined (READLINE_CALLBACKS)
1020static int
cb41b9e7 1021_rl_insert_next_callback (_rl_callback_generic_arg *data)
5bdf8622 1022{
cb41b9e7 1023 int count, r;
5bdf8622
DJ
1024
1025 count = data->count;
cb41b9e7
TT
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 }
5bdf8622
DJ
1038
1039 /* Deregister function, let rl_callback_read_char deallocate data */
1040 _rl_callback_func = 0;
1041 _rl_want_redisplay = 1;
cb41b9e7
TT
1042
1043 if (count == 0)
1044 return r;
1045
5bdf8622
DJ
1046 return _rl_insert_next (count);
1047}
1048#endif
1049
1050int
cb41b9e7 1051rl_quoted_insert (int count, int key)
5bdf8622
DJ
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
cb41b9e7
TT
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
5bdf8622
DJ
1079 return _rl_insert_next (count);
1080}
1081
9255ee31
EZ
1082/* Insert a tab character. */
1083int
cb41b9e7 1084rl_tab_insert (int count, int key)
9255ee31
EZ
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. */
1092int
cb41b9e7 1093rl_newline (int count, int key)
9255ee31 1094{
b4f26d54
TT
1095 if (rl_mark_active_p ())
1096 {
1097 rl_deactivate_mark ();
1098 (*rl_redisplay_function) ();
1099 _rl_want_redisplay = 0;
1100 }
1101
9255ee31
EZ
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 ();
5bdf8622
DJ
1113 if (_rl_vi_textmod_command (_rl_vi_last_command) == 0) /* XXX */
1114 _rl_vi_reset_last ();
9255ee31
EZ
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
cc88a640 1123 if (_rl_echoing_p)
9255ee31
EZ
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. */
1132int
cb41b9e7 1133rl_do_lowercase_version (int ignore1, int ignore2)
9255ee31
EZ
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. */
1141int
cb41b9e7 1142_rl_overwrite_rubout (int count, int key)
9255ee31
EZ
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. */
5bdf8622
DJ
1170 if (rl_point < rl_end)
1171 {
1172 opoint = rl_point;
1173 _rl_insert_char (l, ' ');
1174 rl_point = opoint;
1175 }
9255ee31
EZ
1176
1177 rl_end_undo_group ();
1178
1179 return 0;
1180}
1181
1182/* Rubout the character behind point. */
1183int
cb41b9e7 1184rl_rubout (int count, int key)
9255ee31
EZ
1185{
1186 if (count < 0)
1187 return (rl_delete (-count, key));
1188
1189 if (!rl_point)
1190 {
1191 rl_ding ();
775e241e 1192 return 1;
9255ee31
EZ
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
1201int
cb41b9e7 1202_rl_rubout_char (int count, int key)
9255ee31
EZ
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 ();
775e241e 1214 return 1;
9255ee31
EZ
1215 }
1216
5bdf8622 1217 orig_point = rl_point;
9255ee31
EZ
1218 if (count > 1 || rl_explicit_arg)
1219 {
5bdf8622 1220 rl_backward_char (count, key);
9255ee31
EZ
1221 rl_kill_text (orig_point, rl_point);
1222 }
5bdf8622 1223 else if (MB_CUR_MAX == 1 || rl_byte_oriented)
9255ee31 1224 {
5bdf8622
DJ
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. */
775e241e 1228 if (rl_point == rl_end && ISPRINT ((unsigned char)c) && _rl_last_c_pos)
9255ee31
EZ
1229 {
1230 int l;
1231 l = rl_character_len (c, rl_point);
1232 _rl_erase_at_end_of_line (l);
1233 }
1234 }
5bdf8622
DJ
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 }
9255ee31
EZ
1240
1241 return 0;
1242}
1243
1244/* Delete the character under the cursor. Given a numeric argument,
1245 kill that many characters instead. */
1246int
cb41b9e7 1247rl_delete (int count, int key)
9255ee31 1248{
cc88a640
JK
1249 int xpoint;
1250
9255ee31
EZ
1251 if (count < 0)
1252 return (_rl_rubout_char (-count, key));
1253
1254 if (rl_point == rl_end)
1255 {
1256 rl_ding ();
775e241e 1257 return 1;
9255ee31
EZ
1258 }
1259
1260 if (count > 1 || rl_explicit_arg)
1261 {
cc88a640 1262 xpoint = rl_point;
9255ee31
EZ
1263 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1264 rl_forward_char (count, key);
1265 else
9255ee31
EZ
1266 rl_forward_byte (count, key);
1267
cc88a640
JK
1268 rl_kill_text (xpoint, rl_point);
1269 rl_point = xpoint;
9255ee31
EZ
1270 }
1271 else
1272 {
cc88a640
JK
1273 xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
1274 rl_delete_text (rl_point, xpoint);
9255ee31 1275 }
5bdf8622 1276 return 0;
9255ee31
EZ
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. */
1283int
cb41b9e7 1284rl_rubout_or_delete (int count, int key)
9255ee31
EZ
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. */
1293int
cb41b9e7 1294rl_delete_horizontal_space (int count, int ignore)
9255ee31 1295{
cc88a640 1296 int start;
9255ee31
EZ
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 }
5bdf8622
DJ
1311
1312 if (rl_point < 0)
1313 rl_point = 0;
1314
9255ee31
EZ
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. */
1321int
cb41b9e7 1322rl_delete_or_show_completions (int count, int key)
9255ee31
EZ
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. */
1336int
cb41b9e7 1337rl_insert_comment (int count, int key)
9255ee31
EZ
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. */
1374int
cb41b9e7 1375rl_upcase_word (int count, int key)
9255ee31
EZ
1376{
1377 return (rl_change_case (count, UpCase));
1378}
1379
1380/* Lowercase the word at point. */
1381int
cb41b9e7 1382rl_downcase_word (int count, int key)
9255ee31
EZ
1383{
1384 return (rl_change_case (count, DownCase));
1385}
1386
1387/* Upcase the first letter, downcase the rest. */
1388int
cb41b9e7 1389rl_capitalize_word (int count, int key)
9255ee31
EZ
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. */
1399static int
cb41b9e7 1400rl_change_case (int count, int op)
9255ee31 1401{
5bdf8622 1402 int start, next, end;
cb41b9e7
TT
1403 int inword, nc, nop;
1404 wchar_t c;
5bdf8622
DJ
1405#if defined (HANDLE_MULTIBYTE)
1406 wchar_t wc, nwc;
1407 char mb[MB_LEN_MAX+1];
cc88a640
JK
1408 int mlen;
1409 size_t m;
1410 mbstate_t mps;
5bdf8622 1411#endif
9255ee31
EZ
1412
1413 start = rl_point;
1414 rl_forward_word (count, 0);
1415 end = rl_point;
1416
5bdf8622
DJ
1417 if (op != UpCase && op != DownCase && op != CapCase)
1418 {
1419 rl_ding ();
775e241e 1420 return 1;
5bdf8622
DJ
1421 }
1422
9255ee31
EZ
1423 if (count < 0)
1424 SWAP (start, end);
1425
5bdf8622 1426#if defined (HANDLE_MULTIBYTE)
cc88a640 1427 memset (&mps, 0, sizeof (mbstate_t));
5bdf8622
DJ
1428#endif
1429
9255ee31
EZ
1430 /* We are going to modify some text, so let's prepare to undo it. */
1431 rl_modifying (start, end);
1432
5bdf8622
DJ
1433 inword = 0;
1434 while (start < end)
9255ee31 1435 {
5bdf8622
DJ
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);
9255ee31 1439
5bdf8622
DJ
1440 if (_rl_walphabetic (c) == 0)
1441 {
1442 inword = 0;
1443 start = next;
1444 continue;
1445 }
9255ee31 1446
5bdf8622
DJ
1447 if (op == CapCase)
1448 {
1449 nop = inword ? DownCase : UpCase;
1450 inword = 1;
9255ee31 1451 }
5bdf8622
DJ
1452 else
1453 nop = op;
cb41b9e7
TT
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)
5bdf8622
DJ
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 {
cc88a640
JK
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';
5bdf8622
DJ
1470 nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
1471 if (nwc != wc) /* just skip unchanged characters */
1472 {
cb41b9e7 1473 char *s, *e;
b4f26d54
TT
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 }
cc88a640
JK
1486 if (mlen > 0)
1487 mb[mlen] = '\0';
cb41b9e7
TT
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 {
b4f26d54
TT
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;
cb41b9e7
TT
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 }
5bdf8622
DJ
1515 }
1516 }
1517#endif
1518
1519 start = next;
9255ee31 1520 }
5bdf8622 1521
9255ee31
EZ
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. */
1534int
cb41b9e7 1535rl_transpose_words (int count, int key)
9255ee31
EZ
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;
775e241e 1559 return 1;
9255ee31
EZ
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 ();
cc88a640
JK
1586 xfree (word1);
1587 xfree (word2);
9255ee31
EZ
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. */
1594int
cb41b9e7 1595rl_transpose_chars (int count, int key)
9255ee31
EZ
1596{
1597#if defined (HANDLE_MULTIBYTE)
1598 char *dummy;
5bdf8622 1599 int i;
9255ee31
EZ
1600#else
1601 char dummy[2];
1602#endif
5bdf8622 1603 int char_length, prev_point;
9255ee31
EZ
1604
1605 if (count == 0)
1606 return 0;
1607
1608 if (!rl_point || rl_end < 2)
1609 {
1610 rl_ding ();
775e241e 1611 return 1;
9255ee31
EZ
1612 }
1613
1614 rl_begin_undo_group ();
1615
1616 if (rl_point == rl_end)
1617 {
5bdf8622 1618 rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
9255ee31
EZ
1619 count = 1;
1620 }
1621
9255ee31 1622 prev_point = rl_point;
5bdf8622 1623 rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
9255ee31
EZ
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)
cc88a640 1645 xfree (dummy);
9255ee31
EZ
1646#endif
1647
1648 return 0;
1649}
1650
1651/* **************************************************************** */
1652/* */
1653/* Character Searching */
1654/* */
1655/* **************************************************************** */
1656
1657int
1658#if defined (HANDLE_MULTIBYTE)
cb41b9e7 1659_rl_char_search_internal (int count, int dir, char *smbchar, int len)
9255ee31 1660#else
cb41b9e7 1661_rl_char_search_internal (int count, int dir, int schar)
9255ee31
EZ
1662#endif
1663{
1664 int pos, inc;
1665#if defined (HANDLE_MULTIBYTE)
1666 int prepos;
1667#endif
1668
cc88a640 1669 if (dir == 0)
775e241e 1670 return 1;
cc88a640 1671
9255ee31
EZ
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 ();
775e241e 1679 return 1;
9255ee31
EZ
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)
1724static int
cb41b9e7 1725_rl_char_search (int count, int fdir, int bdir)
9255ee31
EZ
1726{
1727 char mbchar[MB_LEN_MAX];
1728 int mb_len;
1729
1730 mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
1731
cc88a640 1732 if (mb_len <= 0)
775e241e 1733 return 1;
cc88a640 1734
9255ee31
EZ
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 */
1741static int
cb41b9e7 1742_rl_char_search (int count, int fdir, int bdir)
9255ee31
EZ
1743{
1744 int c;
1745
b4f26d54 1746 c = _rl_bracketed_read_key ();
cc88a640 1747 if (c < 0)
775e241e 1748 return 1;
cc88a640 1749
9255ee31
EZ
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
5bdf8622
DJ
1757#if defined (READLINE_CALLBACKS)
1758static 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
9255ee31 1769int
cb41b9e7 1770rl_char_search (int count, int key)
9255ee31 1771{
5bdf8622
DJ
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
9255ee31
EZ
1783 return (_rl_char_search (count, FFIND, BFIND));
1784}
1785
1786int
cb41b9e7 1787rl_backward_char_search (int count, int key)
9255ee31 1788{
5bdf8622
DJ
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
9255ee31
EZ
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. */
1810int
cb41b9e7 1811_rl_set_mark_at_pos (int position)
9255ee31 1812{
cb41b9e7 1813 if (position < 0 || position > rl_end)
775e241e 1814 return 1;
9255ee31
EZ
1815
1816 rl_mark = position;
1817 return 0;
1818}
1819
1820/* A bindable command to set the mark. */
1821int
cb41b9e7 1822rl_set_mark (int count, int key)
9255ee31
EZ
1823{
1824 return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
1825}
1826
1827/* Exchange the position of mark and point. */
1828int
cb41b9e7 1829rl_exchange_point_and_mark (int count, int key)
9255ee31
EZ
1830{
1831 if (rl_mark > rl_end)
1832 rl_mark = -1;
1833
cb41b9e7 1834 if (rl_mark < 0)
9255ee31
EZ
1835 {
1836 rl_ding ();
cb41b9e7 1837 rl_mark = 0; /* like _RL_FIX_POINT */
775e241e 1838 return 1;
9255ee31
EZ
1839 }
1840 else
b4f26d54
TT
1841 {
1842 SWAP (rl_point, rl_mark);
1843 rl_activate_mark ();
1844 }
9255ee31
EZ
1845
1846 return 0;
1847}
b4f26d54
TT
1848
1849/* Active mark support */
1850
1851/* Is the region active? */
1852static int mark_active = 0;
1853
1854/* Does the current command want the mark to remain active when it completes? */
1855int _rl_keep_mark_active;
1856
1857void
1858rl_keep_mark_active (void)
1859{
1860 _rl_keep_mark_active++;
1861}
1862
1863void
1864rl_activate_mark (void)
1865{
1866 mark_active = 1;
1867 rl_keep_mark_active ();
1868}
1869
1870void
1871rl_deactivate_mark (void)
1872{
1873 mark_active = 0;
1874}
1875
1876int
1877rl_mark_active_p (void)
1878{
1879 return (mark_active);
1880}
This page took 0.979393 seconds and 4 git commands to generate.