Skip to content

Commit 6e55e85

Browse files
zeertzjqchrisbra
authored andcommitted
patch 9.0.1825: wrong cursor position with virt text and 'linebreak'
Problem: Wrong cursor position with virtual text before a whitespace character and 'linebreak'. Solution: Always set "col_adj" to "size - 1" and apply 'linebreak' after adding the size of 'breakindent' and 'showbreak'. closes: #12956 Signed-off-by: Christian Brabandt <[email protected]> Co-authored-by: zeertzjq <[email protected]>
1 parent 5bbcfbc commit 6e55e85

5 files changed

Lines changed: 87 additions & 59 deletions

File tree

src/charset.c

Lines changed: 54 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,14 +1118,8 @@ win_lbr_chartabsize(
11181118
char_u *s = cts->cts_ptr;
11191119
colnr_T vcol = cts->cts_vcol;
11201120
#ifdef FEAT_LINEBREAK
1121-
int c;
11221121
int size;
1123-
colnr_T col2;
1124-
colnr_T col_adj = 0; // vcol + screen size of tab
1125-
colnr_T colmax;
11261122
int mb_added = 0;
1127-
char_u *ps;
1128-
int tab_corr = (*s == TAB);
11291123
int n;
11301124
char_u *sbr;
11311125
int no_sbr = FALSE;
@@ -1248,55 +1242,7 @@ win_lbr_chartabsize(
12481242
# endif
12491243

12501244
# ifdef FEAT_LINEBREAK
1251-
c = *s;
1252-
if (tab_corr)
1253-
col_adj = size - 1;
1254-
1255-
/*
1256-
* If 'linebreak' set check at a blank before a non-blank if the line
1257-
* needs a break here
1258-
*/
1259-
if (wp->w_p_lbr
1260-
&& VIM_ISBREAK(c)
1261-
&& !VIM_ISBREAK((int)s[1])
1262-
&& wp->w_p_wrap
1263-
&& wp->w_width != 0)
1264-
{
1265-
/*
1266-
* Count all characters from first non-blank after a blank up to next
1267-
* non-blank after a blank.
1268-
*/
1269-
int numberextra = win_col_off(wp);
1270-
col2 = vcol;
1271-
colmax = (colnr_T)(wp->w_width - numberextra - col_adj);
1272-
if (vcol >= colmax)
1273-
{
1274-
colmax += col_adj;
1275-
n = colmax + win_col_off2(wp);
1276-
if (n > 0)
1277-
colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
1278-
}
1279-
1280-
for (;;)
1281-
{
1282-
ps = s;
1283-
MB_PTR_ADV(s);
1284-
c = *s;
1285-
if (!(c != NUL
1286-
&& (VIM_ISBREAK(c)
1287-
|| (!VIM_ISBREAK(c)
1288-
&& (col2 == vcol || !VIM_ISBREAK((int)*ps))))))
1289-
break;
1290-
1291-
col2 += win_chartabsize(wp, s, col2);
1292-
if (col2 >= colmax) // doesn't fit
1293-
{
1294-
size = colmax - vcol + col_adj;
1295-
break;
1296-
}
1297-
}
1298-
}
1299-
else if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
1245+
if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
13001246
&& wp->w_p_wrap && in_win_border(wp, vcol))
13011247
{
13021248
++size; // Count the ">" in the last column.
@@ -1314,11 +1260,10 @@ win_lbr_chartabsize(
13141260
{
13151261
int col_off_prev = win_col_off(wp);
13161262
int width2 = wp->w_width - col_off_prev + win_col_off2(wp);
1317-
vcol += mb_added;
1263+
colnr_T wcol = vcol + col_off_prev;
13181264
#ifdef FEAT_PROP_POPUP
1319-
vcol -= wp->w_virtcol_first_char;
1265+
wcol -= wp->w_virtcol_first_char;
13201266
#endif
1321-
colnr_T wcol = vcol + col_off_prev;
13221267
colnr_T max_head_vcol = cts->cts_max_head_vcol;
13231268
int added = 0;
13241269

@@ -1342,6 +1287,8 @@ win_lbr_chartabsize(
13421287
if (max_head_vcol <= 0 || vcol < max_head_vcol)
13431288
head += head_prev;
13441289
}
1290+
else
1291+
head_prev = 0;
13451292
wcol += col_off_prev;
13461293
}
13471294

@@ -1374,7 +1321,7 @@ win_lbr_chartabsize(
13741321
else if (max_head_vcol < 0)
13751322
{
13761323
int off = 0;
1377-
if (c != NUL
1324+
if (*s != NUL
13781325
&& ((State & MODE_NORMAL) || cts->cts_start_incl))
13791326
off += cts->cts_cur_text_width;
13801327
if (off >= prev_rem)
@@ -1386,8 +1333,56 @@ win_lbr_chartabsize(
13861333

13871334
size += added;
13881335
}
1336+
13891337
if (headp != NULL)
13901338
*headp = head;
1339+
1340+
/*
1341+
* If 'linebreak' set check at a blank before a non-blank if the line
1342+
* needs a break here
1343+
*/
1344+
if (wp->w_p_lbr
1345+
&& VIM_ISBREAK((int)s[0])
1346+
&& !VIM_ISBREAK((int)s[1])
1347+
&& wp->w_p_wrap
1348+
&& wp->w_width != 0)
1349+
{
1350+
/*
1351+
* Count all characters from first non-blank after a blank up to next
1352+
* non-blank after a blank.
1353+
*/
1354+
int numberextra = win_col_off(wp);
1355+
colnr_T col_adj = size - 1;
1356+
colnr_T colmax = (colnr_T)(wp->w_width - numberextra - col_adj);
1357+
if (vcol >= colmax)
1358+
{
1359+
colmax += col_adj;
1360+
n = colmax + win_col_off2(wp);
1361+
if (n > 0)
1362+
colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
1363+
}
1364+
1365+
colnr_T vcol2 = vcol;
1366+
for (;;)
1367+
{
1368+
char_u *ps = s;
1369+
MB_PTR_ADV(s);
1370+
int c = *s;
1371+
if (!(c != NUL
1372+
&& (VIM_ISBREAK(c)
1373+
|| (!VIM_ISBREAK(c)
1374+
&& (vcol2 == vcol || !VIM_ISBREAK((int)*ps))))))
1375+
break;
1376+
1377+
vcol2 += win_chartabsize(wp, s, vcol2);
1378+
if (vcol2 >= colmax) // doesn't fit
1379+
{
1380+
size = colmax - vcol + col_adj;
1381+
break;
1382+
}
1383+
}
1384+
}
1385+
13911386
return size;
13921387
# endif
13931388
#endif
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
|a+0&#ffffff0@49
2+
| @1|++0#4040ff13&|b+0#e000e06&@9| +0#0000000&@36
3+
@2|++0#4040ff13&|c+0#0000000&@43>c| @1
4+
|~+0#4040ff13&| @48
5+
|~| @48
6+
| +0#0000000&@31|1|,|9|6|-|1|4|8| @5|A|l@1|
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
|a+0&#ffffff0@44|b+0#e000e06&@4
2+
| +0#0000000&@1|++0#4040ff13&|b+0#e000e06&@4| +0#0000000&@41
3+
@2|++0#4040ff13&|c+0#0000000&@43>c| @1
4+
|~+0#4040ff13&| @48
5+
|~| @48
6+
| +0#0000000&@31|1|,|9|1|-|1|4|8| @5|A|l@1|

src/testdir/test_textprop.vim

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2791,6 +2791,25 @@ func Test_prop_before_tab_skipcol()
27912791
call StopVimInTerminal(buf)
27922792
endfunc
27932793

2794+
func Test_prop_inserts_text_before_linebreak()
2795+
CheckRunVimInTerminal
2796+
2797+
let lines =<< trim END
2798+
setlocal linebreak showbreak=+ breakindent breakindentopt=shift:2
2799+
call setline(1, repeat('a', 50) .. ' ' .. repeat('c', 45))
2800+
call prop_type_add('theprop', #{highlight: 'Special'})
2801+
call prop_add(1, 51, #{type: 'theprop', text: repeat('b', 10), text_wrap: 'wrap'})
2802+
normal! $
2803+
END
2804+
call writefile(lines, 'XscriptPropsBeforeLinebreak', 'D')
2805+
let buf = RunVimInTerminal('-S XscriptPropsBeforeLinebreak', #{rows: 6, cols: 50})
2806+
call VerifyScreenDump(buf, 'Test_prop_inserts_text_before_linebreak_1', {})
2807+
call term_sendkeys(buf, '05x$')
2808+
call VerifyScreenDump(buf, 'Test_prop_inserts_text_before_linebreak_2', {})
2809+
2810+
call StopVimInTerminal(buf)
2811+
endfunc
2812+
27942813
func Test_prop_inserts_text_lcs_extends()
27952814
CheckRunVimInTerminal
27962815

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,8 @@ static char *(features[]) =
699699

700700
static int included_patches[] =
701701
{ /* Add new patch number below this line */
702+
/**/
703+
1825,
702704
/**/
703705
1824,
704706
/**/

0 commit comments

Comments
 (0)