diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2021-10-13 21:35:37 +0200 |
---|---|---|
committer | Björn Linse <bjorn.linse@gmail.com> | 2021-10-23 14:17:09 +0200 |
commit | 8d7816cf27c4ab08d9eff9e7ce3c541105c30ece (patch) | |
tree | 5ae91446ed6602a509ff06ea24aab525281b6b67 /src/nvim/decoration.c | |
parent | 8ade2f5b0495ee41868e52d48816d02249e2364d (diff) | |
download | rneovim-8d7816cf27c4ab08d9eff9e7ce3c541105c30ece.tar.gz rneovim-8d7816cf27c4ab08d9eff9e7ce3c541105c30ece.tar.bz2 rneovim-8d7816cf27c4ab08d9eff9e7ce3c541105c30ece.zip |
feat(decorations): support more than one virt_lines block
Diffstat (limited to 'src/nvim/decoration.c')
-rw-r--r-- | src/nvim/decoration.c | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 931c3fa20a..c0f3c32f93 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -91,12 +91,31 @@ void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor) if (kv_size(decor->virt_text)) { redraw_buf_line_later(buf, row1+1); } + + if (kv_size(decor->virt_lines)) { + redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, + row1+1+(decor->virt_lines_above?0:1))); + } +} + +void decor_remove(buf_T *buf, int row, int row2, Decoration *decor) +{ + if (kv_size(decor->virt_lines)) { + assert(buf->b_virt_line_blocks > 0); + buf->b_virt_line_blocks--; + } + decor_redraw(buf, row, row2, decor); + decor_free(decor); } void decor_free(Decoration *decor) { if (decor && !decor->shared) { clear_virttext(&decor->virt_text); + for (size_t i = 0; i < kv_size(decor->virt_lines); i++) { + clear_virttext(&kv_A(decor->virt_lines, i).line); + } + kv_destroy(decor->virt_lines); xfree(decor); } } @@ -118,7 +137,7 @@ Decoration *decor_find_virttext(buf_T *buf, int row, uint64_t ns_id) mtmark_t mark = marktree_itr_current(itr); if (mark.row < 0 || mark.row > row) { break; - } else if (mt_decor_level(mark.id) < 1) { + } else if (marktree_decor_level(mark.id) < kDecorLevelVisible) { goto next_mark; } ExtmarkItem *item = map_ref(uint64_t, ExtmarkItem)(buf->b_extmark_index, @@ -162,7 +181,7 @@ bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state) break; } if ((mark.row < top_row && mark.id&MARKTREE_END_FLAG) - || mt_decor_level(mark.id) < 1) { + || marktree_decor_level(mark.id) < kDecorLevelVisible) { goto next_mark; } @@ -255,7 +274,8 @@ int decor_redraw_col(buf_T *buf, int col, int win_col, bool hidden, DecorState * break; } - if ((mark.id&MARKTREE_END_FLAG) || mt_decor_level(mark.id) < 1) { + if ((mark.id&MARKTREE_END_FLAG) + || marktree_decor_level(mark.id) < kDecorLevelVisible) { goto next_mark; } @@ -417,33 +437,38 @@ void decor_free_all_mem(void) } -int decor_virtual_lines(win_T *wp, linenr_T lnum) +int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines) { buf_T *buf = wp->w_buffer; - if (!buf->b_virt_line_mark) { + if (!buf->b_virt_line_blocks) { + // Only pay for what you use: in case virt_lines feature is not active + // in a buffer, plines do not need to access the marktree at all return 0; } - if (buf->b_virt_line_pos < 0) { - mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL); - if (pos.row < 0) { - buf->b_virt_line_mark = 0; + + int virt_lines = 0; + int row = (int)MAX(lnum - 2, 0); + int end_row = (int)lnum; + MarkTreeIter itr[1] = { 0 }; + marktree_itr_get(buf->b_marktree, row, 0, itr); + while (true) { + mtmark_t mark = marktree_itr_current(itr); + if (mark.row < 0 || mark.row >= end_row) { + break; + } else if (marktree_decor_level(mark.id) < kDecorLevelVirtLine) { + goto next_mark; + } + bool above = mark.row > (int)(lnum - 2); + ExtmarkItem *item = map_ref(uint64_t, ExtmarkItem)(buf->b_extmark_index, mark.id, false); + if (item && item->decor && item->decor->virt_lines_above == above) { + virt_lines += (int)kv_size(item->decor->virt_lines); + if (lines) { + kv_splice(*lines, item->decor->virt_lines); + } } - buf->b_virt_line_pos = pos.row + (buf->b_virt_line_above ? 0 : 1); +next_mark: + marktree_itr_next(buf->b_marktree, itr); } - return (lnum-1 == buf->b_virt_line_pos) ? (int)kv_size(buf->b_virt_lines) : 0; -} - -void clear_virt_lines(buf_T *buf, int row) -{ - if (row > -1) { - redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, - row+1+(buf->b_virt_line_above?0:1))); - } - for (size_t i = 0; i < kv_size(buf->b_virt_lines); i++) { - clear_virttext(&kv_A(buf->b_virt_lines, i)); - } - kv_destroy(buf->b_virt_lines); // re-initializes - buf->b_virt_line_pos = -1; - buf->b_virt_line_mark = 0; + return virt_lines; } |