diff options
Diffstat (limited to 'src/nvim/ex_cmds.c')
-rw-r--r-- | src/nvim/ex_cmds.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 494ebce370..a0618ce7d7 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2230,8 +2230,16 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum // End Visual mode before switching to another buffer, so the text can be // copied into the GUI selection buffer. + // Careful: may trigger ModeChanged() autocommand + + // Should we block autocommands here? reset_VIsual(); + // autocommands freed window :( + if (oldwin != NULL && !win_valid(oldwin)) { + oldwin = NULL; + } + if ((command != NULL || newlnum > (linenr_T)0) && *get_vim_var_str(VV_SWAPCOMMAND) == NUL) { // Set v:swapcommand for the SwapExists autocommands. @@ -3169,21 +3177,21 @@ static bool sub_joining_lines(exarg_T *eap, char *pat, const char *sub, const ch /// Slightly more memory that is strictly necessary is allocated to reduce the /// frequency of memory (re)allocation. /// -/// @param[in,out] new_start pointer to the memory for the replacement text -/// @param[in] needed_len amount of memory needed +/// @param[in,out] new_start pointer to the memory for the replacement text +/// @param[in,out] new_start_len pointer to length of new_start +/// @param[in] needed_len amount of memory needed /// /// @returns pointer to the end of the allocated memory -static char *sub_grow_buf(char **new_start, int needed_len) - FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_RET +static char *sub_grow_buf(char **new_start, int *new_start_len, int needed_len) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { - int new_start_len = 0; char *new_end; if (*new_start == NULL) { // Get some space for a temporary buffer to do the // substitution into (and some extra space to avoid // too many calls to xmalloc()/free()). - new_start_len = needed_len + 50; - *new_start = xmalloc((size_t)new_start_len); + *new_start_len = needed_len + 50; + *new_start = xmalloc((size_t)(*new_start_len)); **new_start = NUL; new_end = *new_start; } else { @@ -3192,9 +3200,9 @@ static char *sub_grow_buf(char **new_start, int needed_len) // extra to avoid too many calls to xmalloc()/free()). size_t len = strlen(*new_start); needed_len += (int)len; - if (needed_len > new_start_len) { - new_start_len = needed_len + 50; - *new_start = xrealloc(*new_start, (size_t)new_start_len); + if (needed_len > *new_start_len) { + *new_start_len = needed_len + 50; + *new_start = xrealloc(*new_start, (size_t)(*new_start_len)); } new_end = *new_start + len; } @@ -3519,6 +3527,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ colnr_T matchcol; colnr_T prev_matchcol = MAXCOL; char *new_end, *new_start = NULL; + int new_start_len = 0; char *p1; bool did_sub = false; int lastone; @@ -3564,7 +3573,8 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ // accordingly. // // The new text is built up in new_start[]. It has some extra - // room to avoid using xmalloc()/free() too often. + // room to avoid using xmalloc()/free() too often. new_start_len is + // the length of the allocated memory at new_start. // // Make a copy of the old line, so it won't be taken away when // updating the screen or handling a multi-line match. The "old_" @@ -3943,15 +3953,19 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ p1 = ml_get(sub_firstlnum + (linenr_T)nmatch - 1); nmatch_tl += nmatch - 1; } - size_t copy_len = (size_t)(regmatch.startpos[0].col - copycol); - new_end = sub_grow_buf(&new_start, + int copy_len = regmatch.startpos[0].col - copycol; + new_end = sub_grow_buf(&new_start, &new_start_len, (colnr_T)strlen(p1) - regmatch.endpos[0].col - + (colnr_T)copy_len + sublen + 1); + + copy_len + sublen + 1); // copy the text up to the part that matched - memmove(new_end, sub_firstline + copycol, copy_len); + memmove(new_end, sub_firstline + copycol, (size_t)copy_len); new_end += copy_len; + if (new_start_len - copy_len < sublen) { + sublen = new_start_len - copy_len - 1; + } + // Finally, at this point we can know where the match actually will // start in the new text int start_col = (int)(new_end - new_start); |