]> git.ipfire.org Git - thirdparty/bash.git/blobdiff - lib/readline/text.c
Imported from ../bash-3.1.tar.gz.
[thirdparty/bash.git] / lib / readline / text.c
index d917e99b9bd63c659da105ed7ceac6d5becc7b32..9053e96903bb1c7bb78323a42c80a35061042a14 100644 (file)
@@ -1,6 +1,6 @@
 /* text.c -- text handling commands for readline. */
 
-/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
 
    This file is part of the GNU Readline Library, a library for
    reading lines of text with interactive input and history editing.
 static int rl_change_case PARAMS((int, int));
 static int _rl_char_search PARAMS((int, int, int));
 
+#if defined (READLINE_CALLBACKS)
+static int _rl_insert_next_callback PARAMS((_rl_callback_generic_arg *));
+static int _rl_char_search_callback PARAMS((_rl_callback_generic_arg *));
+#endif
+
 /* **************************************************************** */
 /*                                                                 */
 /*                     Insert and Delete                           */
@@ -420,8 +425,7 @@ rl_end_of_line (count, key)
   return 0;
 }
 
-/* XXX - these might need changes for multibyte characters */
-/* Move forward a word.  We do what Emacs does. */
+/* Move forward a word.  We do what Emacs does.  Handles multibyte chars. */
 int
 rl_forward_word (count, key)
      int count, key;
@@ -438,68 +442,80 @@ rl_forward_word (count, key)
 
       /* If we are not in a word, move forward until we are in one.
         Then, move forward until we hit a non-alphabetic character. */
-      c = rl_line_buffer[rl_point];
-      if (rl_alphabetic (c) == 0)
+      c = _rl_char_value (rl_line_buffer, rl_point);
+
+      if (_rl_walphabetic (c) == 0)
        {
-         while (++rl_point < rl_end)
+         rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+         while (rl_point < rl_end)
            {
-             c = rl_line_buffer[rl_point];
-             if (rl_alphabetic (c))
+             c = _rl_char_value (rl_line_buffer, rl_point);
+             if (_rl_walphabetic (c))
                break;
+             rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
            }
        }
 
       if (rl_point == rl_end)
        return 0;
 
-      while (++rl_point < rl_end)
+      rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+      while (rl_point < rl_end)
        {
-         c = rl_line_buffer[rl_point];
-         if (rl_alphabetic (c) == 0)
+         c = _rl_char_value (rl_line_buffer, rl_point);
+         if (_rl_walphabetic (c) == 0)
            break;
+         rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
        }
+
       --count;
     }
 
   return 0;
 }
 
