diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/extmark.c | 1 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 1 | ||||
-rw-r--r-- | src/nvim/autocmd.c | 3 | ||||
-rw-r--r-- | src/nvim/charset.c | 10 | ||||
-rw-r--r-- | src/nvim/decoration.c | 53 | ||||
-rw-r--r-- | src/nvim/decoration.h | 19 | ||||
-rw-r--r-- | src/nvim/decoration_provider.c | 231 | ||||
-rw-r--r-- | src/nvim/decoration_provider.h | 26 | ||||
-rw-r--r-- | src/nvim/highlight.c | 1 | ||||
-rw-r--r-- | src/nvim/main.c | 1 | ||||
-rw-r--r-- | src/nvim/mark.c | 2 | ||||
-rw-r--r-- | src/nvim/memory.c | 2 | ||||
-rw-r--r-- | src/nvim/normal.c | 1 | ||||
-rw-r--r-- | src/nvim/option.c | 6 | ||||
-rw-r--r-- | src/nvim/popupmnu.c | 7 | ||||
-rw-r--r-- | src/nvim/regexp.c | 10 | ||||
-rw-r--r-- | src/nvim/screen.c | 148 | ||||
-rw-r--r-- | src/nvim/testdir/test_regexp_latin.vim | 16 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 4 |
19 files changed, 322 insertions, 220 deletions
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 0ee8134ec4..e355f82f4d 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -8,6 +8,7 @@ #include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/decoration_provider.h" #include "nvim/extmark.h" #include "nvim/lua/executor.h" #include "nvim/memline.h" diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index b2d866ae0e..ebf4f65c91 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -22,6 +22,7 @@ #include "nvim/charset.h" #include "nvim/context.h" #include "nvim/decoration.h" +#include "nvim/decoration_provider.h" #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index a850e5c1a0..dfcdfd8203 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -2428,9 +2428,8 @@ char *aucmd_exec_default_desc(AucmdExecutable acc) default: return NULL; } - - abort(); } + char *aucmd_exec_to_string(AutoCmd *ac, AucmdExecutable acc) { switch (acc.type) { diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 97aac67627..3383dd2a76 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -928,10 +928,12 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en // continue until the NUL posptr = NULL; } else { - // Special check for an empty line, which can happen on exit, when - // ml_get_buf() always returns an empty string. - if (*ptr == NUL) { - pos->col = 0; + // In a few cases the position can be beyond the end of the line. + for (colnr_T i = 0; i < pos->col; i++) { + if (ptr[i] == NUL) { + pos->col = i; + break; + } } posptr = ptr + pos->col; posptr -= utf_head_off(line, posptr); diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index b533f4c46f..94bf1feeee 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -523,59 +523,6 @@ void decor_add_ephemeral(int start_row, int start_col, int end_row, int end_col, } -DecorProvider *get_decor_provider(NS ns_id, bool force) -{ - size_t i; - size_t len = kv_size(decor_providers); - for (i = 0; i < len; 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; - } - - // Adding a new provider, so allocate room in the vector - (void)kv_a(decor_providers, len); - if (i < len) { - // New ns_id needs to be inserted between existing providers to maintain - // ordering, so shift other providers with larger ns_id - memmove(&kv_A(decor_providers, i + 1), - &kv_A(decor_providers, i), - (len - i) * sizeof(kv_a(decor_providers, i))); - } - DecorProvider *item = &kv_a(decor_providers, i); - *item = DECORATION_PROVIDER_INIT(ns_id); - - return item; -} - -void decor_provider_clear(DecorProvider *p) -{ - if (p == NULL) { - return; - } - NLUA_CLEAR_REF(p->redraw_start); - NLUA_CLEAR_REF(p->redraw_buf); - NLUA_CLEAR_REF(p->redraw_win); - NLUA_CLEAR_REF(p->redraw_line); - NLUA_CLEAR_REF(p->redraw_end); - p->active = false; -} - -void decor_free_all_mem(void) -{ - for (size_t i = 0; i < kv_size(decor_providers); i++) { - decor_provider_clear(&kv_A(decor_providers, i)); - } - kv_destroy(decor_providers); -} - int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines) { diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h index c186a1b1fd..8df53caa0a 100644 --- a/src/nvim/decoration.h +++ b/src/nvim/decoration.h @@ -82,26 +82,7 @@ typedef struct { int eol_col; } DecorState; -typedef struct { - NS ns_id; - bool active; - LuaRef redraw_start; - LuaRef redraw_buf; - LuaRef redraw_win; - LuaRef redraw_line; - LuaRef redraw_end; - LuaRef hl_def; - int hl_valid; -} DecorProvider; - -EXTERN kvec_t(DecorProvider) decor_providers INIT(= KV_INITIAL_VALUE); EXTERN DecorState decor_state INIT(= { 0 }); -EXTERN bool provider_active INIT(= false); - -#define DECORATION_PROVIDER_INIT(ns_id) (DecorProvider) \ - { ns_id, false, LUA_NOREF, LUA_NOREF, \ - LUA_NOREF, LUA_NOREF, LUA_NOREF, \ - LUA_NOREF, -1 } static inline bool decor_has_sign(Decoration *decor) { diff --git a/src/nvim/decoration_provider.c b/src/nvim/decoration_provider.c new file mode 100644 index 0000000000..6efcb08b9d --- /dev/null +++ b/src/nvim/decoration_provider.c @@ -0,0 +1,231 @@ +// 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 "nvim/api/extmark.h" +#include "nvim/api/private/helpers.h" +#include "nvim/buffer.h" +#include "nvim/decoration.h" +#include "nvim/decoration_provider.h" +#include "nvim/highlight.h" +#include "nvim/lua/executor.h" + +static kvec_t(DecorProvider) decor_providers = KV_INITIAL_VALUE; + +#define DECORATION_PROVIDER_INIT(ns_id) (DecorProvider) \ + { ns_id, false, LUA_NOREF, LUA_NOREF, \ + LUA_NOREF, LUA_NOREF, LUA_NOREF, \ + LUA_NOREF, -1 } + +static bool decor_provider_invoke(NS ns_id, const char *name, LuaRef ref, + Array args, bool default_true, char **perr) +{ + Error err = ERROR_INIT; + + textlock++; + provider_active = true; + Object ret = nlua_call_ref(ref, name, args, true, &err); + provider_active = false; + textlock--; + + if (!ERROR_SET(&err) + && api_object_to_bool(ret, "provider %s retval", default_true, &err)) { + return true; + } + + if (ERROR_SET(&err)) { + const char *ns_name = describe_ns(ns_id); + ELOG("error in provider %s:%s: %s", ns_name, name, err.msg); + bool verbose_errs = true; // TODO(bfredl): + if (verbose_errs && perr && *perr == NULL) { + static char errbuf[IOSIZE]; + snprintf(errbuf, sizeof errbuf, "%s: %s", ns_name, err.msg); + *perr = xstrdup(errbuf); + } + } + + api_free_object(ret); + return false; +} + +/// For each provider invoke the 'start' callback +/// +/// @param[out] providers Decoration providers +/// @param[out] err Provider err +void decor_providers_start(DecorProviders *providers, int type, char **err) +{ + kvi_init(*providers); + + for (size_t i = 0; i < kv_size(decor_providers); i++) { + DecorProvider *p = &kv_A(decor_providers, i); + if (!p->active) { + continue; + } + + bool active; + if (p->redraw_start != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 2); + args.items[0] = INTEGER_OBJ((int)display_tick); + args.items[1] = INTEGER_OBJ(type); + active = decor_provider_invoke(p->ns_id, "start", p->redraw_start, args, true, err); + } else { + active = true; + } + + if (active) { + kvi_push(*providers, p); + } + } +} + +/// For each provider run 'win'. If result is not false, then collect the +/// 'on_line' callback to call inside win_line +/// +/// @param wp Window +/// @param providers Decoration providers +/// @param[out] line_providers Enabled line providers to invoke in win_line +/// @param[out] err Provider error +void decor_providers_invoke_win(win_T *wp, DecorProviders *providers, + DecorProviders *line_providers, char **err) +{ + kvi_init(*line_providers); + + linenr_T knownmax = ((wp->w_valid & VALID_BOTLINE) + ? wp->w_botline + : (wp->w_topline + wp->w_height_inner)); + + for (size_t k = 0; k < kv_size(*providers); k++) { + DecorProvider *p = kv_A(*providers, k); + if (p && p->redraw_win != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 4); + args.items[0] = WINDOW_OBJ(wp->handle); + args.items[1] = BUFFER_OBJ(wp->w_buffer->handle); + // TODO(bfredl): we are not using this, but should be first drawn line? + args.items[2] = INTEGER_OBJ(wp->w_topline-1); + args.items[3] = INTEGER_OBJ(knownmax); + if (decor_provider_invoke(p->ns_id, "win", p->redraw_win, args, true, err)) { + kvi_push(*line_providers, p); + } + } + } + + win_check_ns_hl(wp); +} + +/// For each provider invoke the 'line' callback for a given window row. +/// +/// @param wp Window +/// @param providers Decoration providers +/// @param row Row to invoke line callback for +/// @param[out] has_decor Set when at least one provider invokes a line callback +/// @param[out] err Provider error +void providers_invoke_line(win_T *wp, DecorProviders *providers, int row, bool *has_decor, + char **err) +{ + for (size_t k = 0; k < kv_size(*providers); k++) { + DecorProvider *p = kv_A(*providers, k); + if (p && p->redraw_line != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 3); + args.items[0] = WINDOW_OBJ(wp->handle); + args.items[1] = BUFFER_OBJ(wp->w_buffer->handle); + args.items[2] = INTEGER_OBJ(row); + if (decor_provider_invoke(p->ns_id, "line", p->redraw_line, args, true, err)) { + *has_decor = true; + } else { + // return 'false' or error: skip rest of this window + kv_A(*providers, k) = NULL; + } + + win_check_ns_hl(wp); + } + } +} + + +/// For each provider invoke the 'buf' callback for a given buffer. +/// +/// @param buf Buffer +/// @param providers Decoration providers +/// @param[out] err Provider error +void decor_providers_invoke_buf(buf_T *buf, DecorProviders *providers, char **err) +{ + for (size_t i = 0; i < kv_size(*providers); i++) { + DecorProvider *p = kv_A(*providers, i); + if (p && p->redraw_buf != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 1); + args.items[0] = BUFFER_OBJ(buf->handle); + decor_provider_invoke(p->ns_id, "buf", p->redraw_buf, args, true, err); + } + } +} + + +/// For each provider invoke the 'end' callback +/// +/// @param providers Decoration providers +/// @param displaytick Display tick +/// @param[out] err Provider error +void decor_providers_invoke_end(DecorProviders *providers, char **err) +{ + for (size_t i = 0; i < kv_size(*providers); i++) { + DecorProvider *p = kv_A(*providers, i); + if (p && p->active && p->redraw_end != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 1); + args.items[0] = INTEGER_OBJ((int)display_tick); + decor_provider_invoke(p->ns_id, "end", p->redraw_end, args, true, err); + } + } +} + +DecorProvider *get_decor_provider(NS ns_id, bool force) +{ + size_t i; + size_t len = kv_size(decor_providers); + for (i = 0; i < len; 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; + } + + // Adding a new provider, so allocate room in the vector + (void)kv_a(decor_providers, len); + if (i < len) { + // New ns_id needs to be inserted between existing providers to maintain + // ordering, so shift other providers with larger ns_id + memmove(&kv_A(decor_providers, i + 1), + &kv_A(decor_providers, i), + (len - i) * sizeof(kv_a(decor_providers, i))); + } + DecorProvider *item = &kv_a(decor_providers, i); + *item = DECORATION_PROVIDER_INIT(ns_id); + + return item; +} + +void decor_provider_clear(DecorProvider *p) +{ + if (p == NULL) { + return; + } + NLUA_CLEAR_REF(p->redraw_start); + NLUA_CLEAR_REF(p->redraw_buf); + NLUA_CLEAR_REF(p->redraw_win); + NLUA_CLEAR_REF(p->redraw_line); + NLUA_CLEAR_REF(p->redraw_end); + p->active = false; +} + +void decor_free_all_mem(void) +{ + for (size_t i = 0; i < kv_size(decor_providers); i++) { + decor_provider_clear(&kv_A(decor_providers, i)); + } + kv_destroy(decor_providers); +} + diff --git a/src/nvim/decoration_provider.h b/src/nvim/decoration_provider.h new file mode 100644 index 0000000000..3ec7c80357 --- /dev/null +++ b/src/nvim/decoration_provider.h @@ -0,0 +1,26 @@ +#ifndef NVIM_DECORATION_PROVIDER_H +#define NVIM_DECORATION_PROVIDER_H + +#include "nvim/buffer_defs.h" + +typedef struct { + NS ns_id; + bool active; + LuaRef redraw_start; + LuaRef redraw_buf; + LuaRef redraw_win; + LuaRef redraw_line; + LuaRef redraw_end; + LuaRef hl_def; + int hl_valid; +} DecorProvider; + +typedef kvec_withinit_t(DecorProvider *, 4) DecorProviders; + +EXTERN bool provider_active INIT(= false); + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "decoration_provider.h.generated.h" +#endif + +#endif // NVIM_DECORATION_PROVIDER_H diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 3aa9190db6..abbda1e9fa 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -5,6 +5,7 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/decoration_provider.h" #include "nvim/highlight.h" #include "nvim/highlight_defs.h" #include "nvim/lua/executor.h" diff --git a/src/nvim/main.c b/src/nvim/main.c index 7281809c06..a575aba50a 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -14,6 +14,7 @@ #include "nvim/channel.h" #include "nvim/charset.h" #include "nvim/decoration.h" +#include "nvim/decoration_provider.h" #include "nvim/diff.h" #include "nvim/eval.h" #include "nvim/ex_cmds.h" diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 8b29aa3676..b770fef05c 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -630,7 +630,7 @@ static char_u *mark_line(pos_T *mp, int lead_len) if (mp->lnum == 0 || mp->lnum > curbuf->b_ml.ml_line_count) { return vim_strsave((char_u *)"-invalid-"); } - assert(Columns >= 0 && (size_t)Columns <= SIZE_MAX); + assert(Columns >= 0); // Allow for up to 5 bytes per character. s = vim_strnsave(skipwhite(ml_get(mp->lnum)), (size_t)Columns * 5); diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 677ff8f522..d68ca6b62e 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -10,7 +10,7 @@ #include "nvim/api/extmark.h" #include "nvim/context.h" -#include "nvim/decoration.h" +#include "nvim/decoration_provider.h" #include "nvim/eval.h" #include "nvim/highlight.h" #include "nvim/lua/executor.h" diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 5c39e9c8bf..0e5e0ab403 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -3568,7 +3568,6 @@ static void nv_zet(cmdarg_T *cap) bool undo = false; int l_p_siso = (int)get_sidescrolloff_value(curwin); - assert(l_p_siso <= INT_MAX); if (ascii_isdigit(nchar)) { /* diff --git a/src/nvim/option.c b/src/nvim/option.c index a0706dfa14..191b635dc0 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5664,12 +5664,10 @@ void comp_col(void) } } assert(sc_col >= 0 - && INT_MIN + sc_col <= Columns - && Columns - sc_col <= INT_MAX); + && INT_MIN + sc_col <= Columns); sc_col = Columns - sc_col; assert(ru_col >= 0 - && INT_MIN + ru_col <= Columns - && Columns - ru_col <= INT_MAX); + && INT_MIN + ru_col <= Columns); ru_col = Columns - ru_col; if (sc_col <= 0) { // screen too narrow, will become a mess sc_col = 1; diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index d7726409b5..e354a589a5 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -289,8 +289,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i if (pum_rl) { pum_width = pum_col - pum_scrollbar + 1; } else { - assert(Columns - pum_col - pum_scrollbar >= INT_MIN - && Columns - pum_col - pum_scrollbar <= INT_MAX); + assert(Columns - pum_col - pum_scrollbar >= 0); pum_width = Columns - pum_col - pum_scrollbar; } @@ -356,7 +355,6 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i } else { pum_col = 0; } - assert(Columns - 1 >= INT_MIN); pum_width = Columns - 1; } else { if (max_width > p_pw) { @@ -367,8 +365,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i if (pum_rl) { pum_col = max_width - 1; } else { - assert(Columns - max_width >= INT_MIN - && Columns - max_width <= INT_MAX); + assert(Columns - max_width >= 0); pum_col = Columns - max_width; } pum_width = max_width - pum_scrollbar; diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 412cdac21b..009a26d4e0 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -1136,8 +1136,8 @@ static bool reg_match_visual(void) return false; } + col = (colnr_T)(rex.input - rex.line); if (mode == 'v') { - col = (colnr_T)(rex.input - rex.line); if ((lnum == top.lnum && col < top.col) || (lnum == bot.lnum && col >= bot.col + (*p_sel != 'e'))) { return false; @@ -1152,8 +1152,12 @@ static bool reg_match_visual(void) if (top.col == MAXCOL || bot.col == MAXCOL || curswant == MAXCOL) { end = MAXCOL; } - unsigned int cols_u = win_linetabsize(wp, rex.line, - (colnr_T)(rex.input - rex.line)); + + // getvvcol() flushes rex.line, need to get it again + rex.line = reg_getline(rex.lnum); + rex.input = rex.line + col; + + unsigned int cols_u = win_linetabsize(wp, rex.line, col); assert(cols_u <= MAXCOL); colnr_T cols = (colnr_T)cols_u; if (cols < start || cols > end - (*p_sel == 'e')) { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index c8092c3503..0a1f388456 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -75,6 +75,7 @@ #include "nvim/cursor.h" #include "nvim/cursor_shape.h" #include "nvim/decoration.h" +#include "nvim/decoration_provider.h" #include "nvim/diff.h" #include "nvim/edit.h" #include "nvim/eval.h" @@ -126,8 +127,6 @@ #define MB_FILLER_CHAR '<' /* character used when a double-width character * doesn't fit. */ -typedef kvec_withinit_t(DecorProvider *, 4) Providers; - // temporary buffer for rendering a single screenline, so it can be // compared with previous contents to calculate smallest delta. // Per-cell attributes @@ -168,36 +167,6 @@ static bool resizing = false; static char *provider_err = NULL; -static bool provider_invoke(NS ns_id, const char *name, LuaRef ref, Array args, bool default_true) -{ - Error err = ERROR_INIT; - - textlock++; - provider_active = true; - Object ret = nlua_call_ref(ref, name, args, true, &err); - provider_active = false; - textlock--; - - if (!ERROR_SET(&err) - && api_object_to_bool(ret, "provider %s retval", default_true, &err)) { - return true; - } - - if (ERROR_SET(&err)) { - const char *ns_name = describe_ns(ns_id); - ELOG("error in provider %s:%s: %s", ns_name, name, err.msg); - bool verbose_errs = true; // TODO(bfredl): - if (verbose_errs && provider_err == NULL) { - static char errbuf[IOSIZE]; - snprintf(errbuf, sizeof errbuf, "%s: %s", ns_name, err.msg); - provider_err = xstrdup(errbuf); - } - } - - api_free_object(ret); - return false; -} - /// Redraw a window later, with update_screen(type). /// /// Set must_redraw only if not already set to a higher value. @@ -501,28 +470,8 @@ int update_screen(int type) ui_comp_set_screen_valid(true); - Providers providers; - kvi_init(providers); - for (size_t i = 0; i < kv_size(decor_providers); i++) { - DecorProvider *p = &kv_A(decor_providers, i); - if (!p->active) { - continue; - } - - bool active; - if (p->redraw_start != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 2); - args.items[0] = INTEGER_OBJ(display_tick); - args.items[1] = INTEGER_OBJ(type); - active = provider_invoke(p->ns_id, "start", p->redraw_start, args, true); - } else { - active = true; - } - - if (active) { - kvi_push(providers, p); - } - } + DecorProviders providers; + decor_providers_start(&providers, type, &provider_err); // "start" callback could have changed highlights for global elements if (win_check_ns_hl(NULL)) { @@ -591,14 +540,7 @@ int update_screen(int type) } if (buf->b_mod_tick_decor < display_tick) { - for (size_t i = 0; i < kv_size(providers); i++) { - DecorProvider *p = kv_A(providers, i); - if (p && p->redraw_buf != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 1); - args.items[0] = BUFFER_OBJ(buf->handle); - provider_invoke(p->ns_id, "buf", p->redraw_buf, args, true); - } - } + decor_providers_invoke_buf(buf, &providers, &provider_err); buf->b_mod_tick_decor = display_tick; } } @@ -668,18 +610,7 @@ int update_screen(int type) } did_intro = true; - for (size_t i = 0; i < kv_size(providers); i++) { - DecorProvider *p = kv_A(providers, i); - if (!p->active) { - continue; - } - - if (p->redraw_end != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 1); - args.items[0] = INTEGER_OBJ(display_tick); - provider_invoke(p->ns_id, "end", p->redraw_end, args, true); - } - } + decor_providers_invoke_end(&providers, &provider_err); kvi_destroy(providers); @@ -766,7 +697,7 @@ bool win_cursorline_standout(const win_T *wp) * mid: from mid_start to mid_end (update inversion or changed text) * bot: from bot_start to last row (when scrolled up) */ -static void win_update(win_T *wp, Providers *providers) +static void win_update(win_T *wp, DecorProviders *providers) { buf_T *buf = wp->w_buffer; int type; @@ -1377,30 +1308,8 @@ static void win_update(win_T *wp, Providers *providers) decor_redraw_reset(buf, &decor_state); - Providers line_providers; - kvi_init(line_providers); - - linenr_T knownmax = ((wp->w_valid & VALID_BOTLINE) - ? wp->w_botline - : (wp->w_topline + wp->w_height_inner)); - - for (size_t k = 0; k < kv_size(*providers); k++) { - DecorProvider *p = kv_A(*providers, k); - if (p && p->redraw_win != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 4); - args.items[0] = WINDOW_OBJ(wp->handle); - args.items[1] = BUFFER_OBJ(buf->handle); - // TODO(bfredl): we are not using this, but should be first drawn line? - args.items[2] = INTEGER_OBJ(wp->w_topline-1); - args.items[3] = INTEGER_OBJ(knownmax); - if (provider_invoke(p->ns_id, "win", p->redraw_win, args, true)) { - kvi_push(line_providers, p); - } - } - } - - win_check_ns_hl(wp); - + DecorProviders line_providers; + decor_providers_invoke_win(wp, providers, &line_providers, &provider_err); for (;;) { /* stop updating when reached the end of the window (check for _past_ @@ -2028,6 +1937,17 @@ static size_t fill_foldcolumn(char_u *p, win_T *wp, foldinfo_T foldinfo, linenr_ return MAX(char_counter + (fdc-i), (size_t)fdc); } +static inline void provider_err_virt_text(linenr_T lnum, char *err) +{ + Decoration err_decor = DECORATION_INIT; + int hl_err = syn_check_group(S_LEN("ErrorMsg")); + kv_push(err_decor.virt_text, + ((VirtTextChunk){ .text = provider_err, + .hl_id = hl_err })); + err_decor.virt_text_width = mb_string2cells((char_u *)err); + decor_add_ephemeral(lnum-1, 0, lnum-1, 0, &err_decor); +} + /// Display line "lnum" of window 'wp' on the screen. /// wp->w_virtcol needs to be valid. /// @@ -2043,7 +1963,7 @@ static size_t fill_foldcolumn(char_u *p, win_T *wp, foldinfo_T foldinfo, linenr_ /// /// @return the number of last row the line occupies. static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, - bool number_only, foldinfo_T foldinfo, Providers *providers) + bool number_only, foldinfo_T foldinfo, DecorProviders *providers) { int c = 0; // init for GCC long vcol = 0; // virtual column (for tabs) @@ -2231,34 +2151,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc has_decor = decor_redraw_line(buf, lnum-1, &decor_state); - for (size_t k = 0; k < kv_size(*providers); k++) { - DecorProvider *p = kv_A(*providers, k); - if (p && p->redraw_line != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 3); - args.items[0] = WINDOW_OBJ(wp->handle); - args.items[1] = BUFFER_OBJ(buf->handle); - args.items[2] = INTEGER_OBJ(lnum-1); - if (provider_invoke(p->ns_id, "line", p->redraw_line, args, true)) { - has_decor = true; - } else { - // return 'false' or error: skip rest of this window - kv_A(*providers, k) = NULL; - } - - win_check_ns_hl(wp); - } - } + providers_invoke_line(wp, providers, lnum-1, &has_decor, &provider_err); if (provider_err) { - Decoration err_decor = DECORATION_INIT; - int hl_err = syn_check_group(S_LEN("ErrorMsg")); - kv_push(err_decor.virt_text, - ((VirtTextChunk){ .text = provider_err, - .hl_id = hl_err })); - err_decor.virt_text_width = mb_string2cells((char_u *)provider_err); - decor_add_ephemeral(lnum-1, 0, lnum-1, 0, &err_decor); - provider_err = NULL; + provider_err_virt_text(lnum, provider_err); has_decor = true; + provider_err = NULL; } if (has_decor) { diff --git a/src/nvim/testdir/test_regexp_latin.vim b/src/nvim/testdir/test_regexp_latin.vim index a92f7e1192..a0f5ebfb9f 100644 --- a/src/nvim/testdir/test_regexp_latin.vim +++ b/src/nvim/testdir/test_regexp_latin.vim @@ -795,4 +795,20 @@ func Test_using_mark_position() bwipe! endfunc +func Test_using_visual_position() + " this was using freed memory + new + exe "norm 0o\<Esc>\<C-V>k\<C-X>o0" + /\%V + bwipe! +endfunc + +func Test_using_invalid_visual_position() + " this was going beyond the end of the line + new + exe "norm 0o000\<Esc>0\<C-V>$s0" + /\%V + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 1ad82b7290..79a6b9ed0e 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1475,8 +1475,8 @@ static void tui_guess_size(UI *ui) // 1 - look for non-default 'columns' and 'lines' options during startup if (data->is_starting && (Columns != DFLT_COLS || Rows != DFLT_ROWS)) { did_user_set_dimensions = true; - assert(Columns >= INT_MIN && Columns <= INT_MAX); - assert(Rows >= INT_MIN && Rows <= INT_MAX); + assert(Columns >= 0); + assert(Rows >= 0); width = Columns; height = Rows; goto end; |