diff options
Diffstat (limited to 'src/nvim/highlight.c')
-rw-r--r-- | src/nvim/highlight.c | 163 |
1 files changed, 118 insertions, 45 deletions
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 141761c52e..8729c74ce8 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -11,9 +11,10 @@ #include "nvim/api/private/helpers.h" #include "nvim/api/private/validate.h" #include "nvim/api/ui.h" +#include "nvim/decoration_defs.h" #include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" -#include "nvim/gettext.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/highlight.h" #include "nvim/highlight_defs.h" @@ -22,6 +23,7 @@ #include "nvim/macros_defs.h" #include "nvim/map_defs.h" #include "nvim/memory.h" +#include "nvim/memory_defs.h" #include "nvim/message.h" #include "nvim/option.h" #include "nvim/popupmenu.h" @@ -40,6 +42,7 @@ 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; +static Set(cstr_t) urls = SET_INIT; #define attr_entry(i) attr_entries.keys[i] @@ -113,26 +116,28 @@ retry: {} // new attr id, send event to remote ui:s int id = (int)k; - Array inspect = hl_inspect(id); + Arena arena = ARENA_EMPTY; + Array inspect = hl_inspect(id, &arena); // Note: internally we don't distinguish between cterm and rgb attributes, // remote_ui_hl_attr_define will however. ui_call_hl_attr_define(id, entry.attr, entry.attr, inspect); - api_free_array(inspect); + arena_mem_free(arena_finish(&arena)); return id; } /// When a UI connects, we need to send it the table of highlights used so far. -void ui_send_all_hls(UI *ui) +void ui_send_all_hls(RemoteUI *ui) { for (size_t i = 1; i < set_size(&attr_entries); i++) { - Array inspect = hl_inspect((int)i); + Arena arena = ARENA_EMPTY; + Array inspect = hl_inspect((int)i, &arena); HlAttrs attr = attr_entry(i).attr; remote_ui_hl_attr_define(ui, (Integer)i, attr, attr, inspect); - api_free_array(inspect); + arena_mem_free(arena_finish(&arena)); } for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) { - remote_ui_hl_group_set(ui, cstr_as_string((char *)hlf_names[hlf]), + remote_ui_hl_group_set(ui, cstr_as_string(hlf_names[hlf]), highlight_attr[hlf]); } } @@ -201,13 +206,13 @@ 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, CSTR_TO_OBJ(syn_id2name(hl_id))); + ADD_C(args, CSTR_AS_OBJ(syn_id2name(hl_id))); ADD_C(args, BOOLEAN_OBJ(link)); // TODO(bfredl): preload the "global" attr dict? Error err = ERROR_INIT; recursive++; - Object ret = nlua_call_ref(p->hl_def, "hl_def", args, true, &err); + Object ret = nlua_call_ref(p->hl_def, "hl_def", args, kRetObject, NULL, &err); recursive--; // TODO(bfredl): or "inherit", combine with global value? @@ -216,7 +221,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault) HlAttrs attrs = HLATTRS_INIT; if (ret.type == kObjectTypeDictionary) { fallback = false; - Dict(highlight) dict = { 0 }; + Dict(highlight) dict = KEYDICT_INIT; if (api_dict_to_keydict(&dict, KeyDict_highlight_get_field, ret.data.dictionary, &err)) { attrs = dict2hlattrs(&dict, true, &it.link_id, &err); @@ -364,7 +369,7 @@ void update_window_hl(win_T *wp, bool invalid) // wp->w_hl_attr_normal group. HL_ATTR(HLF_NFLOAT) is always named. // determine window specific background set in 'winhighlight' - bool float_win = wp->w_floating && !wp->w_float_config.external; + bool float_win = wp->w_floating && !wp->w_config.external; if (float_win && hl_def[HLF_NFLOAT] != 0) { wp->w_hl_attr_normal = hl_def[HLF_NFLOAT]; } else if (hl_def[HLF_COUNT] > 0) { @@ -377,19 +382,19 @@ void update_window_hl(win_T *wp, bool invalid) wp->w_hl_attr_normal = hl_apply_winblend(wp, wp->w_hl_attr_normal); } - wp->w_float_config.shadow = false; - if (wp->w_floating && wp->w_float_config.border) { + wp->w_config.shadow = false; + if (wp->w_floating && wp->w_config.border) { for (int i = 0; i < 8; i++) { int attr = hl_def[HLF_BORDER]; - if (wp->w_float_config.border_hl_ids[i]) { + if (wp->w_config.border_hl_ids[i]) { attr = hl_get_ui_attr(ns_id, HLF_BORDER, - wp->w_float_config.border_hl_ids[i], false); + wp->w_config.border_hl_ids[i], false); } attr = hl_apply_winblend(wp, attr); if (syn_attr2entry(attr).hl_blend > 0) { - wp->w_float_config.shadow = true; + wp->w_config.shadow = true; } - wp->w_float_config.border_attr[i] = attr; + wp->w_config.border_attr[i] = attr; } } @@ -473,6 +478,7 @@ int hl_get_underline(void) .rgb_bg_color = -1, .rgb_sp_color = -1, .hl_blend = -1, + .url = -1, }, .kind = kHlUI, .id1 = 0, @@ -480,6 +486,43 @@ int hl_get_underline(void) }); } +/// Augment an existing attribute with a URL. +/// +/// @param attr Existing attribute to combine with +/// @param url The URL to associate with the highlight attribute +/// @return Combined attribute +int hl_add_url(int attr, const char *url) +{ + HlAttrs attrs = HLATTRS_INIT; + + MHPutStatus status; + uint32_t k = set_put_idx(cstr_t, &urls, url, &status); + if (status != kMHExisting) { + urls.keys[k] = xstrdup(url); + } + + attrs.url = (int32_t)k; + + int new = get_attr_entry((HlEntry){ + .attr = attrs, + .kind = kHlUI, + .id1 = 0, + .id2 = 0, + }); + + return hl_combine_attr(attr, new); +} + +/// Get a URL by its index. +/// +/// @param index URL index +/// @return URL +const char *hl_get_url(uint32_t index) +{ + assert(urls.keys); + return urls.keys[index]; +} + /// Get attribute code for forwarded :terminal highlights. int hl_get_term_attr(HlAttrs *aep) { @@ -490,12 +533,18 @@ int hl_get_term_attr(HlAttrs *aep) /// Clear all highlight tables. void clear_hl_tables(bool reinit) { + const char *url = NULL; + set_foreach(&urls, url, { + xfree((void *)url); + }); + if (reinit) { 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); + set_clear(cstr_t, &urls); memset(highlight_attr_last, -1, sizeof(highlight_attr_last)); highlight_attr_set_all(); highlight_changed(); @@ -506,6 +555,7 @@ void clear_hl_tables(bool reinit) map_destroy(int, &blend_attr_entries); map_destroy(int, &blendthrough_attr_entries); map_destroy(ColorKey, &ns_hls); + set_destroy(cstr_t, &urls); } } @@ -597,6 +647,10 @@ int hl_combine_attr(int char_attr, int prim_attr) new_en.hl_blend = prim_aep.hl_blend; } + if ((new_en.url == -1) && (prim_aep.url >= 0)) { + new_en.url = prim_aep.url; + } + id = get_attr_entry((HlEntry){ .attr = new_en, .kind = kHlCombine, .id1 = char_attr, .id2 = prim_attr }); if (id > 0) { @@ -678,8 +732,8 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through) } cattrs.cterm_bg_color = fattrs.cterm_bg_color; - cattrs.cterm_fg_color = cterm_blend(ratio, battrs.cterm_fg_color, - fattrs.cterm_bg_color); + cattrs.cterm_fg_color = (int16_t)cterm_blend(ratio, battrs.cterm_fg_color, + fattrs.cterm_bg_color); cattrs.rgb_ae_attr &= ~(HL_FG_INDEXED | HL_BG_INDEXED); } else { cattrs = fattrs; @@ -713,7 +767,8 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through) static int rgb_blend(int ratio, int rgb1, int rgb2) { - int a = ratio, b = 100 - ratio; + int a = ratio; + int b = 100 - ratio; int r1 = (rgb1 & 0xFF0000) >> 16; int g1 = (rgb1 & 0x00FF00) >> 8; int b1 = (rgb1 & 0x0000FF) >> 0; @@ -726,7 +781,7 @@ static int rgb_blend(int ratio, int rgb1, int rgb2) return (mr << 16) + (mg << 8) + mb; } -static int cterm_blend(int ratio, int c1, int c2) +static int cterm_blend(int ratio, int16_t c1, int16_t c2) { // 1. Convert cterm color numbers to RGB. // 2. Blend the RGB colors. @@ -940,7 +995,11 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e { #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; + int32_t fg = -1; + int32_t bg = -1; + int32_t ctermfg = -1; + int32_t ctermbg = -1; + int32_t sp = -1; int blend = -1; int16_t mask = 0; int16_t cterm_mask = 0; @@ -1027,7 +1086,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e // Handle cterm attrs if (dict->cterm.type == kObjectTypeDictionary) { - Dict(highlight_cterm) cterm[1] = { 0 }; + Dict(highlight_cterm) cterm[1] = KEYDICT_INIT; if (!api_dict_to_keydict(cterm, KeyDict_highlight_cterm_get_field, dict->cterm.data.dictionary, err)) { return hlattrs; @@ -1078,12 +1137,12 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e hlattrs.rgb_fg_color = fg; hlattrs.rgb_sp_color = sp; hlattrs.hl_blend = blend; - hlattrs.cterm_bg_color = ctermbg == -1 ? 0 : ctermbg + 1; - hlattrs.cterm_fg_color = ctermfg == -1 ? 0 : ctermfg + 1; + hlattrs.cterm_bg_color = ctermbg == -1 ? 0 : (int16_t)(ctermbg + 1); + hlattrs.cterm_fg_color = ctermfg == -1 ? 0 : (int16_t)(ctermfg + 1); hlattrs.cterm_ae_attr = cterm_mask; } else { - hlattrs.cterm_bg_color = bg == -1 ? 0 : bg + 1; - hlattrs.cterm_fg_color = fg == -1 ? 0 : fg + 1; + hlattrs.cterm_bg_color = bg == -1 ? 0 : (int16_t)(bg + 1); + hlattrs.cterm_fg_color = fg == -1 ? 0 : (int16_t)(fg + 1); hlattrs.cterm_ae_attr = mask; } @@ -1119,17 +1178,30 @@ int object_to_color(Object val, char *key, bool rgb, Error *err) } } -Array hl_inspect(int attr) +Array hl_inspect(int attr, Arena *arena) { - // TODO(bfredl): use arena allocation - Array ret = ARRAY_DICT_INIT; - if (hlstate_active) { - hl_inspect_impl(&ret, attr); + if (!hlstate_active) { + return (Array)ARRAY_DICT_INIT; } + Array ret = arena_array(arena, hl_inspect_size(attr)); + hl_inspect_impl(&ret, attr, arena); return ret; } -static void hl_inspect_impl(Array *arr, int attr) +static size_t hl_inspect_size(int attr) +{ + if (attr <= 0 || attr >= (int)set_size(&attr_entries)) { + return 0; + } + + HlEntry e = attr_entry(attr); + if (e.kind == kHlCombine || e.kind == kHlBlend || e.kind == kHlBlendThrough) { + return hl_inspect_size(e.id1) + hl_inspect_size(e.id2); + } + return 1; +} + +static void hl_inspect_impl(Array *arr, int attr, Arena *arena) { Dictionary item = ARRAY_DICT_INIT; if (attr <= 0 || attr >= (int)set_size(&attr_entries)) { @@ -1139,35 +1211,36 @@ static void hl_inspect_impl(Array *arr, int attr) HlEntry e = attr_entry(attr); switch (e.kind) { case kHlSyntax: - PUT(item, "kind", CSTR_TO_OBJ("syntax")); - PUT(item, "hi_name", - CSTR_TO_OBJ(syn_id2name(e.id1))); + item = arena_dict(arena, 3); + PUT_C(item, "kind", CSTR_AS_OBJ("syntax")); + PUT_C(item, "hi_name", CSTR_AS_OBJ(syn_id2name(e.id1))); break; case kHlUI: - PUT(item, "kind", CSTR_TO_OBJ("ui")); + item = arena_dict(arena, 4); + PUT_C(item, "kind", CSTR_AS_OBJ("ui")); const char *ui_name = (e.id1 == -1) ? "Normal" : hlf_names[e.id1]; - PUT(item, "ui_name", CSTR_TO_OBJ(ui_name)); - PUT(item, "hi_name", - CSTR_TO_OBJ(syn_id2name(e.id2))); + PUT_C(item, "ui_name", CSTR_AS_OBJ(ui_name)); + PUT_C(item, "hi_name", CSTR_AS_OBJ(syn_id2name(e.id2))); break; case kHlTerminal: - PUT(item, "kind", CSTR_TO_OBJ("term")); + item = arena_dict(arena, 2); + PUT_C(item, "kind", CSTR_AS_OBJ("term")); break; case kHlCombine: case kHlBlend: case kHlBlendThrough: // attribute combination is associative, so flatten to an array - hl_inspect_impl(arr, e.id1); - hl_inspect_impl(arr, e.id2); + hl_inspect_impl(arr, e.id1, arena); + hl_inspect_impl(arr, e.id2, arena); return; case kHlUnknown: case kHlInvalid: return; } - PUT(item, "id", INTEGER_OBJ(attr)); - ADD(*arr, DICTIONARY_OBJ(item)); + PUT_C(item, "id", INTEGER_OBJ(attr)); + ADD_C(*arr, DICTIONARY_OBJ(item)); } |