To: vim_dev@googlegroups.com Subject: Patch 8.0.1139 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1139 Problem: Using window toolbar changes state. Solution: Always execute window toolbar actions in Normal mode. Files: runtime/doc/gui.txt, src/structs.h, src/ex_docmd.c, src/proto/ex_docmd.pro, src/menu.c *** ../vim-8.0.1138/runtime/doc/gui.txt 2017-09-17 23:02:17.180074376 +0200 --- runtime/doc/gui.txt 2017-09-23 15:26:00.522061122 +0200 *************** *** 783,806 **** from the main menu bar. You must then use the |:popup| or |:tearoff| command to display it. ! *window-toolbar* Each window can have a local toolbar. This uses the first line of the window, ! thus reduces the space for the text by one line. ! Only text can be used. When using Unicode special characters can be used to make the items look like icons. If the items do not fit then the last ones cannot be used. The toolbar does not wrap. Example for debugger tools: > ! amenu 1.10 WinBar.Step :Step ! amenu 1.20 WinBar.Next :Next ! amenu 1.30 WinBar.Finish :Finish ! amenu 1.40 WinBar.Cont :Continue < The window toolbar uses the ToolbarLine and ToolbarButton highlight groups. *popup-menu* In the Win32, GTK+, Motif, Athena and Photon GUI, you can define the special menu "PopUp". This is the menu that is displayed when the right mouse --- 784,816 ---- from the main menu bar. You must then use the |:popup| or |:tearoff| command to display it. ! *window-toolbar* *WinBar* Each window can have a local toolbar. This uses the first line of the window, ! thus reduces the space for the text by one line. The items in the toolbar ! must start with "WinBar". ! Only text can be used. When using Unicode, special characters can be used to make the items look like icons. If the items do not fit then the last ones cannot be used. The toolbar does not wrap. + Note that Vim may be in any mode when executing these commands. The menu + should be defined for Normal mode and will be executed without changing the + current mode. Thus if the current window is in Visual mode and the menu + command does not intentionally change the mode, Vim will remain in Visual + mode. Best is to use `:nnoremenu` to avoid side effects. + Example for debugger tools: > ! nnoremenu 1.10 WinBar.Step :Step ! nnoremenu 1.20 WinBar.Next :Next ! nnoremenu 1.30 WinBar.Finish :Finish ! nnoremenu 1.40 WinBar.Cont :Continue < The window toolbar uses the ToolbarLine and ToolbarButton highlight groups. + When splitting the window the window toolbar is not copied to the new window. + *popup-menu* In the Win32, GTK+, Motif, Athena and Photon GUI, you can define the special menu "PopUp". This is the menu that is displayed when the right mouse *** ../vim-8.0.1138/src/structs.h 2017-09-22 15:20:27.744148592 +0200 --- src/structs.h 2017-09-23 15:39:39.625110739 +0200 *************** *** 3405,3407 **** --- 3405,3420 ---- 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; *** ../vim-8.0.1138/src/ex_docmd.c 2017-09-22 15:20:27.732148666 +0200 --- src/ex_docmd.c 2017-09-23 16:24:53.284454219 +0200 *************** *** 10107,10125 **** } /* * ":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; #ifdef FEAT_MBYTE char_u *arg = NULL; int l; --- 10107,10167 ---- } /* + * 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) { ! save_state_T save_state; #ifdef FEAT_MBYTE char_u *arg = NULL; int l; *************** *** 10136,10146 **** 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 /* --- 10178,10183 ---- *************** *** 10206,10218 **** } #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) { /* * Repeat the :normal command for each line in the range. When no --- 10243,10250 ---- } #endif ! ++ex_normal_busy; ! if (save_current_state(&save_state)) { /* * Repeat the :normal command for each line in the range. When no *************** *** 10240,10259 **** /* Might not return to the main loop when in an event handler. */ update_topline_cursor(); ! /* Restore the previous typeahead. */ ! restore_typeahead(&tabuf); ! --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 --- 10272,10279 ---- /* Might not return to the main loop when in an event handler. */ update_topline_cursor(); ! restore_current_state(&save_state); --ex_normal_busy; #ifdef FEAT_MOUSE setmouse(); #endif *** ../vim-8.0.1138/src/proto/ex_docmd.pro 2017-09-14 22:55:33.333391448 +0200 --- src/proto/ex_docmd.pro 2017-09-23 15:48:33.193856799 +0200 *************** *** 51,56 **** --- 51,58 ---- 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); *** ../vim-8.0.1138/src/menu.c 2017-09-17 23:02:17.168074448 +0200 --- src/menu.c 2017-09-23 15:59:55.477667258 +0200 *************** *** 2242,2248 **** execute_menu(exarg_T *eap, vimmenu_T *menu) { char_u *mode; ! int idx; /* Use the Insert mode entry when returning to Insert mode. */ if (restart_edit --- 2242,2248 ---- execute_menu(exarg_T *eap, vimmenu_T *menu) { char_u *mode; ! int idx = -1; /* Use the Insert mode entry when returning to Insert mode. */ if (restart_edit *************** *** 2306,2312 **** if (*p_sel == 'e' && gchar_cursor() != NUL) ++curwin->w_cursor.col; } ! else { mode = (char_u *)"Normal"; idx = MENU_INDEX_NORMAL; --- 2306,2314 ---- 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; *************** *** 2322,2329 **** || current_SID != 0 #endif ) ! exec_normal_cmd(menu->strings[idx], menu->noremap[idx], menu->silent[idx]); else ins_typebuf(menu->strings[idx], menu->noremap[idx], 0, TRUE, menu->silent[idx]); --- 2324,2339 ---- || current_SID != 0 #endif ) ! { ! 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,2417 **** if (col >= item->wb_startcol && col <= item->wb_endcol) { win_T *save_curwin = NULL; if (wp != curwin) { /* Clicking in the window toolbar of a not-current window. ! * Make that window the current one and go to Normal mode. */ save_curwin = curwin; curwin = wp; curbuf = curwin->w_buffer; check_cursor(); --- 2416,2433 ---- 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 save Visual mode. */ save_curwin = curwin; + VIsual_active = FALSE; curwin = wp; curbuf = curwin->w_buffer; check_cursor(); *************** *** 2423,2428 **** --- 2439,2449 ---- { 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; } } } *** ../vim-8.0.1138/src/version.c 2017-09-23 15:08:13.188518868 +0200 --- src/version.c 2017-09-23 15:45:09.495100298 +0200 *************** *** 763,764 **** --- 763,766 ---- { /* Add new patch number below this line */ + /**/ + 1139, /**/ -- Rule #1: Don't give somebody a tool that he's going to hurt himself with. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///