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