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