]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0289: 'linebreak' may lead to wrong Visual block highlighting v9.2.0289
authorzeertzjq <zeertzjq@outlook.com>
Fri, 3 Apr 2026 09:48:49 +0000 (09:48 +0000)
committerChristian Brabandt <cb@256bit.org>
Fri, 3 Apr 2026 09:48:49 +0000 (09:48 +0000)
Problem:  'linebreak' may lead to wrong Visual block highlighting when
          end char occupies multiple cells (after 7.4.467).
Solution: Exclude 'linebreak' from the ending column instead of setting
          'virtualedit' temporarily (zeertzjq).

fixes:  #19898
closes: #19900

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
30 files changed:
src/change.c
src/charset.c
src/cindent.c
src/drawline.c
src/drawscreen.c
src/edit.c
src/evalfunc.c
src/ex_cmds.c
src/gui_xim.c
src/indent.c
src/misc1.c
src/misc2.c
src/mouse.c
src/move.c
src/normal.c
src/ops.c
src/popupwin.c
src/proto/charset.pro
src/regexp.c
src/regexp_bt.c
src/regexp_nfa.c
src/register.c
src/search.c
src/testdir/dumps/Test_visual_block_hl_with_linebreak_1.dump [new file with mode: 0644]
src/testdir/dumps/Test_visual_block_hl_with_linebreak_2.dump [new file with mode: 0644]
src/testdir/dumps/Test_visual_block_hl_with_linebreak_3.dump [new file with mode: 0644]
src/testdir/dumps/Test_visual_block_hl_with_linebreak_4.dump [new file with mode: 0644]
src/testdir/test_listlbr_utf8.vim
src/version.c
src/vim.h

index 3a4fefb2b825963aa2f695e4bf8a192e71d01ca0..8dd7e9d9ba5e20c5aab477b31492a553c64ffa70 100644 (file)
@@ -1263,7 +1263,7 @@ ins_char_bytes(char_u *buf, int charlen)
            // characters (zero if it's a TAB).  Count the number of bytes to
            // be deleted to make room for the new character, counting screen
            // cells.  May result in adding spaces to fill a gap.
