# HG changeset patch # User Christian Brabandt # Date 1506177905 -7200 # Node ID 718787498836b04c212b9f71780569a04df3ba8e # Parent 983f47a69df006f634597b713ada54b399288893 patch 8.0.1139: using window toolbar changes state commit https://github.com/vim/vim/commit/a21a6a9ade7bec3a07992d4d900d4ce82eeb8a29 Author: Bram Moolenaar 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. diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- 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 --- 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; } } } diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro --- 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 --- 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 --- 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,