From 860fea1a3f880c2da0ac351a9523156bcfc67361 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 31 Jan 2023 07:08:23 +0800 Subject: fix(highlight): properly deal with underline mask when listing (#22057) --- src/nvim/highlight.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 9dab91cc2b..c20eac3c28 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -842,14 +842,14 @@ void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb) PUT_C(hl, "underline", BOOLEAN_OBJ(true)); break; - case HL_UNDERDOUBLE: - PUT_C(hl, "underdouble", BOOLEAN_OBJ(true)); - break; - case HL_UNDERCURL: PUT_C(hl, "undercurl", BOOLEAN_OBJ(true)); break; + case HL_UNDERDOUBLE: + PUT_C(hl, "underdouble", BOOLEAN_OBJ(true)); + break; + case HL_UNDERDOTTED: PUT_C(hl, "underdotted", BOOLEAN_OBJ(true)); break; @@ -930,8 +930,8 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e CHECK_FLAG(dict, mask, bold, , HL_BOLD); CHECK_FLAG(dict, mask, italic, , HL_ITALIC); CHECK_FLAG(dict, mask, underline, , HL_UNDERLINE); - CHECK_FLAG(dict, mask, underdouble, , HL_UNDERDOUBLE); CHECK_FLAG(dict, mask, undercurl, , HL_UNDERCURL); + CHECK_FLAG(dict, mask, underdouble, , HL_UNDERDOUBLE); CHECK_FLAG(dict, mask, underdotted, , HL_UNDERDOTTED); CHECK_FLAG(dict, mask, underdashed, , HL_UNDERDASHED); CHECK_FLAG(dict, mask, standout, , HL_STANDOUT); -- cgit From 4be6c6cf0ddf5e31d4103cb5df06651ba6f4897b Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 11 Feb 2023 11:05:57 +0100 Subject: refactor: replace char_u with char (#21901) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/highlight.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index c20eac3c28..5936e4ff2b 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -205,7 +205,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault) if (!valid_item && p->hl_def != LUA_NOREF && !recursive) { MAXSIZE_TEMP_ARRAY(args, 3); ADD_C(args, INTEGER_OBJ((Integer)ns_id)); - ADD_C(args, STRING_OBJ(cstr_to_string((char *)syn_id2name(hl_id)))); + ADD_C(args, STRING_OBJ(cstr_to_string(syn_id2name(hl_id)))); ADD_C(args, BOOLEAN_OBJ(link)); // TODO(bfredl): preload the "global" attr dict? @@ -1115,7 +1115,7 @@ static void hl_inspect_impl(Array *arr, int attr) case kHlSyntax: PUT(item, "kind", STRING_OBJ(cstr_to_string("syntax"))); PUT(item, "hi_name", - STRING_OBJ(cstr_to_string((char *)syn_id2name(e.id1)))); + STRING_OBJ(cstr_to_string(syn_id2name(e.id1)))); break; case kHlUI: @@ -1123,7 +1123,7 @@ static void hl_inspect_impl(Array *arr, int attr) const char *ui_name = (e.id1 == -1) ? "Normal" : hlf_names[e.id1]; PUT(item, "ui_name", STRING_OBJ(cstr_to_string(ui_name))); PUT(item, "hi_name", - STRING_OBJ(cstr_to_string((char *)syn_id2name(e.id2)))); + STRING_OBJ(cstr_to_string(syn_id2name(e.id2)))); break; case kHlTerminal: -- cgit From ff3d04b75b4a9314815c37d53ebc4d035a043335 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 08:07:38 -0500 Subject: refactor(api): VALIDATE macros #22256 - VALIDATE() takes a format string - deduplicate check_string_array - VALIDATE_RANGE - validate UI args --- src/nvim/highlight.c | 60 +++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 5936e4ff2b..5e53bf273f 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -12,6 +12,7 @@ #include "lauxlib.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/api/ui.h" #include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" @@ -971,35 +972,33 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e return hlattrs; } - if (dict->blend.type == kObjectTypeInteger) { + if (HAS_KEY(dict->blend)) { + VALIDATE_T("blend", kObjectTypeInteger, dict->blend.type, { + return hlattrs; + }); + Integer blend0 = dict->blend.data.integer; - if (blend0 < 0 || blend0 > 100) { - api_set_error(err, kErrorTypeValidation, "'blend' is not between 0 to 100"); - } else { - blend = (int)blend0; - } - } else if (HAS_KEY(dict->blend)) { - api_set_error(err, kErrorTypeValidation, "'blend' must be an integer"); - } - if (ERROR_SET(err)) { - return hlattrs; + VALIDATE_RANGE((blend0 >= 0 && blend0 <= 100), "blend", { + return hlattrs; + }); + blend = (int)blend0; } if (HAS_KEY(dict->link) || HAS_KEY(dict->global_link)) { - if (link_id) { - if (HAS_KEY(dict->global_link)) { - *link_id = object_to_hl_id(dict->global_link, "link", err); - mask |= HL_GLOBAL; - } else { - *link_id = object_to_hl_id(dict->link, "link", err); - } - - if (ERROR_SET(err)) { - return hlattrs; - } - } else { + if (!link_id) { api_set_error(err, kErrorTypeValidation, "Invalid Key: '%s'", HAS_KEY(dict->global_link) ? "global_link" : "link"); + return hlattrs; + } + if (HAS_KEY(dict->global_link)) { + *link_id = object_to_hl_id(dict->global_link, "link", err); + mask |= HL_GLOBAL; + } else { + *link_id = object_to_hl_id(dict->link, "link", err); + } + + if (ERROR_SET(err)) { + return hlattrs; } } @@ -1026,7 +1025,9 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e // TODO(clason): handle via gen_api_dispatch cterm_mask_provided = true; } else if (HAS_KEY(dict->cterm)) { - api_set_error(err, kErrorTypeValidation, "'cterm' must be a Dictionary."); + VALIDATE_T("cterm", kObjectTypeDictionary, dict->cterm.type, { + return hlattrs; + }); } #undef CHECK_FLAG @@ -1083,13 +1084,14 @@ int object_to_color(Object val, char *key, bool rgb, Error *err) } else { color = name_to_ctermcolor(str.data); } - if (color < 0) { - api_set_error(err, kErrorTypeValidation, "'%s' is not a valid color", str.data); - } + VALIDATE_S((color >= 0), "highlight color", str.data, { + return color; + }); return color; } else { - api_set_error(err, kErrorTypeValidation, "'%s' must be string or integer", key); - return 0; + VALIDATE(false, "Invalid %s: expected String or Integer", key, { + return 0; + }); } } -- cgit From 556f8646c01d1751cf39fe4df9c622899dceab9d Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 14:19:28 -0500 Subject: refactor(api): consistent VALIDATE messages #22262 Problem: Validation messages are not consistently formatted. - Parameter names sometimes are NOT quoted. - Descriptive names (non-parameters) sometimes ARE quoted. Solution: Always quote the `name` value passed to a VALIDATE macro _unless_ the value has whitespace. --- src/nvim/highlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 5e53bf273f..cf72102b60 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -1089,7 +1089,7 @@ int object_to_color(Object val, char *key, bool rgb, Error *err) }); return color; } else { - VALIDATE(false, "Invalid %s: expected String or Integer", key, { + VALIDATE_EXP(false, key, "String or Integer", NULL, { return 0; }); } -- cgit From 09b3432eaff3abcadb56d61b6f247f992b80b63f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 16 Feb 2023 10:07:18 -0500 Subject: fix(api): allow empty Lua table for nested dicts #22268 Problem: The Lua-API bridge allows Dict params to be empty Lua (list) tables at the function-signature level. But not for _nested_ Dicts, because they are not modeled: https://github.com/neovim/neovim/blob/fae754073289566051433fae74ec65783f9e7a6a/src/nvim/api/keysets.lua#L184 Some API functions like nvim_cmd check for kObjectTypeDictionary and don't handle the case of empty Lua tables (treated as "Array"). Solution: Introduce VALIDATE_T_DICT and use it in places where kObjectTypeDictionary was being checked directly. fixes #21005 --- src/nvim/highlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index cf72102b60..72da66cfc2 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -1025,7 +1025,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e // TODO(clason): handle via gen_api_dispatch cterm_mask_provided = true; } else if (HAS_KEY(dict->cterm)) { - VALIDATE_T("cterm", kObjectTypeDictionary, dict->cterm.type, { + VALIDATE_EXP(false, "cterm", "Dict", api_typename(dict->cterm.type), { return hlattrs; }); } -- cgit From 524e1a06432ed7a88c1e183d81812dd48dc18cfb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 23 Feb 2023 16:15:04 +0800 Subject: fix(highlight): avoid ORing underline flags (#22372) When combining attributes use the one that takes priority. For :highlight command use the last one specified. For API use a hard-coded order same as the order in docs. --- src/nvim/highlight.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 72da66cfc2..305e84276c 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -507,6 +507,16 @@ void hl_invalidate_blends(void) update_window_hl(curwin, true); } +/// Combine HlAttrFlags. +/// The underline attribute in "prim_ae" overrules the one in "char_ae" if both are present. +static int16_t hl_combine_ae(int16_t char_ae, int16_t prim_ae) +{ + int16_t char_ul = char_ae & HL_UNDERLINE_MASK; + int16_t prim_ul = prim_ae & HL_UNDERLINE_MASK; + int16_t new_ul = prim_ul ? prim_ul : char_ul; + return (char_ae & ~HL_UNDERLINE_MASK) | (prim_ae & ~HL_UNDERLINE_MASK) | new_ul; +} + // Combine special attributes (e.g., for spelling) with other attributes // (e.g., for syntax highlighting). // "prim_attr" overrules "char_attr". @@ -537,12 +547,12 @@ int hl_combine_attr(int char_attr, int prim_attr) if (prim_aep.cterm_ae_attr & HL_NOCOMBINE) { new_en.cterm_ae_attr = prim_aep.cterm_ae_attr; } else { - new_en.cterm_ae_attr |= prim_aep.cterm_ae_attr; + new_en.cterm_ae_attr = hl_combine_ae(new_en.cterm_ae_attr, prim_aep.cterm_ae_attr); } if (prim_aep.rgb_ae_attr & HL_NOCOMBINE) { new_en.rgb_ae_attr = prim_aep.rgb_ae_attr; } else { - new_en.rgb_ae_attr |= prim_aep.rgb_ae_attr; + new_en.rgb_ae_attr = hl_combine_ae(new_en.rgb_ae_attr, prim_aep.rgb_ae_attr); } if (prim_aep.cterm_fg_color > 0) { @@ -664,7 +674,7 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through) } else { cattrs = fattrs; if (ratio >= 50) { - cattrs.rgb_ae_attr |= battrs.rgb_ae_attr; + cattrs.rgb_ae_attr = hl_combine_ae(battrs.rgb_ae_attr, cattrs.rgb_ae_attr); } cattrs.rgb_fg_color = rgb_blend(ratio/2, battrs.rgb_fg_color, fattrs.rgb_fg_color); @@ -924,7 +934,10 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e #define CHECK_FLAG(d, m, name, extra, flag) \ if (api_object_to_bool(d->name##extra, #name, false, err)) { \ - m = m | flag; \ + if (flag & HL_UNDERLINE_MASK) { \ + m &= ~HL_UNDERLINE_MASK; \ + } \ + m |= flag; \ } CHECK_FLAG(dict, mask, reverse, , HL_INVERSE); -- cgit From c0fe6c040e19ef9102a8507ffcbd88b83186326a Mon Sep 17 00:00:00 2001 From: Null Chilly <56817415+nullchilly@users.noreply.github.com> Date: Thu, 23 Mar 2023 16:31:39 +0700 Subject: feat(api): add nvim_get_hl (#22693) Problem: no way of getting all highlight group definitions in a namespace. Solution: add `nvim_get_hl()`, deprecate `nvim_get_hl_by_name()` and `nvim_get_hl_by_id()`. --- src/nvim/highlight.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 305e84276c..a97f8f4142 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -821,7 +821,7 @@ Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error * return dic; } Dictionary retval = arena_dict(arena, HLATTRS_DICT_SIZE); - hlattrs2dict(&retval, syn_attr2entry((int)attr_id), rgb); + hlattrs2dict(&retval, syn_attr2entry((int)attr_id), rgb, false); return retval; } @@ -830,7 +830,9 @@ Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error * /// @param[in/out] hl Dictionary with pre-allocated space for HLATTRS_DICT_SIZE elements /// @param[in] aep data to convert /// @param use_rgb use 'gui*' settings if true, else resorts to 'cterm*' -void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb) +/// @param short_keys change (foreground, background, special) to (fg, bg, sp) for 'gui*' settings +/// (foreground, background) to (ctermfg, ctermbg) for 'cterm*' settings +void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb, bool short_keys) { assert(dict->capacity >= HLATTRS_DICT_SIZE); // at most 16 items Dictionary hl = *dict; @@ -887,32 +889,34 @@ void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb) } if (use_rgb) { - if (mask & HL_FG_INDEXED) { - PUT_C(hl, "fg_indexed", BOOLEAN_OBJ(true)); - } - - if (mask & HL_BG_INDEXED) { - PUT_C(hl, "bg_indexed", BOOLEAN_OBJ(true)); - } - if (ae.rgb_fg_color != -1) { - PUT_C(hl, "foreground", INTEGER_OBJ(ae.rgb_fg_color)); + PUT_C(hl, short_keys ? "fg" : "foreground", INTEGER_OBJ(ae.rgb_fg_color)); } if (ae.rgb_bg_color != -1) { - PUT_C(hl, "background", INTEGER_OBJ(ae.rgb_bg_color)); + PUT_C(hl, short_keys ? "bg" : "background", INTEGER_OBJ(ae.rgb_bg_color)); } if (ae.rgb_sp_color != -1) { - PUT_C(hl, "special", INTEGER_OBJ(ae.rgb_sp_color)); + PUT_C(hl, short_keys ? "sp" : "special", INTEGER_OBJ(ae.rgb_sp_color)); + } + + if (!short_keys) { + if (mask & HL_FG_INDEXED) { + PUT_C(hl, "fg_indexed", BOOLEAN_OBJ(true)); + } + + if (mask & HL_BG_INDEXED) { + PUT_C(hl, "bg_indexed", BOOLEAN_OBJ(true)); + } } } else { if (ae.cterm_fg_color != 0) { - PUT_C(hl, "foreground", INTEGER_OBJ(ae.cterm_fg_color - 1)); + PUT_C(hl, short_keys ? "ctermfg" : "foreground", INTEGER_OBJ(ae.cterm_fg_color - 1)); } if (ae.cterm_bg_color != 0) { - PUT_C(hl, "background", INTEGER_OBJ(ae.cterm_bg_color - 1)); + PUT_C(hl, short_keys ? "ctermbg" : "background", INTEGER_OBJ(ae.cterm_bg_color - 1)); } } -- cgit From 6d267ad30cf539f520b46e3c92939f7031ce116f Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 23 Mar 2023 12:44:05 +0100 Subject: fix(api): make nvim_get_hl return 'cterm' attrs properly --- src/nvim/highlight.c | 53 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index a97f8f4142..36da057ddc 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -821,7 +821,7 @@ Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error * return dic; } Dictionary retval = arena_dict(arena, HLATTRS_DICT_SIZE); - hlattrs2dict(&retval, syn_attr2entry((int)attr_id), rgb, false); + hlattrs2dict(&retval, NULL, syn_attr2entry((int)attr_id), rgb, false); return retval; } @@ -832,99 +832,98 @@ Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error * /// @param use_rgb use 'gui*' settings if true, else resorts to 'cterm*' /// @param short_keys change (foreground, background, special) to (fg, bg, sp) for 'gui*' settings /// (foreground, background) to (ctermfg, ctermbg) for 'cterm*' settings -void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb, bool short_keys) +void hlattrs2dict(Dictionary *hl, Dictionary *hl_attrs, HlAttrs ae, bool use_rgb, bool short_keys) { - assert(dict->capacity >= HLATTRS_DICT_SIZE); // at most 16 items - Dictionary hl = *dict; + hl_attrs = hl_attrs ? hl_attrs : hl; + assert(hl->capacity >= HLATTRS_DICT_SIZE); // at most 16 items + assert(hl_attrs->capacity >= HLATTRS_DICT_SIZE); // at most 16 items int mask = use_rgb ? ae.rgb_ae_attr : ae.cterm_ae_attr; if (mask & HL_INVERSE) { - PUT_C(hl, "reverse", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "reverse", BOOLEAN_OBJ(true)); } if (mask & HL_BOLD) { - PUT_C(hl, "bold", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "bold", BOOLEAN_OBJ(true)); } if (mask & HL_ITALIC) { - PUT_C(hl, "italic", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "italic", BOOLEAN_OBJ(true)); } switch (mask & HL_UNDERLINE_MASK) { case HL_UNDERLINE: - PUT_C(hl, "underline", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "underline", BOOLEAN_OBJ(true)); break; case HL_UNDERCURL: - PUT_C(hl, "undercurl", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "undercurl", BOOLEAN_OBJ(true)); break; case HL_UNDERDOUBLE: - PUT_C(hl, "underdouble", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "underdouble", BOOLEAN_OBJ(true)); break; case HL_UNDERDOTTED: - PUT_C(hl, "underdotted", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "underdotted", BOOLEAN_OBJ(true)); break; case HL_UNDERDASHED: - PUT_C(hl, "underdashed", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "underdashed", BOOLEAN_OBJ(true)); break; } if (mask & HL_STANDOUT) { - PUT_C(hl, "standout", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "standout", BOOLEAN_OBJ(true)); } if (mask & HL_STRIKETHROUGH) { - PUT_C(hl, "strikethrough", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "strikethrough", BOOLEAN_OBJ(true)); } if (mask & HL_ALTFONT) { - PUT_C(hl, "altfont", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "altfont", BOOLEAN_OBJ(true)); } if (mask & HL_NOCOMBINE) { - PUT_C(hl, "nocombine", BOOLEAN_OBJ(true)); + PUT_C(*hl_attrs, "nocombine", BOOLEAN_OBJ(true)); } if (use_rgb) { if (ae.rgb_fg_color != -1) { - PUT_C(hl, short_keys ? "fg" : "foreground", INTEGER_OBJ(ae.rgb_fg_color)); + PUT_C(*hl, short_keys ? "fg" : "foreground", INTEGER_OBJ(ae.rgb_fg_color)); } if (ae.rgb_bg_color != -1) { - PUT_C(hl, short_keys ? "bg" : "background", INTEGER_OBJ(ae.rgb_bg_color)); + PUT_C(*hl, short_keys ? "bg" : "background", INTEGER_OBJ(ae.rgb_bg_color)); } if (ae.rgb_sp_color != -1) { - PUT_C(hl, short_keys ? "sp" : "special", INTEGER_OBJ(ae.rgb_sp_color)); + PUT_C(*hl, short_keys ? "sp" : "special", INTEGER_OBJ(ae.rgb_sp_color)); } if (!short_keys) { if (mask & HL_FG_INDEXED) { - PUT_C(hl, "fg_indexed", BOOLEAN_OBJ(true)); + PUT_C(*hl, "fg_indexed", BOOLEAN_OBJ(true)); } if (mask & HL_BG_INDEXED) { - PUT_C(hl, "bg_indexed", BOOLEAN_OBJ(true)); + PUT_C(*hl, "bg_indexed", BOOLEAN_OBJ(true)); } } } else { if (ae.cterm_fg_color != 0) { - PUT_C(hl, short_keys ? "ctermfg" : "foreground", INTEGER_OBJ(ae.cterm_fg_color - 1)); + PUT_C(*hl, short_keys ? "ctermfg" : "foreground", INTEGER_OBJ(ae.cterm_fg_color - 1)); } if (ae.cterm_bg_color != 0) { - PUT_C(hl, short_keys ? "ctermbg" : "background", INTEGER_OBJ(ae.cterm_bg_color - 1)); + PUT_C(*hl, short_keys ? "ctermbg" : "background", INTEGER_OBJ(ae.cterm_bg_color - 1)); } } - if (ae.hl_blend > -1) { - PUT_C(hl, "blend", INTEGER_OBJ(ae.hl_blend)); + if (ae.hl_blend > -1 && (use_rgb || !short_keys)) { + PUT_C(*hl, "blend", INTEGER_OBJ(ae.hl_blend)); } - - *dict = hl; } HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *err) -- cgit From 0f42aa1f2a860ce6d72a825b397fe09c875613b5 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 6 Apr 2023 10:03:37 +0200 Subject: fix(highlight): use winhl=Foo:Bar even when Bar is empty fixes #22906 --- src/nvim/highlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 36da057ddc..f4d851cfec 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -303,7 +303,7 @@ int hl_get_ui_attr(int ns_id, int idx, int final_id, bool optional) bool available = false; if (final_id > 0) { - int syn_attr = syn_ns_id2attr(ns_id, final_id, optional); + int syn_attr = syn_ns_id2attr(ns_id, final_id, &optional); if (syn_attr > 0) { attrs = syn_attr2entry(syn_attr); available = true; -- cgit From efb0896f21e03f64e3a14e7c09994e81956f47b9 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 3 Apr 2023 15:21:24 +0200 Subject: refactor(api): make typed dicts appear as types in the source code problem: can we have Serde? solution: we have Serde at home This by itself is just a change of notation, that could be quickly merged to avoid messy merge conflicts, but upcoming changes are planned: - keysets no longer need to be defined in one single file. `keysets.h` is just the initial automatic conversion of the previous `keysets.lua`. keysets just used in a single api/{scope}.h can be moved to that file, later on. - Typed dicts will have more specific types than Object. this will enable most of the existing manual typechecking boilerplate to be eliminated. We will need some annotation for missing value, i e a boolean will need to be represented as a TriState (none/false/true) in some cases. - Eventually: optional parameters in form of a `Dict opts` final parameter will get added in some form to metadata. this will require a discussion/desicion about type forward compatibility. --- src/nvim/highlight.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index f4d851cfec..e2f3e2aafa 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -11,6 +11,7 @@ #include "klib/kvec.h" #include "lauxlib.h" #include "nvim/api/private/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/api/private/validate.h" #include "nvim/api/ui.h" -- cgit From 03ca36d1f8d027c95edd46f3127284e9a3577990 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 10 May 2023 23:46:50 +0800 Subject: fix(highlight): apply 'winblend' to NormalNC (#23555) --- src/nvim/highlight.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index e2f3e2aafa..cc332c530d 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -398,6 +398,15 @@ void update_window_hl(win_T *wp, bool invalid) } else { wp->w_hl_attr_normalnc = hl_def[HLF_INACTIVE]; } + + // if blend= attribute is not set, 'winblend' value overrides it. + if (wp->w_floating && wp->w_p_winbl > 0) { + HlEntry entry = kv_A(attr_entries, wp->w_hl_attr_normalnc); + if (entry.attr.hl_blend == -1) { + entry.attr.hl_blend = (int)wp->w_p_winbl; + wp->w_hl_attr_normalnc = get_attr_entry(entry); + } + } } void update_ns_hl(int ns_id) -- cgit From e2fdd53d8c015913e8be4ff708fc3488558c8906 Mon Sep 17 00:00:00 2001 From: bfredl Date: Sun, 14 May 2023 18:45:56 +0200 Subject: refactor(map): avoid duplicated khash_t types for values This reduces the total number of khash_t instantiations from 22 to 8. Make the khash internal functions take the size of values as a runtime parameter. This is abstracted with typesafe Map containers which are still specialized for both key, value type. Introduce `Set(key)` type for when there is no value. Refactor shada.c to use Map/Set instead of khash directly. This requires `map_ref` operation to be more flexible. Return pointers to both key and value, plus an indicator for new_item. As a bonus, `map_key` is now redundant. Instead of Map(cstr_t, FileMarks), use a pointer map as the FileMarks struct is humongous. Make `event_strings` actually work like an intern pool instead of wtf it was doing before. --- src/nvim/highlight.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index cc332c530d..a53da95fba 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -50,7 +50,7 @@ static Map(int, int) blendthrough_attr_entries = MAP_INIT; /// highlight entries private to a namespace static Map(ColorKey, ColorItem) ns_hls; typedef int NSHlAttr[HLF_COUNT + 1]; -static PMap(handle_T) ns_hl_attr; +static PMap(int) ns_hl_attr; void highlight_init(void) { @@ -277,7 +277,7 @@ bool hl_check_ns(void) hl_attr_active = highlight_attr; if (ns > 0) { update_ns_hl(ns); - NSHlAttr *hl_def = (NSHlAttr *)pmap_get(handle_T)(&ns_hl_attr, ns); + NSHlAttr *hl_def = (NSHlAttr *)pmap_get(int)(&ns_hl_attr, ns); if (hl_def) { hl_attr_active = *hl_def; } @@ -335,7 +335,7 @@ void update_window_hl(win_T *wp, bool invalid) if (ns_id != wp->w_ns_hl_active || wp->w_ns_hl_attr == NULL) { wp->w_ns_hl_active = ns_id; - wp->w_ns_hl_attr = *(NSHlAttr *)pmap_get(handle_T)(&ns_hl_attr, ns_id); + wp->w_ns_hl_attr = *(NSHlAttr *)pmap_get(int)(&ns_hl_attr, ns_id); if (!wp->w_ns_hl_attr) { // No specific highlights, use the defaults. wp->w_ns_hl_attr = highlight_attr; @@ -419,7 +419,7 @@ void update_ns_hl(int ns_id) return; } - NSHlAttr **alloc = (NSHlAttr **)pmap_ref(handle_T)(&ns_hl_attr, ns_id, true); + NSHlAttr **alloc = (NSHlAttr **)pmap_put_ref(int)(&ns_hl_attr, ns_id, NULL, NULL); if (*alloc == NULL) { *alloc = xmalloc(sizeof(**alloc)); } @@ -491,28 +491,28 @@ void clear_hl_tables(bool reinit) { if (reinit) { kv_size(attr_entries) = 1; - map_clear(HlEntry, int)(&attr_entry_ids); - map_clear(int, int)(&combine_attr_entries); - map_clear(int, int)(&blend_attr_entries); - map_clear(int, int)(&blendthrough_attr_entries); + map_clear(HlEntry, &attr_entry_ids); + map_clear(int, &combine_attr_entries); + map_clear(int, &blend_attr_entries); + map_clear(int, &blendthrough_attr_entries); memset(highlight_attr_last, -1, sizeof(highlight_attr_last)); highlight_attr_set_all(); highlight_changed(); screen_invalidate_highlights(); } else { kv_destroy(attr_entries); - map_destroy(HlEntry, int)(&attr_entry_ids); - map_destroy(int, int)(&combine_attr_entries); - map_destroy(int, int)(&blend_attr_entries); - map_destroy(int, int)(&blendthrough_attr_entries); - map_destroy(ColorKey, ColorItem)(&ns_hls); + map_destroy(HlEntry, &attr_entry_ids); + map_destroy(int, &combine_attr_entries); + map_destroy(int, &blend_attr_entries); + map_destroy(int, &blendthrough_attr_entries); + map_destroy(ColorKey, &ns_hls); } } void hl_invalidate_blends(void) { - map_clear(int, int)(&blend_attr_entries); - map_clear(int, int)(&blendthrough_attr_entries); + map_clear(int, &blend_attr_entries); + map_clear(int, &blendthrough_attr_entries); highlight_changed(); update_window_hl(curwin, true); } -- cgit From cfd4fdfea4d0e68ea50ad412b88b5289ded6fd6f Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Tue, 23 May 2023 14:25:10 +0600 Subject: refactor(api): new helper macros Adds new API helper macros `CSTR_AS_OBJ()`, `STATIC_CSTR_AS_OBJ()`, and `STATIC_CSTR_TO_OBJ()`, which cleans up a lot of the current code. These macros will also be used extensively in the upcoming option refactor PRs because then API Objects will be used to get/set options. This PR also modifies pre-existing code to use old API helper macros like `CSTR_TO_OBJ()` to make them cleaner. --- src/nvim/highlight.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index a53da95fba..fad113adc5 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -207,7 +207,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault) if (!valid_item && p->hl_def != LUA_NOREF && !recursive) { MAXSIZE_TEMP_ARRAY(args, 3); ADD_C(args, INTEGER_OBJ((Integer)ns_id)); - ADD_C(args, STRING_OBJ(cstr_to_string(syn_id2name(hl_id)))); + ADD_C(args, CSTR_TO_OBJ(syn_id2name(hl_id))); ADD_C(args, BOOLEAN_OBJ(link)); // TODO(bfredl): preload the "global" attr dict? @@ -1141,21 +1141,21 @@ static void hl_inspect_impl(Array *arr, int attr) HlEntry e = kv_A(attr_entries, attr); switch (e.kind) { case kHlSyntax: - PUT(item, "kind", STRING_OBJ(cstr_to_string("syntax"))); + PUT(item, "kind", CSTR_TO_OBJ("syntax")); PUT(item, "hi_name", - STRING_OBJ(cstr_to_string(syn_id2name(e.id1)))); + CSTR_TO_OBJ(syn_id2name(e.id1))); break; case kHlUI: - PUT(item, "kind", STRING_OBJ(cstr_to_string("ui"))); + PUT(item, "kind", CSTR_TO_OBJ("ui")); const char *ui_name = (e.id1 == -1) ? "Normal" : hlf_names[e.id1]; - PUT(item, "ui_name", STRING_OBJ(cstr_to_string(ui_name))); + PUT(item, "ui_name", CSTR_TO_OBJ(ui_name)); PUT(item, "hi_name", - STRING_OBJ(cstr_to_string(syn_id2name(e.id2)))); + CSTR_TO_OBJ(syn_id2name(e.id2))); break; case kHlTerminal: - PUT(item, "kind", STRING_OBJ(cstr_to_string("term"))); + PUT(item, "kind", CSTR_TO_OBJ("term")); break; case kHlCombine: -- cgit From 7bc93e0e2f246dd78026a3472d929a0fe450f70d Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 1 Aug 2023 14:01:19 +0200 Subject: refactor(api): use typed keysets Initially this is just for geting rid of boilerplate, but eventually the types could get exposed as metadata --- src/nvim/highlight.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index fad113adc5..3755b7ae05 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -226,8 +226,8 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault) if (api_dict_to_keydict(&dict, KeyDict_highlight_get_field, ret.data.dictionary, &err)) { attrs = dict2hlattrs(&dict, true, &it.link_id, &err); - fallback = api_object_to_bool(dict.fallback, "fallback", true, &err); - tmp = api_object_to_bool(dict.fallback, "tmp", false, &err); + fallback = GET_BOOL_OR_TRUE(&dict, highlight, fallback); + tmp = dict.fallback; // or false if (it.link_id >= 0) { fallback = true; } @@ -938,6 +938,7 @@ void hlattrs2dict(Dictionary *hl, Dictionary *hl_attrs, HlAttrs ae, bool use_rgb HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *err) { +#define HAS_KEY_X(d, key) HAS_KEY(d, highlight, key) HlAttrs hlattrs = HLATTRS_INIT; int32_t fg = -1, bg = -1, ctermfg = -1, ctermbg = -1, sp = -1; int blend = -1; @@ -946,7 +947,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e bool cterm_mask_provided = false; #define CHECK_FLAG(d, m, name, extra, flag) \ - if (api_object_to_bool(d->name##extra, #name, false, err)) { \ + if (d->name##extra) { \ if (flag & HL_UNDERLINE_MASK) { \ m &= ~HL_UNDERLINE_MASK; \ } \ @@ -971,52 +972,48 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e CHECK_FLAG(dict, mask, nocombine, , HL_NOCOMBINE); CHECK_FLAG(dict, mask, default, _, HL_DEFAULT); - if (HAS_KEY(dict->fg)) { + if (HAS_KEY_X(dict, fg)) { fg = object_to_color(dict->fg, "fg", use_rgb, err); - } else if (HAS_KEY(dict->foreground)) { + } else if (HAS_KEY_X(dict, foreground)) { fg = object_to_color(dict->foreground, "foreground", use_rgb, err); } if (ERROR_SET(err)) { return hlattrs; } - if (HAS_KEY(dict->bg)) { + if (HAS_KEY_X(dict, bg)) { bg = object_to_color(dict->bg, "bg", use_rgb, err); - } else if (HAS_KEY(dict->background)) { + } else if (HAS_KEY_X(dict, background)) { bg = object_to_color(dict->background, "background", use_rgb, err); } if (ERROR_SET(err)) { return hlattrs; } - if (HAS_KEY(dict->sp)) { + if (HAS_KEY_X(dict, sp)) { sp = object_to_color(dict->sp, "sp", true, err); - } else if (HAS_KEY(dict->special)) { + } else if (HAS_KEY_X(dict, special)) { sp = object_to_color(dict->special, "special", true, err); } if (ERROR_SET(err)) { return hlattrs; } - if (HAS_KEY(dict->blend)) { - VALIDATE_T("blend", kObjectTypeInteger, dict->blend.type, { - return hlattrs; - }); - - Integer blend0 = dict->blend.data.integer; + if (HAS_KEY_X(dict, blend)) { + Integer blend0 = dict->blend; VALIDATE_RANGE((blend0 >= 0 && blend0 <= 100), "blend", { return hlattrs; }); blend = (int)blend0; } - if (HAS_KEY(dict->link) || HAS_KEY(dict->global_link)) { + if (HAS_KEY_X(dict, link) || HAS_KEY_X(dict, global_link)) { if (!link_id) { api_set_error(err, kErrorTypeValidation, "Invalid Key: '%s'", - HAS_KEY(dict->global_link) ? "global_link" : "link"); + HAS_KEY_X(dict, global_link) ? "global_link" : "link"); return hlattrs; } - if (HAS_KEY(dict->global_link)) { + if (HAS_KEY_X(dict, global_link)) { *link_id = object_to_hl_id(dict->global_link, "link", err); mask |= HL_GLOBAL; } else { @@ -1050,21 +1047,21 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e // empty list from Lua API should clear all cterm attributes // TODO(clason): handle via gen_api_dispatch cterm_mask_provided = true; - } else if (HAS_KEY(dict->cterm)) { + } else if (HAS_KEY_X(dict, cterm)) { VALIDATE_EXP(false, "cterm", "Dict", api_typename(dict->cterm.type), { return hlattrs; }); } #undef CHECK_FLAG - if (HAS_KEY(dict->ctermfg)) { + if (HAS_KEY_X(dict, ctermfg)) { ctermfg = object_to_color(dict->ctermfg, "ctermfg", false, err); if (ERROR_SET(err)) { return hlattrs; } } - if (HAS_KEY(dict->ctermbg)) { + if (HAS_KEY_X(dict, ctermbg)) { ctermbg = object_to_color(dict->ctermbg, "ctermbg", false, err); if (ERROR_SET(err)) { return hlattrs; @@ -1091,6 +1088,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e } return hlattrs; +#undef HAS_KEY_X } int object_to_color(Object val, char *key, bool rgb, Error *err) -- cgit From 5970157e1d22fd5e05ae5d3bd949f807fb7a744c Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 17 May 2023 16:08:06 +0200 Subject: refactor(map): enhanced implementation, Clean Codeā„¢, etc etc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This involves two redesigns of the map.c implementations: 1. Change of macro style and code organization The old khash.h and map.c implementation used huge #define blocks with a lot of backslash line continuations. This instead uses the "implementation file" .c.h pattern. Such a file is meant to be included multiple times, with different macros set prior to inclusion as parameters. we already use this pattern e.g. for eval/typval_encode.c.h to implement different typval encoders reusing a similar structure. We can structure this code into two parts. one that only depends on key type and is enough to implement sets, and one which depends on both key and value to implement maps (as a wrapper around sets, with an added value[] array) 2. Separate the main hash buckets from the key / value arrays Change the hack buckets to only contain an index into separate key / value arrays This is a common pattern in modern, state of the art hashmap implementations. Even though this leads to one more allocated array, it is this often is a net reduction of memory consumption. Consider key+value consuming at least 12 bytes per pair. On average, we will have twice as many buckets per item. Thus old implementation: 2*12 = 24 bytes per item New implementation 1*12 + 2*4 = 20 bytes per item And the difference gets bigger with larger items. One might think we have pulled a fast one here, as wouldn't the average size of the new key/value arrays be 1.5 slots per items due to amortized grows? But remember, these arrays are fully dense, and thus the accessed memory, measured in _cache lines_, the unit which actually matters, will be the fully used memory but just rounded up to the nearest cache line boundary. This has some other interesting properties, such as an insert-only set/map will be fully ordered by insert only. Preserving this ordering in face of deletions is more tricky tho. As we currently don't use ordered maps, the "delete" operation maintains compactness of the item arrays in the simplest way by breaking the ordering. It would be possible to implement an order-preserving delete although at some cost, like allowing the items array to become non-dense until the next rehash. Finally, in face of these two major changes, all code used in khash.h has been integrated into map.c and friends. Given the heavy edits it makes no sense to "layer" the code into a vendored and a wrapper part. Rather, the layered cake follows the specialization depth: code shared for all maps, code specialized to a key type (and its equivalence relation), and finally code specialized to value+key type. --- src/nvim/highlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 3755b7ae05..29e5db7a96 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -167,7 +167,7 @@ void ns_hl_def(NS ns_id, int hl_id, HlAttrs attrs, int link_id, Dict(highlight) return; } if ((attrs.rgb_ae_attr & HL_DEFAULT) - && map_has(ColorKey, ColorItem)(&ns_hls, ColorKey(ns_id, hl_id))) { + && map_has(ColorKey, &ns_hls, (ColorKey(ns_id, hl_id)))) { return; } DecorProvider *p = get_decor_provider(ns_id, true); -- cgit From a6d745865a7f8b17f016b1879ed28376fed7b6b2 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 12 Sep 2023 11:54:36 +0200 Subject: refactor(highlight): merge redundant attr_entries and attr_entry_ids structs An insert-only set now defines a monotonically increasing ordering by itself. It can be used to both lookup the key from index, and vice versa. --- src/nvim/highlight.c | 64 +++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 29e5db7a96..df4bffdac3 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -40,13 +40,13 @@ static bool hlstate_active = false; -static kvec_t(HlEntry) attr_entries = KV_INITIAL_VALUE; - -static Map(HlEntry, int) attr_entry_ids = MAP_INIT; +static Set(HlEntry) attr_entries = SET_INIT; static Map(int, int) combine_attr_entries = MAP_INIT; static Map(int, int) blend_attr_entries = MAP_INIT; static Map(int, int) blendthrough_attr_entries = MAP_INIT; +#define attr_entry(i) attr_entries.keys[i] + /// highlight entries private to a namespace static Map(ColorKey, ColorItem) ns_hls; typedef int NSHlAttr[HLF_COUNT + 1]; @@ -55,8 +55,8 @@ static PMap(int) ns_hl_attr; void highlight_init(void) { // index 0 is no attribute, add dummy entry: - kv_push(attr_entries, ((HlEntry){ .attr = HLATTRS_INIT, .kind = kHlUnknown, - .id1 = 0, .id2 = 0 })); + set_put(HlEntry, &attr_entries, ((HlEntry){ .attr = HLATTRS_INIT, .kind = kHlInvalid, + .id1 = 0, .id2 = 0 })); } /// @return true if hl table was reset @@ -77,6 +77,7 @@ bool highlight_use_hlstate(void) /// @return 0 for error. static int get_attr_entry(HlEntry entry) { + bool retried = false; if (!hlstate_active) { // This information will not be used, erase it and reduce the table size. entry.kind = kHlUnknown; @@ -84,17 +85,19 @@ static int get_attr_entry(HlEntry entry) entry.id2 = 0; } - int id = map_get(HlEntry, int)(&attr_entry_ids, entry); - if (id > 0) { - return id; +retry: {} + MhPutStatus status; + uint32_t k = set_put_idx(HlEntry, &attr_entries, entry, &status); + if (status == kMHExisting) { + return (int)k; } static bool recursive = false; - if (kv_size(attr_entries) > MAX_TYPENR) { + if (set_size(&attr_entries) > MAX_TYPENR) { // Running out of attribute entries! remove all attributes, and // compute new ones for all groups. // When called recursively, we are really out of numbers. - if (recursive) { + if (recursive || retried) { emsg(_("E424: Too many different highlighting attributes in use")); return 0; } @@ -107,17 +110,12 @@ static int get_attr_entry(HlEntry entry) // This entry is now invalid, don't put it return 0; } + retried = true; + goto retry; } - size_t next_id = kv_size(attr_entries); - if (next_id > INT_MAX) { - ELOG("The index on attr_entries has overflowed"); - return 0; - } - id = (int)next_id; - kv_push(attr_entries, entry); - - map_put(HlEntry, int)(&attr_entry_ids, entry, id); + // new attr id, send event to remote ui:s + int id = (int)k; Array inspect = hl_inspect(id); @@ -131,10 +129,10 @@ static int get_attr_entry(HlEntry entry) /// When a UI connects, we need to send it the table of highlights used so far. void ui_send_all_hls(UI *ui) { - for (size_t i = 1; i < kv_size(attr_entries); i++) { + for (size_t i = 1; i < set_size(&attr_entries); i++) { Array inspect = hl_inspect((int)i); - remote_ui_hl_attr_define(ui, (Integer)i, kv_A(attr_entries, i).attr, - kv_A(attr_entries, i).attr, inspect); + HlAttrs attr = attr_entry(i).attr; + remote_ui_hl_attr_define(ui, (Integer)i, attr, attr, inspect); api_free_array(inspect); } for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) { @@ -364,7 +362,7 @@ void update_window_hl(win_T *wp, bool invalid) // if blend= attribute is not set, 'winblend' value overrides it. if (wp->w_floating && wp->w_p_winbl > 0) { - HlEntry entry = kv_A(attr_entries, wp->w_hl_attr_normal); + HlEntry entry = attr_entry(wp->w_hl_attr_normal); if (entry.attr.hl_blend == -1) { entry.attr.hl_blend = (int)wp->w_p_winbl; wp->w_hl_attr_normal = get_attr_entry(entry); @@ -401,7 +399,7 @@ void update_window_hl(win_T *wp, bool invalid) // if blend= attribute is not set, 'winblend' value overrides it. if (wp->w_floating && wp->w_p_winbl > 0) { - HlEntry entry = kv_A(attr_entries, wp->w_hl_attr_normalnc); + HlEntry entry = attr_entry(wp->w_hl_attr_normalnc); if (entry.attr.hl_blend == -1) { entry.attr.hl_blend = (int)wp->w_p_winbl; wp->w_hl_attr_normalnc = get_attr_entry(entry); @@ -490,8 +488,8 @@ int hl_get_term_attr(HlAttrs *aep) void clear_hl_tables(bool reinit) { if (reinit) { - kv_size(attr_entries) = 1; - map_clear(HlEntry, &attr_entry_ids); + set_clear(HlEntry, &attr_entries); + highlight_init(); map_clear(int, &combine_attr_entries); map_clear(int, &blend_attr_entries); map_clear(int, &blendthrough_attr_entries); @@ -500,8 +498,7 @@ void clear_hl_tables(bool reinit) highlight_changed(); screen_invalidate_highlights(); } else { - kv_destroy(attr_entries); - map_destroy(HlEntry, &attr_entry_ids); + set_destroy(HlEntry, &attr_entries); map_destroy(int, &combine_attr_entries); map_destroy(int, &blend_attr_entries); map_destroy(int, &blendthrough_attr_entries); @@ -809,11 +806,11 @@ static int hl_cterm2rgb_color(int nr) /// Get highlight attributes for a attribute code HlAttrs syn_attr2entry(int attr) { - if (attr <= 0 || attr >= (int)kv_size(attr_entries)) { + if (attr <= 0 || attr >= (int)set_size(&attr_entries)) { // invalid attribute code, or the tables were cleared return HLATTRS_INIT; } - return kv_A(attr_entries, attr).attr; + return attr_entry(attr).attr; } /// Gets highlight description for id `attr_id` as a map. @@ -825,7 +822,7 @@ Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error * return dic; } - if (attr_id <= 0 || attr_id >= (int)kv_size(attr_entries)) { + if (attr_id <= 0 || attr_id >= (int)set_size(&attr_entries)) { api_set_error(err, kErrorTypeException, "Invalid attribute id: %" PRId64, attr_id); return dic; @@ -1132,11 +1129,11 @@ Array hl_inspect(int attr) static void hl_inspect_impl(Array *arr, int attr) { Dictionary item = ARRAY_DICT_INIT; - if (attr <= 0 || attr >= (int)kv_size(attr_entries)) { + if (attr <= 0 || attr >= (int)set_size(&attr_entries)) { return; } - HlEntry e = kv_A(attr_entries, attr); + HlEntry e = attr_entry(attr); switch (e.kind) { case kHlSyntax: PUT(item, "kind", CSTR_TO_OBJ("syntax")); @@ -1165,6 +1162,7 @@ static void hl_inspect_impl(Array *arr, int attr) return; case kHlUnknown: + case kHlInvalid: return; } PUT(item, "id", INTEGER_OBJ(attr)); -- cgit From 8da986ea877b07a5eb117446f410f2a7fc8cd9cb Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 13 Sep 2023 13:39:18 +0200 Subject: refactor(grid): change schar_T representation to be more compact Previously, a screen cell would occupy 28+4=32 bytes per cell as we always made space for up to MAX_MCO+1 codepoints in a cell. As an example, even a pretty modest 50*80 screen would consume 50*80*2*32 = 256000, i e a quarter megabyte With the factor of two due to the TUI side buffer, and even more when using msg_grid and/or ext_multigrid. This instead stores a 4-byte union of either: - a valid UTF-8 sequence up to 4 bytes - an escape char which is invalid UTF-8 (0xFF) plus a 24-bit index to a glyph cache This avoids allocating space for huge composed glyphs _upfront_, while still keeping rendering such glyphs reasonably fast (1 hash table lookup + one plain index lookup). If the same large glyphs are using repeatedly on the screen, this is still a net reduction of memory/cache consumption. The only case which really gets worse is if you blast the screen full with crazy emojis and zalgo text and even this case only leads to 4 extra bytes per char. When only <= 4-byte glyphs are used, plus the 4-byte attribute code, i e 8 bytes in total there is a factor of four reduction of memory use. Memory which will be quite hot in cache as the screen buffer is scanned over in win_line() buffer text drawing A slight complication is that the representation depends on host byte order. I've tested this manually by compling and running this in qemu-s390x and it works fine. We might add a qemu based solution to CI at some point. --- src/nvim/highlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index df4bffdac3..3728db31d8 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -86,7 +86,7 @@ static int get_attr_entry(HlEntry entry) } retry: {} - MhPutStatus status; + MHPutStatus status; uint32_t k = set_put_idx(HlEntry, &attr_entries, entry, &status); if (status == kMHExisting) { return (int)k; -- cgit From cf8b2c0e74fd5e723b0c15c2ce84e6900fd322d3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 12:05:28 +0800 Subject: build(iwyu): add a few more _defs.h mappings (#25435) --- src/nvim/highlight.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 3728db31d8..14239f44cc 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -5,11 +5,10 @@ #include #include -#include #include -#include "klib/kvec.h" #include "lauxlib.h" +#include "nvim/api/keysets.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" @@ -22,7 +21,6 @@ #include "nvim/highlight.h" #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" -#include "nvim/log.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" #include "nvim/map.h" -- cgit From 1bbbca267d05709029a691c36e7c1fe415c9facc Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 8 Oct 2023 00:40:23 +0200 Subject: fix(PVS/V547): expression is always true/false --- src/nvim/highlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 14239f44cc..337f9e968d 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -332,7 +332,7 @@ void update_window_hl(win_T *wp, bool invalid) wp->w_ns_hl_active = ns_id; wp->w_ns_hl_attr = *(NSHlAttr *)pmap_get(int)(&ns_hl_attr, ns_id); - if (!wp->w_ns_hl_attr) { + if (!wp->w_ns_hl_attr) { // -V547 // No specific highlights, use the defaults. wp->w_ns_hl_attr = highlight_attr; } -- cgit From 5f03a1eaabfc8de2b3a9c666fcd604763f41e152 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 20 Oct 2023 15:10:33 +0200 Subject: build(lint): remove unnecessary clint.py rules Uncrustify is the source of truth where possible. Remove any redundant checks from clint.py. --- src/nvim/highlight.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 337f9e968d..88bf5dbd6e 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -478,7 +478,7 @@ int hl_get_underline(void) /// Get attribute code for forwarded :terminal highlights. int hl_get_term_attr(HlAttrs *aep) { - return get_attr_entry((HlEntry){ .attr= *aep, .kind = kHlTerminal, + return get_attr_entry((HlEntry){ .attr = *aep, .kind = kHlTerminal, .id1 = 0, .id2 = 0 }); } @@ -842,7 +842,7 @@ void hlattrs2dict(Dictionary *hl, Dictionary *hl_attrs, HlAttrs ae, bool use_rgb hl_attrs = hl_attrs ? hl_attrs : hl; assert(hl->capacity >= HLATTRS_DICT_SIZE); // at most 16 items assert(hl_attrs->capacity >= HLATTRS_DICT_SIZE); // at most 16 items - int mask = use_rgb ? ae.rgb_ae_attr : ae.cterm_ae_attr; + int mask = use_rgb ? ae.rgb_ae_attr : ae.cterm_ae_attr; if (mask & HL_INVERSE) { PUT_C(*hl_attrs, "reverse", BOOLEAN_OBJ(true)); -- cgit From 6c3e170e5668e72b2b144a86b4e8278bc70daa48 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Nov 2023 15:12:58 +0800 Subject: fix(highlight): apply 'winblend' to float border (#25981) --- src/nvim/highlight.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 88bf5dbd6e..a0114bbbe8 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -374,10 +374,15 @@ void update_window_hl(win_T *wp, bool invalid) if (wp->w_float_config.border_hl_ids[i]) { attr = hl_get_ui_attr(ns_id, HLF_BORDER, wp->w_float_config.border_hl_ids[i], false); - HlAttrs a = syn_attr2entry(attr); - if (a.hl_blend) { - wp->w_float_config.shadow = true; - } + } + HlAttrs a = syn_attr2entry(attr); + if (a.hl_blend == -1 && wp->w_p_winbl > 0) { + HlEntry entry = attr_entry(attr); + a.hl_blend = entry.attr.hl_blend = (int)wp->w_p_winbl; + attr = get_attr_entry(entry); + } + if (a.hl_blend > 0) { + wp->w_float_config.shadow = true; } wp->w_float_config.border_attr[i] = attr; } -- cgit From 9ecb43b6372feb49d6d497c41aa75d2cce1a1446 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 12 Nov 2023 09:23:34 +0800 Subject: fix(float): apply 'winblend' to title/footer highlight (#25999) --- src/nvim/highlight.c | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index a0114bbbe8..6d6bcacd83 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -323,6 +323,23 @@ int hl_get_ui_attr(int ns_id, int idx, int final_id, bool optional) .id1 = idx, .id2 = final_id }); } +/// Apply 'winblend' to highlight attributes. +/// +/// @param wp The window to get 'winblend' value from. +/// @param attr The original attribute code. +/// +/// @return The attribute code with 'winblend' applied. +int hl_apply_winblend(win_T *wp, int attr) +{ + HlEntry entry = attr_entry(attr); + // if blend= attribute is not set, 'winblend' value overrides it. + if (entry.attr.hl_blend == -1 && wp->w_p_winbl > 0) { + entry.attr.hl_blend = (int)wp->w_p_winbl; + attr = get_attr_entry(entry); + } + return attr; +} + void update_window_hl(win_T *wp, bool invalid) { int ns_id = wp->w_ns_hl; @@ -358,13 +375,8 @@ void update_window_hl(win_T *wp, bool invalid) wp->w_hl_attr_normal = float_win ? HL_ATTR(HLF_NFLOAT) : 0; } - // if blend= attribute is not set, 'winblend' value overrides it. - if (wp->w_floating && wp->w_p_winbl > 0) { - HlEntry entry = attr_entry(wp->w_hl_attr_normal); - if (entry.attr.hl_blend == -1) { - entry.attr.hl_blend = (int)wp->w_p_winbl; - wp->w_hl_attr_normal = get_attr_entry(entry); - } + if (wp->w_floating) { + wp->w_hl_attr_normal = hl_apply_winblend(wp, wp->w_hl_attr_normal); } wp->w_float_config.shadow = false; @@ -375,13 +387,8 @@ void update_window_hl(win_T *wp, bool invalid) attr = hl_get_ui_attr(ns_id, HLF_BORDER, wp->w_float_config.border_hl_ids[i], false); } - HlAttrs a = syn_attr2entry(attr); - if (a.hl_blend == -1 && wp->w_p_winbl > 0) { - HlEntry entry = attr_entry(attr); - a.hl_blend = entry.attr.hl_blend = (int)wp->w_p_winbl; - attr = get_attr_entry(entry); - } - if (a.hl_blend > 0) { + attr = hl_apply_winblend(wp, attr); + if (syn_attr2entry(attr).hl_blend > 0) { wp->w_float_config.shadow = true; } wp->w_float_config.border_attr[i] = attr; @@ -400,13 +407,8 @@ void update_window_hl(win_T *wp, bool invalid) wp->w_hl_attr_normalnc = hl_def[HLF_INACTIVE]; } - // if blend= attribute is not set, 'winblend' value overrides it. - if (wp->w_floating && wp->w_p_winbl > 0) { - HlEntry entry = attr_entry(wp->w_hl_attr_normalnc); - if (entry.attr.hl_blend == -1) { - entry.attr.hl_blend = (int)wp->w_p_winbl; - wp->w_hl_attr_normalnc = get_attr_entry(entry); - } + if (wp->w_floating) { + wp->w_hl_attr_normalnc = hl_apply_winblend(wp, wp->w_hl_attr_normalnc); } } -- cgit From 353a4be7e84fdc101318215bdcc8a7e780d737fe Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 12 Nov 2023 13:13:58 +0100 Subject: build: remove PVS We already have an extensive suite of static analysis tools we use, which causes a fair bit of redundancy as we get duplicate warnings. PVS is also prone to give false warnings which creates a lot of work to identify and disable. --- src/nvim/highlight.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 6d6bcacd83..cff62e736b 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // highlight.c: low level code for UI and syntax highlighting #include @@ -349,7 +346,7 @@ void update_window_hl(win_T *wp, bool invalid) wp->w_ns_hl_active = ns_id; wp->w_ns_hl_attr = *(NSHlAttr *)pmap_get(int)(&ns_hl_attr, ns_id); - if (!wp->w_ns_hl_attr) { // -V547 + if (!wp->w_ns_hl_attr) { // No specific highlights, use the defaults. wp->w_ns_hl_attr = highlight_attr; } -- cgit From 574d25642fc9ca65b396633aeab6e2d32778b642 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Nov 2023 17:21:58 +0800 Subject: refactor: move Arena and ArenaMem to memory_defs.h (#26240) --- src/nvim/highlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index cff62e736b..dcd6e0e8ad 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -2,9 +2,9 @@ #include #include +#include #include -#include "lauxlib.h" #include "nvim/api/keysets.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" -- cgit From e3f735ef101d670555f44226614a5c3557053b1f Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 27 Nov 2023 20:13:32 +0100 Subject: refactor: fix includes for api/autocmd.h --- src/nvim/highlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index dcd6e0e8ad..0ea95fc60e 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -5,7 +5,7 @@ #include #include -#include "nvim/api/keysets.h" +#include "nvim/api/keysets_defs.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" -- cgit From 6c14ae6bfaf51415b555e9a6b85d1d280976358d Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 27 Nov 2023 20:27:32 +0100 Subject: refactor: rename types.h to types_defs.h --- src/nvim/highlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 0ea95fc60e..9f58890ae0 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -25,7 +25,7 @@ #include "nvim/message.h" #include "nvim/option.h" #include "nvim/popupmenu.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/vim.h" -- cgit From 79b6ff28ad1204fbb4199b9092f5c578d88cb28e Mon Sep 17 00:00:00 2001 From: dundargoc Date: Tue, 28 Nov 2023 20:31:00 +0100 Subject: refactor: fix headers with IWYU --- src/nvim/highlight.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 9f58890ae0..6cd966c3b4 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -19,15 +19,15 @@ #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/lua/executor.h" -#include "nvim/macros.h" -#include "nvim/map.h" +#include "nvim/macros_defs.h" +#include "nvim/map_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/option.h" #include "nvim/popupmenu.h" #include "nvim/types_defs.h" #include "nvim/ui.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "highlight.c.generated.h" -- cgit From 86cc791debba09c8ed1aa0d863be844108866a38 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 29 Nov 2023 23:10:21 +0800 Subject: refactor: move function macros out of vim_defs.h (#26300) --- src/nvim/highlight.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/highlight.c') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 6cd966c3b4..141761c52e 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -25,6 +25,7 @@ #include "nvim/message.h" #include "nvim/option.h" #include "nvim/popupmenu.h" +#include "nvim/strings.h" #include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/vim_defs.h" -- cgit