aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_cmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ex_cmds.c')
-rw-r--r--src/nvim/ex_cmds.c96
1 files changed, 70 insertions, 26 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 95390b1a70..49bf9972b1 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -814,7 +814,11 @@ void ex_retab(exarg_T *eap)
// len is actual number of white characters used
len = num_spaces + num_tabs;
old_len = (long)STRLEN(ptr);
- long new_len = old_len - col + start_col + len + 1;
+ const long new_len = old_len - col + start_col + len + 1;
+ if (new_len <= 0 || new_len >= MAXCOL) {
+ emsg(_(e_resulting_text_too_long));
+ break;
+ }
new_line = xmalloc(new_len);
if (start_col > 0) {
@@ -847,6 +851,10 @@ void ex_retab(exarg_T *eap)
break;
}
vcol += win_chartabsize(curwin, ptr + col, (colnr_T)vcol);
+ if (vcol >= MAXCOL) {
+ emsg(_(e_resulting_text_too_long));
+ break;
+ }
col += utfc_ptr2len(ptr + col);
}
if (new_line == NULL) { // out of memory
@@ -980,8 +988,10 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
foldMoveRange(win, &win->w_folds, line1, line2, dest);
}
}
- curbuf->b_op_start.lnum = dest - num_lines + 1;
- curbuf->b_op_end.lnum = dest;
+ if (!cmdmod.lockmarks) {
+ curbuf->b_op_start.lnum = dest - num_lines + 1;
+ curbuf->b_op_end.lnum = dest;
+ }
line_off = -num_lines;
byte_off = -extent_byte;
} else {
@@ -991,10 +1001,14 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
foldMoveRange(win, &win->w_folds, dest + 1, line1 - 1, line2);
}
}
- curbuf->b_op_start.lnum = dest + 1;
- curbuf->b_op_end.lnum = dest + num_lines;
+ if (!cmdmod.lockmarks) {
+ curbuf->b_op_start.lnum = dest + 1;
+ curbuf->b_op_end.lnum = dest + num_lines;
+ }
+ }
+ if (!cmdmod.lockmarks) {
+ curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
}
- curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
mark_adjust_nofold(last_line - num_lines + 1, last_line,
-(last_line - dest - extra), 0L, kExtmarkNOOP);
@@ -1057,9 +1071,11 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
char_u *p;
count = line2 - line1 + 1;
- curbuf->b_op_start.lnum = n + 1;
- curbuf->b_op_end.lnum = n + count;
- curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+ if (!cmdmod.lockmarks) {
+ curbuf->b_op_start.lnum = n + 1;
+ curbuf->b_op_end.lnum = n + count;
+ curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+ }
/*
* there are three situations:
@@ -1099,6 +1115,9 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
}
appended_lines_mark(n, count);
+ if (VIsual_active) {
+ check_pos(curbuf, &VIsual);
+ }
msgmore((long)count);
}
@@ -1269,12 +1288,18 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd,
char_u *cmd_buf;
buf_T *old_curbuf = curbuf;
int shell_flags = 0;
+ const pos_T orig_start = curbuf->b_op_start;
+ const pos_T orig_end = curbuf->b_op_end;
const int stmp = p_stmp;
if (*cmd == NUL) { // no filter command
return;
}
+ const bool save_lockmarks = cmdmod.lockmarks;
+ // Temporarily disable lockmarks since that's needed to propagate changed
+ // regions of the buffer for foldUpdate(), linecount, etc.
+ cmdmod.lockmarks = false;
cursor_save = curwin->w_cursor;
linecount = line2 - line1 + 1;
@@ -1349,7 +1374,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd,
ui_cursor_goto(Rows - 1, 0);
if (do_out) {
- if (u_save((line2), (linenr_T)(line2 + 1)) == FAIL) {
+ if (u_save(line2, (linenr_T)(line2 + 1)) == FAIL) {
xfree(cmd_buf);
goto error;
}
@@ -1455,10 +1480,15 @@ error:
filterend:
+ cmdmod.lockmarks = save_lockmarks;
if (curbuf != old_curbuf) {
no_wait_return--;
emsg(_("E135: *Filter* Autocommands must not change current buffer"));
+ } else if (cmdmod.lockmarks) {
+ curbuf->b_op_start = orig_start;
+ curbuf->b_op_end = orig_end;
}
+
if (itmp != NULL) {
os_remove((char *)itmp);
}
@@ -3031,14 +3061,15 @@ void ex_append(exarg_T *eap)
// eap->line2 pointed to the end of the buffer and nothing was appended)
// "end" is set to lnum when something has been appended, otherwise
// it is the same as "start" -- Acevedo
- curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ?
- eap->line2 + 1 : curbuf->b_ml.ml_line_count;
- if (eap->cmdidx != CMD_append) {
- --curbuf->b_op_start.lnum;
+ if (!cmdmod.lockmarks) {
+ curbuf->b_op_start.lnum
+ = (eap->line2 < curbuf->b_ml.ml_line_count) ? eap->line2 + 1 : curbuf->b_ml.ml_line_count;
+ if (eap->cmdidx != CMD_append) {
+ curbuf->b_op_start.lnum--;
+ }
+ curbuf->b_op_end.lnum = (eap->line2 < lnum) ? lnum : curbuf->b_op_start.lnum;
+ curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
}
- curbuf->b_op_end.lnum = (eap->line2 < lnum)
- ? lnum : curbuf->b_op_start.lnum;
- curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
curwin->w_cursor.lnum = lnum;
check_cursor_lnum();
beginline(BL_SOL | BL_FIX);
@@ -3629,8 +3660,14 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// We do it here once to avoid it to be replaced over and over again.
// But don't do it when it starts with "\=", then it's an expression.
assert(sub != NULL);
+
+ bool sub_needs_free = false;
if (!(sub[0] == '\\' && sub[1] == '=')) {
+ char_u *source = sub;
sub = regtilde(sub, p_magic);
+ // When previewing, the new pattern allocated by regtilde() needs to be freed
+ // in this function because it will not be used or freed by regtilde() later.
+ sub_needs_free = preview && sub != source;
}
// Check for a match on each line.
@@ -4351,10 +4388,12 @@ skip:
}
if (sub_nsubs > start_nsubs) {
- // Set the '[ and '] marks.
- curbuf->b_op_start.lnum = eap->line1;
- curbuf->b_op_end.lnum = line2;
- curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+ if (!cmdmod.lockmarks) {
+ // Set the '[ and '] marks.
+ curbuf->b_op_start.lnum = eap->line1;
+ curbuf->b_op_end.lnum = line2;
+ curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+ }
if (!global_busy) {
// when interactive leave cursor on the match
@@ -4425,6 +4464,10 @@ skip:
kv_destroy(preview_lines.subresults);
+ if (sub_needs_free) {
+ xfree(sub);
+ }
+
return preview_buf;
#undef ADJUST_SUB_FIRSTLNUM
#undef PUSH_PREVIEW_LINES
@@ -5068,8 +5111,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
&& ((arg[1] != NUL && arg[2] == NUL)
|| (vim_strchr((char_u *)"%_z@", arg[1]) != NULL
&& arg[2] != NUL))) {
- STRCPY(d, "/\\\\");
- STRCPY(d + 3, arg + 1);
+ vim_snprintf((char *)d, IOSIZE, "/\\\\%s", arg + 1);
// Check for "/\\_$", should be "/\\_\$"
if (d[3] == '_' && d[4] == '$') {
STRCPY(d + 4, "\\$");
@@ -5822,7 +5864,7 @@ void ex_helpclose(exarg_T *eap)
{
FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
if (bt_help(win->w_buffer)) {
- win_close(win, false);
+ win_close(win, false, eap->forceit);
return;
}
}
@@ -6107,12 +6149,14 @@ char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags)
p++;
// Find the flags
- while (*p == 'g' || *p == 'j') {
+ while (*p == 'g' || *p == 'j' || *p == 'f') {
if (flags != NULL) {
if (*p == 'g') {
*flags |= VGR_GLOBAL;
- } else {
+ } else if (*p == 'j') {
*flags |= VGR_NOJUMP;
+ } else {
+ *flags |= VGR_FUZZY;
}
}
p++;