From 590ec878a52b3b3d4453475f1eb4899f2b37969f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 2 Mar 2018 20:58:42 +0100 Subject: [PATCH 1/8] patch 8.0.1556: may not parse the t_RS response correctly Problem: May not parse the t_RS response correctly, resulting in wrong characters in the input stream. Solution: When the t_RS response is partly received wait for more characters. --- src/term.c | 57 ++++++++++++++++++++++++++++++--------------------- src/version.c | 2 ++ 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/term.c b/src/term.c index 19760f82c5..12c4f2e5bd 100644 --- a/src/term.c +++ b/src/term.c @@ -4866,7 +4866,7 @@ check_termcode( * {tail} can be Esc>\ or STERM * * Check for cursor shape response from xterm: - * {lead}1$r q{tail} + * {lead}1$r q{tail} * * {lead} can be P or DCS * {tail} can be Esc>\ or STERM @@ -4897,35 +4897,46 @@ check_termcode( break; } } - else if ((len >= j + 6 && isdigit(argp[3])) - && argp[4] == ' ' - && argp[5] == 'q') + else { - /* cursor shape response */ - i = j + 6; - if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\') - || tp[i] == STERM) + /* Probably the cursor shape response. Make sure that "i" + * is equal to "len" when there are not sufficient + * characters. */ + for (i = j + 3; i < len; ++i) { - int number = argp[3] - '0'; + if (i - j == 3 && !isdigit(tp[i])) + break; + if (i - j == 4 && tp[i] != ' ') + break; + if (i - j == 5 && tp[i] != 'q') + break; + if (i - j == 6 && tp[i] != ESC && tp[i] != STERM) + break; + if ((i - j == 6 && tp[i] == STERM) + || (i - j == 7 && tp[i] == '\\')) + { + int number = argp[3] - '0'; - /* 0, 1 = block blink, 2 = block - * 3 = underline blink, 4 = underline - * 5 = vertical bar blink, 6 = vertical bar */ - number = number == 0 ? 1 : number; - initial_cursor_shape = (number + 1) / 2; - /* The blink flag is actually inverted, compared to - * the value set with T_SH. */ - initial_cursor_shape_blink = + /* 0, 1 = block blink, 2 = block + * 3 = underline blink, 4 = underline + * 5 = vertical bar blink, 6 = vertical bar */ + number = number == 0 ? 1 : number; + initial_cursor_shape = (number + 1) / 2; + /* The blink flag is actually inverted, compared to + * the value set with T_SH. */ + initial_cursor_shape_blink = (number & 1) ? FALSE : TRUE; - rcs_status = STATUS_GOT; - LOG_TR("Received cursor shape response"); + rcs_status = STATUS_GOT; + LOG_TR("Received cursor shape response"); - key_name[0] = (int)KS_EXTRA; - key_name[1] = (int)KE_IGNORE; - slen = i + 1 + (tp[i] == ESC); + key_name[0] = (int)KS_EXTRA; + key_name[1] = (int)KE_IGNORE; + slen = i + 1; # ifdef FEAT_EVAL - set_vim_var_string(VV_TERMSTYLERESP, tp, slen); + set_vim_var_string(VV_TERMSTYLERESP, tp, slen); # endif + break; + } } } diff --git a/src/version.c b/src/version.c index 9a61422a11..e1f406a430 100644 --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1556, /**/ 1555, /**/ From c71807db9c1821baf86796cd76952df36ff1a29a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 3 Mar 2018 15:06:52 +0100 Subject: [PATCH 2/8] patch 8.0.1557: printf() does not work with only one argument Problem: printf() does not work with only one argument. (Daniel Hahler) Solution: Allow using just the format. (Ken Takata, closes #2687) --- src/evalfunc.c | 2 +- src/testdir/test_expr.vim | 3 +++ src/version.c | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index 5b684bd946..e866f4ce1c 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -738,7 +738,7 @@ static struct fst {"pow", 2, 2, f_pow}, #endif {"prevnonblank", 1, 1, f_prevnonblank}, - {"printf", 2, 19, f_printf}, + {"printf", 1, 19, f_printf}, {"pumvisible", 0, 0, f_pumvisible}, #ifdef FEAT_PYTHON3 {"py3eval", 1, 1, f_py3eval}, diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim index c47bc228bc..c14b6e671a 100644 --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -131,6 +131,9 @@ func Test_option_value() endfunc function Test_printf_misc() + call assert_equal('123', printf('123')) + call assert_fails("call printf('123', 3)", "E767:") + call assert_equal('123', printf('%d', 123)) call assert_equal('123', printf('%i', 123)) call assert_equal('123', printf('%D', 123)) diff --git a/src/version.c b/src/version.c index e1f406a430..7d5418592f 100644 --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1557, /**/ 1556, /**/ From aef8c3da2ba59285b7cfde559ae21cdce6ba6919 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 3 Mar 2018 18:59:16 +0100 Subject: [PATCH 3/8] patch 8.0.1558: no right-click menu in a terminal Problem: No right-click menu in a terminal. Solution: Implement the right click menu for the terminal. --- src/feature.h | 7 ++ src/menu.c | 124 ++++++++++++----------- src/normal.c | 146 ++++++++++++++------------- src/popupmnu.c | 223 +++++++++++++++++++++++++++++++++++------ src/proto/menu.pro | 3 +- src/proto/popupmnu.pro | 1 + src/version.c | 2 + 7 files changed, 349 insertions(+), 157 deletions(-) diff --git a/src/feature.h b/src/feature.h index d29e599a9b..2d57d6704d 100644 --- a/src/feature.h +++ b/src/feature.h @@ -726,6 +726,13 @@ # endif #endif +/* + * popup menu in a terminal + */ +#if defined(FEAT_MENU) && !defined(ALWAYS_USE_GUI) && defined(FEAT_INS_EXPAND) +# define FEAT_TERM_POPUP_MENU +#endif + /* There are two ways to use XPM. */ #if (defined(HAVE_XM_XPMP_H) && defined(FEAT_GUI_MOTIF)) \ || defined(HAVE_X11_XPM_H) diff --git a/src/menu.c b/src/menu.c index 310cf5928f..e453135ae8 100644 --- a/src/menu.c +++ b/src/menu.c @@ -34,10 +34,6 @@ static int menu_namecmp(char_u *name, char_u *mname); static int get_menu_cmd_modes(char_u *, int, int *, int *); static char_u *popup_mode_name(char_u *name, int idx); static char_u *menu_text(char_u *text, int *mnemonic, char_u **actext); -#ifdef FEAT_GUI -static int get_menu_mode(void); -static void gui_update_menus_recurse(vimmenu_T *, int); -#endif #if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF) static void gui_create_tearoffs_recurse(vimmenu_T *menu, const char_u *pname, int *pri_tab, int pri_idx); @@ -1871,7 +1867,7 @@ menu_is_tearoff(char_u *name UNUSED) } #endif -#ifdef FEAT_GUI +#if defined(FEAT_GUI) || defined(FEAT_TERM_POPUP_MENU) || defined(PROTO) static int get_menu_mode(void) @@ -1895,6 +1891,60 @@ get_menu_mode(void) return MENU_INDEX_INVALID; } +/* + * Display the Special "PopUp" menu as a pop-up at the current mouse + * position. The "PopUpn" menu is for Normal mode, "PopUpi" for Insert mode, + * etc. + */ + void +show_popupmenu(void) +{ + vimmenu_T *menu; + int mode; + + mode = get_menu_mode(); + if (mode == MENU_INDEX_INVALID) + return; + mode = menu_mode_chars[mode]; + +# ifdef FEAT_AUTOCMD + { + char_u ename[2]; + + ename[0] = mode; + ename[1] = NUL; + apply_autocmds(EVENT_MENUPOPUP, ename, NULL, FALSE, curbuf); + } +# endif + + for (menu = root_menu; menu != NULL; menu = menu->next) + if (STRNCMP("PopUp", menu->name, 5) == 0 && menu->name[5] == mode) + break; + + /* Only show a popup when it is defined and has entries */ + if (menu != NULL && menu->children != NULL) + { +# if defined(FEAT_GUI) + if (gui.in_use) + { + /* Update the menus now, in case the MenuPopup autocommand did + * anything. */ + gui_update_menus(0); + gui_mch_show_popupmenu(menu); + } +# endif +# if defined(FEAT_GUI) && defined(FEAT_TERM_POPUP_MENU) + else +# endif +# if defined(FEAT_TERM_POPUP_MENU) + pum_show_popupmenu(menu); +# endif + } +} +#endif + +#if defined(FEAT_GUI) || defined(PROTO) + /* * Check that a pointer appears in the menu tree. Used to protect from using * a menu that was deleted after it was selected but before the event was @@ -1955,28 +2005,28 @@ gui_update_menus_recurse(vimmenu_T *menu, int mode) while (menu) { if ((menu->modes & menu->enabled & mode) -#if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF) +# if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF) || menu_is_tearoff(menu->dname) -#endif +# endif ) grey = FALSE; else grey = TRUE; -#ifdef FEAT_GUI_ATHENA +# ifdef FEAT_GUI_ATHENA /* Hiding menus doesn't work for Athena, it can cause a crash. */ gui_mch_menu_grey(menu, grey); -#else +# else /* Never hide a toplevel menu, it may make the menubar resize or * disappear. Same problem for ToolBar items. */ if (vim_strchr(p_go, GO_GREY) != NULL || menu->parent == NULL -# ifdef FEAT_TOOLBAR +# ifdef FEAT_TOOLBAR || menu_is_toolbar(menu->parent->name) -# endif +# endif ) gui_mch_menu_grey(menu, grey); else gui_mch_menu_hidden(menu, grey); -#endif +# endif gui_update_menus_recurse(menu->children, mode); menu = menu->next; } @@ -2010,15 +2060,15 @@ gui_update_menus(int modes) gui_mch_draw_menubar(); prev_mode = mode; force_menu_update = FALSE; -#ifdef FEAT_GUI_W32 +# ifdef FEAT_GUI_W32 /* This can leave a tearoff as active window - make sure we * have the focus */ gui_mch_activate_window(); -#endif +# endif } } -#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \ +# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(PROTO) /* * Check if a key is used as a mnemonic for a toplevel menu. @@ -2037,47 +2087,7 @@ gui_is_menu_shortcut(int key) return TRUE; return FALSE; } -#endif - -/* - * Display the Special "PopUp" menu as a pop-up at the current mouse - * position. The "PopUpn" menu is for Normal mode, "PopUpi" for Insert mode, - * etc. - */ - void -gui_show_popupmenu(void) -{ - vimmenu_T *menu; - int mode; - - mode = get_menu_mode(); - if (mode == MENU_INDEX_INVALID) - return; - mode = menu_mode_chars[mode]; - -#ifdef FEAT_AUTOCMD - { - char_u ename[2]; - - ename[0] = mode; - ename[1] = NUL; - apply_autocmds(EVENT_MENUPOPUP, ename, NULL, FALSE, curbuf); - } -#endif - - for (menu = root_menu; menu != NULL; menu = menu->next) - if (STRNCMP("PopUp", menu->name, 5) == 0 && menu->name[5] == mode) - break; - - /* Only show a popup when it is defined and has entries */ - if (menu != NULL && menu->children != NULL) - { - /* Update the menus now, in case the MenuPopup autocommand did - * anything. */ - gui_update_menus(0); - gui_mch_show_popupmenu(menu); - } -} +# endif #endif /* FEAT_GUI */ #if (defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)) || defined(PROTO) @@ -2238,7 +2248,7 @@ gui_destroy_tearoffs_recurse(vimmenu_T *menu) * Execute "menu". Use by ":emenu" and the window toolbar. * "eap" is NULL for the window toolbar. */ - static void + void execute_menu(exarg_T *eap, vimmenu_T *menu) { char_u *mode; diff --git a/src/normal.c b/src/normal.c index c234c3206f..cea8c9f167 100644 --- a/src/normal.c +++ b/src/normal.c @@ -2286,12 +2286,12 @@ op_function(oparg_T *oap UNUSED) * Do the appropriate action for the current mouse click in the current mode. * Not used for Command-line mode. * - * Normal Mode: + * Normal and Visual Mode: * event modi- position visual change action * fier cursor window * left press - yes end yes * left press C yes end yes "^]" (2) - * left press S yes end yes "*" (2) + * left press S yes end (popup: extend) yes "*" (2) * left drag - yes start if moved no * left relse - yes start if moved no * middle press - yes if not active no put register @@ -2670,82 +2670,94 @@ do_mouse( if (which_button == MOUSE_RIGHT && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) { - /* - * NOTE: Ignore right button down and drag mouse events. - * Windows only shows the popup menu on the button up event. - */ -#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ - || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) - if (!is_click) - return FALSE; -#endif -#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) - if (is_click || is_drag) - return FALSE; -#endif #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) + || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) \ + || defined(FEAT_TERM_POPUP_MENU) +# ifdef FEAT_GUI if (gui.in_use) { - jump_flags = 0; - if (STRCMP(p_mousem, "popup_setpos") == 0) - { - /* First set the cursor position before showing the popup - * menu. */ - if (VIsual_active) - { - pos_T m_pos; +# if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ + || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) + if (!is_click) + /* Ignore right button release events, only shows the popup + * menu on the button down event. */ + return FALSE; +# endif +# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) + if (is_click || is_drag) + /* Ignore right button down and drag mouse events. Windows + * only shows the popup menu on the button up event. */ + return FALSE; +# endif + } +# endif +# if defined(FEAT_GUI) && defined(FEAT_TERM_POPUP_MENU) + else +# endif +# if defined(FEAT_TERM_POPUP_MENU) + if (!is_click) + /* Ignore right button release events, only shows the popup + * menu on the button down event. */ + return FALSE; +#endif - /* - * set MOUSE_MAY_STOP_VIS if we are outside the - * selection or the current window (might have false - * negative here) - */ - if (mouse_row < curwin->w_winrow - || mouse_row - > (curwin->w_winrow + curwin->w_height)) - jump_flags = MOUSE_MAY_STOP_VIS; - else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER) - jump_flags = MOUSE_MAY_STOP_VIS; - else + jump_flags = 0; + if (STRCMP(p_mousem, "popup_setpos") == 0) + { + /* First set the cursor position before showing the popup + * menu. */ + if (VIsual_active) + { + pos_T m_pos; + + /* + * set MOUSE_MAY_STOP_VIS if we are outside the + * selection or the current window (might have false + * negative here) + */ + if (mouse_row < curwin->w_winrow + || mouse_row + > (curwin->w_winrow + curwin->w_height)) + jump_flags = MOUSE_MAY_STOP_VIS; + else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER) + jump_flags = MOUSE_MAY_STOP_VIS; + else + { + if ((LT_POS(curwin->w_cursor, VIsual) + && (LT_POS(m_pos, curwin->w_cursor) + || LT_POS(VIsual, m_pos))) + || (LT_POS(VIsual, curwin->w_cursor) + && (LT_POS(m_pos, VIsual) + || LT_POS(curwin->w_cursor, m_pos)))) { - if ((LT_POS(curwin->w_cursor, VIsual) - && (LT_POS(m_pos, curwin->w_cursor) - || LT_POS(VIsual, m_pos))) - || (LT_POS(VIsual, curwin->w_cursor) - && (LT_POS(m_pos, VIsual) - || LT_POS(curwin->w_cursor, m_pos)))) - { + jump_flags = MOUSE_MAY_STOP_VIS; + } + else if (VIsual_mode == Ctrl_V) + { + getvcols(curwin, &curwin->w_cursor, &VIsual, + &leftcol, &rightcol); + getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL); + if (m_pos.col < leftcol || m_pos.col > rightcol) jump_flags = MOUSE_MAY_STOP_VIS; - } - else if (VIsual_mode == Ctrl_V) - { - getvcols(curwin, &curwin->w_cursor, &VIsual, - &leftcol, &rightcol); - getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL); - if (m_pos.col < leftcol || m_pos.col > rightcol) - jump_flags = MOUSE_MAY_STOP_VIS; - } } } - else - jump_flags = MOUSE_MAY_STOP_VIS; } - if (jump_flags) - { - jump_flags = jump_to_mouse(jump_flags, NULL, which_button); - update_curbuf(VIsual_active ? INVERTED : VALID); - setcursor(); - out_flush(); /* Update before showing popup menu */ - } -# ifdef FEAT_MENU - gui_show_popupmenu(); -# endif - return (jump_flags & CURSOR_MOVED) != 0; + else + jump_flags = MOUSE_MAY_STOP_VIS; } - else - return FALSE; + if (jump_flags) + { + jump_flags = jump_to_mouse(jump_flags, NULL, which_button); + update_curbuf(VIsual_active ? INVERTED : VALID); + setcursor(); + out_flush(); /* Update before showing popup menu */ + } +# ifdef FEAT_MENU + show_popupmenu(); + got_click = FALSE; /* ignore release events */ +# endif + return (jump_flags & CURSOR_MOVED) != 0; #else return FALSE; #endif diff --git a/src/popupmnu.c b/src/popupmnu.c index d9def36647..6cfd95a4e9 100644 --- a/src/popupmnu.c +++ b/src/popupmnu.c @@ -422,9 +422,11 @@ pum_redraw(void) char_u *st; int saved = *p; - *p = NUL; + if (saved != NUL) + *p = NUL; st = transstr(s); - *p = saved; + if (saved != NUL) + *p = saved; #ifdef FEAT_RIGHTLEFT if (curwin->w_p_rl) { @@ -830,6 +832,43 @@ pum_get_height(void) return pum_height; } +# if defined(FEAT_BEVAL_TERM) || defined(FEAT_TERM_POPUP_MENU) || defined(PROTO) + static void +pum_position_at_mouse(int min_width) +{ + if (Rows - mouse_row > pum_size) + { + /* Enough space below the mouse row. */ + pum_row = mouse_row + 1; + if (pum_height > Rows - pum_row) + pum_height = Rows - pum_row; + } + else + { + /* Show above the mouse row, reduce height if it does not fit. */ + pum_row = mouse_row - pum_size; + if (pum_row < 0) + { + pum_height += pum_row; + pum_row = 0; + } + } + if (Columns - mouse_col >= pum_base_width + || Columns - mouse_col > min_width) + /* Enough space to show at mouse column. */ + pum_col = mouse_col; + else + /* Not enough space, right align with window. */ + pum_col = Columns - (pum_base_width > min_width + ? min_width : pum_base_width); + + pum_width = Columns - pum_col; + if (pum_width > pum_base_width + 1) + pum_width = pum_base_width + 1; +} + +# endif + # if defined(FEAT_BEVAL_TERM) || defined(PROTO) static pumitem_T *balloon_array = NULL; static int balloon_arraysize; @@ -1028,36 +1067,7 @@ ui_post_balloon(char_u *mesg, list_T *list) pum_scrollbar = 0; pum_height = balloon_arraysize; - if (Rows - mouse_row > pum_size) - { - /* Enough space below the mouse row. */ - pum_row = mouse_row + 1; - if (pum_height > Rows - pum_row) - pum_height = Rows - pum_row; - } - else - { - /* Show above the mouse row, reduce height if it does not fit. */ - pum_row = mouse_row - pum_size; - if (pum_row < 0) - { - pum_height += pum_row; - pum_row = 0; - } - } - if (Columns - mouse_col >= pum_base_width - || Columns - mouse_col > BALLOON_MIN_WIDTH) - /* Enough space to show at mouse column. */ - pum_col = mouse_col; - else - /* Not enough space, right align with window. */ - pum_col = Columns - (pum_base_width > BALLOON_MIN_WIDTH - ? BALLOON_MIN_WIDTH : pum_base_width); - - pum_width = Columns - pum_col; - if (pum_width > pum_base_width + 1) - pum_width = pum_base_width + 1; - + pum_position_at_mouse(BALLOON_MIN_WIDTH); pum_selected = -1; pum_first = 0; pum_redraw(); @@ -1075,4 +1085,153 @@ ui_may_remove_balloon(void) } # endif +# if defined(FEAT_TERM_POPUP_MENU) || defined(PROTO) +/* + * Select the pum entry at the mouse position. + */ + static void +pum_select_mouse_pos(void) +{ + int idx = mouse_row - pum_row; + + if (idx < 0 || idx >= pum_size) + pum_selected = -1; + else if (*pum_array[idx].pum_text != NUL) + pum_selected = idx; +} + +/* + * Execute the currently selected popup menu item. + */ + static void +pum_execute_menu(vimmenu_T *menu) +{ + vimmenu_T *mp; + int idx = 0; + exarg_T ea; + + for (mp = menu->children; mp != NULL; mp = mp->next) + if (idx++ == pum_selected) + { + vim_memset(&ea, 0, sizeof(ea)); + execute_menu(&ea, mp); + break; + } +} + +/* + * Open the terminal version of the popup menu and don't return until it is + * closed. + */ + void +pum_show_popupmenu(vimmenu_T *menu) +{ + vimmenu_T *mp; + int idx = 0; + pumitem_T *array; +#ifdef FEAT_BEVAL_TERM + int save_bevalterm = p_bevalterm; +#endif + + pum_undisplay(); + pum_size = 0; + + for (mp = menu->children; mp != NULL; mp = mp->next) + ++pum_size; + + array = (pumitem_T *)alloc_clear((unsigned)sizeof(pumitem_T) * pum_size); + if (array == NULL) + return; + + for (mp = menu->children; mp != NULL; mp = mp->next) + if (menu_is_separator(mp->dname)) + array[idx++].pum_text = (char_u *)""; + else + array[idx++].pum_text = mp->dname; + + pum_array = array; + pum_compute_size(); + pum_scrollbar = 0; + pum_height = pum_size; + pum_position_at_mouse(20); + + pum_selected = -1; + pum_first = 0; +# ifdef FEAT_BEVAL_TERM + p_bevalterm = TRUE; /* track mouse movement */ + mch_setmouse(TRUE); +# endif + + for (;;) + { + int c; + + pum_redraw(); + setcursor(); + out_flush(); + + c = vgetc(); + if (c == ESC) + break; + else if (c == CAR || c == NL) + { + /* enter: select current item, if any, and close */ + pum_execute_menu(menu); + break; + } + else if (c == 'k' || c == K_UP || c == K_MOUSEUP) + { + /* cursor up: select previous item */ + while (pum_selected > 0) + { + --pum_selected; + if (*array[pum_selected].pum_text != NUL) + break; + } + } + else if (c == 'j' || c == K_DOWN || c == K_MOUSEDOWN) + { + /* cursor down: select next item */ + while (pum_selected < pum_size - 1) + { + ++pum_selected; + if (*array[pum_selected].pum_text != NUL) + break; + } + } + else if (c == K_RIGHTMOUSE) + { + /* Right mouse down: reposition the menu. */ + vungetc(c); + break; + } + else if (c == K_LEFTDRAG || c == K_RIGHTDRAG || c == K_MOUSEMOVE) + { + /* mouse moved: selec item in the mouse row */ + pum_select_mouse_pos(); + } + else if (c == K_LEFTMOUSE || c == K_LEFTMOUSE_NM || c == K_RIGHTRELEASE) + { + /* left mouse click: select clicked item, if any, and close; + * right mouse release: select clicked item, close if any */ + pum_select_mouse_pos(); + if (pum_selected >= 0) + { + pum_execute_menu(menu); + break; + } + if (c == K_LEFTMOUSE || c == K_LEFTMOUSE_NM) + break; + } + } + + vim_free(array); + pum_undisplay(); +# ifdef FEAT_BEVAL_TERM + p_bevalterm = save_bevalterm; + mch_setmouse(TRUE); +# endif +} +# endif + #endif diff --git a/src/proto/menu.pro b/src/proto/menu.pro index bd3d26b92c..4c8e710d8f 100644 --- a/src/proto/menu.pro +++ b/src/proto/menu.pro @@ -12,12 +12,13 @@ int menu_is_popup(char_u *name); int menu_is_child_of_popup(vimmenu_T *menu); int menu_is_toolbar(char_u *name); int menu_is_separator(char_u *name); +void show_popupmenu(void); int check_menu_pointer(vimmenu_T *root, vimmenu_T *menu_to_check); void gui_create_initial_menus(vimmenu_T *menu); void gui_update_menus(int modes); int gui_is_menu_shortcut(int key); -void gui_show_popupmenu(void); void gui_mch_toggle_tearoffs(int enable); +void execute_menu(exarg_T *eap, vimmenu_T *menu); void ex_emenu(exarg_T *eap); void winbar_click(win_T *wp, int col); vimmenu_T *gui_find_menu(char_u *path_name); diff --git a/src/proto/popupmnu.pro b/src/proto/popupmnu.pro index 272730433f..d2f6baf46b 100644 --- a/src/proto/popupmnu.pro +++ b/src/proto/popupmnu.pro @@ -9,4 +9,5 @@ int split_message(char_u *mesg, pumitem_T **array); void ui_remove_balloon(void); void ui_post_balloon(char_u *mesg, list_T *list); void ui_may_remove_balloon(void); +void pum_show_popupmenu(vimmenu_T *menu); /* vim: set ft=c : */ diff --git a/src/version.c b/src/version.c index 7d5418592f..f6972163c8 100644 --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1558, /**/ 1557, /**/ From 658a154cbf2362c49a9797d9b2b9b69f481cd940 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 3 Mar 2018 19:29:43 +0100 Subject: [PATCH 4/8] patch 8.0.1559: build failure without GUI Problem: Build failure without GUI. Solution: Adjust #ifdef for get_fpos_of_mouse(). --- src/ui.c | 3 ++- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui.c b/src/ui.c index 5cccd4457d..b758c4f1d0 100644 --- a/src/ui.c +++ b/src/ui.c @@ -3199,7 +3199,8 @@ mouse_find_win(int *rowp, int *colp UNUSED) #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \ || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_PHOTON) || defined(PROTO) + || defined(FEAT_GUI_PHOTON) || defined(FEAT_TERM_POPUP_MENU) \ + || defined(PROTO) /* * Translate window coordinates to buffer position without any side effects */ diff --git a/src/version.c b/src/version.c index f6972163c8..716b29b4d4 100644 --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1559, /**/ 1558, /**/ From 3767b61ad99fe6ff2cace2dccb5d35331786735f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 3 Mar 2018 19:51:58 +0100 Subject: [PATCH 5/8] patch 8.0.1560: build failure without GUI on MS-Windows Problem: Build failure without GUI on MS-Windows. Solution: Adjust #ifdef for vcol2col(). --- src/ui.c | 3 ++- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui.c b/src/ui.c index b758c4f1d0..f89c14525b 100644 --- a/src/ui.c +++ b/src/ui.c @@ -3246,7 +3246,8 @@ get_fpos_of_mouse(pos_T *mpos) #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \ || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_PHOTON) || defined(FEAT_BEVAL) || defined(PROTO) + || defined(FEAT_GUI_PHOTON) || defined(FEAT_BEVAL) \ + || defined(FEAT_TERM_POPUP_MENU) || defined(PROTO) /* * Convert a virtual (screen) column to a character column. * The first column is one. diff --git a/src/version.c b/src/version.c index 716b29b4d4..f8777dcfdf 100644 --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1560, /**/ 1559, /**/ From 069dafc1ded60d9ee0fee4bcecce78ac8a235d87 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 3 Mar 2018 20:02:19 +0100 Subject: [PATCH 6/8] patch 8.0.1561: crash with rust syntax highligting Problem: Crash with rust syntax highligting. (Edd Barrett) Solution: Avoid going past the end of an empty line. --- src/syntax.c | 3 ++- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/syntax.c b/src/syntax.c index 81f4604709..d0d4515e0e 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -2470,7 +2470,8 @@ syn_current_attr( /* nextgroup ends at end of line, unless "skipnl" or "skipempty" present */ if (current_next_list != NULL - && syn_getcurline()[current_col + 1] == NUL + && (line = syn_getcurline())[current_col] != NUL + && line[current_col + 1] == NUL && !(current_next_flags & (HL_SKIPNL | HL_SKIPEMPTY))) current_next_list = NULL; diff --git a/src/version.c b/src/version.c index f8777dcfdf..ae51d723e3 100644 --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1561, /**/ 1560, /**/ From 71137fed4d77e985d49ca32c79f030512767b8ce Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 3 Mar 2018 20:47:21 +0100 Subject: [PATCH 7/8] patch 8.0.1562: the terminal debugger can't set a breakpoint with the mouse Problem: The terminal debugger can't set a breakpoint with the mouse. Solution: Add popup menu entries. --- runtime/doc/terminal.txt | 76 ++++++++++++------- .../dist/opt/termdebug/plugin/termdebug.vim | 68 +++++++++++++---- src/version.c | 2 + 3 files changed, 103 insertions(+), 43 deletions(-) diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index 9a35341f76..4bd0373bef 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -7,8 +7,6 @@ Terminal window support *terminal* -WARNING: THIS IS ONLY PARTLY IMPLEMENTED, ANYTHING CAN STILL CHANGE - The terminal feature is optional, use this to check if your Vim has it: > echo has('terminal') If the result is "1" you have it. @@ -40,7 +38,6 @@ If the result is "1" you have it. {Vi does not have any of these commands} {only available when compiled with the |+terminal| feature} - The terminal feature requires the |+multi_byte|, |+job| and |+channel| features. ============================================================================== @@ -481,7 +478,7 @@ program window A terminal window for the executed program. When "run" is The current window is used to show the source code. When gdb pauses the source file location will be displayed, if possible. A sign is used to -highlight the current position (using highlight group debugPC). +highlight the current position, using highlight group debugPC. If the buffer in the current window is modified, another window will be opened to display the current gdb position. @@ -506,6 +503,7 @@ You should now have three windows: source - where you started, has a window toolbar with buttons gdb - you can type gdb commands here program - the executed program will use this window + You can use CTRL-W CTRL-W or the mouse to move focus between windows. Put focus on the gdb window and type: > break ex_help @@ -526,6 +524,8 @@ displayed: This way you can inspect the value of local variables. You can also focus the gdb window and use a "print" command, e.g.: > print *eap +If mouse pointer movements are working, Vim will also show a balloon when the +mouse rests on text that can be evaluated by gdb. Now go back to the source window and put the cursor on the first line after the for loop, then type: > @@ -561,38 +561,42 @@ Put focus on the gdb window to type commands there. Some common ones are: - frame N go to the Nth stack frame - continue continue execution -In the window showing the source code these commands can used to control gdb: - :Run [args] run the program with [args] or the previous arguments - :Arguments {args} set arguments for the next :Run +In the window showing the source code these commands can be used to control gdb: + `:Run` [args] run the program with [args] or the previous arguments + `:Arguments` {args} set arguments for the next `:Run` - :Break set a breakpoint at the current line; a sign will be displayed - :Delete delete a breakpoint at the current line + `:Break` set a breakpoint at the current line; a sign will be displayed + `:Clear` delete the breakpoint at the current line - :Step execute the gdb "step" command - :Over execute the gdb "next" command (:Next is a Vim command) - :Finish execute the gdb "finish" command - :Continue execute the gdb "continue" command - :Stop interrupt the program + `:Step` execute the gdb "step" command + `:Over` execute the gdb "next" command (`:Next` is a Vim command) + `:Finish` execute the gdb "finish" command + `:Continue` execute the gdb "continue" command + `:Stop` interrupt the program If 'mouse' is set the plugin adds a window toolbar with these entries: - Step :Step - Next :Over - Finish :Finish - Cont :Continue - Stop :Stop - Eval :Evaluate + Step `:Step` + Next `:Over` + Finish `:Finish` + Cont `:Continue` + Stop `:Stop` + Eval `:Evaluate` This way you can use the mouse to perform the most common commands. You need to have the 'mouse' option set to enable mouse clicks. +You can add the window toolbar in other windows you open with: > + :Winbar + Inspecting variables ~ *termdebug-variables* - :Evaluate evaluate the expression under the cursor - K same - :Evaluate {expr} evaluate {expr} - :'<,'>Evaluate evaluate the Visually selected text + `:Evaluate` evaluate the expression under the cursor + `K` same + `:Evaluate` {expr} evaluate {expr} + `:'<,'>Evaluate` evaluate the Visually selected text This is similar to using "print" in the gdb window. +You can usually shorten `:Evaluate` to `:Ev`. Other commands ~ @@ -609,17 +613,21 @@ will break the debugger. Customizing ~ - *termdebug-customizing* + +GDB command *termdebug-customizing* + To change the name of the gdb command, set the "termdebugger" variable before invoking `:Termdebug`: > let termdebugger = "mygdb" -< *gdb-version* +< *gdb-version* Only debuggers fully compatible with gdb will work. Vim uses the GDB/MI interface. This probably requires gdb version 7.12. if you get this error: Undefined command: "new-ui". Try "help".~ Then your gdb is too old. - *hl-debugPC* *hl-debugBreakpoint* + +Colors *hl-debugPC* *hl-debugBreakpoint* + The color of the signs can be adjusted with these highlight groups: - debugPC the current position - debugBreakpoint a breakpoint @@ -632,6 +640,20 @@ When 'background' is "dark": hi debugPC term=reverse ctermbg=darkblue guibg=darkblue hi debugBreakpoint term=reverse ctermbg=red guibg=red + +Popup menu *termdebug_popup* + +By default the Termdebug plugin sets 'mousemodel' to "popup_setpos" and adds +these entries to the popup menu: + Set breakpoint `:Break` + Clear breakpoint `:Clear` + Evaluate `:Evaluate` +If you don't want this then disable it with: > + let g:termdebug_popup = 0 + + +Vim window width *termdebug_wide* + To change the width of the Vim window when debugging starts, and use a vertical split: > let g:termdebug_wide = 163 diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 84ac0de424..add0de9817 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -201,7 +201,7 @@ endfunc " Install commands in the current window to control the debugger. func s:InstallCommands() command Break call s:SetBreakpoint() - command Delete call s:DeleteBreakpoint() + command Clear call s:ClearBreakpoint() command Step call s:SendCommand('-exec-step') command Over call s:SendCommand('-exec-next') command Finish call s:SendCommand('-exec-finish') @@ -212,24 +212,42 @@ func s:InstallCommands() command -range -nargs=* Evaluate call s:Evaluate(, ) command Gdb call win_gotoid(s:gdbwin) command Program call win_gotoid(s:ptywin) + command Winbar call s:InstallWinbar() " TODO: can the K mapping be restored? nnoremap K :Evaluate if has('menu') && &mouse != '' - nnoremenu WinBar.Step :Step - nnoremenu WinBar.Next :Over - nnoremenu WinBar.Finish :Finish - nnoremenu WinBar.Cont :Continue - nnoremenu WinBar.Stop :Stop - nnoremenu WinBar.Eval :Evaluate + call s:InstallWinbar() + + if !exists('g:termdebug_popup') || g:termdebug_popup != 0 + let s:saved_mousemodel = &mousemodel + let &mousemodel = 'popup_setpos' + an 1.200 PopUp.-SEP3- + an 1.210 PopUp.Set\ breakpoint :Break + an 1.220 PopUp.Clear\ breakpoint :Clear + an 1.230 PopUp.Evaluate :Evaluate + endif endif endfunc +let s:winbar_winids = [] + +" Install the window toolbar in the current window. +func s:InstallWinbar() + nnoremenu WinBar.Step :Step + nnoremenu WinBar.Next :Over + nnoremenu WinBar.Finish :Finish + nnoremenu WinBar.Cont :Continue + nnoremenu WinBar.Stop :Stop + nnoremenu WinBar.Eval :Evaluate + call add(s:winbar_winids, win_getid(winnr())) +endfunc + " Delete installed debugger commands in the current window. func s:DeleteCommands() delcommand Break - delcommand Delete + delcommand Clear delcommand Step delcommand Over delcommand Finish @@ -240,16 +258,34 @@ func s:DeleteCommands() delcommand Evaluate delcommand Gdb delcommand Program + delcommand Winbar nunmap K if has('menu') - aunmenu WinBar.Step - aunmenu WinBar.Next - aunmenu WinBar.Finish - aunmenu WinBar.Cont - aunmenu WinBar.Stop - aunmenu WinBar.Eval + " Remove the WinBar entries from all windows where it was added. + let curwinid = win_getid(winnr()) + for winid in s:winbar_winids + if win_gotoid(winid) + aunmenu WinBar.Step + aunmenu WinBar.Next + aunmenu WinBar.Finish + aunmenu WinBar.Cont + aunmenu WinBar.Stop + aunmenu WinBar.Eval + endif + endfor + call win_gotoid(curwinid) + let s:winbar_winids = [] + + if exists('s:saved_mousemodel') + let &mousemodel = s:saved_mousemodel + unlet s:saved_mousemodel + aunmenu PopUp.-SEP3- + aunmenu PopUp.Set\ breakpoint + aunmenu PopUp.Clear\ breakpoint + aunmenu PopUp.Evaluate + endif endif exe 'sign unplace ' . s:pc_id @@ -278,8 +314,8 @@ func s:SetBreakpoint() endif endfunc -" :Delete - Delete a breakpoint at the cursor position. -func s:DeleteBreakpoint() +" :Clear - Delete a breakpoint at the cursor position. +func s:ClearBreakpoint() let fname = fnameescape(expand('%:p')) let lnum = line('.') for [key, val] in items(s:breakpoints) diff --git a/src/version.c b/src/version.c index ae51d723e3..200ed6f2ff 100644 --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1562, /**/ 1561, /**/ From 3f54fd319f6641b4bed478bcc90cdb39ede68e31 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 3 Mar 2018 21:29:55 +0100 Subject: [PATCH 8/8] patch 8.0.1563: timeout of getwinposx() can be too short Problem: Timeout of getwinposx() can be too short. (lilydjwg) Solution: Add getwinpos(). (closes #2689) --- runtime/doc/eval.txt | 17 +++++++++++++---- src/evalfunc.c | 38 ++++++++++++++++++++++++++++++++++++-- src/proto/term.pro | 2 +- src/term.c | 6 +++--- src/version.c | 2 ++ 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 578e5d327f..51f059f4e3 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2192,8 +2192,9 @@ gettabvar({nr}, {varname} [, {def}]) gettabwinvar({tabnr}, {winnr}, {name} [, {def}]) any {name} in {winnr} in tab page {tabnr} getwininfo([{winid}]) List list of windows -getwinposx() Number X coord in pixels of GUI Vim window -getwinposy() Number Y coord in pixels of GUI Vim window +getwinpos([{tmeout}]) List X and Y coord in pixels of the Vim window +getwinposx() Number X coord in pixels of the Vim window +getwinposy() Number Y coord in pixels of the Vim window getwinvar({nr}, {varname} [, {def}]) any variable {varname} in window {nr} glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) @@ -4878,16 +4879,24 @@ gettabwinvar({tabnr}, {winnr}, {varname} [, {def}]) *gettabwinvar()* :let list_is_on = gettabwinvar(1, 2, '&list') :echo "myvar = " . gettabwinvar(3, 1, 'myvar') < +getwinpos([{timeout}]) *getwinpos()* + The result is a list with two numbers, the result of + getwinposx() and getwinposy() combined: + [x-pos, y-pos] + {timeout} can be used to specify how long to wait in msec for + a response from the terminal. When omitted 100 msec is used. + *getwinposx()* getwinposx() The result is a Number, which is the X coordinate in pixels of the left hand side of the GUI Vim window. Also works for an - xterm. + xterm (uses a timeout of 100 msec). The result will be -1 if the information is not available. The value can be used with `:winpos`. *getwinposy()* getwinposy() The result is a Number, which is the Y coordinate in pixels of - the top of the GUI Vim window. Also works for an xterm. + the top of the GUI Vim window. Also works for an xterm (uses + a timeout of 100 msec). The result will be -1 if the information is not available. The value can be used with `:winpos`. diff --git a/src/evalfunc.c b/src/evalfunc.c index e866f4ce1c..b02c956132 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -197,6 +197,7 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv); static void f_gettabvar(typval_T *argvars, typval_T *rettv); static void f_gettabwinvar(typval_T *argvars, typval_T *rettv); static void f_getwininfo(typval_T *argvars, typval_T *rettv); +static void f_getwinpos(typval_T *argvars, typval_T *rettv); static void f_getwinposx(typval_T *argvars, typval_T *rettv); static void f_getwinposy(typval_T *argvars, typval_T *rettv); static void f_getwinvar(typval_T *argvars, typval_T *rettv); @@ -641,6 +642,7 @@ static struct fst {"gettabvar", 2, 3, f_gettabvar}, {"gettabwinvar", 3, 4, f_gettabwinvar}, {"getwininfo", 0, 1, f_getwininfo}, + {"getwinpos", 0, 1, f_getwinpos}, {"getwinposx", 0, 0, f_getwinposx}, {"getwinposy", 0, 0, f_getwinposy}, {"getwinvar", 2, 3, f_getwinvar}, @@ -5526,6 +5528,38 @@ f_win_screenpos(typval_T *argvars, typval_T *rettv) list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1); } +/* + * "getwinpos({timeout})" function + */ + static void +f_getwinpos(typval_T *argvars UNUSED, typval_T *rettv) +{ + int x = -1; + int y = -1; + + if (rettv_list_alloc(rettv) == FAIL) + return; +#ifdef FEAT_GUI + if (gui.in_use) + gui_mch_get_winpos(&x, &y); +# if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE) + else +# endif +#endif +#if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE) + { + varnumber_T timeout = 100; + + if (argvars[0].v_type != VAR_UNKNOWN) + timeout = get_tv_number(&argvars[0]); + term_get_winpos(&x, &y, timeout); + } +#endif + list_append_number(rettv->vval.v_list, (varnumber_T)x); + list_append_number(rettv->vval.v_list, (varnumber_T)y); +} + + /* * "getwinposx()" function */ @@ -5547,7 +5581,7 @@ f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv) { int x, y; - if (term_get_winpos(&x, &y) == OK) + if (term_get_winpos(&x, &y, (varnumber_T)100) == OK) rettv->vval.v_number = x; } #endif @@ -5574,7 +5608,7 @@ f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv) { int x, y; - if (term_get_winpos(&x, &y) == OK) + if (term_get_winpos(&x, &y, (varnumber_T)100) == OK) rettv->vval.v_number = y; } #endif diff --git a/src/proto/term.pro b/src/proto/term.pro index 92cb26d58b..42405dda5f 100644 --- a/src/proto/term.pro +++ b/src/proto/term.pro @@ -24,7 +24,7 @@ void term_cursor_right(int i); void term_append_lines(int line_count); void term_delete_lines(int line_count); void term_set_winpos(int x, int y); -int term_get_winpos(int *x, int *y); +int term_get_winpos(int *x, int *y, varnumber_T timeout); void term_set_winsize(int height, int width); void term_fg_color(int n); void term_bg_color(int n); diff --git a/src/term.c b/src/term.c index 12c4f2e5bd..7dbbefa49a 100644 --- a/src/term.c +++ b/src/term.c @@ -2789,7 +2789,7 @@ static int waiting_for_winpos = FALSE; * Returns OK or FAIL. */ int -term_get_winpos(int *x, int *y) +term_get_winpos(int *x, int *y, varnumber_T timeout) { int count = 0; @@ -2801,8 +2801,8 @@ term_get_winpos(int *x, int *y) OUT_STR(T_CGP); out_flush(); - /* Try reading the result for 100 msec. */ - while (count++ < 10) + /* Try reading the result for "timeout" msec. */ + while (count++ < timeout / 10) { (void)vpeekc_nomap(); if (winpos_x >= 0 && winpos_y >= 0) diff --git a/src/version.c b/src/version.c index 200ed6f2ff..c780826e65 100644 --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1563, /**/ 1562, /**/