Mercurial > vim
comparison src/charset.c @ 33077:d03841a271aa v9.0.1825
patch 9.0.1825: wrong cursor position with virt text and 'linebreak'
Commit: https://github.com/vim/vim/commit/6e55e85f92aff43c1b3cb564201440f3552d63f0
Author: zeertzjq <zeertzjq@outlook.com>
Date: Wed Aug 30 16:55:09 2023 +0200
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 <cb@256bit.org>
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Wed, 30 Aug 2023 17:00:03 +0200 |
parents | 0561bf3ba10c |
children | 4be1ffa13b56 |
comparison
equal
deleted
inserted
replaced
33076:d36b31ab54c4 | 33077:d03841a271aa |
---|---|
1116 char_u *line = cts->cts_line; // start of the line | 1116 char_u *line = cts->cts_line; // start of the line |
1117 #endif | 1117 #endif |
1118 char_u *s = cts->cts_ptr; | 1118 char_u *s = cts->cts_ptr; |
1119 colnr_T vcol = cts->cts_vcol; | 1119 colnr_T vcol = cts->cts_vcol; |
1120 #ifdef FEAT_LINEBREAK | 1120 #ifdef FEAT_LINEBREAK |
1121 int c; | |
1122 int size; | 1121 int size; |
1123 colnr_T col2; | |
1124 colnr_T col_adj = 0; // vcol + screen size of tab | |
1125 colnr_T colmax; | |
1126 int mb_added = 0; | 1122 int mb_added = 0; |
1127 char_u *ps; | |
1128 int tab_corr = (*s == TAB); | |
1129 int n; | 1123 int n; |
1130 char_u *sbr; | 1124 char_u *sbr; |
1131 int no_sbr = FALSE; | 1125 int no_sbr = FALSE; |
1132 #endif | 1126 #endif |
1133 | 1127 |
1246 } | 1240 } |
1247 } | 1241 } |
1248 # endif | 1242 # endif |
1249 | 1243 |
1250 # ifdef FEAT_LINEBREAK | 1244 # ifdef FEAT_LINEBREAK |
1251 c = *s; | 1245 if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1 |
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 | |
1300 && wp->w_p_wrap && in_win_border(wp, vcol)) | 1246 && wp->w_p_wrap && in_win_border(wp, vcol)) |
1301 { | 1247 { |
1302 ++size; // Count the ">" in the last column. | 1248 ++size; // Count the ">" in the last column. |
1303 mb_added = 1; | 1249 mb_added = 1; |
1304 } | 1250 } |
1312 // When "size" is 0, no new screen line is started. | 1258 // When "size" is 0, no new screen line is started. |
1313 if (size > 0 && wp->w_p_wrap && (*sbr != NUL || wp->w_p_bri)) | 1259 if (size > 0 && wp->w_p_wrap && (*sbr != NUL || wp->w_p_bri)) |
1314 { | 1260 { |
1315 int col_off_prev = win_col_off(wp); | 1261 int col_off_prev = win_col_off(wp); |
1316 int width2 = wp->w_width - col_off_prev + win_col_off2(wp); | 1262 int width2 = wp->w_width - col_off_prev + win_col_off2(wp); |
1317 vcol += mb_added; | 1263 colnr_T wcol = vcol + col_off_prev; |
1318 #ifdef FEAT_PROP_POPUP | 1264 #ifdef FEAT_PROP_POPUP |
1319 vcol -= wp->w_virtcol_first_char; | 1265 wcol -= wp->w_virtcol_first_char; |
1320 #endif | 1266 #endif |
1321 colnr_T wcol = vcol + col_off_prev; | |
1322 colnr_T max_head_vcol = cts->cts_max_head_vcol; | 1267 colnr_T max_head_vcol = cts->cts_max_head_vcol; |
1323 int added = 0; | 1268 int added = 0; |
1324 | 1269 |
1325 // cells taken by 'showbreak'/'breakindent' before current char | 1270 // cells taken by 'showbreak'/'breakindent' before current char |
1326 int head_prev = 0; | 1271 int head_prev = 0; |
1340 wcol += head_prev; | 1285 wcol += head_prev; |
1341 added += head_prev; | 1286 added += head_prev; |
1342 if (max_head_vcol <= 0 || vcol < max_head_vcol) | 1287 if (max_head_vcol <= 0 || vcol < max_head_vcol) |
1343 head += head_prev; | 1288 head += head_prev; |
1344 } | 1289 } |
1290 else | |
1291 head_prev = 0; | |
1345 wcol += col_off_prev; | 1292 wcol += col_off_prev; |
1346 } | 1293 } |
1347 | 1294 |
1348 if (wcol + size > wp->w_width) | 1295 if (wcol + size > wp->w_width) |
1349 { | 1296 { |
1372 + width2 - 1) / width2 * head_mid; | 1319 + width2 - 1) / width2 * head_mid; |
1373 #ifdef FEAT_PROP_POPUP | 1320 #ifdef FEAT_PROP_POPUP |
1374 else if (max_head_vcol < 0) | 1321 else if (max_head_vcol < 0) |
1375 { | 1322 { |
1376 int off = 0; | 1323 int off = 0; |
1377 if (c != NUL | 1324 if (*s != NUL |
1378 && ((State & MODE_NORMAL) || cts->cts_start_incl)) | 1325 && ((State & MODE_NORMAL) || cts->cts_start_incl)) |
1379 off += cts->cts_cur_text_width; | 1326 off += cts->cts_cur_text_width; |
1380 if (off >= prev_rem) | 1327 if (off >= prev_rem) |
1381 head += (1 + (off - prev_rem) / width) * head_mid; | 1328 head += (1 + (off - prev_rem) / width) * head_mid; |
1382 } | 1329 } |
1384 } | 1331 } |
1385 } | 1332 } |
1386 | 1333 |
1387 size += added; | 1334 size += added; |
1388 } | 1335 } |
1336 | |
1389 if (headp != NULL) | 1337 if (headp != NULL) |
1390 *headp = head; | 1338 *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 | |
1391 return size; | 1386 return size; |
1392 # endif | 1387 # endif |
1393 #endif | 1388 #endif |
1394 } | 1389 } |
1395 | 1390 |