xref: /openbsd/gnu/lib/libreadline/text.c (revision 9704b281)
1 /* text.c -- text handling commands for readline. */
2 
3 /* Copyright (C) 1987-2002 Free Software Foundation, Inc.
4 
5    This file is part of the GNU Readline Library, a library for
6    reading lines of text with interactive input and history editing.
7 
8    The GNU Readline Library is free software; you can redistribute it
9    and/or modify it under the terms of the GNU General Public License
10    as published by the Free Software Foundation; either version 2, or
11    (at your option) any later version.
12 
13    The GNU Readline Library is distributed in the hope that it will be
14    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    The GNU General Public License is often shipped with GNU software, and
19    is generally kept in a file called COPYING or LICENSE.  If you do not
20    have a copy of the license, write to the Free Software Foundation,
21    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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 /* **************************************************************** */
66 /*								    */
67 /*			Insert and Delete			    */
68 /*								    */
69 /* **************************************************************** */
70 
71 /* Insert a string of text into the line at point.  This is the only
72    way that you should do insertion.  _rl_insert_char () calls this
73    function.  Returns the number of characters inserted. */
74 int
rl_insert_text(string)75 rl_insert_text (string)
76      const char *string;
77 {
78   register int i, l;
79 
80   l = (string && *string) ? strlen (string) : 0;
81   if (l == 0)
82     return 0;
83 
84   if (rl_end + l >= rl_line_buffer_len)
85     rl_extend_line_buffer (rl_end + l);
86 
87   for (i = rl_end; i >= rl_point; i--)
88     rl_line_buffer[i + l] = rl_line_buffer[i];
89   strncpy (rl_line_buffer + rl_point, string, l);
90 
91   /* Remember how to undo this if we aren't undoing something. */
92   if (_rl_doing_an_undo == 0)
93     {
94       /* If possible and desirable, concatenate the undos. */
95       if ((l == 1) &&
96 	  rl_undo_list &&
97 	  (rl_undo_list->what == UNDO_INSERT) &&
98 	  (rl_undo_list->end == rl_point) &&
99 	  (rl_undo_list->end - rl_undo_list->start < 20))
100 	rl_undo_list->end++;
101       else
102 	rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
103     }
104   rl_point += l;
105   rl_end += l;
106   rl_line_buffer[rl_end] = '\0';
107   return l;
108 }
109 
110 /* Delete the string between FROM and TO.  FROM is inclusive, TO is not.
111    Returns the number of characters deleted. */
112 int
rl_delete_text(from,to)113 rl_delete_text (from, to)
114      int from, to;
115 {
116   register char *text;
117   register int diff, i;
118 
119   /* Fix it if the caller is confused. */
120   if (from > to)
121     SWAP (from, to);
122 
123   /* fix boundaries */
124   if (to > rl_end)
125     {
126       to = rl_end;
127       if (from > to)
128 	from = to;
129     }
130   if (from < 0)
131     from = 0;
132 
133   text = rl_copy_text (from, to);
134 
135   /* Some versions of strncpy() can't handle overlapping arguments. */
136   diff = to - from;
137   for (i = from; i < rl_end - diff; i++)
138     rl_line_buffer[i] = rl_line_buffer[i + diff];
139 
140   /* Remember how to undo this delete. */
141   if (_rl_doing_an_undo == 0)
142     rl_add_undo (UNDO_DELETE, from, to, text);
143   else
144     free (text);
145 
146   rl_end -= diff;
147   rl_line_buffer[rl_end] = '\0';
148   return (diff);
149 }
150 
151 /* Fix up point so that it is within the line boundaries after killing
152    text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
153    boundaries also. */
154 
155 #define _RL_FIX_POINT(x) \
156 	do { \
157 	if (x > rl_end) \
158 	  x = rl_end; \
159 	else if (x < 0) \
160 	  x = 0; \
161 	} while (0)
162 
163 void
_rl_fix_point(fix_mark_too)164 _rl_fix_point (fix_mark_too)
165      int fix_mark_too;
166 {
167   _RL_FIX_POINT (rl_point);
168   if (fix_mark_too)
169     _RL_FIX_POINT (rl_mark);
170 }
171 #undef _RL_FIX_POINT
172 
173 int
_rl_replace_text(text,start,end)174 _rl_replace_text (text, start, end)
175      const char *text;
176      int start, end;
177 {
178   int n;
179 
180   rl_begin_undo_group ();
181   rl_delete_text (start, end + 1);
182   rl_point = start;
183   n = rl_insert_text (text);
184   rl_end_undo_group ();
185 
186   return n;
187 }
188 
189 /* Replace the current line buffer contents with TEXT.  If CLEAR_UNDO is
190    non-zero, we free the current undo list. */
191 void
rl_replace_line(text,clear_undo)192 rl_replace_line (text, clear_undo)
193      const char *text;
194      int clear_undo;
195 {
196   int len;
197 
198   len = strlen (text);
199   if (len >= rl_line_buffer_len)
200     rl_extend_line_buffer (len);
201   strlcpy (rl_line_buffer, text, rl_line_buffer_len);
202   rl_end = len;
203 
204   if (clear_undo)
205     rl_free_undo_list ();
206 
207   _rl_fix_point (1);
208 }
209 
210 /* **************************************************************** */
211 /*								    */
212 /*			Readline character functions		    */
213 /*								    */
214 /* **************************************************************** */
215 
216 /* This is not a gap editor, just a stupid line input routine.  No hair
217    is involved in writing any of the functions, and none should be. */
218 
219 /* Note that:
220 
221    rl_end is the place in the string that we would place '\0';
222    i.e., it is always safe to place '\0' there.
223 
224    rl_point is the place in the string where the cursor is.  Sometimes
225    this is the same as rl_end.
226 
227    Any command that is called interactively receives two arguments.
228    The first is a count: the numeric arg pased to this command.
229    The second is the key which invoked this command.
230 */
231 
232 /* **************************************************************** */
233 /*								    */
234 /*			Movement Commands			    */
235 /*								    */
236 /* **************************************************************** */
237 
238 /* Note that if you `optimize' the display for these functions, you cannot
239    use said functions in other functions which do not do optimizing display.
240    I.e., you will have to update the data base for rl_redisplay, and you
241    might as well let rl_redisplay do that job. */
242 
243 /* Move forward COUNT bytes. */
244 int
rl_forward_byte(count,key)245 rl_forward_byte (count, key)
246      int count, key;
247 {
248   if (count < 0)
249     return (rl_backward_byte (-count, key));
250 
251   if (count > 0)
252     {
253       int end = rl_point + count;
254 #if defined (VI_MODE)
255       int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
256 #else
257       int lend = rl_end;
258 #endif
259 
260       if (end > lend)
261 	{
262 	  rl_point = lend;
263 	  rl_ding ();
264 	}
265       else
266 	rl_point = end;
267     }
268 
269   if (rl_end < 0)
270     rl_end = 0;
271 
272   return 0;
273 }
274 
275 #if defined (HANDLE_MULTIBYTE)
276 /* Move forward COUNT characters. */
277 int
rl_forward_char(count,key)278 rl_forward_char (count, key)
279      int count, key;
280 {
281   int point;
282 
283   if (MB_CUR_MAX == 1 || rl_byte_oriented)
284     return (rl_forward_byte (count, key));
285 
286   if (count < 0)
287     return (rl_backward_char (-count, key));
288 
289   if (count > 0)
290     {
291       point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
292 
293 #if defined (VI_MODE)
294       if (rl_end <= point && rl_editing_mode == vi_mode)
295 	point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
296 #endif
297 
298       if (rl_point == point)
299 	rl_ding ();
300 
301       rl_point = point;
302 
303       if (rl_end < 0)
304 	rl_end = 0;
305     }
306 
307   return 0;
308 }
309 #else /* !HANDLE_MULTIBYTE */
310 int
rl_forward_char(count,key)311 rl_forward_char (count, key)
312      int count, key;
313 {
314   return (rl_forward_byte (count, key));
315 }
316 #endif /* !HANDLE_MULTIBYTE */
317 
318 /* Backwards compatibility. */
319 int
rl_forward(count,key)320 rl_forward (count, key)
321      int count, key;
322 {
323   return (rl_forward_char (count, key));
324 }
325 
326 /* Move backward COUNT bytes. */
327 int
rl_backward_byte(count,key)328 rl_backward_byte (count, key)
329      int count, key;
330 {
331   if (count < 0)
332     return (rl_forward_byte (-count, key));
333 
334   if (count > 0)
335     {
336       if (rl_point < count)
337 	{
338 	  rl_point = 0;
339 	  rl_ding ();
340 	}
341       else
342 	rl_point -= count;
343     }
344 
345   if (rl_point < 0)
346     rl_point = 0;
347 
348   return 0;
349 }
350 
351 #if defined (HANDLE_MULTIBYTE)
352 /* Move backward COUNT characters. */
353 int
rl_backward_char(count,key)354 rl_backward_char (count, key)
355      int count, key;
356 {
357   int point;
358 
359   if (MB_CUR_MAX == 1 || rl_byte_oriented)
360     return (rl_backward_byte (count, key));
361 
362   if (count < 0)
363     return (rl_forward_char (-count, key));
364 
365   if (count > 0)
366     {
367       point = rl_point;
368 
369       while (count > 0 && point > 0)
370 	{
371 	  point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
372 	  count--;
373 	}
374       if (count > 0)
375 	{
376 	  rl_point = 0;
377 	  rl_ding ();
378 	}
379       else
380         rl_point = point;
381     }
382 
383   return 0;
384 }
385 #else
386 int
rl_backward_char(count,key)387 rl_backward_char (count, key)
388      int count, key;
389 {
390   return (rl_backward_byte (count, key));
391 }
392 #endif
393 
394 /* Backwards compatibility. */
395 int
rl_backward(count,key)396 rl_backward (count, key)
397      int count, key;
398 {
399   return (rl_backward_char (count, key));
400 }
401 
402 /* Move to the beginning of the line. */
403 int
rl_beg_of_line(count,key)404 rl_beg_of_line (count, key)
405      int count, key;
406 {
407   rl_point = 0;
408   return 0;
409 }
410 
411 /* Move to the end of the line. */
412 int
rl_end_of_line(count,key)413 rl_end_of_line (count, key)
414      int count, key;
415 {
416   rl_point = rl_end;
417   return 0;
418 }
419 
420 /* XXX - these might need changes for multibyte characters */
421 /* Move forward a word.  We do what Emacs does. */
422 int
rl_forward_word(count,key)423 rl_forward_word (count, key)
424      int count, key;
425 {
426   int c;
427 
428   if (count < 0)
429     return (rl_backward_word (-count, key));
430 
431   while (count)
432     {
433       if (rl_point == rl_end)
434 	return 0;
435 
436       /* If we are not in a word, move forward until we are in one.
437 	 Then, move forward until we hit a non-alphabetic character. */
438       c = rl_line_buffer[rl_point];
439       if (rl_alphabetic (c) == 0)
440 	{
441 	  while (++rl_point < rl_end)
442 	    {
443 	      c = rl_line_buffer[rl_point];
444 	      if (rl_alphabetic (c))
445 		break;
446 	    }
447 	}
448 
449       if (rl_point == rl_end)
450 	return 0;
451 
452       while (++rl_point < rl_end)
453 	{
454 	  c = rl_line_buffer[rl_point];
455 	  if (rl_alphabetic (c) == 0)
456 	    break;
457 	}
458       --count;
459     }
460 
461   return 0;
462 }
463 
464 /* Move backward a word.  We do what Emacs does. */
465 int
rl_backward_word(count,key)466 rl_backward_word (count, key)
467      int count, key;
468 {
469   int c;
470 
471   if (count < 0)
472     return (rl_forward_word (-count, key));
473 
474   while (count)
475     {
476       if (!rl_point)
477 	return 0;
478 
479       /* Like rl_forward_word (), except that we look at the characters
480 	 just before point. */
481 
482       c = rl_line_buffer[rl_point - 1];
483       if (rl_alphabetic (c) == 0)
484 	{
485 	  while (--rl_point)
486 	    {
487 	      c = rl_line_buffer[rl_point - 1];
488 	      if (rl_alphabetic (c))
489 		break;
490 	    }
491 	}
492 
493       while (rl_point)
494 	{
495 	  c = rl_line_buffer[rl_point - 1];
496 	  if (rl_alphabetic (c) == 0)
497 	    break;
498 	  else
499 	    --rl_point;
500 	}
501 
502       --count;
503     }
504 
505   return 0;
506 }
507 
508 /* Clear the current line.  Numeric argument to C-l does this. */
509 int
rl_refresh_line(ignore1,ignore2)510 rl_refresh_line (ignore1, ignore2)
511      int ignore1, ignore2;
512 {
513   int curr_line;
514 
515   curr_line = _rl_current_display_line ();
516 
517   _rl_move_vert (curr_line);
518   _rl_move_cursor_relative (0, rl_line_buffer);   /* XXX is this right */
519 
520   _rl_clear_to_eol (0);		/* arg of 0 means to not use spaces */
521 
522   rl_forced_update_display ();
523   rl_display_fixed = 1;
524 
525   return 0;
526 }
527 
528 /* C-l typed to a line without quoting clears the screen, and then reprints
529    the prompt and the current input line.  Given a numeric arg, redraw only
530    the current line. */
531 int
rl_clear_screen(count,key)532 rl_clear_screen (count, key)
533      int count, key;
534 {
535   if (rl_explicit_arg)
536     {
537       rl_refresh_line (count, key);
538       return 0;
539     }
540 
541   _rl_clear_screen ();		/* calls termcap function to clear screen */
542   rl_forced_update_display ();
543   rl_display_fixed = 1;
544 
545   return 0;
546 }
547 
548 int
rl_arrow_keys(count,c)549 rl_arrow_keys (count, c)
550      int count, c;
551 {
552   int ch;
553 
554   RL_SETSTATE(RL_STATE_MOREINPUT);
555   ch = rl_read_key ();
556   RL_UNSETSTATE(RL_STATE_MOREINPUT);
557 
558   switch (_rl_to_upper (ch))
559     {
560     case 'A':
561       rl_get_previous_history (count, ch);
562       break;
563 
564     case 'B':
565       rl_get_next_history (count, ch);
566       break;
567 
568     case 'C':
569       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
570 	rl_forward_char (count, ch);
571       else
572 	rl_forward_byte (count, ch);
573       break;
574 
575     case 'D':
576       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
577 	rl_backward_char (count, ch);
578       else
579 	rl_backward_byte (count, ch);
580       break;
581 
582     default:
583       rl_ding ();
584     }
585 
586   return 0;
587 }
588 
589 /* **************************************************************** */
590 /*								    */
591 /*			Text commands				    */
592 /*								    */
593 /* **************************************************************** */
594 
595 #ifdef HANDLE_MULTIBYTE
596 static char pending_bytes[MB_LEN_MAX];
597 static int pending_bytes_length = 0;
598 static mbstate_t ps = {0};
599 #endif
600 
601 /* Insert the character C at the current location, moving point forward.
602    If C introduces a multibyte sequence, we read the whole sequence and
603    then insert the multibyte char into the line buffer. */
604 int
_rl_insert_char(count,c)605 _rl_insert_char (count, c)
606      int count, c;
607 {
608   register int i;
609   char *string;
610 #ifdef HANDLE_MULTIBYTE
611   int string_size;
612   char incoming[MB_LEN_MAX + 1];
613   int incoming_length = 0;
614   mbstate_t ps_back;
615   static int stored_count = 0;
616 #endif
617 
618   if (count <= 0)
619     return 0;
620 
621 #if defined (HANDLE_MULTIBYTE)
622   if (MB_CUR_MAX == 1 || rl_byte_oriented)
623     {
624       incoming[0] = c;
625       incoming[1] = '\0';
626       incoming_length = 1;
627     }
628   else
629     {
630       wchar_t wc;
631       size_t ret;
632 
633       if (stored_count <= 0)
634 	stored_count = count;
635       else
636 	count = stored_count;
637 
638       ps_back = ps;
639       pending_bytes[pending_bytes_length++] = c;
640       ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
641 
642       if (ret == (size_t)-2)
643 	{
644 	  /* Bytes too short to compose character, try to wait for next byte.
645 	     Restore the state of the byte sequence, because in this case the
646 	     effect of mbstate is undefined. */
647 	  ps = ps_back;
648 	  return 1;
649 	}
650       else if (ret == (size_t)-1)
651 	{
652 	  /* Invalid byte sequence for the current locale.  Treat first byte
653 	     as a single character. */
654 	  incoming[0] = pending_bytes[0];
655 	  incoming[1] = '\0';
656 	  incoming_length = 1;
657 	  pending_bytes_length--;
658 	  memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
659 	  /* Clear the state of the byte sequence, because in this case the
660 	     effect of mbstate is undefined. */
661 	  memset (&ps, 0, sizeof (mbstate_t));
662 	}
663       else if (ret == (size_t)0)
664 	{
665 	  incoming[0] = '\0';
666 	  incoming_length = 0;
667 	  pending_bytes_length--;
668 	  /* Clear the state of the byte sequence, because in this case the
669 	     effect of mbstate is undefined. */
670 	  memset (&ps, 0, sizeof (mbstate_t));
671 	}
672       else
673 	{
674 	  /* We successfully read a single multibyte character. */
675 	  memcpy (incoming, pending_bytes, pending_bytes_length);
676 	  incoming[pending_bytes_length] = '\0';
677 	  incoming_length = pending_bytes_length;
678 	  pending_bytes_length = 0;
679 	}
680     }
681 #endif /* HANDLE_MULTIBYTE */
682 
683   /* If we can optimize, then do it.  But don't let people crash
684      readline because of extra large arguments. */
685   if (count > 1 && count <= 1024)
686     {
687 #if defined (HANDLE_MULTIBYTE)
688       string_size = count * incoming_length;
689       string = (char *)xmalloc (1 + string_size);
690 
691       i = 0;
692       while (i < string_size)
693 	{
694 	  strncpy (string + i, incoming, incoming_length);
695 	  i += incoming_length;
696 	}
697       incoming_length = 0;
698       stored_count = 0;
699 #else /* !HANDLE_MULTIBYTE */
700       string = (char *)xmalloc (1 + count);
701 
702       for (i = 0; i < count; i++)
703 	string[i] = c;
704 #endif /* !HANDLE_MULTIBYTE */
705 
706       string[i] = '\0';
707       rl_insert_text (string);
708       free (string);
709 
710       return 0;
711     }
712 
713   if (count > 1024)
714     {
715       int decreaser;
716 #if defined (HANDLE_MULTIBYTE)
717       string_size = incoming_length * 1024;
718       string = (char *)xmalloc (1 + string_size);
719 
720       i = 0;
721       while (i < string_size)
722 	{
723 	  strncpy (string + i, incoming, incoming_length);
724 	  i += incoming_length;
725 	}
726 
727       while (count)
728 	{
729 	  decreaser = (count > 1024) ? 1024 : count;
730 	  string[decreaser*incoming_length] = '\0';
731 	  rl_insert_text (string);
732 	  count -= decreaser;
733 	}
734 
735       free (string);
736       incoming_length = 0;
737       stored_count = 0;
738 #else /* !HANDLE_MULTIBYTE */
739       char str[1024+1];
740 
741       for (i = 0; i < 1024; i++)
742 	str[i] = c;
743 
744       while (count)
745 	{
746 	  decreaser = (count > 1024 ? 1024 : count);
747 	  str[decreaser] = '\0';
748 	  rl_insert_text (str);
749 	  count -= decreaser;
750 	}
751 #endif /* !HANDLE_MULTIBYTE */
752 
753       return 0;
754     }
755 
756 #if defined (HANDLE_MULTIBYTE)
757   if (MB_CUR_MAX == 1 || rl_byte_oriented)
758     {
759 #endif
760       /* We are inserting a single character.
761 	 If there is pending input, then make a string of all of the
762 	 pending characters that are bound to rl_insert, and insert
763 	 them all. */
764       if (_rl_any_typein ())
765 	_rl_insert_typein (c);
766       else
767 	{
768 	  /* Inserting a single character. */
769 	  char str[2];
770 
771 	  str[1] = '\0';
772 	  str[0] = c;
773 	  rl_insert_text (str);
774 	}
775 #if defined (HANDLE_MULTIBYTE)
776     }
777   else
778     {
779       rl_insert_text (incoming);
780       stored_count = 0;
781     }
782 #endif
783 
784   return 0;
785 }
786 
787 /* Overwrite the character at point (or next COUNT characters) with C.
788    If C introduces a multibyte character sequence, read the entire sequence
789    before starting the overwrite loop. */
790 int
_rl_overwrite_char(count,c)791 _rl_overwrite_char (count, c)
792      int count, c;
793 {
794   int i;
795 #if defined (HANDLE_MULTIBYTE)
796   char mbkey[MB_LEN_MAX];
797   int k;
798 
799   /* Read an entire multibyte character sequence to insert COUNT times. */
800   if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
801     k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
802 #endif
803 
804   for (i = 0; i < count; i++)
805     {
806       rl_begin_undo_group ();
807 
808       if (rl_point < rl_end)
809 	rl_delete (1, c);
810 
811 #if defined (HANDLE_MULTIBYTE)
812       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
813 	rl_insert_text (mbkey);
814       else
815 #endif
816 	_rl_insert_char (1, c);
817 
818       rl_end_undo_group ();
819     }
820 
821   return 0;
822 }
823 
824 int
rl_insert(count,c)825 rl_insert (count, c)
826      int count, c;
827 {
828   return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
829 					 : _rl_overwrite_char (count, c));
830 }
831 
832 /* Insert the next typed character verbatim. */
833 int
rl_quoted_insert(count,key)834 rl_quoted_insert (count, key)
835      int count, key;
836 {
837   int c;
838 
839 #if defined (HANDLE_SIGNALS)
840   _rl_disable_tty_signals ();
841 #endif
842 
843   RL_SETSTATE(RL_STATE_MOREINPUT);
844   c = rl_read_key ();
845   RL_UNSETSTATE(RL_STATE_MOREINPUT);
846 
847 #if defined (HANDLE_SIGNALS)
848   _rl_restore_tty_signals ();
849 #endif
850 
851   return (_rl_insert_char (count, c));
852 }
853 
854 /* Insert a tab character. */
855 int
rl_tab_insert(count,key)856 rl_tab_insert (count, key)
857      int count, key;
858 {
859   return (_rl_insert_char (count, '\t'));
860 }
861 
862 /* What to do when a NEWLINE is pressed.  We accept the whole line.
863    KEY is the key that invoked this command.  I guess it could have
864    meaning in the future. */
865 int
rl_newline(count,key)866 rl_newline (count, key)
867      int count, key;
868 {
869   rl_done = 1;
870 
871   if (_rl_history_preserve_point)
872     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
873 
874   RL_SETSTATE(RL_STATE_DONE);
875 
876 #if defined (VI_MODE)
877   if (rl_editing_mode == vi_mode)
878     {
879       _rl_vi_done_inserting ();
880       _rl_vi_reset_last ();
881     }
882 #endif /* VI_MODE */
883 
884   /* If we've been asked to erase empty lines, suppress the final update,
885      since _rl_update_final calls rl_crlf(). */
886   if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
887     return 0;
888 
889   if (readline_echoing_p)
890     _rl_update_final ();
891   return 0;
892 }
893 
894 /* What to do for some uppercase characters, like meta characters,
895    and some characters appearing in emacs_ctlx_keymap.  This function
896    is just a stub, you bind keys to it and the code in _rl_dispatch ()
897    is special cased. */
898 int
rl_do_lowercase_version(ignore1,ignore2)899 rl_do_lowercase_version (ignore1, ignore2)
900      int ignore1, ignore2;
901 {
902   return 0;
903 }
904 
905 /* This is different from what vi does, so the code's not shared.  Emacs
906    rubout in overwrite mode has one oddity:  it replaces a control
907    character that's displayed as two characters (^X) with two spaces. */
908 int
_rl_overwrite_rubout(count,key)909 _rl_overwrite_rubout (count, key)
910      int count, key;
911 {
912   int opoint;
913   int i, l;
914 
915   if (rl_point == 0)
916     {
917       rl_ding ();
918       return 1;
919     }
920 
921   opoint = rl_point;
922 
923   /* L == number of spaces to insert */
924   for (i = l = 0; i < count; i++)
925     {
926       rl_backward_char (1, key);
927       l += rl_character_len (rl_line_buffer[rl_point], rl_point);	/* not exactly right */
928     }
929 
930   rl_begin_undo_group ();
931 
932   if (count > 1 || rl_explicit_arg)
933     rl_kill_text (opoint, rl_point);
934   else
935     rl_delete_text (opoint, rl_point);
936 
937   /* Emacs puts point at the beginning of the sequence of spaces. */
938   opoint = rl_point;
939   _rl_insert_char (l, ' ');
940   rl_point = opoint;
941 
942   rl_end_undo_group ();
943 
944   return 0;
945 }
946 
947 /* Rubout the character behind point. */
948 int
rl_rubout(count,key)949 rl_rubout (count, key)
950      int count, key;
951 {
952   if (count < 0)
953     return (rl_delete (-count, key));
954 
955   if (!rl_point)
956     {
957       rl_ding ();
958       return -1;
959     }
960 
961   if (rl_insert_mode == RL_IM_OVERWRITE)
962     return (_rl_overwrite_rubout (count, key));
963 
964   return (_rl_rubout_char (count, key));
965 }
966 
967 int
_rl_rubout_char(count,key)968 _rl_rubout_char (count, key)
969      int count, key;
970 {
971   int orig_point;
972   unsigned char c;
973 
974   /* Duplicated code because this is called from other parts of the library. */
975   if (count < 0)
976     return (rl_delete (-count, key));
977 
978   if (rl_point == 0)
979     {
980       rl_ding ();
981       return -1;
982     }
983 
984   if (count > 1 || rl_explicit_arg)
985     {
986       orig_point = rl_point;
987 #if defined (HANDLE_MULTIBYTE)
988       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
989 	rl_backward_char (count, key);
990       else
991 #endif
992         rl_backward_byte (count, key);
993       rl_kill_text (orig_point, rl_point);
994     }
995   else
996     {
997 #if defined (HANDLE_MULTIBYTE)
998       if (MB_CUR_MAX == 1 || rl_byte_oriented)
999 	{
1000 #endif
1001 	  c = rl_line_buffer[--rl_point];
1002 	  rl_delete_text (rl_point, rl_point + 1);
1003 #if defined (HANDLE_MULTIBYTE)
1004 	}
1005       else
1006 	{
1007 	  int orig_point;
1008 
1009 	  orig_point = rl_point;
1010 	  rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1011 	  c = rl_line_buffer[rl_point];
1012 	  rl_delete_text (rl_point, orig_point);
1013 	}
1014 #endif /* HANDLE_MULTIBYTE */
1015 
1016       /* I don't think that the hack for end of line is needed for
1017 	 multibyte chars. */
1018 #if defined (HANDLE_MULTIBYTE)
1019       if (MB_CUR_MAX == 1 || rl_byte_oriented)
1020 #endif
1021       if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
1022 	{
1023 	  int l;
1024 	  l = rl_character_len (c, rl_point);
1025 	  _rl_erase_at_end_of_line (l);
1026 	}
1027     }
1028 
1029   return 0;
1030 }
1031 
1032 /* Delete the character under the cursor.  Given a numeric argument,
1033    kill that many characters instead. */
1034 int
rl_delete(count,key)1035 rl_delete (count, key)
1036      int count, key;
1037 {
1038   int r;
1039 
1040   if (count < 0)
1041     return (_rl_rubout_char (-count, key));
1042 
1043   if (rl_point == rl_end)
1044     {
1045       rl_ding ();
1046       return -1;
1047     }
1048 
1049   if (count > 1 || rl_explicit_arg)
1050     {
1051       int orig_point = rl_point;
1052 #if defined (HANDLE_MULTIBYTE)
1053       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1054 	rl_forward_char (count, key);
1055       else
1056 #endif
1057 	rl_forward_byte (count, key);
1058 
1059       r = rl_kill_text (orig_point, rl_point);
1060       rl_point = orig_point;
1061       return r;
1062     }
1063   else
1064     {
1065       int new_point;
1066       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1067 	new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
1068       else
1069 	new_point = rl_point + 1;
1070 
1071       return (rl_delete_text (rl_point, new_point));
1072     }
1073 }
1074 
1075 /* Delete the character under the cursor, unless the insertion
1076    point is at the end of the line, in which case the character
1077    behind the cursor is deleted.  COUNT is obeyed and may be used
1078    to delete forward or backward that many characters. */
1079 int
rl_rubout_or_delete(count,key)1080 rl_rubout_or_delete (count, key)
1081      int count, key;
1082 {
1083   if (rl_end != 0 && rl_point == rl_end)
1084     return (_rl_rubout_char (count, key));
1085   else
1086     return (rl_delete (count, key));
1087 }
1088 
1089 /* Delete all spaces and tabs around point. */
1090 int
rl_delete_horizontal_space(count,ignore)1091 rl_delete_horizontal_space (count, ignore)
1092      int count, ignore;
1093 {
1094   int start = rl_point;
1095 
1096   while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
1097     rl_point--;
1098 
1099   start = rl_point;
1100 
1101   while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1102     rl_point++;
1103 
1104   if (start != rl_point)
1105     {
1106       rl_delete_text (start, rl_point);
1107       rl_point = start;
1108     }
1109   return 0;
1110 }
1111 
1112 /* Like the tcsh editing function delete-char-or-list.  The eof character
1113    is caught before this is invoked, so this really does the same thing as
1114    delete-char-or-list-or-eof, as long as it's bound to the eof character. */
1115 int
rl_delete_or_show_completions(count,key)1116 rl_delete_or_show_completions (count, key)
1117      int count, key;
1118 {
1119   if (rl_end != 0 && rl_point == rl_end)
1120     return (rl_possible_completions (count, key));
1121   else
1122     return (rl_delete (count, key));
1123 }
1124 
1125 #ifndef RL_COMMENT_BEGIN_DEFAULT
1126 #define RL_COMMENT_BEGIN_DEFAULT "#"
1127 #endif
1128 
1129 /* Turn the current line into a comment in shell history.
1130    A K*rn shell style function. */
1131 int
rl_insert_comment(count,key)1132 rl_insert_comment (count, key)
1133      int count, key;
1134 {
1135   char *rl_comment_text;
1136   int rl_comment_len;
1137 
1138   rl_beg_of_line (1, key);
1139   rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
1140 
1141   if (rl_explicit_arg == 0)
1142     rl_insert_text (rl_comment_text);
1143   else
1144     {
1145       rl_comment_len = strlen (rl_comment_text);
1146       if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
1147 	rl_delete_text (rl_point, rl_point + rl_comment_len);
1148       else
1149 	rl_insert_text (rl_comment_text);
1150     }
1151 
1152   (*rl_redisplay_function) ();
1153   rl_newline (1, '\n');
1154 
1155   return (0);
1156 }
1157 
1158 /* **************************************************************** */
1159 /*								    */
1160 /*			Changing Case				    */
1161 /*								    */
1162 /* **************************************************************** */
1163 
1164 /* The three kinds of things that we know how to do. */
1165 #define UpCase 1
1166 #define DownCase 2
1167 #define CapCase 3
1168 
1169 /* Uppercase the word at point. */
1170 int
rl_upcase_word(count,key)1171 rl_upcase_word (count, key)
1172      int count, key;
1173 {
1174   return (rl_change_case (count, UpCase));
1175 }
1176 
1177 /* Lowercase the word at point. */
1178 int
rl_downcase_word(count,key)1179 rl_downcase_word (count, key)
1180      int count, key;
1181 {
1182   return (rl_change_case (count, DownCase));
1183 }
1184 
1185 /* Upcase the first letter, downcase the rest. */
1186 int
rl_capitalize_word(count,key)1187 rl_capitalize_word (count, key)
1188      int count, key;
1189 {
1190  return (rl_change_case (count, CapCase));
1191 }
1192 
1193 /* The meaty function.
1194    Change the case of COUNT words, performing OP on them.
1195    OP is one of UpCase, DownCase, or CapCase.
1196    If a negative argument is given, leave point where it started,
1197    otherwise, leave it where it moves to. */
1198 static int
rl_change_case(count,op)1199 rl_change_case (count, op)
1200      int count, op;
1201 {
1202   register int start, end;
1203   int inword, c;
1204 
1205   start = rl_point;
1206   rl_forward_word (count, 0);
1207   end = rl_point;
1208 
1209   if (count < 0)
1210     SWAP (start, end);
1211 
1212   /* We are going to modify some text, so let's prepare to undo it. */
1213   rl_modifying (start, end);
1214 
1215   for (inword = 0; start < end; start++)
1216     {
1217       c = rl_line_buffer[start];
1218       switch (op)
1219 	{
1220 	case UpCase:
1221 	  rl_line_buffer[start] = _rl_to_upper (c);
1222 	  break;
1223 
1224 	case DownCase:
1225 	  rl_line_buffer[start] = _rl_to_lower (c);
1226 	  break;
1227 
1228 	case CapCase:
1229 	  rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
1230 	  inword = rl_alphabetic (rl_line_buffer[start]);
1231 	  break;
1232 
1233 	default:
1234 	  rl_ding ();
1235 	  return -1;
1236 	}
1237     }
1238   rl_point = end;
1239   return 0;
1240 }
1241 
1242 /* **************************************************************** */
1243 /*								    */
1244 /*			Transposition				    */
1245 /*								    */
1246 /* **************************************************************** */
1247 
1248 /* Transpose the words at point.  If point is at the end of the line,
1249    transpose the two words before point. */
1250 int
rl_transpose_words(count,key)1251 rl_transpose_words (count, key)
1252      int count, key;
1253 {
1254   char *word1, *word2;
1255   int w1_beg, w1_end, w2_beg, w2_end;
1256   int orig_point = rl_point;
1257 
1258   if (!count)
1259     return 0;
1260 
1261   /* Find the two words. */
1262   rl_forward_word (count, key);
1263   w2_end = rl_point;
1264   rl_backward_word (1, key);
1265   w2_beg = rl_point;
1266   rl_backward_word (count, key);
1267   w1_beg = rl_point;
1268   rl_forward_word (1, key);
1269   w1_end = rl_point;
1270 
1271   /* Do some check to make sure that there really are two words. */
1272   if ((w1_beg == w2_beg) || (w2_beg < w1_end))
1273     {
1274       rl_ding ();
1275       rl_point = orig_point;
1276       return -1;
1277     }
1278 
1279   /* Get the text of the words. */
1280   word1 = rl_copy_text (w1_beg, w1_end);
1281   word2 = rl_copy_text (w2_beg, w2_end);
1282 
1283   /* We are about to do many insertions and deletions.  Remember them
1284      as one operation. */
1285   rl_begin_undo_group ();
1286 
1287   /* Do the stuff at word2 first, so that we don't have to worry
1288      about word1 moving. */
1289   rl_point = w2_beg;
1290   rl_delete_text (w2_beg, w2_end);
1291   rl_insert_text (word1);
1292 
1293   rl_point = w1_beg;
1294   rl_delete_text (w1_beg, w1_end);
1295   rl_insert_text (word2);
1296 
1297   /* This is exactly correct since the text before this point has not
1298      changed in length. */
1299   rl_point = w2_end;
1300 
1301   /* I think that does it. */
1302   rl_end_undo_group ();
1303   free (word1);
1304   free (word2);
1305 
1306   return 0;
1307 }
1308 
1309 /* Transpose the characters at point.  If point is at the end of the line,
1310    then transpose the characters before point. */
1311 int
rl_transpose_chars(count,key)1312 rl_transpose_chars (count, key)
1313      int count, key;
1314 {
1315 #if defined (HANDLE_MULTIBYTE)
1316   char *dummy;
1317   int i, prev_point;
1318 #else
1319   char dummy[2];
1320 #endif
1321   int char_length;
1322 
1323   if (count == 0)
1324     return 0;
1325 
1326   if (!rl_point || rl_end < 2)
1327     {
1328       rl_ding ();
1329       return -1;
1330     }
1331 
1332   rl_begin_undo_group ();
1333 
1334   if (rl_point == rl_end)
1335     {
1336       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1337 	rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1338       else
1339 	--rl_point;
1340       count = 1;
1341     }
1342 
1343 #if defined (HANDLE_MULTIBYTE)
1344   prev_point = rl_point;
1345   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1346     rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1347   else
1348 #endif
1349     rl_point--;
1350 
1351 #if defined (HANDLE_MULTIBYTE)
1352   char_length = prev_point - rl_point;
1353   dummy = (char *)xmalloc (char_length + 1);
1354   for (i = 0; i < char_length; i++)
1355     dummy[i] = rl_line_buffer[rl_point + i];
1356   dummy[i] = '\0';
1357 #else
1358   dummy[0] = rl_line_buffer[rl_point];
1359   dummy[char_length = 1] = '\0';
1360 #endif
1361 
1362   rl_delete_text (rl_point, rl_point + char_length);
1363 
1364   rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1365 
1366   _rl_fix_point (0);
1367   rl_insert_text (dummy);
1368   rl_end_undo_group ();
1369 
1370 #if defined (HANDLE_MULTIBYTE)
1371   free (dummy);
1372 #endif
1373 
1374   return 0;
1375 }
1376 
1377 /* **************************************************************** */
1378 /*								    */
1379 /*			Character Searching			    */
1380 /*								    */
1381 /* **************************************************************** */
1382 
1383 int
1384 #if defined (HANDLE_MULTIBYTE)
_rl_char_search_internal(count,dir,smbchar,len)1385 _rl_char_search_internal (count, dir, smbchar, len)
1386      int count, dir;
1387      char *smbchar;
1388      int len;
1389 #else
1390 _rl_char_search_internal (count, dir, schar)
1391      int count, dir, schar;
1392 #endif
1393 {
1394   int pos, inc;
1395 #if defined (HANDLE_MULTIBYTE)
1396   int prepos;
1397 #endif
1398 
1399   pos = rl_point;
1400   inc = (dir < 0) ? -1 : 1;
1401   while (count)
1402     {
1403       if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
1404 	{
1405 	  rl_ding ();
1406 	  return -1;
1407 	}
1408 
1409 #if defined (HANDLE_MULTIBYTE)
1410       pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
1411 		      : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1412 #else
1413       pos += inc;
1414 #endif
1415       do
1416 	{
1417 #if defined (HANDLE_MULTIBYTE)
1418 	  if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
1419 #else
1420 	  if (rl_line_buffer[pos] == schar)
1421 #endif
1422 	    {
1423 	      count--;
1424 	      if (dir < 0)
1425 	        rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
1426 					: pos;
1427 	      else
1428 		rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
1429 					: pos;
1430 	      break;
1431 	    }
1432 #if defined (HANDLE_MULTIBYTE)
1433 	  prepos = pos;
1434 #endif
1435 	}
1436 #if defined (HANDLE_MULTIBYTE)
1437       while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
1438 		       : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
1439 #else
1440       while ((dir < 0) ? pos-- : ++pos < rl_end);
1441 #endif
1442     }
1443   return (0);
1444 }
1445 
1446 /* Search COUNT times for a character read from the current input stream.
1447    FDIR is the direction to search if COUNT is non-negative; otherwise
1448    the search goes in BDIR.  So much is dependent on HANDLE_MULTIBYTE
1449    that there are two separate versions of this function. */
1450 #if defined (HANDLE_MULTIBYTE)
1451 static int
_rl_char_search(count,fdir,bdir)1452 _rl_char_search (count, fdir, bdir)
1453      int count, fdir, bdir;
1454 {
1455   char mbchar[MB_LEN_MAX];
1456   int mb_len;
1457 
1458   mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
1459 
1460   if (count < 0)
1461     return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
1462   else
1463     return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
1464 }
1465 #else /* !HANDLE_MULTIBYTE */
1466 static int
_rl_char_search(count,fdir,bdir)1467 _rl_char_search (count, fdir, bdir)
1468      int count, fdir, bdir;
1469 {
1470   int c;
1471 
1472   RL_SETSTATE(RL_STATE_MOREINPUT);
1473   c = rl_read_key ();
1474   RL_UNSETSTATE(RL_STATE_MOREINPUT);
1475 
1476   if (count < 0)
1477     return (_rl_char_search_internal (-count, bdir, c));
1478   else
1479     return (_rl_char_search_internal (count, fdir, c));
1480 }
1481 #endif /* !HANDLE_MULTIBYTE */
1482 
1483 int
rl_char_search(count,key)1484 rl_char_search (count, key)
1485      int count, key;
1486 {
1487   return (_rl_char_search (count, FFIND, BFIND));
1488 }
1489 
1490 int
rl_backward_char_search(count,key)1491 rl_backward_char_search (count, key)
1492      int count, key;
1493 {
1494   return (_rl_char_search (count, BFIND, FFIND));
1495 }
1496 
1497 /* **************************************************************** */
1498 /*								    */
1499 /*		   The Mark and the Region.			    */
1500 /*								    */
1501 /* **************************************************************** */
1502 
1503 /* Set the mark at POSITION. */
1504 int
_rl_set_mark_at_pos(position)1505 _rl_set_mark_at_pos (position)
1506      int position;
1507 {
1508   if (position > rl_end)
1509     return -1;
1510 
1511   rl_mark = position;
1512   return 0;
1513 }
1514 
1515 /* A bindable command to set the mark. */
1516 int
rl_set_mark(count,key)1517 rl_set_mark (count, key)
1518      int count, key;
1519 {
1520   return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
1521 }
1522 
1523 /* Exchange the position of mark and point. */
1524 int
rl_exchange_point_and_mark(count,key)1525 rl_exchange_point_and_mark (count, key)
1526      int count, key;
1527 {
1528   if (rl_mark > rl_end)
1529     rl_mark = -1;
1530 
1531   if (rl_mark == -1)
1532     {
1533       rl_ding ();
1534       return -1;
1535     }
1536   else
1537     SWAP (rl_point, rl_mark);
1538 
1539   return 0;
1540 }
1541