Import of readline 4.3.
[deliverable/binutils-gdb.git] / readline / display.c
index 9fff8cc2acb61b09dd59365a07a033c9adda9508..dec0de3e0d78dc874ff01ad58b9293d64047c666 100644 (file)
@@ -47,6 +47,7 @@
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
+#include "rlmbutil.h"
 
 /* Termcap library stuff. */
 #include "tcap.h"
@@ -63,14 +64,21 @@ extern char *strchr (), *strrchr ();
 #endif /* !strchr && !__STDC__ */
 
 #if defined (HACK_TERMCAP_MOTION)
-extern char *term_forward_char;
+extern char *_rl_term_forward_char;
 #endif
 
-static void update_line __P((char *, char *, int, int, int, int));
-static void space_to_eol __P((int));
-static void delete_chars __P((int));
-static void insert_some_chars __P((char *, int));
-static void cr __P((void));
+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, int));
+static void cr PARAMS((void));
+
+#if defined (HANDLE_MULTIBYTE)
+static int _rl_col_width PARAMS((char *, int, int));
+static int *_rl_wrapped_line;
+#else
+#  define _rl_col_width(l, s, e)       (((e) <= (s)) ? 0 : (e) - (s))
+#endif
 
 static int *inv_lbreaks, *vis_lbreaks;
 static int inv_lbsize, vis_lbsize;
@@ -107,7 +115,7 @@ static int inv_lbsize, vis_lbsize;
    RL_DISPLAY_FIXED variable.  This is good for efficiency. */
 
 /* Application-specific redisplay function. */
-VFunction *rl_redisplay_function = rl_redisplay;
+rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
 
 /* Global variables declared here. */
 /* What YOU turn on when you have handled all redisplay yourself. */
@@ -146,27 +154,40 @@ static int forced_display;
 /* Default and initial buffer size.  Can grow. */
 static int line_size = 1024;
 
+/* Variables to keep track of the expanded prompt string, which may
+   include invisible characters. */
+
 static char *local_prompt, *local_prompt_prefix;
-static int visible_length, prefix_length;
+static int prompt_visible_length, prompt_prefix_length;
 
 /* The number of invisible characters in the line currently being
    displayed on the screen. */
 static int visible_wrap_offset;
 
-/* static so it can be shared between rl_redisplay and update_line */
+/* The number of invisible characters in the prompt string.  Static so it
+   can be shared between rl_redisplay and update_line */
 static int wrap_offset;
 
-/* The index of the last invisible_character in the prompt string. */
-static int last_invisible;
+/* The index of the last invisible character in the prompt string. */
+static int prompt_last_invisible;
 
 /* The length (buffer offset) of the first line of the last (possibly
    multi-line) buffer displayed on the screen. */
 static int visible_first_line_len;
 
+/* Number of invisible characters on the first physical line of the prompt.
+   Only valid when the number of physical characters in the prompt exceeds
+   (or is equal to) _rl_screenwidth. */
+static int prompt_invis_chars_first_line;
+
+static int prompt_last_screen_line;
+
 /* 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
-   index of the last invisible character in the returned string. */
+   index of the last invisible character in the returned string. NIFLP,
+   if non-zero, is a place to store the number of invisible characters in
+   the first prompt line. */
 
 /* Current implementation:
        \001 (^A) start non-visible characters
@@ -176,12 +197,12 @@ static int visible_first_line_len;
    \002 are assumed to be `visible'. */        
 
 static char *
-expand_prompt (pmt, lp, lip)
+expand_prompt (pmt, lp, lip, niflp)
      char *pmt;
-     int *lp, *lip;
+     int *lp, *lip, *niflp;
 {
   char *r, *ret, *p;
-  int l, rl, last, ignoring;
+  int l, rl, last, ignoring, ninvis, invfl;
 
   /* Short-circuit if we can. */
   if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
@@ -193,9 +214,11 @@ expand_prompt (pmt, lp, lip)
     }
 
   l = strlen (pmt);
-  r = ret = xmalloc (l + 1);
-  
-  for (rl = ignoring = last = 0, p = pmt; p && *p; p++)
+  r = ret = (char *)xmalloc (l + 1);
+
+  invfl = 0;   /* invisible chars in first line of prompt */
+
+  for (rl = ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
     {
       /* This code strips the invisible character string markers
         RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
@@ -215,14 +238,23 @@ expand_prompt (pmt, lp, lip)
          *r++ = *p;
          if (!ignoring)
            rl++;
+         else
+           ninvis++;
+         if (rl == _rl_screenwidth)
+           invfl = ninvis;
        }
     }
 
+  if (rl < _rl_screenwidth)
+    invfl = ninvis;
+
   *r = '\0';
   if (lp)
     *lp = rl;
   if (lip)
     *lip = last;
+  if (niflp)
+    *niflp = invfl;
   return ret;
 }
 
@@ -234,7 +266,7 @@ _rl_strip_prompt (pmt)
 {
   char *ret;
 
-  ret = expand_prompt (pmt, (int *)NULL, (int *)NULL);
+  ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL);
   return ret;
 }
 
@@ -246,8 +278,8 @@ _rl_strip_prompt (pmt)
  *               (portion after the final newline)
  * local_prompt_prefix = portion before last newline of rl_display_prompt,
  *                      expanded via expand_prompt
- * visible_length = number of visible characters in local_prompt
- * prefix_length = number of visible characters in local_prompt_prefix
+ * prompt_visible_length = number of visible characters in local_prompt
+ * prompt_prefix_length = number of visible characters in local_prompt_prefix
  *
  * This function is called once per call to readline().  It may also be
  * called arbitrarily to expand the primary prompt.
@@ -263,12 +295,11 @@ rl_expand_prompt (prompt)
   int c;
 
   /* Clear out any saved values. */
-  if (local_prompt)
-    free (local_prompt);
-  if (local_prompt_prefix)
-    free (local_prompt_prefix);
+  FREE (local_prompt);
+  FREE (local_prompt_prefix);
+
   local_prompt = local_prompt_prefix = (char *)0;
-  last_invisible = visible_length = 0;
+  prompt_last_invisible = prompt_visible_length = 0;
 
   if (prompt == 0 || *prompt == 0)
     return (0);
@@ -276,22 +307,28 @@ rl_expand_prompt (prompt)
   p = strrchr (prompt, '\n');
   if (!p)
     {
-      /* The prompt is only one line. */
-      local_prompt = expand_prompt (prompt, &visible_length, &last_invisible);
+      /* The prompt is only one logical line, though it might wrap. */
+      local_prompt = expand_prompt (prompt, &prompt_visible_length,
+                                           &prompt_last_invisible,
+                                           &prompt_invis_chars_first_line);
       local_prompt_prefix = (char *)0;
-      return (visible_length);
+      return (prompt_visible_length);
     }
   else
     {
       /* The prompt spans multiple lines. */
       t = ++p;
-      local_prompt = expand_prompt (p, &visible_length, &last_invisible);
+      local_prompt = expand_prompt (p, &prompt_visible_length,
+                                      &prompt_last_invisible,
+                                      &prompt_invis_chars_first_line);
       c = *t; *t = '\0';
       /* The portion of the prompt string up to and including the
         final newline is now null-terminated. */
-      local_prompt_prefix = expand_prompt (prompt, &prefix_length, (int *)NULL);
+      local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
+                                                  (int *)NULL,
+                                                  &prompt_invis_chars_first_line);
       *t = c;
-      return (prefix_length);
+      return (prompt_prefix_length);
     }
 }
 
