diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index bf0b5a1a6b..0808f13491 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -473,6 +473,8 @@ bool decor_redraw_line(win_T *wp, int row, DecorState *state) int const cur_end = state->current_end; int fut_beg = state->future_begin; + // Move future ranges to start right after current ranges. + // Otherwise future ranges will grow forward indefinitely. if (fut_beg == count) { fut_beg = count = cur_end; } else if (fut_beg != cur_end) { @@ -528,6 +530,7 @@ static void decor_range_insert(DecorState *state, DecorRange *range) range->ordering = state->new_range_ordering++; int index; + // Get space for a new `DecorRange` from the freelist or allocate. if (state->free_slot_i >= 0) { index = state->free_slot_i; DecorRangeSlot *slot = &kv_A(state->slots, index); @@ -635,11 +638,11 @@ void decor_init_draw_col(int win_col, bool hidden, DecorRange *item) void decor_recheck_draw_col(int win_col, bool hidden, DecorState *state) { - int const count = state->current_end; + int const end = state->current_end; int *const indices = state->ranges_i.items; DecorRangeSlot *const slots = state->slots.items; - for (int i = 0; i < count; i++) { + for (int i = 0; i < end; i++) { DecorRange *const r = &slots[indices[i]].range; if (r->draw_col == -3) { decor_init_draw_col(win_col, hidden, r); @@ -683,6 +686,7 @@ next_mark: int cur_end = state->current_end; int fut_beg = state->future_begin; + // Promote future ranges before the cursor to active. for (; fut_beg < count; fut_beg++) { int const index = indices[fut_beg]; DecorRange *const r = &slots[index].range; @@ -711,7 +715,7 @@ next_mark: cur_end++; } - if (fut_beg != count) { + if (fut_beg < count) { DecorRange *r = &slots[indices[fut_beg]].range; if (r->start_row == row) { col_until = MIN(col_until, r->start_col - 1); diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h index ec944c5169..1d268c982b 100644 --- a/src/nvim/decoration.h +++ b/src/nvim/decoration.h @@ -27,17 +27,19 @@ typedef enum { kDecorKindVirtText, kDecorKindVirtLines, kDecorKindUIWatched, -} DecorRangeKind; +} DecorRangeKindEnum; + +typedef uint8_t DecorRangeKind; typedef struct { int start_row; int start_col; int end_row; int end_col; - int ordering; + int ordering; ///< range insertion order DecorPriority priority; bool owned; ///< ephemeral decoration, free memory immediately - DecorRangeKind kind: 8; + DecorRangeKind kind; // next pointers MUST NOT be used, these are separate ranges // vt->next could be pointing to freelist memory at this point union { diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 93b66a9ba3..bf14ce1d4a 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -256,11 +256,11 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int int right_pos = max_col; bool const do_eol = state->eol_col > -1; - int const count = state->current_end; + int const end = state->current_end; int *const indices = state->ranges_i.items; DecorRangeSlot *const slots = state->slots.items; - for (int i = 0; i < count; i++) { + for (int i = 0; i < end; i++) { DecorRange *item = &slots[indices[i]].range; if (!(item->start_row == state->row && decor_virt_pos(item))) { continue; @@ -796,11 +796,11 @@ static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t wlv->virt_inline = VIRTTEXT_EMPTY; wlv->virt_inline_i = 0; DecorState *state = &decor_state; - int const count = state->current_end; + int const end = state->current_end; int *const indices = state->ranges_i.items; DecorRangeSlot *const slots = state->slots.items; - for (int i = 0; i < count; i++) { + for (int i = 0; i < end; i++) { DecorRange *item = &slots[indices[i]].range; if (item->draw_col == -3) { // No more inline virtual text before this non-inline virtual text item,