diff options
Diffstat (limited to 'src/nvim/ops.c')
-rw-r--r-- | src/nvim/ops.c | 561 |
1 files changed, 303 insertions, 258 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c index d3a47d77a2..435ca106ab 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5,13 +5,18 @@ // op_change, op_yank, do_put, do_join #include <assert.h> +#include <ctype.h> #include <inttypes.h> +#include <limits.h> #include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> -#include "klib/kvec.h" +#include "nvim/api/private/defs.h" #include "nvim/ascii.h" #include "nvim/assert.h" +#include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/change.h" #include "nvim/charset.h" @@ -20,16 +25,19 @@ #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" -#include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/ex_getln.h" #include "nvim/extmark.h" #include "nvim/fold.h" +#include "nvim/garray.h" #include "nvim/getchar.h" +#include "nvim/gettext.h" #include "nvim/globals.h" +#include "nvim/highlight_defs.h" #include "nvim/indent.h" #include "nvim/indent_c.h" -#include "nvim/log.h" +#include "nvim/keycodes.h" #include "nvim/macros.h" #include "nvim/mark.h" #include "nvim/mbyte.h" @@ -43,13 +51,14 @@ #include "nvim/option.h" #include "nvim/os/input.h" #include "nvim/os/time.h" -#include "nvim/path.h" #include "nvim/plines.h" +#include "nvim/screen.h" #include "nvim/search.h" #include "nvim/state.h" #include "nvim/strings.h" #include "nvim/terminal.h" #include "nvim/textformat.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/vim.h" @@ -71,7 +80,7 @@ struct block_def { int startspaces; // 'extra' cols before first char int endspaces; // 'extra' cols after last char int textlen; // chars in block - char_u *textstart; // pointer to 1st char (partially) in block + char *textstart; // pointer to 1st char (partially) in block colnr_T textcol; // index of chars (partially) in block colnr_T start_vcol; // start col of 1st char wholly inside block colnr_T end_vcol; // start col of 1st char wholly after block @@ -81,7 +90,7 @@ struct block_def { int pre_whitesp; // screen cols of ws before block int pre_whitesp_c; // chars of ws before block colnr_T end_char_vcols; // number of vcols of post-block char - colnr_T start_char_vcols; // number of vcols of pre-block char + colnr_T start_char_vcols; // number of vcols of pre-block char }; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -95,8 +104,7 @@ struct block_def { // The names of operators. // IMPORTANT: Index must correspond with defines in vim.h!!! // The third field indicates whether the operator always works on lines. -static char opchars[][3] = -{ +static char opchars[][3] = { { NUL, NUL, 0 }, // OP_NOP { 'd', NUL, OPF_CHANGE }, // OP_DELETE { 'y', NUL, 0 }, // OP_YANK @@ -256,10 +264,10 @@ void op_shift(oparg_T *oap, int curs_top, int amount) "%" PRId64 " line %sed %d times", amount); char *msg_line_plural = NGETTEXT("%" PRId64 " lines %sed %d time", "%" PRId64 " lines %sed %d times", amount); - vim_snprintf((char *)IObuff, IOSIZE, + vim_snprintf(IObuff, IOSIZE, NGETTEXT(msg_line_single, msg_line_plural, oap->line_count), (int64_t)oap->line_count, op, amount); - msg_attr_keep((char *)IObuff, 0, true, false); + msg_attr_keep(IObuff, 0, true, false); } if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) { @@ -327,7 +335,7 @@ static void shift_block(oparg_T *oap, int amount) { const bool left = (oap->op_type == OP_LSHIFT); const int oldstate = State; - char_u *newp; + char *newp; const int oldcol = curwin->w_cursor.col; const int sw_val = (int)get_sw_value_indent(curbuf); const int ts_val = (int)curbuf->b_p_ts; @@ -350,7 +358,7 @@ static void shift_block(oparg_T *oap, int amount) return; // multiplication overflow } - char_u *const oldp = (char_u *)get_cursor_line_ptr(); + char *const oldp = get_cursor_line_ptr(); int startcol, oldlen, newlen; @@ -361,9 +369,9 @@ static void shift_block(oparg_T *oap, int amount) // 4. Construct new string total += bd.pre_whitesp; // all virtual WS up to & incl a split TAB colnr_T ws_vcol = bd.start_vcol - bd.pre_whitesp; - char_u *old_textstart = bd.textstart; + char *old_textstart = bd.textstart; if (bd.startspaces) { - if (utfc_ptr2len((char *)bd.textstart) == 1) { + if (utfc_ptr2len(bd.textstart) == 1) { bd.textstart++; } else { ws_vcol = 0; @@ -374,13 +382,13 @@ static void shift_block(oparg_T *oap, int amount) // TODO(vim): is passing bd.textstart for start of the line OK? chartabsize_T cts; init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, - bd.start_vcol, (char *)bd.textstart, (char *)bd.textstart); + bd.start_vcol, bd.textstart, bd.textstart); while (ascii_iswhite(*cts.cts_ptr)) { incr = lbr_chartabsize_adv(&cts); total += incr; cts.cts_vcol += incr; } - bd.textstart = (char_u *)cts.cts_ptr; + bd.textstart = cts.cts_ptr; bd.start_vcol = cts.cts_vcol; clear_chartabsize_arg(&cts); @@ -395,10 +403,10 @@ static void shift_block(oparg_T *oap, int amount) // if we're splitting a TAB, allow for it int col_pre = bd.pre_whitesp_c - (bd.startspaces != 0); bd.textcol -= col_pre; - const int len = (int)STRLEN(bd.textstart) + 1; + const int len = (int)strlen(bd.textstart) + 1; int col = bd.textcol + i + j + len; assert(col >= 0); - newp = (char_u *)xmalloc((size_t)col); + newp = xmalloc((size_t)col); memset(newp, NUL, (size_t)col); memmove(newp, oldp, (size_t)bd.textcol); startcol = bd.textcol; @@ -411,14 +419,14 @@ static void shift_block(oparg_T *oap, int amount) } else { // left colnr_T destination_col; // column to which text in block will // be shifted - char_u *verbatim_copy_end; // end of the part of the line which is + char *verbatim_copy_end; // end of the part of the line which is // copied verbatim colnr_T verbatim_copy_width; // the (displayed) width of this part // of line size_t fill; // nr of spaces that replace a TAB size_t new_line_len; // the length of the line after the // block shift - char_u *non_white = bd.textstart; + char *non_white = bd.textstart; // Firstly, let's find the first non-whitespace character that is // displayed after the block's start column and the character's column @@ -438,13 +446,13 @@ static void shift_block(oparg_T *oap, int amount) chartabsize_T cts; init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, - non_white_col, (char *)bd.textstart, (char *)non_white); + non_white_col, bd.textstart, non_white); while (ascii_iswhite(*cts.cts_ptr)) { incr = lbr_chartabsize_adv(&cts); cts.cts_vcol += incr; } non_white_col = cts.cts_vcol; - non_white = (char_u *)cts.cts_ptr; + non_white = cts.cts_ptr; clear_chartabsize_arg(&cts); const colnr_T block_space_width = non_white_col - oap->start_vcol; @@ -467,7 +475,7 @@ static void shift_block(oparg_T *oap, int amount) verbatim_copy_width -= bd.start_char_vcols; } init_chartabsize_arg(&cts, curwin, 0, verbatim_copy_width, - (char *)bd.textstart, (char *)verbatim_copy_end); + bd.textstart, verbatim_copy_end); while (cts.cts_vcol < destination_col) { incr = lbr_chartabsize(&cts); if (cts.cts_vcol + incr > destination_col) { @@ -477,7 +485,7 @@ static void shift_block(oparg_T *oap, int amount) MB_PTR_ADV(cts.cts_ptr); } verbatim_copy_width = cts.cts_vcol; - verbatim_copy_end = (char_u *)cts.cts_ptr; + verbatim_copy_end = cts.cts_ptr; clear_chartabsize_arg(&cts); // If "destination_col" is different from the width of the initial @@ -492,9 +500,9 @@ static void shift_block(oparg_T *oap, int amount) // - the beginning of the original line up to "verbatim_copy_end", // - "fill" number of spaces, // - the rest of the line, pointed to by non_white. - new_line_len = verbatim_diff + fill + STRLEN(non_white) + 1; + new_line_len = verbatim_diff + fill + strlen(non_white) + 1; - newp = (char_u *)xmalloc(new_line_len); + newp = xmalloc(new_line_len); startcol = (int)verbatim_diff; oldlen = bd.textcol + (int)(non_white - bd.textstart) - (int)verbatim_diff; newlen = (int)fill; @@ -503,7 +511,7 @@ 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, (char *)newp, false); + ml_replace(curwin->w_cursor.lnum, newp, false); changed_bytes(curwin->w_cursor.lnum, bd.textcol); extmark_splice_cols(curbuf, (int)curwin->w_cursor.lnum - 1, startcol, oldlen, newlen, @@ -515,14 +523,14 @@ static void shift_block(oparg_T *oap, int amount) /// 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) +static void block_insert(oparg_T *oap, char *s, int b_insert, struct block_def *bdp) { int ts_val; int count = 0; // extra spaces to replace a cut TAB int spaces = 0; // non-zero if cutting a TAB colnr_T offset; // pointer along new line - size_t s_len = STRLEN(s); - char_u *newp, *oldp; // new, old lines + size_t s_len = strlen(s); + char *newp, *oldp; // new, old lines linenr_T lnum; // loop var int oldstate = State; State = MODE_INSERT; // don't want MODE_REPLACE for State @@ -533,7 +541,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def continue; // OP_INSERT, line ends before block start } - oldp = (char_u *)ml_get(lnum); + oldp = ml_get(lnum); if (b_insert) { ts_val = bdp->start_char_vcols; @@ -562,7 +570,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def if (spaces > 0) { // avoid copying part of a multi-byte character - offset -= utf_head_off((char *)oldp, (char *)oldp + offset); + offset -= utf_head_off(oldp, oldp + offset); } if (spaces < 0) { // can happen when the cursor was moved spaces = 0; @@ -570,7 +578,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def assert(count >= 0); // Make sure the allocated size matches what is actually copied below. - newp = xmalloc(STRLEN(oldp) + (size_t)spaces + s_len + newp = xmalloc(strlen(oldp) + (size_t)spaces + s_len + (spaces > 0 && !bdp->is_short ? (size_t)ts_val - (size_t)spaces : 0) + (size_t)count + 1); @@ -607,7 +615,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def } STRMOVE(newp + offset, oldp); - ml_replace(lnum, (char *)newp, false); + ml_replace(lnum, newp, false); extmark_splice_cols(curbuf, (int)lnum - 1, startcol, skipped, offset - startcol, kExtmarkUndo); @@ -628,7 +636,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def void op_reindent(oparg_T *oap, Indenter how) { long i = 0; - char_u *l; + char *l; int amount; linenr_T first_changed = 0; linenr_T last_changed = 0; @@ -658,7 +666,7 @@ void op_reindent(oparg_T *oap, Indenter how) // 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(get_cursor_line_ptr()); + l = skipwhite(get_cursor_line_ptr()); if (*l == NUL) { // empty or blank line amount = 0; } else { @@ -706,14 +714,14 @@ void op_reindent(oparg_T *oap, Indenter how) } // Keep the last expression line here, for repeating. -static char_u *expr_line = NULL; +static char *expr_line = NULL; /// Get an expression for the "\"=expr1" or "CTRL-R =expr1" /// /// @return '=' when OK, NUL otherwise. int get_expr_register(void) { - char_u *new_line; + char *new_line; new_line = getcmdline('=', 0L, 0, true); if (new_line == NULL) { @@ -722,7 +730,7 @@ int get_expr_register(void) if (*new_line == NUL) { // use previous line xfree(new_line); } else { - set_expr_line((char *)new_line); + set_expr_line(new_line); } return '='; } @@ -732,7 +740,7 @@ int get_expr_register(void) void set_expr_line(char *new_line) { xfree(expr_line); - expr_line = (char_u *)new_line; + expr_line = new_line; } /// Get the result of the '=' register expression. @@ -750,7 +758,7 @@ char *get_expr_line(void) // Make a copy of the expression, because evaluating it may cause it to be // changed. - expr_copy = xstrdup((char *)expr_line); + expr_copy = xstrdup(expr_line); // When we are invoked recursively limit the evaluation to 10 levels. // Then return the string as-is. @@ -771,7 +779,7 @@ char *get_expr_line_src(void) if (expr_line == NULL) { return NULL; } - return xstrdup((char *)expr_line); + return xstrdup(expr_line); } /// @return whether `regname` is a valid name of a yank register. @@ -894,7 +902,7 @@ bool yank_register_mline(int regname) /// @return FAIL for failure, OK otherwise. int do_record(int c) { - char_u *p; + char *p; static int regname; yankreg_T *old_y_previous; int retval; @@ -919,10 +927,10 @@ int do_record(int c) dict_T *dict = get_v_event(&save_v_event); // The recorded text contents. - p = get_recorded(); + p = (char *)get_recorded(); if (p != NULL) { // Remove escaping for K_SPECIAL in multi-byte chars. - vim_unescape_ks(p); + vim_unescape_ks((char_u *)p); (void)tv_dict_add_str(dict, S_LEN("regcontents"), (const char *)p); } @@ -974,7 +982,7 @@ static void set_yreg_additional_data(yankreg_T *reg, dict_T *additional_data) /// uppercase). "p" must have been allocated. /// /// @return FAIL for failure, OK otherwise -static int stuff_yank(int regname, char_u *p) +static int stuff_yank(int regname, char *p) { // check for read-only register if (regname != 0 && !valid_yank_reg(regname, true)) { @@ -988,18 +996,18 @@ 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 **pp = &(reg->y_array[reg->y_size - 1]); - char_u *lp = xmalloc(strlen(*pp) + STRLEN(p) + 1); + char *lp = xmalloc(strlen(*pp) + strlen(p) + 1); STRCPY(lp, *pp); // TODO(philix): use xstpcpy() in stuff_yank() STRCAT(lp, p); xfree(p); xfree(*pp); - *pp = (char *)lp; + *pp = lp; } else { free_register(reg); set_yreg_additional_data(reg, NULL); - reg->y_array = xmalloc(sizeof(char_u *)); - reg->y_array[0] = (char *)p; + reg->y_array = xmalloc(sizeof(char *)); + reg->y_array[0] = p; reg->y_size = 1; reg->y_type = kMTCharWise; } @@ -1020,22 +1028,22 @@ static int execreg_lastc = NUL; /// 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 **lines, size_t *idx) +static char *execreg_line_continuation(char **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); + ga_init(&ga, (int)sizeof(char), 400); - char_u *p; + char *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(lines[i]); + p = skipwhite(lines[i]); if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' ')) { break; } @@ -1045,14 +1053,14 @@ static char_u *execreg_line_continuation(char **lines, size_t *idx) // join all the lines ga_concat(&ga, lines[cmd_start]); for (size_t j = cmd_start + 1; j <= cmd_end; j++) { - p = (char_u *)skipwhite(lines[j]); + p = skipwhite(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_concat(&ga, p + 1); } } ga_append(&ga, NUL); @@ -1060,7 +1068,7 @@ static char_u *execreg_line_continuation(char **lines, size_t *idx) ga_clear(&ga); *idx = i; - return (char_u *)str; + return str; } /// Execute a yank register: copy it into the stuff buffer @@ -1072,7 +1080,7 @@ static char_u *execreg_line_continuation(char **lines, size_t *idx) /// @return FAIL for failure, OK otherwise int do_execreg(int regname, int colon, int addcr, int silent) { - char_u *p; + char *p; int retval = OK; if (regname == '@') { // repeat previous one @@ -1101,22 +1109,22 @@ int do_execreg(int regname, int colon, int addcr, int silent) // don't keep the cmdline containing @: XFREE_CLEAR(new_last_cmdline); // Escape all control characters with a CTRL-V - p = vim_strsave_escaped_ext((char_u *)last_cmdline, - (char_u *)"\001\002\003\004\005\006\007" + p = vim_strsave_escaped_ext(last_cmdline, + "\001\002\003\004\005\006\007" "\010\011\012\013\014\015\016\017" "\020\021\022\023\024\025\026\027" "\030\031\032\033\034\035\036\037", Ctrl_V, false); // When in Visual mode "'<,'>" will be prepended to the command. // Remove it when it's already there. - if (VIsual_active && STRNCMP(p, "'<,'>", 5) == 0) { + if (VIsual_active && strncmp(p, "'<,'>", 5) == 0) { retval = put_in_typebuf(p + 5, true, true, silent); } else { retval = put_in_typebuf(p, true, true, silent); } xfree(p); } else if (regname == '=') { - p = (char_u *)get_expr_line(); + p = get_expr_line(); if (p == NULL) { return FAIL; } @@ -1151,16 +1159,16 @@ int do_execreg(int regname, int colon, int addcr, int silent) } // Handle line-continuation for :@<register> - char_u *str = (char_u *)reg->y_array[i]; + char *str = reg->y_array[i]; bool free_str = false; if (colon && i > 0) { - p = (char_u *)skipwhite((char *)str); + p = skipwhite(str); if (*p == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' ')) { str = execreg_line_continuation(reg->y_array, &i); free_str = true; } } - escaped = vim_strsave_escape_ks((char *)str); + escaped = vim_strsave_escape_ks(str); if (free_str) { xfree(str); } @@ -1185,18 +1193,20 @@ static void put_reedit_in_typebuf(int silent) { char_u buf[3]; - if (restart_edit != NUL) { - if (restart_edit == 'V') { - buf[0] = 'g'; - buf[1] = 'R'; - buf[2] = NUL; - } else { - buf[0] = (char_u)(restart_edit == 'I' ? 'i' : restart_edit); - buf[1] = NUL; - } - if (ins_typebuf((char *)buf, REMAP_NONE, 0, true, silent) == OK) { - restart_edit = NUL; - } + if (restart_edit == NUL) { + return; + } + + if (restart_edit == 'V') { + buf[0] = 'g'; + buf[1] = 'R'; + buf[2] = NUL; + } else { + buf[0] = (char_u)(restart_edit == 'I' ? 'i' : restart_edit); + buf[1] = NUL; + } + if (ins_typebuf((char *)buf, REMAP_NONE, 0, true, silent) == OK) { + restart_edit = NUL; } } @@ -1206,7 +1216,7 @@ static void put_reedit_in_typebuf(int silent) /// @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) +static int put_in_typebuf(char *s, bool esc, bool colon, int silent) { int retval = OK; @@ -1218,9 +1228,9 @@ static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent) char *p; if (esc) { - p = vim_strsave_escape_ks((char *)s); + p = vim_strsave_escape_ks(s); } else { - p = (char *)s; + p = s; } if (p == NULL) { retval = FAIL; @@ -1339,11 +1349,11 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg) if (last_search_pat() == NULL && errmsg) { emsg(_(e_noprevre)); } - *argp = (char *)last_search_pat(); + *argp = last_search_pat(); return true; case '.': // last inserted text - *argp = (char *)get_last_insert_save(); + *argp = get_last_insert_save(); *allocated = true; if (*argp == NULL && errmsg) { emsg(_(e_noinstext)); @@ -1355,9 +1365,8 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg) if (!errmsg) { return false; } - *argp - = (char *)file_name_at_cursor(FNAME_MESS | FNAME_HYP | (regname == Ctrl_P ? FNAME_EXP : 0), - 1L, NULL); + *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP | (regname == Ctrl_P ? FNAME_EXP : 0), + 1L, NULL); *allocated = true; return true; @@ -1410,11 +1419,11 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr) } for (size_t i = 0; i < reg->y_size; i++) { - cmdline_paste_str((char_u *)reg->y_array[i], literally); + cmdline_paste_str(reg->y_array[i], literally); // Insert ^M between lines, unless `remcr` is true. if (i < reg->y_size - 1 && !remcr) { - cmdline_paste_str((char_u *)"\r", literally); + cmdline_paste_str("\r", literally); } // Check for CTRL-C, in case someone tries to paste a few thousand @@ -1447,8 +1456,8 @@ int op_delete(oparg_T *oap) { int n; linenr_T lnum; - char_u *ptr; - char_u *newp, *oldp; + char *ptr; + char *newp, *oldp; struct block_def bd = { 0 }; linenr_T old_lcount = curbuf->b_ml.ml_line_count; @@ -1481,11 +1490,11 @@ int op_delete(oparg_T *oap) && oap->line_count > 1 && oap->motion_force == NUL && oap->op_type == OP_DELETE) { - ptr = (char_u *)ml_get(oap->end.lnum) + oap->end.col; + ptr = ml_get(oap->end.lnum) + oap->end.col; if (*ptr != NUL) { ptr += oap->inclusive; } - ptr = (char_u *)skipwhite((char *)ptr); + ptr = skipwhite(ptr); if (*ptr == NUL && inindent(0)) { oap->motion_type = kMTLineWise; } @@ -1579,8 +1588,8 @@ int op_delete(oparg_T *oap) // If we delete a TAB, it may be replaced by several characters. // Thus the number of characters may increase! n = bd.textlen - bd.startspaces - bd.endspaces; - oldp = (char_u *)ml_get(lnum); - newp = (char_u *)xmalloc(STRLEN(oldp) - (size_t)n + 1); + oldp = ml_get(lnum); + newp = xmalloc(strlen(oldp) - (size_t)n + 1); // copy up to deleted part memmove(newp, oldp, (size_t)bd.textcol); // insert spaces @@ -1590,7 +1599,7 @@ 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, (char *)newp, false); + ml_replace(lnum, newp, false); extmark_splice_cols(curbuf, (int)lnum - 1, bd.textcol, bd.textlen, bd.startspaces + bd.endspaces, @@ -1697,8 +1706,8 @@ int op_delete(oparg_T *oap) if (virtual_op) { // fix up things for virtualedit-delete: // break the tabs which are going to get in our way - char_u *curline = (char_u *)get_cursor_line_ptr(); - int len = (int)STRLEN(curline); + char *curline = get_cursor_line_ptr(); + int len = (int)strlen(curline); if (oap->end.coladd != 0 && (int)oap->end.col >= len - 1 @@ -1777,10 +1786,12 @@ setmarks: /// Used for deletion. static void mb_adjust_opend(oparg_T *oap) { - if (oap->inclusive) { - char *p = ml_get(oap->end.lnum); - oap->end.col += utf_cp_tail_off(p, p + oap->end.col); + if (!oap->inclusive) { + return; } + + char *p = ml_get(oap->end.lnum); + oap->end.col += utf_cp_tail_off(p, p + oap->end.col); } /// Put character 'c' at position 'lp' @@ -1811,10 +1822,10 @@ static int op_replace(oparg_T *oap, int c) { int n, numc; int num_chars; - char_u *newp, *oldp; + char *newp, *oldp; colnr_T oldlen; struct block_def bd; - char_u *after_p = NULL; + char *after_p = NULL; int had_ctrl_v_cr = false; if ((curbuf->b_ml.ml_flags & ML_EMPTY) || oap->empty) { @@ -1886,8 +1897,8 @@ static int op_replace(oparg_T *oap, int c) num_chars = numc; numc *= utf_char2len(c); - oldp = (char_u *)get_cursor_line_ptr(); - oldlen = (int)STRLEN(oldp); + oldp = get_cursor_line_ptr(); + oldlen = (int)strlen(oldp); size_t newp_size = (size_t)bd.textcol + (size_t)bd.startspaces; if (had_ctrl_v_cr || (c != '\r' && c != '\n')) { @@ -1913,7 +1924,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, (char *)newp + newp_len); + newp_len += utf_char2bytes(c, newp + newp_len); } if (!bd.is_short) { // insert post-spaces @@ -1926,16 +1937,16 @@ static int op_replace(oparg_T *oap, int c) } else { // Replacing with \r or \n means splitting the line. after_p_len = (size_t)col; - after_p = (char_u *)xmalloc(after_p_len); + after_p = xmalloc(after_p_len); memmove(after_p, oldp, after_p_len); newrows = 1; } // replace the line - ml_replace(curwin->w_cursor.lnum, (char *)newp, false); + ml_replace(curwin->w_cursor.lnum, newp, false); curbuf_splice_pending++; linenr_T baselnum = curwin->w_cursor.lnum; if (after_p != NULL) { - ml_append(curwin->w_cursor.lnum++, (char *)after_p, (int)after_p_len, false); + ml_append(curwin->w_cursor.lnum++, after_p, (int)after_p_len, false); appended_lines_mark(curwin->w_cursor.lnum, 1L); oap->end.lnum++; xfree(after_p); @@ -2087,7 +2098,7 @@ void op_tilde(oparg_T *oap) for (;;) { did_change |= swapchars(oap->op_type, &pos, pos.lnum == oap->end.lnum ? oap->end.col + 1 : - (int)STRLEN(ml_get_pos(&pos))); + (int)strlen(ml_get_pos(&pos))); if (ltoreq(oap->end, pos) || inc(&pos) == -1) { break; } @@ -2130,7 +2141,7 @@ static int swapchars(int op_type, pos_T *pos, int length) int did_change = 0; for (int todo = length; todo > 0; todo--) { - const int len = utfc_ptr2len((char *)ml_get_pos(pos)); + const int len = utfc_ptr2len(ml_get_pos(pos)); // we're counting bytes, not characters if (len > 0) { @@ -2239,7 +2250,7 @@ void op_insert(oparg_T *oap, long count1) } curwin->w_ve_flags = VE_ALL; coladvance_force(oap->op_type == OP_APPEND - ? oap->end_vcol + 1 : getviscol()); + ? oap->end_vcol + 1 : getviscol()); if (oap->op_type == OP_APPEND) { curwin->w_cursor.col--; } @@ -2408,7 +2419,7 @@ void op_insert(oparg_T *oap, long count1) ins_text = xstrnsave(firstline, (size_t)ins_len); // block handled here if (u_save(oap->start.lnum, (linenr_T)(oap->end.lnum + 1)) == OK) { - block_insert(oap, (char_u *)ins_text, (oap->op_type == OP_INSERT), &bd); + block_insert(oap, ins_text, (oap->op_type == OP_INSERT), &bd); } curwin->w_cursor.col = oap->start.col; @@ -2430,10 +2441,10 @@ int op_change(oparg_T *oap) long ins_len; long pre_textlen = 0; long pre_indent = 0; - char_u *newp; - char_u *firstline; - char_u *ins_text; - char_u *oldp; + char *newp; + char *firstline; + char *ins_text; + char *oldp; struct block_def bd; l = oap->start.col; @@ -2465,9 +2476,9 @@ int op_change(oparg_T *oap) || gchar_cursor() == NUL)) { coladvance_force(getviscol()); } - firstline = (char_u *)ml_get(oap->start.lnum); - pre_textlen = (long)STRLEN(firstline); - pre_indent = (long)getwhitecols((char *)firstline); + firstline = ml_get(oap->start.lnum); + pre_textlen = (long)strlen(firstline); + pre_indent = (long)getwhitecols(firstline); bd.textcol = curwin->w_cursor.col; } @@ -2475,8 +2486,14 @@ int op_change(oparg_T *oap) fix_indent(); } + // Reset finish_op now, don't want it set inside edit(). + const bool save_finish_op = finish_op; + finish_op = false; + retval = edit(NUL, false, (linenr_T)1); + finish_op = save_finish_op; + // In Visual block mode, handle copying the new text to all lines of the // block. // Don't repeat the insert when Insert mode ended with CTRL-C. @@ -2484,20 +2501,20 @@ int op_change(oparg_T *oap) && oap->start.lnum != oap->end.lnum && !got_int) { // Auto-indenting may have changed the indent. If the cursor was past // the indent, exclude that indent change from the inserted text. - firstline = (char_u *)ml_get(oap->start.lnum); + firstline = ml_get(oap->start.lnum); if (bd.textcol > (colnr_T)pre_indent) { - long new_indent = (long)getwhitecols((char *)firstline); + long new_indent = (long)getwhitecols(firstline); pre_textlen += new_indent - pre_indent; bd.textcol += (colnr_T)(new_indent - pre_indent); } - ins_len = (long)STRLEN(firstline) - pre_textlen; + ins_len = (long)strlen(firstline) - pre_textlen; if (ins_len > 0) { // Subsequent calls to ml_get() flush the firstline data - take a // copy of the inserted text. - ins_text = (char_u *)xmalloc((size_t)(ins_len + 1)); - STRLCPY(ins_text, firstline + bd.textcol, ins_len + 1); + ins_text = xmalloc((size_t)(ins_len + 1)); + xstrlcpy(ins_text, firstline + bd.textcol, (size_t)ins_len + 1); for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; linenr++) { block_prep(oap, &bd, linenr, true); @@ -2512,8 +2529,8 @@ int op_change(oparg_T *oap) } else { vpos.coladd = 0; } - oldp = (char_u *)ml_get(linenr); - newp = xmalloc(STRLEN(oldp) + (size_t)vpos.coladd + oldp = ml_get(linenr); + newp = xmalloc(strlen(oldp) + (size_t)vpos.coladd + (size_t)ins_len + 1); // copy up to block start memmove(newp, oldp, (size_t)bd.textcol); @@ -2524,7 +2541,7 @@ int op_change(oparg_T *oap) offset += ins_len; oldp += bd.textcol; STRMOVE(newp + offset, oldp); - ml_replace(linenr, (char *)newp, false); + ml_replace(linenr, newp, false); extmark_splice_cols(curbuf, (int)linenr - 1, bd.textcol, 0, vpos.coladd + (int)ins_len, kExtmarkUndo); } @@ -2559,12 +2576,14 @@ void free_register(yankreg_T *reg) FUNC_ATTR_NONNULL_ALL { set_yreg_additional_data(reg, NULL); - if (reg->y_array != NULL) { - for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included - xfree(reg->y_array[i]); - } - XFREE_CLEAR(reg->y_array); + if (reg->y_array == NULL) { + return; + } + + for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included + xfree(reg->y_array[i]); } + XFREE_CLEAR(reg->y_array); } /// Yanks the text between "oap->start" and "oap->end" into a yank register. @@ -2604,8 +2623,8 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) MotionType yank_type = oap->motion_type; size_t yanklines = (size_t)oap->line_count; linenr_T yankendlnum = oap->end.lnum; - char_u *p; - char_u *pnew; + char *p; + char *pnew; struct block_def bd; yankreg_T *curr = reg; // copy of current register @@ -2663,7 +2682,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) colnr_T startcol = 0, endcol = MAXCOL; int is_oneChar = false; colnr_T cs, ce; - p = (char_u *)ml_get(lnum); + p = ml_get(lnum); bd.startspaces = 0; bd.endspaces = 0; @@ -2688,7 +2707,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) // Don't add space for double-wide // char; endcol will be on last byte // of multi-byte char. - && utf_head_off((char *)p, (char *)p + endcol) == 0)) { + && utf_head_off(p, p + endcol) == 0)) { if (oap->start.lnum == oap->end.lnum && oap->start.col == oap->end.col) { // Special case: inside a single char @@ -2705,7 +2724,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) } } if (endcol == MAXCOL) { - endcol = (colnr_T)STRLEN(p); + endcol = (colnr_T)strlen(p); } if (startcol > endcol || is_oneChar) { @@ -2724,7 +2743,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)); + new_ptr = xmalloc(sizeof(char *) * (curr->y_size + reg->y_size)); for (j = 0; j < curr->y_size; j++) { new_ptr[j] = curr->y_array[j]; } @@ -2746,7 +2765,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++] = (char *)pnew; + curr->y_array[j++] = pnew; y_idx = 1; } else { y_idx = 0; @@ -2812,8 +2831,8 @@ 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] = (char *)pnew; + char *pnew = xmallocz((size_t)size); + reg->y_array[y_idx] = pnew; memset(pnew, ' ', (size_t)bd->startspaces); pnew += bd->startspaces; memmove(pnew, bd->textstart, (size_t)bd->textlen); @@ -2824,7 +2843,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx, int s = bd->textlen + bd->endspaces; while (s > 0 && ascii_iswhite(*(bd->textstart + s - 1))) { - s = s - utf_head_off((char *)bd->textstart, (char *)bd->textstart + s - 1) - 1; + s = s - utf_head_off(bd->textstart, bd->textstart + s - 1) - 1; pnew--; } } @@ -2993,11 +3012,11 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) // strlen(ml_get(curwin->w_cursor.lnum)). With 'virtualedit' and the // cursor past the end of the line, curwin->w_cursor.coladd is // incremented instead of curwin->w_cursor.col. - char_u *cursor_pos = (char_u *)get_cursor_pos_ptr(); + char *cursor_pos = get_cursor_pos_ptr(); bool one_past_line = (*cursor_pos == NUL); bool eol = false; if (!one_past_line) { - eol = (*(cursor_pos + utfc_ptr2len((char *)cursor_pos)) == NUL); + eol = (*(cursor_pos + utfc_ptr2len(cursor_pos)) == NUL); } bool ve_allows = (cur_ve_flags == VE_ALL || cur_ve_flags == VE_ONEMORE); @@ -3067,7 +3086,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) if (y_array != NULL) { break; } - y_array = xmalloc(y_size * sizeof(char_u *)); + y_array = xmalloc(y_size * sizeof(char *)); } } else { y_size = 1; // use fake one-line yank register @@ -3132,7 +3151,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) if (y_size == 0 || y_array == NULL) { semsg(_("E353: Nothing in register %s"), - regname == 0 ? (char_u *)"\"" : transchar(regname)); + regname == 0 ? "\"" : transchar(regname)); goto end; } @@ -3273,7 +3292,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) shortline = (vcol < col) || (vcol == col && !*ptr); - if (vcol < col) { // line too short, padd with spaces + if (vcol < col) { // line too short, pad with spaces bd.startspaces = col - vcol; } else if (vcol > col) { bd.endspaces = vcol - col; @@ -3370,6 +3389,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) // adjust '] mark curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1; curbuf->b_op_end.col = bd.textcol + (colnr_T)totlen - 1; + if (curbuf->b_op_end.col < 0) { + curbuf->b_op_end.col = 0; + } curbuf->b_op_end.coladd = 0; if (flags & PUT_CURSEND) { colnr_T len; @@ -3694,20 +3716,23 @@ void adjust_cursor_eol(void) { unsigned int cur_ve_flags = get_ve_flags(); - if (curwin->w_cursor.col > 0 - && gchar_cursor() == NUL - && (cur_ve_flags & VE_ONEMORE) == 0 - && !(restart_edit || (State & MODE_INSERT))) { - // Put the cursor on the last character in the line. - dec_cursor(); + const bool adj_cursor = (curwin->w_cursor.col > 0 + && gchar_cursor() == NUL + && (cur_ve_flags & VE_ONEMORE) == 0 + && !(restart_edit || (State & MODE_INSERT))); + if (!adj_cursor) { + return; + } + + // Put the cursor on the last character in the line. + dec_cursor(); - if (cur_ve_flags == VE_ALL) { - colnr_T scol, ecol; + if (cur_ve_flags == VE_ALL) { + colnr_T scol, ecol; - // Coladd is set to the width of the last character. - getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol); - curwin->w_cursor.coladd = ecol - scol + 1; - } + // Coladd is set to the width of the last character. + getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol); + curwin->w_cursor.coladd = ecol - scol + 1; } } @@ -3746,10 +3771,10 @@ int get_unname_register(void) /// ":dis" and ":registers": Display the contents of the yank registers. void ex_display(exarg_T *eap) { - char_u *p; + char *p; yankreg_T *yb; int name; - char_u *arg = (char_u *)eap->arg; + char *arg = eap->arg; int clen; int type; @@ -3771,7 +3796,7 @@ void ex_display(exarg_T *eap) type = 'b'; break; } - if (arg != NULL && vim_strchr((char *)arg, name) == NULL) { + if (arg != NULL && vim_strchr(arg, name) == NULL) { continue; // did not ask for this register } @@ -3815,10 +3840,10 @@ void ex_display(exarg_T *eap) 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((char *)p, clen); + for (p = yb->y_array[j]; + *p != NUL && (n -= ptr2cells(p)) >= 0; p++) { // -V1019 + clen = utfc_ptr2len(p); + msg_outtrans_len(p, clen); p += clen - 1; } } @@ -3831,15 +3856,15 @@ void ex_display(exarg_T *eap) } // display last inserted text - if ((p = get_last_insert()) != NULL - && (arg == NULL || vim_strchr((char *)arg, '.') != NULL) && !got_int - && !message_filtered((char *)p)) { + if ((p = (char *)get_last_insert()) != NULL + && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int + && !message_filtered(p)) { msg_puts("\n c \". "); - dis_msg((char *)p, true); + dis_msg(p, true); } // display last command line - if (last_cmdline != NULL && (arg == NULL || vim_strchr((char *)arg, ':') != NULL) + if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL) && !got_int && !message_filtered(last_cmdline)) { msg_puts("\n c \": "); dis_msg(last_cmdline, false); @@ -3847,14 +3872,14 @@ void ex_display(exarg_T *eap) // display current file name if (curbuf->b_fname != NULL - && (arg == NULL || vim_strchr((char *)arg, '%') != NULL) && !got_int + && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int && !message_filtered(curbuf->b_fname)) { msg_puts("\n c \"% "); dis_msg(curbuf->b_fname, false); } // display alternate file name - if ((arg == NULL || vim_strchr((char *)arg, '%') != NULL) && !got_int) { + if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int) { char *fname; linenr_T dummy; @@ -3866,17 +3891,17 @@ void ex_display(exarg_T *eap) // display last search pattern if (last_search_pat() != NULL - && (arg == NULL || vim_strchr((char *)arg, '/') != NULL) && !got_int - && !message_filtered((char *)last_search_pat())) { + && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int + && !message_filtered(last_search_pat())) { msg_puts("\n c \"/ "); - dis_msg((char *)last_search_pat(), false); + dis_msg(last_search_pat(), false); } // display last used expression - if (expr_line != NULL && (arg == NULL || vim_strchr((char *)arg, '=') != NULL) - && !got_int && !message_filtered((char *)expr_line)) { + if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL) + && !got_int && !message_filtered(expr_line)) { msg_puts("\n c \"= "); - dis_msg((char *)expr_line, false); + dis_msg(expr_line, false); } } @@ -4188,11 +4213,13 @@ static bool reset_lbr(void) /// Restore 'linebreak' and take care of side effects. static void restore_lbr(bool lbr_saved) { - if (!curwin->w_p_lbr && lbr_saved) { - // changing 'linebreak' may require w_virtcol to be updated - curwin->w_p_lbr = true; - curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL); + if (curwin->w_p_lbr || !lbr_saved) { + return; } + + // changing 'linebreak' may require w_virtcol to be updated + curwin->w_p_lbr = true; + curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL); } /// prepare a few things for block mode yank/delete/tilde @@ -4329,7 +4356,7 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool bdp->textlen = (int)(pend - pstart); } bdp->textcol = (colnr_T)(pstart - line); - bdp->textstart = (char_u *)pstart; + bdp->textstart = pstart; restore_lbr(lbr_saved); } @@ -4451,13 +4478,13 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd) int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) { int col; - char_u *buf1 = NULL; - char_u buf2[NUMBUFLEN]; + char *buf1 = NULL; + char buf2[NUMBUFLEN]; int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin static bool hexupper = false; // 0xABC uvarnumber_T n; uvarnumber_T oldn; - char_u *ptr; + char *ptr; int c; int todel; int firstdigit; @@ -4484,10 +4511,10 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) } curwin->w_cursor = *pos; - ptr = (char_u *)ml_get(pos->lnum); + ptr = ml_get(pos->lnum); col = pos->col; - if (*ptr == NUL || col + !!save_coladd >= (int)STRLEN(ptr)) { + if (*ptr == NUL || col + !!save_coladd >= (int)strlen(ptr)) { goto theend; } @@ -4496,14 +4523,14 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) if (do_bin) { while (col > 0 && ascii_isbdigit(ptr[col])) { col--; - col -= utf_head_off((char *)ptr, (char *)ptr + col); + col -= utf_head_off(ptr, ptr + col); } } if (do_hex) { while (col > 0 && ascii_isxdigit(ptr[col])) { col--; - col -= utf_head_off((char *)ptr, (char *)ptr + col); + col -= utf_head_off(ptr, ptr + col); } } if (do_bin @@ -4511,7 +4538,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) && !((col > 0 && (ptr[col] == 'X' || ptr[col] == 'x') && ptr[col - 1] == '0' - && !utf_head_off((char *)ptr, (char *)ptr + col - 1) + && !utf_head_off(ptr, ptr + col - 1) && ascii_isxdigit(ptr[col + 1])))) { // In case of binary/hexadecimal pattern overlap match, rescan @@ -4519,7 +4546,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) while (col > 0 && ascii_isdigit(ptr[col])) { col--; - col -= utf_head_off((char *)ptr, (char *)ptr + col); + col -= utf_head_off(ptr, ptr + col); } } @@ -4527,17 +4554,17 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) && col > 0 && (ptr[col] == 'X' || ptr[col] == 'x') && ptr[col - 1] == '0' - && !utf_head_off((char *)ptr, (char *)ptr + col - 1) + && !utf_head_off(ptr, ptr + col - 1) && ascii_isxdigit(ptr[col + 1])) || (do_bin && col > 0 && (ptr[col] == 'B' || ptr[col] == 'b') && ptr[col - 1] == '0' - && !utf_head_off((char *)ptr, (char *)ptr + col - 1) + && !utf_head_off(ptr, ptr + col - 1) && ascii_isbdigit(ptr[col + 1]))) { // Found hexadecimal or binary number, move to its start. col--; - col -= utf_head_off((char *)ptr, (char *)ptr + col); + col -= utf_head_off(ptr, ptr + col); } else { // Search forward and then backward to find the start of number. col = pos->col; @@ -4559,7 +4586,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((char *)ptr + col); + int mb_len = utfc_ptr2len(ptr + col); col += mb_len; length -= mb_len; @@ -4570,7 +4597,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) } if (col > pos->col && ptr[col - 1] == '-' - && !utf_head_off((char *)ptr, (char *)ptr + col - 1) + && !utf_head_off(ptr, ptr + col - 1) && !do_unsigned) { negative = true; was_positive = false; @@ -4578,7 +4605,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) } // If a number was found, and saving for undo works, replace the number. - firstdigit = ptr[col]; + firstdigit = (uint8_t)ptr[col]; if (!ascii_isdigit(firstdigit) && !(do_alpha && ASCII_ISALPHA(firstdigit))) { beep_flush(); goto theend; @@ -4616,7 +4643,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) curwin->w_cursor.col = col; } else { if (col > 0 && ptr[col - 1] == '-' - && !utf_head_off((char *)ptr, (char *)ptr + col - 1) + && !utf_head_off(ptr, ptr + col - 1) && !visual && !do_unsigned) { // negative number @@ -4627,11 +4654,11 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) // get the number value (unsigned) if (visual && VIsual_mode != 'V') { maxlen = (curbuf->b_visual.vi_curswant == MAXCOL - ? (int)STRLEN(ptr) - col + ? (int)strlen(ptr) - col : length); } - vim_str2nr((char *)ptr + col, &pre, &length, + vim_str2nr(ptr + col, &pre, &length, 0 + (do_bin ? STR2NR_BIN : 0) + (do_oct ? STR2NR_OCT : 0) + (do_hex ? STR2NR_HEX : 0), @@ -4732,7 +4759,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) length--; } if (pre == 'b' || pre == 'B' || pre == 'x' || pre == 'X') { - *ptr++ = (char_u)pre; + *ptr++ = (char)pre; length--; } @@ -4754,15 +4781,15 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) buf2[i] = '\0'; } else if (pre == 0) { - vim_snprintf((char *)buf2, ARRAY_SIZE(buf2), "%" PRIu64, (uint64_t)n); + vim_snprintf(buf2, ARRAY_SIZE(buf2), "%" PRIu64, (uint64_t)n); } else if (pre == '0') { - vim_snprintf((char *)buf2, ARRAY_SIZE(buf2), "%" PRIo64, (uint64_t)n); + vim_snprintf(buf2, ARRAY_SIZE(buf2), "%" PRIo64, (uint64_t)n); } else if (hexupper) { - vim_snprintf((char *)buf2, ARRAY_SIZE(buf2), "%" PRIX64, (uint64_t)n); + vim_snprintf(buf2, ARRAY_SIZE(buf2), "%" PRIX64, (uint64_t)n); } else { - vim_snprintf((char *)buf2, ARRAY_SIZE(buf2), "%" PRIx64, (uint64_t)n); + vim_snprintf(buf2, ARRAY_SIZE(buf2), "%" PRIx64, (uint64_t)n); } - length -= (int)STRLEN(buf2); + length -= (int)strlen(buf2); // Adjust number of zeros to the new number of digits, so the // total length of the number remains the same. @@ -4775,7 +4802,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) } *ptr = NUL; STRCAT(buf1, buf2); - ins_str((char *)buf1); // insert the new number + ins_str(buf1); // insert the new number endpos = curwin->w_cursor; if (curwin->w_cursor.col) { curwin->w_cursor.col--; @@ -5032,7 +5059,7 @@ void write_reg_contents_lst(int name, char **strings, bool must_append, MotionTy return; } - str_to_reg(reg, yank_type, (char *)strings, STRLEN(strings), + str_to_reg(reg, yank_type, (char *)strings, strlen((char *)strings), block_len, true); finish_write_reg(name, reg, old_y_previous); } @@ -5064,7 +5091,7 @@ void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_app // Special case: '/' search pattern if (name == '/') { - set_last_search_pat((char_u *)str, RE_SEARCH, true, true); + set_last_search_pat(str, RE_SEARCH, true, true); return; } @@ -5096,7 +5123,7 @@ void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_app if (must_append && expr_line) { // append has been specified and expr_line already exists, so we'll // append the new string to expr_line. - size_t exprlen = STRLEN(expr_line); + size_t exprlen = strlen(expr_line); totlen += exprlen; offset = exprlen; @@ -5154,7 +5181,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str, // Count the number of lines within the string if (str_list) { - for (char_u **ss = (char_u **)str; *ss != NULL; ss++) { + for (char **ss = (char **)str; *ss != NULL; ss++) { newlines++; } } else { @@ -5176,7 +5203,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str, } // Grow the register array to hold the pointers to the new lines. - char **pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(char_u *)); + char **pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(char *)); y_ptr->y_array = pp; size_t lnum = y_ptr->y_size; // The current line number. @@ -5186,8 +5213,8 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str, // Find the end of each line and save it into the array. if (str_list) { - for (char_u **ss = (char_u **)str; *ss != NULL; ss++, lnum++) { - size_t ss_len = STRLEN(*ss); + for (char **ss = (char **)str; *ss != NULL; ss++, lnum++) { + size_t ss_len = strlen(*ss); pp[lnum] = xmemdupz(*ss, ss_len); if (ss_len > maxlen) { maxlen = ss_len; @@ -5195,12 +5222,11 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str, } } else { size_t line_len; - for (const char_u *start = (char_u *)str, *end = (char_u *)str + len; + for (const char *start = str, *end = str + len; start < end + extraline; start += line_len + 1, lnum++) { assert(end - start >= 0); - line_len = (size_t)((char_u *)xmemscan(start, '\n', - (size_t)(end - start)) - start); + line_len = (size_t)((char *)xmemscan(start, '\n', (size_t)(end - start)) - start); if (line_len > maxlen) { maxlen = line_len; } @@ -5252,8 +5278,8 @@ void clear_oparg(oparg_T *oap) /// 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) +static varnumber_T line_count_info(char *line, varnumber_T *wc, varnumber_T *cc, varnumber_T limit, + int eol_size) { varnumber_T i; varnumber_T words = 0; @@ -5270,7 +5296,7 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c is_word = 1; } chars++; - i += utfc_ptr2len((char *)line + i); + i += utfc_ptr2len(line + i); } if (is_word) { @@ -5294,9 +5320,9 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c /// @param dict when not NULL, store the info there instead of showing it. void cursor_pos_info(dict_T *dict) { - char_u *p; - char_u buf1[50]; - char_u buf2[40]; + char *p; + char buf1[50]; + char buf2[40]; linenr_T lnum; varnumber_T byte_count = 0; varnumber_T bom_count = 0; @@ -5378,7 +5404,7 @@ void cursor_pos_info(dict_T *dict) // Do extra processing for VIsual mode. if (l_VIsual_active && lnum >= min_pos.lnum && lnum <= max_pos.lnum) { - char_u *s = NULL; + char *s = NULL; long len = 0L; switch (l_VIsual_mode) { @@ -5390,7 +5416,7 @@ void cursor_pos_info(dict_T *dict) len = (long)bd.textlen; break; case 'V': - s = (char_u *)ml_get(lnum); + s = ml_get(lnum); len = MAXCOL; break; case 'v': { @@ -5399,7 +5425,7 @@ void cursor_pos_info(dict_T *dict) colnr_T end_col = (lnum == max_pos.lnum) ? max_pos.col - start_col + 1 : MAXCOL; - s = (char_u *)ml_get(lnum) + start_col; + s = ml_get(lnum) + start_col; len = end_col; } break; @@ -5410,7 +5436,7 @@ void cursor_pos_info(dict_T *dict) if (lnum == curbuf->b_ml.ml_line_count && !curbuf->b_p_eol && (curbuf->b_p_bin || !curbuf->b_p_fixeol) - && (long)STRLEN(s) < len) { + && (long)strlen(s) < len) { byte_count_cursor -= eol_size; } } @@ -5420,14 +5446,14 @@ void cursor_pos_info(dict_T *dict) word_count_cursor += word_count; char_count_cursor += char_count; byte_count_cursor = byte_count - + line_count_info((char_u *)ml_get(lnum), &word_count_cursor, + + line_count_info(ml_get(lnum), &word_count_cursor, &char_count_cursor, (varnumber_T)curwin->w_cursor.col + 1, eol_size); } } // Add to the running totals - byte_count += line_count_info((char_u *)ml_get(lnum), &word_count, &char_count, + byte_count += line_count_info(ml_get(lnum), &word_count, &char_count, (varnumber_T)MAXCOL, eol_size); } @@ -5442,7 +5468,7 @@ void cursor_pos_info(dict_T *dict) getvcols(curwin, &min_pos, &max_pos, &min_pos.col, &max_pos.col); int64_t cols; STRICT_SUB(oparg.end_vcol + 1, oparg.start_vcol, &cols, int64_t); - vim_snprintf((char *)buf1, sizeof(buf1), _("%" PRId64 " Cols; "), + vim_snprintf(buf1, sizeof(buf1), _("%" PRId64 " Cols; "), cols); } else { buf1[0] = NUL; @@ -5450,7 +5476,7 @@ void cursor_pos_info(dict_T *dict) if (char_count_cursor == byte_count_cursor && char_count == byte_count) { - vim_snprintf((char *)IObuff, IOSIZE, + vim_snprintf(IObuff, IOSIZE, _("Selected %s%" PRId64 " of %" PRId64 " Lines;" " %" PRId64 " of %" PRId64 " Words;" " %" PRId64 " of %" PRId64 " Bytes"), @@ -5459,7 +5485,7 @@ void cursor_pos_info(dict_T *dict) (int64_t)word_count_cursor, (int64_t)word_count, (int64_t)byte_count_cursor, (int64_t)byte_count); } else { - vim_snprintf((char *)IObuff, IOSIZE, + vim_snprintf(IObuff, IOSIZE, _("Selected %s%" PRId64 " of %" PRId64 " Lines;" " %" PRId64 " of %" PRId64 " Words;" " %" PRId64 " of %" PRId64 " Chars;" @@ -5471,30 +5497,30 @@ void cursor_pos_info(dict_T *dict) (int64_t)byte_count_cursor, (int64_t)byte_count); } } else { - p = (char_u *)get_cursor_line_ptr(); + p = get_cursor_line_ptr(); validate_virtcol(); - col_print((char *)buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1, + col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); - col_print((char *)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) { - vim_snprintf((char *)IObuff, IOSIZE, + vim_snprintf(IObuff, IOSIZE, _("Col %s of %s; Line %" PRId64 " of %" PRId64 ";" " Word %" PRId64 " of %" PRId64 ";" " Byte %" PRId64 " of %" PRId64 ""), - (char *)buf1, (char *)buf2, + buf1, buf2, (int64_t)curwin->w_cursor.lnum, (int64_t)curbuf->b_ml.ml_line_count, (int64_t)word_count_cursor, (int64_t)word_count, (int64_t)byte_count_cursor, (int64_t)byte_count); } else { - vim_snprintf((char *)IObuff, IOSIZE, + vim_snprintf(IObuff, IOSIZE, _("Col %s of %s; Line %" PRId64 " of %" PRId64 ";" " Word %" PRId64 " of %" PRId64 ";" " Char %" PRId64 " of %" PRId64 ";" " Byte %" PRId64 " of %" PRId64 ""), - (char *)buf1, (char *)buf2, + buf1, buf2, (int64_t)curwin->w_cursor.lnum, (int64_t)curbuf->b_ml.ml_line_count, (int64_t)word_count_cursor, (int64_t)word_count, @@ -5507,19 +5533,19 @@ void cursor_pos_info(dict_T *dict) bom_count = bomb_size(); if (dict == NULL && bom_count > 0) { const size_t len = strlen(IObuff); - vim_snprintf((char *)IObuff + len, IOSIZE - len, + vim_snprintf(IObuff + len, IOSIZE - len, _("(+%" PRId64 " for BOM)"), (int64_t)bom_count); } if (dict == NULL) { // Don't shorten this message, the user asked for it. - p = (char_u *)p_shm; + p = p_shm; p_shm = ""; if (p_ch < 1) { msg_start(); msg_scroll = true; } - msg((char *)IObuff); - p_shm = (char *)p; + msg(IObuff); + p_shm = p; } } @@ -5553,13 +5579,22 @@ static void op_colon(oparg_T *oap) } else { stuffnumReadbuff((long)oap->start.lnum); } - if (oap->end.lnum != oap->start.lnum) { + + // When using !! on a closed fold the range ".!" works best to operate + // on, it will be made the whole closed fold later. + linenr_T endOfStartFold = oap->start.lnum; + (void)hasFolding(oap->start.lnum, NULL, &endOfStartFold); + if (oap->end.lnum != oap->start.lnum && oap->end.lnum != endOfStartFold) { + // Make it a range with the end line. stuffcharReadbuff(','); if (oap->end.lnum == curwin->w_cursor.lnum) { stuffcharReadbuff('.'); } else if (oap->end.lnum == curbuf->b_ml.ml_line_count) { stuffcharReadbuff('$'); - } else if (oap->start.lnum == curwin->w_cursor.lnum) { + } else if (oap->start.lnum == curwin->w_cursor.lnum + // do not use ".+number" for a closed fold, it would count + // folded lines twice + && !hasFolding(oap->end.lnum, NULL, NULL)) { stuffReadbuff(".+"); stuffnumReadbuff(oap->line_count - 1); } else { @@ -5591,10 +5626,11 @@ static void op_colon(oparg_T *oap) static Callback opfunc_cb; /// Process the 'operatorfunc' option value. -/// @return OK or FAIL -int set_operatorfunc_option(void) +void set_operatorfunc_option(char **errmsg) { - return option_set_callback_func(p_opfunc, &opfunc_cb); + if (option_set_callback_func(p_opfunc, &opfunc_cb) == FAIL) { + *errmsg = e_invarg; + } } #if defined(EXITFREE) @@ -5604,12 +5640,17 @@ void free_operatorfunc_option(void) } #endif +/// Mark the global 'operatorfunc' callback with "copyID" so that it is not +/// garbage collected. +bool set_ref_in_opfunc(int copyID) +{ + return set_ref_in_callback(&opfunc_cb, copyID, NULL, NULL); +} + /// 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; @@ -5636,9 +5677,11 @@ static void op_function(const oparg_T *oap) // Reset virtual_op so that 'virtualedit' can be changed in the // function. + const TriState save_virtual_op = virtual_op; virtual_op = kNone; // Reset finish_op so that mode() returns the right value. + const bool save_finish_op = finish_op; finish_op = false; typval_T rettv; @@ -6052,7 +6095,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((char *)ml_get_pos(&oap->end)); + const int l = utfc_ptr2len(ml_get_pos(&oap->end)); if (l > 1) { oap->end.col += l - 1; } @@ -6178,8 +6221,6 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) // Restore linebreak, so that when the user edits it looks as before. restore_lbr(lbr_saved); - // Reset finish_op now, don't want it set inside edit(). - finish_op = false; if (op_change(oap)) { // will call edit() cap->retval |= CA_COMMAND_BUSY; } @@ -6203,7 +6244,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) // If 'equalprg' is empty, do the indenting internally. if (oap->op_type == OP_INDENT && *get_equalprg() == NUL) { if (curbuf->b_p_lisp) { - op_reindent(oap, get_lisp_indent); + if (use_indentexpr_for_lisp()) { + op_reindent(oap, get_expr_indent); + } else { + op_reindent(oap, get_lisp_indent); + } break; } op_reindent(oap, @@ -6398,7 +6443,7 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing) } if (!eval_has_provider("clipboard")) { - if (batch_change_count == 1 && !quiet + if (batch_change_count <= 1 && !quiet && (!clipboard_didwarn || (explicit_cb_reg && !redirecting()))) { clipboard_didwarn = true; // Do NOT error (emsg()) here--if it interrupts :redir we get into @@ -6554,8 +6599,8 @@ 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 = (char_u *)TV_LIST_ITEM_TV(tv_list_last(res))->vval.v_string; - if (regtype == NULL || STRLEN(regtype) > 1) { + char *regtype = TV_LIST_ITEM_TV(tv_list_last(res))->vval.v_string; + if (regtype == NULL || strlen(regtype) > 1) { goto err; } switch (regtype[0]) { |