@@ -310,16 +347,16 @@ init_line_structures (minsize)
     {
       if (line_size < minsize)
        line_size = minsize;
-      visible_line = xmalloc (line_size);
-      invisible_line = xmalloc (line_size);
+      visible_line = (char *)xmalloc (line_size);
+      invisible_line = (char *)xmalloc (line_size);
     }
   else if (line_size < minsize)        /* ensure it can hold MINSIZE chars */
     {
       line_size *= 2;
       if (line_size < minsize)
        line_size = minsize;
-      visible_line = xrealloc (visible_line, line_size);
-      invisible_line = xrealloc (invisible_line, line_size);
+      visible_line = (char *)xrealloc (visible_line, line_size);
+      invisible_line = (char *)xrealloc (invisible_line, line_size);
     }
 
   for (n = minsize; n < line_size; n++)
@@ -334,6 +371,9 @@ init_line_structures (minsize)
       inv_lbsize = vis_lbsize = 256;
       inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
       vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
+#if defined (HANDLE_MULTIBYTE)
+      _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int));
+#endif
       inv_lbreaks[0] = vis_lbreaks[0] = 0;
     }
 }
@@ -347,6 +387,13 @@ rl_redisplay ()
   int c_pos, inv_botlin, lb_botlin, lb_linenum;
   int newlines, lpos, temp;
   char *prompt_this_line;
+#if defined (HANDLE_MULTIBYTE)
+  wchar_t wc;
+  size_t wc_bytes;
+  int wc_width;
+  mbstate_t ps;
+  int _rl_wrapped_multicolumn = 0;
+#endif
 
   if (!readline_echoing_p)
     return;
@@ -396,14 +443,14 @@ rl_redisplay ()
          if (temp >= line_size)
            {
              line_size = (temp + 1024) - (temp % 1024);
-             visible_line = xrealloc (visible_line, line_size);
-             line = invisible_line = xrealloc (invisible_line, line_size);
+             visible_line = (char *)xrealloc (visible_line, line_size);
+             line = invisible_line = (char *)xrealloc (invisible_line, line_size);
            }
          strncpy (line + out, local_prompt, local_len);
          out += local_len;
        }
       line[out] = '\0';
-      wrap_offset = local_len - visible_length;
+      wrap_offset = local_len - prompt_visible_length;
     }
   else
     {
@@ -430,13 +477,13 @@ rl_redisplay ()
       if (temp >= line_size)
        {
          line_size = (temp + 1024) - (temp % 1024);
-         visible_line = xrealloc (visible_line, line_size);
-         line = invisible_line = xrealloc (invisible_line, line_size);
+         visible_line = (char *)xrealloc (visible_line, line_size);
+         line = invisible_line = (char *)xrealloc (invisible_line, line_size);
        }
       strncpy (line + out,  prompt_this_line, pmtlen);
       out += pmtlen;
       line[out] = '\0';
-      wrap_offset = 0;
+      wrap_offset = prompt_invis_chars_first_line = 0;
     }
 
 #define CHECK_INV_LBREAKS() \
@@ -447,51 +494,126 @@ rl_redisplay ()
            inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
          } \
       } while (0)
-         
+
+#if defined (HANDLE_MULTIBYTE)   
 #define CHECK_LPOS() \
       do { \
        lpos++; \
-       if (lpos >= screenwidth) \
+       if (lpos >= _rl_screenwidth) \
          { \
            if (newlines >= (inv_lbsize - 2)) \
              { \
                inv_lbsize *= 2; \
                inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
+               _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
              } \
            inv_lbreaks[++newlines] = out; \
+           _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \
            lpos = 0; \
          } \
       } while (0)
+#else
+#define CHECK_LPOS() \
+      do { \
+       lpos++; \
+       if (lpos >= _rl_screenwidth) \
+         { \
+           if (newlines >= (inv_lbsize - 2)) \
+             { \
+               inv_lbsize *= 2; \
+               inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
+             } \
+           inv_lbreaks[++newlines] = out; \
+           lpos = 0; \
+         } \
+      } while (0)
+#endif
 
   /* inv_lbreaks[i] is where line i starts in the buffer. */
   inv_lbreaks[newlines = 0] = 0;
   lpos = out - wrap_offset;
+#if defined (HANDLE_MULTIBYTE)
+  memset (_rl_wrapped_line, 0, vis_lbsize);
+#endif
+
+  /* prompt_invis_chars_first_line is the number of invisible characters in
+     the first physical line of the prompt.
+     wrap_offset - prompt_invis_chars_first_line is the number of invis
+     chars on the second line. */
 
-  /* XXX - what if lpos is already >= screenwidth before we start drawing the
+  /* what if lpos is already >= _rl_screenwidth before we start drawing the
      contents of the command line? */
-  while (lpos >= screenwidth)
+  while (lpos >= _rl_screenwidth)
     {
-      /* XXX - possible fix from Darin Johnson <darin@acuson.com> for prompt
-        string with invisible characters that is longer than the screen
-        width.  XXX - this doesn't work right if invisible characters have
-        to be put on the second screen line -- it adds too much (the number
-        of invisible chars after the screenwidth). */
-      temp = ((newlines + 1) * screenwidth) + ((newlines == 0) ? wrap_offset : 0);
+      /* fix from Darin Johnson <darin@acuson.com> for prompt string with
+         invisible characters that is longer than the screen width.  The
+         prompt_invis_chars_first_line variable could be made into an array
+         saying how many invisible characters there are per line, but that's
+         probably too much work for the benefit gained.  How many people have
+         prompts that exceed two physical lines? */
+      temp = ((newlines + 1) * _rl_screenwidth) +
+#if 0
+             ((newlines == 0) ? prompt_invis_chars_first_line : 0) +
+#else
+             ((newlines == 0 && local_prompt_prefix == 0) ? prompt_invis_chars_first_line : 0) +
+#endif
+             ((newlines == 1) ? wrap_offset : 0);
 
       inv_lbreaks[++newlines] = temp;
-      lpos -= screenwidth;
+      lpos -= _rl_screenwidth;
     }
 
