Patch 9.0.0151
Problem:    A "below" aligned text property does not work with 'nowrap'.
Solution:   Start a new screen line to display the virtual text.
            (closes #10851)
Files:      src/drawline.c, src/textprop.c, src/proto/textprop.pro,
            src/misc1.c, src/testdir/test_textprop.vim,
            src/testdir/dumps/Test_prop_with_text_after_nowrap_1.dump


*** ../vim-9.0.0150/src/drawline.c      2022-08-05 21:39:26.956564292 +0100
--- src/drawline.c      2022-08-06 13:08:05.957342921 +0100
***************
*** 249,254 ****
--- 249,392 ----
  }
  #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.
+  */
+     static void
+ draw_screen_line(win_T *wp, winlinevars_T *wlv)
+ {
+ #ifdef FEAT_SYN_HL
+     long      v;
+ 
+     // Highlight 'cursorcolumn' & 'colorcolumn' past end of the line.
+     if (wp->w_p_wrap)
+       v = wp->w_skipcol;
+     else
+       v = wp->w_leftcol;
+ 
+     // check if line ends before left margin
+     if (wlv->vcol < v + wlv->col - win_col_off(wp))
+       wlv->vcol = v + wlv->col - win_col_off(wp);
+ # ifdef FEAT_CONCEAL
+     // Get rid of the boguscols now, we want to draw until the right
+     // edge for 'cursorcolumn'.
+     wlv->col -= wlv->boguscols;
+     wlv->boguscols = 0;
+ #  define VCOL_HLC (wlv->vcol - wlv->vcol_off)
+ # else
+ #  define VCOL_HLC (wlv->vcol)
+ # endif
+ 
+     if (wlv->draw_color_col)
+       wlv->draw_color_col = advance_color_col(VCOL_HLC, &wlv->color_cols);
+ 
+     if (((wp->w_p_cuc
+                   && (int)wp->w_virtcol >= VCOL_HLC - wlv->eol_hl_off
+                   && (int)wp->w_virtcol <
+                        (long)wp->w_width * (wlv->row - wlv->startrow + 1) + v
+                        && wlv->lnum != wp->w_cursor.lnum)
+           || wlv->draw_color_col
+           || wlv->win_attr != 0)
+ # ifdef FEAT_RIGHTLEFT
+           && !wp->w_p_rl
+ # endif
+           )
+     {
+       int     rightmost_vcol = 0;
+       int     i;
+ 
+       if (wp->w_p_cuc)
+           rightmost_vcol = wp->w_virtcol;
+       if (wlv->draw_color_col)
+           // determine rightmost colorcolumn to possibly draw
+           for (i = 0; wlv->color_cols[i] >= 0; ++i)
+               if (rightmost_vcol < wlv->color_cols[i])
+                   rightmost_vcol = wlv->color_cols[i];
+ 
+       while (wlv->col < wp->w_width)
+       {
+           ScreenLines[wlv->off] = ' ';
+           if (enc_utf8)
+               ScreenLinesUC[wlv->off] = 0;
+           ScreenCols[wlv->off] = MAXCOL;
+           ++wlv->col;
+           if (wlv->draw_color_col)
+               wlv->draw_color_col = advance_color_col(
+                                                  VCOL_HLC, &wlv->color_cols);
+ 
+           if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol)
+               ScreenAttrs[wlv->off++] = HL_ATTR(HLF_CUC);
+           else if (wlv->draw_color_col && VCOL_HLC == *wlv->color_cols)
+               ScreenAttrs[wlv->off++] = HL_ATTR(HLF_MC);
+           else
+               ScreenAttrs[wlv->off++] = wlv->win_attr;
+ 
+           if (VCOL_HLC >= rightmost_vcol && wlv->win_attr == 0)
+               break;
+ 
+           ++wlv->vcol;
+       }
+     }
+ #endif
+ 
+     screen_line(wp, wlv->screen_row, wp->w_wincol, wlv->col,
+                                         wp->w_width, wlv->screen_line_flags);
+     ++wlv->row;
+     ++wlv->screen_row;
+ }
+ #undef VCOL_HLC
+ 
+ /*
+  * Start a screen line at column zero.
+  */
+     static void
+ win_line_start(win_T *wp, winlinevars_T *wlv)
+ {
+     wlv->col = 0;
+     wlv->off = (unsigned)(current_ScreenLine - ScreenLines);
+ 
+ #ifdef FEAT_RIGHTLEFT
+     if (wp->w_p_rl)
+     {
+       // Rightleft window: process the text in the normal direction, but put
+       // it in current_ScreenLine[] from right to left.  Start at the
+       // rightmost column of the window.
+       wlv->col = wp->w_width - 1;
+       wlv->off += wlv->col;
+       wlv->screen_line_flags |= SLF_RIGHTLEFT;
+     }
+ #endif
+ }
+ 
  /*
   * Display line "lnum" of window 'wp' on the screen.
   * Start at row "startrow", stop when "endrow" is reached.
***************
*** 265,282 ****
      int               nochange UNUSED,        // not updating for changed text
      int               number_only)            // only update the number column
  {
!     int               col = 0;                // visual column on screen
!     unsigned  off;                    // offset in ScreenLines/ScreenAttrs
      int               c = 0;                  // init for GCC
-     long      vcol = 0;               // virtual column (for tabs)
  #ifdef FEAT_LINEBREAK
      long      vcol_sbr = -1;          // virtual column after showbreak
  #endif
!     long      vcol_prev = -1;         // "vcol" of previous character
      char_u    *line;                  // current line
      char_u    *ptr;                   // current position in "line"
-     int               row;                    // row in the window, excl 
w_winrow
-     int               screen_row;             // row on the screen, incl 
w_winrow
  
      char_u    extra[21];              // "%ld " and 'fdc' must fit in here
      int               n_extra = 0;            // number of extra bytes
--- 403,417 ----
      int               nochange UNUSED,        // not updating for changed text
      int               number_only)            // only update the number column
  {
!     winlinevars_T     wlv;            // variables passed between functions
! 
      int               c = 0;                  // init for GCC
  #ifdef FEAT_LINEBREAK
      long      vcol_sbr = -1;          // virtual column after showbreak
  #endif
!     long      vcol_prev = -1;         // "wlv.vcol" of previous character
      char_u    *line;                  // current line
      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
***************
*** 324,331 ****
      int               vi_attr = 0;            // attributes for Visual and 
incsearch
                                        // highlighting
      int               wcr_attr = 0;           // attributes from 'wincolor'
-     int               win_attr = 0;           // background for whole window, 
except
-                                       // margins and "~" lines.
      int               area_attr = 0;          // attributes desired by 
highlighting
      int               search_attr = 0;        // attributes desired by 
'hlsearch'
  #ifdef FEAT_SYN_HL
--- 459,464 ----
***************
*** 335,344 ****
      int               prev_syntax_attr = 0;   // syntax_attr at 
prev_syntax_col
      int               has_syntax = FALSE;     // this buffer has syntax highl.
      int               save_did_emsg;
-     int               draw_color_col = FALSE; // highlight colorcolumn
-     int               *color_cols = NULL;     // pointer to according columns 
array
  #endif
-     int               eol_hl_off = 0;         // 1 if highlighted char after 
EOL
  #ifdef FEAT_PROP_POPUP
      int               text_prop_count;
      int               text_prop_next = 0;     // next text property to use
--- 468,474 ----
***************
*** 461,467 ****
      int               feedback_col = 0;
      int               feedback_old_attr = -1;
  #endif
-     int               screen_line_flags = 0;
  
  #if defined(FEAT_CONCEAL) || defined(FEAT_SEARCH_EXTRA)
      int               match_conc      = 0;    // cchar for match functions
--- 591,596 ----
***************
*** 473,502 ****
      int               prev_syntax_id  = 0;
      int               conceal_attr    = HL_ATTR(HLF_CONCEAL);
      int               is_concealing   = FALSE;
-     int               boguscols       = 0;    // nonexistent columns added to 
force
-                                       // wrapping
-     int               vcol_off        = 0;    // offset for concealed 
characters
      int               did_wcol        = FALSE;
      int               old_boguscols   = 0;
! # define VCOL_HLC (vcol - vcol_off)
  # define FIX_FOR_BOGUSCOLS \
      { \
!       n_extra += vcol_off; \
!       vcol -= vcol_off; \
!       vcol_off = 0; \
!       col -= boguscols; \
!       old_boguscols = boguscols; \
!       boguscols = 0; \
      }
  #else
! # define VCOL_HLC (vcol)
  #endif
  
      if (startrow > endrow)            // past the end already!
        return startrow;
  
!     row = startrow;
!     screen_row = row + W_WINROW(wp);
  
      if (!number_only)
      {
--- 602,632 ----
      int               prev_syntax_id  = 0;
      int               conceal_attr    = HL_ATTR(HLF_CONCEAL);
      int               is_concealing   = FALSE;
      int               did_wcol        = FALSE;
      int               old_boguscols   = 0;
! # 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; \
!       old_boguscols = wlv.boguscols; \
!       wlv.boguscols = 0; \
      }
  #else
! # define VCOL_HLC (wlv.vcol)
  #endif
  
      if (startrow > endrow)            // past the end already!
        return startrow;
  
!     CLEAR_FIELD(wlv);
! 
!     wlv.lnum = lnum;
!     wlv.startrow = startrow;
!     wlv.row = startrow;
!     wlv.screen_row = wlv.row + W_WINROW(wp);
  
      if (!number_only)
      {
***************
*** 533,541 ****
        }
  
        // Check for columns to display for 'colorcolumn'.
!       color_cols = wp->w_p_cc_cols;
!       if (color_cols != NULL)
!           draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
  #endif
  
  #ifdef FEAT_TERMINAL
--- 663,671 ----
        }
  
        // Check for columns to display for 'colorcolumn'.
!       wlv.color_cols = wp->w_p_cc_cols;
!       if (wlv.color_cols != NULL)
!           wlv.draw_color_col = advance_color_col(VCOL_HLC, &wlv.color_cols);
  #endif
  
  #ifdef FEAT_TERMINAL
***************
*** 543,549 ****
        {
            extra_check = TRUE;
            get_term_attr = TRUE;
!           win_attr = term_get_attr(wp, lnum, -1);
        }
  #endif
  
--- 673,679 ----
        {
            extra_check = TRUE;
            get_term_attr = TRUE;
!           wlv.win_attr = term_get_attr(wp, lnum, -1);
        }
  #endif
  
***************
*** 823,835 ****
      wcr_attr = get_wcr_attr(wp);
      if (wcr_attr != 0)
      {
!       win_attr = wcr_attr;
        area_highlighting = TRUE;
      }
  
  #ifdef FEAT_PROP_POPUP
      if (WIN_IS_POPUP(wp))
!       screen_line_flags |= SLF_POPUP;
  #endif
  
      // 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the
--- 953,965 ----
      wcr_attr = get_wcr_attr(wp);
      if (wcr_attr != 0)
      {
!       wlv.win_attr = wcr_attr;
        area_highlighting = TRUE;
      }
  
  #ifdef FEAT_PROP_POPUP
      if (WIN_IS_POPUP(wp))
!       wlv.screen_line_flags |= SLF_POPUP;
  #endif
  
      // 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the
***************
*** 844,850 ****
        chartabsize_T   cts;
        int             charsize = 0;
  
!       init_chartabsize_arg(&cts, wp, lnum, vcol, line, ptr);
        while (cts.cts_vcol < v && *cts.cts_ptr != NUL)
        {
            charsize = win_lbr_chartabsize(&cts, NULL);
--- 974,980 ----
        chartabsize_T   cts;
        int             charsize = 0;
  
!       init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, ptr);
        while (cts.cts_vcol < v && *cts.cts_ptr != NUL)
        {
            charsize = win_lbr_chartabsize(&cts, NULL);
***************
*** 852,858 ****
            prev_ptr = cts.cts_ptr;
            MB_PTR_ADV(cts.cts_ptr);
        }
!       vcol = cts.cts_vcol;
        ptr = cts.cts_ptr;
        clear_chartabsize_arg(&cts);
  
--- 982,988 ----
            prev_ptr = cts.cts_ptr;
            MB_PTR_ADV(cts.cts_ptr);
        }
!       wlv.vcol = cts.cts_vcol;
        ptr = cts.cts_ptr;
        clear_chartabsize_arg(&cts);
  
***************
*** 862,893 ****
        // - 'virtualedit' is set, or
        // - the visual mode is active,
        // the end of the line may be before the start of the displayed part.
!       if (vcol < v && (
  #ifdef FEAT_SYN_HL
!            wp->w_p_cuc || draw_color_col ||
  #endif
             virtual_active() ||
             (VIsual_active && wp->w_buffer == curwin->w_buffer)))
!           vcol = v;
  
        // Handle a character that's not completely on the screen: Put ptr at
        // that character but skip the first few screen characters.
!       if (vcol > v)
        {
!           vcol -= charsize;
            ptr = prev_ptr;
            // If the character fits on the screen, don't need to skip it.
            // Except for a TAB.
!           if (( (*mb_ptr2cells)(ptr) >= charsize || *ptr == TAB) && col == 0)
!              n_skip = v - vcol;
        }
  
        // Adjust for when the inverted text is before the screen,
        // and when the start of the inverted text is before the screen.
!       if (tocol <= vcol)
            fromcol = 0;
!       else if (fromcol >= 0 && fromcol < vcol)
!           fromcol = vcol;
  
  #ifdef FEAT_LINEBREAK
        // When w_skipcol is non-zero, first line needs 'showbreak'
--- 992,1024 ----
        // - 'virtualedit' is set, or
        // - the visual mode is active,
        // the end of the line may be before the start of the displayed part.
!       if (wlv.vcol < v && (
  #ifdef FEAT_SYN_HL
!            wp->w_p_cuc || wlv.draw_color_col ||
  #endif
             virtual_active() ||
             (VIsual_active && wp->w_buffer == curwin->w_buffer)))
!           wlv.vcol = v;
  
        // Handle a character that's not completely on the screen: Put ptr at
        // that character but skip the first few screen characters.
!       if (wlv.vcol > v)
        {
!           wlv.vcol -= charsize;
            ptr = prev_ptr;
            // If the character fits on the screen, don't need to skip it.
            // Except for a TAB.
!           if (((*mb_ptr2cells)(ptr) >= charsize || *ptr == TAB)
!                                                              && wlv.col == 0)
!              n_skip = v - wlv.vcol;
        }
  
        // Adjust for when the inverted text is before the screen,
        // and when the start of the inverted text is before the screen.
!       if (tocol <= wlv.vcol)
            fromcol = 0;
!       else if (fromcol >= 0 && fromcol < wlv.vcol)
!           fromcol = wlv.vcol;
  
  #ifdef FEAT_LINEBREAK
        // When w_skipcol is non-zero, first line needs 'showbreak'
***************
*** 1039,1058 ****
      }
  #endif
  
!     off = (unsigned)(current_ScreenLine - ScreenLines);
!     col = 0;
! 
! #ifdef FEAT_RIGHTLEFT
!     if (wp->w_p_rl)
!     {
!       // Rightleft window: process the text in the normal direction, but put
!       // it in current_ScreenLine[] from right to left.  Start at the
!       // rightmost column of the window.
!       col = wp->w_width - 1;
!       off += col;
!       screen_line_flags |= SLF_RIGHTLEFT;
!     }
! #endif
  
      // Repeat for the whole displayed line.
      for (;;)
--- 1170,1176 ----
      }
  #endif
  
!     win_line_start(wp, &wlv);
  
      // Repeat for the whole displayed line.
      for (;;)
***************
*** 1130,1137 ****
                // buffer or when using Netbeans.
                if (signcolumn_on(wp))
                    get_sign_display_info(FALSE, wp, lnum, &sattr, wcr_attr,
!                           row, startrow, filler_lines, filler_todo, &c_extra,
!                           &c_final, extra, &p_extra, &n_extra, &char_attr);
            }
  #endif
  
--- 1248,1256 ----
                // 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
  
***************
*** 1141,1148 ****
                // 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)
!                       && (row == startrow + filler_lines
!                           || vim_strchr(p_cpo, CPO_NUMCOL) == NULL))
                {
  #ifdef FEAT_SIGNS
                    // If 'signcolumn' is set to 'number' and a sign is present
--- 1260,1267 ----
                // 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)
!                       && (wlv.row == startrow + filler_lines
!                                    || vim_strchr(p_cpo, CPO_NUMCOL) == NULL))
                {
  #ifdef FEAT_SIGNS
                    // If 'signcolumn' is set to 'number' and a sign is present
***************
*** 1151,1164 ****
                    if ((*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')
                            && sign_present)
                        get_sign_display_info(TRUE, wp, lnum, &sattr, wcr_attr,
!                               row, startrow, filler_lines, filler_todo,
                                &c_extra, &c_final, extra, &p_extra, &n_extra,
                                &char_attr);
                    else
  #endif
                    {
                      // Draw the line number (empty space after wrapping).
!                     if (row == startrow + filler_lines)
                      {
                        long num;
                        char *fmt = "%*ld ";
--- 1270,1283 ----
                    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
                    {
                      // Draw the line number (empty space after wrapping).
!                     if (wlv.row == startrow + filler_lines)
                      {
                        long num;
                        char *fmt = "%*ld ";
***************
*** 1221,1228 ****
                      if (wp->w_p_cul
                              && lnum == wp->w_cursor.lnum
                              && (wp->w_p_culopt_flags & CULOPT_NBR)
!                             && (row == startrow + filler_lines
!                                 || (row > startrow + filler_lines
                                     && (wp->w_p_culopt_flags & CULOPT_LINE))))
                        char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLN));
  #endif
--- 1340,1347 ----
                      if (wp->w_p_cul
                              && lnum == wp->w_cursor.lnum
                              && (wp->w_p_culopt_flags & CULOPT_NBR)
!                             && (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
***************
*** 1258,1264 ****
            {
                draw_state = WL_BRI;
                // if need_showbreak is set, breakindent also applies
!               if (wp->w_p_bri && (row != startrow || need_showbreak)
  # ifdef FEAT_DIFF
                        && filler_lines == 0
  # endif
--- 1377,1383 ----
            {
                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
                        && filler_lines == 0
  # endif
***************
*** 1274,1280 ****
                    c_final = NUL;
                    n_extra = get_breakindent_win(wp,
                                       ml_get_buf(wp->w_buffer, lnum, FALSE));
!                   if (row == startrow)
                    {
                        n_extra -= win_col_off2(wp);
                        if (n_extra < 0)
--- 1393,1399 ----
                    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)
***************
*** 1284,1290 ****
                        need_showbreak = FALSE;
                    // Correct end of highlighted area for 'breakindent',
                    // required when 'linebreak' is also set.
!                   if (tocol == vcol)
                        tocol += n_extra;
                }
            }
--- 1403,1409 ----
                        need_showbreak = FALSE;
                    // Correct end of highlighted area for 'breakindent',
                    // required when 'linebreak' is also set.
!                   if (tocol == wlv.vcol)
                        tocol += n_extra;
                }
            }
***************
*** 1312,1321 ****
                    }
  #  ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
!                       n_extra = col + 1;
                    else
  #  endif
!                       n_extra = wp->w_width - col;
                    char_attr = HL_ATTR(HLF_DED);
                }
  # endif
--- 1431,1440 ----
                    }
  #  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
***************
*** 1330,1342 ****
                    n_extra = (int)STRLEN(sbr);
                    if (wp->w_skipcol == 0 || !wp->w_p_wrap)
                        need_showbreak = FALSE;
!                   vcol_sbr = vcol + MB_CHARLEN(sbr);
                    // Correct end of highlighted area for 'showbreak',
                    // required when 'linebreak' is also set.
!                   if (tocol == vcol)
                        tocol += n_extra;
                    // combine 'showbreak' with 'wincolor'
!                   char_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
  #  ifdef FEAT_SYN_HL
                    // combine 'showbreak' with 'cursorline'
                    if (cul_attr != 0)
--- 1449,1461 ----
                    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)
***************
*** 1360,1372 ****
                    char_attr = saved_char_attr;
                }
                else
!                   char_attr = win_attr;
            }
        }
  #ifdef FEAT_SYN_HL
        if (cul_screenline && draw_state == WL_LINE
!               && vcol >= left_curline_col
!               && vcol < right_curline_col)
        {
            cul_attr = HL_ATTR(HLF_CUL);
            line_attr = cul_attr;
--- 1479,1491 ----
                    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)
        {
            cul_attr = HL_ATTR(HLF_CUL);
            line_attr = cul_attr;
***************
*** 1377,1415 ****
        // When only displaying the (relative) line number and that's done,
        // stop here.
        if (((dollar_vcol >= 0 && wp == curwin
!                  && lnum == wp->w_cursor.lnum && vcol >= (long)wp->w_virtcol)
                || (number_only && draw_state > WL_NR))
  #ifdef FEAT_DIFF
                                   && filler_todo <= 0
  #endif
                )
        {
!           screen_line(wp, screen_row, wp->w_wincol, col, -wp->w_width,
!                                                           screen_line_flags);
            // Pretend we have finished updating the window.  Except when
            // 'cursorcolumn' is set.
  #ifdef FEAT_SYN_HL
            if (wp->w_p_cuc)
!               row = wp->w_cline_row + wp->w_cline_height;
            else
  #endif
!               row = wp->w_height;
            break;
        }
  
        if (draw_state == WL_LINE && (area_highlighting || extra_check))
        {
            // handle Visual or match highlighting in this line
!           if (vcol == fromcol
!                   || (has_mbyte && vcol + 1 == fromcol && n_extra == 0
                        && (*mb_ptr2cells)(ptr) > 1)
                    || ((int)vcol_prev == fromcol_prev
!                       && vcol_prev < vcol     // not at margin
!                       && vcol < tocol))
                area_attr = vi_attr;            // start highlighting
            else if (area_attr != 0
!                   && (vcol == tocol
!                       || (noinvcur && (colnr_T)vcol == wp->w_virtcol)))
                area_attr = 0;                  // stop highlighting
  
  #ifdef FEAT_SEARCH_EXTRA
--- 1496,1534 ----
        // When only displaying the (relative) line number and that's done,
        // 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
                )
        {
!           screen_line(wp, wlv.screen_row, wp->w_wincol, wlv.col, -wp->w_width,
!                                                       wlv.screen_line_flags);
            // Pretend we have finished updating the window.  Except when
            // 'cursorcolumn' is set.
  #ifdef FEAT_SYN_HL
            if (wp->w_p_cuc)
!               wlv.row = wp->w_cline_row + wp->w_cline_height;
            else
  #endif
!               wlv.row = wp->w_height;
            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
!                       && wlv.vcol < tocol))
                area_attr = vi_attr;            // start highlighting
            else if (area_attr != 0
!                   && (wlv.vcol == tocol
!                       || (noinvcur && (colnr_T)wlv.vcol == wp->w_virtcol)))
                area_attr = 0;                  // stop highlighting
  
  #ifdef FEAT_SEARCH_EXTRA
***************
*** 1445,1452 ****
                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 || (vcol >= left_curline_col
!                                               && vcol <= right_curline_col)))
                    line_attr = hl_combine_attr(
                                          line_attr, HL_ATTR(HLF_CUL));
            }
--- 1564,1571 ----
                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,1588 ****
                            // win_lbr_chartabsize().
                            if ((right || below || !wrap) && wp->w_width > 2)
                            {
!                               int     added = wp->w_width - col;
                                int     n_used = n_extra;
                                char_u  *l;
                                int     strsize = wrap
--- 1701,1707 ----
                            // win_lbr_chartabsize().
                            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
***************
*** 1595,1602 ****
                                    // Right-align: fill with spaces
                                    if (right)
                                        added -= strsize;
!                                   if (added < 0 || (below && col == 0)
!                                              || (!below && n_used < n_extra))
                                        added = 0;
                                    // add 1 for NUL, 2 for when '…' is used
                                    l = alloc(n_used + added + 3);
--- 1714,1723 ----
                                    // Right-align: fill with spaces
                                    if (right)
                                        added -= strsize;
!                                   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);
***************
*** 1625,1630 ****
--- 1746,1767 ----
                                        n_attr_skip = added;
                                    }
                                }
+ 
+                               // When 'wrap' is off then for "below" we need
+                               // to start a new line explictly.
+                               if (!wp->w_p_wrap)
+                               {
+                                   draw_screen_line(wp, &wlv);
+ 
+                                   // When line got too long for screen break
+                                   // here.
+                                   if (wlv.row == endrow)
+                                   {
+                                       ++wlv.row;
+                                       break;
+                                   }
+                                   win_line_start(wp, &wlv);
+                               }
                            }
                        }
                        // reset the ID in the copy to avoid it being used
***************
*** 1653,1659 ****
                syntax_attr = 0;
  # ifdef FEAT_TERMINAL
                if (get_term_attr)
!                   syntax_attr = term_get_attr(wp, lnum, vcol);
  # endif
                // Get syntax attribute.
                if (has_syntax)
--- 1790,1796 ----
                syntax_attr = 0;
  # ifdef FEAT_TERMINAL
                if (get_term_attr)
!                   syntax_attr = term_get_attr(wp, lnum, wlv.vcol);
  # endif
                // Get syntax attribute.
                if (has_syntax)
***************
*** 1742,1749 ****
  # endif
            }
            else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL)
!                               || vcol < fromcol || vcol_prev < fromcol_prev
!                               || vcol >= tocol))
            {
                // Use line_attr when not in the Visual or 'incsearch' area
                // (area_attr may be 0 when "noinvcur" is set).
--- 1879,1886 ----
  # endif
            }
            else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL)
!                             || wlv.vcol < fromcol || vcol_prev < fromcol_prev
!                             || wlv.vcol >= tocol))
            {
                // Use line_attr when not in the Visual or 'incsearch' area
                // (area_attr may be 0 when "noinvcur" is set).
***************
*** 1777,1788 ****
        }
  
        // combine attribute with 'wincolor'
!       if (win_attr != 0)
        {
            if (char_attr == 0)
!               char_attr = win_attr;
            else
!               char_attr = hl_combine_attr(win_attr, char_attr);
        }
  
        // Get the next character to put on the screen.
--- 1914,1925 ----
        }
  
        // 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.
***************
*** 1846,1854 ****
                    // last column.
                    if ((
  # ifdef FEAT_RIGHTLEFT
!                           wp->w_p_rl ? (col <= 0) :
  # endif
!                                   (col >= wp->w_width - 1))
                            && (*mb_char2cells)(mb_c) == 2)
                    {
                        c = '>';
--- 1983,1991 ----
                    // last column.
                    if ((
  # ifdef FEAT_RIGHTLEFT
!                           wp->w_p_rl ? (wlv.col <= 0) :
  # endif
!                                   (wlv.col >= wp->w_width - 1))
                            && (*mb_char2cells)(mb_c) == 2)
                    {
                        c = '>';
***************
*** 1860,1866 ****
                        if (cul_attr)
                            multi_attr = hl_combine_attr(multi_attr, cul_attr);
  #endif
!                       multi_attr = hl_combine_attr(win_attr, multi_attr);
  
                        // put the pointer back to output the double-width
                        // character at the start of the next line.
--- 1997,2003 ----
                        if (cul_attr)
                            multi_attr = hl_combine_attr(multi_attr, cul_attr);
  #endif
!                       multi_attr = hl_combine_attr(wlv.win_attr, multi_attr);
  
                        // put the pointer back to output the double-width
                        // character at the start of the next line.
***************
*** 1952,1958 ****
                        {
                            n_attr = n_extra + 1;
                            extra_attr = hl_combine_attr(
!                                                    win_attr, HL_ATTR(HLF_8));
                            saved_attr2 = char_attr; // save current attr
                        }
                    }
--- 2089,2095 ----
                        {
                            n_attr = n_extra + 1;
                            extra_attr = hl_combine_attr(
!                                                wlv.win_attr, HL_ATTR(HLF_8));
                            saved_attr2 = char_attr; // save current attr
                        }
                    }
***************
*** 2022,2028 ****
                            {
                                n_attr = n_extra + 1;
                                extra_attr = hl_combine_attr(
!                                                    win_attr, HL_ATTR(HLF_8));
                                saved_attr2 = char_attr; // save current attr
                            }
                            mb_c = c;
--- 2159,2165 ----
                            {
                                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;
***************
*** 2034,2049 ****
                // next line.
                if ((
  # ifdef FEAT_RIGHTLEFT
!                           wp->w_p_rl ? (col <= 0) :
  # endif
!                               (col >= wp->w_width - 1))
                        && (*mb_char2cells)(mb_c) == 2)
                {
                    c = '>';
                    mb_c = c;
                    mb_utf8 = FALSE;
                    mb_l = 1;
!                   multi_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
                    // Put pointer back so that the character will be
                    // displayed at the start of the next line.
                    --ptr;
--- 2171,2186 ----
                // next line.
                if ((
  # ifdef FEAT_RIGHTLEFT
!                           wp->w_p_rl ? (wlv.col <= 0) :
  # endif
!                               (wlv.col >= wp->w_width - 1))
                        && (*mb_char2cells)(mb_c) == 2)
                {
                    c = '>';
                    mb_c = c;
                    mb_utf8 = FALSE;
                    mb_l = 1;
!                   multi_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
                    // Put pointer back so that the character will be
                    // displayed at the start of the next line.
                    --ptr;
***************
*** 2066,2072 ****
                    if (area_attr == 0 && search_attr == 0)
                    {
                        n_attr = n_extra + 1;
!                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
                        saved_attr2 = char_attr; // save current attr
                    }
                    mb_c = c;
--- 2203,2210 ----
                    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;
***************
*** 2174,2185 ****
                    char_u  *p = ptr - (mb_off + 1);
                    chartabsize_T cts;
  
!                   init_chartabsize_arg(&cts, wp, lnum, 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 (vcol == vcol_sbr)
                    {
                        n_extra -= MB_CHARLEN(get_showbreak_value(wp));
                        if (n_extra < 0)
--- 2312,2323 ----
                    char_u  *p = ptr - (mb_off + 1);
                    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)
***************
*** 2191,2203 ****
                        // include the complete width of the character
                        search_attr = 0;
  
!                   if (c == TAB && n_extra + col > wp->w_width)
  # ifdef FEAT_VARTABS
!                       n_extra = tabstop_padding(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
!                                      - vcol % (int)wp->w_buffer->b_p_ts - 1;
  # endif
  
                    c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' ';
--- 2329,2342 ----
                        // 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 : ' ';
***************
*** 2254,2260 ****
                    if (area_attr == 0 && search_attr == 0)
                    {
                        n_attr = 1;
!                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_8));
                        saved_attr2 = char_attr; // save current attr
                    }
                    mb_c = c;
--- 2393,2400 ----
                    if (area_attr == 0 && search_attr == 0)
                    {
                        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;
***************
*** 2293,2299 ****
                    if (!attr_pri)
                    {
                        n_attr = 1;
!                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_8));
                        saved_attr2 = char_attr; // save current attr
                    }
                    mb_c = c;
--- 2433,2440 ----
                    if (!attr_pri)
                    {
                        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;
***************
*** 2317,2330 ****
                if (c == TAB && (!wp->w_p_list || wp->w_lcs_chars.tab1))
                {
                    int tab_len = 0;
!                   long vcol_adjusted = vcol; // removed showbreak length
  #ifdef FEAT_LINEBREAK
                    char_u *sbr = get_showbreak_value(wp);
  
                    // only adjust the tab_len, when at the first column
                    // after the showbreak value was drawn
!                   if (*sbr != NUL && vcol == vcol_sbr && wp->w_p_wrap)
!                       vcol_adjusted = vcol - MB_CHARLEN(sbr);
  #endif
                    // tab amount depends on current column
  #ifdef FEAT_VARTABS
--- 2458,2471 ----
                if (c == TAB && (!wp->w_p_list || wp->w_lcs_chars.tab1))
                {
                    int tab_len = 0;
!                   long vcol_adjusted = wlv.vcol; // removed showbreak length
  #ifdef FEAT_LINEBREAK
                    char_u *sbr = get_showbreak_value(wp);
  
                    // only adjust the tab_len, when at the first column
                    // after the showbreak value was drawn
!                   if (*sbr != NUL && wlv.vcol == vcol_sbr && wp->w_p_wrap)
!                       vcol_adjusted = wlv.vcol - MB_CHARLEN(sbr);
  #endif
                    // tab amount depends on current column
  #ifdef FEAT_VARTABS
***************
*** 2350,2358 ****
                        int     saved_nextra = n_extra;
  
  # ifdef FEAT_CONCEAL
!                       if (vcol_off > 0)
                            // there are characters to conceal
!                           tab_len += vcol_off;
  
                        // boguscols before FIX_FOR_BOGUSCOLS macro from above
                        if (wp->w_p_list && wp->w_lcs_chars.tab1
--- 2491,2499 ----
                        int     saved_nextra = n_extra;
  
  # ifdef FEAT_CONCEAL
!                       if (wlv.vcol_off > 0)
                            // there are characters to conceal
!                           tab_len += wlv.vcol_off;
  
                        // boguscols before FIX_FOR_BOGUSCOLS macro from above
                        if (wp->w_p_list && wp->w_lcs_chars.tab1
***************
*** 2399,2413 ****
  # ifdef FEAT_CONCEAL
                            // n_extra will be increased by FIX_FOX_BOGUSCOLS
                            // macro below, so need to adjust for that here
!                           if (vcol_off > 0)
!                               n_extra -= vcol_off;
  # endif
                        }
                    }
  #endif
  #ifdef FEAT_CONCEAL
                    {
!                       int vc_saved = vcol_off;
  
                        // Tab alignment should be identical regardless of
                        // 'conceallevel' value. So tab compensates of all
--- 2540,2554 ----
  # 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
                        }
                    }
  #endif
  #ifdef FEAT_CONCEAL
                    {
!                       int vc_saved = wlv.vcol_off;
  
                        // Tab alignment should be identical regardless of
                        // 'conceallevel' value. So tab compensates of all
***************
*** 2439,2445 ****
                            c_extra = wp->w_lcs_chars.tab2;
                        c_final = wp->w_lcs_chars.tab3;
                        n_attr = tab_len + 1;
!                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_8));
                        saved_attr2 = char_attr; // save current attr
                        mb_c = c;
                        if (enc_utf8 && utf_char2len(c) > 1)
--- 2580,2587 ----
                            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)
***************
*** 2459,2474 ****
                else if (c == NUL
                        && (wp->w_p_list
                            || ((fromcol >= 0 || fromcol_prev >= 0)
!                               && tocol > vcol
                                && VIsual_mode != Ctrl_V
                                && (
  # ifdef FEAT_RIGHTLEFT
!                                   wp->w_p_rl ? (col >= 0) :
  # endif
!                                   (col < wp->w_width))
                                && !(noinvcur
                                    && lnum == wp->w_cursor.lnum
!                                   && (colnr_T)vcol == wp->w_virtcol)))
                        && lcs_eol_one > 0)
                {
                    // Display a '$' after the line or highlight an extra
--- 2601,2616 ----
                else if (c == NUL
                        && (wp->w_p_list
                            || ((fromcol >= 0 || fromcol_prev >= 0)
!                               && tocol > wlv.vcol
                                && VIsual_mode != Ctrl_V
                                && (
  # ifdef FEAT_RIGHTLEFT
!                                   wp->w_p_rl ? (wlv.col >= 0) :
  # endif
!                                   (wlv.col < wp->w_width))
                                && !(noinvcur
                                    && lnum == wp->w_cursor.lnum
!                                   && (colnr_T)wlv.vcol == wp->w_virtcol)))
                        && lcs_eol_one > 0)
                {
                    // Display a '$' after the line or highlight an extra
***************
*** 2492,2498 ****
                        // In virtualedit, visual selections may extend
                        // beyond end of line.
                        if (area_highlighting && virtual_active()
!                               && tocol != MAXCOL && vcol < tocol)
                            n_extra = 0;
                        else
                        {
--- 2634,2640 ----
                        // In virtualedit, visual selections may extend
                        // beyond end of line.
                        if (area_highlighting && virtual_active()
!                               && tocol != MAXCOL && wlv.vcol < tocol)
                            n_extra = 0;
                        else
                        {
***************
*** 2510,2516 ****
                    --ptr;          // put it back at the NUL
                    if (!attr_pri)
                    {
!                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
                        n_attr = 1;
                    }
                    mb_c = c;
--- 2652,2659 ----
                    --ptr;          // put it back at the NUL
                    if (!attr_pri)
                    {
!                       extra_attr = hl_combine_attr(wlv.win_attr,
!                                                             HL_ATTR(HLF_AT));
                        n_attr = 1;
                    }
                    mb_c = c;
***************
*** 2556,2562 ****
                    if (!attr_pri)
                    {
                        n_attr = n_extra + 1;
!                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_8));
                        saved_attr2 = char_attr; // save current attr
                    }
                    mb_utf8 = FALSE;    // don't draw as UTF-8
--- 2699,2706 ----
                    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
***************
*** 2566,2577 ****
                             || VIsual_mode == 'v')
                         && virtual_active()
                         && tocol != MAXCOL
!                        && vcol < tocol
                         && (
  #ifdef FEAT_RIGHTLEFT
!                           wp->w_p_rl ? (col >= 0) :
  #endif
!                           (col < wp->w_width)))
                {
                    c = ' ';
                    --ptr;          // put it back at the NUL
--- 2710,2721 ----
                             || VIsual_mode == 'v')
                         && virtual_active()
                         && tocol != MAXCOL
!                        && wlv.vcol < tocol
                         && (
  #ifdef FEAT_RIGHTLEFT
!                           wp->w_p_rl ? (wlv.col >= 0) :
  #endif
!                           (wlv.col < wp->w_width)))
                {
                    c = ' ';
                    --ptr;          // put it back at the NUL
***************
*** 2582,2597 ****
                            diff_hlf != (hlf_T)0 ||
  # endif
  # ifdef FEAT_TERMINAL
!                           win_attr != 0 ||
  # endif
                            line_attr != 0
                        ) && (
  # ifdef FEAT_RIGHTLEFT
!                           wp->w_p_rl ? (col >= 0) :
  # endif
!                           (col
  # ifdef FEAT_CONCEAL
!                               - boguscols
  # endif
                                            < wp->w_width)))
                {
--- 2726,2741 ----
                            diff_hlf != (hlf_T)0 ||
  # endif
  # ifdef FEAT_TERMINAL
!                           wlv.win_attr != 0 ||
  # endif
                            line_attr != 0
                        ) && (
  # ifdef FEAT_RIGHTLEFT
!                           wp->w_p_rl ? (wlv.col >= 0) :
  # endif
!                           (wlv.col
  # ifdef FEAT_CONCEAL
!                               - wlv.boguscols
  # endif
                                            < wp->w_width)))
                {
***************
*** 2618,2639 ****
                            if (wp->w_p_cul && lnum == wp->w_cursor.lnum
                                    && wp->w_p_culopt_flags != CULOPT_NBR
                                    && (!cul_screenline
!                                       || (vcol >= left_curline_col
!                                                && vcol <= right_curline_col)))
                                char_attr = hl_combine_attr(
                                          char_attr, HL_ATTR(HLF_CUL));
                        }
                    }
  # endif
  # ifdef FEAT_TERMINAL
!                   if (win_attr != 0)
                    {
!                       char_attr = win_attr;
                        if (wp->w_p_cul && lnum == wp->w_cursor.lnum
                                    && wp->w_p_culopt_flags != CULOPT_NBR)
                        {
!                           if (!cul_screenline || (vcol >= left_curline_col
!                                                 && vcol <= right_curline_col))
                                char_attr = hl_combine_attr(
                                              char_attr, HL_ATTR(HLF_CUL));
                        }
--- 2762,2783 ----
                            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));
                        }
***************
*** 2676,2696 ****
                    prev_syntax_id = syntax_seqnr;
  
                    if (n_extra > 0)
!                       vcol_off += n_extra;
!                   vcol += n_extra;
                    if (wp->w_p_wrap && n_extra > 0)
                    {
  # ifdef FEAT_RIGHTLEFT
                        if (wp->w_p_rl)
                        {
!                           col -= n_extra;
!                           boguscols -= n_extra;
                        }
                        else
  # endif
                        {
!                           boguscols += n_extra;
!                           col += n_extra;
                        }
                    }
                    n_extra = 0;
--- 2820,2840 ----
                    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;
***************
*** 2730,2744 ****
        if (!did_wcol && draw_state == WL_LINE
                && wp == curwin && lnum == wp->w_cursor.lnum
                && conceal_cursor_line(wp)
!               && (int)wp->w_virtcol <= vcol + n_skip)
        {
  # ifdef FEAT_RIGHTLEFT
            if (wp->w_p_rl)
!               wp->w_wcol = wp->w_width - col + boguscols - 1;
            else
  # endif
!               wp->w_wcol = col - boguscols;
!           wp->w_wrow = row;
            did_wcol = TRUE;
            curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
  # ifdef FEAT_PROP_POPUP
--- 2874,2888 ----
        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)
        {
  # ifdef FEAT_RIGHTLEFT
            if (wp->w_p_rl)
!               wp->w_wcol = wp->w_width - wlv.col + wlv.boguscols - 1;
            else
  # endif
!               wp->w_wcol = wlv.col - wlv.boguscols;
!           wp->w_wrow = wlv.row;
            did_wcol = TRUE;
            curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
  # ifdef FEAT_PROP_POPUP
***************
*** 2779,2785 ****
                getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL);
            else
                tcol = preedit_end_col;
!           if ((long)preedit_start_col <= vcol && vcol < (long)tcol)
            {
                if (feedback_old_attr < 0)
                {
--- 2923,2929 ----
                getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL);
            else
                tcol = preedit_end_col;
!           if ((long)preedit_start_col <= wlv.vcol && wlv.vcol < (long)tcol)
            {
                if (feedback_old_attr < 0)
                {
***************
*** 2805,2811 ****
        if (lcs_prec_todo != NUL
                && wp->w_p_list
                && (wp->w_p_wrap ?
!                   (wp->w_skipcol > 0  && row == 0) :
                    wp->w_leftcol > 0)
  #ifdef FEAT_DIFF
                && filler_todo <= 0
--- 2949,2955 ----
        if (lcs_prec_todo != NUL
                && wp->w_p_list
                && (wp->w_p_wrap ?
!                   (wp->w_skipcol > 0  && wlv.row == 0) :
                    wp->w_leftcol > 0)
  #ifdef FEAT_DIFF
                && filler_todo <= 0
***************
*** 2823,2829 ****
                c_final = NUL;
                n_extra = 1;
                n_attr = 2;
!               extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
            }
            mb_c = c;
            if (enc_utf8 && utf_char2len(c) > 1)
--- 2967,2973 ----
                c_final = NUL;
                n_extra = 1;
                n_attr = 2;
!               extra_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
            }
            mb_c = c;
            if (enc_utf8 && utf_char2len(c) > 1)
***************
*** 2837,2843 ****
            if (!attr_pri)
            {
                saved_attr3 = char_attr; // save current attr
!               char_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
                n_attr3 = 1;
            }
        }
--- 2981,2987 ----
            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;
            }
        }
***************
*** 2847,2853 ****
  #if defined(LINE_ATTR)
                || did_line_attr == 1
  #endif
!               ) && eol_hl_off == 0)
        {
  #ifdef FEAT_SEARCH_EXTRA
            // flag to indicate whether prevcol equals startcol of search_hl or
--- 2991,2997 ----
  #if defined(LINE_ATTR)
                || did_line_attr == 1
  #endif
!               ) && wlv.eol_hl_off == 0)
        {
  #ifdef FEAT_SEARCH_EXTRA
            // flag to indicate whether prevcol equals startcol of search_hl or
***************
*** 2860,2866 ****
            // char on the screen, just overwrite that one (tricky!)  Not
            // needed when a '$' was displayed for 'list'.
            if (wp->w_lcs_chars.eol == lcs_eol_one
!                   && ((area_attr != 0 && vcol == fromcol
                            && (VIsual_mode != Ctrl_V
                                || lnum == VIsual.lnum
                                || lnum == curwin->w_cursor.lnum)
--- 3004,3010 ----
            // char on the screen, just overwrite that one (tricky!)  Not
            // needed when a '$' was displayed for 'list'.
            if (wp->w_lcs_chars.eol == lcs_eol_one
!                   && ((area_attr != 0 && wlv.vcol == fromcol
                            && (VIsual_mode != Ctrl_V
                                || lnum == VIsual.lnum
                                || lnum == curwin->w_cursor.lnum)
***************
*** 2887,2914 ****
  #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
!                   if (col < 0)
                        n = 1;
                }
                else
  #endif
                {
!                   if (col >= wp->w_width)
                        n = -1;
                }
                if (n != 0)
                {
                    // At the window boundary, highlight the last character
                    // instead (better than nothing).
!                   off += n;
!                   col += n;
                }
                else
                {
                    // Add a blank character to highlight.
!                   ScreenLines[off] = ' ';
                    if (enc_utf8)
!                       ScreenLinesUC[off] = 0;
                }
  #ifdef FEAT_SEARCH_EXTRA
                if (area_attr == 0)
--- 3031,3058 ----
  #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
!                   if (wlv.col < 0)
                        n = 1;
                }
                else
  #endif
                {
!                   if (wlv.col >= wp->w_width)
                        n = -1;
                }
                if (n != 0)
                {
                    // At the window boundary, highlight the last character
                    // instead (better than nothing).
!                   wlv.off += n;
!                   wlv.col += n;
                }
                else
                {
                    // Add a blank character to highlight.
!                   ScreenLines[wlv.off] = ' ';
                    if (enc_utf8)
!                       ScreenLinesUC[wlv.off] = 0;
                }
  #ifdef FEAT_SEARCH_EXTRA
                if (area_attr == 0)
***************
*** 2919,3031 ****
                                               (long)(ptr - line), &char_attr);
                }
  #endif
!               ScreenAttrs[off] = char_attr;
!               ScreenCols[off] = MAXCOL;
  #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
!                   --col;
!                   --off;
                }
                else
  #endif
                {
!                   ++col;
!                   ++off;
                }
!               ++vcol;
!               eol_hl_off = 1;
            }
        }
  
        // At end of the text line.
        if (c == NUL)
        {
! #ifdef FEAT_SYN_HL
!           // Highlight 'cursorcolumn' & 'colorcolumn' past end of the line.
!           if (wp->w_p_wrap)
!               v = wp->w_skipcol;
!           else
!               v = wp->w_leftcol;
! 
!           // check if line ends before left margin
!           if (vcol < v + col - win_col_off(wp))
!               vcol = v + col - win_col_off(wp);
! #ifdef FEAT_CONCEAL
!           // Get rid of the boguscols now, we want to draw until the right
!           // edge for 'cursorcolumn'.
!           col -= boguscols;
!           boguscols = 0;
! #endif
! 
!           if (draw_color_col)
!               draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
! 
!           if (((wp->w_p_cuc
!                     && (int)wp->w_virtcol >= VCOL_HLC - eol_hl_off
!                     && (int)wp->w_virtcol <
!                                  (long)wp->w_width * (row - startrow + 1) + v
!                     && lnum != wp->w_cursor.lnum)
!                   || draw_color_col
!                   || win_attr != 0)
! # ifdef FEAT_RIGHTLEFT
!                   && !wp->w_p_rl
! # endif
!                   )
!           {
!               int     rightmost_vcol = 0;
!               int     i;
! 
!               if (wp->w_p_cuc)
!                   rightmost_vcol = wp->w_virtcol;
!               if (draw_color_col)
!                   // determine rightmost colorcolumn to possibly draw
!                   for (i = 0; color_cols[i] >= 0; ++i)
!                       if (rightmost_vcol < color_cols[i])
!                           rightmost_vcol = color_cols[i];
! 
!               while (col < wp->w_width)
!               {
!                   ScreenLines[off] = ' ';
!                   if (enc_utf8)
!                       ScreenLinesUC[off] = 0;
!                   ScreenCols[off] = MAXCOL;
!                   ++col;
!                   if (draw_color_col)
!                       draw_color_col = advance_color_col(VCOL_HLC,
!                                                                &color_cols);
! 
!                   if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol)
!                       ScreenAttrs[off++] = HL_ATTR(HLF_CUC);
!                   else if (draw_color_col && VCOL_HLC == *color_cols)
!                       ScreenAttrs[off++] = HL_ATTR(HLF_MC);
!                   else
!                       ScreenAttrs[off++] = win_attr;
! 
!                   if (VCOL_HLC >= rightmost_vcol && win_attr == 0)
!                       break;
! 
!                   ++vcol;
!               }
!           }
! #endif
! 
!           screen_line(wp, screen_row, wp->w_wincol, col,
!                                         wp->w_width, screen_line_flags);
!           row++;
  
            // Update w_cline_height and w_cline_folded if the cursor line was
            // updated (saves a call to plines() later).
            if (wp == curwin && lnum == curwin->w_cursor.lnum)
            {
                curwin->w_cline_row = startrow;
!               curwin->w_cline_height = row - startrow;
  #ifdef FEAT_FOLDING
                curwin->w_cline_folded = FALSE;
  #endif
                curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
            }
- 
            break;
        }
  
--- 3063,3103 ----
                                               (long)(ptr - line), &char_attr);
                }
  #endif
!               ScreenAttrs[wlv.off] = char_attr;
!               ScreenCols[wlv.off] = MAXCOL;
  #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
!                   --wlv.col;
!                   --wlv.off;
                }
                else
  #endif
                {
!                   ++wlv.col;
!                   ++wlv.off;
                }
!               ++wlv.vcol;
!               wlv.eol_hl_off = 1;
            }
        }
  
        // At end of the text line.
        if (c == NUL)
        {
!           draw_screen_line(wp, &wlv);
  
            // Update w_cline_height and w_cline_folded if the cursor line was
            // updated (saves a call to plines() later).
            if (wp == curwin && lnum == curwin->w_cursor.lnum)
            {
                curwin->w_cline_row = startrow;
!               curwin->w_cline_height = wlv.row - startrow;
  #ifdef FEAT_FOLDING
                curwin->w_cline_folded = FALSE;
  #endif
                curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
            }
            break;
        }
  
***************
*** 3040,3054 ****
  #endif
                && (
  #ifdef FEAT_RIGHTLEFT
!                   wp->w_p_rl ? col == 0 :
  #endif
!                   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(win_attr, HL_ATTR(HLF_AT));
            mb_c = c;
            if (enc_utf8 && utf_char2len(c) > 1)
            {
--- 3112,3126 ----
  #endif
                && (
  #ifdef FEAT_RIGHTLEFT
!                   wp->w_p_rl ? wlv.col == 0 :
  #endif
!                   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)
            {
***************
*** 3062,3069 ****
  
  #ifdef FEAT_SYN_HL
        // advance to the next 'colorcolumn'
!       if (draw_color_col)
!           draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
  
        // Highlight the cursor column if 'cursorcolumn' is set.  But don't
        // highlight the cursor position itself.
--- 3134,3141 ----
  
  #ifdef FEAT_SYN_HL
        // advance to the next 'colorcolumn'
!       if (wlv.draw_color_col)
!           wlv.draw_color_col = advance_color_col(VCOL_HLC, &wlv.color_cols);
  
        // Highlight the cursor column if 'cursorcolumn' is set.  But don't
        // highlight the cursor position itself.
***************
*** 3087,3093 ****
                vcol_save_attr = char_attr;
                char_attr = hl_combine_attr(char_attr, HL_ATTR(HLF_CUC));
            }
!           else if (draw_color_col && VCOL_HLC == *color_cols)
            {
                vcol_save_attr = char_attr;
                char_attr = hl_combine_attr(char_attr, HL_ATTR(HLF_MC));
--- 3159,3165 ----
                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));
***************
*** 3097,3103 ****
  
        // Store character to be displayed.
        // Skip characters that are left of the screen for 'nowrap'.
!       vcol_prev = vcol;
        if (draw_state < WL_LINE || n_skip <= 0)
        {
            // Store the character.
--- 3169,3175 ----
  
        // 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.
***************
*** 3105,3120 ****
            if (has_mbyte && wp->w_p_rl && (*mb_char2cells)(mb_c) > 1)
            {
                // A double-wide character is: put first half in left cell.
!               --off;
!               --col;
            }
  #endif
!           ScreenLines[off] = c;
            if (enc_dbcs == DBCS_JPNU)
            {
                if ((mb_c & 0xff00) == 0x8e00)
!                   ScreenLines[off] = 0x8e;
!               ScreenLines2[off] = mb_c & 0xff;
            }
            else if (enc_utf8)
            {
--- 3177,3192 ----
            if (has_mbyte && wp->w_p_rl && (*mb_char2cells)(mb_c) > 1)
            {
                // A double-wide character is: put first half in left cell.
!               --wlv.off;
!               --wlv.col;
            }
  #endif
!           ScreenLines[wlv.off] = c;
            if (enc_dbcs == DBCS_JPNU)
            {
                if ((mb_c & 0xff00) == 0x8e00)
!                   ScreenLines[wlv.off] = 0x8e;
!               ScreenLines2[wlv.off] = mb_c & 0xff;
            }
            else if (enc_utf8)
            {
***************
*** 3122,3203 ****
                {
                    int i;
  
!                   ScreenLinesUC[off] = mb_c;
                    if ((c & 0xff) == 0)
!                       ScreenLines[off] = 0x80;   // avoid storing zero
                    for (i = 0; i < Screen_mco; ++i)
                    {
!                       ScreenLinesC[i][off] = u8cc[i];
                        if (u8cc[i] == 0)
                            break;
                    }
                }
                else
!                   ScreenLinesUC[off] = 0;
            }
            if (multi_attr)
            {
!               ScreenAttrs[off] = multi_attr;
                multi_attr = 0;
            }
            else
!               ScreenAttrs[off] = char_attr;
  
!           ScreenCols[off] = (colnr_T)(prev_ptr - line);
  
            if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
            {
                // Need to fill two screen columns.
!               ++off;
!               ++col;
                if (enc_utf8)
                    // UTF-8: Put a 0 in the second screen char.
!                   ScreenLines[off] = 0;
                else
                    // DBCS: Put second byte in the second screen char.
!                   ScreenLines[off] = mb_c & 0xff;
                if (draw_state > WL_NR
  #ifdef FEAT_DIFF
                        && filler_todo <= 0
  #endif
                        )
!                   ++vcol;
                // When "tocol" is halfway a character, set it to the end of
                // the character, otherwise highlighting won't stop.
!               if (tocol == vcol)
                    ++tocol;
  
!               ScreenCols[off] = (colnr_T)(prev_ptr - line);
  
  #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
                    // now it's time to backup one cell
!                   --off;
!                   --col;
                }
  #endif
            }
  #ifdef FEAT_RIGHTLEFT
            if (wp->w_p_rl)
            {
!               --off;
!               --col;
            }
            else
  #endif
            {
!               ++off;
!               ++col;
            }
        }
  #ifdef FEAT_CONCEAL
        else if (wp->w_p_cole > 0 && is_concealing)
        {
            --n_skip;
!           ++vcol_off;
            if (n_extra > 0)
!               vcol_off += n_extra;
            if (wp->w_p_wrap)
            {
                // Special voodoo required if 'wrap' is on.
--- 3194,3275 ----
                {
                    int i;
  
!                   ScreenLinesUC[wlv.off] = mb_c;
                    if ((c & 0xff) == 0)
!                       ScreenLines[wlv.off] = 0x80;   // avoid storing zero
                    for (i = 0; i < Screen_mco; ++i)
                    {
!                       ScreenLinesC[i][wlv.off] = u8cc[i];
                        if (u8cc[i] == 0)
                            break;
                    }
                }
                else
!                   ScreenLinesUC[wlv.off] = 0;
            }
            if (multi_attr)
            {
!               ScreenAttrs[wlv.off] = multi_attr;
                multi_attr = 0;
            }
            else
!               ScreenAttrs[wlv.off] = char_attr;
  
!           ScreenCols[wlv.off] = (colnr_T)(prev_ptr - line);
  
            if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
            {
                // Need to fill two screen columns.
!               ++wlv.off;
!               ++wlv.col;
                if (enc_utf8)
                    // UTF-8: Put a 0 in the second screen char.
!                   ScreenLines[wlv.off] = 0;
                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
                        )
!                   ++wlv.vcol;
                // When "tocol" is halfway a character, set it to the end of
                // the character, otherwise highlighting won't stop.
!               if (tocol == wlv.vcol)
                    ++tocol;
  
!               ScreenCols[wlv.off] = (colnr_T)(prev_ptr - line);
  
  #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
                    // now it's time to backup one cell
!                   --wlv.off;
!                   --wlv.col;
                }
  #endif
            }
  #ifdef FEAT_RIGHTLEFT
            if (wp->w_p_rl)
            {
!               --wlv.off;
!               --wlv.col;
            }
            else
  #endif
            {
!               ++wlv.off;
!               ++wlv.col;
            }
        }
  #ifdef FEAT_CONCEAL
        else if (wp->w_p_cole > 0 && is_concealing)
        {
            --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.
***************
*** 3207,3230 ****
                // take up the same screen space when parts are concealed,
                // so that cursor line computations aren't messed up.
                //
!               // To avoid the fictitious advance of 'col' causing
                // 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)
                {
!                   vcol += n_extra;
  # ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
                    {
!                       col -= n_extra;
!                       boguscols -= n_extra;
                    }
                    else
  # endif
                    {
!                       col += n_extra;
!                       boguscols += n_extra;
                    }
                    n_extra = 0;
                    n_attr = 0;
--- 3279,3302 ----
                // take up the same screen space when parts are concealed,
                // so that cursor line computations aren't messed up.
                //
!               // To avoid the fictitious advance of 'wlv.col' causing
                // 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;
***************
*** 3237,3271 ****
  # ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
                    {
!                       --boguscols;
!                       --col;
                    }
                    else
  # endif
                    {
!                       ++boguscols;
!                       ++col;
                    }
                }
  
  # ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
!                   --boguscols;
!                   --col;
                }
                else
  # endif
                {
!                   ++boguscols;
!                   ++col;
                }
            }
            else
            {
                if (n_extra > 0)
                {
!                   vcol += n_extra;
                    n_extra = 0;
                    n_attr = 0;
                }
--- 3309,3343 ----
  # ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
                    {
!                       --wlv.boguscols;
!                       --wlv.col;
                    }
                    else
  # endif
                    {
!                       ++wlv.boguscols;
!                       ++wlv.col;
                    }
                }
  
  # ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
!                   --wlv.boguscols;
!                   --wlv.col;
                }
                else
  # endif
                {
!                   ++wlv.boguscols;
!                   ++wlv.col;
                }
            }
            else
            {
                if (n_extra > 0)
                {
!                   wlv.vcol += n_extra;
                    n_extra = 0;
                    n_attr = 0;
                }
***************
*** 3276,3289 ****
        else
            --n_skip;
  
!       // Only advance the "vcol" when after the 'number' or 'relativenumber'
!       // column.
        if (draw_state > WL_NR
  #ifdef FEAT_DIFF
                && filler_todo <= 0
  #endif
                )
!           ++vcol;
  
  #ifdef FEAT_SYN_HL
        if (vcol_save_attr >= 0)
--- 3348,3361 ----
        else
            --n_skip;
  
!       // Only advance the "wlv.vcol" when after the 'number' or
!       // 'relativenumber' column.
        if (draw_state > WL_NR
  #ifdef FEAT_DIFF
                && filler_todo <= 0
  #endif
                )
!           ++wlv.vcol;
  
  #ifdef FEAT_SYN_HL
        if (vcol_save_attr >= 0)
***************
*** 3305,3313 ****
        // so far.  If there is no more to display it is caught above.
        if ((
  #ifdef FEAT_RIGHTLEFT
!           wp->w_p_rl ? (col < 0) :
  #endif
!                                   (col >= wp->w_width))
                && (draw_state != WL_LINE
                    || *ptr != NUL
  #ifdef FEAT_DIFF
--- 3377,3385 ----
        // so far.  If there is no more to display it is caught above.
        if ((
  #ifdef FEAT_RIGHTLEFT
!           wp->w_p_rl ? (wlv.col < 0) :
  #endif
!                                   (wlv.col >= wp->w_width))
                && (draw_state != WL_LINE
                    || *ptr != NUL
  #ifdef FEAT_DIFF
***************
*** 3322,3336 ****
                )
        {
  #ifdef FEAT_CONCEAL
!           screen_line(wp, screen_row, wp->w_wincol, col - boguscols,
!                                         wp->w_width, screen_line_flags);
!           boguscols = 0;
  #else
!           screen_line(wp, screen_row, wp->w_wincol, col,
!                                         wp->w_width, screen_line_flags);
  #endif
!           ++row;
!           ++screen_row;
  
            // When not wrapping and finished diff lines, or when displayed
            // '$' and highlighting until last column, break here.
--- 3394,3409 ----
                )
        {
  #ifdef FEAT_CONCEAL
!           screen_line(wp, wlv.screen_row, wp->w_wincol,
!                           wlv.col - wlv.boguscols,
!                                         wp->w_width, wlv.screen_line_flags);
!           wlv.boguscols = 0;
  #else
!           screen_line(wp, wlv.screen_row, wp->w_wincol, wlv.col,
!                                         wp->w_width, wlv.screen_line_flags);
  #endif
!           ++wlv.row;
!           ++wlv.screen_row;
  
            // When not wrapping and finished diff lines, or when displayed
            // '$' and highlighting until last column, break here.
***************
*** 3351,3369 ****
  #endif
                    )
            {
!               win_draw_end(wp, '@', ' ', TRUE, row, wp->w_height, HLF_AT);
!               draw_vsep_win(wp, row);
!               row = endrow;
            }
  
            // When line got too long for screen break here.
!           if (row == endrow)
            {
!               ++row;
                break;
            }
  
!           if (screen_cur_row == screen_row - 1
  #ifdef FEAT_DIFF
                     && filler_todo <= 0
  #endif
--- 3424,3442 ----
  #endif
                    )
            {
!               win_draw_end(wp, '@', ' ', TRUE, wlv.row, wp->w_height, HLF_AT);
!               draw_vsep_win(wp, wlv.row);
!               wlv.row = endrow;
            }
  
            // When line got too long for screen break here.
!           if (wlv.row == endrow)
            {
!               ++wlv.row;
                break;
            }
  
!           if (screen_cur_row == wlv.screen_row - 1
  #ifdef FEAT_DIFF
                     && filler_todo <= 0
  #endif
***************
*** 3373,3379 ****
                     && wp->w_width == Columns)
            {
                // Remember that the line wraps, used for modeless copy.
!               LineWraps[screen_row - 1] = TRUE;
  
                // Special trick to make copy/paste of wrapped lines work with
                // xterm/screen: write an extra character beyond the end of
--- 3446,3452 ----
                     && wp->w_width == Columns)
            {
                // Remember that the line wraps, used for modeless copy.
!               LineWraps[wlv.screen_row - 1] = TRUE;
  
                // Special trick to make copy/paste of wrapped lines work with
                // xterm/screen: write an extra character beyond the end of
***************
*** 3390,3435 ****
                         && !gui.in_use
  #endif
                         && !(has_mbyte
!                            && ((*mb_off2cells)(LineOffset[screen_row],
!                                    LineOffset[screen_row] + screen_Columns)
                                                                          == 2
!                                || (*mb_off2cells)(LineOffset[screen_row - 1]
!                                                       + (int)Columns - 2,
!                                    LineOffset[screen_row] + screen_Columns)
!                                                                       == 2)))
                {
                    // First make sure we are at the end of the screen line,
                    // then output the same character again to let the
                    // terminal know about the wrap.  If the terminal doesn't
                    // auto-wrap, we overwrite the character.
                    if (screen_cur_col != wp->w_width)
!                       screen_char(LineOffset[screen_row - 1]
!                                                     + (unsigned)Columns - 1,
!                                         screen_row - 1, (int)(Columns - 1));
  
                    // When there is a multi-byte character, just output a
                    // space to keep it simple.
                    if (has_mbyte && MB_BYTE2LEN(ScreenLines[LineOffset[
!                                       screen_row - 1] + (Columns - 1)]) > 1)
                        out_char(' ');
                    else
!                       out_char(ScreenLines[LineOffset[screen_row - 1]
                                                            + (Columns - 1)]);
                    // force a redraw of the first char on the next line
!                   ScreenAttrs[LineOffset[screen_row]] = (sattr_T)-1;
                    screen_start();     // don't know where cursor is now
                }
            }
  
!           col = 0;
!           off = (unsigned)(current_ScreenLine - ScreenLines);
! #ifdef FEAT_RIGHTLEFT
!           if (wp->w_p_rl)
!           {
!               col = wp->w_width - 1;  // col is not used if breaking!
!               off += col;
!           }
! #endif
  
            // reset the drawing state for the start of a wrapped line
            draw_state = WL_START;
--- 3463,3501 ----
                         && !gui.in_use
  #endif
                         && !(has_mbyte
!                            && ((*mb_off2cells)(LineOffset[wlv.screen_row],
!                                  LineOffset[wlv.screen_row] + screen_Columns)
                                                                          == 2
!                                || (*mb_off2cells)(
!                                    LineOffset[wlv.screen_row - 1]
!                                                           + (int)Columns - 2,
!                                    LineOffset[wlv.screen_row]
!                                                     + screen_Columns) == 2)))
                {
                    // First make sure we are at the end of the screen line,
                    // then output the same character again to let the
                    // terminal know about the wrap.  If the terminal doesn't
                    // auto-wrap, we overwrite the character.
                    if (screen_cur_col != wp->w_width)
!                       screen_char(LineOffset[wlv.screen_row - 1]
!                                                      + (unsigned)Columns - 1,
!                                      wlv.screen_row - 1, (int)(Columns - 1));
  
                    // When there is a multi-byte character, just output a
                    // space to keep it simple.
                    if (has_mbyte && MB_BYTE2LEN(ScreenLines[LineOffset[
!                                    wlv.screen_row - 1] + (Columns - 1)]) > 1)
                        out_char(' ');
                    else
!                       out_char(ScreenLines[LineOffset[wlv.screen_row - 1]
                                                            + (Columns - 1)]);
                    // force a redraw of the first char on the next line
!                   ScreenAttrs[LineOffset[wlv.screen_row]] = (sattr_T)-1;
                    screen_start();     // don't know where cursor is now
                }
            }
  
!           win_line_start(wp, &wlv);
  
            // reset the drawing state for the start of a wrapped line
            draw_state = WL_START;
***************
*** 3482,3486 ****
  #endif
  
      vim_free(p_extra_free);
!     return row;
  }
--- 3548,3552 ----
  #endif
  
      vim_free(p_extra_free);
!     return wlv.row;
  }
*** ../vim-9.0.0150/src/textprop.c      2022-08-05 19:46:44.550471107 +0100
--- src/textprop.c      2022-08-06 13:35:57.990095387 +0100
***************
*** 594,599 ****
--- 594,622 ----
      return (int)(proplen / sizeof(textprop_T));
  }
  
+ /*
+  * Return the number of text properties with "below" alignment in line "lnum".
+  */
+     int
+ prop_count_below(buf_T *buf, linenr_T lnum)
+ {
+     char_u    *props;
+     int               count = get_text_props(buf, lnum, &props, FALSE);
+     int               result = 0;
+     textprop_T        prop;
+     int               i;
+ 
+     if (count == 0)
+       return 0;
+     for (i = 0; i < count; ++i)
+     {
+       mch_memmove(&prop, props + i * sizeof(prop), sizeof(prop));
+       if (prop.tp_col == MAXCOL && (prop.tp_flags & TP_FLAG_ALIGN_BELOW))
+           ++result;
+     }
+     return result;
+ }
+ 
  /**
   * Return the number of text properties on line "lnum" in the current buffer.
   * When "only_starting" is true only text properties starting in this line 
will
*** ../vim-9.0.0150/src/proto/textprop.pro      2022-08-05 19:46:44.550471107 
+0100
--- src/proto/textprop.pro      2022-08-06 13:35:45.078103582 +0100
***************
*** 4,9 ****
--- 4,10 ----
  void f_prop_add_list(typval_T *argvars, typval_T *rettv);
  int prop_add_common(linenr_T start_lnum, colnr_T start_col, dict_T *dict, 
buf_T *default_buf, typval_T *dict_arg);
  int get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int 
will_change);
+ int prop_count_below(buf_T *buf, linenr_T lnum);
  int count_props(linenr_T lnum, int only_starting, int last_line);
  int find_visible_prop(win_T *wp, int type_id, int id, textprop_T *prop, 
linenr_T *found_lnum);
  void add_text_props(linenr_T lnum, textprop_T *text_props, int 
text_prop_count);
*** ../vim-9.0.0150/src/misc1.c 2022-07-25 18:13:33.050580738 +0100
--- src/misc1.c 2022-08-06 13:31:56.874231594 +0100
***************
*** 364,372 ****
  #endif
      int               lines;
  
-     if (!wp->w_p_wrap)
-       return 1;
- 
      if (wp->w_width == 0)
        return 1;
  
--- 364,369 ----
***************
*** 377,383 ****
        return 1;
  #endif
  
!     lines = plines_win_nofold(wp, lnum);
      if (winheight > 0 && lines > wp->w_height)
        return wp->w_height;
      return lines;
--- 374,389 ----
        return 1;
  #endif
  
!     if (!wp->w_p_wrap)
!       lines = 1
! #ifdef FEAT_PROP_POPUP
!           // add a line for each "below" aligned text property
!                   + prop_count_below(wp->w_buffer, lnum)
! #endif
!       ;
!     else
!       lines = plines_win_nofold(wp, lnum);
! 
      if (winheight > 0 && lines > wp->w_height)
        return wp->w_height;
      return lines;
*** ../vim-9.0.0150/src/testdir/test_textprop.vim       2022-08-05 
21:39:26.956564292 +0100
--- src/testdir/test_textprop.vim       2022-08-06 13:43:08.809783689 +0100
***************
*** 2426,2431 ****
--- 2426,2452 ----
    call delete('XscriptPropsWithTextAfterWraps')
  endfunc
  
+ func Test_props_with_text_after_nowrap()
+   CheckRunVimInTerminal
+ 
+   let lines =<< trim END
+       set nowrap
+       call setline(1, ['one', 'two', 'three'])
+       call prop_type_add('belowprop', #{highlight: 'ErrorMsg'})
+       call prop_type_add('anotherprop', #{highlight: 'Search'})
+       call prop_add(1, 0, #{type: 'belowprop', text: ' Below the line ', 
text_align: 'below'})
+       call prop_add(2, 0, #{type: 'anotherprop', text: 'another', text_align: 
'below'})
+       call prop_add(2, 0, #{type: 'belowprop', text: 'One More Here', 
text_align: 'below'})
+       normal G$
+   END
+   call writefile(lines, 'XscriptPropsAfterNowrap')
+   let buf = RunVimInTerminal('-S XscriptPropsAfterNowrap', #{rows: 8, cols: 
60})
+   call VerifyScreenDump(buf, 'Test_prop_with_text_after_nowrap_1', {})
+ 
+   call StopVimInTerminal(buf)
+   call delete('XscriptPropsAfterNowrap')
+ endfunc
+ 
  func Test_removed_prop_with_text_cleans_up_array()
    new
    call setline(1, 'some text here')
*** ../vim-9.0.0150/src/testdir/dumps/Test_prop_with_text_after_nowrap_1.dump   
2022-08-06 13:46:32.833195928 +0100
--- src/testdir/dumps/Test_prop_with_text_after_nowrap_1.dump   2022-08-06 
13:43:12.369780882 +0100
***************
*** 0 ****
--- 1,8 ----
+ |o+0&#ffffff0|n|e| @56
+ | +0#ffffff16#e000002|B|e|l|o|w| |t|h|e| |l|i|n|e| | +0#0000000#ffffff0@43
+ |t|w|o| @56
+ |a+0&#ffff4012|n|o|t|h|e|r| +0&#ffffff0@52
+ |O+0#ffffff16#e000002|n|e| |M|o|r|e| |H|e|r|e| +0#0000000#ffffff0@46
+ |t|h|r|e>e| @54
+ |~+0#4040ff13&| @58
+ | +0#0000000&@41|3|,|5| @10|A|l@1| 
*** ../vim-9.0.0150/src/version.c       2022-08-06 11:35:24.892762681 +0100
--- src/version.c       2022-08-06 13:45:07.377656910 +0100
***************
*** 737,738 ****
--- 737,740 ----
  {   /* Add new patch number below this line */
+ /**/
+     151,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
254. You wake up daily with your keyboard printed on your forehead.

 /// 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/20220806124849.832A81C0CD2%40moolenaar.net.

Raspunde prin e-mail lui