diff options
Diffstat (limited to 'src/nvim/ex_cmds.c')
-rw-r--r-- | src/nvim/ex_cmds.c | 107 |
1 files changed, 78 insertions, 29 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 4965eb9c20..c7910e148d 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -814,7 +814,11 @@ void ex_retab(exarg_T *eap) // len is actual number of white characters used len = num_spaces + num_tabs; old_len = (long)STRLEN(ptr); - long new_len = old_len - col + start_col + len + 1; + const long new_len = old_len - col + start_col + len + 1; + if (new_len <= 0 || new_len >= MAXCOL) { + emsg(_(e_resulting_text_too_long)); + break; + } new_line = xmalloc(new_len); if (start_col > 0) { @@ -847,6 +851,10 @@ void ex_retab(exarg_T *eap) break; } vcol += win_chartabsize(curwin, ptr + col, (colnr_T)vcol); + if (vcol >= MAXCOL) { + emsg(_(e_resulting_text_too_long)); + break; + } col += utfc_ptr2len(ptr + col); } if (new_line == NULL) { // out of memory @@ -980,8 +988,10 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) foldMoveRange(win, &win->w_folds, line1, line2, dest); } } - curbuf->b_op_start.lnum = dest - num_lines + 1; - curbuf->b_op_end.lnum = dest; + if (!cmdmod.lockmarks) { + curbuf->b_op_start.lnum = dest - num_lines + 1; + curbuf->b_op_end.lnum = dest; + } line_off = -num_lines; byte_off = -extent_byte; } else { @@ -991,10 +1001,14 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) foldMoveRange(win, &win->w_folds, dest + 1, line1 - 1, line2); } } - curbuf->b_op_start.lnum = dest + 1; - curbuf->b_op_end.lnum = dest + num_lines; + if (!cmdmod.lockmarks) { + curbuf->b_op_start.lnum = dest + 1; + curbuf->b_op_end.lnum = dest + num_lines; + } + } + if (!cmdmod.lockmarks) { + curbuf->b_op_start.col = curbuf->b_op_end.col = 0; } - curbuf->b_op_start.col = curbuf->b_op_end.col = 0; mark_adjust_nofold(last_line - num_lines + 1, last_line, -(last_line - dest - extra), 0L, kExtmarkNOOP); @@ -1057,9 +1071,11 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n) char_u *p; count = line2 - line1 + 1; - curbuf->b_op_start.lnum = n + 1; - curbuf->b_op_end.lnum = n + count; - curbuf->b_op_start.col = curbuf->b_op_end.col = 0; + if (!cmdmod.lockmarks) { + curbuf->b_op_start.lnum = n + 1; + curbuf->b_op_end.lnum = n + count; + curbuf->b_op_start.col = curbuf->b_op_end.col = 0; + } /* * there are three situations: @@ -1099,6 +1115,9 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n) } appended_lines_mark(n, count); + if (VIsual_active) { + check_pos(curbuf, &VIsual); + } msgmore((long)count); } @@ -1269,12 +1288,18 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, char_u *cmd_buf; buf_T *old_curbuf = curbuf; int shell_flags = 0; + const pos_T orig_start = curbuf->b_op_start; + const pos_T orig_end = curbuf->b_op_end; const int stmp = p_stmp; if (*cmd == NUL) { // no filter command return; } + const bool save_lockmarks = cmdmod.lockmarks; + // Temporarily disable lockmarks since that's needed to propagate changed + // regions of the buffer for foldUpdate(), linecount, etc. + cmdmod.lockmarks = false; cursor_save = curwin->w_cursor; linecount = line2 - line1 + 1; @@ -1349,7 +1374,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, ui_cursor_goto(Rows - 1, 0); if (do_out) { - if (u_save((line2), (linenr_T)(line2 + 1)) == FAIL) { + if (u_save(line2, (linenr_T)(line2 + 1)) == FAIL) { xfree(cmd_buf); goto error; } @@ -1455,10 +1480,15 @@ error: filterend: + cmdmod.lockmarks = save_lockmarks; if (curbuf != old_curbuf) { no_wait_return--; emsg(_("E135: *Filter* Autocommands must not change current buffer")); + } else if (cmdmod.lockmarks) { + curbuf->b_op_start = orig_start; + curbuf->b_op_end = orig_end; } + if (itmp != NULL) { os_remove((char *)itmp); } @@ -1913,7 +1943,7 @@ int do_write(exarg_T *eap) // If 'filetype' was empty try detecting it now. if (*curbuf->b_p_ft == NUL) { - if (au_has_group((char_u *)"filetypedetect")) { + if (augroup_exists("filetypedetect")) { (void)do_doautocmd((char_u *)"filetypedetect BufRead", true, NULL); } do_modelines(0); @@ -3006,7 +3036,12 @@ void ex_append(exarg_T *eap) did_undo = true; ml_append(lnum, theline, (colnr_T)0, false); - appended_lines_mark(lnum + (empty ? 1 : 0), 1L); + if (empty) { + // there are no marks below the inserted lines + appended_lines(lnum, 1L); + } else { + appended_lines_mark(lnum, 1L); + } xfree(theline); ++lnum; @@ -3025,15 +3060,16 @@ void ex_append(exarg_T *eap) // "start" is set to eap->line2+1 unless that position is invalid (when // eap->line2 pointed to the end of the buffer and nothing was appended) // "end" is set to lnum when something has been appended, otherwise - // it is the same than "start" -- Acevedo - curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ? - eap->line2 + 1 : curbuf->b_ml.ml_line_count; - if (eap->cmdidx != CMD_append) { - --curbuf->b_op_start.lnum; + // it is the same as "start" -- Acevedo + if (!cmdmod.lockmarks) { + curbuf->b_op_start.lnum + = (eap->line2 < curbuf->b_ml.ml_line_count) ? eap->line2 + 1 : curbuf->b_ml.ml_line_count; + if (eap->cmdidx != CMD_append) { + curbuf->b_op_start.lnum--; + } + curbuf->b_op_end.lnum = (eap->line2 < lnum) ? lnum : curbuf->b_op_start.lnum; + curbuf->b_op_start.col = curbuf->b_op_end.col = 0; } - curbuf->b_op_end.lnum = (eap->line2 < lnum) - ? lnum : curbuf->b_op_start.lnum; - curbuf->b_op_start.col = curbuf->b_op_end.col = 0; curwin->w_cursor.lnum = lnum; check_cursor_lnum(); beginline(BL_SOL | BL_FIX); @@ -3624,8 +3660,14 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle // We do it here once to avoid it to be replaced over and over again. // But don't do it when it starts with "\=", then it's an expression. assert(sub != NULL); + + bool sub_needs_free = false; if (!(sub[0] == '\\' && sub[1] == '=')) { + char_u *source = sub; sub = regtilde(sub, p_magic); + // When previewing, the new pattern allocated by regtilde() needs to be freed + // in this function because it will not be used or freed by regtilde() later. + sub_needs_free = preview && sub != source; } // Check for a match on each line. @@ -4346,10 +4388,12 @@ skip: } if (sub_nsubs > start_nsubs) { - // Set the '[ and '] marks. - curbuf->b_op_start.lnum = eap->line1; - curbuf->b_op_end.lnum = line2; - curbuf->b_op_start.col = curbuf->b_op_end.col = 0; + if (!cmdmod.lockmarks) { + // Set the '[ and '] marks. + curbuf->b_op_start.lnum = eap->line1; + curbuf->b_op_end.lnum = line2; + curbuf->b_op_start.col = curbuf->b_op_end.col = 0; + } if (!global_busy) { // when interactive leave cursor on the match @@ -4420,6 +4464,10 @@ skip: kv_destroy(preview_lines.subresults); + if (sub_needs_free) { + xfree(sub); + } + return preview_buf; #undef ADJUST_SUB_FIRSTLNUM #undef PUSH_PREVIEW_LINES @@ -5063,8 +5111,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool && ((arg[1] != NUL && arg[2] == NUL) || (vim_strchr((char_u *)"%_z@", arg[1]) != NULL && arg[2] != NUL))) { - STRCPY(d, "/\\\\"); - STRCPY(d + 3, arg + 1); + vim_snprintf((char *)d, IOSIZE, "/\\\\%s", arg + 1); // Check for "/\\_$", should be "/\\_\$" if (d[3] == '_' && d[4] == '$') { STRCPY(d + 4, "\\$"); @@ -5817,7 +5864,7 @@ void ex_helpclose(exarg_T *eap) { FOR_ALL_WINDOWS_IN_TAB(win, curtab) { if (bt_help(win->w_buffer)) { - win_close(win, false); + win_close(win, false, eap->forceit); return; } } @@ -6102,12 +6149,14 @@ char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags) p++; // Find the flags - while (*p == 'g' || *p == 'j') { + while (*p == 'g' || *p == 'j' || *p == 'f') { if (flags != NULL) { if (*p == 'g') { *flags |= VGR_GLOBAL; - } else { + } else if (*p == 'j') { *flags |= VGR_NOJUMP; + } else { + *flags |= VGR_FUZZY; } } p++; |