mirror of
https://github.com/neovim/neovim.git
synced 2025-09-18 17:28:23 +00:00
vim-patch:8.0.1139: using window toolbar changes state
Problem: Using window toolbar changes state.
Solution: Always execute window toolbar actions in Normal mode.
a21a6a9ade
This commit is contained in:
@@ -334,7 +334,7 @@ typedef struct {
|
||||
// Struct to hold the saved typeahead for save_typeahead().
|
||||
typedef struct {
|
||||
typebuf_T save_typebuf;
|
||||
int typebuf_valid; // TRUE when save_typebuf valid
|
||||
bool typebuf_valid; // true when save_typebuf valid
|
||||
int old_char;
|
||||
int old_mod_mask;
|
||||
buffheader_T save_readbuf1;
|
||||
|
@@ -8209,6 +8209,57 @@ void update_topline_cursor(void)
|
||||
update_curswant();
|
||||
}
|
||||
|
||||
// Save the current State and go to Normal mode.
|
||||
// Return true if the typeahead could be saved.
|
||||
bool save_current_state(save_state_T *sst)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
sst->save_msg_scroll = msg_scroll;
|
||||
sst->save_restart_edit = restart_edit;
|
||||
sst->save_msg_didout = msg_didout;
|
||||
sst->save_State = State;
|
||||
sst->save_insertmode = p_im;
|
||||
sst->save_finish_op = finish_op;
|
||||
sst->save_opcount = opcount;
|
||||
sst->save_reg_executing = reg_executing;
|
||||
|
||||
msg_scroll = false; // no msg scrolling in Normal mode
|
||||
restart_edit = 0; // don't go to Insert mode
|
||||
p_im = false; // don't use 'insertmode
|
||||
|
||||
// Save the current typeahead. This is required to allow using ":normal"
|
||||
// from an event handler and makes sure we don't hang when the argument
|
||||
// ends with half a command.
|
||||
save_typeahead(&sst->tabuf);
|
||||
return sst->tabuf.typebuf_valid;
|
||||
}
|
||||
|
||||
void restore_current_state(save_state_T *sst)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// Restore the previous typeahead.
|
||||
restore_typeahead(&sst->tabuf);
|
||||
|
||||
msg_scroll = sst->save_msg_scroll;
|
||||
if (force_restart_edit) {
|
||||
force_restart_edit = false;
|
||||
} else {
|
||||
// Some function (terminal_enter()) was aware of ex_normal and decided to
|
||||
// override the value of restart_edit anyway.
|
||||
restart_edit = sst->save_restart_edit;
|
||||
}
|
||||
p_im = sst->save_insertmode;
|
||||
finish_op = sst->save_finish_op;
|
||||
opcount = sst->save_opcount;
|
||||
reg_executing = sst->save_reg_executing;
|
||||
msg_didout |= sst->save_msg_didout; // don't reset msg_didout now
|
||||
|
||||
// Restore the state (needed when called from a function executed for
|
||||
// 'indentexpr'). Update the mouse and cursor, they may have changed.
|
||||
State = sst->save_State;
|
||||
ui_cursor_shape(); // may show different cursor shape
|
||||
}
|
||||
|
||||
/*
|
||||
* ":normal[!] {commands}": Execute normal mode commands.
|
||||
*/
|
||||
@@ -8218,15 +8269,7 @@ static void ex_normal(exarg_T *eap)
|
||||
EMSG("Can't re-enter normal mode from terminal mode");
|
||||
return;
|
||||
}
|
||||
int save_msg_scroll = msg_scroll;
|
||||
int save_restart_edit = restart_edit;
|
||||
int save_msg_didout = msg_didout;
|
||||
int save_State = State;
|
||||
tasave_T tabuf;
|
||||
int save_insertmode = p_im;
|
||||
int save_finish_op = finish_op;
|
||||
long save_opcount = opcount;
|
||||
const int save_reg_executing = reg_executing;
|
||||
save_state_T save_state;
|
||||
char_u *arg = NULL;
|
||||
int l;
|
||||
char_u *p;
|
||||
@@ -8239,11 +8282,6 @@ static void ex_normal(exarg_T *eap)
|
||||
EMSG(_("E192: Recursive use of :normal too deep"));
|
||||
return;
|
||||
}
|
||||
++ex_normal_busy;
|
||||
|
||||
msg_scroll = FALSE; /* no msg scrolling in Normal mode */
|
||||
restart_edit = 0; /* don't go to Insert mode */
|
||||
p_im = FALSE; /* don't use 'insertmode' */
|
||||
|
||||
/*
|
||||
* vgetc() expects a CSI and K_SPECIAL to have been escaped. Don't do
|
||||
@@ -8277,19 +8315,11 @@ static void ex_normal(exarg_T *eap)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the current typeahead. This is required to allow using ":normal"
|
||||
* from an event handler and makes sure we don't hang when the argument
|
||||
* ends with half a command.
|
||||
*/
|
||||
save_typeahead(&tabuf);
|
||||
// TODO(philix): after save_typeahead() this is always TRUE
|
||||
if (tabuf.typebuf_valid) {
|
||||
/*
|
||||
* Repeat the :normal command for each line in the range. When no
|
||||
* range given, execute it just once, without positioning the cursor
|
||||
* first.
|
||||
*/
|
||||
ex_normal_busy++;
|
||||
if (save_current_state(&save_state)) {
|
||||
// Repeat the :normal command for each line in the range. When no
|
||||
// range given, execute it just once, without positioning the cursor
|
||||
// first.
|
||||
do {
|
||||
if (eap->addr_count != 0) {
|
||||
curwin->w_cursor.lnum = eap->line1++;
|
||||
@@ -8306,29 +8336,12 @@ static void ex_normal(exarg_T *eap)
|
||||
/* Might not return to the main loop when in an event handler. */
|
||||
update_topline_cursor();
|
||||
|
||||
/* Restore the previous typeahead. */
|
||||
restore_typeahead(&tabuf);
|
||||
restore_current_state(&save_state);
|
||||
|
||||
--ex_normal_busy;
|
||||
msg_scroll = save_msg_scroll;
|
||||
if (force_restart_edit) {
|
||||
force_restart_edit = false;
|
||||
} else {
|
||||
// Some function (terminal_enter()) was aware of ex_normal and decided to
|
||||
// override the value of restart_edit anyway.
|
||||
restart_edit = save_restart_edit;
|
||||
}
|
||||
p_im = save_insertmode;
|
||||
finish_op = save_finish_op;
|
||||
opcount = save_opcount;
|
||||
reg_executing = save_reg_executing;
|
||||
msg_didout |= save_msg_didout; // don't reset msg_didout now
|
||||
ex_normal_busy--;
|
||||
|
||||
/* Restore the state (needed when called from a function executed for
|
||||
* 'indentexpr'). Update the mouse and cursor, they may have changed. */
|
||||
State = save_State;
|
||||
setmouse();
|
||||
ui_cursor_shape(); /* may show different cursor shape */
|
||||
ui_cursor_shape(); // may show different cursor shape
|
||||
xfree(arg);
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,20 @@
|
||||
#define EXMODE_NORMAL 1
|
||||
#define EXMODE_VIM 2
|
||||
|
||||
// Structure used to save the current state. Used when executing Normal mode
|
||||
// commands while in any other mode.
|
||||
typedef struct {
|
||||
int save_msg_scroll;
|
||||
int save_restart_edit;
|
||||
int save_msg_didout;
|
||||
int save_State;
|
||||
int save_insertmode;
|
||||
bool save_finish_op;
|
||||
long save_opcount;
|
||||
int save_reg_executing;
|
||||
tasave_T tabuf;
|
||||
} save_state_T;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ex_docmd.h.generated.h"
|
||||
#endif
|
||||
|
@@ -1216,7 +1216,7 @@ void save_typeahead(tasave_T *tp)
|
||||
{
|
||||
tp->save_typebuf = typebuf;
|
||||
alloc_typebuf();
|
||||
tp->typebuf_valid = TRUE;
|
||||
tp->typebuf_valid = true;
|
||||
tp->old_char = old_char;
|
||||
tp->old_mod_mask = old_mod_mask;
|
||||
old_char = -1;
|
||||
|
@@ -1410,7 +1410,7 @@ static int menu_is_hidden(char_u *name)
|
||||
static void execute_menu(const exarg_T *eap, vimmenu_T *menu)
|
||||
FUNC_ATTR_NONNULL_ARG(2)
|
||||
{
|
||||
int idx;
|
||||
int idx = -1;
|
||||
char_u *mode;
|
||||
|
||||
// Use the Insert mode entry when returning to Insert mode.
|
||||
@@ -1464,9 +1464,13 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu)
|
||||
|
||||
/* Adjust the cursor to make sure it is in the correct pos
|
||||
* for exclusive mode */
|
||||
if (*p_sel == 'e' && gchar_cursor() != NUL)
|
||||
++curwin->w_cursor.col;
|
||||
} else {
|
||||
if (*p_sel == 'e' && gchar_cursor() != NUL) {
|
||||
curwin->w_cursor.col++;
|
||||
}
|
||||
}
|
||||
|
||||
// For the WinBar menu always use the Normal mode menu.
|
||||
if (idx == -1 || eap == NULL) {
|
||||
mode = (char_u *)"Normal";
|
||||
idx = MENU_INDEX_NORMAL;
|
||||
}
|
||||
@@ -1477,8 +1481,15 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu)
|
||||
// Also for the window toolbar
|
||||
// Otherwise put them in the typeahead buffer.
|
||||
if (eap == NULL || current_sctx.sc_sid != 0) {
|
||||
save_state_T save_state;
|
||||
|
||||
ex_normal_busy++;
|
||||
if (save_current_state(&save_state)) {
|
||||
exec_normal_cmd(menu->strings[idx], menu->noremap[idx],
|
||||
menu->silent[idx]);
|
||||
}
|
||||
restore_current_state(&save_state);
|
||||
ex_normal_busy--;
|
||||
} else {
|
||||
ins_typebuf(menu->strings[idx], menu->noremap[idx], 0, true,
|
||||
menu->silent[idx]);
|
||||
@@ -1540,11 +1551,17 @@ void winbar_click(win_T *wp, int col)
|
||||
|
||||
if (col >= item->wb_startcol && col <= item->wb_endcol) {
|
||||
win_T *save_curwin = NULL;
|
||||
const pos_T save_visual = VIsual;
|
||||
const int save_visual_active = VIsual_active;
|
||||
const int save_visual_select = VIsual_select;
|
||||
const int save_visual_reselect = VIsual_reselect;
|
||||
const int save_visual_mode = VIsual_mode;
|
||||
|
||||
if (wp != curwin) {
|
||||
// Clicking in the window toolbar of a not-current window.
|
||||
// Make that window the current one and go to Normal mode.
|
||||
// Make that window the current one and save Visual mode.
|
||||
save_curwin = curwin;
|
||||
VIsual_active = false;
|
||||
curwin = wp;
|
||||
curbuf = curwin->w_buffer;
|
||||
check_cursor();
|
||||
@@ -1555,6 +1572,11 @@ void winbar_click(win_T *wp, int col)
|
||||
if (save_curwin != NULL) {
|
||||
curwin = save_curwin;
|
||||
curbuf = curwin->w_buffer;
|
||||
VIsual = save_visual;
|
||||
VIsual_active = save_visual_active;
|
||||
VIsual_select = save_visual_select;
|
||||
VIsual_reselect = save_visual_reselect;
|
||||
VIsual_mode = save_visual_mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user