Replace the nologin shell script with a tiny c version. Just for the sake
[dragonfly/netmp.git] / contrib / readline-5.0 / text.c
blobd917e99b9bd63c659da105ed7ceac6d5becc7b32
1 /* text.c -- text handling commands for readline. */
3 /* Copyright (C) 1987-2004 Free Software Foundation, Inc.
5 This file is part of the GNU Readline Library, a library for
6 reading lines of text with interactive input and history editing.
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.
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.
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
24 #if defined (HAVE_CONFIG_H)
25 # include <config.h>
26 #endif
28 #if defined (HAVE_UNISTD_H)
29 # include <unistd.h>
30 #endif /* HAVE_UNISTD_H */
32 #if defined (HAVE_STDLIB_H)
33 # include <stdlib.h>
34 #else
35 # include "ansi_stdlib.h"
36 #endif /* HAVE_STDLIB_H */
38 #if defined (HAVE_LOCALE_H)
39 # include <locale.h>
40 #endif
42 #include <stdio.h>
44 /* System-specific feature definitions and include files. */
45 #include "rldefs.h"
46 #include "rlmbutil.h"
48 #if defined (__EMX__)
49 # define INCL_DOSPROCESS
50 # include <os2.h>
51 #endif /* __EMX__ */
53 /* Some standard library routines. */
54 #include "readline.h"
55 #include "history.h"
57 #include "rlprivate.h"
58 #include "rlshell.h"
59 #include "xmalloc.h"
61 /* Forward declarations. */
62 static int rl_change_case PARAMS((int, int));
63 static int _rl_char_search PARAMS((int, int, int));
65 /* **************************************************************** */
66 /* */
67 /* Insert and Delete */
68 /* */
69 /* **************************************************************** */
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
75 rl_insert_text (string)
76 const char *string;
78 register int i, l;
80 l = (string && *string) ? strlen (string) : 0;
81 if (l == 0)
82 return 0;
84 if (rl_end + l >= rl_line_buffer_len)
85 rl_extend_line_buffer (rl_end + l);
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);
91 /* Remember how to undo this if we aren't undoing something. */
92 if (_rl_doing_an_undo == 0)
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);
104 rl_point += l;
105 rl_end += l;
106 rl_line_buffer[rl_end] = '\0';
107 return l;
110 /* Delete the string between FROM and TO. FROM is inclusive, TO is not.
111 Returns the number of characters deleted. */
113 rl_delete_text (from, to)
114 int from, to;
116 register char *text;
117 register int diff, i;
119 /* Fix it if the caller is confused. */
120 if (from > to)
121 SWAP (from, to);
123 /* fix boundaries */
124 if (to > rl_end)
126 to = rl_end;
127 if (from > to)
128 from = to;
130 if (from < 0)
131 from = 0;
133 text = rl_copy_text (from, to);
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];
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);
146 rl_end -= diff;
147 rl_line_buffer[rl_end] = '\0';
148 return (diff);
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. */
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)
163 void
164 _rl_fix_point (fix_mark_too)
165 int fix_mark_too;
167 _RL_FIX_POINT (rl_point);
168 if (fix_mark_too)
169 _RL_FIX_POINT (rl_mark);
171 #undef _RL_FIX_POINT
173 /* Replace the contents of the line buffer between START and END with
174 TEXT. The operation is undoable. To replace the entire line in an
175 undoable mode, use _rl_replace_text(text, 0, rl_end); */
177 _rl_replace_text (text, start, end)
178 const char *text;
179 int start, end;
181 int n;
183 rl_begin_undo_group ();
184 rl_delete_text (start, end + 1);
185 rl_point = start;
186 n = rl_insert_text (text);
187 rl_end_undo_group ();
189 return n;
192 /* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is
193 non-zero, we free the current undo list. */
194 void
195 rl_replace_line (text, clear_undo)
196 const char *text;
197 int clear_undo;
199 int len;
201 len = strlen (text);
202 if (len >= rl_line_buffer_len)
203 rl_extend_line_buffer (len);
204 strcpy (rl_line_buffer, text);
205 rl_end = len;
207 if (clear_undo)
208 rl_free_undo_list ();
210 _rl_fix_point (1);
213 /* **************************************************************** */
214 /* */
215 /* Readline character functions */
216 /* */
217 /* **************************************************************** */
219 /* This is not a gap editor, just a stupid line input routine. No hair
220 is involved in writing any of the functions, and none should be. */
222 /* Note that:
224 rl_end is the place in the string that we would place '\0';
225 i.e., it is always safe to place '\0' there.
227 rl_point is the place in the string where the cursor is. Sometimes
228 this is the same as rl_end.
230 Any command that is called interactively receives two arguments.
231 The first is a count: the numeric arg pased to this command.
232 The second is the key which invoked this command.
235 /* **************************************************************** */
236 /* */
237 /* Movement Commands */
238 /* */
239 /* **************************************************************** */
241 /* Note that if you `optimize' the display for these functions, you cannot
242 use said functions in other functions which do not do optimizing display.
243 I.e., you will have to update the data base for rl_redisplay, and you
244 might as well let rl_redisplay do that job. */
246 /* Move forward COUNT bytes. */
248 rl_forward_byte (count, key)
249 int count, key;
251 if (count < 0)
252 return (rl_backward_byte (-count, key));
254 if (count > 0)
256 int end = rl_point + count;
257 #if defined (VI_MODE)
258 int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
259 #else
260 int lend = rl_end;
261 #endif
263 if (end > lend)
265 rl_point = lend;
266 rl_ding ();
268 else
269 rl_point = end;
272 if (rl_end < 0)
273 rl_end = 0;
275 return 0;
278 #if defined (HANDLE_MULTIBYTE)
279 /* Move forward COUNT characters. */
281 rl_forward_char (count, key)
282 int count, key;
284 int point;
286 if (MB_CUR_MAX == 1 || rl_byte_oriented)
287 return (rl_forward_byte (count, key));
289 if (count < 0)
290 return (rl_backward_char (-count, key));
292 if (count > 0)
294 point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
296 #if defined (VI_MODE)
297 if (rl_end <= point && rl_editing_mode == vi_mode)
298 point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
299 #endif
301 if (rl_point == point)
302 rl_ding ();
304 rl_point = point;
306 if (rl_end < 0)
307 rl_end = 0;
310 return 0;
312 #else /* !HANDLE_MULTIBYTE */
314 rl_forward_char (count, key)
315 int count, key;
317 return (rl_forward_byte (count, key));
319 #endif /* !HANDLE_MULTIBYTE */
321 /* Backwards compatibility. */
323 rl_forward (count, key)
324 int count, key;
326 return (rl_forward_char (count, key));
329 /* Move backward COUNT bytes. */
331 rl_backward_byte (count, key)
332 int count, key;
334 if (count < 0)
335 return (rl_forward_byte (-count, key));
337 if (count > 0)
339 if (rl_point < count)
341 rl_point = 0;
342 rl_ding ();
344 else
345 rl_point -= count;
348 if (rl_point < 0)
349 rl_point = 0;
351 return 0;
354 #if defined (HANDLE_MULTIBYTE)
355 /* Move backward COUNT characters. */
357 rl_backward_char (count, key)
358 int count, key;
360 int point;
362 if (MB_CUR_MAX == 1 || rl_byte_oriented)
363 return (rl_backward_byte (count, key));
365 if (count < 0)
366 return (rl_forward_char (-count, key));
368 if (count > 0)
370 point = rl_point;
372 while (count > 0 && point > 0)
374 point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
375 count--;
377 if (count > 0)
379 rl_point = 0;
380 rl_ding ();
382 else
383 rl_point = point;
386 return 0;
388 #else
390 rl_backward_char (count, key)
391 int count, key;
393 return (rl_backward_byte (count, key));
395 #endif
397 /* Backwards compatibility. */
399 rl_backward (count, key)
400 int count, key;
402 return (rl_backward_char (count, key));
405 /* Move to the beginning of the line. */
407 rl_beg_of_line (count, key)
408 int count, key;
410 rl_point = 0;
411 return 0;
414 /* Move to the end of the line. */
416 rl_end_of_line (count, key)
417 int count, key;
419 rl_point = rl_end;
420 return 0;
423 /* XXX - these might need changes for multibyte characters */
424 /* Move forward a word. We do what Emacs does. */
426 rl_forward_word (count, key)
427 int count, key;
429 int c;
431 if (count < 0)
432 return (rl_backward_word (-count, key));
434 while (count)
436 if (rl_point == rl_end)
437 return 0;
439 /* If we are not in a word, move forward until we are in one.
440 Then, move forward until we hit a non-alphabetic character. */
441 c = rl_line_buffer[rl_point];
442 if (rl_alphabetic (c) == 0)
444 while (++rl_point < rl_end)
446 c = rl_line_buffer[rl_point];
447 if (rl_alphabetic (c))
448 break;
452 if (rl_point == rl_end)
453 return 0;
455 while (++rl_point < rl_end)
457 c = rl_line_buffer[rl_point];
458 if (rl_alphabetic (c) == 0)
459 break;
461 --count;
464 return 0;
467 /* Move backward a word. We do what Emacs does. */
469 rl_backward_word (count, key)
470 int count, key;
472 int c;
474 if (count < 0)
475 return (rl_forward_word (-count, key));
477 while (count)
479 if (!rl_point)
480 return 0;
482 /* Like rl_forward_word (), except that we look at the characters
483 just before point. */
485 c = rl_line_buffer[rl_point - 1];
486 if (rl_alphabetic (c) == 0)
488 while (--rl_point)
490 c = rl_line_buffer[rl_point - 1];
491 if (rl_alphabetic (c))
492 break;
496 while (rl_point)
498 c = rl_line_buffer[rl_point - 1];
499 if (rl_alphabetic (c) == 0)
500 break;
501 else
502 --rl_point;
505 --count;
508 return 0;
511 /* Clear the current line. Numeric argument to C-l does this. */
513 rl_refresh_line (ignore1, ignore2)
514 int ignore1, ignore2;
516 int curr_line;
518 curr_line = _rl_current_display_line ();
520 _rl_move_vert (curr_line);
521 _rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */
523 _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */
525 rl_forced_update_display ();
526 rl_display_fixed = 1;
528 return 0;
531 /* C-l typed to a line without quoting clears the screen, and then reprints
532 the prompt and the current input line. Given a numeric arg, redraw only
533 the current line. */
535 rl_clear_screen (count, key)
536 int count, key;
538 if (rl_explicit_arg)
540 rl_refresh_line (count, key);
541 return 0;
544 _rl_clear_screen (); /* calls termcap function to clear screen */
545 rl_forced_update_display ();
546 rl_display_fixed = 1;
548 return 0;
552 rl_arrow_keys (count, c)
553 int count, c;
555 int ch;
557 RL_SETSTATE(RL_STATE_MOREINPUT);
558 ch = rl_read_key ();
559 RL_UNSETSTATE(RL_STATE_MOREINPUT);
561 switch (_rl_to_upper (ch))
563 case 'A':
564 rl_get_previous_history (count, ch);
565 break;
567 case 'B':
568 rl_get_next_history (count, ch);
569 break;
571 case 'C':
572 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
573 rl_forward_char (count, ch);
574 else
575 rl_forward_byte (count, ch);
576 break;
578 case 'D':
579 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
580 rl_backward_char (count, ch);
581 else
582 rl_backward_byte (count, ch);
583 break;
585 default:
586 rl_ding ();
589 return 0;
592 /* **************************************************************** */
593 /* */
594 /* Text commands */
595 /* */
596 /* **************************************************************** */
598 #ifdef HANDLE_MULTIBYTE
599 static char pending_bytes[MB_LEN_MAX];
600 static int pending_bytes_length = 0;
601 static mbstate_t ps = {0};
602 #endif
604 /* Insert the character C at the current location, moving point forward.
605 If C introduces a multibyte sequence, we read the whole sequence and
606 then insert the multibyte char into the line buffer. */
608 _rl_insert_char (count, c)
609 int count, c;
611 register int i;
612 char *string;
613 #ifdef HANDLE_MULTIBYTE
614 int string_size;
615 char incoming[MB_LEN_MAX + 1];
616 int incoming_length = 0;
617 mbstate_t ps_back;
618 static int stored_count = 0;
619 #endif
621 if (count <= 0)
622 return 0;
624 #if defined (HANDLE_MULTIBYTE)
625 if (MB_CUR_MAX == 1 || rl_byte_oriented)
627 incoming[0] = c;
628 incoming[1] = '\0';
629 incoming_length = 1;
631 else
633 wchar_t wc;
634 size_t ret;
636 if (stored_count <= 0)
637 stored_count = count;
638 else
639 count = stored_count;
641 ps_back = ps;
642 pending_bytes[pending_bytes_length++] = c;
643 ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
645 if (ret == (size_t)-2)
647 /* Bytes too short to compose character, try to wait for next byte.
648 Restore the state of the byte sequence, because in this case the
649 effect of mbstate is undefined. */
650 ps = ps_back;
651 return 1;
653 else if (ret == (size_t)-1)
655 /* Invalid byte sequence for the current locale. Treat first byte
656 as a single character. */
657 incoming[0] = pending_bytes[0];
658 incoming[1] = '\0';
659 incoming_length = 1;
660 pending_bytes_length--;
661 memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
662 /* Clear the state of the byte sequence, because in this case the
663 effect of mbstate is undefined. */
664 memset (&ps, 0, sizeof (mbstate_t));
666 else if (ret == (size_t)0)
668 incoming[0] = '\0';
669 incoming_length = 0;
670 pending_bytes_length--;
671 /* Clear the state of the byte sequence, because in this case the
672 effect of mbstate is undefined. */
673 memset (&ps, 0, sizeof (mbstate_t));
675 else
677 /* We successfully read a single multibyte character. */
678 memcpy (incoming, pending_bytes, pending_bytes_length);
679 incoming[pending_bytes_length] = '\0';
680 incoming_length = pending_bytes_length;
681 pending_bytes_length = 0;
684 #endif /* HANDLE_MULTIBYTE */
686 /* If we can optimize, then do it. But don't let people crash
687 readline because of extra large arguments. */
688 if (count > 1 && count <= 1024)
690 #if defined (HANDLE_MULTIBYTE)
691 string_size = count * incoming_length;
692 string = (char *)xmalloc (1 + string_size);
694 i = 0;
695 while (i < string_size)
697 strncpy (string + i, incoming, incoming_length);
698 i += incoming_length;
700 incoming_length = 0;
701 stored_count = 0;
702 #else /* !HANDLE_MULTIBYTE */
703 string = (char *)xmalloc (1 + count);
705 for (i = 0; i < count; i++)
706 string[i] = c;
707 #endif /* !HANDLE_MULTIBYTE */
709 string[i] = '\0';
710 rl_insert_text (string);
711 free (string);
713 return 0;
716 if (count > 1024)
718 int decreaser;
719 #if defined (HANDLE_MULTIBYTE)
720 string_size = incoming_length * 1024;
721 string = (char *)xmalloc (1 + string_size);
723 i = 0;
724 while (i < string_size)
726 strncpy (string + i, incoming, incoming_length);
727 i += incoming_length;
730 while (count)
732 decreaser = (count > 1024) ? 1024 : count;
733 string[decreaser*incoming_length] = '\0';
734 rl_insert_text (string);
735 count -= decreaser;
738 free (string);
739 incoming_length = 0;
740 stored_count = 0;
741 #else /* !HANDLE_MULTIBYTE */
742 char str[1024+1];
744 for (i = 0; i < 1024; i++)
745 str[i] = c;
747 while (count)
749 decreaser = (count > 1024 ? 1024 : count);
750 str[decreaser] = '\0';
751 rl_insert_text (str);
752 count -= decreaser;
754 #endif /* !HANDLE_MULTIBYTE */
756 return 0;
759 #if defined (HANDLE_MULTIBYTE)
760 if (MB_CUR_MAX == 1 || rl_byte_oriented)
762 #endif
763 /* We are inserting a single character.
764 If there is pending input, then make a string of all of the
765 pending characters that are bound to rl_insert, and insert
766 them all. */
767 if (_rl_any_typein ())
768 _rl_insert_typein (c);
769 else
771 /* Inserting a single character. */
772 char str[2];
774 str[1] = '\0';
775 str[0] = c;
776 rl_insert_text (str);
778 #if defined (HANDLE_MULTIBYTE)
780 else
782 rl_insert_text (incoming);
783 stored_count = 0;
785 #endif
787 return 0;
790 /* Overwrite the character at point (or next COUNT characters) with C.
791 If C introduces a multibyte character sequence, read the entire sequence
792 before starting the overwrite loop. */
794 _rl_overwrite_char (count, c)
795 int count, c;
797 int i;
798 #if defined (HANDLE_MULTIBYTE)
799 char mbkey[MB_LEN_MAX];
800 int k;
802 /* Read an entire multibyte character sequence to insert COUNT times. */
803 if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
804 k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
805 #endif
807 rl_begin_undo_group ();
809 for (i = 0; i < count; i++)
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);
818 if (rl_point < rl_end)
819 rl_delete (1, c);
822 rl_end_undo_group ();
824 return 0;
828 rl_insert (count, c)
829 int count, c;
831 return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
832 : _rl_overwrite_char (count, c));
835 /* Insert the next typed character verbatim. */
837 rl_quoted_insert (count, key)
838 int count, key;
840 int c;
842 #if defined (HANDLE_SIGNALS)
843 _rl_disable_tty_signals ();
844 #endif
846 RL_SETSTATE(RL_STATE_MOREINPUT);
847 c = rl_read_key ();
848 RL_UNSETSTATE(RL_STATE_MOREINPUT);
850 #if defined (HANDLE_SIGNALS)
851 _rl_restore_tty_signals ();
852 #endif
854 return (_rl_insert_char (count, c));
857 /* Insert a tab character. */
859 rl_tab_insert (count, key)
860 int count, key;
862 return (_rl_insert_char (count, '\t'));
865 /* What to do when a NEWLINE is pressed. We accept the whole line.
866 KEY is the key that invoked this command. I guess it could have
867 meaning in the future. */
869 rl_newline (count, key)
870 int count, key;
872 rl_done = 1;
874 if (_rl_history_preserve_point)
875 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
877 RL_SETSTATE(RL_STATE_DONE);
879 #if defined (VI_MODE)
880 if (rl_editing_mode == vi_mode)
882 _rl_vi_done_inserting ();
883 if (_rl_vi_textmod_command (_rl_vi_last_command) == 0) /* XXX */
884 _rl_vi_reset_last ();
886 #endif /* VI_MODE */
888 /* If we've been asked to erase empty lines, suppress the final update,
889 since _rl_update_final calls rl_crlf(). */
890 if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
891 return 0;
893 if (readline_echoing_p)
894 _rl_update_final ();
895 return 0;
898 /* What to do for some uppercase characters, like meta characters,
899 and some characters appearing in emacs_ctlx_keymap. This function
900 is just a stub, you bind keys to it and the code in _rl_dispatch ()
901 is special cased. */
903 rl_do_lowercase_version (ignore1, ignore2)
904 int ignore1, ignore2;
906 return 0;
909 /* This is different from what vi does, so the code's not shared. Emacs
910 rubout in overwrite mode has one oddity: it replaces a control
911 character that's displayed as two characters (^X) with two spaces. */
913 _rl_overwrite_rubout (count, key)
914 int count, key;
916 int opoint;
917 int i, l;
919 if (rl_point == 0)
921 rl_ding ();
922 return 1;
925 opoint = rl_point;
927 /* L == number of spaces to insert */
928 for (i = l = 0; i < count; i++)
930 rl_backward_char (1, key);
931 l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */
934 rl_begin_undo_group ();
936 if (count > 1 || rl_explicit_arg)
937 rl_kill_text (opoint, rl_point);
938 else
939 rl_delete_text (opoint, rl_point);
941 /* Emacs puts point at the beginning of the sequence of spaces. */
942 if (rl_point < rl_end)
944 opoint = rl_point;
945 _rl_insert_char (l, ' ');
946 rl_point = opoint;
949 rl_end_undo_group ();
951 return 0;
954 /* Rubout the character behind point. */
956 rl_rubout (count, key)
957 int count, key;
959 if (count < 0)
960 return (rl_delete (-count, key));
962 if (!rl_point)
964 rl_ding ();
965 return -1;
968 if (rl_insert_mode == RL_IM_OVERWRITE)
969 return (_rl_overwrite_rubout (count, key));
971 return (_rl_rubout_char (count, key));
975 _rl_rubout_char (count, key)
976 int count, key;
978 int orig_point;
979 unsigned char c;
981 /* Duplicated code because this is called from other parts of the library. */
982 if (count < 0)
983 return (rl_delete (-count, key));
985 if (rl_point == 0)
987 rl_ding ();
988 return -1;
991 if (count > 1 || rl_explicit_arg)
993 orig_point = rl_point;
994 #if defined (HANDLE_MULTIBYTE)
995 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
996 rl_backward_char (count, key);
997 else
998 #endif
999 rl_backward_byte (count, key);
1000 rl_kill_text (orig_point, rl_point);
1002 else
1004 #if defined (HANDLE_MULTIBYTE)
1005 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1007 #endif
1008 c = rl_line_buffer[--rl_point];
1009 rl_delete_text (rl_point, rl_point + 1);
1010 #if defined (HANDLE_MULTIBYTE)
1012 else
1014 int orig_point;
1016 orig_point = rl_point;
1017 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1018 c = rl_line_buffer[rl_point];
1019 rl_delete_text (rl_point, orig_point);
1021 #endif /* HANDLE_MULTIBYTE */
1023 /* I don't think that the hack for end of line is needed for
1024 multibyte chars. */
1025 #if defined (HANDLE_MULTIBYTE)
1026 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1027 #endif
1028 if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
1030 int l;
1031 l = rl_character_len (c, rl_point);
1032 _rl_erase_at_end_of_line (l);
1036 return 0;
1039 /* Delete the character under the cursor. Given a numeric argument,
1040 kill that many characters instead. */
1042 rl_delete (count, key)
1043 int count, key;
1045 int r;
1047 if (count < 0)
1048 return (_rl_rubout_char (-count, key));
1050 if (rl_point == rl_end)
1052 rl_ding ();
1053 return -1;
1056 if (count > 1 || rl_explicit_arg)
1058 int orig_point = rl_point;
1059 #if defined (HANDLE_MULTIBYTE)
1060 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1061 rl_forward_char (count, key);
1062 else
1063 #endif
1064 rl_forward_byte (count, key);
1066 r = rl_kill_text (orig_point, rl_point);
1067 rl_point = orig_point;
1068 return r;
1070 else
1072 int new_point;
1073 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1074 new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
1075 else
1076 new_point = rl_point + 1;
1078 return (rl_delete_text (rl_point, new_point));
1082 /* Delete the character under the cursor, unless the insertion
1083 point is at the end of the line, in which case the character
1084 behind the cursor is deleted. COUNT is obeyed and may be used
1085 to delete forward or backward that many characters. */
1087 rl_rubout_or_delete (count, key)
1088 int count, key;
1090 if (rl_end != 0 && rl_point == rl_end)
1091 return (_rl_rubout_char (count, key));
1092 else
1093 return (rl_delete (count, key));
1096 /* Delete all spaces and tabs around point. */
1098 rl_delete_horizontal_space (count, ignore)
1099 int count, ignore;
1101 int start = rl_point;
1103 while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
1104 rl_point--;
1106 start = rl_point;
1108 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1109 rl_point++;
1111 if (start != rl_point)
1113 rl_delete_text (start, rl_point);
1114 rl_point = start;
1116 return 0;
1119 /* Like the tcsh editing function delete-char-or-list. The eof character
1120 is caught before this is invoked, so this really does the same thing as
1121 delete-char-or-list-or-eof, as long as it's bound to the eof character. */
1123 rl_delete_or_show_completions (count, key)
1124 int count, key;
1126 if (rl_end != 0 && rl_point == rl_end)
1127 return (rl_possible_completions (count, key));
1128 else
1129 return (rl_delete (count, key));
1132 #ifndef RL_COMMENT_BEGIN_DEFAULT
1133 #define RL_COMMENT_BEGIN_DEFAULT "#"
1134 #endif
1136 /* Turn the current line into a comment in shell history.
1137 A K*rn shell style function. */
1139 rl_insert_comment (count, key)
1140 int count, key;
1142 char *rl_comment_text;
1143 int rl_comment_len;
1145 rl_beg_of_line (1, key);
1146 rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
1148 if (rl_explicit_arg == 0)
1149 rl_insert_text (rl_comment_text);
1150 else
1152 rl_comment_len = strlen (rl_comment_text);
1153 if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
1154 rl_delete_text (rl_point, rl_point + rl_comment_len);
1155 else
1156 rl_insert_text (rl_comment_text);
1159 (*rl_redisplay_function) ();
1160 rl_newline (1, '\n');
1162 return (0);
1165 /* **************************************************************** */
1166 /* */
1167 /* Changing Case */
1168 /* */
1169 /* **************************************************************** */
1171 /* The three kinds of things that we know how to do. */
1172 #define UpCase 1
1173 #define DownCase 2
1174 #define CapCase 3
1176 /* Uppercase the word at point. */
1178 rl_upcase_word (count, key)
1179 int count, key;
1181 return (rl_change_case (count, UpCase));
1184 /* Lowercase the word at point. */
1186 rl_downcase_word (count, key)
1187 int count, key;
1189 return (rl_change_case (count, DownCase));
1192 /* Upcase the first letter, downcase the rest. */
1194 rl_capitalize_word (count, key)
1195 int count, key;
1197 return (rl_change_case (count, CapCase));
1200 /* The meaty function.
1201 Change the case of COUNT words, performing OP on them.
1202 OP is one of UpCase, DownCase, or CapCase.
1203 If a negative argument is given, leave point where it started,
1204 otherwise, leave it where it moves to. */
1205 static int
1206 rl_change_case (count, op)
1207 int count, op;
1209 register int start, end;
1210 int inword, c;
1212 start = rl_point;
1213 rl_forward_word (count, 0);
1214 end = rl_point;
1216 if (count < 0)
1217 SWAP (start, end);
1219 /* We are going to modify some text, so let's prepare to undo it. */
1220 rl_modifying (start, end);
1222 for (inword = 0; start < end; start++)
1224 c = rl_line_buffer[start];
1225 switch (op)
1227 case UpCase:
1228 rl_line_buffer[start] = _rl_to_upper (c);
1229 break;
1231 case DownCase:
1232 rl_line_buffer[start] = _rl_to_lower (c);
1233 break;
1235 case CapCase:
1236 rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
1237 inword = rl_alphabetic (rl_line_buffer[start]);
1238 break;
1240 default:
1241 rl_ding ();
1242 return -1;
1245 rl_point = end;
1246 return 0;
1249 /* **************************************************************** */
1250 /* */
1251 /* Transposition */
1252 /* */
1253 /* **************************************************************** */
1255 /* Transpose the words at point. If point is at the end of the line,
1256 transpose the two words before point. */
1258 rl_transpose_words (count, key)
1259 int count, key;
1261 char *word1, *word2;
1262 int w1_beg, w1_end, w2_beg, w2_end;
1263 int orig_point = rl_point;
1265 if (!count)
1266 return 0;
1268 /* Find the two words. */
1269 rl_forward_word (count, key);
1270 w2_end = rl_point;
1271 rl_backward_word (1, key);
1272 w2_beg = rl_point;
1273 rl_backward_word (count, key);
1274 w1_beg = rl_point;
1275 rl_forward_word (1, key);
1276 w1_end = rl_point;
1278 /* Do some check to make sure that there really are two words. */
1279 if ((w1_beg == w2_beg) || (w2_beg < w1_end))
1281 rl_ding ();
1282 rl_point = orig_point;
1283 return -1;
1286 /* Get the text of the words. */
1287 word1 = rl_copy_text (w1_beg, w1_end);
1288 word2 = rl_copy_text (w2_beg, w2_end);
1290 /* We are about to do many insertions and deletions. Remember them
1291 as one operation. */
1292 rl_begin_undo_group ();
1294 /* Do the stuff at word2 first, so that we don't have to worry
1295 about word1 moving. */
1296 rl_point = w2_beg;
1297 rl_delete_text (w2_beg, w2_end);
1298 rl_insert_text (word1);
1300 rl_point = w1_beg;
1301 rl_delete_text (w1_beg, w1_end);
1302 rl_insert_text (word2);
1304 /* This is exactly correct since the text before this point has not
1305 changed in length. */
1306 rl_point = w2_end;
1308 /* I think that does it. */
1309 rl_end_undo_group ();
1310 free (word1);
1311 free (word2);
1313 return 0;
1316 /* Transpose the characters at point. If point is at the end of the line,
1317 then transpose the characters before point. */
1319 rl_transpose_chars (count, key)
1320 int count, key;
1322 #if defined (HANDLE_MULTIBYTE)
1323 char *dummy;
1324 int i, prev_point;
1325 #else
1326 char dummy[2];
1327 #endif
1328 int char_length;
1330 if (count == 0)
1331 return 0;
1333 if (!rl_point || rl_end < 2)
1335 rl_ding ();
1336 return -1;
1339 rl_begin_undo_group ();
1341 if (rl_point == rl_end)
1343 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1344 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1345 else
1346 --rl_point;
1347 count = 1;
1350 #if defined (HANDLE_MULTIBYTE)
1351 prev_point = rl_point;
1352 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1353 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1354 else
1355 #endif
1356 rl_point--;
1358 #if defined (HANDLE_MULTIBYTE)
1359 char_length = prev_point - rl_point;
1360 dummy = (char *)xmalloc (char_length + 1);
1361 for (i = 0; i < char_length; i++)
1362 dummy[i] = rl_line_buffer[rl_point + i];
1363 dummy[i] = '\0';
1364 #else
1365 dummy[0] = rl_line_buffer[rl_point];
1366 dummy[char_length = 1] = '\0';
1367 #endif
1369 rl_delete_text (rl_point, rl_point + char_length);
1371 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1373 _rl_fix_point (0);
1374 rl_insert_text (dummy);
1375 rl_end_undo_group ();
1377 #if defined (HANDLE_MULTIBYTE)
1378 free (dummy);
1379 #endif
1381 return 0;
1384 /* **************************************************************** */
1385 /* */
1386 /* Character Searching */
1387 /* */
1388 /* **************************************************************** */
1391 #if defined (HANDLE_MULTIBYTE)
1392 _rl_char_search_internal (count, dir, smbchar, len)
1393 int count, dir;
1394 char *smbchar;
1395 int len;
1396 #else
1397 _rl_char_search_internal (count, dir, schar)
1398 int count, dir, schar;
1399 #endif
1401 int pos, inc;
1402 #if defined (HANDLE_MULTIBYTE)
1403 int prepos;
1404 #endif
1406 pos = rl_point;
1407 inc = (dir < 0) ? -1 : 1;
1408 while (count)
1410 if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
1412 rl_ding ();
1413 return -1;
1416 #if defined (HANDLE_MULTIBYTE)
1417 pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
1418 : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1419 #else
1420 pos += inc;
1421 #endif
1424 #if defined (HANDLE_MULTIBYTE)
1425 if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
1426 #else
1427 if (rl_line_buffer[pos] == schar)
1428 #endif
1430 count--;
1431 if (dir < 0)
1432 rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
1433 : pos;
1434 else
1435 rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
1436 : pos;
1437 break;
1439 #if defined (HANDLE_MULTIBYTE)
1440 prepos = pos;
1441 #endif
1443 #if defined (HANDLE_MULTIBYTE)
1444 while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
1445 : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
1446 #else
1447 while ((dir < 0) ? pos-- : ++pos < rl_end);
1448 #endif
1450 return (0);
1453 /* Search COUNT times for a character read from the current input stream.
1454 FDIR is the direction to search if COUNT is non-negative; otherwise
1455 the search goes in BDIR. So much is dependent on HANDLE_MULTIBYTE
1456 that there are two separate versions of this function. */
1457 #if defined (HANDLE_MULTIBYTE)
1458 static int
1459 _rl_char_search (count, fdir, bdir)
1460 int count, fdir, bdir;
1462 char mbchar[MB_LEN_MAX];
1463 int mb_len;
1465 mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
1467 if (count < 0)
1468 return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
1469 else
1470 return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
1472 #else /* !HANDLE_MULTIBYTE */
1473 static int
1474 _rl_char_search (count, fdir, bdir)
1475 int count, fdir, bdir;
1477 int c;
1479 RL_SETSTATE(RL_STATE_MOREINPUT);
1480 c = rl_read_key ();
1481 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1483 if (count < 0)
1484 return (_rl_char_search_internal (-count, bdir, c));
1485 else
1486 return (_rl_char_search_internal (count, fdir, c));
1488 #endif /* !HANDLE_MULTIBYTE */
1491 rl_char_search (count, key)
1492 int count, key;
1494 return (_rl_char_search (count, FFIND, BFIND));
1498 rl_backward_char_search (count, key)
1499 int count, key;
1501 return (_rl_char_search (count, BFIND, FFIND));
1504 /* **************************************************************** */
1505 /* */
1506 /* The Mark and the Region. */
1507 /* */
1508 /* **************************************************************** */
1510 /* Set the mark at POSITION. */
1512 _rl_set_mark_at_pos (position)
1513 int position;
1515 if (position > rl_end)
1516 return -1;
1518 rl_mark = position;
1519 return 0;
1522 /* A bindable command to set the mark. */
1524 rl_set_mark (count, key)
1525 int count, key;
1527 return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
1530 /* Exchange the position of mark and point. */
1532 rl_exchange_point_and_mark (count, key)
1533 int count, key;
1535 if (rl_mark > rl_end)
1536 rl_mark = -1;
1538 if (rl_mark == -1)
1540 rl_ding ();
1541 return -1;
1543 else
1544 SWAP (rl_point, rl_mark);
1546 return 0;