--- readline-4.2a/shlib/Makefile.in.utf8	2001-11-02 17:41:23.000000000 +0100
+++ readline-4.2a/shlib/Makefile.in	2002-07-11 10:45:51.000000000 +0200
@@ -114,7 +114,7 @@
 	   $(topdir)/history.c $(topdir)/histsearch.c $(topdir)/histexpand.c \
 	   $(topdir)/histfile.c $(topdir)/nls.c $(topdir)/search.c \
 	   $(topdir)/shell.c $(topdir)/savestring.c $(topdir)/compat.c \
-	   $(topdir)/tilde.c
+	   $(topdir)/tilde.c $(topdir)/testUTF8.c
 
 # The header files for this library.
 HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
@@ -126,7 +126,8 @@
 SHARED_OBJ = readline.so vi_mode.so funmap.so keymaps.so parens.so search.so \
 	  rltty.so complete.so bind.so isearch.so display.so signals.so \
 	  util.so kill.so undo.so macro.so input.so callback.so terminal.so \
-	  nls.so xmalloc.so $(SHARED_HISTOBJ) $(SHARED_TILDEOBJ) compat.so
+	  nls.so xmalloc.so $(SHARED_HISTOBJ) $(SHARED_TILDEOBJ) compat.so \
+	  testUTF8.so
 
 ##########################################################################
 
@@ -368,6 +369,7 @@
 savestring.so: $(topdir)/savestring.c
 shell.so: $(topdir)/shell.c
 tilde.so: $(topdir)/tilde.c
+testUTF8.so: $(topdir)/testUTF8.c
 
 readline.so: readline.c
 vi_mode.so: vi_mode.c
@@ -398,3 +400,4 @@
 savestring.so: savestring.c
 shell.so: shell.c
 tilde.so: tilde.c
+testUTF8.so: testUTF8.c
--- readline-4.2a/Makefile.in.utf8	2001-11-02 17:41:09.000000000 +0100
+++ readline-4.2a/Makefile.in	2002-07-11 10:43:47.000000000 +0200
@@ -97,7 +97,7 @@
 	   $(srcdir)/history.c $(srcdir)/histsearch.c $(srcdir)/histexpand.c \
 	   $(srcdir)/histfile.c $(srcdir)/nls.c $(srcdir)/search.c \
 	   $(srcdir)/shell.c $(srcdir)/savestring.c $(srcdir)/tilde.c \
-	   $(srcdir)/compat.c
+	   $(srcdir)/compat.c $(srcdir)/testUTF8.c
 
 # The header files for this library.
 HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
@@ -110,7 +110,7 @@
 OBJECTS = readline.o vi_mode.o funmap.o keymaps.o parens.o search.o \
 	  rltty.o complete.o bind.o isearch.o display.o signals.o \
 	  util.o kill.o undo.o macro.o input.o callback.o terminal.o \
-	  nls.o compat.o xmalloc.o $(HISTOBJ) $(TILDEOBJ)
+	  nls.o compat.o xmalloc.o testUTF8.o $(HISTOBJ) $(TILDEOBJ)
 
 # The texinfo files which document this library.
 DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo
@@ -447,6 +447,7 @@
 histsearch.o: $(srcdir)/histsearch.c
 savestring.o: $(srcdir)/savestring.c
 shell.o: $(srcdir)/shell.c
+testUTF8.o: $(srcdir)/testUTF8.c
 tilde.o: $(srcdir)/tilde.c
 
 readline.o: readline.c
@@ -478,3 +479,4 @@
 savestring.o: savestring.c
 shell.o: shell.c
 tilde.o: tilde.c
+testUTF8.o: testUTF8.c
--- readline-4.2a/chardefs.h.utf8	2001-11-08 14:17:21.000000000 +0100
+++ readline-4.2a/chardefs.h	2002-07-11 10:43:47.000000000 +0200
@@ -58,6 +58,13 @@
 #define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
 #define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
 
+/* ADVANCES_CURSOR is 1 for ASCII characters and for the first raw character
+   of a UTF-8 sequence; it's 0 for the tail of a UTF-8 sequence. In a string
+   of correct UTF-8, the number of logical characters is equal to the sum
+   of ADVANCES_CURSOR applied to its characters. */
+#define ADVANCES_CURSOR(c) \
+  (!rl_utf8_mode || (unsigned char)(c) < 0x80 || (unsigned char)(c) >= 0xC0)
+
 #define CTRL(c) ((c) & control_character_mask)
 #define META(c) ((c) | meta_character_bit)
 
--- readline-4.2a/complete.c.utf8	2001-10-15 20:31:41.000000000 +0200
+++ readline-4.2a/complete.c	2002-07-11 10:43:47.000000000 +0200
@@ -58,6 +58,7 @@
 
 /* Some standard library routines. */
 #include "readline.h"
+#include "chardefs.h"
 #include "xmalloc.h"
 #include "rlprivate.h"
 
@@ -91,6 +92,10 @@
    longest string in that array. */
 rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL;
 
