]> git.ipfire.org Git - thirdparty/bash.git/blobdiff - lib/readline/display.c
Imported from ../bash-3.2.48.tar.gz.
[thirdparty/bash.git] / lib / readline / display.c
index 47ff06159747583defb3a320b92a8b4614497856..2a482ef5dbc38eed5687fe36fa33181cd1bdc9f8 100644 (file)
@@ -391,14 +391,14 @@ rl_expand_prompt (prompt)
       t = ++p;
       local_prompt = expand_prompt (p, &prompt_visible_length,
                                       &prompt_last_invisible,
-                                      (int *)NULL,
+                                      &prompt_invis_chars_first_line,
                                       &prompt_physical_chars);
       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, &prompt_prefix_length,
                                                   (int *)NULL,
-                                                  &prompt_invis_chars_first_line,
+                                                  (int *)NULL,
                                                   (int *)NULL);
       *t = c;
       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
@@ -561,6 +561,17 @@ rl_redisplay ()
       wrap_offset = prompt_invis_chars_first_line = 0;
     }
 
+#if defined (HANDLE_MULTIBYTE)
+#define CHECK_INV_LBREAKS() \
+      do { \
+       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)); \
+         } \
+      } while (0)
+#else
 #define CHECK_INV_LBREAKS() \
       do { \
        if (newlines >= (inv_lbsize - 2)) \
@@ -569,6 +580,7 @@ rl_redisplay ()
            inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
          } \
       } while (0)
+#endif /* HANDLE_MULTIBYTE */
 
 #if defined (HANDLE_MULTIBYTE)   
 #define CHECK_LPOS() \
@@ -898,6 +910,10 @@ rl_redisplay ()
             second and subsequent lines start at inv_lbreaks[N], offset by
             OFFSET (which has already been calculated above).  */
 
+#define INVIS_FIRST()  (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
+#define WRAP_OFFSET(line, offset)  ((line == 0) \
+                                       ? (offset ? INVIS_FIRST() : 0) \
+                                       : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
 #define VIS_LLEN(l)    ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
 #define INV_LLEN(l)    (inv_lbreaks[l+1] - inv_lbreaks[l])
@@ -932,7 +948,13 @@ rl_redisplay ()
                  _rl_last_c_pos != o_cpos &&
                  _rl_last_c_pos > wrap_offset &&
                  o_cpos < prompt_last_invisible)
-               _rl_last_c_pos -= wrap_offset;
+               _rl_last_c_pos -= prompt_invis_chars_first_line;        /* XXX - was wrap_offset */
+             else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth &&
+                       (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
+                       cpos_adjusted == 0 &&
+                       _rl_last_c_pos != o_cpos &&
+                       _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
+               _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
                  
              /* If this is the line with the prompt, we might need to
                 compensate for invisible characters in the new line. Do
@@ -1036,7 +1058,7 @@ rl_redisplay ()
                tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset;
              else
                tx = nleft;
-             if (_rl_last_c_pos > tx)
+             if (tx >= 0 && _rl_last_c_pos > tx)
                {
                  _rl_backspace (_rl_last_c_pos - tx);  /* XXX */
                  _rl_last_c_pos = tx;
@@ -1192,7 +1214,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
      int current_line, omax, nmax, inv_botlin;
 {
   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
-  int temp, lendiff, wsatend, od, nd;
+  int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
   int current_invis_chars;
   int col_lendiff, col_temp;
 #if defined (HANDLE_MULTIBYTE)
@@ -1208,7 +1230,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
     temp = _rl_last_c_pos;
   else
-    temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
+    temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
   if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
        && _rl_last_v_pos == current_line - 1)
     {
@@ -1453,6 +1475,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
        _rl_last_c_pos = lendiff;
     }
 
+  o_cpos = _rl_last_c_pos;
+
   /* When this function returns, _rl_last_c_pos is correct, and an absolute
      cursor postion in multibyte mode, but a buffer index when not in a
      multibyte locale. */
@@ -1462,7 +1486,9 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
   /* We need to indicate that the cursor position is correct in the presence of
      invisible characters in the prompt string.  Let's see if setting this when
      we make sure we're at the end of the drawn prompt string works. */
-  if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_last_c_pos == prompt_physical_chars)
+  if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && 
+      (_rl_last_c_pos > 0 || o_cpos > 0) &&
+      _rl_last_c_pos == prompt_physical_chars)
     cpos_adjusted = 1;
 #endif
 #endif
