comparison src/drawline.c @ 30205:ed6f3d2593df v9.0.0438

patch 9.0.0438: cannot put virtual text above a line Commit: https://github.com/vim/vim/commit/04e0ed1ddf399d609dbcb7dbf19e531da1fe6172 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Sep 10 20:00:56 2022 +0100 patch 9.0.0438: cannot put virtual text above a line Problem: Cannot put virtual text above a line. Solution: Add the "above" value for "text_align".
author Bram Moolenaar <Bram@vim.org>
date Sat, 10 Sep 2022 21:15:03 +0200
parents 4b9b237d1211
children 4fedacdad3b4
comparison
equal deleted inserted replaced
30204:b6c11bb32c89 30205:ed6f3d2593df
277 } 277 }
278 #endif 278 #endif
279 279
280 #if defined(FEAT_PROP_POPUP) || defined(PROTO) 280 #if defined(FEAT_PROP_POPUP) || defined(PROTO)
281 /* 281 /*
282 * Return the cell size of virtual text after truncation.
283 */
284 static int
285 textprop_size_after_trunc(
286 win_T *wp,
287 int flags, // TP_FLAG_ALIGN_*
288 int added,
289 char_u *text,
290 int *n_used_ptr)
291 {
292 int space = (flags & (TP_FLAG_ALIGN_BELOW | TP_FLAG_ALIGN_ABOVE))
293 ? wp->w_width : added;
294 int len = (int)STRLEN(text);
295 int strsize = 0;
296 int n_used;
297
298 // if the remaining size is to small wrap anyway and use the next line
299 if (space < PROP_TEXT_MIN_CELLS)
300 space += wp->w_width;
301 for (n_used = 0; n_used < len; n_used += (*mb_ptr2len)(text + n_used))
302 {
303 int clen = ptr2cells(text + n_used);
304
305 if (strsize + clen > space)
306 break;
307 strsize += clen;
308 }
309 *n_used_ptr = n_used;
310 return strsize;
311 }
312
313 /*
282 * Take care of padding, right-align and truncation of virtual text after a 314 * Take care of padding, right-align and truncation of virtual text after a
283 * line. 315 * line.
284 * if "n_attr" is not NULL then "n_extra" and "p_extra" are adjusted for any 316 * if "n_attr" is not NULL then "n_extra" and "p_extra" are adjusted for any
285 * padding, right-align and truncation. Otherwise only the size is computed. 317 * padding, right-align and truncation. Otherwise only the size is computed.
286 * When "n_attr" is NULL returns the number of screen cells used. 318 * When "n_attr" is NULL returns the number of screen cells used.
295 char_u **p_extra, // virtual text 327 char_u **p_extra, // virtual text
296 int *n_attr, // attribute cells, NULL if not used 328 int *n_attr, // attribute cells, NULL if not used
297 int *n_attr_skip) // cells to skip attr, NULL if not used 329 int *n_attr_skip) // cells to skip attr, NULL if not used
298 { 330 {
299 int right = (tp->tp_flags & TP_FLAG_ALIGN_RIGHT); 331 int right = (tp->tp_flags & TP_FLAG_ALIGN_RIGHT);
332 int above = (tp->tp_flags & TP_FLAG_ALIGN_ABOVE);
300 int below = (tp->tp_flags & TP_FLAG_ALIGN_BELOW); 333 int below = (tp->tp_flags & TP_FLAG_ALIGN_BELOW);
301 int wrap = (tp->tp_flags & TP_FLAG_WRAP); 334 int wrap = (tp->tp_flags & TP_FLAG_WRAP);
302 int padding = tp->tp_col == MAXCOL && tp->tp_len > 1 335 int padding = tp->tp_col == MAXCOL && tp->tp_len > 1
303 ? tp->tp_len - 1 : 0; 336 ? tp->tp_len - 1 : 0;
304 int col_with_padding = vcol + (below ? 0 : padding); 337 int col_with_padding = vcol + (below ? 0 : padding);
305 int col_off = 0; 338 int col_off = 0;
306 int room = wp->w_width - col_with_padding; 339 int room = wp->w_width - col_with_padding;
307 int added = room; 340 int before = room; // spaces before the text
341 int after = 0; // spaces after the text
308 int n_used = *n_extra; 342 int n_used = *n_extra;
309 char_u *l = NULL; 343 char_u *l = NULL;
310 int strsize = vim_strsize(*p_extra); 344 int strsize = vim_strsize(*p_extra);
311 int cells = wrap ? strsize 345 int cells = wrap ? strsize : textprop_size_after_trunc(wp,
312 : textprop_size_after_trunc(wp, below, added, *p_extra, &n_used); 346 tp->tp_flags, before, *p_extra, &n_used);
313 347
314 if (wrap || right || below || padding > 0 || n_used < *n_extra) 348 if (wrap || right || above || below || padding > 0 || n_used < *n_extra)
315 { 349 {
316 // Right-align: fill with spaces 350 if (above)
317 if (right) 351 {
318 added -= cells; 352 before = 0;
319 if (added < 0 353 after = wp->w_width - cells;
320 || !(right || below) 354 }
321 || (below 355 else
322 ? (col_with_padding == 0 || !wp->w_p_wrap) 356 {
323 : (n_used < *n_extra))) 357 // Right-align: fill with before
324 { 358 if (right)
325 if (right && (wrap || room < PROP_TEXT_MIN_CELLS)) 359 before -= cells;
326 { 360 if (before < 0
327 // right-align on next line instead of wrapping if possible 361 || !(right || below)
328 col_off = win_col_off(wp) + win_col_off2(wp); 362 || (below
329 added = wp->w_width - col_off - strsize + room; 363 ? (col_with_padding == 0 || !wp->w_p_wrap)
330 if (added < 0) 364 : (n_used < *n_extra)))
331 added = 0; 365 {
366 if (right && (wrap || room < PROP_TEXT_MIN_CELLS))
367 {
368 // right-align on next line instead of wrapping if possible
369 col_off = win_col_off(wp) + win_col_off2(wp);
370 before = wp->w_width - col_off - strsize + room;
371 if (before < 0)
372 before = 0;
373 else
374 n_used = *n_extra;
375 }
332 else 376 else
333 n_used = *n_extra; 377 before = 0;
334 } 378 }
335 else
336 added = 0;
337 } 379 }
338 380
339 // With 'nowrap' add one to show the "extends" character if needed (it 381 // With 'nowrap' add one to show the "extends" character if needed (it
340 // doesn't show if the text just fits). 382 // doesn't show if the text just fits).
341 if (!wp->w_p_wrap 383 if (!wp->w_p_wrap
344 && wp->w_p_list) 386 && wp->w_p_list)
345 ++n_used; 387 ++n_used;
346 388
347 // add 1 for NUL, 2 for when '…' is used 389 // add 1 for NUL, 2 for when '…' is used
348 if (n_attr != NULL) 390 if (n_attr != NULL)
349 l = alloc(n_used + added + padding + 3); 391 l = alloc(n_used + before + after + padding + 3);
350 if (n_attr == NULL || l != NULL) 392 if (n_attr == NULL || l != NULL)
351 { 393 {
352 int off = 0; 394 int off = 0;
353 395
354 if (n_attr != NULL) 396 if (n_attr != NULL)
355 { 397 {
356 vim_memset(l, ' ', added); 398 vim_memset(l, ' ', before);
357 off += added; 399 off += before;
358 if (padding > 0) 400 if (padding > 0)
359 { 401 {
360 vim_memset(l + off, ' ', padding); 402 vim_memset(l + off, ' ', padding);
361 off += padding; 403 off += padding;
362 } 404 }
363 vim_strncpy(l + off, *p_extra, n_used); 405 vim_strncpy(l + off, *p_extra, n_used);
364 off += n_used; 406 off += n_used;
365 } 407 }
366 else 408 else
367 { 409 {
368 off = added + padding + n_used; 410 off = before + after + padding + n_used;
369 cells += added + padding; 411 cells += before + after + padding;
370 } 412 }
371 if (n_attr != NULL) 413 if (n_attr != NULL)
372 { 414 {
373 if (n_used < *n_extra && wp->w_p_wrap) 415 if (n_used < *n_extra && wp->w_p_wrap)
374 { 416 {
383 } 425 }
384 else 426 else
385 // change last character to '>' 427 // change last character to '>'
386 *lp = '>'; 428 *lp = '>';
387 } 429 }
430 else if (after > 0)
431 {
432 vim_memset(l + off, ' ', after);
433 l[off + after] = NUL;
434 }
435
388 *p_extra = l; 436 *p_extra = l;
389 *n_extra = n_used + added + padding; 437 *n_extra = n_used + before + after + padding;
390 *n_attr = mb_charlen(*p_extra); 438 *n_attr = mb_charlen(*p_extra);
391 *n_attr_skip = added + padding + col_off; 439 *n_attr_skip = before + padding + col_off;
392 } 440 }
393 } 441 }
394 } 442 }
395 443
396 if (n_attr == NULL) 444 if (n_attr == NULL)
1692 // Add any text property that starts in this column. 1740 // Add any text property that starts in this column.
1693 // With 'nowrap' and not in the first screen line only "below" 1741 // With 'nowrap' and not in the first screen line only "below"
1694 // text prop can show. 1742 // text prop can show.
1695 while (text_prop_next < text_prop_count 1743 while (text_prop_next < text_prop_count
1696 && (text_props[text_prop_next].tp_col == MAXCOL 1744 && (text_props[text_prop_next].tp_col == MAXCOL
1697 ? (*ptr == NUL 1745 ? ((*ptr == NUL
1698 && (wp->w_p_wrap 1746 && (wp->w_p_wrap
1699 || wlv.row == startrow 1747 || wlv.row == startrow
1700 || (text_props[text_prop_next].tp_flags 1748 || (text_props[text_prop_next].tp_flags
1701 & TP_FLAG_ALIGN_BELOW))) 1749 & TP_FLAG_ALIGN_BELOW)))
1750 || (bcol == 0 &&
1751 (text_props[text_prop_next].tp_flags
1752 & TP_FLAG_ALIGN_ABOVE)))
1702 : bcol >= text_props[text_prop_next].tp_col - 1)) 1753 : bcol >= text_props[text_prop_next].tp_col - 1))
1703 { 1754 {
1704 if (text_props[text_prop_next].tp_col == MAXCOL 1755 if (text_props[text_prop_next].tp_col == MAXCOL
1705 && *ptr == NUL && wp->w_p_list && lcs_eol_one > 0) 1756 && *ptr == NUL && wp->w_p_list && lcs_eol_one > 0)
1706 { 1757 {
1771 1822
1772 if (p != NULL) 1823 if (p != NULL)
1773 { 1824 {
1774 int right = (tp->tp_flags 1825 int right = (tp->tp_flags
1775 & TP_FLAG_ALIGN_RIGHT); 1826 & TP_FLAG_ALIGN_RIGHT);
1827 int above = (tp->tp_flags
1828 & TP_FLAG_ALIGN_ABOVE);
1776 int below = (tp->tp_flags 1829 int below = (tp->tp_flags
1777 & TP_FLAG_ALIGN_BELOW); 1830 & TP_FLAG_ALIGN_BELOW);
1778 int wrap = (tp->tp_flags & TP_FLAG_WRAP); 1831 int wrap = (tp->tp_flags & TP_FLAG_WRAP);
1779 int padding = tp->tp_col == MAXCOL 1832 int padding = tp->tp_col == MAXCOL
1780 && tp->tp_len > 1 1833 && tp->tp_len > 1
1795 text_prop_attr_comb = 0; 1848 text_prop_attr_comb = 0;
1796 if (*ptr == NUL) 1849 if (*ptr == NUL)
1797 // don't combine char attr after EOL 1850 // don't combine char attr after EOL
1798 text_prop_flags &= ~PT_FLAG_COMBINE; 1851 text_prop_flags &= ~PT_FLAG_COMBINE;
1799 #ifdef FEAT_LINEBREAK 1852 #ifdef FEAT_LINEBREAK
1800 if (below || right || !wrap) 1853 if (above || below || right || !wrap)
1801 { 1854 {
1802 // no 'showbreak' before "below" text property 1855 // no 'showbreak' before "below" text property
1803 // or after "right" text property 1856 // or after "above" or "right" text property
1804 need_showbreak = FALSE; 1857 need_showbreak = FALSE;
1805 dont_use_showbreak = TRUE; 1858 dont_use_showbreak = TRUE;
1806 } 1859 }
1807 #endif 1860 #endif
1808 // Keep in sync with where 1861 if ((right || above || below || !wrap || padding > 0)
1809 // textprop_size_after_trunc() is called in
1810 // win_lbr_chartabsize().
1811 if ((right || below || !wrap || padding > 0)
1812 && wp->w_width > 2) 1862 && wp->w_width > 2)
1813 { 1863 {
1814 char_u *prev_p_extra = wlv.p_extra; 1864 char_u *prev_p_extra = wlv.p_extra;
1815 int start_line; 1865 int start_line;
1816 1866