+  prompt_last_screen_line = newlines;
+
+  /* Draw the rest of the line (after the prompt) into invisible_line, keeping
+     track of where the cursor is (c_pos), the number of the line containing
+     the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
+     It maintains an array of line breaks for display (inv_lbreaks).
+     This handles expanding tabs for display and displaying meta characters. */
   lb_linenum = 0;
+#if defined (HANDLE_MULTIBYTE)
+  in = 0;
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    {
+      memset (&ps, 0, sizeof (mbstate_t));
+      wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
+    }
+  else
+    wc_bytes = 1;
+  while (in < rl_end)
+#else
   for (in = 0; in < rl_end; in++)
+#endif
     {
       c = (unsigned char)rl_line_buffer[in];
 
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         if (wc_bytes == (size_t)-1 || wc_bytes == (size_t)-2)
+           {
+             /* Byte sequence is invalid or shortened.  Assume that the
+                first byte represents a character. */
+             wc_bytes = 1;
+             /* Assume that a character occupies a single column. */
+             wc_width = 1;
+             memset (&ps, 0, sizeof (mbstate_t));
+           }
+         else if (wc_bytes == (size_t)0)
+           break;                      /* Found '\0' */
+         else
+           {
+             temp = wcwidth (wc);
+             wc_width = (temp < 0) ? 1 : temp;
+           }
+       }
+#endif
+
       if (out + 8 >= line_size)                /* XXX - 8 for \t */
        {
          line_size *= 2;
-         visible_line = xrealloc (visible_line, line_size);
-         invisible_line = xrealloc (invisible_line, line_size);
+         visible_line = (char *)xrealloc (visible_line, line_size);
+         invisible_line = (char *)xrealloc (invisible_line, line_size);
          line = invisible_line;
        }
 
@@ -501,15 +623,19 @@ rl_redisplay ()
          lb_linenum = newlines;
        }
 
+#if defined (HANDLE_MULTIBYTE)
+      if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
+#else
       if (META_CHAR (c))
+#endif
        {
          if (_rl_output_meta_chars == 0)
            {
              sprintf (line + out, "\\%o", c);
 
-             if (lpos + 4 >= screenwidth)
+             if (lpos + 4 >= _rl_screenwidth)
                {
-                 temp = screenwidth - lpos;
+                 temp = _rl_screenwidth - lpos;
                  CHECK_INV_LBREAKS ();
                  inv_lbreaks[++newlines] = out + temp;
                  lpos = 4 - temp;
@@ -528,7 +654,7 @@ rl_redisplay ()
 #if defined (DISPLAY_TABS)
       else if (c == '\t')
        {
-         register int temp, newout;
+         register int newout;
 
 #if 0
          newout = (out | (int)7) + 1;
@@ -536,10 +662,10 @@ rl_redisplay ()
          newout = out + 8 - lpos % 8;
 #endif
          temp = newout - out;
-         if (lpos + temp >= screenwidth)
+         if (lpos + temp >= _rl_screenwidth)
            {
              register int temp2;
-             temp2 = screenwidth - lpos;
+             temp2 = _rl_screenwidth - lpos;
              CHECK_INV_LBREAKS ();
              inv_lbreaks[++newlines] = out + temp2;
              lpos = temp - temp2;
@@ -554,7 +680,7 @@ rl_redisplay ()
            }
        }
 #endif
-      else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && term_up && *term_up)
+      else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
        {
          line[out++] = '\0';   /* XXX - sentinel */
          CHECK_INV_LBREAKS ();
@@ -570,9 +696,52 @@ rl_redisplay ()
        }
       else
        {
+#if defined (HANDLE_MULTIBYTE)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           {
+             register int i;
+
+             _rl_wrapped_multicolumn = 0;
+
+             if (_rl_screenwidth < lpos + wc_width)
+               for (i = lpos; i < _rl_screenwidth; i++)
+                 {
+                   /* The space will be removed in update_line() */
+                   line[out++] = ' ';
+                   _rl_wrapped_multicolumn++;
+                   CHECK_LPOS();
+                 }
+             if (in == rl_point)
+               {
+                 c_pos = out;
+                 lb_linenum = newlines;
+               }
+             for (i = in; i < in+wc_bytes; i++)
+               line[out++] = rl_line_buffer[i];
+             for (i = 0; i < wc_width; i++)
+               CHECK_LPOS();
+           }
+         else
+           {
+             line[out++] = c;
+             CHECK_LPOS();
+           }
+#else
          line[out++] = c;
          CHECK_LPOS();
+#endif
        }
+
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         in += wc_bytes;
+         wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
+       }
+      else
+        in++;
+#endif
+
     }
   line[out] = '\0';
   if (c_pos < 0)
@@ -586,7 +755,8 @@ rl_redisplay ()
   inv_lbreaks[newlines+1] = out;
   cursor_linenum = lb_linenum;
 
-  /* C_POS == position in buffer where cursor should be placed. */
+  /* C_POS == position in buffer where cursor should be placed.
+     CURSOR_LINENUM == line number where the cursor should be placed. */
 
   /* PWP: now is when things get a bit hairy.  The visible and invisible
      line buffers are really multiple lines, which would wrap every
@@ -597,7 +767,7 @@ rl_redisplay ()
      otherwise, let long lines display in a single terminal line, and
      horizontally scroll it. */
 
