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.c98
1 files changed, 57 insertions, 41 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 382c4943ff..b17b4c584e 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -36,7 +36,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"
@@ -460,7 +459,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);
}
@@ -974,7 +973,7 @@ static int normal_execute(VimState *state, int key)
s->old_col = curwin->w_curswant;
s->c = key;
- LANGMAP_ADJUST(s->c, true);
+ LANGMAP_ADJUST(s->c, get_real_state() != SELECTMODE);
// If a mapping was started in Visual or Select mode, remember the length
// of the mapping. This is used below to not return to Insert mode for as
@@ -1131,6 +1130,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();
@@ -1361,7 +1361,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.
@@ -1518,10 +1518,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" */
@@ -1795,10 +1792,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
if (oap->line_count < 2)
oap->line_count = 2;
if (curwin->w_cursor.lnum + oap->line_count - 1 >
- curbuf->b_ml.ml_line_count)
+ curbuf->b_ml.ml_line_count) {
beep_flush();
- else {
- do_join(oap->line_count, oap->op_type == OP_JOIN, true, true, true);
+ } else {
+ do_join((size_t)oap->line_count, oap->op_type == OP_JOIN,
+ true, true, true);
auto_format(false, true);
}
break;
@@ -2109,6 +2107,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.
@@ -2345,12 +2357,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;
}
@@ -2457,7 +2464,7 @@ do_mouse (
(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);
+ &doesrange, true, NULL, NULL);
clear_tv(&rettv);
break;
}
@@ -2465,10 +2472,7 @@ do_mouse (
}
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;
}
@@ -3640,10 +3644,11 @@ 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();
+ }
}
/*
@@ -3659,7 +3664,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;
@@ -3671,6 +3676,7 @@ find_decl (
bool save_p_scs;
bool retval = true;
bool incll;
+ int searchflags = flags_arg;
pat = xmalloc(len + 7);
@@ -3744,10 +3750,12 @@ find_decl (
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. */
+ // 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. Remove SEARCH_START from
+ // flags to avoid getting stuck at one position.
found_pos = curwin->w_cursor;
+ searchflags &= ~SEARCH_START;
}
if (t == false) {
@@ -5918,6 +5926,8 @@ static void nv_replace(cmdarg_T *cap)
curwin->w_set_curswant = true;
set_last_insert(cap->nchar);
}
+
+ foldUpdateAfterInsert();
}
/*
@@ -7666,7 +7676,7 @@ static void nv_join(cmdarg_T *cap)
prep_redo(cap->oap->regname, cap->count0,
NUL, cap->cmdchar, NUL, NUL, cap->nchar);
- do_join(cap->count0, cap->nchar == NUL, true, true, true);
+ do_join((size_t)cap->count0, cap->nchar == NUL, true, true, true);
}
}
@@ -7715,16 +7725,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
@@ -7871,15 +7887,15 @@ 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(loop.events);
+ multiqueue_process_events(main_loop.events);
cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
}