]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20041021 snapshot
authorChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 18:38:20 +0000 (13:38 -0500)
committerChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 18:38:20 +0000 (13:38 -0500)
27 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
bashline.c
bashline.c~
doc/version.texi
execute_cmd.c
execute_cmd.c~
externs.h
general.c
general.c.diff [new file with mode: 0644]
lib/readline/mbutil.c
lib/readline/mbutil.c~ [new file with mode: 0644]
lib/readline/rlmbutil.h
lib/readline/rlmbutil.h~ [new file with mode: 0644]
lib/readline/rltty.c
lib/readline/rltty.c~ [new file with mode: 0644]
lib/readline/text.c
lib/readline/text.c.save [new file with mode: 0644]
lib/readline/text.c.save2 [new file with mode: 0644]
lib/readline/util.c
lib/readline/util.c~ [new file with mode: 0644]
lib/sh/shquote.c
lib/sh/strtrans.c
parse.y
tests/RUN-ONE-TEST
tests/run-nquote4
variables.c

index 5374fc7b0134917bef111d52d635d407027e3925..75a1cc255beb04277ee64122f05e5d51c6bc828e 100644 (file)
@@ -10358,3 +10358,76 @@ builtins/pushd.def
 lib/readline/shell.c
        - change sh_set_lines_and_columns to prefer setenv, which has
          predictable memory allocation behavior, to putenv, which does not
+
+                                  10/19
+                                  -----
+variables.c
+       - change push_exported_var so that a tempenv variable has to have the
+         export attribute set (which they all do -- something to look at) and
+         the `propagate' attribute set to be propagated down to the next
+         scope
+
+execute_cmd.c
+       - change execute_builtin so that if CMD_COMMAND_BUILTIN is set in the
+         passed flags argument, call pop_scope with a value that says the
+         builtin is not special, since `command' means that preceding variable
+         assignments don't persist in the environment.  Fixes problem with
+         variable assignments preceding command preceding special builtin
+         kept those variable assignments around (when in posix mode)
+
+                                  10/20
+                                  -----
+lib/sh/shquote.c
+       - new function, sh_mkdoublequoted, brackets a given string with
+         double quotes and returns a new string.  Flags argument, if non-
+         zero, means to quote embedded double quotes with backslashes
+
+externs.h
+       - new extern declaration for sh_mkdoublequoted
+
+parse.y
+       - use sh_mkdoublequoted after calling localeexpand()
+
+lib/sh/strtrans.c
+       - change ansicstr to understand that  (flags & 4) != 0 means to remove
+         backslash from unrecognized escape sequences
+
+general.c
+       - fix logic problem in assignment() that caused non-variable-starter
+         characters to be allowed, resulting in things like `1=xxx' creating
+         a variable `1' in the hash table
+
+                                  10/21
+                                  -----
+bashline.c
+       - don't call programmable_completions with an assignment statement
+         argument
+
+                                  10/22
+                                  -----
+lib/readline/rltty.c
+       - in prepare_terminal_settings, turn echoing on (readline_echoing_p)
+         if get_tty_settings fails because the input is not a terminal
+
+                                  10/24
+                                  -----
+lib/readline/util.c
+       - include rlmbutil.h for multibyte definitions
+       - new function, _rl_walphabetic, wide char version of rl_alphabetic
+
+lib/readline/mbutil.c
+       - new function, _rl_char_value(buf, ind), returns value of (possibly
+         multibyte) character at buf[ind]
+
+lib/readline/rlmbutil.h
+       - extern defines for _rl_walphabetic and _rl_char_value for when
+         multibyte chars are not being used
+       - new wrapper definitions for _rl_find_next_mbchar (MB_NEXTCHAR) and
+         _rl_find_prev_mbchar (MB_PREVCHAR) that try to avoid unneeded
+         function calls
+
+lib/readline/text.c
+       - fix rl_foward_word to work with multibyte characters (or in a
+         multibyte locale) using above utility functions
+       - fix rl_backward_word to work with multibyte characters (or in a
+         multibyte locale) using above utility functions
index 77e1c5195677b5257303ddab9276e6c65f307c20..1fbb6a96dd1fd1b023485d6e219743ceb6975ba3 100644 (file)
@@ -10352,3 +10352,77 @@ doc/bash.1,lib/readline/doc/{readline.3,rluser.texi}
 builtins/pushd.def
        - make the first check for option `--' skip the rest of option
          checking
+
+                                  10/16
+                                  -----
+lib/readline/shell.c
+       - change sh_set_lines_and_columns to prefer setenv, which has
+         predictable memory allocation behavior, to putenv, which does not
+
+                                  10/19
+                                  -----
+variables.c
+       - change push_exported_var so that a tempenv variable has to have the
+         export attribute set (which they all do -- something to look at) and
+         the `propagate' attribute set to be propagated down to the next
+         scope
+
+execute_cmd.c
+       - change execute_builtin so that if CMD_COMMAND_BUILTIN is set in the
+         passed flags argument, call pop_scope with a value that says the
+         builtin is not special, since `command' means that preceding variable
+         assignments don't persist in the environment.  Fixes problem with
+         variable assignments preceding command preceding special builtin
+         kept those variable assignments around (when in posix mode)
+
+                                  10/20
+                                  -----
+lib/sh/shquote.c
+       - new function, sh_mkdoublequoted, brackets a given string with
+         double quotes and returns a new string.  Flags argument, if non-
+         zero, means to quote embedded double quotes with backslashes
+
+externs.h
+       - new extern declaration for sh_mkdoublequoted
+
+parse.y
+       - use sh_mkdoublequoted after calling localeexpand()
+
+lib/sh/strtrans.c
+       - change ansicstr to understand that  (flags & 4) != 0 means to remove
+         backslash from unrecognized escape sequences
+
+general.c
+       - fix logic problem in assignment() that caused non-variable-starter
+         characters to be allowed, resulting in things like `1=xxx' creating
+         a variable `1' in the hash table
+
+                                  10/21
+                                  -----
+bashline.c
+       - don't call programmable_completions with an assignment statement
+         argument
+
+                                  10/22
+                                  -----
+lib/readline/rltty.c
+       - in prepare_terminal_settings, turn echoing on (readline_echoing_p)
+         if get_tty_settings fails because the input is not a terminal
+
+                                  10/24
+                                  -----
+lib/readline/util.c
+       - include rlmbutil.h for multibyte definitions
+       - new function, _rl_walphabetic, wide char version of rl_alphabetic
+
+lib/readline/mbutil.c
+       - new function, _rl_char_value(buf, ind), returns value of (possibly
+         multibyte) character at buf[ind]
+
+lib/readline/rlmbutil.h
+       - extern defines for _rl_walphabetic and _rl_char_value for when
+         multibyte chars are not being used
+
+lib/readline/text.c
+       - fix rl_foward_word to work with multibyte characters (or in a
+         multibyte locale) using above utility functions
index 7d641613c3fd4d4f7accfe77ef38327c128adaef..1ab44999f03b1524eabb2e6b017708e4f1354019 100644 (file)
@@ -1073,7 +1073,7 @@ attempt_shell_completion (text, start, end)
       s = find_cmd_start (start);
       e = find_cmd_end (end);
       n = find_cmd_name (s);
-      if (e > s)
+      if (e > s && assignment (n, 0) == 0)
        prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
       else
        foundcs = 0;
index 7d2b2298a6e1db55366da1f18f533394efeb4ecc..7d641613c3fd4d4f7accfe77ef38327c128adaef 100644 (file)
@@ -1166,7 +1166,10 @@ bash_default_completion (text, start, end, qc, in_command_position)
               directory (because it's not in $PATH), but the found name is
               also a command in the current directory, suppress appending any
               terminating character, since it's ambiguous. */
-           rl_completion_suppress_append = 1;
+           {
+             rl_completion_suppress_append = 1;
+             rl_filename_completion_desired = 0;
+           }
          else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0]))
            /* There are multiple instances of the same match (duplicate
               completions haven't yet been removed).  In this case, all of
@@ -1176,7 +1179,10 @@ bash_default_completion (text, start, end, qc, in_command_position)
               Remember: we only care if there's eventually a single unique
               completion.  If there are multiple completions this won't
               make a difference and the problem won't occur. */
-           rl_completion_suppress_append = 1;
+           {
+             rl_completion_suppress_append = 1;
+             rl_filename_completion_desired = 0;
+           }
        }
     }
 
index 1f19521d37e9fdaa03f9c8672c2840812f8f06bc..0490f6a51fd43f64621074c52732bdcf93e65221 100644 (file)
@@ -4,7 +4,7 @@ Copyright (C) 1988-2004 Free Software Foundation, Inc.
 
 @set EDITION 3.1-devel
 @set VERSION 3.1-devel
-@set UPDATED 15 October 2004
+@set UPDATED 20 October 2004
 @set UPDATED-MONTH October 2004
 
-@set LASTCHANGE Fri Oct 15 14:53:01 EDT 2004
+@set LASTCHANGE Wed Oct 20 09:54:44 EDT 2004
index 968f23454cc9f69bb10a8dd5185d86864442e162..96887a97f770389386d7fe895487eaf69d268daf 100644 (file)
@@ -3053,7 +3053,7 @@ execute_builtin (builtin, words, flags, subshell)
        {
          push_scope (VC_BLTNENV, temporary_env);
          if (subshell == 0)
-           add_unwind_protect (pop_scope, "1");
+           add_unwind_protect (pop_scope, (flags & CMD_COMMAND_BUILTIN) ? 0 : "1");
           temporary_env = (HASH_TABLE *)NULL;    
        }
     }
index 968f23454cc9f69bb10a8dd5185d86864442e162..cd9b083229c9d263fe81275e94c6e4d53ba78eb1 100644 (file)
@@ -2281,6 +2281,7 @@ execute_while_or_until (while_command, type)
       return_value = execute_command (while_command->test);
       REAP ();
 
+itrace("execute_while_or_until: test returns %d", return_value);
       /* Need to handle `break' in the test when we would break out of the
          loop.  The job control code will set `breaking' to loop_level
          when a job in a loop is stopped with SIGTSTP.  If the stopped job
@@ -2303,6 +2304,7 @@ execute_while_or_until (while_command, type)
       body_status = execute_command (while_command->action);
       QUIT;
 
+itrace("execute_while_or_until: body returns %d", body_status);
       if (breaking)
        {
          breaking--;
@@ -3053,7 +3055,7 @@ execute_builtin (builtin, words, flags, subshell)
        {
          push_scope (VC_BLTNENV, temporary_env);
          if (subshell == 0)
-           add_unwind_protect (pop_scope, "1");
+           add_unwind_protect (pop_scope, (flags & CMD_COMMAND_BUILTIN) ? 0 : "1");
           temporary_env = (HASH_TABLE *)NULL;    
        }
     }
index b382cbdeb148a3ba927360ec324a6c6680a395f8..541832ef73b38be89b2a2fccf9e23d809993fe58 100644 (file)
--- a/externs.h
+++ b/externs.h
@@ -235,6 +235,7 @@ extern int sh_regmatch __P((const char *, const char *, int));
 /* declarations for functions defined in lib/sh/shquote.c */
 extern char *sh_single_quote __P((char *));
 extern char *sh_double_quote __P((char *));
+extern char *sh_mkdoublequoted __P((const char *, int, int));
 extern char *sh_un_double_quote __P((char *));
 extern char *sh_backslash_quote __P((char *));
 extern char *sh_backslash_quote_for_double_quotes __P((char *));
index de31707dc91b2d9296ab6c839c692780043af8f7..46a959d90a1b97398bd5d7eb5f1b28cbb61d585d 100644 (file)
--- a/general.c
+++ b/general.c
@@ -269,7 +269,7 @@ assignment (string, flags)
   c = string[indx = 0];
 
 #if defined (ARRAY_VARS)
-  if ((legal_variable_starter (c) == 0) && (flags && c != '[')) /* ] */
+  if ((legal_variable_starter (c) == 0) && (flags == 0 || c != '[')) /* ] */
 #else
   if (legal_variable_starter (c) == 0)
 #endif
diff --git a/general.c.diff b/general.c.diff
new file mode 100644 (file)
index 0000000..6c3d76b
--- /dev/null
@@ -0,0 +1,15 @@
+*** ../bash-3.0-patched/general.c      Wed Apr 14 23:20:13 2004
+--- general.c  Wed Oct 20 16:59:59 2004
+***************
+*** 268,272 ****
+  
+  #if defined (ARRAY_VARS)
+!   if ((legal_variable_starter (c) == 0) && (flags && c != '[')) /* ] */
+  #else
+    if (legal_variable_starter (c) == 0)
+--- 268,272 ----
+  
+  #if defined (ARRAY_VARS)
+!   if ((legal_variable_starter (c) == 0) && (flags == 0 || c != '[')) /* ] */
+  #else
+    if (legal_variable_starter (c) == 0)
index 695845a60f4e5fbc5a765ca2a34ac9a00d2673c9..933eecc073bd26e94732a70113fc6b0be24c7d24 100644 (file)
@@ -313,6 +313,28 @@ _rl_is_mbchar_matched (string, seed, end, mbchar, length)
       return 0;
   return 1;
 }
+
+wchar_t
+_rl_char_value (buf, ind)
+     char *buf;
+     int ind;
+{
+  size_t tmp;
+  wchar_t wc;
+  mbstate_t ps;
+  int l;
+
+  if (MB_LEN_MAX == 1 || rl_byte_oriented)
+    return ((wchar_t) buf[ind]);
+  l = strlen (buf);
+  if (ind >= l - 1)
+    return ((wchar_t) buf[ind]);
+  memset (&ps, 0, sizeof (mbstate_t));
+  tmp = mbrtowc (&wc, buf + ind, l - ind, &ps);
+  if (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp))  
+    return ((wchar_t) buf[ind]);
+  return wc;
+}
 #endif /* HANDLE_MULTIBYTE */
 
 /* Find next `count' characters started byte point of the specified seed.
