aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/normal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/normal.c')
-rw-r--r--src/nvim/normal.c1437
1 files changed, 767 insertions, 670 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index c95e5e1a15..0e3946740a 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1,8 +1,11 @@
-/*
- * normal.c: Contains the main routine for processing characters in command
- * mode. Communicates closely with the code in ops.c to handle
- * the operators.
- */
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
+//
+// normal.c: Contains the main routine for processing characters in command
+// mode. Communicates closely with the code in ops.c to handle
+// the operators.
+//
#include <assert.h>
#include <inttypes.h>
@@ -10,6 +13,7 @@
#include <stdbool.h>
#include <stdlib.h>
+#include "nvim/log.h"
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/normal.h"
@@ -36,7 +40,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/move.h"
#include "nvim/mouse.h"
@@ -46,6 +49,7 @@
#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/spell.h"
+#include "nvim/spellfile.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
@@ -60,12 +64,9 @@
typedef struct normal_state {
VimState state;
- linenr_T conceal_old_cursor_line;
- linenr_T conceal_new_cursor_line;
bool command_finished;
bool ctrl_w;
bool need_flushbuf;
- bool conceal_update_lines;
bool set_prevcount;
bool previous_got_int; // `got_int` was true
bool cmdwin; // command-line window normal mode
@@ -153,196 +154,195 @@ static const struct nv_cmd {
short cmd_arg; /* value for ca.arg */
} nv_cmds[] =
{
- {NUL, nv_error, 0, 0},
- {Ctrl_A, nv_addsub, 0, 0},
- {Ctrl_B, nv_page, NV_STS, BACKWARD},
- {Ctrl_C, nv_esc, 0, true},
- {Ctrl_D, nv_halfpage, 0, 0},
- {Ctrl_E, nv_scroll_line, 0, true},
- {Ctrl_F, nv_page, NV_STS, FORWARD},
- {Ctrl_G, nv_ctrlg, 0, 0},
- {Ctrl_H, nv_ctrlh, 0, 0},
- {Ctrl_I, nv_pcmark, 0, 0},
- {NL, nv_down, 0, false},
- {Ctrl_K, nv_error, 0, 0},
- {Ctrl_L, nv_clear, 0, 0},
- {Ctrl_M, nv_down, 0, true},
- {Ctrl_N, nv_down, NV_STS, false},
- {Ctrl_O, nv_ctrlo, 0, 0},
- {Ctrl_P, nv_up, NV_STS, false},
- {Ctrl_Q, nv_visual, 0, false},
- {Ctrl_R, nv_redo, 0, 0},
- {Ctrl_S, nv_ignore, 0, 0},
- {Ctrl_T, nv_tagpop, NV_NCW, 0},
- {Ctrl_U, nv_halfpage, 0, 0},
- {Ctrl_V, nv_visual, 0, false},
- {'V', nv_visual, 0, false},
- {'v', nv_visual, 0, false},
- {Ctrl_W, nv_window, 0, 0},
- {Ctrl_X, nv_addsub, 0, 0},
- {Ctrl_Y, nv_scroll_line, 0, false},
- {Ctrl_Z, nv_suspend, 0, 0},
- {ESC, nv_esc, 0, false},
- {Ctrl_BSL, nv_normal, NV_NCH_ALW, 0},
- {Ctrl_RSB, nv_ident, NV_NCW, 0},
- {Ctrl_HAT, nv_hat, NV_NCW, 0},
- {Ctrl__, nv_error, 0, 0},
- {' ', nv_right, 0, 0},
- {'!', nv_operator, 0, 0},
- {'"', nv_regname, NV_NCH_NOP|NV_KEEPREG, 0},
- {'#', nv_ident, 0, 0},
- {'$', nv_dollar, 0, 0},
- {'%', nv_percent, 0, 0},
- {'&', nv_optrans, 0, 0},
- {'\'', nv_gomark, NV_NCH_ALW, true},
- {'(', nv_brace, 0, BACKWARD},
- {')', nv_brace, 0, FORWARD},
- {'*', nv_ident, 0, 0},
- {'+', nv_down, 0, true},
- {',', nv_csearch, 0, true},
- {'-', nv_up, 0, true},
- {'.', nv_dot, NV_KEEPREG, 0},
- {'/', nv_search, 0, false},
- {'0', nv_beginline, 0, 0},
- {'1', nv_ignore, 0, 0},
- {'2', nv_ignore, 0, 0},
- {'3', nv_ignore, 0, 0},
- {'4', nv_ignore, 0, 0},
- {'5', nv_ignore, 0, 0},
- {'6', nv_ignore, 0, 0},
- {'7', nv_ignore, 0, 0},
- {'8', nv_ignore, 0, 0},
- {'9', nv_ignore, 0, 0},
- {':', nv_colon, 0, 0},
- {';', nv_csearch, 0, false},
- {'<', nv_operator, NV_RL, 0},
- {'=', nv_operator, 0, 0},
- {'>', nv_operator, NV_RL, 0},
- {'?', nv_search, 0, false},
- {'@', nv_at, NV_NCH_NOP, false},
- {'A', nv_edit, 0, 0},
- {'B', nv_bck_word, 0, 1},
- {'C', nv_abbrev, NV_KEEPREG, 0},
- {'D', nv_abbrev, NV_KEEPREG, 0},
- {'E', nv_wordcmd, 0, true},
- {'F', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD},
- {'G', nv_goto, 0, true},
- {'H', nv_scroll, 0, 0},
- {'I', nv_edit, 0, 0},
- {'J', nv_join, 0, 0},
- {'K', nv_ident, 0, 0},
- {'L', nv_scroll, 0, 0},
- {'M', nv_scroll, 0, 0},
- {'N', nv_next, 0, SEARCH_REV},
- {'O', nv_open, 0, 0},
- {'P', nv_put, 0, 0},
- {'Q', nv_exmode, NV_NCW, 0},
- {'R', nv_Replace, 0, false},
- {'S', nv_subst, NV_KEEPREG, 0},
- {'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD},
- {'U', nv_Undo, 0, 0},
- {'W', nv_wordcmd, 0, true},
- {'X', nv_abbrev, NV_KEEPREG, 0},
- {'Y', nv_abbrev, NV_KEEPREG, 0},
- {'Z', nv_Zet, NV_NCH_NOP|NV_NCW, 0},
- {'[', nv_brackets, NV_NCH_ALW, BACKWARD},
- {'\\', nv_error, 0, 0},
- {']', nv_brackets, NV_NCH_ALW, FORWARD},
- {'^', nv_beginline, 0, BL_WHITE | BL_FIX},
- {'_', nv_lineop, 0, 0},
- {'`', nv_gomark, NV_NCH_ALW, false},
- {'a', nv_edit, NV_NCH, 0},
- {'b', nv_bck_word, 0, 0},
- {'c', nv_operator, 0, 0},
- {'d', nv_operator, 0, 0},
- {'e', nv_wordcmd, 0, false},
- {'f', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD},
- {'g', nv_g_cmd, NV_NCH_ALW, false},
- {'h', nv_left, NV_RL, 0},
- {'i', nv_edit, NV_NCH, 0},
- {'j', nv_down, 0, false},
- {'k', nv_up, 0, false},
- {'l', nv_right, NV_RL, 0},
- {'m', nv_mark, NV_NCH_NOP, 0},
- {'n', nv_next, 0, 0},
- {'o', nv_open, 0, 0},
- {'p', nv_put, 0, 0},
- {'q', nv_record, NV_NCH, 0},
- {'r', nv_replace, NV_NCH_NOP|NV_LANG, 0},
- {'s', nv_subst, NV_KEEPREG, 0},
- {'t', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD},
- {'u', nv_undo, 0, 0},
- {'w', nv_wordcmd, 0, false},
- {'x', nv_abbrev, NV_KEEPREG, 0},
- {'y', nv_operator, 0, 0},
- {'z', nv_zet, NV_NCH_ALW, 0},
- {'{', nv_findpar, 0, BACKWARD},
- {'|', nv_pipe, 0, 0},
- {'}', nv_findpar, 0, FORWARD},
- {'~', nv_tilde, 0, 0},
-
- /* pound sign */
- {POUND, nv_ident, 0, 0},
- {K_MOUSEUP, nv_mousescroll, 0, MSCR_UP},
- {K_MOUSEDOWN, nv_mousescroll, 0, MSCR_DOWN},
- {K_MOUSELEFT, nv_mousescroll, 0, MSCR_LEFT},
- {K_MOUSERIGHT, nv_mousescroll, 0, MSCR_RIGHT},
- {K_LEFTMOUSE, nv_mouse, 0, 0},
- {K_LEFTMOUSE_NM, nv_mouse, 0, 0},
- {K_LEFTDRAG, nv_mouse, 0, 0},
- {K_LEFTRELEASE, nv_mouse, 0, 0},
- {K_LEFTRELEASE_NM, nv_mouse, 0, 0},
- {K_MIDDLEMOUSE, nv_mouse, 0, 0},
- {K_MIDDLEDRAG, nv_mouse, 0, 0},
- {K_MIDDLERELEASE, nv_mouse, 0, 0},
- {K_RIGHTMOUSE, nv_mouse, 0, 0},
- {K_RIGHTDRAG, nv_mouse, 0, 0},
- {K_RIGHTRELEASE, nv_mouse, 0, 0},
- {K_X1MOUSE, nv_mouse, 0, 0},
- {K_X1DRAG, nv_mouse, 0, 0},
- {K_X1RELEASE, nv_mouse, 0, 0},
- {K_X2MOUSE, nv_mouse, 0, 0},
- {K_X2DRAG, nv_mouse, 0, 0},
- {K_X2RELEASE, nv_mouse, 0, 0},
- {K_IGNORE, nv_ignore, NV_KEEPREG, 0},
- {K_NOP, nv_nop, 0, 0},
- {K_INS, nv_edit, 0, 0},
- {K_KINS, nv_edit, 0, 0},
- {K_BS, nv_ctrlh, 0, 0},
- {K_UP, nv_up, NV_SSS|NV_STS, false},
- {K_S_UP, nv_page, NV_SS, BACKWARD},
- {K_DOWN, nv_down, NV_SSS|NV_STS, false},
- {K_S_DOWN, nv_page, NV_SS, FORWARD},
- {K_LEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0},
- {K_S_LEFT, nv_bck_word, NV_SS|NV_RL, 0},
- {K_C_LEFT, nv_bck_word, NV_SSS|NV_RL|NV_STS, 1},
- {K_RIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0},
- {K_S_RIGHT, nv_wordcmd, NV_SS|NV_RL, false},
- {K_C_RIGHT, nv_wordcmd, NV_SSS|NV_RL|NV_STS, true},
- {K_PAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD},
- {K_KPAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD},
- {K_PAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD},
- {K_KPAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD},
- {K_END, nv_end, NV_SSS|NV_STS, false},
- {K_KEND, nv_end, NV_SSS|NV_STS, false},
- {K_S_END, nv_end, NV_SS, false},
- {K_C_END, nv_end, NV_SSS|NV_STS, true},
- {K_HOME, nv_home, NV_SSS|NV_STS, 0},
- {K_KHOME, nv_home, NV_SSS|NV_STS, 0},
- {K_S_HOME, nv_home, NV_SS, 0},
- {K_C_HOME, nv_goto, NV_SSS|NV_STS, false},
- {K_DEL, nv_abbrev, 0, 0},
- {K_KDEL, nv_abbrev, 0, 0},
- {K_UNDO, nv_kundo, 0, 0},
- {K_HELP, nv_help, NV_NCW, 0},
- {K_F1, nv_help, NV_NCW, 0},
- {K_XF1, nv_help, NV_NCW, 0},
- {K_SELECT, nv_select, 0, 0},
- {K_F8, farsi_fkey, 0, 0},
- {K_F9, farsi_fkey, 0, 0},
- {K_EVENT, nv_event, NV_KEEPREG, 0},
- {K_FOCUSGAINED, nv_focusgained, NV_KEEPREG, 0},
- {K_FOCUSLOST, nv_focuslost, NV_KEEPREG, 0},
+ { NUL, nv_error, 0, 0 },
+ { Ctrl_A, nv_addsub, 0, 0 },
+ { Ctrl_B, nv_page, NV_STS, BACKWARD },
+ { Ctrl_C, nv_esc, 0, true },
+ { Ctrl_D, nv_halfpage, 0, 0 },
+ { Ctrl_E, nv_scroll_line, 0, true },
+ { Ctrl_F, nv_page, NV_STS, FORWARD },
+ { Ctrl_G, nv_ctrlg, 0, 0 },
+ { Ctrl_H, nv_ctrlh, 0, 0 },
+ { Ctrl_I, nv_pcmark, 0, 0 },
+ { NL, nv_down, 0, false },
+ { Ctrl_K, nv_error, 0, 0 },
+ { Ctrl_L, nv_clear, 0, 0 },
+ { Ctrl_M, nv_down, 0, true },
+ { Ctrl_N, nv_down, NV_STS, false },
+ { Ctrl_O, nv_ctrlo, 0, 0 },
+ { Ctrl_P, nv_up, NV_STS, false },
+ { Ctrl_Q, nv_visual, 0, false },
+ { Ctrl_R, nv_redo, 0, 0 },
+ { Ctrl_S, nv_ignore, 0, 0 },
+ { Ctrl_T, nv_tagpop, NV_NCW, 0 },
+ { Ctrl_U, nv_halfpage, 0, 0 },
+ { Ctrl_V, nv_visual, 0, false },
+ { 'V', nv_visual, 0, false },
+ { 'v', nv_visual, 0, false },
+ { Ctrl_W, nv_window, 0, 0 },
+ { Ctrl_X, nv_addsub, 0, 0 },
+ { Ctrl_Y, nv_scroll_line, 0, false },
+ { Ctrl_Z, nv_suspend, 0, 0 },
+ { ESC, nv_esc, 0, false },
+ { Ctrl_BSL, nv_normal, NV_NCH_ALW, 0 },
+ { Ctrl_RSB, nv_ident, NV_NCW, 0 },
+ { Ctrl_HAT, nv_hat, NV_NCW, 0 },
+ { Ctrl__, nv_error, 0, 0 },
+ { ' ', nv_right, 0, 0 },
+ { '!', nv_operator, 0, 0 },
+ { '"', nv_regname, NV_NCH_NOP|NV_KEEPREG, 0 },
+ { '#', nv_ident, 0, 0 },
+ { '$', nv_dollar, 0, 0 },
+ { '%', nv_percent, 0, 0 },
+ { '&', nv_optrans, 0, 0 },
+ { '\'', nv_gomark, NV_NCH_ALW, true },
+ { '(', nv_brace, 0, BACKWARD },
+ { ')', nv_brace, 0, FORWARD },
+ { '*', nv_ident, 0, 0 },
+ { '+', nv_down, 0, true },
+ { ',', nv_csearch, 0, true },
+ { '-', nv_up, 0, true },
+ { '.', nv_dot, NV_KEEPREG, 0 },
+ { '/', nv_search, 0, false },
+ { '0', nv_beginline, 0, 0 },
+ { '1', nv_ignore, 0, 0 },
+ { '2', nv_ignore, 0, 0 },
+ { '3', nv_ignore, 0, 0 },
+ { '4', nv_ignore, 0, 0 },
+ { '5', nv_ignore, 0, 0 },
+ { '6', nv_ignore, 0, 0 },
+ { '7', nv_ignore, 0, 0 },
+ { '8', nv_ignore, 0, 0 },
+ { '9', nv_ignore, 0, 0 },
+ { ':', nv_colon, 0, 0 },
+ { ';', nv_csearch, 0, false },
+ { '<', nv_operator, NV_RL, 0 },
+ { '=', nv_operator, 0, 0 },
+ { '>', nv_operator, NV_RL, 0 },
+ { '?', nv_search, 0, false },
+ { '@', nv_at, NV_NCH_NOP, false },
+ { 'A', nv_edit, 0, 0 },
+ { 'B', nv_bck_word, 0, 1 },
+ { 'C', nv_abbrev, NV_KEEPREG, 0 },
+ { 'D', nv_abbrev, NV_KEEPREG, 0 },
+ { 'E', nv_wordcmd, 0, true },
+ { 'F', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD },
+ { 'G', nv_goto, 0, true },
+ { 'H', nv_scroll, 0, 0 },
+ { 'I', nv_edit, 0, 0 },
+ { 'J', nv_join, 0, 0 },
+ { 'K', nv_ident, 0, 0 },
+ { 'L', nv_scroll, 0, 0 },
+ { 'M', nv_scroll, 0, 0 },
+ { 'N', nv_next, 0, SEARCH_REV },
+ { 'O', nv_open, 0, 0 },
+ { 'P', nv_put, 0, 0 },
+ { 'Q', nv_exmode, NV_NCW, 0 },
+ { 'R', nv_Replace, 0, false },
+ { 'S', nv_subst, NV_KEEPREG, 0 },
+ { 'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD },
+ { 'U', nv_Undo, 0, 0 },
+ { 'W', nv_wordcmd, 0, true },
+ { 'X', nv_abbrev, NV_KEEPREG, 0 },
+ { 'Y', nv_abbrev, NV_KEEPREG, 0 },
+ { 'Z', nv_Zet, NV_NCH_NOP|NV_NCW, 0 },
+ { '[', nv_brackets, NV_NCH_ALW, BACKWARD },
+ { '\\', nv_error, 0, 0 },
+ { ']', nv_brackets, NV_NCH_ALW, FORWARD },
+ { '^', nv_beginline, 0, BL_WHITE | BL_FIX },
+ { '_', nv_lineop, 0, 0 },
+ { '`', nv_gomark, NV_NCH_ALW, false },
+ { 'a', nv_edit, NV_NCH, 0 },
+ { 'b', nv_bck_word, 0, 0 },
+ { 'c', nv_operator, 0, 0 },
+ { 'd', nv_operator, 0, 0 },
+ { 'e', nv_wordcmd, 0, false },
+ { 'f', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD },
+ { 'g', nv_g_cmd, NV_NCH_ALW, false },
+ { 'h', nv_left, NV_RL, 0 },
+ { 'i', nv_edit, NV_NCH, 0 },
+ { 'j', nv_down, 0, false },
+ { 'k', nv_up, 0, false },
+ { 'l', nv_right, NV_RL, 0 },
+ { 'm', nv_mark, NV_NCH_NOP, 0 },
+ { 'n', nv_next, 0, 0 },
+ { 'o', nv_open, 0, 0 },
+ { 'p', nv_put, 0, 0 },
+ { 'q', nv_record, NV_NCH, 0 },
+ { 'r', nv_replace, NV_NCH_NOP|NV_LANG, 0 },
+ { 's', nv_subst, NV_KEEPREG, 0 },
+ { 't', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD },
+ { 'u', nv_undo, 0, 0 },
+ { 'w', nv_wordcmd, 0, false },
+ { 'x', nv_abbrev, NV_KEEPREG, 0 },
+ { 'y', nv_operator, 0, 0 },
+ { 'z', nv_zet, NV_NCH_ALW, 0 },
+ { '{', nv_findpar, 0, BACKWARD },
+ { '|', nv_pipe, 0, 0 },
+ { '}', nv_findpar, 0, FORWARD },
+ { '~', nv_tilde, 0, 0 },
+
+ // pound sign
+ { POUND, nv_ident, 0, 0 },
+ { K_MOUSEUP, nv_mousescroll, 0, MSCR_UP },
+ { K_MOUSEDOWN, nv_mousescroll, 0, MSCR_DOWN },
+ { K_MOUSELEFT, nv_mousescroll, 0, MSCR_LEFT },
+ { K_MOUSERIGHT, nv_mousescroll, 0, MSCR_RIGHT },
+ { K_LEFTMOUSE, nv_mouse, 0, 0 },
+ { K_LEFTMOUSE_NM, nv_mouse, 0, 0 },
+ { K_LEFTDRAG, nv_mouse, 0, 0 },
+ { K_LEFTRELEASE, nv_mouse, 0, 0 },
+ { K_LEFTRELEASE_NM, nv_mouse, 0, 0 },
+ { K_MIDDLEMOUSE, nv_mouse, 0, 0 },
+ { K_MIDDLEDRAG, nv_mouse, 0, 0 },
+ { K_MIDDLERELEASE, nv_mouse, 0, 0 },
+ { K_RIGHTMOUSE, nv_mouse, 0, 0 },
+ { K_RIGHTDRAG, nv_mouse, 0, 0 },
+ { K_RIGHTRELEASE, nv_mouse, 0, 0 },
+ { K_X1MOUSE, nv_mouse, 0, 0 },
+ { K_X1DRAG, nv_mouse, 0, 0 },
+ { K_X1RELEASE, nv_mouse, 0, 0 },
+ { K_X2MOUSE, nv_mouse, 0, 0 },
+ { K_X2DRAG, nv_mouse, 0, 0 },
+ { K_X2RELEASE, nv_mouse, 0, 0 },
+ { K_IGNORE, nv_ignore, NV_KEEPREG, 0 },
+ { K_NOP, nv_nop, 0, 0 },
+ { K_INS, nv_edit, 0, 0 },
+ { K_KINS, nv_edit, 0, 0 },
+ { K_BS, nv_ctrlh, 0, 0 },
+ { K_UP, nv_up, NV_SSS|NV_STS, false },
+ { K_S_UP, nv_page, NV_SS, BACKWARD },
+ { K_DOWN, nv_down, NV_SSS|NV_STS, false },
+ { K_S_DOWN, nv_page, NV_SS, FORWARD },
+ { K_LEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0 },
+ { K_S_LEFT, nv_bck_word, NV_SS|NV_RL, 0 },
+ { K_C_LEFT, nv_bck_word, NV_SSS|NV_RL|NV_STS, 1 },
+ { K_RIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0 },
+ { K_S_RIGHT, nv_wordcmd, NV_SS|NV_RL, false },
+ { K_C_RIGHT, nv_wordcmd, NV_SSS|NV_RL|NV_STS, true },
+ { K_PAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD },
+ { K_KPAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD },
+ { K_PAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD },
+ { K_KPAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD },
+ { K_END, nv_end, NV_SSS|NV_STS, false },
+ { K_KEND, nv_end, NV_SSS|NV_STS, false },
+ { K_S_END, nv_end, NV_SS, false },
+ { K_C_END, nv_end, NV_SSS|NV_STS, true },
+ { K_HOME, nv_home, NV_SSS|NV_STS, 0 },
+ { K_KHOME, nv_home, NV_SSS|NV_STS, 0 },
+ { K_S_HOME, nv_home, NV_SS, 0 },
+ { K_C_HOME, nv_goto, NV_SSS|NV_STS, false },
+ { K_DEL, nv_abbrev, 0, 0 },
+ { K_KDEL, nv_abbrev, 0, 0 },
+ { K_UNDO, nv_kundo, 0, 0 },
+ { K_HELP, nv_help, NV_NCW, 0 },
+ { K_F1, nv_help, NV_NCW, 0 },
+ { K_XF1, nv_help, NV_NCW, 0 },
+ { K_SELECT, nv_select, 0, 0 },
+ { K_F8, farsi_f8, 0, 0 },
+ { K_F9, farsi_f9, 0, 0 },
+ { K_EVENT, nv_event, NV_KEEPREG, 0 },
+ { K_COMMAND, nv_colon, 0, 0 },
};
/* Number of commands in nv_cmds[]. */
@@ -460,7 +460,7 @@ void normal_enter(bool cmdwin, bool noexmode)
normal_state_init(&state);
state.cmdwin = cmdwin;
state.noexmode = noexmode;
- state.toplevel = !cmdwin && !noexmode;
+ state.toplevel = (!cmdwin || cmdwin_result == 0) && !noexmode;
state_enter(&state.state);
}
@@ -538,7 +538,7 @@ static bool normal_handle_special_visual_command(NormalState *s)
return false;
}
-static bool normal_need_aditional_char(NormalState *s)
+static bool normal_need_additional_char(NormalState *s)
{
int flags = nv_cmds[s->idx].cmd_flags;
bool pending_op = s->oa.op_type != OP_NOP;
@@ -618,7 +618,7 @@ static void normal_redraw_mode_message(NormalState *s)
update_screen(0);
// now reset it, otherwise it's put in the history again
keep_msg = kmsg;
- msg_attr(kmsg, keep_msg_attr);
+ msg_attr((const char *)kmsg, keep_msg_attr);
xfree(kmsg);
}
setcursor();
@@ -642,8 +642,7 @@ static void normal_get_additional_char(NormalState *s)
bool langmap_active = false; // using :lmap mappings
int lang; // getting a text character
- ++no_mapping;
- ++allow_keys; // no mapping for nchar, but allow key codes
+ no_mapping++;
// Don't generate a CursorHold event here, most commands can't handle
// it, e.g., nv_replace(), nv_csearch().
did_cursorhold = true;
@@ -681,8 +680,7 @@ static void normal_get_additional_char(NormalState *s)
}
if (lang && curbuf->b_p_iminsert == B_IMODE_LMAP) {
// Allow mappings defined with ":lmap".
- --no_mapping;
- --allow_keys;
+ no_mapping--;
if (repl) {
State = LREPLACE;
} else {
@@ -695,9 +693,7 @@ static void normal_get_additional_char(NormalState *s)
if (langmap_active) {
// Undo the decrement done above
- ++no_mapping;
- ++allow_keys;
- State = NORMAL_BUSY;
+ no_mapping++;
}
State = NORMAL_BUSY;
s->need_flushbuf |= add_to_showcmd(*cp);
@@ -781,8 +777,7 @@ static void normal_get_additional_char(NormalState *s)
}
no_mapping++;
}
- --no_mapping;
- --allow_keys;
+ no_mapping--;
}
static void normal_invert_horizontal(NormalState *s)
@@ -832,8 +827,7 @@ static bool normal_get_command_count(NormalState *s)
}
if (s->ctrl_w) {
- ++no_mapping;
- ++allow_keys; // no mapping for nchar, but keys
+ no_mapping++;
}
++no_zero_mapping; // don't map zero here
@@ -841,8 +835,7 @@ static bool normal_get_command_count(NormalState *s)
LANGMAP_ADJUST(s->c, true);
--no_zero_mapping;
if (s->ctrl_w) {
- --no_mapping;
- --allow_keys;
+ no_mapping--;
}
s->need_flushbuf |= add_to_showcmd(s->c);
}
@@ -852,12 +845,10 @@ static bool normal_get_command_count(NormalState *s)
s->ctrl_w = true;
s->ca.opcount = s->ca.count0; // remember first count
s->ca.count0 = 0;
- ++no_mapping;
- ++allow_keys; // no mapping for nchar, but keys
+ no_mapping++;
s->c = plain_vgetc(); // get next character
LANGMAP_ADJUST(s->c, true);
- --no_mapping;
- --allow_keys;
+ no_mapping--;
s->need_flushbuf |= add_to_showcmd(s->c);
return true;
}
@@ -925,9 +916,7 @@ normal_end:
checkpcmark(); // check if we moved since setting pcmark
xfree(s->ca.searchbuf);
- if (has_mbyte) {
- mb_adjust_cursor();
- }
+ mb_check_adjust_col(curwin); // #6203
if (curwin->w_p_scb && s->toplevel) {
validate_cursor(); // may need to update w_leftcol
@@ -1091,7 +1080,7 @@ static int normal_execute(VimState *state, int key)
}
// Get an additional character if we need one.
- if (normal_need_aditional_char(s)) {
+ if (normal_need_additional_char(s)) {
normal_get_additional_char(s);
}
@@ -1131,6 +1120,7 @@ static int normal_execute(VimState *state, int key)
start_selection();
unshift_special(&s->ca);
s->idx = find_command(s->ca.cmdchar);
+ assert(s->idx >= 0);
} else if ((nv_cmds[s->idx].cmd_flags & NV_SSS)
&& (mod_mask & MOD_MASK_SHIFT)) {
start_selection();
@@ -1164,7 +1154,7 @@ static void normal_check_stuff_buffer(NormalState *s)
if (need_start_insertmode && goto_im() && !VIsual_active) {
need_start_insertmode = false;
- stuffReadbuff((uint8_t *)"i"); // start insert mode next
+ stuffReadbuff("i"); // start insert mode next
// skip the fileinfo message now, because it would be shown
// after insert mode finishes!
need_fileinfo = false;
@@ -1208,27 +1198,17 @@ static void normal_check_cursor_moved(NormalState *s)
apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, false, curbuf);
}
- if (curwin->w_p_cole > 0) {
- s->conceal_old_cursor_line = last_cursormoved.lnum;
- s->conceal_new_cursor_line = curwin->w_cursor.lnum;
- s->conceal_update_lines = true;
- }
-
last_cursormoved = curwin->w_cursor;
}
}
static void normal_check_text_changed(NormalState *s)
{
- // Trigger TextChanged if b_changedtick differs.
+ // Trigger TextChanged if changedtick differs.
if (!finish_op && has_event(EVENT_TEXTCHANGED)
- && last_changedtick != curbuf->b_changedtick) {
- if (last_changedtick_buf == curbuf) {
- apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, false, curbuf);
- }
-
- last_changedtick_buf = curbuf;
- last_changedtick = curbuf->b_changedtick;
+ && curbuf->b_last_changedtick != buf_get_changedtick(curbuf)) {
+ apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, false, curbuf);
+ curbuf->b_last_changedtick = buf_get_changedtick(curbuf);
}
}
@@ -1257,6 +1237,13 @@ static void normal_redraw(NormalState *s)
update_topline();
validate_cursor();
+ // If the cursor moves horizontally when 'concealcursor' is active, then the
+ // current line needs to be redrawn in order to calculate the correct
+ // cursor position.
+ if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin)) {
+ redrawWinline(curwin, curwin->w_cursor.lnum);
+ }
+
if (VIsual_active) {
update_curbuf(INVERTED); // update inverted part
} else if (must_redraw) {
@@ -1276,11 +1263,12 @@ static void normal_redraw(NormalState *s)
// msg_attr_keep() will set keep_msg to NULL, must free the string here.
// Don't reset keep_msg, msg_attr_keep() uses it to check for duplicates.
char *p = (char *)keep_msg;
- msg_attr((uint8_t *)p, keep_msg_attr);
+ msg_attr(p, keep_msg_attr);
xfree(p);
}
- if (need_fileinfo) { // show file info after redraw
+ // show fileinfo after redraw
+ if (need_fileinfo && !shortmess(SHM_FILEINFO)) {
fileinfo(false, true, false);
need_fileinfo = false;
}
@@ -1291,22 +1279,6 @@ static void normal_redraw(NormalState *s)
may_clear_sb_text(); // clear scroll-back text on next msg
showruler(false);
- if (s->conceal_update_lines
- && (s->conceal_old_cursor_line !=
- s->conceal_new_cursor_line
- || conceal_cursor_line(curwin)
- || need_cursor_line_redraw)) {
- if (s->conceal_old_cursor_line !=
- s->conceal_new_cursor_line
- && s->conceal_old_cursor_line <=
- curbuf->b_ml.ml_line_count) {
- update_single_line(curwin, s->conceal_old_cursor_line);
- }
-
- update_single_line(curwin, s->conceal_new_cursor_line);
- curwin->w_valid &= ~VALID_CROW;
- }
-
setcursor();
}
@@ -1335,6 +1307,14 @@ static int normal_check(VimState *state)
normal_check_cursor_moved(s);
normal_check_text_changed(s);
+ // Updating diffs from changed() does not always work properly,
+ // esp. updating folds. Do an update just before redrawing if
+ // needed.
+ if (curtab->tp_diff_update || curtab->tp_diff_invalid) {
+ ex_diffupdate(NULL);
+ curtab->tp_diff_update = false;
+ }
+
// Scroll-binding for diff mode may have been postponed until
// here. Avoids doing it for every change.
if (diff_need_scrollbind) {
@@ -1361,7 +1341,7 @@ static int normal_check(VimState *state)
// Dict internally somewhere.
// "may_garbage_collect" is reset in vgetc() which is invoked through
// do_exmode() and normal_cmd().
- may_garbage_collect = s->toplevel;
+ may_garbage_collect = !s->cmdwin && !s->noexmode;
// Update w_curswant if w_set_curswant has been set.
// Postponed until here to avoid computing w_virtcol too often.
@@ -1447,8 +1427,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
oap->motion_type = kMTCharWise;
} else if (oap->motion_force == Ctrl_V) {
// Change line- or characterwise motion into Visual block mode.
- VIsual_active = true;
- VIsual = oap->start;
+ if (!VIsual_active) {
+ VIsual_active = true;
+ VIsual = oap->start;
+ }
VIsual_mode = Ctrl_V;
VIsual_select = false;
VIsual_reselect = false;
@@ -1458,9 +1440,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
/* Never redo "zf" (define fold). */
if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK)
&& ((!VIsual_active || oap->motion_force)
- /* Also redo Operator-pending Visual mode mappings */
- || (VIsual_active && cap->cmdchar == ':'
- && oap->op_type != OP_COLON))
+ // Also redo Operator-pending Visual mode mappings.
+ || (cap->cmdchar == ':' && oap->op_type != OP_COLON))
&& cap->cmdchar != 'D'
&& oap->op_type != OP_FOLD
&& oap->op_type != OP_FOLDOPEN
@@ -1478,16 +1459,17 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
* If 'cpoptions' does not contain 'r', insert the search
* pattern to really repeat the same command.
*/
- if (vim_strchr(p_cpo, CPO_REDO) == NULL)
+ if (vim_strchr(p_cpo, CPO_REDO) == NULL) {
AppendToRedobuffLit(cap->searchbuf, -1);
+ }
AppendToRedobuff(NL_STR);
- } else if (cap->cmdchar == ':') {
- /* do_cmdline() has stored the first typed line in
- * "repeat_cmdline". When several lines are typed repeating
- * won't be possible. */
- if (repeat_cmdline == NULL)
+ } else if (cap->cmdchar == ':' || cap->cmdchar == K_COMMAND) {
+ // do_cmdline() has stored the first typed line in
+ // "repeat_cmdline". When several lines are typed repeating
+ // won't be possible.
+ if (repeat_cmdline == NULL) {
ResetRedobuff();
- else {
+ } else {
AppendToRedobuffLit(repeat_cmdline, -1);
AppendToRedobuff(NL_STR);
xfree(repeat_cmdline);
@@ -1518,10 +1500,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
coladvance(curwin->w_curswant);
}
cap->count0 = redo_VIsual_count;
- if (redo_VIsual_count != 0)
- cap->count1 = redo_VIsual_count;
- else
- cap->count1 = 1;
+ cap->count1 = (cap->count0 == 0 ? 1 : cap->count0);
} else if (VIsual_active) {
if (!gui_yank) {
/* Save the current VIsual area for '< and '> marks, and "gv" */
@@ -1559,8 +1538,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
}
oap->start = VIsual;
- if (VIsual_mode == 'V')
+ if (VIsual_mode == 'V') {
oap->start.col = 0;
+ oap->start.coladd = 0;
+ }
}
/*
@@ -1598,6 +1579,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
oap->start = curwin->w_cursor;
}
+ // Just in case lines were deleted that make the position invalid.
+ check_pos(curwin->w_buffer, &oap->end);
oap->line_count = oap->end.lnum - oap->start.lnum + 1;
/* Set "virtual_op" before resetting VIsual_active. */
@@ -1644,16 +1627,22 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
/* Prepare for redoing. Only use the nchar field for "r",
* otherwise it might be the second char of the operator. */
if (cap->cmdchar == 'g' && (cap->nchar == 'n'
- || cap->nchar == 'N'))
+ || cap->nchar == 'N')) {
prep_redo(oap->regname, cap->count0,
- get_op_char(oap->op_type), get_extra_op_char(oap->op_type),
- oap->motion_force, cap->cmdchar, cap->nchar);
- else if (cap->cmdchar != ':')
- prep_redo(oap->regname, 0L, NUL, 'v',
- get_op_char(oap->op_type),
- get_extra_op_char(oap->op_type),
- oap->op_type == OP_REPLACE
- ? cap->nchar : NUL);
+ get_op_char(oap->op_type), get_extra_op_char(oap->op_type),
+ oap->motion_force, cap->cmdchar, cap->nchar);
+ } else if (cap->cmdchar != ':') {
+ int nchar = oap->op_type == OP_REPLACE ? cap->nchar : NUL;
+
+ // reverse what nv_replace() did
+ if (nchar == REPLACE_CR_NCHAR) {
+ nchar = CAR;
+ } else if (nchar == REPLACE_NL_NCHAR) {
+ nchar = NL;
+ }
+ prep_redo(oap->regname, 0L, NUL, 'v', get_op_char(oap->op_type),
+ get_extra_op_char(oap->op_type), nchar);
+ }
if (!redo_VIsual_busy) {
redo_VIsual_mode = resel_VIsual_mode;
redo_VIsual_vcol = resel_VIsual_vcol;
@@ -1812,7 +1801,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
} else {
(void)op_delete(oap);
if (oap->motion_type == kMTLineWise && has_format_option(FO_AUTO)) {
- u_save_cursor(); // cursor line wasn't saved yet
+ // cursor line wasn't saved yet
+ if (u_save_cursor() == FAIL) {
+ break;
+ }
}
auto_format(false, true);
}
@@ -1863,10 +1855,12 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
break;
case OP_FILTER:
- if (vim_strchr(p_cpo, CPO_FILTER) != NULL)
- AppendToRedobuff((char_u *)"!\r"); /* use any last used !cmd */
- else
- bangredo = true; /* do_bang() will put cmd in redo buffer */
+ if (vim_strchr(p_cpo, CPO_FILTER) != NULL) {
+ AppendToRedobuff("!\r"); // Use any last used !cmd.
+ } else {
+ bangredo = true; // do_bang() will put cmd in redo buffer.
+ }
+ FALLTHROUGH;
case OP_INDENT:
case OP_COLON:
@@ -1901,12 +1895,13 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
break;
case OP_FORMAT:
- if (*curbuf->b_p_fex != NUL)
- op_formatexpr(oap); /* use expression */
- else if (*p_fp != NUL)
- op_colon(oap); /* use external command */
- else
- op_format(oap, false); /* use internal function */
+ if (*curbuf->b_p_fex != NUL) {
+ op_formatexpr(oap); // use expression
+ } else if (*p_fp != NUL || *curbuf->b_p_fp != NUL) {
+ op_colon(oap); // use external command
+ } else {
+ op_format(oap, false); // use internal function
+ }
break;
case OP_FORMAT2:
@@ -1914,7 +1909,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
break;
case OP_FUNCTION:
- op_function(oap); /* call 'operatorfunc' */
+ // Restore linebreak, so that when the user edits it looks as
+ // before.
+ curwin->w_p_lbr = lbr_saved;
+ op_function(oap); // call 'operatorfunc'
break;
case OP_INSERT:
@@ -1945,8 +1943,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
* the lines. */
auto_format(false, true);
- if (restart_edit == 0)
+ if (restart_edit == 0) {
restart_edit = restart_edit_save;
+ } else {
+ cap->retval |= CA_COMMAND_BUSY;
+ }
}
break;
@@ -2007,7 +2008,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
default:
clearopbeep(oap);
}
- virtual_op = MAYBE;
+ virtual_op = kNone;
if (!gui_yank) {
/*
* if 'sol' not set, go back to old column for some commands
@@ -2022,6 +2023,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
curwin->w_cursor = old_cursor;
}
clearop(oap);
+ motion_force = NUL;
}
curwin->w_p_lbr = lbr_saved;
}
@@ -2032,40 +2034,44 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
static void op_colon(oparg_T *oap)
{
stuffcharReadbuff(':');
- if (oap->is_VIsual)
- stuffReadbuff((char_u *)"'<,'>");
- else {
- /*
- * Make the range look nice, so it can be repeated.
- */
- if (oap->start.lnum == curwin->w_cursor.lnum)
+ if (oap->is_VIsual) {
+ stuffReadbuff("'<,'>");
+ } else {
+ // Make the range look nice, so it can be repeated.
+ if (oap->start.lnum == curwin->w_cursor.lnum) {
stuffcharReadbuff('.');
- else
+ } else {
stuffnumReadbuff((long)oap->start.lnum);
+ }
if (oap->end.lnum != oap->start.lnum) {
stuffcharReadbuff(',');
- if (oap->end.lnum == curwin->w_cursor.lnum)
+ if (oap->end.lnum == curwin->w_cursor.lnum) {
stuffcharReadbuff('.');
- else if (oap->end.lnum == curbuf->b_ml.ml_line_count)
+ } else if (oap->end.lnum == curbuf->b_ml.ml_line_count) {
stuffcharReadbuff('$');
- else if (oap->start.lnum == curwin->w_cursor.lnum) {
- stuffReadbuff((char_u *)".+");
+ } else if (oap->start.lnum == curwin->w_cursor.lnum) {
+ stuffReadbuff(".+");
stuffnumReadbuff(oap->line_count - 1);
- } else
+ } else {
stuffnumReadbuff((long)oap->end.lnum);
+ }
}
}
- if (oap->op_type != OP_COLON)
- stuffReadbuff((char_u *)"!");
+ if (oap->op_type != OP_COLON) {
+ stuffReadbuff("!");
+ }
if (oap->op_type == OP_INDENT) {
- stuffReadbuff(get_equalprg());
- stuffReadbuff((char_u *)"\n");
+ stuffReadbuff((const char *)get_equalprg());
+ stuffReadbuff("\n");
} else if (oap->op_type == OP_FORMAT) {
- if (*p_fp == NUL)
- stuffReadbuff((char_u *)"fmt");
- else
- stuffReadbuff(p_fp);
- stuffReadbuff((char_u *)"\n']");
+ if (*curbuf->b_p_fp != NUL) {
+ stuffReadbuff((const char *)curbuf->b_p_fp);
+ } else if (*p_fp != NUL) {
+ stuffReadbuff((const char *)p_fp);
+ } else {
+ stuffReadbuff("fmt");
+ }
+ stuffReadbuff("\n']");
}
/*
@@ -2078,8 +2084,7 @@ static void op_colon(oparg_T *oap)
*/
static void op_function(oparg_T *oap)
{
- char_u *(argv[1]);
- int save_virtual_op = virtual_op;
+ const TriState save_virtual_op = virtual_op;
if (*p_opfunc == NUL)
EMSG(_("E774: 'operatorfunc' is empty"));
@@ -2092,17 +2097,17 @@ static void op_function(oparg_T *oap)
decl(&curbuf->b_op_end);
}
- if (oap->motion_type == kMTBlockWise) {
- argv[0] = (char_u *)"block";
- } else if (oap->motion_type == kMTLineWise) {
- argv[0] = (char_u *)"line";
- } else {
- argv[0] = (char_u *)"char";
- }
+ const char_u *const argv[1] = {
+ (const char_u *)(((const char *const[]) {
+ [kMTBlockWise] = "block",
+ [kMTLineWise] = "line",
+ [kMTCharWise] = "char",
+ })[oap->motion_type]),
+ };
- /* Reset virtual_op so that 'virtualedit' can be changed in the
- * function. */
- virtual_op = MAYBE;
+ // Reset virtual_op so that 'virtualedit' can be changed in the
+ // function.
+ virtual_op = kNone;
(void)call_func_retnr(p_opfunc, 1, argv, false);
@@ -2110,6 +2115,20 @@ static void op_function(oparg_T *oap)
}
}
+// Move the current tab to tab in same column as mouse or to end of the
+// tabline if there is no tab there.
+static void move_tab_to_mouse(void)
+{
+ int tabnr = tab_page_click_defs[mouse_col].tabnr;
+ if (tabnr <= 0) {
+ tabpage_move(9999);
+ } else if (tabnr < tabpage_index(curtab)) {
+ tabpage_move(tabnr - 1);
+ } else {
+ tabpage_move(tabnr);
+ }
+}
+
/*
* Do the appropriate action for the current mouse click in the current mode.
* Not used for Command-line mode.
@@ -2294,7 +2313,7 @@ do_mouse (
if (VIsual_active) {
if (VIsual_select) {
stuffcharReadbuff(Ctrl_G);
- stuffReadbuff((char_u *)"\"+p");
+ stuffReadbuff("\"+p");
} else {
stuffcharReadbuff('y');
stuffcharReadbuff(K_MIDDLEMOUSE);
@@ -2321,10 +2340,11 @@ do_mouse (
if (regname == 0 && eval_has_provider("clipboard")) {
regname = '*';
}
- if ((State & REPLACE_FLAG) && !yank_register_mline(regname))
+ if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) {
insert_reg(regname, true);
- else {
- do_put(regname, NULL, BACKWARD, 1L, fixindent | PUT_CURSEND);
+ } else {
+ do_put(regname, NULL, BACKWARD, 1L,
+ (fixindent ? PUT_FIXINDENT : 0) | PUT_CURSEND);
/* Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r */
AppendCharToRedobuff(Ctrl_R);
@@ -2346,12 +2366,7 @@ do_mouse (
if (mouse_row == 0 && firstwin->w_winrow > 0) {
if (is_drag) {
if (in_tab_line) {
- if (tab_page_click_defs[mouse_col].type == kStlClickTabClose) {
- tabpage_move(9999);
- } else {
- int tabnr = tab_page_click_defs[mouse_col].tabnr;
- tabpage_move(tabnr < tabpage_index(curtab) ? tabnr - 1 : tabnr);
- }
+ move_tab_to_mouse();
}
return false;
}
@@ -2454,22 +2469,19 @@ do_mouse (
};
typval_T rettv;
int doesrange;
- (void) call_func((char_u *) tab_page_click_defs[mouse_col].func,
- (int) strlen(tab_page_click_defs[mouse_col].func),
- &rettv, ARRAY_SIZE(argv), argv,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &doesrange, true, NULL);
- clear_tv(&rettv);
+ (void)call_func((char_u *)tab_page_click_defs[mouse_col].func,
+ (int)strlen(tab_page_click_defs[mouse_col].func),
+ &rettv, ARRAY_SIZE(argv), argv, NULL,
+ curwin->w_cursor.lnum, curwin->w_cursor.lnum,
+ &doesrange, true, NULL, NULL);
+ tv_clear(&rettv);
break;
}
}
}
return true;
} else if (is_drag && in_tab_line) {
- tabpage_move(tab_page_click_defs[mouse_col].type == kStlClickTabClose
- ? 9999
- : tab_page_click_defs[mouse_col].tabnr - 1);
- in_tab_line = false;
+ move_tab_to_mouse();
return false;
}
@@ -2684,7 +2696,8 @@ do_mouse (
*/
if (restart_edit != 0)
where_paste_started = curwin->w_cursor;
- do_put(regname, NULL, dir, count, fixindent | PUT_CURSEND);
+ do_put(regname, NULL, dir, count,
+ (fixindent ? PUT_FIXINDENT : 0)| PUT_CURSEND);
}
/*
* Ctrl-Mouse click or double click in a quickfix window jumps to the
@@ -2693,13 +2706,12 @@ do_mouse (
else if (((mod_mask & MOD_MASK_CTRL)
|| (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
&& bt_quickfix(curbuf)) {
- if (State & INSERT)
- stuffcharReadbuff(Ctrl_O);
- if (curwin->w_llist_ref == NULL) /* quickfix window */
- stuffReadbuff((char_u *)":.cc\n");
- else /* location list window */
- stuffReadbuff((char_u *)":.ll\n");
- got_click = false; /* ignore drag&release now */
+ if (curwin->w_llist_ref == NULL) { // quickfix window
+ do_cmdline_cmd(".cc");
+ } else { // location list window
+ do_cmdline_cmd(".ll");
+ }
+ got_click = false; // ignore drag&release now
}
/*
* Ctrl-Mouse click (or double click in a help window) jumps to the tag
@@ -2734,10 +2746,9 @@ do_mouse (
} else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT))
&& mouse_has(MOUSE_VISUAL)) {
if (is_click || !VIsual_active) {
- if (VIsual_active)
+ if (VIsual_active) {
orig_cursor = VIsual;
- else {
- check_visual_highlight();
+ } else {
VIsual = curwin->w_cursor;
orig_cursor = VIsual;
VIsual_active = true;
@@ -2840,9 +2851,10 @@ static void find_start_of_word(pos_T *pos)
while (pos->col > 0) {
col = pos->col - 1;
- col -= (*mb_head_off)(line, line + col);
- if (get_mouse_class(line + col) != cclass)
+ col -= utf_head_off(line, line + col);
+ if (get_mouse_class(line + col) != cclass) {
break;
+ }
pos->col = col;
}
}
@@ -2859,8 +2871,8 @@ static void find_end_of_word(pos_T *pos)
line = ml_get(pos->lnum);
if (*p_sel == 'e' && pos->col > 0) {
- --pos->col;
- pos->col -= (*mb_head_off)(line, line + pos->col);
+ pos->col--;
+ pos->col -= utf_head_off(line, line + pos->col);
}
cclass = get_mouse_class(line + pos->col);
while (line[pos->col] != NUL) {
@@ -2907,21 +2919,6 @@ static int get_mouse_class(char_u *p)
}
/*
- * Check if highlighting for visual mode is possible, give a warning message
- * if not.
- */
-void check_visual_highlight(void)
-{
- static bool did_check = false;
-
- if (full_screen) {
- if (!did_check && hl_attr(HLF_V) == 0)
- MSG(_("Warning: terminal cannot highlight"));
- did_check = true;
- }
-}
-
-/*
* End Visual mode.
* This function should ALWAYS be called to end Visual mode, except from
* do_pending_operator().
@@ -2971,6 +2968,43 @@ void reset_VIsual(void)
}
}
+// Check for a balloon-eval special item to include when searching for an
+// identifier. When "dir" is BACKWARD "ptr[-1]" must be valid!
+// Returns true if the character at "*ptr" should be included.
+// "dir" is FORWARD or BACKWARD, the direction of searching.
+// "*colp" is in/decremented if "ptr[-dir]" should also be included.
+// "bnp" points to a counter for square brackets.
+static bool find_is_eval_item(
+ const char_u *const ptr,
+ int *const colp,
+ int *const bnp,
+ const int dir)
+{
+ // Accept everything inside [].
+ if ((*ptr == ']' && dir == BACKWARD) || (*ptr == '[' && dir == FORWARD)) {
+ *bnp += 1;
+ }
+ if (*bnp > 0) {
+ if ((*ptr == '[' && dir == BACKWARD) || (*ptr == ']' && dir == FORWARD)) {
+ *bnp -= 1;
+ }
+ return true;
+ }
+
+ // skip over "s.var"
+ if (*ptr == '.') {
+ return true;
+ }
+
+ // two-character item: s->var
+ if (ptr[dir == BACKWARD ? 0 : 1] == '>'
+ && ptr[dir == BACKWARD ? -1 : 0] == '-') {
+ *colp += dir;
+ return true;
+ }
+ return false;
+}
+
/*
* Find the identifier under or to the right of the cursor.
* "find_type" can have one of three values:
@@ -3011,6 +3045,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
int this_class = 0;
int prev_class;
int prevcol;
+ int bn = 0; // bracket nesting
/*
* if i == 0: try to find an identifier
@@ -3022,71 +3057,62 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
* 1. skip to start of identifier/string
*/
col = startcol;
- if (has_mbyte) {
- while (ptr[col] != NUL) {
- this_class = mb_get_class(ptr + col);
- if (this_class != 0 && (i == 1 || this_class != 1))
- break;
- col += (*mb_ptr2len)(ptr + col);
+ while (ptr[col] != NUL) {
+ // Stop at a ']' to evaluate "a[x]".
+ if ((find_type & FIND_EVAL) && ptr[col] == ']') {
+ break;
}
- } else
- while (ptr[col] != NUL
- && (i == 0 ? !vim_iswordc(ptr[col]) : ascii_iswhite(ptr[col]))
- )
- ++col;
-
-
- /*
- * 2. Back up to start of identifier/string.
- */
- if (has_mbyte) {
- /* Remember class of character under cursor. */
this_class = mb_get_class(ptr + col);
- while (col > 0 && this_class != 0) {
- prevcol = col - 1 - (*mb_head_off)(ptr, ptr + col - 1);
- prev_class = mb_get_class(ptr + prevcol);
- if (this_class != prev_class
- && (i == 0
- || prev_class == 0
- || (find_type & FIND_IDENT))
- )
- break;
- col = prevcol;
+ if (this_class != 0 && (i == 1 || this_class != 1)) {
+ break;
}
+ col += utfc_ptr2len(ptr + col);
+ }
- /* If we don't want just any old string, or we've found an
- * identifier, stop searching. */
- if (this_class > 2)
- this_class = 2;
- if (!(find_type & FIND_STRING) || this_class == 2)
- break;
- } else {
- while (col > 0
- && ((i == 0
- ? vim_iswordc(ptr[col - 1])
- : (!ascii_iswhite(ptr[col - 1])
- && (!(find_type & FIND_IDENT)
- || !vim_iswordc(ptr[col - 1]))))
- ))
- --col;
+ // When starting on a ']' count it, so that we include the '['.
+ bn = ptr[col] == ']';
- /* If we don't want just any old string, or we've found an
- * identifier, stop searching. */
- if (!(find_type & FIND_STRING) || vim_iswordc(ptr[col]))
+ //
+ // 2. Back up to start of identifier/string.
+ //
+ // Remember class of character under cursor.
+ if ((find_type & FIND_EVAL) && ptr[col] == ']') {
+ this_class = mb_get_class((char_u *)"a");
+ } else {
+ this_class = mb_get_class(ptr + col);
+ }
+ while (col > 0 && this_class != 0) {
+ prevcol = col - 1 - utf_head_off(ptr, ptr + col - 1);
+ prev_class = mb_get_class(ptr + prevcol);
+ if (this_class != prev_class
+ && (i == 0
+ || prev_class == 0
+ || (find_type & FIND_IDENT))
+ && (!(find_type & FIND_EVAL)
+ || prevcol == 0
+ || !find_is_eval_item(ptr + prevcol, &prevcol, &bn, BACKWARD))) {
break;
+ }
+ col = prevcol;
+ }
+
+ // If we don't want just any old string, or we've found an
+ // identifier, stop searching.
+ if (this_class > 2) {
+ this_class = 2;
+ }
+ if (!(find_type & FIND_STRING) || this_class == 2) {
+ break;
}
}
- if (ptr[col] == NUL || (i == 0 && (
- has_mbyte ? this_class != 2 :
- !vim_iswordc(ptr[col])))) {
- /*
- * didn't find an identifier or string
- */
- if (find_type & FIND_STRING)
+ if (ptr[col] == NUL || (i == 0 && this_class != 2)) {
+ // Didn't find an identifier or string.
+ if (find_type & FIND_STRING) {
EMSG(_("E348: No string under cursor"));
- else
+ } else {
EMSG(_(e_noident));
+ }
return 0;
}
ptr += col;
@@ -3095,21 +3121,20 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
/*
* 3. Find the end if the identifier/string.
*/
+ bn = 0;
+ startcol -= col;
col = 0;
- if (has_mbyte) {
- /* Search for point of changing multibyte character class. */
- this_class = mb_get_class(ptr);
- while (ptr[col] != NUL
- && ((i == 0 ? mb_get_class(ptr + col) == this_class
- : mb_get_class(ptr + col) != 0)
- ))
- col += (*mb_ptr2len)(ptr + col);
- } else
- while ((i == 0 ? vim_iswordc(ptr[col])
- : (ptr[col] != NUL && !ascii_iswhite(ptr[col])))
- ) {
- ++col;
- }
+ // Search for point of changing multibyte character class.
+ this_class = mb_get_class(ptr);
+ while (ptr[col] != NUL
+ && ((i == 0
+ ? mb_get_class(ptr + col) == this_class
+ : mb_get_class(ptr + col) != 0)
+ || ((find_type & FIND_EVAL)
+ && col <= (int)startcol
+ && find_is_eval_item(ptr + col, &col, &bn, FORWARD)))) {
+ col += utfc_ptr2len(ptr + col);
+ }
assert(col >= 0);
return (size_t)col;
@@ -3409,10 +3434,10 @@ static void display_showcmd(void)
int len;
len = (int)STRLEN(showcmd_buf);
- if (len == 0)
+ if (len == 0) {
showcmd_is_clear = true;
- else {
- screen_puts(showcmd_buf, (int)Rows - 1, sc_col, 0);
+ } else {
+ grid_puts(&default_grid, showcmd_buf, (int)Rows - 1, sc_col, 0);
showcmd_is_clear = false;
}
@@ -3420,7 +3445,8 @@ static void display_showcmd(void)
* clear the rest of an old message by outputting up to SHOWCMD_COLS
* spaces
*/
- screen_puts((char_u *)" " + len, (int)Rows - 1, sc_col + len, 0);
+ grid_puts(&default_grid, (char_u *)" " + len, (int)Rows - 1,
+ sc_col + len, 0);
setcursor(); /* put cursor back where it belongs */
}
@@ -3509,7 +3535,8 @@ void check_scrollbind(linenr_T topline_diff, long leftcol_diff)
* loop through the scrollbound windows and scroll accordingly
*/
VIsual_select = VIsual_active = 0;
- for (curwin = firstwin; curwin; curwin = curwin->w_next) {
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ curwin = wp;
curbuf = curwin->w_buffer;
/* skip original window and windows with 'noscrollbind' */
if (curwin == old_curwin || !curwin->w_p_scb) {
@@ -3641,10 +3668,44 @@ nv_gd (
size_t len;
char_u *ptr;
if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0
- || !find_decl(ptr, len, nchar == 'd', thisblock, 0))
+ || !find_decl(ptr, len, nchar == 'd', thisblock, SEARCH_START)) {
clearopbeep(oap);
- else if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP)
+ } else if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) {
foldOpenCursor();
+ }
+}
+
+// Return true if line[offset] is not inside a C-style comment or string, false
+// otherwise.
+static bool is_ident(char_u *line, int offset)
+{
+ bool incomment = false;
+ int instring = 0;
+ int prev = 0;
+
+ for (int i = 0; i < offset && line[i] != NUL; i++) {
+ if (instring != 0) {
+ if (prev != '\\' && line[i] == instring) {
+ instring = 0;
+ }
+ } else if ((line[i] == '"' || line[i] == '\'') && !incomment) {
+ instring = line[i];
+ } else {
+ if (incomment) {
+ if (prev == '*' && line[i] == '/') {
+ incomment = false;
+ }
+ } else if (prev == '/' && line[i] == '*') {
+ incomment = true;
+ } else if (prev == '/' && line[i] == '/') {
+ return false;
+ }
+ }
+
+ prev = line[i];
+ }
+
+ return incomment == false && instring == 0;
}
/*
@@ -3660,7 +3721,7 @@ find_decl (
size_t len,
bool locally,
bool thisblock,
- int searchflags /* flags passed to searchit() */
+ int flags_arg // flags passed to searchit()
)
{
char_u *pat;
@@ -3672,6 +3733,8 @@ find_decl (
bool save_p_scs;
bool retval = true;
bool incll;
+ int searchflags = flags_arg;
+ bool valid;
pat = xmalloc(len + 7);
@@ -3706,20 +3769,25 @@ find_decl (
/* Search forward for the identifier, ignore comment lines. */
clearpos(&found_pos);
for (;; ) {
+ valid = false;
+ (void)valid; // Avoid "dead assignment" warning.
t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD,
pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL);
if (curwin->w_cursor.lnum >= old_pos.lnum)
t = false; /* match after start is failure too */
if (thisblock && t != false) {
- pos_T *pos;
-
- /* Check that the block the match is in doesn't end before the
- * position where we started the search from. */
- if ((pos = findmatchlimit(NULL, '}', FM_FORWARD,
- (int)(old_pos.lnum - curwin->w_cursor.lnum + 1))) != NULL
- && pos->lnum < old_pos.lnum)
+ const int64_t maxtravel = old_pos.lnum - curwin->w_cursor.lnum + 1;
+ const pos_T *pos = findmatchlimit(NULL, '}', FM_FORWARD, maxtravel);
+
+ // Check that the block the match is in doesn't end before the
+ // position where we started the search from.
+ if (pos != NULL && pos->lnum < old_pos.lnum) {
+ // There can't be a useful match before the end of this block.
+ // Skip to the end
+ curwin->w_cursor = *pos;
continue;
+ }
}
if (t == false) {
@@ -3736,19 +3804,36 @@ find_decl (
curwin->w_cursor.col = 0;
continue;
}
- if (!locally) /* global search: use first match found */
+ valid = is_ident(get_cursor_line_ptr(), curwin->w_cursor.col);
+
+ // If the current position is not a valid identifier and a previous match is
+ // present, favor that one instead.
+ if (!valid && found_pos.lnum != 0) {
+ curwin->w_cursor = found_pos;
break;
- if (curwin->w_cursor.lnum >= par_pos.lnum) {
- /* If we previously found a valid position, use it. */
- if (found_pos.lnum != 0)
+ }
+ // global search: use first match found
+ if (valid && !locally) {
+ break;
+ }
+ if (valid && curwin->w_cursor.lnum >= par_pos.lnum) {
+ // If we previously found a valid position, use it.
+ if (found_pos.lnum != 0) {
curwin->w_cursor = found_pos;
+ }
break;
}
- /* For finding a local variable and the match is before the "{" search
- * to find a later match. For K&R style function declarations this
- * skips the function header without types. */
- found_pos = curwin->w_cursor;
+ // For finding a local variable and the match is before the "{" or
+ // inside a comment, continue searching. For K&R style function
+ // declarations this skips the function header without types.
+ if (!valid) {
+ clearpos(&found_pos);
+ } else {
+ found_pos = curwin->w_cursor;
+ }
+ // Remove SEARCH_START from flags to avoid getting stuck at one position.
+ searchflags &= ~SEARCH_START;
}
if (t == false) {
@@ -3790,18 +3875,16 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
col_off1 = curwin_col_off();
col_off2 = col_off1 - curwin_col_off2();
- width1 = curwin->w_width - col_off1;
- width2 = curwin->w_width - col_off2;
+ width1 = curwin->w_grid.Columns - col_off1;
+ width2 = curwin->w_grid.Columns - col_off2;
if (width2 == 0) {
width2 = 1; // Avoid divide by zero.
}
- if (curwin->w_width != 0) {
- /*
- * Instead of sticking at the last character of the buffer line we
- * try to stick in the last column of the screen.
- */
+ if (curwin->w_grid.Columns != 0) {
+ // Instead of sticking at the last character of the buffer line we
+ // try to stick in the last column of the screen.
if (curwin->w_curswant == MAXCOL) {
atend = true;
validate_virtcol();
@@ -3842,9 +3925,11 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
(void)hasFolding(curwin->w_cursor.lnum,
&curwin->w_cursor.lnum, NULL);
linelen = linetabsize(get_cursor_line_ptr());
- if (linelen > width1)
- curwin->w_curswant += (((linelen - width1 - 1) / width2)
- + 1) * width2;
+ if (linelen > width1) {
+ int w = (((linelen - width1 - 1) / width2) + 1) * width2;
+ assert(curwin->w_curswant <= INT_MAX - w);
+ curwin->w_curswant += w;
+ }
}
} else { /* dir == FORWARD */
if (linelen > width1)
@@ -3917,8 +4002,12 @@ static void nv_mousescroll(cmdarg_T *cap)
row = mouse_row;
col = mouse_col;
- /* find the window at the pointer coordinates */
- curwin = mouse_find_win(&row, &col);
+ // find the window at the pointer coordinates
+ win_T *const wp = mouse_find_win(&row, &col);
+ if (wp == NULL) {
+ return;
+ }
+ curwin = wp;
curbuf = curwin->w_buffer;
}
@@ -4028,12 +4117,10 @@ static void nv_zet(cmdarg_T *cap)
return;
n = nchar - '0';
for (;; ) {
- ++no_mapping;
- ++allow_keys; /* no mapping for nchar, but allow key codes */
+ no_mapping++;
nchar = plain_vgetc();
LANGMAP_ADJUST(nchar, true);
- --no_mapping;
- --allow_keys;
+ no_mapping--;
(void)add_to_showcmd(nchar);
if (nchar == K_DEL || nchar == K_KDEL)
n /= 10;
@@ -4094,12 +4181,12 @@ dozet:
else
curwin->w_cursor.lnum = curwin->w_botline;
}
- /* FALLTHROUGH */
+ FALLTHROUGH;
case NL:
case CAR:
case K_KENTER:
beginline(BL_WHITE | BL_FIX);
- /* FALLTHROUGH */
+ FALLTHROUGH;
case 't': scroll_cursor_top(0, true);
redraw_later(VALID);
@@ -4108,7 +4195,7 @@ dozet:
/* "z." and "zz": put cursor in middle of screen */
case '.': beginline(BL_WHITE | BL_FIX);
- /* FALLTHROUGH */
+ FALLTHROUGH;
case 'z': scroll_cursor_halfway(true);
redraw_later(VALID);
@@ -4126,10 +4213,10 @@ dozet:
curwin->w_cursor.lnum = 1;
else
curwin->w_cursor.lnum = curwin->w_topline - 1;
- /* FALLTHROUGH */
+ FALLTHROUGH;
case '-':
beginline(BL_WHITE | BL_FIX);
- /* FALLTHROUGH */
+ FALLTHROUGH;
case 'b': scroll_cursor_bot(0, true);
redraw_later(VALID);
@@ -4138,8 +4225,8 @@ dozet:
/* "zH" - scroll screen right half-page */
case 'H':
- cap->count1 *= curwin->w_width / 2;
- /* FALLTHROUGH */
+ cap->count1 *= curwin->w_grid.Columns / 2;
+ FALLTHROUGH;
/* "zh" - scroll screen to the right */
case 'h':
@@ -4153,9 +4240,9 @@ dozet:
}
break;
- /* "zL" - scroll screen left half-page */
- case 'L': cap->count1 *= curwin->w_width / 2;
- /* FALLTHROUGH */
+ // "zL" - scroll screen left half-page
+ case 'L': cap->count1 *= curwin->w_grid.Columns / 2;
+ FALLTHROUGH;
/* "zl" - scroll screen to the left */
case 'l':
@@ -4190,11 +4277,12 @@ dozet:
col = 0; /* like the cursor is in col 0 */
else
getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
- n = curwin->w_width - curwin_col_off();
- if (col + l_p_siso < n)
+ n = curwin->w_grid.Columns - curwin_col_off();
+ if (col + l_p_siso < n) {
col = 0;
- else
+ } else {
col = col + l_p_siso - n + 1;
+ }
if (curwin->w_leftcol != col) {
curwin->w_leftcol = col;
redraw_later(NOT_VALID);
@@ -4361,20 +4449,18 @@ dozet:
break;
- case 'u': /* "zug" and "zuw": undo "zg" and "zw" */
- ++no_mapping;
- ++allow_keys; /* no mapping for nchar, but allow key codes */
+ case 'u': // "zug" and "zuw": undo "zg" and "zw"
+ no_mapping++;
nchar = plain_vgetc();
LANGMAP_ADJUST(nchar, true);
- --no_mapping;
- --allow_keys;
+ no_mapping--;
(void)add_to_showcmd(nchar);
if (vim_strchr((char_u *)"gGwW", nchar) == NULL) {
clearopbeep(cap->oap);
break;
}
undo = true;
- /*FALLTHROUGH*/
+ FALLTHROUGH;
case 'g': /* "zg": add good word to word list */
case 'w': /* "zw": add wrong word to word list */
@@ -4455,26 +4541,25 @@ static void nv_exmode(cmdarg_T *cap)
}
}
-/*
- * Handle a ":" command.
- */
+/// Handle a ":" command and <Cmd>.
static void nv_colon(cmdarg_T *cap)
{
int old_p_im;
bool cmd_result;
+ bool is_cmdkey = cap->cmdchar == K_COMMAND;
- if (VIsual_active)
+ if (VIsual_active && !is_cmdkey) {
nv_operator(cap);
- else {
+ } else {
if (cap->oap->op_type != OP_NOP) {
// Using ":" as a movement is characterwise exclusive.
cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
- } else if (cap->count0) {
- /* translate "count:" into ":.,.+(count - 1)" */
+ } else if (cap->count0 && !is_cmdkey) {
+ // translate "count:" into ":.,.+(count - 1)"
stuffcharReadbuff('.');
if (cap->count0 > 1) {
- stuffReadbuff((char_u *)",.+");
+ stuffReadbuff(",.+");
stuffnumReadbuff(cap->count0 - 1L);
}
}
@@ -4485,9 +4570,9 @@ static void nv_colon(cmdarg_T *cap)
old_p_im = p_im;
- /* get a command line and execute it */
- cmd_result = do_cmdline(NULL, getexline, NULL,
- cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0);
+ // get a command line and execute it
+ cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL,
+ cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0);
/* If 'insertmode' changed, enter or exit Insert mode */
if (p_im != old_p_im) {
@@ -4665,6 +4750,11 @@ static void nv_ident(cmdarg_T *cap)
char_u *kp = *curbuf->b_p_kp == NUL ? p_kp : curbuf->b_p_kp; // 'keywordprg'
assert(*kp != NUL); // option.c:do_set() should default to ":help" if empty.
bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command
+ bool kp_help = (STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0);
+ if (kp_help && *skipwhite(ptr) == NUL) {
+ EMSG(_(e_noident)); // found white space only
+ return;
+ }
size_t buf_size = n * 2 + 30 + STRLEN(kp);
char *buf = xmalloc(buf_size);
buf[0] = NUL;
@@ -4687,7 +4777,9 @@ static void nv_ident(cmdarg_T *cap)
break;
case 'K':
- if (kp_ex) {
+ if (kp_help) {
+ STRCPY(buf, "he! ");
+ } else if (kp_ex) {
if (cap->count0 != 0) { // Send the count to the ex command.
snprintf(buf, buf_size, "%" PRId64, (int64_t)(cap->count0));
}
@@ -4749,13 +4841,16 @@ static void nv_ident(cmdarg_T *cap)
}
}
- /*
- * Now grab the chars in the identifier
- */
- if (cmdchar == 'K' && !kp_ex) {
- /* Escape the argument properly for a shell command */
+ // Now grab the chars in the identifier
+ if (cmdchar == 'K' && !kp_help) {
ptr = vim_strnsave(ptr, n);
- p = vim_strsave_shellescape(ptr, true, true);
+ if (kp_ex) {
+ // Escape the argument properly for an Ex command
+ p = (char_u *)vim_strsave_fnameescape((const char *)ptr, false);
+ } else {
+ // Escape the argument properly for a shell command
+ p = vim_strsave_shellescape(ptr, true, true);
+ }
xfree(ptr);
char *newbuf = xrealloc(buf, STRLEN(buf) + STRLEN(p) + 1);
buf = newbuf;
@@ -4892,11 +4987,11 @@ static void nv_scroll(cmdarg_T *cap)
/* Don't count filler lines above the window. */
used -= diff_check_fill(curwin, curwin->w_topline)
- curwin->w_topfill;
- validate_botline(); /* make sure w_empty_rows is valid */
- half = (curwin->w_height - curwin->w_empty_rows + 1) / 2;
- for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; ++n) {
- /* Count half he number of filler lines to be "below this
- * line" and half to be "above the next line". */
+ validate_botline(); // make sure w_empty_rows is valid
+ half = (curwin->w_grid.Rows - curwin->w_empty_rows + 1) / 2;
+ for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; n++) {
+ // Count half he number of filler lines to be "below this
+ // line" and half to be "above the next line".
if (n > 0 && used + diff_check_fill(curwin, curwin->w_topline
+ n) / 2 >= half) {
--n;
@@ -4908,9 +5003,10 @@ static void nv_scroll(cmdarg_T *cap)
if (hasFolding(curwin->w_topline + n, NULL, &lnum))
n = lnum - curwin->w_topline;
}
- if (n > 0 && used > curwin->w_height)
- --n;
- } else { /* (cap->cmdchar == 'H') */
+ if (n > 0 && used > curwin->w_grid.Rows) {
+ n--;
+ }
+ } else { // (cap->cmdchar == 'H')
n = cap->count1 - 1;
if (hasAnyFolding(curwin)) {
/* Count a fold for one screen line. */
@@ -4927,7 +5023,10 @@ static void nv_scroll(cmdarg_T *cap)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
}
- cursor_correct(); /* correct for 'so' */
+ // Correct for 'so', except when an operator is pending.
+ if (cap->oap->op_type == OP_NOP) {
+ cursor_correct();
+ }
beginline(BL_SOL | BL_FIX);
}
@@ -4962,26 +5061,21 @@ static void nv_right(cmdarg_T *cap)
if ((!PAST_LINE && oneright() == false)
|| (PAST_LINE && *get_cursor_pos_ptr() == NUL)
) {
- /*
- * <Space> wraps to next line if 'whichwrap' has 's'.
- * 'l' wraps to next line if 'whichwrap' has 'l'.
- * CURS_RIGHT wraps to next line if 'whichwrap' has '>'.
- */
- if ( ((cap->cmdchar == ' '
- && vim_strchr(p_ww, 's') != NULL)
- || (cap->cmdchar == 'l'
- && vim_strchr(p_ww, 'l') != NULL)
- || (cap->cmdchar == K_RIGHT
- && vim_strchr(p_ww, '>') != NULL))
- && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
- /* When deleting we also count the NL as a character.
- * Set cap->oap->inclusive when last char in the line is
- * included, move to next line after that */
- if ( cap->oap->op_type != OP_NOP
- && !cap->oap->inclusive
- && !lineempty(curwin->w_cursor.lnum))
+ // <Space> wraps to next line if 'whichwrap' has 's'.
+ // 'l' wraps to next line if 'whichwrap' has 'l'.
+ // CURS_RIGHT wraps to next line if 'whichwrap' has '>'.
+ if (((cap->cmdchar == ' ' && vim_strchr(p_ww, 's') != NULL)
+ || (cap->cmdchar == 'l' && vim_strchr(p_ww, 'l') != NULL)
+ || (cap->cmdchar == K_RIGHT && vim_strchr(p_ww, '>') != NULL))
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
+ // When deleting we also count the NL as a character.
+ // Set cap->oap->inclusive when last char in the line is
+ // included, move to next line after that
+ if (cap->oap->op_type != OP_NOP
+ && !cap->oap->inclusive
+ && !LINEEMPTY(curwin->w_cursor.lnum)) {
cap->oap->inclusive = true;
- else {
+ } else {
++curwin->w_cursor.lnum;
curwin->w_cursor.col = 0;
curwin->w_cursor.coladd = 0;
@@ -4991,12 +5085,14 @@ static void nv_right(cmdarg_T *cap)
continue;
}
if (cap->oap->op_type == OP_NOP) {
- /* Only beep and flush if not moved at all */
- if (n == cap->count1)
+ // Only beep and flush if not moved at all
+ if (n == cap->count1) {
beep_flush();
+ }
} else {
- if (!lineempty(curwin->w_cursor.lnum))
+ if (!LINEEMPTY(curwin->w_cursor.lnum)) {
cap->oap->inclusive = true;
+ }
}
break;
} else if (PAST_LINE) {
@@ -5054,13 +5150,12 @@ static void nv_left(cmdarg_T *cap)
coladvance((colnr_T)MAXCOL);
curwin->w_set_curswant = true;
- /* When the NL before the first char has to be deleted we
- * put the cursor on the NUL after the previous line.
- * This is a very special case, be careful!
- * Don't adjust op_end now, otherwise it won't work. */
- if ( (cap->oap->op_type == OP_DELETE
- || cap->oap->op_type == OP_CHANGE)
- && !lineempty(curwin->w_cursor.lnum)) {
+ // When the NL before the first char has to be deleted we
+ // put the cursor on the NUL after the previous line.
+ // This is a very special case, be careful!
+ // Don't adjust op_end now, otherwise it won't work.
+ if ((cap->oap->op_type == OP_DELETE || cap->oap->op_type == OP_CHANGE)
+ && !LINEEMPTY(curwin->w_cursor.lnum)) {
char_u *cp = get_cursor_pos_ptr();
if (*cp != NUL) {
@@ -5159,13 +5254,13 @@ static void nv_gotofile(cmdarg_T *cap)
if (ptr != NULL) {
// do autowrite if necessary
- if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf)) {
+ if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !buf_hide(curbuf)) {
(void)autowrite(curbuf, false);
}
setpcmark();
- (void)do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
- P_HID(curbuf) ? ECMD_HIDE : 0, curwin);
- if (cap->nchar == 'F' && lnum >= 0) {
+ if (do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
+ buf_hide(curbuf) ? ECMD_HIDE : 0, curwin) == OK
+ && cap->nchar == 'F' && lnum >= 0) {
curwin->w_cursor.lnum = lnum;
check_cursor_lnum();
beginline(BL_SOL | BL_FIX);
@@ -5215,6 +5310,7 @@ static void nv_dollar(cmdarg_T *cap)
static void nv_search(cmdarg_T *cap)
{
oparg_T *oap = cap->oap;
+ pos_T save_cursor = curwin->w_cursor;
if (cap->cmdchar == '?' && cap->oap->op_type == OP_ROT13) {
/* Translate "g??" to "g?g?" */
@@ -5224,6 +5320,8 @@ static void nv_search(cmdarg_T *cap)
return;
}
+ // When using 'incsearch' the cursor may be moved to set a different search
+ // start position.
cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0);
if (cap->searchbuf == NULL) {
@@ -5232,7 +5330,8 @@ static void nv_search(cmdarg_T *cap)
}
(void)normal_search(cap, cap->cmdchar, cap->searchbuf,
- (cap->arg ? 0 : SEARCH_MARK));
+ (cap->arg || !equalpos(save_cursor, curwin->w_cursor))
+ ? 0 : SEARCH_MARK);
}
/*
@@ -5614,6 +5713,8 @@ static void nv_brackets(cmdarg_T *cap)
cap->nchar == 's', false, NULL) == 0) {
clearopbeep(cap->oap);
break;
+ } else {
+ curwin->w_set_curswant = true;
}
if (cap->oap->op_type == OP_NOP && (fdo_flags & FDO_SEARCH) && KeyTyped)
foldOpenCursor();
@@ -5783,10 +5884,13 @@ static void nv_replace(cmdarg_T *cap)
if (got_int)
reset_VIsual();
if (had_ctrl_v) {
- if (cap->nchar == '\r')
- cap->nchar = -1;
- else if (cap->nchar == '\n')
- cap->nchar = -2;
+ // Use a special (negative) number to make a difference between a
+ // literal CR or NL and a line break.
+ if (cap->nchar == CAR) {
+ cap->nchar = REPLACE_CR_NCHAR;
+ } else if (cap->nchar == NL) {
+ cap->nchar = REPLACE_NL_NCHAR;
+ }
}
nv_operator(cap);
return;
@@ -5919,6 +6023,8 @@ static void nv_replace(cmdarg_T *cap)
curwin->w_set_curswant = true;
set_last_insert(cap->nchar);
}
+
+ foldUpdateAfterInsert();
}
/*
@@ -6021,10 +6127,11 @@ static void n_swapchar(cmdarg_T *cap)
pos_T startpos;
int did_change = 0;
- if (checkclearopq(cap->oap))
+ if (checkclearopq(cap->oap)) {
return;
+ }
- if (lineempty(curwin->w_cursor.lnum) && vim_strchr(p_ww, '~') == NULL) {
+ if (LINEEMPTY(curwin->w_cursor.lnum) && vim_strchr(p_ww, '~') == NULL) {
clearopbeep(cap->oap);
return;
}
@@ -6058,7 +6165,7 @@ static void n_swapchar(cmdarg_T *cap)
curwin->w_set_curswant = true;
if (did_change) {
changed_lines(startpos.lnum, startpos.col, curwin->w_cursor.lnum + 1,
- 0L);
+ 0L, true);
curbuf->b_op_start = startpos;
curbuf->b_op_end = curwin->w_cursor;
if (curbuf->b_op_end.col > 0)
@@ -6149,17 +6256,15 @@ static void nv_abbrev(cmdarg_T *cap)
*/
static void nv_optrans(cmdarg_T *cap)
{
- static char_u *(ar[8]) = {(char_u *)"dl", (char_u *)"dh",
- (char_u *)"d$", (char_u *)"c$",
- (char_u *)"cl", (char_u *)"cc",
- (char_u *)"yy", (char_u *)":s\r"};
- static char_u *str = (char_u *)"xXDCsSY&";
+ static const char *(ar[]) = { "dl", "dh", "d$", "c$", "cl", "cc", "yy",
+ ":s\r" };
+ static const char *str = "xXDCsSY&";
if (!checkclearopq(cap->oap)) {
if (cap->count0) {
stuffnumReadbuff(cap->count0);
}
- stuffReadbuff(ar[(int)(vim_strchr(str, cap->cmdchar) - str)]);
+ stuffReadbuff(ar[strchr(str, (char)cap->cmdchar) - str]);
}
cap->opcount = 0;
}
@@ -6173,7 +6278,7 @@ static void nv_gomark(cmdarg_T *cap)
pos_T *pos;
int c;
pos_T old_cursor = curwin->w_cursor;
- int old_KeyTyped = KeyTyped; /* getting file may reset it */
+ const bool old_KeyTyped = KeyTyped; // getting file may reset it
if (cap->cmdchar == 'g')
c = cap->extra_char;
@@ -6189,15 +6294,18 @@ static void nv_gomark(cmdarg_T *cap)
} else
nv_cursormark(cap, cap->arg, pos);
- /* May need to clear the coladd that a mark includes. */
- if (!virtual_active())
+ // May need to clear the coladd that a mark includes.
+ if (!virtual_active()) {
curwin->w_cursor.coladd = 0;
+ }
+ check_cursor_col();
if (cap->oap->op_type == OP_NOP
&& pos != NULL
&& (pos == (pos_T *)-1 || !equalpos(old_cursor, *pos))
&& (fdo_flags & FDO_MARK)
- && old_KeyTyped)
+ && old_KeyTyped) {
foldOpenCursor();
+ }
}
/*
@@ -6207,7 +6315,7 @@ static void nv_pcmark(cmdarg_T *cap)
{
pos_T *pos;
linenr_T lnum = curwin->w_cursor.lnum;
- int old_KeyTyped = KeyTyped; /* getting file may reset it */
+ const bool old_KeyTyped = KeyTyped; // getting file may reset it
if (!checkclearopq(cap->oap)) {
if (cap->cmdchar == 'g')
@@ -6267,8 +6375,8 @@ static void nv_visual(cmdarg_T *cap)
/* 'v', 'V' and CTRL-V can be used while an operator is pending to make it
* characterwise, linewise, or blockwise. */
if (cap->oap->op_type != OP_NOP) {
- cap->oap->motion_force = cap->cmdchar;
- finish_op = false; /* operator doesn't finish now but later */
+ motion_force = cap->oap->motion_force = cap->cmdchar;
+ finish_op = false; // operator doesn't finish now but later
return;
}
@@ -6281,9 +6389,8 @@ static void nv_visual(cmdarg_T *cap)
VIsual_mode = cap->cmdchar;
showmode();
}
- redraw_curbuf_later(INVERTED); /* update the inversion */
- } else { /* start Visual mode */
- check_visual_highlight();
+ redraw_curbuf_later(INVERTED); // update the inversion
+ } else { // start Visual mode
if (cap->count0 > 0 && resel_VIsual_mode != NUL) {
/* use previously selected part */
VIsual = curwin->w_cursor;
@@ -6372,9 +6479,6 @@ void may_start_select(int c)
*/
static void n_start_visual_mode(int c)
{
- /* Check for redraw before changing the state. */
- conceal_check_cursur_line();
-
VIsual_mode = c;
VIsual_active = true;
VIsual_reselect = true;
@@ -6390,8 +6494,8 @@ static void n_start_visual_mode(int c)
foldAdjustVisual();
setmouse();
- /* Check for redraw after changing the state. */
- conceal_check_cursur_line();
+ // Check for redraw after changing the state.
+ conceal_check_cursor_line();
if (p_smd && msg_silent == 0)
redraw_cmdline = true; /* show visual mode later */
@@ -6536,7 +6640,7 @@ static void nv_g_cmd(cmdarg_T *cap)
*/
case K_BS:
cap->nchar = Ctrl_H;
- /* FALLTHROUGH */
+ FALLTHROUGH;
case 'h':
case 'H':
case Ctrl_H:
@@ -6602,7 +6706,7 @@ static void nv_g_cmd(cmdarg_T *cap)
*/
case '^':
flag = true;
- /* FALLTHROUGH */
+ FALLTHROUGH;
case '0':
case 'm':
@@ -6611,9 +6715,9 @@ static void nv_g_cmd(cmdarg_T *cap)
oap->motion_type = kMTCharWise;
oap->inclusive = false;
if (curwin->w_p_wrap
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
) {
- int width1 = curwin->w_width - curwin_col_off();
+ int width1 = curwin->w_grid.Columns - curwin_col_off();
int width2 = width1 + curwin_col_off2();
validate_virtcol();
@@ -6625,10 +6729,11 @@ static void nv_g_cmd(cmdarg_T *cap)
/* Go to the middle of the screen line. When 'number' or
* 'relativenumber' is on and lines are wrapping the middle can be more
* to the left. */
- if (cap->nchar == 'm')
- i += (curwin->w_width - curwin_col_off()
+ if (cap->nchar == 'm') {
+ i += (curwin->w_grid.Columns - curwin_col_off()
+ ((curwin->w_p_wrap && i > 0)
? curwin_col_off2() : 0)) / 2;
+ }
coladvance((colnr_T)i);
if (flag) {
do
@@ -6672,11 +6777,11 @@ static void nv_g_cmd(cmdarg_T *cap)
oap->motion_type = kMTCharWise;
oap->inclusive = true;
if (curwin->w_p_wrap
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
) {
curwin->w_curswant = MAXCOL; /* so we stay at the end */
if (cap->count1 == 1) {
- int width1 = curwin->w_width - col_off;
+ int width1 = curwin->w_grid.Columns - col_off;
int width2 = width1 + curwin_col_off2();
validate_virtcol();
@@ -6702,7 +6807,7 @@ static void nv_g_cmd(cmdarg_T *cap)
} else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == false)
clearopbeep(oap);
} else {
- i = curwin->w_leftcol + curwin->w_width - col_off - 1;
+ i = curwin->w_leftcol + curwin->w_grid.Columns - col_off - 1;
coladvance((colnr_T)i);
/* Make sure we stick in this column. */
@@ -6780,7 +6885,7 @@ static void nv_g_cmd(cmdarg_T *cap)
/* "g'm" and "g`m": jump to mark without setting pcmark */
case '\'':
cap->arg = true;
- /*FALLTHROUGH*/
+ FALLTHROUGH;
case '`':
nv_gomark(cap);
break;
@@ -6811,7 +6916,7 @@ static void nv_g_cmd(cmdarg_T *cap)
else
show_utf8();
break;
-
+ // "g<": show scrollback text
case '<':
show_sb_text();
break;
@@ -6838,7 +6943,7 @@ static void nv_g_cmd(cmdarg_T *cap)
case 'q':
case 'w':
oap->cursor_start = curwin->w_cursor;
- /*FALLTHROUGH*/
+ FALLTHROUGH;
case '~':
case 'u':
case 'U':
@@ -6943,8 +7048,6 @@ static void nv_g_cmd(cmdarg_T *cap)
*/
static void n_opencmd(cmdarg_T *cap)
{
- linenr_T oldline = curwin->w_cursor.lnum;
-
if (!checkclearopq(cap->oap)) {
if (cap->cmdchar == 'O')
/* Open above the first line of a folded sequence of lines */
@@ -6963,10 +7066,7 @@ static void n_opencmd(cmdarg_T *cap)
has_format_option(FO_OPEN_COMS)
? OPENLINE_DO_COM : 0,
0)) {
- if (curwin->w_p_cole > 0 && oldline != curwin->w_cursor.lnum) {
- update_single_line(curwin, oldline);
- }
- if (curwin->w_p_cul) {
+ if (win_cursorline_standout(curwin)) {
// force redraw of cursorline
curwin->w_valid &= ~VALID_CROW;
}
@@ -7067,7 +7167,7 @@ static void set_op_var(int optype)
assert(opchar0 >= 0 && opchar0 <= UCHAR_MAX);
opchars[0] = (char) opchar0;
- int opchar1 = get_extra_op_char(optype);
+ int opchar1 = get_extra_op_char(optype);
assert(opchar1 >= 0 && opchar1 <= UCHAR_MAX);
opchars[1] = (char) opchar1;
@@ -7185,8 +7285,10 @@ static void nv_wordcmd(cmdarg_T *cap)
// Another strangeness: When standing on the end of a word "ce" will
// change until the end of the next word, but "cw" will change only one
// character! This is done by setting "flag".
- cap->oap->inclusive = true;
- word_end = true;
+ if (vim_strchr(p_cpo, CPO_CHANGEW) != NULL) {
+ cap->oap->inclusive = true;
+ word_end = true;
+ }
flag = true;
}
}
@@ -7280,11 +7382,11 @@ static bool unadjust_for_sel(void)
pp = &curwin->w_cursor;
else
pp = &VIsual;
- if (pp->coladd > 0)
- --pp->coladd;
- else if (pp->col > 0) {
- --pp->col;
- mb_adjustpos(curbuf, pp);
+ if (pp->coladd > 0) {
+ pp->coladd--;
+ } else if (pp->col > 0) {
+ pp->col--;
+ mark_mb_adjustpos(curbuf, pp);
} else if (pp->lnum > 1) {
--pp->lnum;
pp->col = (colnr_T)STRLEN(ml_get(pp->lnum));
@@ -7378,8 +7480,10 @@ static void nv_esc(cmdarg_T *cap)
if (restart_edit == 0
&& cmdwin_type == 0
&& !VIsual_active
- && no_reason)
- MSG(_("Type :quit<Enter> to exit Nvim"));
+ && no_reason) {
+ MSG(_("Type :qa! and press <Enter> to abandon all changes"
+ " and exit Nvim"));
+ }
/* Don't reset "restart_edit" when 'insertmode' is set, it won't be
* set again below when halfway through a mapping. */
@@ -7410,27 +7514,23 @@ static void nv_esc(cmdarg_T *cap)
restart_edit = 'a';
}
-/*
- * Handle "A", "a", "I", "i" and <Insert> commands.
- */
+/// Handle "A", "a", "I", "i" and <Insert> commands.
static void nv_edit(cmdarg_T *cap)
{
- /* <Insert> is equal to "i" */
- if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS)
+ // <Insert> is equal to "i"
+ if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS) {
cap->cmdchar = 'i';
+ }
- /* in Visual mode "A" and "I" are an operator */
- if (VIsual_active && (cap->cmdchar == 'A' || cap->cmdchar == 'I'))
+ // in Visual mode "A" and "I" are an operator
+ if (VIsual_active && (cap->cmdchar == 'A' || cap->cmdchar == 'I')) {
v_visop(cap);
-
- /* in Visual mode and after an operator "a" and "i" are for text objects */
- else if ((cap->cmdchar == 'a' || cap->cmdchar == 'i')
- && (cap->oap->op_type != OP_NOP
- || VIsual_active
- )) {
+ // in Visual mode and after an operator "a" and "i" are for text objects
+ } else if ((cap->cmdchar == 'a' || cap->cmdchar == 'i')
+ && (cap->oap->op_type != OP_NOP || VIsual_active)) {
nv_object(cap);
- } else if (!curbuf->b_p_ma && !p_im) {
- /* Only give this error when 'insertmode' is off. */
+ } else if (!curbuf->b_p_ma && !p_im && !curbuf->terminal) {
+ // Only give this error when 'insertmode' is off.
EMSG(_(e_modifiable));
clearop(cap->oap);
} else if (!checkclearopq(cap->oap)) {
@@ -7603,11 +7703,13 @@ static void nv_record(cmdarg_T *cap)
if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') {
stuffcharReadbuff(cap->nchar);
stuffcharReadbuff(K_CMDWIN);
- } else
- /* (stop) recording into a named register, unless executing a
- * register */
- if (!Exec_reg && do_record(cap->nchar) == false)
- clearopbeep(cap->oap);
+ } else {
+ // (stop) recording into a named register, unless executing a
+ // register.
+ if (!Exec_reg && do_record(cap->nchar) == FAIL) {
+ clearopbeep(cap->oap);
+ }
+ }
}
}
@@ -7716,16 +7818,22 @@ static void nv_put(cmdarg_T *cap)
savereg = copy_register(regname);
}
- /* Now delete the selected text. */
- cap->cmdchar = 'd';
- cap->nchar = NUL;
- cap->oap->regname = NUL;
- nv_operator(cap);
- do_pending_operator(cap, 0, false);
- empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
+ // To place the cursor correctly after a blockwise put, and to leave the
+ // text in the correct position when putting over a selection with
+ // 'virtualedit' and past the end of the line, we use the 'c' operator in
+ // do_put(), which requires the visual selection to still be active.
+ if (!VIsual_active || VIsual_mode == 'V' || regname != '.') {
+ // Now delete the selected text.
+ cap->cmdchar = 'd';
+ cap->nchar = NUL;
+ cap->oap->regname = NUL;
+ nv_operator(cap);
+ do_pending_operator(cap, 0, false);
+ empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
- /* delete PUT_LINE_BACKWARD; */
- cap->oap->regname = regname;
+ // delete PUT_LINE_BACKWARD;
+ cap->oap->regname = regname;
+ }
/* When deleted a linewise Visual area, put the register as
* lines to avoid it joined with the next line. When deletion was
@@ -7809,7 +7917,7 @@ static void get_op_vcol(
colnr_T end;
if (VIsual_mode != Ctrl_V
- || (!initial && oap->end.col < curwin->w_width)) {
+ || (!initial && oap->end.col < curwin->w_grid.Columns)) {
return;
}
@@ -7817,7 +7925,7 @@ static void get_op_vcol(
// prevent from moving onto a trail byte
if (has_mbyte) {
- mb_adjustpos(curwin->w_buffer, &oap->end);
+ mark_mb_adjustpos(curwin->w_buffer, &oap->end);
}
getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
@@ -7872,28 +7980,17 @@ static void nv_event(cmdarg_T *cap)
{
// Garbage collection should have been executed before blocking for events in
// the `os_inchar` in `state_enter`, but we also disable it here in case the
- // `os_inchar` branch was not executed(!queue_empty(loop.events), which could
- // have `may_garbage_collect` set to true in `normal_check`).
+ // `os_inchar` branch was not executed (!multiqueue_empty(loop.events), which
+ // could have `may_garbage_collect` set to true in `normal_check`).
//
// That is because here we may run code that calls `os_inchar`
// later(`f_confirm` or `get_keystroke` for example), but in these cases it is
// not safe to perform garbage collection because there could be unreferenced
// lists or dicts being used.
may_garbage_collect = false;
- queue_process_events(main_loop.events);
+ multiqueue_process_events(main_loop.events);
cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
-}
-
-/// Trigger FocusGained event.
-static void nv_focusgained(cmdarg_T *cap)
-{
- apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
-}
-
-/// Trigger FocusLost event.
-static void nv_focuslost(cmdarg_T *cap)
-{
- apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
+ finish_op = false;
}
/*