diff options
Diffstat (limited to 'src/nvim/normal.c')
-rw-r--r-- | src/nvim/normal.c | 1139 |
1 files changed, 149 insertions, 990 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 47ad000385..8f4240c062 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -8,14 +8,21 @@ // #include <assert.h> +#include <ctype.h> #include <inttypes.h> +#include <limits.h> #include <stdbool.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> +#include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/ascii.h" +#include "nvim/autocmd.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/change.h" #include "nvim/charset.h" #include "nvim/cmdhist.h" @@ -25,8 +32,6 @@ #include "nvim/drawscreen.h" #include "nvim/edit.h" #include "nvim/eval.h" -#include "nvim/eval/userfunc.h" -#include "nvim/event/loop.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" @@ -34,18 +39,18 @@ #include "nvim/fileio.h" #include "nvim/fold.h" #include "nvim/getchar.h" +#include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/grid.h" #include "nvim/help.h" -#include "nvim/indent.h" +#include "nvim/highlight_defs.h" #include "nvim/keycodes.h" -#include "nvim/log.h" -#include "nvim/main.h" +#include "nvim/macros.h" #include "nvim/mapping.h" #include "nvim/mark.h" +#include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" -#include "nvim/menu.h" #include "nvim/message.h" #include "nvim/mouse.h" #include "nvim/move.h" @@ -57,16 +62,19 @@ #include "nvim/plines.h" #include "nvim/profile.h" #include "nvim/quickfix.h" +#include "nvim/screen.h" #include "nvim/search.h" #include "nvim/spell.h" #include "nvim/spellfile.h" #include "nvim/spellsuggest.h" #include "nvim/state.h" +#include "nvim/statusline.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" #include "nvim/textformat.h" #include "nvim/textobject.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/vim.h" @@ -145,8 +153,7 @@ static const struct nv_cmd { nv_func_T cmd_func; ///< function for this command uint16_t cmd_flags; ///< NV_ flags int16_t cmd_arg; ///< value for ca.arg -} nv_cmds[] = -{ +} nv_cmds[] = { { NUL, nv_error, 0, 0 }, { Ctrl_A, nv_addsub, 0, 0 }, { Ctrl_B, nv_page, NV_STS, BACKWARD }, @@ -613,6 +620,7 @@ static bool normal_need_redraw_mode_message(NormalState *s) && stuff_empty() && typebuf_typed() && emsg_silent == 0 + && !in_assert_fails && !did_wait_return && s->oa.op_type == OP_NOP); } @@ -629,18 +637,18 @@ static void normal_redraw_mode_message(NormalState *s) // If need to redraw, and there is a "keep_msg", redraw before the // delay if (must_redraw && keep_msg != NULL && !emsg_on_display) { - char_u *kmsg; + char *kmsg; - kmsg = (char_u *)keep_msg; + kmsg = keep_msg; keep_msg = NULL; // Showmode() will clear keep_msg, but we want to use it anyway. // First update w_topline. setcursor(); - update_screen(0); + update_screen(); // now reset it, otherwise it's put in the history again - keep_msg = (char *)kmsg; + keep_msg = kmsg; - kmsg = vim_strsave((char_u *)keep_msg); + kmsg = xstrdup(keep_msg); msg_attr((const char *)kmsg, keep_msg_attr); xfree(kmsg); } @@ -1132,6 +1140,7 @@ static int normal_execute(VimState *state, int key) if (s->need_flushbuf) { ui_flush(); } + if (s->ca.cmdchar != K_IGNORE && s->ca.cmdchar != K_EVENT) { did_cursorhold = false; } @@ -1222,8 +1231,7 @@ static void normal_check_interrupt(NormalState *s) static void normal_check_window_scrolled(NormalState *s) { if (!finish_op) { - // Trigger Scroll if the viewport changed. - may_trigger_winscrolled(); + may_trigger_win_scrolled_resized(); } } @@ -1284,9 +1292,9 @@ static void normal_redraw(NormalState *s) if (VIsual_active) { redraw_curbuf_later(UPD_INVERTED); // update inverted part - update_screen(0); + update_screen(); } else if (must_redraw) { - update_screen(0); + update_screen(); } else if (redraw_cmdline || clear_cmdline || redraw_mode) { showmode(); } @@ -1389,6 +1397,9 @@ static int normal_check(VimState *state) fclose(time_fd); time_fd = NULL; } + // After the first screen update may start triggering WinScrolled + // autocmd events. Store all the scroll positions and sizes now. + may_make_initial_scroll_size_snapshot(); } // May perform garbage collection when waiting for a character, but @@ -1433,856 +1444,6 @@ static void set_vcount_ca(cmdarg_T *cap, bool *set_prevcount) *set_prevcount = false; // only set v:prevcount once } -/// 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); - } -} - -/// Call click definition function for column "col" in the "click_defs" array for button -/// "which_button". -static void call_click_def_func(StlClickDefinition *click_defs, int col, int which_button) -{ - typval_T argv[] = { - { - .v_lock = VAR_FIXED, - .v_type = VAR_NUMBER, - .vval = { - .v_number = (varnumber_T)click_defs[col].tabnr - }, - }, - { - .v_lock = VAR_FIXED, - .v_type = VAR_NUMBER, - .vval = { - .v_number = ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK - ? 4 - : ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK - ? 3 - : ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK - ? 2 - : 1))) - }, - }, - { - .v_lock = VAR_FIXED, - .v_type = VAR_STRING, - .vval = { - .v_string = (which_button == MOUSE_LEFT - ? "l" - : (which_button == MOUSE_RIGHT - ? "r" - : (which_button == MOUSE_MIDDLE - ? "m" - : "?"))) - }, - }, - { - .v_lock = VAR_FIXED, - .v_type = VAR_STRING, - .vval = { - .v_string = (char[]) { - (char)(mod_mask & MOD_MASK_SHIFT ? 's' : ' '), - (char)(mod_mask & MOD_MASK_CTRL ? 'c' : ' '), - (char)(mod_mask & MOD_MASK_ALT ? 'a' : ' '), - (char)(mod_mask & MOD_MASK_META ? 'm' : ' '), - NUL - } - }, - } - }; - typval_T rettv; - (void)call_vim_function(click_defs[col].func, ARRAY_SIZE(argv), argv, &rettv); - tv_clear(&rettv); -} - -/// Do the appropriate action for the current mouse click in the current mode. -/// Not used for Command-line 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 (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 -/// middle press - yes if active no yank and put -/// right press - yes start or extend yes -/// right press S yes no change yes "#" (2) -/// right drag - yes extend no -/// right relse - yes extend no -/// -/// Insert or Replace Mode: -/// event modi- position visual change action -/// fier cursor window -/// left press - yes (cannot be active) yes -/// left press C yes (cannot be active) yes "CTRL-O^]" (2) -/// left press S yes (cannot be active) yes "CTRL-O*" (2) -/// left drag - yes start or extend (1) no CTRL-O (1) -/// left relse - yes start or extend (1) no CTRL-O (1) -/// middle press - no (cannot be active) no put register -/// right press - yes start or extend yes CTRL-O -/// right press S yes (cannot be active) yes "CTRL-O#" (2) -/// -/// (1) only if mouse pointer moved since press -/// (2) only if click is in same buffer -/// -/// @param oap operator argument, can be NULL -/// @param c K_LEFTMOUSE, etc -/// @param dir Direction to 'put' if necessary -/// @param fixindent PUT_FIXINDENT if fixing indent necessary -/// -/// @return true if start_arrow() should be called for edit mode. -bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) -{ - static bool got_click = false; // got a click some time back - - int which_button; // MOUSE_LEFT, _MIDDLE or _RIGHT - bool is_click; // If false it's a drag or release event - bool is_drag; // If true it's a drag event - int jump_flags = 0; // flags for jump_to_mouse() - pos_T start_visual; - bool moved; // Has cursor moved? - bool in_winbar; // mouse in window bar - bool in_status_line; // mouse in status line - static bool in_tab_line = false; // mouse clicked in tab line - bool in_sep_line; // mouse in vertical separator line - int c1, c2; - pos_T save_cursor; - win_T *old_curwin = curwin; - static pos_T orig_cursor; - colnr_T leftcol, rightcol; - pos_T end_visual; - long diff; - int old_active = VIsual_active; - int old_mode = VIsual_mode; - int regname; - - save_cursor = curwin->w_cursor; - - for (;;) { - which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag); - if (is_drag) { - // If the next character is the same mouse event then use that - // one. Speeds up dragging the status line. - // Note: Since characters added to the stuff buffer in the code - // below need to come before the next character, do not do this - // when the current character was stuffed. - if (!KeyStuffed && vpeekc() != NUL) { - int nc; - int save_mouse_grid = mouse_grid; - int save_mouse_row = mouse_row; - int save_mouse_col = mouse_col; - - // Need to get the character, peeking doesn't get the actual one. - nc = safe_vgetc(); - if (c == nc) { - continue; - } - vungetc(nc); - mouse_grid = save_mouse_grid; - mouse_row = save_mouse_row; - mouse_col = save_mouse_col; - } - } - break; - } - - if (c == K_MOUSEMOVE) { - // Mouse moved without a button pressed. - return false; - } - - // Ignore drag and release events if we didn't get a click. - if (is_click) { - got_click = true; - } else { - if (!got_click) { // didn't get click, ignore - return false; - } - if (!is_drag) { // release, reset got_click - got_click = false; - if (in_tab_line) { - in_tab_line = false; - return false; - } - } - } - - // CTRL right mouse button does CTRL-T - if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT) { - if (State & MODE_INSERT) { - stuffcharReadbuff(Ctrl_O); - } - if (count > 1) { - stuffnumReadbuff(count); - } - stuffcharReadbuff(Ctrl_T); - got_click = false; // ignore drag&release now - return false; - } - - // CTRL only works with left mouse button - if ((mod_mask & MOD_MASK_CTRL) && which_button != MOUSE_LEFT) { - return false; - } - - // When a modifier is down, ignore drag and release events, as well as - // multiple clicks and the middle mouse button. - // Accept shift-leftmouse drags when 'mousemodel' is "popup.*". - if ((mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT - | MOD_MASK_META)) - && (!is_click - || (mod_mask & MOD_MASK_MULTI_CLICK) - || which_button == MOUSE_MIDDLE) - && !((mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT)) - && mouse_model_popup() - && which_button == MOUSE_LEFT) - && !((mod_mask & MOD_MASK_ALT) - && !mouse_model_popup() - && which_button == MOUSE_RIGHT)) { - return false; - } - - // If the button press was used as the movement command for an operator (eg - // "d<MOUSE>"), or it is the middle button that is held down, ignore - // drag/release events. - if (!is_click && which_button == MOUSE_MIDDLE) { - return false; - } - - if (oap != NULL) { - regname = oap->regname; - } else { - regname = 0; - } - - // Middle mouse button does a 'put' of the selected text - if (which_button == MOUSE_MIDDLE) { - if (State == MODE_NORMAL) { - // If an operator was pending, we don't know what the user wanted to do. - // Go back to normal mode: Clear the operator and beep(). - if (oap != NULL && oap->op_type != OP_NOP) { - clearopbeep(oap); - return false; - } - - // If visual was active, yank the highlighted text and put it - // before the mouse pointer position. - // In Select mode replace the highlighted text with the clipboard. - if (VIsual_active) { - if (VIsual_select) { - stuffcharReadbuff(Ctrl_G); - stuffReadbuff("\"+p"); - } else { - stuffcharReadbuff('y'); - stuffcharReadbuff(K_MIDDLEMOUSE); - } - return false; - } - // The rest is below jump_to_mouse() - } else if ((State & MODE_INSERT) == 0) { - return false; - } - - // Middle click in insert mode doesn't move the mouse, just insert the - // contents of a register. '.' register is special, can't insert that - // with do_put(). - // Also paste at the cursor if the current mode isn't in 'mouse' (only - // happens for the GUI). - if ((State & MODE_INSERT)) { - if (regname == '.') { - insert_reg(regname, true); - } else { - if (regname == 0 && eval_has_provider("clipboard")) { - regname = '*'; - } - if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) { - insert_reg(regname, true); - } 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); - AppendCharToRedobuff(fixindent ? Ctrl_P : Ctrl_O); - AppendCharToRedobuff(regname == 0 ? '"' : regname); - } - } - return false; - } - } - - // When dragging or button-up stay in the same window. - if (!is_click) { - jump_flags |= MOUSE_FOCUS | MOUSE_DID_MOVE; - } - - start_visual.lnum = 0; - - // Check for clicking in the tab page line. - if (mouse_grid <= 1 && mouse_row == 0 && firstwin->w_winrow > 0) { - if (is_drag) { - if (in_tab_line) { - move_tab_to_mouse(); - } - return false; - } - - // click in a tab selects that tab page - if (is_click - && cmdwin_type == 0 - && mouse_col < Columns) { - in_tab_line = true; - c1 = tab_page_click_defs[mouse_col].tabnr; - switch (tab_page_click_defs[mouse_col].type) { - case kStlClickDisabled: - break; - case kStlClickTabClose: { - tabpage_T *tp; - - // Close the current or specified tab page. - if (c1 == 999) { - tp = curtab; - } else { - tp = find_tabpage(c1); - } - if (tp == curtab) { - if (first_tabpage->tp_next != NULL) { - tabpage_close(false); - } - } else if (tp != NULL) { - tabpage_close_other(tp, false); - } - break; - } - case kStlClickTabSwitch: - if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) { - // double click opens new page - end_visual_mode(); - tabpage_new(); - tabpage_move(c1 == 0 ? 9999 : c1 - 1); - } else { - // Go to specified tab page, or next one if not clicking - // on a label. - goto_tabpage(c1); - - // It's like clicking on the status line of a window. - if (curwin != old_curwin) { - end_visual_mode(); - } - } - break; - case kStlClickFuncRun: - call_click_def_func(tab_page_click_defs, mouse_col, which_button); - break; - } - } - return true; - } else if (is_drag && in_tab_line) { - move_tab_to_mouse(); - return false; - } - - // When 'mousemodel' is "popup" or "popup_setpos", translate mouse events: - // right button up -> pop-up menu - // shift-left button -> right button - // alt-left button -> alt-right button - if (mouse_model_popup()) { - if (which_button == MOUSE_RIGHT - && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) { - if (!is_click) { - // Ignore right button release events, only shows the popup - // menu on the button down event. - return false; - } - 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(curwin->w_cursor, VIsual) - && (lt(m_pos, curwin->w_cursor) || lt(VIsual, m_pos))) - || (lt(VIsual, curwin->w_cursor) - && (lt(m_pos, VIsual) || lt(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 { - jump_flags = MOUSE_MAY_STOP_VIS; - } - } - if (jump_flags) { - jump_flags = jump_to_mouse(jump_flags, NULL, which_button); - redraw_curbuf_later(VIsual_active ? UPD_INVERTED : UPD_VALID); - update_screen(0); - setcursor(); - ui_flush(); // Update before showing popup menu - } - show_popupmenu(); - got_click = false; // ignore release events - return (jump_flags & CURSOR_MOVED) != 0; - } - if (which_button == MOUSE_LEFT - && (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT))) { - which_button = MOUSE_RIGHT; - mod_mask &= ~MOD_MASK_SHIFT; - } - } - - if ((State & (MODE_NORMAL | MODE_INSERT)) - && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) { - if (which_button == MOUSE_LEFT) { - if (is_click) { - // stop Visual mode for a left click in a window, but not when on a status line - if (VIsual_active) { - jump_flags |= MOUSE_MAY_STOP_VIS; - } - } else { - jump_flags |= MOUSE_MAY_VIS; - } - } else if (which_button == MOUSE_RIGHT) { - if (is_click && VIsual_active) { - // Remember the start and end of visual before moving the cursor. - if (lt(curwin->w_cursor, VIsual)) { - start_visual = curwin->w_cursor; - end_visual = VIsual; - } else { - start_visual = VIsual; - end_visual = curwin->w_cursor; - } - } - jump_flags |= MOUSE_FOCUS; - jump_flags |= MOUSE_MAY_VIS; - } - } - - // If an operator is pending, ignore all drags and releases until the next mouse click. - if (!is_drag && oap != NULL && oap->op_type != OP_NOP) { - got_click = false; - oap->motion_type = kMTCharWise; - } - - // When releasing the button let jump_to_mouse() know. - if (!is_click && !is_drag) { - jump_flags |= MOUSE_RELEASED; - } - - // JUMP! - jump_flags = jump_to_mouse(jump_flags, - oap == NULL ? NULL : &(oap->inclusive), - which_button); - - moved = (jump_flags & CURSOR_MOVED); - in_winbar = (jump_flags & MOUSE_WINBAR); - in_status_line = (jump_flags & IN_STATUS_LINE); - in_sep_line = (jump_flags & IN_SEP_LINE); - - if ((in_winbar || in_status_line) && is_click) { - // Handle click event on window bar or status lin - int click_grid = mouse_grid; - int click_row = mouse_row; - int click_col = mouse_col; - win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col); - if (wp == NULL) { - return false; - } - - StlClickDefinition *click_defs = in_status_line ? wp->w_status_click_defs - : wp->w_winbar_click_defs; - - if (in_status_line && global_stl_height() > 0) { - // global statusline is displayed for the current window, - // and spans the whole screen. - click_defs = curwin->w_status_click_defs; - click_col = mouse_col; - } - - if (click_defs != NULL) { - switch (click_defs[click_col].type) { - case kStlClickDisabled: - break; - case kStlClickFuncRun: - call_click_def_func(click_defs, click_col, which_button); - break; - default: - assert(false && "winbar and statusline only support %@ for clicks"); - break; - } - } - - return false; - } else if (in_winbar) { - // A drag or release event in the window bar has no side effects. - return false; - } - - // When jumping to another window, clear a pending operator. That's a bit - // friendlier than beeping and not jumping to that window. - if (curwin != old_curwin && oap != NULL && oap->op_type != OP_NOP) { - clearop(oap); - } - - if (mod_mask == 0 - && !is_drag - && (jump_flags & (MOUSE_FOLD_CLOSE | MOUSE_FOLD_OPEN)) - && which_button == MOUSE_LEFT) { - // open or close a fold at this line - if (jump_flags & MOUSE_FOLD_OPEN) { - openFold(curwin->w_cursor, 1L); - } else { - closeFold(curwin->w_cursor, 1L); - } - // don't move the cursor if still in the same window - if (curwin == old_curwin) { - curwin->w_cursor = save_cursor; - } - } - - // Set global flag that we are extending the Visual area with mouse dragging; - // temporarily minimize 'scrolloff'. - if (VIsual_active && is_drag && get_scrolloff_value(curwin)) { - // In the very first line, allow scrolling one line - if (mouse_row == 0) { - mouse_dragging = 2; - } else { - mouse_dragging = 1; - } - } - - // When dragging the mouse above the window, scroll down. - if (is_drag && mouse_row < 0 && !in_status_line) { - scroll_redraw(false, 1L); - mouse_row = 0; - } - - if (start_visual.lnum) { // right click in visual mode - // When ALT is pressed make Visual mode blockwise. - if (mod_mask & MOD_MASK_ALT) { - VIsual_mode = Ctrl_V; - } - - // In Visual-block mode, divide the area in four, pick up the corner - // that is in the quarter that the cursor is in. - if (VIsual_mode == Ctrl_V) { - getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol); - if (curwin->w_curswant > (leftcol + rightcol) / 2) { - end_visual.col = leftcol; - } else { - end_visual.col = rightcol; - } - if (curwin->w_cursor.lnum >= - (start_visual.lnum + end_visual.lnum) / 2) { - end_visual.lnum = start_visual.lnum; - } - - // move VIsual to the right column - start_visual = curwin->w_cursor; // save the cursor pos - curwin->w_cursor = end_visual; - coladvance(end_visual.col); - VIsual = curwin->w_cursor; - curwin->w_cursor = start_visual; // restore the cursor - } else { - // If the click is before the start of visual, change the start. - // If the click is after the end of visual, change the end. If - // the click is inside the visual, change the closest side. - if (lt(curwin->w_cursor, start_visual)) { - VIsual = end_visual; - } else if (lt(end_visual, curwin->w_cursor)) { - VIsual = start_visual; - } else { - // In the same line, compare column number - if (end_visual.lnum == start_visual.lnum) { - if (curwin->w_cursor.col - start_visual.col > - end_visual.col - curwin->w_cursor.col) { - VIsual = start_visual; - } else { - VIsual = end_visual; - } - } else { - // In different lines, compare line number - diff = (curwin->w_cursor.lnum - start_visual.lnum) - - (end_visual.lnum - curwin->w_cursor.lnum); - - if (diff > 0) { // closest to end - VIsual = start_visual; - } else if (diff < 0) { // closest to start - VIsual = end_visual; - } else { // in the middle line - if (curwin->w_cursor.col < - (start_visual.col + end_visual.col) / 2) { - VIsual = end_visual; - } else { - VIsual = start_visual; - } - } - } - } - } - } else if ((State & MODE_INSERT) && VIsual_active) { - // If Visual mode started in insert mode, execute "CTRL-O" - stuffcharReadbuff(Ctrl_O); - } - - // Middle mouse click: Put text before cursor. - if (which_button == MOUSE_MIDDLE) { - if (regname == 0 && eval_has_provider("clipboard")) { - regname = '*'; - } - if (yank_register_mline(regname)) { - if (mouse_past_bottom) { - dir = FORWARD; - } - } else if (mouse_past_eol) { - dir = FORWARD; - } - - if (fixindent) { - c1 = (dir == BACKWARD) ? '[' : ']'; - c2 = 'p'; - } else { - c1 = (dir == FORWARD) ? 'p' : 'P'; - c2 = NUL; - } - prep_redo(regname, count, NUL, c1, NUL, c2, NUL); - - // Remember where the paste started, so in edit() Insstart can be set to this position - if (restart_edit != 0) { - where_paste_started = curwin->w_cursor; - } - do_put(regname, NULL, dir, count, - (fixindent ? PUT_FIXINDENT : 0)| PUT_CURSEND); - } else if (((mod_mask & MOD_MASK_CTRL) || (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) - && bt_quickfix(curbuf)) { - // Ctrl-Mouse click or double click in a quickfix window jumps to the - // error under the mouse pointer. - 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 - } else if ((mod_mask & MOD_MASK_CTRL) - || (curbuf->b_help && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)) { - // Ctrl-Mouse click (or double click in a help window) jumps to the tag - // under the mouse pointer. - if (State & MODE_INSERT) { - stuffcharReadbuff(Ctrl_O); - } - stuffcharReadbuff(Ctrl_RSB); - got_click = false; // ignore drag&release now - } else if ((mod_mask & MOD_MASK_SHIFT)) { - // Shift-Mouse click searches for the next occurrence of the word under - // the mouse pointer - if (State & MODE_INSERT || (VIsual_active && VIsual_select)) { - stuffcharReadbuff(Ctrl_O); - } - if (which_button == MOUSE_LEFT) { - stuffcharReadbuff('*'); - } else { // MOUSE_RIGHT - stuffcharReadbuff('#'); - } - } else if (in_status_line || in_sep_line) { - // Do nothing if on status line or vertical separator - // Handle double clicks otherwise - } else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (MODE_NORMAL | MODE_INSERT))) { - if (is_click || !VIsual_active) { - if (VIsual_active) { - orig_cursor = VIsual; - } else { - VIsual = curwin->w_cursor; - orig_cursor = VIsual; - VIsual_active = true; - VIsual_reselect = true; - // start Select mode if 'selectmode' contains "mouse" - may_start_select('o'); - setmouse(); - } - if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) { - // Double click with ALT pressed makes it blockwise. - if (mod_mask & MOD_MASK_ALT) { - VIsual_mode = Ctrl_V; - } else { - VIsual_mode = 'v'; - } - } else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK) { - VIsual_mode = 'V'; - } else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK) { - VIsual_mode = Ctrl_V; - } - } - // A double click selects a word or a block. - if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) { - pos_T *pos = NULL; - int gc; - - if (is_click) { - // If the character under the cursor (skipping white space) is - // not a word character, try finding a match and select a (), - // {}, [], #if/#endif, etc. block. - end_visual = curwin->w_cursor; - while (gc = gchar_pos(&end_visual), ascii_iswhite(gc)) { - inc(&end_visual); - } - if (oap != NULL) { - oap->motion_type = kMTCharWise; - } - if (oap != NULL - && VIsual_mode == 'v' - && !vim_iswordc(gchar_pos(&end_visual)) - && equalpos(curwin->w_cursor, VIsual) - && (pos = findmatch(oap, NUL)) != NULL) { - curwin->w_cursor = *pos; - if (oap->motion_type == kMTLineWise) { - VIsual_mode = 'V'; - } else if (*p_sel == 'e') { - if (lt(curwin->w_cursor, VIsual)) { - VIsual.col++; - } else { - curwin->w_cursor.col++; - } - } - } - } - - if (pos == NULL && (is_click || is_drag)) { - // When not found a match or when dragging: extend to include a word. - if (lt(curwin->w_cursor, orig_cursor)) { - find_start_of_word(&curwin->w_cursor); - find_end_of_word(&VIsual); - } else { - find_start_of_word(&VIsual); - if (*p_sel == 'e' && *get_cursor_pos_ptr() != NUL) { - curwin->w_cursor.col += - utfc_ptr2len((char *)get_cursor_pos_ptr()); - } - find_end_of_word(&curwin->w_cursor); - } - } - curwin->w_set_curswant = true; - } - if (is_click) { - redraw_curbuf_later(UPD_INVERTED); // update the inversion - } - } else if (VIsual_active && !old_active) { - if (mod_mask & MOD_MASK_ALT) { - VIsual_mode = Ctrl_V; - } else { - VIsual_mode = 'v'; - } - } - - // If Visual mode changed show it later. - if ((!VIsual_active && old_active && mode_displayed) - || (VIsual_active && p_smd && msg_silent == 0 - && (!old_active || VIsual_mode != old_mode))) { - redraw_cmdline = true; - } - - return moved; -} - -/// Move "pos" back to the start of the word it's in. -static void find_start_of_word(pos_T *pos) -{ - char_u *line; - int cclass; - int col; - - line = ml_get(pos->lnum); - cclass = get_mouse_class(line + pos->col); - - while (pos->col > 0) { - col = pos->col - 1; - col -= utf_head_off(line, line + col); - if (get_mouse_class(line + col) != cclass) { - break; - } - pos->col = col; - } -} - -/// Move "pos" forward to the end of the word it's in. -/// When 'selection' is "exclusive", the position is just after the word. -static void find_end_of_word(pos_T *pos) -{ - char_u *line; - int cclass; - int col; - - line = ml_get(pos->lnum); - if (*p_sel == 'e' && pos->col > 0) { - pos->col--; - pos->col -= utf_head_off(line, line + pos->col); - } - cclass = get_mouse_class(line + pos->col); - while (line[pos->col] != NUL) { - col = pos->col + utfc_ptr2len((char *)line + pos->col); - if (get_mouse_class(line + col) != cclass) { - if (*p_sel == 'e') { - pos->col = col; - } - break; - } - pos->col = col; - } -} - -/// Get class of a character for selection: same class means same word. -/// 0: blank -/// 1: punctuation groups -/// 2: normal word character -/// >2: multi-byte word character. -static int get_mouse_class(char_u *p) -{ - if (MB_BYTE2LEN(p[0]) > 1) { - return mb_get_class(p); - } - - const int c = *p; - if (c == ' ' || c == '\t') { - return 0; - } - if (vim_iswordc(c)) { - return 2; - } - - // There are a few special cases where we want certain combinations of - // characters to be considered as a single word. These are things like - // "->", "/ *", "*=", "+=", "&=", "<=", ">=", "!=" etc. Otherwise, each - // character is in its own class. - if (c != NUL && vim_strchr("-+*/%<>&|^!=", c) != NULL) { - return 1; - } - return c; -} - /// End Visual mode. /// This function should ALWAYS be called to end Visual mode, except from /// do_pending_operator(). @@ -2416,7 +1577,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text // if i == 0: try to find an identifier // if i == 1: try to find any non-white text - char_u *ptr = ml_get_buf(wp->w_buffer, lnum, false); + char *ptr = ml_get_buf(wp->w_buffer, lnum, false); for (i = (find_type & FIND_IDENT) ? 0 : 1; i < 2; i++) { // 1. skip to start of identifier/text col = startcol; @@ -2429,7 +1590,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text if (this_class != 0 && (i == 1 || this_class != 1)) { break; } - col += utfc_ptr2len((char *)ptr + col); + col += utfc_ptr2len(ptr + col); } // When starting on a ']' count it, so that we include the '['. @@ -2440,7 +1601,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text // // Remember class of character under cursor. if ((find_type & FIND_EVAL) && ptr[col] == ']') { - this_class = mb_get_class((char_u *)"a"); + this_class = mb_get_class("a"); } else { this_class = mb_get_class(ptr + col); } @@ -2453,7 +1614,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text || (find_type & FIND_IDENT)) && (!(find_type & FIND_EVAL) || prevcol == 0 - || !find_is_eval_item(ptr + prevcol, &prevcol, &bn, BACKWARD))) { + || !find_is_eval_item((char_u *)ptr + prevcol, &prevcol, &bn, BACKWARD))) { break; } col = prevcol; @@ -2479,7 +1640,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text return 0; } ptr += col; - *text = (char *)ptr; + *text = ptr; if (textcol != NULL) { *textcol = col; } @@ -2496,8 +1657,8 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text : 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((char *)ptr + col); + && find_is_eval_item((char_u *)ptr + col, &col, &bn, FORWARD)))) { + col += utfc_ptr2len(ptr + col); } assert(col >= 0); @@ -2622,9 +1783,7 @@ void may_clear_cmdline(void) } // Routines for displaying a partly typed command -#define SHOWCMD_BUFLEN (SHOWCMD_COLS + 1 + 30) -static char_u showcmd_buf[SHOWCMD_BUFLEN]; -static char_u old_showcmd_buf[SHOWCMD_BUFLEN]; // For push_showcmd() +static char old_showcmd_buf[SHOWCMD_BUFLEN]; // For push_showcmd() static bool showcmd_is_clear = true; static bool showcmd_visual = false; @@ -2663,12 +1822,12 @@ void clear_showcmd(void) getvcols(curwin, &curwin->w_cursor, &VIsual, &leftcol, &rightcol); p_sbr = saved_sbr; curwin->w_p_sbr = saved_w_sbr; - snprintf((char *)showcmd_buf, SHOWCMD_BUFLEN, "%" PRId64 "x%" PRId64, + snprintf(showcmd_buf, SHOWCMD_BUFLEN, "%" PRId64 "x%" PRId64, (int64_t)lines, (int64_t)rightcol - leftcol + 1); } else if (VIsual_mode == 'V' || VIsual.lnum != curwin->w_cursor.lnum) { - snprintf((char *)showcmd_buf, SHOWCMD_BUFLEN, "%" PRId64, (int64_t)lines); + snprintf(showcmd_buf, SHOWCMD_BUFLEN, "%" PRId64, (int64_t)lines); } else { - char_u *s, *e; + char *s, *e; int l; int bytes = 0; int chars = 0; @@ -2681,7 +1840,7 @@ void clear_showcmd(void) e = ml_get_pos(&VIsual); } while ((*p_sel != 'e') ? s <= e : s < e) { - l = utfc_ptr2len((char *)s); + l = utfc_ptr2len(s); if (l == 0) { bytes++; chars++; @@ -2692,9 +1851,9 @@ void clear_showcmd(void) s += l; } if (bytes == chars) { - sprintf((char *)showcmd_buf, "%d", chars); + snprintf(showcmd_buf, SHOWCMD_BUFLEN, "%d", chars); } else { - sprintf((char *)showcmd_buf, "%d-%d", chars, bytes); + snprintf(showcmd_buf, SHOWCMD_BUFLEN, "%d-%d", chars, bytes); } } int limit = ui_has(kUIMessages) ? SHOWCMD_BUFLEN - 1 : SHOWCMD_COLS; @@ -2751,8 +1910,8 @@ bool add_to_showcmd(int c) if (*p == ' ') { STRCPY(p, "<20>"); } - size_t old_len = STRLEN(showcmd_buf); - size_t extra_len = STRLEN(p); + size_t old_len = strlen(showcmd_buf); + size_t extra_len = strlen(p); size_t limit = ui_has(kUIMessages) ? SHOWCMD_BUFLEN - 1 : SHOWCMD_COLS; if (old_len + extra_len > limit) { size_t overflow = old_len + extra_len - limit; @@ -2784,7 +1943,7 @@ static void del_from_showcmd(int len) return; } - old_len = (int)STRLEN(showcmd_buf); + old_len = (int)strlen(showcmd_buf); if (len > old_len) { len = old_len; } @@ -2817,13 +1976,23 @@ void pop_showcmd(void) static void display_showcmd(void) { - if (!ui_has_messages()) { + int len = (int)strlen(showcmd_buf); + showcmd_is_clear = (len == 0); + + if (*p_sloc == 's') { + win_redr_status(curwin); + setcursor(); // put cursor back where it belongs + return; + } + if (*p_sloc == 't') { + draw_tabline(); + setcursor(); // put cursor back where it belongs + return; + } + // 'showcmdloc' is "last" or empty + if (p_ch == 0 && !ui_has(kUIMessages)) { return; } - - int len; - len = (int)STRLEN(showcmd_buf); - showcmd_is_clear = (len == 0); if (ui_has(kUIMessages)) { MAXSIZE_TEMP_ARRAY(content, 1); @@ -2831,7 +2000,7 @@ static void display_showcmd(void) if (len > 0) { // placeholder for future highlight support ADD_C(chunk, INTEGER_OBJ(0)); - ADD_C(chunk, STRING_OBJ(cstr_as_string((char *)showcmd_buf))); + ADD_C(chunk, STRING_OBJ(cstr_as_string(showcmd_buf))); ADD_C(content, ARRAY_OBJ(chunk)); } ui_call_msg_showcmd(content); @@ -2843,7 +2012,7 @@ static void display_showcmd(void) grid_puts_line_start(&msg_grid_adj, showcmd_row); if (!showcmd_is_clear) { - grid_puts(&msg_grid_adj, (char *)showcmd_buf, showcmd_row, sc_col, + grid_puts(&msg_grid_adj, showcmd_buf, showcmd_row, sc_col, HL_ATTR(HLF_MSG)); } @@ -3059,7 +2228,7 @@ static void nv_gd(oparg_T *oap, int nchar, int thisblock) /// @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) +static bool is_ident(const char_u *line, int offset) { bool incomment = false; int instring = 0; @@ -3100,7 +2269,7 @@ static bool is_ident(char_u *line, int offset) /// @return fail when not found. bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_arg) { - char_u *pat; + char *pat; pos_T old_pos; pos_T par_pos; pos_T found_pos; @@ -3116,7 +2285,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_ // Put "\V" before the pattern to avoid that the special meaning of "." // and "~" causes trouble. assert(len <= INT_MAX); - sprintf((char *)pat, vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", + sprintf(pat, vim_iswordp((char *)ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", // NOLINT(runtime/printf) (int)len, ptr); old_pos = curwin->w_cursor; save_p_ws = p_ws; @@ -3134,7 +2303,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_ } else { par_pos = curwin->w_cursor; while (curwin->w_cursor.lnum > 1 - && *skipwhite((char *)get_cursor_line_ptr()) != NUL) { + && *skipwhite(get_cursor_line_ptr()) != NUL) { curwin->w_cursor.lnum--; } } @@ -3144,7 +2313,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_ clearpos(&found_pos); for (;;) { t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD, - pat, 1L, searchflags, RE_LAST, NULL); + (char_u *)pat, 1L, searchflags, RE_LAST, NULL); if (curwin->w_cursor.lnum >= old_pos.lnum) { t = false; // match after start is failure too } @@ -3171,13 +2340,13 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_ } break; } - if (get_leader_len((char *)get_cursor_line_ptr(), NULL, false, true) > 0) { + if (get_leader_len(get_cursor_line_ptr(), NULL, false, true) > 0) { // Ignore this line, continue at start of next line. curwin->w_cursor.lnum++; curwin->w_cursor.col = 0; continue; } - bool valid = is_ident(get_cursor_line_ptr(), curwin->w_cursor.col); + bool valid = is_ident((char_u *)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. @@ -3361,7 +2530,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist) virtcol -= vim_strsize((char *)get_showbreak_value(curwin)); } - int c = utf_ptr2char((char *)get_cursor_pos_ptr()); + int c = utf_ptr2char(get_cursor_pos_ptr()); if (dir == FORWARD && virtcol < curwin->w_curswant && (curwin->w_curswant <= (colnr_T)width1) && !vim_isprintc(c) && c > 255) { @@ -3410,7 +2579,7 @@ static void nv_mousescroll(cmdarg_T *cap) if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN) { if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { (void)onepage(cap->arg ? FORWARD : BACKWARD, 1L); - } else { + } else if (p_mousescroll_vert > 0) { cap->count1 = p_mousescroll_vert; cap->count0 = p_mousescroll_vert; nv_scroll_line(cap); @@ -3514,6 +2683,7 @@ static bool nv_z_get_count(cmdarg_T *cap, int *nchar_arg) no_mapping--; allow_keys--; (void)add_to_showcmd(nchar); + if (nchar == K_DEL || nchar == K_KDEL) { n /= 10; } else if (ascii_isdigit(nchar)) { @@ -3554,6 +2724,7 @@ static int nv_zg_zw(cmdarg_T *cap, int nchar) no_mapping--; allow_keys--; (void)add_to_showcmd(nchar); + if (vim_strchr("gGwW", nchar) == NULL) { clearopbeep(cap->oap); return OK; @@ -3579,7 +2750,7 @@ static int nv_zg_zw(cmdarg_T *cap, int nchar) len = spell_move_to(curwin, FORWARD, true, true, NULL); emsg_off--; if (len != 0 && curwin->w_cursor.col <= pos.col) { - ptr = (char *)ml_get_pos(&curwin->w_cursor); + ptr = ml_get_pos(&curwin->w_cursor); } curwin->w_cursor = pos; } @@ -3588,7 +2759,7 @@ static int nv_zg_zw(cmdarg_T *cap, int nchar) return FAIL; } assert(len <= INT_MAX); - spell_add_word((char_u *)ptr, (int)len, + spell_add_word(ptr, (int)len, nchar == 'w' || nchar == 'W' ? SPELL_ADD_BAD : SPELL_ADD_GOOD, (nchar == 'G' || nchar == 'W') ? 0 : (int)cap->count1, undo); @@ -3605,7 +2776,7 @@ static void nv_zet(cmdarg_T *cap) long old_fdl = curwin->w_p_fdl; int old_fen = curwin->w_p_fen; - int l_p_siso = (int)get_sidescrolloff_value(curwin); + int siso = (int)get_sidescrolloff_value(curwin); if (ascii_isdigit(nchar) && !nv_z_get_count(cap, &nchar)) { return; @@ -3735,8 +2906,8 @@ static void nv_zet(cmdarg_T *cap) } else { getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL); } - if (col > l_p_siso) { - col -= l_p_siso; + if (col > siso) { + col -= siso; } else { col = 0; } @@ -3756,10 +2927,10 @@ static void nv_zet(cmdarg_T *cap) getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col); } n = curwin->w_width_inner - curwin_col_off(); - if (col + l_p_siso < n) { + if (col + siso < n) { col = 0; } else { - col = col + l_p_siso - n + 1; + col = col + siso - n + 1; } if (curwin->w_leftcol != col) { curwin->w_leftcol = col; @@ -4057,7 +3228,7 @@ static void nv_colon(cmdarg_T *cap) } else if (cap->oap->op_type != OP_NOP && (cap->oap->start.lnum > curbuf->b_ml.ml_line_count || cap->oap->start.col > - (colnr_T)STRLEN(ml_get(cap->oap->start.lnum)) + (colnr_T)strlen(ml_get(cap->oap->start.lnum)) || did_emsg)) { // The start of the operator has become invalid by the Ex command. clearopbeep(cap->oap); @@ -4164,7 +3335,7 @@ void do_nv_ident(int c1, int c2) /// 'K' normal-mode command. Get the command to lookup the keyword under the /// cursor. -static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, char **ptr_arg, +static size_t nv_K_getcmd(cmdarg_T *cap, char *kp, bool kp_help, bool kp_ex, char **ptr_arg, size_t n, char *buf, size_t buf_size) { if (kp_help) { @@ -4201,8 +3372,8 @@ static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, c // When a count is given, turn it into a range. Is this // really what we want? - bool isman = (STRCMP(kp, "man") == 0); - bool isman_s = (STRCMP(kp, "man -s") == 0); + bool isman = (strcmp(kp, "man") == 0); + bool isman_s = (strcmp(kp, "man -s") == 0); if (cap->count0 != 0 && !(isman || isman_s)) { snprintf(buf, buf_size, ".,.+%" PRId64, (int64_t)(cap->count0 - 1)); } @@ -4216,7 +3387,7 @@ static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, c } STRCAT(buf, " "); if (cap->count0 != 0 && (isman || isman_s)) { - snprintf(buf + STRLEN(buf), buf_size - STRLEN(buf), "%" PRId64, + snprintf(buf + strlen(buf), buf_size - strlen(buf), "%" PRId64, (int64_t)cap->count0); STRCAT(buf, " "); } @@ -4234,12 +3405,12 @@ static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, c static void nv_ident(cmdarg_T *cap) { char *ptr = NULL; - char_u *p; + char *p; size_t n = 0; // init for GCC int cmdchar; bool g_cmd; // "g" command bool tag_cmd = false; - char_u *aux_ptr; + char *aux_ptr; if (cap->cmdchar == 'g') { // "g*", "g#", "g]" and "gCTRL-]" cmdchar = cap->nchar; @@ -4275,14 +3446,14 @@ static void nv_ident(cmdarg_T *cap) // Allocate buffer to put the command in. Inserting backslashes can // double the length of the word. p_kp / curbuf->b_p_kp could be added // and some numbers. - char_u *kp = *curbuf->b_p_kp == NUL ? p_kp : (char_u *)curbuf->b_p_kp; // 'keywordprg' - bool kp_help = (*kp == NUL || STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0); + char *kp = *curbuf->b_p_kp == NUL ? (char *)p_kp : curbuf->b_p_kp; // 'keywordprg' + bool kp_help = (*kp == NUL || strcmp(kp, ":he") == 0 || strcmp(kp, ":help") == 0); if (kp_help && *skipwhite(ptr) == NUL) { emsg(_(e_noident)); // found white space only return; } bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command - size_t buf_size = n * 2 + 30 + STRLEN(kp); + size_t buf_size = n * 2 + 30 + strlen(kp); char *buf = xmalloc(buf_size); buf[0] = NUL; @@ -4294,9 +3465,9 @@ static void nv_ident(cmdarg_T *cap) // Call setpcmark() first, so "*``" puts the cursor back where // it was. setpcmark(); - curwin->w_cursor.col = (colnr_T)(ptr - (char *)get_cursor_line_ptr()); + curwin->w_cursor.col = (colnr_T)(ptr - get_cursor_line_ptr()); - if (!g_cmd && vim_iswordp((char_u *)ptr)) { + if (!g_cmd && vim_iswordp(ptr)) { STRCPY(buf, "\\<"); } no_smartcase = true; // don't use 'smartcase' now @@ -4311,11 +3482,7 @@ static void nv_ident(cmdarg_T *cap) case ']': tag_cmd = true; - if (p_cst) { - STRCPY(buf, "cstag "); - } else { - STRCPY(buf, "ts "); - } + STRCPY(buf, "ts "); break; default: @@ -4336,45 +3503,45 @@ static void nv_ident(cmdarg_T *cap) ptr = xstrnsave(ptr, n); if (kp_ex) { // Escape the argument properly for an Ex command - p = (char_u *)vim_strsave_fnameescape((const char *)ptr, VSE_NONE); + p = vim_strsave_fnameescape((const char *)ptr, VSE_NONE); } else { // Escape the argument properly for a shell command - p = vim_strsave_shellescape((char_u *)ptr, true, true); + p = vim_strsave_shellescape(ptr, true, true); } xfree(ptr); - char *newbuf = xrealloc(buf, STRLEN(buf) + STRLEN(p) + 1); + char *newbuf = xrealloc(buf, strlen(buf) + strlen(p) + 1); buf = newbuf; STRCAT(buf, p); xfree(p); } else { if (cmdchar == '*') { - aux_ptr = (char_u *)(p_magic ? "/.*~[^$\\" : "/^$\\"); + aux_ptr = (magic_isset() ? "/.*~[^$\\" : "/^$\\"); } else if (cmdchar == '#') { - aux_ptr = (char_u *)(p_magic ? "/?.*~[^$\\" : "/?^$\\"); + aux_ptr = (magic_isset() ? "/?.*~[^$\\" : "/?^$\\"); } else if (tag_cmd) { if (curbuf->b_help) { // ":help" handles unescaped argument - aux_ptr = (char_u *)""; + aux_ptr = ""; } else { - aux_ptr = (char_u *)"\\|\"\n["; + aux_ptr = "\\|\"\n["; } } else { - aux_ptr = (char_u *)"\\|\"\n*?["; + aux_ptr = "\\|\"\n*?["; } - p = (char_u *)buf + STRLEN(buf); + p = buf + strlen(buf); while (n-- > 0) { // put a backslash before \ and some others - if (vim_strchr((char *)aux_ptr, *ptr) != NULL) { + if (vim_strchr(aux_ptr, *ptr) != NULL) { *p++ = '\\'; } // When current byte is a part of multibyte character, copy all // bytes of that character. const size_t len = (size_t)(utfc_ptr2len(ptr) - 1); for (size_t i = 0; i < len && n > 0; i++, n--) { - *p++ = (char_u)(*ptr++); + *p++ = *ptr++; } - *p++ = (char_u)(*ptr++); + *p++ = *ptr++; } *p = NUL; } @@ -4382,13 +3549,13 @@ static void nv_ident(cmdarg_T *cap) // Execute the command. if (cmdchar == '*' || cmdchar == '#') { if (!g_cmd - && vim_iswordp(mb_prevptr(get_cursor_line_ptr(), (char_u *)ptr))) { + && vim_iswordp(mb_prevptr(get_cursor_line_ptr(), ptr))) { STRCAT(buf, "\\>"); } // put pattern in search history init_history(); - add_to_history(HIST_SEARCH, (char_u *)buf, true, NUL); + add_to_history(HIST_SEARCH, buf, true, NUL); (void)normal_search(cap, cmdchar == '*' ? '/' : '?', buf, 0, NULL); } else { @@ -4425,14 +3592,14 @@ bool get_visual_text(cmdarg_T *cap, char **pp, size_t *lenp) return false; } if (VIsual_mode == 'V') { - *pp = (char *)get_cursor_line_ptr(); - *lenp = STRLEN(*pp); + *pp = get_cursor_line_ptr(); + *lenp = strlen(*pp); } else { if (lt(curwin->w_cursor, VIsual)) { - *pp = (char *)ml_get_pos(&curwin->w_cursor); + *pp = ml_get_pos(&curwin->w_cursor); *lenp = (size_t)VIsual.col - (size_t)curwin->w_cursor.col + 1; } else { - *pp = (char *)ml_get_pos(&VIsual); + *pp = ml_get_pos(&VIsual); *lenp = (size_t)curwin->w_cursor.col - (size_t)VIsual.col + 1; } if (**pp == NUL) { @@ -4451,7 +3618,7 @@ bool get_visual_text(cmdarg_T *cap, char **pp, size_t *lenp) static void nv_tagpop(cmdarg_T *cap) { if (!checkclearopq(cap->oap)) { - do_tag((char_u *)"", DT_POP, (int)cap->count1, false, true); + do_tag("", DT_POP, (int)cap->count1, false, true); } } @@ -4478,7 +3645,9 @@ static void nv_scroll(cmdarg_T *cap) && curwin->w_cursor.lnum > curwin->w_topline; n--) { (void)hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL); - curwin->w_cursor.lnum--; + if (curwin->w_cursor.lnum > curwin->w_topline) { + curwin->w_cursor.lnum--; + } } } else { curwin->w_cursor.lnum -= (linenr_T)cap->count1 - 1; @@ -4600,7 +3769,7 @@ static void nv_right(cmdarg_T *cap) if (virtual_active()) { oneright(); } else { - curwin->w_cursor.col += utfc_ptr2len((char *)get_cursor_pos_ptr()); + curwin->w_cursor.col += utfc_ptr2len(get_cursor_pos_ptr()); } } } @@ -4648,10 +3817,10 @@ static void nv_left(cmdarg_T *cap) // 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(); + char *cp = get_cursor_pos_ptr(); if (*cp != NUL) { - curwin->w_cursor.col += utfc_ptr2len((char *)cp); + curwin->w_cursor.col += utfc_ptr2len(cp); } cap->retval |= CA_NO_ADJ_OP_END; } @@ -4723,7 +3892,7 @@ static void nv_down(cmdarg_T *cap) /// Grab the file name under the cursor and edit it. static void nv_gotofile(cmdarg_T *cap) { - char_u *ptr; + char *ptr; linenr_T lnum = -1; if (check_text_locked(cap->oap)) { @@ -4734,7 +3903,7 @@ static void nv_gotofile(cmdarg_T *cap) return; } - ptr = grab_file_name(cap->count1, &lnum); + ptr = (char *)grab_file_name(cap->count1, &lnum); if (ptr != NULL) { // do autowrite if necessary @@ -4742,7 +3911,7 @@ static void nv_gotofile(cmdarg_T *cap) (void)autowrite(curbuf, false); } setpcmark(); - if (do_ecmd(0, (char *)ptr, NULL, NULL, ECMD_LAST, + 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; @@ -4849,7 +4018,7 @@ static int normal_search(cmdarg_T *cap, int dir, char *pat, int opt, int *wrappe curwin->w_set_curswant = true; CLEAR_FIELD(sia); - int i = do_search(cap->oap, dir, dir, (char_u *)pat, cap->count1, + int i = do_search(cap->oap, dir, dir, pat, cap->count1, opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, &sia); if (wrapped != NULL) { *wrapped = sia.sa_wrapped; @@ -5058,7 +4227,7 @@ static void nv_brackets(cmdarg_T *cap) } else { // Make a copy, if the line was changed it will be freed. ptr = xstrnsave(ptr, len); - find_pattern_in_path((char_u *)ptr, 0, len, true, + find_pattern_in_path(ptr, 0, len, true, cap->count0 == 0 ? !isupper(cap->nchar) : false, (((cap->nchar & 0xf) == ('d' & 0xf)) ? FIND_DEFINE @@ -5151,9 +4320,8 @@ static void nv_brackets(cmdarg_T *cap) cap->nchar == 's', false, NULL) == 0) { clearopbeep(cap->oap); break; - } else { - curwin->w_set_curswant = true; } + curwin->w_set_curswant = true; } if (cap->oap->op_type == OP_NOP && (fdo_flags & FDO_SEARCH) && KeyTyped) { foldOpenCursor(); @@ -5297,7 +4465,7 @@ static void nv_kundo(cmdarg_T *cap) /// Handle the "r" command. static void nv_replace(cmdarg_T *cap) { - char_u *ptr; + char *ptr; int had_ctrl_v; if (checkclearop(cap->oap)) { @@ -5361,7 +4529,7 @@ static void nv_replace(cmdarg_T *cap) // Abort if not enough characters to replace. ptr = get_cursor_pos_ptr(); - if (STRLEN(ptr) < (unsigned)cap->count1 + if (strlen(ptr) < (unsigned)cap->count1 || (mb_charlen(ptr) < cap->count1)) { clearopbeep(cap->oap); return; @@ -5692,6 +4860,10 @@ static void nv_gomark(cmdarg_T *cap) { int name; MarkMove flags = jop_flags & JOP_VIEW ? kMarkSetView : 0; // flags for moving to the mark + if (cap->oap->op_type != OP_NOP) { + // When there is a pending operator, do not restore the view as this is usually unexpected. + flags = 0; + } MarkMoveRes move_res = 0; // Result from moving to the mark const bool old_KeyTyped = KeyTyped; // getting file may reset it @@ -5743,7 +4915,7 @@ static void nv_pcmark(cmdarg_T *cap) fm = get_changelist(curbuf, curwin, (int)cap->count1); } else { fm = get_jumplist(curwin, (int)cap->count1); - flags |= KMarkNoContext | kMarkJumpList; + flags |= KMarkNoContext | kMarkJumpList; } // Changelist and jumplist have their own error messages. Therefore avoid // calling nv_mark_move_to() when not found to avoid incorrect error @@ -5841,10 +5013,12 @@ static void nv_visual(cmdarg_T *cap) VIsual_mode = resel_VIsual_mode; if (VIsual_mode == 'v') { if (resel_VIsual_line_count <= 1) { - validate_virtcol(); + update_curswant_force(); assert(cap->count0 >= INT_MIN && cap->count0 <= INT_MAX); - curwin->w_curswant = (curwin->w_virtcol - + resel_VIsual_vcol * (int)cap->count0 - 1); + curwin->w_curswant += resel_VIsual_vcol * (int)cap->count0; + if (*p_sel != 'e') { + curwin->w_curswant--; + } } else { curwin->w_curswant = resel_VIsual_vcol; } @@ -5854,10 +5028,9 @@ static void nv_visual(cmdarg_T *cap) curwin->w_curswant = MAXCOL; coladvance(MAXCOL); } else if (VIsual_mode == Ctrl_V) { - validate_virtcol(); + update_curswant_force(); assert(cap->count0 >= INT_MIN && cap->count0 <= INT_MAX); - curwin->w_curswant = (curwin->w_virtcol - + resel_VIsual_vcol * (int)cap->count0 - 1); + curwin->w_curswant += resel_VIsual_vcol * (int)cap->count0 - 1; coladvance(curwin->w_curswant); } else { curwin->w_set_curswant = true; @@ -6068,7 +5241,7 @@ static void nv_g_underscore_cmd(cmdarg_T *cap) return; } - char_u *ptr = get_cursor_line_ptr(); + char *ptr = get_cursor_line_ptr(); // In Visual mode we may end up after the line. if (curwin->w_cursor.col > 0 && ptr[curwin->w_cursor.col] == NUL) { @@ -6106,9 +5279,7 @@ static void nv_g_dollar_cmd(cmdarg_T *cap) coladvance((colnr_T)i); // Make sure we stick in this column. - validate_virtcol(); - curwin->w_curswant = curwin->w_virtcol; - curwin->w_set_curswant = false; + update_curswant_force(); if (curwin->w_cursor.col > 0 && curwin->w_p_wrap) { // Check for landing on a character that got split at // the end of the line. We do not want to advance to @@ -6139,9 +5310,7 @@ static void nv_g_dollar_cmd(cmdarg_T *cap) } // Make sure we stick in this column. - validate_virtcol(); - curwin->w_curswant = curwin->w_virtcol; - curwin->w_set_curswant = false; + update_curswant_force(); } } @@ -6151,7 +5320,7 @@ static void nv_gi_cmd(cmdarg_T *cap) if (curbuf->b_last_insert.mark.lnum != 0) { curwin->w_cursor = curbuf->b_last_insert.mark; check_cursor_lnum(); - int i = (int)STRLEN(get_cursor_line_ptr()); + int i = (int)strlen(get_cursor_line_ptr()); if (curwin->w_cursor.col > (colnr_T)i) { if (virtual_active()) { curwin->w_cursor.coladd += curwin->w_cursor.col - i; @@ -6513,8 +5682,7 @@ static void n_opencmd(cmdarg_T *cap) if (u_save((linenr_T)(curwin->w_cursor.lnum - (cap->cmdchar == 'O' ? 1 : 0)), (linenr_T)(curwin->w_cursor.lnum + - (cap->cmdchar == 'o' ? 1 : 0)) - ) + (cap->cmdchar == 'o' ? 1 : 0))) && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD, has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : 0, 0, NULL)) { @@ -6834,7 +6002,7 @@ bool unadjust_for_sel(void) mark_mb_adjustpos(curbuf, pp); } else if (pp->lnum > 1) { pp->lnum--; - pp->col = (colnr_T)STRLEN(ml_get(pp->lnum)); + pp->col = (colnr_T)strlen(ml_get(pp->lnum)); return true; } } @@ -6917,10 +6085,7 @@ static void nv_esc(cmdarg_T *cap) && cap->oap->regname == 0); if (cap->arg) { // true for CTRL-C - if (restart_edit == 0 - && cmdwin_type == 0 - && !VIsual_active - && no_reason) { + if (restart_edit == 0 && cmdwin_type == 0 && !VIsual_active && no_reason) { if (anyBufIsChanged()) { msg(_("Type :qa! and press <Enter> to abandon all changes" " and exit Nvim")); @@ -6971,7 +6136,7 @@ void set_cursor_for_append_to_line(void) coladvance(MAXCOL); State = save_State; } else { - curwin->w_cursor.col += (colnr_T)STRLEN(get_cursor_pos_ptr()); + curwin->w_cursor.col += (colnr_T)strlen(get_cursor_pos_ptr()); } } @@ -7064,7 +6229,7 @@ static void nv_object(cmdarg_T *cap) { bool flag; bool include; - char_u *mps_save; + char *mps_save; if (cap->cmdchar == 'i') { include = false; // "ix" = inner object: exclude white space @@ -7072,7 +6237,7 @@ static void nv_object(cmdarg_T *cap) include = true; // "ax" = an object: include white space } // Make sure (), [], {} and <> are in 'matchpairs' - mps_save = (char_u *)curbuf->b_p_mps; + mps_save = curbuf->b_p_mps; curbuf->b_p_mps = "(:),{:},[:],<:>"; switch (cap->nchar) { @@ -7127,7 +6292,7 @@ static void nv_object(cmdarg_T *cap) break; } - curbuf->b_p_mps = (char *)mps_save; + curbuf->b_p_mps = mps_save; if (!flag) { clearopbeep(cap->oap); } @@ -7396,12 +6561,6 @@ static void nv_event(cmdarg_T *cap) } } -/// @return true when 'mousemodel' is set to "popup" or "popup_setpos". -static bool mouse_model_popup(void) -{ - return p_mousem[0] == 'p'; -} - void normal_cmd(oparg_T *oap, bool toplevel) { NormalState s; |