diff --git a/lib/readline/mbutil.c~ b/lib/readline/mbutil.c~
new file mode 100644 (file)
index 0000000..870a341
--- /dev/null
@@ -0,0 +1,372 @@
+/* mbutil.c -- readline multibyte character utility functions */
+
+/* Copyright (C) 2001-2004 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.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "posixjmp.h"
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>     /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (TIOCSTAT_IN_SYS_IOCTL)
+#  include <sys/ioctl.h>
+#endif /* TIOCSTAT_IN_SYS_IOCTL */
+
+/* Some standard library routines. */
+#include "readline.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* Declared here so it can be shared between the readline and history
+   libraries. */
+#if defined (HANDLE_MULTIBYTE)
+int rl_byte_oriented = 0;
+#else
+int rl_byte_oriented = 1;
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*             Multibyte Character Utility Functions               */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined(HANDLE_MULTIBYTE)
+
+static int
+_rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
+     char *string;
+     int seed, count, find_non_zero;
+{
+  size_t tmp = 0;
+  mbstate_t ps;
+  int point = 0;
+  wchar_t wc;
+
+  memset(&ps, 0, sizeof (mbstate_t));
+  if (seed < 0)
+    seed = 0;
+  if (count <= 0)
+    return seed;
+
+  point = seed + _rl_adjust_point(string, seed, &ps);
+  /* if this is true, means that seed was not pointed character
+     started byte.  So correct the point and consume count */
+  if (seed < point)
+    count--;
+
+  while (count > 0)  
+    {
+      tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps);
+      if (MB_INVALIDCH ((size_t)tmp))
+       {
+         /* invalid bytes. asume a byte represents a character */
+         point++;
+         count--;
+         /* reset states. */
+         memset(&ps, 0, sizeof(mbstate_t));
+       }
+      else if (MB_NULLWCH (tmp))
+       break;                  /* found wide '\0' */
+      else
+       {
+         /* valid bytes */
+         point += tmp;
+         if (find_non_zero)
+           {
+             if (wcwidth (wc) == 0)
+               continue;
+             else
+               count--;
+           }
+         else
+           count--;
+       }
+    }
+
+  if (find_non_zero)
+    {
+      tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
+      while (tmp > 0 && wcwidth (wc) == 0)
+       {
+         point += tmp;
+         tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
+         if (MB_NULLWCH (tmp) || MB_INVALIDCH (tmp))
+           break;
+       }
+    }
+    return point;
+}
+
+static int
+_rl_find_prev_mbchar_internal (string, seed, find_non_zero)
+     char *string;
+     int seed, find_non_zero;
+{
+  mbstate_t ps;
+  int prev, non_zero_prev, point, length;
+  size_t tmp;
+  wchar_t wc;
+
+  memset(&ps, 0, sizeof(mbstate_t));
+  length = strlen(string);
+  
+  if (seed < 0)
+    return 0;
+  else if (length < seed)
+    return length;
+
+  prev = non_zero_prev = point = 0;
+  while (point < seed)
+    {
+      tmp = mbrtowc (&wc, string + point, length - point, &ps);
+      if (MB_INVALIDCH ((size_t)tmp))
+       {
+         /* in this case, bytes are invalid or shorted to compose
+            multibyte char, so assume that the first byte represents
+            a single character anyway. */
+         tmp = 1;
+         /* clear the state of the byte sequence, because
+            in this case effect of mbstate is undefined  */
+         memset(&ps, 0, sizeof (mbstate_t));
+
+         /* Since we're assuming that this byte represents a single
+            non-zero-width character, don't forget about it. */
+         prev = point;
+       }
+      else if (MB_NULLWCH (tmp))
+       break;                  /* Found '\0' char.  Can this happen? */
+      else
+       {
+         if (find_non_zero)
+           {
+             if (wcwidth (wc) != 0)
+               prev = point;
+           }
+         else
+           prev = point;  
+       }
+
+      point += tmp;
+    }
+
+  return prev;
+}
+
+/* return the number of bytes parsed from the multibyte sequence starting
+   at src, if a non-L'\0' wide character was recognized. It returns 0, 
+   if a L'\0' wide character was recognized. It  returns (size_t)(-1), 
+   if an invalid multibyte sequence was encountered. It returns (size_t)(-2) 
+   if it couldn't parse a complete  multibyte character.  */
+int
+_rl_get_char_len (src, ps)
+     char *src;
+     mbstate_t *ps;
+{
+  size_t tmp;
+
+  tmp = mbrlen((const char *)src, (size_t)strlen (src), ps);
+  if (tmp == (size_t)(-2))
+    {
+      /* shorted to compose multibyte char */
+      if (ps)
+       memset (ps, 0, sizeof(mbstate_t));
+      return -2;
+    }
+  else if (tmp == (size_t)(-1))
+    {
+      /* invalid to compose multibyte char */
+      /* initialize the conversion state */
+      if (ps)
+       memset (ps, 0, sizeof(mbstate_t));
+      return -1;
+    }
+  else if (tmp == (size_t)0)
+    return 0;
+  else
+    return (int)tmp;
+}
+
+/* compare the specified two characters. If the characters matched,
+   return 1. Otherwise return 0. */
+int
+_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
+     char *buf1;
+     int pos1;
+     mbstate_t *ps1;
+     char *buf2;
+     int pos2;
+     mbstate_t *ps2;
+{
+  int i, w1, w2;
+
+  if ((w1 = _rl_get_char_len (&buf1[pos1], ps1)) <= 0 || 
+       (w2 = _rl_get_char_len (&buf2[pos2], ps2)) <= 0 ||
+       (w1 != w2) ||
+       (buf1[pos1] != buf2[pos2]))
+    return 0;
+
+  for (i = 1; i < w1; i++)
+    if (buf1[pos1+i] != buf2[pos2+i])
+      return 0;
+
+  return 1;
+}
+
+/* adjust pointed byte and find mbstate of the point of string.
+   adjusted point will be point <= adjusted_point, and returns
+   differences of the byte(adjusted_point - point).
+   if point is invalied (point < 0 || more than string length),
+   it returns -1 */
+int
+_rl_adjust_point(string, point, ps)
+     char *string;
+     int point;
+     mbstate_t *ps;
+{
+  size_t tmp = 0;
+  int length;
+  int pos = 0;
+
+  length = strlen(string);
+  if (point < 0)
+    return -1;
+  if (length < point)
+    return -1;
+  
+  while (pos < point)
+    {
+      tmp = mbrlen (string + pos, length - pos, ps);
+      if (MB_INVALIDCH ((size_t)tmp))
+       {
+         /* in this case, bytes are invalid or shorted to compose
+            multibyte char, so assume that the first byte represents
+            a single character anyway. */
+         pos++;
+         /* clear the state of the byte sequence, because
+            in this case effect of mbstate is undefined  */
+         if (ps)
+           memset (ps, 0, sizeof (mbstate_t));
+       }
+      else if (MB_NULLWCH (tmp))
+       pos++;
+      else
+       pos += tmp;
+    }
+
+  return (pos - point);
+}
+
+int
+_rl_is_mbchar_matched (string, seed, end, mbchar, length)
+     char *string;
+     int seed, end;
+     char *mbchar;
+     int length;
+{
+  int i;
+
+  if ((end - seed) < length)
+    return 0;
+
+  for (i = 0; i < length; i++)
+    if (string[seed + i] != mbchar[i])
+      return 0;
+  return 1;
+}
+
+#ifdef _rl_char_value
+#error whoops
+#endif
+
+wchar_t
+_rl_char_value (char *buf, int ind)
+{
+  size_t tmp;
+  wchar_t wc;
+  mbstate_t ps;
+  int l;
+
+  if (MB_LEN_MAX == 1 || rl_byte_oriented)
+    return ((wchar_t) buf[ind]);
+  l = strlen (buf);
+  if (ind >= l - 1)
+    return ((wchar_t) buf[ind]);
+  memset (&ps, 0, sizeof (mbstate_t));
+  tmp = mbrtowc (&wc, buf + ind, l - ind, &ps);
+  if (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp))  
+    return ((wchar_t) buf[ind]);
+  return wc;
+}
+#endif /* HANDLE_MULTIBYTE */
+
+/* Find next `count' characters started byte point of the specified seed.
+   If flags is MB_FIND_NONZERO, we look for non-zero-width multibyte
+   characters. */
+#undef _rl_find_next_mbchar
+int
+_rl_find_next_mbchar (string, seed, count, flags)
+     char *string;
+     int seed, count, flags;
+{
+#if defined (HANDLE_MULTIBYTE)
+  return _rl_find_next_mbchar_internal (string, seed, count, flags);
+#else
+  return (seed + count);
+#endif
+}
+
+/* Find previous character started byte point of the specified seed.
+   Returned point will be point <= seed.  If flags is MB_FIND_NONZERO,
+   we look for non-zero-width multibyte characters. */
+#undef _rl_find_prev_mbchar
+int
+_rl_find_prev_mbchar (string, seed, flags)
+     char *string;
+     int seed, flags;
+{
+#if defined (HANDLE_MULTIBYTE)
+  return _rl_find_prev_mbchar_internal (string, seed, flags);
+#else
+  return ((seed == 0) ? seed : seed - 1);
+#endif
+}
index 77cc026e3e8aa7a64838a0f77b7400141b2d7814..9cdd87c01c345632b6d8771fb26c344b0d102c38 100644 (file)
@@ -97,6 +97,18 @@ extern int _rl_read_mbstring PARAMS((int, char *, int));
 
 extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int));
 
+extern int _rl_char_value PARAMS((char *, int));
+extern int _rl_walphabetic PARAMS((wchar_t));
+
+#define MB_NEXTCHAR(b,s,c,f) \
+       ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) \
+               ? _rl_find_next_mbchar ((b), (s), (c), (f)) \
+               : ((s) + (c)))
+#define MB_PREVCHAR(b,s,f) \
+       ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) \
+               ? _rl_find_prev_mbchar ((b), (s), (f)) \
+               : ((s) - 1))
+
 #define MB_INVALIDCH(x)                ((x) == (size_t)-1 || (x) == (size_t)-2)
 #define MB_NULLWCH(x)          ((x) == 0)
 
@@ -111,6 +123,13 @@ extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int));
 #define _rl_find_prev_mbchar(b, i, f)          (((i) == 0) ? (i) : ((i) - 1))
 #define _rl_find_next_mbchar(b, i1, i2, f)     ((i1) + (i2))
 
+#define _rl_char_value(buf,ind)        ((buf)[(ind)])
+
+#define _rl_walphabetic(c)     (rl_alphabetic (c))
+
+#define MB_NEXTCHAR(b,s,c,f)   ((s) + (c))
+#define MB_PREVCHAR(b,s,f)     ((s) - 1)
+
 #define MB_INVALIDCH(x)                (0)
 #define MB_NULLWCH(x)          (0)
 
diff --git a/lib/readline/rlmbutil.h~ b/lib/readline/rlmbutil.h~
new file mode 100644 (file)
index 0000000..eb71821
--- /dev/null
@@ -0,0 +1,140 @@
+/* rlmbutil.h -- utility functions for multibyte characters. */
+
+/* Copyright (C) 2001 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.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RL_MBUTIL_H_)
+#define _RL_MBUTIL_H_
+
+#include "rlstdc.h"
+
+/************************************************/
+/* check multibyte capability for I18N code     */
+/************************************************/
+
+/* For platforms which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+   /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
+#  include <wchar.h>
+#  include <wctype.h>
+#  if defined (HAVE_MBSRTOWCS) && defined (HAVE_MBRTOWC) && defined (HAVE_MBRLEN) && defined (HAVE_WCWIDTH)
+     /* system is supposed to support XPG5 */
+#    define HANDLE_MULTIBYTE      1
+#  endif
+#endif
+
+/* If we don't want multibyte chars even on a system that supports them, let
+   the configuring user turn multibyte support off. */
+#if defined (NO_MULTIBYTE_SUPPORT)
+#  undef HANDLE_MULTIBYTE
+#endif
+
+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
+#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
+#  define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
+#  define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0)
+#  define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0)
+#  define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
+#  define mbrlen(s, n, ps) (mbrlen) (s, n, 0)
+#  define mbstate_t int
+#endif
+
+/* Make sure MB_LEN_MAX is at least 16 on systems that claim to be able to
+   handle multibyte chars (some systems define MB_LEN_MAX as 1) */
+#ifdef HANDLE_MULTIBYTE
+#  include <limits.h>
+#  if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16)
+#    undef MB_LEN_MAX
+#  endif
+#  if !defined (MB_LEN_MAX)
+#    define MB_LEN_MAX 16
+#  endif
+#endif
+
+/************************************************/
+/* end of multibyte capability checks for I18N  */
+/************************************************/
+
+/*
+ * Flags for _rl_find_prev_mbchar and _rl_find_next_mbchar:
+ *
+ * MB_FIND_ANY         find any multibyte character
+ * MB_FIND_NONZERO     find a non-zero-width multibyte character
+ */
+
+#define MB_FIND_ANY    0x00
+#define MB_FIND_NONZERO        0x01
+
+extern int _rl_find_prev_mbchar PARAMS((char *, int, int));
+extern int _rl_find_next_mbchar PARAMS((char *, int, int, int));
+
+#ifdef HANDLE_MULTIBYTE
+
+extern int _rl_compare_chars PARAMS((char *, int, mbstate_t *, char *, int, mbstate_t *));
+extern int _rl_get_char_len PARAMS((char *, mbstate_t *));
+extern int _rl_adjust_point PARAMS((char *, int, mbstate_t *));
+
+extern int _rl_read_mbchar PARAMS((char *, int));
+extern int _rl_read_mbstring PARAMS((int, char *, int));
+
+extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int));
+
+extern int _rl_char_value PARAMS((char *, int));
+extern int _rl_walphabetic PARAMS((wchar_t));
+
+#define NEXT_MBCHAR(b,s,c,f) \
+       ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) \
+               ? _rl_find_next_mbchar ((b), (s), (c), (f)) \
+               : ((s) + (c)))
+#define PREV_MBCHAR(b,s,f) \
+       ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) \
+               ? _rl_find_prev_mbchar ((b), (s), (f)) \
+               : ((s) - 1))
+
+#define MB_INVALIDCH(x)                ((x) == (size_t)-1 || (x) == (size_t)-2)
+#define MB_NULLWCH(x)          ((x) == 0)
+
+#else /* !HANDLE_MULTIBYTE */
+
+#undef MB_LEN_MAX
+#undef MB_CUR_MAX
+
+#define MB_LEN_MAX     1
+#define MB_CUR_MAX     1
+
+#define _rl_find_prev_mbchar(b, i, f)          (((i) == 0) ? (i) : ((i) - 1))
+#define _rl_find_next_mbchar(b, i1, i2, f)     ((i1) + (i2))
+
+#define _rl_char_value(buf,ind)        ((buf)[(ind)])
+
+#define _rl_walphabetic(c)     (rl_alphabetic (c))
+
+#define NEXT_MBCHAR(b,s,c,f)   ((s) + (c))
+#define PREV_MBCHAR(b,s,f)     ((s) - 1)
+
+#define MB_INVALIDCH(x)                (0)
+#define MB_NULLWCH(x)          (0)
+
+#endif /* !HANDLE_MULTIBYTE */
+
+extern int rl_byte_oriented;
+
+#endif /* _RL_MBUTIL_H_ */
index f233647abb0cedaaa4daaed1088d7b73eb686b5c..8b89a8a5b14a05e728b6569bc87204f00e111547 100644 (file)
@@ -233,6 +233,7 @@ get_tty_settings (tty, tiop)
 
   tiop->flags = tiop->lflag = 0;
 
+  errno = 0;
   if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0)
     return -1;
   tiop->flags |= SGTTY_SET;