-  if (_rl_horizontal_scroll_mode == 0 && term_up && *term_up)
+  if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
     {
       int nleft, pos, changed_screen_line;
 
@@ -608,8 +778,13 @@ rl_redisplay ()
          /* 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 >= screenchars)
-           out = screenchars - 1;
+         if (out >= _rl_screenchars)
+           {
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
+             else
+               out = _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
@@ -639,7 +814,7 @@ rl_redisplay ()
                  (wrap_offset > visible_wrap_offset) &&
                  (_rl_last_c_pos < visible_first_line_len))
                {
-                 nleft = screenwidth + wrap_offset - _rl_last_c_pos;
+                 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
                  if (nleft)
                    _rl_clear_to_eol (nleft);
                }
@@ -660,7 +835,7 @@ rl_redisplay ()
                  _rl_move_vert (linenum);
                  _rl_move_cursor_relative (0, tt);
                  _rl_clear_to_eol
-                   ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth);
+                   ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
                }
            }
          _rl_vis_botlin = inv_botlin;
@@ -671,7 +846,7 @@ rl_redisplay ()
          if (changed_screen_line)
            {
              _rl_move_vert (cursor_linenum);
-             /* If we moved up to the line with the prompt using term_up,
+             /* If we moved up to the line with the prompt using _rl_term_up,
                 the physical cursor position on the screen stays the same,
                 but the buffer position needs to be adjusted to account
                 for invisible characters. */
@@ -684,18 +859,21 @@ rl_redisplay ()
             the characters from the current cursor position.  But we
             only need to reprint it if the cursor is before the last
             invisible character in the prompt string. */
-         nleft = visible_length + wrap_offset;
+         nleft = prompt_visible_length + wrap_offset;
          if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
-             _rl_last_c_pos <= last_invisible && local_prompt)
+             _rl_last_c_pos <= prompt_last_invisible && local_prompt)
            {
 #if defined (__MSDOS__)
              putc ('\r', rl_outstream);
 #else
-             if (term_cr)
-               tputs (term_cr, 1, _rl_output_character_function);
+             if (_rl_term_cr)
+               tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
              _rl_output_some_chars (local_prompt, nleft);
-             _rl_last_c_pos = nleft;
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               _rl_last_c_pos = _rl_col_width(local_prompt, 0, nleft);
+             else
+               _rl_last_c_pos = nleft;
            }
 
          /* Where on that line?  And where does that line start
@@ -711,10 +889,15 @@ rl_redisplay ()
          if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
            {
              _rl_backspace (_rl_last_c_pos - nleft);
-             _rl_last_c_pos = nleft;
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               _rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft);
+             else
+               _rl_last_c_pos = nleft;
            }
 
-         if (nleft != _rl_last_c_pos)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           _rl_move_cursor_relative (nleft, &invisible_line[pos]);
+         else if (nleft != _rl_last_c_pos)
            _rl_move_cursor_relative (nleft, &invisible_line[pos]);
        }
     }
@@ -731,11 +914,11 @@ rl_redisplay ()
 
       /* The number of characters that will be displayed before the cursor. */
       ndisp = c_pos - wrap_offset;
-      nleft  = visible_length + 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);
-      t = screenwidth / 3;
+      t = _rl_screenwidth / 3;
 
       /* If the number of characters had already exceeded the screenwidth,
         last_lmargin will be > 0. */
@@ -743,7 +926,7 @@ rl_redisplay ()
       /* If the number of characters to be displayed is more than the screen
         width, compute the starting offset so that the cursor is about
         two-thirds of the way across the screen. */
-      if (phys_c_pos > screenwidth - 2)
+      if (phys_c_pos > _rl_screenwidth - 2)
        {
          lmargin = c_pos - (2 * t);
          if (lmargin < 0)
@@ -753,7 +936,7 @@ rl_redisplay ()
          if (wrap_offset && lmargin > 0 && lmargin < nleft)
            lmargin = nleft;
        }
-      else if (ndisp < screenwidth - 2)                /* XXX - was -1 */
+      else if (ndisp < _rl_screenwidth - 2)            /* XXX - was -1 */
        lmargin = 0;
       else if (phys_c_pos < 1)
        {
@@ -775,7 +958,7 @@ rl_redisplay ()
         the whole line, indicate that with a special character at the
         right edge of the screen.  If LMARGIN is 0, we need to take the
         wrap offset into account. */
-      t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
+      t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
       if (t < out)
        line[t - 1] = '>';
 
@@ -785,8 +968,8 @@ rl_redisplay ()
          update_line (&visible_line[last_lmargin],
                       &invisible_line[lmargin],
                       0,
-                      screenwidth + visible_wrap_offset,
-                      screenwidth + (lmargin ? 0 : wrap_offset),
+                      _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
@@ -797,12 +980,12 @@ rl_redisplay ()
              (_rl_last_c_pos == out) &&
              t < visible_first_line_len)
            {
-             nleft = screenwidth - t;
+             nleft = _rl_screenwidth - t;
              _rl_clear_to_eol (nleft);
            }
          visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
-         if (visible_first_line_len > screenwidth)
-           visible_first_line_len = screenwidth;
+         if (visible_first_line_len > _rl_screenwidth)
+           visible_first_line_len = _rl_screenwidth;
 
          _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
          last_lmargin = lmargin;
@@ -812,11 +995,11 @@ rl_redisplay ()
 
   /* Swap visible and non-visible lines. */
   {
-    char *temp = visible_line;
+    char *vtemp = visible_line;
     int *itemp = vis_lbreaks, ntemp = vis_lbsize;
 
     visible_line = invisible_line;
-    invisible_line = temp;
+    invisible_line = vtemp;
 
     vis_lbreaks = inv_lbreaks;
     inv_lbreaks = itemp;
@@ -859,6 +1042,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
   int temp, lendiff, wsatend, od, nd;
   int current_invis_chars;
+  int col_lendiff, col_temp;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t ps_new, ps_old;
+  int new_offset, old_offset, tmp;
+#endif
 
   /* 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
@@ -866,20 +1054,98 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
      emulators.  In this calculation, TEMP is the physical screen
      position of the cursor. */
   temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
-  if (temp == screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
-      && _rl_last_v_pos == current_line - 1)
+  if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
+       && _rl_last_v_pos == current_line - 1)
     {
-      if (new[0])
-       putc (new[0], rl_outstream);
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         wchar_t wc;
+         mbstate_t ps;
+         int tempwidth, bytes;
+         size_t ret;
+
+         /* This fixes only double-column characters, but if the wrapped
+            character comsumes more than three columns, spaces will be
+            inserted in the string buffer. */
+         if (_rl_wrapped_line[current_line] > 0)
+           _rl_clear_to_eol (_rl_wrapped_line[current_line]);
+
+         memset (&ps, 0, sizeof (mbstate_t));
+         ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
+         if (ret == (size_t)-1 || ret == (size_t)-2)
+           {
+             tempwidth = 1;
+             ret = 1;
+           }
+         else if (ret == 0)
+           tempwidth = 0;
+         else
+           tempwidth = wcwidth (wc);
+
+         if (tempwidth > 0)
+           {
+             int count;
+             bytes = ret;
+             for (count = 0; count < bytes; count++)
+               putc (new[count], rl_outstream);
+             _rl_last_c_pos = tempwidth;
+             _rl_last_v_pos++;
+             memset (&ps, 0, sizeof (mbstate_t));
+             ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
+             if (ret != 0 && bytes != 0)
+               {
+                 if (ret == (size_t)-1 || ret == (size_t)-2)
+                   memmove (old+bytes, old+1, strlen (old+1));
+                 else
+                   memmove (old+bytes, old+ret, strlen (old+ret));
+                 memcpy (old, new, bytes);
+               }
+           }
+         else
+           {
+             putc (' ', rl_outstream);
+             _rl_last_c_pos = 1;
+             _rl_last_v_pos++;
+             if (old[0] && new[0])
+               old[0] = new[0];
+           }
+       }
       else
-       putc (' ', rl_outstream);
-      _rl_last_c_pos = 1;              /* XXX */
-      _rl_last_v_pos++;
-      if (old[0] && new[0])
-       old[0] = new[0];
+#endif
+       {
+         if (new[0])
+           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];
+       }
     }
