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.c1733
1 files changed, 843 insertions, 890 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 95390b1a70..28e1893b31 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -14,7 +14,6 @@
#include <string.h>
#include "nvim/api/buffer.h"
-#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/ascii.h"
#include "nvim/buffer.h"
@@ -38,6 +37,7 @@
#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/input.h"
#include "nvim/log.h"
@@ -72,7 +72,6 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-
/// Case matching style to use for :substitute
typedef enum {
kSubHonorOptions = 0, ///< Honor the user's 'ignorecase'/'smartcase' options
@@ -111,12 +110,10 @@ typedef struct {
# include "ex_cmds.c.generated.h"
#endif
-static int preview_bufnr = 0;
-
/// ":ascii" and "ga" implementation
void do_ascii(const exarg_T *const eap)
{
- char_u *dig;
+ char *dig;
int cc[MAX_MCO];
int c = utfc_ptr2char(get_cursor_pos_ptr(), cc);
if (c == NUL) {
@@ -136,8 +133,8 @@ void do_ascii(const exarg_T *const eap)
: c);
char buf1[20];
if (vim_isprintc_strict(c) && (c < ' ' || c > '~')) {
- char_u buf3[7];
- transchar_nonprint(curbuf, buf3, c);
+ char buf3[7];
+ transchar_nonprint(curbuf, (char_u *)buf3, c);
vim_snprintf(buf1, sizeof(buf1), " <%s>", (char *)buf3);
} else {
buf1[0] = NUL;
@@ -145,19 +142,17 @@ void do_ascii(const exarg_T *const eap)
char buf2[20];
buf2[0] = NUL;
- dig = get_digraph_for_char(cval);
+ dig = (char *)get_digraph_for_char(cval);
if (dig != NULL) {
- iobuff_len += (
- vim_snprintf((char *)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));
+ iobuff_len += (size_t)vim_snprintf((char *)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);
} else {
- iobuff_len += (
- vim_snprintf((char *)IObuff + iobuff_len,
- sizeof(IObuff) - iobuff_len,
- _("<%s>%s%s %d, Hex %02x, Octal %03o"),
- transchar(c), buf1, buf2, cval, cval, cval));
+ iobuff_len += (size_t)vim_snprintf((char *)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++];
@@ -193,25 +188,23 @@ void do_ascii(const exarg_T *const eap)
if (utf_iscomposing(c)) {
IObuff[iobuff_len++] = ' '; // Draw composing char on top of a space.
}
- iobuff_len += utf_char2bytes(c, IObuff + iobuff_len);
+ iobuff_len += (size_t)utf_char2bytes(c, (char *)IObuff + iobuff_len);
- dig = get_digraph_for_char(c);
+ dig = (char *)get_digraph_for_char(c);
if (dig != NULL) {
- iobuff_len += (
- vim_snprintf((char *)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));
+ iobuff_len += (size_t)vim_snprintf((char *)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 += (
- vim_snprintf((char *)IObuff + iobuff_len,
- sizeof(IObuff) - iobuff_len,
- (c < 0x10000
- ? _("> %d, Hex %04x, Octal %o")
- : _("> %d, Hex %08x, Octal %o")),
- c, c, c));
+ iobuff_len += (size_t)vim_snprintf((char *)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;
@@ -225,9 +218,7 @@ void do_ascii(const exarg_T *const eap)
msg((char *)IObuff);
}
-/*
- * ":left", ":center" and ":right": align text.
- */
+/// ":left", ":center" and ":right": align text.
void ex_align(exarg_T *eap)
{
pos_T save_curpos;
@@ -246,7 +237,7 @@ void ex_align(exarg_T *eap)
}
}
- width = atoi((char *)eap->arg);
+ width = atoi(eap->arg);
save_curpos = curwin->w_cursor;
if (eap->cmdidx == CMD_left) { // width is used for new indent
if (width >= 0) {
@@ -259,10 +250,10 @@ void ex_align(exarg_T *eap)
* if invalid value, use 80
*/
if (width <= 0) {
- width = curbuf->b_p_tw;
+ width = (int)curbuf->b_p_tw;
}
if (width == 0 && curbuf->b_p_wm > 0) {
- width = curwin->w_width_inner - curbuf->b_p_wm;
+ width = curwin->w_width_inner - (int)curbuf->b_p_wm;
}
if (width <= 0) {
width = 80;
@@ -324,20 +315,17 @@ void ex_align(exarg_T *eap)
beginline(BL_WHITE | BL_FIX);
}
-/*
- * Get the length of the current line, excluding trailing white space.
- */
+/// @return the length of the current line, excluding trailing white space.
static int linelen(int *has_tab)
{
- char_u *line;
- char_u *first;
- char_u *last;
- int save;
+ 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();
+ line = (char *)get_cursor_line_ptr();
if (*line == NUL) {
return 0;
}
@@ -346,12 +334,11 @@ static int linelen(int *has_tab)
// find the character after the last non-blank character
for (last = first + STRLEN(first);
- last > first && ascii_iswhite(last[-1]); last--) {
- }
- save = *last;
+ last > first && ascii_iswhite(last[-1]); last--) {}
+ char save = *last;
*last = NUL;
// Get line length.
- len = linetabsize(line);
+ len = linetabsize((char_u *)line);
// Check for embedded TAB.
if (has_tab != NULL) {
*has_tab = vim_strchr(first, TAB) != NULL;
@@ -363,8 +350,8 @@ static int linelen(int *has_tab)
// Buffer for two lines used during sorting. They are allocated to
// contain the longest line being sorted.
-static char_u *sortbuf1;
-static char_u *sortbuf2;
+static char *sortbuf1;
+static char *sortbuf2;
static int sort_lc; ///< sort using locale
static int sort_ic; ///< ignore case
@@ -436,10 +423,10 @@ static int sort_compare(const void *s1, const void *s2)
// guarantee that the first pointer becomes invalid when obtaining the
// second one.
memcpy(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr,
- l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1);
+ (size_t)(l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1));
sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = NUL;
memcpy(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr,
- l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1);
+ (size_t)(l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1));
sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = NUL;
result = string_compare(sortbuf1, sortbuf2);
@@ -447,24 +434,24 @@ static int sort_compare(const void *s1, const void *s2)
// If two lines have the same value, preserve the original line order.
if (result == 0) {
- return (int)(l1.lnum - l2.lnum);
+ return l1.lnum - l2.lnum;
}
return result;
}
-// ":sort".
+/// ":sort".
void ex_sort(exarg_T *eap)
{
regmatch_T regmatch;
int len;
linenr_T lnum;
long maxlen = 0;
- size_t count = (size_t)(eap->line2 - eap->line1 + 1);
+ size_t count = (size_t)(eap->line2 - eap->line1) + 1;
size_t i;
- char_u *p;
- char_u *s;
- char_u *s2;
- char_u c; // temporary character storage
+ char *p;
+ char *s;
+ char *s2;
+ char c; // temporary character storage
bool unique = false;
long deleted;
colnr_T start_col;
@@ -488,8 +475,9 @@ 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 (p = eap->arg; *p != NUL; p++) {
if (ascii_iswhite(*p)) {
+ // Skip
} else if (*p == 'i') {
sort_ic = true;
} else if (*p == 'l') {
@@ -516,11 +504,11 @@ void ex_sort(exarg_T *eap)
} else if (*p == '"') {
// comment start
break;
- } else if (check_nextcmd(p) != NULL) {
- eap->nextcmd = check_nextcmd(p);
+ } else if (check_nextcmd((char_u *)p) != NULL) {
+ eap->nextcmd = (char *)check_nextcmd((char_u *)p);
break;
} else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) {
- s = skip_regexp(p + 1, *p, true, NULL);
+ s = (char *)skip_regexp((char_u *)p + 1, *p, true, NULL);
if (*s != *p) {
emsg(_(e_invalpat));
goto sortend;
@@ -532,7 +520,7 @@ void ex_sort(exarg_T *eap)
emsg(_(e_noprevre));
goto sortend;
}
- regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
+ regmatch.regprog = vim_regcomp((char *)last_search_pat(), RE_MAGIC);
} else {
regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
}
@@ -563,8 +551,8 @@ 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);
+ for (lnum = eap->line1; lnum <= eap->line2; lnum++) {
+ s = (char *)ml_get(lnum);
len = (int)STRLEN(s);
if (maxlen < len) {
maxlen = len;
@@ -574,10 +562,10 @@ void ex_sort(exarg_T *eap)
end_col = len;
if (regmatch.regprog != NULL && vim_regexec(&regmatch, s, 0)) {
if (sort_rx) {
- start_col = (colnr_T)(regmatch.startp[0] - s);
- end_col = (colnr_T)(regmatch.endp[0] - s);
+ start_col = (colnr_T)(regmatch.startp[0] - (char_u *)s);
+ end_col = (colnr_T)(regmatch.endp[0] - (char_u *)s);
} else {
- start_col = (colnr_T)(regmatch.endp[0] - s);
+ start_col = (colnr_T)(regmatch.endp[0] - (char_u *)s);
}
} else if (regmatch.regprog != NULL) {
end_col = 0;
@@ -593,11 +581,11 @@ void ex_sort(exarg_T *eap)
p = s + start_col;
if (sort_nr) {
if (sort_what & STR2NR_HEX) {
- s = skiptohex(p);
+ s = (char *)skiptohex((char_u *)p);
} else if (sort_what & STR2NR_BIN) {
- s = (char_u *)skiptobin((char *)p);
+ s = (char *)skiptobin(p);
} else {
- s = skiptodigit(p);
+ s = (char *)skiptodigit((char_u *)p);
}
if (s > p && s[-1] == '-') {
s--; // include preceding negative sign
@@ -608,7 +596,7 @@ void ex_sort(exarg_T *eap)
nrs[lnum - eap->line1].st_u.num.value = 0;
} else {
nrs[lnum - eap->line1].st_u.num.is_number = true;
- vim_str2nr(s, NULL, NULL, sort_what,
+ vim_str2nr((char_u *)s, NULL, NULL, sort_what,
&nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false);
}
} else {
@@ -621,7 +609,7 @@ void ex_sort(exarg_T *eap)
// empty line should sort before any number
nrs[lnum - eap->line1].st_u.value_flt = -DBL_MAX;
} else {
- nrs[lnum - eap->line1].st_u.value_flt = strtod((char *)s, NULL);
+ nrs[lnum - eap->line1].st_u.value_flt = strtod(s, NULL);
}
}
*s2 = c;
@@ -642,8 +630,8 @@ void ex_sort(exarg_T *eap)
}
// Allocate a buffer that can hold the longest line.
- sortbuf1 = xmalloc(maxlen + 1);
- sortbuf2 = xmalloc(maxlen + 1);
+ sortbuf1 = xmalloc((size_t)maxlen + 1);
+ sortbuf2 = xmalloc((size_t)maxlen + 1);
// Sort the array of line numbers. Note: can't be interrupted!
qsort((void *)nrs, count, sizeof(sorti_T), sort_compare);
@@ -665,9 +653,9 @@ void ex_sort(exarg_T *eap)
change_occurred = true;
}
- s = ml_get(get_lnum);
+ s = (char *)ml_get(get_lnum);
size_t bytelen = STRLEN(s) + 1; // include EOL in bytelen
- old_count += 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".
@@ -675,7 +663,7 @@ void ex_sort(exarg_T *eap)
if (ml_append(lnum++, sortbuf1, (colnr_T)0, false) == FAIL) {
break;
}
- new_count += bytelen;
+ new_count += (bcount_t)bytelen;
}
fast_breakcheck();
if (got_int) {
@@ -693,21 +681,21 @@ void ex_sort(exarg_T *eap)
}
// Adjust marks for deleted (or added) lines and prepare for displaying.
- deleted = (long)(count - (lnum - eap->line2));
+ deleted = (long)count - (lnum - eap->line2);
if (deleted > 0) {
- mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted,
+ mark_adjust(eap->line2 - (linenr_T)deleted, eap->line2, (long)MAXLNUM, (linenr_T)(-deleted),
kExtmarkNOOP);
msgmore(-deleted);
} else if (deleted < 0) {
- mark_adjust(eap->line2, MAXLNUM, -deleted, 0L, kExtmarkNOOP);
+ mark_adjust(eap->line2, MAXLNUM, (linenr_T)(-deleted), 0L, kExtmarkNOOP);
}
if (change_occurred || deleted != 0) {
- extmark_splice(curbuf, eap->line1-1, 0,
- count, 0, old_count,
+ extmark_splice(curbuf, eap->line1 - 1, 0,
+ (int)count, 0, old_count,
lnum - eap->line2, 0, new_count, kExtmarkUndo);
- changed_lines(eap->line1, 0, eap->line2 + 1, -deleted, true);
+ changed_lines(eap->line1, 0, eap->line2 + 1, (linenr_T)(-deleted), true);
}
curwin->w_cursor.lnum = eap->line1;
@@ -723,9 +711,7 @@ sortend:
}
}
-/*
- * ":retab".
- */
+/// ":retab".
void ex_retab(exarg_T *eap)
{
linenr_T lnum;
@@ -738,11 +724,11 @@ void ex_retab(exarg_T *eap)
long start_col = 0; // For start of white-space string
long start_vcol = 0; // For start of white-space string
long old_len;
- char_u *ptr;
- char_u *new_line = (char_u *)1; // init to non-NULL
+ char *ptr;
+ char *new_line = (char *)1; // init to non-NULL
bool did_undo; // called u_save for current line
long *new_vts_array = NULL;
- char_u *new_ts_str; // string value of tab argument
+ char *new_ts_str; // string value of tab argument
int save_list;
linenr_T first_line = 0; // first changed line
@@ -752,7 +738,7 @@ void ex_retab(exarg_T *eap)
curwin->w_p_list = 0; // don't want list mode here
new_ts_str = eap->arg;
- if (!tabstop_set(eap->arg, &new_vts_array)) {
+ if (!tabstop_set((char_u *)eap->arg, &new_vts_array)) {
return;
}
while (ascii_isdigit(*(eap->arg)) || *(eap->arg) == ',') {
@@ -766,10 +752,10 @@ void ex_retab(exarg_T *eap)
new_vts_array = curbuf->b_p_vts_array;
new_ts_str = NULL;
} else {
- new_ts_str = vim_strnsave(new_ts_str, eap->arg - new_ts_str);
+ new_ts_str = xstrnsave(new_ts_str, (size_t)(eap->arg - new_ts_str));
}
for (lnum = eap->line1; !got_int && lnum <= eap->line2; lnum++) {
- ptr = ml_get(lnum);
+ ptr = (char *)ml_get(lnum);
col = 0;
vcol = 0;
did_undo = false;
@@ -795,7 +781,7 @@ void ex_retab(exarg_T *eap)
if (!curbuf->b_p_et) {
int t, s;
- tabstop_fromto(start_vcol, vcol,
+ tabstop_fromto((colnr_T)start_vcol, (colnr_T)vcol,
curbuf->b_p_ts, new_vts_array, &t, &s);
num_tabs = t;
num_spaces = s;
@@ -814,8 +800,12 @@ 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;
- new_line = xmalloc(new_len);
+ 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((size_t)new_len);
if (start_col > 0) {
memmove(new_line, ptr, (size_t)start_col);
@@ -828,7 +818,7 @@ void ex_retab(exarg_T *eap)
}
if (ml_replace(lnum, new_line, false) == OK) {
// "new_line" may have been copied
- new_line = curbuf->b_ml.ml_line_ptr;
+ new_line = (char *)curbuf->b_ml.ml_line_ptr;
extmark_splice_cols(curbuf, lnum - 1, 0, (colnr_T)old_len,
(colnr_T)new_len - 1, kExtmarkUndo);
}
@@ -846,7 +836,11 @@ void ex_retab(exarg_T *eap)
if (ptr[col] == NUL) {
break;
}
- vcol += win_chartabsize(curwin, ptr + col, (colnr_T)vcol);
+ vcol += win_chartabsize(curwin, (char_u *)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
@@ -882,8 +876,7 @@ void ex_retab(exarg_T *eap)
long *old_vts_ary = curbuf->b_p_vts_array;
if (tabstop_count(old_vts_ary) > 0 || tabstop_count(new_vts_array) > 1) {
- set_string_option_direct("vts", -1, new_ts_str,
- OPT_FREE | OPT_LOCAL, 0);
+ set_string_option_direct("vts", -1, new_ts_str, OPT_FREE | OPT_LOCAL, 0);
curbuf->b_p_vts_array = new_vts_array;
xfree(old_vts_ary);
} else {
@@ -899,14 +892,12 @@ void ex_retab(exarg_T *eap)
u_clearline();
}
-/*
- * :move command - move lines line1-line2 to line dest
- *
- * return FAIL for failure, OK otherwise
- */
+/// :move command - move lines line1-line2 to line dest
+///
+/// @return FAIL for failure, OK otherwise
int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
{
- char_u *str;
+ char *str;
linenr_T l;
linenr_T extra; // Num lines added before line1
linenr_T num_lines; // Num lines moved
@@ -931,9 +922,9 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
}
bcount_t start_byte = ml_find_line_or_offset(curbuf, line1, NULL, true);
- bcount_t end_byte = ml_find_line_or_offset(curbuf, line2+1, NULL, true);
- bcount_t extent_byte = end_byte-start_byte;
- bcount_t dest_byte = ml_find_line_or_offset(curbuf, dest+1, NULL, true);
+ bcount_t end_byte = ml_find_line_or_offset(curbuf, line2 + 1, NULL, true);
+ bcount_t extent_byte = end_byte - start_byte;
+ bcount_t dest_byte = ml_find_line_or_offset(curbuf, dest + 1, NULL, true);
num_lines = line2 - line1 + 1;
@@ -945,7 +936,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
return FAIL;
}
for (extra = 0, l = line1; l <= line2; l++) {
- str = vim_strsave(ml_get(l + extra));
+ str = (char *)vim_strsave(ml_get(l + extra));
ml_append(dest + l - line1, str, (colnr_T)0, false);
xfree(str);
if (dest < line1) {
@@ -970,7 +961,11 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
*/
last_line = curbuf->b_ml.ml_line_count;
mark_adjust_nofold(line1, line2, last_line - line2, 0L, kExtmarkNOOP);
+
+ disable_fold_update++;
changed_lines(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) {
@@ -980,8 +975,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.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ 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,17 +988,23 @@ 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.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ curbuf->b_op_start.lnum = dest + 1;
+ curbuf->b_op_end.lnum = dest + num_lines;
+ }
+ }
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ 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);
+ disable_fold_update++;
changed_lines(last_line - num_lines + 1, 0, last_line + 1, -extra, false);
+ disable_fold_update--;
// send update regarding the new lines that were added
- buf_updates_send_changes(curbuf, dest + 1, num_lines, 0, true);
+ buf_updates_send_changes(curbuf, dest + 1, num_lines, 0);
/*
* Now we delete the original text -- webb
@@ -1017,9 +1020,9 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
smsg(NGETTEXT("1 line moved", "%" PRId64 " lines moved", num_lines), (int64_t)num_lines);
}
- extmark_move_region(curbuf, line1-1, 0, start_byte,
- line2-line1+1, 0, extent_byte,
- dest+line_off, 0, dest_byte+byte_off,
+ extmark_move_region(curbuf, line1 - 1, 0, start_byte,
+ line2 - line1 + 1, 0, extent_byte,
+ dest + line_off, 0, dest_byte + byte_off,
kExtmarkUndo);
/*
@@ -1043,23 +1046,23 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
}
// send nvim_buf_lines_event regarding lines that were deleted
- buf_updates_send_changes(curbuf, line1 + extra, 0, num_lines, true);
+ buf_updates_send_changes(curbuf, line1 + extra, 0, num_lines);
return OK;
}
-/*
- * ":copy"
- */
+/// ":copy"
void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
{
linenr_T count;
- char_u *p;
+ char *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.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ 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:
@@ -1080,7 +1083,7 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
while (line1 <= line2) {
// need to use vim_strsave() because the line will be unlocked within
// ml_append()
- p = vim_strsave(ml_get(line1));
+ p = (char *)vim_strsave(ml_get(line1));
ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, false);
xfree(p);
@@ -1099,11 +1102,14 @@ 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);
}
-static char_u *prevcmd = NULL; // the previous command
+static char *prevcmd = NULL; // the previous command
#if defined(EXITFREE)
void free_prev_shellcmd(void)
@@ -1113,23 +1119,21 @@ void free_prev_shellcmd(void)
#endif
-/*
- * 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.
- */
+/// 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.
void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out)
FUNC_ATTR_NONNULL_ALL
{
- char_u *arg = eap->arg; // command
+ char *arg = eap->arg; // command
linenr_T line1 = eap->line1; // start of range
linenr_T line2 = eap->line2; // end of range
- char_u *newcmd = NULL; // the new command
+ char *newcmd = NULL; // the new command
bool free_newcmd = false; // need to free() newcmd
- char_u *t;
- char_u *p;
- char_u *trailarg;
- int len;
+ char *t;
+ char *p;
+ char *trailarg;
+ size_t len;
int scroll_save = msg_scroll;
//
@@ -1153,9 +1157,9 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
bool ins_prevcmd = forceit;
trailarg = arg;
do {
- len = (int)STRLEN(trailarg) + 1;
+ len = STRLEN(trailarg) + 1;
if (newcmd != NULL) {
- len += (int)STRLEN(newcmd);
+ len += STRLEN(newcmd);
}
if (ins_prevcmd) {
if (prevcmd == NULL) {
@@ -1163,7 +1167,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
xfree(newcmd);
return;
}
- len += (int)STRLEN(prevcmd);
+ len += STRLEN(prevcmd);
}
t = xmalloc(len);
*t = NUL;
@@ -1205,7 +1209,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
// If % or # appears in the command, it must have been escaped.
// Reescape them, so that redoing them does not substitute them by the
// buffername.
- char_u *cmd = vim_strsave_escaped(prevcmd, (char_u *)"%#");
+ char *cmd = (char *)vim_strsave_escaped((char_u *)prevcmd, (char_u *)"%#");
AppendToRedobuffLit(cmd, -1);
xfree(cmd);
@@ -1258,23 +1262,29 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
/// We use output redirection if do_out is true.
///
/// @param eap for forced 'ff' and 'fenc'
-static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, bool do_in,
+static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, bool do_in,
bool do_out)
{
- char_u *itmp = NULL;
- char_u *otmp = NULL;
+ char *itmp = NULL;
+ char *otmp = NULL;
linenr_T linecount;
linenr_T read_linecount;
pos_T cursor_save;
- char_u *cmd_buf;
+ char *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 int save_cmod_flags = cmdmod.cmod_flags;
+ // Temporarily disable lockmarks since that's needed to propagate changed
+ // regions of the buffer for foldUpdate(), linecount, etc.
+ cmdmod.cmod_flags &= ~CMOD_LOCKMARKS;
cursor_save = curwin->w_cursor;
linecount = line2 - line1 + 1;
@@ -1316,8 +1326,8 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd,
curbuf->b_op_start.lnum = line1;
curbuf->b_op_end.lnum = line2;
curwin->w_cursor.lnum = line2;
- } else if ((do_in && (itmp = vim_tempname()) == NULL)
- || (do_out && (otmp = vim_tempname()) == NULL)) {
+ } else if ((do_in && (itmp = (char *)vim_tempname()) == NULL)
+ || (do_out && (otmp = (char *)vim_tempname()) == NULL)) {
emsg(_(e_notmp));
goto filterend;
}
@@ -1326,7 +1336,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd,
* The writing and reading of temp files will not be shown.
* Vi also doesn't do this and the messages are not very informative.
*/
- ++no_wait_return; // don't call wait_return() while busy
+ no_wait_return++; // don't call wait_return() while busy
if (itmp != NULL && buf_write(curbuf, itmp, NULL, line1, line2, eap,
false, false, false, true) == FAIL) {
msg_putchar('\n'); // Keep message from buf_write().
@@ -1349,7 +1359,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;
}
@@ -1358,7 +1368,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd,
read_linecount = curbuf->b_ml.ml_line_count;
// Pass on the kShellOptDoOut flag when the output is being redirected.
- call_shell(cmd_buf, kShellOptFilter | shell_flags, NULL);
+ call_shell((char_u *)cmd_buf, (ShellOpts)(kShellOptFilter | shell_flags), NULL);
xfree(cmd_buf);
did_check_timestamps = FALSE;
@@ -1373,7 +1383,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd,
if (do_out) {
if (otmp != NULL) {
if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, eap,
- READ_FILTER) != OK) {
+ READ_FILTER, false) != OK) {
if (!aborting()) {
msg_putchar('\n');
semsg(_(e_notread), otmp);
@@ -1394,7 +1404,8 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd,
}
if (do_in) {
- if (cmdmod.keepmarks || vim_strchr(p_cpo, CPO_REMMARK) == NULL) {
+ if ((cmdmod.cmod_flags & CMOD_KEEPMARKS)
+ || vim_strchr(p_cpo, CPO_REMMARK) == NULL) {
// TODO(bfredl): Currently not active for extmarks. What would we
// do if columns don't match, assume added/deleted bytes at the
// end of each line?
@@ -1455,15 +1466,20 @@ error:
filterend:
+ cmdmod.cmod_flags = save_cmod_flags;
if (curbuf != old_curbuf) {
no_wait_return--;
emsg(_("E135: *Filter* Autocommands must not change current buffer"));
+ } else if (cmdmod.cmod_flags & CMOD_LOCKMARKS) {
+ curbuf->b_op_start = orig_start;
+ curbuf->b_op_end = orig_end;
}
+
if (itmp != NULL) {
- os_remove((char *)itmp);
+ os_remove(itmp);
}
if (otmp != NULL) {
- os_remove((char *)otmp);
+ os_remove(otmp);
}
xfree(itmp);
xfree(otmp);
@@ -1473,7 +1489,7 @@ filterend:
/// When "cmd" is NULL start an interactive shell.
///
/// @param flags may be SHELL_DOOUT when output is redirected
-void do_shell(char_u *cmd, int flags)
+void do_shell(char *cmd, int flags)
{
// Disallow shell commands from .exrc and .vimrc in current directory for
// security reasons.
@@ -1482,7 +1498,6 @@ void do_shell(char_u *cmd, int flags)
return;
}
-
/*
* For autocommands we want to get the output on the current screen, to
* avoid having to type return below.
@@ -1505,7 +1520,7 @@ void do_shell(char_u *cmd, int flags)
// This ui_cursor_goto is required for when the '\n' resulted in a "delete line
// 1" command to the terminal.
ui_cursor_goto(msg_row, msg_col);
- (void)call_shell(cmd, flags, NULL);
+ (void)call_shell((char_u *)cmd, (ShellOpts)flags, NULL);
msg_didout = true;
did_check_timestamps = false;
need_check_timestamps = true;
@@ -1544,7 +1559,7 @@ static char *find_pipe(const char *cmd)
/// @param itmp NULL or the input file.
/// @param otmp NULL or the output file.
/// @returns an allocated string with the shell command.
-char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
+char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
{
bool is_fish_shell =
#if defined(UNIX)
@@ -1552,14 +1567,18 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
#else
false;
#endif
+ 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.
len += is_fish_shell ? sizeof("begin; " "; end") - 1
- : sizeof("(" ")") - 1;
+ : is_pwsh ? sizeof("Start-Process ")
+ : sizeof("(" ")") - 1;
if (itmp != NULL) {
- len += STRLEN(itmp) + sizeof(" { " " < " " } ") - 1;
+ len += is_pwsh ? STRLEN(itmp) + sizeof(" -RedirectStandardInput ")
+ : STRLEN(itmp) + sizeof(" { " " < " " } ") - 1;
}
if (otmp != NULL) {
len += STRLEN(otmp) + STRLEN(p_srr) + 2; // two extra spaces (" "),
@@ -1569,22 +1588,34 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
#if defined(UNIX)
// Put delimiters around the command (for concatenated commands) when
// redirecting input and/or output.
- if (itmp != NULL || otmp != NULL) {
+ if (is_pwsh) {
+ xstrlcpy(buf, "Start-Process ", len);
+ xstrlcat(buf, cmd, len);
+ } else if (itmp != NULL || otmp != NULL) {
char *fmt = is_fish_shell ? "begin; %s; end"
: "(%s)";
- vim_snprintf(buf, len, fmt, (char *)cmd);
+ vim_snprintf(buf, len, fmt, cmd);
} else {
- xstrlcpy(buf, (char *)cmd, len);
+ xstrlcpy(buf, cmd, len);
}
if (itmp != NULL) {
- xstrlcat(buf, " < ", len - 1);
- xstrlcat(buf, (const char *)itmp, len - 1);
+ if (is_pwsh) {
+ xstrlcat(buf, " -RedirectStandardInput ", len - 1);
+ } else {
+ xstrlcat(buf, " < ", len - 1);
+ }
+ xstrlcat(buf, itmp, len - 1);
}
#else
// For shells that don't understand braces around commands, at least allow
// the use of commands in a pipe.
- xstrlcpy(buf, (char *)cmd, len);
+ if (is_pwsh) {
+ xstrlcpy(buf, "Start-Process ", len);
+ xstrlcat(buf, cmd, len);
+ } else {
+ xstrlcpy(buf, cmd, len);
+ }
if (itmp != NULL) {
// If there is a pipe, we have to put the '<' in front of it.
// Don't do this when 'shellquote' is not empty, otherwise the
@@ -1595,10 +1626,14 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
*p = NUL;
}
}
- xstrlcat(buf, " < ", len);
- xstrlcat(buf, (const char *)itmp, len);
+ if (is_pwsh) {
+ xstrlcat(buf, " -RedirectStandardInput ", len);
+ } else {
+ xstrlcat(buf, " < ", 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);
@@ -1607,9 +1642,9 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
}
#endif
if (otmp != NULL) {
- append_redir(buf, len, (char *)p_srr, (char *)otmp);
+ append_redir(buf, len, (char *)p_srr, otmp);
}
- return (char_u *)buf;
+ return buf;
}
/// Append output redirection for the given file to the end of the buffer
@@ -1636,9 +1671,9 @@ void append_redir(char *const buf, const size_t buflen, const char *const opt,
}
if (p != NULL) {
*end = ' '; // not really needed? Not with sh, ksh or bash
- vim_snprintf(end + 1, (size_t)(buflen - (end + 1 - buf)), opt, fname);
+ vim_snprintf(end + 1, (size_t)((ptrdiff_t)buflen - (end + 1 - buf)), opt, fname);
} else {
- vim_snprintf(end, (size_t)(buflen - (end - buf)), " %s %s", opt, fname);
+ vim_snprintf(end, (size_t)((ptrdiff_t)buflen - (end - buf)), " %s %s", opt, fname);
}
}
@@ -1654,9 +1689,7 @@ void print_line_no_prefix(linenr_T lnum, int use_number, int list)
msg_prt_line(ml_get(lnum), list);
}
-/*
- * Print a text line. Also in silent mode ("ex -s").
- */
+/// Print a text line. Also in silent mode ("ex -s").
void print_line(linenr_T lnum, int use_number, int list)
{
int save_silent = silent_mode;
@@ -1678,9 +1711,9 @@ void print_line(linenr_T lnum, int use_number, int list)
info_message = false;
}
-int rename_buffer(char_u *new_fname)
+int rename_buffer(char *new_fname)
{
- char_u *fname, *sfname, *xfname;
+ char *fname, *sfname, *xfname;
buf_T *buf;
buf = curbuf;
@@ -1712,7 +1745,7 @@ int rename_buffer(char_u *new_fname)
curbuf->b_flags |= BF_NOTEDITED;
if (xfname != NULL && *xfname != NUL) {
buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, 0);
- if (buf != NULL && !cmdmod.keepalt) {
+ if (buf != NULL && (cmdmod.cmod_flags & CMOD_KEEPALT) == 0) {
curwin->w_alt_fnum = buf->b_fnum;
}
}
@@ -1724,9 +1757,7 @@ int rename_buffer(char_u *new_fname)
return OK;
}
-/*
- * ":file[!] [fname]".
- */
+/// ":file[!] [fname]".
void ex_file(exarg_T *eap)
{
// ":0file" removes the file name. Check for illegal uses ":3file",
@@ -1752,9 +1783,7 @@ void ex_file(exarg_T *eap)
}
}
-/*
- * ":update".
- */
+/// ":update".
void ex_update(exarg_T *eap)
{
if (curbufIsChanged()) {
@@ -1762,9 +1791,7 @@ void ex_update(exarg_T *eap)
}
}
-/*
- * ":write" and ":saveas".
- */
+/// ":write" and ":saveas".
void ex_write(exarg_T *eap)
{
if (eap->cmdidx == CMD_saveas) {
@@ -1780,21 +1807,19 @@ void ex_write(exarg_T *eap)
}
}
-/*
- * write current buffer to file 'eap->arg'
- * if 'eap->append' is TRUE, append to the file
- *
- * if *eap->arg == NUL write to current file
- *
- * return FAIL for failure, OK otherwise
- */
+/// write current buffer to file 'eap->arg'
+/// if 'eap->append' is TRUE, append to the file
+///
+/// if *eap->arg == NUL write to current file
+///
+/// @return FAIL for failure, OK otherwise
int do_write(exarg_T *eap)
{
int other;
- char_u *fname = NULL; // init to shut up gcc
- char_u *ffname;
+ char *fname = NULL; // init to shut up gcc
+ char *ffname;
int retval = FAIL;
- char_u *free_fname = NULL;
+ char *free_fname = NULL;
buf_T *alt_buf = NULL;
int name_was_missing;
@@ -1811,11 +1836,9 @@ int do_write(exarg_T *eap)
other = FALSE;
} else {
fname = ffname;
- free_fname = (char_u *)fix_fname((char *)ffname);
- /*
- * When out-of-memory, keep unexpanded file name, because we MUST be
- * able to write the file in this situation.
- */
+ free_fname = fix_fname(ffname);
+ // When out-of-memory, keep unexpanded file name, because we MUST be
+ // able to write the file in this situation.
if (free_fname != NULL) {
ffname = free_fname;
}
@@ -1852,15 +1875,13 @@ int do_write(exarg_T *eap)
if (!other) {
ffname = curbuf->b_ffname;
fname = curbuf->b_fname;
- /*
- * Not writing the whole file is only allowed with '!'.
- */
+ // Not writing the whole file is only allowed with '!'.
if ((eap->line1 != 1
|| eap->line2 != curbuf->b_ml.ml_line_count)
&& !eap->forceit
&& !eap->append
&& !p_wa) {
- if (p_confirm || cmdmod.confirm) {
+ if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
if (vim_dialog_yesno(VIM_QUESTION, NULL,
(char_u *)_("Write partial file?"), 2) != VIM_YES) {
goto theend;
@@ -1913,8 +1934,8 @@ int do_write(exarg_T *eap)
// If 'filetype' was empty try detecting it now.
if (*curbuf->b_p_ft == NUL) {
- if (au_has_group((char_u *)"filetypedetect")) {
- (void)do_doautocmd((char_u *)"filetypedetect BufRead", true, NULL);
+ if (augroup_exists("filetypedetect")) {
+ (void)do_doautocmd("filetypedetect BufRead", true, NULL);
}
do_modelines(0);
}
@@ -1926,7 +1947,7 @@ int do_write(exarg_T *eap)
name_was_missing = curbuf->b_ffname == NULL;
retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
- eap, eap->append, eap->forceit, TRUE, FALSE);
+ eap, eap->append, eap->forceit, true, false);
// After ":saveas fname" reset 'readonly'.
if (eap->cmdidx == CMD_saveas) {
@@ -1957,33 +1978,30 @@ theend:
/// @param other writing under other name
///
/// @return OK if it's OK, FAIL if it is not.
-int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int other)
+int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int other)
{
- /*
- * write to other file or b_flags set or not writing the whole file:
- * overwriting only allowed with '!'
- */
+ // Write to another file or b_flags set or not writing the whole file:
+ // overwriting only allowed with '!'
if ((other
|| (buf->b_flags & BF_NOTEDITED)
|| ((buf->b_flags & BF_NEW)
&& vim_strchr(p_cpo, CPO_OVERNEW) == NULL)
|| (buf->b_flags & BF_READERR))
&& !p_wa
- && !bt_nofile(buf)
- && os_path_exists(ffname)) {
+ && os_path_exists((char_u *)ffname)) {
if (!eap->forceit && !eap->append) {
#ifdef UNIX
// It is possible to open a directory on Unix.
- if (os_isdir(ffname)) {
+ if (os_isdir((char_u *)ffname)) {
semsg(_(e_isadir2), ffname);
return FAIL;
}
#endif
- if (p_confirm || cmdmod.confirm) {
- char_u buff[DIALOG_MSG_SIZE];
+ if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
+ char buff[DIALOG_MSG_SIZE];
- dialog_msg(buff, _("Overwrite existing file \"%s\"?"), fname);
- if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES) {
+ dialog_msg((char *)buff, _("Overwrite existing file \"%s\"?"), fname);
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)buff, 2) != VIM_YES) {
return FAIL;
}
eap->forceit = TRUE;
@@ -1995,9 +2013,9 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int
// For ":w! filename" check that no swap file exists for "filename".
if (other && !emsg_silent) {
- char_u *dir;
- char_u *p;
- char_u *swapname;
+ char *dir;
+ char *p;
+ char *swapname;
// We only try the first entry in 'directory', without checking if
// it's writable. If the "." directory is not writable the write
@@ -2009,19 +2027,19 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int
STRCPY(dir, ".");
} else {
dir = xmalloc(MAXPATHL);
- p = p_dir;
+ p = (char *)p_dir;
copy_option_part(&p, dir, MAXPATHL, ",");
}
- swapname = makeswapname(fname, ffname, curbuf, dir);
+ swapname = (char *)makeswapname((char_u *)fname, (char_u *)ffname, curbuf, (char_u *)dir);
xfree(dir);
- if (os_path_exists(swapname)) {
- if (p_confirm || cmdmod.confirm) {
- char_u buff[DIALOG_MSG_SIZE];
+ if (os_path_exists((char_u *)swapname)) {
+ if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
+ char buff[DIALOG_MSG_SIZE];
- dialog_msg(buff,
+ dialog_msg((char *)buff,
_("Swap file \"%s\" exists, overwrite anyway?"),
swapname);
- if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2)
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)buff, 2)
!= VIM_YES) {
xfree(swapname);
return FAIL;
@@ -2040,9 +2058,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int
return OK;
}
-/*
- * Handle ":wnext", ":wNext" and ":wprevious" commands.
- */
+/// Handle ":wnext", ":wNext" and ":wprevious" commands.
void ex_wnext(exarg_T *eap)
{
int i;
@@ -2059,9 +2075,7 @@ void ex_wnext(exarg_T *eap)
}
}
-/*
- * ":wall", ":wqall" and ":xall": Write all changed files (and exit).
- */
+/// ":wall", ":wqall" and ":xall": Write all changed files (and exit).
void do_wqall(exarg_T *eap)
{
int error = 0;
@@ -2095,9 +2109,8 @@ void do_wqall(exarg_T *eap)
semsg(_("E141: No file name for buffer %" PRId64), (int64_t)buf->b_fnum);
error++;
} else if (check_readonly(&eap->forceit, buf)
- || check_overwrite(eap, buf, buf->b_fname, buf->b_ffname,
- FALSE) == FAIL) {
- ++error;
+ || check_overwrite(eap, buf, buf->b_fname, buf->b_ffname, false) == FAIL) {
+ error++;
} else {
bufref_T bufref;
set_bufref(&bufref, buf);
@@ -2119,8 +2132,9 @@ void do_wqall(exarg_T *eap)
}
}
-// Check the 'write' option.
-// Return true and give a message when it's not st.
+/// Check the 'write' option.
+///
+/// @return true and give a message when it's not st.
bool not_writing(void)
{
if (p_write) {
@@ -2130,33 +2144,31 @@ bool not_writing(void)
return true;
}
-/*
- * Check if a buffer is read-only (either 'readonly' option is set or file is
- * read-only). Ask for overruling in a dialog. Return TRUE and give an error
- * message when the buffer is readonly.
- */
+/// Check if a buffer is read-only (either 'readonly' option is set or file is
+/// read-only). Ask for overruling in a dialog. Return TRUE and give an error
+/// message when the buffer is readonly.
static int check_readonly(int *forceit, buf_T *buf)
{
// Handle a file being readonly when the 'readonly' option is set or when
// the file exists and permissions are read-only.
if (!*forceit && (buf->b_p_ro
- || (os_path_exists(buf->b_ffname)
- && !os_file_is_writable((char *)buf->b_ffname)))) {
- if ((p_confirm || cmdmod.confirm) && buf->b_fname != NULL) {
- char_u buff[DIALOG_MSG_SIZE];
+ || (os_path_exists((char_u *)buf->b_ffname)
+ && !os_file_is_writable(buf->b_ffname)))) {
+ if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && buf->b_fname != NULL) {
+ char buff[DIALOG_MSG_SIZE];
if (buf->b_p_ro) {
- dialog_msg(buff,
+ dialog_msg((char *)buff,
_("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"),
buf->b_fname);
} else {
- dialog_msg(buff,
- _(
- "File permissions of \"%s\" are read-only.\nIt may still be possible to write it.\nDo you wish to try?"),
+ dialog_msg((char *)buff,
+ _("File permissions of \"%s\" are read-only.\nIt may still be possible to "
+ "write it.\nDo you wish to try?"),
buf->b_fname);
}
- if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) == VIM_YES) {
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)buff, 2) == VIM_YES) {
// Set forceit, to force the writing of a readonly file
*forceit = TRUE;
return FALSE;
@@ -2175,22 +2187,23 @@ static int check_readonly(int *forceit, buf_T *buf)
return FALSE;
}
-// Try to abandon the current file and edit a new or existing file.
-// "fnum" is the number of the file, if zero use "ffname_arg"/"sfname_arg".
-// "lnum" is the line number for the cursor in the new file (if non-zero).
-//
-// Return:
-// GETFILE_ERROR for "normal" error,
-// GETFILE_NOT_WRITTEN for "not written" error,
-// GETFILE_SAME_FILE for success
-// GETFILE_OPEN_OTHER for successfully opening another file.
-int getfile(int fnum, char_u *ffname_arg, char_u *sfname_arg, int setpm, linenr_T lnum, int forceit)
+/// Try to abandon the current file and edit a new or existing file.
+///
+/// @param fnum the number of the file, if zero use "ffname_arg"/"sfname_arg".
+/// @param lnum the line number for the cursor in the new file (if non-zero).
+///
+/// @return:
+/// GETFILE_ERROR for "normal" error,
+/// GETFILE_NOT_WRITTEN for "not written" error,
+/// GETFILE_SAME_FILE for success
+/// GETFILE_OPEN_OTHER for successfully opening another file.
+int getfile(int fnum, char *ffname_arg, char *sfname_arg, int setpm, linenr_T lnum, int forceit)
{
- char_u *ffname = ffname_arg;
- char_u *sfname = sfname_arg;
+ char *ffname = ffname_arg;
+ char *sfname = sfname_arg;
int other;
int retval;
- char_u *free_me = NULL;
+ char *free_me = NULL;
if (text_locked()) {
return GETFILE_ERROR;
@@ -2279,19 +2292,19 @@ theend:
/// info of the previous buffer for "oldwin" is stored.
///
/// @return FAIL for failure, OK otherwise
-int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T newlnum, int flags,
+int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum, int flags,
win_T *oldwin)
{
bool other_file; // true if editing another file
int oldbuf; // TRUE if using existing buffer
bool auto_buf = false; // true if autocommands brought us
// into the buffer unexpectedly
- char_u *new_name = NULL;
+ char *new_name = NULL;
bool did_set_swapcommand = false;
buf_T *buf;
bufref_T bufref;
bufref_T old_curbuf;
- char_u *free_fname = NULL;
+ char *free_fname = NULL;
int retval = FAIL;
long n;
pos_T orig_pos;
@@ -2299,7 +2312,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
int newcol = -1;
int solcol = -1;
pos_T *pos;
- char_u *command = NULL;
+ char *command = NULL;
bool did_get_winopts = false;
int readfile_flags = 0;
bool did_inc_redrawing_disabled = false;
@@ -2341,7 +2354,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
ffname = curbuf->b_ffname;
sfname = curbuf->b_fname;
}
- free_fname = (char_u *)fix_fname((char *)ffname); // may expand to full path name
+ free_fname = fix_fname(ffname); // may expand to full path name
if (free_fname != NULL) {
ffname = free_fname;
}
@@ -2399,8 +2412,10 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
* Otherwise we re-use the current buffer.
*/
if (other_file) {
+ const int prev_alt_fnum = curwin->w_alt_fnum;
+
if (!(flags & (ECMD_ADDBUF | ECMD_ALTBUF))) {
- if (!cmdmod.keepalt) {
+ if ((cmdmod.cmod_flags & CMOD_KEEPALT) == 0) {
curwin->w_alt_fnum = curbuf->b_fnum;
}
if (oldwin != NULL) {
@@ -2417,7 +2432,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
linenr_T tlnum = 0;
if (command != NULL) {
- tlnum = atol((char *)command);
+ tlnum = (linenr_T)atol(command);
if (tlnum <= 0) {
tlnum = 1L;
}
@@ -2442,6 +2457,10 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
if (buf == NULL) {
goto theend;
}
+ if (curwin->w_alt_fnum == buf->b_fnum && prev_alt_fnum != 0) {
+ // reusing the buffer, keep the old alternate file
+ curwin->w_alt_fnum = prev_alt_fnum;
+ }
if (buf->b_ml.ml_mfp == NULL) {
// No memfile yet.
oldbuf = false;
@@ -2464,7 +2483,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
// 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_findfpos(buf);
+ pos = &buflist_findfmark(buf)->mark;
newlnum = pos->lnum;
solcol = pos->col;
}
@@ -2490,18 +2509,21 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
// - If we ended up in the new buffer already, need to skip a few
// things, set auto_buf.
if (buf->b_fname != NULL) {
- new_name = vim_strsave(buf->b_fname);
+ new_name = xstrdup(buf->b_fname);
}
+ const bufref_T save_au_new_curbuf = au_new_curbuf;
set_bufref(&au_new_curbuf, buf);
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf);
cmdwin_type = save_cmdwin_type;
if (!bufref_valid(&au_new_curbuf)) {
// New buffer has been deleted.
delbuf_msg(new_name); // Frees new_name.
+ au_new_curbuf = save_au_new_curbuf;
goto theend;
}
if (aborting()) { // autocmds may abort script processing
xfree(new_name);
+ au_new_curbuf = save_au_new_curbuf;
goto theend;
}
if (buf == curbuf) { // already in new buffer
@@ -2522,9 +2544,9 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
// Close the link to the current buffer. This will set
// oldwin->w_buffer to NULL.
u_sync(false);
- const bool did_decrement = close_buffer(oldwin, curbuf,
- (flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD,
- false);
+ const bool did_decrement
+ = close_buffer(oldwin, curbuf, (flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD,
+ false, false);
// Autocommands may have closed the window.
if (win_valid(the_curwin)) {
@@ -2535,12 +2557,14 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
// autocmds may abort script processing
if (aborting() && curwin->w_buffer != NULL) {
xfree(new_name);
+ au_new_curbuf = save_au_new_curbuf;
goto theend;
}
// Be careful again, like above.
if (!bufref_valid(&au_new_curbuf)) {
// New buffer has been deleted.
delbuf_msg(new_name); // Frees new_name.
+ au_new_curbuf = save_au_new_curbuf;
goto theend;
}
if (buf == curbuf) { // already in new buffer
@@ -2580,8 +2604,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
did_get_winopts = true;
}
xfree(new_name);
- au_new_curbuf.br_buf = NULL;
- au_new_curbuf.br_buf_free_count = 0;
+ au_new_curbuf = save_au_new_curbuf;
}
curwin->w_pcmark.lnum = 1;
@@ -2636,7 +2659,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
}
buf = curbuf;
if (buf->b_fname != NULL) {
- new_name = vim_strsave(buf->b_fname);
+ new_name = (char *)vim_strsave((char_u *)buf->b_fname);
} else {
new_name = NULL;
}
@@ -2760,7 +2783,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
// keep it. Also when it moves within a line. But not when it moves
// to the first non-blank.
if (!equalpos(curwin->w_cursor, orig_pos)) {
- const char_u *text = get_cursor_line_ptr();
+ const char *text = (char *)get_cursor_line_ptr();
if (curwin->w_cursor.lnum != orig_pos.lnum
|| curwin->w_cursor.col != (int)(skipwhite(text) - text)) {
@@ -2870,14 +2893,9 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
redraw_curbuf_later(NOT_VALID); // redraw this buffer later
}
- if (p_im) {
- need_start_insertmode = true;
- }
-
// Change directories when the 'acd' option is set.
do_autochdir();
-
theend:
if (bufref_valid(&old_curbuf) && old_curbuf.br_buf->terminal != NULL) {
terminal_check_size(old_curbuf.br_buf->terminal);
@@ -2893,10 +2911,10 @@ theend:
return retval;
}
-static void delbuf_msg(char_u *name)
+static void delbuf_msg(char *name)
{
semsg(_("E143: Autocommands unexpectedly deleted new buffer %s"),
- name == NULL ? (char_u *)"" : name);
+ name == NULL ? "" : name);
xfree(name);
au_new_curbuf.br_buf = NULL;
au_new_curbuf.br_buf_free_count = 0;
@@ -2904,16 +2922,14 @@ static void delbuf_msg(char_u *name)
static int append_indent = 0; // autoindent for first line
-/*
- * ":insert" and ":append", also used by ":change"
- */
+/// ":insert" and ":append", also used by ":change"
void ex_append(exarg_T *eap)
{
- char_u *theline;
+ char *theline;
bool did_undo = false;
linenr_T lnum = eap->line2;
int indent = 0;
- char_u *p;
+ char *p;
int vcol;
int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
@@ -2936,9 +2952,9 @@ void ex_append(exarg_T *eap)
lnum = 0;
}
- State = INSERT; // behave like in Insert mode
+ State = MODE_INSERT; // behave like in Insert mode
if (curbuf->b_p_iminsert == B_IMODE_LMAP) {
- State |= LANGMAP;
+ State |= MODE_LANGMAP;
}
for (;;) {
@@ -2962,18 +2978,17 @@ void ex_append(exarg_T *eap)
if (p == NULL) {
p = eap->nextcmd + STRLEN(eap->nextcmd);
}
- theline = vim_strnsave(eap->nextcmd, p - eap->nextcmd);
+ theline = xstrnsave(eap->nextcmd, (size_t)(p - eap->nextcmd));
if (*p != NUL) {
p++;
}
eap->nextcmd = p;
} else {
- // Set State to avoid the cursor shape to be set to INSERT mode
- // when getline() returns.
int save_State = State;
- State = CMDLINE;
- theline = eap->getline(eap->cstack->cs_looplevel > 0 ? -1 :
- NUL, eap->cookie, indent, true);
+ // Set State to avoid the cursor shape to be set to MODE_INSERT
+ // state when getline() returns.
+ State = MODE_CMDLINE;
+ theline = eap->getline(eap->cstack->cs_looplevel > 0 ? -1 : NUL, eap->cookie, indent, true);
State = save_State;
}
lines_left = Rows - 1;
@@ -3021,7 +3036,7 @@ void ex_append(exarg_T *eap)
empty = 0;
}
}
- State = NORMAL;
+ State = MODE_NORMAL;
if (eap->forceit) {
curbuf->b_p_ai = !curbuf->b_p_ai;
@@ -3031,14 +3046,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.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ 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);
@@ -3047,9 +3063,7 @@ void ex_append(exarg_T *eap)
ex_no_reprint = true;
}
-/*
- * ":change"
- */
+/// ":change"
void ex_change(exarg_T *eap)
{
linenr_T lnum;
@@ -3082,9 +3096,9 @@ void ex_change(exarg_T *eap)
void ex_z(exarg_T *eap)
{
- char_u *x;
+ char *x;
int64_t bigness;
- char_u *kind;
+ char *kind;
int minus = 0;
linenr_T start, end, curs, i;
int j;
@@ -3118,7 +3132,7 @@ void ex_z(exarg_T *eap)
emsg(_("E144: non-numeric argument to :z"));
return;
}
- bigness = atol((char *)x);
+ bigness = atol(x);
// bigness could be < 0 if atol(x) overflows.
if (bigness > 2 * curbuf->b_ml.ml_line_count || bigness < 0) {
@@ -3133,44 +3147,43 @@ void ex_z(exarg_T *eap)
// the number of '-' and '+' multiplies the distance
if (*kind == '-' || *kind == '+') {
- for (x = kind + 1; *x == *kind; x++) {
- }
+ for (x = kind + 1; *x == *kind; x++) {}
}
switch (*kind) {
case '-':
- start = lnum - bigness * (linenr_T)(x - kind) + 1;
- end = start + bigness - 1;
+ start = lnum - (linenr_T)bigness * (linenr_T)(x - kind) + 1;
+ end = start + (linenr_T)bigness - 1;
curs = end;
break;
case '=':
- start = lnum - (bigness + 1) / 2 + 1;
- end = lnum + (bigness + 1) / 2 - 1;
+ start = lnum - ((linenr_T)bigness + 1) / 2 + 1;
+ end = lnum + ((linenr_T)bigness + 1) / 2 - 1;
curs = lnum;
minus = 1;
break;
case '^':
- start = lnum - bigness * 2;
- end = lnum - bigness;
- curs = lnum - bigness;
+ start = lnum - (linenr_T)bigness * 2;
+ end = lnum - (linenr_T)bigness;
+ curs = lnum - (linenr_T)bigness;
break;
case '.':
- start = lnum - (bigness + 1) / 2 + 1;
- end = lnum + (bigness + 1) / 2 - 1;
+ start = lnum - ((linenr_T)bigness + 1) / 2 + 1;
+ end = lnum + ((linenr_T)bigness + 1) / 2 - 1;
curs = end;
break;
default: // '+'
start = lnum;
if (*kind == '+') {
- start += bigness * (linenr_T)(x - kind - 1) + 1;
+ start += (linenr_T)bigness * (linenr_T)(x - kind - 1) + 1;
} else if (eap->addr_count == 0) {
++start;
}
- end = start + bigness - 1;
+ end = start + (linenr_T)bigness - 1;
curs = end;
break;
}
@@ -3216,9 +3229,9 @@ void ex_z(exarg_T *eap)
ex_no_reprint = true;
}
-// Check if the secure flag is set (.exrc or .vimrc in current directory).
-// If so, give an error message and return true.
-// Otherwise, return false.
+/// @return true if the secure flag is set (.exrc or .vimrc in current directory)
+/// and also give an error message.
+/// Otherwise, return false.
bool check_secure(void)
{
if (secure) {
@@ -3274,7 +3287,7 @@ void sub_set_replacement(SubReplacementString sub)
/// @param[in] save Save pattern to options, history
///
/// @returns true if :substitute can be replaced with a join command
-static bool sub_joining_lines(exarg_T *eap, char_u *pat, char_u *sub, char_u *cmd, bool save)
+static bool sub_joining_lines(exarg_T *eap, char *pat, char *sub, char *cmd, bool save)
FUNC_ATTR_NONNULL_ARG(1, 3, 4)
{
// TODO(vim): find a generic solution to make line-joining operations more
@@ -3304,7 +3317,7 @@ static bool sub_joining_lines(exarg_T *eap, char_u *pat, char_u *sub, char_u *cm
// plus one extra line if not at the end of file.
+ (eap->line2 < curbuf->b_ml.ml_line_count ? 1 : 0);
if (joined_lines_count > 1) {
- do_join(joined_lines_count, FALSE, TRUE, FALSE, true);
+ do_join((size_t)joined_lines_count, false, true, false, true);
sub_nsubs = joined_lines_count - 1;
sub_nlines = 1;
do_sub_msg(false);
@@ -3312,10 +3325,10 @@ static bool sub_joining_lines(exarg_T *eap, char_u *pat, char_u *sub, char_u *cm
}
if (save) {
- if (!cmdmod.keeppatterns) {
- save_re_pat(RE_SUBST, pat, p_magic);
+ if ((cmdmod.cmod_flags & CMOD_KEEPPATTERNS) == 0) {
+ save_re_pat(RE_SUBST, (char_u *)pat, p_magic);
}
- add_to_history(HIST_SEARCH, pat, true, NUL);
+ add_to_history(HIST_SEARCH, (char_u *)pat, true, NUL);
}
return true;
@@ -3333,17 +3346,17 @@ static bool sub_joining_lines(exarg_T *eap, char_u *pat, char_u *sub, char_u *cm
/// @param[in] needed_len amount of memory needed
///
/// @returns pointer to the end of the allocated memory
-static char_u *sub_grow_buf(char_u **new_start, int needed_len)
+static char *sub_grow_buf(char **new_start, int needed_len)
FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_RET
{
int new_start_len = 0;
- char_u *new_end;
+ 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(new_start_len);
+ *new_start = xmalloc((size_t)new_start_len);
**new_start = NUL;
new_end = *new_start;
} else {
@@ -3351,10 +3364,10 @@ static char_u *sub_grow_buf(char_u **new_start, int needed_len)
// substitution into. If not, make it larger (with a bit
// extra to avoid too many calls to xmalloc()/free()).
size_t len = STRLEN(*new_start);
- needed_len += len;
+ needed_len += (int)len;
if (needed_len > new_start_len) {
new_start_len = needed_len + 50;
- *new_start = xrealloc(*new_start, new_start_len);
+ *new_start = xrealloc(*new_start, (size_t)new_start_len);
}
new_end = *new_start + len;
}
@@ -3369,7 +3382,7 @@ static char_u *sub_grow_buf(char_u **new_start, int needed_len)
/// @param[in,out] which_pat pattern type from which to get default search
///
/// @returns pointer to the end of the flags, which may be the end of the string
-static char_u *sub_parse_flags(char_u *cmd, subflags_T *subflags, int *which_pat)
+static char *sub_parse_flags(char *cmd, subflags_T *subflags, int *which_pat)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
// Find trailing options. When '&' is used, keep old options.
@@ -3440,8 +3453,8 @@ 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.
-/// @return buffer used for 'inccommand' preview
-static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle_T bufnr)
+/// @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)
{
long i = 0;
regmmatch_T regmatch;
@@ -3455,28 +3468,23 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
.do_number = false,
.do_ic = kSubHonorOptions
};
- char_u *pat = NULL, *sub = NULL; // init for GCC
+ char *pat = NULL, *sub = NULL; // init for GCC
int delimiter;
bool has_second_delim = false;
int sublen;
bool got_quit = false;
bool got_match = false;
int which_pat;
- char_u *cmd = eap->arg;
+ 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 old_line_count = curbuf->b_ml.ml_line_count;
- char_u *sub_firstline; // allocated copy of first sub line
+ 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_src_id = 0; // Source id for the preview highlight
static int pre_hl_id = 0;
- buf_T *orig_buf = curbuf; // save to reset highlighting
pos_T old_cursor = curwin->w_cursor;
- int start_nsubs;
- int save_ma = 0;
- int save_b_changed = curbuf->b_changed;
- bool preview = (State & CMDPREVIEW);
+ long start_nsubs;
bool did_save = false;
@@ -3493,32 +3501,32 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
}
// new pattern and substitution
if (eap->cmd[0] == 's' && *cmd != NUL && !ascii_iswhite(*cmd)
- && vim_strchr((char_u *)"0123456789cegriIp|\"", *cmd) == NULL) {
+ && vim_strchr("0123456789cegriIp|\"", *cmd) == NULL) {
// don't accept alphanumeric for separator
if (check_regexp_delim(*cmd) == FAIL) {
- return NULL;
+ return 0;
}
// undocumented vi feature:
// "\/sub/" and "\?sub?" use last used search pattern (almost like
// //sub/r). "\&sub&" use last substitute pattern (like //sub/).
if (*cmd == '\\') {
- ++cmd;
- if (vim_strchr((char_u *)"/?&", *cmd) == NULL) {
+ cmd++;
+ if (vim_strchr("/?&", *cmd) == NULL) {
emsg(_(e_backslash));
- return NULL;
+ return 0;
}
if (*cmd != '&') {
which_pat = RE_SEARCH; // use last '/' pattern
}
- pat = (char_u *)""; // empty search pattern
- delimiter = *cmd++; // remember delimiter character
+ pat = ""; // empty search pattern
+ delimiter = (char_u)(*cmd++); // remember delimiter character
has_second_delim = true;
} else { // find the end of the regexp
which_pat = RE_LAST; // use last used regexp
- delimiter = *cmd++; // remember delimiter character
+ delimiter = (char_u)(*cmd++); // remember delimiter character
pat = cmd; // remember start of search pat
- cmd = skip_regexp(cmd, delimiter, p_magic, &eap->arg);
+ cmd = (char *)skip_regexp((char_u *)cmd, delimiter, p_magic, (char_u **)&eap->arg);
if (cmd[0] == delimiter) { // end delimiter found
*cmd++ = NUL; // replace it with a NUL
has_second_delim = true;
@@ -3542,9 +3550,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
MB_PTR_ADV(cmd);
}
- if (!eap->skip && !preview) {
+ if (!eap->skip && !cmdpreview) {
sub_set_replacement((SubReplacementString) {
- .sub = xstrdup((char *)sub),
+ .sub = xstrdup(sub),
.timestamp = os_time(),
.additional_elements = NULL,
});
@@ -3552,18 +3560,18 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
} else if (!eap->skip) { // use previous pattern and substitution
if (old_sub.sub == NULL) { // there is no previous command
emsg(_(e_nopresub));
- return NULL;
+ return 0;
}
pat = NULL; // search_regcomp() will use previous pattern
- sub = (char_u *)old_sub.sub;
+ sub = 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, !preview)) {
- return NULL;
+ if (sub != NULL && sub_joining_lines(eap, pat, sub, cmd, !cmdpreview)) {
+ return 0;
}
cmd = sub_parse_flags(cmd, &subflags, &which_pat);
@@ -3574,13 +3582,13 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// check for a trailing count
cmd = skipwhite(cmd);
if (ascii_isdigit(*cmd)) {
- i = getdigits_long(&cmd, true, 0);
+ i = getdigits_long((char_u **)&cmd, true, 0);
if (i <= 0 && !eap->skip && subflags.do_error) {
emsg(_(e_zerocount));
- return NULL;
+ return 0;
}
eap->line1 = eap->line2;
- eap->line2 += i - 1;
+ eap->line2 += (linenr_T)i - 1;
if (eap->line2 > curbuf->b_ml.ml_line_count) {
eap->line2 = curbuf->b_ml.ml_line_count;
}
@@ -3591,29 +3599,29 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
*/
cmd = skipwhite(cmd);
if (*cmd && *cmd != '"') { // if not end-of-line or comment
- eap->nextcmd = check_nextcmd(cmd);
+ eap->nextcmd = (char *)check_nextcmd((char_u *)cmd);
if (eap->nextcmd == NULL) {
emsg(_(e_trailing));
- return NULL;
+ return 0;
}
}
if (eap->skip) { // not executing commands, only parsing
- return NULL;
+ return 0;
}
if (!subflags.do_count && !MODIFIABLE(curbuf)) {
// Substitution is not allowed in non-'modifiable' buffer
emsg(_(e_modifiable));
- return NULL;
+ return 0;
}
- if (search_regcomp(pat, RE_SUBST, which_pat, (preview ? 0 : SEARCH_HIS),
+ if (search_regcomp((char_u *)pat, RE_SUBST, which_pat, (cmdpreview ? 0 : SEARCH_HIS),
&regmatch) == FAIL) {
if (subflags.do_error) {
emsg(_(e_invcmd));
}
- return NULL;
+ return 0;
}
// the 'i' or 'I' flag overrules 'ignorecase' and 'smartcase'
@@ -3625,12 +3633,32 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
sub_firstline = NULL;
- // ~ 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.
- // But don't do it when it starts with "\=", then it's an expression.
assert(sub != NULL);
- if (!(sub[0] == '\\' && sub[1] == '=')) {
- sub = regtilde(sub, p_magic);
+
+ bool sub_needs_free = false;
+ 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;
+ } else {
+ char *source = sub;
+ sub = (char *)regtilde((char_u *)sub, p_magic, cmdpreview);
+ // 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 = cmdpreview && sub != source;
+ }
+
+ bool cmdheight0 = p_ch < 1 && !ui_has(kUIMessages);
+ if (cmdheight0) {
+ // If cmdheight is 0, cmdheight must be set to 1 when we enter command line.
+ set_option_value("ch", 1L, NULL, 0);
+ redraw_statuslines();
}
// Check for a match on each line.
@@ -3639,7 +3667,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
for (linenr_T lnum = eap->line1;
lnum <= line2 && !got_quit && !aborting()
- && (!preview || preview_lines.lines_needed <= (linenr_T)p_cwh
+ && (!cmdpreview || preview_lines.lines_needed <= (linenr_T)p_cwh
|| lnum <= curwin->w_botline);
lnum++) {
long nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
@@ -3648,8 +3676,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
colnr_T copycol;
colnr_T matchcol;
colnr_T prev_matchcol = MAXCOL;
- char_u *new_end, *new_start = NULL;
- char_u *p1;
+ char *new_end, *new_start = NULL;
+ char *p1;
bool did_sub = false;
int lastone;
long nmatch_tl = 0; // nr of lines matched below lnum
@@ -3749,7 +3777,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
break;
}
if (sub_firstline == NULL) {
- sub_firstline = vim_strsave(ml_get(sub_firstlnum));
+ sub_firstline = (char *)vim_strsave(ml_get(sub_firstlnum));
}
// Save the line number of the last change for the final
@@ -3806,13 +3834,13 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
}
}
- if (subflags.do_ask && !preview) {
+ if (subflags.do_ask && !cmdpreview) {
int typed = 0;
- // change State to CONFIRM, so that the mouse works
+ // change State to MODE_CONFIRM, so that the mouse works
// properly
int save_State = State;
- State = CONFIRM;
+ State = MODE_CONFIRM;
setmouse(); // disable mouse in xterm
curwin->w_cursor.col = regmatch.startpos[0].col;
@@ -3823,7 +3851,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// When 'cpoptions' contains "u" don't sync undo when
// asking for confirmation.
if (vim_strchr(p_cpo, CPO_UNDO) != NULL) {
- ++no_u_sync;
+ no_u_sync++;
}
/*
@@ -3832,7 +3860,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
while (subflags.do_ask) {
if (exmode_active) {
char *prompt;
- char_u *resp;
+ char *resp;
colnr_T sc, ec;
print_line_no_prefix(lnum, subflags.do_number, subflags.do_list);
@@ -3843,25 +3871,34 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
curwin->w_cursor.col = 0;
}
getvcol(curwin, &curwin->w_cursor, NULL, NULL, &ec);
+ curwin->w_cursor.col = regmatch.startpos[0].col;
if (subflags.do_number || curwin->w_p_nu) {
int numw = number_width(curwin) + 1;
sc += numw;
ec += numw;
}
- prompt = xmallocz(ec + 1);
- memset(prompt, ' ', sc);
- memset(prompt + sc, '^', ec - sc + 1);
- resp = (char_u *)getcmdline_prompt(NUL, prompt, 0, EXPAND_NOTHING,
- NULL, CALLBACK_NONE);
+ prompt = xmallocz((size_t)ec + 1);
+ memset(prompt, ' ', (size_t)sc);
+ memset(prompt + sc, '^', (size_t)(ec - sc) + 1);
+ resp = getcmdline_prompt(-1, prompt, 0, EXPAND_NOTHING, NULL, CALLBACK_NONE);
msg_putchar('\n');
xfree(prompt);
if (resp != NULL) {
- typed = *resp;
+ typed = (char_u)(*resp);
xfree(resp);
+ } else {
+ // getcmdline_prompt() returns NULL if there is no command line to return.
+ typed = NUL;
+ }
+ // When ":normal" runs out of characters we get
+ // an empty line. Use "q" to get out of the
+ // loop.
+ if (ex_normal_busy && typed == NUL) {
+ typed = 'q';
}
} else {
- char_u *orig_line = NULL;
+ char *orig_line = NULL;
int len_change = 0;
const bool save_p_lz = p_lz;
int save_p_fen = curwin->w_p_fen;
@@ -3881,8 +3918,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// really update the line, it would change
// what matches. Temporarily replace the line
// and change it back afterwards.
- orig_line = vim_strsave(ml_get(lnum));
- char_u *new_line = concat_str(new_start, sub_firstline + copycol);
+ orig_line = (char *)vim_strsave(ml_get(lnum));
+ char *new_line = (char *)concat_str((char_u *)new_start,
+ (char_u *)sub_firstline + copycol);
// Position the cursor relative to the end of the line, the
// previous substitute may have inserted or deleted characters
@@ -3916,15 +3954,17 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
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);
- msg_no_more = FALSE;
- msg_scroll = i;
+ msg_no_more = false;
+ msg_scroll = (int)i;
showruler(true);
ui_cursor_goto(msg_row, msg_col);
RedrawingDisabled = temp;
no_mapping++; // don't map this key
+ allow_keys++; // allow special keys
typed = plain_vgetc();
no_mapping--;
+ allow_keys--;
// clear the question
msg_didout = false; // don't scroll up
@@ -3968,7 +4008,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
State = save_State;
setmouse();
if (vim_strchr(p_cpo, CPO_UNDO) != NULL) {
- --no_u_sync;
+ no_u_sync--;
}
if (typed == 'n') {
@@ -3996,7 +4036,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// go beyond the last line of the buffer.
if (nmatch > curbuf->b_ml.ml_line_count - sub_firstlnum + 1) {
nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1;
- current_match.end.lnum = sub_firstlnum + nmatch;
+ current_match.end.lnum = sub_firstlnum + (linenr_T)nmatch;
skip_match = true;
}
@@ -4005,9 +4045,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
/* For a multi-line match, make a copy of the last matched */ \
/* line and continue in that one. */ \
if (nmatch > 1) { \
- sub_firstlnum += nmatch - 1; \
+ sub_firstlnum += (linenr_T)nmatch - 1; \
xfree(sub_firstline); \
- sub_firstline = vim_strsave(ml_get(sub_firstlnum)); \
+ sub_firstline = (char *)vim_strsave(ml_get(sub_firstlnum)); \
/* When going beyond the last line, stop substituting. */ \
if (sub_firstlnum <= line2) { \
do_again = true; \
@@ -4019,7 +4059,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
/* Already hit end of the buffer, sub_firstlnum is one */ \
/* less than what it ought to be. */ \
xfree(sub_firstline); \
- sub_firstline = vim_strsave((char_u *)""); \
+ sub_firstline = xstrdup(""); \
copycol = 0; \
} \
} while (0)
@@ -4027,25 +4067,25 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// 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 (preview && !has_second_delim) {
+ if (cmdpreview && !has_second_delim) {
current_match.start.col = regmatch.startpos[0].col;
if (current_match.end.lnum == 0) {
- current_match.end.lnum = sub_firstlnum + nmatch - 1;
+ current_match.end.lnum = sub_firstlnum + (linenr_T)nmatch - 1;
}
current_match.end.col = regmatch.endpos[0].col;
ADJUST_SUB_FIRSTLNUM();
- lnum += nmatch - 1;
+ lnum += (linenr_T)nmatch - 1;
goto skip;
}
-
// 3. Substitute the string. During 'inccommand' preview only do this if
// there is a replace pattern.
- if (!preview || has_second_delim) {
+ if (!cmdpreview || has_second_delim) {
long lnum_start = lnum; // save the start lnum
- save_ma = curbuf->b_p_ma;
+ int save_ma = curbuf->b_p_ma;
+ int save_sandbox = sandbox;
if (subflags.do_count) {
// prevent accidentally changing the buffer by a function
curbuf->b_p_ma = false;
@@ -4054,19 +4094,24 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// Save flags for recursion. They can change for e.g.
// :s/^/\=execute("s#^##gn")
subflags_T subflags_save = subflags;
- // get length of substitution part
+
+ // Disallow changing text or switching window in an expression.
+ textlock++;
+ // Get length of substitution part, including the NUL.
+ // When it fails sublen is zero.
sublen = vim_regsub_multi(&regmatch,
sub_firstlnum - regmatch.startpos[0].lnum,
- sub, sub_firstline, false, p_magic, true);
+ (char_u *)sub, (char_u *)sub_firstline, 0,
+ REGSUB_BACKSLASH | (p_magic ? REGSUB_MAGIC : 0));
+ textlock--;
+
// If getting the substitute string caused an error, don't do
// the replacement.
// Don't keep flags set by a recursive call
subflags = subflags_save;
- if (aborting() || subflags.do_count) {
+ if (sublen == 0 || aborting() || subflags.do_count) {
curbuf->b_p_ma = save_ma;
- if (sandbox > 0) {
- sandbox--;
- }
+ sandbox = save_sandbox;
goto skip;
}
@@ -4078,13 +4123,13 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
if (nmatch == 1) {
p1 = sub_firstline;
} else {
- p1 = ml_get(sub_firstlnum + nmatch - 1);
+ p1 = (char *)ml_get(sub_firstlnum + (linenr_T)nmatch - 1);
nmatch_tl += nmatch - 1;
}
- size_t copy_len = regmatch.startpos[0].col - copycol;
+ size_t copy_len = (size_t)(regmatch.startpos[0].col - copycol);
new_end = sub_grow_buf(&new_start,
- (STRLEN(p1) - regmatch.endpos[0].col)
- + copy_len + sublen + 1);
+ (colnr_T)STRLEN(p1) - regmatch.endpos[0].col
+ + (colnr_T)copy_len + sublen + 1);
// copy the text up to the part that matched
memmove(new_end, sub_firstline + copycol, copy_len);
@@ -4092,12 +4137,15 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// Finally, at this point we can know where the match actually will
// start in the new text
- int start_col = new_end - new_start;
+ int start_col = (int)(new_end - new_start);
current_match.start.col = start_col;
+ textlock++;
(void)vim_regsub_multi(&regmatch,
sub_firstlnum - regmatch.startpos[0].lnum,
- sub, new_end, true, p_magic, true);
+ (char_u *)sub, (char_u *)new_end, sublen,
+ REGSUB_COPY | REGSUB_BACKSLASH | (p_magic ? REGSUB_MAGIC : 0));
+ textlock--;
sub_nsubs++;
did_sub = true;
@@ -4113,12 +4161,11 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// TODO(bfredl): this has some robustness issues, look into later.
bcount_t replaced_bytes = 0;
lpos_T start = regmatch.startpos[0], end = regmatch.endpos[0];
- for (i = 0; i < nmatch-1; i++) {
- replaced_bytes += STRLEN(ml_get(lnum_start+i)) + 1;
+ for (i = 0; i < nmatch - 1; i++) {
+ replaced_bytes += (bcount_t)STRLEN(ml_get((linenr_T)(lnum_start + i))) + 1;
}
replaced_bytes += end.col - start.col;
-
// Now the trick is to replace CTRL-M chars with a real line
// break. This would make it impossible to insert a CTRL-M in
// the text. The line break can be avoided by preceding the
@@ -4127,6 +4174,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// That is Vi compatible.
for (p1 = new_end; *p1; p1++) {
if (p1[0] == '\\' && p1[1] != NUL) { // remove backslash
+ sublen--; // correct the byte counts for extmark_splice()
STRMOVE(p1, p1 + 1);
} else if (*p1 == CAR) {
if (u_inssub(lnum) == OK) { // prepare for undo
@@ -4157,7 +4205,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
p1 += utfc_ptr2len(p1) - 1;
}
}
- size_t new_endcol = STRLEN(new_start);
+ colnr_T new_endcol = (colnr_T)STRLEN(new_start);
current_match.end.col = new_endcol;
current_match.end.lnum = lnum;
@@ -4169,12 +4217,11 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
u_save_cursor();
did_save = true;
}
- extmark_splice(curbuf, lnum_start-1, start_col,
- end.lnum-start.lnum, matchcols, replaced_bytes,
- lnum-lnum_start, subcols, sublen-1, kExtmarkUndo);
+ 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);
}
-
// 4. If subflags.do_all is set, find next match.
// Prevent endless loop with patterns that match empty
// strings, e.g. :s/$/pat/g or :s/[a-z]* /(&)/g.
@@ -4241,13 +4288,13 @@ skip:
for (i = 0; i < nmatch_tl; i++) {
ml_delete(lnum, false);
}
- mark_adjust(lnum, lnum + nmatch_tl - 1,
- (long)MAXLNUM, -nmatch_tl, kExtmarkNOOP);
+ mark_adjust(lnum, lnum + (linenr_T)nmatch_tl - 1,
+ (long)MAXLNUM, (linenr_T)(-nmatch_tl), kExtmarkNOOP);
if (subflags.do_ask) {
- deleted_lines(lnum, nmatch_tl);
+ deleted_lines(lnum, (linenr_T)nmatch_tl);
}
lnum--;
- line2 -= nmatch_tl; // nr of lines decreases
+ line2 -= (linenr_T)nmatch_tl; // nr of lines decreases
nmatch_tl = 0;
}
@@ -4287,21 +4334,29 @@ skip:
lnum -= regmatch.startpos[0].lnum;
}
+ // uncrustify:off
+
#define PUSH_PREVIEW_LINES() \
do { \
- linenr_T match_lines = current_match.end.lnum \
- - current_match.start.lnum +1; \
- if (preview_lines.subresults.size > 0) { \
- linenr_T last = kv_last(preview_lines.subresults).end.lnum; \
- if (last == current_match.start.lnum) { \
- preview_lines.lines_needed += match_lines - 1; \
+ if (cmdpreview) { \
+ linenr_T match_lines = current_match.end.lnum \
+ - current_match.start.lnum +1; \
+ if (preview_lines.subresults.size > 0) { \
+ linenr_T last = kv_last(preview_lines.subresults).end.lnum; \
+ if (last == current_match.start.lnum) { \
+ preview_lines.lines_needed += match_lines - 1; \
+ } else { \
+ preview_lines.lines_needed += match_lines; \
+ } \
+ } else { \
+ preview_lines.lines_needed += match_lines; \
} \
- } else { \
- preview_lines.lines_needed += match_lines; \
+ kv_push(preview_lines.subresults, current_match); \
} \
- kv_push(preview_lines.subresults, current_match); \
} while (0)
+ // uncrustify:on
+
// Push the match to preview_lines.
PUSH_PREVIEW_LINES();
@@ -4335,12 +4390,11 @@ 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 - i, i, false);
+ changed_lines(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;
- buf_updates_send_changes(curbuf, first_line, num_added, num_removed,
- do_buf_event);
+ buf_updates_send_changes(curbuf, first_line, num_added, num_removed);
}
xfree(sub_firstline); // may have to free allocated copy of the line
@@ -4351,10 +4405,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.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // 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
@@ -4365,7 +4421,7 @@ skip:
beginline(BL_WHITE | BL_FIX);
}
}
- if (!preview && !do_sub_msg(subflags.do_count) && subflags.do_ask) {
+ if (!cmdpreview && !do_sub_msg(subflags.do_count) && subflags.do_ask) {
msg("");
}
} else {
@@ -4393,42 +4449,39 @@ skip:
}
vim_regfree(regmatch.regprog);
+ xfree(sub_copy);
+ if (sub_needs_free) {
+ xfree(sub);
+ }
// Restore the flag values, they can be used for ":&&".
subflags.do_all = save_do_all;
subflags.do_ask = save_do_ask;
+ int retv = 0;
+
// Show 'inccommand' preview if there are matched lines.
- buf_T *preview_buf = NULL;
- size_t subsize = preview_lines.subresults.size;
- if (preview && !aborting()) {
+ if (cmdpreview && !aborting()) {
if (got_quit || profile_passed_limit(timeout)) { // Too slow, disable.
- set_string_option_direct("icm", -1, (char_u *)"", OPT_FREE,
- SID_NONE);
+ set_string_option_direct("icm", -1, "", OPT_FREE, SID_NONE);
} else if (*p_icm != NUL && pat != NULL) {
- if (pre_src_id == 0) {
- // Get a unique new src_id, saved in a static
- pre_src_id = (int)nvim_create_namespace((String)STRING_INIT);
- }
if (pre_hl_id == 0) {
pre_hl_id = syn_check_group(S_LEN("Substitute"));
}
- curbuf->b_changed = save_b_changed; // preserve 'modified' during preview
- preview_buf = show_sub(eap, old_cursor, &preview_lines,
- pre_hl_id, pre_src_id, bufnr);
- if (subsize > 0) {
- extmark_clear(orig_buf, pre_src_id, eap->line1-1, 0,
- kv_last(preview_lines.subresults).end.lnum-1, MAXCOL);
- }
+ retv = show_sub(eap, old_cursor, &preview_lines, pre_hl_id, cmdpreview_ns, cmdpreview_bufnr);
}
}
- kv_destroy(preview_lines.subresults);
+ if (cmdheight0) {
+ // Restore cmdheight
+ set_option_value("ch", 0L, NULL, 0);
+ }
- return preview_buf;
+ kv_destroy(preview_lines.subresults);
+ return retv;
#undef ADJUST_SUB_FIRSTLNUM
#undef PUSH_PREVIEW_LINES
-} // NOLINT(readability/fn_size)
+}
/// Give message for number of substitutions.
/// Can also be used after a ":global" command.
@@ -4479,42 +4532,40 @@ bool do_sub_msg(bool count_only)
return false;
}
-static void global_exe_one(char_u *const cmd, const linenr_T lnum)
+static void global_exe_one(char *const cmd, const linenr_T lnum)
{
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = 0;
if (*cmd == NUL || *cmd == '\n') {
- do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT);
+ do_cmdline("p", NULL, NULL, DOCMD_NOWAIT);
} else {
do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT);
}
}
-/*
- * Execute a global command of the form:
- *
- * g/pattern/X : execute X on all lines where pattern matches
- * v/pattern/X : execute X on all lines where pattern does not match
- *
- * where 'X' is an EX command
- *
- * The command character (as well as the trailing slash) is optional, and
- * is assumed to be 'p' if missing.
- *
- * This is implemented in two passes: first we scan the file for the pattern and
- * set a mark for each line that (not) matches. Secondly we execute the command
- * for each line that has a mark. This is required because after deleting
- * lines we do not know where to search for the next match.
- */
+/// Execute a global command of the form:
+///
+/// g/pattern/X : execute X on all lines where pattern matches
+/// v/pattern/X : execute X on all lines where pattern does not match
+///
+/// where 'X' is an EX command
+///
+/// The command character (as well as the trailing slash) is optional, and
+/// is assumed to be 'p' if missing.
+///
+/// This is implemented in two passes: first we scan the file for the pattern and
+/// set a mark for each line that (not) matches. Secondly we execute the command
+/// for each line that has a mark. This is required because after deleting
+/// lines we do not know where to search for the next match.
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_u *cmd; // command argument
+ char *cmd; // command argument
- char_u delim; // delimiter, normally '/'
- char_u *pat;
+ char delim; // delimiter, normally '/'
+ char *pat;
regmmatch_T regmatch;
int match;
int which_pat;
@@ -4531,7 +4582,7 @@ void ex_global(exarg_T *eap)
if (eap->forceit) { // ":global!" is like ":vglobal"
type = 'v';
} else {
- type = *eap->cmd;
+ type = (uint8_t)(*eap->cmd);
}
cmd = eap->arg;
which_pat = RE_LAST; // default: use last used regexp
@@ -4542,8 +4593,8 @@ void ex_global(exarg_T *eap)
* "\&": use previous substitute pattern.
*/
if (*cmd == '\\') {
- ++cmd;
- if (vim_strchr((char_u *)"/?&", *cmd) == NULL) {
+ cmd++;
+ if (vim_strchr("/?&", *cmd) == NULL) {
emsg(_(e_backslash));
return;
}
@@ -4552,8 +4603,8 @@ void ex_global(exarg_T *eap)
} else {
which_pat = RE_SEARCH; // use previous search pattern
}
- ++cmd;
- pat = (char_u *)"";
+ cmd++;
+ pat = "";
} else if (*cmd == NUL) {
emsg(_("E148: Regular expression missing from global"));
return;
@@ -4561,25 +4612,22 @@ void ex_global(exarg_T *eap)
return;
} else {
delim = *cmd; // get the delimiter
- if (delim) {
- ++cmd; // skip delimiter if there is one
- }
+ cmd++; // skip delimiter if there is one
pat = cmd; // remember start of pattern
- cmd = skip_regexp(cmd, delim, p_magic, &eap->arg);
+ cmd = (char *)skip_regexp((char_u *)cmd, delim, p_magic, (char_u **)&eap->arg);
if (cmd[0] == delim) { // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
}
- if (search_regcomp(pat, RE_BOTH, which_pat, SEARCH_HIS, &regmatch) == FAIL) {
+ if (search_regcomp((char_u *)pat, RE_BOTH, which_pat, SEARCH_HIS, &regmatch) == FAIL) {
emsg(_(e_invcmd));
return;
}
if (global_busy) {
lnum = curwin->w_cursor.lnum;
- match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
- (colnr_T)0, NULL, NULL);
+ match = (int)vim_regexec_multi(&regmatch, curwin, curbuf, lnum, 0, NULL, NULL);
if ((type == 'g' && match) || (type == 'v' && !match)) {
global_exe_one(cmd, lnum);
}
@@ -4587,8 +4635,7 @@ void ex_global(exarg_T *eap)
// 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 = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
- (colnr_T)0, NULL, NULL);
+ match = (int)vim_regexec_multi(&regmatch, curwin, curbuf, lnum, 0, NULL, NULL);
if (regmatch.regprog == NULL) {
break; // re-compiling regprog failed
}
@@ -4617,12 +4664,11 @@ void ex_global(exarg_T *eap)
}
/// Execute `cmd` on lines marked with ml_setmarked().
-void global_exe(char_u *cmd)
+void global_exe(char *cmd)
{
linenr_T old_lcount; // b_ml.ml_line_count before the command
buf_T *old_buf = curbuf; // remember what buffer we started in
linenr_T lnum; // line number according to old situation
- int save_mapped_ctrl_c = mapped_ctrl_c;
// Set current position only once for a global command.
// If global_busy is set, setpcmark() will not do anything.
@@ -4631,8 +4677,6 @@ void global_exe(char_u *cmd)
// When the command writes a message, don't overwrite the command.
msg_didout = true;
- // Disable CTRL-C mapping, let it interrupt (potentially long output).
- mapped_ctrl_c = 0;
sub_nsubs = 0;
sub_nlines = 0;
@@ -4645,7 +4689,6 @@ void global_exe(char_u *cmd)
os_breakcheck();
}
- mapped_ctrl_c = save_mapped_ctrl_c;
global_busy = 0;
if (global_need_beginline) {
beginline(BL_WHITE | BL_FIX);
@@ -4713,33 +4756,30 @@ bool prepare_tagpreview(bool undo_sync)
and 'cursorbind' */
curwin->w_p_diff = false; // no 'diff'
set_string_option_direct("fdc", -1, // no 'foldcolumn'
- (char_u *)"0", OPT_FREE, SID_NONE);
+ "0", OPT_FREE, SID_NONE);
return true;
}
}
return false;
}
-
-/*
- * ":help": open a read-only window on a help file
- */
+/// ":help": open a read-only window on a help file
void ex_help(exarg_T *eap)
{
- char_u *arg;
- char_u *tag;
+ char *arg;
+ char *tag;
FILE *helpfd; // file descriptor of help file
int n;
int i;
win_T *wp;
int num_matches;
- char_u **matches;
- char_u *p;
+ char **matches;
+ char *p;
int empty_fnum = 0;
int alt_fnum = 0;
buf_T *buf;
int len;
- char_u *lang;
+ char *lang;
const bool old_KeyTyped = KeyTyped;
if (eap != NULL) {
@@ -4747,7 +4787,7 @@ void ex_help(exarg_T *eap)
* A ":help" command ends at the first LF, or at a '|' that is
* followed by some text. Set nextcmd to the following command.
*/
- for (arg = eap->arg; *arg; ++arg) {
+ for (arg = eap->arg; *arg; arg++) {
if (*arg == '\n' || *arg == '\r'
|| (*arg == '|' && arg[1] != NUL && arg[1] != '|')) {
*arg++ = NUL;
@@ -4766,7 +4806,7 @@ void ex_help(exarg_T *eap)
return;
}
} else {
- arg = (char_u *)"";
+ arg = "";
}
// remove trailing blanks
@@ -4780,14 +4820,13 @@ void ex_help(exarg_T *eap)
// When no argument given go to the index.
if (*arg == NUL) {
- arg = (char_u *)"help.txt";
+ arg = "help.txt";
}
/*
* Check if there is a match for the argument.
*/
- n = find_help_tags(arg, &num_matches, &matches,
- eap != NULL && eap->forceit);
+ n = find_help_tags(arg, &num_matches, &matches, eap != NULL && eap->forceit);
i = 0;
if (n != FAIL && lang != NULL) {
@@ -4807,22 +4846,21 @@ void ex_help(exarg_T *eap)
semsg(_("E149: Sorry, no help for %s"), arg);
}
if (n != FAIL) {
- FreeWild(num_matches, matches);
+ FreeWild(num_matches, (char_u **)matches);
}
return;
}
// The first match (in the requested language) is the best match.
- tag = vim_strsave(matches[i]);
- FreeWild(num_matches, matches);
+ tag = xstrdup(matches[i]);
+ FreeWild(num_matches, (char_u **)matches);
/*
* Re-use an existing help window or open a new one.
* Always open a new one for ":tab help".
*/
- if (!bt_help(curwin->w_buffer)
- || cmdmod.tab != 0) {
- if (cmdmod.tab != 0) {
+ if (!bt_help(curwin->w_buffer) || cmdmod.cmod_tab != 0) {
+ if (cmdmod.cmod_tab != 0) {
wp = NULL;
} else {
wp = NULL;
@@ -4848,7 +4886,7 @@ void ex_help(exarg_T *eap)
// specified, the current window is vertically split and
// narrow.
n = WSP_HELP;
- if (cmdmod.split == 0 && curwin->w_width != Columns
+ if (cmdmod.cmod_split == 0 && curwin->w_width != Columns
&& curwin->w_width < 80) {
n |= WSP_TOP;
}
@@ -4868,23 +4906,22 @@ void ex_help(exarg_T *eap)
alt_fnum = curbuf->b_fnum;
(void)do_ecmd(0, NULL, NULL, NULL, ECMD_LASTL,
ECMD_HIDE + ECMD_SET_HELP,
- NULL // buffer is still open, don't store info
- );
- if (!cmdmod.keepalt) {
+ NULL); // buffer is still open, don't store info
+
+ if ((cmdmod.cmod_flags & CMOD_KEEPALT) == 0) {
curwin->w_alt_fnum = alt_fnum;
}
empty_fnum = curbuf->b_fnum;
}
}
- if (!p_im) {
- restart_edit = 0; // don't want insert mode in help file
- }
+ restart_edit = 0; // don't want insert mode in help file
+
// Restore KeyTyped, setting 'filetype=help' may reset it.
// It is needed for do_tag top open folds under the cursor.
KeyTyped = old_KeyTyped;
- do_tag(tag, DT_HELP, 1, FALSE, TRUE);
+ do_tag((char_u *)tag, DT_HELP, 1, false, true);
// Delete the empty buffer if we're not using it. Careful: autocommands
// may have jumped to another window, check that the buffer is not in a
@@ -4897,7 +4934,8 @@ void ex_help(exarg_T *eap)
}
// keep the previous alternate file
- if (alt_fnum != 0 && curwin->w_alt_fnum == empty_fnum && !cmdmod.keepalt) {
+ if (alt_fnum != 0 && curwin->w_alt_fnum == empty_fnum
+ && (cmdmod.cmod_flags & CMOD_KEEPALT) == 0) {
curwin->w_alt_fnum = alt_fnum;
}
@@ -4905,13 +4943,11 @@ erret:
xfree(tag);
}
-
-/*
- * In an argument search for a language specifiers in the form "@xx".
- * Changes the "@" to NUL if found, and returns a pointer to "xx".
- * Returns NULL if not found.
- */
-char_u *check_help_lang(char_u *arg)
+/// In an argument search for a language specifiers in the form "@xx".
+/// Changes the "@" to NUL if found, and returns a pointer to "xx".
+///
+/// @return NULL if not found.
+char *check_help_lang(char *arg)
{
int len = (int)STRLEN(arg);
@@ -4937,10 +4973,11 @@ char_u *check_help_lang(char_u *arg)
/// @param wrong_case no matching case
///
/// @return a heuristic indicating how well the given string matches.
-int help_heuristic(char_u *matched_string, int offset, int wrong_case)
+int help_heuristic(char *matched_string, int offset, int wrong_case)
+ FUNC_ATTR_PURE
{
int num_letters;
- char_u *p;
+ char *p;
num_letters = 0;
for (p = matched_string; *p; p++) {
@@ -4973,13 +5010,11 @@ int help_heuristic(char_u *matched_string, int offset, int wrong_case)
if (matched_string[0] == '+' && matched_string[1] != NUL) {
offset += 100;
}
- return (int)(100 * num_letters + STRLEN(matched_string) + offset);
+ return 100 * num_letters + (int)STRLEN(matched_string) + offset;
}
-/*
- * Compare functions for qsort() below, that checks the help heuristics number
- * that has been put after the tagname by find_tags().
- */
+/// Compare functions for qsort() below, that checks the help heuristics number
+/// that has been put after the tagname by find_tags().
static int help_compare(const void *s1, const void *s2)
{
char *p1;
@@ -4987,47 +5022,77 @@ static int help_compare(const void *s1, const void *s2)
p1 = *(char **)s1 + strlen(*(char **)s1) + 1;
p2 = *(char **)s2 + strlen(*(char **)s2) + 1;
- return strcmp(p1, p2);
+
+ // Compare by help heuristic number first.
+ int cmp = strcmp(p1, p2);
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ // Compare by strings as tie-breaker when same heuristic number.
+ return strcmp(*(char **)s1, *(char **)s2);
}
-// Find all help tags matching "arg", sort them and return in matches[], with
-// the number of matches in num_matches.
-// The matches will be sorted with a "best" match algorithm.
-// When "keep_lang" is true try keeping the language of the current buffer.
-int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool keep_lang)
+/// Find all help tags matching "arg", sort them and return in matches[], with
+/// the number of matches in num_matches.
+/// The matches will be sorted with a "best" match algorithm.
+/// When "keep_lang" is true try keeping the language of the current buffer.
+int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep_lang)
{
int i;
- static const char *(mtable[]) = {
- "*", "g*", "[*", "]*",
- "/*", "/\\*", "\"*", "**",
- "/\\(\\)", "/\\%(\\)",
- "?", ":?", "?<CR>", "g?", "g?g?", "g??",
- "-?", "q?", "v_g?",
- "/\\?", "/\\z(\\)", "\\=", ":s\\=",
- "[count]", "[quotex]",
- "[range]", ":[range]",
- "[pattern]", "\\|", "\\%$",
- "s/\\~", "s/\\U", "s/\\L",
- "s/\\1", "s/\\2", "s/\\3", "s/\\9"
- };
- static const char *(rtable[]) = {
- "star", "gstar", "[star", "]star",
- "/star", "/\\\\star", "quotestar", "starstar",
- "/\\\\(\\\\)", "/\\\\%(\\\\)",
- "?", ":?", "?<CR>", "g?", "g?g?", "g??",
- "-?", "q?", "v_g?",
- "/\\\\?", "/\\\\z(\\\\)", "\\\\=", ":s\\\\=",
- "\\[count]", "\\[quotex]",
- "\\[range]", ":\\[range]",
- "\\[pattern]", "\\\\bar", "/\\\\%\\$",
- "s/\\\\\\~", "s/\\\\U", "s/\\\\L",
- "s/\\\\1", "s/\\\\2", "s/\\\\3", "s/\\\\9"
+
+ // Specific tags that either have a specific replacement or won't go
+ // throught the generic rules.
+ static char *(except_tbl[][2]) = {
+ { "*", "star" },
+ { "g*", "gstar" },
+ { "[*", "[star" },
+ { "]*", "]star" },
+ { ":*", ":star" },
+ { "/*", "/star" }, // NOLINT
+ { "/\\*", "/\\\\star" },
+ { "\"*", "quotestar" },
+ { "**", "starstar" },
+ { "cpo-*", "cpo-star" },
+ { "/\\(\\)", "/\\\\(\\\\)" },
+ { "/\\%(\\)", "/\\\\%(\\\\)" },
+ { "?", "?" },
+ { "??", "??" },
+ { ":?", ":?" },
+ { "?<CR>", "?<CR>" },
+ { "g?", "g?" },
+ { "g?g?", "g?g?" },
+ { "g??", "g??" },
+ { "-?", "-?" },
+ { "q?", "q?" },
+ { "v_g?", "v_g?" },
+ { "/\\?", "/\\\\?" },
+ { "/\\z(\\)", "/\\\\z(\\\\)" },
+ { "\\=", "\\\\=" },
+ { ":s\\=", ":s\\\\=" },
+ { "[count]", "\\[count]" },
+ { "[quotex]", "\\[quotex]" },
+ { "[range]", "\\[range]" },
+ { ":[range]", ":\\[range]" },
+ { "[pattern]", "\\[pattern]" },
+ { "\\|", "\\\\bar" },
+ { "\\%$", "/\\\\%\\$" },
+ { "s/\\~", "s/\\\\\\~" },
+ { "s/\\U", "s/\\\\U" },
+ { "s/\\L", "s/\\\\L" },
+ { "s/\\1", "s/\\\\1" },
+ { "s/\\2", "s/\\\\2" },
+ { "s/\\3", "s/\\\\3" },
+ { "s/\\9", "s/\\\\9" },
+ { NULL, NULL }
};
+
static const char *(expr_table[]) = {
"!=?", "!~?", "<=?", "<?", "==?", "=~?",
">=?", ">?", "is?", "isnot?"
};
- char_u *d = IObuff; // assume IObuff is long enough!
+ char *d = (char *)IObuff; // assume IObuff is long enough!
+ d[0] = NUL;
if (STRNICMP(arg, "expr-", 5) == 0) {
// When the string starting with "expr-" and containing '?' and matches
@@ -5049,16 +5114,16 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
}
} else {
// Recognize a few exceptions to the rule. Some strings that contain
- // '*' with "star". Otherwise '*' is recognized as a wildcard.
- for (i = (int)ARRAY_SIZE(mtable); --i >= 0;) {
- if (STRCMP(arg, mtable[i]) == 0) {
- STRCPY(d, rtable[i]);
+ // '*'are changed to "star", otherwise '*' is recognized as a wildcard.
+ for (i = 0; except_tbl[i][0] != NULL; i++) {
+ if (STRCMP(arg, except_tbl[i][0]) == 0) {
+ STRCPY(d, except_tbl[i][1]);
break;
}
}
}
- if (i < 0) { // no match in table
+ if (d[0] == NUL) { // no match in table
// Replace "\S" with "/\\S", etc. Otherwise every tag is matched.
// Also replace "\%^" and "\%(", they match every tag too.
// Also "\zs", "\z1", etc.
@@ -5066,10 +5131,9 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
// And also "\_$" and "\_^".
if (arg[0] == '\\'
&& ((arg[1] != NUL && arg[2] == NUL)
- || (vim_strchr((char_u *)"%_z@", arg[1]) != NULL
+ || (vim_strchr("%_z@", arg[1]) != NULL
&& arg[2] != NUL))) {
- STRCPY(d, "/\\\\");
- STRCPY(d + 3, arg + 1);
+ vim_snprintf(d, IOSIZE, "/\\\\%s", arg + 1);
// Check for "/\\_$", should be "/\\_\$"
if (d[3] == '_' && d[4] == '$') {
STRCPY(d + 4, "\\$");
@@ -5089,14 +5153,14 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
if (*arg == '(' && arg[1] == '\'') {
arg++;
}
- for (const char_u *s = arg; *s; s++) {
+ for (const char *s = arg; *s; s++) {
// Replace "|" with "bar" and '"' with "quote" to match the name of
// the tags for these commands.
// Replace "*" with ".*" and "?" with "." to match command line
// completion.
// Insert a backslash before '~', '$' and '.' to avoid their
// special meaning.
- if (d - IObuff > IOSIZE - 10) { // getting too long!?
+ if ((char_u *)d - IObuff > IOSIZE - 10) { // getting too long!?
break;
}
switch (*s) {
@@ -5126,17 +5190,16 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
* ":help i_^_CTRL-D" work.
* Insert '-' before and after "CTRL-X" when applicable.
*/
- if (*s < ' ' || (*s == '^' && s[1] && (ASCII_ISALPHA(s[1])
- || vim_strchr((char_u *)
- "?@[\\]^",
- s[1]) != NULL))) {
- if (d > IObuff && d[-1] != '_' && d[-1] != '\\') {
+ if (*s < ' '
+ || (*s == '^' && s[1]
+ && (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", s[1]) != NULL))) {
+ if ((char_u *)d > IObuff && d[-1] != '_' && d[-1] != '\\') {
*d++ = '_'; // prepend a '_' to make x_CTRL-x
}
STRCPY(d, "CTRL-");
d += 5;
if (*s < ' ') {
- *d++ = *s + '@';
+ *d++ = (char)(*s + '@');
if (d[-1] == '\\') {
*d++ = '\\'; // double a backslash
}
@@ -5188,15 +5251,15 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
*d = NUL;
if (*IObuff == '`') {
- if (d > IObuff + 2 && d[-1] == '`') {
+ if ((char_u *)d > IObuff + 2 && d[-1] == '`') {
// remove the backticks from `command`
memmove(IObuff, IObuff + 1, STRLEN(IObuff));
d[-2] = NUL;
- } else if (d > IObuff + 3 && d[-2] == '`' && d[-1] == ',') {
+ } else if ((char_u *)d > IObuff + 3 && d[-2] == '`' && d[-1] == ',') {
// remove the backticks and comma from `command`,
memmove(IObuff, IObuff + 1, STRLEN(IObuff));
d[-3] = NUL;
- } else if (d > IObuff + 4 && d[-3] == '`'
+ } else if ((char_u *)d > IObuff + 4 && d[-3] == '`'
&& d[-2] == '\\' && d[-1] == '.') {
// remove the backticks and dot from `command`\.
memmove(IObuff, IObuff + 1, STRLEN(IObuff));
@@ -5212,7 +5275,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
if (keep_lang) {
flags |= TAG_KEEP_LANG;
}
- if (find_tags(IObuff, num_matches, matches, flags, MAXCOL, NULL) == OK
+ if (find_tags(IObuff, num_matches, (char_u ***)matches, flags, MAXCOL, NULL) == OK
&& *num_matches > 0) {
// Sort the matches found on the heuristic number that is after the
// tag name.
@@ -5230,15 +5293,14 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
static void prepare_help_buffer(void)
{
curbuf->b_help = true;
- set_string_option_direct("buftype", -1, (char_u *)"help",
- OPT_FREE|OPT_LOCAL, 0);
+ set_string_option_direct("buftype", -1, "help", OPT_FREE|OPT_LOCAL, 0);
// Always set these options after jumping to a help tag, because the
// user may have an autocommand that gets in the way.
// Accept all ASCII chars for keywords, except ' ', '*', '"', '|', and
// latin1 word characters (for translated help files).
// Only set it when needed, buf_init_chartab() is some work.
- char_u *p = (char_u *)"!-~,^*,^|,^\",192-255";
+ char *p = "!-~,^*,^|,^\",192-255";
if (STRCMP(curbuf->b_p_isk, p) != 0) {
set_string_option_direct("isk", -1, p, OPT_FREE|OPT_LOCAL, 0);
check_buf_options(curbuf);
@@ -5246,8 +5308,7 @@ static void prepare_help_buffer(void)
}
// Don't use the global foldmethod.
- set_string_option_direct("fdm", -1, (char_u *)"manual",
- OPT_FREE|OPT_LOCAL, 0);
+ set_string_option_direct("fdm", -1, "manual", OPT_FREE|OPT_LOCAL, 0);
curbuf->b_p_ts = 8; // 'tabstop' is 8.
curwin->w_p_list = FALSE; // No list mode.
@@ -5266,14 +5327,12 @@ static void prepare_help_buffer(void)
set_buflisted(FALSE);
}
-/*
- * After reading a help file: May cleanup a help buffer when syntax
- * highlighting is not used.
- */
+/// After reading a help file: May cleanup a help buffer when syntax
+/// highlighting is not used.
void fix_help_buffer(void)
{
linenr_T lnum;
- char_u *line;
+ char *line;
bool in_example = false;
// Set filetype to "help".
@@ -5285,13 +5344,13 @@ void fix_help_buffer(void)
if (!syntax_present(curwin)) {
for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) {
- line = ml_get_buf(curbuf, lnum, false);
+ line = (char *)ml_get_buf(curbuf, lnum, false);
const size_t len = STRLEN(line);
if (in_example && len > 0 && !ascii_iswhite(line[0])) {
// End of example: non-white or '<' in first column.
if (line[0] == '<') {
// blank-out a '<' in the first column
- line = ml_get_buf(curbuf, lnum, true);
+ line = (char *)ml_get_buf(curbuf, lnum, true);
line[0] = ' ';
}
in_example = false;
@@ -5299,12 +5358,12 @@ void fix_help_buffer(void)
if (!in_example && len > 0) {
if (line[len - 1] == '>' && (len == 1 || line[len - 2] == ' ')) {
// blank-out a '>' in the last column (start of example)
- line = ml_get_buf(curbuf, lnum, true);
+ line = (char *)ml_get_buf(curbuf, lnum, true);
line[len - 1] = ' ';
in_example = true;
} else if (line[len - 1] == '~') {
// blank-out a '~' at the end of line (header marker)
- line = ml_get_buf(curbuf, lnum, true);
+ line = (char *)ml_get_buf(curbuf, lnum, true);
line[len - 1] = ' ';
}
}
@@ -5315,32 +5374,32 @@ void fix_help_buffer(void)
* In the "help.txt" and "help.abx" file, add the locally added help
* files. This uses the very first line in the help file.
*/
- char_u *const fname = path_tail(curbuf->b_fname);
- if (fnamecmp(fname, "help.txt") == 0
- || (fnamencmp(fname, "help.", 5) == 0
+ char *const fname = path_tail(curbuf->b_fname);
+ if (FNAMECMP(fname, "help.txt") == 0
+ || (FNAMENCMP(fname, "help.", 5) == 0
&& ASCII_ISALPHA(fname[5])
&& ASCII_ISALPHA(fname[6])
&& TOLOWER_ASC(fname[7]) == 'x'
&& fname[8] == NUL)) {
for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; lnum++) {
- line = ml_get_buf(curbuf, lnum, false);
- if (strstr((char *)line, "*local-additions*") == NULL) {
+ line = (char *)ml_get_buf(curbuf, lnum, false);
+ if (strstr(line, "*local-additions*") == NULL) {
continue;
}
// Go through all directories in 'runtimepath', skipping
// $VIMRUNTIME.
- char_u *p = p_rtp;
+ char *p = (char *)p_rtp;
while (*p != NUL) {
- copy_option_part(&p, NameBuff, MAXPATHL, ",");
- char_u *const rt = (char_u *)vim_getenv("VIMRUNTIME");
+ copy_option_part(&p, (char *)NameBuff, MAXPATHL, ",");
+ char *const rt = vim_getenv("VIMRUNTIME");
if (rt != NULL
- && path_full_compare(rt, NameBuff, false, true) != kEqualFiles) {
+ && path_full_compare(rt, (char *)NameBuff, false, true) != kEqualFiles) {
int fcount;
- char_u **fnames;
- char_u *s;
+ char **fnames;
+ char *s;
vimconv_T vc;
- char_u *cp;
+ char *cp;
// Find all "doc/ *.txt" files in this directory.
if (!add_pathsep((char *)NameBuff)
@@ -5352,9 +5411,9 @@ void fix_help_buffer(void)
// Note: We cannot just do `&NameBuff` because it is a statically sized array
// so `NameBuff == &NameBuff` according to C semantics.
- char_u *buff_list[1] = { NameBuff };
- if (gen_expand_wildcards(1, buff_list, &fcount,
- &fnames, EW_FILE|EW_SILENT) == OK
+ char *buff_list[1] = { (char *)NameBuff };
+ if (gen_expand_wildcards(1, (char_u **)buff_list, &fcount,
+ (char_u ***)&fnames, EW_FILE|EW_SILENT) == OK
&& fcount > 0) {
// If foo.abx is found use it instead of foo.txt in
// the same directory.
@@ -5366,27 +5425,27 @@ void fix_help_buffer(void)
if (fnames[i1] == NULL || fnames[i2] == NULL) {
continue;
}
- const char_u *const f1 = fnames[i1];
- const char_u *const f2 = fnames[i2];
- const char_u *const t1 = path_tail(f1);
- const char_u *const t2 = path_tail(f2);
- const char_u *const e1 = STRRCHR(t1, '.');
- const char_u *const e2 = STRRCHR(t2, '.');
+ const char *const f1 = fnames[i1];
+ const char *const f2 = fnames[i2];
+ const char *const t1 = path_tail(f1);
+ const char *const t2 = path_tail(f2);
+ const char *const e1 = (char *)STRRCHR(t1, '.');
+ const char *const e2 = (char *)STRRCHR(t2, '.');
if (e1 == NULL || e2 == NULL) {
continue;
}
- if (fnamecmp(e1, ".txt") != 0
- && fnamecmp(e1, fname + 4) != 0) {
+ if (FNAMECMP(e1, ".txt") != 0
+ && FNAMECMP(e1, fname + 4) != 0) {
// Not .txt and not .abx, remove it.
XFREE_CLEAR(fnames[i1]);
continue;
}
if (e1 - f1 != e2 - f2
- || fnamencmp(f1, f2, e1 - f1) != 0) {
+ || FNAMENCMP(f1, f2, e1 - f1) != 0) {
continue;
}
- if (fnamecmp(e1, ".txt") == 0
- && fnamecmp(e2, fname + 4) == 0) {
+ if (FNAMECMP(e1, ".txt") == 0
+ && FNAMECMP(e2, fname + 4) == 0) {
// use .abx instead of .txt
XFREE_CLEAR(fnames[i1]);
}
@@ -5397,13 +5456,13 @@ void fix_help_buffer(void)
continue;
}
- FILE *const fd = os_fopen((char *)fnames[fi], "r");
+ FILE *const fd = os_fopen(fnames[fi], "r");
if (fd == NULL) {
continue;
}
vim_fgets(IObuff, IOSIZE, fd);
if (IObuff[0] == '*'
- && (s = vim_strchr(IObuff + 1, '*'))
+ && (s = vim_strchr((char *)IObuff + 1, '*'))
!= NULL) {
TriState this_utf = kNone;
// Change tag definition to a
@@ -5417,7 +5476,7 @@ void fix_help_buffer(void)
// The text is utf-8 when a byte
// above 127 is found and no
// illegal byte sequence is found.
- if (*s >= 0x80 && this_utf != kFalse) {
+ if ((char_u)(*s) >= 0x80 && this_utf != kFalse) {
this_utf = kTrue;
const int l = utf_ptr2len(s);
if (l == 1) {
@@ -5436,26 +5495,26 @@ void fix_help_buffer(void)
p_enc);
if (vc.vc_type == CONV_NONE) {
// No conversion needed.
- cp = IObuff;
+ cp = (char *)IObuff;
} else {
// Do the conversion. If it fails
// use the unconverted text.
- cp = string_convert(&vc, IObuff, NULL);
+ cp = (char *)string_convert(&vc, IObuff, NULL);
if (cp == NULL) {
- cp = IObuff;
+ cp = (char *)IObuff;
}
}
convert_setup(&vc, NULL, NULL);
ml_append(lnum, cp, (colnr_T)0, false);
- if (cp != IObuff) {
+ if ((char_u *)cp != IObuff) {
xfree(cp);
}
lnum++;
}
fclose(fd);
}
- FreeWild(fcount, fnames);
+ FreeWild(fcount, (char_u **)fnames);
}
}
xfree(rt);
@@ -5465,23 +5524,18 @@ void fix_help_buffer(void)
}
}
-/*
- * ":exusage"
- */
+/// ":exusage"
void ex_exusage(exarg_T *eap)
{
do_cmdline_cmd("help ex-cmd-index");
}
-/*
- * ":viusage"
- */
+/// ":viusage"
void ex_viusage(exarg_T *eap)
{
do_cmdline_cmd("help normal-index");
}
-
/// Generate tags in one help directory
///
/// @param dir Path to the doc directory
@@ -5490,15 +5544,15 @@ void ex_viusage(exarg_T *eap)
/// French)
/// @param add_help_tags Whether to add the "help-tags" tag
/// @param ignore_writeerr ignore write error
-static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname, bool add_help_tags,
+static void helptags_one(char *dir, const char *ext, const char *tagfname, bool add_help_tags,
bool ignore_writeerr)
FUNC_ATTR_NONNULL_ALL
{
garray_T ga;
int filecount;
- char_u **files;
- char_u *p1, *p2;
- char_u *s;
+ char **files;
+ char *p1, *p2;
+ char *s;
TriState utf8 = kNone;
bool mix = false; // detected mixed encodings
@@ -5513,8 +5567,8 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
// Note: We cannot just do `&NameBuff` because it is a statically sized array
// so `NameBuff == &NameBuff` according to C semantics.
- char_u *buff_list[1] = { NameBuff };
- if (gen_expand_wildcards(1, buff_list, &filecount, &files,
+ char *buff_list[1] = { (char *)NameBuff };
+ if (gen_expand_wildcards(1, (char_u **)buff_list, &filecount, (char_u ***)&files,
EW_FILE|EW_SILENT) == FAIL
|| filecount == 0) {
if (!got_int) {
@@ -5539,7 +5593,7 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
if (!ignore_writeerr) {
semsg(_("E152: Cannot open %s for writing"), NameBuff);
}
- FreeWild(filecount, files);
+ FreeWild(filecount, (char_u **)files);
return;
}
@@ -5547,30 +5601,29 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
// add the "help-tags" tag.
ga_init(&ga, (int)sizeof(char_u *), 100);
if (add_help_tags
- || path_full_compare((char_u *)"$VIMRUNTIME/doc",
- dir, false, true) == kEqualFiles) {
+ || path_full_compare("$VIMRUNTIME/doc", dir, false, true) == kEqualFiles) {
size_t s_len = 18 + STRLEN(tagfname);
s = xmalloc(s_len);
- snprintf((char *)s, s_len, "help-tags\t%s\t1\n", tagfname);
- GA_APPEND(char_u *, &ga, s);
+ snprintf(s, s_len, "help-tags\t%s\t1\n", tagfname);
+ GA_APPEND(char *, &ga, s);
}
// Go over all the files and extract the tags.
for (int fi = 0; fi < filecount && !got_int; fi++) {
- FILE *const fd = os_fopen((char *)files[fi], "r");
+ FILE *const fd = os_fopen(files[fi], "r");
if (fd == NULL) {
semsg(_("E153: Unable to open %s for reading"), files[fi]);
continue;
}
- const char_u *const fname = files[fi] + dirlen + 1;
+ const char *const fname = files[fi] + dirlen + 1;
bool firstline = true;
while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) {
if (firstline) {
// Detect utf-8 file by a non-ASCII char in the first line.
TriState this_utf8 = kNone;
- for (s = IObuff; *s != NUL; s++) {
- if (*s >= 0x80) {
+ for (s = (char *)IObuff; *s != NUL; s++) {
+ if ((char_u)(*s) >= 0x80) {
this_utf8 = kTrue;
const int l = utf_ptr2len(s);
if (l == 1) {
@@ -5594,9 +5647,9 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
}
firstline = false;
}
- p1 = vim_strchr(IObuff, '*'); // find first '*'
+ p1 = vim_strchr((char *)IObuff, '*'); // find first '*'
while (p1 != NULL) {
- p2 = (char_u *)strchr((const char *)p1 + 1, '*'); // Find second '*'.
+ p2 = strchr((const char *)p1 + 1, '*'); // Find second '*'.
if (p2 != NULL && p2 > p1 + 1) { // Skip "*" and "**".
for (s = p1 + 1; s < p2; s++) {
if (*s == ' ' || *s == '\t' || *s == '|') {
@@ -5608,15 +5661,15 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
// characters, there is white space before it and is
// followed by a white character or end-of-line.
if (s == p2
- && (p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t')
- && (vim_strchr((char_u *)" \t\n\r", s[1]) != NULL
+ && ((char_u *)p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t')
+ && (vim_strchr(" \t\n\r", s[1]) != NULL
|| s[1] == '\0')) {
*p2 = '\0';
p1++;
- size_t s_len= (p2 - p1) + STRLEN(fname) + 2;
+ size_t s_len= (size_t)(p2 - p1) + STRLEN(fname) + 2;
s = xmalloc(s_len);
- GA_APPEND(char_u *, &ga, s);
- snprintf((char *)s, s_len, "%s\t%s", p1, fname);
+ GA_APPEND(char *, &ga, s);
+ snprintf(s, s_len, "%s\t%s", p1, fname);
// find next '*'
p2 = vim_strchr(p2 + 1, '*');
@@ -5630,7 +5683,7 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
fclose(fd);
}
- FreeWild(filecount, files);
+ FreeWild(filecount, (char_u **)files);
if (!got_int && ga.ga_data != NULL) {
// Sort the tags.
@@ -5638,8 +5691,8 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
// Check for duplicates.
for (int i = 1; i < ga.ga_len; i++) {
- p1 = ((char_u **)ga.ga_data)[i - 1];
- p2 = ((char_u **)ga.ga_data)[i];
+ p1 = ((char **)ga.ga_data)[i - 1];
+ p2 = ((char **)ga.ga_data)[i];
while (*p1 == *p2) {
if (*p2 == '\t') {
*p2 = NUL;
@@ -5661,10 +5714,10 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
// Write the tags into the file.
for (int i = 0; i < ga.ga_len; i++) {
- s = ((char_u **)ga.ga_data)[i];
+ s = ((char **)ga.ga_data)[i];
if (STRNCMP(s, "help-tags\t", 10) == 0) {
// help-tags entry was added in formatted form
- fputs((char *)s, fd_tags);
+ fputs(s, fd_tags);
} else {
fprintf(fd_tags, "%s\t/" "*", s);
for (p1 = s; *p1 != '\t'; p1++) {
@@ -5687,16 +5740,16 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
}
/// Generate tags in one help directory, taking care of translations.
-static void do_helptags(char_u *dirname, bool add_help_tags, bool ignore_writeerr)
+static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr)
FUNC_ATTR_NONNULL_ALL
{
int len;
garray_T ga;
- char_u lang[2];
- char_u ext[5];
- char_u fname[8];
+ char lang[2];
+ char ext[5];
+ char fname[8];
int filecount;
- char_u **files;
+ char **files;
// Get a list of all files in the help directory and in subdirectories.
STRLCPY(NameBuff, dirname, sizeof(NameBuff));
@@ -5708,8 +5761,8 @@ static void do_helptags(char_u *dirname, bool add_help_tags, bool ignore_writeer
// Note: We cannot just do `&NameBuff` because it is a statically sized array
// so `NameBuff == &NameBuff` according to C semantics.
- char_u *buff_list[1] = { NameBuff };
- if (gen_expand_wildcards(1, buff_list, &filecount, &files,
+ char *buff_list[1] = { (char *)NameBuff };
+ if (gen_expand_wildcards(1, (char_u **)buff_list, &filecount, (char_u ***)&files,
EW_FILE|EW_SILENT) == FAIL
|| filecount == 0) {
semsg(_("E151: No match: %s"), NameBuff);
@@ -5734,8 +5787,8 @@ static void do_helptags(char_u *dirname, bool add_help_tags, bool ignore_writeer
&& ASCII_ISALPHA(files[i][len - 2])
&& TOLOWER_ASC(files[i][len - 1]) == 'x') {
// ".abx" -> language "ab"
- lang[0] = TOLOWER_ASC(files[i][len - 3]);
- lang[1] = TOLOWER_ASC(files[i][len - 2]);
+ lang[0] = (char)TOLOWER_ASC(files[i][len - 3]);
+ lang[1] = (char)TOLOWER_ASC(files[i][len - 2]);
} else {
continue;
}
@@ -5749,8 +5802,8 @@ static void do_helptags(char_u *dirname, bool add_help_tags, bool ignore_writeer
if (j == ga.ga_len) {
// New language, add it.
ga_grow(&ga, 2);
- ((char_u *)ga.ga_data)[ga.ga_len++] = lang[0];
- ((char_u *)ga.ga_data)[ga.ga_len++] = lang[1];
+ ((char *)ga.ga_data)[ga.ga_len++] = lang[0];
+ ((char *)ga.ga_data)[ga.ga_len++] = lang[1];
}
}
@@ -5759,8 +5812,8 @@ static void do_helptags(char_u *dirname, bool add_help_tags, bool ignore_writeer
*/
for (j = 0; j < ga.ga_len; j += 2) {
STRCPY(fname, "tags-xx");
- fname[5] = ((char_u *)ga.ga_data)[j];
- fname[6] = ((char_u *)ga.ga_data)[j + 1];
+ fname[5] = ((char *)ga.ga_data)[j];
+ fname[6] = ((char *)ga.ga_data)[j + 1];
if (fname[5] == 'e' && fname[6] == 'n') {
// English is an exception: use ".txt" and "tags".
fname[4] = NUL;
@@ -5771,26 +5824,24 @@ static void do_helptags(char_u *dirname, bool add_help_tags, bool ignore_writeer
ext[1] = fname[5];
ext[2] = fname[6];
}
- helptags_one(dirname, ext, fname, add_help_tags, ignore_writeerr);
+ helptags_one(dirname, (char *)ext, (char *)fname, add_help_tags, ignore_writeerr);
}
ga_clear(&ga);
- FreeWild(filecount, files);
+ FreeWild(filecount, (char_u **)files);
}
-static void helptags_cb(char_u *fname, void *cookie)
+static void helptags_cb(char *fname, void *cookie)
FUNC_ATTR_NONNULL_ALL
{
do_helptags(fname, *(bool *)cookie, true);
}
-/*
- * ":helptags"
- */
+/// ":helptags"
void ex_helptags(exarg_T *eap)
{
expand_T xpc;
- char_u *dirname;
+ char *dirname;
bool add_help_tags = false;
// Check for ":helptags ++t {dir}".
@@ -5804,9 +5855,9 @@ void ex_helptags(exarg_T *eap)
} else {
ExpandInit(&xpc);
xpc.xp_context = EXPAND_DIRECTORIES;
- dirname = ExpandOne(&xpc, eap->arg, NULL,
- WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
- if (dirname == NULL || !os_isdir(dirname)) {
+ dirname = (char *)ExpandOne(&xpc, (char_u *)eap->arg, NULL,
+ WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
+ if (dirname == NULL || !os_isdir((char_u *)dirname)) {
semsg(_("E150: Not a directory: %s"), eap->arg);
} else {
do_helptags(dirname, add_help_tags, false);
@@ -5815,65 +5866,36 @@ void ex_helptags(exarg_T *eap)
}
}
-/*
- * ":helpclose": Close one help window
- */
+/// ":helpclose": Close one help window
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;
}
}
}
-/// Tries to enter to an existing window of given buffer. If no existing buffer
-/// is found, creates a new split.
-///
-/// Returns OK/FAIL.
-int sub_preview_win(buf_T *preview_buf)
-{
- if (preview_buf != NULL) {
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == preview_buf) {
- win_enter(wp, false);
-
- return OK;
- }
- }
- }
- return win_split((int)p_cwh, WSP_BOT);
-}
-
/// Shows the effects of the :substitute command being typed ('inccommand').
/// If inccommand=split, shows a preview window and later restores the layout.
-static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, int hl_id,
- int src_id, handle_T bufnr)
+///
+/// @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)
FUNC_ATTR_NONNULL_ALL
{
- win_T *save_curwin = curwin;
- cmdmod_T save_cmdmod = cmdmod;
- char_u *save_shm_p = vim_strsave(p_shm);
+ char *save_shm_p = (char *)vim_strsave(p_shm);
PreviewLines lines = *preview_lines;
buf_T *orig_buf = curbuf;
-
// We keep a special-purpose buffer around, but don't assume it exists.
- buf_T *preview_buf = bufnr ? buflist_findnr(bufnr) : 0;
- cmdmod.split = 0; // disable :leftabove/botright modifiers
- cmdmod.tab = 0; // disable :tab modifier
- cmdmod.noswapfile = true; // disable swap for preview buffer
+ buf_T *cmdpreview_buf = NULL;
+
// disable file info message
- set_string_option_direct("shm", -1, (char_u *)"F", OPT_FREE,
- SID_NONE);
+ set_string_option_direct("shm", -1, "F", OPT_FREE, SID_NONE);
- bool outside_curline = (eap->line1 != old_cusr.lnum
- || eap->line2 != old_cusr.lnum);
- bool preview = outside_curline && (*p_icm != 'n');
- if (preview_buf == curbuf) { // Preview buffer cannot preview itself!
- preview = false;
- preview_buf = NULL;
- }
+ // Update the topline to ensure that main window is on the correct line
+ update_topline(curwin);
// Place cursor on nearest matching line, to undo do_sub() cursor placement.
for (size_t i = 0; i < lines.subresults.size; i++) {
@@ -5888,27 +5910,17 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines
// Width of the "| lnum|..." column which displays the line numbers.
linenr_T highest_num_line = 0;
int col_width = 0;
+ // Use preview window only when inccommand=split and range is not just the current line
+ bool preview = (*p_icm == 's') && (eap->line1 != old_cusr.lnum || eap->line2 != old_cusr.lnum);
- if (preview && sub_preview_win(preview_buf) != FAIL) {
- buf_open_scratch(preview_buf ? bufnr : 0, "[Preview]");
- buf_clear();
- preview_buf = curbuf;
- curbuf->b_p_bl = false;
- curbuf->b_p_ma = true;
- curbuf->b_p_ul = -1;
- curbuf->b_p_tw = 0; // Reset 'textwidth' (was set by ftplugin)
- curwin->w_p_cul = false;
- curwin->w_p_cuc = false;
- curwin->w_p_spell = false;
- curwin->w_p_fen = false;
+ if (preview) {
+ cmdpreview_buf = buflist_findnr(cmdpreview_bufnr);
+ assert(cmdpreview_buf != NULL);
if (lines.subresults.size > 0) {
highest_num_line = kv_last(lines.subresults).end.lnum;
- col_width = log10(highest_num_line) + 1 + 3;
+ col_width = (int)log10(highest_num_line) + 1 + 3;
}
- } else {
- // Failed to split the window, don't show 'inccommand' preview.
- preview_buf = NULL;
}
char *str = NULL; // construct the line to show in here
@@ -5918,10 +5930,13 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines
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 (preview_buf) {
+ 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
@@ -5949,7 +5964,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines
line = "";
} else {
line = (char *)ml_get_buf(orig_buf, next_linenr, false);
- line_size = strlen(line) + col_width + 1;
+ line_size = strlen(line) + (size_t)col_width + 1;
// Reallocate if line not long enough
if (line_size > old_line_size) {
@@ -5958,125 +5973,61 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines
}
}
// Put "|lnum| line" into `str` and append it to the preview buffer.
- snprintf(str, line_size, "|%*ld| %s", col_width - 3,
+ 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, (char_u *)str, true);
+ ml_replace(1, str, true);
} else {
- ml_append(linenr_preview, (char_u *)str, (colnr_T)line_size, false);
+ ml_append(linenr_preview, str, (colnr_T)line_size, false);
}
+ aucmd_restbuf(&aco);
linenr_preview += 1;
}
linenr_origbuf = match.end.lnum;
- bufhl_add_hl_pos_offset(preview_buf, src_id, hl_id, p_start,
- p_end, col_width);
+ bufhl_add_hl_pos_offset(cmdpreview_buf, (int)cmdpreview_ns, hl_id, p_start, p_end, col_width);
}
- bufhl_add_hl_pos_offset(orig_buf, src_id, hl_id, match.start,
- match.end, 0);
+ bufhl_add_hl_pos_offset(orig_buf, (int)cmdpreview_ns, hl_id, match.start, match.end, 0);
}
- xfree(str);
- redraw_later(curwin, SOME_VALID);
- win_enter(save_curwin, false); // Return to original window
- update_topline(curwin);
-
- // Update screen now.
- int save_rd = RedrawingDisabled;
- RedrawingDisabled = 0;
- update_screen(SOME_VALID);
- RedrawingDisabled = save_rd;
+ xfree(str);
set_string_option_direct("shm", -1, save_shm_p, OPT_FREE, SID_NONE);
xfree(save_shm_p);
- cmdmod = save_cmdmod;
-
- return preview_buf;
+ return preview ? 2 : 1;
}
-/// Closes any open windows for inccommand preview buffer.
-void close_preview_windows(void)
+/// :substitute command.
+void ex_substitute(exarg_T *eap)
{
- block_autocmds();
- buf_T *buf = preview_bufnr ? buflist_findnr(preview_bufnr) : NULL;
- if (buf != NULL) {
- close_windows(buf, false);
- }
- unblock_autocmds();
+ (void)do_sub(eap, profile_zero(), 0, 0);
}
-/// :substitute command
-///
-/// If 'inccommand' is empty: calls do_sub().
-/// If 'inccommand' is set: shows a "live" preview then removes the changes.
-/// from undo history.
-void ex_substitute(exarg_T *eap)
+/// :substitute command preview callback.
+int ex_substitute_preview(exarg_T *eap, long cmdpreview_ns, handle_T cmdpreview_bufnr)
{
- bool preview = (State & CMDPREVIEW);
- if (*p_icm == NUL || !preview) { // 'inccommand' is disabled
- close_preview_windows();
- (void)do_sub(eap, profile_zero(), true, preview_bufnr);
-
- return;
+ // Only preview once the pattern delimiter has been typed
+ if (*eap->arg && !ASCII_ISALNUM(*eap->arg)) {
+ char *save_eap = eap->arg;
+ int retv = do_sub(eap, profile_setlimit(p_rdt), cmdpreview_ns, cmdpreview_bufnr);
+ eap->arg = save_eap;
+ return retv;
}
- block_autocmds(); // Disable events during command preview.
-
- char_u *save_eap = eap->arg;
- garray_T save_view;
- win_size_save(&save_view); // Save current window sizes.
- save_search_patterns();
- int save_changedtick = buf_get_changedtick(curbuf);
- time_t save_b_u_time_cur = curbuf->b_u_time_cur;
- u_header_T *save_b_u_newhead = curbuf->b_u_newhead;
- long save_b_p_ul = curbuf->b_p_ul;
- int save_w_p_cul = curwin->w_p_cul;
- int save_w_p_cuc = curwin->w_p_cuc;
-
- curbuf->b_p_ul = LONG_MAX; // make sure we can undo all changes
- curwin->w_p_cul = false; // Disable 'cursorline'
- curwin->w_p_cuc = false; // Disable 'cursorcolumn'
-
- // Don't show search highlighting during live substitution
- bool save_hls = p_hls;
- p_hls = false;
- buf_T *preview_buf = do_sub(eap, profile_setlimit(p_rdt), false,
- preview_bufnr);
- p_hls = save_hls;
-
- if (preview_buf != NULL) {
- preview_bufnr = preview_buf->handle;
- }
-
- if (save_changedtick != buf_get_changedtick(curbuf)) {
- // Undo invisibly. This also moves the cursor!
- if (!u_undo_and_forget(1)) {
- abort();
- }
- // Restore newhead. It is meaningless when curhead is valid, but we must
- // restore it so that undotree() is identical before/after the preview.
- curbuf->b_u_newhead = save_b_u_newhead;
- curbuf->b_u_time_cur = save_b_u_time_cur;
- buf_set_changedtick(curbuf, save_changedtick);
- }
-
- curbuf->b_p_ul = save_b_p_ul;
- curwin->w_p_cul = save_w_p_cul; // Restore 'cursorline'
- curwin->w_p_cuc = save_w_p_cuc; // Restore 'cursorcolumn'
- eap->arg = save_eap;
- restore_search_patterns();
- win_size_restore(&save_view);
- ga_clear(&save_view);
- unblock_autocmds();
+ return 0;
}
/// Skip over the pattern argument of ":vimgrep /pat/[g][j]".
/// Put the start of the pattern in "*s", unless "s" is NULL.
-/// If "flags" is not NULL put the flags in it: VGR_GLOBAL, VGR_NOJUMP.
-/// If "s" is not NULL terminate the pattern with a NUL.
-/// Return a pointer to the char just past the pattern plus flags.
-char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags)
+///
+/// @param flags if not NULL, put the flags in it: VGR_GLOBAL, VGR_NOJUMP.
+/// @param s if not NULL, terminate the pattern with a NUL.
+///
+/// @return a pointer to the char just past the pattern plus flags.
+char *skip_vimgrep_pat(char *p, char **s, int *flags)
{
int c;
@@ -6085,7 +6036,7 @@ char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags)
if (s != NULL) {
*s = p;
}
- p = skiptowhite(p);
+ p = (char *)skiptowhite((char_u *)p);
if (s != NULL && *p != NUL) {
*p++ = NUL;
}
@@ -6094,8 +6045,8 @@ char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags)
if (s != NULL) {
*s = p + 1;
}
- c = *p;
- p = skip_regexp(p + 1, c, true, NULL);
+ c = (char_u)(*p);
+ p = (char *)skip_regexp((char_u *)p + 1, c, true, NULL);
if (*p != c) {
return NULL;
}
@@ -6107,12 +6058,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++;
@@ -6141,7 +6094,7 @@ void ex_oldfiles(exarg_T *eap)
if (!message_filtered((char_u *)fname)) {
msg_outnum(nr);
msg_puts(": ");
- msg_outtrans((char_u *)tv_get_string(TV_LIST_ITEM_TV(li)));
+ msg_outtrans((char *)tv_get_string(TV_LIST_ITEM_TV(li)));
msg_clr_eos();
msg_putchar('\n');
ui_flush(); // output one line at a time
@@ -6153,19 +6106,19 @@ void ex_oldfiles(exarg_T *eap)
got_int = false;
// File selection prompt on ":browse oldfiles"
- if (cmdmod.browse) {
+ if (cmdmod.cmod_flags & CMOD_BROWSE) {
quit_more = false;
nr = prompt_for_number(false);
msg_starthere();
if (nr > 0 && nr <= tv_list_len(l)) {
- const char *const p = tv_list_find_str(l, nr - 1);
+ const char *const p = tv_list_find_str(l, (int)nr - 1);
if (p == NULL) {
return;
}
- char *const s = (char *)expand_env_save((char_u *)p);
- eap->arg = (char_u *)s;
+ char *const s = expand_env_save((char *)p);
+ eap->arg = s;
eap->cmdidx = CMD_edit;
- cmdmod.browse = false;
+ cmdmod.cmod_flags &= ~CMOD_BROWSE;
do_exedit(eap, NULL);
xfree(s);
}