-           getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
+           getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL, 0);
            new_vcol = vcol + chartabsize(buf, vcol);
            while (oldp[col + oldlen] != NUL && vcol < new_vcol)
            {
index 49320fcb646b5396b037381adfeeb3075828ba1d..1fbbf98f76d47413ad419483dfd2ff54e54f6cdf 100644 (file)
@@ -905,7 +905,7 @@ win_linetabsize_cts(chartabsize_T *cts, colnr_T len)
     for ( ; *cts->cts_ptr != NUL && (len == MAXCOL || cts->cts_ptr < cts->cts_line + len);
                                                      MB_PTR_ADV(cts->cts_ptr))
     {
-       vcol += win_lbr_chartabsize(cts, NULL);
+       vcol += win_lbr_chartabsize(cts, NULL, NULL);
        if (vcol > MAXCOL)
        {
            cts->cts_vcol = MAXCOL;
@@ -919,7 +919,7 @@ win_linetabsize_cts(chartabsize_T *cts, colnr_T len)
     if (len == MAXCOL && cts->cts_has_prop_with_text && *cts->cts_ptr == NUL)
     {
        int head = 0;
-       (void)win_lbr_chartabsize(cts, &head);
+       (void)win_lbr_chartabsize(cts, &head, NULL);
        vcol += cts->cts_cur_text_width + head;
        // when properties are above or below the empty line must also be
        // counted
@@ -1186,7 +1186,7 @@ lbr_chartabsize(chartabsize_T *cts)
        RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, cts->cts_ptr, cts->cts_vcol)
 #if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
     }
-    return win_lbr_chartabsize(cts, NULL);
+    return win_lbr_chartabsize(cts, NULL, NULL);
 #endif
 }
 
@@ -1209,19 +1209,24 @@ lbr_chartabsize_adv(chartabsize_T *cts)
  * inserts text.
  * This function is used very often, keep it fast!!!!
  *
- * If "headp" not NULL, set "*headp" to the size of 'showbreak'/'breakindent'
+ * If "headp" isn't NULL, set "*headp" to the size of 'showbreak'/'breakindent'
  * included in the return value.
  * When "cts->cts_max_head_vcol" is positive, only count in "*headp" the size
  * of 'showbreak'/'breakindent' before "cts->cts_max_head_vcol".
  * When "cts->cts_max_head_vcol" is negative, only count in "*headp" the size
  * of 'showbreak'/'breakindent' before where cursor should be placed.
  *
- * Warning: "*headp" may not be set if it's 0, init to 0 before calling.
+ * If "tailp" isn't NULL, set "*tailp" to the size of 'linebreak' included in
+ * the return value.
+ *
+ * Warning: "*headp" and "*tailp" may not be set if the value is 0, init to 0
+ * before calling.
  */
     int
 win_lbr_chartabsize(
        chartabsize_T   *cts,
-       int             *headp UNUSED)
+       int             *headp UNUSED,
+       int             *tailp UNUSED)
 {
     win_T      *wp = cts->cts_win;
 #if defined(FEAT_PROP_POPUP) || defined(FEAT_LINEBREAK)
@@ -1470,6 +1475,7 @@ win_lbr_chartabsize(
     if (headp != NULL)
        *headp = head;
 
+    int size_before_lbr = size;
     int need_lbr = FALSE;
     /*
      * If 'linebreak' set check at a blank before a non-blank if the line
@@ -1522,6 +1528,9 @@ win_lbr_chartabsize(
        }
     }
 
+    if (tailp != NULL)
+       *tailp = size - size_before_lbr;
+
 #  ifdef FEAT_PROP_POPUP
     size += cts->cts_first_char;
 #  endif
@@ -1598,6 +1607,10 @@ in_win_border(win_T *wp, colnr_T vcol)
  * cursor: where the cursor is on this character (first char, except for TAB)
  *    end: on the last position of this character (TAB, ctrl)
  *
+ * When 'linebreak' follows this character, "end" is set to the position before
+ * 'linebreak' if "flags" contains GETVCOL_END_EXCL_LBR, otherwise it's set to
+ * the end of 'linebreak'.
+ *
  * This is used very often, keep it fast!
  */
     void
@@ -1606,13 +1619,15 @@ getvcol(
     pos_T      *pos,
     colnr_T    *start,
     colnr_T    *cursor,
-    colnr_T    *end)
+    colnr_T    *end,
+    int                flags)
 {
     colnr_T    vcol;
     char_u     *ptr;           // points to current char
     char_u     *line;          // start of the line
     int                incr;
     int                head;
+    int                tail;
 #ifdef FEAT_VARTABS
     int                *vts = wp->w_buffer->b_p_vts_array;
 #endif
@@ -1693,6 +1708,8 @@ getvcol(
            vcol += incr;
            ptr = next_ptr;
        }
+
+       tail = 0;
     }
     else
     {
@@ -1701,7 +1718,8 @@ getvcol(
            // A tab gets expanded, depending on the current column.
            // Other things also take up space.
            head = 0;
-           incr = win_lbr_chartabsize(&cts, &head);
+           tail = 0;
+           incr = win_lbr_chartabsize(&cts, &head, &tail);
            // make sure we don't go past the end of the line
            if (*cts.cts_ptr == NUL)
            {
@@ -1736,7 +1754,7 @@ getvcol(
     if (start != NULL)
        *start = vcol + head;
     if (end != NULL)
-       *end = vcol + incr - 1;
+       *end = vcol + incr - (flags & GETVCOL_END_EXCL_LBR ? tail : 0) - 1;
     if (cursor != NULL)
     {
        if (*ptr == TAB
@@ -1746,6 +1764,7 @@ getvcol(
                && !(VIsual_active
                                && (*p_sel == 'e' || LTOREQ_POS(*pos, VIsual)))
                )
+           // TODO: subtracting "tail" may lead to better cursor position
            *cursor = vcol + incr - 1;      // cursor at end
        else
        {
@@ -1775,9 +1794,9 @@ getvcol_nolist(pos_T *posp)
 
     curwin->w_p_list = FALSE;
     if (posp->coladd)
-       getvvcol(curwin, posp, NULL, &vcol, NULL);
+       getvvcol(curwin, posp, NULL, &vcol, NULL, 0);
     else
-       getvcol(curwin, posp, NULL, &vcol, NULL);
+       getvcol(curwin, posp, NULL, &vcol, NULL, 0);
     curwin->w_p_list = list_save;
     return vcol;
 }
@@ -1791,7 +1810,8 @@ getvvcol(
     pos_T      *pos,
     colnr_T    *start,
     colnr_T    *cursor,
-    colnr_T    *end)
+    colnr_T    *end,
+    int                flags)
 {
     colnr_T    col;
     colnr_T    coladd;
@@ -1801,7 +1821,7 @@ getvvcol(
     if (virtual_active())
     {
        // For virtual mode, only want one value
-       getvcol(wp, pos, &col, NULL, NULL);
+       getvcol(wp, pos, &col, NULL, NULL, flags);
 
        coladd = pos->coladd;
        endadd = 0;
@@ -1829,7 +1849,7 @@ getvvcol(
            *end = col + endadd;
     }
     else
-       getvcol(wp, pos, start, cursor, end);
+       getvcol(wp, pos, start, cursor, end, flags);
 }
 
 /*
@@ -1842,19 +1862,20 @@ getvcols(
     pos_T      *pos1,
     pos_T      *pos2,
     colnr_T    *left,
-    colnr_T    *right)
+    colnr_T    *right,
+    int                flags)
 {
     colnr_T    from1, from2, to1, to2;
 
     if (LT_POSP(pos1, pos2))
     {
-       getvvcol(wp, pos1, &from1, NULL, &to1);
-       getvvcol(wp, pos2, &from2, NULL, &to2);
+       getvvcol(wp, pos1, &from1, NULL, &to1, flags);
+       getvvcol(wp, pos2, &from2, NULL, &to2, flags);
     }
     else
     {
-       getvvcol(wp, pos2, &from1, NULL, &to1);
-       getvvcol(wp, pos1, &from2, NULL, &to2);
+       getvvcol(wp, pos2, &from1, NULL, &to1, flags);
+       getvvcol(wp, pos1, &from2, NULL, &to2, flags);
     }
     if (from2 < from1)
        *left = from2;
index 1b4ad0fa4a312b1da8d78a24dadca8bba9ed2087..ddd268176b72f6d959b406ee2d403a9b553f27d7 100644 (file)
@@ -978,7 +978,7 @@ get_indent_nolabel (linenr_T lnum)  // XXX
 
     fp.col = (colnr_T)(p - l);
     fp.lnum = lnum;
-    getvcol(curwin, &fp, &col, NULL, NULL);
+    getvcol(curwin, &fp, &col, NULL, NULL, 0);
     return (int)col;
 }
 
@@ -1062,7 +1062,7 @@ cin_first_id_amount(void)
     p = skipwhite(p + len);
     fp.lnum = curwin->w_cursor.lnum;
     fp.col = (colnr_T)(p - line);
-    getvcol(curwin, &fp, &col, NULL, NULL);
+    getvcol(curwin, &fp, &col, NULL, NULL, 0);
     return (int)col;
 }
 
@@ -1110,7 +1110,7 @@ cin_get_equal_amount(linenr_T lnum)
 
     fp.lnum = lnum;
     fp.col = (colnr_T)(s - line);
-    getvcol(curwin, &fp, &col, NULL, NULL);
+    getvcol(curwin, &fp, &col, NULL, NULL, 0);
     return (int)col;
 }
 
@@ -1705,7 +1705,7 @@ get_baseclass_amount(int col)
     else
     {
        curwin->w_cursor.col = col;
-       getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+       getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL, 0);
        amount = (int)vcol;
     }
     if (amount < curbuf->b_ind_cpp_baseclass)
@@ -2265,7 +2265,7 @@ get_c_indent(void)
        if (trypos  != NULL)
        {
            // find how indented the line beginning the comment is
-           getvcol(curwin, trypos, &col, NULL, NULL);
+           getvcol(curwin, trypos, &col, NULL, NULL, 0);
            amount = col;
            goto theend;
        }
@@ -2287,7 +2287,7 @@ get_c_indent(void)
        int     done = FALSE;
 
        // find how indented the line beginning the comment is
-       getvcol(curwin, comment_pos, &col, NULL, NULL);
+       getvcol(curwin, comment_pos, &col, NULL, NULL, 0);
        amount = col;
        *lead_start = NUL;
        *lead_middle = NUL;
@@ -2413,7 +2413,7 @@ get_c_indent(void)
                    if (*look != NUL)               // if something after it
                        comment_pos->col = (colnr_T)(skipwhite(look) - start);
                }
-               getvcol(curwin, comment_pos, &col, NULL, NULL);
+               getvcol(curwin, comment_pos, &col, NULL, NULL, 0);
                amount = col;
                if (curbuf->b_ind_in_comment2 || *look == NUL)
                    amount += curbuf->b_ind_in_comment;
@@ -2615,7 +2615,7 @@ get_c_indent(void)
                // if we did the above "if".
                if (our_paren_pos.col > 0)
                {
-                   getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
+                   getvcol(curwin, &our_paren_pos, &col, NULL, NULL, 0);
                    if (cur_amount > (int)col)
                        cur_amount = col;
                }
@@ -2704,7 +2704,7 @@ get_c_indent(void)
        look = skipwhite(start);
        if (*look == '{')
        {
-           getvcol(curwin, trypos, &col, NULL, NULL);
+           getvcol(curwin, trypos, &col, NULL, NULL, 0);
            amount = col;
            if (*start == '{')
                start_brace = BRACE_IN_COL0;
index b7910832baee03a8737514fcb53919066b6660b4..b9b92a1e9e45b7f7331e5d5b8ca222ead1f1df3c 100644 (file)
@@ -1418,7 +1418,8 @@ win_line(
                        wlv.fromcol = 0;
                    else
                    {
-                       getvvcol(wp, top, (colnr_T *)&wlv.fromcol, NULL, NULL);
+                       getvvcol(wp, top, (colnr_T *)&wlv.fromcol,
+                                                               NULL, NULL, 0);
                        if (gchar_pos(top) == NUL)
                            wlv.tocol = wlv.fromcol + 1;
                    }
@@ -1437,11 +1438,11 @@ win_line(
                        pos = *bot;
                        if (*p_sel == 'e')
                            getvvcol(wp, &pos, (colnr_T *)&wlv.tocol,
-                                                                  NULL, NULL);
+                                                               NULL, NULL, 0);
                        else
                        {
                            getvvcol(wp, &pos, NULL, NULL,
-                                                       (colnr_T *)&wlv.tocol);
+                                                    (colnr_T *)&wlv.tocol, 0);
                            ++wlv.tocol;
                        }
                    }
@@ -1480,14 +1481,14 @@ win_line(
        {
            if (lnum == curwin->w_cursor.lnum)
                getvcol(curwin, &(curwin->w_cursor),
-                                         (colnr_T *)&wlv.fromcol, NULL, NULL);
+                                      (colnr_T *)&wlv.fromcol, NULL, NULL, 0);
            else
                wlv.fromcol = 0;
            if (lnum == curwin->w_cursor.lnum + search_match_lines)
            {
                pos.lnum = lnum;
                pos.col = search_match_endcol;
-               getvcol(curwin, &pos, (colnr_T *)&wlv.tocol, NULL, NULL);
+               getvcol(curwin, &pos, (colnr_T *)&wlv.tocol, NULL, NULL, 0);
            }
            else
                wlv.tocol = MAXCOL;
@@ -1761,7 +1762,7 @@ win_line(
     {
        chartabsize_T cts;
        init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
-       (void)win_lbr_chartabsize(&cts, NULL);
+       (void)win_lbr_chartabsize(&cts, NULL, NULL);
        vcol_first_char = cts.cts_first_char;
        clear_chartabsize_arg(&cts);
     }
@@ -1785,7 +1786,7 @@ win_line(
        while (cts.cts_vcol < v)
        {
            head = 0;
-           charsize = win_lbr_chartabsize(&cts, &head);
+           charsize = win_lbr_chartabsize(&cts, &head, NULL);
            cts.cts_vcol += charsize;
            prev_ptr = cts.cts_ptr;
            if (*prev_ptr == NUL)
@@ -3120,7 +3121,8 @@ win_line(
                    // do not want virtual text counted here
                    cts.cts_has_prop_with_text = FALSE;
 # endif
-                   wlv.n_extra = win_lbr_chartabsize(&cts, NULL) - 1;
+                   // TODO: consider using "tailp" here
+                   wlv.n_extra = win_lbr_chartabsize(&cts, NULL, NULL) - 1;
                    clear_chartabsize_arg(&cts);
 
                    if (on_last_col && c != TAB)
@@ -3780,7 +3782,7 @@ win_line(
            colnr_T tcol;
 
            if (preedit_end_col == MAXCOL)
-               getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL);
+               getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL, 0);
            else
                tcol = preedit_end_col;
            if ((long)preedit_start_col <= wlv.vcol && wlv.vcol < (long)tcol)
index 68ba60572ca437ead1c62380528e6d1d69755889..d619859bd05c58c5010693d850cf277c8ac8b49d 100644 (file)
@@ -769,7 +769,7 @@ win_redr_ruler(win_T *wp, int always, int ignore_pum)
        if (wp->w_p_list && wp->w_lcs_chars.tab1 == NUL)
        {
            wp->w_p_list = FALSE;
-           getvvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL);
+           getvvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL, 0);
            wp->w_p_list = TRUE;
        }
 
@@ -2078,17 +2078,10 @@ win_update(win_T *wp)
            if (VIsual_mode == Ctrl_V)
            {
                colnr_T     fromc, toc;
-#if defined(FEAT_LINEBREAK)
-               int         save_ve_flags = curwin->w_ve_flags;
 
-               if (curwin->w_p_lbr)
-                   curwin->w_ve_flags = VE_ALL;
-#endif
-               getvcols(wp, &VIsual, &curwin->w_cursor, &fromc, &toc);
+               getvcols(wp, &VIsual, &curwin->w_cursor, &fromc, &toc,
+                                                        GETVCOL_END_EXCL_LBR);
                ++toc;
-#if defined(FEAT_LINEBREAK)
-               curwin->w_ve_flags = save_ve_flags;
-#endif
                // Highlight to the end of the line, unless 'virtualedit' has
                // "block".
                if (curwin->w_curswant == MAXCOL)
@@ -2110,7 +2103,7 @@ win_update(win_T *wp)
                            colnr_T t;
 
                            pos.col = (int)ml_get_buf_len(wp->w_buffer, pos.lnum);
-                           getvvcol(wp, &pos, NULL, NULL, &t);
+                           getvvcol(wp, &pos, NULL, NULL, &t, 0);
                            if (toc < t)
                                toc = t;
                        }
index 2392361fbf9d4ff479e99618cdce90fd4646ed2b..79a4177bfcd96900ce292f1595c8402c459ea18f 100644 (file)
@@ -3354,7 +3354,7 @@ replace_do_bs(int limit_col)
        {
            // Get the number of screen cells used by the character we are
            // going to delete.
-           getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
+           getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL, 0);
            orig_vcols = chartabsize(ml_get_cursor(), start_vcol);
        }
        if (has_mbyte)
@@ -5152,8 +5152,8 @@ ins_tab(void)
        }
 
        // compute virtual column numbers of first white and cursor
-       getvcol(curwin, &fpos, &vcol, NULL, NULL);
-       getvcol(curwin, cursor, &want_vcol, NULL, NULL);
+       getvcol(curwin, &fpos, &vcol, NULL, NULL, 0);
+       getvcol(curwin, cursor, &want_vcol, NULL, NULL, 0);
 
        init_chartabsize_arg(&cts, curwin, 0, vcol, tab, tab);
 
index de6975a0d4f97ba8e54f12100be09c35f9e8b631..f026b384e7aff3b8dc71b049c4054f95266d4f0a 100644 (file)
@@ -6186,8 +6186,8 @@ getregionpos(
        int     lbr_saved = reset_lbr();
 #endif
 
-       getvvcol(curwin, p1, &sc1, NULL, &ec1);
-       getvvcol(curwin, p2, &sc2, NULL, &ec2);
+       getvvcol(curwin, p1, &sc1, NULL, &ec1, 0);
+       getvvcol(curwin, p2, &sc2, NULL, &ec2, 0);
 
 #ifdef FEAT_LINEBREAK
        restore_lbr(lbr_saved);
@@ -12782,7 +12782,7 @@ f_virtcol(typval_T *argvars, typval_T *rettv)
            if (fp->col > len)
                fp->col = len;
        }
-       getvvcol(curwin, fp, &vcol_start, NULL, &vcol_end);
+       getvvcol(curwin, fp, &vcol_start, NULL, &vcol_end, 0);
        ++vcol_start;
        ++vcol_end;
     }
index d4d57d0a704955368033056b6acd33f4a6892b2e..4382ea5b70659f7060b2c1036a7e8afb4f1a4361 100644 (file)
@@ -4585,11 +4585,13 @@ ex_substitute(exarg_T *eap)
                            print_line_no_prefix(lnum,
                                         subflags.do_number, subflags.do_list);
 
-                           getvcol(curwin, &curwin->w_cursor, &sc, NULL, NULL);
+                           getvcol(curwin, &curwin->w_cursor,
+                                                          &sc, NULL, NULL, 0);
                            curwin->w_cursor.col = regmatch.endpos[0].col - 1;
                            if (curwin->w_cursor.col < 0)
                                curwin->w_cursor.col = 0;
-                           getvcol(curwin, &curwin->w_cursor, NULL, NULL, &ec);
+                           getvcol(curwin, &curwin->w_cursor,
+                                                          NULL, NULL, &ec, 0);
                            curwin->w_cursor.col = regmatch.startpos[0].col;
                            if (subflags.do_number || curwin->w_p_nu)
                            {
index 8e9b750a41a932d1733fab9780f633d7c6f50be3..26b125d919402dc920b780de741c77ea1729fb2f 100644 (file)
@@ -174,7 +174,7 @@ init_preedit_start_col(void)
     if (State & MODE_CMDLINE)
        preedit_start_col = cmdline_getvcol_cursor();
     else if (curwin != NULL && curwin->w_buffer != NULL)
-       getvcol(curwin, &curwin->w_cursor, &preedit_start_col, NULL, NULL);
+       getvcol(curwin, &curwin->w_cursor, &preedit_start_col, NULL, NULL, 0);
     // Prevent that preediting marks the buffer as changed.
     xim_changed_while_preediting = curbuf->b_changed;
 }
index 26f60701c27644709e933d62ecc13d5acaba45f7..8fe4177c3024c2fdc9d1ab18b2cb710226c494ea 100644 (file)
@@ -866,7 +866,7 @@ get_number_indent(linenr_T lnum)
 
     if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL)
        return -1;
-    getvcol(curwin, &pos, &col, NULL, NULL);
+    getvcol(curwin, &pos, &col, NULL, NULL, 0);
     return (int)col;
 }
 
index 8a951298b911fb89cb71c7c31f79e4e160c06c81..3fa34c35e7c18fccb09545f89e2320fa13b7002b 100644 (file)
@@ -467,7 +467,7 @@ plines_win_col(win_T *wp, linenr_T lnum, long column)
     init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
     while (*cts.cts_ptr != NUL && --column >= 0)
     {
-       cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
+       cts.cts_vcol += win_lbr_chartabsize(&cts, NULL, NULL);
        MB_PTR_ADV(cts.cts_ptr);
     }
 
@@ -481,7 +481,7 @@ plines_win_col(win_T *wp, linenr_T lnum, long column)
     col = cts.cts_vcol;
     if (*cts.cts_ptr == TAB && (State & MODE_NORMAL)
                                    && (!wp->w_p_list || wp->w_lcs_chars.tab1))
-       col += win_lbr_chartabsize(&cts, NULL) - 1;
+       col += win_lbr_chartabsize(&cts, NULL, NULL) - 1;
     clear_chartabsize_arg(&cts);
 
     /*
index a7f52e55ebc0a2d63f8b4a0013f09f924b4cae21..1d3a35b062a873b3e3332b45ad1c29b9bc46fb0e 100644 (file)
@@ -43,7 +43,7 @@ getviscol(void)
 {
     colnr_T    x;
 
-    getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL);
+    getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL, 0);
     return (int)x;
 }
 
@@ -77,7 +77,7 @@ getviscol2(colnr_T col, colnr_T coladd)
     pos.lnum = curwin->w_cursor.lnum;
     pos.col = col;
     pos.coladd = coladd;
-    getvvcol(curwin, &pos, &x, NULL, NULL);
+    getvvcol(curwin, &pos, &x, NULL, NULL, 0);
     return (int)x;
 }
 
@@ -185,7 +185,7 @@ coladvance2(
 #endif
            // Count a tab for what it's worth (if list mode not on)
 #ifdef FEAT_LINEBREAK
-           csize = win_lbr_chartabsize(&cts, &head);
+           csize = win_lbr_chartabsize(&cts, &head, NULL);
            MB_PTR_ADV(cts.cts_ptr);
 #else
            csize = lbr_chartabsize_adv(&cts);
@@ -298,7 +298,7 @@ coladvance2(
            {
                colnr_T     scol, ecol;
 
-               getvcol(curwin, pos, &scol, NULL, &ecol);
+               getvcol(curwin, pos, &scol, NULL, &ecol, 0);
                pos->coladd = ecol - scol;
            }
        }
@@ -606,7 +606,7 @@ check_cursor_col_win(win_T *win)
            {
                int cs, ce;
 
-               getvcol(win, &win->w_cursor, &cs, NULL, &ce);
+               getvcol(win, &win->w_cursor, &cs, NULL, &ce, 0);
                if (win->w_cursor.coladd > ce - cs)
                    win->w_cursor.coladd = ce - cs;
            }
@@ -702,7 +702,7 @@ set_leftcol(colnr_T leftcol)
     // advance the cursor one more char.  If this fails (last char of the
     // line) adjust the scrolling.
     colnr_T    s, e;
-    getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
+    getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e, 0);
     if (e > (colnr_T)lastcol)
     {
        retval = TRUE;
index e043e1b4fc6391bef708be4d1aff04ddbd162e7a..3f2f86dc83f05ff917536b038e3b6b1fefd3d813 100644 (file)
@@ -663,8 +663,8 @@ do_mouse(
                        else if (VIsual_mode == Ctrl_V)
                        {
                            getvcols(curwin, &curwin->w_cursor, &VIsual,
-                                                    &leftcol, &rightcol);
-                           getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
+                                                    &leftcol, &rightcol, 0);
+                           getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL, 0);
                            if (m_pos.col < leftcol || m_pos.col > rightcol)
                                jump_flags = MOUSE_MAY_STOP_VIS;
                        }
@@ -831,7 +831,8 @@ do_mouse(
        // that is in the quarter that the cursor is in.
        if (VIsual_mode == Ctrl_V)
        {
-           getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol);
+           getvcols(curwin, &start_visual, &end_visual,
+                                                   &leftcol, &rightcol, 0);
            if (curwin->w_curswant > (leftcol + rightcol) / 2)
                end_visual.col = leftcol;
            else
@@ -3250,7 +3251,7 @@ vcol2col(win_T *wp, linenr_T lnum, int vcol, colnr_T *coladdp)
     init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
     while (cts.cts_vcol < vcol && *cts.cts_ptr != NUL)
     {
-       int size = win_lbr_chartabsize(&cts, NULL);
+       int size = win_lbr_chartabsize(&cts, NULL, NULL);
        if (cts.cts_vcol + size > vcol)
            break;
        cts.cts_vcol += size;
index ebc88536174ef56a7e80c7a5fca551c94823c1cc..ee9a8eb5aaed93409e8f76d8193703f97e9ae2c1 100644 (file)
@@ -361,7 +361,7 @@ update_topline(void)
 
                // Check that the cursor position is visible.  Add columns for
                // the marker displayed in the top-left if needed.
-               getvvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+               getvvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL, 0);
                overlap = sms_marker_overlap(curwin, -1);
                if (curwin->w_skipcol + overlap > vcol)
                    check_topline = TRUE;
@@ -1021,7 +1021,7 @@ validate_virtcol_win(win_T *wp)
 #ifdef FEAT_PROP_POPUP
     wp->w_virtcol_first_char = 0;
 #endif
-    getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL);
+    getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL, 0);
 #ifdef FEAT_SYN_HL
     redraw_for_cursorcolumn(wp);
 #endif
@@ -1183,7 +1183,7 @@ curs_columns(
     else
 #endif
        getvvcol(curwin, &curwin->w_cursor,
-                               &startcol, &(curwin->w_virtcol), &endcol);
+                                 &startcol, &(curwin->w_virtcol), &endcol, 0);
 
     // remove '$' from change command when cursor moves onto it
     if (startcol > dollar_vcol)
@@ -1491,7 +1491,7 @@ textpos2screenpos(
        else
 # endif
        {
-           getvcol(wp, pos, &scol, &ccol, &ecol);
+           getvcol(wp, pos, &scol, &ccol, &ecol, 0);
 
            // similar to what is done in validate_cursor_col()
            col = scol;
index 01ea4c0915a2314427b9194e7712afa6f5410650..e7be7575762d936b5928ccb84743acd50f871a98 100644 (file)
@@ -1652,7 +1652,8 @@ clear_showcmd(void)
            p_sbr = empty_option;
            curwin->w_p_sbr = empty_option;
 #endif
-           getvcols(curwin, &curwin->w_cursor, &VIsual, &leftcol, &rightcol);
+           getvcols(curwin, &curwin->w_cursor, &VIsual,
+                                                   &leftcol, &rightcol, 0);
 #ifdef FEAT_LINEBREAK
            p_sbr = saved_sbr;
            curwin->w_p_sbr = saved_w_sbr;
@@ -2765,7 +2766,7 @@ nv_zet(cmdarg_T *cap)
                        col = 0;        // like the cursor is in col 0
                    else
 #endif
-                   getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
+                   getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL, 0);
                    if ((long)col > siso)
                        col -= siso;
                    else
@@ -2786,7 +2787,7 @@ nv_zet(cmdarg_T *cap)
                        col = 0;        // like the cursor is in col 0
                    else
 #endif
-                   getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
+                   getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col, 0);
                    n = curwin->w_width - curwin_col_off();
                    if ((long)col + siso < n)
                        col = 0;
@@ -4295,7 +4296,7 @@ nv_csearch(cmdarg_T *cap)
     {
        colnr_T scol, ecol;
 
-       getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+       getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol, 0);
        curwin->w_cursor.coladd = ecol - scol;
     }
     else
@@ -5000,7 +5001,7 @@ v_swap_corners(int cmdchar)
     if (cmdchar == 'O' && VIsual_mode == Ctrl_V)
     {
        old_cursor = curwin->w_cursor;
-       getvcols(curwin, &old_cursor, &VIsual, &left, &right);
+       getvcols(curwin, &old_cursor, &VIsual, &left, &right, 0);
        curwin->w_cursor.lnum = VIsual.lnum;
        coladvance(left);
        VIsual = curwin->w_cursor;
@@ -5927,7 +5928,7 @@ nv_g_dollar_cmd(cmdarg_T *cap)
        {
            colnr_T vcol;
 
-           getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &vcol);
+           getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &vcol, 0);
            if (vcol >= curwin->w_leftcol + curwin->w_width - col_off)
                --curwin->w_cursor.col;
        }
@@ -6765,7 +6766,7 @@ unadjust_for_sel_inner(pos_T *pp)
        mb_adjustpos(curbuf, pp);
        if (virtual_active())
        {
-           getvcol(curwin, pp, &cs, NULL, &ce);
+           getvcol(curwin, pp, &cs, NULL, &ce, 0);
            pp->coladd = ce - cs;
        }
     }
index 3fad2b44fd0401c7fd3bec708fd644a408c2537f..140cdc8c580b39bfa73f52dac56d9534a91b6b70 100644 (file)
--- a/src/ops.c
+++ b/src/ops.c
@@ -2064,7 +2064,7 @@ adjust_cursor_eol(void)
        colnr_T     scol, ecol;
 
        // Coladd is set to the width of the last character.
-       getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+       getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol, 0);
        curwin->w_cursor.coladd = ecol - scol + 1;
     }
 }
@@ -2396,6 +2396,9 @@ theend:
 
 #ifdef FEAT_LINEBREAK
 /*
+ * TODO: consider using "tailp" of win_lbr_chartabsize() instead of temporarily
+ * resetting 'linebreak'.
+ *
  * Reset 'linebreak' and take care of side effects.
  * Returns the previous value, to be passed to restore_lbr().
  */
@@ -2617,7 +2620,7 @@ charwise_block_prep(
        startcol = start.col;
        if (virtual_op)
        {
-           getvcol(curwin, &start, &cs, NULL, &ce);
+           getvcol(curwin, &start, &cs, NULL, &ce, false);
            if (ce != cs && start.coladd > 0)
            {
                // Part of a tab selected -- but don't
@@ -2636,7 +2639,7 @@ charwise_block_prep(
        endcol = end.col;
        if (virtual_op)
        {
-           getvcol(curwin, &end, &cs, NULL, &ce);
+           getvcol(curwin, &end, &cs, NULL, &ce, false);
            if (p[endcol] == NUL || (cs + end.coladd < ce
                        // Don't add space for double-wide
                        // char; endcol will be on last byte
@@ -3409,7 +3412,7 @@ cursor_pos_info(dict_T *dict)
                oparg.block_mode = TRUE;
                oparg.op_type = OP_NOP;
                getvcols(curwin, &min_pos, &max_pos,
-                                         &oparg.start_vcol, &oparg.end_vcol);
+                                       &oparg.start_vcol, &oparg.end_vcol, 0);
 #ifdef FEAT_LINEBREAK
                p_sbr = saved_sbr;
                curwin->w_p_sbr = saved_w_sbr;
@@ -3511,8 +3514,8 @@ cursor_pos_info(dict_T *dict)
            {
                if (VIsual_mode == Ctrl_V && curwin->w_curswant < MAXCOL)
                {
-                   getvcols(curwin, &min_pos, &max_pos, &min_pos.col,
-                                                                   &max_pos.col);
+                   getvcols(curwin, &min_pos, &max_pos,
+                                               &min_pos.col, &max_pos.col, 0);
                    vim_snprintf((char *)buf1, sizeof(buf1), _("%ld Cols; "),
                            (long)(oparg.end_vcol - oparg.start_vcol + 1));
                }
@@ -3798,11 +3801,11 @@ get_op_vcol(
     if (has_mbyte)
        mb_adjustpos(curwin->w_buffer, &oap->end);
 
-    getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
+    getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol, 0);
 
     if (!redo_VIsual_busy)
     {
-       getvvcol(curwin, &(oap->end), &start, NULL, &end);
+       getvvcol(curwin, &(oap->end), &start, NULL, &end, 0);
 
        if (start < oap->start_vcol)
            oap->start_vcol = start;
@@ -3825,7 +3828,7 @@ get_op_vcol(
                curwin->w_cursor.lnum <= oap->end.lnum;
                                        ++curwin->w_cursor.lnum)
        {
-           getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
+           getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end, 0);
            if (end > oap->end_vcol)
                oap->end_vcol = end;
        }
@@ -4130,12 +4133,12 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
                {
                    if (VIsual_mode != Ctrl_V)
                        getvvcol(curwin, &(oap->end),
-                                                 NULL, NULL, &oap->end_vcol);
+                                               NULL, NULL, &oap->end_vcol, 0);
                    if (VIsual_mode == Ctrl_V || oap->line_count <= 1)
                    {
                        if (VIsual_mode != Ctrl_V)
                            getvvcol(curwin, &(oap->start),
-                                               &oap->start_vcol, NULL, NULL);
+                                             &oap->start_vcol, NULL, NULL, 0);
                        resel_VIsual_vcol = oap->end_vcol - oap->start_vcol + 1;
                    }
                    else
index d54751600fc9f22007272320428abfd954386edc..cbbb7c6e5d0723dc66af00542370d3e7dba16e04 100644 (file)
@@ -212,11 +212,11 @@ set_mousemoved_columns(win_T *wp, int flags)
     // convert text column to mouse column
     pos.col = col;
     pos.coladd = 0;
-    getvcol(textwp, &pos, &mcol, NULL, NULL);
+    getvcol(textwp, &pos, &mcol, NULL, NULL, 0);
     wp->w_popup_mouse_mincol = mcol;
 
     pos.col = col + (colnr_T)STRLEN(text) - 1;
-    getvcol(textwp, &pos, NULL, NULL, &mcol);
+    getvcol(textwp, &pos, NULL, NULL, &mcol, 0);
     wp->w_popup_mouse_maxcol = mcol;
     vim_free(text);
 }
index c9af1b0d617394d9622ddcf0ad23d82446e48946..bc09b01b8ccd797b3a1a70032d868cfb086adb8e 100644 (file)
@@ -40,11 +40,11 @@ void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum, colnr_T
 void clear_chartabsize_arg(chartabsize_T *cts);
 int lbr_chartabsize(chartabsize_T *cts);
 int lbr_chartabsize_adv(chartabsize_T *cts);
-int win_lbr_chartabsize(chartabsize_T *cts, int *headp);
-void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
+int win_lbr_chartabsize(chartabsize_T *cts, int *headp, int *tailp);
+void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end, int flags);
 colnr_T getvcol_nolist(pos_T *posp);
-void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
-void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right);
+void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end, int flags);
+void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right, int flags);
 char_u *skipwhite(char_u *q);
 char_u *skipwhite_and_nl(char_u *q);
 int getwhitecols_curline(void);
index 34325e61d4a85ace3a4eb969f1ef89236dc8abe1..6ac74467f967507b46980d21f9749c3d6e6097ce 100644 (file)
@@ -1464,8 +1464,8 @@ reg_match_visual(void)
     }
     else if (mode == Ctrl_V)
     {
-       getvvcol(wp, &top, &start, NULL, &end);
-       getvvcol(wp, &bot, &start2, NULL, &end2);
+       getvvcol(wp, &top, &start, NULL, &end, 0);
+       getvvcol(wp, &bot, &start2, NULL, &end2, 0);
        if (start2 < start)
            start = start2;
        if (end2 > end)
index 37fba5e6fdd73bb577ba7351cdc02777f9f09bfa..063510c643e1790c68be130a494b96ce389a1807 100644 (file)
@@ -1689,7 +1689,7 @@ regatom(int *flagp)
                                          colnr_T vcol = 0;
 
                                          getvvcol(curwin, &curwin->w_cursor,
-                                                           NULL, NULL, &vcol);
+                                                        NULL, NULL, &vcol, 0);
                                          ++vcol;
                                          n = vcol;
                                      }
index 807bc203c738e5f751172482fdc1838cd6147e38..b17d4d34934aa32a1896c061238b8534332cb53d 100644 (file)
@@ -1717,7 +1717,7 @@ nfa_regatom(void)
                                    colnr_T vcol = 0;
 
                                    getvvcol(curwin, &curwin->w_cursor,
-                                                           NULL, NULL, &vcol);
+                                                        NULL, NULL, &vcol, 0);
                                    n = ++vcol;
                                }
                                // \%{n}v  \%{n}<v  \%{n}>v
index de89b18646d2bd5f8c214c331ba772a7dd6b2243..a20e5c1d0f6d3753778ab501124573ff149be038 100644 (file)
@@ -1855,9 +1855,9 @@ do_put(
        if (dir == FORWARD && c != NUL)
        {
            if (cur_ve_flags == VE_ALL)
-               getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
+               getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2, 0);
            else
-               getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
+               getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col, 0);
 
            if (has_mbyte)
                // move to start of next multi-byte character
@@ -1868,7 +1868,7 @@ do_put(
            ++col;
        }
        else
-           getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
+           getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2, 0);
 
        col += curwin->w_cursor.coladd;
        if (cur_ve_flags == VE_ALL
@@ -2112,7 +2112,7 @@ do_put(
                    pos.lnum = lnum;
                    pos.col = col;
                    pos.coladd = 0;
-                   getvcol(curwin, &pos, NULL, &vcol, NULL);
+                   getvcol(curwin, &pos, NULL, &vcol, NULL, 0);
                }
            }
 
index 5d50b1fc5b2ac4d1fd587c58f0524559ab8778ad..9b51ef94a947bd6fb3fa8e14aae46d298897378e 100644 (file)
@@ -2858,7 +2858,7 @@ showmatch(
        return;
 
     if (!curwin->w_p_wrap)
-       getvcol(curwin, lpos, NULL, &vcol, NULL);
+       getvcol(curwin, lpos, NULL, &vcol, NULL, 0);
 
     int col_visible = (curwin->w_p_wrap
            || (vcol >= curwin->w_leftcol
diff --git a/src/testdir/dumps/Test_visual_block_hl_with_linebreak_1.dump b/src/testdir/dumps/Test_visual_block_hl_with_linebreak_1.dump
new file mode 100644 (file)
index 0000000..a1825a9
--- /dev/null
@@ -0,0 +1,6 @@
+|f+0#0000001#a8a8a8255|o@1| |x+0#0000000#ffffff0@9| @5||+1&&| +0&&@53
+|f+0#0000001#a8a8a8255|o@1> +0#0000000#ffffff0@16||+1&&|~+0#4040ff13&| @52
+|x+0#0000000&@19||+1&&|~+0#4040ff13&| @52
+|~| @18||+1#0000000&|~+0#4040ff13&| @52
+|<+3#0000000&|a|m|e|]| |[|+|]| |2|,|4| @3|A|l@1| |[+1&&|N|o| |N|a|m|e|]| @26|0|,|0|-|1| @9|A|l@1
+|-+2&&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@45|2|x|2|0| @6
diff --git a/src/testdir/dumps/Test_visual_block_hl_with_linebreak_2.dump b/src/testdir/dumps/Test_visual_block_hl_with_linebreak_2.dump
new file mode 100644 (file)
index 0000000..d3dae66
--- /dev/null
@@ -0,0 +1,6 @@
+|f+0&#ffffff0|o+0#0000001#a8a8a8255@1| @4|b+0#0000000#ffffff0|a|r| @63
+|f|o+0#0000001#a8a8a8255@1|1|2|3|4|5|b+0#0000000#ffffff0|a|r| @63
+|f>o|o+0#0000001#a8a8a8255| @4|b+0#0000000#ffffff0|a|r| @63
+|~+0#4040ff13&| @73
+|~| @73
+|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@28|3|x|7| @6|3|,|2| @10|A|l@1| 
diff --git a/src/testdir/dumps/Test_visual_block_hl_with_linebreak_3.dump b/src/testdir/dumps/Test_visual_block_hl_with_linebreak_3.dump
new file mode 100644 (file)
index 0000000..fe26ea2
--- /dev/null
@@ -0,0 +1,6 @@
+|f+0&#ffffff0|o+0#0000001#a8a8a8255@1|<|f@3|>|b+0#0000000#ffffff0|a|r| @62
+|f|o+0#0000001#a8a8a8255@1|1|2|3|4|5|6|b+0#0000000#ffffff0|a|r| @62
+|f>o|o+0#0000001#a8a8a8255|<|f@3|>|b+0#0000000#ffffff0|a|r| @62
+|~+0#4040ff13&| @73
+|~| @73
+|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@28|3|x|8| @6|3|,|2| @10|A|l@1| 
diff --git a/src/testdir/dumps/Test_visual_block_hl_with_linebreak_4.dump b/src/testdir/dumps/Test_visual_block_hl_with_linebreak_4.dump
new file mode 100644 (file)
index 0000000..cc4c19d
--- /dev/null
@@ -0,0 +1,6 @@
+|x+0&#ffffff0@1|x+0#0000001#a8a8a8255@7|x+0#0000000#ffffff0@4| @59
+|x@1|x+0#0000001#a8a8a8255@1|f+0#0000000#ffffff0|o@1|:| |x+0#0000001#a8a8a8255|x+0#0000000#ffffff0@4| @59
+|x@1|x+0#0000001#a8a8a8255@1|b+0#0000000#ffffff0|a|r|:| >x@5| @59
+|~+0#4040ff13&| @73
+|~| @73
+|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@28|3|x|8| @6|3|,|5|-|1|0| @7|A|l@1| 
index be77566a79cc73fd715770e988c84d8899599fe1..bde1a49580be46af21cd5994b3555d6dbfee3b1e 100644 (file)
@@ -385,4 +385,71 @@ func Test_visual_ends_before_showbreak()
   call StopVimInTerminal(buf)
 endfunc
 
+func Test_visual_block_hl_with_linebreak()
+  CheckScreendump
+
+  let lines =<< trim END
+    func Case1()
+      20vnew
+      setlocal linebreak
+      call setline(1, ['foo ' .. repeat('x', 10), 'foo ' .. repeat('x', 20)])
+      exe "normal! gg0\<C-V>3lj"
+    endfunc
+
+    func Case2()
+      setlocal nolinebreak
+      call setline(1, ["foo\tbar", 'foo12345bar', "foo\tbar"])
+      exe "normal! gg03l\<C-V>2j2h"
+    endfunc
+
+    func Case3()
+      setlocal nolinebreak
+      call setline(1, ["foo\uffffbar", 'foo123456bar', "foo\uffffbar"])
+      exe "normal! gg03l\<C-V>2j2h"
+    endfunc
+
+    func Case4()
+      setlocal nolinebreak
+      call setline(1, [repeat('x', 15), repeat('x', 10), repeat('x', 10)])
+      call prop_type_add('test', {})
+      call prop_add(2, 5, #{text: "foo: ",type: "test"})
+      call prop_add(3, 5, #{text: "bar: ",type: "test"})
+      exe "normal! gg02l\<C-V>2j2l"
+    endfunc
+
+    " FIXME: clipboard=autoselect sometimes changes Visual highlight
+    set clipboard=
+  END
+  call writefile(lines, 'XvisualBlockHlWithLinebreak', 'D')
+  let buf = RunVimInTerminal('-S XvisualBlockHlWithLinebreak', #{rows: 6})
+
+  " 'linebreak' after end char (initially fixed by patch 7.4.467)
+  call term_sendkeys(buf, ":call Case1()\r")
+  call VerifyScreenDump(buf, 'Test_visual_block_hl_with_linebreak_1', {})
+
+  " TAB as end char: 'linebreak' shouldn't break Visual block hl
+  call term_sendkeys(buf, "\<Esc>:bwipe! | call Case2()\r")
+  call VerifyScreenDump(buf, 'Test_visual_block_hl_with_linebreak_2', {})
+  call term_sendkeys(buf, "\<Esc>:setlocal linebreak\rgv")
+  call term_wait(buf, 50)
+  call VerifyScreenDump(buf, 'Test_visual_block_hl_with_linebreak_2', {})
+
+  " Unprintable end char: 'linebreak' shouldn't break Visual block hl
+  call term_sendkeys(buf, "\<Esc>:bwipe! | call Case3()\r")
+  call VerifyScreenDump(buf, 'Test_visual_block_hl_with_linebreak_3', {})
+  call term_sendkeys(buf, "\<Esc>:setlocal linebreak\rgv")
+  call term_wait(buf, 50)
+  call VerifyScreenDump(buf, 'Test_visual_block_hl_with_linebreak_3', {})
+
+  " Virtual text before end char: 'linebreak' shouldn't break Visual block hl
+  call term_sendkeys(buf, "\<Esc>:bwipe! | call Case4()\r")
+  call VerifyScreenDump(buf, 'Test_visual_block_hl_with_linebreak_4', {})
+  call term_sendkeys(buf, "\<Esc>:setlocal linebreak\rgv")
+  call term_wait(buf, 50)
+  call VerifyScreenDump(buf, 'Test_visual_block_hl_with_linebreak_4', {})
+
+  call term_sendkeys(buf, "\<Esc>")
+  call StopVimInTerminal(buf)
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index e81115c3105fc592279af7d9bf8e4e65b67137c4..64db5b8842556c44754f5d9a25b7cfe08f97302d 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    289,
 /**/
     288,
 /**/
index f2e3a161013219ee777444d53e8221266c2e0f79..51d0cc1f322e63bfa0a096eaa1744ef5a8f91848 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -3093,4 +3093,7 @@ long elapsed(DWORD start_tick);
 #define CF_INTERFACE   2       // inside an interface
 #define CF_ABSTRACT_METHOD     4       // inside an abstract class
 
+// Flags used by getvcol()
+#define GETVCOL_END_EXCL_LBR   1
+
 #endif // VIM__H