+
       
   /* Find first difference. */
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    {
+      memset (&ps_new, 0, sizeof(mbstate_t));
+      memset (&ps_old, 0, sizeof(mbstate_t));
+
+      new_offset = old_offset = 0;
+      for (ofd = old, nfd = new;
+          (ofd - old < omax) && *ofd &&
+            _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
+       {
+         old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
+         new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
+         ofd = old + old_offset;
+         nfd = new + new_offset;
+       }
+    }
+  else
+#endif
   for (ofd = old, nfd = new;
        (ofd - old < omax) && *ofd && (*ofd == *nfd);
        ofd++, nfd++)
@@ -896,6 +1162,33 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
     return;
 
   wsatend = 1;                 /* flag for trailing whitespace */
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    {
+      ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
+      nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
+      while ((ols > ofd) && (nls > nfd))
+       {
+         memset (&ps_old, 0, sizeof (mbstate_t));
+         memset (&ps_new, 0, sizeof (mbstate_t));
+
+         _rl_adjust_point (old, ols - old, &ps_old);
+         _rl_adjust_point (new, nls - new, &ps_new);
+
+         if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
+           break;
+
+         if (*ols == ' ')
+           wsatend = 0;
+
+         ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
+         nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
+       }
+    }
+  else
+    {
+#endif /* HANDLE_MULTIBYTE */
   ols = oe - 1;                        /* find last same */
   nls = ne - 1;
   while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
@@ -905,18 +1198,38 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
       ols--;
       nls--;
     }
+#if defined (HANDLE_MULTIBYTE)
+    }
+#endif
 
   if (wsatend)
     {
       ols = oe;
       nls = ne;
     }
+#if defined (HANDLE_MULTIBYTE)
+  /* This may not work for stateful encoding, but who cares?  To handle
+     stateful encoding properly, we have to scan each string from the
+     beginning and compare. */
+  else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
+#else
   else if (*ols != *nls)
+#endif
     {
       if (*ols)                        /* don't step past the NUL */
-       ols++;
+       {
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
+         else
+           ols++;
+       }
       if (*nls)
-       nls++;
+       {
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
+         else
+           nls++;
+       }
     }
 
   /* count of invisible characters in the current invisible line. */
@@ -943,33 +1256,59 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
   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 &&
-      term_cr && lendiff > visible_length && _rl_last_c_pos > 0 &&
-      od > lendiff && _rl_last_c_pos < last_invisible)
+      _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
+      od >= lendiff && _rl_last_c_pos <= prompt_last_invisible)
     {
 #if defined (__MSDOS__)
       putc ('\r', rl_outstream);
 #else
-      tputs (term_cr, 1, _rl_output_character_function);
+      tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       _rl_output_some_chars (local_prompt, lendiff);
-      _rl_last_c_pos = lendiff;
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff);
+      else
+       _rl_last_c_pos = lendiff;
     }
 
   _rl_move_cursor_relative (od, old);
 
-  /* if (len (new) > len (old)) */
+  /* if (len (new) > len (old))
+     lendiff == difference in buffer
+     col_lendiff == difference on screen
+     When not using multibyte characters, these are equal */
   lendiff = (nls - nfd) - (ols - ofd);
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
+  else
+    col_lendiff = lendiff;
 
   /* 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,
      lendiff needs to be adjusted. */
   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
       current_invis_chars != visible_wrap_offset)
-    lendiff += visible_wrap_offset - current_invis_chars;
+    {
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         lendiff += visible_wrap_offset - current_invis_chars;
+         col_lendiff += visible_wrap_offset - current_invis_chars;
+       }
+      else
+       {
+         lendiff += visible_wrap_offset - current_invis_chars;
+         col_lendiff = lendiff;
+       }
+    }
 
   /* Insert (diff (len (old), len (new)) ch. */
   temp = ne - nfd;
-  if (lendiff > 0)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    col_temp = _rl_col_width (new, nfd - new, ne - new);
+  else
+    col_temp = temp;
+
+  if (col_lendiff > 0) /* XXX - was lendiff */
     {
       /* Non-zero if we're increasing the number of lines. */
       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
@@ -977,17 +1316,17 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
         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 (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!_rl_term_autowrap || !gl))
+      if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
        {
-         /* If lendiff > visible_length and _rl_last_c_pos == 0 and
+         /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
             _rl_horizontal_scroll_mode == 1, inserting the characters with
-            term_IC or term_ic will screw up the screen because of the
+            _rl_term_IC or _rl_term_ic will screw up the screen because of the
             invisible characters.  We need to just draw them. */
          if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
-                       lendiff <= visible_length || !current_invis_chars))
+                       lendiff <= prompt_visible_length || !current_invis_chars))
            {
-             insert_some_chars (nfd, lendiff);
-             _rl_last_c_pos += lendiff;
+             insert_some_chars (nfd, lendiff, col_lendiff);
+             _rl_last_c_pos += col_lendiff;
            }
          else if (*ols == 0)
            {
@@ -996,7 +1335,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
              /* 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_last_c_pos += lendiff;
+             _rl_last_c_pos += col_lendiff;
            }
          else
            {
@@ -1004,7 +1343,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
                 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 += col_temp;
              return;
            }
          /* Copy (new) chars to screen from first diff to last match. */
@@ -1012,37 +1351,41 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
          if ((temp - lendiff) > 0)
            {
              _rl_output_some_chars (nfd + lendiff, temp - lendiff);
-             _rl_last_c_pos += temp - lendiff;
+#if 0
+             _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff) - col_lendiff;
+#else
+             _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
+#endif
            }
        }
       else
        {
          /* cannot insert chars, write to EOL */
          _rl_output_some_chars (nfd, temp);
-         _rl_last_c_pos += temp;
+         _rl_last_c_pos += col_temp;
        }
     }
   else                         /* Delete characters from line. */
     {
       /* If possible and inexpensive to use terminal deletion, then do so. */
-      if (term_dc && (2 * temp) >= -lendiff)
+      if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
        {
          /* If all we're doing is erasing the invisible characters in the
             prompt string, don't bother.  It screws up the assumptions
             about what's on the screen. */
          if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
              -lendiff == visible_wrap_offset)
-           lendiff = 0;
+           col_lendiff = 0;
 
-         if (lendiff)
-           delete_chars (-lendiff); /* delete (diff) characters */
+         if (col_lendiff)
+           delete_chars (-col_lendiff); /* delete (diff) characters */
 
          /* Copy (new) chars to screen from first diff to last match */
          temp = nls - nfd;
          if (temp > 0)
            {
              _rl_output_some_chars (nfd, temp);
-             _rl_last_c_pos += temp;
+             _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
            }
        }
       /* Otherwise, print over the existing material. */