@@ -518,6 +519,7 @@ get_tty_settings (tty, tiop)
 {
   set_winsize (tty);
 
+  errno = 0;
   if (_get_tty_settings (tty, tiop) < 0)
     return -1;
 
@@ -651,6 +653,13 @@ rl_prep_terminal (meta_flag)
 
   if (get_tty_settings (tty, &tio) < 0)
     {
+#if defined (ENOTSUP)
+      /* MacOS X, at least, lies about the value of errno if tcgetattr fails. */
+      if (errno == ENOTTY || errno == ENOTSUP)
+#else
+      if (errno == ENOTTY)
+#endif
+       readline_echoing_p = 1;         /* XXX */
       release_sigint ();
       return;
     }
diff --git a/lib/readline/rltty.c~ b/lib/readline/rltty.c~
new file mode 100644 (file)
index 0000000..22947bd
--- /dev/null
@@ -0,0 +1,979 @@
+/* rltty.c -- functions to prepare and restore the terminal for readline's
+   use. */
+
+/* Copyright (C) 1992 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.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL)
+#  include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL */
+
+#include "rltty.h"
+#include "readline.h"
+#include "rlprivate.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal;
+rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal;
+
+static void block_sigint PARAMS((void));
+static void release_sigint PARAMS((void));
+
+static void set_winsize PARAMS((int));
+
+/* **************************************************************** */
+/*                                                                 */
+/*                        Signal Management                        */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined (HAVE_POSIX_SIGNALS)
+static sigset_t sigint_set, sigint_oset;
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+static int sigint_oldmask;
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+static int sigint_blocked;
+
+/* Cause SIGINT to not be delivered until the corresponding call to
+   release_sigint(). */
+static void
+block_sigint ()
+{
+  if (sigint_blocked)
+    return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+  sigemptyset (&sigint_set);
+  sigemptyset (&sigint_oset);
+  sigaddset (&sigint_set, SIGINT);
+  sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+  sigint_oldmask = sigblock (sigmask (SIGINT));
+#  else /* !HAVE_BSD_SIGNALS */
+#    if defined (HAVE_USG_SIGHOLD)
+  sighold (SIGINT);
+#    endif /* HAVE_USG_SIGHOLD */
+#  endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+  sigint_blocked = 1;
+}
+
+/* Allow SIGINT to be delivered. */
+static void
+release_sigint ()
+{
+  if (sigint_blocked == 0)
+    return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+  sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
+#else
+#  if defined (HAVE_BSD_SIGNALS)
+  sigsetmask (sigint_oldmask);
+#  else /* !HAVE_BSD_SIGNALS */
+#    if defined (HAVE_USG_SIGHOLD)
+  sigrelse (SIGINT);
+#    endif /* HAVE_USG_SIGHOLD */
+#  endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+  sigint_blocked = 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                   Saving and Restoring the TTY                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means that the terminal is in a prepped state. */
+static int terminal_prepped;
+
+static _RL_TTY_CHARS _rl_tty_chars, _rl_last_tty_chars;
+
+/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
+   and output is suspended. */
+#if defined (__ksr1__)
+static int ksrflow;
+#endif
+
+/* Dummy call to force a backgrounded readline to stop before it tries
+   to get the tty settings. */
+static void
+set_winsize (tty)
+     int tty;
+{
+#if defined (TIOCGWINSZ)
+  struct winsize w;
+
+  if (ioctl (tty, TIOCGWINSZ, &w) == 0)
+      (void) ioctl (tty, TIOCSWINSZ, &w);
+#endif /* TIOCGWINSZ */
+}
+
+#if defined (NEW_TTY_DRIVER)
+
+/* Values for the `flags' field of a struct bsdtty.  This tells which
+   elements of the struct bsdtty have been fetched from the system and
+   are valid. */
+#define SGTTY_SET      0x01
+#define LFLAG_SET      0x02
+#define TCHARS_SET     0x04
+#define LTCHARS_SET    0x08
+
+struct bsdtty {
+  struct sgttyb sgttyb;        /* Basic BSD tty driver information. */
+  int lflag;           /* Local mode flags, like LPASS8. */
+#if defined (TIOCGETC)
+  struct tchars tchars;        /* Terminal special characters, including ^S and ^Q. */
+#endif
+#if defined (TIOCGLTC)
+  struct ltchars ltchars; /* 4.2 BSD editing characters */
+#endif
+  int flags;           /* Bitmap saying which parts of the struct are valid. */
+};
+
+#define TIOTYPE struct bsdtty
+
+static TIOTYPE otio;
+
+static void save_tty_chars PARAMS((TIOTYPE *));
+static int _get_tty_settings PARAMS((int, TIOTYPE *));
+static int get_tty_settings PARAMS((int, TIOTYPE *));
+static int _set_tty_settings PARAMS((int, TIOTYPE *));
+static int set_tty_settings PARAMS((int, TIOTYPE *));
+
+static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+
+static void
+save_tty_chars (tiop)
+     TIOTYPE *tiop;
+{
+  _rl_last_tty_chars = _rl_tty_chars;
+
+  if (tiop->flags & SGTTY_SET)
+    {
+      _rl_tty_chars.t_erase = tiop->sgttyb.sg_erase;
+      _rl_tty_chars.t_kill = tiop->sgttyb.sg_kill;
+    }
+
+  if (tiop->flags & TCHARS_SET)
+    {
+      _rl_tty_chars.t_intr = tiop->tchars.t_intrc;
+      _rl_tty_chars.t_quit = tiop->tchars.t_quitc;
+      _rl_tty_chars.t_start = tiop->tchars.t_startc;
+      _rl_tty_chars.t_stop = tiop->tchars.t_stopc;
+      _rl_tty_chars.t_eof = tiop->tchars.t_eofc;
+      _rl_tty_chars.t_eol = '\n';
+      _rl_tty_chars.t_eol2 = tiop->tchars.t_brkc;
+    }
+
+  if (tiop->flags & LTCHARS_SET)
+    {
+      _rl_tty_chars.t_susp = tiop->ltchars.t_suspc;
+      _rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc;
+      _rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc;
+      _rl_tty_chars.t_flush = tiop->ltchars.t_flushc;
+      _rl_tty_chars.t_werase = tiop->ltchars.t_werasc;
+      _rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc;
+    }
+
+  _rl_tty_chars.t_status = -1;
+}
+
+static int
+get_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  set_winsize (tty);
+
+  tiop->flags = tiop->lflag = 0;
+
+  errno = 0;
+  if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0)
+    return -1;
+  tiop->flags |= SGTTY_SET;
+
+#if defined (TIOCLGET)
+  if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0)
+    tiop->flags |= LFLAG_SET;
+#endif
+
+#if defined (TIOCGETC)
+  if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0)
+    tiop->flags |= TCHARS_SET;
+#endif
+
+#if defined (TIOCGLTC)
+  if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0)
+    tiop->flags |= LTCHARS_SET;
+#endif
+
+  return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  if (tiop->flags & SGTTY_SET)
+    {
+      ioctl (tty, TIOCSETN, &(tiop->sgttyb));
+      tiop->flags &= ~SGTTY_SET;
+    }
+  readline_echoing_p = 1;
+
+#if defined (TIOCLSET)
+  if (tiop->flags & LFLAG_SET)
+    {
+      ioctl (tty, TIOCLSET, &(tiop->lflag));
+      tiop->flags &= ~LFLAG_SET;
+    }
+#endif
+
+#if defined (TIOCSETC)
+  if (tiop->flags & TCHARS_SET)
+    {
+      ioctl (tty, TIOCSETC, &(tiop->tchars));
+      tiop->flags &= ~TCHARS_SET;
+    }
+#endif
+
+#if defined (TIOCSLTC)
+  if (tiop->flags & LTCHARS_SET)
+    {
+      ioctl (tty, TIOCSLTC, &(tiop->ltchars));
+      tiop->flags &= ~LTCHARS_SET;
+    }
+#endif
+
+  return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, oldtio, tiop)
+     int meta_flag;
+     TIOTYPE oldtio, *tiop;
+{
+  readline_echoing_p = (oldtio.sgttyb.sg_flags & ECHO);
+
+  /* Copy the original settings to the structure we're going to use for
+     our settings. */
+  tiop->sgttyb = oldtio.sgttyb;
+  tiop->lflag = oldtio.lflag;
+#if defined (TIOCGETC)
+  tiop->tchars = oldtio.tchars;
+#endif
+#if defined (TIOCGLTC)
+  tiop->ltchars = oldtio.ltchars;
+#endif
+  tiop->flags = oldtio.flags;
+
+  /* First, the basic settings to put us into character-at-a-time, no-echo
+     input mode. */
+  tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
+  tiop->sgttyb.sg_flags |= CBREAK;
+
+  /* If this terminal doesn't care how the 8th bit is used, then we can
+     use it for the meta-key.  If only one of even or odd parity is
+     specified, then the terminal is using parity, and we cannot. */
+#if !defined (ANYP)
+#  define ANYP (EVENP | ODDP)
+#endif
+  if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) ||
+      ((oldtio.sgttyb.sg_flags & ANYP) == 0))
+    {
+      tiop->sgttyb.sg_flags |= ANYP;
+
+      /* Hack on local mode flags if we can. */
+#if defined (TIOCLGET)
+#  if defined (LPASS8)
+      tiop->lflag |= LPASS8;
+#  endif /* LPASS8 */
+#endif /* TIOCLGET */
+    }
+
+#if defined (TIOCGETC)
+#  if defined (USE_XON_XOFF)
+  /* Get rid of terminal output start and stop characters. */
+  tiop->tchars.t_stopc = -1; /* C-s */
+  tiop->tchars.t_startc = -1; /* C-q */
+
+  /* If there is an XON character, bind it to restart the output. */
+  if (oldtio.tchars.t_startc != -1)
+    rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
+#  endif /* USE_XON_XOFF */
+
+  /* If there is an EOF char, bind _rl_eof_char to it. */
+  if (oldtio.tchars.t_eofc != -1)
+    _rl_eof_char = oldtio.tchars.t_eofc;
+
+#  if defined (NO_KILL_INTR)
+  /* Get rid of terminal-generated SIGQUIT and SIGINT. */
+  tiop->tchars.t_quitc = -1; /* C-\ */
+  tiop->tchars.t_intrc = -1; /* C-c */
+#  endif /* NO_KILL_INTR */
+#endif /* TIOCGETC */
+
+#if defined (TIOCGLTC)
+  /* Make the interrupt keys go away.  Just enough to make people happy. */
+  tiop->ltchars.t_dsuspc = -1; /* C-y */
+  tiop->ltchars.t_lnextc = -1; /* C-v */
+#endif /* TIOCGLTC */
+}
+
+#else  /* !defined (NEW_TTY_DRIVER) */
+
+#if !defined (VMIN)
+#  define VMIN VEOF
+#endif
+
+#if !defined (VTIME)
+#  define VTIME VEOL
+#endif
+
+#if defined (TERMIOS_TTY_DRIVER)
+#  define TIOTYPE struct termios
+#  define DRAIN_OUTPUT(fd)     tcdrain (fd)
+#  define GETATTR(tty, tiop)   (tcgetattr (tty, tiop))
+#  ifdef M_UNIX
+#    define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop))
+#  else
+#    define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop))
+#  endif /* !M_UNIX */
+#else
+#  define TIOTYPE struct termio
+#  define DRAIN_OUTPUT(fd)
+#  define GETATTR(tty, tiop)   (ioctl (tty, TCGETA, tiop))
+#  define SETATTR(tty, tiop)   (ioctl (tty, TCSETAW, tiop))
+#endif /* !TERMIOS_TTY_DRIVER */
+
+static TIOTYPE otio;
+
+static void save_tty_chars PARAMS((TIOTYPE *));
+static int _get_tty_settings PARAMS((int, TIOTYPE *));
+static int get_tty_settings PARAMS((int, TIOTYPE *));
+static int _set_tty_settings PARAMS((int, TIOTYPE *));
+static int set_tty_settings PARAMS((int, TIOTYPE *));
+
+static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
+
+#if defined (FLUSHO)
+#  define OUTPUT_BEING_FLUSHED(tp)  (tp->c_lflag & FLUSHO)
+#else
+#  define OUTPUT_BEING_FLUSHED(tp)  0
+#endif
+
+static void
+save_tty_chars (tiop)
+     TIOTYPE *tiop;
+{
+  _rl_last_tty_chars = _rl_tty_chars;
+
+  _rl_tty_chars.t_eof = tiop->c_cc[VEOF];
+  _rl_tty_chars.t_eol = tiop->c_cc[VEOL];
+#ifdef VEOL2
+  _rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2];
+#endif
+  _rl_tty_chars.t_erase = tiop->c_cc[VERASE];
+#ifdef VWERASE
+  _rl_tty_chars.t_werase = tiop->c_cc[VWERASE];
+#endif
+  _rl_tty_chars.t_kill = tiop->c_cc[VKILL];
+#ifdef VREPRINT
+  _rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT];
+#endif
+  _rl_tty_chars.t_intr = tiop->c_cc[VINTR];
+  _rl_tty_chars.t_quit = tiop->c_cc[VQUIT];
+#ifdef VSUSP
+  _rl_tty_chars.t_susp = tiop->c_cc[VSUSP];
+#endif
+#ifdef VDSUSP
+  _rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP];
+#endif
+#ifdef VSTART
+  _rl_tty_chars.t_start = tiop->c_cc[VSTART];
+#endif
+#ifdef VSTOP
+  _rl_tty_chars.t_stop = tiop->c_cc[VSTOP];
+#endif
+#ifdef VLNEXT
+  _rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT];
+#endif
+#ifdef VDISCARD
+  _rl_tty_chars.t_flush = tiop->c_cc[VDISCARD];
+#endif
+#ifdef VSTATUS
+  _rl_tty_chars.t_status = tiop->c_cc[VSTATUS];
+#endif
+}
+
+#if defined (_AIX) || defined (_AIX41)
+/* Currently this is only used on AIX */
+static void
+rltty_warning (msg)
+     char *msg;
+{
+  fprintf (stderr, "readline: warning: %s\n", msg);
+}
+#endif
+
+#if defined (_AIX)
+void
+setopost(tp)
+TIOTYPE *tp;
+{
+  if ((tp->c_oflag & OPOST) == 0)
+    {
+      rltty_warning ("turning on OPOST for terminal\r");
+      tp->c_oflag |= OPOST|ONLCR;
+    }
+}
+#endif
+
+static int
+_get_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  int ioctl_ret;
+
+  while (1)
+    {
+      ioctl_ret = GETATTR (tty, tiop);
+      if (ioctl_ret < 0)
+       {
+         if (errno != EINTR)
+           return -1;
+         else
+           continue;
+       }
+      if (OUTPUT_BEING_FLUSHED (tiop))
+       {
+#if defined (FLUSHO) && defined (_AIX41)
+         rltty_warning ("turning off output flushing");
+         tiop->c_lflag &= ~FLUSHO;
+         break;
+#else
+         continue;
+#endif
+       }
+      break;
+    }
+
+  return 0;
+}
+
+static int
+get_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  set_winsize (tty);
+
+  errno = 0;
+fprintf(stderr, "get_tty_settings: errno = %d\n", errno);
+  if (_get_tty_settings (tty, tiop) < 0)
+    return -1;
+
+#if defined (_AIX)
+  setopost(tiop);
+#endif
+
+  return 0;
+}
+
+static int
+_set_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  while (SETATTR (tty, tiop) < 0)
+    {
+      if (errno != EINTR)
+       return -1;
+      errno = 0;
+    }
+  return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  if (_set_tty_settings (tty, tiop) < 0)
+    return -1;
+    
+#if 0
+
+#if defined (TERMIOS_TTY_DRIVER)
+#  if defined (__ksr1__)
+  if (ksrflow)
+    {
+      ksrflow = 0;
+      tcflow (tty, TCOON);
+    }
+#  else /* !ksr1 */
+  tcflow (tty, TCOON);         /* Simulate a ^Q. */
+#  endif /* !ksr1 */
+#else
+  ioctl (tty, TCXONC, 1);      /* Simulate a ^Q. */
+#endif /* !TERMIOS_TTY_DRIVER */
+
+#endif /* 0 */
+
+  return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, oldtio, tiop)
+     int meta_flag;
+     TIOTYPE oldtio, *tiop;
+{
+  readline_echoing_p = (oldtio.c_lflag & ECHO);
+
+  tiop->c_lflag &= ~(ICANON | ECHO);
+
+  if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
+    _rl_eof_char = oldtio.c_cc[VEOF];
+
+#if defined (USE_XON_XOFF)
+#if defined (IXANY)
+  tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
+#else
+  /* `strict' Posix systems do not define IXANY. */
+  tiop->c_iflag &= ~(IXON | IXOFF);
+#endif /* IXANY */
+#endif /* USE_XON_XOFF */
+
+  /* Only turn this off if we are using all 8 bits. */
+  if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
+    tiop->c_iflag &= ~(ISTRIP | INPCK);
+
+  /* Make sure we differentiate between CR and NL on input. */
+  tiop->c_iflag &= ~(ICRNL | INLCR);
+
+#if !defined (HANDLE_SIGNALS)
+  tiop->c_lflag &= ~ISIG;
+#else
+  tiop->c_lflag |= ISIG;
+#endif
+
+  tiop->c_cc[VMIN] = 1;
+  tiop->c_cc[VTIME] = 0;
+
+#if defined (FLUSHO)
+  if (OUTPUT_BEING_FLUSHED (tiop))
+    {
+      tiop->c_lflag &= ~FLUSHO;
+      oldtio.c_lflag &= ~FLUSHO;
+    }
+#endif
+
+  /* Turn off characters that we need on Posix systems with job control,
+     just to be sure.  This includes ^Y and ^V.  This should not really
+     be necessary.  */
+#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
+
+#if defined (VLNEXT)
+  tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+
+#if defined (VDSUSP)
+  tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+
+#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
+}
+#endif  /* NEW_TTY_DRIVER */
+
+/* Put the terminal in CBREAK mode so that we can detect key presses. */
+void
+rl_prep_terminal (meta_flag)
+     int meta_flag;
+{
+  int tty;
+  TIOTYPE tio;
+
+  if (terminal_prepped)
+    return;
+
+  /* Try to keep this function from being INTerrupted. */
+  block_sigint ();
+
+  tty = fileno (rl_instream);
+
+  errno = 0;
+  if (get_tty_settings (tty, &tio) < 0)
+    {
+      if (errno == ENOTTY)
+       readline_echoing_p = 1;         /* XXX */
+else fprintf(stderr, "get_tty_settings fails but errno == %d\n", errno);
+      release_sigint ();
+      return;
+    }
+
+  otio = tio;
+
+  if (_rl_bind_stty_chars)
+    rl_tty_unset_default_bindings (_rl_keymap);
+  save_tty_chars (&otio);
+  RL_SETSTATE(RL_STATE_TTYCSAVED);
+  if (_rl_bind_stty_chars)
+    _rl_bind_tty_special_chars (_rl_keymap, tio);
+
+  prepare_terminal_settings (meta_flag, otio, &tio);
+
+  if (set_tty_settings (tty, &tio) < 0)
+    {
+      release_sigint ();
+      return;
+    }
+
+  if (_rl_enable_keypad)
+    _rl_control_keypad (1);
+
+  fflush (rl_outstream);
+  terminal_prepped = 1;
+  RL_SETSTATE(RL_STATE_TERMPREPPED);
+
+  release_sigint ();
+}
+
+/* Restore the terminal's normal settings and modes. */
+void
+rl_deprep_terminal ()
+{
+  int tty;
+
+  if (!terminal_prepped)
+    return;
+
+  /* Try to keep this function from being interrupted. */
+  block_sigint ();
+
+  tty = fileno (rl_instream);
+
+  if (_rl_enable_keypad)
+    _rl_control_keypad (0);
+
+  fflush (rl_outstream);
+
+  if (set_tty_settings (tty, &otio) < 0)
+    {
+      release_sigint ();
+      return;
+    }
+
+  terminal_prepped = 0;
+  RL_UNSETSTATE(RL_STATE_TERMPREPPED);
+
+  release_sigint ();
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Bogus Flow Control                          */
+/*                                                                 */
+/* **************************************************************** */
+
+int
+rl_restart_output (count, key)
+     int count, key;
+{
+  int fildes = fileno (rl_outstream);
+#if defined (TIOCSTART)
+#if defined (apollo)
+  ioctl (&fildes, TIOCSTART, 0);
+#else
+  ioctl (fildes, TIOCSTART, 0);
+#endif /* apollo */
+
+#else /* !TIOCSTART */
+#  if defined (TERMIOS_TTY_DRIVER)
+#    if defined (__ksr1__)
+  if (ksrflow)
+    {
+      ksrflow = 0;
+      tcflow (fildes, TCOON);
+    }
+#    else /* !ksr1 */
+  tcflow (fildes, TCOON);              /* Simulate a ^Q. */
+#    endif /* !ksr1 */
+#  else /* !TERMIOS_TTY_DRIVER */
+#    if defined (TCXONC)
+  ioctl (fildes, TCXONC, TCOON);
+#    endif /* TCXONC */
+#  endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTART */
+
+  return 0;
+}
+
+int
+rl_stop_output (count, key)
+     int count, key;
+{
+  int fildes = fileno (rl_instream);
+
+#if defined (TIOCSTOP)
+# if defined (apollo)
+  ioctl (&fildes, TIOCSTOP, 0);
+# else
+  ioctl (fildes, TIOCSTOP, 0);
+# endif /* apollo */
+#else /* !TIOCSTOP */
+# if defined (TERMIOS_TTY_DRIVER)
+#  if defined (__ksr1__)
+  ksrflow = 1;
+#  endif /* ksr1 */
+  tcflow (fildes, TCOOFF);
+# else
+#   if defined (TCXONC)
+  ioctl (fildes, TCXONC, TCOON);
+#   endif /* TCXONC */
+# endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTOP */
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Default Key Bindings                        */
+/*                                                                 */
+/* **************************************************************** */
+
+#define SET_SPECIAL(sc, func)  set_special_char(kmap, &ttybuff, sc, func)
+
+#if defined (NEW_TTY_DRIVER)
+static void
+set_special_char (kmap, tiop, sc, func)
+     Keymap kmap;
+     TIOTYPE *tiop;
+     int sc;
+     rl_command_func_t *func;
+{
+  if (sc != -1 && kmap[(unsigned char)sc].type == ISFUNC)
+    kmap[(unsigned char)sc].function = func;
+}
+
+#define RESET_SPECIAL(c) \
+  if (c != -1 && kmap[(unsigned char)c].type == ISFUNC)
+    kmap[(unsigned char)c].function = rl_insert;
+
+static void
+_rl_bind_tty_special_chars (kmap, ttybuff)
+     Keymap kmap;
+     TIOTYPE ttybuff;
+{
+  if (ttybuff.flags & SGTTY_SET)
+    {
+      SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
+      SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
+    }
+
+#  if defined (TIOCGLTC)
+  if (ttybuff.flags & LTCHARS_SET)
+    {
+      SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
+      SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
+    }
+#  endif /* TIOCGLTC */
+}
+
+#else /* !NEW_TTY_DRIVER */
+static void
+set_special_char (kmap, tiop, sc, func)
+     Keymap kmap;
+     TIOTYPE *tiop;
+     int sc;
+     rl_command_func_t *func;
+{
+  unsigned char uc;
+
+  uc = tiop->c_cc[sc];
+  if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC)
+    kmap[uc].function = func;
+}
+
+/* used later */
+#define RESET_SPECIAL(uc) \
+  if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
+    kmap[uc].function = rl_insert;
+
+static void
+_rl_bind_tty_special_chars (kmap, ttybuff)
+     Keymap kmap;
+     TIOTYPE ttybuff;
+{
+  SET_SPECIAL (VERASE, rl_rubout);
+  SET_SPECIAL (VKILL, rl_unix_line_discard);
+
+#  if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+  SET_SPECIAL (VLNEXT, rl_quoted_insert);
+#  endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+#  if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+  SET_SPECIAL (VWERASE, rl_unix_word_rubout);
+#  endif /* VWERASE && TERMIOS_TTY_DRIVER */
+}
+
+#endif /* !NEW_TTY_DRIVER */
+
+/* Set the system's default editing characters to their readline equivalents
+   in KMAP.  Should be static, now that we have rl_tty_set_default_bindings. */
+void
+rltty_set_default_bindings (kmap)
+     Keymap kmap;
+{
+  TIOTYPE ttybuff;
+  int tty;
+  static int called = 0;
+
+  tty = fileno (rl_instream);
+
+  if (get_tty_settings (tty, &ttybuff) == 0)
+    _rl_bind_tty_special_chars (kmap, ttybuff);
+}
+
+/* New public way to set the system default editing chars to their readline
+   equivalents. */
+void
+rl_tty_set_default_bindings (kmap)
+     Keymap kmap;
+{
+  rltty_set_default_bindings (kmap);
+}
+
+/* Rebind all of the tty special chars that readline worries about back
+   to self-insert.  Call this before saving the current terminal special
+   chars with save_tty_chars().  This only works on POSIX termios or termio
+   systems. */
+void
+rl_tty_unset_default_bindings (kmap)
+     Keymap kmap;
+{
+  /* Don't bother before we've saved the tty special chars at least once. */
+  if (RL_ISSTATE(RL_STATE_TTYCSAVED) == 0)
+    return;
+
+  RESET_SPECIAL (_rl_tty_chars.t_erase);
+  RESET_SPECIAL (_rl_tty_chars.t_kill);
+
+#  if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+  RESET_SPECIAL (_rl_tty_chars.t_lnext);
+#  endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+#  if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+  RESET_SPECIAL (_rl_tty_chars.t_werase);
+#  endif /* VWERASE && TERMIOS_TTY_DRIVER */
+}
+
+#if defined (HANDLE_SIGNALS)
+
+#if defined (NEW_TTY_DRIVER)
+int
+_rl_disable_tty_signals ()
+{
+  return 0;
+}
+
+int
+_rl_restore_tty_signals ()
+{
+  return 0;
+}
+#else
+
+static TIOTYPE sigstty, nosigstty;
+static int tty_sigs_disabled = 0;
+
+int
+_rl_disable_tty_signals ()
+{
+  if (tty_sigs_disabled)
+    return 0;
+
+  if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0)
+    return -1;
+
+  nosigstty = sigstty;
+
+  nosigstty.c_lflag &= ~ISIG;
+  nosigstty.c_iflag &= ~IXON;
+
+  if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0)
+    return (_set_tty_settings (fileno (rl_instream), &sigstty));
+
+  tty_sigs_disabled = 1;
+  return 0;
+}
+
+int
+_rl_restore_tty_signals ()
+{
+  int r;
+
+  if (tty_sigs_disabled == 0)
+    return 0;
+
+  r = _set_tty_settings (fileno (rl_instream), &sigstty);
+
+  if (r == 0)
+    tty_sigs_disabled = 0;
+
+  return r;
+}
+#endif /* !NEW_TTY_DRIVER */
+
+#endif /* HANDLE_SIGNALS */
index d917e99b9bd63c659da105ed7ceac6d5becc7b32..af335807d27c249b84b8f466a24125b01a5dab5f 100644 (file)
@@ -420,8 +420,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 +437,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;
diff --git a/lib/readline/text.c.save b/lib/readline/text.c.save
new file mode 100644 (file)
index 0000000..d917e99
--- /dev/null
@@ -0,0 +1,1547 @@
+/* text.c -- text handling commands for readline. */
+
+/* Copyright (C) 1987-2004 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.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+#  include <locale.h>
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (__EMX__)
+#  define INCL_DOSPROCESS
+#  include <os2.h>
+#endif /* __EMX__ */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+/* Forward declarations. */
+static int rl_change_case PARAMS((int, int));
+static int _rl_char_search PARAMS((int, int, int));
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Insert and Delete                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Insert a string of text into the line at point.  This is the only
+   way that you should do insertion.  _rl_insert_char () calls this
+   function.  Returns the number of characters inserted. */
+int
+rl_insert_text (string)
+     const char *string;
+{
+  register int i, l;
+
+  l = (string && *string) ? strlen (string) : 0;
+  if (l == 0)
+    return 0;
+
+  if (rl_end + l >= rl_line_buffer_len)
+    rl_extend_line_buffer (rl_end + l);
+
+  for (i = rl_end; i >= rl_point; i--)
+    rl_line_buffer[i + l] = rl_line_buffer[i];
+  strncpy (rl_line_buffer + rl_point, string, l);
+
+  /* Remember how to undo this if we aren't undoing something. */
+  if (_rl_doing_an_undo == 0)
+    {
+      /* If possible and desirable, concatenate the undos. */
+      if ((l == 1) &&
+         rl_undo_list &&
+         (rl_undo_list->what == UNDO_INSERT) &&
+         (rl_undo_list->end == rl_point) &&
+         (rl_undo_list->end - rl_undo_list->start < 20))
+       rl_undo_list->end++;
+      else
+       rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+    }
+  rl_point += l;
+  rl_end += l;
+  rl_line_buffer[rl_end] = '\0';
+  return l;
+}
+
+/* Delete the string between FROM and TO.  FROM is inclusive, TO is not.
+   Returns the number of characters deleted. */
+int
+rl_delete_text (from, to)
+     int from, to;
+{
+  register char *text;
+  register int diff, i;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    SWAP (from, to);
+
+  /* fix boundaries */
+  if (to > rl_end)
+    {
+      to = rl_end;
+      if (from > to)
+       from = to;
+    }
+  if (from < 0)
+    from = 0;
+
+  text = rl_copy_text (from, to);
+
+  /* Some versions of strncpy() can't handle overlapping arguments. */
+  diff = to - from;
+  for (i = from; i < rl_end - diff; i++)
+    rl_line_buffer[i] = rl_line_buffer[i + diff];
+
+  /* Remember how to undo this delete. */
+  if (_rl_doing_an_undo == 0)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    free (text);
+
+  rl_end -= diff;
+  rl_line_buffer[rl_end] = '\0';
+  return (diff);
+}
+
+/* Fix up point so that it is within the line boundaries after killing
+   text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
+   boundaries also. */
+
+#define _RL_FIX_POINT(x) \
+       do { \
+       if (x > rl_end) \
+         x = rl_end; \
+       else if (x < 0) \
+         x = 0; \
+       } while (0)
+
+void
+_rl_fix_point (fix_mark_too)
+     int fix_mark_too;
+{
+  _RL_FIX_POINT (rl_point);
+  if (fix_mark_too)
+    _RL_FIX_POINT (rl_mark);
+}
+#undef _RL_FIX_POINT
+
+/* Replace the contents of the line buffer between START and END with
+   TEXT.  The operation is undoable.  To replace the entire line in an
+   undoable mode, use _rl_replace_text(text, 0, rl_end); */
+int
+_rl_replace_text (text, start, end)
+     const char *text;
+     int start, end;
+{
+  int n;
+
+  rl_begin_undo_group ();
+  rl_delete_text (start, end + 1);
+  rl_point = start;
+  n = rl_insert_text (text);
+  rl_end_undo_group ();
+
+  return n;
+}
+
+/* Replace the current line buffer contents with TEXT.  If CLEAR_UNDO is
+   non-zero, we free the current undo list. */
+void
+rl_replace_line (text, clear_undo)
+     const char *text;
+     int clear_undo;
+{
+  int len;
+
+  len = strlen (text);
+  if (len >= rl_line_buffer_len)
+    rl_extend_line_buffer (len);
+  strcpy (rl_line_buffer, text);
+  rl_end = len;
+
+  if (clear_undo)
+    rl_free_undo_list ();
+
+  _rl_fix_point (1);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Readline character functions                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine.  No hair
+   is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+   rl_end is the place in the string that we would place '\0';
+   i.e., it is always safe to place '\0' there.
+
+   rl_point is the place in the string where the cursor is.  Sometimes
+   this is the same as rl_end.
+
+   Any command that is called interactively receives two arguments.
+   The first is a count: the numeric arg pased to this command.
+   The second is the key which invoked this command.
+*/
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Movement Commands                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+   use said functions in other functions which do not do optimizing display.
+   I.e., you will have to update the data base for rl_redisplay, and you
+   might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT bytes. */
+int
+rl_forward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_backward_byte (-count, key));
+
+  if (count > 0)
+    {
+      int end = rl_point + count;
+#if defined (VI_MODE)
+      int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
+#else
+      int lend = rl_end;
+#endif
+
+      if (end > lend)
+       {
+         rl_point = lend;
+         rl_ding ();
+       }
+      else
+       rl_point = end;
+    }
+
+  if (rl_end < 0)
+    rl_end = 0;
+
+  return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move forward COUNT characters. */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_forward_byte (count, key));
+
+  if (count < 0)
+    return (rl_backward_char (-count, key));
+
+  if (count > 0)
+    {
+      point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+#if defined (VI_MODE)
+      if (rl_end <= point && rl_editing_mode == vi_mode)
+       point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
+#endif
+
+      if (rl_point == point)
+       rl_ding ();
+
+      rl_point = point;
+
+      if (rl_end < 0)
+       rl_end = 0;
+    }
+
+  return 0;
+}
+#else /* !HANDLE_MULTIBYTE */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  return (rl_forward_byte (count, key));
+}
+#endif /* !HANDLE_MULTIBYTE */
+  
+/* Backwards compatibility. */
+int
+rl_forward (count, key)
+     int count, key;
+{
+  return (rl_forward_char (count, key));
+}
+
+/* Move backward COUNT bytes. */
+int
+rl_backward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_forward_byte (-count, key));
+
+  if (count > 0)
+    {
+      if (rl_point < count)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+       rl_point -= count;
+    }
+
+  if (rl_point < 0)
+    rl_point = 0;
+
+  return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move backward COUNT characters. */
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_backward_byte (count, key));
+
+  if (count < 0)
+    return (rl_forward_char (-count, key));
+
+  if (count > 0)
+    {
+      point = rl_point;
+
+      while (count > 0 && point > 0)
+       {
+         point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
+         count--;
+       }
+      if (count > 0)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+        rl_point = point;
+    }
+
+  return 0;
+}
+#else
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  return (rl_backward_byte (count, key));
+}
+#endif
+
+/* Backwards compatibility. */
+int
+rl_backward (count, key)
+     int count, key;
+{
+  return (rl_backward_char (count, key));
+}
+
+/* Move to the beginning of the line. */
+int
+rl_beg_of_line (count, key)
+     int count, key;
+{
+  rl_point = 0;
+  return 0;
+}
+
+/* Move to the end of the line. */
+int
+rl_end_of_line (count, key)
+     int count, key;
+{
+  rl_point = rl_end;
+  return 0;
+}
+
+/* XXX - these might need changes for multibyte characters */
+/* Move forward a word.  We do what Emacs does. */
+int
+rl_forward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    return (rl_backward_word (-count, key));
+
+  while (count)
+    {
+      if (rl_point == rl_end)
+       return 0;
+
+      /* 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)
+       {
+         while (++rl_point < rl_end)
+           {
+             c = rl_line_buffer[rl_point];
+             if (rl_alphabetic (c))
+               break;
+           }
+       }
+
+      if (rl_point == rl_end)
+       return 0;
+
+      while (++rl_point < rl_end)
+       {
+         c = rl_line_buffer[rl_point];
+         if (rl_alphabetic (c) == 0)
+           break;
+       }
+      --count;
+    }
+
+  return 0;
+}
+
+/* Move backward a word.  We do what Emacs does. */
+int
+rl_backward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    return (rl_forward_word (-count, key));
+
+  while (count)
+    {
+      if (!rl_point)
+       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)
+       {
+         while (--rl_point)
+           {
+             c = rl_line_buffer[rl_point - 1];
+             if (rl_alphabetic (c))
+               break;
+           }
+       }
+
+      while (rl_point)
+       {
+         c = rl_line_buffer[rl_point - 1];
+         if (rl_alphabetic (c) == 0)
+           break;
+         else
+           --rl_point;
+       }
+
+      --count;
+    }
+
+  return 0;
+}
+
+/* Clear the current line.  Numeric argument to C-l does this. */
+int
+rl_refresh_line (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  int curr_line;
+
+  curr_line = _rl_current_display_line ();
+
+  _rl_move_vert (curr_line);
+  _rl_move_cursor_relative (0, rl_line_buffer);   /* XXX is this right */
+
+  _rl_clear_to_eol (0);                /* arg of 0 means to not use spaces */
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+   the prompt and the current input line.  Given a numeric arg, redraw only
+   the current line. */
+int
+rl_clear_screen (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg)
+    {
+      rl_refresh_line (count, key);
+      return 0;
+    }
+
+  _rl_clear_screen ();         /* calls termcap function to clear screen */
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+int
+rl_arrow_keys (count, c)
+     int count, c;
+{
+  int ch;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  ch = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  switch (_rl_to_upper (ch))
+    {
+    case 'A':
+      rl_get_previous_history (count, ch);
+      break;
+
+    case 'B':
+      rl_get_next_history (count, ch);
+      break;
+
+    case 'C':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_forward_char (count, ch);
+      else
+       rl_forward_byte (count, ch);
+      break;
+
+    case 'D':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_backward_char (count, ch);
+      else
+       rl_backward_byte (count, ch);
+      break;
+
+    default:
+      rl_ding ();
+    }
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Text commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef HANDLE_MULTIBYTE
+static char pending_bytes[MB_LEN_MAX];
+static int pending_bytes_length = 0;
+static mbstate_t ps = {0};
+#endif
+
+/* Insert the character C at the current location, moving point forward.
+   If C introduces a multibyte sequence, we read the whole sequence and
+   then insert the multibyte char into the line buffer. */
+int
+_rl_insert_char (count, c)
+     int count, c;
+{
+  register int i;
+  char *string;
+#ifdef HANDLE_MULTIBYTE
+  int string_size;
+  char incoming[MB_LEN_MAX + 1];
+  int incoming_length = 0;
+  mbstate_t ps_back;
+  static int stored_count = 0;
+#endif
+
+  if (count <= 0)
+    return 0;
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+      incoming[0] = c;
+      incoming[1] = '\0';
+      incoming_length = 1;
+    }
+  else
+    {
+      wchar_t wc;
+      size_t ret;
+
+      if (stored_count <= 0)
+       stored_count = count;
+      else
+       count = stored_count;
+
+      ps_back = ps;
+      pending_bytes[pending_bytes_length++] = c;
+      ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
+
+      if (ret == (size_t)-2)
+       {
+         /* Bytes too short to compose character, try to wait for next byte.
+            Restore the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         ps = ps_back;
+         return 1;
+       }
+      else if (ret == (size_t)-1)
+       {
+         /* Invalid byte sequence for the current locale.  Treat first byte
+            as a single character. */
+         incoming[0] = pending_bytes[0];
+         incoming[1] = '\0';
+         incoming_length = 1;
+         pending_bytes_length--;
+         memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else if (ret == (size_t)0)
+       {
+         incoming[0] = '\0';
+         incoming_length = 0;
+         pending_bytes_length--;
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else
+       {
+         /* We successfully read a single multibyte character. */
+         memcpy (incoming, pending_bytes, pending_bytes_length);
+         incoming[pending_bytes_length] = '\0';
+         incoming_length = pending_bytes_length;
+         pending_bytes_length = 0;
+       }
+    }
+#endif /* HANDLE_MULTIBYTE */
+         
+  /* If we can optimize, then do it.  But don't let people crash
+     readline because of extra large arguments. */
+  if (count > 1 && count <= 1024)
+    {
+#if defined (HANDLE_MULTIBYTE)
+      string_size = count * incoming_length;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      string = (char *)xmalloc (1 + count);
+
+      for (i = 0; i < count; i++)
+       string[i] = c;
+#endif /* !HANDLE_MULTIBYTE */
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      free (string);
+
+      return 0;
+    }
+
+  if (count > 1024)
+    {
+      int decreaser;
+#if defined (HANDLE_MULTIBYTE)
+      string_size = incoming_length * 1024;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+
+      while (count)
+       {
+         decreaser = (count > 1024) ? 1024 : count;
+         string[decreaser*incoming_length] = '\0';
+         rl_insert_text (string);
+         count -= decreaser;
+       }
+
+      free (string);
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      char str[1024+1];
+
+      for (i = 0; i < 1024; i++)
+       str[i] = c;
+
+      while (count)
+       {
+         decreaser = (count > 1024 ? 1024 : count);
+         str[decreaser] = '\0';
+         rl_insert_text (str);
+         count -= decreaser;
+       }
+#endif /* !HANDLE_MULTIBYTE */
+
+      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
+        them all. */
+      if (_rl_any_typein ())
+       _rl_insert_typein (c);
+      else
+       {
+         /* Inserting a single character. */
+         char str[2];
+
+         str[1] = '\0';
+         str[0] = c;
+         rl_insert_text (str);
+       }
+#if defined (HANDLE_MULTIBYTE)
+    }
+  else
+    {
+      rl_insert_text (incoming);
+      stored_count = 0;
+    }
+#endif
+
+  return 0;
+}
+
+/* Overwrite the character at point (or next COUNT characters) with C.
+   If C introduces a multibyte character sequence, read the entire sequence
+   before starting the overwrite loop. */
+int
+_rl_overwrite_char (count, c)
+     int count, c;
+{
+  int i;
+#if defined (HANDLE_MULTIBYTE)
+  char mbkey[MB_LEN_MAX];
+  int k;
+
+  /* Read an entire multibyte character sequence to insert COUNT times. */
+  if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
+#endif
+
+  rl_begin_undo_group ();
+
+  for (i = 0; i < count; i++)
+    {
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_insert_text (mbkey);
+      else
+#endif
+       _rl_insert_char (1, c);
+
+      if (rl_point < rl_end)
+       rl_delete (1, c);
+    }
+
+  rl_end_undo_group ();
+
+  return 0;
+}
+
+int
+rl_insert (count, c)
+     int count, c;
+{
+  return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
+                                        : _rl_overwrite_char (count, c));
+}
+
+/* Insert the next typed character verbatim. */
+int
+rl_quoted_insert (count, key)
+     int count, key;
+{
+  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 ();
+#endif
+
+  return (_rl_insert_char (count, c));  
+}
+
+/* Insert a tab character. */
+int
+rl_tab_insert (count, key)
+     int count, key;
+{
+  return (_rl_insert_char (count, '\t'));
+}
+
+/* What to do when a NEWLINE is pressed.  We accept the whole line.
+   KEY is the key that invoked this command.  I guess it could have
+   meaning in the future. */
+int
+rl_newline (count, key)
+     int count, key;
+{
+  rl_done = 1;
+
+  if (_rl_history_preserve_point)
+    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+  RL_SETSTATE(RL_STATE_DONE);
+
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    {
+      _rl_vi_done_inserting ();
+      if (_rl_vi_textmod_command (_rl_vi_last_command) == 0)   /* XXX */
+       _rl_vi_reset_last ();
+    }
+#endif /* VI_MODE */
+
+  /* If we've been asked to erase empty lines, suppress the final update,
+     since _rl_update_final calls rl_crlf(). */
+  if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
+    return 0;
+
+  if (readline_echoing_p)
+    _rl_update_final ();
+  return 0;
+}
+
+/* What to do for some uppercase characters, like meta characters,
+   and some characters appearing in emacs_ctlx_keymap.  This function
+   is just a stub, you bind keys to it and the code in _rl_dispatch ()
+   is special cased. */
+int
+rl_do_lowercase_version (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  return 0;
+}
+
+/* This is different from what vi does, so the code's not shared.  Emacs
+   rubout in overwrite mode has one oddity:  it replaces a control
+   character that's displayed as two characters (^X) with two spaces. */
+int
+_rl_overwrite_rubout (count, key)
+     int count, key;
+{
+  int opoint;
+  int i, l;
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  opoint = rl_point;
+
+  /* L == number of spaces to insert */
+  for (i = l = 0; i < count; i++)
+    {
+      rl_backward_char (1, key);
+      l += rl_character_len (rl_line_buffer[rl_point], rl_point);      /* not exactly right */
+    }
+
+  rl_begin_undo_group ();
+
+  if (count > 1 || rl_explicit_arg)
+    rl_kill_text (opoint, rl_point);
+  else
+    rl_delete_text (opoint, rl_point);
+
+  /* Emacs puts point at the beginning of the sequence of spaces. */
+  if (rl_point < rl_end)
+    {
+      opoint = rl_point;
+      _rl_insert_char (l, ' ');
+      rl_point = opoint;
+    }
+
+  rl_end_undo_group ();
+
+  return 0;
+}
+  
+/* Rubout the character behind point. */
+int
+rl_rubout (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (!rl_point)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (rl_insert_mode == RL_IM_OVERWRITE)
+    return (_rl_overwrite_rubout (count, key));
+
+  return (_rl_rubout_char (count, key));
+}
+
+int
+_rl_rubout_char (count, key)
+     int count, key;
+{
+  int orig_point;
+  unsigned char c;
+
+  /* Duplicated code because this is called from other parts of the library. */
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  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_kill_text (orig_point, rl_point);
+    }
+  else
+    {
+#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
+      if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
+       {
+         int l;
+         l = rl_character_len (c, rl_point);
+         _rl_erase_at_end_of_line (l);
+       }
+    }
+
+  return 0;
+}
+
+/* Delete the character under the cursor.  Given a numeric argument,
+   kill that many characters instead. */
+int
+rl_delete (count, key)
+     int count, key;
+{
+  int r;
+
+  if (count < 0)
+    return (_rl_rubout_char (-count, key));
+
+  if (rl_point == rl_end)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  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);
+      rl_point = orig_point;
+      return r;
+    }
+  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;
+       
+      return (rl_delete_text (rl_point, new_point));
+    }
+}
+
+/* Delete the character under the cursor, unless the insertion
+   point is at the end of the line, in which case the character
+   behind the cursor is deleted.  COUNT is obeyed and may be used
+   to delete forward or backward that many characters. */      
+int
+rl_rubout_or_delete (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (_rl_rubout_char (count, key));
+  else
+    return (rl_delete (count, key));
+}  
+
+/* Delete all spaces and tabs around point. */
+int
+rl_delete_horizontal_space (count, ignore)
+     int count, ignore;
+{
+  int start = rl_point;
+
+  while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
+    rl_point--;
+
+  start = rl_point;
+
+  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+    rl_point++;
+
+  if (start != rl_point)
+    {
+      rl_delete_text (start, rl_point);
+      rl_point = start;
+    }
+  return 0;
+}
+
+/* Like the tcsh editing function delete-char-or-list.  The eof character
+   is caught before this is invoked, so this really does the same thing as
+   delete-char-or-list-or-eof, as long as it's bound to the eof character. */
+int
+rl_delete_or_show_completions (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (rl_possible_completions (count, key));
+  else
+    return (rl_delete (count, key));
+}
+
+#ifndef RL_COMMENT_BEGIN_DEFAULT
+#define RL_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+/* Turn the current line into a comment in shell history.
+   A K*rn shell style function. */
+int
+rl_insert_comment (count, key)
+     int count, key;
+{
+  char *rl_comment_text;
+  int rl_comment_len;
+
+  rl_beg_of_line (1, key);
+  rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
+
+  if (rl_explicit_arg == 0)
+    rl_insert_text (rl_comment_text);
+  else
+    {
+      rl_comment_len = strlen (rl_comment_text);
+      if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
+       rl_delete_text (rl_point, rl_point + rl_comment_len);
+      else
+       rl_insert_text (rl_comment_text);
+    }
+
+  (*rl_redisplay_function) ();
+  rl_newline (1, '\n');
+
+  return (0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Changing Case                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+int
+rl_upcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+int
+rl_downcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+int
+rl_capitalize_word (count, key)
+     int count, key;
+{
+ return (rl_change_case (count, CapCase));
+}
+
+/* The meaty function.
+   Change the case of COUNT words, performing OP on them.
+   OP is one of UpCase, DownCase, or CapCase.
+   If a negative argument is given, leave point where it started,
+   otherwise, leave it where it moves to. */
+static int
+rl_change_case (count, op)
+     int count, op;
+{
+  register int start, end;
+  int inword, c;
+
+  start = rl_point;
+  rl_forward_word (count, 0);
+  end = rl_point;
+
+  if (count < 0)
+    SWAP (start, end);
+
+  /* We are going to modify some text, so let's prepare to undo it. */
+  rl_modifying (start, end);
+
+  for (inword = 0; start < end; start++)
+    {
+      c = rl_line_buffer[start];
+      switch (op)
+       {
+       case UpCase:
+         rl_line_buffer[start] = _rl_to_upper (c);
+         break;
+
+       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;
+
+       default:
+         rl_ding ();
+         return -1;
+       }
+    }
+  rl_point = end;
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Transposition                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Transpose the words at point.  If point is at the end of the line,
+   transpose the two words before point. */
+int
+rl_transpose_words (count, key)
+     int count, key;
+{
+  char *word1, *word2;
+  int w1_beg, w1_end, w2_beg, w2_end;
+  int orig_point = rl_point;
+
+  if (!count)
+    return 0;
+
+  /* Find the two words. */
+  rl_forward_word (count, key);
+  w2_end = rl_point;
+  rl_backward_word (1, key);
+  w2_beg = rl_point;
+  rl_backward_word (count, key);
+  w1_beg = rl_point;
+  rl_forward_word (1, key);
+  w1_end = rl_point;
+
+  /* Do some check to make sure that there really are two words. */
+  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+    {
+      rl_ding ();
+      rl_point = orig_point;
+      return -1;
+    }
+
+  /* Get the text of the words. */
+  word1 = rl_copy_text (w1_beg, w1_end);
+  word2 = rl_copy_text (w2_beg, w2_end);
+
+  /* We are about to do many insertions and deletions.  Remember them
+     as one operation. */
+  rl_begin_undo_group ();
+
+  /* Do the stuff at word2 first, so that we don't have to worry
+     about word1 moving. */
+  rl_point = w2_beg;
+  rl_delete_text (w2_beg, w2_end);
+  rl_insert_text (word1);
+
+  rl_point = w1_beg;
+  rl_delete_text (w1_beg, w1_end);
+  rl_insert_text (word2);
+
+  /* This is exactly correct since the text before this point has not
+     changed in length. */
+  rl_point = w2_end;
+
+  /* I think that does it. */
+  rl_end_undo_group ();
+  free (word1);
+  free (word2);
+
+  return 0;
+}
+
+/* Transpose the characters at point.  If point is at the end of the line,
+   then transpose the characters before point. */
+int
+rl_transpose_chars (count, key)
+     int count, key;
+{
+#if defined (HANDLE_MULTIBYTE)
+  char *dummy;
+  int i, prev_point;
+#else
+  char dummy[2];
+#endif
+  int char_length;
+
+  if (count == 0)
+    return 0;
+
+  if (!rl_point || rl_end < 2)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  rl_begin_undo_group ();
+
+  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;
+      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--;
+
+#if defined (HANDLE_MULTIBYTE)
+  char_length = prev_point - rl_point;
+  dummy = (char *)xmalloc (char_length + 1);
+  for (i = 0; i < char_length; i++)
+    dummy[i] = rl_line_buffer[rl_point + i];
+  dummy[i] = '\0';
+#else
+  dummy[0] = rl_line_buffer[rl_point];
+  dummy[char_length = 1] = '\0';
+#endif
+
+  rl_delete_text (rl_point, rl_point + char_length);
+
+  rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+  _rl_fix_point (0);
+  rl_insert_text (dummy);
+  rl_end_undo_group ();
+
+#if defined (HANDLE_MULTIBYTE)
+  free (dummy);
+#endif
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Character Searching                         */
+/*                                                                 */
+/* **************************************************************** */
+
+int
+#if defined (HANDLE_MULTIBYTE)
+_rl_char_search_internal (count, dir, smbchar, len)
+     int count, dir;
+     char *smbchar;
+     int len;
+#else
+_rl_char_search_internal (count, dir, schar)
+     int count, dir, schar;
+#endif
+{
+  int pos, inc;
+#if defined (HANDLE_MULTIBYTE)
+  int prepos;
+#endif
+
+  pos = rl_point;
+  inc = (dir < 0) ? -1 : 1;
+  while (count)
+    {
+      if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
+       {
+         rl_ding ();
+         return -1;
+       }
+
+#if defined (HANDLE_MULTIBYTE)
+      pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                     : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+#else
+      pos += inc;
+#endif
+      do
+       {
+#if defined (HANDLE_MULTIBYTE)
+         if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
+#else
+         if (rl_line_buffer[pos] == schar)
+#endif
+           {
+             count--;
+             if (dir < 0)
+               rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                                       : pos;
+             else
+               rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
+                                       : pos;
+             break;
+           }
+#if defined (HANDLE_MULTIBYTE)
+         prepos = pos;
+#endif
+       }
+#if defined (HANDLE_MULTIBYTE)
+      while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
+                      : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
+#else
+      while ((dir < 0) ? pos-- : ++pos < rl_end);
+#endif
+    }
+  return (0);
+}
+
+/* Search COUNT times for a character read from the current input stream.
+   FDIR is the direction to search if COUNT is non-negative; otherwise
+   the search goes in BDIR.  So much is dependent on HANDLE_MULTIBYTE
+   that there are two separate versions of this function. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  char mbchar[MB_LEN_MAX];
+  int mb_len;
+
+  mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
+  else
+    return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
+}
+#else /* !HANDLE_MULTIBYTE */
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, c));
+  else
+    return (_rl_char_search_internal (count, fdir, c));
+}
+#endif /* !HANDLE_MULTIBYTE */
+
+int
+rl_char_search (count, key)
+     int count, key;
+{
+  return (_rl_char_search (count, FFIND, BFIND));
+}
+
+int
+rl_backward_char_search (count, key)
+     int count, key;
+{
+  return (_rl_char_search (count, BFIND, FFIND));
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                The Mark and the Region.                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+int
+_rl_set_mark_at_pos (position)
+     int position;
+{
+  if (position > rl_end)
+    return -1;
+
+  rl_mark = position;
+  return 0;
+}
+
+/* A bindable command to set the mark. */
+int
+rl_set_mark (count, key)
+     int count, key;
+{
+  return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
+}
+
+/* Exchange the position of mark and point. */
+int
+rl_exchange_point_and_mark (count, key)
+     int count, key;
+{
+  if (rl_mark > rl_end)
+    rl_mark = -1;
+
+  if (rl_mark == -1)
+    {
+      rl_ding ();
+      return -1;
+    }
+  else
+    SWAP (rl_point, rl_mark);
+
+  return 0;
+}
diff --git a/lib/readline/text.c.save2 b/lib/readline/text.c.save2
new file mode 100644 (file)
index 0000000..9d5dd9f
--- /dev/null
@@ -0,0 +1,1553 @@
+/* text.c -- text handling commands for readline. */
+
+/* Copyright (C) 1987-2004 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.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+#  include <locale.h>
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (__EMX__)
+#  define INCL_DOSPROCESS
+#  include <os2.h>
+#endif /* __EMX__ */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+/* Forward declarations. */
+static int rl_change_case PARAMS((int, int));
+static int _rl_char_search PARAMS((int, int, int));
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Insert and Delete                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Insert a string of text into the line at point.  This is the only
+   way that you should do insertion.  _rl_insert_char () calls this
+   function.  Returns the number of characters inserted. */
+int
+rl_insert_text (string)
+     const char *string;
+{
+  register int i, l;
+
+  l = (string && *string) ? strlen (string) : 0;
+  if (l == 0)
+    return 0;
+
+  if (rl_end + l >= rl_line_buffer_len)
+    rl_extend_line_buffer (rl_end + l);
+
+  for (i = rl_end; i >= rl_point; i--)
+    rl_line_buffer[i + l] = rl_line_buffer[i];
+  strncpy (rl_line_buffer + rl_point, string, l);
+
+  /* Remember how to undo this if we aren't undoing something. */
+  if (_rl_doing_an_undo == 0)
+    {
+      /* If possible and desirable, concatenate the undos. */
+      if ((l == 1) &&
+         rl_undo_list &&
+         (rl_undo_list->what == UNDO_INSERT) &&
+         (rl_undo_list->end == rl_point) &&
+         (rl_undo_list->end - rl_undo_list->start < 20))
+       rl_undo_list->end++;
+      else
+       rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+    }
+  rl_point += l;
+  rl_end += l;
+  rl_line_buffer[rl_end] = '\0';
+  return l;
+}
+
+/* Delete the string between FROM and TO.  FROM is inclusive, TO is not.
+   Returns the number of characters deleted. */
+int
+rl_delete_text (from, to)
+     int from, to;
+{
+  register char *text;
+  register int diff, i;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    SWAP (from, to);
+
+  /* fix boundaries */
+  if (to > rl_end)
+    {
+      to = rl_end;
+      if (from > to)
+       from = to;
+    }
+  if (from < 0)
+    from = 0;
+
+  text = rl_copy_text (from, to);
+
+  /* Some versions of strncpy() can't handle overlapping arguments. */
+  diff = to - from;
+  for (i = from; i < rl_end - diff; i++)
+    rl_line_buffer[i] = rl_line_buffer[i + diff];
+
+  /* Remember how to undo this delete. */
+  if (_rl_doing_an_undo == 0)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    free (text);
+
+  rl_end -= diff;
+  rl_line_buffer[rl_end] = '\0';
+  return (diff);
+}
+
+/* Fix up point so that it is within the line boundaries after killing
+   text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
+   boundaries also. */
+
+#define _RL_FIX_POINT(x) \
+       do { \
+       if (x > rl_end) \
+         x = rl_end; \
+       else if (x < 0) \
+         x = 0; \
+       } while (0)
+
+void
+_rl_fix_point (fix_mark_too)
+     int fix_mark_too;
+{
+  _RL_FIX_POINT (rl_point);
+  if (fix_mark_too)
+    _RL_FIX_POINT (rl_mark);
+}
+#undef _RL_FIX_POINT
+
+/* Replace the contents of the line buffer between START and END with
+   TEXT.  The operation is undoable.  To replace the entire line in an
+   undoable mode, use _rl_replace_text(text, 0, rl_end); */
+int
+_rl_replace_text (text, start, end)
+     const char *text;
+     int start, end;
+{
+  int n;
+
+  rl_begin_undo_group ();
+  rl_delete_text (start, end + 1);
+  rl_point = start;
+  n = rl_insert_text (text);
+  rl_end_undo_group ();
+
+  return n;
+}
+
+/* Replace the current line buffer contents with TEXT.  If CLEAR_UNDO is
+   non-zero, we free the current undo list. */
+void
+rl_replace_line (text, clear_undo)
+     const char *text;
+     int clear_undo;
+{
+  int len;
+
+  len = strlen (text);
+  if (len >= rl_line_buffer_len)
+    rl_extend_line_buffer (len);
+  strcpy (rl_line_buffer, text);
+  rl_end = len;
+
+  if (clear_undo)
+    rl_free_undo_list ();
+
+  _rl_fix_point (1);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Readline character functions                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine.  No hair
+   is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+   rl_end is the place in the string that we would place '\0';
+   i.e., it is always safe to place '\0' there.
+
+   rl_point is the place in the string where the cursor is.  Sometimes
+   this is the same as rl_end.
+
+   Any command that is called interactively receives two arguments.
+   The first is a count: the numeric arg pased to this command.
+   The second is the key which invoked this command.
+*/
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Movement Commands                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+   use said functions in other functions which do not do optimizing display.
+   I.e., you will have to update the data base for rl_redisplay, and you
+   might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT bytes. */
+int
+rl_forward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_backward_byte (-count, key));
+
+  if (count > 0)
+    {
+      int end = rl_point + count;
+#if defined (VI_MODE)
+      int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
+#else
+      int lend = rl_end;
+#endif
+
+      if (end > lend)
+       {
+         rl_point = lend;
+         rl_ding ();
+       }
+      else
+       rl_point = end;
+    }
+
+  if (rl_end < 0)
+    rl_end = 0;
+
+  return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move forward COUNT characters. */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_forward_byte (count, key));
+
+  if (count < 0)
+    return (rl_backward_char (-count, key));
+
+  if (count > 0)
+    {
+      point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+#if defined (VI_MODE)
+      if (rl_end <= point && rl_editing_mode == vi_mode)
+       point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
+#endif
+
+      if (rl_point == point)
+       rl_ding ();
+
+      rl_point = point;
+
+      if (rl_end < 0)
+       rl_end = 0;
+    }
+
+  return 0;
+}
+#else /* !HANDLE_MULTIBYTE */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  return (rl_forward_byte (count, key));
+}
+#endif /* !HANDLE_MULTIBYTE */
+  
+/* Backwards compatibility. */
+int
+rl_forward (count, key)
+     int count, key;
+{
+  return (rl_forward_char (count, key));
+}
+
+/* Move backward COUNT bytes. */
+int
+rl_backward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_forward_byte (-count, key));
+
+  if (count > 0)
+    {
+      if (rl_point < count)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+       rl_point -= count;
+    }
+
+  if (rl_point < 0)
+    rl_point = 0;
+
+  return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move backward COUNT characters. */
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_backward_byte (count, key));
+
+  if (count < 0)
+    return (rl_forward_char (-count, key));
+
+  if (count > 0)
+    {
+      point = rl_point;
+
+      while (count > 0 && point > 0)
+       {
+         point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
+         count--;
+       }
+      if (count > 0)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+        rl_point = point;
+    }
+
+  return 0;
+}
+#else
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  return (rl_backward_byte (count, key));
+}
+#endif
+
+/* Backwards compatibility. */
+int
+rl_backward (count, key)
+     int count, key;
+{
+  return (rl_backward_char (count, key));
+}
+
+/* Move to the beginning of the line. */
+int
+rl_beg_of_line (count, key)
+     int count, key;
+{
+  rl_point = 0;
+  return 0;
+}
+
+/* Move to the end of the line. */
+int
+rl_end_of_line (count, key)
+     int count, key;
+{
+  rl_point = rl_end;
+  return 0;
+}
+
+/* XXX - these might need changes for multibyte characters */
+/* Move forward a word.  We do what Emacs does. */
+int
+rl_forward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    return (rl_backward_word (-count, key));
+
+  while (count)
+    {
+      if (rl_point == rl_end)
+       return 0;
+
+      /* 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_char_value (rl_line_buffer, rl_point);
+
+      if (_rl_walphabetic (c) == 0)
+       {
+         rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+         while (rl_point < rl_end)
+           {
+             c = _rl_char_value (rl_line_buffer, rl_point);
+             if (_rl_walphabetic (c))
+               break;
+             rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+           }
+       }
+
+      if (rl_point == rl_end)
+       return 0;
+
+      rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+      while (rl_point < rl_end)
+       {
+         c = _rl_char_value (rl_line_buffer, rl_point);
+         if (_rl_walphabetic (c) == 0)
+           break;
+         rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+       }
+
+      --count;
+    }
+
+  return 0;
+}
+
+/* Move backward a word.  We do what Emacs does. */
+int
+rl_backward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    return (rl_forward_word (-count, key));
+
+  while (count)
+    {
+      if (!rl_point)
+       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)
+       {
+         while (--rl_point)
+           {
+             c = rl_line_buffer[rl_point - 1];
+             if (rl_alphabetic (c))
+               break;
+           }
+       }
+
+      while (rl_point)
+       {
+         c = rl_line_buffer[rl_point - 1];
+         if (rl_alphabetic (c) == 0)
+           break;
+         else
+           --rl_point;
+       }
+
+      --count;
+    }
+
+  return 0;
+}
+
+/* Clear the current line.  Numeric argument to C-l does this. */
+int
+rl_refresh_line (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  int curr_line;
+
+  curr_line = _rl_current_display_line ();
+
+  _rl_move_vert (curr_line);
+  _rl_move_cursor_relative (0, rl_line_buffer);   /* XXX is this right */
+
+  _rl_clear_to_eol (0);                /* arg of 0 means to not use spaces */
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+   the prompt and the current input line.  Given a numeric arg, redraw only
+   the current line. */
+int
+rl_clear_screen (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg)
+    {
+      rl_refresh_line (count, key);
+      return 0;
+    }
+
+  _rl_clear_screen ();         /* calls termcap function to clear screen */
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+int
+rl_arrow_keys (count, c)
+     int count, c;
+{
+  int ch;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  ch = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  switch (_rl_to_upper (ch))
+    {
+    case 'A':
+      rl_get_previous_history (count, ch);
+      break;
+
+    case 'B':
+      rl_get_next_history (count, ch);
+      break;
+
+    case 'C':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_forward_char (count, ch);
+      else
+       rl_forward_byte (count, ch);
+      break;
+
+    case 'D':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_backward_char (count, ch);
+      else
+       rl_backward_byte (count, ch);
+      break;
+
+    default:
+      rl_ding ();
+    }
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Text commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef HANDLE_MULTIBYTE
+static char pending_bytes[MB_LEN_MAX];
+static int pending_bytes_length = 0;
+static mbstate_t ps = {0};
+#endif
+
+/* Insert the character C at the current location, moving point forward.
+   If C introduces a multibyte sequence, we read the whole sequence and
+   then insert the multibyte char into the line buffer. */
+int
+_rl_insert_char (count, c)
+     int count, c;
+{
+  register int i;
+  char *string;
+#ifdef HANDLE_MULTIBYTE
+  int string_size;
+  char incoming[MB_LEN_MAX + 1];
+  int incoming_length = 0;
+  mbstate_t ps_back;
+  static int stored_count = 0;
+#endif
+
+  if (count <= 0)
+    return 0;
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+      incoming[0] = c;
+      incoming[1] = '\0';
+      incoming_length = 1;
+    }
+  else
+    {
+      wchar_t wc;
+      size_t ret;
+
+      if (stored_count <= 0)
+       stored_count = count;
+      else
+       count = stored_count;
+
+      ps_back = ps;
+      pending_bytes[pending_bytes_length++] = c;
+      ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
+
+      if (ret == (size_t)-2)
+       {
+         /* Bytes too short to compose character, try to wait for next byte.
+            Restore the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         ps = ps_back;
+         return 1;
+       }
+      else if (ret == (size_t)-1)
+       {
+         /* Invalid byte sequence for the current locale.  Treat first byte
+            as a single character. */
+         incoming[0] = pending_bytes[0];
+         incoming[1] = '\0';
+         incoming_length = 1;
+         pending_bytes_length--;
+         memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else if (ret == (size_t)0)
+       {
+         incoming[0] = '\0';
+         incoming_length = 0;
+         pending_bytes_length--;
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else
+       {
+         /* We successfully read a single multibyte character. */
+         memcpy (incoming, pending_bytes, pending_bytes_length);
+         incoming[pending_bytes_length] = '\0';
+         incoming_length = pending_bytes_length;
+         pending_bytes_length = 0;
+       }
+    }
+#endif /* HANDLE_MULTIBYTE */
+         
+  /* If we can optimize, then do it.  But don't let people crash
+     readline because of extra large arguments. */
+  if (count > 1 && count <= 1024)
+    {
+#if defined (HANDLE_MULTIBYTE)
+      string_size = count * incoming_length;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      string = (char *)xmalloc (1 + count);
+
+      for (i = 0; i < count; i++)
+       string[i] = c;
+#endif /* !HANDLE_MULTIBYTE */
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      free (string);
+
+      return 0;
+    }
+
+  if (count > 1024)
+    {
+      int decreaser;
+#if defined (HANDLE_MULTIBYTE)
+      string_size = incoming_length * 1024;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+
+      while (count)
+       {
+         decreaser = (count > 1024) ? 1024 : count;
+         string[decreaser*incoming_length] = '\0';
+         rl_insert_text (string);
+         count -= decreaser;
+       }
+
+      free (string);
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      char str[1024+1];
+
+      for (i = 0; i < 1024; i++)
+       str[i] = c;
+
+      while (count)
+       {
+         decreaser = (count > 1024 ? 1024 : count);
+         str[decreaser] = '\0';
+         rl_insert_text (str);
+         count -= decreaser;
+       }
+#endif /* !HANDLE_MULTIBYTE */
+
+      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
+        them all. */
+      if (_rl_any_typein ())
+       _rl_insert_typein (c);
+      else
+       {
+         /* Inserting a single character. */
+         char str[2];
+
+         str[1] = '\0';
+         str[0] = c;
+         rl_insert_text (str);
+       }
+#if defined (HANDLE_MULTIBYTE)
+    }
+  else
+    {
+      rl_insert_text (incoming);
+      stored_count = 0;
+    }
+#endif
+
+  return 0;
+}
+
+/* Overwrite the character at point (or next COUNT characters) with C.
+   If C introduces a multibyte character sequence, read the entire sequence
+   before starting the overwrite loop. */
+int
+_rl_overwrite_char (count, c)
+     int count, c;
+{
+  int i;
+#if defined (HANDLE_MULTIBYTE)
+  char mbkey[MB_LEN_MAX];
+  int k;
+
+  /* Read an entire multibyte character sequence to insert COUNT times. */
+  if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
+#endif
+
+  rl_begin_undo_group ();
+
+  for (i = 0; i < count; i++)
+    {
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_insert_text (mbkey);
+      else
+#endif
+       _rl_insert_char (1, c);
+
+      if (rl_point < rl_end)
+       rl_delete (1, c);
+    }
+
+  rl_end_undo_group ();
+
+  return 0;
+}
+
+int
+rl_insert (count, c)
+     int count, c;
+{
+  return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
+                                        : _rl_overwrite_char (count, c));
+}
+
+/* Insert the next typed character verbatim. */
+int
+rl_quoted_insert (count, key)
+     int count, key;
+{
+  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 ();
+#endif
+
+  return (_rl_insert_char (count, c));  
+}
+
+/* Insert a tab character. */
+int
+rl_tab_insert (count, key)
+     int count, key;
+{
+  return (_rl_insert_char (count, '\t'));
+}
+
+/* What to do when a NEWLINE is pressed.  We accept the whole line.
+   KEY is the key that invoked this command.  I guess it could have
+   meaning in the future. */
+int
+rl_newline (count, key)
+     int count, key;
+{
+  rl_done = 1;
+
+  if (_rl_history_preserve_point)
+    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+  RL_SETSTATE(RL_STATE_DONE);
+
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    {
+      _rl_vi_done_inserting ();
+      if (_rl_vi_textmod_command (_rl_vi_last_command) == 0)   /* XXX */
+       _rl_vi_reset_last ();
+    }
+#endif /* VI_MODE */
+
+  /* If we've been asked to erase empty lines, suppress the final update,
+     since _rl_update_final calls rl_crlf(). */
+  if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
+    return 0;
+
+  if (readline_echoing_p)
+    _rl_update_final ();
+  return 0;
+}
+
+/* What to do for some uppercase characters, like meta characters,
+   and some characters appearing in emacs_ctlx_keymap.  This function
+   is just a stub, you bind keys to it and the code in _rl_dispatch ()
+   is special cased. */
+int
+rl_do_lowercase_version (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  return 0;
+}
+
+/* This is different from what vi does, so the code's not shared.  Emacs
+   rubout in overwrite mode has one oddity:  it replaces a control
+   character that's displayed as two characters (^X) with two spaces. */
+int
+_rl_overwrite_rubout (count, key)
+     int count, key;
+{
+  int opoint;
+  int i, l;
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  opoint = rl_point;
+
+  /* L == number of spaces to insert */
+  for (i = l = 0; i < count; i++)
+    {
+      rl_backward_char (1, key);
+      l += rl_character_len (rl_line_buffer[rl_point], rl_point);      /* not exactly right */
+    }
+
+  rl_begin_undo_group ();
+
+  if (count > 1 || rl_explicit_arg)
+    rl_kill_text (opoint, rl_point);
+  else
+    rl_delete_text (opoint, rl_point);
+
+  /* Emacs puts point at the beginning of the sequence of spaces. */
+  if (rl_point < rl_end)
+    {
+      opoint = rl_point;
+      _rl_insert_char (l, ' ');
+      rl_point = opoint;
+    }
+
+  rl_end_undo_group ();
+
+  return 0;
+}
+  
+/* Rubout the character behind point. */
+int
+rl_rubout (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (!rl_point)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (rl_insert_mode == RL_IM_OVERWRITE)
+    return (_rl_overwrite_rubout (count, key));
+
+  return (_rl_rubout_char (count, key));
+}
+
+int
+_rl_rubout_char (count, key)
+     int count, key;
+{
+  int orig_point;
+  unsigned char c;
+
+  /* Duplicated code because this is called from other parts of the library. */
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  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_kill_text (orig_point, rl_point);
+    }
+  else
+    {
+#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
+      if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
+       {
+         int l;
+         l = rl_character_len (c, rl_point);
+         _rl_erase_at_end_of_line (l);
+       }
+    }
+
+  return 0;
+}
+
+/* Delete the character under the cursor.  Given a numeric argument,
+   kill that many characters instead. */
+int
+rl_delete (count, key)
+     int count, key;
+{
+  int r;
+
+  if (count < 0)
+    return (_rl_rubout_char (-count, key));
+
+  if (rl_point == rl_end)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  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);
+      rl_point = orig_point;
+      return r;
+    }
+  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;
+       
+      return (rl_delete_text (rl_point, new_point));
+    }
+}
+
+/* Delete the character under the cursor, unless the insertion
+   point is at the end of the line, in which case the character
+   behind the cursor is deleted.  COUNT is obeyed and may be used
+   to delete forward or backward that many characters. */      
+int
+rl_rubout_or_delete (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (_rl_rubout_char (count, key));
+  else
+    return (rl_delete (count, key));
+}  
+
+/* Delete all spaces and tabs around point. */
+int
+rl_delete_horizontal_space (count, ignore)
+     int count, ignore;
+{
+  int start = rl_point;
+
+  while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
+    rl_point--;
+
+  start = rl_point;
+
+  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+    rl_point++;
+
+  if (start != rl_point)
+    {
+      rl_delete_text (start, rl_point);
+      rl_point = start;
+    }
+  return 0;
+}
+
+/* Like the tcsh editing function delete-char-or-list.  The eof character
+   is caught before this is invoked, so this really does the same thing as
+   delete-char-or-list-or-eof, as long as it's bound to the eof character. */
+int
+rl_delete_or_show_completions (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (rl_possible_completions (count, key));
+  else
+    return (rl_delete (count, key));
+}
+
+#ifndef RL_COMMENT_BEGIN_DEFAULT
+#define RL_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+/* Turn the current line into a comment in shell history.
+   A K*rn shell style function. */
+int
+rl_insert_comment (count, key)
+     int count, key;
+{
+  char *rl_comment_text;
+  int rl_comment_len;
+
+  rl_beg_of_line (1, key);
+  rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
+
+  if (rl_explicit_arg == 0)
+    rl_insert_text (rl_comment_text);
+  else
+    {
+      rl_comment_len = strlen (rl_comment_text);
+      if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
+       rl_delete_text (rl_point, rl_point + rl_comment_len);
+      else
+       rl_insert_text (rl_comment_text);
+    }
+
+  (*rl_redisplay_function) ();
+  rl_newline (1, '\n');
+
+  return (0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Changing Case                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+int
+rl_upcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+int
+rl_downcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+int
+rl_capitalize_word (count, key)
+     int count, key;
+{
+ return (rl_change_case (count, CapCase));
+}
+
+/* The meaty function.
+   Change the case of COUNT words, performing OP on them.
+   OP is one of UpCase, DownCase, or CapCase.
+   If a negative argument is given, leave point where it started,
+   otherwise, leave it where it moves to. */
+static int
+rl_change_case (count, op)
+     int count, op;
+{
+  register int start, end;
+  int inword, c;
+
+  start = rl_point;
+  rl_forward_word (count, 0);
+  end = rl_point;
+
+  if (count < 0)
+    SWAP (start, end);
+
+  /* We are going to modify some text, so let's prepare to undo it. */
+  rl_modifying (start, end);
+
+  for (inword = 0; start < end; start++)
+    {
+      c = rl_line_buffer[start];
+      switch (op)
+       {
+       case UpCase:
+         rl_line_buffer[start] = _rl_to_upper (c);
+         break;
+
+       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;
+
+       default:
+         rl_ding ();
+         return -1;
+       }
+    }
+  rl_point = end;
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Transposition                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Transpose the words at point.  If point is at the end of the line,
+   transpose the two words before point. */
+int
+rl_transpose_words (count, key)
+     int count, key;
+{
+  char *word1, *word2;
+  int w1_beg, w1_end, w2_beg, w2_end;
+  int orig_point = rl_point;
+
+  if (!count)
+    return 0;
+
+  /* Find the two words. */
+  rl_forward_word (count, key);
+  w2_end = rl_point;
+  rl_backward_word (1, key);
+  w2_beg = rl_point;
+  rl_backward_word (count, key);
+  w1_beg = rl_point;
+  rl_forward_word (1, key);
+  w1_end = rl_point;
+
+  /* Do some check to make sure that there really are two words. */
+  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+    {
+      rl_ding ();
+      rl_point = orig_point;
+      return -1;
+    }
+
+  /* Get the text of the words. */
+  word1 = rl_copy_text (w1_beg, w1_end);
+  word2 = rl_copy_text (w2_beg, w2_end);
+
+  /* We are about to do many insertions and deletions.  Remember them
+     as one operation. */
+  rl_begin_undo_group ();
+
+  /* Do the stuff at word2 first, so that we don't have to worry
+     about word1 moving. */
+  rl_point = w2_beg;
+  rl_delete_text (w2_beg, w2_end);
+  rl_insert_text (word1);
+
+  rl_point = w1_beg;
+  rl_delete_text (w1_beg, w1_end);
+  rl_insert_text (word2);
+
+  /* This is exactly correct since the text before this point has not
+     changed in length. */
+  rl_point = w2_end;
+
+  /* I think that does it. */
+  rl_end_undo_group ();
+  free (word1);
+  free (word2);
+
+  return 0;
+}
+
+/* Transpose the characters at point.  If point is at the end of the line,
+   then transpose the characters before point. */
+int
+rl_transpose_chars (count, key)
+     int count, key;
+{
+#if defined (HANDLE_MULTIBYTE)
+  char *dummy;
+  int i, prev_point;
+#else
+  char dummy[2];
+#endif
+  int char_length;
+
+  if (count == 0)
+    return 0;
+
+  if (!rl_point || rl_end < 2)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  rl_begin_undo_group ();
+
+  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;
+      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--;
+
+#if defined (HANDLE_MULTIBYTE)
+  char_length = prev_point - rl_point;
+  dummy = (char *)xmalloc (char_length + 1);
+  for (i = 0; i < char_length; i++)
+    dummy[i] = rl_line_buffer[rl_point + i];
+  dummy[i] = '\0';
+#else
+  dummy[0] = rl_line_buffer[rl_point];
+  dummy[char_length = 1] = '\0';
+#endif
+
+  rl_delete_text (rl_point, rl_point + char_length);
+
+  rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+  _rl_fix_point (0);
+  rl_insert_text (dummy);
+  rl_end_undo_group ();
+
+#if defined (HANDLE_MULTIBYTE)
+  free (dummy);
+#endif
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Character Searching                         */
+/*                                                                 */
+/* **************************************************************** */
+
+int
+#if defined (HANDLE_MULTIBYTE)
+_rl_char_search_internal (count, dir, smbchar, len)
+     int count, dir;
+     char *smbchar;
+     int len;
+#else
+_rl_char_search_internal (count, dir, schar)
+     int count, dir, schar;
+#endif
+{
+  int pos, inc;
+#if defined (HANDLE_MULTIBYTE)
+  int prepos;
+#endif
+
+  pos = rl_point;
+  inc = (dir < 0) ? -1 : 1;
+  while (count)
+    {
+      if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
+       {
+         rl_ding ();
+         return -1;
+       }
+
+#if defined (HANDLE_MULTIBYTE)
+      pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                     : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+#else
+      pos += inc;
+#endif
+      do
+       {
+#if defined (HANDLE_MULTIBYTE)
+         if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
+#else
+         if (rl_line_buffer[pos] == schar)
+#endif
+           {
+             count--;
+             if (dir < 0)
+               rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                                       : pos;
+             else
+               rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
+                                       : pos;
+             break;
+           }
+#if defined (HANDLE_MULTIBYTE)
+         prepos = pos;
+#endif
+       }
+#if defined (HANDLE_MULTIBYTE)
+      while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
+                      : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
+#else
+      while ((dir < 0) ? pos-- : ++pos < rl_end);
+#endif
+    }
+  return (0);
+}
+
+/* Search COUNT times for a character read from the current input stream.
+   FDIR is the direction to search if COUNT is non-negative; otherwise
+   the search goes in BDIR.  So much is dependent on HANDLE_MULTIBYTE
+   that there are two separate versions of this function. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  char mbchar[MB_LEN_MAX];
+  int mb_len;
+
+  mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
+  else
+    return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
+}
+#else /* !HANDLE_MULTIBYTE */
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, c));
+  else
+    return (_rl_char_search_internal (count, fdir, c));
+}
+#endif /* !HANDLE_MULTIBYTE */
+
+int
+rl_char_search (count, key)
+     int count, key;
+{
+  return (_rl_char_search (count, FFIND, BFIND));
+}
+
+int
+rl_backward_char_search (count, key)
+     int count, key;
+{
+  return (_rl_char_search (count, BFIND, FFIND));
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                The Mark and the Region.                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+int
+_rl_set_mark_at_pos (position)
+     int position;
+{
+  if (position > rl_end)
+    return -1;
+
+  rl_mark = position;
+  return 0;
+}
+
+/* A bindable command to set the mark. */
+int
+rl_set_mark (count, key)
+     int count, key;
+{
+  return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
+}
+
+/* Exchange the position of mark and point. */
+int
+rl_exchange_point_and_mark (count, key)
+     int count, key;
+{
+  if (rl_mark > rl_end)
+    rl_mark = -1;
+
+  if (rl_mark == -1)
+    {
+      rl_ding ();
+      return -1;
+    }
+  else
+    SWAP (rl_point, rl_mark);
+
+  return 0;
+}
index a632d81129cb2d854814f03dd814ffd2f28dd1f4..d4b532f510df35868f8b3b9599ecb280a5be65d0 100644 (file)
@@ -44,6 +44,7 @@
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
+#include "rlmbutil.h"
 
 #if defined (TIOCSTAT_IN_SYS_IOCTL)
 #  include <sys/ioctl.h>
@@ -78,6 +79,22 @@ rl_alphabetic (c)
            strchr (pathname_alphabetic_chars, c) != NULL);
 }
 