@@ -1506,11 +1532,31 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
     {
       /* Non-zero if we're increasing the number of lines. */
       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
+      /* If col_lendiff is > 0, implying that the new string takes up more
+        screen real estate than the old, but lendiff is < 0, meaning that it
+        takes fewer bytes, we need to just output the characters starting
+        from the first difference.  These will overwrite what is on the
+        display, so there's no reason to do a smart update.  This can really
+        only happen in a multibyte environment. */
+      if (lendiff < 0)
+       {
+         _rl_output_some_chars (nfd, temp);
+         _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
+         /* If nfd begins before any invisible characters in the prompt,
+            adjust _rl_last_c_pos to account for wrap_offset and set
+            cpos_adjusted to let the caller know. */
+         if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+           {
+             _rl_last_c_pos -= wrap_offset;
+             cpos_adjusted = 1;
+           }
+         return;
+       }
       /* 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 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
+      else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _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
@@ -1533,11 +1579,16 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
            }
          else
            {
-             /* We have horizontal scrolling and we are not inserting at
-                the end.  We have invisible characters in this line.  This
-                is a dumb update. */
              _rl_output_some_chars (nfd, temp);
              _rl_last_c_pos += col_temp;
+             /* If nfd begins before any invisible characters in the prompt,
+                adjust _rl_last_c_pos to account for wrap_offset and set
+                cpos_adjusted to let the caller know. */
+             if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+               {
+                 _rl_last_c_pos -= wrap_offset;
+                 cpos_adjusted = 1;
+               }
              return;
            }
          /* Copy (new) chars to screen from first diff to last match. */
@@ -1545,15 +1596,15 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
          if ((temp - lendiff) > 0)
            {
              _rl_output_some_chars (nfd + lendiff, temp - lendiff);
-#if 1
             /* XXX -- this bears closer inspection.  Fixes a redisplay bug
                reported against bash-3.0-alpha by Andreas Schwab involving
                multibyte characters and prompt strings with invisible
                characters, but was previously disabled. */
-             _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
-#else
-             _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
-#endif
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               twidth = _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
+             else
+               twidth = temp - lendiff;
+             _rl_last_c_pos += twidth;
            }
        }
       else
@@ -1586,8 +1637,22 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
          temp = nls - nfd;
          if (temp > 0)
            {
+             /* If nfd begins at the prompt, or before the invisible
+                characters in the prompt, we need to adjust _rl_last_c_pos
+                in a multibyte locale to account for the wrap offset and
+                set cpos_adjusted accordingly. */
              _rl_output_some_chars (nfd, temp);
-             _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               {
+                  _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
+                  if (current_line == 0 && wrap_offset &&  ((nfd - new) <= prompt_last_invisible))
+                   {
+                     _rl_last_c_pos -= wrap_offset;
+                     cpos_adjusted = 1;
+                   }
+               }
+              else
+                _rl_last_c_pos += temp;
            }
        }
       /* Otherwise, print over the existing material. */
@@ -1595,8 +1660,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
        {
          if (temp > 0)
            {
+             /* If nfd begins at the prompt, or before the invisible
+                characters in the prompt, we need to adjust _rl_last_c_pos
+                in a multibyte locale to account for the wrap offset and
+                set cpos_adjusted accordingly. */
              _rl_output_some_chars (nfd, temp);
              _rl_last_c_pos += col_temp;               /* XXX */
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               {
+                 if (current_line == 0 && wrap_offset &&  ((nfd - new) <= prompt_last_invisible))
+                   {
+                     _rl_last_c_pos -= wrap_offset;
+                     cpos_adjusted = 1;
+                   }
+               }
            }
          lendiff = (oe - old) - (ne - new);
          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -1721,7 +1798,7 @@ _rl_move_cursor_relative (new, data)
   int woff;                    /* number of invisible chars on current line */
   int cpos, dpos;              /* current and desired cursor positions */
 
-  woff = W_OFFSET (_rl_last_v_pos, wrap_offset);
+  woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
   cpos = _rl_last_c_pos;
 #if defined (HANDLE_MULTIBYTE)
   /* If we have multibyte characters, NEW is indexed by the buffer point in
@@ -1732,7 +1809,14 @@ _rl_move_cursor_relative (new, data)
   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
     {
       dpos = _rl_col_width (data, 0, new);
-      if (dpos > prompt_last_invisible)                /* XXX - don't use woff here */
+      /* Use NEW when comparing against the last invisible character in the
+        prompt string, since they're both buffer indices and DPOS is a
+        desired display position. */
+      if ((new > prompt_last_invisible) ||             /* XXX - don't use woff here */
+         (prompt_physical_chars > _rl_screenwidth &&
+          _rl_last_v_pos == prompt_last_screen_line &&
+          wrap_offset != woff &&
+          new > (prompt_last_invisible-_rl_screenwidth-wrap_offset)))
        {
          dpos -= woff;
          /* Since this will be assigned to _rl_last_c_pos at the end (more
@@ -2380,6 +2464,8 @@ _rl_col_width (str, start, end)
 
   if (end <= start)
     return 0;
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (end - start);
 
   memset (&ps, 0, sizeof (mbstate_t));