]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.0151: a "below" aligned text property does not work with 'nowrap' v9.0.0151
authorBram Moolenaar <Bram@vim.org>
Sat, 6 Aug 2022 12:48:20 +0000 (13:48 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 6 Aug 2022 12:48:20 +0000 (13:48 +0100)
Problem:    A "below" aligned text property does not work with 'nowrap'.
Solution:   Start a new screen line to display the virtual text.
            (closes #10851)

src/drawline.c
src/misc1.c
src/proto/textprop.pro
src/testdir/dumps/Test_prop_with_text_after_nowrap_1.dump [new file with mode: 0644]
src/testdir/test_textprop.vim
src/textprop.c
src/version.c

index 9e03b38a725a393f9af4fab49fc719c3ead748c4..0d7c5b49646b1133b571f0b711665a436886632c 100644 (file)
@@ -249,6 +249,144 @@ text_prop_compare(const void *s1, const void *s2)
 }
 #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,18 +403,15 @@ win_line(
     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
+    winlinevars_T      wlv;            // variables passed between functions
+
     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
+    long       vcol_prev = -1;         // "wlv.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
@@ -324,8 +459,6 @@ win_line(
     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
@@ -335,10 +468,7 @@ win_line(
     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
@@ -461,7 +591,6 @@ win_line(
     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
@@ -473,30 +602,31 @@ win_line(
     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 VCOL_HLC (wlv.vcol - wlv.vcol_off)
 # define FIX_FOR_BOGUSCOLS \
     { \
-       n_extra += vcol_off; \
-       vcol -= vcol_off; \
-       vcol_off = 0; \
-       col -= boguscols; \
-       old_boguscols = boguscols; \
-       boguscols = 0; \
+       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 (vcol)
+# define VCOL_HLC (wlv.vcol)
 #endif
 
     if (startrow > endrow)             // past the end already!
        return startrow;
 
-    row = startrow;
-    screen_row = row + W_WINROW(wp);
+    CLEAR_FIELD(wlv);
+
+    wlv.lnum = lnum;
+    wlv.startrow = startrow;
+    wlv.row = startrow;
+    wlv.screen_row = wlv.row + W_WINROW(wp);
 
     if (!number_only)
     {
@@ -533,9 +663,9 @@ win_line(
        }
 
        // 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);
+       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,7 +673,7 @@ win_line(
        {
            extra_check = TRUE;
            get_term_attr = TRUE;
-           win_attr = term_get_attr(wp, lnum, -1);
+           wlv.win_attr = term_get_attr(wp, lnum, -1);
        }
 #endif
 
@@ -823,13 +953,13 @@ win_line(
     wcr_attr = get_wcr_attr(wp);
     if (wcr_attr != 0)
     {
-       win_attr = wcr_attr;
+       wlv.win_attr = wcr_attr;
        area_highlighting = TRUE;
     }
 
 #ifdef FEAT_PROP_POPUP
     if (WIN_IS_POPUP(wp))
-       screen_line_flags |= SLF_POPUP;
+       wlv.screen_line_flags |= SLF_POPUP;
 #endif
 
     // 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the
@@ -844,7 +974,7 @@ win_line(
        chartabsize_T   cts;
        int             charsize = 0;
 
-       init_chartabsize_arg(&cts, wp, lnum, vcol, line, ptr);
+       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,7 +982,7 @@ win_line(
            prev_ptr = cts.cts_ptr;
            MB_PTR_ADV(cts.cts_ptr);
        }
-       vcol = cts.cts_vcol;
+       wlv.vcol = cts.cts_vcol;
        ptr = cts.cts_ptr;
        clear_chartabsize_arg(&cts);
 
@@ -862,32 +992,33 @@ win_line(
        // - '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 && (
+       if (wlv.vcol < v && (
 #ifdef FEAT_SYN_HL
-            wp->w_p_cuc || draw_color_col ||
+            wp->w_p_cuc || wlv.draw_color_col ||
 #endif
             virtual_active() ||
             (VIsual_active && wp->w_buffer == curwin->w_buffer)))
-           vcol = v;
+           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 (vcol > v)
+       if (wlv.vcol > v)
        {
-           vcol -= charsize;
+           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) && col == 0)
-              n_skip = v - vcol;
+           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 <= vcol)
+       if (tocol <= wlv.vcol)
            fromcol = 0;
-       else if (fromcol >= 0 && fromcol < vcol)
-           fromcol = vcol;
+       else if (fromcol >= 0 && fromcol < wlv.vcol)
+           fromcol = wlv.vcol;
 
 #ifdef FEAT_LINEBREAK
        // When w_skipcol is non-zero, first line needs 'showbreak'
@@ -1039,20 +1170,7 @@ win_line(
     }
 #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
+    win_line_start(wp, &wlv);
 
     // Repeat for the whole displayed line.
     for (;;)
@@ -1130,8 +1248,9 @@ win_line(
                // 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);
+                           wlv.row, startrow, filler_lines, filler_todo,
+                           &c_extra, &c_final, extra, &p_extra, &n_extra,
+                           &char_attr);
            }
 #endif
 
@@ -1141,8 +1260,8 @@ win_line(
                // 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))
+                       && (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,14 +1270,14 @@ win_line(
                    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,
+                               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 (row == startrow + filler_lines)
+                     if (wlv.row == startrow + filler_lines)
                      {
                        long num;
                        char *fmt = "%*ld ";
@@ -1221,8 +1340,8 @@ win_line(
                      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
+                             && (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,7 +1377,7 @@ win_line(
            {
                draw_state = WL_BRI;
                // if need_showbreak is set, breakindent also applies
-               if (wp->w_p_bri && (row != startrow || need_showbreak)
+               if (wp->w_p_bri && (wlv.row != startrow || need_showbreak)
 # ifdef FEAT_DIFF
                        && filler_lines == 0
 # endif
@@ -1274,7 +1393,7 @@ win_line(
                    c_final = NUL;
                    n_extra = get_breakindent_win(wp,
                                       ml_get_buf(wp->w_buffer, lnum, FALSE));
-                   if (row == startrow)
+                   if (wlv.row == startrow)
                    {
                        n_extra -= win_col_off2(wp);
                        if (n_extra < 0)
@@ -1284,7 +1403,7 @@ win_line(
                        need_showbreak = FALSE;
                    // Correct end of highlighted area for 'breakindent',
                    // required when 'linebreak' is also set.
-                   if (tocol == vcol)
+                   if (tocol == wlv.vcol)
                        tocol += n_extra;
                }
            }
@@ -1312,10 +1431,10 @@ win_line(
                    }
 #  ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
-                       n_extra = col + 1;
+                       n_extra = wlv.col + 1;
                    else
 #  endif
-                       n_extra = wp->w_width - col;
+                       n_extra = wp->w_width - wlv.col;
                    char_attr = HL_ATTR(HLF_DED);
                }
 # endif
@@ -1330,13 +1449,13 @@ win_line(
                    n_extra = (int)STRLEN(sbr);
                    if (wp->w_skipcol == 0 || !wp->w_p_wrap)
                        need_showbreak = FALSE;
-                   vcol_sbr = vcol + MB_CHARLEN(sbr);
+                   vcol_sbr = wlv.vcol + MB_CHARLEN(sbr);
                    // Correct end of highlighted area for 'showbreak',
                    // required when 'linebreak' is also set.
-                   if (tocol == vcol)
+                   if (tocol == wlv.vcol)
                        tocol += n_extra;
                    // combine 'showbreak' with 'wincolor'
-                   char_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
+                   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,13 +1479,13 @@ win_line(
                    char_attr = saved_char_attr;
                }
                else
-                   char_attr = win_attr;
+                   char_attr = wlv.win_attr;
            }
        }
 #ifdef FEAT_SYN_HL
        if (cul_screenline && draw_state == WL_LINE
-               && vcol >= left_curline_col
-               && vcol < right_curline_col)
+               && wlv.vcol >= left_curline_col
+               && wlv.vcol < right_curline_col)
        {
            cul_attr = HL_ATTR(HLF_CUL);
            line_attr = cul_attr;
@@ -1377,39 +1496,39 @@ win_line(
        // 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)
+                  && 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, screen_row, wp->w_wincol, col, -wp->w_width,
-                                                           screen_line_flags);
+           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)
-               row = wp->w_cline_row + wp->w_cline_height;
+               wlv.row = wp->w_cline_row + wp->w_cline_height;
            else
 #endif
-               row = wp->w_height;
+               wlv.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
+           if (wlv.vcol == fromcol
+                   || (has_mbyte && wlv.vcol + 1 == fromcol && n_extra == 0
                        && (*mb_ptr2cells)(ptr) > 1)
                    || ((int)vcol_prev == fromcol_prev
-                       && vcol_prev < vcol     // not at margin
-                       && vcol < tocol))
+                       && vcol_prev < wlv.vcol // not at margin
+                       && wlv.vcol < tocol))
                area_attr = vi_attr;            // start highlighting
            else if (area_attr != 0
-                   && (vcol == tocol
-                       || (noinvcur && (colnr_T)vcol == wp->w_virtcol)))
+                   && (wlv.vcol == tocol
+                       || (noinvcur && (colnr_T)wlv.vcol == wp->w_virtcol)))
                area_attr = 0;                  // stop highlighting
 
 #ifdef FEAT_SEARCH_EXTRA
@@ -1445,8 +1564,8 @@ win_line(
                line_attr = HL_ATTR(diff_hlf);
                if (wp->w_p_cul && lnum == wp->w_cursor.lnum
                        && wp->w_p_culopt_flags != CULOPT_NBR
-                       && (!cul_screenline || (vcol >= left_curline_col
-                                               && vcol <= right_curline_col)))
+                       && (!cul_screenline || (wlv.vcol >= left_curline_col
+                                           && wlv.vcol <= right_curline_col)))
                    line_attr = hl_combine_attr(
                                          line_attr, HL_ATTR(HLF_CUL));
            }
@@ -1582,7 +1701,7 @@ win_line(
                            // win_lbr_chartabsize().
                            if ((right || below || !wrap) && wp->w_width > 2)
                            {
-                               int     added = wp->w_width - col;
+                               int     added = wp->w_width - wlv.col;
                                int     n_used = n_extra;
                                char_u  *l;
                                int     strsize = wrap
@@ -1595,8 +1714,10 @@ win_line(
                                    // Right-align: fill with spaces
                                    if (right)
                                        added -= strsize;
-                                   if (added < 0 || (below && col == 0)
-                                              || (!below && n_used < n_extra))
+                                   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,6 +1746,22 @@ win_line(
                                        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,7 +1790,7 @@ win_line(
                syntax_attr = 0;
 # ifdef FEAT_TERMINAL
                if (get_term_attr)
-                   syntax_attr = term_get_attr(wp, lnum, vcol);
+                   syntax_attr = term_get_attr(wp, lnum, wlv.vcol);
 # endif
                // Get syntax attribute.
                if (has_syntax)
@@ -1742,8 +1879,8 @@ win_line(
 # endif
            }
            else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL)
-                               || vcol < fromcol || vcol_prev < fromcol_prev
-                               || vcol >= tocol))
+                             || 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,12 +1914,12 @@ win_line(
        }
 
        // combine attribute with 'wincolor'
-       if (win_attr != 0)
+       if (wlv.win_attr != 0)
        {
            if (char_attr == 0)
-               char_attr = win_attr;
+               char_attr = wlv.win_attr;
            else
-               char_attr = hl_combine_attr(win_attr, char_attr);
+               char_attr = hl_combine_attr(wlv.win_attr, char_attr);
        }
 
        // Get the next character to put on the screen.
@@ -1846,9 +1983,9 @@ win_line(
                    // last column.
                    if ((
 # ifdef FEAT_RIGHTLEFT
-                           wp->w_p_rl ? (col <= 0) :
+                           wp->w_p_rl ? (wlv.col <= 0) :
 # endif
-                                   (col >= wp->w_width - 1))
+                                   (wlv.col >= wp->w_width - 1))
                            && (*mb_char2cells)(mb_c) == 2)
                    {
                        c = '>';
@@ -1860,7 +1997,7 @@ win_line(
                        if (cul_attr)
                            multi_attr = hl_combine_attr(multi_attr, cul_attr);
 #endif
-                       multi_attr = hl_combine_attr(win_attr, multi_attr);
+                       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,7 +2089,7 @@ win_line(
                        {
                            n_attr = n_extra + 1;
                            extra_attr = hl_combine_attr(
-                                                    win_attr, HL_ATTR(HLF_8));
+                                                wlv.win_attr, HL_ATTR(HLF_8));
                            saved_attr2 = char_attr; // save current attr
                        }
                    }
@@ -2022,7 +2159,7 @@ win_line(
                            {
                                n_attr = n_extra + 1;
                                extra_attr = hl_combine_attr(
-                                                    win_attr, HL_ATTR(HLF_8));
+                                                wlv.win_attr, HL_ATTR(HLF_8));
                                saved_attr2 = char_attr; // save current attr
                            }
                            mb_c = c;
@@ -2034,16 +2171,16 @@ win_line(
                // next line.
                if ((
 # ifdef FEAT_RIGHTLEFT
-                           wp->w_p_rl ? (col <= 0) :
+                           wp->w_p_rl ? (wlv.col <= 0) :
 # endif
-                               (col >= wp->w_width - 1))
+                               (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(win_attr, HL_ATTR(HLF_AT));
+                   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,7 +2203,8 @@ win_line(
                    if (area_attr == 0 && search_attr == 0)
                    {
                        n_attr = n_extra + 1;
-                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
+                       extra_attr = hl_combine_attr(
+                                               wlv.win_attr, HL_ATTR(HLF_AT));
                        saved_attr2 = char_attr; // save current attr
                    }
                    mb_c = c;
@@ -2174,12 +2312,12 @@ win_line(
                    char_u  *p = ptr - (mb_off + 1);
                    chartabsize_T cts;
 
-                   init_chartabsize_arg(&cts, wp, lnum, vcol, line, p);
+                   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 (vcol == vcol_sbr)
+                   if (wlv.vcol == vcol_sbr)
                    {
                        n_extra -= MB_CHARLEN(get_showbreak_value(wp));
                        if (n_extra < 0)
@@ -2191,13 +2329,14 @@ win_line(
                        // include the complete width of the character
                        search_attr = 0;
 
-                   if (c == TAB && n_extra + col > wp->w_width)
+                   if (c == TAB && n_extra + wlv.col > wp->w_width)
 # ifdef FEAT_VARTABS
-                       n_extra = tabstop_padding(vcol, wp->w_buffer->b_p_ts,
+                       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
-                                      - vcol % (int)wp->w_buffer->b_p_ts - 1;
+                                   - wlv.vcol % (int)wp->w_buffer->b_p_ts - 1;
 # endif
 
                    c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' ';
@@ -2254,7 +2393,8 @@ win_line(
                    if (area_attr == 0 && search_attr == 0)
                    {
                        n_attr = 1;
-                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_8));
+                       extra_attr = hl_combine_attr(wlv.win_attr,
+                                                              HL_ATTR(HLF_8));
                        saved_attr2 = char_attr; // save current attr
                    }
                    mb_c = c;
@@ -2293,7 +2433,8 @@ win_line(
                    if (!attr_pri)
                    {
                        n_attr = 1;
-                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_8));
+                       extra_attr = hl_combine_attr(wlv.win_attr,
+                                                              HL_ATTR(HLF_8));
                        saved_attr2 = char_attr; // save current attr
                    }
                    mb_c = c;
@@ -2317,14 +2458,14 @@ win_line(
                if (c == TAB && (!wp->w_p_list || wp->w_lcs_chars.tab1))
                {
                    int tab_len = 0;
-                   long vcol_adjusted = vcol; // removed showbreak length
+                   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 && vcol == vcol_sbr && wp->w_p_wrap)
-                       vcol_adjusted = vcol - MB_CHARLEN(sbr);
+                   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,9 +2491,9 @@ win_line(
                        int     saved_nextra = n_extra;
 
 # ifdef FEAT_CONCEAL
-                       if (vcol_off > 0)
+                       if (wlv.vcol_off > 0)
                            // there are characters to conceal
-                           tab_len += vcol_off;
+                           tab_len += wlv.vcol_off;
 
                        // boguscols before FIX_FOR_BOGUSCOLS macro from above
                        if (wp->w_p_list && wp->w_lcs_chars.tab1
@@ -2399,15 +2540,15 @@ win_line(
 # 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;
+                           if (wlv.vcol_off > 0)
+                               n_extra -= wlv.vcol_off;
 # endif
                        }
                    }
 #endif
 #ifdef FEAT_CONCEAL
                    {
-                       int vc_saved = vcol_off;
+                       int vc_saved = wlv.vcol_off;
 
                        // Tab alignment should be identical regardless of
                        // 'conceallevel' value. So tab compensates of all
@@ -2439,7 +2580,8 @@ win_line(
                            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));
+                       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,16 +2601,16 @@ win_line(
                else if (c == NUL
                        && (wp->w_p_list
                            || ((fromcol >= 0 || fromcol_prev >= 0)
-                               && tocol > vcol
+                               && tocol > wlv.vcol
                                && VIsual_mode != Ctrl_V
                                && (
 # ifdef FEAT_RIGHTLEFT
-                                   wp->w_p_rl ? (col >= 0) :
+                                   wp->w_p_rl ? (wlv.col >= 0) :
 # endif
-                                   (col < wp->w_width))
+                                   (wlv.col < wp->w_width))
                                && !(noinvcur
                                    && lnum == wp->w_cursor.lnum
-                                   && (colnr_T)vcol == wp->w_virtcol)))
+                                   && (colnr_T)wlv.vcol == wp->w_virtcol)))
                        && lcs_eol_one > 0)
                {
                    // Display a '$' after the line or highlight an extra
@@ -2492,7 +2634,7 @@ win_line(
                        // In virtualedit, visual selections may extend
                        // beyond end of line.
                        if (area_highlighting && virtual_active()
-                               && tocol != MAXCOL && vcol < tocol)
+                               && tocol != MAXCOL && wlv.vcol < tocol)
                            n_extra = 0;
                        else
                        {
@@ -2510,7 +2652,8 @@ win_line(
                    --ptr;          // put it back at the NUL
                    if (!attr_pri)
                    {
-                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
+                       extra_attr = hl_combine_attr(wlv.win_attr,
+                                                             HL_ATTR(HLF_AT));
                        n_attr = 1;
                    }
                    mb_c = c;
@@ -2556,7 +2699,8 @@ win_line(
                    if (!attr_pri)
                    {
                        n_attr = n_extra + 1;
-                       extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_8));
+                       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,12 +2710,12 @@ win_line(
                             || VIsual_mode == 'v')
                         && virtual_active()
                         && tocol != MAXCOL
-                        && vcol < tocol
+                        && wlv.vcol < tocol
                         && (
 #ifdef FEAT_RIGHTLEFT
-                           wp->w_p_rl ? (col >= 0) :
+                           wp->w_p_rl ? (wlv.col >= 0) :
 #endif
-                           (col < wp->w_width)))
+                           (wlv.col < wp->w_width)))
                {
                    c = ' ';
                    --ptr;          // put it back at the NUL
@@ -2582,16 +2726,16 @@ win_line(
                            diff_hlf != (hlf_T)0 ||
 # endif
 # ifdef FEAT_TERMINAL
-                           win_attr != 0 ||
+                           wlv.win_attr != 0 ||
 # endif
                            line_attr != 0
                        ) && (
 # ifdef FEAT_RIGHTLEFT
-                           wp->w_p_rl ? (col >= 0) :
+                           wp->w_p_rl ? (wlv.col >= 0) :
 # endif
-                           (col
+                           (wlv.col
 # ifdef FEAT_CONCEAL
-                               - boguscols
+                               - wlv.boguscols
 # endif
                                            < wp->w_width)))
                {
@@ -2618,22 +2762,22 @@ win_line(
                            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)))
+                                       || (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 (win_attr != 0)
+                   if (wlv.win_attr != 0)
                    {
-                       char_attr = win_attr;
+                       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 || (vcol >= left_curline_col
-                                                 && vcol <= right_curline_col))
+                           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,21 +2820,21 @@ win_line(
                    prev_syntax_id = syntax_seqnr;
 
                    if (n_extra > 0)
-                       vcol_off += n_extra;
-                   vcol += n_extra;
+                       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)
                        {
-                           col -= n_extra;
-                           boguscols -= n_extra;
+                           wlv.col -= n_extra;
+                           wlv.boguscols -= n_extra;
                        }
                        else
 # endif
                        {
-                           boguscols += n_extra;
-                           col += n_extra;
+                           wlv.boguscols += n_extra;
+                           wlv.col += n_extra;
                        }
                    }
                    n_extra = 0;
@@ -2730,15 +2874,15 @@ win_line(
        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)
+               && (int)wp->w_virtcol <= wlv.vcol + n_skip)
        {
 # ifdef FEAT_RIGHTLEFT
            if (wp->w_p_rl)
-               wp->w_wcol = wp->w_width - col + boguscols - 1;
+               wp->w_wcol = wp->w_width - wlv.col + wlv.boguscols - 1;
            else
 # endif
-               wp->w_wcol = col - boguscols;
-           wp->w_wrow = row;
+               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,7 +2923,7 @@ win_line(
                getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL);
            else
                tcol = preedit_end_col;
-           if ((long)preedit_start_col <= vcol && vcol < (long)tcol)
+           if ((long)preedit_start_col <= wlv.vcol && wlv.vcol < (long)tcol)
            {
                if (feedback_old_attr < 0)
                {
@@ -2805,7 +2949,7 @@ win_line(
        if (lcs_prec_todo != NUL
                && wp->w_p_list
                && (wp->w_p_wrap ?
-                   (wp->w_skipcol > 0  && row == 0) :
+                   (wp->w_skipcol > 0  && wlv.row == 0) :
                    wp->w_leftcol > 0)
 #ifdef FEAT_DIFF
                && filler_todo <= 0
@@ -2823,7 +2967,7 @@ win_line(
                c_final = NUL;
                n_extra = 1;
                n_attr = 2;
-               extra_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
+               extra_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
            }
            mb_c = c;
            if (enc_utf8 && utf_char2len(c) > 1)
@@ -2837,7 +2981,7 @@ win_line(
            if (!attr_pri)
            {
                saved_attr3 = char_attr; // save current attr
-               char_attr = hl_combine_attr(win_attr, HL_ATTR(HLF_AT));
+               char_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
                n_attr3 = 1;
            }
        }
@@ -2847,7 +2991,7 @@ win_line(
 #if defined(LINE_ATTR)
                || did_line_attr == 1
 #endif
-               ) && eol_hl_off == 0)
+               ) && wlv.eol_hl_off == 0)
        {
 #ifdef FEAT_SEARCH_EXTRA
            // flag to indicate whether prevcol equals startcol of search_hl or
@@ -2860,7 +3004,7 @@ win_line(
            // 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
+                   && ((area_attr != 0 && wlv.vcol == fromcol
                            && (VIsual_mode != Ctrl_V
                                || lnum == VIsual.lnum
                                || lnum == curwin->w_cursor.lnum)
@@ -2887,28 +3031,28 @@ win_line(
 #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
-                   if (col < 0)
+                   if (wlv.col < 0)
                        n = 1;
                }
                else
 #endif
                {
-                   if (col >= wp->w_width)
+                   if (wlv.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;
+                   wlv.off += n;
+                   wlv.col += n;
                }
                else
                {
                    // Add a blank character to highlight.
-                   ScreenLines[off] = ' ';
+                   ScreenLines[wlv.off] = ' ';
                    if (enc_utf8)
-                       ScreenLinesUC[off] = 0;
+                       ScreenLinesUC[wlv.off] = 0;
                }
 #ifdef FEAT_SEARCH_EXTRA
                if (area_attr == 0)
@@ -2919,113 +3063,41 @@ win_line(
                                               (long)(ptr - line), &char_attr);
                }
 #endif
-               ScreenAttrs[off] = char_attr;
-               ScreenCols[off] = MAXCOL;
+               ScreenAttrs[wlv.off] = char_attr;
+               ScreenCols[wlv.off] = MAXCOL;
 #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
-                   --col;
-                   --off;
+                   --wlv.col;
+                   --wlv.off;
                }
                else
 #endif
                {
-                   ++col;
-                   ++off;
+                   ++wlv.col;
+                   ++wlv.off;
                }
-               ++vcol;
-               eol_hl_off = 1;
+               ++wlv.vcol;
+               wlv.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++;
+           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 = 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,15 +3112,15 @@ win_line(
 #endif
                && (
 #ifdef FEAT_RIGHTLEFT
-                   wp->w_p_rl ? col == 0 :
+                   wp->w_p_rl ? wlv.col == 0 :
 #endif
-                   col == wp->w_width - 1)
+                   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(win_attr, HL_ATTR(HLF_AT));
+           char_attr = hl_combine_attr(wlv.win_attr, HL_ATTR(HLF_AT));
            mb_c = c;
            if (enc_utf8 && utf_char2len(c) > 1)
            {
@@ -3062,8 +3134,8 @@ win_line(
 
 #ifdef FEAT_SYN_HL
        // advance to the next 'colorcolumn'
-       if (draw_color_col)
-           draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
+       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,7 +3159,7 @@ win_line(
                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)
+           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,7 +3169,7 @@ win_line(
 
        // Store character to be displayed.
        // Skip characters that are left of the screen for 'nowrap'.
-       vcol_prev = vcol;
+       vcol_prev = wlv.vcol;
        if (draw_state < WL_LINE || n_skip <= 0)
        {
            // Store the character.
@@ -3105,16 +3177,16 @@ win_line(
            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;
+               --wlv.off;
+               --wlv.col;
            }
 #endif
-           ScreenLines[off] = c;
+           ScreenLines[wlv.off] = c;
            if (enc_dbcs == DBCS_JPNU)
            {
                if ((mb_c & 0xff00) == 0x8e00)
-                   ScreenLines[off] = 0x8e;
-               ScreenLines2[off] = mb_c & 0xff;
+                   ScreenLines[wlv.off] = 0x8e;
+               ScreenLines2[wlv.off] = mb_c & 0xff;
            }
            else if (enc_utf8)
            {
@@ -3122,82 +3194,82 @@ win_line(
                {
                    int i;
 
-                   ScreenLinesUC[off] = mb_c;
+                   ScreenLinesUC[wlv.off] = mb_c;
                    if ((c & 0xff) == 0)
-                       ScreenLines[off] = 0x80;   // avoid storing zero
+                       ScreenLines[wlv.off] = 0x80;   // avoid storing zero
                    for (i = 0; i < Screen_mco; ++i)
                    {
-                       ScreenLinesC[i][off] = u8cc[i];
+                       ScreenLinesC[i][wlv.off] = u8cc[i];
                        if (u8cc[i] == 0)
                            break;
                    }
                }
                else
-                   ScreenLinesUC[off] = 0;
+                   ScreenLinesUC[wlv.off] = 0;
            }
            if (multi_attr)
            {
-               ScreenAttrs[off] = multi_attr;
+               ScreenAttrs[wlv.off] = multi_attr;
                multi_attr = 0;
            }
            else
-               ScreenAttrs[off] = char_attr;
+               ScreenAttrs[wlv.off] = char_attr;
 
-           ScreenCols[off] = (colnr_T)(prev_ptr - line);
+           ScreenCols[wlv.off] = (colnr_T)(prev_ptr - line);
 
            if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
            {
                // Need to fill two screen columns.
-               ++off;
-               ++col;
+               ++wlv.off;
+               ++wlv.col;
                if (enc_utf8)
                    // UTF-8: Put a 0 in the second screen char.
-                   ScreenLines[off] = 0;
+                   ScreenLines[wlv.off] = 0;
                else
                    // DBCS: Put second byte in the second screen char.
-                   ScreenLines[off] = mb_c & 0xff;
+                   ScreenLines[wlv.off] = mb_c & 0xff;
                if (draw_state > WL_NR
 #ifdef FEAT_DIFF
                        && filler_todo <= 0
 #endif
                        )
-                   ++vcol;
+                   ++wlv.vcol;
                // When "tocol" is halfway a character, set it to the end of
                // the character, otherwise highlighting won't stop.
-               if (tocol == vcol)
+               if (tocol == wlv.vcol)
                    ++tocol;
 
-               ScreenCols[off] = (colnr_T)(prev_ptr - line);
+               ScreenCols[wlv.off] = (colnr_T)(prev_ptr - line);
 
 #ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
                    // now it's time to backup one cell
-                   --off;
-                   --col;
+                   --wlv.off;
+                   --wlv.col;
                }
 #endif
            }
 #ifdef FEAT_RIGHTLEFT
            if (wp->w_p_rl)
            {
-               --off;
-               --col;
+               --wlv.off;
+               --wlv.col;
            }
            else
 #endif
            {
-               ++off;
-               ++col;
+               ++wlv.off;
+               ++wlv.col;
            }
        }
 #ifdef FEAT_CONCEAL
        else if (wp->w_p_cole > 0 && is_concealing)
        {
            --n_skip;
-           ++vcol_off;
+           ++wlv.vcol_off;
            if (n_extra > 0)
-               vcol_off += n_extra;
+               wlv.vcol_off += n_extra;
            if (wp->w_p_wrap)
            {
                // Special voodoo required if 'wrap' is on.
@@ -3207,24 +3279,24 @@ win_line(
                // 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
+               // 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)
                {
-                   vcol += n_extra;
+                   wlv.vcol += n_extra;
 # ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
                    {
-                       col -= n_extra;
-                       boguscols -= n_extra;
+                       wlv.col -= n_extra;
+                       wlv.boguscols -= n_extra;
                    }
                    else
 # endif
                    {
-                       col += n_extra;
-                       boguscols += n_extra;
+                       wlv.col += n_extra;
+                       wlv.boguscols += n_extra;
                    }
                    n_extra = 0;
                    n_attr = 0;
@@ -3237,35 +3309,35 @@ win_line(
 # ifdef FEAT_RIGHTLEFT
                    if (wp->w_p_rl)
                    {
-                       --boguscols;
-                       --col;
+                       --wlv.boguscols;
+                       --wlv.col;
                    }
                    else
 # endif
                    {
-                       ++boguscols;
-                       ++col;
+                       ++wlv.boguscols;
+                       ++wlv.col;
                    }
                }
 
 # ifdef FEAT_RIGHTLEFT
                if (wp->w_p_rl)
                {
-                   --boguscols;
-                   --col;
+                   --wlv.boguscols;
+                   --wlv.col;
                }
                else
 # endif
                {
-                   ++boguscols;
-                   ++col;
+                   ++wlv.boguscols;
+                   ++wlv.col;
                }
            }
            else
            {
                if (n_extra > 0)
                {
-                   vcol += n_extra;
+                   wlv.vcol += n_extra;
                    n_extra = 0;
                    n_attr = 0;
                }
@@ -3276,14 +3348,14 @@ win_line(
        else
            --n_skip;
 
-       // Only advance the "vcol" when after the 'number' or 'relativenumber'
-       // column.
+       // Only advance the "wlv.vcol" when after the 'number' or
+       // 'relativenumber' column.
        if (draw_state > WL_NR
 #ifdef FEAT_DIFF
                && filler_todo <= 0
 #endif
                )
-           ++vcol;
+           ++wlv.vcol;
 
 #ifdef FEAT_SYN_HL
        if (vcol_save_attr >= 0)
@@ -3305,9 +3377,9 @@ win_line(
        // so far.  If there is no more to display it is caught above.
        if ((
 #ifdef FEAT_RIGHTLEFT
-           wp->w_p_rl ? (col < 0) :
+           wp->w_p_rl ? (wlv.col < 0) :
 #endif
-                                   (col >= wp->w_width))
+                                   (wlv.col >= wp->w_width))
                && (draw_state != WL_LINE
                    || *ptr != NUL
 #ifdef FEAT_DIFF
@@ -3322,15 +3394,16 @@ win_line(
                )
        {
 #ifdef FEAT_CONCEAL
-           screen_line(wp, screen_row, wp->w_wincol, col - boguscols,
-                                         wp->w_width, screen_line_flags);
-           boguscols = 0;
+           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, screen_row, wp->w_wincol, col,
-                                         wp->w_width, screen_line_flags);
+           screen_line(wp, wlv.screen_row, wp->w_wincol, wlv.col,
+                                         wp->w_width, wlv.screen_line_flags);
 #endif
-           ++row;
-           ++screen_row;
+           ++wlv.row;
+           ++wlv.screen_row;
 
            // When not wrapping and finished diff lines, or when displayed
            // '$' and highlighting until last column, break here.
@@ -3351,19 +3424,19 @@ win_line(
 #endif
                    )
            {
-               win_draw_end(wp, '@', ' ', TRUE, row, wp->w_height, HLF_AT);
-               draw_vsep_win(wp, row);
-               row = endrow;
+               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 (row == endrow)
+           if (wlv.row == endrow)
            {
-               ++row;
+               ++wlv.row;
                break;
            }
 
-           if (screen_cur_row == screen_row - 1
+           if (screen_cur_row == wlv.screen_row - 1
 #ifdef FEAT_DIFF
                     && filler_todo <= 0
 #endif
@@ -3373,7 +3446,7 @@ win_line(
                     && wp->w_width == Columns)
            {
                // Remember that the line wraps, used for modeless copy.
-               LineWraps[screen_row - 1] = TRUE;
+               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,46 +3463,39 @@ win_line(
                         && !gui.in_use
 #endif
                         && !(has_mbyte
-                            && ((*mb_off2cells)(LineOffset[screen_row],
-                                    LineOffset[screen_row] + screen_Columns)
+                            && ((*mb_off2cells)(LineOffset[wlv.screen_row],
+                                  LineOffset[wlv.screen_row] + screen_Columns)
                                                                          == 2
-                                || (*mb_off2cells)(LineOffset[screen_row - 1]
-                                                       + (int)Columns - 2,
-                                    LineOffset[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[screen_row - 1]
-                                                     + (unsigned)Columns - 1,
-                                         screen_row - 1, (int)(Columns - 1));
+                       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[
-                                       screen_row - 1] + (Columns - 1)]) > 1)
+                                    wlv.screen_row - 1] + (Columns - 1)]) > 1)
                        out_char(' ');
                    else
-                       out_char(ScreenLines[LineOffset[screen_row - 1]
+                       out_char(ScreenLines[LineOffset[wlv.screen_row - 1]
                                                            + (Columns - 1)]);
                    // force a redraw of the first char on the next line
-                   ScreenAttrs[LineOffset[screen_row]] = (sattr_T)-1;
+                   ScreenAttrs[LineOffset[wlv.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
+           win_line_start(wp, &wlv);
 
            // reset the drawing state for the start of a wrapped line
            draw_state = WL_START;
@@ -3482,5 +3548,5 @@ win_line(
 #endif
 
     vim_free(p_extra_free);
-    return row;
+    return wlv.row;
 }
index 76ac88e8d6c5e6542d6d56b9a113ca3a1098582f..f3d90f876d6a3dbcde57a459a3b075c5511d7403 100644 (file)
@@ -364,9 +364,6 @@ plines_win_nofill(
 #endif
     int                lines;
 
-    if (!wp->w_p_wrap)
-       return 1;
-
     if (wp->w_width == 0)
        return 1;
 
@@ -377,7 +374,16 @@ plines_win_nofill(
        return 1;
 #endif
 
-    lines = plines_win_nofold(wp, lnum);
+    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;
index 3d2e68f79bd924035d5c8475829f8fd68bd629cc..c72b0ef260611c9f027334ec9e68fa88ac90d0c2 100644 (file)
@@ -4,6 +4,7 @@ void f_prop_add(typval_T *argvars, typval_T *rettv);
 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);
diff --git a/src/testdir/dumps/Test_prop_with_text_after_nowrap_1.dump b/src/testdir/dumps/Test_prop_with_text_after_nowrap_1.dump
new file mode 100644 (file)
index 0000000..3f5083d
--- /dev/null
@@ -0,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| 
index 9bb37135ea8f2553dced7af2716d73441dda1be1..0ecac6d89147d858a0e86a765d00e5fffcf09d1f 100644 (file)
@@ -2426,6 +2426,27 @@ func Test_props_with_text_after_wraps()
   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')
index 9e643f718544268d8692a8591b0f484114cc507c..2cd85b4221af598dca038ef68c96867a5f95243d 100644 (file)
@@ -594,6 +594,29 @@ get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change)
     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
index 27d269e9f12a9ecafd81d635f8bb32d12737e811..1e37a8e3d242325b6039cc12e2c7e7d9db50ca92 100644 (file)
@@ -735,6 +735,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    151,
 /**/
     150,
 /**/