+extern int rl_utf8_mode;
+extern int rl_count_chars ();
+extern int rl_count_raw_chars ();
+
 #if defined (VISIBLE_STATS)
 #  if !defined (X_OK)
 #    define X_OK 1
@@ -438,7 +443,7 @@
       else \
 	{ \
 	  putc (c, rl_outstream); \
-	  printed_len++; \
+	  printed_len += ADVANCES_CURSOR (c); \
 	} \
     } while (0)
 
@@ -812,6 +817,9 @@
 	      break;
 	}
 
+      while (si && !ADVANCES_CURSOR (match_list[i][si]))
+	si--;
+
       if (low > si)
 	low = si;
     }
@@ -1035,7 +1043,7 @@
   for (max = 0, i = 1; matches[i]; i++)
     {
       temp = printable_part (matches[i]);
-      len = strlen (temp);
+      len = rl_count_chars (temp, strlen (temp));
 
       if (len > max)
 	max = len;
--- readline-4.2a/display.c.utf8	2001-10-30 22:11:44.000000000 +0100
+++ readline-4.2a/display.c	2002-07-11 10:43:47.000000000 +0200
@@ -65,7 +65,7 @@
 static void update_line PARAMS((char *, char *, int, int, int, int));
 static void space_to_eol PARAMS((int));
 static void delete_chars PARAMS((int));
-static void insert_some_chars PARAMS((char *, int));
+static void insert_some_chars PARAMS((char *, int, int));
 static void cr PARAMS((void));
 
 static int *inv_lbreaks, *vis_lbreaks;
@@ -170,6 +170,40 @@
 
 static int prompt_last_screen_line;
 
+/* Converts the number of logical characters to the number of raw characters */
+int
+rl_count_chars (string, count)
+     char *string;
+     int count;
+{
+  if (rl_utf8_mode)
+    {
+      int chars = 0;
+      for ( ; count--; string++)
+	chars += ADVANCES_CURSOR (*string);
+      return chars;
+    }
+  else
+    return count;
+}
+
+/* Converts the number of raw characters to the number of logical characters */
+int
+rl_count_raw_chars (string, count)
+     char *string;
+     int count;
+{
+  if (rl_utf8_mode)
+    {
+      char *s = string;
+      while (count--)
+	do s++; while (!ADVANCES_CURSOR (*s));
+      return s - string;
+    }
+  else
+    return count;
+}
+
 /* Expand the prompt string S and return the number of visible
    characters in *LP, if LP is not null.  This is currently more-or-less
    a placeholder for expansion.  LIP, if non-null is a place to store the
@@ -197,7 +231,7 @@
     {
       r = savestring (pmt);
       if (lp)
-	*lp = strlen (r);
+	*lp = rl_count_chars (r, strlen (r));
       return r;
     }
 
@@ -225,7 +259,7 @@
 	{
 	  *r++ = *p;
 	  if (!ignoring)
-	    rl++;
+	    rl += ADVANCES_CURSOR (*p);
 	  else
 	    ninvis++;
 	  if (rl == _rl_screenwidth)
@@ -368,6 +402,7 @@
 rl_redisplay ()
 {
   register int in, out, c, linenum, cursor_linenum;
+  int out_utf8_start, out_utf8_stop, out_utf8;
   register char *line;
   int c_pos, inv_botlin, lb_botlin, lb_linenum;
   int newlines, lpos, temp;
@@ -390,6 +425,7 @@
 
   line = invisible_line;
   out = inv_botlin = 0;
+  out_utf8_start = -1;
 
   /* Mark the line as modified or not.  We only do this for history
      lines. */
@@ -428,7 +464,7 @@
 	  out += local_len;
 	}
       line[out] = '\0';
-      wrap_offset = local_len - prompt_visible_length;
+      wrap_offset = rl_count_chars (local_prompt, local_len) - prompt_visible_length;
     }
   else
     {
@@ -490,7 +526,7 @@
 
   /* inv_lbreaks[i] is where line i starts in the buffer. */
   inv_lbreaks[newlines = 0] = 0;
-  lpos = out - wrap_offset;
+  lpos = rl_count_chars (line, out) - wrap_offset;
 
   /* prompt_invis_chars_first_line is the number of invisible characters in
      the first physical line of the prompt.
@@ -511,7 +547,7 @@
              ((newlines == 0) ? prompt_invis_chars_first_line : 0) +
              ((newlines == 1) ? wrap_offset : 0);
 
-      inv_lbreaks[++newlines] = temp;
+      inv_lbreaks[++newlines] = rl_count_raw_chars (line, temp);
       lpos -= _rl_screenwidth;
     }
 
@@ -561,8 +597,46 @@
 	    }
 	  else
 	    {
-	      line[out++] = c;
-	      CHECK_LPOS();
+	      if (rl_utf8_mode)
+		{
+		  /* rl_line_buffer can contain ill-formed or unterminated
+		     UTF-8 characters. This is normal during insertion of
+		     UTF-8 encoded text. These partial characters will not
+		     be displayed at all. The output line will always be
+		     in correct UTF-8. */
+		  if (ADVANCES_CURSOR (c))
+		    {
+		      /* Begin a new character, even when some other one
+			 was left unfinished. */
+		      out_utf8 = out_utf8_start = out;
+		      line[out_utf8++] = c;
+		      out_utf8_stop = out_utf8_start;
+		      /* The number of bytes in which the character is encoded
+			 is equal to the number of highest bits set in the
+			 first byte. */
+		      while (c & 0x80)
+			{
+			  out_utf8_stop++;
+			  c <<= 1;
+			}
+		    }
+		  else if (out == out_utf8_start)
+		    {
+		      /* A character is being composed. */
+		      line[out_utf8++] = c;
+		      if (out_utf8 == out_utf8_stop)
+			{
+			  /* A character successfully finished. */
+			  out = out_utf8;
+			  CHECK_LPOS();
+			}
+		    }
+		}
+	      else
+		{
+		  line[out++] = c;
+		  CHECK_LPOS();
+		}
 	    }
 	}
 #if defined (DISPLAY_TABS)
