text.c revision 136644
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. */
62static int rl_change_case PARAMS((int, int));
63static 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. */
74int
75rl_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. */
112int
113rl_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
163void
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); */
176int
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. */
194void
195rl_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. */
247int
248rl_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. */
280int
281rl_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 */
313int
314rl_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. */
322int
323rl_forward (count, key)
324     int count, key;
325{
326  return (rl_forward_char (count, key));
327}
328
329/* Move backward COUNT bytes. */
330int
331rl_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. */
356int
357rl_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
389int
390rl_backward_char (count, key)
391     int count, key;
392{
393  return (rl_backward_byte (count, key));
394}
395#endif
396
397/* Backwards compatibility. */
398int
399rl_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. */
406int
407rl_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. */
415int
416rl_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. */
425int
426rl_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. */
468int
469rl_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. */
512int
513rl_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. */
534int
535rl_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
551int
552rl_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
599static char pending_bytes[MB_LEN_MAX];
600static int pending_bytes_length = 0;
601static 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. */
607int
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. */
793int
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
827int
828rl_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. */
836int
837rl_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. */
858int
859rl_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. */
868int
869rl_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. */
902int
903rl_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. */
912int
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. */
955int
956rl_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
974int
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. */
1041int
1042rl_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. */
1086int
1087rl_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. */
1097int
1098rl_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. */
1122int
1123rl_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. */
1138int
1139rl_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. */
1177int
1178rl_upcase_word (count, key)
1179     int count, key;
1180{
1181  return (rl_change_case (count, UpCase));
1182}
1183
1184/* Lowercase the word at point. */
1185int
1186rl_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. */
1193int
1194rl_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. */
1205static int
1206rl_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. */
1257int
1258rl_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. */
1318int
1319rl_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
1390int
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)
1458static 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 */
1473static 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
1490int
1491rl_char_search (count, key)
1492     int count, key;
1493{
1494  return (_rl_char_search (count, FFIND, BFIND));
1495}
1496
1497int
1498rl_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. */
1511int
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. */
1523int
1524rl_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. */
1531int
1532rl_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}
1548