+#if defined (HANDLE_MULTIBYTE)
+int
+_rl_walphabetic (wc)
+     wchar_t wc;
+{
+  int c;
+
+  if (iswalnum (wc))
+    return (1);     
+
+  c = wc & 0177;
+  return (_rl_allow_pathname_alphabetic_chars &&
+           strchr (pathname_alphabetic_chars, c) != NULL);
+}
+#endif
+
 /* How to abort things. */
 int
 _rl_abort_internal ()
diff --git a/lib/readline/util.c~ b/lib/readline/util.c~
new file mode 100644 (file)
index 0000000..18de206
--- /dev/null
@@ -0,0 +1,355 @@
+/* util.c -- readline utility functions */
+
+/* Copyright (C) 1987, 1989, 1992 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.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "posixjmp.h"
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>           /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (TIOCSTAT_IN_SYS_IOCTL)
+#  include <sys/ioctl.h>
+#endif /* TIOCSTAT_IN_SYS_IOCTL */
+
+/* Some standard library routines. */
+#include "readline.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Utility Functions                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return 0 if C is not a member of the class of characters that belong
+   in words, or 1 if it is. */
+
+int _rl_allow_pathname_alphabetic_chars = 0;
+static const char *pathname_alphabetic_chars = "/-_=~.#$";
+
+int
+rl_alphabetic (c)
+     int c;
+{
+  if (ALPHABETIC (c))
+    return (1);
+
+  return (_rl_allow_pathname_alphabetic_chars &&
+           strchr (pathname_alphabetic_chars, c) != NULL);
+}
+
+#if defined (HANDLE_MULTIBYTE)
+int
+rl_walphabetic (wc)
+     wchar_t wc;
+{
+  int c;
+
+  if (iswalnum (wc))
+    return (1);     
+
+  c = wc & 0177;
+  return (_rl_allow_pathname_alphabetic_chars &&
+           strchr (pathname_alphabetic_chars, c) != NULL);
+}
+#endif
+
+/* How to abort things. */
+int
+_rl_abort_internal ()
+{
+  rl_ding ();
+  rl_clear_message ();
+  _rl_init_argument ();
+  rl_clear_pending_input ();
+
+  RL_UNSETSTATE (RL_STATE_MACRODEF);
+  while (rl_executing_macro)
+    _rl_pop_executing_macro ();
+
+  rl_last_func = (rl_command_func_t *)NULL;
+  longjmp (readline_top_level, 1);
+  return (0);
+}
+
+int
+rl_abort (count, key)
+     int count, key;
+{
+  return (_rl_abort_internal ());
+}
+
+int
+rl_tty_status (count, key)
+     int count, key;
+{
+#if defined (TIOCSTAT)
+  ioctl (1, TIOCSTAT, (char *)0);
+  rl_refresh_line (count, key);
+#else
+  rl_ding ();
+#endif
+  return 0;
+}
+
+/* Return a copy of the string between FROM and TO.
+   FROM is inclusive, TO is not. */
+char *
+rl_copy_text (from, to)
+     int from, to;
+{
+  register int length;
+  char *copy;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    SWAP (from, to);
+
+  length = to - from;
+  copy = (char *)xmalloc (1 + length);
+  strncpy (copy, rl_line_buffer + from, length);
+  copy[length] = '\0';
+  return (copy);
+}
+
+/* Increase the size of RL_LINE_BUFFER until it has enough space to hold
+   LEN characters. */
+void
+rl_extend_line_buffer (len)
+     int len;
+{
+  while (len >= rl_line_buffer_len)
+    {
+      rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
+      rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len);
+    }
+
+  _rl_set_the_line ();
+}
+
+
+/* A function for simple tilde expansion. */
+int
+rl_tilde_expand (ignore, key)
+     int ignore, key;
+{
+  register int start, end;
+  char *homedir, *temp;
+  int len;
+
+  end = rl_point;
+  start = end - 1;
+
+  if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
+    {
+      homedir = tilde_expand ("~");
+      _rl_replace_text (homedir, start, end);
+      return (0);
+    }
+  else if (rl_line_buffer[start] != '~')
+    {
+      for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--)
+        ;
+      start++;
+    }
+
+  end = start;
+  do
+    end++;
+  while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end);
+
+  if (whitespace (rl_line_buffer[end]) || end >= rl_end)
+    end--;
+
+  /* If the first character of the current word is a tilde, perform
+     tilde expansion and insert the result.  If not a tilde, do
+     nothing. */
+  if (rl_line_buffer[start] == '~')
+    {
+      len = end - start + 1;
+      temp = (char *)xmalloc (len + 1);
+      strncpy (temp, rl_line_buffer + start, len);
+      temp[len] = '\0';
+      homedir = tilde_expand (temp);
+      free (temp);
+
+      _rl_replace_text (homedir, start, end);
+    }
+
+  return (0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     String Utility Functions                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Determine if s2 occurs in s1.  If so, return a pointer to the
+   match in s1.  The compare is case insensitive. */
+char *
+_rl_strindex (s1, s2)
+     register const char *s1, *s2;
+{
+  register int i, l, len;
+
+  for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
+    if (_rl_strnicmp (s1 + i, s2, l) == 0)
+      return ((char *) (s1 + i));
+  return ((char *)NULL);
+}
+
+#ifndef HAVE_STRPBRK
+/* Find the first occurrence in STRING1 of any character from STRING2.
+   Return a pointer to the character in STRING1. */
+char *
+_rl_strpbrk (string1, string2)
+     const char *string1, *string2;
+{
+  register const char *scan;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t ps;
+  register int i, v;
+
+  memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
+  for (; *string1; string1++)
+    {
+      for (scan = string2; *scan; scan++)
+       {
+         if (*string1 == *scan)
+           return ((char *)string1);
+       }
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         v = _rl_get_char_len (string1, &ps);
+         if (v > 1)
+           string1 += v - 1;   /* -1 to account for auto-increment in loop */
+       }
+#endif
+    }
+  return ((char *)NULL);
+}
+#endif
+
+#if !defined (HAVE_STRCASECMP)
+/* Compare at most COUNT characters from string1 to string2.  Case
+   doesn't matter. */
+int
+_rl_strnicmp (string1, string2, count)
+     char *string1, *string2;
+     int count;
+{
+  register char ch1, ch2;
+
+  while (count)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (_rl_to_upper(ch1) == _rl_to_upper(ch2))
+       count--;
+      else
+        break;
+    }
+  return (count);
+}
+
+/* strcmp (), but caseless. */
+int
+_rl_stricmp (string1, string2)
+     char *string1, *string2;
+{
+  register char ch1, ch2;
+
+  while (*string1 && *string2)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (_rl_to_upper(ch1) != _rl_to_upper(ch2))
+       return (1);
+    }
+  return (*string1 - *string2);
+}
+#endif /* !HAVE_STRCASECMP */
+
+/* Stupid comparison routine for qsort () ing strings. */
+int
+_rl_qsort_string_compare (s1, s2)
+  char **s1, **s2;
+{
+#if defined (HAVE_STRCOLL)
+  return (strcoll (*s1, *s2));
+#else
+  int result;
+
+  result = **s1 - **s2;
+  if (result == 0)
+    result = strcmp (*s1, *s2);
+
+  return result;
+#endif
+}
+
+/* Function equivalents for the macros defined in chardefs.h. */
+#define FUNCTION_FOR_MACRO(f)  int (f) (c) int c; { return f (c); }
+
+FUNCTION_FOR_MACRO (_rl_digit_p)
+FUNCTION_FOR_MACRO (_rl_digit_value)
+FUNCTION_FOR_MACRO (_rl_lowercase_p)
+FUNCTION_FOR_MACRO (_rl_pure_alphabetic)
+FUNCTION_FOR_MACRO (_rl_to_lower)
+FUNCTION_FOR_MACRO (_rl_to_upper)
+FUNCTION_FOR_MACRO (_rl_uppercase_p)
+
+/* Backwards compatibility, now that savestring has been removed from
+   all `public' readline header files. */
+#undef _rl_savestring
+char *
+_rl_savestring (s)
+     const char *s;
+{
+  return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s)));
+}
index 5f8097eb71d66fb1651157a0d4de8fbdd26c49b5..abb0402edc0c07759d1cb8856bf3f8f84a855885 100644 (file)
@@ -95,6 +95,32 @@ sh_double_quote (string)
   return (result);
 }
 
