aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_cmds.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
commit931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch)
treed8c1843a95da5ea0bb4acc09f7e37843d9995c86 /src/nvim/ex_cmds.c
parent142d9041391780ac15b89886a54015fdc5c73995 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-userreg.tar.gz
rneovim-userreg.tar.bz2
rneovim-userreg.zip
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'src/nvim/ex_cmds.c')
-rw-r--r--src/nvim/ex_cmds.c757
1 files changed, 368 insertions, 389 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 437a05f61d..e369397047 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1,12 +1,10 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
// ex_cmds.c: some functions for command line commands
#include <assert.h>
#include <ctype.h>
#include <float.h>
#include <inttypes.h>
+#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
@@ -18,11 +16,12 @@
#include "auto/config.h"
#include "klib/kvec.h"
#include "nvim/arglist.h"
-#include "nvim/ascii.h"
+#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
+#include "nvim/bufwrite.h"
#include "nvim/change.h"
#include "nvim/channel.h"
#include "nvim/charset.h"
@@ -44,17 +43,16 @@
#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/func_attr.h"
#include "nvim/getchar.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
-#include "nvim/grid_defs.h"
#include "nvim/help.h"
-#include "nvim/highlight_defs.h"
+#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/input.h"
-#include "nvim/lua/executor.h"
-#include "nvim/macros.h"
+#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
@@ -66,26 +64,28 @@
#include "nvim/normal.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
-#include "nvim/os/fs_defs.h"
+#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
#include "nvim/plines.h"
+#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
-#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/spell.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/terminal.h"
-#include "nvim/types.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
-#include "nvim/vim.h"
+#include "nvim/vim_defs.h"
#include "nvim/window.h"
/// Case matching style to use for :substitute
@@ -126,20 +126,28 @@ typedef struct {
# include "ex_cmds.c.generated.h"
#endif
+static const char e_non_numeric_argument_to_z[]
+ = N_("E144: Non-numeric argument to :z");
+
/// ":ascii" and "ga" implementation
-void do_ascii(const exarg_T *const eap)
+void do_ascii(exarg_T *eap)
{
- char *dig;
- int cc[MAX_MCO];
- int c = utfc_ptr2char(get_cursor_pos_ptr(), cc);
- if (c == NUL) {
- msg("NUL");
+ char *data = get_cursor_pos_ptr();
+ size_t len = (size_t)utfc_ptr2len(data);
+
+ if (len == 0) {
+ msg("NUL", 0);
return;
}
- size_t iobuff_len = 0;
+ bool need_clear = true;
+ msg_sb_eol();
+ msg_start();
+
+ int c = utf_ptr2char(data);
+ size_t off = 0;
- int ci = 0;
+ // TODO(bfredl): merge this with the main loop
if (c < 0x80) {
if (c == NL) { // NUL is stored as NL.
c = NUL;
@@ -148,56 +156,39 @@ void do_ascii(const exarg_T *const eap)
? NL // NL is stored as CR.
: c);
char buf1[20];
- if (vim_isprintc_strict(c) && (c < ' ' || c > '~')) {
+ if (vim_isprintc(c) && (c < ' ' || c > '~')) {
char buf3[7];
- transchar_nonprint(curbuf, (char_u *)buf3, c);
- vim_snprintf(buf1, sizeof(buf1), " <%s>", (char *)buf3);
+ transchar_nonprint(curbuf, buf3, c);
+ vim_snprintf(buf1, sizeof(buf1), " <%s>", buf3);
} else {
buf1[0] = NUL;
}
char buf2[20];
buf2[0] = NUL;
- dig = get_digraph_for_char(cval);
+ char *dig = get_digraph_for_char(cval);
if (dig != NULL) {
- iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
- sizeof(IObuff) - iobuff_len,
- _("<%s>%s%s %d, Hex %02x, Oct %03o, Digr %s"),
- transchar(c), buf1, buf2, cval, cval, cval, dig);
+ vim_snprintf(IObuff, sizeof(IObuff),
+ _("<%s>%s%s %d, Hex %02x, Oct %03o, Digr %s"),
+ transchar(c), buf1, buf2, cval, cval, cval, dig);
} else {
- iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
- sizeof(IObuff) - iobuff_len,
- _("<%s>%s%s %d, Hex %02x, Octal %03o"),
- transchar(c), buf1, buf2, cval, cval, cval);
- }
-
- c = cc[ci++];
- }
-
-#define SPACE_FOR_DESC (1 + 1 + 1 + MB_MAXBYTES + 16 + 4 + 3 + 3 + 1)
- // Space for description:
- // - 1 byte for separator (starting from second entry)
- // - 1 byte for "<"
- // - 1 byte for space to draw composing character on (optional, but really
- // mostly required)
- // - up to MB_MAXBYTES bytes for character itself
- // - 16 bytes for raw text ("> , Hex , Octal ").
- // - at least 4 bytes for hexadecimal representation
- // - at least 3 bytes for decimal representation
- // - at least 3 bytes for octal representation
- // - 1 byte for NUL
- //
- // Taking into account MAX_MCO and characters which need 8 bytes for
- // hexadecimal representation, but not taking translation into account:
- // resulting string will occupy less then 400 bytes (conservative estimate).
- //
- // Less then 1000 bytes if translation multiplies number of bytes needed for
- // raw text by 6, so it should always fit into 1025 bytes reserved for IObuff.
+ vim_snprintf(IObuff, sizeof(IObuff),
+ _("<%s>%s%s %d, Hex %02x, Octal %03o"),
+ transchar(c), buf1, buf2, cval, cval, cval);
+ }
+
+ msg_multiline(IObuff, 0, true, &need_clear);
+
+ off += (size_t)utf_ptr2len(data); // needed for overlong ascii?
+ }
// Repeat for combining characters, also handle multiby here.
- while (c >= 0x80 && iobuff_len < sizeof(IObuff) - SPACE_FOR_DESC) {
+ while (off < len) {
+ c = utf_ptr2char(data + off);
+
+ size_t iobuff_len = 0;
// This assumes every multi-byte char is printable...
- if (iobuff_len > 0) {
+ if (off > 0) {
IObuff[iobuff_len++] = ' ';
}
IObuff[iobuff_len++] = '<';
@@ -206,43 +197,37 @@ void do_ascii(const exarg_T *const eap)
}
iobuff_len += (size_t)utf_char2bytes(c, IObuff + iobuff_len);
- dig = get_digraph_for_char(c);
+ char *dig = get_digraph_for_char(c);
if (dig != NULL) {
- iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
- sizeof(IObuff) - iobuff_len,
- (c < 0x10000
- ? _("> %d, Hex %04x, Oct %o, Digr %s")
- : _("> %d, Hex %08x, Oct %o, Digr %s")),
- c, c, c, dig);
+ vim_snprintf(IObuff + iobuff_len, sizeof(IObuff) - iobuff_len,
+ (c < 0x10000
+ ? _("> %d, Hex %04x, Oct %o, Digr %s")
+ : _("> %d, Hex %08x, Oct %o, Digr %s")),
+ c, c, c, dig);
} else {
- iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
- sizeof(IObuff) - iobuff_len,
- (c < 0x10000
- ? _("> %d, Hex %04x, Octal %o")
- : _("> %d, Hex %08x, Octal %o")),
- c, c, c);
- }
- if (ci == MAX_MCO) {
- break;
+ vim_snprintf(IObuff + iobuff_len, sizeof(IObuff) - iobuff_len,
+ (c < 0x10000
+ ? _("> %d, Hex %04x, Octal %o")
+ : _("> %d, Hex %08x, Octal %o")),
+ c, c, c);
}
- c = cc[ci++];
- }
- if (ci != MAX_MCO && c != 0) {
- xstrlcpy(IObuff + iobuff_len, " ...", sizeof(IObuff) - iobuff_len);
+
+ msg_multiline(IObuff, 0, true, &need_clear);
+
+ off += (size_t)utf_ptr2len(data + off); // needed for overlong ascii?
}
- msg(IObuff);
+ if (need_clear) {
+ msg_clr_eos();
+ }
+ msg_end();
}
/// ":left", ":center" and ":right": align text.
void ex_align(exarg_T *eap)
{
- pos_T save_curpos;
- int len;
int indent = 0;
int new_indent;
- int has_tab;
- int width;
if (curwin->w_p_rl) {
// switch left and right aligning
@@ -253,8 +238,8 @@ void ex_align(exarg_T *eap)
}
}
- width = atoi(eap->arg);
- save_curpos = curwin->w_cursor;
+ int width = atoi(eap->arg);
+ pos_T save_curpos = curwin->w_cursor;
if (eap->cmdidx == CMD_left) { // width is used for new indent
if (width >= 0) {
indent = width;
@@ -283,8 +268,8 @@ void ex_align(exarg_T *eap)
if (eap->cmdidx == CMD_left) { // left align
new_indent = indent;
} else {
- has_tab = false; // avoid uninit warnings
- len = linelen(eap->cmdidx == CMD_right ? &has_tab : NULL) - get_indent();
+ int has_tab = false; // avoid uninit warnings
+ int len = linelen(eap->cmdidx == CMD_right ? &has_tab : NULL) - get_indent();
if (len <= 0) { // skip blank lines
continue;
@@ -319,7 +304,7 @@ void ex_align(exarg_T *eap)
}
(void)set_indent(new_indent, 0); // set indent
}
- changed_lines(eap->line1, 0, eap->line2 + 1, 0L, true);
+ changed_lines(curbuf, eap->line1, 0, eap->line2 + 1, 0, true);
curwin->w_cursor = save_curpos;
beginline(BL_WHITE | BL_FIX);
}
@@ -327,29 +312,24 @@ void ex_align(exarg_T *eap)
/// @return the length of the current line, excluding trailing white space.
static int linelen(int *has_tab)
{
- char *line;
- char *first;
char *last;
- int len;
// Get the line. If it's empty bail out early (could be the empty string
// for an unloaded buffer).
- line = get_cursor_line_ptr();
+ char *line = get_cursor_line_ptr();
if (*line == NUL) {
return 0;
}
// find the first non-blank character
- first = skipwhite(line);
+ char *first = skipwhite(line);
// find the character after the last non-blank character
for (last = first + strlen(first);
last > first && ascii_iswhite(last[-1]); last--) {}
char save = *last;
*last = NUL;
- // Get line length.
- len = linetabsize(line);
- // Check for embedded TAB.
- if (has_tab != NULL) {
+ int len = linetabsize_str(line); // Get line length.
+ if (has_tab != NULL) { // Check for embedded TAB.
*has_tab = vim_strchr(first, TAB) != NULL;
}
*last = save;
@@ -389,7 +369,7 @@ typedef struct {
static int string_compare(const void *s1, const void *s2) FUNC_ATTR_NONNULL_ALL
{
if (sort_lc) {
- return strcoll((char *)s1, (char *)s2);
+ return strcoll((const char *)s1, (const char *)s2);
}
return sort_ic ? STRICMP(s1, s2) : strcmp(s1, s2);
}
@@ -418,10 +398,10 @@ static int sort_compare(const void *s1, const void *s2)
result = l1.st_u.num.is_number - l2.st_u.num.is_number;
} else {
result = l1.st_u.num.value == l2.st_u.num.value
- ? 0
- : l1.st_u.num.value > l2.st_u.num.value
- ? 1
- : -1;
+ ? 0
+ : l1.st_u.num.value > l2.st_u.num.value
+ ? 1
+ : -1;
}
} else if (sort_flt) {
result = l1.st_u.value_flt == l2.st_u.value_flt
@@ -452,19 +432,10 @@ static int sort_compare(const void *s1, const void *s2)
void ex_sort(exarg_T *eap)
{
regmatch_T regmatch;
- int len;
- linenr_T lnum;
- long maxlen = 0;
+ int maxlen = 0;
size_t count = (size_t)(eap->line2 - eap->line1) + 1;
size_t i;
- char *p;
- char *s;
- char *s2;
- char c; // temporary character storage
bool unique = false;
- long deleted;
- colnr_T start_col;
- colnr_T end_col;
int sort_what = 0;
// Sorting one line is really quick!
@@ -484,7 +455,7 @@ void ex_sort(exarg_T *eap)
size_t format_found = 0;
bool change_occurred = false; // Buffer contents changed.
- for (p = eap->arg; *p != NUL; p++) {
+ for (char *p = eap->arg; *p != NUL; p++) {
if (ascii_iswhite(*p)) {
// Skip
} else if (*p == 'i') {
@@ -517,7 +488,7 @@ void ex_sort(exarg_T *eap)
eap->nextcmd = check_nextcmd(p);
break;
} else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) {
- s = skip_regexp_err(p + 1, *p, true);
+ char *s = skip_regexp_err(p + 1, *p, true);
if (s == NULL) {
goto sortend;
}
@@ -559,15 +530,15 @@ void ex_sort(exarg_T *eap)
// numbers sorting it's the number to sort on. This means the pattern
// matching and number conversion only has to be done once per line.
// Also get the longest line length for allocating "sortbuf".
- for (lnum = eap->line1; lnum <= eap->line2; lnum++) {
- s = ml_get(lnum);
- len = (int)strlen(s);
+ for (linenr_T lnum = eap->line1; lnum <= eap->line2; lnum++) {
+ char *s = ml_get(lnum);
+ int len = (int)strlen(s);
if (maxlen < len) {
maxlen = len;
}
- start_col = 0;
- end_col = len;
+ colnr_T start_col = 0;
+ colnr_T end_col = len;
if (regmatch.regprog != NULL && vim_regexec(&regmatch, s, 0)) {
if (sort_rx) {
start_col = (colnr_T)(regmatch.startp[0] - s);
@@ -580,13 +551,13 @@ void ex_sort(exarg_T *eap)
}
if (sort_nr || sort_flt) {
- // Make sure vim_str2nr doesn't read any digits past the end
+ // Make sure vim_str2nr() doesn't read any digits past the end
// of the match, by temporarily terminating the string there
- s2 = s + end_col;
- c = *s2;
+ char *s2 = s + end_col;
+ char c = *s2; // temporary character storage
*s2 = NUL;
// Sorting on number: Store the number itself.
- p = s + start_col;
+ char *p = s + start_col;
if (sort_nr) {
if (sort_what & STR2NR_HEX) {
s = skiptohex(p);
@@ -605,7 +576,7 @@ void ex_sort(exarg_T *eap)
} else {
nrs[lnum - eap->line1].st_u.num.is_number = true;
vim_str2nr(s, NULL, NULL, sort_what,
- &nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false);
+ &nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false, NULL);
}
} else {
s = skipwhite(p);
@@ -651,7 +622,7 @@ void ex_sort(exarg_T *eap)
bcount_t old_count = 0, new_count = 0;
// Insert the lines in the sorted order below the last one.
- lnum = eap->line2;
+ linenr_T lnum = eap->line2;
for (i = 0; i < count; i++) {
const linenr_T get_lnum = nrs[eap->forceit ? count - i - 1 : i].lnum;
@@ -661,14 +632,14 @@ void ex_sort(exarg_T *eap)
change_occurred = true;
}
- s = ml_get(get_lnum);
+ char *s = ml_get(get_lnum);
size_t bytelen = strlen(s) + 1; // include EOL in bytelen
old_count += (bcount_t)bytelen;
if (!unique || i == 0 || string_compare(s, sortbuf1) != 0) {
// Copy the line into a buffer, it may become invalid in
// ml_append(). And it's needed for "unique".
STRCPY(sortbuf1, s);
- if (ml_append(lnum++, sortbuf1, (colnr_T)0, false) == FAIL) {
+ if (ml_append(lnum++, sortbuf1, 0, false) == FAIL) {
break;
}
new_count += (bcount_t)bytelen;
@@ -689,13 +660,12 @@ void ex_sort(exarg_T *eap)
}
// Adjust marks for deleted (or added) lines and prepare for displaying.
- deleted = (long)count - (lnum - eap->line2);
+ linenr_T deleted = (linenr_T)count - (lnum - eap->line2);
if (deleted > 0) {
- mark_adjust(eap->line2 - (linenr_T)deleted, eap->line2, (long)MAXLNUM, (linenr_T)(-deleted),
- kExtmarkNOOP);
+ mark_adjust(eap->line2 - deleted, eap->line2, MAXLNUM, -deleted, kExtmarkNOOP);
msgmore(-deleted);
} else if (deleted < 0) {
- mark_adjust(eap->line2, MAXLNUM, (linenr_T)(-deleted), 0L, kExtmarkNOOP);
+ mark_adjust(eap->line2, MAXLNUM, -deleted, 0, kExtmarkNOOP);
}
if (change_occurred || deleted != 0) {
@@ -703,7 +673,7 @@ void ex_sort(exarg_T *eap)
(int)count, 0, old_count,
lnum - eap->line2, 0, new_count, kExtmarkUndo);
- changed_lines(eap->line1, 0, eap->line2 + 1, (linenr_T)(-deleted), true);
+ changed_lines(curbuf, eap->line1, 0, eap->line2 + 1, -deleted, true);
}
curwin->w_cursor.lnum = eap->line1;
@@ -724,7 +694,6 @@ sortend:
/// @return FAIL for failure, OK otherwise
int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
{
- char *str;
linenr_T l;
linenr_T extra; // Num lines added before line1
linenr_T num_lines; // Num lines moved
@@ -761,8 +730,8 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
return FAIL;
}
for (extra = 0, l = line1; l <= line2; l++) {
- str = xstrdup(ml_get(l + extra));
- ml_append(dest + l - line1, str, (colnr_T)0, false);
+ char *str = xstrdup(ml_get(l + extra));
+ ml_append(dest + l - line1, str, 0, false);
xfree(str);
if (dest < line1) {
extra++;
@@ -783,16 +752,16 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
// And Finally we adjust the marks we put at the end of the file back to
// their final destination at the new text position -- webb
last_line = curbuf->b_ml.ml_line_count;
- mark_adjust_nofold(line1, line2, last_line - line2, 0L, kExtmarkNOOP);
+ mark_adjust_nofold(line1, line2, last_line - line2, 0, kExtmarkNOOP);
disable_fold_update++;
- changed_lines(last_line - num_lines + 1, 0, last_line + 1, num_lines, false);
+ changed_lines(curbuf, last_line - num_lines + 1, 0, last_line + 1, num_lines, false);
disable_fold_update--;
int line_off = 0;
bcount_t byte_off = 0;
if (dest >= line2) {
- mark_adjust_nofold(line2 + 1, dest, -num_lines, 0L, kExtmarkNOOP);
+ mark_adjust_nofold(line2 + 1, dest, -num_lines, 0, kExtmarkNOOP);
FOR_ALL_TAB_WINDOWS(tab, win) {
if (win->w_buffer == curbuf) {
foldMoveRange(win, &win->w_folds, line1, line2, dest);
@@ -805,7 +774,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
line_off = -num_lines;
byte_off = -extent_byte;
} else {
- mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0L, kExtmarkNOOP);
+ mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0, kExtmarkNOOP);
FOR_ALL_TAB_WINDOWS(tab, win) {
if (win->w_buffer == curbuf) {
foldMoveRange(win, &win->w_folds, dest + 1, line1 - 1, line2);
@@ -820,10 +789,10 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
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);
+ -(last_line - dest - extra), 0, kExtmarkNOOP);
disable_fold_update++;
- changed_lines(last_line - num_lines + 1, 0, last_line + 1, -extra, false);
+ changed_lines(curbuf, last_line - num_lines + 1, 0, last_line + 1, -extra, false);
disable_fold_update--;
// send update regarding the new lines that were added
@@ -838,8 +807,8 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
ml_delete(line1 + extra, true);
}
if (!global_busy && num_lines > p_report) {
- smsg(NGETTEXT("%" PRId64 " line moved",
- "%" PRId64 " lines moved", num_lines),
+ smsg(0, NGETTEXT("%" PRId64 " line moved",
+ "%" PRId64 " lines moved", num_lines),
(int64_t)num_lines);
}
@@ -861,9 +830,9 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
if (dest > last_line + 1) {
dest = last_line + 1;
}
- changed_lines(line1, 0, dest, 0L, false);
+ changed_lines(curbuf, line1, 0, dest, 0, false);
} else {
- changed_lines(dest + 1, 0, line1 + num_lines, 0L, false);
+ changed_lines(curbuf, dest + 1, 0, line1 + num_lines, 0, false);
}
// send nvim_buf_lines_event regarding lines that were deleted
@@ -875,10 +844,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
/// ":copy"
void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
{
- linenr_T count;
- char *p;
-
- count = line2 - line1 + 1;
+ linenr_T count = line2 - line1 + 1;
if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
curbuf->b_op_start.lnum = n + 1;
curbuf->b_op_end.lnum = n + count;
@@ -902,8 +868,8 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
while (line1 <= line2) {
// need to use xstrdup() because the line will be unlocked within
// ml_append()
- p = xstrdup(ml_get(line1));
- ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, false);
+ char *p = xstrdup(ml_get(line1));
+ ml_append(curwin->w_cursor.lnum, p, 0, false);
xfree(p);
// situation 2: skip already copied lines
@@ -925,7 +891,7 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
check_pos(curbuf, &VIsual);
}
- msgmore((long)count);
+ msgmore(count);
}
static char *prevcmd = NULL; // the previous command
@@ -938,6 +904,17 @@ void free_prev_shellcmd(void)
#endif
+/// Check that "prevcmd" is not NULL. If it is NULL then give an error message
+/// and return false.
+static int prevcmd_is_set(void)
+{
+ if (prevcmd == NULL) {
+ emsg(_(e_noprev));
+ return false;
+ }
+ return true;
+}
+
/// Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd"
/// Bangs in the argument are replaced with the previously entered command.
/// Remember the argument.
@@ -949,15 +926,9 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
linenr_T line2 = eap->line2; // end of range
char *newcmd = NULL; // the new command
bool free_newcmd = false; // need to free() newcmd
- char *t;
- char *p;
- char *trailarg;
- size_t len;
int scroll_save = msg_scroll;
- //
// Disallow shell commands in secure mode
- //
if (check_secure()) {
return;
}
@@ -973,21 +944,20 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
bool ins_prevcmd = forceit;
// Skip leading white space to avoid a strange error with some shells.
- trailarg = skipwhite(arg);
+ char *trailarg = skipwhite(arg);
do {
- len = strlen(trailarg) + 1;
+ size_t len = strlen(trailarg) + 1;
if (newcmd != NULL) {
len += strlen(newcmd);
}
if (ins_prevcmd) {
- if (prevcmd == NULL) {
- emsg(_(e_noprev));
+ if (!prevcmd_is_set()) {
xfree(newcmd);
return;
}
len += strlen(prevcmd);
}
- t = xmalloc(len);
+ char *t = xmalloc(len);
*t = NUL;
if (newcmd != NULL) {
STRCAT(t, newcmd);
@@ -995,7 +965,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
if (ins_prevcmd) {
STRCAT(t, prevcmd);
}
- p = t + strlen(t);
+ char *p = t + strlen(t);
STRCAT(t, trailarg);
xfree(newcmd);
newcmd = t;
@@ -1018,10 +988,20 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
}
} while (trailarg != NULL);
- xfree(prevcmd);
- prevcmd = newcmd;
+ // Only set "prevcmd" if there is a command to run, otherwise keep te one
+ // we have.
+ if (strlen(newcmd) > 0) {
+ xfree(prevcmd);
+ prevcmd = newcmd;
+ } else {
+ free_newcmd = true;
+ }
if (bangredo) { // put cmd in redo buffer for ! command
+ if (!prevcmd_is_set()) {
+ goto theend;
+ }
+
// If % or # appears in the command, it must have been escaped.
// Reescape them, so that redoing them does not substitute them by the
// buffername.
@@ -1034,6 +1014,9 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
}
// Add quotes around the command, for shells that need them.
if (*p_shq != NUL) {
+ if (free_newcmd) {
+ xfree(newcmd);
+ }
newcmd = xmalloc(strlen(prevcmd) + 2 * strlen(p_shq) + 1);
STRCPY(newcmd, p_shq);
STRCAT(newcmd, prevcmd);
@@ -1045,7 +1028,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
msg_start();
msg_putchar(':');
msg_putchar('!');
- msg_outtrans(newcmd);
+ msg_outtrans(newcmd, 0);
msg_clr_eos();
ui_cursor_goto(msg_row, msg_col);
@@ -1056,6 +1039,8 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
do_filter(line1, line2, eap, newcmd, do_in, do_out);
apply_autocmds(EVENT_SHELLFILTERPOST, NULL, NULL, false, curbuf);
}
+
+theend:
if (free_newcmd) {
xfree(newcmd);
}
@@ -1081,10 +1066,6 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
{
char *itmp = NULL;
char *otmp = NULL;
- linenr_T linecount;
- linenr_T read_linecount;
- pos_T cursor_save;
- char *cmd_buf;
buf_T *old_curbuf = curbuf;
int shell_flags = 0;
const pos_T orig_start = curbuf->b_op_start;
@@ -1100,12 +1081,12 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
// regions of the buffer for foldUpdate(), linecount, etc.
cmdmod.cmod_flags &= ~CMOD_LOCKMARKS;
- cursor_save = curwin->w_cursor;
- linecount = line2 - line1 + 1;
+ pos_T cursor_save = curwin->w_cursor;
+ linenr_T linecount = line2 - line1 + 1;
curwin->w_cursor.lnum = line1;
curwin->w_cursor.col = 0;
changed_line_abv_curs();
- invalidate_botline();
+ invalidate_botline(curwin);
// When using temp files:
// 1. * Form temp file names
@@ -1166,7 +1147,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
}
// Create the shell command in allocated memory.
- cmd_buf = make_filter_cmd(cmd, itmp, otmp);
+ char *cmd_buf = make_filter_cmd(cmd, itmp, otmp);
ui_cursor_goto(Rows - 1, 0);
if (do_out) {
@@ -1176,7 +1157,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
}
redraw_curbuf_later(UPD_VALID);
}
- read_linecount = curbuf->b_ml.ml_line_count;
+ linenr_T read_linecount = curbuf->b_ml.ml_line_count;
// Pass on the kShellOptDoOut flag when the output is being redirected.
call_shell(cmd_buf, (ShellOpts)(kShellOptFilter | shell_flags), NULL);
@@ -1193,7 +1174,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
if (do_out) {
if (otmp != NULL) {
- if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, eap,
+ if (readfile(otmp, NULL, line2, 0, (linenr_T)MAXLNUM, eap,
READ_FILTER, false) != OK) {
if (!aborting()) {
msg_putchar('\n');
@@ -1222,13 +1203,13 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
// end of each line?
if (read_linecount >= linecount) {
// move all marks from old lines to new lines
- mark_adjust(line1, line2, linecount, 0L, kExtmarkNOOP);
+ mark_adjust(line1, line2, linecount, 0, kExtmarkNOOP);
} else {
// move marks from old lines to new lines, delete marks
// that are in deleted lines
- mark_adjust(line1, line1 + read_linecount - 1, linecount, 0L,
+ mark_adjust(line1, line1 + read_linecount - 1, linecount, 0,
kExtmarkNOOP);
- mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0L,
+ mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0,
kExtmarkNOOP);
}
}
@@ -1255,12 +1236,12 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
if (do_in) {
vim_snprintf(msg_buf, sizeof(msg_buf),
_("%" PRId64 " lines filtered"), (int64_t)linecount);
- if (msg(msg_buf) && !msg_scroll) {
+ if (msg(msg_buf, 0) && !msg_scroll) {
// save message to display it after redraw
set_keep_msg(msg_buf, 0);
}
} else {
- msgmore((long)linecount);
+ msgmore(linecount);
}
}
} else {
@@ -1325,7 +1306,9 @@ void do_shell(char *cmd, int flags)
// 1" command to the terminal.
ui_cursor_goto(msg_row, msg_col);
(void)call_shell(cmd, (ShellOpts)flags, NULL);
- msg_didout = true;
+ if (msg_silent == 0) {
+ msg_didout = true;
+ }
did_check_timestamps = false;
need_check_timestamps = true;
@@ -1367,12 +1350,12 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
{
bool is_fish_shell =
#if defined(UNIX)
- strncmp((char *)invocation_path_tail(p_sh, NULL), "fish", 4) == 0;
+ strncmp(invocation_path_tail(p_sh, NULL), "fish", 4) == 0;
#else
false;
#endif
- bool is_pwsh = strncmp((char *)invocation_path_tail(p_sh, NULL), "pwsh", 4) == 0
- || strncmp((char *)invocation_path_tail(p_sh, NULL), "powershell",
+ bool is_pwsh = strncmp(invocation_path_tail(p_sh, NULL), "pwsh", 4) == 0
+ || strncmp(invocation_path_tail(p_sh, NULL), "powershell",
10) == 0;
size_t len = strlen(cmd) + 1; // At least enough space for cmd + NULL.
@@ -1382,8 +1365,8 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
: 0;
if (itmp != NULL) {
- len += is_pwsh ? strlen(itmp) + sizeof("& { Get-Content " " | & " " }") - 1 + 6 // +6: #20530
- : strlen(itmp) + sizeof(" { " " < " " } ") - 1;
+ len += is_pwsh ? strlen(itmp) + sizeof("& { Get-Content " " | & " " }") - 1 + 6 // +6: #20530
+ : strlen(itmp) + sizeof(" { " " < " " } ") - 1;
}
if (otmp != NULL) {
len += strlen(otmp) + strlen(p_srr) + 2; // two extra spaces (" "),
@@ -1394,7 +1377,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
if (is_pwsh) {
if (itmp != NULL) {
xstrlcpy(buf, "& { Get-Content ", len - 1); // FIXME: should we add "-Encoding utf8"?
- xstrlcat(buf, (const char *)itmp, len - 1);
+ xstrlcat(buf, itmp, len - 1);
xstrlcat(buf, " | & ", len - 1); // FIXME: add `&` ourself or leave to user?
xstrlcat(buf, cmd, len - 1);
xstrlcat(buf, " }", len - 1);
@@ -1407,7 +1390,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
// redirecting input and/or output.
if (itmp != NULL || otmp != NULL) {
char *fmt = is_fish_shell ? "begin; %s; end"
- : "(%s)";
+ : "(%s)";
vim_snprintf(buf, len, fmt, cmd);
} else {
xstrlcpy(buf, cmd, len);
@@ -1415,7 +1398,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
if (itmp != NULL) {
xstrlcat(buf, " < ", len - 1);
- xstrlcat(buf, (const char *)itmp, len - 1);
+ xstrlcat(buf, itmp, len - 1);
}
#else
// For shells that don't understand braces around commands, at least allow
@@ -1432,9 +1415,9 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
}
}
xstrlcat(buf, " < ", len);
- xstrlcat(buf, (const char *)itmp, len);
+ xstrlcat(buf, itmp, len);
if (*p_shq == NUL) {
- const char *const p = find_pipe((const char *)cmd);
+ const char *const p = find_pipe(cmd);
if (p != NULL) {
xstrlcat(buf, " ", len - 1); // Insert a space before the '|' for DOS
xstrlcat(buf, p, len - 1);
@@ -1507,7 +1490,6 @@ void print_line(linenr_T lnum, int use_number, int list)
print_line_no_prefix(lnum, use_number, list);
if (save_silent) {
msg_putchar('\n');
- ui_flush();
silent_mode = save_silent;
}
info_message = false;
@@ -1515,10 +1497,7 @@ void print_line(linenr_T lnum, int use_number, int list)
int rename_buffer(char *new_fname)
{
- char *fname, *sfname, *xfname;
- buf_T *buf;
-
- buf = curbuf;
+ buf_T *buf = curbuf;
apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
// buffer changed, don't change name now
if (buf != curbuf) {
@@ -1532,9 +1511,9 @@ int rename_buffer(char *new_fname)
// name, which will become the alternate file name.
// But don't set the alternate file name if the buffer didn't have a
// name.
- fname = curbuf->b_ffname;
- sfname = curbuf->b_sfname;
- xfname = curbuf->b_fname;
+ char *fname = curbuf->b_ffname;
+ char *sfname = curbuf->b_sfname;
+ char *xfname = curbuf->b_fname;
curbuf->b_ffname = NULL;
curbuf->b_sfname = NULL;
if (setfname(curbuf, new_fname, NULL, true) == FAIL) {
@@ -1628,17 +1607,15 @@ int do_write(exarg_T *eap)
{
int other;
char *fname = NULL; // init to shut up gcc
- char *ffname;
int retval = FAIL;
char *free_fname = NULL;
buf_T *alt_buf = NULL;
- int name_was_missing;
if (not_writing()) { // check 'write' option
return FAIL;
}
- ffname = eap->arg;
+ char *ffname = eap->arg;
if (*ffname == NUL) {
if (eap->cmdidx == CMD_saveas) {
emsg(_(e_argreq));
@@ -1660,7 +1637,7 @@ int do_write(exarg_T *eap)
if (other) {
if (vim_strchr(p_cpo, CPO_ALTWRITE) != NULL
|| eap->cmdidx == CMD_saveas) {
- alt_buf = setaltfname(ffname, fname, (linenr_T)1);
+ alt_buf = setaltfname(ffname, fname, 1);
} else {
alt_buf = buflist_findname(ffname);
}
@@ -1764,7 +1741,7 @@ int do_write(exarg_T *eap)
}
}
- name_was_missing = curbuf->b_ffname == NULL;
+ int name_was_missing = curbuf->b_ffname == NULL;
retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
eap, eap->append, eap->forceit, true, false);
@@ -1824,7 +1801,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
char buff[DIALOG_MSG_SIZE];
- dialog_msg((char *)buff, _("Overwrite existing file \"%s\"?"), fname);
+ dialog_msg(buff, _("Overwrite existing file \"%s\"?"), fname);
if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES) {
return FAIL;
}
@@ -1860,7 +1837,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
char buff[DIALOG_MSG_SIZE];
- dialog_msg((char *)buff,
+ dialog_msg(buff,
_("Swap file \"%s\" exists, overwrite anyway?"),
swapname);
if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2)
@@ -1906,6 +1883,9 @@ void do_wqall(exarg_T *eap)
int save_forceit = eap->forceit;
if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall) {
+ if (before_quit_all(eap) == FAIL) {
+ return;
+ }
exiting = true;
}
@@ -1980,11 +1960,11 @@ static int check_readonly(int *forceit, buf_T *buf)
char buff[DIALOG_MSG_SIZE];
if (buf->b_p_ro) {
- dialog_msg((char *)buff,
+ dialog_msg(buff,
_("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"),
buf->b_fname);
} else {
- dialog_msg((char *)buff,
+ dialog_msg(buff,
_("File permissions of \"%s\" are read-only.\nIt may still be possible to "
"write it.\nDo you wish to try?"),
buf->b_fname);
@@ -2067,7 +2047,7 @@ int getfile(int fnum, char *ffname_arg, char *sfname_arg, int setpm, linenr_T ln
if (lnum != 0) {
curwin->w_cursor.lnum = lnum;
}
- check_cursor_lnum();
+ check_cursor_lnum(curwin);
beginline(BL_SOL | BL_FIX);
retval = GETFILE_SAME_FILE; // it's in the same file
} else if (do_ecmd(fnum, ffname, sfname, NULL, lnum,
@@ -2127,17 +2107,14 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
bufref_T old_curbuf;
char *free_fname = NULL;
int retval = FAIL;
- long n;
- pos_T orig_pos;
linenr_T topline = 0;
int newcol = -1;
int solcol = -1;
- pos_T *pos;
char *command = NULL;
bool did_get_winopts = false;
int readfile_flags = 0;
bool did_inc_redrawing_disabled = false;
- long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
+ OptInt *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
if (eap != NULL) {
command = eap->do_ecmd_cmd;
@@ -2209,9 +2186,17 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// End Visual mode before switching to another buffer, so the text can be
// copied into the GUI selection buffer.
+ // Careful: may trigger ModeChanged() autocommand
+
+ // Should we block autocommands here?
reset_VIsual();
- if ((command != NULL || newlnum > (linenr_T)0)
+ // autocommands freed window :(
+ if (oldwin != NULL && !win_valid(oldwin)) {
+ oldwin = NULL;
+ }
+
+ if ((command != NULL || newlnum > 0)
&& *get_vim_var_str(VV_SWAPCOMMAND) == NUL) {
// Set v:swapcommand for the SwapExists autocommands.
const size_t len = (command != NULL) ? strlen(command) + 3 : 30;
@@ -2251,7 +2236,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
if (command != NULL) {
tlnum = (linenr_T)atol(command);
if (tlnum <= 0) {
- tlnum = 1L;
+ tlnum = 1;
}
}
// Add BLN_NOCURWIN to avoid a new wininfo items are associated
@@ -2263,7 +2248,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
}
goto theend;
}
- buf = buflist_new(ffname, sfname, 0L,
+ buf = buflist_new(ffname, sfname, 0,
BLN_CURBUF | (flags & ECMD_SET_HELP ? 0 : BLN_LISTED));
// Autocmds may change curwin and curbuf.
if (oldwin != NULL) {
@@ -2300,7 +2285,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// May jump to last used line number for a loaded buffer or when asked
// for explicitly
if ((oldbuf && newlnum == ECMD_LASTL) || newlnum == ECMD_LAST) {
- pos = &buflist_findfmark(buf)->mark;
+ pos_T *pos = &buflist_findfmark(buf)->mark;
newlnum = pos->lnum;
solcol = pos->col;
}
@@ -2555,7 +2540,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// Careful: open_buffer() and apply_autocmds() may change the current
// buffer and window.
- orig_pos = curwin->w_cursor;
+ pos_T orig_pos = curwin->w_cursor;
topline = curwin->w_topline;
if (!oldbuf) { // need to read the file
swap_exists_action = SEA_DIALOG;
@@ -2621,7 +2606,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// If the window options were changed may need to set the spell language.
// Can only do this after the buffer has been properly setup.
if (did_get_winopts && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) {
- (void)did_set_spelllang(curwin);
+ (void)parse_spelllang(curwin);
}
if (command == NULL) {
@@ -2631,7 +2616,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
check_cursor();
} else if (newlnum > 0) { // line number from caller or old position
curwin->w_cursor.lnum = newlnum;
- check_cursor_lnum();
+ check_cursor_lnum(curwin);
if (solcol >= 0 && !p_sol) {
// 'sol' is off: Use last known column.
curwin->w_cursor.col = solcol;
@@ -2660,11 +2645,11 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// Obey the 'O' flag in 'cpoptions': overwrite any previous file
// message.
- if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) {
+ if (shortmess(SHM_OVERALL) && !msg_listdo_overwrite && !exiting && p_verbose == 0) {
msg_scroll = false;
}
if (!msg_scroll) { // wait a bit when overwriting an error msg
- check_for_delay(false);
+ msg_check_for_delay(false);
}
msg_start();
msg_scroll = msg_scroll_save;
@@ -2690,7 +2675,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
RedrawingDisabled--;
did_inc_redrawing_disabled = false;
if (!skip_redraw) {
- n = *so_ptr;
+ OptInt n = *so_ptr;
if (topline == 0 && command == NULL) {
*so_ptr = 999; // force cursor to be vertically centered in the window
}
@@ -2737,7 +2722,6 @@ void ex_append(exarg_T *eap)
linenr_T lnum = eap->line2;
int indent = 0;
char *p;
- int vcol;
int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
// the ! flag toggles autoindent
@@ -2764,7 +2748,7 @@ void ex_append(exarg_T *eap)
State |= MODE_LANGMAP;
}
- for (;;) {
+ while (true) {
msg_scroll = true;
need_wait_return = false;
if (curbuf->b_p_ai) {
@@ -2785,7 +2769,7 @@ void ex_append(exarg_T *eap)
if (p == NULL) {
p = eap->nextcmd + strlen(eap->nextcmd);
}
- theline = xstrnsave(eap->nextcmd, (size_t)(p - eap->nextcmd));
+ theline = xmemdupz(eap->nextcmd, (size_t)(p - eap->nextcmd));
if (*p != NUL) {
p++;
}
@@ -2804,7 +2788,7 @@ void ex_append(exarg_T *eap)
}
// Look for the "." after automatic indent.
- vcol = 0;
+ int vcol = 0;
for (p = theline; indent > vcol; p++) {
if (*p == ' ') {
vcol++;
@@ -2827,19 +2811,19 @@ void ex_append(exarg_T *eap)
}
did_undo = true;
- ml_append(lnum, theline, (colnr_T)0, false);
+ ml_append(lnum, theline, 0, false);
if (empty) {
// there are no marks below the inserted lines
- appended_lines(lnum, 1L);
+ appended_lines(lnum, 1);
} else {
- appended_lines_mark(lnum, 1L);
+ appended_lines_mark(lnum, 1);
}
xfree(theline);
lnum++;
if (empty) {
- ml_delete(2L, false);
+ ml_delete(2, false);
empty = 0;
}
}
@@ -2863,7 +2847,7 @@ void ex_append(exarg_T *eap)
curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
}
curwin->w_cursor.lnum = lnum;
- check_cursor_lnum();
+ check_cursor_lnum(curwin);
beginline(BL_SOL | BL_FIX);
need_wait_return = false; // don't use wait_return() now
@@ -2893,7 +2877,7 @@ void ex_change(exarg_T *eap)
}
// make sure the cursor is not beyond the end of the file now
- check_cursor_lnum();
+ check_cursor_lnum(curwin);
deleted_lines_mark(eap->line1, (eap->line2 - lnum));
// ":append" on the line above the deleted lines.
@@ -2903,12 +2887,9 @@ void ex_change(exarg_T *eap)
void ex_z(exarg_T *eap)
{
- char *x;
int64_t bigness;
- char *kind;
int minus = 0;
- linenr_T start, end, curs, i;
- int j;
+ linenr_T start, end, curs;
linenr_T lnum = eap->line2;
// Vi compatible: ":z!" uses display height, without a count uses
@@ -2924,8 +2905,8 @@ void ex_z(exarg_T *eap)
bigness = 1;
}
- x = eap->arg;
- kind = x;
+ char *x = eap->arg;
+ char *kind = x;
if (*kind == '-' || *kind == '+' || *kind == '='
|| *kind == '^' || *kind == '.') {
x++;
@@ -2936,7 +2917,7 @@ void ex_z(exarg_T *eap)
if (*x != 0) {
if (!ascii_isdigit(*x)) {
- emsg(_("E144: non-numeric argument to :z"));
+ emsg(_(e_non_numeric_argument_to_z));
return;
}
bigness = atol(x);
@@ -2946,7 +2927,7 @@ void ex_z(exarg_T *eap)
bigness = 2 * curbuf->b_ml.ml_line_count;
}
- p_window = bigness;
+ p_window = (int)bigness;
if (*kind == '=') {
bigness += 2;
}
@@ -3009,11 +2990,11 @@ void ex_z(exarg_T *eap)
curs = 1;
}
- for (i = start; i <= end; i++) {
+ for (linenr_T i = start; i <= end; i++) {
if (minus && i == lnum) {
msg_putchar('\n');
- for (j = 1; j < Columns; j++) {
+ for (int j = 1; j < Columns; j++) {
msg_putchar('-');
}
}
@@ -3023,7 +3004,7 @@ void ex_z(exarg_T *eap)
if (minus && i == lnum) {
msg_putchar('\n');
- for (j = 1; j < Columns; j++) {
+ for (int j = 1; j < Columns; j++) {
msg_putchar('-');
}
}
@@ -3149,21 +3130,21 @@ static bool sub_joining_lines(exarg_T *eap, char *pat, const char *sub, const ch
/// Slightly more memory that is strictly necessary is allocated to reduce the
/// frequency of memory (re)allocation.
///
-/// @param[in,out] new_start pointer to the memory for the replacement text
-/// @param[in] needed_len amount of memory needed
+/// @param[in,out] new_start pointer to the memory for the replacement text
+/// @param[in,out] new_start_len pointer to length of new_start
+/// @param[in] needed_len amount of memory needed
///
/// @returns pointer to the end of the allocated memory
-static char *sub_grow_buf(char **new_start, int needed_len)
- FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_RET
+static char *sub_grow_buf(char **new_start, int *new_start_len, int needed_len)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
- int new_start_len = 0;
char *new_end;
if (*new_start == NULL) {
// Get some space for a temporary buffer to do the
// substitution into (and some extra space to avoid
// too many calls to xmalloc()/free()).
- new_start_len = needed_len + 50;
- *new_start = xmalloc((size_t)new_start_len);
+ *new_start_len = needed_len + 50;
+ *new_start = xmalloc((size_t)(*new_start_len));
**new_start = NUL;
new_end = *new_start;
} else {
@@ -3172,9 +3153,9 @@ static char *sub_grow_buf(char **new_start, int needed_len)
// extra to avoid too many calls to xmalloc()/free()).
size_t len = strlen(*new_start);
needed_len += (int)len;
- if (needed_len > new_start_len) {
- new_start_len = needed_len + 50;
- *new_start = xrealloc(*new_start, (size_t)new_start_len);
+ if (needed_len > *new_start_len) {
+ *new_start_len = needed_len + 50;
+ *new_start = xrealloc(*new_start, (size_t)(*new_start_len));
}
new_end = *new_start + len;
}
@@ -3242,6 +3223,25 @@ static char *sub_parse_flags(char *cmd, subflags_T *subflags, int *which_pat)
return cmd;
}
+/// Skip over the "sub" part in :s/pat/sub/ where "delimiter" is the separating
+/// character.
+static char *skip_substitute(char *start, int delimiter)
+{
+ char *p = start;
+
+ while (p[0]) {
+ if (p[0] == delimiter) { // end delimiter found
+ *p++ = NUL; // replace it with a NUL
+ break;
+ }
+ if (p[0] == '\\' && p[1] != 0) { // skip escaped characters
+ p++;
+ }
+ MB_PTR_ADV(p);
+ }
+ return p;
+}
+
static int check_regexp_delim(int c)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -3259,9 +3259,11 @@ static int check_regexp_delim(int c)
///
/// The usual escapes are supported as described in the regexp docs.
///
-/// @param do_buf_event If `true`, send buffer updates.
+/// @param cmdpreview_ns The namespace to show 'inccommand' preview highlights.
+/// If <= 0, preview shouldn't be shown.
/// @return 0, 1 or 2. See show_cmdpreview() for more information on what the return value means.
-static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T cmdpreview_bufnr)
+static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_ns,
+ const handle_T cmdpreview_bufnr)
{
#define ADJUST_SUB_FIRSTLNUM() \
do { \
@@ -3287,7 +3289,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
} \
} while (0)
- long i = 0;
+ int i = 0;
regmmatch_T regmatch;
static subflags_T subflags = {
.do_all = false,
@@ -3308,14 +3310,14 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
int which_pat;
char *cmd = eap->arg;
linenr_T first_line = 0; // first changed line
- linenr_T last_line= 0; // below last changed line AFTER the change
+ linenr_T last_line = 0; // below last changed line AFTER the change
linenr_T old_line_count = curbuf->b_ml.ml_line_count;
char *sub_firstline; // allocated copy of first sub line
bool endcolumn = false; // cursor in last column when done
PreviewLines preview_lines = { KV_INITIAL_VALUE, 0 };
static int pre_hl_id = 0;
pos_T old_cursor = curwin->w_cursor;
- long start_nsubs;
+ int start_nsubs;
bool did_save = false;
@@ -3366,20 +3368,11 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// Small incompatibility: vi sees '\n' as end of the command, but in
// Vim we want to use '\n' to find/substitute a NUL.
- sub = cmd; // remember the start of the substitution
-
- while (cmd[0]) {
- if (cmd[0] == delimiter) { // end delimiter found
- *cmd++ = NUL; // replace it with a NUL
- break;
- }
- if (cmd[0] == '\\' && cmd[1] != 0) { // skip escaped characters
- cmd++;
- }
- MB_PTR_ADV(cmd);
- }
+ char *p = cmd; // remember the start of the substitution
+ cmd = skip_substitute(cmd, delimiter);
+ sub = xstrdup(p);
- if (!eap->skip && !cmdpreview) {
+ if (!eap->skip && cmdpreview_ns <= 0) {
sub_set_replacement((SubReplacementString) {
.sub = xstrdup(sub),
.timestamp = os_time(),
@@ -3392,14 +3385,15 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
return 0;
}
pat = NULL; // search_regcomp() will use previous pattern
- sub = old_sub.sub;
+ sub = xstrdup(old_sub.sub);
// Vi compatibility quirk: repeating with ":s" keeps the cursor in the
// last column after using "$".
endcolumn = (curwin->w_curswant == MAXCOL);
}
- if (sub != NULL && sub_joining_lines(eap, pat, sub, cmd, !cmdpreview)) {
+ if (sub != NULL && sub_joining_lines(eap, pat, sub, cmd, cmdpreview_ns <= 0)) {
+ xfree(sub);
return 0;
}
@@ -3411,9 +3405,16 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// check for a trailing count
cmd = skipwhite(cmd);
if (ascii_isdigit(*cmd)) {
- i = getdigits_long(&cmd, true, 0);
+ i = getdigits_int(&cmd, true, INT_MAX);
if (i <= 0 && !eap->skip && subflags.do_error) {
emsg(_(e_zerocount));
+ xfree(sub);
+ return 0;
+ } else if (i >= INT_MAX) {
+ char buf[20];
+ vim_snprintf(buf, sizeof(buf), "%d", i);
+ semsg(_(e_val_too_large), buf);
+ xfree(sub);
return 0;
}
eap->line1 = eap->line2;
@@ -3429,25 +3430,29 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
eap->nextcmd = check_nextcmd(cmd);
if (eap->nextcmd == NULL) {
semsg(_(e_trailing_arg), cmd);
+ xfree(sub);
return 0;
}
}
if (eap->skip) { // not executing commands, only parsing
+ xfree(sub);
return 0;
}
if (!subflags.do_count && !MODIFIABLE(curbuf)) {
// Substitution is not allowed in non-'modifiable' buffer
emsg(_(e_modifiable));
+ xfree(sub);
return 0;
}
if (search_regcomp(pat, NULL, RE_SUBST, which_pat,
- (cmdpreview ? 0 : SEARCH_HIS), &regmatch) == FAIL) {
+ (cmdpreview_ns > 0 ? 0 : SEARCH_HIS), &regmatch) == FAIL) {
if (subflags.do_error) {
emsg(_(e_invcmd));
}
+ xfree(sub);
return 0;
}
@@ -3462,22 +3467,20 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
assert(sub != NULL);
- char *sub_copy = NULL;
-
// If the substitute pattern starts with "\=" then it's an expression.
// Make a copy, a recursive function may free it.
// Otherwise, '~' in the substitute pattern is replaced with the old
// pattern. We do it here once to avoid it to be replaced over and over
// again.
if (sub[0] == '\\' && sub[1] == '=') {
- sub = xstrdup(sub);
- sub_copy = sub;
+ char *p = xstrdup(sub);
+ xfree(sub);
+ sub = p;
} else {
- char *newsub = regtilde(sub, magic_isset(), cmdpreview);
- if (newsub != sub) {
- // newsub was allocated, free it later.
- sub_copy = newsub;
- sub = newsub;
+ char *p = regtilde(sub, magic_isset(), cmdpreview_ns > 0);
+ if (p != sub) {
+ xfree(sub);
+ sub = p;
}
}
@@ -3487,20 +3490,21 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
for (linenr_T lnum = eap->line1;
lnum <= line2 && !got_quit && !aborting()
- && (!cmdpreview || preview_lines.lines_needed <= (linenr_T)p_cwh
+ && (cmdpreview_ns <= 0 || preview_lines.lines_needed <= (linenr_T)p_cwh
|| lnum <= curwin->w_botline);
lnum++) {
- long nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
- (colnr_T)0, NULL, NULL);
+ int nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
+ 0, NULL, NULL);
if (nmatch) {
colnr_T copycol;
colnr_T matchcol;
colnr_T prev_matchcol = MAXCOL;
char *new_end, *new_start = NULL;
+ int new_start_len = 0;
char *p1;
bool did_sub = false;
int lastone;
- long nmatch_tl = 0; // nr of lines matched below lnum
+ linenr_T nmatch_tl = 0; // nr of lines matched below lnum
int do_again; // do it again after joining lines
bool skip_match = false;
linenr_T sub_firstlnum; // nr of first sub line
@@ -3542,7 +3546,8 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// accordingly.
//
// The new text is built up in new_start[]. It has some extra
- // room to avoid using xmalloc()/free() too often.
+ // room to avoid using xmalloc()/free() too often. new_start_len is
+ // the length of the allocated memory at new_start.
//
// Make a copy of the old line, so it won't be taken away when
// updating the screen or handling a multi-line match. The "old_"
@@ -3563,10 +3568,10 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// 3. substitute the string.
// 4. if subflags.do_all is set, find next match
// 5. break if there isn't another match in this line
- for (;;) {
+ while (true) {
SubResult current_match = {
.start = { 0, 0 },
- .end = { 0, 0 },
+ .end = { 0, 0 },
.pre_match = 0,
};
// lnum is where the match start, but maybe not the pattern match,
@@ -3648,7 +3653,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
}
}
- if (subflags.do_ask && !cmdpreview) {
+ if (subflags.do_ask && cmdpreview_ns <= 0) {
int typed = 0;
// change State to MODE_CONFIRM, so that the mouse works
@@ -3754,6 +3759,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
update_topline(curwin);
validate_cursor();
redraw_later(curwin, UPD_SOME_VALID);
+ show_cursor_info_later(true);
update_screen();
highlight_match = false;
redraw_later(curwin, UPD_SOME_VALID);
@@ -3768,11 +3774,10 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// needed
msg_no_more = true;
msg_ext_set_kind("confirm_sub");
- smsg_attr(HL_ATTR(HLF_R), // Same highlight as wait_return().
- _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub);
+ // Same highlight as wait_return().
+ smsg(HL_ATTR(HLF_R), _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub);
msg_no_more = false;
- msg_scroll = (int)i;
- show_cursor_info(true);
+ msg_scroll = i;
if (!ui_has(kUIMessages)) {
ui_cursor_goto(msg_row, msg_col);
}
@@ -3856,17 +3861,21 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1;
current_match.end.lnum = sub_firstlnum + (linenr_T)nmatch;
skip_match = true;
+ // safety check
+ if (nmatch < 0) {
+ goto skip;
+ }
}
// Save the line numbers for the preview buffer
// NOTE: If the pattern matches a final newline, the next line will
// be shown also, but should not be highlighted. Intentional for now.
- if (cmdpreview && !has_second_delim) {
+ if (cmdpreview_ns > 0 && !has_second_delim) {
current_match.start.col = regmatch.startpos[0].col;
if (current_match.end.lnum == 0) {
current_match.end.lnum = sub_firstlnum + (linenr_T)nmatch - 1;
}
- current_match.end.col = regmatch.endpos[0].col;
+ current_match.end.col = regmatch.endpos[0].col;
ADJUST_SUB_FIRSTLNUM();
lnum += (linenr_T)nmatch - 1;
@@ -3876,8 +3885,8 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// 3. Substitute the string. During 'inccommand' preview only do this if
// there is a replace pattern.
- if (!cmdpreview || has_second_delim) {
- long lnum_start = lnum; // save the start lnum
+ if (cmdpreview_ns <= 0 || has_second_delim) {
+ linenr_T lnum_start = lnum; // save the start lnum
int save_ma = curbuf->b_p_ma;
int save_sandbox = sandbox;
if (subflags.do_count) {
@@ -3921,15 +3930,19 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
p1 = ml_get(sub_firstlnum + (linenr_T)nmatch - 1);
nmatch_tl += nmatch - 1;
}
- size_t copy_len = (size_t)(regmatch.startpos[0].col - copycol);
- new_end = sub_grow_buf(&new_start,
+ int copy_len = regmatch.startpos[0].col - copycol;
+ new_end = sub_grow_buf(&new_start, &new_start_len,
(colnr_T)strlen(p1) - regmatch.endpos[0].col
- + (colnr_T)copy_len + sublen + 1);
+ + copy_len + sublen + 1);
// copy the text up to the part that matched
- memmove(new_end, sub_firstline + copycol, copy_len);
+ memmove(new_end, sub_firstline + copycol, (size_t)copy_len);
new_end += copy_len;
+ if (new_start_len - copy_len < sublen) {
+ sublen = new_start_len - copy_len - 1;
+ }
+
// Finally, at this point we can know where the match actually will
// start in the new text
int start_col = (int)(new_end - new_start);
@@ -3977,10 +3990,10 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
*p1 = NUL; // truncate up to the CR
ml_append(lnum - 1, new_start,
(colnr_T)(p1 - new_start + 1), false);
- mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L, kExtmarkNOOP);
+ mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1, 0, kExtmarkNOOP);
if (subflags.do_ask) {
- appended_lines(lnum - 1, 1L);
+ appended_lines(lnum - 1, 1);
} else {
if (first_line == 0) {
first_line = lnum;
@@ -4015,7 +4028,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
}
extmark_splice(curbuf, (int)lnum_start - 1, start_col,
end.lnum - start.lnum, matchcols, replaced_bytes,
- lnum - (linenr_T)lnum_start, subcols, sublen - 1, kExtmarkUndo);
+ lnum - lnum_start, subcols, sublen - 1, kExtmarkUndo);
}
// 4. If subflags.do_all is set, find next match.
@@ -4078,13 +4091,12 @@ skip:
for (i = 0; i < nmatch_tl; i++) {
ml_delete(lnum, false);
}
- mark_adjust(lnum, lnum + (linenr_T)nmatch_tl - 1,
- (long)MAXLNUM, (linenr_T)(-nmatch_tl), kExtmarkNOOP);
+ mark_adjust(lnum, lnum + nmatch_tl - 1, MAXLNUM, -nmatch_tl, kExtmarkNOOP);
if (subflags.do_ask) {
- deleted_lines(lnum, (linenr_T)nmatch_tl);
+ deleted_lines(lnum, nmatch_tl);
}
lnum--;
- line2 -= (linenr_T)nmatch_tl; // nr of lines decreases
+ line2 -= nmatch_tl; // nr of lines decreases
nmatch_tl = 0;
}
@@ -4126,7 +4138,7 @@ skip:
#define PUSH_PREVIEW_LINES() \
do { \
- if (cmdpreview) { \
+ if (cmdpreview_ns > 0) { \
linenr_T match_lines = current_match.end.lnum \
- current_match.start.lnum +1; \
if (preview_lines.subresults.size > 0) { \
@@ -4178,7 +4190,7 @@ skip:
// the line number before the change (same as adding the number of
// deleted lines).
i = curbuf->b_ml.ml_line_count - old_line_count;
- changed_lines(first_line, 0, last_line - (linenr_T)i, (linenr_T)i, false);
+ changed_lines(curbuf, first_line, 0, last_line - (linenr_T)i, (linenr_T)i, false);
int64_t num_added = last_line - first_line;
int64_t num_removed = num_added - i;
@@ -4209,8 +4221,8 @@ skip:
beginline(BL_WHITE | BL_FIX);
}
}
- if (!cmdpreview && !do_sub_msg(subflags.do_count) && subflags.do_ask && p_ch > 0) {
- msg("");
+ if (cmdpreview_ns <= 0 && !do_sub_msg(subflags.do_count) && subflags.do_ask && p_ch > 0) {
+ msg("", 0);
}
} else {
global_need_beginline = true;
@@ -4225,7 +4237,7 @@ skip:
} else if (got_match) {
// did find something but nothing substituted
if (p_ch > 0) {
- msg("");
+ msg("", 0);
}
} else if (subflags.do_error) {
// nothing found
@@ -4239,7 +4251,7 @@ skip:
}
vim_regfree(regmatch.regprog);
- xfree(sub_copy);
+ xfree(sub);
// Restore the flag values, they can be used for ":&&".
subflags.do_all = save_do_all;
@@ -4248,7 +4260,7 @@ skip:
int retv = 0;
// Show 'inccommand' preview if there are matched lines.
- if (cmdpreview && !aborting()) {
+ if (cmdpreview_ns > 0 && !aborting()) {
if (got_quit || profile_passed_limit(timeout)) { // Too slow, disable.
set_string_option_direct("icm", -1, "", OPT_FREE, SID_NONE);
} else if (*p_icm != NUL && pat != NULL) {
@@ -4287,19 +4299,19 @@ bool do_sub_msg(bool count_only)
}
char *msg_single = count_only
- ? NGETTEXT("%" PRId64 " match on %" PRId64 " line",
- "%" PRId64 " matches on %" PRId64 " line", sub_nsubs)
- : NGETTEXT("%" PRId64 " substitution on %" PRId64 " line",
- "%" PRId64 " substitutions on %" PRId64 " line", sub_nsubs);
+ ? NGETTEXT("%" PRId64 " match on %" PRId64 " line",
+ "%" PRId64 " matches on %" PRId64 " line", sub_nsubs)
+ : NGETTEXT("%" PRId64 " substitution on %" PRId64 " line",
+ "%" PRId64 " substitutions on %" PRId64 " line", sub_nsubs);
char *msg_plural = count_only
- ? NGETTEXT("%" PRId64 " match on %" PRId64 " lines",
- "%" PRId64 " matches on %" PRId64 " lines", sub_nsubs)
- : NGETTEXT("%" PRId64 " substitution on %" PRId64 " lines",
- "%" PRId64 " substitutions on %" PRId64 " lines", sub_nsubs);
- vim_snprintf_add((char *)msg_buf, sizeof(msg_buf),
+ ? NGETTEXT("%" PRId64 " match on %" PRId64 " lines",
+ "%" PRId64 " matches on %" PRId64 " lines", sub_nsubs)
+ : NGETTEXT("%" PRId64 " substitution on %" PRId64 " lines",
+ "%" PRId64 " substitutions on %" PRId64 " lines", sub_nsubs);
+ vim_snprintf_add(msg_buf, sizeof(msg_buf),
NGETTEXT(msg_single, msg_plural, sub_nlines),
(int64_t)sub_nsubs, (int64_t)sub_nlines);
- if (msg(msg_buf)) {
+ if (msg(msg_buf, 0)) {
// save message to display it after redraw
set_keep_msg(msg_buf, 0);
}
@@ -4340,15 +4352,12 @@ static void global_exe_one(char *const cmd, const linenr_T lnum)
void ex_global(exarg_T *eap)
{
linenr_T lnum; // line number according to old situation
- int ndone = 0;
int type; // first char of cmd: 'v' or 'g'
- char *cmd; // command argument
+ char *cmd; // command argument
char delim; // delimiter, normally '/'
char *pat;
regmmatch_T regmatch;
- int match;
- int which_pat;
// When nesting the command works on one line. This allows for
// ":g/found/v/notfound/command".
@@ -4365,7 +4374,7 @@ void ex_global(exarg_T *eap)
type = (uint8_t)(*eap->cmd);
}
cmd = eap->arg;
- which_pat = RE_LAST; // default: use last used regexp
+ int which_pat = RE_LAST; // default: use last used regexp
// undocumented vi feature:
// "\/" and "\?": use previous search pattern.
@@ -4407,15 +4416,16 @@ void ex_global(exarg_T *eap)
if (global_busy) {
lnum = curwin->w_cursor.lnum;
- match = (int)vim_regexec_multi(&regmatch, curwin, curbuf, lnum, 0, NULL, NULL);
+ int match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, 0, NULL, NULL);
if ((type == 'g' && match) || (type == 'v' && !match)) {
global_exe_one(cmd, lnum);
}
} else {
+ int ndone = 0;
// pass 1: set marks for each (not) matching line
for (lnum = eap->line1; lnum <= eap->line2 && !got_int; lnum++) {
// a match on this line?
- match = (int)vim_regexec_multi(&regmatch, curwin, curbuf, lnum, 0, NULL, NULL);
+ int match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, 0, NULL, NULL);
if (regmatch.regprog == NULL) {
break; // re-compiling regprog failed
}
@@ -4428,12 +4438,12 @@ void ex_global(exarg_T *eap)
// pass 2: execute the command for each line that has been marked
if (got_int) {
- msg(_(e_interr));
+ msg(_(e_interr), 0);
} else if (ndone == 0) {
if (type == 'v') {
- smsg(_("Pattern found in every line: %s"), used_pat);
+ smsg(0, _("Pattern found in every line: %s"), used_pat);
} else {
- smsg(_("Pattern not found: %s"), used_pat);
+ smsg(0, _("Pattern not found: %s"), used_pat);
}
} else {
global_exe(cmd);
@@ -4541,7 +4551,7 @@ bool prepare_tagpreview(bool undo_sync)
///
/// @return 1 if preview window isn't needed, 2 if preview window is needed.
static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, int hl_id,
- long cmdpreview_ns, handle_T cmdpreview_bufnr)
+ int cmdpreview_ns, handle_T cmdpreview_bufnr)
FUNC_ATTR_NONNULL_ALL
{
char *save_shm_p = xstrdup(p_shm);
@@ -4589,15 +4599,15 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
linenr_T linenr_origbuf = 0; // last line added to original buffer
linenr_T next_linenr = 0; // next line to show for the match
- // Temporarily switch to preview buffer
- aco_save_T aco;
-
for (size_t matchidx = 0; matchidx < lines.subresults.size; matchidx++) {
SubResult match = lines.subresults.items[matchidx];
if (cmdpreview_buf) {
lpos_T p_start = { 0, match.start.col }; // match starts here in preview
- lpos_T p_end = { 0, match.end.col }; // ... and ends here
+ lpos_T p_end = { 0, match.end.col }; // ... and ends here
+
+ // You Might Gonna Need It
+ buf_ensure_loaded(cmdpreview_buf);
if (match.pre_match == 0) {
next_linenr = match.start.lnum;
@@ -4622,7 +4632,7 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
if (next_linenr == orig_buf->b_ml.ml_line_count + 1) {
line = "";
} else {
- line = ml_get_buf(orig_buf, next_linenr, false);
+ line = ml_get_buf(orig_buf, next_linenr);
line_size = strlen(line) + (size_t)col_width + 1;
// Reallocate if line not long enough
@@ -4634,21 +4644,18 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
// Put "|lnum| line" into `str` and append it to the preview buffer.
snprintf(str, line_size, "|%*" PRIdLINENR "| %s", col_width - 3,
next_linenr, line);
- // Temporarily switch to preview buffer
- aucmd_prepbuf(&aco, cmdpreview_buf);
if (linenr_preview == 0) {
- ml_replace(1, str, true);
+ ml_replace_buf(cmdpreview_buf, 1, str, true);
} else {
- ml_append(linenr_preview, str, (colnr_T)line_size, false);
+ ml_append_buf(cmdpreview_buf, linenr_preview, str, (colnr_T)line_size, false);
}
- aucmd_restbuf(&aco);
linenr_preview += 1;
}
linenr_origbuf = match.end.lnum;
- bufhl_add_hl_pos_offset(cmdpreview_buf, (int)cmdpreview_ns, hl_id, p_start, p_end, col_width);
+ bufhl_add_hl_pos_offset(cmdpreview_buf, cmdpreview_ns, hl_id, p_start, p_end, col_width);
}
- bufhl_add_hl_pos_offset(orig_buf, (int)cmdpreview_ns, hl_id, match.start, match.end, 0);
+ bufhl_add_hl_pos_offset(orig_buf, cmdpreview_ns, hl_id, match.start, match.end, 0);
}
xfree(str);
@@ -4666,7 +4673,7 @@ void ex_substitute(exarg_T *eap)
}
/// :substitute command preview callback.
-int ex_substitute_preview(exarg_T *eap, long cmdpreview_ns, handle_T cmdpreview_bufnr)
+int ex_substitute_preview(exarg_T *eap, int cmdpreview_ns, handle_T cmdpreview_bufnr)
{
// Only preview once the pattern delimiter has been typed
if (*eap->arg && !ASCII_ISALNUM(*eap->arg)) {
@@ -4688,8 +4695,6 @@ int ex_substitute_preview(exarg_T *eap, long cmdpreview_ns, handle_T cmdpreview_
/// @return a pointer to the char just past the pattern plus flags.
char *skip_vimgrep_pat(char *p, char **s, int *flags)
{
- int c;
-
if (vim_isIDc((uint8_t)(*p))) {
// ":vimgrep pattern fname"
if (s != NULL) {
@@ -4704,7 +4709,7 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags)
if (s != NULL) {
*s = p + 1;
}
- c = (uint8_t)(*p);
+ int c = (uint8_t)(*p);
p = skip_regexp(p + 1, c, true);
if (*p != c) {
return NULL;
@@ -4737,10 +4742,10 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags)
void ex_oldfiles(exarg_T *eap)
{
list_T *l = get_vim_var_list(VV_OLDFILES);
- long nr = 0;
+ int nr = 0;
if (l == NULL) {
- msg(_("No old files"));
+ msg(_("No old files"), 0);
return;
}
@@ -4752,10 +4757,10 @@ void ex_oldfiles(exarg_T *eap)
}
nr++;
const char *fname = tv_get_string(TV_LIST_ITEM_TV(li));
- if (!message_filtered((char *)fname)) {
+ if (!message_filtered(fname)) {
msg_outnum(nr);
msg_puts(": ");
- msg_outtrans((char *)tv_get_string(TV_LIST_ITEM_TV(li)));
+ msg_outtrans(tv_get_string(TV_LIST_ITEM_TV(li)), 0);
msg_clr_eos();
msg_putchar('\n');
os_breakcheck();
@@ -4771,7 +4776,7 @@ void ex_oldfiles(exarg_T *eap)
nr = prompt_for_number(false);
msg_starthere();
if (nr > 0 && nr <= tv_list_len(l)) {
- const char *const p = tv_list_find_str(l, (int)nr - 1);
+ const char *const p = tv_list_find_str(l, nr - 1);
if (p == NULL) {
return;
}
@@ -4784,29 +4789,3 @@ void ex_oldfiles(exarg_T *eap)
}
}
}
-
-void ex_trust(exarg_T *eap)
-{
- const char *const p = skiptowhite(eap->arg);
- char *arg1 = xmemdupz(eap->arg, (size_t)(p - eap->arg));
- const char *action = "allow";
- const char *path = skipwhite(p);
-
- if (strcmp(arg1, "++deny") == 0) {
- action = "deny";
- } else if (strcmp(arg1, "++remove") == 0) {
- action = "remove";
- } else if (*arg1 != '\0') {
- semsg(e_invarg2, arg1);
- goto theend;
- }
-
- if (path[0] == '\0') {
- path = NULL;
- }
-
- nlua_trust(action, path);
-
-theend:
- xfree(arg1);
-}