Patch 9.0.0153
Problem:    No fold and sign column for virtual text with "below" align and
            'nowrap'.
Solution:   Go back to draw state WL_START when moving to the next line.
            (closes #10851)
Files:      src/drawline.c, src/testdir/test_textprop.vim,
            src/testdir/dumps/Test_prop_with_text_after_nowrap_2.dump


*** ../vim-9.0.0152/src/drawline.c      2022-08-06 14:21:48.902455645 +0100
--- src/drawline.c      2022-08-06 15:56:52.327000213 +0100
***************
*** 75,80 ****
--- 75,163 ----
  }
  #endif
  
+ // structure with variables passed between win_line() and other functions
+ typedef struct {
+     int               draw_state;     // what to draw next
+ 
+     linenr_T  lnum;           // line number to be drawn
+ 
+     int               startrow;       // first row in the window to be drawn
+     int               row;            // row in the window, excl w_winrow
+     int               screen_row;     // row on the screen, incl w_winrow
+ 
+     long      vcol;           // virtual column, before wrapping
+     int               col;            // visual column on screen, after 
wrapping
+ #ifdef FEAT_CONCEAL
+     int               boguscols;      // nonexistent columns added to "col" 
to force
+                               // wrapping
+     int               vcol_off;       // offset for concealed characters
+ #endif
+ #ifdef FEAT_SYN_HL
+     int               draw_color_col; // highlight colorcolumn
+     int               *color_cols;    // pointer to according columns array
+ #endif
+     int               eol_hl_off;     // 1 if highlighted char after EOL
+ 
+     unsigned  off;            // offset in ScreenLines/ScreenAttrs
+ 
+     int               win_attr;       // background for the whole window, 
except
+                               // margins and "~" lines.
+ 
+     int               screen_line_flags;  // flags for screen_line()
+ 
+     // TRUE when 'cursorlineopt' has "screenline" and cursor is in this line
+     int               cul_screenline;
+ 
+     int               char_attr;      // attributes for the next character
+ 
+     int               n_extra;        // number of extra bytes
+     char_u    *p_extra;       // string of extra chars, plus NUL, only used
+                               // when c_extra and c_final are NUL
+     int               c_extra;        // extra chars, all the same
+     int               c_final;        // final char, mandatory if set
+ 
+     // saved "extra" items for when draw_state becomes WL_LINE (again)
+     int               saved_n_extra;
+     char_u    *saved_p_extra;
+     int               saved_c_extra;
+     int               saved_c_final;
+     int               saved_char_attr;
+ 
+ #ifdef FEAT_DIFF
+     hlf_T     diff_hlf;       // type of diff highlighting
+ #endif
+ } winlinevars_T;
+ 
+ // draw_state values for items that are drawn in sequence:
+ #define WL_START      0               // nothing done yet, must be zero
+ #ifdef FEAT_CMDWIN
+ # define WL_CMDLINE   (WL_START + 1)  // cmdline window column
+ #else
+ # define WL_CMDLINE   WL_START
+ #endif
+ #ifdef FEAT_FOLDING
+ # define WL_FOLD      (WL_CMDLINE + 1)        // 'foldcolumn'
+ #else
+ # define WL_FOLD      WL_CMDLINE
+ #endif
+ #ifdef FEAT_SIGNS
+ # define WL_SIGN      (WL_FOLD + 1)   // column for signs
+ #else
+ # define WL_SIGN      WL_FOLD         // column for signs
+ #endif
+ #define WL_NR         (WL_SIGN + 1)   // line number
+ #ifdef FEAT_LINEBREAK
+ # define WL_BRI               (WL_NR + 1)     // 'breakindent'
+ #else
+ # define WL_BRI               WL_NR
+ #endif
+ #if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF)
+ # define WL_SBR               (WL_BRI + 1)    // 'showbreak' or 'diff'
+ #else
+ # define WL_SBR               WL_BRI
+ #endif
+ #define WL_LINE               (WL_SBR + 1)    // text in the line
+ 
  #ifdef FEAT_SIGNS
  /*
   * Return TRUE if CursorLineSign highlight is to be used.
***************
*** 97,114 ****
        int             nrcol,
        win_T           *wp,
        linenr_T        lnum,
        sign_attrs_T    *sattr,
        int             wcr_attr,
-       int             row,
-       int             startrow,
        int             filler_lines UNUSED,
        int             filler_todo UNUSED,
!       int             *c_extrap,
!       int             *c_finalp,
!       char_u          *extra,
!       char_u          **pp_extra,
!       int             *n_extrap,
!       int             *char_attrp)
  {
      int       text_sign;
  # ifdef FEAT_SIGN_ICONS
--- 180,191 ----
        int             nrcol,
        win_T           *wp,
        linenr_T        lnum,
+       winlinevars_T   *wlv,
        sign_attrs_T    *sattr,
        int             wcr_attr,
        int             filler_lines UNUSED,
        int             filler_todo UNUSED,
!       char_u          *extra)
  {
      int       text_sign;
  # ifdef FEAT_SIGN_ICONS
***************
*** 116,135 ****
  # endif
  
      // Draw two cells with the sign value or blank.
!     *c_extrap = ' ';
!     *c_finalp = NUL;
      if (nrcol)
!       *n_extrap = number_width(wp) + 1;
      else
      {
        if (use_cursor_line_sign(wp, lnum))
!           *char_attrp = hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLS));
        else
!           *char_attrp = hl_combine_attr(wcr_attr, HL_ATTR(HLF_SC));
!       *n_extrap = 2;
      }
  
!     if (row == startrow
  #ifdef FEAT_DIFF
            + filler_lines && filler_todo <= 0
  #endif
--- 193,212 ----
  # endif
  
      // Draw two cells with the sign value or blank.
!     wlv->c_extra = ' ';
!     wlv->c_final = NUL;
      if (nrcol)
!       wlv->n_extra = number_width(wp) + 1;
      else
      {
        if (use_cursor_line_sign(wp, lnum))
!           wlv->char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLS));
        else
!           wlv->char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_SC));
!       wlv->n_extra = 2;
      }
  
!     if (wlv->row == wlv->startrow
  #ifdef FEAT_DIFF
            + filler_lines && filler_todo <= 0
  #endif
***************
*** 143,179 ****
            // Use the image in this position.
            if (nrcol)
            {
!               *c_extrap = NUL;
                sprintf((char *)extra, "%-*c ", number_width(wp), SIGN_BYTE);
!               *pp_extra = extra;
!               *n_extrap = (int)STRLEN(*pp_extra);
            }
            else
!               *c_extrap = SIGN_BYTE;
  #  ifdef FEAT_NETBEANS_INTG
            if (netbeans_active() && (buf_signcount(wp->w_buffer, lnum) > 1))
            {
                if (nrcol)
                {
!                   *c_extrap = NUL;
                    sprintf((char *)extra, "%-*c ", number_width(wp),
                                                        MULTISIGN_BYTE);
!                   *pp_extra = extra;
!                   *n_extrap = (int)STRLEN(*pp_extra);
                }
                else
!                   *c_extrap = MULTISIGN_BYTE;
            }
  #  endif
!           *c_finalp = NUL;
!           *char_attrp = icon_sign;
        }
        else
  # endif
            if (text_sign != 0)
            {
!               *pp_extra = sattr->sat_text;
!               if (*pp_extra != NULL)
                {
                    if (nrcol)
                    {
--- 220,256 ----
            // Use the image in this position.
            if (nrcol)
            {
!               wlv->c_extra = NUL;
                sprintf((char *)extra, "%-*c ", number_width(wp), SIGN_BYTE);
!               wlv->p_extra = extra;
!               wlv->n_extra = (int)STRLEN(wlv->p_extra);
            }
            else
!               wlv->c_extra = SIGN_BYTE;
  #  ifdef FEAT_NETBEANS_INTG
            if (netbeans_active() && (buf_signcount(wp->w_buffer, lnum) > 1))
            {
                if (nrcol)
                {
!                   wlv->c_extra = NUL;
                    sprintf((char *)extra, "%-*c ", number_width(wp),
                                                        MULTISIGN_BYTE);
!                   wlv->p_extra = extra;
!                   wlv->n_extra = (int)STRLEN(wlv->p_extra);
                }
                else
!                   wlv->c_extra = MULTISIGN_BYTE;
            }
  #  endif
!           wlv->c_final = NUL;
!           wlv->char_attr = icon_sign;
        }
        else
  # endif
            if (text_sign != 0)
            {
!               wlv->p_extra = sattr->sat_text;
!               if (wlv->p_extra != NULL)
                {
                    if (nrcol)
                    {
***************
*** 182,200 ****
                        for (n = 0; n < width; n++)
                            extra[n] = ' ';
                        extra[n] = 0;
!                       STRCAT(extra, *pp_extra);
                        STRCAT(extra, " ");
!                       *pp_extra = extra;
                    }
!                   *c_extrap = NUL;
!                   *c_finalp = NUL;
!                   *n_extrap = (int)STRLEN(*pp_extra);
                }
  
                if (use_cursor_line_sign(wp, lnum) && sattr->sat_culhl > 0)
!                   *char_attrp = sattr->sat_culhl;
                else
!                   *char_attrp = sattr->sat_texthl;
            }
      }
  }
--- 259,277 ----
                        for (n = 0; n < width; n++)
                            extra[n] = ' ';
                        extra[n] = 0;
!                       STRCAT(extra, wlv->p_extra);
                        STRCAT(extra, " ");
!                       wlv->p_extra = extra;
                    }
!                   wlv->c_extra = NUL;
!                   wlv->c_final = NUL;
!                   wlv->n_extra = (int)STRLEN(wlv->p_extra);
                }
  
                if (use_cursor_line_sign(wp, lnum) && sattr->sat_culhl > 0)
!                   wlv->char_attr = sattr->sat_culhl;
                else
!                   wlv->char_attr = sattr->sat_texthl;
            }
      }
  }
***************
*** 249,282 ****
  }
  #endif
  
- // structure with variables passed between win_line() and other functions
- typedef struct {
-     linenr_T  lnum;           // line number to be drawn
- 
-     int               startrow;       // first row in the window to be drawn
-     int               row;            // row in the window, excl w_winrow
-     int               screen_row;     // row on the screen, incl w_winrow
- 
-     long      vcol;           // virtual column, before wrapping
-     int               col;            // visual column on screen, after 
wrapping
- #ifdef FEAT_CONCEAL
-     int               boguscols;      // nonexistent columns added to "col" 
to force
-                               // wrapping
-     int               vcol_off;       // offset for concealed characters
- #endif
- #ifdef FEAT_SYN_HL
-     int               draw_color_col; // highlight colorcolumn
-     int               *color_cols;    // pointer to according columns array
- #endif
-     int               eol_hl_off;     // 1 if highlighted char after EOL
- 
-     unsigned  off;            // offset in ScreenLines/ScreenAttrs
- 
-     int               win_attr;       // background for the whole window, 
except
-                               // margins and "~" lines.
-     int               screen_line_flags;
- } winlinevars_T;
- 
  /*
   * Called when finished with the line: draw the screen line and handle any
   * highlighting until the right of the window.
--- 326,331 ----
***************
*** 367,375 ****
  
  /*
   * Start a screen line at column zero.
   */
      static void