@@ -649,8 +723,8 @@
 	  /* If we have more than a screenful of material to display, then
 	     only display a screenful.  We should display the last screen,
 	     not the first.  */
-	  if (out >= _rl_screenchars)
-	    out = _rl_screenchars - 1;
+	  if (rl_count_chars (line, out) >= _rl_screenchars)
+	    out = rl_count_raw_chars (line, _rl_screenchars - 1);
 
 	  /* The first line is at character position 0 in the buffer.  The
 	     second and subsequent lines start at inv_lbreaks[N], offset by
@@ -675,8 +749,8 @@
 		 implies that we completely overwrite the old visible line)
 		 and the new line is shorter than the old.  Make sure we are
 		 at the end of the new line before clearing. */
-	      if (linenum == 0 &&
-		  inv_botlin == 0 && _rl_last_c_pos == out &&
+	      if (linenum == 0 && inv_botlin == 0 &&
+		  _rl_last_c_pos == rl_count_raw_chars (line, out) &&
 		  (wrap_offset > visible_wrap_offset) &&
 		  (_rl_last_c_pos < visible_first_line_len))
 		{
@@ -687,7 +761,10 @@
 
 	      /* Since the new first line is now visible, save its length. */
 	      if (linenum == 0)
-		visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
+		visible_first_line_len = (inv_botlin > 0) ?
+		  rl_count_chars (line, inv_lbreaks[1])
+		:
+		  rl_count_chars (line, out) - wrap_offset;
 	    }
 
 	  /* We may have deleted some lines.  If so, clear the left over
@@ -701,7 +778,7 @@
 		  _rl_move_vert (linenum);
 		  _rl_move_cursor_relative (0, tt);
 		  _rl_clear_to_eol
-		    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
+                    ((linenum == _rl_vis_botlin) ? rl_count_chars (tt, strlen (tt)) : _rl_screenwidth);
 		}
 	    }
 	  _rl_vis_botlin = inv_botlin;
@@ -727,7 +804,7 @@
 	     invisible character in the prompt string. */
 	  nleft = prompt_visible_length + wrap_offset;
 	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
-	      _rl_last_c_pos <= prompt_last_invisible && local_prompt)
+	      _rl_last_c_pos <= rl_count_chars (local_prompt, prompt_last_invisible) && local_prompt)
 	    {
 #if defined (__MSDOS__)
 	      putc ('\r', rl_outstream);
@@ -735,7 +812,8 @@
 	      if (_rl_term_cr)
 		tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
-	      _rl_output_some_chars (local_prompt, nleft);
+	      _rl_output_some_chars (local_prompt,
+				     rl_count_raw_chars (local_prompt, nleft));
 	      _rl_last_c_pos = nleft;
 	    }
 
@@ -744,10 +822,10 @@
 	  pos = inv_lbreaks[cursor_linenum];
 	  /* nleft == number of characters in the line buffer between the
 	     start of the line and the cursor position. */
-	  nleft = c_pos - pos;
+	  nleft = rl_count_chars (&invisible_line[pos], c_pos - pos);
 
