comparison src/charset.c @ 32981:2415680a2554 v9.0.1783

commit b557f4898208105b674df605403cac1b1292707b Author: zeertzjq <zeertzjq@outlook.com> Date: Tue Aug 22 22:07:34 2023 +0200 patch 9.0.1783: Display issues with virt text smoothscroll and showbreak Problem: Wrong display with wrapping virtual text or unprintable chars, 'showbreak' and 'smoothscroll'. Solution: Don't skip cells taken by 'showbreak' in screen lines before "w_skipcol". Combined "n_skip" and "skip_cells". closes: #12597 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: zeertzjq <zeertzjq@outlook.com>
author Christian Brabandt <cb@256bit.org>
date Thu, 24 Aug 2023 07:47:10 +0200
parents 5d17e74a756d
children 68a12270d21b ebb36e3d5299
comparison
equal deleted inserted replaced
32964:c7a332a34fe7 32981:2415680a2554
1095 * Return the screen size of the character indicated by "cts". 1095 * Return the screen size of the character indicated by "cts".
1096 * "cts->cts_cur_text_width" is set to the extra size for a text property that 1096 * "cts->cts_cur_text_width" is set to the extra size for a text property that
1097 * inserts text. 1097 * inserts text.
1098 * This function is used very often, keep it fast!!!! 1098 * This function is used very often, keep it fast!!!!
1099 * 1099 *
1100 * If "headp" not NULL, set *headp to the size of what we for 'showbreak' 1100 * If "headp" not NULL, set "*headp" to the size of 'showbreak'/'breakindent'
1101 * string at start of line. Warning: *headp is only set if it's a non-zero 1101 * included in the return value.
1102 * value, init to 0 before calling. 1102 * When "cts->cts_max_head_vcol" is positive, only count in "*headp" the size
1103 * of 'showbreak'/'breakindent' before "cts->cts_max_head_vcol".
1104 * When "cts->cts_max_head_vcol" is negative, only count in "*headp" the size
1105 * of 'showbreak'/'breakindent' before where cursor should be placed.
1106 *
1107 * Warning: "*headp" may not be set if it's 0, init to 0 before calling.
1103 */ 1108 */
1104 int 1109 int
1105 win_lbr_chartabsize( 1110 win_lbr_chartabsize(
1106 chartabsize_T *cts, 1111 chartabsize_T *cts,
1107 int *headp UNUSED) 1112 int *headp UNUSED)
1116 int c; 1121 int c;
1117 int size; 1122 int size;
1118 colnr_T col2; 1123 colnr_T col2;
1119 colnr_T col_adj = 0; // vcol + screen size of tab 1124 colnr_T col_adj = 0; // vcol + screen size of tab
1120 colnr_T colmax; 1125 colnr_T colmax;
1121 int added;
1122 int mb_added = 0; 1126 int mb_added = 0;
1123 int numberextra;
1124 char_u *ps; 1127 char_u *ps;
1125 int tab_corr = (*s == TAB); 1128 int tab_corr = (*s == TAB);
1126 int n; 1129 int n;
1127 char_u *sbr; 1130 char_u *sbr;
1128 int no_sbr = FALSE; 1131 int no_sbr = FALSE;
1254 { 1257 {
1255 /* 1258 /*
1256 * Count all characters from first non-blank after a blank up to next 1259 * Count all characters from first non-blank after a blank up to next
1257 * non-blank after a blank. 1260 * non-blank after a blank.
1258 */ 1261 */
1259 numberextra = win_col_off(wp); 1262 int numberextra = win_col_off(wp);
1260 col2 = vcol; 1263 col2 = vcol;
1261 colmax = (colnr_T)(wp->w_width - numberextra - col_adj); 1264 colmax = (colnr_T)(wp->w_width - numberextra - col_adj);
1262 if (vcol >= colmax) 1265 if (vcol >= colmax)
1263 { 1266 {
1264 colmax += col_adj; 1267 colmax += col_adj;
1294 } 1297 }
1295 1298
1296 /* 1299 /*
1297 * May have to add something for 'breakindent' and/or 'showbreak' 1300 * May have to add something for 'breakindent' and/or 'showbreak'
1298 * string at start of line. 1301 * string at start of line.
1299 * Set *headp to the size of what we add.
1300 * Do not use 'showbreak' at the NUL after the text. 1302 * Do not use 'showbreak' at the NUL after the text.
1301 */ 1303 */
1302 added = 0; 1304 int head = mb_added;
1303 sbr = (c == NUL || no_sbr) ? empty_option : get_showbreak_value(wp); 1305 sbr = (c == NUL || no_sbr) ? empty_option : get_showbreak_value(wp);
1304 if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && vcol != 0) 1306 if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap)
1305 { 1307 {
1306 colnr_T sbrlen = 0; 1308 int col_off_prev = win_col_off(wp);
1307 int numberwidth = win_col_off(wp); 1309 int width2 = wp->w_width - col_off_prev + win_col_off2(wp);
1308 1310 vcol += mb_added;
1309 numberextra = numberwidth;
1310 vcol += numberextra + mb_added;
1311 #ifdef FEAT_PROP_POPUP 1311 #ifdef FEAT_PROP_POPUP
1312 vcol -= wp->w_virtcol_first_char; 1312 vcol -= wp->w_virtcol_first_char;
1313 #endif 1313 #endif
1314 if (vcol >= (colnr_T)wp->w_width) 1314 colnr_T wcol = vcol + col_off_prev;
1315 { 1315 // cells taken by 'showbreak'/'breakindent' before current char
1316 vcol -= wp->w_width; 1316 int head_prev = 0;
1317 numberextra = wp->w_width - (numberextra - win_col_off2(wp)); 1317 if (wcol >= wp->w_width)
1318 if (vcol >= numberextra && numberextra > 0) 1318 {
1319 vcol %= numberextra; 1319 wcol -= wp->w_width;
1320 col_off_prev = wp->w_width - width2;
1321 if (wcol >= width2 && width2 > 0)
1322 wcol %= width2;
1320 if (*sbr != NUL) 1323 if (*sbr != NUL)
1321 { 1324 head_prev += vim_strsize(sbr);
1322 sbrlen = (colnr_T)MB_CHARLEN(sbr); 1325 if (wp->w_p_bri)
1323 if (vcol >= sbrlen) 1326 head_prev += get_breakindent_win(wp, line);
1324 vcol -= sbrlen; 1327 if (wcol < head_prev)
1325 } 1328 wcol = head_prev;
1326 if (vcol >= numberextra && numberextra > 0) 1329 wcol += col_off_prev;
1327 vcol = vcol % numberextra; 1330 }
1328 else if (vcol > 0 && numberextra > 0) 1331
1329 vcol += numberwidth - win_col_off2(wp); 1332 if ((vcol > 0 && wcol == col_off_prev + head_prev)
1330 1333 || wcol + size > wp->w_width)
1331 numberwidth -= win_col_off2(wp); 1334 {
1332 } 1335 int added = 0;
1333 if (vcol == 0 || vcol + size + sbrlen > (colnr_T)wp->w_width) 1336 colnr_T max_head_vcol = cts->cts_max_head_vcol;
1334 { 1337
1335 added = 0; 1338 if (vcol > 0 && wcol == col_off_prev + head_prev)
1339 {
1340 added += head_prev;
1341 if (max_head_vcol <= 0 || vcol < max_head_vcol)
1342 head += head_prev;
1343 }
1344
1345 // cells taken by 'showbreak'/'breakindent' halfway current char
1346 int head_mid = 0;
1336 if (*sbr != NUL) 1347 if (*sbr != NUL)
1337 { 1348 head_mid += vim_strsize(sbr);
1338 if (size + sbrlen + numberwidth > (colnr_T)wp->w_width) 1349 if (wp->w_p_bri)
1350 head_mid += get_breakindent_win(wp, line);
1351 if (head_mid > 0)
1352 {
1353 if (wcol + size > wp->w_width)
1339 { 1354 {
1340 // calculate effective window width 1355 // calculate effective window width
1341 int width = (colnr_T)wp->w_width - sbrlen - numberwidth; 1356 int prev_rem = wp->w_width - wcol;
1342 int prev_width = vcol 1357 int width = width2 - head_mid;
1343 ? ((colnr_T)wp->w_width - (sbrlen + vcol)) : 0;
1344 1358
1345 if (width <= 0) 1359 if (width <= 0)
1346 width = (colnr_T)1; 1360 width = 1;
1347 added += ((size - prev_width) / width) * vim_strsize(sbr); 1361 // divide "size - prev_width" by "width", rounding up
1348 if ((size - prev_width) % width) 1362 int cnt = (size - prev_rem + width - 1) / width;
1349 // wrapped, add another length of 'sbr' 1363 added += cnt * head_mid;
1350 added += vim_strsize(sbr); 1364
1365 if (max_head_vcol == 0
1366 || vcol + size + added < max_head_vcol)
1367 head += cnt * head_mid;
1368 else if (max_head_vcol > vcol + head_prev + prev_rem)
1369 head += (max_head_vcol - (vcol + head_prev + prev_rem)
1370 + width2 - 1) / width2 * head_mid;
1371 #ifdef FEAT_PROP_POPUP
1372 else if (max_head_vcol < 0)
1373 {
1374 int off = 0;
1375 if ((State & MODE_NORMAL) || cts->cts_start_incl)
1376 off += cts->cts_cur_text_width;
1377 if (off >= prev_rem)
1378 head += (1 + (off - prev_rem) / width) * head_mid;
1379 }
1380 #endif
1351 } 1381 }
1352 else 1382 }
1353 added += vim_strsize(sbr);
1354 }
1355 if (wp->w_p_bri)
1356 added += get_breakindent_win(wp, line);
1357 1383
1358 size += added; 1384 size += added;
1359 if (vcol != 0)
1360 added = 0;
1361 } 1385 }
1362 } 1386 }
1363 if (headp != NULL) 1387 if (headp != NULL)
1364 *headp = added + mb_added; 1388 *headp = head;
1365 return size; 1389 return size;
1366 # endif 1390 # endif
1367 #endif 1391 #endif
1368 } 1392 }
1369 1393
1481 // always start on the first byte 1505 // always start on the first byte
1482 posptr -= (*mb_head_off)(line, posptr); 1506 posptr -= (*mb_head_off)(line, posptr);
1483 } 1507 }
1484 1508
1485 init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line); 1509 init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
1510 cts.cts_max_head_vcol = -1;
1486 1511
1487 /* 1512 /*
1488 * This function is used very often, do some speed optimizations. 1513 * This function is used very often, do some speed optimizations.
1489 * When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set 1514 * When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
1490 * and there are no text properties with "text" use a simple loop. 1515 * and there are no text properties with "text" use a simple loop.