mirror of
https://github.com/neovim/neovim.git
synced 2026-02-05 03:51:21 +10:00
This expands on the global "don't pay for what you don't use" rules for these special extmark decorations: - inline virtual text, which needs to be processed in plines.c when we calculate the size of text on screen - virtual lines, which are needed when calculating "filler" lines - signs, with text and/or highlights, both of which needs to be processed for the entire line already at the beginning of a line. This adds a count to each node of the marktree, for how many special marks of each kind can be found in the subtree for this node. This makes it possible to quickly skip over these extra checks, when working in regions of the buffer not containing these kind of marks, instead of before where this could just be skipped if the entire _buffer_ didn't contain such marks.
104 lines
2.3 KiB
C
104 lines
2.3 KiB
C
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include "nvim/decoration_defs.h"
|
|
#include "nvim/map_defs.h"
|
|
|
|
enum {
|
|
MT_MAX_DEPTH = 20,
|
|
MT_BRANCH_FACTOR = 10,
|
|
// note max branch is actually 2*MT_BRANCH_FACTOR
|
|
// and strictly this is ceil(log2(2*MT_BRANCH_FACTOR + 1))
|
|
// as we need a pseudo-index for "right before this node"
|
|
MT_LOG2_BRANCH = 5,
|
|
};
|
|
|
|
typedef struct {
|
|
int32_t row;
|
|
int32_t col;
|
|
} MTPos;
|
|
#define MTPos(r, c) ((MTPos){ .row = (r), .col = (c) })
|
|
|
|
// Currently there are four counts, which makes for a uint32_t[4] per node
|
|
// which makes for nice autovectorization into a single XMM or NEON register
|
|
typedef enum {
|
|
kMTMetaInline,
|
|
kMTMetaLines,
|
|
kMTMetaSignHL,
|
|
kMTMetaSignText,
|
|
kMTMetaCount, // sentinel, must be last
|
|
} MetaIndex;
|
|
|
|
#define kMTFilterSelect ((uint32_t)-1)
|
|
|
|
// a filter should be set to kMTFilterSelect for the selected kinds, zero otherwise
|
|
typedef const uint32_t *MetaFilter;
|
|
|
|
typedef struct mtnode_s MTNode;
|
|
|
|
typedef struct {
|
|
MTPos pos;
|
|
int lvl;
|
|
MTNode *x;
|
|
int i;
|
|
struct {
|
|
int oldcol;
|
|
int i;
|
|
} s[MT_MAX_DEPTH];
|
|
|
|
size_t intersect_idx;
|
|
MTPos intersect_pos;
|
|
MTPos intersect_pos_x;
|
|
} MarkTreeIter;
|
|
|
|
#define marktree_itr_valid(itr) ((itr)->x != NULL)
|
|
// access raw key: flags in MT_FLAG_EXTERNAL_MASK and decor_data are safe to modify.
|
|
#define mt_itr_rawkey(itr) ((itr)->x->key[(itr)->i])
|
|
|
|
// Internal storage
|
|
//
|
|
// NB: actual marks have flags > 0, so we can use (row,col,0) pseudo-key for
|
|
// "space before (row,col)"
|
|
typedef struct {
|
|
MTPos pos;
|
|
uint32_t ns;
|
|
uint32_t id;
|
|
uint16_t flags;
|
|
DecorInlineData decor_data; // "ext" tag in flags
|
|
} MTKey;
|
|
|
|
typedef struct {
|
|
MTKey start;
|
|
MTPos end_pos;
|
|
bool end_right_gravity;
|
|
} MTPair;
|
|
|
|
typedef kvec_withinit_t(uint64_t, 4) Intersection;
|
|
|
|
// part of mtnode_s which is only allocated for inner nodes:
|
|
// pointer to children as well as their meta counts
|
|
struct mtnode_inner_s {
|
|
MTNode *i_ptr[2 * MT_BRANCH_FACTOR];
|
|
uint32_t i_meta[2 * MT_BRANCH_FACTOR][kMTMetaCount];
|
|
};
|
|
|
|
struct mtnode_s {
|
|
int32_t n;
|
|
int16_t level;
|
|
int16_t p_idx; // index in parent
|
|
Intersection intersect;
|
|
MTNode *parent;
|
|
MTKey key[2 * MT_BRANCH_FACTOR - 1];
|
|
struct mtnode_inner_s s[];
|
|
};
|
|
|
|
typedef struct {
|
|
MTNode *root;
|
|
uint32_t meta_root[kMTMetaCount];
|
|
size_t n_keys, n_nodes;
|
|
PMap(uint64_t) id2node[1];
|
|
} MarkTree;
|