-/* Move backward a word.  We do what Emacs does. */
+/* Move backward a word.  We do what Emacs does.  Handles multibyte chars. */
 int
 rl_backward_word (count, key)
      int count, key;
 {
-  int c;
+  int c, p;
 
   if (count < 0)
     return (rl_forward_word (-count, key));
 
   while (count)
     {
-      if (!rl_point)
+      if (rl_point == 0)
        return 0;
 
       /* Like rl_forward_word (), except that we look at the characters
         just before point. */
 
-      c = rl_line_buffer[rl_point - 1];
-      if (rl_alphabetic (c) == 0)
+      p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      c = _rl_char_value (rl_line_buffer, p);
+
+      if (_rl_walphabetic (c) == 0)
        {
-         while (--rl_point)
+         rl_point = p;
+         while (rl_point > 0)
            {
-             c = rl_line_buffer[rl_point - 1];
-             if (rl_alphabetic (c))
+             p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+             c = _rl_char_value (rl_line_buffer, p);
+             if (_rl_walphabetic (c))
                break;
+             rl_point = p;
            }
        }
 
       while (rl_point)
        {
-         c = rl_line_buffer[rl_point - 1];
-         if (rl_alphabetic (c) == 0)
+         p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+         c = _rl_char_value (rl_line_buffer, p);         
+         if (_rl_walphabetic (c) == 0)
            break;
          else
-           --rl_point;
+           rl_point = p;
        }
 
       --count;
@@ -756,10 +772,8 @@ _rl_insert_char (count, c)
       return 0;
     }
 
-#if defined (HANDLE_MULTIBYTE)
   if (MB_CUR_MAX == 1 || rl_byte_oriented)
     {
-#endif
       /* We are inserting a single character.
         If there is pending input, then make a string of all of the
         pending characters that are bound to rl_insert, and insert
@@ -775,8 +789,8 @@ _rl_insert_char (count, c)
          str[0] = c;
          rl_insert_text (str);
        }
-#if defined (HANDLE_MULTIBYTE)
     }
+#if defined (HANDLE_MULTIBYTE)
   else
     {
       rl_insert_text (incoming);
@@ -833,27 +847,63 @@ rl_insert (count, c)
 }
 
 /* Insert the next typed character verbatim. */
-int
-rl_quoted_insert (count, key)
-     int count, key;
+static int
+_rl_insert_next (count)
+     int count;
 {
   int c;
 
-#if defined (HANDLE_SIGNALS)
-  _rl_disable_tty_signals ();
-#endif
-
   RL_SETSTATE(RL_STATE_MOREINPUT);
   c = rl_read_key ();
   RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
 #if defined (HANDLE_SIGNALS)
-  _rl_restore_tty_signals ();
+  if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
+    _rl_restore_tty_signals ();
 #endif
 
   return (_rl_insert_char (count, c));  
 }
 
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_insert_next_callback (data)
+     _rl_callback_generic_arg *data;
+{
+  int count;
+
+  count = data->count;
+
+  /* Deregister function, let rl_callback_read_char deallocate data */
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+  return _rl_insert_next (count);
+}
+#endif
+  
+int
+rl_quoted_insert (count, key)
+     int count, key;
+{
+  /* Let's see...should the callback interface futz with signal handling? */
+#if defined (HANDLE_SIGNALS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
+    _rl_disable_tty_signals ();
+#endif
+
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_func = _rl_insert_next_callback;
+      return (0);
+    }
+#endif
+      
+  return _rl_insert_next (count);
+}
+
 /* Insert a tab character. */
 int
 rl_tab_insert (count, key)
@@ -988,43 +1038,17 @@ _rl_rubout_char (count, key)
       return -1;
     }
 
+  orig_point = rl_point;
   if (count > 1 || rl_explicit_arg)
     {
-      orig_point = rl_point;
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       rl_backward_char (count, key);
-      else
-#endif
-        rl_backward_byte (count, key);
+      rl_backward_char (count, key);
       rl_kill_text (orig_point, rl_point);
     }
-  else
+  else if (MB_CUR_MAX == 1 || rl_byte_oriented)
     {
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX == 1 || rl_byte_oriented)
-       {
-#endif
-         c = rl_line_buffer[--rl_point];
-         rl_delete_text (rl_point, rl_point + 1);
-#if defined (HANDLE_MULTIBYTE)
-       }
-      else
-       {
-         int orig_point;
-
-         orig_point = rl_point;
-         rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
-         c = rl_line_buffer[rl_point];
-         rl_delete_text (rl_point, orig_point);
-       }
-#endif /* HANDLE_MULTIBYTE */
-
-      /* I don't think that the hack for end of line is needed for
-        multibyte chars. */
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX == 1 || rl_byte_oriented)
-#endif
+      c = rl_line_buffer[--rl_point];
+      rl_delete_text (rl_point, orig_point);
+      /* The erase-at-end-of-line hack is of questionable merit now. */
       if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
        {
          int l;
@@ -1032,6 +1056,11 @@ _rl_rubout_char (count, key)
          _rl_erase_at_end_of_line (l);
        }
     }
+  else
+    {
+      rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      rl_delete_text (rl_point, orig_point);
+    }
 
   return 0;
 }
@@ -1056,11 +1085,9 @@ rl_delete (count, key)
   if (count > 1 || rl_explicit_arg)
     {
       int orig_point = rl_point;
-#if defined (HANDLE_MULTIBYTE)
       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
        rl_forward_char (count, key);
       else
-#endif
        rl_forward_byte (count, key);
 
       r = rl_kill_text (orig_point, rl_point);
@@ -1070,11 +1097,8 @@ rl_delete (count, key)
   else
     {
       int new_point;
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
-      else
-       new_point = rl_point + 1;
-       
+
+      new_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
       return (rl_delete_text (rl_point, new_point));
     }
 }
@@ -1113,6 +1137,10 @@ rl_delete_horizontal_space (count, ignore)
       rl_delete_text (start, rl_point);
       rl_point = start;
     }
+
+  if (rl_point < 0)
+    rl_point = 0;
+
   return 0;
 }
 
