Problem: ml_get error when win_execute redraws with Visual selection.
Solution: Disable Visual area temporarily. (closes #9479)
*/
void
switch_to_win_for_buf(
- buf_T *buf,
- win_T **save_curwinp,
- tabpage_T **save_curtabp,
- bufref_T *save_curbuf)
+ buf_T *buf,
+ switchwin_T *switchwin,
+ bufref_T *save_curbuf)
{
win_T *wp;
tabpage_T *tp;
if (find_win_for_buf(buf, &wp, &tp) == FAIL)
switch_buffer(save_curbuf, buf);
- else if (switch_win(save_curwinp, save_curtabp, wp, tp, TRUE) == FAIL)
+ else if (switch_win(switchwin, wp, tp, TRUE) == FAIL)
{
- restore_win(*save_curwinp, *save_curtabp, TRUE);
+ restore_win(switchwin, TRUE);
switch_buffer(save_curbuf, buf);
}
}
void
restore_win_for_buf(
- win_T *save_curwin,
- tabpage_T *save_curtab,
- bufref_T *save_curbuf)
+ switchwin_T *switchwin,
+ bufref_T *save_curbuf)
{
if (save_curbuf->br_buf == NULL)
- restore_win(save_curwin, save_curtab, TRUE);
+ restore_win(switchwin, TRUE);
else
restore_buffer(save_curbuf);
}
int id;
tabpage_T *tp;
win_T *wp;
- win_T *save_curwin;
- tabpage_T *save_curtab;
+ switchwin_T switchwin;
if (in_vim9script()
&& (check_for_string_arg(argvars, 0) == FAIL
wp = win_id2wp_tp(id, &tp);
if (wp != NULL && tp != NULL)
{
- if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, TRUE)
- == OK)
+ if (switch_win_noblock(&switchwin, wp, tp, TRUE) == OK)
{
check_cursor();
fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
}
- restore_win_noblock(save_curwin, save_curtab, TRUE);
+ restore_win_noblock(&switchwin, TRUE);
}
}
else
dictitem_T *v;
tabpage_T *tp = NULL;
int done = FALSE;
- win_T *oldcurwin;
- tabpage_T *oldtabpage;
+ switchwin_T switchwin;
int need_switch_win;
if (off == 1)
// autocommands get blocked.
need_switch_win = !(tp == curtab && win == curwin);
if (!need_switch_win
- || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK)
+ || switch_win(&switchwin, win, tp, TRUE) == OK)
{
if (*varname == '&')
{
if (need_switch_win)
// restore previous notion of curwin
- restore_win(oldcurwin, oldtabpage, TRUE);
+ restore_win(&switchwin, TRUE);
}
if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
setwinvar(typval_T *argvars, int off)
{
win_T *win;
- win_T *save_curwin;
- tabpage_T *save_curtab;
+ switchwin_T switchwin;
int need_switch_win;
char_u *varname, *winvarname;
typval_T *varp;
{
need_switch_win = !(tp == curtab && win == curwin);
if (!need_switch_win
- || switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK)
+ || switch_win(&switchwin, win, tp, TRUE) == OK)
{
if (*varname == '&')
set_option_from_tv(varname + 1, varp);
}
}
if (need_switch_win)
- restore_win(save_curwin, save_curtab, TRUE);
+ restore_win(&switchwin, TRUE);
}
}
void
f_gettabvar(typval_T *argvars, typval_T *rettv)
{
- win_T *oldcurwin;
- tabpage_T *tp, *oldtabpage;
+ switchwin_T switchwin;
+ tabpage_T *tp;
dictitem_T *v;
char_u *varname;
int done = FALSE;
{
// Set tp to be our tabpage, temporarily. Also set the window to the
// first window in the tabpage, otherwise the window is not valid.
- if (switch_win(&oldcurwin, &oldtabpage,
+ if (switch_win(&switchwin,
tp == curtab || tp->tp_firstwin == NULL ? firstwin
: tp->tp_firstwin, tp, TRUE) == OK)
{
}
// restore previous notion of curwin
- restore_win(oldcurwin, oldtabpage, TRUE);
+ restore_win(&switchwin, TRUE);
}
if (!done && argvars[2].v_type != VAR_UNKNOWN)
int id;
tabpage_T *tp;
win_T *wp;
- win_T *save_curwin;
- tabpage_T *save_curtab;
+ switchwin_T switchwin;
// Return an empty string if something fails.
rettv->v_type = VAR_STRING;
}
#endif
- if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, TRUE) == OK)
+ if (switch_win_noblock(&switchwin, wp, tp, TRUE) == OK)
{
check_cursor();
execute_common(argvars, rettv, 1);
}
- restore_win_noblock(save_curwin, save_curtab, TRUE);
+ restore_win_noblock(&switchwin, TRUE);
#ifdef FEAT_AUTOCHDIR
if (apply_acd)
do_autochdir();
*/
int
switch_win(
- win_T **save_curwin,
- tabpage_T **save_curtab,
- win_T *win,
- tabpage_T *tp,
- int no_display)
+ switchwin_T *switchwin,
+ win_T *win,
+ tabpage_T *tp,
+ int no_display)
{
block_autocmds();
- return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display);
+ return switch_win_noblock(switchwin, win, tp, no_display);
}
/*
*/
int
switch_win_noblock(
- win_T **save_curwin,
- tabpage_T **save_curtab,
- win_T *win,
- tabpage_T *tp,
- int no_display)
+ switchwin_T *switchwin,
+ win_T *win,
+ tabpage_T *tp,
+ int no_display)
{
- *save_curwin = curwin;
+ CLEAR_POINTER(switchwin);
+ 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)
{
- *save_curtab = curtab;
+ switchwin->sw_curtab = curtab;
if (no_display)
{
curtab->tp_firstwin = firstwin;
*/
void
restore_win(
- win_T *save_curwin,
- tabpage_T *save_curtab,
- int no_display)
+ switchwin_T *switchwin,
+ int no_display)
{
- restore_win_noblock(save_curwin, save_curtab, no_display);
+ restore_win_noblock(switchwin, no_display);
unblock_autocmds();
}
*/
void
restore_win_noblock(
- win_T *save_curwin,
- tabpage_T *save_curtab,
- int no_display)
+ switchwin_T *switchwin,
+ int no_display)
{
- if (save_curtab != NULL && valid_tabpage(save_curtab))
+ if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab))
{
if (no_display)
{
curtab->tp_firstwin = firstwin;
curtab->tp_lastwin = lastwin;
curtab->tp_topframe = topframe;
- curtab = save_curtab;
+ curtab = switchwin->sw_curtab;
firstwin = curtab->tp_firstwin;
lastwin = curtab->tp_lastwin;
topframe = curtab->tp_topframe;
}
else
- goto_tabpage_tp(save_curtab, FALSE, FALSE);
+ goto_tabpage_tp(switchwin->sw_curtab, FALSE, FALSE);
}
- if (win_valid(save_curwin))
+
+ if (!switchwin->sw_same_win)
+ VIsual_active = switchwin->sw_visual_active;
+
+ if (win_valid(switchwin->sw_curwin))
{
- curwin = save_curwin;
+ curwin = switchwin->sw_curwin;
curbuf = curwin->w_buffer;
}
# ifdef FEAT_PROP_POPUP
int opt_type,
void *from)
{
- win_T *save_curwin = NULL;
- tabpage_T *save_curtab = NULL;
+ switchwin_T switchwin;
bufref_T save_curbuf;
int set_ret = 0;
switch (opt_type)
{
case SREQ_WIN:
- if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
+ if (switch_win(&switchwin, (win_T *)from,
win_find_tabpage((win_T *)from), FALSE) == FAIL)
{
- restore_win(save_curwin, save_curtab, TRUE);
+ restore_win(&switchwin, TRUE);
if (VimTryEnd())
return -1;
PyErr_SET_VIM(N_("problem while switching windows"));
return -1;
}
set_ret = set_option_value_err(key, numval, stringval, opt_flags);
- restore_win(save_curwin, save_curtab, TRUE);
+ restore_win(&switchwin, TRUE);
break;
case SREQ_BUF:
switch_buffer(&save_curbuf, (buf_T *)from);
SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
{
bufref_T save_curbuf = {NULL, 0, 0};
- win_T *save_curwin = NULL;
- tabpage_T *save_curtab = NULL;
+ switchwin_T switchwin;
// First of all, we check the type of the supplied Python object.
// There are three cases:
if (line == Py_None || line == NULL)
{
PyErr_Clear();
- switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
+ switchwin.sw_curwin = NULL;
+ switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
VimTryStart();
RAISE_DELETE_LINE_FAIL;
else
{
- if (buf == curbuf && (save_curwin != NULL
+ if (buf == curbuf && (switchwin.sw_curwin != NULL
|| save_curbuf.br_buf == NULL))
// Using an existing window for the buffer, adjust the cursor
// position.
deleted_lines_mark((linenr_T)n, 1L);
}
- restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
+ restore_win_for_buf(&switchwin, &save_curbuf);
if (VimTryEnd())
return FAIL;
// We do not need to free "save" if ml_replace() consumes it.
PyErr_Clear();
- switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
+ switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
if (u_savesub((linenr_T)n) == FAIL)
{
else
changed_bytes((linenr_T)n, 0);
- restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
+ restore_win_for_buf(&switchwin, &save_curbuf);
// Check that the cursor is not beyond the end of the line now.
if (buf == curbuf)
PyInt *len_change)
{
bufref_T save_curbuf = {NULL, 0, 0};
- win_T *save_curwin = NULL;
- tabpage_T *save_curtab = NULL;
+ switchwin_T switchwin;
// First of all, we check the type of the supplied Python object.
// There are three cases:
PyErr_Clear();
VimTryStart();
- switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
+ switchwin.sw_curwin = NULL;
+ switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
if (u_savedel((linenr_T)lo, (long)n) == FAIL)
RAISE_UNDO_FAIL;
break;
}
}
- if (buf == curbuf && (save_curwin != NULL
+ if (buf == curbuf && (switchwin.sw_curwin != NULL
|| save_curbuf.br_buf == NULL))
// Using an existing window for the buffer, adjust the cursor
// position.
deleted_lines_mark((linenr_T)lo, (long)i);
}
- restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
+ restore_win_for_buf(&switchwin, &save_curbuf);
if (VimTryEnd())
return FAIL;
PyErr_Clear();
// START of region without "return". Must call restore_buffer()!
- switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
+ switchwin.sw_curwin = NULL;
+ switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
RAISE_UNDO_FAIL;
(long)MAXLNUM, (long)extra);
changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
- if (buf == curbuf && (save_curwin != NULL
+ if (buf == curbuf && (switchwin.sw_curwin != NULL
|| save_curbuf.br_buf == NULL))
// Using an existing window for the buffer, adjust the cursor
// position.
py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
// END of region without "return".
- restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
+ restore_win_for_buf(&switchwin, &save_curbuf);
if (VimTryEnd())
return FAIL;
InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
{
bufref_T save_curbuf = {NULL, 0, 0};
- win_T *save_curwin = NULL;
- tabpage_T *save_curtab = NULL;
+ switchwin_T switchwin;
// First of all, we check the type of the supplied Python object.
// It must be a string or a list, or the call is in error.
PyErr_Clear();
VimTryStart();
- switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
+ switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
RAISE_UNDO_FAIL;
appended_lines_mark((linenr_T)n, 1L);
vim_free(str);
- restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
+ restore_win_for_buf(&switchwin, &save_curbuf);
update_screen(VALID);
if (VimTryEnd())
PyErr_Clear();
VimTryStart();
- switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
+ switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
RAISE_UNDO_FAIL;
// Free the array of lines. All of its contents have now
// been freed.
PyMem_Free(array);
- restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
+ restore_win_for_buf(&switchwin, &save_curbuf);
update_screen(VALID);
void f_setline(typval_T *argvars, typval_T *rettv);
void switch_buffer(bufref_T *save_curbuf, buf_T *buf);
void restore_buffer(bufref_T *save_curbuf);
-void switch_to_win_for_buf(buf_T *buf, win_T **save_curwinp, tabpage_T **save_curtabp, bufref_T *save_curbuf);
-void restore_win_for_buf(win_T *save_curwin, tabpage_T *save_curtab, bufref_T *save_curbuf);
+void switch_to_win_for_buf(buf_T *buf, switchwin_T *switchwin, bufref_T *save_curbuf);
+void restore_win_for_buf(switchwin_T *switchwin, bufref_T *save_curbuf);
/* vim: set ft=c : */
void f_winrestview(typval_T *argvars, typval_T *rettv);
void f_winsaveview(typval_T *argvars, typval_T *rettv);
void f_winwidth(typval_T *argvars, typval_T *rettv);
-int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp, int no_display);
-int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp, int no_display);
-void restore_win(win_T *save_curwin, tabpage_T *save_curtab, int no_display);
-void restore_win_noblock(win_T *save_curwin, tabpage_T *save_curtab, int no_display);
+int switch_win(switchwin_T *switchwin, win_T *win, tabpage_T *tp, int no_display);
+int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, int no_display);
+void restore_win(switchwin_T *switchwin, int no_display);
+void restore_win_noblock(switchwin_T *switchwin, int no_display);
/* vim: set ft=c : */
FILTERMAP_MAPNEW
} filtermap_T;
+// Structure used by switch_win() to pass values to restore_win()
+typedef struct {
+ win_T *sw_curwin;
+ tabpage_T *sw_curtab;
+ int sw_same_win; // VIsual_active was not reset
+ int sw_visual_active;
+} switchwin_T;
unlet xyz
endfunc
+func Test_win_execute_visual_redraw()
+ call setline(1, ['a', 'b', 'c'])
+ new
+ wincmd p
+ call feedkeys("G\<C-V>", 'txn')
+ call win_execute(winnr('#')->win_getid(), 'redraw')
+ bwipe!
+ bwipe!
+endfunc
+
func Test_win_execute_on_startup()
CheckRunVimInTerminal
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 4018,
/**/
4017,
/**/