Fix kldstat option.
[dragonfly.git] / contrib / readline-5.0 / text.c
1 /* text.c -- text handling commands for readline. */
2
3 /* Copyright (C) 1987-2004 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
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
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
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 /* 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); */
176 int
177 _rl_replace_text (text, start, end)
178      const char *text;
179      int start, end;
180 {
181   int n;
182
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 ();
188
189   return n;
190 }
191
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;
198 {
199   int len;
200
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;
206
207   if (clear_undo)
208     rl_free_undo_list ();
209
210   _rl_fix_point (1);
211 }
212
213 /* **************************************************************** */
214 /*                                                                  */
215 /*                      Readline character functions                */
216 /*                                                                  */
217 /* **************************************************************** */
218
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. */
221
222 /* Note that:
223
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.
226
227    rl_point is the place in the string where the cursor is.  Sometimes
228    this is the same as rl_end.
229
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.
233 */
234
235 /* **************************************************************** */
236 /*                                                                  */
237 /*                      Movement Commands                           */
238 /*                                                                  */
239 /* **************************************************************** */
240
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. */
245
246 /* Move forward COUNT bytes. */
247 int
248 rl_forward_byte (count, key)
249      int count, key;
250 {
251   if (count < 0)
252     return (rl_backward_byte (-count, key));
253
254   if (count > 0)
255     {
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
262
263       if (end > lend)
264         {
265           rl_point = lend;
266           rl_ding ();
267         }
268       else
269         rl_point = end;
270     }
271
272   if (rl_end < 0)
273     rl_end = 0;
274
275   return 0;
276 }
277
278 #if defined (HANDLE_MULTIBYTE)
279 /* Move forward COUNT characters. */
280 int
281 rl_forward_char (count, key)
282      int count, key;
283 {
284   int point;
285
286   if (MB_CUR_MAX == 1 || rl_byte_oriented)
287     return (rl_forward_byte (count, key));
288
289   if (count < 0)
290     return (rl_backward_char (-count, key));
291
292   if (count > 0)
293     {
294       point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
295
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
300
301       if (rl_point == point)
302         rl_ding ();
303
304       rl_point = point;
305
306       if (rl_end < 0)
307         rl_end = 0;
308     }
309
310   return 0;
311 }
312 #else /* !HANDLE_MULTIBYTE */
313 int
314 rl_forward_char (count, key)
315      int count, key;
316 {
317   return (rl_forward_byte (count, key));
318 }
319 #endif /* !HANDLE_MULTIBYTE */
320   
321 /* Backwards compatibility. */
322 int
323 rl_forward (count, key)
324      int count, key;
325 {
326   return (rl_forward_char (count, key));
327 }
328
329 /* Move backward COUNT bytes. */
330 int
331 rl_backward_byte (count, key)
332      int count, key;
333 {
334   if (count < 0)
335     return (rl_forward_byte (-count, key));
336
337   if (count > 0)
338     {
339       if (rl_point < count)
340         {
341           rl_point = 0;
342           rl_ding ();
343         }
344       else
345         rl_point -= count;
346     }
347
348   if (rl_point < 0)
349     rl_point = 0;
350
351   return 0;
352 }
353
354 #if defined (HANDLE_MULTIBYTE)
355 /* Move backward COUNT characters. */
356 int
357 rl_backward_char (count, key)
358      int count, key;
359 {
360   int point;
361
362   if (MB_CUR_MAX == 1 || rl_byte_oriented)
363     return (rl_backward_byte (count, key));
364
365   if (count < 0)
366     return (rl_forward_char (-count, key));
367
368   if (count > 0)
369     {
370       point = rl_point;
371
372       while (count > 0 && point > 0)
373         {
374           point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
375           count--;
376         }
377       if (count > 0)
378         {
379           rl_point = 0;
380           rl_ding ();
381         }
382       else
383         rl_point = point;
384     }
385
386   return 0;
387 }
388 #else
389 int
390 rl_backward_char (count, key)
391      int count, key;
392 {
393   return (rl_backward_byte (count, key));
394 }
395 #endif
396
397 /* Backwards compatibility. */
398 int
399 rl_backward (count, key)
400      int count, key;
401 {
402   return (rl_backward_char (count, key));
403 }
404
405 /* Move to the beginning of the line. */
406 int
407 rl_beg_of_line (count, key)
408      int count, key;
409 {
410   rl_point = 0;
411   return 0;
412 }
413
414 /* Move to the end of the line. */
415 int
416 rl_end_of_line (count, key)
417      int count, key;
418 {
419   rl_point = rl_end;
420   return 0;
421 }
422
423 /* XXX - these might need changes for multibyte characters */
424 /* Move forward a word.  We do what Emacs does. */
425 int
426 rl_forward_word (count, key)
427      int count, key;
428 {
429   int c;
430
431   if (count < 0)
432     return (rl_backward_word (-count, key));
433
434   while (count)
435     {
436       if (rl_point == rl_end)
437         return 0;
438
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)
443         {
444           while (++rl_point < rl_end)
445             {
446               c = rl_line_buffer[rl_point];
447               if (rl_alphabetic (c))
448                 break;
449             }
450         }
451
452       if (rl_point == rl_end)
453         return 0;
454
455       while (++rl_point < rl_end)
456         {
457           c = rl_line_buffer[rl_point];
458           if (rl_alphabetic (c) == 0)
459             break;
460         }
461       --count;
462     }
463
464   return 0;
465 }
466
467 /* Move backward a word.  We do what Emacs does. */
468 int
469 rl_backward_word (count, key)
470      int count, key;
471 {
472   int c;
473
474   if (count < 0)
475     return (rl_forward_word (-count, key));
476
477   while (count)
478     {
479       if (!rl_point)
480         return 0;
481
482       /* Like rl_forward_word (), except that we look at the characters
483          just before point. */
484
485       c = rl_line_buffer[rl_point - 1];
486       if (rl_alphabetic (c) == 0)
487         {
488           while (--rl_point)
489             {
490               c = rl_line_buffer[rl_point - 1];
491               if (rl_alphabetic (c))
492                 break;
493             }
494         }
495
496       while (rl_point)
497         {
498           c = rl_line_buffer[rl_point - 1];
499           if (rl_alphabetic (c) == 0)
500             break;
501           else
502             --rl_point;
503         }
504
505       --count;
506     }
507
508   return 0;
509 }
510
511 /* Clear the current line.  Numeric argument to C-l does this. */
512 int
513 rl_refresh_line (ignore1, ignore2)
514      int ignore1, ignore2;
515 {
516   int curr_line;
517
518   curr_line = _rl_current_display_line ();
519
520   _rl_move_vert (curr_line);
521   _rl_move_cursor_relative (0, rl_line_buffer);   /* XXX is this right */
522
523   _rl_clear_to_eol (0);         /* arg of 0 means to not use spaces */
524
525   rl_forced_update_display ();
526   rl_display_fixed = 1;
527
528   return 0;
529 }
530
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. */
534 int
535 rl_clear_screen (count, key)
536      int count, key;
537 {
538   if (rl_explicit_arg)
539     {
540       rl_refresh_line (count, key);
541       return 0;
542     }
543
544   _rl_clear_screen ();          /* calls termcap function to clear screen */
545   rl_forced_update_display ();
546   rl_display_fixed = 1;
547
548   return 0;
549 }
550
551 int
552 rl_arrow_keys (count, c)
553      int count, c;
554 {
555   int ch;
556
557   RL_SETSTATE(RL_STATE_MOREINPUT);
558   ch = rl_read_key ();
559   RL_UNSETSTATE(RL_STATE_MOREINPUT);
560
561   switch (_rl_to_upper (ch))
562     {
563     case 'A':
564       rl_get_previous_history (count, ch);
565       break;
566
567     case 'B':
568       rl_get_next_history (count, ch);
569       break;
570
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;
577
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;
584
585     default:
586       rl_ding ();
587     }
588
589   return 0;
590 }
591
592 /* **************************************************************** */
593 /*                                                                  */
594 /*                      Text commands                               */
595 /*                                                                  */
596 /* **************************************************************** */
597
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
603
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. */
607 int
608 _rl_insert_char (count, c)
609      int count, c;
610 {
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
620
621   if (count <= 0)
622     return 0;
623
624 #if defined (HANDLE_MULTIBYTE)
625   if (MB_CUR_MAX == 1 || rl_byte_oriented)
626     {
627       incoming[0] = c;
628       incoming[1] = '\0';
629       incoming_length = 1;
630     }
631   else
632     {
633       wchar_t wc;
634       size_t ret;
635
636       if (stored_count <= 0)
637         stored_count = count;
638       else
639         count = stored_count;
640
641       ps_back = ps;
642       pending_bytes[pending_bytes_length++] = c;
643       ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
644
645       if (ret == (size_t)-2)
646         {
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;
652         }
653       else if (ret == (size_t)-1)
654         {
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));
665         }
666       else if (ret == (size_t)0)
667         {
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));
674         }
675       else
676         {
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;
682         }
683     }
684 #endif /* HANDLE_MULTIBYTE */
685           
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)
689     {
690 #if defined (HANDLE_MULTIBYTE)
691       string_size = count * incoming_length;
692       string = (char *)xmalloc (1 + string_size);
693
694       i = 0;
695       while (i < string_size)
696         {
697           strncpy (string + i, incoming, incoming_length);
698           i += incoming_length;
699         }
700       incoming_length = 0;
701       stored_count = 0;
702 #else /* !HANDLE_MULTIBYTE */
703       string = (char *)xmalloc (1 + count);
704
705       for (i = 0; i < count; i++)
706         string[i] = c;
707 #endif /* !HANDLE_MULTIBYTE */
708
709       string[i] = '\0';
710       rl_insert_text (string);
711       free (string);
712
713       return 0;
714     }
715
716   if (count > 1024)
717     {
718       int decreaser;
719 #if defined (HANDLE_MULTIBYTE)
720       string_size = incoming_length * 1024;
721       string = (char *)xmalloc (1 + string_size);
722
723       i = 0;
724       while (i < string_size)
725         {
726           strncpy (string + i, incoming, incoming_length);
727           i += incoming_length;
728         }
729
730       while (count)
731         {
732           decreaser = (count > 1024) ? 1024 : count;
733           string[decreaser*incoming_length] = '\0';
734           rl_insert_text (string);
735           count -= decreaser;
736         }
737
738       free (string);
739       incoming_length = 0;
740       stored_count = 0;
741 #else /* !HANDLE_MULTIBYTE */
742       char str[1024+1];
743
744       for (i = 0; i < 1024; i++)
745         str[i] = c;
746
747       while (count)
748         {
749           decreaser = (count > 1024 ? 1024 : count);
750           str[decreaser] = '\0';
751           rl_insert_text (str);
752           count -= decreaser;
753         }
754 #endif /* !HANDLE_MULTIBYTE */
755
756       return 0;
757     }
758
759 #if defined (HANDLE_MULTIBYTE)
760   if (MB_CUR_MAX == 1 || rl_byte_oriented)
761     {
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
770         {
771           /* Inserting a single character. */
772           char str[2];
773
774           str[1] = '\0';
775           str[0] = c;
776           rl_insert_text (str);
777         }
778 #if defined (HANDLE_MULTIBYTE)
779     }
780   else
781     {
782       rl_insert_text (incoming);
783       stored_count = 0;
784     }
785 #endif
786
787   return 0;
788 }
789
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. */
793 int
794 _rl_overwrite_char (count, c)
795      int count, c;
796 {
797   int i;
798 #if defined (HANDLE_MULTIBYTE)
799   char mbkey[MB_LEN_MAX];
800   int k;
801
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
806
807   rl_begin_undo_group ();
808
809   for (i = 0; i < count; i++)
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       if (rl_point < rl_end)
819         rl_delete (1, c);
820     }
821
822   rl_end_undo_group ();
823
824   return 0;
825 }
826
827 int
828 rl_insert (count, c)
829      int count, c;
830 {
831   return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
832                                          : _rl_overwrite_char (count, c));
833 }
834
835 /* Insert the next typed character verbatim. */
836 int
837 rl_quoted_insert (count, key)
838      int count, key;
839 {
840   int c;
841
842 #if defined (HANDLE_SIGNALS)
843   _rl_disable_tty_signals ();
844 #endif
845
846   RL_SETSTATE(RL_STATE_MOREINPUT);
847   c = rl_read_key ();
848   RL_UNSETSTATE(RL_STATE_MOREINPUT);
849
850 #if defined (HANDLE_SIGNALS)
851   _rl_restore_tty_signals ();
852 #endif
853
854   return (_rl_insert_char (count, c));  
855 }
856
857 /* Insert a tab character. */
858 int
859 rl_tab_insert (count, key)
860      int count, key;
861 {
862   return (_rl_insert_char (count, '\t'));
863 }
864
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. */
868 int
869 rl_newline (count, key)
870      int count, key;
871 {
872   rl_done = 1;
873
874   if (_rl_history_preserve_point)
875     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
876
877   RL_SETSTATE(RL_STATE_DONE);
878
879 #if defined (VI_MODE)
880   if (rl_editing_mode == vi_mode)
881     {
882       _rl_vi_done_inserting ();
883       if (_rl_vi_textmod_command (_rl_vi_last_command) == 0)    /* XXX */
884         _rl_vi_reset_last ();
885     }
886 #endif /* VI_MODE */
887
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;
892
893   if (readline_echoing_p)
894     _rl_update_final ();
895   return 0;
896 }
897
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. */
902 int
903 rl_do_lowercase_version (ignore1, ignore2)
904      int ignore1, ignore2;
905 {
906   return 0;
907 }
908
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. */
912 int
913 _rl_overwrite_rubout (count, key)
914      int count, key;
915 {
916   int opoint;
917   int i, l;
918
919   if (rl_point == 0)
920     {
921       rl_ding ();
922       return 1;
923     }
924
925   opoint = rl_point;
926
927   /* L == number of spaces to insert */
928   for (i = l = 0; i < count; i++)
929     {
930       rl_backward_char (1, key);
931       l += rl_character_len (rl_line_buffer[rl_point], rl_point);       /* not exactly right */
932     }
933
934   rl_begin_undo_group ();
935
936   if (count > 1 || rl_explicit_arg)
937     rl_kill_text (opoint, rl_point);
938   else
939     rl_delete_text (opoint, rl_point);
940
941   /* Emacs puts point at the beginning of the sequence of spaces. */
942   if (rl_point < rl_end)
943     {
944       opoint = rl_point;
945       _rl_insert_char (l, ' ');
946       rl_point = opoint;
947     }
948
949   rl_end_undo_group ();
950
951   return 0;
952 }
953   
954 /* Rubout the character behind point. */
955 int
956 rl_rubout (count, key)
957      int count, key;
958 {
959   if (count < 0)
960     return (rl_delete (-count, key));
961
962   if (!rl_point)
963     {
964       rl_ding ();
965       return -1;
966     }
967
968   if (rl_insert_mode == RL_IM_OVERWRITE)
969     return (_rl_overwrite_rubout (count, key));
970
971   return (_rl_rubout_char (count, key));
972 }
973
974 int
975 _rl_rubout_char (count, key)
976      int count, key;
977 {
978   int orig_point;
979   unsigned char c;
980
981   /* Duplicated code because this is called from other parts of the library. */
982   if (count < 0)
983     return (rl_delete (-count, key));
984
985   if (rl_point == 0)
986     {
987       rl_ding ();
988       return -1;
989     }
990
991   if (count > 1 || rl_explicit_arg)
992     {
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);
1001     }
1002   else
1003     {
1004 #if defined (HANDLE_MULTIBYTE)
1005       if (MB_CUR_MAX == 1 || rl_byte_oriented)
1006         {
1007 #endif
1008           c = rl_line_buffer[--rl_point];
1009           rl_delete_text (rl_point, rl_point + 1);
1010 #if defined (HANDLE_MULTIBYTE)
1011         }
1012       else
1013         {
1014           int orig_point;
1015
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);
1020         }
1021 #endif /* HANDLE_MULTIBYTE */
1022
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)
1029         {
1030           int l;
1031           l = rl_character_len (c, rl_point);
1032           _rl_erase_at_end_of_line (l);
1033         }
1034     }
1035
1036   return 0;
1037 }
1038
1039 /* Delete the character under the cursor.  Given a numeric argument,
1040    kill that many characters instead. */
1041 int
1042 rl_delete (count, key)
1043      int count, key;
1044 {
1045   int r;
1046
1047   if (count < 0)
1048     return (_rl_rubout_char (-count, key));
1049
1050   if (rl_point == rl_end)
1051     {
1052       rl_ding ();
1053       return -1;
1054     }
1055
1056   if (count > 1 || rl_explicit_arg)
1057     {
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);
1065
1066       r = rl_kill_text (orig_point, rl_point);
1067       rl_point = orig_point;
1068       return r;
1069     }
1070   else
1071     {
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;
1077         
1078       return (rl_delete_text (rl_point, new_point));
1079     }
1080 }
1081
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. */      
1086 int
1087 rl_rubout_or_delete (count, key)
1088      int count, key;
1089 {
1090   if (rl_end != 0 && rl_point == rl_end)
1091     return (_rl_rubout_char (count, key));
1092   else
1093     return (rl_delete (count, key));
1094 }  
1095
1096 /* Delete all spaces and tabs around point. */
1097 int
1098 rl_delete_horizontal_space (count, ignore)
1099      int count, ignore;
1100 {
1101   int start = rl_point;
1102
1103   while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
1104     rl_point--;
1105
1106   start = rl_point;
1107
1108   while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1109     rl_point++;
1110
1111   if (start != rl_point)
1112     {
1113       rl_delete_text (start, rl_point);
1114       rl_point = start;
1115     }
1116   return 0;
1117 }
1118
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. */
1122 int
1123 rl_delete_or_show_completions (count, key)
1124      int count, key;
1125 {
1126   if (rl_end != 0 && rl_point == rl_end)
1127     return (rl_possible_completions (count, key));
1128   else
1129     return (rl_delete (count, key));
1130 }
1131
1132 #ifndef RL_COMMENT_BEGIN_DEFAULT
1133 #define RL_COMMENT_BEGIN_DEFAULT "#"
1134 #endif
1135
1136 /* Turn the current line into a comment in shell history.
1137    A K*rn shell style function. */
1138 int
1139 rl_insert_comment (count, key)
1140      int count, key;
1141 {
1142   char *rl_comment_text;
1143   int rl_comment_len;
1144
1145   rl_beg_of_line (1, key);
1146   rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
1147
1148   if (rl_explicit_arg == 0)
1149     rl_insert_text (rl_comment_text);
1150   else
1151     {
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);
1157     }
1158
1159   (*rl_redisplay_function) ();
1160   rl_newline (1, '\n');
1161
1162   return (0);
1163 }
1164
1165 /* **************************************************************** */
1166 /*                                                                  */
1167 /*                      Changing Case                               */
1168 /*                                                                  */
1169 /* **************************************************************** */
1170
1171 /* The three kinds of things that we know how to do. */
1172 #define UpCase 1
1173 #define DownCase 2
1174 #define CapCase 3
1175
1176 /* Uppercase the word at point. */
1177 int
1178 rl_upcase_word (count, key)
1179      int count, key;
1180 {
1181   return (rl_change_case (count, UpCase));
1182 }
1183
1184 /* Lowercase the word at point. */
1185 int
1186 rl_downcase_word (count, key)
1187      int count, key;
1188 {
1189   return (rl_change_case (count, DownCase));
1190 }
1191
1192 /* Upcase the first letter, downcase the rest. */
1193 int
1194 rl_capitalize_word (count, key)
1195      int count, key;
1196 {
1197  return (rl_change_case (count, CapCase));
1198 }
1199
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;
1208 {
1209   register int start, end;
1210   int inword, c;
1211
1212   start = rl_point;
1213   rl_forward_word (count, 0);
1214   end = rl_point;
1215
1216   if (count < 0)
1217     SWAP (start, end);
1218
1219   /* We are going to modify some text, so let's prepare to undo it. */
1220   rl_modifying (start, end);
1221
1222   for (inword = 0; start < end; start++)
1223     {
1224       c = rl_line_buffer[start];
1225       switch (op)
1226         {
1227         case UpCase:
1228           rl_line_buffer[start] = _rl_to_upper (c);
1229           break;
1230
1231         case DownCase:
1232           rl_line_buffer[start] = _rl_to_lower (c);
1233           break;
1234
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;
1239
1240         default:
1241           rl_ding ();
1242           return -1;
1243         }
1244     }
1245   rl_point = end;
1246   return 0;
1247 }
1248
1249 /* **************************************************************** */
1250 /*                                                                  */
1251 /*                      Transposition                               */
1252 /*                                                                  */
1253 /* **************************************************************** */
1254
1255 /* Transpose the words at point.  If point is at the end of the line,
1256    transpose the two words before point. */
1257 int
1258 rl_transpose_words (count, key)
1259      int count, key;
1260 {
1261   char *word1, *word2;
1262   int w1_beg, w1_end, w2_beg, w2_end;
1263   int orig_point = rl_point;
1264
1265   if (!count)
1266     return 0;
1267
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;
1277
1278   /* Do some check to make sure that there really are two words. */
1279   if ((w1_beg == w2_beg) || (w2_beg < w1_end))
1280     {
1281       rl_ding ();
1282       rl_point = orig_point;
1283       return -1;
1284     }
1285
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);
1289
1290   /* We are about to do many insertions and deletions.  Remember them
1291      as one operation. */
1292   rl_begin_undo_group ();
1293
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);
1299
1300   rl_point = w1_beg;
1301   rl_delete_text (w1_beg, w1_end);
1302   rl_insert_text (word2);
1303
1304   /* This is exactly correct since the text before this point has not
1305      changed in length. */
1306   rl_point = w2_end;
1307
1308   /* I think that does it. */
1309   rl_end_undo_group ();
1310   free (word1);
1311   free (word2);
1312
1313   return 0;
1314 }
1315
1316 /* Transpose the characters at point.  If point is at the end of the line,
1317    then transpose the characters before point. */
1318 int
1319 rl_transpose_chars (count, key)
1320      int count, key;
1321 {
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;
1329
1330   if (count == 0)
1331     return 0;
1332
1333   if (!rl_point || rl_end < 2)
1334     {
1335       rl_ding ();
1336       return -1;
1337     }
1338
1339   rl_begin_undo_group ();
1340
1341   if (rl_point == rl_end)
1342     {
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;
1348     }
1349
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--;
1357
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
1368
1369   rl_delete_text (rl_point, rl_point + char_length);
1370
1371   rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1372
1373   _rl_fix_point (0);
1374   rl_insert_text (dummy);
1375   rl_end_undo_group ();
1376
1377 #if defined (HANDLE_MULTIBYTE)
1378   free (dummy);
1379 #endif
1380
1381   return 0;
1382 }
1383
1384 /* **************************************************************** */
1385 /*                                                                  */
1386 /*                      Character Searching                         */
1387 /*                                                                  */
1388 /* **************************************************************** */
1389
1390 int
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
1400 {
1401   int pos, inc;
1402 #if defined (HANDLE_MULTIBYTE)
1403   int prepos;
1404 #endif
1405
1406   pos = rl_point;
1407   inc = (dir < 0) ? -1 : 1;
1408   while (count)
1409     {
1410       if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
1411         {
1412           rl_ding ();
1413           return -1;
1414         }
1415
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
1422       do
1423         {
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
1429             {
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;
1438             }
1439 #if defined (HANDLE_MULTIBYTE)
1440           prepos = pos;
1441 #endif
1442         }
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
1449     }
1450   return (0);
1451 }
1452
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;
1461 {
1462   char mbchar[MB_LEN_MAX];
1463   int mb_len;
1464
1465   mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
1466
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));
1471 }
1472 #else /* !HANDLE_MULTIBYTE */
1473 static int
1474 _rl_char_search (count, fdir, bdir)
1475      int count, fdir, bdir;
1476 {
1477   int c;
1478
1479   RL_SETSTATE(RL_STATE_MOREINPUT);
1480   c = rl_read_key ();
1481   RL_UNSETSTATE(RL_STATE_MOREINPUT);
1482
1483   if (count < 0)
1484     return (_rl_char_search_internal (-count, bdir, c));
1485   else
1486     return (_rl_char_search_internal (count, fdir, c));
1487 }
1488 #endif /* !HANDLE_MULTIBYTE */
1489
1490 int
1491 rl_char_search (count, key)
1492      int count, key;
1493 {
1494   return (_rl_char_search (count, FFIND, BFIND));
1495 }
1496
1497 int
1498 rl_backward_char_search (count, key)
1499      int count, key;
1500 {
1501   return (_rl_char_search (count, BFIND, FFIND));
1502 }
1503
1504 /* **************************************************************** */
1505 /*                                                                  */
1506 /*                 The Mark and the Region.                         */
1507 /*                                                                  */
1508 /* **************************************************************** */
1509
1510 /* Set the mark at POSITION. */
1511 int
1512 _rl_set_mark_at_pos (position)
1513      int position;
1514 {
1515   if (position > rl_end)
1516     return -1;
1517
1518   rl_mark = position;
1519   return 0;
1520 }
1521
1522 /* A bindable command to set the mark. */
1523 int
1524 rl_set_mark (count, key)
1525      int count, key;
1526 {
1527   return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
1528 }
1529
1530 /* Exchange the position of mark and point. */
1531 int
1532 rl_exchange_point_and_mark (count, key)
1533      int count, key;
1534 {
1535   if (rl_mark > rl_end)
1536     rl_mark = -1;
1537
1538   if (rl_mark == -1)
1539     {
1540       rl_ding ();
1541       return -1;
1542     }
1543   else
1544     SWAP (rl_point, rl_mark);
1545
1546   return 0;
1547 }