aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/eval.c24
-rw-r--r--src/nvim/eval/funcs.c3
-rw-r--r--src/nvim/eval/typval.h5
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/lua/vim.lua11
-rw-r--r--src/nvim/memline.c4
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/os/input.c20
-rw-r--r--src/nvim/screen.c2
-rw-r--r--src/nvim/state.c28
-rw-r--r--src/nvim/terminal.c2
-rw-r--r--src/nvim/testdir/test_cursor_func.vim5
13 files changed, 78 insertions, 32 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 53717229f6..68c7438ea3 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1024,7 +1024,7 @@ static int insert_handle_key(InsertState *s)
break;
case K_EVENT: // some event
- multiqueue_process_events(main_loop.events);
+ state_handle_k_event();
goto check_pum;
case K_COMMAND: // some command
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 6d97310c1c..63d5216cc4 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -5280,14 +5280,10 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack,
if (ht_stack == NULL) {
abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
} else {
- ht_stack_T *newitem = try_malloc(sizeof(ht_stack_T));
- if (newitem == NULL) {
- abort = true;
- } else {
- newitem->ht = &dd->dv_hashtab;
- newitem->prev = *ht_stack;
- *ht_stack = newitem;
- }
+ ht_stack_T *const newitem = xmalloc(sizeof(ht_stack_T));
+ newitem->ht = &dd->dv_hashtab;
+ newitem->prev = *ht_stack;
+ *ht_stack = newitem;
}
QUEUE *w = NULL;
@@ -5308,14 +5304,10 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack,
if (list_stack == NULL) {
abort = set_ref_in_list(ll, copyID, ht_stack);
} else {
- list_stack_T *newitem = try_malloc(sizeof(list_stack_T));
- if (newitem == NULL) {
- abort = true;
- } else {
- newitem->list = ll;
- newitem->prev = *list_stack;
- *list_stack = newitem;
- }
+ list_stack_T *const newitem = xmalloc(sizeof(list_stack_T));
+ newitem->list = ll;
+ newitem->prev = *list_stack;
+ *list_stack = newitem;
}
}
break;
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 8c8e0d568b..60229e1ebc 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -3029,10 +3029,11 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (argvars[0].v_type == VAR_UNKNOWN) {
// getchar(): blocking wait.
+ // TODO(bfredl): deduplicate shared logic with state_enter ?
if (!(char_avail() || using_script() || input_available())) {
(void)os_inchar(NULL, 0, -1, 0, main_loop.events);
if (!multiqueue_empty(main_loop.events)) {
- multiqueue_process_events(main_loop.events);
+ state_handle_k_event();
continue;
}
}
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index 6fcb01aace..531b17cb59 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -341,8 +341,9 @@ struct ufunc {
///< used for s: variables
int uf_refcount; ///< reference count, see func_name_refcount()
funccall_T *uf_scoped; ///< l: local variables for closure
- char_u uf_name[]; ///< Name of function; can start with <SNR>123_
- ///< (<SNR> is K_SPECIAL KS_EXTRA KE_SNR)
+ char_u uf_name[]; ///< Name of function (actual size equals name);
+ ///< can start with <SNR>123_
+ ///< (<SNR> is K_SPECIAL KS_EXTRA KE_SNR)
};
struct partial_S {
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index d470bfb418..5979f4d3a0 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -935,7 +935,7 @@ static int command_line_execute(VimState *state, int key)
if (s->c == K_EVENT || s->c == K_COMMAND) {
if (s->c == K_EVENT) {
- multiqueue_process_events(main_loop.events);
+ state_handle_k_event();
} else {
do_cmdline(NULL, getcmdkeycmd, NULL, DOCMD_NOWAIT);
}
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index e13b9745a8..eb54ff28ee 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -263,8 +263,15 @@ end
-- vim.fn.{func}(...)
vim.fn = setmetatable({}, {
__index = function(t, key)
- local function _fn(...)
- return vim.call(key, ...)
+ local _fn
+ if vim.api[key] ~= nil then
+ _fn = function()
+ error(string.format("Tried to call API function with vim.fn: use vim.api.%s instead", key))
+ end
+ else
+ _fn = function(...)
+ return vim.call(key, ...)
+ end
end
t[key] = _fn
return _fn
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 293a4d01db..34d8eb0ffe 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -3859,8 +3859,8 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype)
/* May resize here so we don't have to do it in both cases below */
if (buf->b_ml.ml_usedchunks + 1 >= buf->b_ml.ml_numchunks) {
buf->b_ml.ml_numchunks = buf->b_ml.ml_numchunks * 3 / 2;
- buf->b_ml.ml_chunksize = (chunksize_T *)
- xrealloc(buf->b_ml.ml_chunksize,
+ buf->b_ml.ml_chunksize = xrealloc(
+ buf->b_ml.ml_chunksize,
sizeof(chunksize_T) * buf->b_ml.ml_numchunks);
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 4d8b11f832..0b4e2e1f23 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -8103,7 +8103,7 @@ static void nv_event(cmdarg_T *cap)
// lists or dicts being used.
may_garbage_collect = false;
bool may_restart = (restart_edit != 0);
- multiqueue_process_events(main_loop.events);
+ state_handle_k_event();
finish_op = false;
if (may_restart) {
// Tricky: if restart_edit was set before the handler we are in ctrl-o mode,
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 9d6518841a..eca245650a 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -159,16 +159,28 @@ bool os_char_avail(void)
return inbuf_poll(0, NULL) == kInputAvail;
}
-// Check for CTRL-C typed by reading all available characters.
+/// Poll for fast events. `got_int` will be set to `true` if CTRL-C was typed.
+///
+/// This invokes a full libuv loop iteration which can be quite costly.
+/// Prefer `line_breakcheck()` if called in a busy inner loop.
+///
+/// Caller must at least check `got_int` before calling this function again.
+/// checking for other low-level input state like `input_available()` might
+/// also be relevant (i e to throttle idle processing when user input is
+/// available)
void os_breakcheck(void)
{
+ if (got_int) {
+ return;
+ }
+
int save_us = updating_screen;
// We do not want screen_resize() to redraw here.
+ // TODO(bfredl): we are already special casing redraw events, is this
+ // hack still needed?
updating_screen++;
- if (!got_int) {
- loop_poll_events(&main_loop, 0);
- }
+ loop_poll_events(&main_loop, 0);
updating_screen = save_us;
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index c15d7f74ea..aa3a7ae7ed 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -2658,7 +2658,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
// already be in use.
xfree(p_extra_free);
p_extra_free = xmalloc(MAX_MCO * fdc + 1);
- n_extra = fill_foldcolumn(p_extra_free, wp, foldinfo, lnum);
+ n_extra = (int)fill_foldcolumn(p_extra_free, wp, foldinfo, lnum);
p_extra_free[n_extra] = NUL;
p_extra = p_extra_free;
c_extra = NUL;
diff --git a/src/nvim/state.c b/src/nvim/state.c
index b195c1d96b..a3c74789d1 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -75,6 +75,34 @@ getkey:
}
}
+/// process events on main_loop, but interrupt if input is available
+///
+/// This should be used to handle K_EVENT in states accepting input
+/// otherwise bursts of events can block break checking indefinitely.
+void state_handle_k_event(void)
+{
+ while (true) {
+ Event event = multiqueue_get(main_loop.events);
+ if (event.handler) {
+ event.handler(event.argv);
+ }
+
+ if (multiqueue_empty(main_loop.events)) {
+ // don't breakcheck before return, caller should return to main-loop
+ // and handle input already.
+ return;
+ }
+
+ // TODO(bfredl): as an further micro-optimization, we could check whether
+ // event.handler already checked input.
+ os_breakcheck();
+ if (input_available() || got_int) {
+ return;
+ }
+ }
+}
+
+
/// Return true if in the current mode we need to use virtual.
bool virtual_active(void)
{
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 642c443318..f6995cddb6 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -457,7 +457,7 @@ static int terminal_execute(VimState *state, int key)
case K_EVENT:
// We cannot let an event free the terminal yet. It is still needed.
s->term->refcount++;
- multiqueue_process_events(main_loop.events);
+ state_handle_k_event();
s->term->refcount--;
if (s->term->buf_handle == 0) {
s->close = true;
diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim
index 2e190911b2..53b7da517e 100644
--- a/src/nvim/testdir/test_cursor_func.vim
+++ b/src/nvim/testdir/test_cursor_func.vim
@@ -92,6 +92,11 @@ func Test_screenpos()
\ 'endcol': wincol + 9}, screenpos(winid, 2, 22))
close
bwipe!
+
+ call assert_equal({'col': 1, 'row': 1, 'endcol': 1, 'curscol': 1}, screenpos(win_getid(), 1, 1))
+ nmenu WinBar.TEST :
+ call assert_equal({'col': 1, 'row': 2, 'endcol': 1, 'curscol': 1}, screenpos(win_getid(), 1, 1))
+ nunmenu WinBar.TEST
endfunc
func Test_screenpos_number()