blob: f29adf8101c1d53ab8d4e813cab3eff442f784c8 [file] [log] [blame]
Jari Aalto7117c2d2002-07-17 14:10:11 +00001/* text.c -- text handling commands for readline. */
2
Chet Ramey495aee42011-11-22 19:11:26 -05003/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
Jari Aalto7117c2d2002-07-17 14:10:11 +00004
Jari Aalto31859422009-01-12 13:36:28 +00005 This file is part of the GNU Readline Library (Readline), a library
6 for reading lines of text with interactive input and history editing.
Jari Aalto7117c2d2002-07-17 14:10:11 +00007
Jari Aalto31859422009-01-12 13:36:28 +00008 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
Jari Aalto7117c2d2002-07-17 14:10:11 +000011 (at your option) any later version.
12
Jari Aalto31859422009-01-12 13:36:28 +000013 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
Jari Aalto7117c2d2002-07-17 14:10:11 +000016 GNU General Public License for more details.
17
Jari Aalto31859422009-01-12 13:36:28 +000018 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
Jari Aalto7117c2d2002-07-17 14:10:11 +000022#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
Jari Aalto95732b42005-12-07 14:08:12 +000065#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
Chet Ramey00018032011-11-21 20:51:19 -050070/* 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
Jari Aalto7117c2d2002-07-17 14:10:11 +000074/* **************************************************************** */
75/* */
76/* Insert and Delete */
77/* */
78/* **************************************************************** */
79
80/* Insert a string of text into the line at point. This is the only
81 way that you should do insertion. _rl_insert_char () calls this
82 function. Returns the number of characters inserted. */
83int
84rl_insert_text (string)
85 const char *string;
86{
87 register int i, l;
88
89 l = (string && *string) ? strlen (string) : 0;
90 if (l == 0)
91 return 0;
92
93 if (rl_end + l >= rl_line_buffer_len)
94 rl_extend_line_buffer (rl_end + l);
95
96 for (i = rl_end; i >= rl_point; i--)
97 rl_line_buffer[i + l] = rl_line_buffer[i];
98 strncpy (rl_line_buffer + rl_point, string, l);
99
100 /* Remember how to undo this if we aren't undoing something. */
101 if (_rl_doing_an_undo == 0)
102 {
103 /* If possible and desirable, concatenate the undos. */
104 if ((l == 1) &&
105 rl_undo_list &&
106 (rl_undo_list->what == UNDO_INSERT) &&
107 (rl_undo_list->end == rl_point) &&
108 (rl_undo_list->end - rl_undo_list->start < 20))
109 rl_undo_list->end++;
110 else
111 rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
112 }
113 rl_point += l;
114 rl_end += l;
115 rl_line_buffer[rl_end] = '\0';
116 return l;
117}
118
119/* Delete the string between FROM and TO. FROM is inclusive, TO is not.
120 Returns the number of characters deleted. */
121int
122rl_delete_text (from, to)
123 int from, to;
124{
125 register char *text;
126 register int diff, i;
127
128 /* Fix it if the caller is confused. */
129 if (from > to)
130 SWAP (from, to);
131
132 /* fix boundaries */
133 if (to > rl_end)
134 {
135 to = rl_end;
136 if (from > to)
137 from = to;
138 }
139 if (from < 0)
140 from = 0;
141
142 text = rl_copy_text (from, to);
143
144 /* Some versions of strncpy() can't handle overlapping arguments. */
145 diff = to - from;
146 for (i = from; i < rl_end - diff; i++)
147 rl_line_buffer[i] = rl_line_buffer[i + diff];
148
149 /* Remember how to undo this delete. */
150 if (_rl_doing_an_undo == 0)
151 rl_add_undo (UNDO_DELETE, from, to, text);
152 else
Chet Ramey495aee42011-11-22 19:11:26 -0500153 xfree (text);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000154
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
173_rl_fix_point (fix_mark_too)
174 int fix_mark_too;
175{
176 _RL_FIX_POINT (rl_point);
177 if (fix_mark_too)
178 _RL_FIX_POINT (rl_mark);
179}
180#undef _RL_FIX_POINT
181
Jari Aaltob80f6442004-07-27 13:29:18 +0000182/* Replace the contents of the line buffer between START and END with
183 TEXT. The operation is undoable. To replace the entire line in an
184 undoable mode, use _rl_replace_text(text, 0, rl_end); */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000185int
186_rl_replace_text (text, start, end)
187 const char *text;
188 int start, end;
189{
190 int n;
191
Chet Ramey00018032011-11-21 20:51:19 -0500192 n = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000193 rl_begin_undo_group ();
Chet Ramey00018032011-11-21 20:51:19 -0500194 if (start <= end)
195 rl_delete_text (start, end + 1);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000196 rl_point = start;
Chet Ramey00018032011-11-21 20:51:19 -0500197 if (*text)
198 n = rl_insert_text (text);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000199 rl_end_undo_group ();
200
201 return n;
202}
203
204/* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is
205 non-zero, we free the current undo list. */
206void
207rl_replace_line (text, clear_undo)
208 const char *text;
209 int clear_undo;
210{
211 int len;
212
213 len = strlen (text);
214 if (len >= rl_line_buffer_len)
215 rl_extend_line_buffer (len);
216 strcpy (rl_line_buffer, text);
217 rl_end = len;
218
219 if (clear_undo)
220 rl_free_undo_list ();
221
222 _rl_fix_point (1);
223}
224
225/* **************************************************************** */
226/* */
227/* Readline character functions */
228/* */
229/* **************************************************************** */
230
231/* This is not a gap editor, just a stupid line input routine. No hair
232 is involved in writing any of the functions, and none should be. */
233
234/* Note that:
235
236 rl_end is the place in the string that we would place '\0';
237 i.e., it is always safe to place '\0' there.
238
239 rl_point is the place in the string where the cursor is. Sometimes
240 this is the same as rl_end.
241
242 Any command that is called interactively receives two arguments.
Chet Rameyac50fba2014-02-26 09:36:43 -0500243 The first is a count: the numeric arg passed to this command.
Jari Aalto7117c2d2002-07-17 14:10:11 +0000244 The second is the key which invoked this command.
245*/
246
247/* **************************************************************** */
248/* */
249/* Movement Commands */
250/* */
251/* **************************************************************** */
252
253/* Note that if you `optimize' the display for these functions, you cannot
254 use said functions in other functions which do not do optimizing display.
255 I.e., you will have to update the data base for rl_redisplay, and you
256 might as well let rl_redisplay do that job. */
257
258/* Move forward COUNT bytes. */
259int
260rl_forward_byte (count, key)
261 int count, key;
262{
263 if (count < 0)
264 return (rl_backward_byte (-count, key));
265
266 if (count > 0)
267 {
Chet Ramey495aee42011-11-22 19:11:26 -0500268 int end, lend;
269
270 end = rl_point + count;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000271#if defined (VI_MODE)
Chet Ramey495aee42011-11-22 19:11:26 -0500272 lend = rl_end > 0 ? rl_end - (VI_COMMAND_MODE()) : rl_end;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000273#else
Chet Ramey495aee42011-11-22 19:11:26 -0500274 lend = rl_end;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000275#endif
276
277 if (end > lend)
278 {
279 rl_point = lend;
280 rl_ding ();
281 }
282 else
283 rl_point = end;
284 }
285
286 if (rl_end < 0)
287 rl_end = 0;
288
289 return 0;
290}
291
Chet Ramey495aee42011-11-22 19:11:26 -0500292int
293_rl_forward_char_internal (count)
294 int count;
295{
296 int point;
297
298#if defined (HANDLE_MULTIBYTE)
299 point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
300
301#if defined (VI_MODE)
302 if (point >= rl_end && VI_COMMAND_MODE())
303 point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
304#endif
305
306 if (rl_end < 0)
307 rl_end = 0;
308#else
309 point = rl_point + count;
310 if (point > rl_end)
311 point = rl_end;
312#endif
313
314 return (point);
315}
316
Jari Aalto7117c2d2002-07-17 14:10:11 +0000317#if defined (HANDLE_MULTIBYTE)
318/* Move forward COUNT characters. */
319int
320rl_forward_char (count, key)
321 int count, key;
322{
323 int point;
324
325 if (MB_CUR_MAX == 1 || rl_byte_oriented)
326 return (rl_forward_byte (count, key));
327
328 if (count < 0)
329 return (rl_backward_char (-count, key));
330
331 if (count > 0)
332 {
Jari Aalto31859422009-01-12 13:36:28 +0000333 if (rl_point == rl_end && EMACS_MODE())
334 {
335 rl_ding ();
336 return 0;
337 }
338
Chet Ramey495aee42011-11-22 19:11:26 -0500339 point = _rl_forward_char_internal (count);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000340
341 if (rl_point == point)
342 rl_ding ();
343
344 rl_point = point;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000345 }
346
347 return 0;
348}
349#else /* !HANDLE_MULTIBYTE */
350int
351rl_forward_char (count, key)
352 int count, key;
353{
354 return (rl_forward_byte (count, key));
355}
356#endif /* !HANDLE_MULTIBYTE */
357
358/* Backwards compatibility. */
359int
360rl_forward (count, key)
361 int count, key;
362{
363 return (rl_forward_char (count, key));
364}
365
366/* Move backward COUNT bytes. */
367int
368rl_backward_byte (count, key)
369 int count, key;
370{
371 if (count < 0)
372 return (rl_forward_byte (-count, key));
373
374 if (count > 0)
375 {
376 if (rl_point < count)
377 {
378 rl_point = 0;
379 rl_ding ();
380 }
381 else
382 rl_point -= count;
383 }
384
385 if (rl_point < 0)
386 rl_point = 0;
387
388 return 0;
389}
390
391#if defined (HANDLE_MULTIBYTE)
392/* Move backward COUNT characters. */
393int
394rl_backward_char (count, key)
395 int count, key;
396{
397 int point;
398
399 if (MB_CUR_MAX == 1 || rl_byte_oriented)
400 return (rl_backward_byte (count, key));
401
402 if (count < 0)
403 return (rl_forward_char (-count, key));
404
405 if (count > 0)
406 {
407 point = rl_point;
408
409 while (count > 0 && point > 0)
410 {
411 point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
412 count--;
413 }
414 if (count > 0)
415 {
416 rl_point = 0;
417 rl_ding ();
418 }
419 else
420 rl_point = point;
421 }
422
423 return 0;
424}
425#else
426int
427rl_backward_char (count, key)
428 int count, key;
429{
430 return (rl_backward_byte (count, key));
431}
432#endif
433
434/* Backwards compatibility. */
435int
436rl_backward (count, key)
437 int count, key;
438{
439 return (rl_backward_char (count, key));
440}
441
442/* Move to the beginning of the line. */
443int
444rl_beg_of_line (count, key)
445 int count, key;
446{
447 rl_point = 0;
448 return 0;
449}
450
451/* Move to the end of the line. */
452int
453rl_end_of_line (count, key)
454 int count, key;
455{
456 rl_point = rl_end;
457 return 0;
458}
459
Jari Aalto95732b42005-12-07 14:08:12 +0000460/* Move forward a word. We do what Emacs does. Handles multibyte chars. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000461int
462rl_forward_word (count, key)
463 int count, key;
464{
465 int c;
466
467 if (count < 0)
468 return (rl_backward_word (-count, key));
469
470 while (count)
471 {
472 if (rl_point == rl_end)
473 return 0;
474
475 /* If we are not in a word, move forward until we are in one.
476 Then, move forward until we hit a non-alphabetic character. */
Jari Aalto95732b42005-12-07 14:08:12 +0000477 c = _rl_char_value (rl_line_buffer, rl_point);
478
479 if (_rl_walphabetic (c) == 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000480 {
Jari Aalto95732b42005-12-07 14:08:12 +0000481 rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
482 while (rl_point < rl_end)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000483 {
Jari Aalto95732b42005-12-07 14:08:12 +0000484 c = _rl_char_value (rl_line_buffer, rl_point);
485 if (_rl_walphabetic (c))
Jari Aalto7117c2d2002-07-17 14:10:11 +0000486 break;
Jari Aalto95732b42005-12-07 14:08:12 +0000487 rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000488 }
489 }
490
491 if (rl_point == rl_end)
492 return 0;
493
Jari Aalto95732b42005-12-07 14:08:12 +0000494 rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
495 while (rl_point < rl_end)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000496 {
Jari Aalto95732b42005-12-07 14:08:12 +0000497 c = _rl_char_value (rl_line_buffer, rl_point);
498 if (_rl_walphabetic (c) == 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000499 break;
Jari Aalto95732b42005-12-07 14:08:12 +0000500 rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000501 }
Jari Aalto95732b42005-12-07 14:08:12 +0000502
Jari Aalto7117c2d2002-07-17 14:10:11 +0000503 --count;
504 }
505
506 return 0;
507}
508
Jari Aalto95732b42005-12-07 14:08:12 +0000509/* Move backward a word. We do what Emacs does. Handles multibyte chars. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000510int
511rl_backward_word (count, key)
512 int count, key;
513{
Jari Aalto95732b42005-12-07 14:08:12 +0000514 int c, p;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000515
516 if (count < 0)
517 return (rl_forward_word (-count, key));
518
519 while (count)
520 {
Jari Aalto95732b42005-12-07 14:08:12 +0000521 if (rl_point == 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000522 return 0;
523
524 /* Like rl_forward_word (), except that we look at the characters
525 just before point. */
526
Jari Aalto95732b42005-12-07 14:08:12 +0000527 p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
528 c = _rl_char_value (rl_line_buffer, p);
529
530 if (_rl_walphabetic (c) == 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000531 {
Jari Aalto95732b42005-12-07 14:08:12 +0000532 rl_point = p;
533 while (rl_point > 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000534 {
Jari Aalto95732b42005-12-07 14:08:12 +0000535 p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
536 c = _rl_char_value (rl_line_buffer, p);
537 if (_rl_walphabetic (c))
Jari Aalto7117c2d2002-07-17 14:10:11 +0000538 break;
Jari Aalto95732b42005-12-07 14:08:12 +0000539 rl_point = p;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000540 }
541 }
542
543 while (rl_point)
544 {
Jari Aalto95732b42005-12-07 14:08:12 +0000545 p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
546 c = _rl_char_value (rl_line_buffer, p);
547 if (_rl_walphabetic (c) == 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000548 break;
549 else
Jari Aalto95732b42005-12-07 14:08:12 +0000550 rl_point = p;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000551 }
552
553 --count;
554 }
555
556 return 0;
557}
558
559/* Clear the current line. Numeric argument to C-l does this. */
560int
561rl_refresh_line (ignore1, ignore2)
562 int ignore1, ignore2;
563{
564 int curr_line;
565
566 curr_line = _rl_current_display_line ();
567
568 _rl_move_vert (curr_line);
569 _rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */
570
571 _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */
572
573 rl_forced_update_display ();
574 rl_display_fixed = 1;
575
576 return 0;
577}
578
579/* C-l typed to a line without quoting clears the screen, and then reprints
580 the prompt and the current input line. Given a numeric arg, redraw only
581 the current line. */
582int
583rl_clear_screen (count, key)
584 int count, key;
585{
586 if (rl_explicit_arg)
587 {
588 rl_refresh_line (count, key);
589 return 0;
590 }
591
592 _rl_clear_screen (); /* calls termcap function to clear screen */
593 rl_forced_update_display ();
594 rl_display_fixed = 1;
595
596 return 0;
597}
598
599int
Chet Ramey00018032011-11-21 20:51:19 -0500600rl_skip_csi_sequence (count, key)
601 int count, key;
602{
603 int ch;
604
605 RL_SETSTATE (RL_STATE_MOREINPUT);
606 do
607 ch = rl_read_key ();
608 while (ch >= 0x20 && ch < 0x40);
609 RL_UNSETSTATE (RL_STATE_MOREINPUT);
610
611 return 0;
612}
613
614int
Jari Aalto7117c2d2002-07-17 14:10:11 +0000615rl_arrow_keys (count, c)
616 int count, c;
617{
618 int ch;
619
620 RL_SETSTATE(RL_STATE_MOREINPUT);
621 ch = rl_read_key ();
622 RL_UNSETSTATE(RL_STATE_MOREINPUT);
623
624 switch (_rl_to_upper (ch))
625 {
626 case 'A':
627 rl_get_previous_history (count, ch);
628 break;
629
630 case 'B':
631 rl_get_next_history (count, ch);
632 break;
633
634 case 'C':
635 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
636 rl_forward_char (count, ch);
637 else
638 rl_forward_byte (count, ch);
639 break;
640
641 case 'D':
642 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
643 rl_backward_char (count, ch);
644 else
645 rl_backward_byte (count, ch);
646 break;
647
648 default:
649 rl_ding ();
650 }
651
652 return 0;
653}
654
655/* **************************************************************** */
656/* */
657/* Text commands */
658/* */
659/* **************************************************************** */
660
661#ifdef HANDLE_MULTIBYTE
662static char pending_bytes[MB_LEN_MAX];
663static int pending_bytes_length = 0;
664static mbstate_t ps = {0};
665#endif
666
667/* Insert the character C at the current location, moving point forward.
668 If C introduces a multibyte sequence, we read the whole sequence and
669 then insert the multibyte char into the line buffer. */
670int
671_rl_insert_char (count, c)
672 int count, c;
673{
674 register int i;
675 char *string;
676#ifdef HANDLE_MULTIBYTE
677 int string_size;
678 char incoming[MB_LEN_MAX + 1];
679 int incoming_length = 0;
680 mbstate_t ps_back;
681 static int stored_count = 0;
682#endif
683
684 if (count <= 0)
685 return 0;
686
687#if defined (HANDLE_MULTIBYTE)
688 if (MB_CUR_MAX == 1 || rl_byte_oriented)
689 {
690 incoming[0] = c;
691 incoming[1] = '\0';
692 incoming_length = 1;
693 }
694 else
695 {
696 wchar_t wc;
697 size_t ret;
698
699 if (stored_count <= 0)
700 stored_count = count;
701 else
702 count = stored_count;
703
704 ps_back = ps;
705 pending_bytes[pending_bytes_length++] = c;
706 ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
707
708 if (ret == (size_t)-2)
709 {
710 /* Bytes too short to compose character, try to wait for next byte.
711 Restore the state of the byte sequence, because in this case the
712 effect of mbstate is undefined. */
713 ps = ps_back;
714 return 1;
715 }
716 else if (ret == (size_t)-1)
717 {
718 /* Invalid byte sequence for the current locale. Treat first byte
719 as a single character. */
720 incoming[0] = pending_bytes[0];
721 incoming[1] = '\0';
722 incoming_length = 1;
723 pending_bytes_length--;
724 memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
725 /* Clear the state of the byte sequence, because in this case the
726 effect of mbstate is undefined. */
727 memset (&ps, 0, sizeof (mbstate_t));
728 }
729 else if (ret == (size_t)0)
730 {
731 incoming[0] = '\0';
732 incoming_length = 0;
733 pending_bytes_length--;
734 /* Clear the state of the byte sequence, because in this case the
735 effect of mbstate is undefined. */
736 memset (&ps, 0, sizeof (mbstate_t));
737 }
738 else
739 {
740 /* We successfully read a single multibyte character. */
741 memcpy (incoming, pending_bytes, pending_bytes_length);
742 incoming[pending_bytes_length] = '\0';
743 incoming_length = pending_bytes_length;
744 pending_bytes_length = 0;
745 }
746 }
747#endif /* HANDLE_MULTIBYTE */
748
749 /* If we can optimize, then do it. But don't let people crash
750 readline because of extra large arguments. */
Chet Ramey00018032011-11-21 20:51:19 -0500751 if (count > 1 && count <= TEXT_COUNT_MAX)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000752 {
753#if defined (HANDLE_MULTIBYTE)
754 string_size = count * incoming_length;
755 string = (char *)xmalloc (1 + string_size);
756
757 i = 0;
758 while (i < string_size)
759 {
760 strncpy (string + i, incoming, incoming_length);
761 i += incoming_length;
762 }
763 incoming_length = 0;
764 stored_count = 0;
765#else /* !HANDLE_MULTIBYTE */
766 string = (char *)xmalloc (1 + count);
767
768 for (i = 0; i < count; i++)
769 string[i] = c;
770#endif /* !HANDLE_MULTIBYTE */
771
772 string[i] = '\0';
773 rl_insert_text (string);
Chet Ramey495aee42011-11-22 19:11:26 -0500774 xfree (string);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000775
776 return 0;
777 }
778
Chet Ramey00018032011-11-21 20:51:19 -0500779 if (count > TEXT_COUNT_MAX)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000780 {
781 int decreaser;
782#if defined (HANDLE_MULTIBYTE)
Chet Ramey00018032011-11-21 20:51:19 -0500783 string_size = incoming_length * TEXT_COUNT_MAX;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000784 string = (char *)xmalloc (1 + string_size);
785
786 i = 0;
787 while (i < string_size)
788 {
789 strncpy (string + i, incoming, incoming_length);
790 i += incoming_length;
791 }
792
793 while (count)
794 {
Chet Ramey00018032011-11-21 20:51:19 -0500795 decreaser = (count > TEXT_COUNT_MAX) ? TEXT_COUNT_MAX : count;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000796 string[decreaser*incoming_length] = '\0';
797 rl_insert_text (string);
798 count -= decreaser;
799 }
800
Chet Ramey495aee42011-11-22 19:11:26 -0500801 xfree (string);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000802 incoming_length = 0;
803 stored_count = 0;
804#else /* !HANDLE_MULTIBYTE */
Chet Ramey00018032011-11-21 20:51:19 -0500805 char str[TEXT_COUNT_MAX+1];
Jari Aalto7117c2d2002-07-17 14:10:11 +0000806
Chet Ramey00018032011-11-21 20:51:19 -0500807 for (i = 0; i < TEXT_COUNT_MAX; i++)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000808 str[i] = c;
809
810 while (count)
811 {
Chet Ramey00018032011-11-21 20:51:19 -0500812 decreaser = (count > TEXT_COUNT_MAX ? TEXT_COUNT_MAX : count);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000813 str[decreaser] = '\0';
814 rl_insert_text (str);
815 count -= decreaser;
816 }
817#endif /* !HANDLE_MULTIBYTE */
818
819 return 0;
820 }
821
Jari Aalto7117c2d2002-07-17 14:10:11 +0000822 if (MB_CUR_MAX == 1 || rl_byte_oriented)
823 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000824 /* We are inserting a single character.
825 If there is pending input, then make a string of all of the
826 pending characters that are bound to rl_insert, and insert
Chet Ramey495aee42011-11-22 19:11:26 -0500827 them all. Don't do this if we're current reading input from
828 a macro. */
Chet Rameyac50fba2014-02-26 09:36:43 -0500829 if ((RL_ISSTATE (RL_STATE_MACROINPUT) == 0) && _rl_pushed_input_available ())
Jari Aalto7117c2d2002-07-17 14:10:11 +0000830 _rl_insert_typein (c);
831 else
832 {
833 /* Inserting a single character. */
834 char str[2];
835
836 str[1] = '\0';
837 str[0] = c;
838 rl_insert_text (str);
839 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000840 }
Jari Aalto95732b42005-12-07 14:08:12 +0000841#if defined (HANDLE_MULTIBYTE)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000842 else
843 {
844 rl_insert_text (incoming);
845 stored_count = 0;
846 }
847#endif
848
849 return 0;
850}
851
852/* Overwrite the character at point (or next COUNT characters) with C.
853 If C introduces a multibyte character sequence, read the entire sequence
854 before starting the overwrite loop. */
855int
856_rl_overwrite_char (count, c)
857 int count, c;
858{
859 int i;
860#if defined (HANDLE_MULTIBYTE)
861 char mbkey[MB_LEN_MAX];
862 int k;
863
864 /* Read an entire multibyte character sequence to insert COUNT times. */
865 if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
866 k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
867#endif
868
Jari Aaltob80f6442004-07-27 13:29:18 +0000869 rl_begin_undo_group ();
870
Jari Aalto7117c2d2002-07-17 14:10:11 +0000871 for (i = 0; i < count; i++)
872 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000873#if defined (HANDLE_MULTIBYTE)
874 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
875 rl_insert_text (mbkey);
876 else
877#endif
878 _rl_insert_char (1, c);
879
Jari Aaltob80f6442004-07-27 13:29:18 +0000880 if (rl_point < rl_end)
881 rl_delete (1, c);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000882 }
883
Jari Aaltob80f6442004-07-27 13:29:18 +0000884 rl_end_undo_group ();
885
Jari Aalto7117c2d2002-07-17 14:10:11 +0000886 return 0;
887}
888
889int
890rl_insert (count, c)
891 int count, c;
892{
893 return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
894 : _rl_overwrite_char (count, c));
895}
896
897/* Insert the next typed character verbatim. */
Jari Aalto95732b42005-12-07 14:08:12 +0000898static int
899_rl_insert_next (count)
900 int count;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000901{
902 int c;
903
Jari Aalto7117c2d2002-07-17 14:10:11 +0000904 RL_SETSTATE(RL_STATE_MOREINPUT);
905 c = rl_read_key ();
906 RL_UNSETSTATE(RL_STATE_MOREINPUT);
907
Jari Aaltof1be6662008-11-18 13:15:12 +0000908 if (c < 0)
909 return -1;
910
Chet Rameyac50fba2014-02-26 09:36:43 -0500911 if (RL_ISSTATE (RL_STATE_MACRODEF))
912 _rl_add_macro_char (c);
913
Jari Aalto7117c2d2002-07-17 14:10:11 +0000914#if defined (HANDLE_SIGNALS)
Jari Aalto95732b42005-12-07 14:08:12 +0000915 if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
916 _rl_restore_tty_signals ();
Jari Aalto7117c2d2002-07-17 14:10:11 +0000917#endif
918
919 return (_rl_insert_char (count, c));
920}
921
Jari Aalto95732b42005-12-07 14:08:12 +0000922#if defined (READLINE_CALLBACKS)
923static int
924_rl_insert_next_callback (data)
925 _rl_callback_generic_arg *data;
926{
927 int count;
928
929 count = data->count;
930
931 /* Deregister function, let rl_callback_read_char deallocate data */
932 _rl_callback_func = 0;
933 _rl_want_redisplay = 1;
934
935 return _rl_insert_next (count);
936}
937#endif
938
939int
940rl_quoted_insert (count, key)
941 int count, key;
942{
943 /* Let's see...should the callback interface futz with signal handling? */
944#if defined (HANDLE_SIGNALS)
945 if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
946 _rl_disable_tty_signals ();
947#endif
948
949#if defined (READLINE_CALLBACKS)
950 if (RL_ISSTATE (RL_STATE_CALLBACK))
951 {
952 _rl_callback_data = _rl_callback_data_alloc (count);
953 _rl_callback_func = _rl_insert_next_callback;
954 return (0);
955 }
956#endif
957
958 return _rl_insert_next (count);
959}
960
Jari Aalto7117c2d2002-07-17 14:10:11 +0000961/* Insert a tab character. */
962int
963rl_tab_insert (count, key)
964 int count, key;
965{
966 return (_rl_insert_char (count, '\t'));
967}
968
969/* What to do when a NEWLINE is pressed. We accept the whole line.
970 KEY is the key that invoked this command. I guess it could have
971 meaning in the future. */
972int
973rl_newline (count, key)
974 int count, key;
975{
976 rl_done = 1;
977
978 if (_rl_history_preserve_point)
979 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
980
981 RL_SETSTATE(RL_STATE_DONE);
982
983#if defined (VI_MODE)
984 if (rl_editing_mode == vi_mode)
985 {
986 _rl_vi_done_inserting ();
Jari Aaltob80f6442004-07-27 13:29:18 +0000987 if (_rl_vi_textmod_command (_rl_vi_last_command) == 0) /* XXX */
988 _rl_vi_reset_last ();
Jari Aalto7117c2d2002-07-17 14:10:11 +0000989 }
990#endif /* VI_MODE */
991
992 /* If we've been asked to erase empty lines, suppress the final update,
993 since _rl_update_final calls rl_crlf(). */
994 if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
995 return 0;
996
Jari Aalto31859422009-01-12 13:36:28 +0000997 if (_rl_echoing_p)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000998 _rl_update_final ();
999 return 0;
1000}
1001
1002/* What to do for some uppercase characters, like meta characters,
1003 and some characters appearing in emacs_ctlx_keymap. This function
1004 is just a stub, you bind keys to it and the code in _rl_dispatch ()
1005 is special cased. */
1006int
1007rl_do_lowercase_version (ignore1, ignore2)
1008 int ignore1, ignore2;
1009{
1010 return 0;
1011}
1012
1013/* This is different from what vi does, so the code's not shared. Emacs
1014 rubout in overwrite mode has one oddity: it replaces a control
1015 character that's displayed as two characters (^X) with two spaces. */
1016int
1017_rl_overwrite_rubout (count, key)
1018 int count, key;
1019{
1020 int opoint;
1021 int i, l;
1022
1023 if (rl_point == 0)
1024 {
1025 rl_ding ();
1026 return 1;
1027 }
1028
1029 opoint = rl_point;
1030
1031 /* L == number of spaces to insert */
1032 for (i = l = 0; i < count; i++)
1033 {
1034 rl_backward_char (1, key);
1035 l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */
1036 }
1037
1038 rl_begin_undo_group ();
1039
1040 if (count > 1 || rl_explicit_arg)
1041 rl_kill_text (opoint, rl_point);
1042 else
1043 rl_delete_text (opoint, rl_point);
1044
1045 /* Emacs puts point at the beginning of the sequence of spaces. */
Jari Aaltob80f6442004-07-27 13:29:18 +00001046 if (rl_point < rl_end)
1047 {
1048 opoint = rl_point;
1049 _rl_insert_char (l, ' ');
1050 rl_point = opoint;
1051 }
Jari Aalto7117c2d2002-07-17 14:10:11 +00001052
1053 rl_end_undo_group ();
1054
1055 return 0;
1056}
1057
1058/* Rubout the character behind point. */
1059int
1060rl_rubout (count, key)
1061 int count, key;
1062{
1063 if (count < 0)
1064 return (rl_delete (-count, key));
1065
1066 if (!rl_point)
1067 {
1068 rl_ding ();
1069 return -1;
1070 }
1071
1072 if (rl_insert_mode == RL_IM_OVERWRITE)
1073 return (_rl_overwrite_rubout (count, key));
1074
1075 return (_rl_rubout_char (count, key));
1076}
1077
1078int
1079_rl_rubout_char (count, key)
1080 int count, key;
1081{
1082 int orig_point;
1083 unsigned char c;
1084
1085 /* Duplicated code because this is called from other parts of the library. */
1086 if (count < 0)
1087 return (rl_delete (-count, key));
1088
1089 if (rl_point == 0)
1090 {
1091 rl_ding ();
1092 return -1;
1093 }
1094
Jari Aalto95732b42005-12-07 14:08:12 +00001095 orig_point = rl_point;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001096 if (count > 1 || rl_explicit_arg)
1097 {
Jari Aalto95732b42005-12-07 14:08:12 +00001098 rl_backward_char (count, key);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001099 rl_kill_text (orig_point, rl_point);
1100 }
Jari Aalto95732b42005-12-07 14:08:12 +00001101 else if (MB_CUR_MAX == 1 || rl_byte_oriented)
Jari Aalto7117c2d2002-07-17 14:10:11 +00001102 {
Jari Aalto95732b42005-12-07 14:08:12 +00001103 c = rl_line_buffer[--rl_point];
1104 rl_delete_text (rl_point, orig_point);
1105 /* The erase-at-end-of-line hack is of questionable merit now. */
Jari Aalto7117c2d2002-07-17 14:10:11 +00001106 if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
1107 {
1108 int l;
1109 l = rl_character_len (c, rl_point);
1110 _rl_erase_at_end_of_line (l);
1111 }
1112 }
Jari Aalto95732b42005-12-07 14:08:12 +00001113 else
1114 {
1115 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1116 rl_delete_text (rl_point, orig_point);
1117 }
Jari Aalto7117c2d2002-07-17 14:10:11 +00001118
1119 return 0;
1120}
1121
1122/* Delete the character under the cursor. Given a numeric argument,
1123 kill that many characters instead. */
1124int
1125rl_delete (count, key)
1126 int count, key;
1127{
Jari Aalto06285672006-10-10 14:15:34 +00001128 int xpoint;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001129
1130 if (count < 0)
1131 return (_rl_rubout_char (-count, key));
1132
1133 if (rl_point == rl_end)
1134 {
1135 rl_ding ();
1136 return -1;
1137 }
1138
1139 if (count > 1 || rl_explicit_arg)
1140 {
Jari Aalto06285672006-10-10 14:15:34 +00001141 xpoint = rl_point;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001142 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1143 rl_forward_char (count, key);
1144 else
Jari Aalto7117c2d2002-07-17 14:10:11 +00001145 rl_forward_byte (count, key);
1146
Jari Aalto06285672006-10-10 14:15:34 +00001147 rl_kill_text (xpoint, rl_point);
1148 rl_point = xpoint;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001149 }
1150 else
1151 {
Jari Aalto06285672006-10-10 14:15:34 +00001152 xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
1153 rl_delete_text (rl_point, xpoint);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001154 }
Jari Aalto06285672006-10-10 14:15:34 +00001155 return 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001156}
1157
1158/* Delete the character under the cursor, unless the insertion
1159 point is at the end of the line, in which case the character
1160 behind the cursor is deleted. COUNT is obeyed and may be used
1161 to delete forward or backward that many characters. */
1162int
1163rl_rubout_or_delete (count, key)
1164 int count, key;
1165{
1166 if (rl_end != 0 && rl_point == rl_end)
1167 return (_rl_rubout_char (count, key));
1168 else
1169 return (rl_delete (count, key));
1170}
1171
1172/* Delete all spaces and tabs around point. */
1173int
1174rl_delete_horizontal_space (count, ignore)
1175 int count, ignore;
1176{
Chet Ramey00018032011-11-21 20:51:19 -05001177 int start;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001178
1179 while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
1180 rl_point--;
1181
1182 start = rl_point;
1183
1184 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1185 rl_point++;
1186
1187 if (start != rl_point)
1188 {
1189 rl_delete_text (start, rl_point);
1190 rl_point = start;
1191 }
Jari Aalto95732b42005-12-07 14:08:12 +00001192
1193 if (rl_point < 0)
1194 rl_point = 0;
1195
Jari Aalto7117c2d2002-07-17 14:10:11 +00001196 return 0;
1197}
1198
1199/* Like the tcsh editing function delete-char-or-list. The eof character
1200 is caught before this is invoked, so this really does the same thing as
1201 delete-char-or-list-or-eof, as long as it's bound to the eof character. */
1202int
1203rl_delete_or_show_completions (count, key)
1204 int count, key;
1205{
1206 if (rl_end != 0 && rl_point == rl_end)
1207 return (rl_possible_completions (count, key));
1208 else
1209 return (rl_delete (count, key));
1210}
1211
1212#ifndef RL_COMMENT_BEGIN_DEFAULT
1213#define RL_COMMENT_BEGIN_DEFAULT "#"
1214#endif
1215
1216/* Turn the current line into a comment in shell history.
1217 A K*rn shell style function. */
1218int
1219rl_insert_comment (count, key)
1220 int count, key;
1221{
1222 char *rl_comment_text;
1223 int rl_comment_len;
1224
1225 rl_beg_of_line (1, key);
1226 rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
1227
1228 if (rl_explicit_arg == 0)
1229 rl_insert_text (rl_comment_text);
1230 else
1231 {
1232 rl_comment_len = strlen (rl_comment_text);
1233 if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
1234 rl_delete_text (rl_point, rl_point + rl_comment_len);
1235 else
1236 rl_insert_text (rl_comment_text);
1237 }
1238
1239 (*rl_redisplay_function) ();
1240 rl_newline (1, '\n');
1241
1242 return (0);
1243}
1244
1245/* **************************************************************** */
1246/* */
1247/* Changing Case */
1248/* */
1249/* **************************************************************** */
1250
1251/* The three kinds of things that we know how to do. */
1252#define UpCase 1
1253#define DownCase 2
1254#define CapCase 3
1255
1256/* Uppercase the word at point. */
1257int
1258rl_upcase_word (count, key)
1259 int count, key;
1260{
1261 return (rl_change_case (count, UpCase));
1262}
1263
1264/* Lowercase the word at point. */
1265int
1266rl_downcase_word (count, key)
1267 int count, key;
1268{
1269 return (rl_change_case (count, DownCase));
1270}
1271
1272/* Upcase the first letter, downcase the rest. */
1273int
1274rl_capitalize_word (count, key)
1275 int count, key;
1276{
1277 return (rl_change_case (count, CapCase));
1278}
1279
1280/* The meaty function.
1281 Change the case of COUNT words, performing OP on them.
1282 OP is one of UpCase, DownCase, or CapCase.
1283 If a negative argument is given, leave point where it started,
1284 otherwise, leave it where it moves to. */
1285static int
1286rl_change_case (count, op)
1287 int count, op;
1288{
Jari Aalto95732b42005-12-07 14:08:12 +00001289 int start, next, end;
1290 int inword, c, nc, nop;
1291#if defined (HANDLE_MULTIBYTE)
1292 wchar_t wc, nwc;
1293 char mb[MB_LEN_MAX+1];
Jari Aalto06285672006-10-10 14:15:34 +00001294 int mlen;
Chet Ramey00018032011-11-21 20:51:19 -05001295 size_t m;
Jari Aalto06285672006-10-10 14:15:34 +00001296 mbstate_t mps;
Jari Aalto95732b42005-12-07 14:08:12 +00001297#endif
Jari Aalto7117c2d2002-07-17 14:10:11 +00001298
1299 start = rl_point;
1300 rl_forward_word (count, 0);
1301 end = rl_point;
1302
Jari Aalto95732b42005-12-07 14:08:12 +00001303 if (op != UpCase && op != DownCase && op != CapCase)
1304 {
1305 rl_ding ();
1306 return -1;
1307 }
1308
Jari Aalto7117c2d2002-07-17 14:10:11 +00001309 if (count < 0)
1310 SWAP (start, end);
1311
Jari Aalto95732b42005-12-07 14:08:12 +00001312#if defined (HANDLE_MULTIBYTE)
Jari Aalto06285672006-10-10 14:15:34 +00001313 memset (&mps, 0, sizeof (mbstate_t));
Jari Aalto95732b42005-12-07 14:08:12 +00001314#endif
1315
Jari Aalto7117c2d2002-07-17 14:10:11 +00001316 /* We are going to modify some text, so let's prepare to undo it. */
1317 rl_modifying (start, end);
1318
Jari Aalto95732b42005-12-07 14:08:12 +00001319 inword = 0;
1320 while (start < end)
Jari Aalto7117c2d2002-07-17 14:10:11 +00001321 {
Jari Aalto95732b42005-12-07 14:08:12 +00001322 c = _rl_char_value (rl_line_buffer, start);
1323 /* This assumes that the upper and lower case versions are the same width. */
1324 next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO);
1325
1326 if (_rl_walphabetic (c) == 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +00001327 {
Jari Aalto95732b42005-12-07 14:08:12 +00001328 inword = 0;
1329 start = next;
1330 continue;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001331 }
Jari Aalto95732b42005-12-07 14:08:12 +00001332
1333 if (op == CapCase)
1334 {
1335 nop = inword ? DownCase : UpCase;
1336 inword = 1;
1337 }
1338 else
1339 nop = op;
1340 if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c))
1341 {
1342 nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c);
1343 rl_line_buffer[start] = nc;
1344 }
1345#if defined (HANDLE_MULTIBYTE)
1346 else
1347 {
Chet Ramey00018032011-11-21 20:51:19 -05001348 m = mbrtowc (&wc, rl_line_buffer + start, end - start, &mps);
1349 if (MB_INVALIDCH (m))
1350 wc = (wchar_t)rl_line_buffer[start];
1351 else if (MB_NULLWCH (m))
1352 wc = L'\0';
Jari Aalto95732b42005-12-07 14:08:12 +00001353 nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
1354 if (nwc != wc) /* just skip unchanged characters */
1355 {
Jari Aalto06285672006-10-10 14:15:34 +00001356 mlen = wcrtomb (mb, nwc, &mps);
1357 if (mlen > 0)
1358 mb[mlen] = '\0';
Jari Aalto95732b42005-12-07 14:08:12 +00001359 /* Assume the same width */
Jari Aalto06285672006-10-10 14:15:34 +00001360 strncpy (rl_line_buffer + start, mb, mlen);
Jari Aalto95732b42005-12-07 14:08:12 +00001361 }
1362 }
1363#endif
1364
1365 start = next;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001366 }
Jari Aalto95732b42005-12-07 14:08:12 +00001367
Jari Aalto7117c2d2002-07-17 14:10:11 +00001368 rl_point = end;
1369 return 0;
1370}
1371
1372/* **************************************************************** */
1373/* */
1374/* Transposition */
1375/* */
1376/* **************************************************************** */
1377
1378/* Transpose the words at point. If point is at the end of the line,
1379 transpose the two words before point. */
1380int
1381rl_transpose_words (count, key)
1382 int count, key;
1383{
1384 char *word1, *word2;
1385 int w1_beg, w1_end, w2_beg, w2_end;
1386 int orig_point = rl_point;
1387
1388 if (!count)
1389 return 0;
1390
1391 /* Find the two words. */
1392 rl_forward_word (count, key);
1393 w2_end = rl_point;
1394 rl_backward_word (1, key);
1395 w2_beg = rl_point;
1396 rl_backward_word (count, key);
1397 w1_beg = rl_point;
1398 rl_forward_word (1, key);
1399 w1_end = rl_point;
1400
1401 /* Do some check to make sure that there really are two words. */
1402 if ((w1_beg == w2_beg) || (w2_beg < w1_end))
1403 {
1404 rl_ding ();
1405 rl_point = orig_point;
1406 return -1;
1407 }
1408
1409 /* Get the text of the words. */
1410 word1 = rl_copy_text (w1_beg, w1_end);
1411 word2 = rl_copy_text (w2_beg, w2_end);
1412
1413 /* We are about to do many insertions and deletions. Remember them
1414 as one operation. */
1415 rl_begin_undo_group ();
1416
1417 /* Do the stuff at word2 first, so that we don't have to worry
1418 about word1 moving. */
1419 rl_point = w2_beg;
1420 rl_delete_text (w2_beg, w2_end);
1421 rl_insert_text (word1);
1422
1423 rl_point = w1_beg;
1424 rl_delete_text (w1_beg, w1_end);
1425 rl_insert_text (word2);
1426
1427 /* This is exactly correct since the text before this point has not
1428 changed in length. */
1429 rl_point = w2_end;
1430
1431 /* I think that does it. */
1432 rl_end_undo_group ();
Chet Ramey495aee42011-11-22 19:11:26 -05001433 xfree (word1);
1434 xfree (word2);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001435
1436 return 0;
1437}
1438
1439/* Transpose the characters at point. If point is at the end of the line,
1440 then transpose the characters before point. */
1441int
1442rl_transpose_chars (count, key)
1443 int count, key;
1444{
1445#if defined (HANDLE_MULTIBYTE)
1446 char *dummy;
Jari Aalto95732b42005-12-07 14:08:12 +00001447 int i;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001448#else
1449 char dummy[2];
1450#endif
Jari Aalto95732b42005-12-07 14:08:12 +00001451 int char_length, prev_point;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001452
1453 if (count == 0)
1454 return 0;
1455
1456 if (!rl_point || rl_end < 2)
1457 {
1458 rl_ding ();
1459 return -1;
1460 }
1461
1462 rl_begin_undo_group ();
1463
1464 if (rl_point == rl_end)
1465 {
Jari Aalto95732b42005-12-07 14:08:12 +00001466 rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001467 count = 1;
1468 }
1469
Jari Aalto7117c2d2002-07-17 14:10:11 +00001470 prev_point = rl_point;
Jari Aalto95732b42005-12-07 14:08:12 +00001471 rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001472
1473#if defined (HANDLE_MULTIBYTE)
1474 char_length = prev_point - rl_point;
1475 dummy = (char *)xmalloc (char_length + 1);
1476 for (i = 0; i < char_length; i++)
1477 dummy[i] = rl_line_buffer[rl_point + i];
1478 dummy[i] = '\0';
1479#else
1480 dummy[0] = rl_line_buffer[rl_point];
1481 dummy[char_length = 1] = '\0';
1482#endif
1483
1484 rl_delete_text (rl_point, rl_point + char_length);
1485
1486 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1487
1488 _rl_fix_point (0);
1489 rl_insert_text (dummy);
1490 rl_end_undo_group ();
1491
1492#if defined (HANDLE_MULTIBYTE)
Chet Ramey495aee42011-11-22 19:11:26 -05001493 xfree (dummy);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001494#endif
1495
1496 return 0;
1497}
1498
1499/* **************************************************************** */
1500/* */
1501/* Character Searching */
1502/* */
1503/* **************************************************************** */
1504
1505int
1506#if defined (HANDLE_MULTIBYTE)
1507_rl_char_search_internal (count, dir, smbchar, len)
1508 int count, dir;
1509 char *smbchar;
1510 int len;
1511#else
1512_rl_char_search_internal (count, dir, schar)
1513 int count, dir, schar;
1514#endif
1515{
1516 int pos, inc;
1517#if defined (HANDLE_MULTIBYTE)
1518 int prepos;
1519#endif
1520
Chet Ramey495aee42011-11-22 19:11:26 -05001521 if (dir == 0)
1522 return -1;
1523
Jari Aalto7117c2d2002-07-17 14:10:11 +00001524 pos = rl_point;
1525 inc = (dir < 0) ? -1 : 1;
1526 while (count)
1527 {
1528 if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
1529 {
1530 rl_ding ();
1531 return -1;
1532 }
1533
1534#if defined (HANDLE_MULTIBYTE)
1535 pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
1536 : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1537#else
1538 pos += inc;
1539#endif
1540 do
1541 {
1542#if defined (HANDLE_MULTIBYTE)
1543 if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
1544#else
1545 if (rl_line_buffer[pos] == schar)
1546#endif
1547 {
1548 count--;
1549 if (dir < 0)
1550 rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
1551 : pos;
1552 else
1553 rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
1554 : pos;
1555 break;
1556 }
1557#if defined (HANDLE_MULTIBYTE)
1558 prepos = pos;
1559#endif
1560 }
1561#if defined (HANDLE_MULTIBYTE)
1562 while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
1563 : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
1564#else
1565 while ((dir < 0) ? pos-- : ++pos < rl_end);
1566#endif
1567 }
1568 return (0);
1569}
1570
1571/* Search COUNT times for a character read from the current input stream.
1572 FDIR is the direction to search if COUNT is non-negative; otherwise
1573 the search goes in BDIR. So much is dependent on HANDLE_MULTIBYTE
1574 that there are two separate versions of this function. */
1575#if defined (HANDLE_MULTIBYTE)
1576static int
1577_rl_char_search (count, fdir, bdir)
1578 int count, fdir, bdir;
1579{
1580 char mbchar[MB_LEN_MAX];
1581 int mb_len;
1582
1583 mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
1584
Jari Aaltof1be6662008-11-18 13:15:12 +00001585 if (mb_len <= 0)
1586 return -1;
1587
Jari Aalto7117c2d2002-07-17 14:10:11 +00001588 if (count < 0)
1589 return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
1590 else
1591 return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
1592}
1593#else /* !HANDLE_MULTIBYTE */
1594static int
1595_rl_char_search (count, fdir, bdir)
1596 int count, fdir, bdir;
1597{
1598 int c;
1599
1600 RL_SETSTATE(RL_STATE_MOREINPUT);
1601 c = rl_read_key ();
1602 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1603
Jari Aaltof1be6662008-11-18 13:15:12 +00001604 if (c < 0)
1605 return -1;
1606
Jari Aalto7117c2d2002-07-17 14:10:11 +00001607 if (count < 0)
1608 return (_rl_char_search_internal (-count, bdir, c));
1609 else
1610 return (_rl_char_search_internal (count, fdir, c));
1611}
1612#endif /* !HANDLE_MULTIBYTE */
1613
Jari Aalto95732b42005-12-07 14:08:12 +00001614#if defined (READLINE_CALLBACKS)
1615static int
1616_rl_char_search_callback (data)
1617 _rl_callback_generic_arg *data;
1618{
1619 _rl_callback_func = 0;
1620 _rl_want_redisplay = 1;
1621
1622 return (_rl_char_search (data->count, data->i1, data->i2));
1623}
1624#endif
1625
Jari Aalto7117c2d2002-07-17 14:10:11 +00001626int
1627rl_char_search (count, key)
1628 int count, key;
1629{
Jari Aalto95732b42005-12-07 14:08:12 +00001630#if defined (READLINE_CALLBACKS)
1631 if (RL_ISSTATE (RL_STATE_CALLBACK))
1632 {
1633 _rl_callback_data = _rl_callback_data_alloc (count);
1634 _rl_callback_data->i1 = FFIND;
1635 _rl_callback_data->i2 = BFIND;
1636 _rl_callback_func = _rl_char_search_callback;
1637 return (0);
1638 }
1639#endif
1640
Jari Aalto7117c2d2002-07-17 14:10:11 +00001641 return (_rl_char_search (count, FFIND, BFIND));
1642}
1643
1644int
1645rl_backward_char_search (count, key)
1646 int count, key;
1647{
Jari Aalto95732b42005-12-07 14:08:12 +00001648#if defined (READLINE_CALLBACKS)
1649 if (RL_ISSTATE (RL_STATE_CALLBACK))
1650 {
1651 _rl_callback_data = _rl_callback_data_alloc (count);
1652 _rl_callback_data->i1 = BFIND;
1653 _rl_callback_data->i2 = FFIND;
1654 _rl_callback_func = _rl_char_search_callback;
1655 return (0);
1656 }
1657#endif
1658
Jari Aalto7117c2d2002-07-17 14:10:11 +00001659 return (_rl_char_search (count, BFIND, FFIND));
1660}
1661
1662/* **************************************************************** */
1663/* */
1664/* The Mark and the Region. */
1665/* */
1666/* **************************************************************** */
1667
1668/* Set the mark at POSITION. */
1669int
1670_rl_set_mark_at_pos (position)
1671 int position;
1672{
1673 if (position > rl_end)
1674 return -1;
1675
1676 rl_mark = position;
1677 return 0;
1678}
1679
1680/* A bindable command to set the mark. */
1681int
1682rl_set_mark (count, key)
1683 int count, key;
1684{
1685 return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
1686}
1687
1688/* Exchange the position of mark and point. */
1689int
1690rl_exchange_point_and_mark (count, key)
1691 int count, key;
1692{
1693 if (rl_mark > rl_end)
1694 rl_mark = -1;
1695
1696 if (rl_mark == -1)
1697 {
1698 rl_ding ();
1699 return -1;
1700 }
1701 else
1702 SWAP (rl_point, rl_mark);
1703
1704 return 0;
1705}