@@ -1051,15 +1394,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
          if (temp > 0)
            {
              _rl_output_some_chars (nfd, temp);
-             _rl_last_c_pos += temp;
+             _rl_last_c_pos += col_temp;
            }
          lendiff = (oe - old) - (ne - new);
-         if (lendiff)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
+         else
+           col_lendiff = lendiff;
+
+         if (col_lendiff)
            {     
              if (_rl_term_autowrap && current_line < inv_botlin)
-               space_to_eol (lendiff);
+               space_to_eol (col_lendiff);
              else
-               _rl_clear_to_eol (lendiff);
+               _rl_clear_to_eol (col_lendiff);
            }
        }
     }
@@ -1105,12 +1453,15 @@ rl_on_new_line_with_prompt ()
     prompt_last_line = rl_prompt;
 
   l = strlen (prompt_last_line);
-  _rl_last_c_pos = l;
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l);
+  else
+    _rl_last_c_pos = l;
 
   /* Dissect prompt_last_line into screen lines. Note that here we have
      to use the real screenwidth. Readline's notion of screenwidth might be
      one less, see terminal.c. */
-  real_screenwidth = screenwidth + (_rl_term_autowrap ? 0 : 1);
+  real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
   _rl_last_v_pos = l / real_screenwidth;
   /* If the prompt length is a multiple of real_screenwidth, we don't know
      whether the cursor is at the end of the last line, or already at the
@@ -1155,24 +1506,31 @@ rl_forced_update_display ()
 void
 _rl_move_cursor_relative (new, data)
      int new;
-     char *data;
+     const char *data;
 {
   register int i;
 
   /* If we don't have to do anything, then return. */
+#if defined (HANDLE_MULTIBYTE)
+  /* If we have multibyte characters, NEW is indexed by the buffer point in
+     a multibyte string, but _rl_last_c_pos is the display position.  In
+     this case, NEW's display position is not obvious. */
+  if ((MB_CUR_MAX == 1 || rl_byte_oriented ) && _rl_last_c_pos == new) return;
+#else
   if (_rl_last_c_pos == new) return;
+#endif
 
   /* It may be faster to output a CR, and then move forwards instead
      of moving backwards. */
   /* i == current physical cursor position. */
   i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
   if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
-      (_rl_term_autowrap && i == screenwidth))
+      (_rl_term_autowrap && i == _rl_screenwidth))
     {
 #if defined (__MSDOS__)
       putc ('\r', rl_outstream);
 #else
-      tputs (term_cr, 1, _rl_output_character_function);
+      tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif /* !__MSDOS__ */
       _rl_last_c_pos = 0;
     }
@@ -1189,20 +1547,70 @@ _rl_move_cursor_relative (new, data)
         That kind of control is for people who don't know what the
         data is underneath the cursor. */
 #if defined (HACK_TERMCAP_MOTION)
-      if (term_forward_char)
+      if (_rl_term_forward_char)
+       {
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           {
+             int width;
+             width = _rl_col_width (data, _rl_last_c_pos, new);
+             for (i = 0; i < width; i++)
+               tputs (_rl_term_forward_char, 1, _rl_output_character_function);
+           }
+         else
+           {
+             for (i = _rl_last_c_pos; i < new; i++)
+               tputs (_rl_term_forward_char, 1, _rl_output_character_function);
+           }
+       }
+      else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         tputs (_rl_term_cr, 1, _rl_output_character_function);
+         for (i = 0; i < new; i++)
+           putc (data[i], rl_outstream);
+       }
+      else
        for (i = _rl_last_c_pos; i < new; i++)
-         tputs (term_forward_char, 1, _rl_output_character_function);
+         putc (data[i], rl_outstream);
+
+#else /* !HACK_TERMCAP_MOTION */
+
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         tputs (_rl_term_cr, 1, _rl_output_character_function);
+         for (i = 0; i < new; i++)
+           putc (data[i], rl_outstream);
+       }
       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 */
+
+#endif /* !HACK_TERMCAP_MOTION */
+
     }
+#if defined (HANDLE_MULTIBYTE)
+  /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
+     The byte length of the string is probably bigger than the column width
+     of the string, which means that if NEW == _rl_last_c_pos, then NEW's
+     display point is less than _rl_last_c_pos. */
+  else if (_rl_last_c_pos >= new)
+#else
   else if (_rl_last_c_pos > new)
-    _rl_backspace (_rl_last_c_pos - new);
-  _rl_last_c_pos = new;
+#endif
+    {
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         tputs (_rl_term_cr, 1, _rl_output_character_function);
+         for (i = 0; i < new; i++)
+           putc (data[i], rl_outstream);
+       }
+      else
+       _rl_backspace (_rl_last_c_pos - new);
+    }
+
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    _rl_last_c_pos =  _rl_col_width (data, 0, new);
+  else
+    _rl_last_c_pos = new;
 }
 
 /* PWP: move the cursor up or down. */
@@ -1212,7 +1620,7 @@ _rl_move_vert (to)
 {
   register int delta, i;
 
-  if (_rl_last_v_pos == to || to > screenheight)
+  if (_rl_last_v_pos == to || to > _rl_screenheight)
     return;
 
   if ((delta = to - _rl_last_v_pos) > 0)
@@ -1222,7 +1630,7 @@ _rl_move_vert (to)
 #if defined (__MSDOS__)
       putc ('\r', rl_outstream);
 #else
-      tputs (term_cr, 1, _rl_output_character_function);
+      tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       _rl_last_c_pos = 0;
     }
@@ -1231,14 +1639,14 @@ _rl_move_vert (to)
 #ifdef __MSDOS__
       int row, col;
 
-      i = fflush (rl_outstream); /* make sure the cursor pos is current! */
+      l = fflush (rl_outstream); /* make sure the cursor pos is current! */
       ScreenGetCursor (&row, &col);
       ScreenSetCursor ((row + to - _rl_last_v_pos), col);
       delta = i;
 #else /* !__MSDOS__ */
-      if (term_up && *term_up)
+      if (_rl_term_up && *_rl_term_up)
        for (i = 0; i < -delta; i++)
-         tputs (term_up, 1, _rl_output_character_function);
+         tputs (_rl_term_up, 1, _rl_output_character_function);
 #endif /* !__MSDOS__ */
     }
 
@@ -1298,7 +1706,7 @@ rl_character_len (c, pos)
   if (CTRL_CHAR (c) || c == RUBOUT)
     return (2);
 
