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