+/* Turn S into a simple double-quoted string.  If FLAGS is non-zero, quote
+   double quote characters in S with backslashes. */
+char *
+sh_mkdoublequoted (s, slen, flags)
+     const char *s;
+     int slen, flags;
+{
+  char *r, *ret;
+  int rlen;
+
+  rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
+  ret = r = (char *)xmalloc (rlen);
+  
+  *r++ = '"';
+  while (*s)
+    {
+      if (flags && *s == '"')
+       *r++ = '\\';
+      *r++ = *s++;
+    }
+  *r++ = '"';
+  *r = '\0';
+
+  return ret;
+}
+
 /* Remove backslashes that are quoting characters that are special between
    double quotes.  Return a new string.  XXX - should this handle CTLESC
    and CTLNUL? */
index e264e3dbe9ada8e5d8a434f0bb5b63198bb3c9ef..acf9d69ba5457427d111877194c16568242e43fc 100644 (file)
@@ -44,7 +44,8 @@
    that we're translating a string for `echo -e', and therefore should not
    treat a single quote as a character that may be escaped with a backslash.
    If (FLAGS&2) is non-zero, we're expanding for the parser and want to
-   quote CTLESC and CTLNUL with CTLESC */
+   quote CTLESC and CTLNUL with CTLESC.  If (flags&4) is non-zero, we want
+   to remove the backslash before any unrecognized escape sequence. */
 char *
 ansicstr (string, len, flags, sawc, rlen)
      char *string;