-  return ((isprint (uc)) ? 1 : 2);
+  return ((ISPRINT (uc)) ? 1 : 2);
 }
 
 /* How to print things in the "echo-area".  The prompt is treated as a
@@ -1325,7 +1733,12 @@ rl_message (va_alist)
   format = va_arg (args, char *);
 #endif
 
+#if defined (HAVE_VSNPRINTF)
+  vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
+#else
   vsprintf (msg_buf, format, args);
+  msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
+#endif
   va_end (args);
 
   rl_display_prompt = msg_buf;
@@ -1338,6 +1751,7 @@ rl_message (format, arg1, arg2)
      char *format;
 {
   sprintf (msg_buf, format, arg1, arg2);
+  msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
   rl_display_prompt = msg_buf;
   (*rl_redisplay_function) ();
   return 0;
@@ -1373,25 +1787,23 @@ rl_save_prompt ()
 {
   saved_local_prompt = local_prompt;
   saved_local_prefix = local_prompt_prefix;
-  saved_last_invisible = last_invisible;
-  saved_visible_length = visible_length;
+  saved_last_invisible = prompt_last_invisible;
+  saved_visible_length = prompt_visible_length;
 
   local_prompt = local_prompt_prefix = (char *)0;
-  last_invisible = visible_length = 0;
+  prompt_last_invisible = prompt_visible_length = 0;
 }
 
 void
 rl_restore_prompt ()
 {
-  if (local_prompt)
-    free (local_prompt);
-  if (local_prompt_prefix)
-    free (local_prompt_prefix);
+  FREE (local_prompt);
+  FREE (local_prompt_prefix);
 
   local_prompt = saved_local_prompt;
   local_prompt_prefix = saved_local_prefix;
-  last_invisible = saved_last_invisible;
-  visible_length = saved_visible_length;
+  prompt_last_invisible = saved_last_invisible;
+  prompt_visible_length = saved_visible_length;
 }
 
 char *
@@ -1406,7 +1818,7 @@ _rl_make_prompt_for_search (pchar)
   if (saved_local_prompt == 0)
     {
       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
-      pmt = xmalloc (len + 2);
+      pmt = (char *)xmalloc (len + 2);
       if (len)
        strcpy (pmt, rl_prompt);
       pmt[len] = pchar;
@@ -1415,14 +1827,14 @@ _rl_make_prompt_for_search (pchar)
   else
     {
       len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
-      pmt = xmalloc (len + 2);
+      pmt = (char *)xmalloc (len + 2);
       if (len)
        strcpy (pmt, saved_local_prompt);
       pmt[len] = pchar;
       pmt[len+1] = '\0';
       local_prompt = savestring (pmt);
-      last_invisible = saved_last_invisible;
-      visible_length = saved_visible_length + 1;
+      prompt_last_invisible = saved_last_invisible;
+      prompt_visible_length = saved_visible_length + 1;
     }
   return pmt;
 }
@@ -1450,8 +1862,8 @@ _rl_clear_to_eol (count)
      int count;
 {
 #ifndef __MSDOS__
-  if (term_clreol)
-    tputs (term_clreol, 1, _rl_output_character_function);
+  if (_rl_term_clreol)
+    tputs (_rl_term_clreol, 1, _rl_output_character_function);
   else
 #endif
   if (count)
@@ -1479,27 +1891,33 @@ _rl_clear_screen ()
   ScreenClear ();      /* FIXME: only works in text modes */
   ScreenSetCursor (0, 0);  /* term_clrpag is "cl" which homes the cursor */
 #else
-  if (term_clrpag)
-    tputs (term_clrpag, 1, _rl_output_character_function);
+  if (_rl_term_clrpag)
+    tputs (_rl_term_clrpag, 1, _rl_output_character_function);
   else
-    crlf ();
+    rl_crlf ();
 #endif
 }
 
-/* Insert COUNT characters from STRING to the output stream. */
+/* Insert COUNT characters from STRING to the output stream at column COL. */
 static void
-insert_some_chars (string, count)
+insert_some_chars (string, count, col)
      char *string;
-     int count;
+     int count, col;
 {
 #ifdef __MSDOS__
   _rl_output_some_chars (string, count);
 #else  /* !__MSDOS__ */
+  /* DEBUGGING */
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    if (count != col)
+      fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
+
   /* If IC is defined, then we do not have to "enter" insert mode. */
-  if (term_IC)
+  if (_rl_term_IC)
     {
       char *buffer;
-      buffer = tgoto (term_IC, 0, count);
+
+      buffer = tgoto (_rl_term_IC, 0, col);
       tputs (buffer, 1, _rl_output_character_function);
       _rl_output_some_chars (string, count);
     }
@@ -1508,15 +1926,15 @@ insert_some_chars (string, count)
       register int i;
 
       /* If we have to turn on insert-mode, then do so. */
-      if (term_im && *term_im)
-       tputs (term_im, 1, _rl_output_character_function);
+      if (_rl_term_im && *_rl_term_im)
+       tputs (_rl_term_im, 1, _rl_output_character_function);
 
       /* If there is a special command for inserting characters, then
         use that first to open up the space. */
-      if (term_ic && *term_ic)
+      if (_rl_term_ic && *_rl_term_ic)
        {
-         for (i = count; i--; )
-           tputs (term_ic, 1, _rl_output_character_function);
+         for (i = col; i--; )
+           tputs (_rl_term_ic, 1, _rl_output_character_function);
        }
 
       /* Print the text. */
@@ -1524,8 +1942,8 @@ insert_some_chars (string, count)
 
       /* If there is a string to turn off insert mode, we had best use
         it now. */
-      if (term_ei && *term_ei)
-       tputs (term_ei, 1, _rl_output_character_function);
+      if (_rl_term_ei && *_rl_term_ei)
+       tputs (_rl_term_ei, 1, _rl_output_character_function);
     }
 #endif /* !__MSDOS__ */
 }
@@ -1535,21 +1953,21 @@ static void
 delete_chars (count)
      int count;
 {
-  if (count > screenwidth)     /* XXX */
+  if (count > _rl_screenwidth) /* XXX */
     return;
 
 #ifndef __MSDOS__
-  if (term_DC && *term_DC)
+  if (_rl_term_DC && *_rl_term_DC)
     {
       char *buffer;
-      buffer = tgoto (term_DC, count, count);
+      buffer = tgoto (_rl_term_DC, count, count);
       tputs (buffer, count, _rl_output_character_function);
     }
   else
     {
-      if (term_dc && *term_dc)
+      if (_rl_term_dc && *_rl_term_dc)
        while (count--)
-         tputs (term_dc, 1, _rl_output_character_function);
+         tputs (_rl_term_dc, 1, _rl_output_character_function);
     }
 #endif /* !__MSDOS__ */
 }
