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.c800
1 files changed, 484 insertions, 316 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index ad53e9bf24..f5607f3676 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -569,36 +569,33 @@ static bool normal_need_aditional_char(NormalState *s)
static bool normal_need_redraw_mode_message(NormalState *s)
{
return (
- (
// 'showmode' is set and messages can be printed
- p_smd && msg_silent == 0
- // must restart insert mode(ctrl+o or ctrl+l) or we just entered visual
- // mode
- && (restart_edit != 0 || (VIsual_active
- && s->old_pos.lnum == curwin->w_cursor.lnum
- && s->old_pos.col == curwin->w_cursor.col))
- // command-line must be cleared or redrawn
- && (clear_cmdline || redraw_cmdline)
- // some message was printed or scrolled
- && (msg_didout || (msg_didany && msg_scroll))
- // it is fine to remove the current message
- && !msg_nowait
- // the command was the result of direct user input and not a mapping
- && KeyTyped
- )
- ||
- // must restart insert mode, not in visual mode and error message is
- // being shown
- (restart_edit != 0 && !VIsual_active && (msg_scroll && emsg_on_display))
- )
- // no register was used
- && s->oa.regname == 0
- && !(s->ca.retval & CA_COMMAND_BUSY)
- && stuff_empty()
- && typebuf_typed()
- && emsg_silent == 0
- && !did_wait_return
- && s->oa.op_type == OP_NOP;
+ ((p_smd && msg_silent == 0
+ // must restart insert mode(ctrl+o or ctrl+l) or we just entered visual
+ // mode
+ && (restart_edit != 0 || (VIsual_active
+ && s->old_pos.lnum == curwin->w_cursor.lnum
+ && s->old_pos.col == curwin->w_cursor.col))
+ // command-line must be cleared or redrawn
+ && (clear_cmdline || redraw_cmdline)
+ // some message was printed or scrolled
+ && (msg_didout || (msg_didany && msg_scroll))
+ // it is fine to remove the current message
+ && !msg_nowait
+ // the command was the result of direct user input and not a mapping
+ && KeyTyped)
+ // must restart insert mode, not in visual mode and error message is
+ // being shown
+ || (restart_edit != 0 && !VIsual_active && msg_scroll
+ && emsg_on_display))
+ // no register was used
+ && s->oa.regname == 0
+ && !(s->ca.retval & CA_COMMAND_BUSY)
+ && stuff_empty()
+ && typebuf_typed()
+ && emsg_silent == 0
+ && !did_wait_return
+ && s->oa.op_type == OP_NOP);
}
static void normal_redraw_mode_message(NormalState *s)
@@ -1205,9 +1202,9 @@ static void normal_check_interrupt(NormalState *s)
static void normal_check_cursor_moved(NormalState *s)
{
// Trigger CursorMoved if the cursor moved.
- if (!finish_op && (has_cursormoved() || curwin->w_p_cole > 0)
+ if (!finish_op && (has_event(EVENT_CURSORMOVED) || curwin->w_p_cole > 0)
&& !equalpos(last_cursormoved, curwin->w_cursor)) {
- if (has_cursormoved()) {
+ if (has_event(EVENT_CURSORMOVED)) {
apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, false, curbuf);
}
@@ -1224,7 +1221,7 @@ static void normal_check_cursor_moved(NormalState *s)
static void normal_check_text_changed(NormalState *s)
{
// Trigger TextChanged if b_changedtick differs.
- if (!finish_op && has_textchanged()
+ 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);
@@ -1414,11 +1411,12 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
int lbr_saved = curwin->w_p_lbr;
- /* The visual area is remembered for redo */
- static int redo_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */
- static linenr_T redo_VIsual_line_count; /* number of lines */
- static colnr_T redo_VIsual_vcol; /* number of cols or end column */
- static long redo_VIsual_count; /* count for Visual operator */
+ // The visual area is remembered for redo
+ static int redo_VIsual_mode = NUL; // 'v', 'V', or Ctrl-V
+ static linenr_T redo_VIsual_line_count; // number of lines
+ static colnr_T redo_VIsual_vcol; // number of cols or end column
+ static long redo_VIsual_count; // count for Visual operator
+ static int redo_VIsual_arg; // extra argument
bool include_line_break = false;
old_cursor = curwin->w_cursor;
@@ -1430,21 +1428,25 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
|| VIsual_active
) && oap->op_type != OP_NOP) {
// Avoid a problem with unwanted linebreaks in block mode
+ if (curwin->w_p_lbr) {
+ curwin->w_valid &= ~VALID_VIRTCOL;
+ }
curwin->w_p_lbr = false;
oap->is_VIsual = VIsual_active;
- if (oap->motion_force == 'V')
- oap->motion_type = MLINE;
- else if (oap->motion_force == 'v') {
- /* If the motion was linewise, "inclusive" will not have been set.
- * Use "exclusive" to be consistent. Makes "dvj" work nice. */
- if (oap->motion_type == MLINE)
+ if (oap->motion_force == 'V') {
+ oap->motion_type = kMTLineWise;
+ } else if (oap->motion_force == 'v') {
+ // If the motion was linewise, "inclusive" will not have been set.
+ // Use "exclusive" to be consistent. Makes "dvj" work nice.
+ if (oap->motion_type == kMTLineWise) {
oap->inclusive = false;
- /* If the motion already was characterwise, toggle "inclusive" */
- else if (oap->motion_type == MCHAR)
+ } else if (oap->motion_type == kMTCharWise) {
+ // If the motion already was characterwise, toggle "inclusive"
oap->inclusive = !oap->inclusive;
- oap->motion_type = MCHAR;
+ }
+ oap->motion_type = kMTCharWise;
} else if (oap->motion_force == Ctrl_V) {
- /* Change line- or characterwise motion into Visual block mode. */
+ // Change line- or characterwise motion into Visual block mode.
VIsual_active = true;
VIsual = oap->start;
VIsual_mode = Ctrl_V;
@@ -1534,9 +1536,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
curbuf->b_visual_mode_eval = VIsual_mode;
}
- /* In Select mode, a linewise selection is operated upon like a
- * characterwise selection. */
- if (VIsual_select && VIsual_mode == 'V') {
+ // In Select mode, a linewise selection is operated upon like a
+ // characterwise selection.
+ // Special case: gH<Del> deletes the last line.
+ if (VIsual_select && VIsual_mode == 'V'
+ && cap->oap->op_type != OP_DELETE) {
if (lt(VIsual, curwin->w_cursor)) {
VIsual.col = 0;
curwin->w_cursor.col =
@@ -1580,13 +1584,15 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
* automatically. */
curwin->w_valid &= ~VALID_VIRTCOL;
} else {
- /* Include folded lines completely. */
- if (!VIsual_active && oap->motion_type == MLINE) {
+ // Include folded lines completely.
+ if (!VIsual_active && oap->motion_type == kMTLineWise) {
if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum,
- NULL))
+ NULL)) {
curwin->w_cursor.col = 0;
- if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum))
+ }
+ if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum)) {
oap->start.col = (colnr_T)STRLEN(ml_get(oap->start.lnum));
+ }
}
oap->end = oap->start;
oap->start = curwin->w_cursor;
@@ -1598,55 +1604,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
virtual_op = virtual_active();
if (VIsual_active || redo_VIsual_busy) {
- if (VIsual_mode == Ctrl_V) { /* block mode */
- colnr_T start, end;
-
- oap->block_mode = true;
-
- getvvcol(curwin, &(oap->start),
- &oap->start_vcol, NULL, &oap->end_vcol);
- if (!redo_VIsual_busy) {
- getvvcol(curwin, &(oap->end), &start, NULL, &end);
-
- if (start < oap->start_vcol)
- oap->start_vcol = start;
- if (end > oap->end_vcol) {
- if (*p_sel == 'e' && start >= 1
- && start - 1 >= oap->end_vcol)
- oap->end_vcol = start - 1;
- else
- oap->end_vcol = end;
- }
- }
-
- /* if '$' was used, get oap->end_vcol from longest line */
- if (curwin->w_curswant == MAXCOL) {
- curwin->w_cursor.col = MAXCOL;
- oap->end_vcol = 0;
- for (curwin->w_cursor.lnum = oap->start.lnum;
- curwin->w_cursor.lnum <= oap->end.lnum;
- ++curwin->w_cursor.lnum) {
- getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
- if (end > oap->end_vcol)
- oap->end_vcol = end;
- }
- } else if (redo_VIsual_busy)
- oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1;
- /*
- * Correct oap->end.col and oap->start.col to be the
- * upper-left and lower-right corner of the block area.
- *
- * (Actually, this does convert column positions into character
- * positions)
- */
- curwin->w_cursor.lnum = oap->end.lnum;
- coladvance(oap->end_vcol);
- oap->end = curwin->w_cursor;
-
- curwin->w_cursor = oap->start;
- coladvance(oap->start_vcol);
- oap->start = curwin->w_cursor;
- }
+ get_op_vcol(oap, redo_VIsual_vcol, true);
if (!redo_VIsual_busy && !gui_yank) {
/*
@@ -1701,38 +1659,33 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
redo_VIsual_vcol = resel_VIsual_vcol;
redo_VIsual_line_count = resel_VIsual_line_count;
redo_VIsual_count = cap->count0;
+ redo_VIsual_arg = cap->arg;
}
}
- /*
- * oap->inclusive defaults to true.
- * If oap->end is on a NUL (empty line) oap->inclusive becomes
- * false. This makes "d}P" and "v}dP" work the same.
- */
- if (oap->motion_force == NUL || oap->motion_type == MLINE)
+ // oap->inclusive defaults to true.
+ // If oap->end is on a NUL (empty line) oap->inclusive becomes
+ // false. This makes "d}P" and "v}dP" work the same.
+ if (oap->motion_force == NUL || oap->motion_type == kMTLineWise) {
oap->inclusive = true;
- if (VIsual_mode == 'V')
- oap->motion_type = MLINE;
- else {
- oap->motion_type = MCHAR;
- if (VIsual_mode != Ctrl_V && *ml_get_pos(&(oap->end)) == NUL
+ }
+ if (VIsual_mode == 'V') {
+ oap->motion_type = kMTLineWise;
+ } else if (VIsual_mode == 'v') {
+ oap->motion_type = kMTCharWise;
+ if (*ml_get_pos(&(oap->end)) == NUL
&& (include_line_break || !virtual_op)
) {
oap->inclusive = false;
- /* Try to include the newline, unless it's an operator
- * that works on lines only. */
- if (*p_sel != 'o' && !op_on_lines(oap->op_type)) {
- if (oap->end.lnum < curbuf->b_ml.ml_line_count) {
- ++oap->end.lnum;
- oap->end.col = 0;
- oap->end.coladd = 0;
- ++oap->line_count;
- } else {
- /* Cannot move below the last line, make the op
- * inclusive to tell the operation to include the
- * line break. */
- oap->inclusive = true;
- }
+ // Try to include the newline, unless it's an operator
+ // that works on lines only.
+ if (*p_sel != 'o'
+ && !op_on_lines(oap->op_type)
+ && oap->end.lnum < curbuf->b_ml.ml_line_count) {
+ oap->end.lnum++;
+ oap->end.col = 0;
+ oap->end.coladd = 0;
+ oap->line_count++;
}
}
}
@@ -1750,10 +1703,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
VIsual_active = false;
setmouse();
mouse_dragging = 0;
- if (mode_displayed)
- clear_cmdline = true; /* unshow visual mode later */
- else
- clear_showcmd();
+ may_clear_cmdline();
if ((oap->op_type == OP_YANK
|| oap->op_type == OP_COLON
|| oap->op_type == OP_FUNCTION
@@ -1780,7 +1730,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
* oap->empty is set when start and end are the same. The inclusive
* flag affects this too, unless yanking and the end is on a NUL.
*/
- oap->empty = (oap->motion_type == MCHAR
+ oap->empty = (oap->motion_type != kMTLineWise
&& (!oap->inclusive
|| (oap->op_type == OP_YANK
&& gchar_pos(&oap->end) == NUL))
@@ -1805,24 +1755,23 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
/*
* If the end of an operator is in column one while oap->motion_type
- * is MCHAR and oap->inclusive is false, we put op_end after the last
+ * is kMTCharWise and oap->inclusive is false, we put op_end after the last
* character in the previous line. If op_start is on or before the
* first non-blank in the line, the operator becomes linewise
* (strange, but that's the way vi does it).
*/
- if ( oap->motion_type == MCHAR
- && oap->inclusive == false
- && !(cap->retval & CA_NO_ADJ_OP_END)
- && oap->end.col == 0
- && (!oap->is_VIsual || *p_sel == 'o')
- && !oap->block_mode
- && oap->line_count > 1) {
- oap->end_adjusted = true; /* remember that we did this */
- --oap->line_count;
- --oap->end.lnum;
- if (inindent(0))
- oap->motion_type = MLINE;
- else {
+ if (oap->motion_type == kMTCharWise
+ && oap->inclusive == false
+ && !(cap->retval & CA_NO_ADJ_OP_END)
+ && oap->end.col == 0
+ && (!oap->is_VIsual || *p_sel == 'o')
+ && oap->line_count > 1) {
+ oap->end_adjusted = true; // remember that we did this
+ oap->line_count--;
+ oap->end.lnum--;
+ if (inindent(0)) {
+ oap->motion_type = kMTLineWise;
+ } else {
oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
if (oap->end.col) {
--oap->end.col;
@@ -1861,8 +1810,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
CancelRedo();
} else {
(void)op_delete(oap);
- if (oap->motion_type == MLINE && has_format_option(FO_AUTO))
- u_save_cursor(); /* cursor line wasn't saved yet */
+ if (oap->motion_type == kMTLineWise && has_format_option(FO_AUTO)) {
+ u_save_cursor(); // cursor line wasn't saved yet
+ }
auto_format(false, true);
}
break;
@@ -1895,9 +1845,14 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
else
restart_edit_save = 0;
restart_edit = 0;
+
// Restore linebreak, so that when the user edits it looks as before.
- curwin->w_p_lbr = lbr_saved;
- /* Reset finish_op now, don't want it set inside edit(). */
+ if (curwin->w_p_lbr != lbr_saved) {
+ curwin->w_p_lbr = lbr_saved;
+ get_op_vcol(oap, redo_VIsual_mode, false);
+ }
+
+ // Reset finish_op now, don't want it set inside edit().
finish_op = false;
if (op_change(oap)) /* will call edit() */
cap->retval |= CA_COMMAND_BUSY;
@@ -1975,7 +1930,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
restart_edit = 0;
// Restore linebreak, so that when the user edits it looks as before.
- curwin->w_p_lbr = lbr_saved;
+ if (curwin->w_p_lbr != lbr_saved) {
+ curwin->w_p_lbr = lbr_saved;
+ get_op_vcol(oap, redo_VIsual_mode, false);
+ }
op_insert(oap, cap->count1);
@@ -1998,7 +1956,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
CancelRedo();
} else {
// Restore linebreak, so that when the user edits it looks as before.
- curwin->w_p_lbr = lbr_saved;
+ if (curwin->w_p_lbr != lbr_saved) {
+ curwin->w_p_lbr = lbr_saved;
+ get_op_vcol(oap, redo_VIsual_mode, false);
+ }
+
op_replace(oap, cap->nchar);
}
break;
@@ -2027,6 +1989,20 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
deleteFold(oap->start.lnum, oap->end.lnum,
oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
break;
+
+ case OP_NR_ADD:
+ case OP_NR_SUB:
+ if (empty_region_error) {
+ vim_beep(BO_OPER);
+ CancelRedo();
+ } else {
+ VIsual_active = true;
+ curwin->w_p_lbr = lbr_saved;
+ op_addsub(oap, cap->count1, redo_VIsual_arg);
+ VIsual_active = false;
+ }
+ check_cursor_col();
+ break;
default:
clearopbeep(oap);
}
@@ -2035,7 +2011,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
/*
* if 'sol' not set, go back to old column for some commands
*/
- if (!p_sol && oap->motion_type == MLINE && !oap->end_adjusted
+ if (!p_sol && oap->motion_type == kMTLineWise && !oap->end_adjusted
&& (oap->op_type == OP_LSHIFT || oap->op_type == OP_RSHIFT
|| oap->op_type == OP_DELETE)) {
curwin->w_p_lbr = false;
@@ -2044,7 +2020,6 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
} else {
curwin->w_cursor = old_cursor;
}
- oap->block_mode = false;
clearop(oap);
}
curwin->w_p_lbr = lbr_saved;
@@ -2111,16 +2086,18 @@ static void op_function(oparg_T *oap)
/* Set '[ and '] marks to text to be operated on. */
curbuf->b_op_start = oap->start;
curbuf->b_op_end = oap->end;
- if (oap->motion_type != MLINE && !oap->inclusive)
- /* Exclude the end position. */
+ if (oap->motion_type != kMTLineWise && !oap->inclusive) {
+ // Exclude the end position.
decl(&curbuf->b_op_end);
+ }
- if (oap->block_mode)
+ if (oap->motion_type == kMTBlockWise) {
argv[0] = (char_u *)"block";
- else if (oap->motion_type == MLINE)
+ } else if (oap->motion_type == kMTLineWise) {
argv[0] = (char_u *)"line";
- else
+ } else {
argv[0] = (char_u *)"char";
+ }
/* Reset virtual_op so that 'virtualedit' can be changed in the
* function. */
@@ -2368,8 +2345,12 @@ do_mouse (
if (mouse_row == 0 && firstwin->w_winrow > 0) {
if (is_drag) {
if (in_tab_line) {
- c1 = TabPageIdxs[mouse_col];
- tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
+ 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);
+ }
}
return false;
}
@@ -2379,41 +2360,114 @@ do_mouse (
&& cmdwin_type == 0
&& mouse_col < Columns) {
in_tab_line = true;
- c1 = TabPageIdxs[mouse_col];
- if (c1 >= 0) {
- 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)
+ 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: {
+ typval_T argv[] = {
+ {
+ .v_lock = VAR_FIXED,
+ .v_type = VAR_NUMBER,
+ .vval = {
+ .v_number = (varnumber_T) tab_page_click_defs[mouse_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 = (char_u *) (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_u[]) {
+ (char_u) (mod_mask & MOD_MASK_SHIFT ? 's' : ' '),
+ (char_u) (mod_mask & MOD_MASK_CTRL ? 'c' : ' '),
+ (char_u) (mod_mask & MOD_MASK_ALT ? 'a' : ' '),
+ (char_u) (mod_mask & MOD_MASK_META ? 'm' : ' '),
+ NUL
+ }
+ },
+ }
+ };
+ 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);
+ break;
}
- } else if (c1 < 0) {
- 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);
}
}
return true;
} else if (is_drag && in_tab_line) {
- c1 = TabPageIdxs[mouse_col];
- tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
+ tabpage_move(tab_page_click_defs[mouse_col].type == kStlClickTabClose
+ ? 9999
+ : tab_page_click_defs[mouse_col].tabnr - 1);
in_tab_line = false;
return false;
}
@@ -2477,7 +2531,7 @@ do_mouse (
*/
if (!is_drag && oap != NULL && oap->op_type != OP_NOP) {
got_click = false;
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
}
/* When releasing the button let jump_to_mouse() know. */
@@ -2545,11 +2599,10 @@ do_mouse (
end_visual.col = leftcol;
else
end_visual.col = rightcol;
- if (curwin->w_cursor.lnum <
- (start_visual.lnum + end_visual.lnum) / 2)
- end_visual.lnum = end_visual.lnum;
- else
+ 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 */
@@ -2717,21 +2770,23 @@ do_mouse (
end_visual = curwin->w_cursor;
while (gc = gchar_pos(&end_visual), ascii_iswhite(gc))
inc(&end_visual);
- if (oap != NULL)
- oap->motion_type = MCHAR;
+ 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 == MLINE)
+ 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;
+ } else if (*p_sel == 'e') {
+ if (lt(curwin->w_cursor, VIsual)) {
+ VIsual.col++;
+ } else {
+ curwin->w_cursor.col++;
+ }
}
}
}
@@ -2886,10 +2941,7 @@ void end_visual_mode(void)
if (!virtual_active())
curwin->w_cursor.coladd = 0;
- if (mode_displayed)
- clear_cmdline = true; /* unshow visual mode later */
- else
- clear_showcmd();
+ may_clear_cmdline();
adjust_cursor_eol();
}
@@ -3155,10 +3207,19 @@ static void unshift_special(cmdarg_T *cap)
cap->cmdchar = simplify_key(cap->cmdchar, &mod_mask);
}
-/*
- * Routines for displaying a partly typed command
- */
+/// If the mode is currently displayed clear the command line or update the
+/// command displayed.
+static void may_clear_cmdline(void)
+{
+ if (mode_displayed) {
+ // unshow visual mode later
+ clear_cmdline = true;
+ } else {
+ clear_showcmd();
+ }
+}
+// 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() */
@@ -3185,9 +3246,9 @@ void clear_showcmd(void)
top = curwin->w_cursor.lnum;
bot = VIsual.lnum;
}
- /* Include closed folds as a whole. */
- hasFolding(top, &top, NULL);
- hasFolding(bot, NULL, &bot);
+ // Include closed folds as a whole.
+ (void)hasFolding(top, &top, NULL);
+ (void)hasFolding(bot, NULL, &bot);
lines = bot - top + 1;
if (VIsual_mode == Ctrl_V) {
@@ -3537,9 +3598,16 @@ static void nv_help(cmdarg_T *cap)
*/
static void nv_addsub(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)
- && do_addsub(cap->cmdchar, cap->count1))
+ if (!VIsual_active && cap->oap->op_type == OP_NOP) {
prep_redo_cmd(cap);
+ cap->oap->op_type = cap->cmdchar == Ctrl_A ? OP_NR_ADD : OP_NR_SUB;
+ op_addsub(cap->oap, cap->count1, cap->arg);
+ cap->oap->op_type = OP_NOP;
+ } else if (VIsual_active) {
+ nv_operator(cap);
+ } else {
+ clearop(cap->oap);
+ }
}
/*
@@ -3716,7 +3784,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
int width1; /* text width for first screen line */
int width2; /* test width for wrapped screen line */
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
oap->inclusive = (curwin->w_curswant == MAXCOL);
col_off1 = curwin_col_off();
@@ -3861,6 +3929,8 @@ static void nv_mousescroll(cmdarg_T *cap)
cap->count0 = 3;
nv_scroll_line(cap);
}
+ } else {
+ mouse_scroll_horiz(cap->arg);
}
curwin->w_redr_status = true;
@@ -3987,16 +4057,15 @@ static void nv_zet(cmdarg_T *cap)
}
dozet:
- if (
- /* "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc"
- * and "zC" only in Visual mode. "zj" and "zk" are motion
- * commands. */
- cap->nchar != 'f' && cap->nchar != 'F'
- && !(VIsual_active && vim_strchr((char_u *)"dcCoO", cap->nchar))
- && cap->nchar != 'j' && cap->nchar != 'k'
- &&
- checkclearop(cap->oap))
+ // "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc"
+ // and "zC" only in Visual mode. "zj" and "zk" are motion
+ // commands. */
+ if (cap->nchar != 'f' && cap->nchar != 'F'
+ && !(VIsual_active && vim_strchr((char_u *)"dcCoO", cap->nchar))
+ && cap->nchar != 'j' && cap->nchar != 'k'
+ && checkclearop(cap->oap)) {
return;
+ }
/*
* For "z+", "z<CR>", "zt", "z.", "zz", "z^", "z-", "zb":
@@ -4033,6 +4102,7 @@ dozet:
case 't': scroll_cursor_top(0, true);
redraw_later(VALID);
+ set_fraction(curwin);
break;
/* "z." and "zz": put cursor in middle of screen */
@@ -4041,6 +4111,7 @@ dozet:
case 'z': scroll_cursor_halfway(true);
redraw_later(VALID);
+ set_fraction(curwin);
break;
/* "z^", "z-" and "zb": put cursor at bottom of screen */
@@ -4061,6 +4132,7 @@ dozet:
case 'b': scroll_cursor_bot(0, true);
redraw_later(VALID);
+ set_fraction(curwin);
break;
/* "zH" - scroll screen right half-page */
@@ -4394,8 +4466,8 @@ static void nv_colon(cmdarg_T *cap)
nv_operator(cap);
else {
if (cap->oap->op_type != OP_NOP) {
- /* Using ":" as a movement is characterwise exclusive. */
- cap->oap->motion_type = MCHAR;
+ // 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)" */
@@ -4794,7 +4866,7 @@ static void nv_scroll(cmdarg_T *cap)
linenr_T lnum;
int half;
- cap->oap->motion_type = MLINE;
+ cap->oap->motion_type = kMTLineWise;
setpcmark();
if (cap->cmdchar == 'L') {
@@ -4874,7 +4946,7 @@ static void nv_right(cmdarg_T *cap)
return;
}
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
PAST_LINE = (VIsual_active && *p_sel != 'o');
@@ -4961,7 +5033,7 @@ static void nv_left(cmdarg_T *cap)
return;
}
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
for (n = cap->count1; n > 0; --n) {
if (oneleft() == false) {
@@ -5023,11 +5095,12 @@ static void nv_up(cmdarg_T *cap)
cap->arg = BACKWARD;
nv_page(cap);
} else {
- cap->oap->motion_type = MLINE;
- if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false)
+ cap->oap->motion_type = kMTLineWise;
+ if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false) {
clearopbeep(cap->oap);
- else if (cap->arg)
+ } else if (cap->arg) {
beginline(BL_WHITE | BL_FIX);
+ }
}
}
@@ -5041,23 +5114,24 @@ static void nv_down(cmdarg_T *cap)
/* <S-Down> is page down */
cap->arg = FORWARD;
nv_page(cap);
- } else
- /* In a quickfix window a <CR> jumps to the error under the cursor. */
- if (bt_quickfix(curbuf) && cap->cmdchar == CAR)
- if (curwin->w_llist_ref == NULL)
- do_cmdline_cmd(".cc"); /* quickfix window */
- else
- do_cmdline_cmd(".ll"); /* location list window */
- else {
- /* In the cmdline window a <CR> executes the command. */
- if (cmdwin_type != 0 && cap->cmdchar == CAR)
+ } else if (bt_quickfix(curbuf) && cap->cmdchar == CAR) {
+ // In a quickfix window a <CR> jumps to the error under the cursor.
+ if (curwin->w_llist_ref == NULL) {
+ do_cmdline_cmd(".cc"); // quickfix window
+ } else {
+ do_cmdline_cmd(".ll"); // location list window
+ }
+ } else {
+ // In the cmdline window a <CR> executes the command.
+ if (cmdwin_type != 0 && cap->cmdchar == CAR) {
cmdwin_result = CAR;
- else {
- cap->oap->motion_type = MLINE;
- if (cursor_down(cap->count1, cap->oap->op_type == OP_NOP) == false)
+ } else {
+ cap->oap->motion_type = kMTLineWise;
+ if (cursor_down(cap->count1, cap->oap->op_type == OP_NOP) == false) {
clearopbeep(cap->oap);
- else if (cap->arg)
+ } else if (cap->arg) {
beginline(BL_WHITE | BL_FIX);
+ }
}
}
}
@@ -5083,9 +5157,10 @@ static void nv_gotofile(cmdarg_T *cap)
ptr = grab_file_name(cap->count1, &lnum);
if (ptr != NULL) {
- /* do autowrite if necessary */
- if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf))
- autowrite(curbuf, false);
+ // do autowrite if necessary
+ if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf)) {
+ (void)autowrite(curbuf, false);
+ }
setpcmark();
(void)do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
P_HID(curbuf) ? ECMD_HIDE : 0, curwin);
@@ -5117,7 +5192,7 @@ static void nv_end(cmdarg_T *cap)
*/
static void nv_dollar(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = true;
/* In virtual mode when off the edge of a line and an operator
* is pending (whew!) keep the cursor where it is.
@@ -5192,18 +5267,19 @@ static int normal_search(
{
int i;
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
cap->oap->use_reg_one = true;
curwin->w_set_curswant = true;
i = do_search(cap->oap, dir, pat, cap->count1,
- opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL);
- if (i == 0)
+ opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL);
+ if (i == 0) {
clearop(cap->oap);
- else {
- if (i == 2)
- cap->oap->motion_type = MLINE;
+ } else {
+ if (i == 2) {
+ cap->oap->motion_type = kMTLineWise;
+ }
curwin->w_cursor.coladd = 0;
if (cap->oap->op_type == OP_NOP && (fdo_flags & FDO_SEARCH) && KeyTyped)
foldOpenCursor();
@@ -5230,10 +5306,10 @@ static void nv_csearch(cmdarg_T *cap)
else
t_cmd = false;
- cap->oap->motion_type = MCHAR;
- if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == false)
+ cap->oap->motion_type = kMTCharWise;
+ if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == false) {
clearopbeep(cap->oap);
- else {
+ } else {
curwin->w_set_curswant = true;
/* Include a Tab for "tx" and for "dfx". */
if (gchar_cursor() == TAB && virtual_active() && cap->arg == FORWARD
@@ -5265,7 +5341,7 @@ static void nv_brackets(cmdarg_T *cap)
int findc;
int c;
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
old_pos = curwin->w_cursor;
curwin->w_cursor.coladd = 0; /* TODO: don't do this for an error. */
@@ -5555,11 +5631,11 @@ static void nv_percent(cmdarg_T *cap)
linenr_T lnum = curwin->w_cursor.lnum;
cap->oap->inclusive = true;
- if (cap->count0) { /* {cnt}% : goto {cnt} percentage in file */
- if (cap->count0 > 100)
+ if (cap->count0) { // {cnt}% : goto {cnt} percentage in file
+ if (cap->count0 > 100) {
clearopbeep(cap->oap);
- else {
- cap->oap->motion_type = MLINE;
+ } else {
+ cap->oap->motion_type = kMTLineWise;
setpcmark();
/* Round up, so CTRL-G will give same value. Watch out for a
* large line count, the line number must not go negative! */
@@ -5573,8 +5649,8 @@ static void nv_percent(cmdarg_T *cap)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
beginline(BL_SOL | BL_FIX);
}
- } else { /* "%" : go to matching paren */
- cap->oap->motion_type = MCHAR;
+ } else { // "%" : go to matching paren
+ cap->oap->motion_type = kMTCharWise;
cap->oap->use_reg_one = true;
if ((pos = findmatch(cap->oap, NUL)) == NULL)
clearopbeep(cap->oap);
@@ -5599,7 +5675,7 @@ static void nv_percent(cmdarg_T *cap)
*/
static void nv_brace(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->use_reg_one = true;
/* The motion used to be inclusive for "(", but that is not what Vi does. */
cap->oap->inclusive = false;
@@ -5633,7 +5709,7 @@ static void nv_mark(cmdarg_T *cap)
*/
static void nv_findpar(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
cap->oap->use_reg_one = true;
curwin->w_set_curswant = true;
@@ -5737,14 +5813,11 @@ static void nv_replace(cmdarg_T *cap)
return;
}
- /*
- * Replacing with a TAB is done by edit() when it is complicated because
- * 'expandtab' or 'smarttab' is set. CTRL-V TAB inserts a literal TAB.
- * Other characters are done below to avoid problems with things like
- * CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
- */
- if (had_ctrl_v != Ctrl_V && cap->nchar == '\t' &&
- (curbuf->b_p_et || p_sta)) {
+ // Replacing with a TAB is done by edit() when it is complicated because
+ // 'expandtab' or 'smarttab' is set. CTRL-V TAB inserts a literal TAB.
+ // Other characters are done below to avoid problems with things like
+ // CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
+ if (had_ctrl_v != Ctrl_V && cap->nchar == '\t' && (curbuf->b_p_et || p_sta)) {
stuffnumReadbuff(cap->count1);
stuffcharReadbuff('R');
stuffcharReadbuff('\t');
@@ -6011,10 +6084,11 @@ static void nv_cursormark(cmdarg_T *cap, int flag, pos_T *pos)
else
check_cursor();
}
- cap->oap->motion_type = flag ? MLINE : MCHAR;
- if (cap->cmdchar == '`')
+ cap->oap->motion_type = flag ? kMTLineWise : kMTCharWise;
+ if (cap->cmdchar == '`') {
cap->oap->use_reg_one = true;
- cap->oap->inclusive = false; /* ignored if not MCHAR */
+ }
+ cap->oap->inclusive = false; // ignored if not kMTCharWise
curwin->w_set_curswant = true;
}
@@ -6361,9 +6435,20 @@ static void nv_g_cmd(cmdarg_T *cap)
bool flag = false;
switch (cap->nchar) {
- /*
- * "gR": Enter virtual replace mode.
- */
+ // "g^A/g^X": Sequentially increment visually selected region.
+ case Ctrl_A:
+ case Ctrl_X:
+ if (VIsual_active) {
+ cap->arg = true;
+ cap->cmdchar = cap->nchar;
+ cap->nchar = NUL;
+ nv_addsub(cap);
+ } else {
+ clearopbeep(oap);
+ }
+ break;
+
+ // "gR": Enter virtual replace mode.
case 'R':
cap->arg = true;
nv_Replace(cap);
@@ -6480,7 +6565,7 @@ static void nv_g_cmd(cmdarg_T *cap)
if (!curwin->w_p_wrap
|| hasFolding(curwin->w_cursor.lnum, NULL, NULL)
) {
- oap->motion_type = MLINE;
+ oap->motion_type = kMTLineWise;
i = cursor_down(cap->count1, oap->op_type == OP_NOP);
} else
i = nv_screengo(oap, FORWARD, cap->count1);
@@ -6495,7 +6580,7 @@ static void nv_g_cmd(cmdarg_T *cap)
if (!curwin->w_p_wrap
|| hasFolding(curwin->w_cursor.lnum, NULL, NULL)
) {
- oap->motion_type = MLINE;
+ oap->motion_type = kMTLineWise;
i = cursor_up(cap->count1, oap->op_type == OP_NOP);
} else
i = nv_screengo(oap, BACKWARD, cap->count1);
@@ -6522,7 +6607,7 @@ static void nv_g_cmd(cmdarg_T *cap)
case 'm':
case K_HOME:
case K_KHOME:
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
oap->inclusive = false;
if (curwin->w_p_wrap
&& curwin->w_width != 0
@@ -6555,7 +6640,7 @@ static void nv_g_cmd(cmdarg_T *cap)
case '_':
/* "g_": to the last non-blank character in the line or <count> lines
* downward. */
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = true;
curwin->w_curswant = MAXCOL;
if (cursor_down(cap->count1 - 1,
@@ -6583,7 +6668,7 @@ static void nv_g_cmd(cmdarg_T *cap)
{
int col_off = curwin_col_off();
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
oap->inclusive = true;
if (curwin->w_p_wrap
&& curwin->w_width != 0
@@ -6645,23 +6730,19 @@ static void nv_g_cmd(cmdarg_T *cap)
*/
case 'e':
case 'E':
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
curwin->w_set_curswant = true;
oap->inclusive = true;
if (bckend_word(cap->count1, cap->nchar == 'E', false) == false)
clearopbeep(oap);
break;
- /*
- * "g CTRL-G": display info about cursor position
- */
+ // "g CTRL-G": display info about cursor position
case Ctrl_G:
- cursor_pos_info();
+ cursor_pos_info(NULL);
break;
- /*
- * "gi": start Insert at the last position.
- */
+ // "gi": start Insert at the last position.
case 'i':
if (curbuf->b_last_insert.mark.lnum != 0) {
curwin->w_cursor = curbuf->b_last_insert.mark;
@@ -6878,10 +6959,16 @@ static void n_opencmd(cmdarg_T *cap)
(cap->cmdchar == 'o' ? 1 : 0))
)
&& open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
- has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM :
- 0, 0)) {
- if (curwin->w_p_cole > 0 && oldline != curwin->w_cursor.lnum)
+ 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) {
+ // force redraw of cursorline
+ curwin->w_valid &= ~VALID_CROW;
+ }
invoke_edit(cap, false, cap->cmdchar, true);
}
}
@@ -6971,18 +7058,17 @@ static void nv_operator(cmdarg_T *cap)
*/
static void set_op_var(int optype)
{
- char_u opchars[3];
-
- if (optype == OP_NOP)
+ if (optype == OP_NOP) {
set_vim_var_string(VV_OP, NULL, 0);
- else {
+ } else {
+ char opchars[3];
int opchar0 = get_op_char(optype);
assert(opchar0 >= 0 && opchar0 <= UCHAR_MAX);
- opchars[0] = (char_u)opchar0;
+ opchars[0] = (char) opchar0;
int opchar1 = get_extra_op_char(optype);
assert(opchar1 >= 0 && opchar1 <= UCHAR_MAX);
- opchars[1] = (char_u)opchar1;
+ opchars[1] = (char) opchar1;
opchars[2] = NUL;
set_vim_var_string(VV_OP, opchars, -1);
@@ -7000,17 +7086,19 @@ static void set_op_var(int optype)
*/
static void nv_lineop(cmdarg_T *cap)
{
- cap->oap->motion_type = MLINE;
- if (cursor_down(cap->count1 - 1L, cap->oap->op_type == OP_NOP) == false)
+ cap->oap->motion_type = kMTLineWise;
+ if (cursor_down(cap->count1 - 1L, cap->oap->op_type == OP_NOP) == false) {
clearopbeep(cap->oap);
- else if ( (cap->oap->op_type == OP_DELETE /* only with linewise motions */
+ } else if ((cap->oap->op_type == OP_DELETE
+ // only with linewise motions
&& cap->oap->motion_force != 'v'
&& cap->oap->motion_force != Ctrl_V)
|| cap->oap->op_type == OP_LSHIFT
- || cap->oap->op_type == OP_RSHIFT)
+ || cap->oap->op_type == OP_RSHIFT) {
beginline(BL_SOL | BL_FIX);
- else if (cap->oap->op_type != OP_YANK) /* 'Y' does not move cursor */
+ } else if (cap->oap->op_type != OP_YANK) { // 'Y' does not move cursor
beginline(BL_WHITE | BL_FIX);
+ }
}
/*
@@ -7034,7 +7122,7 @@ static void nv_home(cmdarg_T *cap)
*/
static void nv_pipe(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
beginline(0);
if (cap->count0 > 0) {
@@ -7053,7 +7141,7 @@ static void nv_pipe(cmdarg_T *cap)
*/
static void nv_bck_word(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
curwin->w_set_curswant = true;
if (bck_word(cap->count1, cap->arg, false) == false)
@@ -7102,7 +7190,7 @@ static void nv_wordcmd(cmdarg_T *cap)
}
}
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
curwin->w_set_curswant = true;
if (word_end)
n = end_word(cap->count1, cap->arg, flag, false);
@@ -7153,7 +7241,7 @@ static void adjust_cursor(oparg_T *oap)
*/
static void nv_beginline(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
beginline(cap->arg);
if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
@@ -7232,7 +7320,7 @@ static void nv_goto(cmdarg_T *cap)
lnum = curbuf->b_ml.ml_line_count;
else
lnum = 1L;
- cap->oap->motion_type = MLINE;
+ cap->oap->motion_type = kMTLineWise;
setpcmark();
/* When a count is given, use it instead of the default lnum */
@@ -7466,6 +7554,13 @@ static void nv_object(cmdarg_T *cap)
flag = current_block(cap->oap, cap->count1, include, '<', '>');
break;
case 't': /* "at" = a tag block (xml and html) */
+ // Do not adjust oap->end in do_pending_operator()
+ // otherwise there are different results for 'dit'
+ // (note leading whitespace in last line):
+ // 1) <b> 2) <b>
+ // foobar foobar
+ // </b> </b>
+ cap->retval |= CA_NO_ADJ_OP_END;
flag = current_tagblock(cap->oap, cap->count1, include);
break;
case 'p': /* "ap" = a paragraph */
@@ -7658,6 +7753,10 @@ static void nv_put(cmdarg_T *cap)
if (was_visual) {
curbuf->b_visual.vi_start = curbuf->b_op_start;
curbuf->b_visual.vi_end = curbuf->b_op_end;
+ // need to adjust cursor position
+ if (*p_sel == 'e') {
+ inc(&curbuf->b_visual.vi_end);
+ }
}
/* When all lines were selected and deleted do_put() leaves an empty
@@ -7692,6 +7791,75 @@ static void nv_open(cmdarg_T *cap)
n_opencmd(cap);
}
+// Calculate start/end virtual columns for operating in block mode.
+static void get_op_vcol(
+ oparg_T *oap,
+ colnr_T redo_VIsual_vcol,
+ bool initial // when true: adjust position for 'selectmode'
+)
+{
+ colnr_T start;
+ colnr_T end;
+
+ if (VIsual_mode != Ctrl_V
+ || (!initial && oap->end.col < curwin->w_width)) {
+ return;
+ }
+
+ oap->motion_type = kMTBlockWise;
+
+ // prevent from moving onto a trail byte
+ if (has_mbyte) {
+ mb_adjustpos(curwin->w_buffer, &oap->end);
+ }
+
+ getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
+ if (!redo_VIsual_busy) {
+ getvvcol(curwin, &(oap->end), &start, NULL, &end);
+
+ if (start < oap->start_vcol) {
+ oap->start_vcol = start;
+ }
+ if (end > oap->end_vcol) {
+ if (initial && *p_sel == 'e'
+ && start >= 1
+ && start - 1 >= oap->end_vcol) {
+ oap->end_vcol = start - 1;
+ } else {
+ oap->end_vcol = end;
+ }
+ }
+ }
+
+ // if '$' was used, get oap->end_vcol from longest line
+ if (curwin->w_curswant == MAXCOL) {
+ curwin->w_cursor.col = MAXCOL;
+ oap->end_vcol = 0;
+ for (curwin->w_cursor.lnum = oap->start.lnum;
+ curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum) {
+ getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
+ if (end > oap->end_vcol) {
+ oap->end_vcol = end;
+ }
+ }
+ } else if (redo_VIsual_busy) {
+ oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1;
+ }
+
+ // Correct oap->end.col and oap->start.col to be the
+ // upper-left and lower-right corner of the block area.
+ //
+ // (Actually, this does convert column positions into character
+ // positions)
+ curwin->w_cursor.lnum = oap->end.lnum;
+ coladvance(oap->end_vcol);
+ oap->end = curwin->w_cursor;
+
+ curwin->w_cursor = oap->start;
+ coladvance(oap->start_vcol);
+ oap->start = curwin->w_cursor;
+}
+
// Handle an arbitrary event in normal mode
static void nv_event(cmdarg_T *cap)
{