// 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
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/charset.h"
#include "nvim/decoration_provider.h"
#include "nvim/drawscreen.h"
#include "nvim/extmark.h"
#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#include "nvim/memline.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/extmark.c.generated.h"
#endif
void api_extmark_free_all_mem(void)
{
String name;
handle_T id;
map_foreach(&namespace_ids, name, id, {
(void)id;
xfree(name.data);
})
map_destroy(String, handle_T)(&namespace_ids);
}
/// Creates a new \*namespace\* or gets an existing one.
///
/// Namespaces are used for buffer highlights and virtual text, see
/// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.
///
/// Namespaces can be named or anonymous. If `name` matches an existing
/// namespace, the associated id is returned. If `name` is an empty string
/// a new, anonymous namespace is created.
///
/// @param name Namespace name or empty string
/// @return Namespace id
Integer nvim_create_namespace(String name)
FUNC_API_SINCE(5)
{
handle_T id = map_get(String, handle_T)(&namespace_ids, name);
if (id > 0) {
return id;
}
id = next_namespace_id++;
if (name.size > 0) {
String name_alloc = copy_string(name);
map_put(String, handle_T)(&namespace_ids, name_alloc, id);
}
return (Integer)id;
}
/// Gets existing, non-anonymous namespaces.
///
/// @return dict that maps from names to namespace ids.
Dictionary nvim_get_namespaces(void)
FUNC_API_SINCE(5)
{
Dictionary retval = ARRAY_DICT_INIT;
String name;
handle_T id;
map_foreach(&namespace_ids, name, id, {
PUT(retval, name.data, INTEGER_OBJ(id));
})
return retval;
}
const char *describe_ns(NS ns_id)
{
String name;
handle_T id;
map_foreach(&namespace_ids, name, id, {
if ((NS)id == ns_id && name.size) {
return name.data;
}
})
return "(UNKNOWN PLUGIN)";
}
// Is the Namespace in use?
static bool ns_initialized(uint32_t ns)
{
if (ns < 1) {
return false;
}
return ns < (uint32_t)next_namespace_id;
}
static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict)
{
Array rv = ARRAY_DICT_INIT;
if (id) {
ADD(rv, INTEGER_OBJ((Integer)extmark->mark_id));
}
ADD(rv, INTEGER_OBJ(extmark->row));
ADD(rv, INTEGER_OBJ(extmark->col));
if (add_dict) {
Dictionary dict = ARRAY_DICT_INIT;
PUT(dict, "right_gravity", BOOLEAN_OBJ(extmark->right_gravity));
if (extmark->end_row >= 0) {
PUT(dict, "end_row", INTEGER_OBJ(extmark->end_row));
PUT(dict, "end_col", INTEGER_OBJ(extmark->end_col));
PUT(dict, "end_right_gravity", BOOLEAN_OBJ(extmark->end_right_gravity));
}
const Decoration *decor = &extmark->decor;
if (decor->hl_id) {
String name = cstr_to_string((const char *)syn_id2name(decor->hl_id));
PUT(dict, "hl_group", STRING_OBJ(name));
PUT(dict, "hl_eol", BOOLEAN_OBJ(decor->hl_eol));
}
if (decor->hl_mode) {
PUT(dict, "hl_mode", STRING_OBJ(cstr_to_string(hl_mode_str[decor->hl_mode])));
}
if (kv_size(decor->virt_text)) {
Array chunks = ARRAY_DICT_INIT;
for (size_t i = 0; i < decor->virt_text.size; i++) {
Array chunk = ARRAY_DICT_INIT;
VirtTextChunk *vtc = &decor->virt_text.items[i];
ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text)));
if (vtc->hl_id > 0) {
ADD(chunk,
STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id))));
}
ADD(chunks, ARRAY_OBJ(chunk));
}
PUT(dict, "virt_text", ARRAY_OBJ(chunks));
PUT(dict, "virt_text_hide", BOOLEAN_OBJ(decor->virt_text_hide));
if (decor->virt_text_pos == kVTWinCol) {
PUT(dict, "virt_text_win_col", INTEGER_OBJ(decor->col));
}
PUT(dict, "virt_text_pos",
STRING_OBJ(cstr_to_string(virt_text_pos_str[decor->virt_text_pos])));
}
if (decor->ui_watched) {
PUT(dict, "ui_watched", BOOLEAN_OBJ(true));
}
if (kv_size(decor->virt_lines)) {
Array all_chunks = ARRAY_DICT_INIT;
bool virt_lines_leftcol = false;
for (size_t i = 0; i < decor->virt_lines.size; i++) {
Array chunks = ARRAY_DICT_INIT;
VirtText *vt = &decor->virt_lines.items[i].line;
virt_lines_leftcol = decor->virt_lines.items[i].left_col;
for (size_t j = 0; j < vt->size; j++) {
Array chunk = ARRAY_DICT_INIT;
VirtTextChunk *vtc = &vt->items[j];
ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text)));
if (vtc->hl_id > 0) {
ADD(chunk,
STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id))));
|