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:
Jan Edmund Lazo
2020-03-14 12:47:49 -04:00
parent 86d0f67c29
commit 5b3ec39df3
5 changed files with 105 additions and 56 deletions

View File

@@ -334,7 +334,7 @@ typedef struct {
// Struct to hold the saved typeahead for save_typeahead(). // Struct to hold the saved typeahead for save_typeahead().
typedef struct { typedef struct {
typebuf_T save_typebuf; 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_char;
int old_mod_mask; int old_mod_mask;
buffheader_T save_readbuf1; buffheader_T save_readbuf1;

View File

@@ -8209,6 +8209,57 @@ void update_topline_cursor(void)
update_curswant(); 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. * ":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"); EMSG("Can't re-enter normal mode from terminal mode");
return; return;
} }
int save_msg_scroll = msg_scroll; save_state_T save_state;
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;
char_u *arg = NULL; char_u *arg = NULL;
int l; int l;
char_u *p; char_u *p;
@@ -8239,11 +8282,6 @@ static void ex_normal(exarg_T *eap)
EMSG(_("E192: Recursive use of :normal too deep")); EMSG(_("E192: Recursive use of :normal too deep"));
return; 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 * 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)
} }
} }
/* ex_normal_busy++;
* Save the current typeahead. This is required to allow using ":normal" if (save_current_state(&save_state)) {
* from an event handler and makes sure we don't hang when the argument // Repeat the :normal command for each line in the range. When no
* ends with half a command. // range given, execute it just once, without positioning the cursor
*/ // first.
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.
*/
do { do {
if (eap->addr_count != 0) { if (eap->addr_count != 0) {
curwin->w_cursor.lnum = eap->line1++; 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. */ /* Might not return to the main loop when in an event handler. */
update_topline_cursor(); update_topline_cursor();
/* Restore the previous typeahead. */ restore_current_state(&save_state);
restore_typeahead(&tabuf);
--ex_normal_busy; 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
/* 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(); setmouse();
ui_cursor_shape(); /* may show different cursor shape */ ui_cursor_shape(); // may show different cursor shape
xfree(arg); xfree(arg);
} }

View File

@@ -20,6 +20,20 @@
#define EXMODE_NORMAL 1 #define EXMODE_NORMAL 1
#define EXMODE_VIM 2 #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 #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_docmd.h.generated.h" # include "ex_docmd.h.generated.h"
#endif #endif

View File

@@ -1216,7 +1216,7 @@ void save_typeahead(tasave_T *tp)
{ {
tp->save_typebuf = typebuf; tp->save_typebuf = typebuf;
alloc_typebuf(); alloc_typebuf();
tp->typebuf_valid = TRUE; tp->typebuf_valid = true;
tp->old_char = old_char; tp->old_char = old_char;
tp->old_mod_mask = old_mod_mask; tp->old_mod_mask = old_mod_mask;
old_char = -1; old_char = -1;

View File

@@ -1410,7 +1410,7 @@ static int menu_is_hidden(char_u *name)
static void execute_menu(const exarg_T *eap, vimmenu_T *menu) static void execute_menu(const exarg_T *eap, vimmenu_T *menu)
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(2)
{ {
int idx; int idx = -1;
char_u *mode; char_u *mode;
// Use the Insert mode entry when returning to Insert 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 /* Adjust the cursor to make sure it is in the correct pos
* for exclusive mode */ * for exclusive mode */
if (*p_sel == 'e' && gchar_cursor() != NUL) if (*p_sel == 'e' && gchar_cursor() != NUL) {
++curwin->w_cursor.col; curwin->w_cursor.col++;
} else { }
}
// For the WinBar menu always use the Normal mode menu.
if (idx == -1 || eap == NULL) {
mode = (char_u *)"Normal"; mode = (char_u *)"Normal";
idx = MENU_INDEX_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 // Also for the window toolbar
// Otherwise put them in the typeahead buffer. // Otherwise put them in the typeahead buffer.
if (eap == NULL || current_sctx.sc_sid != 0) { if (eap == NULL || current_sctx.sc_sid != 0) {
exec_normal_cmd(menu->strings[idx], menu->noremap[idx], save_state_T save_state;
menu->silent[idx]);
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 { } else {
ins_typebuf(menu->strings[idx], menu->noremap[idx], 0, true, ins_typebuf(menu->strings[idx], menu->noremap[idx], 0, true,
menu->silent[idx]); menu->silent[idx]);
@@ -1540,11 +1551,17 @@ void winbar_click(win_T *wp, int col)
if (col >= item->wb_startcol && col <= item->wb_endcol) { if (col >= item->wb_startcol && col <= item->wb_endcol) {
win_T *save_curwin = NULL; 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) { if (wp != curwin) {
// Clicking in the window toolbar of a not-current window. // 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; save_curwin = curwin;
VIsual_active = false;
curwin = wp; curwin = wp;
curbuf = curwin->w_buffer; curbuf = curwin->w_buffer;
check_cursor(); check_cursor();
@@ -1555,6 +1572,11 @@ void winbar_click(win_T *wp, int col)
if (save_curwin != NULL) { if (save_curwin != NULL) {
curwin = save_curwin; curwin = save_curwin;
curbuf = curwin->w_buffer; 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;
} }
} }
} }