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