diff options
Diffstat (limited to 'src/nvim/api/private/helpers.c')
-rw-r--r-- | src/nvim/api/private/helpers.c | 114 |
1 files changed, 61 insertions, 53 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index d2b787a6f5..5abdc33709 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -177,42 +177,47 @@ Object dict_get_value(dict_T *dict, String key, Error *err) return vim_to_object(&di->di_tv); } -/// Set a value in a scope dict. Objects are recursively expanded into their -/// vimscript equivalents. -/// -/// @param dict The vimscript dict -/// @param key The key -/// @param value The new value -/// @param del Delete key in place of setting it. Argument `value` is ignored in -/// this case. -/// @param retval If true the old value will be converted and returned. -/// @param[out] err Details of an error that may have occurred -/// @return The old value if `retval` is true and the key was present, else NIL -Object dict_set_var(dict_T *dict, String key, Object value, bool del, - bool retval, Error *err) +dictitem_T *dict_check_writable(dict_T *dict, String key, bool del, Error *err) { - Object rv = OBJECT_INIT; dictitem_T *di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size); if (di != NULL) { if (di->di_flags & DI_FLAGS_RO) { api_set_error(err, kErrorTypeException, "Key is read-only: %s", key.data); - return rv; } else if (di->di_flags & DI_FLAGS_LOCK) { api_set_error(err, kErrorTypeException, "Key is locked: %s", key.data); - return rv; } else if (del && (di->di_flags & DI_FLAGS_FIX)) { api_set_error(err, kErrorTypeException, "Key is fixed: %s", key.data); - return rv; } } else if (dict->dv_lock) { api_set_error(err, kErrorTypeException, "Dictionary is locked"); - return rv; } else if (key.size == 0) { api_set_error(err, kErrorTypeValidation, "Key name is empty"); - return rv; } else if (key.size > INT_MAX) { api_set_error(err, kErrorTypeValidation, "Key name is too long"); + } + + return di; +} + +/// Set a value in a scope dict. Objects are recursively expanded into their +/// vimscript equivalents. +/// +/// @param dict The vimscript dict +/// @param key The key +/// @param value The new value +/// @param del Delete key in place of setting it. Argument `value` is ignored in +/// this case. +/// @param retval If true the old value will be converted and returned. +/// @param[out] err Details of an error that may have occurred +/// @return The old value if `retval` is true and the key was present, else NIL +Object dict_set_var(dict_T *dict, String key, Object value, bool del, + bool retval, Error *err) +{ + Object rv = OBJECT_INIT; + dictitem_T *di = dict_check_writable(dict, key, del, err); + + if (ERROR_SET(err)) { return rv; } @@ -1708,33 +1713,6 @@ const char *describe_ns(NS ns_id) return "(UNKNOWN PLUGIN)"; } -DecorProvider *get_provider(NS ns_id, bool force) -{ - ssize_t i; - for (i = 0; i < (ssize_t)kv_size(decor_providers); i++) { - DecorProvider *item = &kv_A(decor_providers, i); - if (item->ns_id == ns_id) { - return item; - } else if (item->ns_id > ns_id) { - break; - } - } - - if (!force) { - return NULL; - } - - for (ssize_t j = (ssize_t)kv_size(decor_providers)-1; j >= i; j++) { - // allocates if needed: - (void)kv_a(decor_providers, (size_t)j+1); - kv_A(decor_providers, (size_t)j+1) = kv_A(decor_providers, j); - } - DecorProvider *item = &kv_a(decor_providers, (size_t)i); - *item = DECORATION_PROVIDER_INIT(ns_id); - - return item; -} - static bool parse_float_anchor(String anchor, FloatAnchor *out) { if (anchor.size == 0) { @@ -1787,10 +1765,13 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err) struct { const char *name; schar_T chars[8]; + bool shadow_color; } defaults[] = { - { "double", { "╔", "═", "╗", "║", "╝", "═", "╚", "║" } }, - { "single", { "┌", "─", "┐", "│", "┘", "─", "└", "│" } }, - { NULL, { { NUL } } }, + { "double", { "╔", "═", "╗", "║", "╝", "═", "╚", "║" }, false }, + { "single", { "┌", "─", "┐", "│", "┘", "─", "└", "│" }, false }, + { "shadow", { "", "", " ", " ", " ", " ", " ", "" }, true }, + { "solid", { " ", " ", " ", " ", " ", " ", " ", " " }, false }, + { NULL, { { NUL } } , false }, }; schar_T *chars = fconfig->border_chars; @@ -1834,13 +1815,16 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err) api_set_error(err, kErrorTypeValidation, "invalid border char"); return; } - if (!string.size - || mb_string2cells_len((char_u *)string.data, string.size) != 1) { + if (string.size + && mb_string2cells_len((char_u *)string.data, string.size) > 1) { api_set_error(err, kErrorTypeValidation, "border chars must be one cell"); + return; } size_t len = MIN(string.size, sizeof(*chars)-1); - memcpy(chars[i], string.data, len); + if (len) { + memcpy(chars[i], string.data, len); + } chars[i][len] = NUL; hl_ids[i] = hl_id; } @@ -1849,6 +1833,13 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err) memcpy(hl_ids+size, hl_ids, sizeof(*hl_ids) * size); size <<= 1; } + if ((chars[7][0] && chars[1][0] && !chars[0][0]) + || (chars[1][0] && chars[3][0] && !chars[2][0]) + || (chars[3][0] && chars[5][0] && !chars[4][0]) + || (chars[5][0] && chars[7][0] && !chars[6][0])) { + api_set_error(err, kErrorTypeValidation, + "corner between used edges must be specified"); + } } else if (style.type == kObjectTypeString) { String str = style.data.string; if (str.size == 0 || strequal(str.data, "none")) { @@ -1859,6 +1850,15 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err) if (strequal(str.data, defaults[i].name)) { memcpy(chars, defaults[i].chars, sizeof(defaults[i].chars)); memset(hl_ids, 0, 8 * sizeof(*hl_ids)); + if (defaults[i].shadow_color) { + int hl_blend = SYN_GROUP_STATIC("FloatShadow"); + int hl_through = SYN_GROUP_STATIC("FloatShadowThrough"); + hl_ids[2] = hl_through; + hl_ids[3] = hl_blend; + hl_ids[4] = hl_blend; + hl_ids[5] = hl_blend; + hl_ids[6] = hl_through; + } return; } } @@ -1914,7 +1914,7 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf, } else if (strequal(key, "height")) { has_height = true; if (val.type == kObjectTypeInteger && val.data.integer > 0) { - fconfig->height= (int)val.data.integer; + fconfig->height = (int)val.data.integer; } else { api_set_error(err, kErrorTypeValidation, "'height' key must be a positive Integer"); @@ -1988,6 +1988,14 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf, "'focusable' key must be Boolean"); return false; } + } else if (strequal(key, "zindex")) { + if (val.type == kObjectTypeInteger && val.data.integer > 0) { + fconfig->zindex = (int)val.data.integer; + } else { + api_set_error(err, kErrorTypeValidation, + "'zindex' key must be a positive Integer"); + return false; + } } else if (!strcmp(key, "border")) { parse_border_style(val, fconfig, err); if (ERROR_SET(err)) { |