fix(api/nvim_win_call): share common win_execute logic

We have to be sure that the bugs fixed in the previous patches also apply to
nvim_win_call.

Checking v8.1.2124 and v8.2.4026 is especially important as these patches were
only applied to win_execute, but nvim_win_call is also affected by the same
bugs. A lot of win_execute's logic can be shared with nvim_win_call, so factor
it out into a common macro to reduce the possibility of this happening again.
This commit is contained in:
Sean Dewar
2022-01-08 12:27:35 +00:00
parent 6820420d3e
commit 452b46fcf7
4 changed files with 97 additions and 23 deletions

View File

@@ -457,12 +457,10 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
try_start();
Object res = OBJECT_INIT;
switchwin_T switchwin;
if (switch_win_noblock(&switchwin, win, tabpage, true) == OK) {
WIN_EXECUTE(win, tabpage, {
Array args = ARRAY_DICT_INIT;
res = nlua_call_ref(fun, NULL, args, true, err);
}
restore_win_noblock(&switchwin, true);
});
try_end(err);
return res;
}

View File

@@ -2181,25 +2181,7 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = NULL;
if (wp != NULL && tp != NULL) {
pos_T curpos = wp->w_cursor;
switchwin_T switchwin;
if (switch_win_noblock(&switchwin, wp, tp, true) == OK) {
check_cursor();
execute_common(argvars, rettv, fptr, 1);
}
restore_win_noblock(&switchwin, true);
// Update the status line if the cursor moved.
if (win_valid(wp) && !equalpos(curpos, wp->w_cursor)) {
wp->w_redr_status = true;
}
// In case the command moved the cursor or changed the Visual area,
// check it is valid.
check_cursor();
if (VIsual_active) {
check_pos(curbuf, &VIsual);
}
WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, fptr, 1));
}
}

View File

@@ -4,6 +4,7 @@
#include <stdbool.h>
#include "nvim/buffer_defs.h"
#include "nvim/mark.h"
// Values for file_name_in_line()
#define FNAME_MESS 1 // give error message
@@ -40,6 +41,30 @@ typedef struct {
bool sw_visual_active;
} switchwin_T;
/// Execute a block of code in the context of window `wp` in tabpage `tp`.
/// Ensures the status line is redrawn and cursor position is valid if it is moved.
#define WIN_EXECUTE(wp, tp, block) \
do { \
win_T *const wp_ = (wp); \
const pos_T curpos_ = wp_->w_cursor; \
switchwin_T switchwin_; \
if (switch_win_noblock(&switchwin_, wp_, (tp), true) == OK) { \
check_cursor(); \
block; \
} \
restore_win_noblock(&switchwin_, true); \
/* Update the status line if the cursor moved. */ \
if (win_valid(wp_) && !equalpos(curpos_, wp_->w_cursor)) { \
wp_->w_redr_status = true; \
} \
/* In case the command moved the cursor or changed the Visual area, */ \
/* check it is valid. */ \
check_cursor(); \
if (VIsual_active) { \
check_pos(curbuf, &VIsual); \
} \
} while (false)
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "window.h.generated.h"
#endif