Merge pull request #26528 from bfredl/nodrawstate

refactor(drawline): remove LineDrawState and wlv->saved_n_extra
This commit is contained in:
bfredl 2023-12-22 11:49:06 +01:00 committed by GitHub
commit d9d9d94343
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 396 additions and 467 deletions

View File

@ -665,9 +665,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
if (HAS_KEY(opts, set_extmark, sign_text)) {
sign.text.ptr = NULL;
VALIDATE_S(init_sign_text(NULL, &sign.text.ptr, opts->sign_text.data),
"sign_text", "", {
sign.text[0] = 0;
VALIDATE_S(init_sign_text(NULL, sign.text, opts->sign_text.data), "sign_text", "", {
goto error;
});
sign.flags |= kSHIsSign;
@ -785,7 +784,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
uint32_t decor_indexed = DECOR_ID_INVALID;
if (sign.flags & kSHIsSign) {
decor_indexed = decor_put_sh(sign);
if (sign.text.ptr != NULL) {
if (sign.text[0]) {
decor_flags |= MT_FLAG_DECOR_SIGNTEXT;
}
if (sign.number_hl_id || sign.line_hl_id || sign.cursorline_hl_id) {

View File

@ -5,6 +5,7 @@
#include "nvim/api/extmark.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
@ -19,6 +20,7 @@
#include "nvim/move.h"
#include "nvim/option_vars.h"
#include "nvim/pos_defs.h"
#include "nvim/sign.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "decoration.c.generated.h"
@ -158,7 +160,7 @@ DecorSignHighlight decor_sh_from_inline(DecorHighlightInline item)
DecorSignHighlight conv = {
.flags = item.flags,
.priority = item.priority,
.text.sc[0] = item.conceal_char,
.text[0] = item.conceal_char,
.hl_id = item.hl_id,
.number_hl_id = 0,
.line_hl_id = 0,
@ -207,7 +209,7 @@ void buf_put_decor_sh(buf_T *buf, DecorSignHighlight *sh, int row1, int row2)
if (sh->flags & kSHIsSign) {
sh->sign_add_id = sign_add_id++;
buf->b_signs++;
if (sh->text.ptr) {
if (sh->text[0]) {
buf->b_signs_with_text++;
buf_signcols_invalidate_range(buf, row1, row2, 1);
}
@ -253,7 +255,7 @@ void buf_remove_decor_sh(buf_T *buf, int row1, int row2, DecorSignHighlight *sh)
if (sh->flags & kSHIsSign) {
assert(buf->b_signs > 0);
buf->b_signs--;
if (sh->text.ptr) {
if (sh->text[0]) {
assert(buf->b_signs_with_text > 0);
buf->b_signs_with_text--;
if (row2 >= row1) {
@ -311,9 +313,6 @@ void decor_free_inner(DecorVirtText *vt, uint32_t first_idx)
uint32_t idx = first_idx;
while (idx != DECOR_ID_INVALID) {
DecorSignHighlight *sh = &kv_A(decor_items, idx);
if (sh->flags & kSHIsSign) {
xfree(sh->text.ptr);
}
if (sh->flags & kSHIsSign) {
xfree(sh->sign_name);
}
@ -362,8 +361,11 @@ void decor_check_invalid_glyphs(void)
{
for (size_t i = 0; i < kv_size(decor_items); i++) {
DecorSignHighlight *it = &kv_A(decor_items, i);
if ((it->flags & kSHConceal) && schar_high(it->text.sc[0])) {
it->text.sc[0] = schar_from_char(schar_get_first_codepoint(it->text.sc[0]));
int width = (it->flags & kSHIsSign) ? SIGN_WIDTH : ((it->flags & kSHConceal) ? 1 : 0);
for (int j = 0; j < width; j++) {
if (schar_high(it->text[j])) {
it->text[j] = schar_from_char(schar_get_first_codepoint(it->text[j]));
}
}
}
}
@ -661,7 +663,7 @@ next_mark:
if (item.start_row == state->row && item.start_col == col) {
DecorSignHighlight *sh = &item.data.sh;
conceal = 2;
conceal_char = sh->text.sc[0];
conceal_char = sh->text[0];
state->col_until = MIN(state->col_until, item.start_col);
conceal_attr = item.attr_id;
}
@ -729,7 +731,7 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[],
while (marktree_itr_step_overlap(buf->b_marktree, itr, &pair)) {
if (!mt_invalid(pair.start) && mt_decor_sign(pair.start)) {
DecorSignHighlight *sh = decor_find_sign(mt_decor(pair.start));
num_text += (sh->text.ptr != NULL);
num_text += (sh->text[0] != NUL);
kv_push(signs, ((SignItem){ sh, pair.start.id }));
}
}
@ -741,7 +743,7 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[],
}
if (!mt_end(mark) && !mt_invalid(mark) && mt_decor_sign(mark)) {
DecorSignHighlight *sh = decor_find_sign(mt_decor(mark));
num_text += (sh->text.ptr != NULL);
num_text += (sh->text[0] != NUL);
kv_push(signs, ((SignItem){ sh, mark.id }));
}
@ -755,8 +757,8 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[],
for (size_t i = 0; i < kv_size(signs); i++) {
DecorSignHighlight *sh = kv_A(signs, i).sh;
if (idx >= 0 && sh->text.ptr) {
sattrs[idx].text = sh->text.ptr;
if (idx >= 0 && sh->text[0]) {
memcpy(sattrs[idx].text, sh->text, SIGN_WIDTH * sizeof(sattr_T));
sattrs[idx--].hl_id = sh->hl_id;
}
if (*num_id == 0) {
@ -1033,7 +1035,7 @@ void decor_to_dict_legacy(Dictionary *dict, DecorInline decor, bool hl_name)
PUT(*dict, "hl_eol", BOOLEAN_OBJ(sh_hl.flags & kSHHlEol));
if (sh_hl.flags & kSHConceal) {
char buf[MAX_SCHAR_SIZE];
schar_get(buf, sh_hl.text.sc[0]);
schar_get(buf, sh_hl.text[0]);
PUT(*dict, "conceal", CSTR_TO_OBJ(buf));
}
@ -1081,8 +1083,10 @@ void decor_to_dict_legacy(Dictionary *dict, DecorInline decor, bool hl_name)
}
if (sh_sign.flags & kSHIsSign) {
if (sh_sign.text.ptr) {
PUT(*dict, "sign_text", CSTR_TO_OBJ(sh_sign.text.ptr));
if (sh_sign.text[0]) {
char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
describe_sign_text(buf, sh_sign.text);
PUT(*dict, "sign_text", CSTR_TO_OBJ(buf));
}
if (sh_sign.sign_name) {

View File

@ -59,11 +59,7 @@ typedef struct {
uint16_t flags;
DecorPriority priority;
int hl_id; // if sign: highlight of sign text
// TODO(bfredl): Later signs should use sc[2] as well.
union {
char *ptr; // sign
schar_T sc[2]; // conceal text (only sc[0] used)
} text;
schar_T text[SIGN_WIDTH]; // conceal text only uses text[0]
// NOTE: if more functionality is added to a Highlight these should be overloaded
// or restructured
char *sign_name;
@ -74,7 +70,7 @@ typedef struct {
uint32_t next;
} DecorSignHighlight;
#define DECOR_SIGN_HIGHLIGHT_INIT { 0, DECOR_PRIORITY_BASE, 0, { .ptr = NULL }, NULL, 0, 0, 0, 0, \
#define DECOR_SIGN_HIGHLIGHT_INIT { 0, DECOR_PRIORITY_BASE, 0, { 0, 0 }, NULL, 0, 0, 0, 0, \
DECOR_ID_INVALID }
enum {

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@
#include "nvim/fold.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/macros_defs.h"
@ -104,7 +105,7 @@ static void buf_set_sign(buf_T *buf, uint32_t *id, char *group, int prio, linenr
DecorSignHighlight sign = DECOR_SIGN_HIGHLIGHT_INIT;
sign.flags |= kSHIsSign;
sign.text.ptr = sp->sn_text ? xstrdup(sp->sn_text) : NULL;
memcpy(sign.text, sp->sn_text, SIGN_WIDTH * sizeof(schar_T));
sign.sign_name = xstrdup(sp->sn_name);
sign.hl_id = sp->sn_text_hl;
sign.line_hl_id = sp->sn_line_hl;
@ -113,7 +114,7 @@ static void buf_set_sign(buf_T *buf, uint32_t *id, char *group, int prio, linenr
sign.priority = (DecorPriority)prio;
bool has_hl = (sp->sn_line_hl || sp->sn_num_hl || sp->sn_cul_hl);
uint16_t decor_flags = (sp->sn_text ? MT_FLAG_DECOR_SIGNTEXT : 0)
uint16_t decor_flags = (sp->sn_text[0] ? MT_FLAG_DECOR_SIGNTEXT : 0)
| (has_hl ? MT_FLAG_DECOR_SIGNHL : 0);
DecorInline decor = { .ext = true, .data.ext = { .vt = NULL, .sh_idx = decor_put_sh(sign) } };
@ -333,9 +334,24 @@ static int sign_cmd_idx(char *begin_cmd, char *end_cmd)
return idx;
}
/// buf must be SIGN_WIDTH * MAX_SCHAR_SIZE (no extra +1 needed)
size_t describe_sign_text(char *buf, schar_T *sign_text)
{
size_t p = 0;
for (int i = 0; i < SIGN_WIDTH; i++) {
schar_get(buf + p, sign_text[i]);
size_t len = strlen(buf + p);
if (len == 0) {
break;
}
p += len;
}
return p;
}
/// Initialize the "text" for a new sign and store in "sign_text".
/// "sp" is NULL for signs added through nvim_buf_set_extmark().
int init_sign_text(sign_T *sp, char **sign_text, char *text)
int init_sign_text(sign_T *sp, schar_T *sign_text, char *text)
{
char *s;
char *endp = text + (int)strlen(text);
@ -350,34 +366,29 @@ int init_sign_text(sign_T *sp, char **sign_text, char *text)
// Count cells and check for non-printable chars
int cells = 0;
for (s = text; s < endp; s += utfc_ptr2len(s)) {
if (!vim_isprintc(utf_ptr2char(s))) {
int c;
sign_text[cells] = utfc_ptr2schar(s, &c);
if (!vim_isprintc(c)) {
break;
}
cells += utf_ptr2cells(s);
int width = utf_char2cells(c);
if (width == 2) {
sign_text[cells + 1] = 0;
}
cells += width;
}
// Currently must be empty, one or two display cells
if (s != endp || cells > 2) {
if (s != endp || cells > SIGN_WIDTH) {
if (sp != NULL) {
semsg(_("E239: Invalid sign text: %s"), text);
}
return FAIL;
}
if (cells < 1) {
if (sp != NULL) {
sp->sn_text = NULL;
}
return OK;
}
if (sp != NULL) {
xfree(sp->sn_text);
}
// Allocate one byte more if we need to pad up with a space.
size_t len = (size_t)(endp - text + (cells == 1));
*sign_text = xstrnsave(text, len);
if (cells == 1) {
STRCPY(*sign_text + len - 1, " ");
sign_text[0] = 0;
} else if (cells == 1) {
sign_text[1] = schar_from_ascii(' ');
}
return OK;
@ -411,7 +422,7 @@ static int sign_define_by_name(char *name, char *icon, char *text, char *linehl,
backslash_halve((*sp)->sn_icon);
}
if (text != NULL && (init_sign_text(*sp, &(*sp)->sn_text, text) == FAIL)) {
if (text != NULL && (init_sign_text(*sp, (*sp)->sn_text, text) == FAIL)) {
return FAIL;
}
@ -436,7 +447,6 @@ static int sign_undefine_by_name(const char *name)
}
xfree(sp->sn_name);
xfree(sp->sn_text);
xfree(sp->sn_icon);
xfree(sp);
return OK;
@ -451,9 +461,11 @@ static void sign_list_defined(sign_T *sp)
msg_outtrans(sp->sn_icon, 0);
msg_puts(_(" (not supported)"));
}
if (sp->sn_text != NULL) {
if (sp->sn_text[0]) {
msg_puts(" text=");
msg_outtrans(sp->sn_text, 0);
char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
describe_sign_text(buf, sp->sn_text);
msg_outtrans(buf, 0);
}
static char *arg[] = { " linehl=", " texthl=", " culhl=", " numhl=" };
int hl[] = { sp->sn_line_hl, sp->sn_text_hl, sp->sn_cul_hl, sp->sn_num_hl };
@ -880,8 +892,10 @@ static dict_T *sign_get_info_dict(sign_T *sp)
if (sp->sn_icon != NULL) {
tv_dict_add_str(d, S_LEN("icon"), sp->sn_icon);
}
if (sp->sn_text != NULL) {
tv_dict_add_str(d, S_LEN("text"), sp->sn_text);
if (sp->sn_text[0]) {
char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
describe_sign_text(buf, sp->sn_text);
tv_dict_add_str(d, S_LEN("text"), buf);
}
static char *arg[] = { "linehl", "texthl", "culhl", "numhl" };
int hl[] = { sp->sn_line_hl, sp->sn_text_hl, sp->sn_cul_hl, sp->sn_num_hl };

View File

@ -1,8 +1,10 @@
#pragma once
#include "nvim/types_defs.h"
/// Sign attributes. Used by the screen refresh routines.
typedef struct {
char *text;
schar_T text[SIGN_WIDTH];
int hl_id;
} SignTextAttrs;
@ -10,13 +12,12 @@ typedef struct {
typedef struct sign {
char *sn_name; // name of sign
char *sn_icon; // name of pixmap
char *sn_text; // text used instead of pixmap
schar_T sn_text[SIGN_WIDTH]; // text used instead of pixmap
int sn_line_hl; // highlight ID for line
int sn_text_hl; // highlight ID for text
int sn_cul_hl; // highlight ID for text on current line when 'cursorline' is set
int sn_num_hl; // highlight ID for line number
} sign_T;
enum { SIGN_WIDTH = 2, }; ///< Number of display cells for a sign in the signcolumn
enum { SIGN_SHOW_MAX = 9, }; ///< Maximum number of signs shown on a single line
enum { SIGN_DEF_PRIO = 10, }; ///< Default sign highlight priority

View File

@ -1640,20 +1640,32 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
char *p = NULL;
if (fold) {
size_t n = fill_foldcolumn(out_p, wp, stcp->foldinfo,
(linenr_T)get_vim_var_nr(VV_LNUM), NULL);
schar_T fold_buf[10];
size_t n = fill_foldcolumn(NULL, wp, stcp->foldinfo,
(linenr_T)get_vim_var_nr(VV_LNUM), 0, fold_buf);
stl_items[curitem].minwid = -((stcp->use_cul ? HLF_CLF : HLF_FC) + 1);
size_t buflen = 0;
// TODO(bfredl): this is very backwards. we must support schar_T
// being used directly in 'statuscol'
for (size_t i = 0; i < n; i++) {
schar_get(out_p + buflen, fold_buf[i]);
buflen += strlen(out_p + buflen);
}
p = out_p;
p[n] = NUL;
}
char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
size_t buflen = 0;
varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM);
for (int i = 0; i < width; i++) {
if (!fold) {
SignTextAttrs *sattr = virtnum ? NULL : &stcp->sattrs[i];
p = sattr && sattr->text ? sattr->text : " ";
stl_items[curitem].minwid = -(sattr && sattr->text
p = " ";
if (sattr && sattr->text[0]) {
describe_sign_text(buf, sattr->text);
p = buf;
}
stl_items[curitem].minwid = -(sattr && sattr->text[0]
? (stcp->sign_cul_id ? stcp->sign_cul_id : sattr->hl_id)
: (stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
}

View File

@ -56,6 +56,8 @@ typedef struct {
} SignRange;
#define SIGNRANGE_INIT { 0, 0 }
enum { SIGN_WIDTH = 2, }; ///< Number of display cells for a sign in the signcolumn
typedef struct file_buffer buf_T;
typedef struct loop Loop;
typedef struct regprog regprog_T;

View File

@ -415,8 +415,8 @@ describe('Signs', function()
feed('gg100aa<Esc>')
screen:expect([[
{1: >> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aa^a |
{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{8: }aa^a |
{8: 2 }b |
{6: 3 }c |
{6: 4 } |
@ -430,10 +430,10 @@ describe('Signs', function()
feed('<C-Y>')
-- number column on virtual lines should be empty
screen:expect([[
VIRT LINES |
{6: }VIRT LINES |
{1: >> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aa^a |
{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{8: }aa^a |
{8: 2 }b |
{6: 3 }c |
{6: 4 } |