changeset 12521:718787498836 v8.0.1139

patch 8.0.1139: using window toolbar changes state commit https://github.com/vim/vim/commit/a21a6a9ade7bec3a07992d4d900d4ce82eeb8a29 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Sep 23 16:33:50 2017 +0200 patch 8.0.1139: using window toolbar changes state Problem: Using window toolbar changes state. Solution: Always execute window toolbar actions in Normal mode.
author Christian Brabandt <cb@256bit.org>
date Sat, 23 Sep 2017 16:45:05 +0200
parents 983f47a69df0
children c9f1b01ee83d
files src/ex_docmd.c src/menu.c src/proto/ex_docmd.pro src/structs.h src/version.c
diffstat 5 files changed, 95 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- 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
--- a/src/menu.c
+++ b/src/menu.c
@@ -2242,7 +2242,7 @@ gui_destroy_tearoffs_recurse(vimmenu_T *
 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 *me
 	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 *me
 		|| 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;
 	    }
 	}
     }
--- 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);
--- 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;
--- 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,