@@ -141,7 +142,10 @@ ansicstr (string, len, flags, sawc, rlen)
                  break;
                }
                /*FALLTHROUGH*/
-           default:  *r++ = '\\'; break;
+           default:
+               if ((flags & 4) == 0)
+                 *r++ = '\\';
+               break;
            }
          if ((flags & 2) && (c == CTLESC || c == CTLNUL))
            *r++ = CTLESC;
diff --git a/parse.y b/parse.y
index 456cfa675c5169192bd8e7b0ae84eacf10e8404f..0d97b83a6762eacca22f9c6553cca6798dc3c606 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -2810,6 +2810,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
                  /* Translate $'...' here. */
                  ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
                  xfree (nestret);
+
                  nestret = sh_single_quote (ttrans);
                  free (ttrans);
                  nestlen = strlen (nestret);
@@ -2820,13 +2821,10 @@ parse_matched_pair (qc, open, close, lenp, flags)
                  /* Locale expand $"..." here. */
                  ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
                  xfree (nestret);
-                 nestret = (char *)xmalloc (ttranslen + 3);
-                 nestret[0] = '"';
-                 strcpy (nestret + 1, ttrans);
-                 nestret[ttranslen + 1] = '"';
-                 nestret[ttranslen += 2] = '\0';
+
+                 nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
                  free (ttrans);
