Skip to content

Commit 23be188

Browse files
zeertzjqchrisbra
authored andcommitted
patch 9.2.0289: 'linebreak' may lead to wrong Visual block highlighting
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 <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent af58a9f commit 23be188

30 files changed

Lines changed: 227 additions & 108 deletions

src/change.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ ins_char_bytes(char_u *buf, int charlen)
12631263
// characters (zero if it's a TAB). Count the number of bytes to
12641264
// be deleted to make room for the new character, counting screen
12651265
// cells. May result in adding spaces to fill a gap.
1266-
getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
1266+
getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL, 0);
12671267
new_vcol = vcol + chartabsize(buf, vcol);
12681268
while (oldp[col + oldlen] != NUL && vcol < new_vcol)
12691269
{

src/charset.c

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,7 @@ win_linetabsize_cts(chartabsize_T *cts, colnr_T len)
905905
for ( ; *cts->cts_ptr != NUL && (len == MAXCOL || cts->cts_ptr < cts->cts_line + len);
906906
MB_PTR_ADV(cts->cts_ptr))
907907
{
908-
vcol += win_lbr_chartabsize(cts, NULL);
908+
vcol += win_lbr_chartabsize(cts, NULL, NULL);
909909
if (vcol > MAXCOL)
910910
{
911911
cts->cts_vcol = MAXCOL;
@@ -919,7 +919,7 @@ win_linetabsize_cts(chartabsize_T *cts, colnr_T len)
919919
if (len == MAXCOL && cts->cts_has_prop_with_text && *cts->cts_ptr == NUL)
920920
{
921921
int head = 0;
922-
(void)win_lbr_chartabsize(cts, &head);
922+
(void)win_lbr_chartabsize(cts, &head, NULL);
923923
vcol += cts->cts_cur_text_width + head;
924924
// when properties are above or below the empty line must also be
925925
// counted
@@ -1186,7 +1186,7 @@ lbr_chartabsize(chartabsize_T *cts)
11861186
RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, cts->cts_ptr, cts->cts_vcol)
11871187
#if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
11881188
}
1189-
return win_lbr_chartabsize(cts, NULL);
1189+
return win_lbr_chartabsize(cts, NULL, NULL);
11901190
#endif
11911191
}
11921192

@@ -1209,19 +1209,24 @@ lbr_chartabsize_adv(chartabsize_T *cts)
12091209
* inserts text.
12101210
* This function is used very often, keep it fast!!!!
12111211
*
1212-
* If "headp" not NULL, set "*headp" to the size of 'showbreak'/'breakindent'
1212+
* If "headp" isn't NULL, set "*headp" to the size of 'showbreak'/'breakindent'
12131213
* included in the return value.
12141214
* When "cts->cts_max_head_vcol" is positive, only count in "*headp" the size
12151215
* of 'showbreak'/'breakindent' before "cts->cts_max_head_vcol".
12161216
* When "cts->cts_max_head_vcol" is negative, only count in "*headp" the size
12171217
* of 'showbreak'/'breakindent' before where cursor should be placed.
12181218
*
1219-
* Warning: "*headp" may not be set if it's 0, init to 0 before calling.
1219+
* If "tailp" isn't NULL, set "*tailp" to the size of 'linebreak' included in
1220+
* the return value.
1221+
*
1222+
* Warning: "*headp" and "*tailp" may not be set if the value is 0, init to 0
1223+
* before calling.
12201224
*/
12211225
int
12221226
win_lbr_chartabsize(
12231227
chartabsize_T *cts,
1224-
int *headp UNUSED)
1228+
int *headp UNUSED,
1229+
int *tailp UNUSED)
12251230
{
12261231
win_T *wp = cts->cts_win;
12271232
#if defined(FEAT_PROP_POPUP) || defined(FEAT_LINEBREAK)
@@ -1470,6 +1475,7 @@ win_lbr_chartabsize(
14701475
if (headp != NULL)
14711476
*headp = head;
14721477

1478+
int size_before_lbr = size;
14731479
int need_lbr = FALSE;
14741480
/*
14751481
* If 'linebreak' set check at a blank before a non-blank if the line
@@ -1522,6 +1528,9 @@ win_lbr_chartabsize(
15221528
}
15231529
}
15241530

1531+
if (tailp != NULL)
1532+
*tailp = size - size_before_lbr;
1533+
15251534
# ifdef FEAT_PROP_POPUP
15261535
size += cts->cts_first_char;
15271536
# endif
@@ -1598,6 +1607,10 @@ in_win_border(win_T *wp, colnr_T vcol)
15981607
* cursor: where the cursor is on this character (first char, except for TAB)
15991608
* end: on the last position of this character (TAB, ctrl)
16001609
*
1610+
* When 'linebreak' follows this character, "end" is set to the position before
1611+
* 'linebreak' if "flags" contains GETVCOL_END_EXCL_LBR, otherwise it's set to
1612+
* the end of 'linebreak'.
1613+
*
16011614
* This is used very often, keep it fast!
16021615
*/
16031616
void
@@ -1606,13 +1619,15 @@ getvcol(
16061619
pos_T *pos,
16071620
colnr_T *start,
16081621
colnr_T *cursor,
1609-
colnr_T *end)
1622+
colnr_T *end,
1623+
int flags)
16101624
{
16111625
colnr_T vcol;
16121626
char_u *ptr; // points to current char
16131627
char_u *line; // start of the line
16141628
int incr;
16151629
int head;
1630+
int tail;
16161631
#ifdef FEAT_VARTABS
16171632
int *vts = wp->w_buffer->b_p_vts_array;
16181633
#endif
@@ -1693,6 +1708,8 @@ getvcol(
16931708
vcol += incr;
16941709
ptr = next_ptr;
16951710
}
1711+
1712+
tail = 0;
16961713
}
16971714
else
16981715
{
@@ -1701,7 +1718,8 @@ getvcol(
17011718
// A tab gets expanded, depending on the current column.
17021719
// Other things also take up space.
17031720
head = 0;
1704-
incr = win_lbr_chartabsize(&cts, &head);
1721+
tail = 0;
1722+
incr = win_lbr_chartabsize(&cts, &head, &tail);
17051723
// make sure we don't go past the end of the line
17061724
if (*cts.cts_ptr == NUL)
17071725
{
@@ -1736,7 +1754,7 @@ getvcol(
17361754
if (start != NULL)
17371755
*start = vcol + head;
17381756
if (end != NULL)
1739-
*end = vcol + incr - 1;
1757+
*end = vcol + incr - (flags & GETVCOL_END_EXCL_LBR ? tail : 0) - 1;
17401758
if (cursor != NULL)
17411759
{
17421760
if (*ptr == TAB
@@ -1746,6 +1764,7 @@ getvcol(
17461764
&& !(VIsual_active
17471765
&& (*p_sel == 'e' || LTOREQ_POS(*pos, VIsual)))
17481766
)
1767+
// TODO: subtracting "tail" may lead to better cursor position
17491768
*cursor = vcol + incr - 1; // cursor at end
17501769
else
17511770
{
@@ -1775,9 +1794,9 @@ getvcol_nolist(pos_T *posp)
17751794

17761795
curwin->w_p_list = FALSE;
17771796
if (posp->coladd)
1778-
getvvcol(curwin, posp, NULL, &vcol, NULL);
1797+
getvvcol(curwin, posp, NULL, &vcol, NULL, 0);
17791798
else
1780-
getvcol(curwin, posp, NULL, &vcol, NULL);
1799+
getvcol(curwin, posp, NULL, &vcol, NULL, 0);
17811800
curwin->w_p_list = list_save;
17821801
return vcol;
17831802
}
@@ -1791,7 +1810,8 @@ getvvcol(
17911810
pos_T *pos,
17921811
colnr_T *start,
17931812
colnr_T *cursor,
1794-
colnr_T *end)
1813+
colnr_T *end,
1814+
int flags)
17951815
{
17961816
colnr_T col;
17971817
colnr_T coladd;
@@ -1801,7 +1821,7 @@ getvvcol(
18011821
if (virtual_active())
18021822
{
18031823
// For virtual mode, only want one value
1804-
getvcol(wp, pos, &col, NULL, NULL);
1824+
getvcol(wp, pos, &col, NULL, NULL, flags);
18051825

18061826
coladd = pos->coladd;
18071827
endadd = 0;
@@ -1829,7 +1849,7 @@ getvvcol(
18291849
*end = col + endadd;
18301850
}
18311851
else
1832-
getvcol(wp, pos, start, cursor, end);
1852+
getvcol(wp, pos, start, cursor, end, flags);
18331853
}
18341854

18351855
/*
@@ -1842,19 +1862,20 @@ getvcols(
18421862
pos_T *pos1,
18431863
pos_T *pos2,
18441864
colnr_T *left,
1845-
colnr_T *right)
1865+
colnr_T *right,
1866+
int flags)
18461867
{
18471868
colnr_T from1, from2, to1, to2;
18481869

18491870
if (LT_POSP(pos1, pos2))
18501871
{
1851-
getvvcol(wp, pos1, &from1, NULL, &to1);
1852-
getvvcol(wp, pos2, &from2, NULL, &to2);
1872+
getvvcol(wp, pos1, &from1, NULL, &to1, flags);
1873+
getvvcol(wp, pos2, &from2, NULL, &to2, flags);
18531874
}
18541875
else
18551876
{
1856-
getvvcol(wp, pos2, &from1, NULL, &to1);
1857-
getvvcol(wp, pos1, &from2, NULL, &to2);
1877+
getvvcol(wp, pos2, &from1, NULL, &to1, flags);
1878+
getvvcol(wp, pos1, &from2, NULL, &to2, flags);
18581879
}
18591880
if (from2 < from1)
18601881
*left = from2;

src/cindent.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ get_indent_nolabel (linenr_T lnum) // XXX
978978

979979
fp.col = (colnr_T)(p - l);
980980
fp.lnum = lnum;
981-
getvcol(curwin, &fp, &col, NULL, NULL);
981+
getvcol(curwin, &fp, &col, NULL, NULL, 0);
982982
return (int)col;
983983
}
984984

@@ -1062,7 +1062,7 @@ cin_first_id_amount(void)
10621062
p = skipwhite(p + len);
10631063
fp.lnum = curwin->w_cursor.lnum;
10641064
fp.col = (colnr_T)(p - line);
1065-
getvcol(curwin, &fp, &col, NULL, NULL);
1065+
getvcol(curwin, &fp, &col, NULL, NULL, 0);
10661066
return (int)col;
10671067
}
10681068

@@ -1110,7 +1110,7 @@ cin_get_equal_amount(linenr_T lnum)
11101110

11111111
fp.lnum = lnum;
11121112
fp.col = (colnr_T)(s - line);
1113-
getvcol(curwin, &fp, &col, NULL, NULL);
1113+
getvcol(curwin, &fp, &col, NULL, NULL, 0);
11141114
return (int)col;
11151115
}
11161116

@@ -1705,7 +1705,7 @@ get_baseclass_amount(int col)
17051705
else
17061706
{
17071707
curwin->w_cursor.col = col;
1708-
getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
1708+
getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL, 0);
17091709
amount = (int)vcol;
17101710
}
17111711
if (amount < curbuf->b_ind_cpp_baseclass)
@@ -2265,7 +2265,7 @@ get_c_indent(void)
22652265
if (trypos != NULL)
22662266
{
22672267
// find how indented the line beginning the comment is
2268-
getvcol(curwin, trypos, &col, NULL, NULL);
2268+
getvcol(curwin, trypos, &col, NULL, NULL, 0);
22692269
amount = col;
22702270
goto theend;
22712271
}
@@ -2287,7 +2287,7 @@ get_c_indent(void)
22872287
int done = FALSE;
22882288

22892289
// find how indented the line beginning the comment is
2290-
getvcol(curwin, comment_pos, &col, NULL, NULL);
2290+
getvcol(curwin, comment_pos, &col, NULL, NULL, 0);
22912291
amount = col;
22922292
*lead_start = NUL;
22932293
*lead_middle = NUL;
@@ -2413,7 +2413,7 @@ get_c_indent(void)
24132413
if (*look != NUL) // if something after it
24142414
comment_pos->col = (colnr_T)(skipwhite(look) - start);
24152415
}
2416-
getvcol(curwin, comment_pos, &col, NULL, NULL);
2416+
getvcol(curwin, comment_pos, &col, NULL, NULL, 0);
24172417
amount = col;
24182418
if (curbuf->b_ind_in_comment2 || *look == NUL)
24192419
amount += curbuf->b_ind_in_comment;
@@ -2615,7 +2615,7 @@ get_c_indent(void)
26152615
// if we did the above "if".
26162616
if (our_paren_pos.col > 0)
26172617
{
2618-
getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
2618+
getvcol(curwin, &our_paren_pos, &col, NULL, NULL, 0);
26192619
if (cur_amount > (int)col)
26202620
cur_amount = col;
26212621
}
@@ -2704,7 +2704,7 @@ get_c_indent(void)
27042704
look = skipwhite(start);
27052705
if (*look == '{')
27062706
{
2707-
getvcol(curwin, trypos, &col, NULL, NULL);
2707+
getvcol(curwin, trypos, &col, NULL, NULL, 0);
27082708
amount = col;
27092709
if (*start == '{')
27102710
start_brace = BRACE_IN_COL0;

src/drawline.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,8 @@ win_line(
14181418
wlv.fromcol = 0;
14191419
else
14201420
{
1421-
getvvcol(wp, top, (colnr_T *)&wlv.fromcol, NULL, NULL);
1421+
getvvcol(wp, top, (colnr_T *)&wlv.fromcol,
1422+
NULL, NULL, 0);
14221423
if (gchar_pos(top) == NUL)
14231424
wlv.tocol = wlv.fromcol + 1;
14241425
}
@@ -1437,11 +1438,11 @@ win_line(
14371438
pos = *bot;
14381439
if (*p_sel == 'e')
14391440
getvvcol(wp, &pos, (colnr_T *)&wlv.tocol,
1440-
NULL, NULL);
1441+
NULL, NULL, 0);
14411442
else
14421443
{
14431444
getvvcol(wp, &pos, NULL, NULL,
1444-
(colnr_T *)&wlv.tocol);
1445+
(colnr_T *)&wlv.tocol, 0);
14451446
++wlv.tocol;
14461447
}
14471448
}
@@ -1480,14 +1481,14 @@ win_line(
14801481
{
14811482
if (lnum == curwin->w_cursor.lnum)
14821483
getvcol(curwin, &(curwin->w_cursor),
1483-
(colnr_T *)&wlv.fromcol, NULL, NULL);
1484+
(colnr_T *)&wlv.fromcol, NULL, NULL, 0);
14841485
else
14851486
wlv.fromcol = 0;
14861487
if (lnum == curwin->w_cursor.lnum + search_match_lines)
14871488
{
14881489
pos.lnum = lnum;
14891490
pos.col = search_match_endcol;
1490-
getvcol(curwin, &pos, (colnr_T *)&wlv.tocol, NULL, NULL);
1491+
getvcol(curwin, &pos, (colnr_T *)&wlv.tocol, NULL, NULL, 0);
14911492
}
14921493
else
14931494
wlv.tocol = MAXCOL;
@@ -1761,7 +1762,7 @@ win_line(
17611762
{
17621763
chartabsize_T cts;
17631764
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
1764-
(void)win_lbr_chartabsize(&cts, NULL);
1765+
(void)win_lbr_chartabsize(&cts, NULL, NULL);
17651766
vcol_first_char = cts.cts_first_char;
17661767
clear_chartabsize_arg(&cts);
17671768
}
@@ -1785,7 +1786,7 @@ win_line(
17851786
while (cts.cts_vcol < v)
17861787
{
17871788
head = 0;
1788-
charsize = win_lbr_chartabsize(&cts, &head);
1789+
charsize = win_lbr_chartabsize(&cts, &head, NULL);
17891790
cts.cts_vcol += charsize;
17901791
prev_ptr = cts.cts_ptr;
17911792
if (*prev_ptr == NUL)
@@ -3120,7 +3121,8 @@ win_line(
31203121
// do not want virtual text counted here
31213122
cts.cts_has_prop_with_text = FALSE;
31223123
# endif
3123-
wlv.n_extra = win_lbr_chartabsize(&cts, NULL) - 1;
3124+
// TODO: consider using "tailp" here
3125+
wlv.n_extra = win_lbr_chartabsize(&cts, NULL, NULL) - 1;
31243126
clear_chartabsize_arg(&cts);
31253127

31263128
if (on_last_col && c != TAB)
@@ -3780,7 +3782,7 @@ win_line(
37803782
colnr_T tcol;
37813783

37823784
if (preedit_end_col == MAXCOL)
3783-
getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL);
3785+
getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL, 0);
37843786
else
37853787
tcol = preedit_end_col;
37863788
if ((long)preedit_start_col <= wlv.vcol && wlv.vcol < (long)tcol)

0 commit comments

Comments
 (0)