Mercurial > vim
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 |