-                 nestlen = ttranslen;
+                 nestlen = ttranslen + 2;
                  retind -= 2;          /* back up before the $" */
                }
 
@@ -2925,19 +2923,12 @@ parse_dparen (c)
   if (reserved_word_acceptable (last_read_token))
     {
       sline = line_number;
-#if 0
-      cmdtyp = parse_arith_cmd (&wval, 1);
-#else
+
       cmdtyp = parse_arith_cmd (&wval, 0);
-#endif
       if (cmdtyp == 1) /* arithmetic command */
        {
          wd = make_word (wval);
-#if 0
-         wd->flags = W_QUOTED;
-#else
          wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB;
-#endif
          yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
          free (wval);  /* make_word copies it */
          return (ARITH_CMD);
@@ -3457,27 +3448,25 @@ read_token_word (character)
                {
                  ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen);
                  free (ttok);
+
                  /* Insert the single quotes and correctly quote any
                     embedded single quotes (allowed because P_ALLOWESC was
                     passed to parse_matched_pair). */
                  ttok = sh_single_quote (ttrans);
                  free (ttrans);
+                 ttranslen = strlen (ttok);
                  ttrans = ttok;
-                 ttranslen = strlen (ttrans);
                }
              else
                {
-                 /* Try to locale-expand the converted string. */
+                 /* Try to locale)-expand the converted string. */
                  ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
                  free (ttok);
 
                  /* Add the double quotes back */
-                 ttok = (char *)xmalloc (ttranslen + 3);
-                 ttok[0] = '"';
-                 strcpy (ttok + 1, ttrans);
-                 ttok[ttranslen + 1] = '"';
-                 ttok[ttranslen += 2] = '\0';
+                 ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
                  free (ttrans);
+                 ttranslen += 2;
                  ttrans = ttok;
                }
 
index 72ec06a2c1fd8dde92acea5e8ac773e35f1d061b..3efcf32d68e9722024b6ca9d67f9e81b2aa5ac04 100755 (executable)
@@ -1,4 +1,4 @@
-BUILD_DIR=/usr/local/build/bash/bash-current
+BUILD_DIR=/usr/local/build/chet/bash/bash-current
 THIS_SH=$BUILD_DIR/bash
 PATH=$PATH:$BUILD_DIR
 
index 006872c852b0c076d576801a4daa4aeb0ce3b773..45bbfd2ed34a0a6d96cd391167b7e458d44627f4 100644 (file)
@@ -1,2 +1,2 @@
-${THIS_SH} ./nquote.tests 2>&1 | grep -v '^expect' > /tmp/xx
-diff /tmp/xx nquote.right && rm -f /tmp/xx
+${THIS_SH} ./nquote4.tests 2>&1 | grep -v '^expect' > /tmp/xx
+diff /tmp/xx nquote4.right && rm -f /tmp/xx
index 92717584380c1f79c04e0701d02a48d7712a0cb2..5c0eba93d3bae809e14b204fab06589460734f63 100644 (file)
@@ -3446,7 +3446,13 @@ push_exported_var (data)
 
   /* If a temp var had its export attribute set, or it's marked to be
      propagated, bind it in the previous scope before disposing it. */
+  /* XXX - This isn't exactly right, because all tempenv variables have the
+    export attribute set. */
+#if 0
   if (exported_p (var) || (var->attributes & att_propagate))
+#else
+  if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
+#endif
     {
       var->attributes &= ~att_tempvar;         /* XXX */
       v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0);