! win_line_start(win_T *wp UNUSED, winlinevars_T *wlv)
  {
      wlv->col = 0;
      wlv->off = (unsigned)(current_ScreenLine - ScreenLines);
--- 416,425 ----
  
  /*
   * Start a screen line at column zero.
+  * When "save_extra" is TRUE save and reset n_extra, p_extra, etc.
   */
      static void
! win_line_start(win_T *wp UNUSED, winlinevars_T *wlv, int save_extra)
  {
      wlv->col = 0;
      wlv->off = (unsigned)(current_ScreenLine - ScreenLines);
***************
*** 385,390 ****
--- 435,460 ----
        wlv->screen_line_flags |= SLF_RIGHTLEFT;
      }
  #endif
+     if (save_extra)
+     {
+       // reset the drawing state for the start of a wrapped line
+       wlv->draw_state = WL_START;
+       wlv->saved_n_extra = wlv->n_extra;
+       wlv->saved_p_extra = wlv->p_extra;
+       wlv->saved_c_extra = wlv->c_extra;
+       wlv->saved_c_final = wlv->c_final;
+ #ifdef FEAT_SYN_HL
+       if (!(wlv->cul_screenline
+ # ifdef FEAT_DIFF
+                   && wlv->diff_hlf == (hlf_T)0
+ # endif
+            ))
+           wlv->saved_char_attr = wlv->char_attr;
+       else
+ #endif
+           wlv->saved_char_attr = 0;
+       wlv->n_extra = 0;
+     }
  }
  
  /*
***************
*** 414,424 ****
      char_u    *ptr;                   // current position in "line"
  
      char_u    extra[21];              // "%ld " and 'fdc' must fit in here
-     int               n_extra = 0;            // number of extra bytes
-     char_u    *p_extra = NULL;        // string of extra chars, plus NUL
      char_u    *p_extra_free = NULL;   // p_extra needs to be freed
!     int               c_extra = NUL;          // extra chars, all the same
!     int               c_final = NUL;          // final char, mandatory if set
      int               extra_attr = 0;         // attributes when n_extra != 0
  #if defined(FEAT_LINEBREAK) && defined(FEAT_PROP_POPUP)
      int               in_linebreak = FALSE;   // n_extra set for showing 
linebreak
--- 484,493 ----
      char_u    *ptr;                   // current position in "line"
  
      char_u    extra[21];              // "%ld " and 'fdc' must fit in here
      char_u    *p_extra_free = NULL;   // p_extra needs to be freed
! #ifdef FEAT_PROP_POPUP
!     char_u    *p_extra_free2 = NULL;   // another p_extra to be freed
! #endif
      int               extra_attr = 0;         // attributes when n_extra != 0
  #if defined(FEAT_LINEBREAK) && defined(FEAT_PROP_POPUP)
      int               in_linebreak = FALSE;   // n_extra set for showing 
linebreak
***************
*** 429,441 ****
      int               lcs_prec_todo = wp->w_lcs_chars.prec;
                                        // prec until it's been used
  
-     // saved "extra" items for when draw_state becomes WL_LINE (again)
-     int               saved_n_extra = 0;
-     char_u    *saved_p_extra = NULL;
-     int               saved_c_extra = 0;
-     int               saved_c_final = 0;
-     int               saved_char_attr = 0;
- 
      int               n_attr = 0;         // chars with special attr
      int               n_attr_skip = 0;    // chars to skip before using 
extra_attr
      int               saved_attr2 = 0;    // char_attr saved for n_attr
--- 498,503 ----
***************
*** 452,458 ****
      pos_T     pos;
      long      v;
  
-     int               char_attr = 0;          // attributes for next character
      int               attr_pri = FALSE;       // char_attr has priority
      int               area_highlighting = FALSE; // Visual or incsearch 
highlighting
                                           // in this line
--- 514,519 ----
***************
*** 511,517 ****
  # define filler_lines 0
  #endif
  #ifdef FEAT_DIFF
-     hlf_T     diff_hlf = (hlf_T)0;    // type of diff highlighting
      int               change_start = MAXCOL;  // first col of changed area
      int               change_end = -1;        // last col of changed area
  #endif
--- 572,577 ----
***************
*** 548,592 ****
  #ifdef FEAT_SYN_HL
      int               cul_attr = 0;           // set when 'cursorline' active
  
-     // 'cursorlineopt' has "screenline" and cursor is in this line
-     int               cul_screenline = FALSE;
- 
      // margin columns for the screen line, needed for when 'cursorlineopt'
      // contains "screenline"
      int               left_curline_col = 0;
      int               right_curline_col = 0;
  #endif
  
-     // draw_state: items that are drawn in sequence:
- #define WL_START      0               // nothing done yet
- #ifdef FEAT_CMDWIN
- # define WL_CMDLINE   (WL_START + 1)  // cmdline window column
- #else
- # define WL_CMDLINE   WL_START
- #endif
- #ifdef FEAT_FOLDING
- # define WL_FOLD      (WL_CMDLINE + 1)        // 'foldcolumn'
- #else
- # define WL_FOLD      WL_CMDLINE
- #endif
- #ifdef FEAT_SIGNS
- # define WL_SIGN      (WL_FOLD + 1)   // column for signs
- #else
- # define WL_SIGN      WL_FOLD         // column for signs
- #endif
- #define WL_NR         (WL_SIGN + 1)   // line number
- #ifdef FEAT_LINEBREAK
- # define WL_BRI               (WL_NR + 1)     // 'breakindent'
- #else
- # define WL_BRI               WL_NR
- #endif
- #if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF)
- # define WL_SBR               (WL_BRI + 1)    // 'showbreak' or 'diff'
- #else
- # define WL_SBR               WL_BRI
- #endif
- #define WL_LINE               (WL_SBR + 1)    // text in the line
-     int               draw_state = WL_START;  // what to draw next
  #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
      int               feedback_col = 0;
      int               feedback_old_attr = -1;
--- 608,619 ----
***************
*** 607,613 ****
  # define VCOL_HLC (wlv.vcol - wlv.vcol_off)
  # define FIX_FOR_BOGUSCOLS \
      { \
!       n_extra += wlv.vcol_off; \
        wlv.vcol -= wlv.vcol_off; \
        wlv.vcol_off = 0; \
        wlv.col -= wlv.boguscols; \
--- 634,640 ----
  # define VCOL_HLC (wlv.vcol - wlv.vcol_off)
  # define FIX_FOR_BOGUSCOLS \
      { \
!       wlv.n_extra += wlv.vcol_off; \
        wlv.vcol -= wlv.vcol_off; \
        wlv.vcol_off = 0; \
        wlv.col -= wlv.boguscols; \
***************
*** 838,851 ****
        if (filler_lines == -1)
        {
            if (diff_find_change(wp, lnum, &change_start, &change_end))
!               diff_hlf = HLF_ADD;     // added line
            else if (change_start == 0)
!               diff_hlf = HLF_TXD;     // changed text
            else
!               diff_hlf = HLF_CHD;     // changed line
        }
        else
!           diff_hlf = HLF_ADD;         // added line
        filler_lines = 0;
        area_highlighting = TRUE;
      }
--- 865,878 ----
        if (filler_lines == -1)
        {
            if (diff_find_change(wp, lnum, &change_start, &change_end))
!               wlv.diff_hlf = HLF_ADD; // added line
            else if (change_start == 0)
!               wlv.diff_hlf = HLF_TXD; // changed text
            else
!               wlv.diff_hlf = HLF_CHD; // changed line
        }
        else
!           wlv.diff_hlf = HLF_ADD;             // added line
        filler_lines = 0;
        area_highlighting = TRUE;
      }
***************
*** 1111,1122 ****
        if (!(wp == curwin && VIsual_active)
                                         && wp->w_p_culopt_flags != CULOPT_NBR)
        {
!           cul_screenline = (wp->w_p_wrap
                                   && (wp->w_p_culopt_flags & CULOPT_SCRLINE));
  
            // Only set line_attr here when "screenline" is not present in
            // 'cursorlineopt'.  Otherwise it's done later.
!           if (!cul_screenline)
            {
                cul_attr = HL_ATTR(HLF_CUL);
  # ifdef FEAT_SIGNS
--- 1138,1149 ----
        if (!(wp == curwin && VIsual_active)
                                         && wp->w_p_culopt_flags != CULOPT_NBR)
        {
!           wlv.cul_screenline = (wp->w_p_wrap
                                   && (wp->w_p_culopt_flags & CULOPT_SCRLINE));
  
            // Only set line_attr here when "screenline" is not present in
            // 'cursorlineopt'.  Otherwise it's done later.
!           if (!wlv.cul_screenline)
            {
                cul_attr = HL_ATTR(HLF_CUL);
  # ifdef FEAT_SIGNS
***************
*** 1170,1176 ****
      }
  #endif
  
!     win_line_start(wp, &wlv);
  
      // Repeat for the whole displayed line.
      for (;;)
--- 1197,1203 ----
      }
  #endif
  
!     win_line_start(wp, &wlv, FALSE);
  
      // Repeat for the whole displayed line.
      for (;;)
***************
*** 1184,1193 ****
  #endif
  
        // Skip this quickly when working on the text.
!       if (draw_state != WL_LINE)
        {
  #ifdef FEAT_SYN_HL
!           if (cul_screenline)
            {
                cul_attr = 0;
                line_attr = line_attr_save;
--- 1211,1220 ----
  #endif
  
        // Skip this quickly when working on the text.
!       if (wlv.draw_state != WL_LINE)
        {
  #ifdef FEAT_SYN_HL
!           if (wlv.cul_screenline)
            {
                cul_attr = 0;
                line_attr = line_attr_save;
***************
*** 1195,1220 ****
  #endif
  
  #ifdef FEAT_CMDWIN
!           if (draw_state == WL_CMDLINE - 1 && n_extra == 0)
            {
!               draw_state = WL_CMDLINE;
                if (cmdwin_type != 0 && wp == curwin)
                {
                    // Draw the cmdline character.
!                   n_extra = 1;
!                   c_extra = cmdwin_type;
!                   c_final = NUL;
!                   char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_AT));
                }
            }
  #endif
  
  #ifdef FEAT_FOLDING
!           if (draw_state == WL_FOLD - 1 && n_extra == 0)
            {
                int fdc = compute_foldcolumn(wp, 0);
  
!               draw_state = WL_FOLD;
                if (fdc > 0)
                {
                    // Draw the 'foldcolumn'.  Allocate a buffer, "extra" may
--- 1222,1247 ----
  #endif
  
  #ifdef FEAT_CMDWIN
!           if (wlv.draw_state == WL_CMDLINE - 1 && wlv.n_extra == 0)
            {
!               wlv.draw_state = WL_CMDLINE;
                if (cmdwin_type != 0 && wp == curwin)
                {
                    // Draw the cmdline character.
!                   wlv.n_extra = 1;
!                   wlv.c_extra = cmdwin_type;
!                   wlv.c_final = NUL;
!                   wlv.char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_AT));
                }
            }
  #endif
  
  #ifdef FEAT_FOLDING
!           if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0)
            {
                int fdc = compute_foldcolumn(wp, 0);
  
!               wlv.draw_state = WL_FOLD;
                if (fdc > 0)
                {
                    // Draw the 'foldcolumn'.  Allocate a buffer, "extra" may
***************
*** 1223,1239 ****
                    p_extra_free = alloc(MAX_MCO * fdc + 1);
                    if (p_extra_free != NULL)
                    {
!                       n_extra = (int)fill_foldcolumn(p_extra_free, wp,
                                                                  FALSE, lnum);
!                       p_extra_free[n_extra] = NUL;
!                       p_extra = p_extra_free;
!                       c_extra = NUL;
!                       c_final = NUL;
                        if (use_cursor_line_sign(wp, lnum))
!                           char_attr =
                                   hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLF));
                        else
!                           char_attr =
                                    hl_combine_attr(wcr_attr, HL_ATTR(HLF_FC));
                    }
                }
--- 1250,1266 ----
                    p_extra_free = alloc(MAX_MCO * fdc + 1);
                    if (p_extra_free != NULL)
                    {
!                       wlv.n_extra = (int)fill_foldcolumn(p_extra_free, wp,
                                                                  FALSE, lnum);
!                       p_extra_free[wlv.n_extra] = NUL;
!                       wlv.p_extra = p_extra_free;
!                       wlv.c_extra = NUL;
!                       wlv.c_final = NUL;
                        if (use_cursor_line_sign(wp, lnum))
!                           wlv.char_attr =
                                   hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLF));
                        else
!                           wlv.char_attr =
                                    hl_combine_attr(wcr_attr, HL_ATTR(HLF_FC));
                    }
                }
***************
*** 1241,1262 ****
  #endif
  
  #ifdef FEAT_SIGNS
!           if (draw_state == WL_SIGN - 1 && n_extra == 0)
            {
!               draw_state = WL_SIGN;
                // Show the sign column when there are any signs in this
                // buffer or when using Netbeans.
                if (signcolumn_on(wp))
!                   get_sign_display_info(FALSE, wp, lnum, &sattr, wcr_attr,
!                           wlv.row, startrow, filler_lines, filler_todo,
!                           &c_extra, &c_final, extra, &p_extra, &n_extra,
!                           &char_attr);
            }
  #endif
  
!           if (draw_state == WL_NR - 1 && n_extra == 0)
            {
!               draw_state = WL_NR;
                // Display the absolute or relative line number. After the
                // first fill with blanks when the 'n' flag isn't in 'cpo'
                if ((wp->w_p_nu || wp->w_p_rnu)
--- 1268,1287 ----
  #endif
  
  #ifdef FEAT_SIGNS
!           if (wlv.draw_state == WL_SIGN - 1 && wlv.n_extra == 0)
            {
!               wlv.draw_state = WL_SIGN;
                // Show the sign column when there are any signs in this
                // buffer or when using Netbeans.
                if (signcolumn_on(wp))
!                   get_sign_display_info(FALSE, wp, lnum, &wlv, &sattr,
!                                  wcr_attr, filler_lines, filler_todo, extra);
            }
  #endif
  
!           if (wlv.draw_state == WL_NR - 1 && wlv.n_extra == 0)
            {
!               wlv.draw_state = WL_NR;
                // Display the absolute or relative line number. After the
                // first fill with blanks when the 'n' flag isn't in 'cpo'
                if ((wp->w_p_nu || wp->w_p_rnu)
***************
*** 1269,1278 ****
                    // number.
                    if ((*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')
                            && sign_present)
!                       get_sign_display_info(TRUE, wp, lnum, &sattr, wcr_attr,
!                               wlv.row, startrow, filler_lines, filler_todo,
!                               &c_extra, &c_final, extra, &p_extra, &n_extra,
!                               &char_attr);
                    else
  #endif
                    {
--- 1294,1301 ----
                    // number.
                    if ((*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')
                            && sign_present)
!                       get_sign_display_info(TRUE, wp, lnum, &wlv, &sattr,
!                                  wcr_attr, filler_lines, filler_todo, extra);
                    else
  #endif
                    {
***************
*** 1300,1307 ****
                        sprintf((char *)extra, fmt,
                                                number_width(wp), num);
                        if (wp->w_skipcol > 0)
!                           for (p_extra = extra; *p_extra == ' '; ++p_extra)
!                               *p_extra = '-';
  #ifdef FEAT_RIGHTLEFT
                        if (wp->w_p_rl)             // reverse line numbers
                        {
--- 1323,1331 ----
                        sprintf((char *)extra, fmt,
                                                number_width(wp), num);
                        if (wp->w_skipcol > 0)
!                           for (wlv.p_extra = extra; *wlv.p_extra == ' ';
!                                                                ++wlv.p_extra)
!                               *wlv.p_extra = '-';
  #ifdef FEAT_RIGHTLEFT
                        if (wp->w_p_rl)             // reverse line numbers
                        {
***************
*** 1319,1335 ****
                            }
                        }
  #endif
!                       p_extra = extra;
!                       c_extra = NUL;
!                       c_final = NUL;
                      }
                      else
                      {
!                       c_extra = ' ';
!                       c_final = NUL;
                      }
!                     n_extra = number_width(wp) + 1;
!                     char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_N));
  #ifdef FEAT_SYN_HL
                      // When 'cursorline' is set highlight the line number of
                      // the current line differently.
--- 1343,1359 ----
                            }
                        }
  #endif
!                       wlv.p_extra = extra;
!                       wlv.c_extra = NUL;
!                       wlv.c_final = NUL;
                      }
                      else
                      {
!                       wlv.c_extra = ' ';
!                       wlv.c_final = NUL;
                      }
!                     wlv.n_extra = number_width(wp) + 1;
!                     wlv.char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_N));
  #ifdef FEAT_SYN_HL
                      // When 'cursorline' is set highlight the line number of
                      // the current line differently.
***************
*** 1343,1381 ****
                              && (wlv.row == startrow + filler_lines
                                  || (wlv.row > startrow + filler_lines
                                     && (wp->w_p_culopt_flags & CULOPT_LINE))))
!                       char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLN));
  #endif
                      if (wp->w_p_rnu && lnum < wp->w_cursor.lnum
                                                      && HL_ATTR(HLF_LNA) != 0)
                          // Use LineNrAbove
!                         char_attr = hl_combine_attr(wcr_attr,
                                                             HL_ATTR(HLF_LNA));
                      if (wp->w_p_rnu && lnum > wp->w_cursor.lnum
                                                      && HL_ATTR(HLF_LNB) != 0)
                          // Use LineNrBelow
!                         char_attr = hl_combine_attr(wcr_attr,
                                                             HL_ATTR(HLF_LNB));
                    }
  #ifdef FEAT_SIGNS
                    if (num_attr)
!                       char_attr = num_attr;
  #endif
                }
            }
  
  #ifdef FEAT_LINEBREAK
!           if (wp->w_briopt_sbr && draw_state == WL_BRI - 1
!                           && n_extra == 0 && *get_showbreak_value(wp) != NUL)
                // draw indent after showbreak value
!               draw_state = WL_BRI;
!           else if (wp->w_briopt_sbr && draw_state == WL_SBR && n_extra == 0)
                // After the showbreak, draw the breakindent
!               draw_state = WL_BRI - 1;
  
            // draw 'breakindent': indent wrapped text accordingly
!           if (draw_state == WL_BRI - 1 && n_extra == 0)
            {
!               draw_state = WL_BRI;
                // if need_showbreak is set, breakindent also applies
                if (wp->w_p_bri && (wlv.row != startrow || need_showbreak)
  # ifdef FEAT_DIFF
--- 1367,1408 ----
                              && (wlv.row == startrow + filler_lines
                                  || (wlv.row > startrow + filler_lines
                                     && (wp->w_p_culopt_flags & CULOPT_LINE))))
!                       wlv.char_attr = hl_combine_attr(wcr_attr,
!                                                            HL_ATTR(HLF_CLN));
  #endif
                      if (wp->w_p_rnu && lnum < wp->w_cursor.lnum
                                                      && HL_ATTR(HLF_LNA) != 0)
                          // Use LineNrAbove
!                         wlv.char_attr = hl_combine_attr(wcr_attr,
                                                             HL_ATTR(HLF_LNA));
                      if (wp->w_p_rnu && lnum > wp->w_cursor.lnum
                                                      && HL_ATTR(HLF_LNB) != 0)
                          // Use LineNrBelow
!                         wlv.char_attr = hl_combine_attr(wcr_attr,
                                                             HL_ATTR(HLF_LNB));
                    }
  #ifdef FEAT_SIGNS
                    if (num_attr)
!                       wlv.char_attr = num_attr;
  #endif
                }
            }
  
  #ifdef FEAT_LINEBREAK
!           if (wp->w_briopt_sbr && wlv.draw_state == WL_BRI - 1
!                           && wlv.n_extra == 0
!                           && *get_showbreak_value(wp) != NUL)
                // draw indent after showbreak value
!               wlv.draw_state = WL_BRI;
!           else if (wp->w_briopt_sbr && wlv.draw_state == WL_SBR
!                                                          && wlv.n_extra == 0)
                // After the showbreak, draw the breakindent
!               wlv.draw_state = WL_BRI - 1;
  
            // draw 'breakindent': indent wrapped text accordingly
!           if (wlv.draw_state == WL_BRI - 1 && wlv.n_extra == 0)
            {
!               wlv.draw_state = WL_BRI;
                // if need_showbreak is set, breakindent also applies
                if (wp->w_p_bri && (wlv.row != startrow || need_showbreak)
  # ifdef FEAT_DIFF
***************
*** 1383,1441 ****
  # endif
                   )
                {
!                   char_attr = 0;
  # ifdef FEAT_DIFF
!                   if (diff_hlf != (hlf_T)0)
!                       char_attr = HL_ATTR(diff_hlf);
  # endif
!                   p_extra = NULL;
!                   c_extra = ' ';
!                   c_final = NUL;
!                   n_extra = get_breakindent_win(wp,
                                       ml_get_buf(wp->w_buffer, lnum, FALSE));
                    if (wlv.row == startrow)
                    {
!                       n_extra -= win_col_off2(wp);
!                       if (n_extra < 0)
!                           n_extra = 0;
                    }
                    if (wp->w_skipcol > 0 && wp->w_p_wrap && wp->w_briopt_sbr)
                        need_showbreak = FALSE;
                    // Correct end of highlighted area for 'breakindent',
                    // required when 'linebreak' is also set.
                    if (tocol == wlv.vcol)
!                       tocol += n_extra;
                }
            }
  #endif
  
  #if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF)
!           if (draw_state == WL_SBR - 1 && n_extra == 0)
            {
                char_u *sbr;
  
!               draw_state = WL_SBR;
  # ifdef FEAT_DIFF
                if (filler_todo > 0)
                {
                    // Draw "deleted" diff line(s).
                    if (char2cells(wp->w_fill_chars.diff) > 1)
                    {
!                       c_extra = '-';
!                       c_final = NUL;
                    }
                    else
                    {
!                       c_extra = wp->w_fill_chars.diff;
!                       c_final = NUL;
                    }
  #  ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
!                       n_extra = wlv.col + 1;
                    else
  #  endif
!                       n_extra = wp->w_width - wlv.col;
!                   char_attr = HL_ATTR(HLF_DED);
                }
  # endif
  # ifdef FEAT_LINEBREAK
--- 1410,1468 ----
  # endif
                   )
                {
!                   wlv.char_attr = 0;
  # ifdef FEAT_DIFF
!                   if (wlv.diff_hlf != (hlf_T)0)
!                       wlv.char_attr = HL_ATTR(wlv.diff_hlf);
  # endif
!                   wlv.p_extra = NULL;
!                   wlv.c_extra = ' ';
!                   wlv.c_final = NUL;
!                   wlv.n_extra = get_breakindent_win(wp,
                                       ml_get_buf(wp->w_buffer, lnum, FALSE));
                    if (wlv.row == startrow)
                    {
!                       wlv.n_extra -= win_col_off2(wp);
!                       if (wlv.n_extra < 0)
!                           wlv.n_extra = 0;
                    }
                    if (wp->w_skipcol > 0 && wp->w_p_wrap && wp->w_briopt_sbr)
                        need_showbreak = FALSE;
                    // Correct end of highlighted area for 'breakindent',
                    // required when 'linebreak' is also set.
                    if (tocol == wlv.vcol)
!                       tocol += wlv.n_extra;
                }
            }
  #endif
  
  #if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF)
!           if (wlv.draw_state == WL_SBR - 1 && wlv.n_extra == 0)
            {
                char_u *sbr;
  
!               wlv.draw_state = WL_SBR;
  # ifdef FEAT_DIFF
                if (filler_todo > 0)
                {
                    // Draw "deleted" diff line(s).
                    if (char2cells(wp->w_fill_chars.diff) > 1)
                    {
!                       wlv.c_extra = '-';
!                       wlv.c_final = NUL;
                    }
                    else
                    {
!                       wlv.c_extra = wp->w_fill_chars.diff;
!                       wlv.c_final = NUL;
                    }
  #  ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
!                       wlv.n_extra = wlv.col + 1;
                    else
  #  endif
!                       wlv.n_extra = wp->w_width - wlv.col;
!                   wlv.char_attr = HL_ATTR(HLF_DED);
                }
  # endif
  # ifdef FEAT_LINEBREAK
***************
*** 1443,1489 ****
                if (*sbr != NUL && need_showbreak)
                {
                    // Draw 'showbreak' at the start of each broken line.
!                   p_extra = sbr;
!                   c_extra = NUL;
!                   c_final = NUL;
!                   n_extra = (int)STRLEN(sbr);
                    if (wp->w_skipcol == 0 || !wp->w_p_wrap)
                        need_showbreak = FALSE;
                    vcol_sbr = wlv.vcol + MB_CHARLEN(sbr);
                    // Correct end of highlighted area for 'showbreak',
                    // required when 'linebreak' is also set.
                    if (tocol == wlv.vcol)
!                       tocol += n_extra;
                    // combine 'showbreak' with 'wincolor'
!                   char_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
  #  ifdef FEAT_SYN_HL
                    // combine 'showbreak' with 'cursorline'
                    if (cul_attr != 0)
!                       char_attr = hl_combine_attr(char_attr, cul_attr);
  #  endif
                }
  # endif
            }
  #endif
  
!           if (draw_state == WL_LINE - 1 && n_extra == 0)
            {
!               draw_state = WL_LINE;
!               if (saved_n_extra)
                {
                    // Continue item from end of wrapped line.
!                   n_extra = saved_n_extra;
!                   c_extra = saved_c_extra;
!                   c_final = saved_c_final;
!                   p_extra = saved_p_extra;
!                   char_attr = saved_char_attr;
                }
                else
!                   char_attr = wlv.win_attr;
            }
        }
  #ifdef FEAT_SYN_HL
!       if (cul_screenline && draw_state == WL_LINE
                && wlv.vcol >= left_curline_col
                && wlv.vcol < right_curline_col)
        {
--- 1470,1518 ----
                if (*sbr != NUL && need_showbreak)
                {
                    // Draw 'showbreak' at the start of each broken line.
!                   wlv.p_extra = sbr;
!                   wlv.c_extra = NUL;
!                   wlv.c_final = NUL;
!                   wlv.n_extra = (int)STRLEN(sbr);
                    if (wp->w_skipcol == 0 || !wp->w_p_wrap)
                        need_showbreak = FALSE;
                    vcol_sbr = wlv.vcol + MB_CHARLEN(sbr);
                    // Correct end of highlighted area for 'showbreak',
                    // required when 'linebreak' is also set.
                    if (tocol == wlv.vcol)
!                       tocol += wlv.n_extra;
                    // combine 'showbreak' with 'wincolor'
!                   wlv.char_attr = hl_combine_attr(wlv.win_attr,
!                                                             HL_ATTR(HLF_AT));
  #  ifdef FEAT_SYN_HL
                    // combine 'showbreak' with 'cursorline'
                    if (cul_attr != 0)
!                       wlv.char_attr = hl_combine_attr(wlv.char_attr,
!                                                                    cul_attr);
  #  endif
                }
  # endif
            }
  #endif
  
!           if (wlv.draw_state == WL_LINE - 1 && wlv.n_extra == 0)
            {
!               wlv.draw_state = WL_LINE;
!               if (wlv.saved_n_extra)
                {
                    // Continue item from end of wrapped line.
!                   wlv.n_extra = wlv.saved_n_extra;
!                   wlv.c_extra = wlv.saved_c_extra;
!                   wlv.c_final = wlv.saved_c_final;
!                   wlv.p_extra = wlv.saved_p_extra;
!                   wlv.char_attr = wlv.saved_char_attr;
                }
                else
!                   wlv.char_attr = wlv.win_attr;
            }
        }
  #ifdef FEAT_SYN_HL
!       if (wlv.cul_screenline && wlv.draw_state == WL_LINE
                && wlv.vcol >= left_curline_col
                && wlv.vcol < right_curline_col)
        {
***************
*** 1497,1503 ****
        // stop here.
        if (((dollar_vcol >= 0 && wp == curwin
                   && lnum == wp->w_cursor.lnum && wlv.vcol >= 
(long)wp->w_virtcol)
!               || (number_only && draw_state > WL_NR))
  #ifdef FEAT_DIFF
                                   && filler_todo <= 0
  #endif
--- 1526,1532 ----
        // stop here.
        if (((dollar_vcol >= 0 && wp == curwin
                   && lnum == wp->w_cursor.lnum && wlv.vcol >= 
(long)wp->w_virtcol)
!               || (number_only && wlv.draw_state > WL_NR))
  #ifdef FEAT_DIFF
                                   && filler_todo <= 0
  #endif
***************
*** 1516,1526 ****
            break;
        }
  
!       if (draw_state == WL_LINE && (area_highlighting || extra_check))
        {
            // handle Visual or match highlighting in this line
            if (wlv.vcol == fromcol
!                   || (has_mbyte && wlv.vcol + 1 == fromcol && n_extra == 0
                        && (*mb_ptr2cells)(ptr) > 1)
                    || ((int)vcol_prev == fromcol_prev
                        && vcol_prev < wlv.vcol // not at margin
--- 1545,1555 ----
            break;
        }
  
!       if (wlv.draw_state == WL_LINE && (area_highlighting || extra_check))
        {
            // handle Visual or match highlighting in this line
            if (wlv.vcol == fromcol
!                   || (has_mbyte && wlv.vcol + 1 == fromcol && wlv.n_extra == 0
                        && (*mb_ptr2cells)(ptr) > 1)
                    || ((int)vcol_prev == fromcol_prev
                        && vcol_prev < wlv.vcol // not at margin
***************
*** 1532,1538 ****
                area_attr = 0;                  // stop highlighting
  
  #ifdef FEAT_SEARCH_EXTRA
!           if (!n_extra)
            {
                // Check for start/end of 'hlsearch' and other matches.
                // After end, check for start/end of next match.
--- 1561,1567 ----
                area_attr = 0;                  // stop highlighting
  
  #ifdef FEAT_SEARCH_EXTRA
!           if (!wlv.n_extra)
            {
                // Check for start/end of 'hlsearch' and other matches.
                // After end, check for start/end of next match.
***************
*** 1553,1570 ****
  #endif
  
  #ifdef FEAT_DIFF
!           if (diff_hlf != (hlf_T)0)
            {
!               if (diff_hlf == HLF_CHD && ptr - line >= change_start
!                                                             && n_extra == 0)
!                   diff_hlf = HLF_TXD;         // changed text
!               if (diff_hlf == HLF_TXD && ptr - line > change_end
!                                                             && n_extra == 0)
!                   diff_hlf = HLF_CHD;         // changed line
!               line_attr = HL_ATTR(diff_hlf);
                if (wp->w_p_cul && lnum == wp->w_cursor.lnum
                        && wp->w_p_culopt_flags != CULOPT_NBR
!                       && (!cul_screenline || (wlv.vcol >= left_curline_col
                                            && wlv.vcol <= right_curline_col)))
                    line_attr = hl_combine_attr(
                                          line_attr, HL_ATTR(HLF_CUL));
--- 1582,1599 ----
  #endif
  
  #ifdef FEAT_DIFF
!           if (wlv.diff_hlf != (hlf_T)0)
            {
!               if (wlv.diff_hlf == HLF_CHD && ptr - line >= change_start
!                                                          && wlv.n_extra == 0)
!                   wlv.diff_hlf = HLF_TXD;             // changed text
!               if (wlv.diff_hlf == HLF_TXD && ptr - line > change_end
!                                                          && wlv.n_extra == 0)
!                   wlv.diff_hlf = HLF_CHD;             // changed line
!               line_attr = HL_ATTR(wlv.diff_hlf);
                if (wp->w_p_cul && lnum == wp->w_cursor.lnum
                        && wp->w_p_culopt_flags != CULOPT_NBR
!                       && (!wlv.cul_screenline || (wlv.vcol >= left_curline_col
                                            && wlv.vcol <= right_curline_col)))
                    line_attr = hl_combine_attr(
                                          line_attr, HL_ATTR(HLF_CUL));
***************
*** 1577,1583 ****
                int pi;
                int bcol = (int)(ptr - line);
  
!               if (n_extra > 0
  # ifdef FEAT_LINEBREAK
                        && !in_linebreak
  # endif
--- 1606,1612 ----
                int pi;
                int bcol = (int)(ptr - line);
  
!               if (wlv.n_extra > 0
  # ifdef FEAT_LINEBREAK
                        && !in_linebreak
  # endif
***************
*** 1608,1614 ****
                }
  
  # ifdef FEAT_LINEBREAK
!               if (n_extra > 0 && in_linebreak)
                    // not on the next char yet, don't start another prop
                    --bcol;
  # endif
--- 1637,1643 ----
                }
  
  # ifdef FEAT_LINEBREAK
!               if (wlv.n_extra > 0 && in_linebreak)
                    // not on the next char yet, don't start another prop
                    --bcol;
  # endif
***************
*** 1628,1634 ****
                text_prop_flags = 0;
                text_prop_type = NULL;
                text_prop_id = 0;
!               if (text_props_active > 0 && n_extra == 0)
                {
                    int used_tpi = -1;
                    int used_attr = 0;
--- 1657,1663 ----
                text_prop_flags = 0;
                text_prop_type = NULL;
                text_prop_id = 0;
!               if (text_props_active > 0 && wlv.n_extra == 0)
                {
                    int used_tpi = -1;
                    int used_attr = 0;
***************
*** 1668,1673 ****
--- 1697,1707 ----
                        char_u *p = ((char_u **)wp->w_buffer
                                                   ->b_textprop_text.ga_data)[
                                                           -text_prop_id - 1];
+ 
+                       // reset the ID in the copy to avoid it being used
+                       // again
+                       text_props[used_tpi].tp_id = -MAXCOL;
+ 
                        if (p != NULL)
                        {
                            int     right = (text_props[used_tpi].tp_flags
***************
*** 1677,1686 ****
                            int     wrap = (text_props[used_tpi].tp_flags
                                                        & TP_FLAG_WRAP);
  
!                           p_extra = p;
!                           c_extra = NUL;
!                           c_final = NUL;
!                           n_extra = (int)STRLEN(p);
                            extra_attr = used_attr;
                            n_attr = mb_charlen(p);
                            text_prop_attr = 0;
--- 1711,1720 ----
                            int     wrap = (text_props[used_tpi].tp_flags
                                                        & TP_FLAG_WRAP);
  
!                           wlv.p_extra = p;
!                           wlv.c_extra = NUL;
!                           wlv.c_final = NUL;
!                           wlv.n_extra = (int)STRLEN(p);
                            extra_attr = used_attr;
                            n_attr = mb_charlen(p);
                            text_prop_attr = 0;
***************
*** 1702,1715 ****
                            if ((right || below || !wrap) && wp->w_width > 2)
                            {
                                int     added = wp->w_width - wlv.col;
!                               int     n_used = n_extra;
                                char_u  *l;
                                int     strsize = wrap
!                                           ? vim_strsize(p_extra)
!                                           : textprop_size_after_trunc(wp,
!                                              below, added, p_extra, &n_used);
  
!                               if (wrap || right || below || n_used < n_extra)
                                {
                                    // Right-align: fill with spaces
                                    if (right)
--- 1736,1750 ----
                            if ((right || below || !wrap) && wp->w_width > 2)
                            {
                                int     added = wp->w_width - wlv.col;
!                               int     n_used = wlv.n_extra;
                                char_u  *l;
                                int     strsize = wrap
!                                         ? vim_strsize(wlv.p_extra)
!                                         : textprop_size_after_trunc(wp,
!                                          below, added, wlv.p_extra, &n_used);
  
!                               if (wrap || right || below
!                                                      || n_used < wlv.n_extra)
                                {
                                    // Right-align: fill with spaces
                                    if (right)
***************
*** 1717,1731 ****
                                    if (added < 0
                                            || (below
                                                ? wlv.col == 0 || !wp->w_p_wrap
!                                               : n_used < n_extra))
                                        added = 0;
                                    // add 1 for NUL, 2 for when '…' is used
                                    l = alloc(n_used + added + 3);
                                    if (l != NULL)
                                    {
                                        vim_memset(l, ' ', added);
!                                       vim_strncpy(l + added, p_extra, n_used);
!                                       if (n_used < n_extra)
                                        {
                                            char_u *lp = l + added + n_used - 1;
  
--- 1752,1767 ----
                                    if (added < 0
                                            || (below
                                                ? wlv.col == 0 || !wp->w_p_wrap
!                                               : n_used < wlv.n_extra))
                                        added = 0;
                                    // add 1 for NUL, 2 for when '…' is used
                                    l = alloc(n_used + added + 3);
                                    if (l != NULL)
                                    {
                                        vim_memset(l, ' ', added);
!                                       vim_strncpy(l + added, wlv.p_extra,
!                                                                      n_used);
!                                       if (n_used < wlv.n_extra)
                                        {
                                            char_u *lp = l + added + n_used - 1;
  
***************
*** 1740,1748 ****
                                                // change last character to '>'
                                                *lp = '>';
                                        }
!                                       vim_free(p_extra_free);
!                                       p_extra = p_extra_free = l;
!                                       n_extra = n_used + added;
                                        n_attr_skip = added;
                                    }
                                }
--- 1776,1784 ----
                                                // change last character to '>'
                                                *lp = '>';
                                        }
!                                       vim_free(p_extra_free2);
!                                       wlv.p_extra = p_extra_free2 = l;
!                                       wlv.n_extra = n_used + added;
                                        n_attr_skip = added;
                                    }
                                }
***************
*** 1760,1772 ****
                                        ++wlv.row;
                                        break;
                                    }
!                                   win_line_start(wp, &wlv);
                                }
                            }
                        }
-                       // reset the ID in the copy to avoid it being used
-                       // again
-                       text_props[used_tpi].tp_id = -MAXCOL;
  
                        // If another text prop follows the condition below at
                        // the last window column must know.
--- 1796,1806 ----
                                        ++wlv.row;
                                        break;
                                    }
!                                   win_line_start(wp, &wlv, TRUE);
!                                   continue;
                                }
                            }
                        }
  
                        // If another text prop follows the condition below at
                        // the last window column must know.
***************
*** 1785,1791 ****
  #endif
  
  #ifdef FEAT_SYN_HL
!           if (extra_check && n_extra == 0)
            {
                syntax_attr = 0;
  # ifdef FEAT_TERMINAL
--- 1819,1825 ----
  #endif
  
  #ifdef FEAT_SYN_HL
!           if (extra_check && wlv.n_extra == 0)
            {
                syntax_attr = 0;
  # ifdef FEAT_TERMINAL
***************
*** 1863,1881 ****
  #ifdef LINE_ATTR
            if (area_attr != 0)
            {
!               char_attr = hl_combine_attr(line_attr, area_attr);
                if (!highlight_match)
                    // let search highlight show in Visual area if possible
!                   char_attr = hl_combine_attr(search_attr, char_attr);
  # ifdef FEAT_SYN_HL
!               char_attr = hl_combine_attr(syntax_attr, char_attr);
  # endif
            }
            else if (search_attr != 0)
            {
!               char_attr = hl_combine_attr(line_attr, search_attr);
  # ifdef FEAT_SYN_HL
!               char_attr = hl_combine_attr(syntax_attr, char_attr);
  # endif
            }
            else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL)
--- 1897,1915 ----
  #ifdef LINE_ATTR
            if (area_attr != 0)
            {
!               wlv.char_attr = hl_combine_attr(line_attr, area_attr);
                if (!highlight_match)
                    // let search highlight show in Visual area if possible
!                   wlv.char_attr = hl_combine_attr(search_attr, wlv.char_attr);
  # ifdef FEAT_SYN_HL
!               wlv.char_attr = hl_combine_attr(syntax_attr, wlv.char_attr);
  # endif
            }
            else if (search_attr != 0)
            {
!               wlv.char_attr = hl_combine_attr(line_attr, search_attr);
  # ifdef FEAT_SYN_HL
!               wlv.char_attr = hl_combine_attr(syntax_attr, wlv.char_attr);
  # endif
            }
            else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL)
***************
*** 1885,1925 ****
                // Use line_attr when not in the Visual or 'incsearch' area
                // (area_attr may be 0 when "noinvcur" is set).
  # ifdef FEAT_SYN_HL
!               char_attr = hl_combine_attr(syntax_attr, line_attr);
  # else
!               char_attr = line_attr;
  # endif
                attr_pri = FALSE;
            }
  #else
            if (area_attr != 0)
!               char_attr = area_attr;
            else if (search_attr != 0)
!               char_attr = search_attr;
  #endif
            else
            {
                attr_pri = FALSE;
  #ifdef FEAT_SYN_HL
!               char_attr = syntax_attr;
  #else
!               char_attr = 0;
  #endif
            }
  #ifdef FEAT_PROP_POPUP
            // override with text property highlight when "override" is TRUE
            if (text_prop_type != NULL && (text_prop_flags & PT_FLAG_OVERRIDE))
!               char_attr = hl_combine_attr(char_attr, text_prop_attr);
  #endif
        }
  
        // combine attribute with 'wincolor'
        if (wlv.win_attr != 0)
        {
!           if (char_attr == 0)
!               char_attr = wlv.win_attr;
            else
!               char_attr = hl_combine_attr(wlv.win_attr, char_attr);
        }
  
        // Get the next character to put on the screen.
--- 1919,1959 ----
                // Use line_attr when not in the Visual or 'incsearch' area
                // (area_attr may be 0 when "noinvcur" is set).
  # ifdef FEAT_SYN_HL
!               wlv.char_attr = hl_combine_attr(syntax_attr, line_attr);
  # else
!               wlv.char_attr = line_attr;
  # endif
                attr_pri = FALSE;
            }
  #else
            if (area_attr != 0)
!               wlv.char_attr = area_attr;
            else if (search_attr != 0)
!               wlv.char_attr = search_attr;
  #endif
            else
            {
                attr_pri = FALSE;
  #ifdef FEAT_SYN_HL
!               wlv.char_attr = syntax_attr;
  #else
!               wlv.char_attr = 0;
  #endif
            }
  #ifdef FEAT_PROP_POPUP
            // override with text property highlight when "override" is TRUE
            if (text_prop_type != NULL && (text_prop_flags & PT_FLAG_OVERRIDE))
!               wlv.char_attr = hl_combine_attr(wlv.char_attr, text_prop_attr);
  #endif
        }
  
        // combine attribute with 'wincolor'
        if (wlv.win_attr != 0)
        {
!           if (wlv.char_attr == 0)
!               wlv.char_attr = wlv.win_attr;
            else
!               wlv.char_attr = hl_combine_attr(wlv.win_attr, wlv.char_attr);
        }
  
        // Get the next character to put on the screen.
***************
*** 1927,1941 ****
        // The "p_extra" points to the extra stuff that is inserted to
        // represent special characters (non-printable stuff) and other
        // things.  When all characters are the same, c_extra is used.
!       // If c_final is set, it will compulsorily be used at the end.
        // "p_extra" must end in a NUL to avoid mb_ptr2len() reads past
        // "p_extra[n_extra]".
        // For the '$' of the 'list' option, n_extra == 1, p_extra == "".
!       if (n_extra > 0)
        {
!           if (c_extra != NUL || (n_extra == 1 && c_final != NUL))
            {
!               c = (n_extra == 1 && c_final != NUL) ? c_final : c_extra;
                mb_c = c;       // doesn't handle non-utf-8 multi-byte!
                if (enc_utf8 && utf_char2len(c) > 1)
                {
--- 1961,1976 ----
        // The "p_extra" points to the extra stuff that is inserted to
        // represent special characters (non-printable stuff) and other
        // things.  When all characters are the same, c_extra is used.
!       // If wlv.c_final is set, it will compulsorily be used at the end.
        // "p_extra" must end in a NUL to avoid mb_ptr2len() reads past
        // "p_extra[n_extra]".
        // For the '$' of the 'list' option, n_extra == 1, p_extra == "".
!       if (wlv.n_extra > 0)
        {
!           if (wlv.c_extra != NUL || (wlv.n_extra == 1 && wlv.c_final != NUL))
            {
!               c = (wlv.n_extra == 1 && wlv.c_final != NUL)
!                                                  ? wlv.c_final : wlv.c_extra;
                mb_c = c;       // doesn't handle non-utf-8 multi-byte!
                if (enc_utf8 && utf_char2len(c) > 1)
                {
***************
*** 1948,1954 ****
            }
            else
            {
!               c = *p_extra;
                if (has_mbyte)
                {
                    mb_c = c;
--- 1983,1989 ----
            }
            else
            {
!               c = *wlv.p_extra;
                if (has_mbyte)
                {
                    mb_c = c;
***************
*** 1956,1968 ****
                    {
                        // If the UTF-8 character is more than one byte:
                        // Decode it into "mb_c".
!                       mb_l = utfc_ptr2len(p_extra);
                        mb_utf8 = FALSE;
!                       if (mb_l > n_extra)
                            mb_l = 1;
                        else if (mb_l > 1)
                        {
!                           mb_c = utfc_ptr2char(p_extra, u8cc);
                            mb_utf8 = TRUE;
                            c = 0xc0;
                        }
--- 1991,2003 ----
                    {
                        // If the UTF-8 character is more than one byte:
                        // Decode it into "mb_c".
!                       mb_l = utfc_ptr2len(wlv.p_extra);
                        mb_utf8 = FALSE;
!                       if (mb_l > wlv.n_extra)
                            mb_l = 1;
                        else if (mb_l > 1)
                        {
!                           mb_c = utfc_ptr2char(wlv.p_extra, u8cc);
                            mb_utf8 = TRUE;
                            c = 0xc0;
                        }
***************
*** 1971,1980 ****
                    {
                        // if this is a DBCS character, put it in "mb_c"
                        mb_l = MB_BYTE2LEN(c);
!                       if (mb_l >= n_extra)
                            mb_l = 1;
                        else if (mb_l > 1)
!                           mb_c = (c << 8) + p_extra[1];
                    }
                    if (mb_l == 0)  // at the NUL at end-of-line
                        mb_l = 1;
--- 2006,2015 ----
                    {
                        // if this is a DBCS character, put it in "mb_c"
                        mb_l = MB_BYTE2LEN(c);
!                       if (mb_l >= wlv.n_extra)
                            mb_l = 1;
                        else if (mb_l > 1)
!                           mb_c = (c << 8) + wlv.p_extra[1];
                    }
                    if (mb_l == 0)  // at the NUL at end-of-line
                        mb_l = 1;
***************
*** 2001,2020 ****
  
                        // put the pointer back to output the double-width
                        // character at the start of the next line.
!                       ++n_extra;
!                       --p_extra;
                    }
                    else
                    {
!                       n_extra -= mb_l - 1;
!                       p_extra += mb_l - 1;
                    }
                }
!               ++p_extra;
            }
!           --n_extra;
  #if defined(FEAT_LINEBREAK) && defined(FEAT_PROP_POPUP)
!           if (n_extra <= 0)
                in_linebreak = FALSE;
  #endif
        }
--- 2036,2055 ----
  
                        // put the pointer back to output the double-width
                        // character at the start of the next line.
!                       ++wlv.n_extra;
!                       --wlv.p_extra;
                    }
                    else
                    {
!                       wlv.n_extra -= mb_l - 1;
!                       wlv.p_extra += mb_l - 1;
                    }
                }
!               ++wlv.p_extra;
            }
!           --wlv.n_extra;
  #if defined(FEAT_LINEBREAK) && defined(FEAT_PROP_POPUP)
!           if (wlv.n_extra <= 0)
                in_linebreak = FALSE;
  #endif
        }
***************
*** 2023,2029 ****
  #ifdef FEAT_LINEBREAK
            int         c0;
  #endif
-           VIM_CLEAR(p_extra_free);
            prev_ptr = ptr;
  
            // Get a character from the line itself.
--- 2058,2063 ----
***************
*** 2078,2096 ****
                        if (wp->w_p_rl)         // reverse
                            rl_mirror(extra);
  # endif
!                       p_extra = extra;
!                       c = *p_extra;
!                       mb_c = mb_ptr2char_adv(&p_extra);
                        mb_utf8 = (c >= 0x80);
!                       n_extra = (int)STRLEN(p_extra);
!                       c_extra = NUL;
!                       c_final = NUL;
                        if (area_attr == 0 && search_attr == 0)
                        {
!                           n_attr = n_extra + 1;
                            extra_attr = hl_combine_attr(
                                                 wlv.win_attr, HL_ATTR(HLF_8));
!                           saved_attr2 = char_attr; // save current attr
                        }
                    }
                    else if (mb_l == 0)  // at the NUL at end-of-line
--- 2112,2130 ----
                        if (wp->w_p_rl)         // reverse
                            rl_mirror(extra);
  # endif
!                       wlv.p_extra = extra;
!                       c = *wlv.p_extra;
!                       mb_c = mb_ptr2char_adv(&wlv.p_extra);
                        mb_utf8 = (c >= 0x80);
!                       wlv.n_extra = (int)STRLEN(wlv.p_extra);
!                       wlv.c_extra = NUL;
!                       wlv.c_final = NUL;
                        if (area_attr == 0 && search_attr == 0)
                        {
!                           n_attr = wlv.n_extra + 1;
                            extra_attr = hl_combine_attr(
                                                 wlv.win_attr, HL_ATTR(HLF_8));
!                           saved_attr2 = wlv.char_attr; // save current attr
                        }
                    }
                    else if (mb_l == 0)  // at the NUL at end-of-line
***************
*** 2150,2166 ****
                                mb_l = 2;
                                STRCPY(extra, "XX");
                            }
!                           p_extra = extra;
!                           n_extra = (int)STRLEN(extra) - 1;
!                           c_extra = NUL;
!                           c_final = NUL;
!                           c = *p_extra++;
                            if (area_attr == 0 && search_attr == 0)
                            {
!                               n_attr = n_extra + 1;
                                extra_attr = hl_combine_attr(
                                                 wlv.win_attr, HL_ATTR(HLF_8));
!                               saved_attr2 = char_attr; // save current attr
                            }
                            mb_c = c;
                        }
--- 2184,2201 ----
                                mb_l = 2;
                                STRCPY(extra, "XX");
                            }
!                           wlv.p_extra = extra;
!                           wlv.n_extra = (int)STRLEN(extra) - 1;
!                           wlv.c_extra = NUL;
!                           wlv.c_final = NUL;
!                           c = *wlv.p_extra++;
                            if (area_attr == 0 && search_attr == 0)
                            {
!                               n_attr = wlv.n_extra + 1;
                                extra_attr = hl_combine_attr(
                                                 wlv.win_attr, HL_ATTR(HLF_8));
!                               // save current attr
!                               saved_attr2 = wlv.char_attr;
                            }
                            mb_c = c;
                        }
***************
*** 2194,2211 ****
                // If a double-width char doesn't fit at the left side display
                // a '<' in the first column.  Don't do this for unprintable
                // characters.
!               if (n_skip > 0 && mb_l > 1 && n_extra == 0)
                {
!                   n_extra = 1;
!                   c_extra = MB_FILLER_CHAR;
!                   c_final = NUL;
                    c = ' ';
                    if (area_attr == 0 && search_attr == 0)
                    {
!                       n_attr = n_extra + 1;
                        extra_attr = hl_combine_attr(
                                                wlv.win_attr, HL_ATTR(HLF_AT));
!                       saved_attr2 = char_attr; // save current attr
                    }
                    mb_c = c;
                    mb_utf8 = FALSE;
--- 2229,2246 ----
                // If a double-width char doesn't fit at the left side display
                // a '<' in the first column.  Don't do this for unprintable
                // characters.
!               if (n_skip > 0 && mb_l > 1 && wlv.n_extra == 0)
                {
!                   wlv.n_extra = 1;
!                   wlv.c_extra = MB_FILLER_CHAR;
!                   wlv.c_final = NUL;
                    c = ' ';
                    if (area_attr == 0 && search_attr == 0)
                    {
!                       n_attr = wlv.n_extra + 1;
                        extra_attr = hl_combine_attr(
                                                wlv.win_attr, HL_ATTR(HLF_AT));
!                       saved_attr2 = wlv.char_attr; // save current attr
                    }
                    mb_c = c;
                    mb_utf8 = FALSE;
***************
*** 2297,2305 ****
                if (spell_attr != 0)
                {
                    if (!attr_pri)
!                       char_attr = hl_combine_attr(char_attr, spell_attr);
                    else
!                       char_attr = hl_combine_attr(spell_attr, char_attr);
                }
  #endif
  #ifdef FEAT_LINEBREAK
--- 2332,2342 ----
                if (spell_attr != 0)
                {
                    if (!attr_pri)
!                       wlv.char_attr = hl_combine_attr(wlv.char_attr,
!                                                                  spell_attr);
                    else
!                       wlv.char_attr = hl_combine_attr(spell_attr,
!                                                               wlv.char_attr);
                }
  #endif
  #ifdef FEAT_LINEBREAK
***************
*** 2313,2327 ****
                    chartabsize_T cts;
  
                    init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, p);
!                   n_extra = win_lbr_chartabsize(&cts, NULL) - 1;
  
                    // We have just drawn the showbreak value, no need to add
                    // space for it again.
                    if (wlv.vcol == vcol_sbr)
                    {
!                       n_extra -= MB_CHARLEN(get_showbreak_value(wp));
!                       if (n_extra < 0)
!                           n_extra = 0;
                    }
                    if (on_last_col && c != TAB)
                        // Do not continue search/match highlighting over the
--- 2350,2364 ----
                    chartabsize_T cts;
  
                    init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, p);
!                   wlv.n_extra = win_lbr_chartabsize(&cts, NULL) - 1;
  
                    // We have just drawn the showbreak value, no need to add
                    // space for it again.
                    if (wlv.vcol == vcol_sbr)
                    {
!                       wlv.n_extra -= MB_CHARLEN(get_showbreak_value(wp));
!                       if (wlv.n_extra < 0)
!                           wlv.n_extra = 0;
                    }
                    if (on_last_col && c != TAB)
                        // Do not continue search/match highlighting over the
***************
*** 2329,2348 ****
                        // include the complete width of the character
                        search_attr = 0;
  
!                   if (c == TAB && n_extra + wlv.col > wp->w_width)
  # ifdef FEAT_VARTABS
!                       n_extra = tabstop_padding(wlv.vcol,
                                              wp->w_buffer->b_p_ts,
                                              wp->w_buffer->b_p_vts_array) - 1;
  # else
!                       n_extra = (int)wp->w_buffer->b_p_ts
                                    - wlv.vcol % (int)wp->w_buffer->b_p_ts - 1;
  # endif
  
!                   c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' ';
!                   c_final = NUL;
  # if defined(FEAT_PROP_POPUP)
!                   if (n_extra > 0 && c != TAB)
                        in_linebreak = TRUE;
  # endif
                    if (VIM_ISWHITE(c))
--- 2366,2385 ----
                        // include the complete width of the character
                        search_attr = 0;
  
!                   if (c == TAB && wlv.n_extra + wlv.col > wp->w_width)
  # ifdef FEAT_VARTABS
!                       wlv.n_extra = tabstop_padding(wlv.vcol,
                                              wp->w_buffer->b_p_ts,
                                              wp->w_buffer->b_p_vts_array) - 1;
  # else
!                       wlv.n_extra = (int)wp->w_buffer->b_p_ts
                                    - wlv.vcol % (int)wp->w_buffer->b_p_ts - 1;
  # endif
  
!                   wlv.c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' ';
!                   wlv.c_final = NUL;
  # if defined(FEAT_PROP_POPUP)
!                   if (wlv.n_extra > 0 && c != TAB)
                        in_linebreak = TRUE;
  # endif
                    if (VIM_ISWHITE(c))
***************
*** 2395,2401 ****
                        n_attr = 1;
                        extra_attr = hl_combine_attr(wlv.win_attr,
                                                               HL_ATTR(HLF_8));
!                       saved_attr2 = char_attr; // save current attr
                    }
                    mb_c = c;
                    if (enc_utf8 && utf_char2len(c) > 1)
--- 2432,2438 ----
                        n_attr = 1;
                        extra_attr = hl_combine_attr(wlv.win_attr,
                                                               HL_ATTR(HLF_8));
!                       saved_attr2 = wlv.char_attr; // save current attr
                    }
                    mb_c = c;
                    if (enc_utf8 && utf_char2len(c) > 1)
***************
*** 2435,2441 ****
                        n_attr = 1;
                        extra_attr = hl_combine_attr(wlv.win_attr,
                                                               HL_ATTR(HLF_8));
!                       saved_attr2 = char_attr; // save current attr
                    }
                    mb_c = c;
                    if (enc_utf8 && utf_char2len(c) > 1)
--- 2472,2478 ----
                        n_attr = 1;
                        extra_attr = hl_combine_attr(wlv.win_attr,
                                                               HL_ATTR(HLF_8));
!                       saved_attr2 = wlv.char_attr; // save current attr
                    }
                    mb_c = c;
                    if (enc_utf8 && utf_char2len(c) > 1)
***************
*** 2481,2494 ****
                    if (!wp->w_p_lbr || !wp->w_p_list)
  #endif
                        // tab amount depends on current column
!                       n_extra = tab_len;
  #ifdef FEAT_LINEBREAK
                    else
                    {
                        char_u  *p;
                        int     len;
                        int     i;
!                       int     saved_nextra = n_extra;
  
  # ifdef FEAT_CONCEAL
                        if (wlv.vcol_off > 0)
--- 2518,2531 ----
                    if (!wp->w_p_lbr || !wp->w_p_list)
  #endif
                        // tab amount depends on current column
!                       wlv.n_extra = tab_len;
  #ifdef FEAT_LINEBREAK
                    else
                    {
                        char_u  *p;
                        int     len;
                        int     i;
!                       int     saved_nextra = wlv.n_extra;
  
  # ifdef FEAT_CONCEAL
                        if (wlv.vcol_off > 0)
***************
*** 2497,2518 ****
  
                        // boguscols before FIX_FOR_BOGUSCOLS macro from above
                        if (wp->w_p_list && wp->w_lcs_chars.tab1
!                                                       && old_boguscols > 0
!                                                       && n_extra > tab_len)
!                           tab_len += n_extra - tab_len;
  # endif
!                       // If n_extra > 0, it gives the number of chars, to
                        // use for a tab, else we need to calculate the width
                        // for a tab.
                        len = (tab_len * mb_char2len(wp->w_lcs_chars.tab2));
                        if (wp->w_lcs_chars.tab3)
                            len += mb_char2len(wp->w_lcs_chars.tab3);
!                       if (n_extra > 0)
!                           len += n_extra - tab_len;
                        c = wp->w_lcs_chars.tab1;
                        p = alloc(len + 1);
                        if (p == NULL)
!                           n_extra = 0;
                        else
                        {
                            vim_memset(p, ' ', len);
--- 2534,2555 ----
  
                        // boguscols before FIX_FOR_BOGUSCOLS macro from above
                        if (wp->w_p_list && wp->w_lcs_chars.tab1
!                                                     && old_boguscols > 0
!                                                     && wlv.n_extra > tab_len)
!                           tab_len += wlv.n_extra - tab_len;
  # endif
!                       // If wlv.n_extra > 0, it gives the number of chars, to
                        // use for a tab, else we need to calculate the width
                        // for a tab.
                        len = (tab_len * mb_char2len(wp->w_lcs_chars.tab2));
                        if (wp->w_lcs_chars.tab3)
                            len += mb_char2len(wp->w_lcs_chars.tab3);
!                       if (wlv.n_extra > 0)
!                           len += wlv.n_extra - tab_len;
                        c = wp->w_lcs_chars.tab1;
                        p = alloc(len + 1);
                        if (p == NULL)
!                           wlv.n_extra = 0;
                        else
                        {
                            vim_memset(p, ' ', len);
***************
*** 2533,2547 ****
                                if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
                                    lcs = wp->w_lcs_chars.tab3;
                                p += mb_char2bytes(lcs, p);
!                               n_extra += mb_char2len(lcs)
                                                  - (saved_nextra > 0 ? 1 : 0);
                            }
!                           p_extra = p_extra_free;
  # ifdef FEAT_CONCEAL
                            // n_extra will be increased by FIX_FOX_BOGUSCOLS
                            // macro below, so need to adjust for that here
                            if (wlv.vcol_off > 0)
!                               n_extra -= wlv.vcol_off;
  # endif
                        }
                    }
--- 2570,2584 ----
                                if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
                                    lcs = wp->w_lcs_chars.tab3;
                                p += mb_char2bytes(lcs, p);
!                               wlv.n_extra += mb_char2len(lcs)
                                                  - (saved_nextra > 0 ? 1 : 0);
                            }
!                           wlv.p_extra = p_extra_free;
  # ifdef FEAT_CONCEAL
                            // n_extra will be increased by FIX_FOX_BOGUSCOLS
                            // macro below, so need to adjust for that here
                            if (wlv.vcol_off > 0)
!                               wlv.n_extra -= wlv.vcol_off;
  # endif
                        }
                    }
***************
*** 2561,2567 ****
                        // Make sure, the highlighting for the tab char will be
                        // correctly set further below (effectively reverts the
                        // FIX_FOR_BOGSUCOLS macro).
!                       if (n_extra == tab_len + vc_saved && wp->w_p_list
                                                && wp->w_lcs_chars.tab1)
                            tab_len += vc_saved;
                    }
--- 2598,2604 ----
                        // Make sure, the highlighting for the tab char will be
                        // correctly set further below (effectively reverts the
                        // FIX_FOR_BOGSUCOLS macro).
!                       if (wlv.n_extra == tab_len + vc_saved && wp->w_p_list
                                                && wp->w_lcs_chars.tab1)
                            tab_len += vc_saved;
                    }
***************
*** 2569,2588 ****
                    mb_utf8 = FALSE;    // don't draw as UTF-8
                    if (wp->w_p_list)
                    {
!                       c = (n_extra == 0 && wp->w_lcs_chars.tab3)
                                                        ? wp->w_lcs_chars.tab3
                                                        : wp->w_lcs_chars.tab1;
  #ifdef FEAT_LINEBREAK
                        if (wp->w_p_lbr)
!                           c_extra = NUL; // using p_extra from above
                        else
  #endif
!                           c_extra = wp->w_lcs_chars.tab2;
!                       c_final = wp->w_lcs_chars.tab3;
                        n_attr = tab_len + 1;
                        extra_attr = hl_combine_attr(wlv.win_attr,
                                                               HL_ATTR(HLF_8));
!                       saved_attr2 = char_attr; // save current attr
                        mb_c = c;
                        if (enc_utf8 && utf_char2len(c) > 1)
                        {
--- 2606,2625 ----
                    mb_utf8 = FALSE;    // don't draw as UTF-8
                    if (wp->w_p_list)
                    {
!                       c = (wlv.n_extra == 0 && wp->w_lcs_chars.tab3)
                                                        ? wp->w_lcs_chars.tab3
                                                        : wp->w_lcs_chars.tab1;
  #ifdef FEAT_LINEBREAK
                        if (wp->w_p_lbr)
!                           wlv.c_extra = NUL; // using p_extra from above
                        else
  #endif
!                           wlv.c_extra = wp->w_lcs_chars.tab2;
!                       wlv.c_final = wp->w_lcs_chars.tab3;
                        n_attr = tab_len + 1;
                        extra_attr = hl_combine_attr(wlv.win_attr,
                                                               HL_ATTR(HLF_8));
!                       saved_attr2 = wlv.char_attr; // save current attr
                        mb_c = c;
                        if (enc_utf8 && utf_char2len(c) > 1)
                        {
***************
*** 2593,2600 ****
                    }
                    else
                    {
!                       c_final = NUL;
!                       c_extra = ' ';
                        c = ' ';
                    }
                }
--- 2630,2637 ----
                    }
                    else
                    {
!                       wlv.c_final = NUL;
!                       wlv.c_extra = ' ';
                        c = ' ';
                    }
                }
***************
*** 2620,2626 ****
                    // "$".
                    if (
  # ifdef FEAT_DIFF
!                           diff_hlf == (hlf_T)0
  #  ifdef LINE_ATTR
                            &&
  #  endif
--- 2657,2663 ----
                    // "$".
                    if (
  # ifdef FEAT_DIFF
!                           wlv.diff_hlf == (hlf_T)0
  #  ifdef LINE_ATTR
                            &&
  #  endif
***************
*** 2635,2647 ****
                        // beyond end of line.
                        if (area_highlighting && virtual_active()
                                && tocol != MAXCOL && wlv.vcol < tocol)
!                           n_extra = 0;
                        else
                        {
!                           p_extra = at_end_str;
!                           n_extra = 1;
!                           c_extra = NUL;
!                           c_final = NUL;
                        }
                    }
                    if (wp->w_p_list && wp->w_lcs_chars.eol > 0)
--- 2672,2684 ----
                        // beyond end of line.
                        if (area_highlighting && virtual_active()
                                && tocol != MAXCOL && wlv.vcol < tocol)
!                           wlv.n_extra = 0;
                        else
                        {
!                           wlv.p_extra = at_end_str;
!                           wlv.n_extra = 1;
!                           wlv.c_extra = NUL;
!                           wlv.c_final = NUL;
                        }
                    }
                    if (wp->w_p_list && wp->w_lcs_chars.eol > 0)
***************
*** 2668,2707 ****
                }
                else if (c != NUL)
                {
!                   p_extra = transchar_buf(wp->w_buffer, c);
!                   if (n_extra == 0)
!                       n_extra = byte2cells(c) - 1;
  #ifdef FEAT_RIGHTLEFT
                    if ((dy_flags & DY_UHEX) && wp->w_p_rl)
!                       rl_mirror(p_extra);     // reverse "<12>"
  #endif
!                   c_extra = NUL;
!                   c_final = NUL;
  #ifdef FEAT_LINEBREAK
                    if (wp->w_p_lbr)
                    {
                        char_u *p;
  
!                       c = *p_extra;
!                       p = alloc(n_extra + 1);
!                       vim_memset(p, ' ', n_extra);
!                       STRNCPY(p, p_extra + 1, STRLEN(p_extra) - 1);
!                       p[n_extra] = NUL;
                        vim_free(p_extra_free);
!                       p_extra_free = p_extra = p;
                    }
                    else
  #endif
                    {
!                       n_extra = byte2cells(c) - 1;
!                       c = *p_extra++;
                    }
                    if (!attr_pri)
                    {
!                       n_attr = n_extra + 1;
                        extra_attr = hl_combine_attr(wlv.win_attr,
                                                               HL_ATTR(HLF_8));
!                       saved_attr2 = char_attr; // save current attr
                    }
                    mb_utf8 = FALSE;    // don't draw as UTF-8
                }
--- 2705,2744 ----
                }
                else if (c != NUL)
                {
!                   wlv.p_extra = transchar_buf(wp->w_buffer, c);
!                   if (wlv.n_extra == 0)
!                       wlv.n_extra = byte2cells(c) - 1;
  #ifdef FEAT_RIGHTLEFT
                    if ((dy_flags & DY_UHEX) && wp->w_p_rl)
!                       rl_mirror(wlv.p_extra); // reverse "<12>"
  #endif
!                   wlv.c_extra = NUL;
!                   wlv.c_final = NUL;
  #ifdef FEAT_LINEBREAK
                    if (wp->w_p_lbr)
                    {
                        char_u *p;
  
!                       c = *wlv.p_extra;
!                       p = alloc(wlv.n_extra + 1);
!                       vim_memset(p, ' ', wlv.n_extra);
!                       STRNCPY(p, wlv.p_extra + 1, STRLEN(wlv.p_extra) - 1);
!                       p[wlv.n_extra] = NUL;
                        vim_free(p_extra_free);
!                       p_extra_free = wlv.p_extra = p;
                    }
                    else
  #endif
                    {
!                       wlv.n_extra = byte2cells(c) - 1;
!                       c = *wlv.p_extra++;
                    }
                    if (!attr_pri)
                    {
!                       n_attr = wlv.n_extra + 1;
                        extra_attr = hl_combine_attr(wlv.win_attr,
                                                               HL_ATTR(HLF_8));
!                       saved_attr2 = wlv.char_attr; // save current attr
                    }
                    mb_utf8 = FALSE;    // don't draw as UTF-8
                }
***************
*** 2723,2729 ****
  #if defined(LINE_ATTR)
                else if ((
  # ifdef FEAT_DIFF
!                           diff_hlf != (hlf_T)0 ||
  # endif
  # ifdef FEAT_TERMINAL
                            wlv.win_attr != 0 ||
--- 2760,2766 ----
  #if defined(LINE_ATTR)
                else if ((
  # ifdef FEAT_DIFF
!                           wlv.diff_hlf != (hlf_T)0 ||
  # endif
  # ifdef FEAT_TERMINAL
                            wlv.win_attr != 0 ||
***************
*** 2747,2788 ****
                    ++did_line_attr;
  
                    // don't do search HL for the rest of the line
!                   if (line_attr != 0 && char_attr == search_attr
                                        && (did_line_attr > 1
                                            || (wp->w_p_list &&
                                                wp->w_lcs_chars.eol > 0)))
!                       char_attr = line_attr;
  # ifdef FEAT_DIFF
!                   if (diff_hlf == HLF_TXD)
                    {
!                       diff_hlf = HLF_CHD;
!                       if (vi_attr == 0 || char_attr != vi_attr)
                        {
!                           char_attr = HL_ATTR(diff_hlf);
                            if (wp->w_p_cul && lnum == wp->w_cursor.lnum
                                    && wp->w_p_culopt_flags != CULOPT_NBR
!                                   && (!cul_screenline
                                        || (wlv.vcol >= left_curline_col
                                            && wlv.vcol <= right_curline_col)))
!                               char_attr = hl_combine_attr(
!                                         char_attr, HL_ATTR(HLF_CUL));
                        }
                    }
  # endif
  # ifdef FEAT_TERMINAL
                    if (wlv.win_attr != 0)
                    {
!                       char_attr = wlv.win_attr;
                        if (wp->w_p_cul && lnum == wp->w_cursor.lnum
                                    && wp->w_p_culopt_flags != CULOPT_NBR)
                        {
!                           if (!cul_screenline || (wlv.vcol >= left_curline_col
                                             && wlv.vcol <= right_curline_col))
!                               char_attr = hl_combine_attr(
!                                             char_attr, HL_ATTR(HLF_CUL));
                        }
                        else if (line_attr)
!                           char_attr = hl_combine_attr(char_attr, line_attr);
                    }
  # endif
                }
--- 2784,2827 ----
                    ++did_line_attr;
  
                    // don't do search HL for the rest of the line
!                   if (line_attr != 0 && wlv.char_attr == search_attr
                                        && (did_line_attr > 1
                                            || (wp->w_p_list &&
                                                wp->w_lcs_chars.eol > 0)))
!                       wlv.char_attr = line_attr;
  # ifdef FEAT_DIFF
!                   if (wlv.diff_hlf == HLF_TXD)
                    {
!                       wlv.diff_hlf = HLF_CHD;
!                       if (vi_attr == 0 || wlv.char_attr != vi_attr)
                        {
!                           wlv.char_attr = HL_ATTR(wlv.diff_hlf);
                            if (wp->w_p_cul && lnum == wp->w_cursor.lnum
                                    && wp->w_p_culopt_flags != CULOPT_NBR
!                                   && (!wlv.cul_screenline
                                        || (wlv.vcol >= left_curline_col
                                            && wlv.vcol <= right_curline_col)))
!                               wlv.char_attr = hl_combine_attr(
!                                         wlv.char_attr, HL_ATTR(HLF_CUL));
                        }
                    }
  # endif
  # ifdef FEAT_TERMINAL
                    if (wlv.win_attr != 0)
                    {
!                       wlv.char_attr = wlv.win_attr;
                        if (wp->w_p_cul && lnum == wp->w_cursor.lnum
                                    && wp->w_p_culopt_flags != CULOPT_NBR)
                        {
!                           if (!wlv.cul_screenline
!                                   || (wlv.vcol >= left_curline_col
                                             && wlv.vcol <= right_curline_col))
!                               wlv.char_attr = hl_combine_attr(
!                                             wlv.char_attr, HL_ATTR(HLF_CUL));
                        }
                        else if (line_attr)
!                           wlv.char_attr = hl_combine_attr(wlv.char_attr,
!                                                                   line_attr);
                    }
  # endif
                }
***************
*** 2797,2803 ****
                && !(lnum_in_visual_area
                                    && vim_strchr(wp->w_p_cocu, 'v') == NULL))
            {
!               char_attr = conceal_attr;
                if (((prev_syntax_id != syntax_seqnr
                                           && (syntax_flags & HL_CONCEAL) != 0)
                            || has_match_conc > 1)
--- 2836,2842 ----
                && !(lnum_in_visual_area
                                    && vim_strchr(wp->w_p_cocu, 'v') == NULL))
            {
!               wlv.char_attr = conceal_attr;
                if (((prev_syntax_id != syntax_seqnr
                                           && (syntax_flags & HL_CONCEAL) != 0)
                            || has_match_conc > 1)
***************
*** 2819,2843 ****
  
                    prev_syntax_id = syntax_seqnr;
  
!                   if (n_extra > 0)
!                       wlv.vcol_off += n_extra;
!                   wlv.vcol += n_extra;
!                   if (wp->w_p_wrap && n_extra > 0)
                    {
  # ifdef FEAT_RIGHTLEFT
                        if (wp->w_p_rl)
                        {
!                           wlv.col -= n_extra;
!                           wlv.boguscols -= n_extra;
                        }
                        else
  # endif
                        {
!                           wlv.boguscols += n_extra;
!                           wlv.col += n_extra;
                        }
                    }
!                   n_extra = 0;
                    n_attr = 0;
                }
                else if (n_skip == 0)
--- 2858,2882 ----
  
                    prev_syntax_id = syntax_seqnr;
  
!                   if (wlv.n_extra > 0)
!                       wlv.vcol_off += wlv.n_extra;
!                   wlv.vcol += wlv.n_extra;
!                   if (wp->w_p_wrap && wlv.n_extra > 0)
                    {
  # ifdef FEAT_RIGHTLEFT
                        if (wp->w_p_rl)
                        {
!                           wlv.col -= wlv.n_extra;
!                           wlv.boguscols -= wlv.n_extra;
                        }
                        else
  # endif
                        {
!                           wlv.boguscols += wlv.n_extra;
!                           wlv.col += wlv.n_extra;
                        }
                    }
!                   wlv.n_extra = 0;
                    n_attr = 0;
                }
                else if (n_skip == 0)
***************
*** 2871,2877 ****
  #ifdef FEAT_CONCEAL
        // In the cursor line and we may be concealing characters: correct
        // the cursor column when we reach its position.
!       if (!did_wcol && draw_state == WL_LINE
                && wp == curwin && lnum == wp->w_cursor.lnum
                && conceal_cursor_line(wp)
                && (int)wp->w_virtcol <= wlv.vcol + n_skip)
--- 2910,2916 ----
  #ifdef FEAT_CONCEAL
        // In the cursor line and we may be concealing characters: correct
        // the cursor column when we reach its position.
!       if (!did_wcol && wlv.draw_state == WL_LINE
                && wp == curwin && lnum == wp->w_cursor.lnum
                && conceal_cursor_line(wp)
                && (int)wp->w_virtcol <= wlv.vcol + n_skip)
***************
*** 2894,2908 ****
        // Use "extra_attr", but don't override visual selection highlighting.
        // Don't use "extra_attr" until n_attr_skip is zero.
        if (n_attr_skip == 0 && n_attr > 0
!               && draw_state == WL_LINE
                && !attr_pri)
        {
  #ifdef LINE_ATTR
            if (line_attr)
!               char_attr = hl_combine_attr(extra_attr, line_attr);
            else
  #endif
!               char_attr = extra_attr;
        }
  
  #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
--- 2933,2947 ----
        // Use "extra_attr", but don't override visual selection highlighting.
        // Don't use "extra_attr" until n_attr_skip is zero.
        if (n_attr_skip == 0 && n_attr > 0
!               && wlv.draw_state == WL_LINE
                && !attr_pri)
        {
  #ifdef LINE_ATTR
            if (line_attr)
!               wlv.char_attr = hl_combine_attr(extra_attr, line_attr);
            else
  #endif
!               wlv.char_attr = extra_attr;
        }
  
  #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
***************
*** 2915,2921 ****
                && (State & MODE_INSERT)
                && !p_imdisable
                && im_is_preediting()
!               && draw_state == WL_LINE)
        {
            colnr_T tcol;
  
--- 2954,2960 ----
                && (State & MODE_INSERT)
                && !p_imdisable
                && im_is_preediting()
!               && wlv.draw_state == WL_LINE)
        {
            colnr_T tcol;
  
***************
*** 2928,2943 ****
                if (feedback_old_attr < 0)
                {
                    feedback_col = 0;
!                   feedback_old_attr = char_attr;
                }
!               char_attr = im_get_feedback_attr(feedback_col);
!               if (char_attr < 0)
!                   char_attr = feedback_old_attr;
                feedback_col++;
            }
            else if (feedback_old_attr >= 0)
            {
!               char_attr = feedback_old_attr;
                feedback_old_attr = -1;
                feedback_col = 0;
            }
--- 2967,2982 ----
                if (feedback_old_attr < 0)
                {
                    feedback_col = 0;
!                   feedback_old_attr = wlv.char_attr;
                }
!               wlv.char_attr = im_get_feedback_attr(feedback_col);
!               if (wlv.char_attr < 0)
!                   wlv.char_attr = feedback_old_attr;
                feedback_col++;
            }
            else if (feedback_old_attr >= 0)
            {
!               wlv.char_attr = feedback_old_attr;
                feedback_old_attr = -1;
                feedback_col = 0;
            }
***************
*** 2954,2960 ****
  #ifdef FEAT_DIFF
                && filler_todo <= 0
  #endif
!               && draw_state > WL_NR
                && c != NUL)
        {
            c = wp->w_lcs_chars.prec;
--- 2993,2999 ----
  #ifdef FEAT_DIFF
                && filler_todo <= 0
  #endif
!               && wlv.draw_state > WL_NR
                && c != NUL)
        {
            c = wp->w_lcs_chars.prec;
***************
*** 2963,2971 ****
            {
                // Double-width character being overwritten by the "precedes"
                // character, need to fill up half the character.
!               c_extra = MB_FILLER_CHAR;
!               c_final = NUL;
!               n_extra = 1;
                n_attr = 2;
                extra_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
            }
--- 3002,3010 ----
            {
                // Double-width character being overwritten by the "precedes"
                // character, need to fill up half the character.
!               wlv.c_extra = MB_FILLER_CHAR;
!               wlv.c_final = NUL;
!               wlv.n_extra = 1;
                n_attr = 2;
                extra_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
            }
***************
*** 2980,2987 ****
                mb_utf8 = FALSE;        // don't draw as UTF-8
            if (!attr_pri)
            {
!               saved_attr3 = char_attr; // save current attr
!               char_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
                n_attr3 = 1;
            }
        }
--- 3019,3026 ----
                mb_utf8 = FALSE;        // don't draw as UTF-8
            if (!attr_pri)
            {
!               saved_attr3 = wlv.char_attr; // save current attr
!               wlv.char_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
                n_attr3 = 1;
            }
        }
***************
*** 3017,3023 ****
                                    && !(wp == curwin && VIsual_active))
  # endif
  # ifdef FEAT_DIFF
!                           && diff_hlf == (hlf_T)0
  # endif
  # if defined(LINE_ATTR)
                            && did_line_attr <= 1
--- 3056,3062 ----
                                    && !(wp == curwin && VIsual_active))
  # endif
  # ifdef FEAT_DIFF
!                           && wlv.diff_hlf == (hlf_T)0
  # endif
  # if defined(LINE_ATTR)
                            && did_line_attr <= 1
***************
*** 3060,3069 ****
                    // Use attributes from match with highest priority among
                    // 'search_hl' and the match list.
                    get_search_match_hl(wp, &screen_search_hl,
!                                              (long)(ptr - line), &char_attr);
                }
  #endif
!               ScreenAttrs[wlv.off] = char_attr;
                ScreenCols[wlv.off] = MAXCOL;
  #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
--- 3099,3108 ----
                    // Use attributes from match with highest priority among
                    // 'search_hl' and the match list.
                    get_search_match_hl(wp, &screen_search_hl,
!                                          (long)(ptr - line), &wlv.char_attr);
                }
  #endif
!               ScreenAttrs[wlv.off] = wlv.char_attr;
                ScreenCols[wlv.off] = MAXCOL;
  #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
***************
*** 3104,3110 ****
        // Show "extends" character from 'listchars' if beyond the line end and
        // 'list' is set.
        if (wp->w_lcs_chars.ext != NUL
!               && draw_state == WL_LINE
                && wp->w_p_list
                && !wp->w_p_wrap
  #ifdef FEAT_DIFF
--- 3143,3149 ----
        // Show "extends" character from 'listchars' if beyond the line end and
        // 'list' is set.
        if (wp->w_lcs_chars.ext != NUL
!               && wlv.draw_state == WL_LINE
                && wp->w_p_list
                && !wp->w_p_wrap
  #ifdef FEAT_DIFF
***************
*** 3117,3126 ****
                    wlv.col == wp->w_width - 1)
                && (*ptr != NUL
                    || (wp->w_p_list && lcs_eol_one > 0)
!                   || (n_extra && (c_extra != NUL || *p_extra != NUL))))
        {
            c = wp->w_lcs_chars.ext;
!           char_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
            mb_c = c;
            if (enc_utf8 && utf_char2len(c) > 1)
            {
--- 3156,3166 ----
                    wlv.col == wp->w_width - 1)
                && (*ptr != NUL
                    || (wp->w_p_list && lcs_eol_one > 0)
!                   || (wlv.n_extra && (wlv.c_extra != NUL
!                                                    || *wlv.p_extra != NUL))))
        {
            c = wp->w_lcs_chars.ext;
!           wlv.char_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
            mb_c = c;
            if (enc_utf8 && utf_char2len(c) > 1)
            {
***************
*** 3144,3153 ****
        // Also highlight the 'colorcolumn' if 'breakindent' and/or 'showbreak'
        // options are set
        vcol_save_attr = -1;
!       if (((draw_state == WL_LINE ||
!            draw_state == WL_BRI ||
!            draw_state == WL_SBR) && !lnum_in_visual_area
!               && search_attr == 0 && area_attr == 0)
  # ifdef FEAT_DIFF
                        && filler_todo <= 0
  # endif
--- 3184,3195 ----
        // Also highlight the 'colorcolumn' if 'breakindent' and/or 'showbreak'
        // options are set
        vcol_save_attr = -1;
!       if (((wlv.draw_state == WL_LINE
!                   || wlv.draw_state == WL_BRI
!                   || wlv.draw_state == WL_SBR)
!               && !lnum_in_visual_area
!               && search_attr == 0
!               && area_attr == 0)
  # ifdef FEAT_DIFF
                        && filler_todo <= 0
  # endif
***************
*** 3156,3168 ****
            if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol
                                                 && lnum != wp->w_cursor.lnum)
            {
!               vcol_save_attr = char_attr;
!               char_attr = hl_combine_attr(char_attr, HL_ATTR(HLF_CUC));
            }
            else if (wlv.draw_color_col && VCOL_HLC == *wlv.color_cols)
            {
!               vcol_save_attr = char_attr;
!               char_attr = hl_combine_attr(char_attr, HL_ATTR(HLF_MC));
            }
        }
  #endif
--- 3198,3211 ----
            if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol
                                                 && lnum != wp->w_cursor.lnum)
            {
!               vcol_save_attr = wlv.char_attr;
!               wlv.char_attr = hl_combine_attr(wlv.char_attr,
!                                                            HL_ATTR(HLF_CUC));
            }
            else if (wlv.draw_color_col && VCOL_HLC == *wlv.color_cols)
            {
!               vcol_save_attr = wlv.char_attr;
!               wlv.char_attr = hl_combine_attr(wlv.char_attr, HL_ATTR(HLF_MC));
            }
        }
  #endif
***************
*** 3170,3176 ****
        // Store character to be displayed.
        // Skip characters that are left of the screen for 'nowrap'.
        vcol_prev = wlv.vcol;
!       if (draw_state < WL_LINE || n_skip <= 0)
        {
            // Store the character.
  #if defined(FEAT_RIGHTLEFT)
--- 3213,3219 ----
        // Store character to be displayed.
        // Skip characters that are left of the screen for 'nowrap'.
        vcol_prev = wlv.vcol;
!       if (wlv.draw_state < WL_LINE || n_skip <= 0)
        {
            // Store the character.
  #if defined(FEAT_RIGHTLEFT)
***************
*** 3213,3219 ****
                multi_attr = 0;
            }
            else
!               ScreenAttrs[wlv.off] = char_attr;
  
            ScreenCols[wlv.off] = (colnr_T)(prev_ptr - line);
  
--- 3256,3262 ----
                multi_attr = 0;
            }
            else
!               ScreenAttrs[wlv.off] = wlv.char_attr;
  
            ScreenCols[wlv.off] = (colnr_T)(prev_ptr - line);
  
***************
*** 3228,3234 ****
                else
                    // DBCS: Put second byte in the second screen char.
                    ScreenLines[wlv.off] = mb_c & 0xff;
!               if (draw_state > WL_NR
  #ifdef FEAT_DIFF
                        && filler_todo <= 0
  #endif
--- 3271,3277 ----
                else
                    // DBCS: Put second byte in the second screen char.
                    ScreenLines[wlv.off] = mb_c & 0xff;
!               if (wlv.draw_state > WL_NR
  #ifdef FEAT_DIFF
                        && filler_todo <= 0
  #endif
***************
*** 3268,3275 ****
        {
            --n_skip;
            ++wlv.vcol_off;
!           if (n_extra > 0)
!               wlv.vcol_off += n_extra;
            if (wp->w_p_wrap)
            {
                // Special voodoo required if 'wrap' is on.
--- 3311,3318 ----
        {
            --n_skip;
            ++wlv.vcol_off;
!           if (wlv.n_extra > 0)
!               wlv.vcol_off += wlv.n_extra;
            if (wp->w_p_wrap)
            {
                // Special voodoo required if 'wrap' is on.
***************
*** 3283,3304 ****
                // trailing junk to be written out of the screen line
                // we are building, 'boguscols' keeps track of the number
                // of bad columns we have advanced.
!               if (n_extra > 0)
                {
!                   wlv.vcol += n_extra;
  # ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
                    {
!                       wlv.col -= n_extra;
!                       wlv.boguscols -= n_extra;
                    }
                    else
  # endif
                    {
!                       wlv.col += n_extra;
!                       wlv.boguscols += n_extra;
                    }
!                   n_extra = 0;
                    n_attr = 0;
                }
  
--- 3326,3347 ----
                // trailing junk to be written out of the screen line
                // we are building, 'boguscols' keeps track of the number
                // of bad columns we have advanced.
!               if (wlv.n_extra > 0)
                {
!                   wlv.vcol += wlv.n_extra;
  # ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
                    {
!                       wlv.col -= wlv.n_extra;
!                       wlv.boguscols -= wlv.n_extra;
                    }
                    else
  # endif
                    {
!                       wlv.col += wlv.n_extra;
!                       wlv.boguscols += wlv.n_extra;
                    }
!                   wlv.n_extra = 0;
                    n_attr = 0;
                }
  
***************
*** 3335,3344 ****
            }
            else
            {
!               if (n_extra > 0)
                {
!                   wlv.vcol += n_extra;
!                   n_extra = 0;
                    n_attr = 0;
                }
            }
--- 3378,3387 ----
            }
            else
            {
!               if (wlv.n_extra > 0)
                {
!                   wlv.vcol += wlv.n_extra;
!                   wlv.n_extra = 0;
                    n_attr = 0;
                }
            }
***************
*** 3350,3356 ****
  
        // Only advance the "wlv.vcol" when after the 'number' or
        // 'relativenumber' column.
!       if (draw_state > WL_NR
  #ifdef FEAT_DIFF
                && filler_todo <= 0
  #endif
--- 3393,3399 ----
  
        // Only advance the "wlv.vcol" when after the 'number' or
        // 'relativenumber' column.
!       if (wlv.draw_state > WL_NR
  #ifdef FEAT_DIFF
                && filler_todo <= 0
  #endif
***************
*** 3359,3375 ****
  
  #ifdef FEAT_SYN_HL
        if (vcol_save_attr >= 0)
!           char_attr = vcol_save_attr;
  #endif
  
        // restore attributes after "predeces" in 'listchars'
!       if (draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0)
!           char_attr = saved_attr3;
  
        // restore attributes after last 'listchars' or 'number' char
!       if (n_attr > 0 && draw_state == WL_LINE
                                          && n_attr_skip == 0 && --n_attr == 0)
!           char_attr = saved_attr2;
        if (n_attr_skip > 0)
            --n_attr_skip;
  
--- 3402,3418 ----
  
  #ifdef FEAT_SYN_HL
        if (vcol_save_attr >= 0)
!           wlv.char_attr = vcol_save_attr;
  #endif
  
        // restore attributes after "predeces" in 'listchars'
!       if (wlv.draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0)
!           wlv.char_attr = saved_attr3;
  
        // restore attributes after last 'listchars' or 'number' char
!       if (n_attr > 0 && wlv.draw_state == WL_LINE
                                          && n_attr_skip == 0 && --n_attr == 0)
!           wlv.char_attr = saved_attr2;
        if (n_attr_skip > 0)
            --n_attr_skip;
  
***************
*** 3380,3386 ****
            wp->w_p_rl ? (wlv.col < 0) :
  #endif
                                    (wlv.col >= wp->w_width))
!               && (draw_state != WL_LINE
                    || *ptr != NUL
  #ifdef FEAT_DIFF
                    || filler_todo > 0
--- 3423,3429 ----
            wp->w_p_rl ? (wlv.col < 0) :
  #endif
                                    (wlv.col >= wp->w_width))
!               && (wlv.draw_state != WL_LINE
                    || *ptr != NUL
  #ifdef FEAT_DIFF
                    || filler_todo > 0
***************
*** 3389,3396 ****
                    || text_prop_follows
  #endif
                    || (wp->w_p_list && wp->w_lcs_chars.eol != NUL
!                                               && p_extra != at_end_str)
!                   || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL)))
                )
        {
  #ifdef FEAT_CONCEAL
--- 3432,3440 ----
                    || text_prop_follows
  #endif
                    || (wp->w_p_list && wp->w_lcs_chars.eol != NUL
!                                               && wlv.p_extra != at_end_str)
!                   || (wlv.n_extra != 0 && (wlv.c_extra != NUL
!                                                     || *wlv.p_extra != NUL)))
                )
        {
  #ifdef FEAT_CONCEAL
***************
*** 3418,3424 ****
                break;
  
            // When the window is too narrow draw all "@" lines.
!           if (draw_state != WL_LINE
  #ifdef FEAT_DIFF
                    && filler_todo <= 0
  #endif
--- 3462,3468 ----
                break;
  
            // When the window is too narrow draw all "@" lines.
!           if (wlv.draw_state != WL_LINE
  #ifdef FEAT_DIFF
                    && filler_todo <= 0
  #endif
***************
*** 3495,3519 ****
                }
            }
  
!           win_line_start(wp, &wlv);
  
-           // reset the drawing state for the start of a wrapped line
-           draw_state = WL_START;
-           saved_n_extra = n_extra;
-           saved_p_extra = p_extra;
-           saved_c_extra = c_extra;
-           saved_c_final = c_final;
- #ifdef FEAT_SYN_HL
-           if (!(cul_screenline
- # ifdef FEAT_DIFF
-                       && diff_hlf == (hlf_T)0
- # endif
-                   ))
-               saved_char_attr = char_attr;
-           else
- #endif
-               saved_char_attr = 0;
-           n_extra = 0;
            lcs_prec_todo = wp->w_lcs_chars.prec;
  #ifdef FEAT_LINEBREAK
            if (!dont_use_showbreak
--- 3539,3546 ----
                }
            }
  
!           win_line_start(wp, &wlv, TRUE);
  
            lcs_prec_todo = wp->w_lcs_chars.prec;
  #ifdef FEAT_LINEBREAK
            if (!dont_use_showbreak
***************
*** 3545,3550 ****
--- 3572,3578 ----
  #ifdef FEAT_PROP_POPUP
      vim_free(text_props);
      vim_free(text_prop_idxs);
+     vim_free(p_extra_free2);
  #endif
  
      vim_free(p_extra_free);
*** ../vim-9.0.0152/src/testdir/test_textprop.vim       2022-08-06 
13:47:16.212982332 +0100
--- src/testdir/test_textprop.vim       2022-08-06 15:42:24.326934307 +0100
***************
*** 2443,2448 ****
--- 2443,2451 ----
    let buf = RunVimInTerminal('-S XscriptPropsAfterNowrap', #{rows: 8, cols: 
60})
    call VerifyScreenDump(buf, 'Test_prop_with_text_after_nowrap_1', {})
  
+   call term_sendkeys(buf, ":set signcolumn=yes foldcolumn=3\<CR>")
+   call VerifyScreenDump(buf, 'Test_prop_with_text_after_nowrap_2', {})
+ 
    call StopVimInTerminal(buf)
    call delete('XscriptPropsAfterNowrap')
  endfunc
*** ../vim-9.0.0152/src/testdir/dumps/Test_prop_with_text_after_nowrap_2.dump   
2022-08-06 15:58:31.386940143 +0100
--- src/testdir/dumps/Test_prop_with_text_after_nowrap_2.dump   2022-08-06 
15:44:15.283043203 +0100
***************
*** 0 ****
--- 1,8 ----
+ | +0#0000e05#a8a8a8255@4|o+0#0000000#ffffff0|n|e| @51
+ | +0#0000e05#a8a8a8255@4| +0#ffffff16#e000002|B|e|l|o|w| |t|h|e| |l|i|n|e| | 
+0#0000000#ffffff0@38
+ | +0#0000e05#a8a8a8255@4|t+0#0000000#ffffff0|w|o| @51
+ | +0#0000e05#a8a8a8255@4|a+0#0000000#ffff4012|n|o|t|h|e|r| +0&#ffffff0@47
+ | +0#0000e05#a8a8a8255@4|O+0#ffffff16#e000002|n|e| |M|o|r|e| |H|e|r|e| 
+0#0000000#ffffff0@41
+ | +0#0000e05#a8a8a8255@4|t+0#0000000#ffffff0|h|r|e>e| @49
+ |~+0#4040ff13&| @58
+ | +0#0000000&@41|3|,|5| @10|A|l@1| 
*** ../vim-9.0.0152/src/version.c       2022-08-06 14:21:48.902455645 +0100
--- src/version.c       2022-08-06 15:44:08.071037507 +0100
***************
*** 737,738 ****
--- 737,740 ----
  {   /* Add new patch number below this line */
+ /**/
+     153,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
255. You work for a newspaper and your editor asks you to write an
     article about Internet addiction...in the "first person."

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220806151045.197441C0F2E%40moolenaar.net.

Raspunde prin e-mail lui