-	  /* Since _rl_backspace() doesn't know about invisible characters in the
-	     prompt, and there's no good way to tell it, we compensate for
+	  /* Since _rl_backspace() doesn't know about invisible characters in
+	     the prompt, and there's no good way to tell it, we compensate for
 	     those characters here and call _rl_backspace() directly. */
 	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
 	    {
@@ -763,6 +841,7 @@
     {
 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
       int lmargin, ndisp, nleft, phys_c_pos, t;
+      int c_pos_char = rl_count_chars (line, c_pos);
 
       /* Always at top line. */
       _rl_last_v_pos = 0;
@@ -771,11 +850,11 @@
 	 will be LMARGIN. */
 
       /* The number of characters that will be displayed before the cursor. */
-      ndisp = c_pos - wrap_offset;
+      ndisp = c_pos_char - wrap_offset;
       nleft  = prompt_visible_length + wrap_offset;
       /* Where the new cursor position will be on the screen.  This can be
 	 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
-      phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
+      phys_c_pos = c_pos_char - (last_lmargin ? last_lmargin : wrap_offset);
       t = _rl_screenwidth / 3;
 
       /* If the number of characters had already exceeded the screenwidth,
@@ -786,7 +865,7 @@
 	 two-thirds of the way across the screen. */
       if (phys_c_pos > _rl_screenwidth - 2)
 	{
-	  lmargin = c_pos - (2 * t);
+	  lmargin = c_pos_char - (2 * t);
 	  if (lmargin < 0)
 	    lmargin = 0;
 	  /* If the left margin would be in the middle of a prompt with
@@ -800,7 +879,7 @@
 	{
 	  /* If we are moving back towards the beginning of the line and
 	     the last margin is no longer correct, compute a new one. */
-	  lmargin = ((c_pos - 1) / t) * t;	/* XXX */
+	  lmargin = ((c_pos_char - 1) / t) * t;	/* XXX */
 	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
 	    lmargin = nleft;
 	}
@@ -810,7 +889,22 @@
       /* If the first character on the screen isn't the first character
 	 in the display line, indicate this with a special character. */
       if (lmargin > 0)
-	line[lmargin] = '<';
+	{
+	  if (rl_utf8_mode)
+	    {
+	      int lmargin_raw = rl_count_raw_chars (line, lmargin);
+	      int len = rl_count_raw_chars (&line[lmargin_raw], 1);
+	      if (len != 1)
+		{
+		  memmove (line + lmargin_raw + 1, line + lmargin_raw + len,
+		    strlen (line + lmargin_raw + len) + 1);
+		  out += 1 - len;
+		}
+	      line[lmargin_raw] = '<';
+	    }
+	  else
+	    line[lmargin] = '<';
+	}
 
       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
 	 the whole line, indicate that with a special character at the
@@ -818,34 +912,48 @@
 	 wrap offset into account. */
       t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
       if (t < out)
-	line[t - 1] = '>';
+	line[rl_count_raw_chars (line, t - 1)] = '>';
 
       if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
 	{
 	  forced_display = 0;
-	  update_line (&visible_line[last_lmargin],
-		       &invisible_line[lmargin],
-		       0,
-		       _rl_screenwidth + visible_wrap_offset,
-		       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
-		       0);
+          if (rl_utf8_mode)
+            {
+              char *visible = &visible_line[rl_count_raw_chars
+                (visible_line, last_lmargin)];
+              char *invisible = &invisible_line[rl_count_raw_chars
+                (invisible_line, lmargin)];
+	      update_line (visible,
+			   invisible,
+			   0,
+			   rl_count_raw_chars (visible, _rl_screenwidth),
+                           rl_count_raw_chars (invisible, _rl_screenwidth + (lmargin ? 0 : wrap_offset)),
+			   0);
+            }
+          else
+	    update_line (&visible_line[last_lmargin],
+			 &invisible_line[lmargin],
+			 0,
+			 _rl_screenwidth + visible_wrap_offset,
+			 _rl_screenwidth + (lmargin ? 0 : wrap_offset),
+			 0);
 
 	  /* If the visible new line is shorter than the old, but the number
 	     of invisible characters is greater, and we are at the end of
 	     the new line, we need to clear to eol. */
 	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
 	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
-	      (_rl_last_c_pos == out) &&
+	      (_rl_last_c_pos == rl_count_chars (line, out)) &&
 	      t < visible_first_line_len)
 	    {
 	      nleft = _rl_screenwidth - t;
 	      _rl_clear_to_eol (nleft);
 	    }
-	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
+	  visible_first_line_len = rl_count_chars (line, out) - lmargin - M_OFFSET (lmargin, wrap_offset);
 	  if (visible_first_line_len > _rl_screenwidth)
 	    visible_first_line_len = _rl_screenwidth;
 
-	  _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
+	  _rl_move_cursor_relative (c_pos_char - lmargin, &invisible_line[rl_count_raw_chars (invisible_line, lmargin)]);
 	  last_lmargin = lmargin;
 	}
     }
@@ -901,6 +1009,8 @@
   int temp, lendiff, wsatend, od, nd;
   int current_invis_chars;
 
+  ofd = old; nfd = new;
+
   /* If we're at the right edge of a terminal that supports xn, we're
      ready to wrap around, so do so.  This fixes problems with knowing
      the exact cursor position and cut-and-paste with certain terminal
@@ -911,20 +1021,30 @@
       && _rl_last_v_pos == current_line - 1)
     {
       if (new[0])
-	putc (new[0], rl_outstream);
+	{
+	  if (rl_utf8_mode)
+	    fwrite (new, 1, rl_count_raw_chars (new, 1), rl_outstream);
+	  else
+	    putc (new[0], rl_outstream);
+	}
       else
 	putc (' ', rl_outstream);
       _rl_last_c_pos = 1;		/* XXX */
       _rl_last_v_pos++;
       if (old[0] && new[0])
-	old[0] = new[0];
+	{
+	  ofd += rl_count_raw_chars (ofd, 1);
+	  nfd += rl_count_raw_chars (nfd, 1);
+	}
     }
       
   /* Find first difference. */
