1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#pragma once
#include <stdbool.h>
#include <stddef.h> // IWYU pragma: keep
#include <stdint.h>
#include "klib/kvec.h"
#include "nvim/decoration_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
#include "nvim/marktree_defs.h"
#include "nvim/pos_defs.h" // IWYU pragma: keep
#include "nvim/sign_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h"
// actual Decor* data is in decoration_defs.h
/// Keep in sync with VirtTextPos in decoration_defs.h
EXTERN const char *const virt_text_pos_str[] INIT( = { "eol", "eol_right_align", "inline",
"overlay", "right_align", "win_col" });
/// Keep in sync with HlMode in decoration_defs.h
EXTERN const char *const hl_mode_str[] INIT( = { "", "replace", "combine", "blend" });
typedef enum {
kDecorKindHighlight,
kDecorKindSign,
kDecorKindVirtText,
kDecorKindVirtLines,
kDecorKindUIWatched,
} DecorRangeKindEnum;
typedef uint8_t DecorRangeKind;
typedef struct {
int start_row;
int start_col;
int end_row;
int end_col;
int ordering; ///< range insertion order
DecorPriority priority;
bool owned; ///< ephemeral decoration, free memory immediately
DecorRangeKind kind;
// next pointers MUST NOT be used, these are separate ranges
// vt->next could be pointing to freelist memory at this point
union {
DecorSignHighlight sh;
DecorVirtText *vt;
struct {
uint32_t ns_id;
uint32_t mark_id;
VirtTextPos pos;
} ui;
} data;
int attr_id; ///< cached lookup of inl.hl_id if it was a highlight
/// Screen column to draw the virtual text.
/// When -1, it should be drawn on the current screen line after deciding where.
/// When -3, it may be drawn at a position yet to be assigned.
/// When -10, it has just been added.
/// When INT_MIN, it should no longer be drawn.
int draw_col;
} DecorRange;
/// DecorRange can be removed from `DecorState` list in any order,
/// so we track available slots using a freelist (with `next_free_i`).
/// The list head is in `DecorState.free_slot_i`.
typedef union {
DecorRange range;
int next_free_i;
} DecorRangeSlot;
typedef struct {
MarkTreeIter itr[1];
kvec_t(DecorRangeSlot) slots;
kvec_t(int) ranges_i;
/// Indices in [0; current_end) of `ranges_i` point to ranges that start
/// before current position. Sorted by priority and order of insertion.
int current_end;
/// Indices in [future_begin, kv_size(ranges_i)) of `ranges_i` point to
/// ranges that start after current position. Sorted by starting position.
int future_begin;
/// Head of DecorRangeSlot freelist. -1 if none are freed.
int free_slot_i;
/// Index for keeping track of range insertion order.
int new_range_ordering;
win_T *win;
int top_row;
int row;
int col_until;
int current;
int eol_col;
int conceal;
schar_T conceal_char;
int conceal_attr;
TriState spell;
bool running_decor_provider;
bool itr_valid;
} DecorState;
EXTERN DecorState decor_state INIT( = { 0 });
// TODO(bfredl): These should maybe be per-buffer, so that all resources
// associated with a buffer can be freed when the buffer is unloaded.
EXTERN kvec_t(DecorSignHighlight) decor_items INIT( = KV_INITIAL_VALUE);
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "decoration.h.generated.h"
# include "decoration.h.inline.generated.h"
#endif
static inline int decor_redraw_col(win_T *wp, int col, int win_col, bool hidden, DecorState *state)
FUNC_ATTR_ALWAYS_INLINE
{
if (col <= state->col_until) {
return state->current;
}
return decor_redraw_col_impl(wp, col, win_col, hidden, state);
}
|