// highlight.c: low level code for UI and syntax highlighting
#include <assert.h>
#include <inttypes.h>
#include <lauxlib.h>
#include <string.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"
#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_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#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"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/vim_defs.h"
#include "highlight.c.generated.h"
static bool hlstate_active = false;
static Set(HlEntry) attr_entries = SET_INIT;
static Map(uint64_t, int) combine_attr_entries = MAP_INIT;
static Map(uint64_t, int) blend_attr_entries = MAP_INIT;
static Map(uint64_t, int) blendthrough_attr_entries = MAP_INIT;
static Set(cstr_t) urls = SET_INIT;
/// Interned font names, referenced by index in HlAttrs.font.
static Set(cstr_t) fonts = SET_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];
static PMap(int) ns_hl_attr;
void highlight_init(void)
{
// index 0 is no attribute, add dummy entry:
set_put(HlEntry, &attr_entries, ((HlEntry){ .attr = HLATTRS_INIT, .kind = kHlInvalid,
.id1 = 0, .id2 = 0 }));
}
/// @return true if hl table was reset
bool highlight_use_hlstate(void)
{
if (hlstate_active) {
return false;
}
hlstate_active = true;
// hl tables must now be rebuilt.
clear_hl_tables(true);
return true;
}
/// Return the attr number for a set of colors and font, and optionally
/// a semantic description (see ext_hlstate documentation).
/// Add a new entry to the attr_entries array if the combination is new.
/// @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;
entry.id1 = 0;
entry.id2 = 0;
}
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 (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 || retried) {
emsg(_("E424: Too many different highlighting attributes in use"));
return 0;
}
recursive = true;
clear_hl_tables(true);
recursive = false;
if (entry.kind == kHlCombine) {
// This entry is now invalid, don't put it
return 0;
}
retried = true;
goto retry;
}
// new attr id, send event to remote ui:s
int id = (int)k;
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);
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(RemoteUI *ui)
{
for (size_t i = 1; i < set_size(&attr_entries); 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);
arena_mem_free(arena_finish(&arena));
}
for (size_t hlf
|