-  for (ofd = old, nfd = new;
-       (ofd - old < omax) && *ofd && (*ofd == *nfd);
-       ofd++, nfd++)
-    ;
+  while (ofd - old < omax && *ofd && *ofd == *nfd)
+    ofd++, nfd++;
+  /* In UTF-8 mode we step back to the boundary of a character
+     in case only beginnings of two UTF-8 sequences are the same. */
+  while (!ADVANCES_CURSOR (*ofd)) ofd--;
+  while (!ADVANCES_CURSOR (*nfd)) nfd--;
 
   /* Move to the end of the screen line.  ND and OD are used to keep track
      of the distance between ne and new and oe and old, respectively, to
@@ -958,6 +1078,10 @@
 	ols++;
       if (*nls)
 	nls++;
+      /* In UTF-8 mode we step forward to the boundary of a character
+	 in case only endings of two UTF-8 sequences are the same. */
+      while (!ADVANCES_CURSOR (*ols)) ols++;
+      while (!ADVANCES_CURSOR (*nls)) nls++;
     }
 
   /* count of invisible characters in the current invisible line. */
@@ -984,8 +1108,8 @@
   lendiff = local_prompt ? strlen (local_prompt) : 0;
   od = ofd - old;	/* index of first difference in visible line */
   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
-      _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
-      od >= lendiff && _rl_last_c_pos <= prompt_last_invisible)
+      _rl_term_cr && rl_count_chars (local_prompt, lendiff) > prompt_visible_length && _rl_last_c_pos > 0 &&
+      rl_count_chars (old, od) >= rl_count_chars (local_prompt, lendiff) && _rl_last_c_pos <= rl_count_chars (local_prompt, prompt_last_invisible))
     {
 #if defined (__MSDOS__)
       putc ('\r', rl_outstream);
@@ -993,13 +1117,13 @@
       tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       _rl_output_some_chars (local_prompt, lendiff);
-      _rl_last_c_pos = lendiff;
+      _rl_last_c_pos = rl_count_chars (local_prompt, lendiff);
     }
 
-  _rl_move_cursor_relative (od, old);
+  _rl_move_cursor_relative (rl_count_chars (old, od), old);
 
   /* if (len (new) > len (old)) */
-  lendiff = (nls - nfd) - (ols - ofd);
+  lendiff = rl_count_chars (nfd, nls - nfd) - rl_count_chars (ofd, ols - ofd);
 
   /* If we are changing the number of invisible characters in a line, and
      the spot of first difference is before the end of the invisible chars,
@@ -1012,13 +1136,14 @@
   temp = ne - nfd;
   if (lendiff > 0)
     {
+      int lendiff_raw = rl_count_raw_chars (nfd, lendiff);
       /* Non-zero if we're increasing the number of lines. */
       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
       /* Sometimes it is cheaper to print the characters rather than
 	 use the terminal's capabilities.  If we're growing the number
 	 of lines, make sure we actually cause the new line to wrap
 	 around on auto-wrapping terminals. */
-      if (_rl_terminal_can_insert && ((2 * temp) >= lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
+      if (_rl_terminal_can_insert && ((2 * temp) >= lendiff_raw || _rl_term_IC) && (!_rl_term_autowrap || !gl))
 	{
 	  /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
 	     _rl_horizontal_scroll_mode == 1, inserting the characters with
@@ -1027,7 +1152,7 @@
 	  if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
 			lendiff <= prompt_visible_length || !current_invis_chars))
 	    {
-	      insert_some_chars (nfd, lendiff);
+	      insert_some_chars (nfd, lendiff, lendiff_raw);
 	      _rl_last_c_pos += lendiff;
 	    }
 	  else if (*ols == 0)
@@ -1036,7 +1161,7 @@
 		 be "inserted".  They can just be placed on the screen. */
 	      /* However, this screws up the rest of this block, which
 		 assumes you've done the insert because you can. */
-	      _rl_output_some_chars (nfd, lendiff);
+	      _rl_output_some_chars (nfd, lendiff_raw);
 	      _rl_last_c_pos += lendiff;
 	    }
 	  else
@@ -1045,22 +1170,22 @@
 		 the end.  We have invisible characters in this line.  This
 		 is a dumb update. */
 	      _rl_output_some_chars (nfd, temp);
-	      _rl_last_c_pos += temp;
+	      _rl_last_c_pos += rl_count_chars (nfd, temp);
 	      return;
 	    }
 	  /* Copy (new) chars to screen from first diff to last match. */
 	  temp = nls - nfd;
-	  if ((temp - lendiff) > 0)
+	  if ((temp - lendiff_raw) > 0)
 	    {
-	      _rl_output_some_chars (nfd + lendiff, temp - lendiff);
-	      _rl_last_c_pos += temp - lendiff;
+	      _rl_output_some_chars (nfd + lendiff_raw, temp - lendiff_raw);
+	      _rl_last_c_pos += rl_count_chars (nfd + lendiff_raw, temp - lendiff_raw);
 	    }
 	}
       else
 	{
 	  /* cannot insert chars, write to EOL */
 	  _rl_output_some_chars (nfd, temp);
-	  _rl_last_c_pos += temp;
+	  _rl_last_c_pos += rl_count_chars (nfd, temp);
 	}
     }
   else				/* Delete characters from line. */
