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