aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ops.c')
-rw-r--r--src/nvim/ops.c1425
1 files changed, 788 insertions, 637 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index ef9fe055ac..3602eb2a3e 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -56,7 +56,6 @@
#include "nvim/undo.h"
#include "nvim/vim.h"
#include "nvim/window.h"
-
#include "nvim/yankmap.h"
struct yank_registers {
@@ -152,10 +151,18 @@ static char opchars[][3] =
{ Ctrl_X, NUL, OPF_CHANGE }, // OP_NR_SUB
};
-/*
- * Translate a command name into an operator type.
- * Must only be called with a valid operator name!
- */
+yankreg_T *get_y_previous(void)
+{
+ return y_previous;
+}
+
+void set_y_previous(yankreg_T *yreg)
+{
+ y_previous = yreg;
+}
+
+/// Translate a command name into an operator type.
+/// Must only be called with a valid operator name!
int get_op_type(int char1, int char2)
{
int i;
@@ -191,40 +198,33 @@ int get_op_type(int char1, int char2)
return i;
}
-/*
- * Return TRUE if operator "op" always works on whole lines.
- */
+/// @return TRUE if operator "op" always works on whole lines.
int op_on_lines(int op)
{
return opchars[op][2] & OPF_LINES;
}
-// Return TRUE if operator "op" changes text.
+/// @return TRUE if operator "op" changes text.
int op_is_change(int op)
{
return opchars[op][2] & OPF_CHANGE;
}
-/*
- * Get first operator command character.
- * Returns 'g' or 'z' if there is another command character.
- */
+/// Get first operator command character.
+///
+/// @return 'g' or 'z' if there is another command character.
int get_op_char(int optype)
{
return opchars[optype][0];
}
-/*
- * Get second operator command character.
- */
+/// Get second operator command character.
int get_extra_op_char(int optype)
{
return opchars[optype][1];
}
-/*
- * op_shift - handle a shift operation
- */
+/// handle a shift operation
void op_shift(oparg_T *oap, int curs_top, int amount)
{
long i;
@@ -284,14 +284,14 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
msg_attr_keep((char *)IObuff, 0, true, false);
}
- /*
- * Set "'[" and "']" marks.
- */
- curbuf->b_op_start = oap->start;
- curbuf->b_op_end.lnum = oap->end.lnum;
- curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
- if (curbuf->b_op_end.col > 0) {
- curbuf->b_op_end.col--;
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // Set "'[" and "']" marks.
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end.lnum = oap->end.lnum;
+ curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ if (curbuf->b_op_end.col > 0) {
+ curbuf->b_op_end.col--;
+ }
}
changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L, true);
@@ -343,10 +343,8 @@ void shift_line(int left, int round, int amount, int call_changed_bytes)
}
}
-/*
- * Shift one line of the current block one shiftwidth right or left.
- * Leaves cursor on first character in block.
- */
+/// Shift one line of the current block one shiftwidth right or left.
+/// Leaves cursor on first character in block.
static void shift_block(oparg_T *oap, int amount)
{
const bool left = (oap->op_type == OP_LSHIFT);
@@ -363,7 +361,7 @@ static void shift_block(oparg_T *oap, int amount)
p_ri = 0; // don't want revins in indent
- State = INSERT; // don't want REPLACE for State
+ State = MODE_INSERT; // don't want MODE_REPLACE for State
block_prep(oap, &bd, curwin->w_cursor.lnum, true);
if (bd.is_short) {
return;
@@ -390,7 +388,7 @@ static void shift_block(oparg_T *oap, int amount)
colnr_T ws_vcol = bd.start_vcol - bd.pre_whitesp;
char_u *old_textstart = bd.textstart;
if (bd.startspaces) {
- if (utfc_ptr2len(bd.textstart) == 1) {
+ if (utfc_ptr2len((char *)bd.textstart) == 1) {
bd.textstart++;
} else {
ws_vcol = 0;
@@ -398,8 +396,8 @@ static void shift_block(oparg_T *oap, int amount)
}
}
for (; ascii_iswhite(*bd.textstart);) {
- // TODO: is passing bd.textstart for start of the line OK?
- incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, (bd.start_vcol));
+ // TODO(fmoralesc): is passing bd.textstart for start of the line OK?
+ incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, bd.start_vcol);
total += incr;
bd.start_vcol += incr;
}
@@ -415,14 +413,14 @@ static void shift_block(oparg_T *oap, int amount)
int col_pre = bd.pre_whitesp_c - (bd.startspaces != 0);
bd.textcol -= col_pre;
const int len = (int)STRLEN(bd.textstart) + 1;
- int col = bd.textcol + i +j + len;
+ int col = bd.textcol + i + j + len;
assert(col >= 0);
newp = (char_u *)xmalloc((size_t)col);
memset(newp, NUL, (size_t)col);
memmove(newp, oldp, (size_t)bd.textcol);
startcol = bd.textcol;
- oldlen = (int)(bd.textstart-old_textstart) + col_pre;
- newlen = i+j;
+ oldlen = (int)(bd.textstart - old_textstart) + col_pre;
+ newlen = i + j;
memset(newp + bd.textcol, TAB, (size_t)i);
memset(newp + bd.textcol + i, ' ', (size_t)j);
// the end
@@ -462,7 +460,6 @@ static void shift_block(oparg_T *oap, int amount)
non_white_col += incr;
}
-
const colnr_T block_space_width = non_white_col - oap->start_vcol;
// We will shift by "total" or "block_space_width", whichever is less.
const colnr_T shift_amount = block_space_width < total
@@ -517,9 +514,9 @@ static void shift_block(oparg_T *oap, int amount)
STRMOVE(newp + verbatim_diff + fill, non_white);
}
// replace the line
- ml_replace(curwin->w_cursor.lnum, newp, false);
+ ml_replace(curwin->w_cursor.lnum, (char *)newp, false);
changed_bytes(curwin->w_cursor.lnum, bd.textcol);
- extmark_splice_cols(curbuf, (int)curwin->w_cursor.lnum-1, startcol,
+ extmark_splice_cols(curbuf, (int)curwin->w_cursor.lnum - 1, startcol,
oldlen, newlen,
kExtmarkUndo);
State = oldstate;
@@ -527,10 +524,8 @@ static void shift_block(oparg_T *oap, int amount)
p_ri = old_p_ri;
}
-/*
- * Insert string "s" (b_insert ? before : after) block :AKelly
- * Caller must prepare for undo.
- */
+/// Insert string "s" (b_insert ? before : after) block :AKelly
+/// Caller must prepare for undo.
static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def *bdp)
{
int p_ts;
@@ -541,7 +536,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
char_u *newp, *oldp; // new, old lines
linenr_T lnum; // loop var
int oldstate = State;
- State = INSERT; // don't want REPLACE for State
+ State = MODE_INSERT; // don't want MODE_REPLACE for State
for (lnum = oap->start.lnum + 1; lnum <= oap->end.lnum; lnum++) {
block_prep(oap, bdp, lnum, true);
@@ -577,21 +572,18 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
}
if (spaces > 0) {
- int off;
-
- // Avoid starting halfway through a multi-byte character.
- if (b_insert) {
- off = utf_head_off(oldp, oldp + offset + spaces);
- } else {
- off = (*mb_off_next)(oldp, oldp + offset);
- offset += off;
- }
- spaces -= off;
- count -= off;
+ // avoid copying part of a multi-byte character
+ offset -= utf_head_off(oldp, oldp + offset);
+ }
+ if (spaces < 0) { // can happen when the cursor was moved
+ spaces = 0;
}
assert(count >= 0);
- newp = (char_u *)xmalloc(STRLEN(oldp) + s_len + (size_t)count + 1);
+ // Make sure the allocated size matches what is actually copied below.
+ newp = xmalloc(STRLEN(oldp) + (size_t)spaces + s_len
+ + (spaces > 0 && !bdp->is_short ? (size_t)p_ts - (size_t)spaces : 0)
+ + (size_t)count + 1);
// copy up to shifted part
memmove(newp, oldp, (size_t)offset);
@@ -606,14 +598,19 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
offset += (int)s_len;
int skipped = 0;
- if (spaces && !bdp->is_short) {
- // insert post-padding
- memset(newp + offset + spaces, ' ', (size_t)(p_ts - spaces));
- // We're splitting a TAB, don't copy it.
- oldp++;
- // We allowed for that TAB, remember this now
- count++;
- skipped = 1;
+ if (spaces > 0 && !bdp->is_short) {
+ if (*oldp == TAB) {
+ // insert post-padding
+ memset(newp + offset + spaces, ' ', (size_t)(p_ts - spaces));
+ // We're splitting a TAB, don't copy it.
+ oldp++;
+ // We allowed for that TAB, remember this now
+ count++;
+ skipped = 1;
+ } else {
+ // Not a TAB, no extra spaces
+ count = spaces;
+ }
}
if (spaces > 0) {
@@ -621,9 +618,9 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
}
STRMOVE(newp + offset, oldp);
- ml_replace(lnum, newp, false);
- extmark_splice_cols(curbuf, (int)lnum-1, startcol,
- skipped, offset-startcol, kExtmarkUndo);
+ ml_replace(lnum, (char *)newp, false);
+ extmark_splice_cols(curbuf, (int)lnum - 1, startcol,
+ skipped, offset - startcol, kExtmarkUndo);
if (lnum == oap->end.lnum) {
// Set "']" mark to the end of the block instead of the end of
@@ -638,12 +635,10 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
State = oldstate;
}
-/*
- * op_reindent - handle reindenting a block of lines.
- */
+/// Handle reindenting a block of lines.
void op_reindent(oparg_T *oap, Indenter how)
{
- long i;
+ long i = 0;
char_u *l;
int amount;
linenr_T first_changed = 0;
@@ -656,38 +651,41 @@ void op_reindent(oparg_T *oap, Indenter how)
return;
}
- for (i = oap->line_count - 1; i >= 0 && !got_int; i--) {
- /* it's a slow thing to do, so give feedback so there's no worry that
- * the computer's just hung. */
+ // Save for undo. Do this once for all lines, much faster than doing this
+ // for each line separately, especially when undoing.
+ if (u_savecommon(curbuf, start_lnum - 1, start_lnum + (linenr_T)oap->line_count,
+ start_lnum + (linenr_T)oap->line_count, false) == OK) {
+ for (i = oap->line_count - 1; i >= 0 && !got_int; i--) {
+ // it's a slow thing to do, so give feedback so there's no worry
+ // that the computer's just hung.
- if (i > 1
- && (i % 50 == 0 || i == oap->line_count - 1)
- && oap->line_count > p_report) {
- smsg(_("%" PRId64 " lines to indent... "), (int64_t)i);
- }
-
- /*
- * Be vi-compatible: For lisp indenting the first line is not
- * indented, unless there is only one line.
- */
- if (i != oap->line_count - 1 || oap->line_count == 1
- || how != get_lisp_indent) {
- l = skipwhite(get_cursor_line_ptr());
- if (*l == NUL) { // empty or blank line
- amount = 0;
- } else {
- amount = how(); // get the indent for this line
+ if (i > 1
+ && (i % 50 == 0 || i == oap->line_count - 1)
+ && oap->line_count > p_report) {
+ smsg(_("%" PRId64 " lines to indent... "), (int64_t)i);
}
- if (amount >= 0 && set_indent(amount, SIN_UNDO)) {
- // did change the indent, call changed_lines() later
- if (first_changed == 0) {
- first_changed = curwin->w_cursor.lnum;
+
+ // Be vi-compatible: For lisp indenting the first line is not
+ // indented, unless there is only one line.
+ if (i != oap->line_count - 1 || oap->line_count == 1
+ || how != get_lisp_indent) {
+ l = (char_u *)skipwhite((char *)get_cursor_line_ptr());
+ if (*l == NUL) { // empty or blank line
+ amount = 0;
+ } else {
+ amount = how(); // get the indent for this line
+ }
+ if (amount >= 0 && set_indent(amount, 0)) {
+ // did change the indent, call changed_lines() later
+ if (first_changed == 0) {
+ first_changed = curwin->w_cursor.lnum;
+ }
+ last_changed = curwin->w_cursor.lnum;
}
- last_changed = curwin->w_cursor.lnum;
}
+ curwin->w_cursor.lnum++;
+ curwin->w_cursor.col = 0; // make sure it's valid
}
- ++curwin->w_cursor.lnum;
- curwin->w_cursor.col = 0; // make sure it's valid
}
// put cursor on first non-blank of indented line
@@ -699,7 +697,7 @@ void op_reindent(oparg_T *oap, Indenter how)
* there is no change still need to remove the Visual highlighting. */
if (last_changed != 0) {
changed_lines(first_changed, 0,
- oap->is_VIsual ? start_lnum + oap->line_count :
+ oap->is_VIsual ? start_lnum + (linenr_T)oap->line_count :
last_changed + 1, 0L, true);
} else if (oap->is_VIsual) {
redraw_curbuf_later(INVERTED);
@@ -711,9 +709,11 @@ void op_reindent(oparg_T *oap, Indenter how)
"%" PRId64 " lines indented ", i),
(int64_t)i);
}
- // set '[ and '] marks
- curbuf->b_op_start = oap->start;
- curbuf->b_op_end = oap->end;
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // set '[ and '] marks
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end = oap->end;
+ }
}
/*
@@ -721,10 +721,9 @@ void op_reindent(oparg_T *oap, Indenter how)
*/
static char_u *expr_line = NULL;
-/*
- * Get an expression for the "\"=expr1" or "CTRL-R =expr1"
- * Returns '=' when OK, NUL otherwise.
- */
+/// Get an expression for the "\"=expr1" or "CTRL-R =expr1"
+///
+/// @return '=' when OK, NUL otherwise.
int get_expr_register(void)
{
char_u *new_line;
@@ -741,20 +740,17 @@ int get_expr_register(void)
return '=';
}
-/*
- * Set the expression for the '=' register.
- * Argument must be an allocated string.
- */
+/// Set the expression for the '=' register.
+/// Argument must be an allocated string.
void set_expr_line(char_u *new_line)
{
xfree(expr_line);
expr_line = new_line;
}
-/*
- * Get the result of the '=' register expression.
- * Returns a pointer to allocated memory, or NULL for failure.
- */
+/// Get the result of the '=' register expression.
+///
+/// @return a pointer to allocated memory, or NULL for failure.
char_u *get_expr_line(void)
{
char_u *expr_copy;
@@ -776,15 +772,13 @@ char_u *get_expr_line(void)
}
nested++;
- rv = eval_to_string(expr_copy, NULL, true);
+ rv = (char_u *)eval_to_string((char *)expr_copy, NULL, true);
nested--;
xfree(expr_copy);
return rv;
}
-/*
- * Get the '=' register expression itself, without evaluating it.
- */
+/// Get the '=' register expression itself, without evaluating it.
char_u *get_expr_line_src(void)
{
if (expr_line == NULL) {
@@ -793,6 +787,7 @@ char_u *get_expr_line_src(void)
return vim_strsave(expr_line);
}
+
int get_userreg(int regname)
{
if ((regname >= 'a' && regname <= 'z')
@@ -810,8 +805,9 @@ int get_userreg(int regname)
return regname + USER_REGISTERS_START;
}
-/// Returns whether `regname` is a valid name of a yank register.
-/// Note: There is no check for 0 (default register), caller should do this.
+/// @return whether `regname` is a valid name of a yank register.
+///
+/// @note: There is no check for 0 (default register), caller should do this.
/// The black hole register '_' is regarded as valid.
///
/// @param regname name of register
@@ -819,7 +815,7 @@ int get_userreg(int regname)
bool valid_yank_reg(int regname, bool writing)
{
if ((regname > 0 && ASCII_ISALNUM(regname))
- || (!writing && vim_strchr((char_u *)"/.%:=", regname) != NULL)
+ || (!writing && vim_strchr("/.%:=", regname) != NULL)
|| regname == '#'
|| regname == '"'
|| regname == '-'
@@ -832,7 +828,7 @@ bool valid_yank_reg(int regname, bool writing)
return false;
}
-/// Return yankreg_T to use, according to the value of `regname`.
+/// @return yankreg_T to use, according to the value of `regname`.
/// Cannot handle the '_' (black hole) register.
/// Must only be called with a valid register name!
///
@@ -892,8 +888,8 @@ static inline bool is_literal_register(int regname)
return regname == '*' || regname == '+';
}
-/// Returns a copy of contents in register `name`
-/// for use in do_put. Should be freed by caller.
+/// @return a copy of contents in register `name` for use in do_put. Should be
+/// freed by caller.
yankreg_T *copy_register(int name)
FUNC_ATTR_NONNULL_RET
{
@@ -904,15 +900,15 @@ yankreg_T *copy_register(int name)
if (copy->y_size == 0) {
copy->y_array = NULL;
} else {
- copy->y_array = xcalloc(copy->y_size, sizeof(char_u *));
+ copy->y_array = xcalloc(copy->y_size, sizeof(char *));
for (size_t i = 0; i < copy->y_size; i++) {
- copy->y_array[i] = vim_strsave(reg->y_array[i]);
+ copy->y_array[i] = xstrdup(reg->y_array[i]);
}
}
return copy;
}
-/// check if the current yank register has kMTLineWise register type
+/// Check if the current yank register has kMTLineWise register type
bool yank_register_mline(int regname)
{
if (regname != 0 && !valid_yank_reg(regname, false)) {
@@ -925,11 +921,9 @@ bool yank_register_mline(int regname)
return reg->y_type == kMTLineWise;
}
-/*
- * Start or stop recording into a yank register.
- *
- * Return FAIL for failure, OK otherwise.
- */
+/// Start or stop recording into a yank register.
+///
+/// @return FAIL for failure, OK otherwise.
int do_record(int c)
{
char_u *p;
@@ -957,18 +951,19 @@ int do_record(int c)
// The recorded text contents.
p = get_recorded();
if (p != NULL) {
- // Remove escaping for CSI and K_SPECIAL in multi-byte chars.
- vim_unescape_csi(p);
+ // Remove escaping for K_SPECIAL in multi-byte chars.
+ vim_unescape_ks(p);
(void)tv_dict_add_str(dict, S_LEN("regcontents"), (const char *)p);
}
// Name of requested register, or empty string for unnamed operation.
- char buf[NUMBUFLEN+2];
+ char buf[NUMBUFLEN + 2];
buf[0] = (char)regname;
buf[1] = NUL;
(void)tv_dict_add_str(dict, S_LEN("regname"), buf);
+ tv_dict_set_keys_readonly(dict);
- // Get the recorded key hits. K_SPECIAL and CSI will be escaped, this
+ // Get the recorded key hits. K_SPECIAL will be escaped, this
// needs to be removed again to put it in a register. exec_reg then
// adds the escaping back later.
apply_autocmds(EVENT_RECORDINGLEAVE, NULL, NULL, false, curbuf);
@@ -1005,12 +1000,10 @@ static void set_yreg_additional_data(yankreg_T *reg, dict_T *additional_data)
reg->additional_data = additional_data;
}
-/*
- * Stuff string "p" into yank register "regname" as a single line (append if
- * uppercase). "p" must have been allocated.
- *
- * return FAIL for failure, OK otherwise
- */
+/// Stuff string "p" into yank register "regname" as a single line (append if
+/// uppercase). "p" must have been allocated.
+///
+/// @return FAIL for failure, OK otherwise
static int stuff_yank(int regname, char_u *p)
{
// check for read-only register
@@ -1024,7 +1017,7 @@ static int stuff_yank(int regname, char_u *p)
}
yankreg_T *reg = get_yank_register(regname, YREG_YANK);
if (is_append_register(regname) && reg->y_array != NULL) {
- char_u **pp = &(reg->y_array[reg->y_size - 1]);
+ char_u **pp = (char_u **)&(reg->y_array[reg->y_size - 1]);
char_u *lp = xmalloc(STRLEN(*pp) + STRLEN(p) + 1);
STRCPY(lp, *pp);
// TODO(philix): use xstpcpy() in stuff_yank()
@@ -1035,8 +1028,8 @@ static int stuff_yank(int regname, char_u *p)
} else {
free_register(reg);
set_yreg_additional_data(reg, NULL);
- reg->y_array = (char_u **)xmalloc(sizeof(char_u *));
- reg->y_array[0] = p;
+ reg->y_array = xmalloc(sizeof(char_u *));
+ reg->y_array[0] = (char *)p;
reg->y_size = 1;
reg->y_type = kMTCharWise;
}
@@ -1046,6 +1039,60 @@ static int stuff_yank(int regname, char_u *p)
static int execreg_lastc = NUL;
+/// When executing a register as a series of ex-commands, if the
+/// line-continuation character is used for a line, then join it with one or
+/// more previous lines. Note that lines are processed backwards starting from
+/// the last line in the register.
+///
+/// @param lines list of lines in the register
+/// @param idx index of the line starting with \ or "\. Join this line with all the immediate
+/// predecessor lines that start with a \ and the first line that doesn't start
+/// with a \. Lines that start with a comment "\ character are ignored.
+/// @returns the concatenated line. The index of the line that should be
+/// processed next is returned in idx.
+static char_u *execreg_line_continuation(char_u **lines, size_t *idx)
+{
+ size_t i = *idx;
+ assert(i > 0);
+ const size_t cmd_end = i;
+
+ garray_T ga;
+ ga_init(&ga, (int)sizeof(char_u), 400);
+
+ char_u *p;
+
+ // search backwards to find the first line of this command.
+ // Any line not starting with \ or "\ is the start of the
+ // command.
+ while (--i > 0) {
+ p = (char_u *)skipwhite((char *)lines[i]);
+ if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' ')) {
+ break;
+ }
+ }
+ const size_t cmd_start = i;
+
+ // join all the lines
+ ga_concat(&ga, (char *)lines[cmd_start]);
+ for (size_t j = cmd_start + 1; j <= cmd_end; j++) {
+ p = (char_u *)skipwhite((char *)lines[j]);
+ if (*p == '\\') {
+ // Adjust the growsize to the current length to
+ // speed up concatenating many lines.
+ if (ga.ga_len > 400) {
+ ga_set_growsize(&ga, MIN(ga.ga_len, 8000));
+ }
+ ga_concat(&ga, (char *)(p + 1));
+ }
+ }
+ ga_append(&ga, NUL);
+ char_u *str = vim_strsave(ga.ga_data);
+ ga_clear(&ga);
+
+ *idx = i;
+ return str;
+}
+
/// Execute a yank register: copy it into the stuff buffer
///
/// @param colon insert ':' before each line
@@ -1126,22 +1173,36 @@ int do_execreg(int regname, int colon, int addcr, int silent)
* Insert lines into typeahead buffer, from last one to first one.
*/
put_reedit_in_typebuf(silent);
- char_u *escaped;
+ char *escaped;
for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included
// insert NL between lines and after last line if type is kMTLineWise
if (reg->y_type == kMTLineWise || i < reg->y_size - 1 || addcr) {
- if (ins_typebuf((char_u *)"\n", remap, 0, true, silent) == FAIL) {
+ if (ins_typebuf("\n", remap, 0, true, silent) == FAIL) {
return FAIL;
}
}
- escaped = vim_strsave_escape_csi(reg->y_array[i]);
+
+ // Handle line-continuation for :@<register>
+ char_u *str = (char_u *)reg->y_array[i];
+ bool free_str = false;
+ if (colon && i > 0) {
+ p = (char_u *)skipwhite((char *)str);
+ if (*p == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' ')) {
+ str = execreg_line_continuation((char_u **)reg->y_array, &i);
+ free_str = true;
+ }
+ }
+ escaped = vim_strsave_escape_ks((char *)str);
+ if (free_str) {
+ xfree(str);
+ }
retval = ins_typebuf(escaped, remap, 0, true, silent);
xfree(escaped);
if (retval == FAIL) {
return FAIL;
}
if (colon
- && ins_typebuf((char_u *)":", remap, 0, true, silent) == FAIL) {
+ && ins_typebuf(":", remap, 0, true, silent) == FAIL) {
return FAIL;
}
}
@@ -1150,10 +1211,8 @@ int do_execreg(int regname, int colon, int addcr, int silent)
return retval;
}
-/*
- * If "restart_edit" is not zero, put it in the typeahead buffer, so that it's
- * used only after other typeahead has been processed.
- */
+/// If "restart_edit" is not zero, put it in the typeahead buffer, so that it's
+/// used only after other typeahead has been processed.
static void put_reedit_in_typebuf(int silent)
{
char_u buf[3];
@@ -1167,7 +1226,7 @@ static void put_reedit_in_typebuf(int silent)
buf[0] = (char_u)(restart_edit == 'I' ? 'i' : restart_edit);
buf[1] = NUL;
}
- if (ins_typebuf(buf, REMAP_NONE, 0, true, silent) == OK) {
+ if (ins_typebuf((char *)buf, REMAP_NONE, 0, true, silent) == OK) {
restart_edit = NUL;
}
}
@@ -1176,7 +1235,7 @@ static void put_reedit_in_typebuf(int silent)
/// Insert register contents "s" into the typeahead buffer, so that it will be
/// executed again.
///
-/// @param esc when true then it is to be taken literally: Escape CSI
+/// @param esc when true then it is to be taken literally: Escape K_SPECIAL
/// characters and no remapping.
/// @param colon add ':' before the line
static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent)
@@ -1185,15 +1244,15 @@ static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent)
put_reedit_in_typebuf(silent);
if (colon) {
- retval = ins_typebuf((char_u *)"\n", REMAP_NONE, 0, true, silent);
+ retval = ins_typebuf("\n", REMAP_NONE, 0, true, silent);
}
if (retval == OK) {
- char_u *p;
+ char *p;
if (esc) {
- p = vim_strsave_escape_csi(s);
+ p = vim_strsave_escape_ks((char *)s);
} else {
- p = s;
+ p = (char *)s;
}
if (p == NULL) {
retval = FAIL;
@@ -1205,7 +1264,7 @@ static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent)
}
}
if (colon && retval == OK) {
- retval = ins_typebuf((char_u *)":", REMAP_NONE, 0, true, silent);
+ retval = ins_typebuf(":", REMAP_NONE, 0, true, silent);
}
return retval;
}
@@ -1316,19 +1375,19 @@ bool get_spec_reg(int regname, char_u **argp, bool *allocated, bool errmsg);
*/
static int eval_urf_put(char_u *ufn, int regname, char_u **argp)
{
- char_u regname_str[5];
+ char regname_str[5];
int len;
len = (*utf_char2len)(regname);
regname_str[len] = 0;
- utf_char2bytes(regname, regname_str);
+ utf_char2bytes(regname, (char*) regname_str);
typval_T args[3];
args[0].v_type = VAR_STRING;
args[1].v_type = VAR_STRING;
args[2].v_type = VAR_UNKNOWN;
- args[0].vval.v_string = (char_u *)"put";
+ args[0].vval.v_string = "put";
args[1].vval.v_string = regname_str;
*argp = (char_u *)call_func_retstr((char *)ufn, 3, args);
@@ -1344,11 +1403,11 @@ static int eval_yank_userreg(const char_u *ufn, int regname, yankreg_T *reg)
if (!reg)
return -1;
- char_u *totalbuf;
+ char *totalbuf;
size_t totallen = 0;
size_t i, j, k;
int ret, len;
- char_u regname_str[5];
+ char regname_str[5];
{
// Concat the contents of the register to pass into the yank()
@@ -1379,11 +1438,11 @@ static int eval_yank_userreg(const char_u *ufn, int regname, yankreg_T *reg)
args[2].v_type = VAR_STRING;
args[3].v_type = VAR_UNKNOWN;
- args[0].vval.v_string = (char_u *)"yank";
+ args[0].vval.v_string = "yank";
args[1].vval.v_string = regname_str;
args[2].vval.v_string = totalbuf;
- char_u *dup_ufn = (char_u *)xstrdup((char *)ufn);
+ char *dup_ufn = strdup((char *)ufn);
ret = (int)call_func_retnr(dup_ufn, 3, args);
xfree(dup_ufn);
xfree(totalbuf);
@@ -1408,11 +1467,11 @@ bool get_spec_reg(
if (errmsg) {
check_fname(); // will give emsg if not set
}
- *argp = curbuf->b_fname;
+ *argp = (char_u *)curbuf->b_fname;
return true;
case '#': // alternate file name
- *argp = getaltfname(errmsg); // may give emsg if not set
+ *argp = (char_u *)getaltfname(errmsg); // may give emsg if not set
return true;
case '=': // result of expression
@@ -1510,7 +1569,7 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
}
for (size_t i = 0; i < reg->y_size; i++) {
- cmdline_paste_str(reg->y_array[i], literally);
+ cmdline_paste_str((char_u *)reg->y_array[i], literally);
// Insert ^M between lines, unless `remcr` is true.
if (i < reg->y_size - 1 && !remcr) {
@@ -1527,7 +1586,7 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
return OK;
}
-// Shift the delete registers: "9 is cleared, "8 becomes "9, etc.
+/// Shift the delete registers: "9 is cleared, "8 becomes "9, etc.
static void shift_delete_registers(bool y_append)
{
free_register(get_global_reg(9)); // free register "9
@@ -1540,11 +1599,9 @@ static void shift_delete_registers(bool y_append)
get_global_reg(1)->y_array = NULL; // set register "1 to empty
}
-/*
- * Handle a delete operation.
- *
- * Return FAIL if undo failed, OK otherwise.
- */
+/// Handle a delete operation.
+///
+/// @return FAIL if undo failed, OK otherwise.
int op_delete(oparg_T *oap)
{
int n;
@@ -1568,6 +1625,11 @@ int op_delete(oparg_T *oap)
return FAIL;
}
+ if (VIsual_select && oap->is_VIsual) {
+ // Use the register given with CTRL_R, defaults to zero
+ oap->regname = VIsual_select_reg;
+ }
+
mb_adjust_opend(oap);
/*
@@ -1584,7 +1646,7 @@ int op_delete(oparg_T *oap)
if (*ptr != NUL) {
ptr += oap->inclusive;
}
- ptr = skipwhite(ptr);
+ ptr = (char_u *)skipwhite((char *)ptr);
if (*ptr == NUL && inindent(0)) {
oap->motion_type = kMTLineWise;
}
@@ -1620,20 +1682,20 @@ int op_delete(oparg_T *oap)
yankreg_T *reg = NULL;
int did_yank = false;
if (oap->regname != 0) {
- // yank without message
- did_yank = op_yank(oap, false, true);
- if (!did_yank) {
- // op_yank failed, don't do anything
+ // check for read-only register
+ if (!valid_yank_reg(oap->regname, true)) {
+ beep_flush();
return OK;
}
+ reg = get_yank_register(oap->regname, YREG_YANK); // yank into specif'd reg
+ op_yank_reg(oap, false, reg, is_append_register(oap->regname)); // yank without message
+ did_yank = true;
}
- /*
- * Put deleted text into register 1 and shift number registers if the
- * delete contains a line break, or when a regname has been specified.
- */
- if (oap->regname != 0 || oap->motion_type == kMTLineWise
- || oap->line_count > 1 || oap->use_reg_one) {
+ // Put deleted text into register 1 and shift number registers if the
+ // delete contains a line break, or when using a specific operator (Vi
+ // compatible)
+ if (oap->motion_type == kMTLineWise || oap->line_count > 1 || oap->use_reg_one) {
shift_delete_registers(is_append_register(oap->regname));
reg = get_global_reg(1);
op_yank_reg(oap, false, reg, false);
@@ -1694,10 +1756,10 @@ int op_delete(oparg_T *oap)
oldp += bd.textcol + bd.textlen;
STRMOVE(newp + bd.textcol + bd.startspaces + bd.endspaces, oldp);
// replace the line
- ml_replace(lnum, newp, false);
+ ml_replace(lnum, (char *)newp, false);
- extmark_splice_cols(curbuf, (int)lnum-1, bd.textcol,
- bd.textlen, bd.startspaces+bd.endspaces,
+ extmark_splice_cols(curbuf, (int)lnum - 1, bd.textcol,
+ bd.textlen, bd.startspaces + bd.endspaces,
kExtmarkUndo);
}
@@ -1732,7 +1794,7 @@ int op_delete(oparg_T *oap)
truncate_line(false); // delete the rest of the line
extmark_splice_cols(curbuf,
- (int)curwin->w_cursor.lnum-1, curwin->w_cursor.col,
+ (int)curwin->w_cursor.lnum - 1, curwin->w_cursor.col,
old_len - curwin->w_cursor.col, 0, kExtmarkUndo);
// leave cursor past last char in line
@@ -1852,8 +1914,8 @@ int op_delete(oparg_T *oap)
curwin->w_cursor = curpos; // restore curwin->w_cursor
(void)do_join(2, false, false, false, false);
curbuf_splice_pending--;
- extmark_splice(curbuf, (int)startpos.lnum-1, startpos.col,
- (int)oap->line_count-1, n, deleted_bytes,
+ extmark_splice(curbuf, (int)startpos.lnum - 1, startpos.col,
+ (int)oap->line_count - 1, n, deleted_bytes,
0, 0, 0, kExtmarkUndo);
}
if (oap->op_type == OP_DELETE) {
@@ -1864,59 +1926,53 @@ int op_delete(oparg_T *oap)
msgmore(curbuf->b_ml.ml_line_count - old_lcount);
setmarks:
- if (oap->motion_type == kMTBlockWise) {
- curbuf->b_op_end.lnum = oap->end.lnum;
- curbuf->b_op_end.col = oap->start.col;
- } else {
- curbuf->b_op_end = oap->start;
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ if (oap->motion_type == kMTBlockWise) {
+ curbuf->b_op_end.lnum = oap->end.lnum;
+ curbuf->b_op_end.col = oap->start.col;
+ } else {
+ curbuf->b_op_end = oap->start;
+ }
+ curbuf->b_op_start = oap->start;
}
- curbuf->b_op_start = oap->start;
return OK;
}
-/*
- * Adjust end of operating area for ending on a multi-byte character.
- * Used for deletion.
- */
+/// Adjust end of operating area for ending on a multi-byte character.
+/// Used for deletion.
static void mb_adjust_opend(oparg_T *oap)
{
- char_u *p;
-
if (oap->inclusive) {
- p = ml_get(oap->end.lnum);
+ char *p = (char *)ml_get(oap->end.lnum);
oap->end.col += mb_tail_off(p, p + oap->end.col);
}
}
-/*
- * Put character 'c' at position 'lp'
- */
+/// Put character 'c' at position 'lp'
static inline void pbyte(pos_T lp, int c)
{
assert(c <= UCHAR_MAX);
*(ml_get_buf(curbuf, lp.lnum, true) + lp.col) = (char_u)c;
if (!curbuf_splice_pending) {
- extmark_splice_cols(curbuf, (int)lp.lnum-1, lp.col, 1, 1, kExtmarkUndo);
+ extmark_splice_cols(curbuf, (int)lp.lnum - 1, lp.col, 1, 1, kExtmarkUndo);
}
}
-// Replace the character under the cursor with "c".
-// This takes care of multi-byte characters.
+/// Replace the character under the cursor with "c".
+/// This takes care of multi-byte characters.
static void replace_character(int c)
{
const int n = State;
- State = REPLACE;
+ State = MODE_REPLACE;
ins_char(c);
State = n;
// Backup to the replaced character.
dec_cursor();
}
-/*
- * Replace a whole area with one character.
- */
+/// Replace a whole area with one character.
static int op_replace(oparg_T *oap, int c)
{
int n, numc;
@@ -2025,7 +2081,7 @@ static int op_replace(oparg_T *oap, int c)
// strlen(newp) at this point
int newp_len = bd.textcol + bd.startspaces;
while (--num_chars >= 0) {
- newp_len += utf_char2bytes(c, newp + newp_len);
+ newp_len += utf_char2bytes(c, (char *)newp + newp_len);
}
if (!bd.is_short) {
// insert post-spaces
@@ -2043,19 +2099,19 @@ static int op_replace(oparg_T *oap, int c)
newrows = 1;
}
// replace the line
- ml_replace(curwin->w_cursor.lnum, newp, false);
+ ml_replace(curwin->w_cursor.lnum, (char *)newp, false);
curbuf_splice_pending++;
linenr_T baselnum = curwin->w_cursor.lnum;
if (after_p != NULL) {
- ml_append(curwin->w_cursor.lnum++, after_p, (int)after_p_len, false);
+ ml_append(curwin->w_cursor.lnum++, (char *)after_p, (int)after_p_len, false);
appended_lines_mark(curwin->w_cursor.lnum, 1L);
oap->end.lnum++;
xfree(after_p);
}
curbuf_splice_pending--;
- extmark_splice(curbuf, (int)baselnum-1, bd.textcol,
+ extmark_splice(curbuf, (int)baselnum - 1, bd.textcol,
0, bd.textlen, bd.textlen,
- newrows, newcols, newrows+newcols, kExtmarkUndo);
+ newrows, newcols, newrows + newcols, kExtmarkUndo);
}
} else {
// Characterwise or linewise motion replace.
@@ -2075,11 +2131,14 @@ static int op_replace(oparg_T *oap, int c)
while (ltoreq(curwin->w_cursor, oap->end)) {
n = gchar_cursor();
if (n != NUL) {
- if (utf_char2len(c) > 1 || utf_char2len(n) > 1) {
+ int new_byte_len = utf_char2len(c);
+ int old_byte_len = utfc_ptr2len((char *)get_cursor_pos_ptr());
+
+ if (new_byte_len > 1 || old_byte_len > 1) {
// This is slow, but it handles replacing a single-byte
// with a multi-byte and the other way around.
if (curwin->w_cursor.lnum == oap->end.lnum) {
- oap->end.col += utf_char2len(c) - utf_char2len(n);
+ oap->end.col += new_byte_len - old_byte_len;
}
replace_character(c);
} else {
@@ -2135,17 +2194,16 @@ static int op_replace(oparg_T *oap, int c)
check_cursor();
changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, 0L, true);
- // Set "'[" and "']" marks.
- curbuf->b_op_start = oap->start;
- curbuf->b_op_end = oap->end;
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // Set "'[" and "']" marks.
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end = oap->end;
+ }
return OK;
}
-
-/*
- * Handle the (non-standard vi) tilde operator. Also for "gu", "gU" and "g?".
- */
+/// Handle the (non-standard vi) tilde operator. Also for "gu", "gU" and "g?".
void op_tilde(oparg_T *oap)
{
pos_T pos;
@@ -2206,11 +2264,11 @@ void op_tilde(oparg_T *oap)
redraw_curbuf_later(INVERTED);
}
- /*
- * Set '[ and '] marks.
- */
- curbuf->b_op_start = oap->start;
- curbuf->b_op_end = oap->end;
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // Set '[ and '] marks.
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end = oap->end;
+ }
if (oap->line_count > p_report) {
smsg(NGETTEXT("%" PRId64 " line changed",
@@ -2219,20 +2277,20 @@ void op_tilde(oparg_T *oap)
}
}
-/*
- * Invoke swapchar() on "length" bytes at position "pos".
- * "pos" is advanced to just after the changed characters.
- * "length" is rounded up to include the whole last multi-byte character.
- * Also works correctly when the number of bytes changes.
- * Returns TRUE if some character was changed.
- */
+/// Invoke swapchar() on "length" bytes at position "pos".
+///
+/// @param pos is advanced to just after the changed characters.
+/// @param length is rounded up to include the whole last multi-byte character.
+/// Also works correctly when the number of bytes changes.
+///
+/// @return TRUE if some character was changed.
static int swapchars(int op_type, pos_T *pos, int length)
FUNC_ATTR_NONNULL_ALL
{
int did_change = 0;
for (int todo = length; todo > 0; todo--) {
- const int len = utfc_ptr2len(ml_get_pos(pos));
+ const int len = utfc_ptr2len((char *)ml_get_pos(pos));
// we're counting bytes, not characters
if (len > 0) {
@@ -2246,11 +2304,13 @@ static int swapchars(int op_type, pos_T *pos, int length)
return did_change;
}
-// If op_type == OP_UPPER: make uppercase,
-// if op_type == OP_LOWER: make lowercase,
-// if op_type == OP_ROT13: do rot13 encoding,
-// else swap case of character at 'pos'
-// returns true when something actually changed.
+/// @param op_type
+/// == OP_UPPER: make uppercase,
+/// == OP_LOWER: make lowercase,
+/// == OP_ROT13: do rot13 encoding,
+/// else swap case of character at 'pos'
+///
+/// @return true when something actually changed.
bool swapchar(int op_type, pos_T *pos)
FUNC_ATTR_NONNULL_ARG(2)
{
@@ -2293,7 +2353,7 @@ bool swapchar(int op_type, pos_T *pos)
curwin->w_cursor = *pos;
// don't use del_char(), it also removes composing chars
- del_bytes(utf_ptr2len(get_cursor_pos_ptr()), false, false);
+ del_bytes(utf_ptr2len((char *)get_cursor_pos_ptr()), false, false);
ins_char(nc);
curwin->w_cursor = sp;
} else {
@@ -2304,9 +2364,7 @@ bool swapchar(int op_type, pos_T *pos)
return false;
}
-/*
- * op_insert - Insert and append operators for Visual mode.
- */
+/// Insert and append operators for Visual mode.
void op_insert(oparg_T *oap, long count1)
{
long ins_len, pre_textlen = 0;
@@ -2329,19 +2387,22 @@ void op_insert(oparg_T *oap, long count1)
// doing block_prep(). When only "block" is used, virtual edit is
// already disabled, but still need it when calling
// coladvance_force().
+ // coladvance_force() uses get_ve_flags() to get the 'virtualedit'
+ // state for the current window. To override that state, we need to
+ // set the window-local value of ve_flags rather than the global value.
if (curwin->w_cursor.coladd > 0) {
- unsigned old_ve_flags = ve_flags;
+ unsigned old_ve_flags = curwin->w_ve_flags;
- ve_flags = VE_ALL;
if (u_save_cursor() == FAIL) {
return;
}
+ curwin->w_ve_flags = VE_ALL;
coladvance_force(oap->op_type == OP_APPEND
? oap->end_vcol + 1 : getviscol());
if (oap->op_type == OP_APPEND) {
--curwin->w_cursor.col;
}
- ve_flags = old_ve_flags;
+ curwin->w_ve_flags = old_ve_flags;
}
// Get the info about the block before entering the text
block_prep(oap, &bd, oap->start.lnum, true);
@@ -2389,6 +2450,7 @@ void op_insert(oparg_T *oap, long count1)
}
t1 = oap->start;
+ const pos_T start_insert = curwin->w_cursor;
(void)edit(NUL, false, (linenr_T)count1);
// When a tab was inserted, and the characters in front of the tab
@@ -2423,23 +2485,18 @@ void op_insert(oparg_T *oap, long count1)
// The user may have moved the cursor before inserting something, try
// to adjust the block for that. But only do it, if the difference
// does not come from indent kicking in.
- if (oap->start.lnum == curbuf->b_op_start_orig.lnum
- && !bd.is_MAX
- && !did_indent) {
+ if (oap->start.lnum == curbuf->b_op_start_orig.lnum && !bd.is_MAX && !did_indent) {
+ const int t = getviscol2(curbuf->b_op_start_orig.col, curbuf->b_op_start_orig.coladd);
+
if (oap->op_type == OP_INSERT
&& oap->start.col + oap->start.coladd
!= curbuf->b_op_start_orig.col + curbuf->b_op_start_orig.coladd) {
- int t = getviscol2(curbuf->b_op_start_orig.col,
- curbuf->b_op_start_orig.coladd);
oap->start.col = curbuf->b_op_start_orig.col;
pre_textlen -= t - oap->start_vcol;
oap->start_vcol = t;
} else if (oap->op_type == OP_APPEND
- && oap->end.col + oap->end.coladd
- >= curbuf->b_op_start_orig.col
- + curbuf->b_op_start_orig.coladd) {
- int t = getviscol2(curbuf->b_op_start_orig.col,
- curbuf->b_op_start_orig.coladd);
+ && oap->start.col + oap->start.coladd
+ >= curbuf->b_op_start_orig.col + curbuf->b_op_start_orig.coladd) {
oap->start.col = curbuf->b_op_start_orig.col;
// reset pre_textlen to the value of OP_INSERT
pre_textlen += bd.textlen;
@@ -2487,15 +2544,27 @@ void op_insert(oparg_T *oap, long count1)
firstline = ml_get(oap->start.lnum);
const size_t len = STRLEN(firstline);
colnr_T add = bd.textcol;
+ colnr_T offset = 0; // offset when cursor was moved in insert mode
if (oap->op_type == OP_APPEND) {
add += bd.textlen;
+ // account for pressing cursor in insert mode when '$' was used
+ if (bd.is_MAX && start_insert.lnum == Insstart.lnum && start_insert.col > Insstart.col) {
+ offset = start_insert.col - Insstart.col;
+ add -= offset;
+ if (oap->end_vcol > offset) {
+ oap->end_vcol -= offset + 1;
+ } else {
+ // moved outside of the visual block, what to do?
+ return;
+ }
+ }
}
if ((size_t)add > len) {
firstline += len; // short line, point to the NUL
} else {
firstline += add;
}
- ins_len = (long)STRLEN(firstline) - pre_textlen;
+ ins_len = (long)STRLEN(firstline) - pre_textlen - offset;
if (pre_textlen >= 0 && ins_len > 0) {
ins_text = vim_strnsave(firstline, (size_t)ins_len);
// block handled here
@@ -2510,11 +2579,9 @@ void op_insert(oparg_T *oap, long count1)
}
}
-/*
- * op_change - handle a change operation
- *
- * return TRUE if edit() returns because of a CTRL-O command
- */
+/// handle a change operation
+///
+/// @return TRUE if edit() returns because of a CTRL-O command
int op_change(oparg_T *oap)
{
colnr_T l;
@@ -2533,10 +2600,7 @@ int op_change(oparg_T *oap)
l = oap->start.col;
if (oap->motion_type == kMTLineWise) {
l = 0;
- if (!p_paste && curbuf->b_p_si
- && !curbuf->b_p_cin) {
- can_si = true; // It's like opening a new line, do si
- }
+ can_si = may_do_si(); // Like opening a new line, do smart indent
}
// First delete the text in the region. In an empty buffer only need to
@@ -2623,9 +2687,9 @@ int op_change(oparg_T *oap)
offset += ins_len;
oldp += bd.textcol;
STRMOVE(newp + offset, oldp);
- ml_replace(linenr, newp, false);
- extmark_splice_cols(curbuf, (int)linenr-1, bd.textcol,
- 0, vpos.coladd+(int)ins_len, kExtmarkUndo);
+ ml_replace(linenr, (char *)newp, false);
+ extmark_splice_cols(curbuf, (int)linenr - 1, bd.textcol,
+ 0, vpos.coladd + (int)ins_len, kExtmarkUndo);
}
}
check_cursor();
@@ -2638,6 +2702,7 @@ int op_change(oparg_T *oap)
return retval;
}
+
/*
* set all the yank registers to empty (called from main())
*/
@@ -2658,10 +2723,10 @@ void clear_registers(void)
#endif
-
/// Free contents of yankreg `reg`.
/// Called for normal freeing and in case of error.
-/// `reg` must not be NULL (but `reg->y_array` might be)
+///
+/// @param reg must not be NULL (but `reg->y_array` might be)
void free_register(yankreg_T *reg)
FUNC_ATTR_NONNULL_ALL
{
@@ -2677,12 +2742,12 @@ void free_register(yankreg_T *reg)
/// Yanks the text between "oap->start" and "oap->end" into a yank register.
/// If we are to append (uppercase register), we first yank into a new yank
/// register and then concatenate the old and the new one.
+/// Do not call this from a delete operation. Use op_yank_reg() instead.
///
/// @param oap operator arguments
/// @param message show message when more than `&report` lines are yanked.
-/// @param deleting whether the function was called from a delete operation.
/// @returns whether the operation register was writable.
-bool op_yank(oparg_T *oap, bool message, int deleting)
+bool op_yank(oparg_T *oap, bool message)
FUNC_ATTR_NONNULL_ALL
{
// check for read-only register
@@ -2701,11 +2766,8 @@ bool op_yank(oparg_T *oap, bool message, int deleting)
return eval_yank_userreg(curbuf->b_p_urf, oap->regname, reg) != -1;
}
- // op_delete will set_clipboard and do_autocmd
- if (!deleting) {
- set_clipboard(oap->regname, reg);
- do_autocmd_textyankpost(oap, reg);
- }
+ set_clipboard(oap->regname, reg);
+ do_autocmd_textyankpost(oap, reg);
return true;
}
@@ -2713,7 +2775,7 @@ bool op_yank(oparg_T *oap, bool message, int deleting)
static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
{
yankreg_T newreg; // new yank register when appending
- char_u **new_ptr;
+ char **new_ptr;
linenr_T lnum; // current line number
size_t j;
MotionType yank_type = oap->motion_type;
@@ -2747,7 +2809,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
reg->y_size = yanklines;
reg->y_type = yank_type; // set the yank register type
reg->y_width = 0;
- reg->y_array = xcalloc(yanklines, sizeof(char_u *));
+ reg->y_array = xcalloc(yanklines, sizeof(char *));
reg->additional_data = NULL;
reg->timestamp = os_time();
@@ -2771,7 +2833,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
break;
case kMTLineWise:
- reg->y_array[y_idx] = vim_strsave(ml_get(lnum));
+ reg->y_array[y_idx] = (char *)vim_strsave(ml_get(lnum));
break;
case kMTCharWise: {
@@ -2841,7 +2903,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
if (curr != reg) { // append the new block to the old block
new_ptr = xmalloc(sizeof(char_u *) * (curr->y_size + reg->y_size));
- for (j = 0; j < curr->y_size; ++j) {
+ for (j = 0; j < curr->y_size; j++) {
new_ptr[j] = curr->y_array[j];
}
xfree(curr->y_array);
@@ -2862,7 +2924,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
STRCAT(pnew, reg->y_array[0]);
xfree(curr->y_array[j]);
xfree(reg->y_array[0]);
- curr->y_array[j++] = pnew;
+ curr->y_array[j++] = (char *)pnew;
y_idx = 1;
} else {
y_idx = 0;
@@ -2873,10 +2935,8 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
curr->y_size = j;
xfree(reg->y_array);
}
- if (curwin->w_p_rnu) {
- redraw_later(curwin, SOME_VALID); // cursor moved to start
- }
- if (message) { // Display message about yank?
+
+ if (message && (p_ch > 0 || ui_has(kUIMessages))) { // Display message about yank?
if (yank_type == kMTCharWise && yanklines == 1) {
yanklines = 0;
}
@@ -2904,21 +2964,20 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
}
}
- /*
- * Set "'[" and "']" marks.
- */
- curbuf->b_op_start = oap->start;
- curbuf->b_op_end = oap->end;
- if (yank_type == kMTLineWise) {
- curbuf->b_op_start.col = 0;
- curbuf->b_op_end.col = MAXCOL;
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // Set "'[" and "']" marks.
+ curbuf->b_op_start = oap->start;
+ curbuf->b_op_end = oap->end;
+ if (yank_type == kMTLineWise) {
+ curbuf->b_op_start.col = 0;
+ curbuf->b_op_end.col = MAXCOL;
+ }
}
-
- return;
}
-// Copy a block range into a register.
-// If "exclude_trailing_space" is set, do not copy trailing whitespaces.
+/// Copy a block range into a register.
+///
+/// @param exclude_trailing_space if true, do not copy trailing whitespaces.
static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx,
bool exclude_trailing_space)
FUNC_ATTR_NONNULL_ALL
@@ -2929,7 +2988,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx,
int size = bd->startspaces + bd->endspaces + bd->textlen;
assert(size >= 0);
char_u *pnew = xmallocz((size_t)size);
- reg->y_array[y_idx] = pnew;
+ reg->y_array[y_idx] = (char *)pnew;
memset(pnew, ' ', (size_t)bd->startspaces);
pnew += bd->startspaces;
memmove(pnew, bd->textstart, (size_t)bd->textlen);
@@ -2939,7 +2998,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx,
if (exclude_trailing_space) {
int s = bd->textlen + bd->endspaces;
- while (ascii_iswhite(*(bd->textstart + s - 1)) && s > 0) {
+ while (s > 0 && ascii_iswhite(*(bd->textstart + s - 1))) {
s = s - utf_head_off(bd->textstart, bd->textstart + s - 1) - 1;
pnew--;
}
@@ -2976,7 +3035,7 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
(void)tv_dict_add_list(dict, S_LEN("regcontents"), list);
// Register type.
- char buf[NUMBUFLEN+2];
+ char buf[NUMBUFLEN + 2];
format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf));
(void)tv_dict_add_str(dict, S_LEN("regtype"), buf);
@@ -3007,13 +3066,14 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
recursive = false;
}
-// Put contents of register "regname" into the text.
-// Caller must check "regname" to be valid!
-// "flags": PUT_FIXINDENT make indent look nice
-// PUT_CURSEND leave cursor after end of new text
-// PUT_LINE force linewise put (":put")
-// PUT_BLOCK_INNER in block mode, do not add trailing spaces
-// dir: BACKWARD for 'P', FORWARD for 'p'
+/// Put contents of register "regname" into the text.
+/// Caller must check "regname" to be valid!
+///
+/// @param flags PUT_FIXINDENT make indent look nice
+/// PUT_CURSEND leave cursor after end of new text
+/// PUT_LINE force linewise put (":put")
+/// PUT_BLOCK_INNER in block mode, do not add trailing spaces
+/// @param dir BACKWARD for 'P', FORWARD for 'p'
void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
{
char_u *ptr;
@@ -3033,7 +3093,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
int incr = 0;
struct block_def bd;
char_u **y_array = NULL;
- long nr_lines = 0;
+ linenr_T nr_lines = 0;
pos_T new_cursor;
int indent;
int orig_indent = 0; // init for gcc
@@ -3044,6 +3104,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
char_u *insert_string = NULL;
bool allocated = false;
long cnt;
+ const pos_T orig_start = curbuf->b_op_start;
+ const pos_T orig_end = curbuf->b_op_end;
+ unsigned int cur_ve_flags = get_ve_flags();
if (flags & PUT_FIXINDENT) {
orig_indent = get_indent();
@@ -3111,10 +3174,10 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
bool one_past_line = (*cursor_pos == NUL);
bool eol = false;
if (!one_past_line) {
- eol = (*(cursor_pos + utfc_ptr2len(cursor_pos)) == NUL);
+ eol = (*(cursor_pos + utfc_ptr2len((char *)cursor_pos)) == NUL);
}
- bool ve_allows = (ve_flags == VE_ALL || ve_flags == VE_ONEMORE);
+ bool ve_allows = (cur_ve_flags == VE_ALL || cur_ve_flags == VE_ONEMORE);
bool eof = curbuf->b_ml.ml_line_count == curwin->w_cursor.lnum
&& one_past_line;
if (ve_allows || !(eol || eof)) {
@@ -3166,8 +3229,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (y_array != NULL) {
y_array[y_size] = ptr;
}
- ++y_size;
- ptr = vim_strchr(ptr, '\n');
+ y_size++;
+ ptr = (char_u *)vim_strchr((char *)ptr, '\n');
if (ptr != NULL) {
if (y_array != NULL) {
*ptr = NUL;
@@ -3200,7 +3263,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
y_type = reg->y_type;
y_width = reg->y_width;
y_size = reg->y_size;
- y_array = reg->y_array;
+ y_array = (char_u **)reg->y_array;
}
if (curbuf->terminal) {
@@ -3220,7 +3283,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
MB_PTR_ADV(p);
}
ptr = vim_strsave(p);
- ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, false);
+ ml_append(curwin->w_cursor.lnum, (char *)ptr, (colnr_T)0, false);
xfree(ptr);
oldp = get_cursor_line_ptr();
@@ -3229,7 +3292,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
MB_PTR_ADV(p);
}
ptr = vim_strnsave(oldp, (size_t)(p - oldp));
- ml_replace(curwin->w_cursor.lnum, ptr, false);
+ ml_replace(curwin->w_cursor.lnum, (char *)ptr, false);
nr_lines++;
dir = FORWARD;
}
@@ -3290,13 +3353,14 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
yanklen = (int)STRLEN(y_array[0]);
- if (ve_flags == VE_ALL && y_type == kMTCharWise) {
+ if (cur_ve_flags == VE_ALL && y_type == kMTCharWise) {
if (gchar_cursor() == TAB) {
- /* Don't need to insert spaces when "p" on the last position of a
- * tab or "P" on the first position. */
int viscol = getviscol();
+ long ts = curbuf->b_p_ts;
+ // Don't need to insert spaces when "p" on the last position of a
+ // tab or "P" on the first position.
if (dir == FORWARD
- ? tabstop_padding(viscol, curbuf->b_p_ts, curbuf->b_p_vts_array) != 1
+ ? tabstop_padding(viscol, ts, curbuf->b_p_vts_array) != 1
: curwin->w_cursor.coladd > 0) {
coladvance_force(viscol);
} else {
@@ -3318,23 +3382,22 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
colnr_T endcol2 = 0;
if (dir == FORWARD && c != NUL) {
- if (ve_flags == VE_ALL) {
+ if (cur_ve_flags == VE_ALL) {
getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
} else {
getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
}
// move to start of next multi-byte character
- curwin->w_cursor.col += utfc_ptr2len(get_cursor_pos_ptr());
+ curwin->w_cursor.col += utfc_ptr2len((char *)get_cursor_pos_ptr());
col++;
} else {
getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
}
col += curwin->w_cursor.coladd;
- if (ve_flags == VE_ALL
- && (curwin->w_cursor.coladd > 0
- || endcol2 == curwin->w_cursor.col)) {
+ if (cur_ve_flags == VE_ALL
+ && (curwin->w_cursor.coladd > 0 || endcol2 == curwin->w_cursor.col)) {
if (dir == FORWARD && c == NUL) {
col++;
}
@@ -3366,7 +3429,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// add a new line
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
- if (ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
+ if (ml_append(curbuf->b_ml.ml_line_count, "",
(colnr_T)1, false) == FAIL) {
break;
}
@@ -3416,18 +3479,27 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
}
- // insert the new text
+ // Insert the new text.
+ // First check for multiplication overflow.
+ if (yanklen + spaces != 0
+ && count > ((INT_MAX - (bd.startspaces + bd.endspaces)) / (yanklen + spaces))) {
+ emsg(_(e_resulting_text_too_long));
+ break;
+ }
+
totlen = (size_t)(count * (yanklen + spaces)
+ bd.startspaces + bd.endspaces);
- int addcount = (int)totlen + lines_appended;
newp = (char_u *)xmalloc(totlen + oldlen + 1);
+
// copy part up to cursor to new line
ptr = newp;
memmove(ptr, oldp, (size_t)bd.textcol);
ptr += bd.textcol;
+
// may insert some spaces before the new text
memset(ptr, ' ', (size_t)bd.startspaces);
ptr += bd.startspaces;
+
// insert the new text
for (long j = 0; j < count; j++) {
memmove(ptr, y_array[i], (size_t)yanklen);
@@ -3438,19 +3510,21 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
memset(ptr, ' ', (size_t)spaces);
ptr += spaces;
} else {
- addcount -= spaces;
+ totlen -= (size_t)spaces; // didn't use these spaces
}
}
+
// may insert some spaces after the new text
memset(ptr, ' ', (size_t)bd.endspaces);
ptr += bd.endspaces;
+
// move the text after the cursor to the end of the line.
int columns = (int)oldlen - bd.textcol - delcount + 1;
assert(columns >= 0);
memmove(ptr, oldp + bd.textcol + delcount, (size_t)columns);
- ml_replace(curwin->w_cursor.lnum, newp, false);
- extmark_splice_cols(curbuf, (int)curwin->w_cursor.lnum-1, bd.textcol,
- delcount, addcount, kExtmarkUndo);
+ ml_replace(curwin->w_cursor.lnum, (char *)newp, false);
+ extmark_splice_cols(curbuf, (int)curwin->w_cursor.lnum - 1, bd.textcol,
+ delcount, (int)totlen + lines_appended, kExtmarkUndo);
++curwin->w_cursor.lnum;
if (i == 0) {
@@ -3459,7 +3533,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
changed_lines(lnum, 0, curbuf->b_op_start.lnum + (linenr_T)y_size
- - (linenr_T)nr_lines, nr_lines, true);
+ - nr_lines, nr_lines, true);
// Set '[ mark.
curbuf->b_op_start = curwin->w_cursor;
@@ -3489,7 +3563,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// if type is kMTCharWise, FORWARD is the same as BACKWARD on the next
// char
if (dir == FORWARD && gchar_cursor() != NUL) {
- int bytelen = utfc_ptr2len(get_cursor_pos_ptr());
+ int bytelen = utfc_ptr2len((char *)get_cursor_pos_ptr());
// put it on the next of the multi-byte character.
col += bytelen;
@@ -3532,10 +3606,18 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
}
- do {
+ if (count == 0 || yanklen == 0) {
+ if (VIsual_active) {
+ lnum = end_lnum;
+ }
+ } else if (count > INT_MAX / yanklen) {
+ // multiplication overflow
+ emsg(_(e_resulting_text_too_long));
+ } else {
totlen = (size_t)(count * yanklen);
- if (totlen > 0) {
+ do {
oldp = ml_get(lnum);
+ oldlen = STRLEN(oldp);
if (lnum > start_lnum) {
pos_T pos = {
.lnum = lnum,
@@ -3546,11 +3628,11 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
col = MAXCOL;
}
}
- if (VIsual_active && col > (int)STRLEN(oldp)) {
+ if (VIsual_active && col > (colnr_T)oldlen) {
lnum++;
continue;
}
- newp = (char_u *)xmalloc((size_t)(STRLEN(oldp) + totlen + 1));
+ newp = (char_u *)xmalloc(totlen + oldlen + 1);
memmove(newp, oldp, (size_t)col);
ptr = newp + col;
for (i = 0; i < (size_t)count; i++) {
@@ -3558,7 +3640,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
ptr += yanklen;
}
STRMOVE(ptr, oldp + col);
- ml_replace(lnum, newp, false);
+ ml_replace(lnum, (char *)newp, false);
// compute the byte offset for the last character
first_byte_off = utf_head_off(newp, ptr - 1);
@@ -3570,16 +3652,16 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
curwin->w_cursor.col += (colnr_T)(totlen - 1);
}
changed_bytes(lnum, col);
- extmark_splice_cols(curbuf, (int)lnum-1, col,
+ extmark_splice_cols(curbuf, (int)lnum - 1, col,
0, (int)totlen, kExtmarkUndo);
- }
- if (VIsual_active) {
- lnum++;
- }
- } while (VIsual_active && lnum <= end_lnum);
+ if (VIsual_active) {
+ lnum++;
+ }
+ } while (VIsual_active && lnum <= end_lnum);
- if (VIsual_active) { // reset lnum to the last visual line
- lnum--;
+ if (VIsual_active) { // reset lnum to the last visual line
+ lnum--;
+ }
}
// put '] at the first byte of the last character
@@ -3593,6 +3675,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
curwin->w_cursor.col -= first_byte_off;
}
} else {
+ linenr_T new_lnum = new_cursor.lnum;
+ size_t len;
+
// Insert at least one line. When y_type is kMTCharWise, break the first
// line in two.
for (cnt = 1; cnt <= count; cnt++) {
@@ -3608,7 +3693,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
STRCPY(newp, y_array[y_size - 1]);
STRCAT(newp, ptr);
// insert second line
- ml_append(lnum, newp, (colnr_T)0, false);
+ ml_append(lnum, (char *)newp, (colnr_T)0, false);
+ new_lnum++;
xfree(newp);
oldp = ml_get(lnum);
@@ -3617,17 +3703,18 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
memmove(newp, oldp, (size_t)col);
// append to first line
memmove(newp + col, y_array[0], (size_t)yanklen + 1);
- ml_replace(lnum, newp, false);
+ ml_replace(lnum, (char *)newp, false);
curwin->w_cursor.lnum = lnum;
i = 1;
}
for (; i < y_size; i++) {
- if ((y_type != kMTCharWise || i < y_size - 1)
- && ml_append(lnum, y_array[i], (colnr_T)0, false)
- == FAIL) {
- goto error;
+ if ((y_type != kMTCharWise || i < y_size - 1)) {
+ if (ml_append(lnum, (char *)y_array[i], (colnr_T)0, false) == FAIL) {
+ goto error;
+ }
+ new_lnum++;
}
lnum++;
++nr_lines;
@@ -3662,20 +3749,24 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
int lastsize = 0;
if (y_type == kMTCharWise
|| (y_type == kMTLineWise && flags & PUT_LINE_SPLIT)) {
- for (i = 0; i < y_size-1; i++) {
+ for (i = 0; i < y_size - 1; i++) {
totsize += (bcount_t)STRLEN(y_array[i]) + 1;
}
- lastsize = (int)STRLEN(y_array[y_size-1]);
+ lastsize = (int)STRLEN(y_array[y_size - 1]);
totsize += lastsize;
}
if (y_type == kMTCharWise) {
- extmark_splice(curbuf, (int)new_cursor.lnum-1, col, 0, 0, 0,
- (int)y_size-1, lastsize, totsize,
+ extmark_splice(curbuf, (int)new_cursor.lnum - 1, col, 0, 0, 0,
+ (int)y_size - 1, lastsize, totsize,
kExtmarkUndo);
} else if (y_type == kMTLineWise && flags & PUT_LINE_SPLIT) {
// Account for last pasted NL + last NL
- extmark_splice(curbuf, (int)new_cursor.lnum-1, col + 1, 0, 0, 0,
- (int)y_size+1, 0, totsize+2, kExtmarkUndo);
+ extmark_splice(curbuf, (int)new_cursor.lnum - 1, col + 1, 0, 0, 0,
+ (int)y_size + 1, 0, totsize + 2, kExtmarkUndo);
+ }
+
+ if (cnt == 1) {
+ new_lnum = lnum;
}
}
@@ -3704,11 +3795,15 @@ error:
// Put the '] mark on the first byte of the last inserted character.
// Correct the length for change in indent.
- curbuf->b_op_end.lnum = lnum;
- col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
+ curbuf->b_op_end.lnum = new_lnum;
+ len = STRLEN(y_array[y_size - 1]);
+ col = (colnr_T)len - lendiff;
if (col > 1) {
- curbuf->b_op_end.col = col - 1 - utf_head_off(y_array[y_size - 1],
- y_array[y_size - 1] + col - 1);
+ curbuf->b_op_end.col = col - 1;
+ if (len > 0) {
+ curbuf->b_op_end.col -= utf_head_off(y_array[y_size - 1],
+ y_array[y_size - 1] + len - 1);
+ }
} else {
curbuf->b_op_end.col = 0;
}
@@ -3727,8 +3822,12 @@ error:
}
curwin->w_cursor.col = 0;
} else {
- curwin->w_cursor.lnum = lnum;
+ curwin->w_cursor.lnum = new_lnum;
curwin->w_cursor.col = col;
+ curbuf->b_op_end = curwin->w_cursor;
+ if (col > 1) {
+ curbuf->b_op_end.col = col - 1;
+ }
}
} else if (y_type == kMTLineWise) {
// put cursor on first non-blank in first inserted line
@@ -3747,6 +3846,10 @@ error:
curwin->w_set_curswant = TRUE;
end:
+ if (cmdmod.cmod_flags & CMOD_LOCKMARKS) {
+ curbuf->b_op_start = orig_start;
+ curbuf->b_op_end = orig_end;
+ }
if (allocated) {
xfree(insert_string);
}
@@ -3758,22 +3861,22 @@ end:
// If the cursor is past the end of the line put it at the end.
adjust_cursor_eol();
-} // NOLINT(readability/fn_size)
+}
-/*
- * When the cursor is on the NUL past the end of the line and it should not be
- * there move it left.
- */
+/// When the cursor is on the NUL past the end of the line and it should not be
+/// there move it left.
void adjust_cursor_eol(void)
{
+ unsigned int cur_ve_flags = get_ve_flags();
+
if (curwin->w_cursor.col > 0
&& gchar_cursor() == NUL
- && (ve_flags & VE_ONEMORE) == 0
- && !(restart_edit || (State & INSERT))) {
+ && (cur_ve_flags & VE_ONEMORE) == 0
+ && !(restart_edit || (State & MODE_INSERT))) {
// Put the cursor on the last character in the line.
dec_cursor();
- if (ve_flags == VE_ALL) {
+ if (cur_ve_flags == VE_ALL) {
colnr_T scol, ecol;
// Coladd is set to the width of the last character.
@@ -3783,9 +3886,7 @@ void adjust_cursor_eol(void)
}
}
-/*
- * Return TRUE if lines starting with '#' should be left aligned.
- */
+/// @return TRUE if lines starting with '#' should be left aligned.
int preprocs_left(void)
{
return ((curbuf->b_p_si && !curbuf->b_p_cin)
@@ -3793,7 +3894,7 @@ int preprocs_left(void)
&& curbuf->b_ind_hash_comment == 0));
}
-// Return the character name of the register with the given number
+/// @return the character name of the register with the given number
int get_register_name(int num)
{
if (num == -1) {
@@ -3817,17 +3918,15 @@ int get_unname_register(void)
return yankmap_find(&y_regs.inner, y_previous);
}
-/*
- * ":dis" and ":registers": Display the contents of the yank registers.
- */
+/// ":dis" and ":registers": Display the contents of the yank registers.
void ex_display(exarg_T *eap)
{
char_u *p;
yankreg_T *yb;
int name;
- char_u *arg = eap->arg;
+ char_u *arg = (char_u *)eap->arg;
int clen;
- char_u type[2];
+ int type;
if (arg != NULL && *arg == NUL) {
arg = NULL;
@@ -3840,18 +3939,17 @@ void ex_display(exarg_T *eap)
name = get_register_name(i);
switch (get_reg_type(name, NULL)) {
case kMTLineWise:
- type[0] = 'l'; break;
+ type = 'l'; break;
case kMTCharWise:
- type[0] = 'c'; break;
+ type = 'c'; break;
default:
- type[0] = 'b'; break;
+ type = 'b'; break;
}
- if (arg != NULL && vim_strchr(arg, name) == NULL) {
+ if (arg != NULL && vim_strchr((char *)arg, name) == NULL) {
continue; // did not ask for this register
}
-
if (i == -1) {
if (y_previous != NULL) {
yb = y_previous;
@@ -3871,88 +3969,88 @@ void ex_display(exarg_T *eap)
}
if (yb->y_array != NULL) {
- msg_putchar('\n');
- msg_puts(" ");
- msg_putchar(type[0]);
- msg_puts(" ");
- msg_putchar('"');
- msg_putchar(name);
- msg_puts(" ");
-
- int n = Columns - 11;
- for (size_t j = 0; j < yb->y_size && n > 1; j++) {
- if (j) {
- msg_puts_attr("^J", attr);
- n -= 2;
+ bool do_show = false;
+
+ for (size_t j = 0; !do_show && j < yb->y_size; j++) {
+ do_show = !message_filtered((char_u *)yb->y_array[j]);
+ }
+
+ if (do_show || yb->y_size == 0) {
+ msg_putchar('\n');
+ msg_puts(" ");
+ msg_putchar(type);
+ msg_puts(" ");
+ msg_putchar('"');
+ msg_putchar(name);
+ msg_puts(" ");
+
+ int n = Columns - 11;
+ for (size_t j = 0; j < yb->y_size && n > 1; j++) {
+ if (j) {
+ msg_puts_attr("^J", attr);
+ n -= 2;
+ }
+ for (p = (char_u *)yb->y_array[j];
+ *p != NUL && (n -= ptr2cells((char *)p)) >= 0; p++) { // -V1019
+ clen = utfc_ptr2len((char *)p);
+ msg_outtrans_len(p, clen);
+ p += clen - 1;
+ }
}
- for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0; p++) { // -V1019 NOLINT(whitespace/line_length)
- clen = utfc_ptr2len(p);
- msg_outtrans_len(p, clen);
- p += clen - 1;
+ if (n > 1 && yb->y_type == kMTLineWise) {
+ msg_puts_attr("^J", attr);
}
+ ui_flush(); // show one line at a time
}
- if (n > 1 && yb->y_type == kMTLineWise) {
- msg_puts_attr("^J", attr);
- }
- ui_flush(); // show one line at a time
+ os_breakcheck();
}
- os_breakcheck();
}
- /*
- * display last inserted text
- */
+ // display last inserted text
if ((p = get_last_insert()) != NULL
- && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int) {
+ && (arg == NULL || vim_strchr((char *)arg, '.') != NULL) && !got_int
+ && !message_filtered(p)) {
msg_puts("\n c \". ");
dis_msg(p, true);
}
- /*
- * display last command line
- */
- if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL)
- && !got_int) {
+ // display last command line
+ if (last_cmdline != NULL && (arg == NULL || vim_strchr((char *)arg, ':') != NULL)
+ && !got_int && !message_filtered(last_cmdline)) {
msg_puts("\n c \": ");
dis_msg(last_cmdline, false);
}
- /*
- * display current file name
- */
+ // display current file name
if (curbuf->b_fname != NULL
- && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int) {
+ && (arg == NULL || vim_strchr((char *)arg, '%') != NULL) && !got_int
+ && !message_filtered((char_u *)curbuf->b_fname)) {
msg_puts("\n c \"% ");
- dis_msg(curbuf->b_fname, false);
+ dis_msg((char_u *)curbuf->b_fname, false);
}
- /*
- * display alternate file name
- */
- if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int) {
- char_u *fname;
+ // display alternate file name
+ if ((arg == NULL || vim_strchr((char *)arg, '%') != NULL) && !got_int) {
+ char *fname;
linenr_T dummy;
- if (buflist_name_nr(0, &fname, &dummy) != FAIL) {
+ if (buflist_name_nr(0, &fname, &dummy) != FAIL && !message_filtered((char_u *)fname)) {
msg_puts("\n c \"# ");
- dis_msg(fname, false);
+ dis_msg((char_u *)fname, false);
}
}
- /*
- * display last search pattern
- */
+ // display last search pattern
if (last_search_pat() != NULL
- && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int) {
+ && (arg == NULL || vim_strchr((char *)arg, '/') != NULL) && !got_int
+ && !message_filtered(last_search_pat())) {
msg_puts("\n c \"/ ");
dis_msg(last_search_pat(), false);
}
- /*
- * display last used expression
- */
- if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL)
- && !got_int) {
+ // display last used expression
+ if (expr_line != NULL && (arg == NULL || vim_strchr((char *)arg, '=') != NULL)
+ && !got_int && !message_filtered(expr_line)) {
msg_puts("\n c \"= ");
dis_msg(expr_line, false);
}
@@ -3971,8 +4069,8 @@ static void dis_msg(const char_u *p, bool skip_esc)
n = Columns - 6;
while (*p != NUL
&& !(*p == ESC && skip_esc && *(p + 1) == NUL)
- && (n -= ptr2cells(p)) >= 0) {
- if ((l = utfc_ptr2len(p)) > 1) {
+ && (n -= ptr2cells((char *)p)) >= 0) {
+ if ((l = utfc_ptr2len((char *)p)) > 1) {
msg_outtrans_len(p, l);
p += l;
} else {
@@ -3997,7 +4095,7 @@ char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_co
{
char_u *comment_flags = NULL;
int lead_len;
- int leader_offset = get_last_leader_offset(line, &comment_flags);
+ int leader_offset = get_last_leader_offset((char *)line, (char **)&comment_flags);
*is_comment = false;
if (leader_offset != -1) {
@@ -4019,7 +4117,7 @@ char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_co
return line;
}
- lead_len = get_leader_len(line, &comment_flags, false, include_space);
+ lead_len = get_leader_len((char *)line, (char **)&comment_flags, false, include_space);
if (lead_len == 0) {
return line;
@@ -4047,14 +4145,14 @@ char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_co
return line;
}
-// Join 'count' lines (minimal 2) at cursor position.
-// When "save_undo" is TRUE save lines for undo first.
-// Set "use_formatoptions" to FALSE when e.g. processing backspace and comment
-// leaders should not be removed.
-// When setmark is true, sets the '[ and '] mark, else, the caller is expected
-// to set those marks.
-//
-// return FAIL for failure, OK otherwise
+/// @param count number of lines (minimal 2) to join at cursor position.
+/// @param save_undo when TRUE, save lines for undo first.
+/// @param use_formatoptions set to FALSE when e.g. processing backspace and comment
+/// leaders should not be removed.
+/// @param setmark when true, sets the '[ and '] mark, else, the caller is expected
+/// to set those marks.
+///
+/// @return FAIL for failure, OK otherwise
int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions, bool setmark)
{
char_u *curr = NULL;
@@ -4091,7 +4189,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
// and setup the array of space strings lengths
for (t = 0; t < (linenr_T)count; t++) {
curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t));
- if (t == 0 && setmark) {
+ if (t == 0 && setmark && (cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
// Set the '[ mark.
curwin->w_buffer->b_op_start.lnum = curwin->w_cursor.lnum;
curwin->w_buffer->b_op_start.col = (colnr_T)STRLEN(curr);
@@ -4110,17 +4208,17 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
}
if (insert_space && t > 0) {
- curr = skipwhite(curr);
+ curr = (char_u *)skipwhite((char *)curr);
if (*curr != NUL
&& *curr != ')'
&& sumsize != 0
&& endcurr1 != TAB
&& (!has_format_option(FO_MBYTE_JOIN)
- || (utf_ptr2char(curr) < 0x100 && endcurr1 < 0x100))
+ || (utf_ptr2char((char *)curr) < 0x100 && endcurr1 < 0x100))
&& (!has_format_option(FO_MBYTE_JOIN2)
- || (utf_ptr2char(curr) < 0x100 && !utf_eat_space(endcurr1))
+ || (utf_ptr2char((char *)curr) < 0x100 && !utf_eat_space(endcurr1))
|| (endcurr1 < 0x100
- && !utf_eat_space(utf_ptr2char(curr))))) {
+ && !utf_eat_space(utf_ptr2char((char *)curr))))) {
// don't add a space if the line is ending in a space
if (endcurr1 == ' ') {
endcurr1 = endcurr2;
@@ -4135,8 +4233,8 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
}
if (t > 0 && curbuf_splice_pending == 0) {
- colnr_T removed = (int)(curr- curr_start);
- extmark_splice(curbuf, (int)curwin->w_cursor.lnum-1, sumsize,
+ colnr_T removed = (int)(curr - curr_start);
+ extmark_splice(curbuf, (int)curwin->w_cursor.lnum - 1, sumsize,
1, removed, removed + 1,
0, spaces[t], spaces[t],
kExtmarkUndo);
@@ -4147,10 +4245,10 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
if (insert_space && currsize > 0) {
cend = curr + currsize;
MB_PTR_BACK(curr, cend);
- endcurr1 = utf_ptr2char(cend);
+ endcurr1 = utf_ptr2char((char *)cend);
if (cend > curr) {
MB_PTR_BACK(curr, cend);
- endcurr2 = utf_ptr2char(cend);
+ endcurr2 = utf_ptr2char((char *)cend);
}
}
line_breakcheck();
@@ -4191,7 +4289,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
const int spaces_removed = (int)((curr - curr_start) - spaces[t]);
linenr_T lnum = curwin->w_cursor.lnum + t;
colnr_T mincol = (colnr_T)0;
- long lnum_amount = -t;
+ linenr_T lnum_amount = -t;
long col_amount = (cend - newp - spaces_removed);
mark_col_adjust(lnum, mincol, lnum_amount, col_amount, spaces_removed);
@@ -4205,14 +4303,14 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
curr += comments[t - 1];
}
if (insert_space && t > 1) {
- curr = skipwhite(curr);
+ curr = (char_u *)skipwhite((char *)curr);
}
currsize = (int)STRLEN(curr);
}
- ml_replace(curwin->w_cursor.lnum, newp, false);
+ ml_replace(curwin->w_cursor.lnum, (char *)newp, false);
- if (setmark) {
+ if (setmark && (cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
// Set the '] mark.
curwin->w_buffer->b_op_end.lnum = curwin->w_cursor.lnum;
curwin->w_buffer->b_op_end.col = sumsize;
@@ -4255,11 +4353,11 @@ theend:
return ret;
}
-/*
- * Return TRUE if the two comment leaders given are the same. "lnum" is
- * the first line. White-space is ignored. Note that the whole of
- * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
- */
+/// @return TRUE if the two comment leaders given are the same.
+///
+/// @param lnum The first line. White-space is ignored.
+///
+/// @note the whole of 'leader1' must match 'leader2_len' characters from 'leader2'.
static int same_leader(linenr_T lnum, int leader1_len, char_u *leader1_flags, int leader2_len,
char_u *leader2_flags)
{
@@ -4309,8 +4407,7 @@ static int same_leader(linenr_T lnum, int leader1_len, char_u *leader1_flags, in
* The first line has to be saved, only one line can be locked at a time.
*/
line1 = vim_strsave(ml_get(lnum));
- for (idx1 = 0; ascii_iswhite(line1[idx1]); ++idx1) {
- }
+ for (idx1 = 0; ascii_iswhite(line1[idx1]); idx1++) {}
line2 = ml_get(lnum + 1);
for (idx2 = 0; idx2 < leader2_len; ++idx2) {
if (!ascii_iswhite(line2[idx2])) {
@@ -4333,7 +4430,7 @@ static int same_leader(linenr_T lnum, int leader1_len, char_u *leader1_flags, in
/// @param keep_cursor keep cursor on same text char
static void op_format(oparg_T *oap, int keep_cursor)
{
- long old_line_count = curbuf->b_ml.ml_line_count;
+ linenr_T old_line_count = curbuf->b_ml.ml_line_count;
// Place the cursor where the "gq" or "gw" command was given, so that "u"
// can put it back there.
@@ -4350,8 +4447,10 @@ static void op_format(oparg_T *oap, int keep_cursor)
redraw_curbuf_later(INVERTED);
}
- // Set '[ mark at the start of the formatted area
- curbuf->b_op_start = oap->start;
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // Set '[ mark at the start of the formatted area
+ curbuf->b_op_start = oap->start;
+ }
// For "gw" remember the cursor position and put it back below (adjusted
// for joined and split lines).
@@ -4359,7 +4458,7 @@ static void op_format(oparg_T *oap, int keep_cursor)
saved_cursor = oap->cursor_start;
}
- format_lines(oap->line_count, keep_cursor);
+ format_lines((linenr_T)oap->line_count, keep_cursor);
/*
* Leave the cursor at the first non-blank of the last formatted line.
@@ -4373,8 +4472,10 @@ static void op_format(oparg_T *oap, int keep_cursor)
old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
msgmore(old_line_count);
- // put '] mark on the end of the formatted area
- curbuf->b_op_end = curwin->w_cursor;
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // put '] mark on the end of the formatted area
+ curbuf->b_op_end = curwin->w_cursor;
+ }
if (keep_cursor) {
curwin->w_cursor = saved_cursor;
@@ -4396,9 +4497,7 @@ static void op_format(oparg_T *oap, int keep_cursor)
}
}
-/*
- * Implementation of the format operator 'gq' for when using 'formatexpr'.
- */
+/// Implementation of the format operator 'gq' for when using 'formatexpr'.
static void op_formatexpr(oparg_T *oap)
{
if (oap->is_VIsual) {
@@ -4434,7 +4533,7 @@ int fex_format(linenr_T lnum, long count, int c)
if (use_sandbox) {
sandbox++;
}
- r = (int)eval_to_number(fex);
+ r = (int)eval_to_number((char *)fex);
if (use_sandbox) {
sandbox--;
}
@@ -4445,8 +4544,9 @@ int fex_format(linenr_T lnum, long count, int c)
return r;
}
-/// Format "line_count" lines, starting at the cursor position.
-/// When "line_count" is negative, format until the end of the paragraph.
+/// @param line_count number of lines to format, starting at the cursor position.
+/// when negative, format until the end of the paragraph.
+///
/// Lines after the cursor line are saved for undo, caller must have saved the
/// first line.
///
@@ -4461,13 +4561,14 @@ void format_lines(linenr_T line_count, int avoid_fex)
int leader_len = 0; // leader len of current line
int next_leader_len; // leader len of next line
char_u *leader_flags = NULL; // flags for leader of current line
- char_u *next_leader_flags; // flags for leader of next line
+ char_u *next_leader_flags = NULL; // flags for leader of next line
bool advance = true;
int second_indent = -1; // indent for second line (comment aware)
bool first_par_line = true;
int smd_save;
long count;
bool need_set_indent = true; // set indent of next paragraph
+ linenr_T first_line = curwin->w_cursor.lnum;
bool force_format = false;
const int old_State = State;
@@ -4578,7 +4679,14 @@ void format_lines(linenr_T line_count, int avoid_fex)
leader_len, leader_flags,
next_leader_len,
next_leader_flags)) {
- is_end_par = true;
+ // Special case: If the next line starts with a line comment
+ // and this line has a line comment after some text, the
+ // paragraph doesn't really end.
+ if (next_leader_flags == NULL
+ || STRNCMP(next_leader_flags, "://", 3) != 0
+ || check_linecomment(get_cursor_line_ptr()) == MAXCOL) {
+ is_end_par = true;
+ }
}
/*
@@ -4587,20 +4695,35 @@ void format_lines(linenr_T line_count, int avoid_fex)
*/
if (is_end_par || force_format) {
if (need_set_indent) {
- // replace indent in first line with minimal number of
- // tabs and spaces, according to current options
- (void)set_indent(get_indent(), SIN_CHANGED);
+ int indent = 0; // amount of indent needed
+
+ // Replace indent in first line of a paragraph with minimal
+ // number of tabs and spaces, according to current options.
+ // For the very first formatted line keep the current
+ // indent.
+ if (curwin->w_cursor.lnum == first_line) {
+ indent = get_indent();
+ } else if (curbuf->b_p_lisp) {
+ indent = get_lisp_indent();
+ } else {
+ if (cindent_on()) {
+ indent = *curbuf->b_p_inde != NUL ? get_expr_indent() : get_c_indent();
+ } else {
+ indent = get_indent();
+ }
+ }
+ (void)set_indent(indent, SIN_CHANGED);
}
// put cursor on last non-space
- State = NORMAL; // don't go past end-of-line
+ State = MODE_NORMAL; // don't go past end-of-line
coladvance(MAXCOL);
while (curwin->w_cursor.col && ascii_isspace(gchar_cursor())) {
dec_cursor();
}
// do the formatting, without 'showmode'
- State = INSERT; // for open_line()
+ State = MODE_INSERT; // for open_line()
smd_save = p_smd;
p_smd = FALSE;
insertchar(NUL, INSCHAR_FORMAT
@@ -4666,9 +4789,7 @@ void format_lines(linenr_T line_count, int avoid_fex)
}
}
-/*
- * Return TRUE if line "lnum" ends in a white character.
- */
+/// @return TRUE if line "lnum" ends in a white character.
static int ends_in_white(linenr_T lnum)
{
char_u *s = ml_get(lnum);
@@ -4681,14 +4802,12 @@ static int ends_in_white(linenr_T lnum)
return ascii_iswhite(s[l]);
}
-/*
- * Blank lines, and lines containing only the comment leader, are left
- * untouched by the formatting. The function returns TRUE in this
- * case. It also returns TRUE when a line starts with the end of a comment
- * ('e' in comment flags), so that this line is skipped, and not joined to the
- * previous line. A new paragraph starts after a blank line, or when the
- * comment leader changes -- webb.
- */
+/// Blank lines, and lines containing only the comment leader, are left
+/// untouched by the formatting. The function returns TRUE in this
+/// case. It also returns TRUE when a line starts with the end of a comment
+/// ('e' in comment flags), so that this line is skipped, and not joined to the
+/// previous line. A new paragraph starts after a blank line, or when the
+/// comment leader changes.
static int fmt_check_par(linenr_T lnum, int *leader_len, char_u **leader_flags, int do_comments)
{
char_u *flags = NULL; // init for GCC
@@ -4696,7 +4815,7 @@ static int fmt_check_par(linenr_T lnum, int *leader_len, char_u **leader_flags,
ptr = ml_get(lnum);
if (do_comments) {
- *leader_len = get_leader_len(ptr, leader_flags, false, true);
+ *leader_len = get_leader_len((char *)ptr, (char **)leader_flags, false, true);
} else {
*leader_len = 0;
}
@@ -4711,15 +4830,15 @@ static int fmt_check_par(linenr_T lnum, int *leader_len, char_u **leader_flags,
}
}
- return *skipwhite(ptr + *leader_len) == NUL
+ return *skipwhite((char *)ptr + *leader_len) == NUL
|| (*leader_len > 0 && *flags == COM_END)
|| startPS(lnum, NUL, FALSE);
}
-/*
- * Return TRUE when a paragraph starts in line "lnum". Return FALSE when the
- * previous line is in the same paragraph. Used for auto-formatting.
- */
+/// Used for auto-formatting.
+///
+/// @return TRUE when a paragraph starts in line "lnum".
+/// FALSE when the previous line is in the same paragraph.
int paragraph_start(linenr_T lnum)
{
char_u *p;
@@ -4757,19 +4876,17 @@ int paragraph_start(linenr_T lnum)
return FALSE;
}
-/*
- * prepare a few things for block mode yank/delete/tilde
- *
- * for delete:
- * - textlen includes the first/last char to be (partly) deleted
- * - start/endspaces is the number of columns that are taken by the
- * first/last deleted char minus the number of columns that have to be
- * deleted.
- * for yank and tilde:
- * - textlen includes the first/last char to be wholly yanked
- * - start/endspaces is the number of columns of the first/last yanked char
- * that are to be yanked.
- */
+/// prepare a few things for block mode yank/delete/tilde
+///
+/// for delete:
+/// - textlen includes the first/last char to be (partly) deleted
+/// - start/endspaces is the number of columns that are taken by the
+/// first/last deleted char minus the number of columns that have to be
+/// deleted.
+/// for yank and tilde:
+/// - textlen includes the first/last char to be wholly yanked
+/// - start/endspaces is the number of columns of the first/last yanked char
+/// that are to be yanked.
static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool is_del)
{
int incr = 0;
@@ -4899,12 +5016,19 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
ssize_t change_cnt = 0;
linenr_T amount = Prenum1;
+ // do_addsub() might trigger re-evaluation of 'foldexpr' halfway, when the
+ // buffer is not completly updated yet. Postpone updating folds until before
+ // the call to changed_lines().
+ disable_fold_update++;
+
if (!VIsual_active) {
pos = curwin->w_cursor;
if (u_save_cursor() == FAIL) {
+ disable_fold_update--;
return;
}
change_cnt = do_addsub(oap->op_type, &pos, 0, amount);
+ disable_fold_update--;
if (change_cnt) {
changed_lines(pos.lnum, 0, pos.lnum + 1, 0L, true);
}
@@ -4915,6 +5039,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
if (u_save((linenr_T)(oap->start.lnum - 1),
(linenr_T)(oap->end.lnum + 1)) == FAIL) {
+ disable_fold_update--;
return;
}
@@ -4961,6 +5086,8 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
amount += Prenum1;
}
}
+
+ disable_fold_update--;
if (change_cnt) {
changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L, true);
}
@@ -4972,7 +5099,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
// Set '[ mark if something changed. Keep the last end
// position from do_addsub().
- if (change_cnt > 0) {
+ if (change_cnt > 0 && (cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
curbuf->b_op_start = startpos;
}
@@ -5015,12 +5142,12 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
pos_T endpos;
colnr_T save_coladd = 0;
- const bool do_hex = vim_strchr(curbuf->b_p_nf, 'x') != NULL; // "heX"
- const bool do_oct = vim_strchr(curbuf->b_p_nf, 'o') != NULL; // "Octal"
- const bool do_bin = vim_strchr(curbuf->b_p_nf, 'b') != NULL; // "Bin"
- const bool do_alpha = vim_strchr(curbuf->b_p_nf, 'p') != NULL; // "alPha"
+ const bool do_hex = vim_strchr((char *)curbuf->b_p_nf, 'x') != NULL; // "heX"
+ const bool do_oct = vim_strchr((char *)curbuf->b_p_nf, 'o') != NULL; // "Octal"
+ const bool do_bin = vim_strchr((char *)curbuf->b_p_nf, 'b') != NULL; // "Bin"
+ const bool do_alpha = vim_strchr((char *)curbuf->b_p_nf, 'p') != NULL; // "alPha"
// "Unsigned"
- const bool do_unsigned = vim_strchr(curbuf->b_p_nf, 'u') != NULL;
+ const bool do_unsigned = vim_strchr((char *)curbuf->b_p_nf, 'u') != NULL;
if (virtual_active()) {
save_coladd = pos->coladd;
@@ -5103,7 +5230,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
if (visual) {
while (ptr[col] != NUL && length > 0 && !ascii_isdigit(ptr[col])
&& !(do_alpha && ASCII_ISALPHA(ptr[col]))) {
- int mb_len = utfc_ptr2len(ptr + col);
+ int mb_len = utfc_ptr2len((char *)ptr + col);
col += mb_len;
length -= mb_len;
@@ -5131,7 +5258,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
if (do_alpha && ASCII_ISALPHA(firstdigit)) {
// decrement or increment alphabetic character
if (op_type == OP_NR_SUB) {
- if (CharOrd(firstdigit) < Prenum1) {
+ if (CHAR_ORD(firstdigit) < Prenum1) {
if (isupper(firstdigit)) {
firstdigit = 'A';
} else {
@@ -5141,7 +5268,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
firstdigit -= (int)Prenum1;
}
} else {
- if (26 - CharOrd(firstdigit) - 1 < Prenum1) {
+ if (26 - CHAR_ORD(firstdigit) - 1 < Prenum1) {
if (isupper(firstdigit)) {
firstdigit = 'Z';
} else {
@@ -5206,13 +5333,13 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
if (!pre) {
if (subtract) {
if (n > oldn) {
- n = 1 + (n ^ (uvarnumber_T)-1);
+ n = 1 + (n ^ (uvarnumber_T) - 1);
negative ^= true;
}
} else {
// add
if (n < oldn) {
- n = (n ^ (uvarnumber_T)-1);
+ n = (n ^ (uvarnumber_T) - 1);
negative ^= true;
}
}
@@ -5326,11 +5453,13 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
}
}
- // set the '[ and '] marks
- curbuf->b_op_start = startpos;
- curbuf->b_op_end = endpos;
- if (curbuf->b_op_end.col > 0) {
- curbuf->b_op_end.col--;
+ if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
+ // set the '[ and '] marks
+ curbuf->b_op_start = startpos;
+ curbuf->b_op_end = endpos;
+ if (curbuf->b_op_end.col > 0) {
+ curbuf->b_op_end.col--;
+ }
}
theend:
@@ -5346,11 +5475,10 @@ theend:
return did_change;
}
-/*
- * Return the type of a register.
- * Used for getregtype()
- * Returns kMTUnknown for error.
- */
+/// Used for getregtype()
+///
+/// @return the type of a register or
+/// kMTUnknown for error.
MotionType get_reg_type(int regname, colnr_T *reg_width)
{
switch (regname) {
@@ -5412,11 +5540,10 @@ void format_reg_type(MotionType reg_type, colnr_T reg_width, char *buf, size_t b
}
}
-
/// When `flags` has `kGRegList` return a list with text `s`.
/// Otherwise just return `s`.
///
-/// Returns a void * for use in get_reg_contents().
+/// @return a void * for use in get_reg_contents().
static void *get_reg_wrap_one_line(char_u *s, int flags)
{
if (!(flags & kGRegList)) {
@@ -5554,7 +5681,7 @@ static void finish_write_reg(int name, yankreg_T *reg, yankreg_T *old_y_previous
}
}
-/// write_reg_contents - store `str` in register `name`
+/// store `str` in register `name`
///
/// @see write_reg_contents_ex
void write_reg_contents(int name, const char_u *str, ssize_t len, int must_append)
@@ -5635,7 +5762,7 @@ void write_reg_contents_ex(int name, const char_u *str, ssize_t len, bool must_a
semsg(_(e_nobufnr), (int64_t)num);
}
} else {
- buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str),
+ buf = buflist_findnr(buflist_findpat((char *)str, (char *)str + STRLEN(str),
true, false, false));
}
if (buf == NULL) {
@@ -5734,7 +5861,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char_u *str
// Grow the register array to hold the pointers to the new lines.
char_u **pp = xrealloc(y_ptr->y_array,
(y_ptr->y_size + newlines) * sizeof(char_u *));
- y_ptr->y_array = pp;
+ y_ptr->y_array = (char **)pp;
size_t lnum = y_ptr->y_size; // The current line number.
@@ -5764,8 +5891,10 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char_u *str
// When appending, copy the previous line and free it after.
size_t extra = append ? STRLEN(pp[--lnum]) : 0;
- char_u *s = xmallocz(line_len + extra);
- memcpy(s, pp[lnum], extra);
+ char *s = xmallocz(line_len + extra);
+ if (extra > 0) {
+ memcpy(s, pp[lnum], extra);
+ }
memcpy(s + extra, start, line_len);
size_t s_len = extra + line_len;
@@ -5773,7 +5902,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char_u *str
xfree(pp[lnum]);
append = false; // only first line is appended
}
- pp[lnum] = s;
+ pp[lnum] = (char_u *)s;
// Convert NULs to '\n' to prevent truncation.
memchrsub(pp[lnum], NUL, '\n', s_len);
@@ -5795,21 +5924,18 @@ void clear_oparg(oparg_T *oap)
memset(oap, 0, sizeof(oparg_T));
}
-
-/*
- * Count the number of bytes, characters and "words" in a line.
- *
- * "Words" are counted by looking for boundaries between non-space and
- * space characters. (it seems to produce results that match 'wc'.)
- *
- * Return value is byte count; word count for the line is added to "*wc".
- * Char count is added to "*cc".
- *
- * The function will only examine the first "limit" characters in the
- * line, stopping if it encounters an end-of-line (NUL byte). In that
- * case, eol_size will be added to the character count to account for
- * the size of the EOL character.
- */
+/// Count the number of bytes, characters and "words" in a line.
+///
+/// "Words" are counted by looking for boundaries between non-space and
+/// space characters. (it seems to produce results that match 'wc'.)
+///
+/// Return value is byte count; word count for the line is added to "*wc".
+/// Char count is added to "*cc".
+///
+/// The function will only examine the first "limit" characters in the
+/// line, stopping if it encounters an end-of-line (NUL byte). In that
+/// case, eol_size will be added to the character count to account for
+/// the size of the EOL character.
static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *cc,
varnumber_T limit, int eol_size)
{
@@ -5828,7 +5954,7 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c
is_word = 1;
}
chars++;
- i += utfc_ptr2len(line + i);
+ i += utfc_ptr2len((char *)line + i);
}
if (is_word) {
@@ -5848,7 +5974,8 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c
/// Give some info about the position of the cursor (for "g CTRL-G").
/// In Visual mode, give some info about the selected region. (In this case,
/// the *_count_cursor variables store running totals for the selection.)
-/// When "dict" is not NULL store the info there instead of showing it.
+///
+/// @param dict when not NULL, store the info there instead of showing it.
void cursor_pos_info(dict_T *dict)
{
char_u *p;
@@ -6031,9 +6158,9 @@ void cursor_pos_info(dict_T *dict)
} else {
p = get_cursor_line_ptr();
validate_virtcol();
- col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
+ col_print((char *)buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
(int)curwin->w_virtcol + 1);
- col_print(buf2, sizeof(buf2), (int)STRLEN(p), linetabsize(p));
+ col_print((char *)buf2, sizeof(buf2), (int)STRLEN(p), linetabsize(p));
if (char_count_cursor == byte_count_cursor
&& char_count == byte_count) {
@@ -6072,6 +6199,10 @@ void cursor_pos_info(dict_T *dict)
// Don't shorten this message, the user asked for it.
p = p_shm;
p_shm = (char_u *)"";
+ if (p_ch < 1) {
+ msg_start();
+ msg_scroll = true;
+ }
msg((char *)IObuff);
p_shm = p;
}
@@ -6094,7 +6225,7 @@ void cursor_pos_info(dict_T *dict)
}
}
-// Handle indent and format operators and visual mode ":".
+/// Handle indent and format operators and visual mode ":".
static void op_colon(oparg_T *oap)
{
stuffcharReadbuff(':');
@@ -6141,12 +6272,14 @@ static void op_colon(oparg_T *oap)
// do_cmdline() does the rest
}
-// Handle the "g@" operator: call 'operatorfunc'.
+/// Handle the "g@" operator: call 'operatorfunc'.
static void op_function(const oparg_T *oap)
FUNC_ATTR_NONNULL_ALL
{
const TriState save_virtual_op = virtual_op;
const bool save_finish_op = finish_op;
+ const pos_T orig_start = curbuf->b_op_start;
+ const pos_T orig_end = curbuf->b_op_end;
if (*p_opfunc == NUL) {
emsg(_("E774: 'operatorfunc' is empty"));
@@ -6163,7 +6296,7 @@ static void op_function(const oparg_T *oap)
argv[0].v_type = VAR_STRING;
argv[1].v_type = VAR_UNKNOWN;
argv[0].vval.v_string =
- (char_u *)(((const char *const[]) {
+ (char *)(((const char *const[]) {
[kMTBlockWise] = "block",
[kMTLineWise] = "line",
[kMTCharWise] = "char",
@@ -6176,10 +6309,14 @@ static void op_function(const oparg_T *oap)
// Reset finish_op so that mode() returns the right value.
finish_op = false;
- (void)call_func_retnr(p_opfunc, 1, argv);
+ (void)call_func_retnr((char *)p_opfunc, 1, argv);
virtual_op = save_virtual_op;
finish_op = save_finish_op;
+ if (cmdmod.cmod_flags & CMOD_LOCKMARKS) {
+ curbuf->b_op_start = orig_start;
+ curbuf->b_op_end = orig_end;
+ }
}
}
@@ -6248,8 +6385,17 @@ static void get_op_vcol(oparg_T *oap, colnr_T redo_VIsual_vcol, bool initial)
oap->start = curwin->w_cursor;
}
-// Handle an operator after Visual mode or when the movement is finished.
-// "gui_yank" is true when yanking text for the clipboard.
+/// Information for redoing the previous Visual selection.
+typedef struct {
+ int rv_mode; ///< 'v', 'V', or Ctrl-V
+ linenr_T rv_line_count; ///< number of lines
+ colnr_T rv_vcol; ///< number of cols or end column
+ long rv_count; ///< count for Visual operator
+ int rv_arg; ///< extra argument
+} redo_VIsual_T;
+
+/// Handle an operator after Visual mode or when the movement is finished.
+/// "gui_yank" is true when yanking text for the clipboard.
void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
{
oparg_T *oap = cap->oap;
@@ -6258,13 +6404,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
int restart_edit_save;
int lbr_saved = curwin->w_p_lbr;
-
// The visual area is remembered for redo
- static int redo_VIsual_mode = NUL; // 'v', 'V', or Ctrl-V
- static linenr_T redo_VIsual_line_count; // number of lines
- static colnr_T redo_VIsual_vcol; // number of cols or end column
- static long redo_VIsual_count; // count for Visual operator
- static int redo_VIsual_arg; // extra argument
+ static redo_VIsual_T redo_VIsual = { NUL, 0, 0, 0, 0 };
+
bool include_line_break = false;
old_cursor = curwin->w_cursor;
@@ -6328,7 +6470,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
// If 'cpoptions' does not contain 'r', insert the search
// pattern to really repeat the same command.
if (vim_strchr(p_cpo, CPO_REDO) == NULL) {
- AppendToRedobuffLit(cap->searchbuf, -1);
+ AppendToRedobuffLit((char *)cap->searchbuf, -1);
}
AppendToRedobuff(NL_STR);
} else if (cap->cmdchar == ':' || cap->cmdchar == K_COMMAND) {
@@ -6338,7 +6480,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
if (repeat_cmdline == NULL) {
ResetRedobuff();
} else {
- AppendToRedobuffLit(repeat_cmdline, -1);
+ AppendToRedobuffLit((char *)repeat_cmdline, -1);
AppendToRedobuff(NL_STR);
XFREE_CLEAR(repeat_cmdline);
}
@@ -6347,28 +6489,27 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
if (redo_VIsual_busy) {
// Redo of an operation on a Visual area. Use the same size from
- // redo_VIsual_line_count and redo_VIsual_vcol.
+ // redo_VIsual.rv_line_count and redo_VIsual.rv_vcol.
oap->start = curwin->w_cursor;
- curwin->w_cursor.lnum += redo_VIsual_line_count - 1;
+ curwin->w_cursor.lnum += redo_VIsual.rv_line_count - 1;
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
}
- VIsual_mode = redo_VIsual_mode;
- if (redo_VIsual_vcol == MAXCOL || VIsual_mode == 'v') {
+ VIsual_mode = redo_VIsual.rv_mode;
+ if (redo_VIsual.rv_vcol == MAXCOL || VIsual_mode == 'v') {
if (VIsual_mode == 'v') {
- if (redo_VIsual_line_count <= 1) {
+ if (redo_VIsual.rv_line_count <= 1) {
validate_virtcol();
- curwin->w_curswant =
- curwin->w_virtcol + redo_VIsual_vcol - 1;
+ curwin->w_curswant = curwin->w_virtcol + redo_VIsual.rv_vcol - 1;
} else {
- curwin->w_curswant = redo_VIsual_vcol;
+ curwin->w_curswant = redo_VIsual.rv_vcol;
}
} else {
curwin->w_curswant = MAXCOL;
}
coladvance(curwin->w_curswant);
}
- cap->count0 = redo_VIsual_count;
+ cap->count0 = redo_VIsual.rv_count;
cap->count1 = (cap->count0 == 0 ? 1 : cap->count0);
} else if (VIsual_active) {
if (!gui_yank) {
@@ -6455,7 +6596,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
virtual_op = virtual_active();
if (VIsual_active || redo_VIsual_busy) {
- get_op_vcol(oap, redo_VIsual_vcol, true);
+ get_op_vcol(oap, redo_VIsual.rv_vcol, true);
if (!redo_VIsual_busy && !gui_yank) {
// Prepare to reselect and redo Visual: this is based on the
@@ -6478,7 +6619,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
resel_VIsual_vcol = oap->end_vcol;
}
}
- resel_VIsual_line_count = oap->line_count;
+ resel_VIsual_line_count = (linenr_T)oap->line_count;
}
// can't redo yank (unless 'y' is in 'cpoptions') and ":"
@@ -6500,6 +6641,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
get_op_char(oap->op_type), get_extra_op_char(oap->op_type),
oap->motion_force, cap->cmdchar, cap->nchar);
} else if (cap->cmdchar != ':' && cap->cmdchar != K_COMMAND) {
+ int opchar = get_op_char(oap->op_type);
+ int extra_opchar = get_extra_op_char(oap->op_type);
int nchar = oap->op_type == OP_REPLACE ? cap->nchar : NUL;
// reverse what nv_replace() did
@@ -6508,15 +6651,20 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
} else if (nchar == REPLACE_NL_NCHAR) {
nchar = NL;
}
- prep_redo(oap->regname, 0L, NUL, 'v', get_op_char(oap->op_type),
- get_extra_op_char(oap->op_type), nchar);
+
+ if (opchar == 'g' && extra_opchar == '@') {
+ // also repeat the count for 'operatorfunc'
+ prep_redo_num2(oap->regname, 0L, NUL, 'v', cap->count0, opchar, extra_opchar, nchar);
+ } else {
+ prep_redo(oap->regname, 0L, NUL, 'v', opchar, extra_opchar, nchar);
+ }
}
if (!redo_VIsual_busy) {
- redo_VIsual_mode = resel_VIsual_mode;
- redo_VIsual_vcol = resel_VIsual_vcol;
- redo_VIsual_line_count = resel_VIsual_line_count;
- redo_VIsual_count = cap->count0;
- redo_VIsual_arg = cap->arg;
+ redo_VIsual.rv_mode = resel_VIsual_mode;
+ redo_VIsual.rv_vcol = resel_VIsual_vcol;
+ redo_VIsual.rv_line_count = resel_VIsual_line_count;
+ redo_VIsual.rv_count = cap->count0;
+ redo_VIsual.rv_arg = cap->arg;
}
}
@@ -6572,7 +6720,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
// Include the trailing byte of a multi-byte char.
if (oap->inclusive) {
- const int l = utfc_ptr2len(ml_get_pos(&oap->end));
+ const int l = utfc_ptr2len((char *)ml_get_pos(&oap->end));
if (l > 1) {
oap->end.col += l - 1;
}
@@ -6630,9 +6778,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
switch (oap->op_type) {
case OP_LSHIFT:
case OP_RSHIFT:
- op_shift(oap, true,
- oap->is_VIsual ? (int)cap->count1 :
- 1);
+ op_shift(oap, true, oap->is_VIsual ? (int)cap->count1 : 1);
auto_format(false, true);
break;
@@ -6676,7 +6822,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
} else {
curwin->w_p_lbr = lbr_saved;
oap->excl_tr_ws = cap->cmdchar == 'z';
- (void)op_yank(oap, !gui_yank, false);
+ (void)op_yank(oap, !gui_yank);
}
check_cursor_col();
break;
@@ -6688,10 +6834,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
CancelRedo();
} else {
// This is a new edit command, not a restart. Need to
- // remember it to make 'insertmode' work with mappings for
- // Visual mode. But do this only once and not when typed and
- // 'insertmode' isn't set.
- if (p_im || !KeyTyped) {
+ // remember it to make i_CTRL-O work with mappings for
+ // Visual mode. But do this only once and not when typed.
+ if (!KeyTyped) {
restart_edit_save = restart_edit;
} else {
restart_edit_save = 0;
@@ -6767,12 +6912,20 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
op_format(oap, true); // use internal function
break;
- case OP_FUNCTION:
+ case OP_FUNCTION: {
+ redo_VIsual_T save_redo_VIsual = redo_VIsual;
+
// Restore linebreak, so that when the user edits it looks as
// before.
curwin->w_p_lbr = lbr_saved;
- op_function(oap); // call 'operatorfunc'
+ // call 'operatorfunc'
+ op_function(oap);
+
+ // Restore the info for redoing Visual mode, the function may
+ // invoke another operator and unintentionally change it.
+ redo_VIsual = save_redo_VIsual;
break;
+ }
case OP_INSERT:
case OP_APPEND:
@@ -6782,7 +6935,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
CancelRedo();
} else {
// This is a new edit command, not a restart. Need to
- // remember it to make 'insertmode' work with mappings for
+ // remember it to make i_CTRL-O work with mappings for
// Visual mode. But do this only once.
restart_edit_save = restart_edit;
restart_edit = 0;
@@ -6853,7 +7006,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
} else {
VIsual_active = true;
curwin->w_p_lbr = lbr_saved;
- op_addsub(oap, cap->count1, redo_VIsual_arg);
+ op_addsub(oap, (linenr_T)cap->count1, redo_VIsual.rv_arg);
VIsual_active = false;
}
check_cursor_col();
@@ -6990,9 +7143,9 @@ bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines)
if (!ascii_isdigit(regtype.data[1])) {
return false;
}
- const char *p = regtype.data+1;
- reg->y_width = getdigits_int((char_u **)&p, false, 1) - 1;
- if (regtype.size > (size_t)(p-regtype.data)) {
+ const char *p = regtype.data + 1;
+ reg->y_width = getdigits_int((char **)&p, false, 1) - 1;
+ if (regtype.size > (size_t)(p - regtype.data)) {
return false;
}
}
@@ -7006,12 +7159,12 @@ bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines)
void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust)
{
- if (reg->y_size > 0 && STRLEN(reg->y_array[reg->y_size-1]) == 0) {
+ if (reg->y_size > 0 && STRLEN(reg->y_array[reg->y_size - 1]) == 0) {
// a known-to-be charwise yank might have a final linebreak
// but otherwise there is no line after the final newline
if (reg->y_type != kMTCharWise) {
if (reg->y_type == kMTUnknown || clipboard_adjust) {
- xfree(reg->y_array[reg->y_size-1]);
+ xfree(reg->y_array[reg->y_size - 1]);
reg->y_size--;
}
if (reg->y_type == kMTUnknown) {
@@ -7070,7 +7223,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
if (TV_LIST_ITEM_TV(tv_list_last(res))->v_type != VAR_STRING) {
goto err;
}
- char_u *regtype = TV_LIST_ITEM_TV(tv_list_last(res))->vval.v_string;
+ char_u *regtype = (char_u *)TV_LIST_ITEM_TV(tv_list_last(res))->vval.v_string;
if (regtype == NULL || STRLEN(regtype) > 1) {
goto err;
}
@@ -7099,7 +7252,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
reg->y_type = kMTUnknown;
}
- reg->y_array = xcalloc((size_t)tv_list_len(lines), sizeof(char_u *));
+ reg->y_array = xcalloc((size_t)tv_list_len(lines), sizeof(char *));
reg->y_size = (size_t)tv_list_len(lines);
reg->additional_data = NULL;
reg->timestamp = 0;
@@ -7111,14 +7264,14 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
if (TV_LIST_ITEM_TV(li)->v_type != VAR_STRING) {
goto err;
}
- reg->y_array[tv_idx++] = (char_u *)xstrdupnul((const char *)TV_LIST_ITEM_TV(li)->vval.v_string);
+ reg->y_array[tv_idx++] = xstrdupnul((const char *)TV_LIST_ITEM_TV(li)->vval.v_string);
});
- if (reg->y_size > 0 && STRLEN(reg->y_array[reg->y_size-1]) == 0) {
+ if (reg->y_size > 0 && STRLEN(reg->y_array[reg->y_size - 1]) == 0) {
// a known-to-be charwise yank might have a final linebreak
// but otherwise there is no line after the final newline
if (reg->y_type != kMTCharWise) {
- xfree(reg->y_array[reg->y_size-1]);
+ xfree(reg->y_array[reg->y_size - 1]);
reg->y_size--;
if (reg->y_type == kMTUnknown) {
reg->y_type = kMTLineWise;
@@ -7248,7 +7401,6 @@ void restore_batch_count(int save_count)
}
}
-
/// Check whether register is empty
static inline bool reg_empty(const yankreg_T *const reg)
FUNC_ATTR_PURE
@@ -7361,7 +7513,6 @@ const yankreg_T *op_reg_get(const char name)
///
/// @return true on success, false on failure.
bool op_reg_set_previous(const char name)
- FUNC_ATTR_WARN_UNUSED_RESULT
{
int i = op_reg_index(name);
if (i == -1) {
@@ -7388,7 +7539,7 @@ bcount_t get_region_bytecount(buf_T *buf, linenr_T start_lnum, linenr_T end_lnum
const char *first = (const char *)ml_get_buf(buf, start_lnum, false);
bcount_t deleted_bytes = (bcount_t)STRLEN(first) - start_col + 1;
- for (linenr_T i = 1; i <= end_lnum-start_lnum-1; i++) {
+ for (linenr_T i = 1; i <= end_lnum - start_lnum - 1; i++) {
if (start_lnum + i > max_lnum) {
return deleted_bytes;
}