@@ -1083,7 +1208,7 @@
 	  if (temp > 0)
 	    {
 	      _rl_output_some_chars (nfd, temp);
-	      _rl_last_c_pos += temp;
+	      _rl_last_c_pos += rl_count_chars (nfd, temp);
 	    }
 	}
       /* Otherwise, print over the existing material. */
@@ -1092,15 +1217,14 @@
 	  if (temp > 0)
 	    {
 	      _rl_output_some_chars (nfd, temp);
-	      _rl_last_c_pos += temp;
+	      _rl_last_c_pos += rl_count_chars (nfd, temp);
 	    }
-	  lendiff = (oe - old) - (ne - new);
 	  if (lendiff)
 	    {	  
 	      if (_rl_term_autowrap && current_line < inv_botlin)
-		space_to_eol (lendiff);
+		space_to_eol (-lendiff);
 	      else
-		_rl_clear_to_eol (lendiff);
+		_rl_clear_to_eol (-lendiff);
 	    }
 	}
     }
@@ -1234,12 +1358,12 @@
 	for (i = _rl_last_c_pos; i < new; i++)
 	  tputs (_rl_term_forward_char, 1, _rl_output_character_function);
       else
-	for (i = _rl_last_c_pos; i < new; i++)
-	  putc (data[i], rl_outstream);
-#else
-      for (i = _rl_last_c_pos; i < new; i++)
-	putc (data[i], rl_outstream);
 #endif /* HACK_TERMCAP_MOTION */
+	{
+	  int new_raw = rl_count_raw_chars (data, new);
+	  for (i = rl_count_raw_chars (data, _rl_last_c_pos); i < new_raw; i++)
+	    putc (data[i], rl_outstream);
+	}
     }
   else if (_rl_last_c_pos > new)
     _rl_backspace (_rl_last_c_pos - new);
@@ -1316,16 +1440,12 @@
   uc = (unsigned char)c;
 
   if (META_CHAR (uc))
-    return ((_rl_output_meta_chars == 0) ? 4 : 1);
+    return ((_rl_output_meta_chars == 0) ? 4 : ADVANCES_CURSOR (uc));
 
-  if (uc == '\t')
-    {
 #if defined (DISPLAY_TABS)
-      return (((pos | 7) + 1) - pos);
-#else
-      return (2);
-#endif /* !DISPLAY_TABS */
-    }
+  if (uc == '\t')
+    return (((pos | 7) + 1) - pos);
+#endif /* DISPLAY_TABS */
 
   if (CTRL_CHAR (c) || c == RUBOUT)
     return (2);
@@ -1516,9 +1636,9 @@
 
 /* Insert COUNT characters from STRING to the output stream. */
 static void
-insert_some_chars (string, count)
+insert_some_chars (string, count, count_raw)
      char *string;
-     int count;
+     int count, count_raw;
 {
   /* If IC is defined, then we do not have to "enter" insert mode. */
   if (_rl_term_IC)
@@ -1526,7 +1646,7 @@
       char *buffer;
       buffer = tgoto (_rl_term_IC, 0, count);
       tputs (buffer, 1, _rl_output_character_function);
-      _rl_output_some_chars (string, count);
+      _rl_output_some_chars (string, count_raw);
     }
   else
     {
@@ -1545,7 +1665,7 @@
 	}
 
       /* Print the text. */
-      _rl_output_some_chars (string, count);
+      _rl_output_some_chars (string, count_raw);
 
       /* If there is a string to turn off insert mode, we had best use
 	 it now. */
@@ -1592,7 +1712,7 @@
     }
   _rl_move_vert (_rl_vis_botlin);
   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
-  if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
+  if (full_lines && _rl_term_autowrap && (rl_count_chars (VIS_CHARS (_rl_vis_botlin), VIS_LLEN(_rl_vis_botlin)) == _rl_screenwidth))
     {
       char *last_line;
 #if 0
@@ -1602,7 +1722,13 @@
 #endif
       _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);
       _rl_clear_to_eol (0);
-      putc (last_line[_rl_screenwidth - 1], rl_outstream);
+      if (rl_utf8_mode)
+      {
+        char *last = last_line + rl_count_raw_chars (last_line, _rl_screenwidth - 1);
+        fwrite (last, 1, rl_count_raw_chars (last, 1), rl_outstream);
+      }
+      else
+        putc (last_line[_rl_screenwidth - 1], rl_outstream);
     }
   _rl_vis_botlin = 0;
   rl_crlf ();
--- readline-4.2a/input.c.utf8	2001-09-12 16:55:50.000000000 +0200
+++ readline-4.2a/input.c	2002-07-11 10:43:47.000000000 +0200
@@ -121,7 +121,7 @@
 /* Get a key from the buffer of characters to be read.
    Return the key in KEY.
    Result is KEY if there was a key, or 0 if there wasn't. */