@@ -1570,20 +1988,17 @@ _rl_update_final ()
     }
   _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) == screenwidth))
+  if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
     {
       char *last_line;
-#if 0
-      last_line = &visible_line[inv_lbreaks[_rl_vis_botlin]];
-#else
+
       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
-#endif
-      _rl_move_cursor_relative (screenwidth - 1, last_line);
+      _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);
       _rl_clear_to_eol (0);
-      putc (last_line[screenwidth - 1], rl_outstream);
+      putc (last_line[_rl_screenwidth - 1], rl_outstream);
     }
   _rl_vis_botlin = 0;
-  crlf ();
+  rl_crlf ();
   fflush (rl_outstream);
   rl_display_fixed++;
 }
@@ -1592,12 +2007,12 @@ _rl_update_final ()
 static void
 cr ()
 {
-  if (term_cr)
+  if (_rl_term_cr)
     {
 #if defined (__MSDOS__)
       putc ('\r', rl_outstream);
 #else
-      tputs (term_cr, 1, _rl_output_character_function);
+      tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       _rl_last_c_pos = 0;
     }
@@ -1611,27 +2026,31 @@ redraw_prompt (t)
      char *t;
 {
   char *oldp, *oldl, *oldlprefix;
-  int oldlen, oldlast, oldplen;
+  int oldlen, oldlast, oldplen, oldninvis;
 
   /* Geez, I should make this a struct. */
   oldp = rl_display_prompt;
   oldl = local_prompt;
   oldlprefix = local_prompt_prefix;
-  oldlen = visible_length;
-  oldplen = prefix_length;
-  oldlast = last_invisible;
+  oldlen = prompt_visible_length;
+  oldplen = prompt_prefix_length;
+  oldlast = prompt_last_invisible;
+  oldninvis = prompt_invis_chars_first_line;
 
   rl_display_prompt = t;
-  local_prompt = expand_prompt (t, &visible_length, &last_invisible);
+  local_prompt = expand_prompt (t, &prompt_visible_length,
+                                  &prompt_last_invisible,
+                                  &prompt_invis_chars_first_line);
   local_prompt_prefix = (char *)NULL;
   rl_forced_update_display ();
 
   rl_display_prompt = oldp;
   local_prompt = oldl;
   local_prompt_prefix = oldlprefix;
-  visible_length = oldlen;
-  prefix_length = oldplen;
-  last_invisible = oldlast;
+  prompt_visible_length = oldlen;
+  prompt_prefix_length = oldplen;
+  prompt_last_invisible = oldlast;
+  prompt_invis_chars_first_line = oldninvis;
 }
       
 /* Redisplay the current line after a SIGWINCH is received. */
@@ -1642,31 +2061,31 @@ _rl_redisplay_after_sigwinch ()
 
   /* Clear the current line and put the cursor at column 0.  Make sure
      the right thing happens if we have wrapped to a new screen line. */
-  if (term_cr)
+  if (_rl_term_cr)
     {
 #if defined (__MSDOS__)
       putc ('\r', rl_outstream);
 #else
-      tputs (term_cr, 1, _rl_output_character_function);
+      tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       _rl_last_c_pos = 0;
 #if defined (__MSDOS__)
-      space_to_eol (screenwidth);
+      space_to_eol (_rl_screenwidth);
       putc ('\r', rl_outstream);
 #else
-      if (term_clreol)
-       tputs (term_clreol, 1, _rl_output_character_function);
+      if (_rl_term_clreol)
+       tputs (_rl_term_clreol, 1, _rl_output_character_function);
       else
        {
-         space_to_eol (screenwidth);
-         tputs (term_cr, 1, _rl_output_character_function);
+         space_to_eol (_rl_screenwidth);
+         tputs (_rl_term_cr, 1, _rl_output_character_function);
        }
 #endif
       if (_rl_last_v_pos > 0)
        _rl_move_vert (0);
     }
   else
-    crlf ();
+    rl_crlf ();
 
   /* Redraw only the last line of a multi-line prompt. */
   t = strrchr (rl_display_prompt, '\n');
@@ -1707,14 +2126,98 @@ _rl_current_display_line ()
   /* Find out whether or not there might be invisible characters in the
      editing buffer. */
   if (rl_display_prompt == rl_prompt)
-    nleft = _rl_last_c_pos - screenwidth - rl_visible_prompt_length;
+    nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
   else
-    nleft = _rl_last_c_pos - screenwidth;
+    nleft = _rl_last_c_pos - _rl_screenwidth;
 
   if (nleft > 0)
-    ret = 1 + nleft / screenwidth;
+    ret = 1 + nleft / _rl_screenwidth;
   else
     ret = 0;
 
   return ret;
 }
+
+#if defined (HANDLE_MULTIBYTE)
+/* Calculate the number of screen columns occupied by STR from START to END.
+   In the case of multibyte characters with stateful encoding, we have to
+   scan from the beginning of the string to take the state into account. */
+static int
+_rl_col_width (str, start, end)
+     char *str;
+     int start, end;
+{
+  wchar_t wc;
+  mbstate_t ps = {0};
+  int tmp, point, width, max;
+
+  if (end <= start)
+    return 0;
+
+  point = 0;
+  max = end;
+
+  while (point < start)
+    {
+      tmp = mbrlen (str + point, max, &ps);
+      if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
+       {
+         /* In this case, the bytes are invalid or too short to compose a
+            multibyte character, so we assume that the first byte represents
+            a single character. */
+         point++;
+         max--;
+
+         /* 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 (tmp == 0)
+        break;         /* Found '\0' */
+      else
+       {
+         point += tmp;
+         max -= tmp;
+       }
+    }
+
+  /* If START is not a byte that starts a character, then POINT will be
+     greater than START.  In this case, assume that (POINT - START) gives
+     a byte count that is the number of columns of difference. */
+  width = point - start;
+
+  while (point < end)
+    {
+      tmp = mbrtowc (&wc, str + point, max, &ps);
+      if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
+       {
+         /* In this case, the bytes are invalid or too short to compose a
+            multibyte character, so we assume that the first byte represents
+            a single character. */
+         point++;
+         max--;
+
+         /* and assume that the byte occupies a single column. */
+         width++;
+
+         /* 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 (tmp == 0)
+        break;                 /* Found '\0' */
+      else
+       {
+         point += tmp;
+         max -= tmp;
+         tmp = wcwidth(wc);
+         width += (tmp >= 0) ? tmp : 1;
+       }
+    }
+
+  width += point - end;
+
+  return width;
+}
+#endif /* HANDLE_MULTIBYTE */
+         
This page took 0.048802 seconds and 4 git commands to generate.