summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-09-23 16:33:50 +0200
committerBram Moolenaar <Bram@vim.org>2017-09-23 16:33:50 +0200
commita21a6a9ade7bec3a07992d4d900d4ce82eeb8a29 (patch)
treefc3e9d9ee37b8f842a038035a7f251c0e3435942
parenteb163d73b11c10b461a2839530173a33d7915a33 (diff)
downloadvim-git-a21a6a9ade7bec3a07992d4d900d4ce82eeb8a29.tar.gz
patch 8.0.1139: using window toolbar changes statev8.0.1139
Problem: Using window toolbar changes state. Solution: Always execute window toolbar actions in Normal mode.
-rw-r--r--src/ex_docmd.c86
-rw-r--r--src/menu.c29
-rw-r--r--src/proto/ex_docmd.pro2
-rw-r--r--src/structs.h13
-rw-r--r--src/version.c2
5 files changed, 95 insertions, 37 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 29435c2ea..c740d037f 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -10107,19 +10107,61 @@ update_topline_cursor(void)
}
/*
+ * Save the current State and go to Normal mode.
+ * Return TRUE if the typeahead could be saved.
+ */
+ int
+save_current_state(save_state_T *sst)
+{
+ 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;
+
+ 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)
+{
+ /* Restore the previous typeahead. */
+ restore_typeahead(&sst->tabuf);
+
+ msg_scroll = sst->save_msg_scroll;
+ restart_edit = sst->save_restart_edit;
+ p_im = sst->save_insertmode;
+ finish_op = sst->save_finish_op;
+ opcount = sst->save_opcount;
+ 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;
+#ifdef CURSOR_SHAPE
+ ui_cursor_shape(); /* may show different cursor shape */
+#endif
+}
+
+/*
* ":normal[!] {commands}": Execute normal mode commands.
*/
void
ex_normal(exarg_T *eap)
{
- 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;
- int save_opcount = opcount;
+ save_state_T save_state;
#ifdef FEAT_MBYTE
char_u *arg = NULL;
int l;
@@ -10136,11 +10178,6 @@ 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' */
#ifdef FEAT_MBYTE
/*
@@ -10206,13 +10243,8 @@ ex_normal(exarg_T *eap)
}
#endif
- /*
- * 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);
- if (tabuf.typebuf_valid)
+ ++ex_normal_busy;
+ if (save_current_state(&save_state))
{
/*
* Repeat the :normal command for each line in the range. When no
@@ -10240,20 +10272,8 @@ 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;
- restart_edit = save_restart_edit;
- p_im = save_insertmode;
- finish_op = save_finish_op;
- opcount = save_opcount;
- 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;
#ifdef FEAT_MOUSE
setmouse();
#endif
diff --git a/src/menu.c b/src/menu.c
index 1ad8a5cb9..f07be97e7 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -2242,7 +2242,7 @@ gui_destroy_tearoffs_recurse(vimmenu_T *menu)
execute_menu(exarg_T *eap, vimmenu_T *menu)
{
char_u *mode;
- int idx;
+ int idx = -1;
/* Use the Insert mode entry when returning to Insert mode. */
if (restart_edit
@@ -2306,7 +2306,9 @@ execute_menu(exarg_T *eap, vimmenu_T *menu)
if (*p_sel == 'e' && gchar_cursor() != NUL)
++curwin->w_cursor.col;
}
- else
+
+ /* For the WinBar menu always use the Normal mode menu. */
+ if (idx == -1 || eap == NULL)
{
mode = (char_u *)"Normal";
idx = MENU_INDEX_NORMAL;
@@ -2322,8 +2324,16 @@ execute_menu(exarg_T *eap, vimmenu_T *menu)
|| current_SID != 0
#endif
)
- exec_normal_cmd(menu->strings[idx], menu->noremap[idx],
+ {
+ 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]);
@@ -2406,12 +2416,18 @@ winbar_click(win_T *wp, int col)
if (col >= item->wb_startcol && col <= item->wb_endcol)
{
win_T *save_curwin = NULL;
+ pos_T save_visual = VIsual;
+ int save_visual_active = VIsual_active;
+ int save_visual_select = VIsual_select;
+ int save_visual_reselect = VIsual_reselect;
+ 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();
@@ -2423,6 +2439,11 @@ winbar_click(win_T *wp, int col)
{
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;
}
}
}
diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro
index 116ff4e72..381953192 100644
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -51,6 +51,8 @@ void ex_redraw(exarg_T *eap);
int vim_mkdir_emsg(char_u *name, int prot);
FILE *open_exfile(char_u *fname, int forceit, char *mode);
void update_topline_cursor(void);
+int save_current_state(save_state_T *sst);
+void restore_current_state(save_state_T *sst);
void ex_normal(exarg_T *eap);
void exec_normal_cmd(char_u *cmd, int remap, int silent);
void exec_normal(int was_typed);
diff --git a/src/structs.h b/src/structs.h
index 4582dca95..946857be5 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -3405,3 +3405,16 @@ typedef struct lval_S
dictitem_T *ll_di; /* The dictitem or NULL */
char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */
} lval_T;
+
+/* 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;
+ int save_finish_op;
+ int save_opcount;
+ tasave_T tabuf;
+} save_state_T;
diff --git a/src/version.c b/src/version.c
index a2f71a3d9..3d5716e4c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -762,6 +762,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1139,
+/**/
1138,
/**/
1137,