-static int
+int
 rl_get_char (key)
      int *key;
 {
@@ -139,7 +139,7 @@
 /* Stuff KEY into the *front* of the input buffer.
    Returns non-zero if successful, zero if there is
    no space left in the buffer. */
-static int
+int
 rl_unget_char (key)
      int key;
 {
--- readline-4.2a/readline.c.utf8	2002-07-11 10:43:47.000000000 +0200
+++ readline-4.2a/readline.c	2002-07-11 10:43:47.000000000 +0200
@@ -48,6 +48,7 @@
 #endif
 
 #include <stdio.h>
+#include <errno.h>
 #include "posixjmp.h"
 
 /* System-specific feature definitions and include files. */
@@ -169,7 +170,7 @@
 
 /* Current prompt. */
 char *rl_prompt = (char *)NULL;
-int rl_visible_prompt_length = 0;
+int rl_visible_prompt_length = 0;	/* in characters */
 
 /* Set to non-zero by calling application if it has already printed rl_prompt
    and does not want readline to do it the first time. */
@@ -203,6 +204,9 @@
 /* Non-zero means to always use horizontal scrolling in line display. */
 int _rl_horizontal_scroll_mode = 0;
 
+/* Non-zero when in UTF-8 mode */
+int rl_utf8_mode = 0;
+
 /* Non-zero means to display an asterisk at the starts of history lines
    which have been modified. */
 int _rl_mark_modified_lines = 0;  
@@ -299,6 +303,14 @@
   rl_initialize ();
   (*rl_prep_term_function) (_rl_meta_flag);
 
+  rl_utf8_mode = is_in_UTF8_mode ();
+  if (rl_utf8_mode == -1)
+    {
+      /* Ignore any error, assume 8-bit mode */
+      errno = 0;
+      rl_utf8_mode = 0;
+    }
+
 #if defined (HANDLE_SIGNALS)
   rl_set_signals ();
 #endif
@@ -1011,8 +1023,8 @@
   return l;
 }
 
-/* Delete the string between FROM and TO.  FROM is
-   inclusive, TO is not. */
+/* Delete the string between raw character positions FROM and TO.
+   FROM is inclusive, TO is not. */
 int
 rl_delete_text (from, to)
      int from, to;
@@ -1029,7 +1041,7 @@
     {
       to = rl_end;
       if (from > to)
-        from = to;
+	from = to;
     }
 
   text = rl_copy_text (from, to);
@@ -1126,22 +1138,47 @@
     rl_backward (-count, key);
   else 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;
+      int lend = rl_end;
+      if (rl_editing_mode == vi_mode && lend)
+      do
+        lend--;
+      while (lend > 0 && !ADVANCES_CURSOR (the_line[lend]));
 #else
       int lend = rl_end;
 #endif
 
-      if (end > lend)
-	{
-	  rl_point = lend;
-	  rl_ding ();
-	}
-      else
-	rl_point = end;
+      if (rl_utf8_mode)
+      {
+        /* The behavior can be confusing with invalid UTF-8 data.
+           The cursor simply skips over characters 0x80..0xBF, which
+           normally forms the tail of an UTF-8 sequence. This applies
+           also to some other editing commands. */
+        for(;;)
+          {
+            count -= ADVANCES_CURSOR (the_line[rl_point]);
+            if (count < 0) break;
+            if (rl_point >= lend)
+              {
+                rl_ding ();
+                break;
+              }
+            rl_point++;
+          }
+        }
+        else
+        {
+          int end = rl_point + count;
+ 
+        if (end > lend)
+          {
+            rl_point = lend;
+	    rl_ding ();
+	  }
+        else
+	  rl_point = end;
+      }
     }
-
   if (rl_end < 0)
     rl_end = 0;
 
@@ -1155,16 +1192,33 @@
 {
   if (count < 0)
     rl_forward (-count, key);
-  else if (count > 0)
-    {
-      if (rl_point < count)
-	{
-	  rl_point = 0;
-	  rl_ding ();
-	}
+  else
+    if (count > 0)
+      {
+      if (rl_utf8_mode)
+        {
+          while (count)
+            {
+              if (rl_point == 0)
+                {
+                  rl_ding ();
+                  break;
+                }
+              rl_point--;
+              count -= ADVANCES_CURSOR (the_line[rl_point]);
+            }
+        }
       else
-        rl_point -= count;
-    }
+        {
+          if (rl_point < count)
+            {
+              rl_point = 0;
+              rl_ding ();
+            }
+          else
+            rl_point -= count;
+        }
+      }
 
   if (rl_point < 0)
     rl_point = 0;
@@ -1362,7 +1416,7 @@
 /*								    */
 /* **************************************************************** */
 
-/* Insert the character C at the current location, moving point forward. */
+/* Insert the raw character C at the current location, moving point forward. */
 int
 rl_insert (count, c)
      int count, c;
@@ -1523,17 +1577,41 @@
       rl_kill_text (orig_point, rl_point);
     }
   else