@@ -1206,42 +1234,80 @@ static int
 rl_change_case (count, op)
      int count, op;
 {
-  register int start, end;
-  int inword, c;
+  int start, next, end;
+  int inword, c, nc, nop;
+#if defined (HANDLE_MULTIBYTE)
+  wchar_t wc, nwc;
+  char mb[MB_LEN_MAX+1];
+  int mblen, p;
+  mbstate_t ps;
+#endif
 
   start = rl_point;
   rl_forward_word (count, 0);
   end = rl_point;
 
+  if (op != UpCase && op != DownCase && op != CapCase)
+    {
+      rl_ding ();
+      return -1;
+    }
+
   if (count < 0)
     SWAP (start, end);
 
+#if defined (HANDLE_MULTIBYTE)
+  memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
   /* We are going to modify some text, so let's prepare to undo it. */
   rl_modifying (start, end);
 
-  for (inword = 0; start < end; start++)
+  inword = 0;
+  while (start < end)
     {
-      c = rl_line_buffer[start];
-      switch (op)
-       {
-       case UpCase:
-         rl_line_buffer[start] = _rl_to_upper (c);
-         break;
+      c = _rl_char_value (rl_line_buffer, start);
+      /*  This assumes that the upper and lower case versions are the same width. */
+      next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO);
 
-       case DownCase:
-         rl_line_buffer[start] = _rl_to_lower (c);
-         break;
-
-       case CapCase:
-         rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
-         inword = rl_alphabetic (rl_line_buffer[start]);
-         break;
+      if (_rl_walphabetic (c) == 0)
+       {
+         inword = 0;
+         start = next;
+         continue;
+       }
 
-       default:
-         rl_ding ();
-         return -1;
+      if (op == CapCase)
+       {
+         nop = inword ? DownCase : UpCase;
+         inword = 1;
+       }
+      else
+       nop = op;
+      if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c))
+       {
+         nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c);
+         rl_line_buffer[start] = nc;
+       }
+#if defined (HANDLE_MULTIBYTE)
+      else
+       {
+         mbrtowc (&wc, rl_line_buffer + start, end - start, &ps);
+         nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
+         if  (nwc != wc)       /*  just skip unchanged characters */
+           {
+             mblen = wcrtomb (mb, nwc, &ps);
+             if (mblen > 0)
+               mb[mblen] = '\0';
+             /* Assume the same width */
+             strncpy (rl_line_buffer + start, mb, mblen);
+           }
        }
+#endif
+
+      start = next;
     }
+
   rl_point = end;
   return 0;
 }
@@ -1321,11 +1387,11 @@ rl_transpose_chars (count, key)
 {
 #if defined (HANDLE_MULTIBYTE)
   char *dummy;
-  int i, prev_point;
+  int i;
 #else
   char dummy[2];
 #endif
-  int char_length;
+  int char_length, prev_point;
 
   if (count == 0)
     return 0;
@@ -1340,20 +1406,12 @@ rl_transpose_chars (count, key)
 
   if (rl_point == rl_end)
     {
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
-      else
-       --rl_point;
+      rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
       count = 1;
     }
 
-#if defined (HANDLE_MULTIBYTE)
   prev_point = rl_point;
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
-  else
-#endif
-    rl_point--;
+  rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
 
 #if defined (HANDLE_MULTIBYTE)
   char_length = prev_point - rl_point;
@@ -1487,10 +1545,33 @@ _rl_char_search (count, fdir, bdir)
 }
 #endif /* !HANDLE_MULTIBYTE */
 
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_char_search_callback (data)
+     _rl_callback_generic_arg *data;
+{
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+
+  return (_rl_char_search (data->count, data->i1, data->i2));
+}
+#endif
+
 int
 rl_char_search (count, key)
      int count, key;
 {
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_data->i1 = FFIND;
+      _rl_callback_data->i2 = BFIND;
+      _rl_callback_func = _rl_char_search_callback;
+      return (0);
+    }
+#endif
+  
   return (_rl_char_search (count, FFIND, BFIND));
 }
 
@@ -1498,6 +1579,17 @@ int
 rl_backward_char_search (count, key)
      int count, key;
 {
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_data->i1 = BFIND;
+      _rl_callback_data->i2 = FFIND;
+      _rl_callback_func = _rl_char_search_callback;
+      return (0);
+    }
+#endif
+
   return (_rl_char_search (count, BFIND, FFIND));
 }