mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #16976 from seandewar/vim-8.2.4018
vim-patch:8.2.{4018,4026,4028} & `nvim_win_call` fixes
This commit is contained in:
commit
9efdd927ff
@ -989,18 +989,16 @@ Object copy_object(Object obj)
|
|||||||
static void set_option_value_for(char *key, int numval, char *stringval, int opt_flags,
|
static void set_option_value_for(char *key, int numval, char *stringval, int opt_flags,
|
||||||
int opt_type, void *from, Error *err)
|
int opt_type, void *from, Error *err)
|
||||||
{
|
{
|
||||||
win_T *save_curwin = NULL;
|
switchwin_T switchwin;
|
||||||
tabpage_T *save_curtab = NULL;
|
|
||||||
aco_save_T aco;
|
aco_save_T aco;
|
||||||
|
|
||||||
try_start();
|
try_start();
|
||||||
switch (opt_type)
|
switch (opt_type)
|
||||||
{
|
{
|
||||||
case SREQ_WIN:
|
case SREQ_WIN:
|
||||||
if (switch_win_noblock(&save_curwin, &save_curtab, (win_T *)from,
|
if (switch_win_noblock(&switchwin, (win_T *)from, win_find_tabpage((win_T *)from), true)
|
||||||
win_find_tabpage((win_T *)from), true)
|
|
||||||
== FAIL) {
|
== FAIL) {
|
||||||
restore_win_noblock(save_curwin, save_curtab, true);
|
restore_win_noblock(&switchwin, true);
|
||||||
if (try_end(err)) {
|
if (try_end(err)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1010,7 +1008,7 @@ static void set_option_value_for(char *key, int numval, char *stringval, int opt
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
set_option_value_err(key, numval, stringval, opt_flags, err);
|
set_option_value_err(key, numval, stringval, opt_flags, err);
|
||||||
restore_win_noblock(save_curwin, save_curtab, true);
|
restore_win_noblock(&switchwin, true);
|
||||||
break;
|
break;
|
||||||
case SREQ_BUF:
|
case SREQ_BUF:
|
||||||
aucmd_prepbuf(&aco, (buf_T *)from);
|
aucmd_prepbuf(&aco, (buf_T *)from);
|
||||||
|
@ -455,17 +455,12 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
|
|||||||
}
|
}
|
||||||
tabpage_T *tabpage = win_find_tabpage(win);
|
tabpage_T *tabpage = win_find_tabpage(win);
|
||||||
|
|
||||||
win_T *save_curwin;
|
|
||||||
tabpage_T *save_curtab;
|
|
||||||
|
|
||||||
try_start();
|
try_start();
|
||||||
Object res = OBJECT_INIT;
|
Object res = OBJECT_INIT;
|
||||||
if (switch_win_noblock(&save_curwin, &save_curtab, win, tabpage, true) ==
|
WIN_EXECUTE(win, tabpage, {
|
||||||
OK) {
|
|
||||||
Array args = ARRAY_DICT_INIT;
|
Array args = ARRAY_DICT_INIT;
|
||||||
res = nlua_call_ref(fun, NULL, args, true, err);
|
res = nlua_call_ref(fun, NULL, args, true, err);
|
||||||
}
|
});
|
||||||
restore_win_noblock(save_curwin, save_curtab, true);
|
|
||||||
try_end(err);
|
try_end(err);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1069,8 +1069,6 @@ void ex_doautoall(exarg_T *eap)
|
|||||||
do_modelines(0);
|
do_modelines(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_cursor(); // just in case lines got deleted
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check *argp for <nomodeline>. When it is present return false, otherwise
|
/// Check *argp for <nomodeline>. When it is present return false, otherwise
|
||||||
@ -1171,6 +1169,10 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
|
|||||||
curbuf = buf;
|
curbuf = buf;
|
||||||
aco->new_curwin_handle = curwin->handle;
|
aco->new_curwin_handle = curwin->handle;
|
||||||
set_bufref(&aco->new_curbuf, curbuf);
|
set_bufref(&aco->new_curbuf, curbuf);
|
||||||
|
|
||||||
|
// disable the Visual area, the position may be invalid in another buffer
|
||||||
|
aco->save_VIsual_active = VIsual_active;
|
||||||
|
VIsual_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cleanup after executing autocommands for a (hidden) buffer.
|
/// Cleanup after executing autocommands for a (hidden) buffer.
|
||||||
@ -1267,6 +1269,12 @@ win_found:
|
|||||||
check_cursor();
|
check_cursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_cursor(); // just in case lines got deleted
|
||||||
|
VIsual_active = aco->save_VIsual_active;
|
||||||
|
if (VIsual_active) {
|
||||||
|
check_pos(curbuf, &VIsual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute autocommands for "event" and file name "fname".
|
/// Execute autocommands for "event" and file name "fname".
|
||||||
|
@ -14,6 +14,7 @@ typedef struct {
|
|||||||
handle_T save_prevwin_handle; ///< ID of saved prevwin
|
handle_T save_prevwin_handle; ///< ID of saved prevwin
|
||||||
bufref_T new_curbuf; ///< new curbuf
|
bufref_T new_curbuf; ///< new curbuf
|
||||||
char_u *globaldir; ///< saved value of globaldir
|
char_u *globaldir; ///< saved value of globaldir
|
||||||
|
bool save_VIsual_active; ///< saved VIsual_active
|
||||||
} aco_save_T;
|
} aco_save_T;
|
||||||
|
|
||||||
typedef struct AutoCmd {
|
typedef struct AutoCmd {
|
||||||
|
@ -6963,10 +6963,9 @@ win_T *find_tabwin(typval_T *wvp, typval_T *tvp)
|
|||||||
/// @param off 1 for gettabwinvar()
|
/// @param off 1 for gettabwinvar()
|
||||||
void getwinvar(typval_T *argvars, typval_T *rettv, int off)
|
void getwinvar(typval_T *argvars, typval_T *rettv, int off)
|
||||||
{
|
{
|
||||||
win_T *win, *oldcurwin;
|
win_T *win;
|
||||||
dictitem_T *v;
|
dictitem_T *v;
|
||||||
tabpage_T *tp = NULL;
|
tabpage_T *tp = NULL;
|
||||||
tabpage_T *oldtabpage = NULL;
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
if (off == 1) {
|
if (off == 1) {
|
||||||
@ -6986,8 +6985,8 @@ void getwinvar(typval_T *argvars, typval_T *rettv, int off)
|
|||||||
// otherwise the window is not valid. Only do this when needed,
|
// otherwise the window is not valid. Only do this when needed,
|
||||||
// autocommands get blocked.
|
// autocommands get blocked.
|
||||||
bool need_switch_win = tp != curtab || win != curwin;
|
bool need_switch_win = tp != curtab || win != curwin;
|
||||||
if (!need_switch_win
|
switchwin_T switchwin;
|
||||||
|| switch_win(&oldcurwin, &oldtabpage, win, tp, true) == OK) {
|
if (!need_switch_win || switch_win(&switchwin, win, tp, true) == OK) {
|
||||||
if (*varname == '&') {
|
if (*varname == '&') {
|
||||||
if (varname[1] == NUL) {
|
if (varname[1] == NUL) {
|
||||||
// get all window-local options in a dict
|
// get all window-local options in a dict
|
||||||
@ -7015,7 +7014,7 @@ void getwinvar(typval_T *argvars, typval_T *rettv, int off)
|
|||||||
|
|
||||||
if (need_switch_win) {
|
if (need_switch_win) {
|
||||||
// restore previous notion of curwin
|
// restore previous notion of curwin
|
||||||
restore_win(oldcurwin, oldtabpage, true);
|
restore_win(&switchwin, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emsg_off--;
|
emsg_off--;
|
||||||
@ -7517,11 +7516,9 @@ void setwinvar(typval_T *argvars, typval_T *rettv, int off)
|
|||||||
typval_T *varp = &argvars[off + 2];
|
typval_T *varp = &argvars[off + 2];
|
||||||
|
|
||||||
if (win != NULL && varname != NULL && varp != NULL) {
|
if (win != NULL && varname != NULL && varp != NULL) {
|
||||||
win_T *save_curwin;
|
|
||||||
tabpage_T *save_curtab;
|
|
||||||
bool need_switch_win = tp != curtab || win != curwin;
|
bool need_switch_win = tp != curtab || win != curwin;
|
||||||
if (!need_switch_win
|
switchwin_T switchwin;
|
||||||
|| switch_win(&save_curwin, &save_curtab, win, tp, true) == OK) {
|
if (!need_switch_win || switch_win(&switchwin, win, tp, true) == OK) {
|
||||||
if (*varname == '&') {
|
if (*varname == '&') {
|
||||||
long numval;
|
long numval;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
@ -7543,7 +7540,7 @@ void setwinvar(typval_T *argvars, typval_T *rettv, int off)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (need_switch_win) {
|
if (need_switch_win) {
|
||||||
restore_win(save_curwin, save_curtab, true);
|
restore_win(&switchwin, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2176,25 +2176,12 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
{
|
{
|
||||||
tabpage_T *tp;
|
tabpage_T *tp;
|
||||||
win_T *wp = win_id2wp_tp(argvars, &tp);
|
win_T *wp = win_id2wp_tp(argvars, &tp);
|
||||||
win_T *save_curwin;
|
|
||||||
tabpage_T *save_curtab;
|
|
||||||
// Return an empty string if something fails.
|
// Return an empty string if something fails.
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
rettv->vval.v_string = NULL;
|
rettv->vval.v_string = NULL;
|
||||||
|
|
||||||
if (wp != NULL && tp != NULL) {
|
if (wp != NULL && tp != NULL) {
|
||||||
pos_T curpos = wp->w_cursor;
|
WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, fptr, 1));
|
||||||
if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, true) ==
|
|
||||||
OK) {
|
|
||||||
check_cursor();
|
|
||||||
execute_common(argvars, rettv, fptr, 1);
|
|
||||||
}
|
|
||||||
restore_win_noblock(save_curwin, save_curtab, true);
|
|
||||||
|
|
||||||
// Update the status line if the cursor moved.
|
|
||||||
if (win_valid(wp) && !equalpos(curpos, wp->w_cursor)) {
|
|
||||||
wp->w_redr_status = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4031,8 +4018,6 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
*/
|
*/
|
||||||
static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
win_T *oldcurwin;
|
|
||||||
tabpage_T *oldtabpage;
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
@ -4046,7 +4031,8 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
win_T *const window = tp == curtab || tp->tp_firstwin == NULL
|
win_T *const window = tp == curtab || tp->tp_firstwin == NULL
|
||||||
? firstwin
|
? firstwin
|
||||||
: tp->tp_firstwin;
|
: tp->tp_firstwin;
|
||||||
if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) {
|
switchwin_T switchwin;
|
||||||
|
if (switch_win(&switchwin, window, tp, true) == OK) {
|
||||||
// look up the variable
|
// look up the variable
|
||||||
// Let gettabvar({nr}, "") return the "t:" dictionary.
|
// Let gettabvar({nr}, "") return the "t:" dictionary.
|
||||||
const dictitem_T *const v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't',
|
const dictitem_T *const v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't',
|
||||||
@ -4059,7 +4045,7 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore previous notion of curwin
|
// restore previous notion of curwin
|
||||||
restore_win(oldcurwin, oldtabpage, true);
|
restore_win(&switchwin, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!done && argvars[2].v_type != VAR_UNKNOWN) {
|
if (!done && argvars[2].v_type != VAR_UNKNOWN) {
|
||||||
@ -5881,18 +5867,16 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
|
|
||||||
if (argvars[1].v_type != VAR_UNKNOWN) {
|
if (argvars[1].v_type != VAR_UNKNOWN) {
|
||||||
tabpage_T *tp;
|
tabpage_T *tp;
|
||||||
win_T *save_curwin;
|
|
||||||
tabpage_T *save_curtab;
|
|
||||||
|
|
||||||
// use window specified in the second argument
|
// use window specified in the second argument
|
||||||
win_T *wp = win_id2wp_tp(&argvars[1], &tp);
|
win_T *wp = win_id2wp_tp(&argvars[1], &tp);
|
||||||
if (wp != NULL && tp != NULL) {
|
if (wp != NULL && tp != NULL) {
|
||||||
if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, true)
|
switchwin_T switchwin;
|
||||||
== OK) {
|
if (switch_win_noblock(&switchwin, wp, tp, true) == OK) {
|
||||||
check_cursor();
|
check_cursor();
|
||||||
fp = var2fpos(&argvars[0], true, &fnum);
|
fp = var2fpos(&argvars[0], true, &fnum);
|
||||||
}
|
}
|
||||||
restore_win_noblock(save_curwin, save_curtab, true);
|
restore_win_noblock(&switchwin, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// use current window
|
// use current window
|
||||||
|
@ -346,10 +346,10 @@ void update_topline(win_T *wp)
|
|||||||
*/
|
*/
|
||||||
void update_topline_win(win_T *win)
|
void update_topline_win(win_T *win)
|
||||||
{
|
{
|
||||||
win_T *save_curwin;
|
switchwin_T switchwin;
|
||||||
switch_win(&save_curwin, NULL, win, NULL, true);
|
switch_win(&switchwin, win, NULL, true);
|
||||||
update_topline(curwin);
|
update_topline(curwin);
|
||||||
restore_win(save_curwin, NULL, true);
|
restore_win(&switchwin, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2543,6 +2543,16 @@ func Test_close_autocmd_tab()
|
|||||||
%bwipe!
|
%bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_Visual_doautoall_redraw()
|
||||||
|
call setline(1, ['a', 'b'])
|
||||||
|
new
|
||||||
|
wincmd p
|
||||||
|
call feedkeys("G\<C-V>", 'txn')
|
||||||
|
autocmd User Explode ++once redraw
|
||||||
|
doautoall User Explode
|
||||||
|
%bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_autocmd_closes_window()
|
func Test_autocmd_closes_window()
|
||||||
au BufNew,BufWinLeave * e %e
|
au BufNew,BufWinLeave * e %e
|
||||||
file yyy
|
file yyy
|
||||||
|
@ -147,3 +147,30 @@ func Test_win_execute_other_tab()
|
|||||||
tabclose
|
tabclose
|
||||||
unlet xyz
|
unlet xyz
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_win_execute_visual_redraw()
|
||||||
|
call setline(1, ['a', 'b', 'c'])
|
||||||
|
new
|
||||||
|
wincmd p
|
||||||
|
" start Visual in current window, redraw in other window with fewer lines
|
||||||
|
call feedkeys("G\<C-V>", 'txn')
|
||||||
|
call win_execute(winnr('#')->win_getid(), 'redraw')
|
||||||
|
call feedkeys("\<Esc>", 'txn')
|
||||||
|
bwipe!
|
||||||
|
bwipe!
|
||||||
|
|
||||||
|
enew
|
||||||
|
new
|
||||||
|
call setline(1, ['a', 'b', 'c'])
|
||||||
|
let winid = win_getid()
|
||||||
|
wincmd p
|
||||||
|
" start Visual in current window, extend it in other window with more lines
|
||||||
|
call feedkeys("\<C-V>", 'txn')
|
||||||
|
call win_execute(winid, 'call feedkeys("G\<C-V>", ''txn'')')
|
||||||
|
redraw
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@ -577,18 +577,19 @@ static void cmd_with_count(char *cmd, char_u *bufp, size_t bufsize, int64_t Pren
|
|||||||
|
|
||||||
void win_set_buf(Window window, Buffer buffer, bool noautocmd, Error *err)
|
void win_set_buf(Window window, Buffer buffer, bool noautocmd, Error *err)
|
||||||
{
|
{
|
||||||
win_T *win = find_window_by_handle(window, err), *save_curwin = curwin;
|
win_T *win = find_window_by_handle(window, err);
|
||||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||||
tabpage_T *tab = win_find_tabpage(win), *save_curtab = curtab;
|
tabpage_T *tab = win_find_tabpage(win);
|
||||||
|
|
||||||
if (!win || !buf) {
|
if (!win || !buf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noautocmd) {
|
if (noautocmd) {
|
||||||
block_autocmds();
|
block_autocmds();
|
||||||
}
|
}
|
||||||
if (switch_win_noblock(&save_curwin, &save_curtab, win, tab, false) == FAIL) {
|
|
||||||
|
switchwin_T switchwin;
|
||||||
|
if (switch_win_noblock(&switchwin, win, tab, false) == FAIL) {
|
||||||
api_set_error(err,
|
api_set_error(err,
|
||||||
kErrorTypeException,
|
kErrorTypeException,
|
||||||
"Failed to switch to window %d",
|
"Failed to switch to window %d",
|
||||||
@ -608,7 +609,7 @@ void win_set_buf(Window window, Buffer buffer, bool noautocmd, Error *err)
|
|||||||
// So do it now.
|
// So do it now.
|
||||||
validate_cursor();
|
validate_cursor();
|
||||||
|
|
||||||
restore_win_noblock(save_curwin, save_curtab, false);
|
restore_win_noblock(&switchwin, false);
|
||||||
if (noautocmd) {
|
if (noautocmd) {
|
||||||
unblock_autocmds();
|
unblock_autocmds();
|
||||||
}
|
}
|
||||||
@ -6631,20 +6632,27 @@ static win_T *get_snapshot_focus(int idx)
|
|||||||
/// triggered, another tabpage access is limited.
|
/// triggered, another tabpage access is limited.
|
||||||
///
|
///
|
||||||
/// @return FAIL if switching to "win" failed.
|
/// @return FAIL if switching to "win" failed.
|
||||||
int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp,
|
int switch_win(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_display)
|
||||||
bool no_display)
|
|
||||||
{
|
{
|
||||||
block_autocmds();
|
block_autocmds();
|
||||||
return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display);
|
return switch_win_noblock(switchwin, win, tp, no_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
// As switch_win() but without blocking autocommands.
|
// As switch_win() but without blocking autocommands.
|
||||||
int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp,
|
int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_display)
|
||||||
bool no_display)
|
|
||||||
{
|
{
|
||||||
*save_curwin = curwin;
|
memset(switchwin, 0, sizeof(switchwin_T));
|
||||||
|
switchwin->sw_curwin = curwin;
|
||||||
|
if (win == curwin) {
|
||||||
|
switchwin->sw_same_win = true;
|
||||||
|
} else {
|
||||||
|
// Disable Visual selection, because redrawing may fail.
|
||||||
|
switchwin->sw_visual_active = VIsual_active;
|
||||||
|
VIsual_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (tp != NULL) {
|
if (tp != NULL) {
|
||||||
*save_curtab = curtab;
|
switchwin->sw_curtab = curtab;
|
||||||
if (no_display) {
|
if (no_display) {
|
||||||
curtab->tp_firstwin = firstwin;
|
curtab->tp_firstwin = firstwin;
|
||||||
curtab->tp_lastwin = lastwin;
|
curtab->tp_lastwin = lastwin;
|
||||||
@ -6666,28 +6674,33 @@ int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab, win_T *win,
|
|||||||
// Restore current tabpage and window saved by switch_win(), if still valid.
|
// Restore current tabpage and window saved by switch_win(), if still valid.
|
||||||
// When "no_display" is true the display won't be affected, no redraw is
|
// When "no_display" is true the display won't be affected, no redraw is
|
||||||
// triggered.
|
// triggered.
|
||||||
void restore_win(win_T *save_curwin, tabpage_T *save_curtab, bool no_display)
|
void restore_win(switchwin_T *switchwin, bool no_display)
|
||||||
{
|
{
|
||||||
restore_win_noblock(save_curwin, save_curtab, no_display);
|
restore_win_noblock(switchwin, no_display);
|
||||||
unblock_autocmds();
|
unblock_autocmds();
|
||||||
}
|
}
|
||||||
|
|
||||||
// As restore_win() but without unblocking autocommands.
|
// As restore_win() but without unblocking autocommands.
|
||||||
void restore_win_noblock(win_T *save_curwin, tabpage_T *save_curtab, bool no_display)
|
void restore_win_noblock(switchwin_T *switchwin, bool no_display)
|
||||||
{
|
{
|
||||||
if (save_curtab != NULL && valid_tabpage(save_curtab)) {
|
if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab)) {
|
||||||
if (no_display) {
|
if (no_display) {
|
||||||
curtab->tp_firstwin = firstwin;
|
curtab->tp_firstwin = firstwin;
|
||||||
curtab->tp_lastwin = lastwin;
|
curtab->tp_lastwin = lastwin;
|
||||||
curtab = save_curtab;
|
curtab = switchwin->sw_curtab;
|
||||||
firstwin = curtab->tp_firstwin;
|
firstwin = curtab->tp_firstwin;
|
||||||
lastwin = curtab->tp_lastwin;
|
lastwin = curtab->tp_lastwin;
|
||||||
} else {
|
} else {
|
||||||
goto_tabpage_tp(save_curtab, false, false);
|
goto_tabpage_tp(switchwin->sw_curtab, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (win_valid(save_curwin)) {
|
|
||||||
curwin = save_curwin;
|
if (!switchwin->sw_same_win) {
|
||||||
|
VIsual_active = switchwin->sw_visual_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (win_valid(switchwin->sw_curwin)) {
|
||||||
|
curwin = switchwin->sw_curwin;
|
||||||
curbuf = curwin->w_buffer;
|
curbuf = curwin->w_buffer;
|
||||||
}
|
}
|
||||||
// If called by win_execute() and executing the command changed the
|
// If called by win_execute() and executing the command changed the
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "nvim/buffer_defs.h"
|
#include "nvim/buffer_defs.h"
|
||||||
|
#include "nvim/mark.h"
|
||||||
|
|
||||||
// Values for file_name_in_line()
|
// Values for file_name_in_line()
|
||||||
#define FNAME_MESS 1 // give error message
|
#define FNAME_MESS 1 // give error message
|
||||||
@ -32,6 +33,38 @@
|
|||||||
#define MIN_COLUMNS 12 // minimal columns for screen
|
#define MIN_COLUMNS 12 // minimal columns for screen
|
||||||
#define MIN_LINES 2 // minimal lines for screen
|
#define MIN_LINES 2 // minimal lines for screen
|
||||||
|
|
||||||
|
/// Structure used by switch_win() to pass values to restore_win()
|
||||||
|
typedef struct {
|
||||||
|
win_T *sw_curwin;
|
||||||
|
tabpage_T *sw_curtab;
|
||||||
|
bool sw_same_win; ///< VIsual_active was not reset
|
||||||
|
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
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "window.h.generated.h"
|
# include "window.h.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -2406,6 +2406,17 @@ describe('lua stdlib', function()
|
|||||||
eq(buf1, meths.get_current_buf())
|
eq(buf1, meths.get_current_buf())
|
||||||
eq(buf2, val)
|
eq(buf2, val)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('does not cause ml_get errors with invalid visual selection', function()
|
||||||
|
-- Should be fixed by vim-patch:8.2.4028.
|
||||||
|
exec_lua [[
|
||||||
|
local a = vim.api
|
||||||
|
local t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end
|
||||||
|
a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"})
|
||||||
|
a.nvim_feedkeys(t "G<C-V>", "txn", false)
|
||||||
|
a.nvim_buf_call(a.nvim_create_buf(false, true), function() vim.cmd "redraw" end)
|
||||||
|
]]
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('vim.api.nvim_win_call', function()
|
describe('vim.api.nvim_win_call', function()
|
||||||
@ -2434,6 +2445,75 @@ describe('lua stdlib', function()
|
|||||||
eq(win1, meths.get_current_win())
|
eq(win1, meths.get_current_win())
|
||||||
eq(win2, val)
|
eq(win2, val)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('does not cause ml_get errors with invalid visual selection', function()
|
||||||
|
-- Add lines to the current buffer and make another window looking into an empty buffer.
|
||||||
|
exec_lua [[
|
||||||
|
_G.a = vim.api
|
||||||
|
_G.t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end
|
||||||
|
_G.win_lines = a.nvim_get_current_win()
|
||||||
|
vim.cmd "new"
|
||||||
|
_G.win_empty = a.nvim_get_current_win()
|
||||||
|
a.nvim_set_current_win(win_lines)
|
||||||
|
a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"})
|
||||||
|
]]
|
||||||
|
|
||||||
|
-- Start Visual in current window, redraw in other window with fewer lines.
|
||||||
|
-- Should be fixed by vim-patch:8.2.4018.
|
||||||
|
exec_lua [[
|
||||||
|
a.nvim_feedkeys(t "G<C-V>", "txn", false)
|
||||||
|
a.nvim_win_call(win_empty, function() vim.cmd "redraw" end)
|
||||||
|
]]
|
||||||
|
|
||||||
|
-- Start Visual in current window, extend it in other window with more lines.
|
||||||
|
-- Fixed for win_execute by vim-patch:8.2.4026, but nvim_win_call should also not be affected.
|
||||||
|
exec_lua [[
|
||||||
|
a.nvim_feedkeys(t "<Esc>gg", "txn", false)
|
||||||
|
a.nvim_set_current_win(win_empty)
|
||||||
|
a.nvim_feedkeys(t "gg<C-V>", "txn", false)
|
||||||
|
a.nvim_win_call(win_lines, function() a.nvim_feedkeys(t "G<C-V>", "txn", false) end)
|
||||||
|
vim.cmd "redraw"
|
||||||
|
]]
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('updates ruler if cursor moved', function()
|
||||||
|
-- Fixed for win_execute in vim-patch:8.1.2124, but should've applied to nvim_win_call too!
|
||||||
|
local screen = Screen.new(30, 5)
|
||||||
|
screen:set_default_attr_ids {
|
||||||
|
[1] = {reverse = true},
|
||||||
|
[2] = {bold = true, reverse = true},
|
||||||
|
}
|
||||||
|
screen:attach()
|
||||||
|
exec_lua [[
|
||||||
|
_G.a = vim.api
|
||||||
|
vim.opt.ruler = true
|
||||||
|
local lines = {}
|
||||||
|
for i = 0, 499 do lines[#lines + 1] = tostring(i) end
|
||||||
|
a.nvim_buf_set_lines(0, 0, -1, true, lines)
|
||||||
|
a.nvim_win_set_cursor(0, {20, 0})
|
||||||
|
vim.cmd "split"
|
||||||
|
_G.win = a.nvim_get_current_win()
|
||||||
|
vim.cmd "wincmd w | redraw"
|
||||||
|
]]
|
||||||
|
screen:expect [[
|
||||||
|
19 |
|
||||||
|
{1:[No Name] [+] 20,1 3%}|
|
||||||
|
^19 |
|
||||||
|
{2:[No Name] [+] 20,1 3%}|
|
||||||
|
|
|
||||||
|
]]
|
||||||
|
exec_lua [[
|
||||||
|
a.nvim_win_call(win, function() a.nvim_win_set_cursor(0, {100, 0}) end)
|
||||||
|
vim.cmd "redraw"
|
||||||
|
]]
|
||||||
|
screen:expect [[
|
||||||
|
99 |
|
||||||
|
{1:[No Name] [+] 100,1 19%}|
|
||||||
|
^19 |
|
||||||
|
{2:[No Name] [+] 20,1 3%}|
|
||||||
|
|
|
||||||
|
]]
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user