-    {
-      unsigned char c = the_line[--rl_point];
+    if (rl_utf8_mode)
+      {
+      int orig_point = rl_point;
+      int l = 0;
+      do {
+        rl_point--;
+        l += rl_character_len (the_line[rl_point], 0);
+      } while (rl_point > 0 && !ADVANCES_CURSOR (the_line[rl_point]));
+      rl_delete_text (rl_point, orig_point);
+
+      /* We can't easily erase a tab, because we don't know the physical
+         cursor position */
+      if (rl_point == rl_end &&
+#if defined (DISPLAY_TABS)
+          the_line[rl_point] != '\t' &&
+#endif /* DISPLAY_TABS */
+          _rl_last_c_pos >= l)
+        _rl_erase_at_end_of_line (l);
+      }
+    else
+      {
+      int c = the_line[--rl_point];
+      int l = rl_character_len (c, 0);
       rl_delete_text (rl_point, rl_point + 1);
 
-      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);
-	}
-    }
+      /* We can't easily erase a tab, because we don't know the physical
+         cursor position */
+      if (rl_point == rl_end &&
+#if defined (DISPLAY_TABS)
+          c != '\t' &&
+#endif /* DISPLAY_TABS */
+          _rl_last_c_pos >= l)
+        _rl_erase_at_end_of_line (l);
+      }
+
   return 0;
 }
 
@@ -1561,7 +1639,16 @@
       return 0;
     }
   else
-    return (rl_delete_text (rl_point, rl_point + 1));
+    if (rl_utf8_mode)
+      {
+	int new_point = rl_point;
+	do
+	  new_point++;
+	while (new_point < rl_end && !ADVANCES_CURSOR (the_line[new_point]));
+	return (rl_delete_text (rl_point, new_point));
+      }
+    else
+      return (rl_delete_text (rl_point, rl_point + 1));
 }
 
 /* Delete the character under the cursor, unless the insertion
@@ -1789,33 +1876,63 @@
 rl_transpose_chars (count, key)
      int count, key;
 {
-  char dummy[2];
+  char dummy[7];
 
   if (!count)
     return 0;
 
-  if (!rl_point || rl_end < 2)
+  if (rl_point > 0 && rl_point == rl_end)
+    {
+      if (rl_utf8_mode)
+      do
+        rl_point--;
+      while (rl_point > 0 && !ADVANCES_CURSOR (the_line[rl_point]));
+      else
+      rl_point--;
+      count = 1;
+    }
+
+  if (!rl_point)
     {
       rl_ding ();
       return -1;
     }
 
-  rl_begin_undo_group ();
-
-  if (rl_point == rl_end)
+  if (rl_utf8_mode)
     {
-      --rl_point;
-      count = 1;
+      do
+      rl_point--;
+      while (rl_point > 0 && !ADVANCES_CURSOR (the_line[rl_point]));
+
+      int i = 0;
+      do {
+      dummy[i] = the_line[rl_point + i];
+      i++;
+      } while (i < 6 && !ADVANCES_CURSOR (the_line[rl_point + i]));
+      dummy[i] = '\0';
+
+      rl_begin_undo_group ();
+
+      rl_delete_text (rl_point, rl_point + i);
+
+      while (the_line[rl_point] && count--)
+      do rl_point++; while (!ADVANCES_CURSOR (the_line[rl_point]));
     }
-  rl_point--;
+  else
+    {
+      rl_point--;
+
+      dummy[0] = the_line[rl_point];
+      dummy[1] = '\0';
 
-  dummy[0] = the_line[rl_point];
-  dummy[1] = '\0';
+      rl_begin_undo_group ();
 
-  rl_delete_text (rl_point, rl_point + 1);
+      rl_delete_text (rl_point, rl_point + 1);
+
+      rl_point += count;
+      _rl_fix_point (0);
+    }
 
-  rl_point += count;
-  _rl_fix_point (0);
   rl_insert_text (dummy);
 
   rl_end_undo_group ();
--- readline-4.2a/rlprivate.h.utf8	2001-10-29 16:24:34.000000000 +0100
+++ readline-4.2a/rlprivate.h	2002-07-11 10:43:47.000000000 +0200
@@ -196,6 +196,9 @@
 extern int _rl_vi_textmod_command PARAMS((int));
 extern void _rl_vi_done_inserting PARAMS((void));
 
+/* testUTF8.c */
+extern int is_in_UTF8_mode __P((void));
+
 /*************************************************************************
  * Undocumented private variables					 *
  *************************************************************************/
@@ -264,4 +267,6 @@
 extern int _rl_doing_an_undo;
 extern int _rl_undo_group_level;
 
+extern int rl_utf8_mode;
+
 #endif /* _RL_PRIVATE_H_ */
--- readline-4.2a/testUTF8.c.utf8	2002-07-11 10:43:47.000000000 +0200
+++ readline-4.2a/testUTF8.c	2002-07-11 10:43:47.000000000 +0200
@@ -0,0 +1,13 @@
+#include <string.h>
+#include <langinfo.h>
+
+/*
+ * return:
+ *  0: unknown mode
+ *  1: UTF-8 mode
+ * rch: these escapes above are unportable & don't work well, for example MC hangs in xterm :(
+ */
+int is_in_UTF8_mode ()
+{
+  return strcmp (nl_langinfo (CODESET), "UTF-8") == 0;
+}
