diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-30 20:35:25 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-30 20:35:25 +0000 |
commit | 1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch) | |
tree | cd08258054db80bb9a11b1061bb091c70b76926a /src/nvim/buffer.c | |
parent | eaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff) | |
parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
download | rneovim-aucmd_textputpost.tar.gz rneovim-aucmd_textputpost.tar.bz2 rneovim-aucmd_textputpost.zip |
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r-- | src/nvim/buffer.c | 529 |
1 files changed, 218 insertions, 311 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 5dcb10751f..8a594dea92 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // // buffer.c: functions for dealing with the buffer structure // @@ -32,8 +29,8 @@ #include "klib/kvec.h" #include "nvim/api/private/helpers.h" #include "nvim/arglist.h" -#include "nvim/ascii.h" -#include "nvim/assert.h" +#include "nvim/ascii_defs.h" +#include "nvim/assert_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/buffer_updates.h" @@ -47,6 +44,7 @@ #include "nvim/digraph.h" #include "nvim/drawscreen.h" #include "nvim/eval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/eval/vars.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" @@ -67,48 +65,51 @@ #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/main.h" -#include "nvim/map.h" +#include "nvim/map_defs.h" #include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/mbyte.h" +#include "nvim/memfile_defs.h" #include "nvim/memline_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" #include "nvim/normal.h" #include "nvim/option.h" +#include "nvim/option_vars.h" #include "nvim/optionstr.h" -#include "nvim/os/fs_defs.h" +#include "nvim/os/fs.h" #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/time.h" #include "nvim/path.h" #include "nvim/plines.h" +#include "nvim/pos_defs.h" #include "nvim/quickfix.h" #include "nvim/regexp.h" #include "nvim/runtime.h" -#include "nvim/screen.h" #include "nvim/search.h" -#include "nvim/sign.h" #include "nvim/spell.h" +#include "nvim/state_defs.h" #include "nvim/statusline.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/terminal.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/usercmd.h" #include "nvim/version.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #include "nvim/window.h" +#include "nvim/winfloat.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "buffer.c.generated.h" #endif -static char *e_auabort = N_("E855: Autocommands caused command to abort"); -static char e_attempt_to_delete_buffer_that_is_in_use_str[] +static const char *e_auabort = N_("E855: Autocommands caused command to abort"); +static const char e_attempt_to_delete_buffer_that_is_in_use_str[] = N_("E937: Attempt to delete a buffer that is in use: %s"); // Number of times free_buffer() was called. @@ -135,21 +136,20 @@ int get_highest_fnum(void) static int read_buffer(int read_stdin, exarg_T *eap, int flags) { int retval = OK; - linenr_T line_count; bool silent = shortmess(SHM_FILEINFO); // Read from the buffer which the text is already filled in and append at // the end. This makes it possible to retry when 'fileformat' or // 'fileencoding' was guessed wrong. - line_count = curbuf->b_ml.ml_line_count; + linenr_T line_count = curbuf->b_ml.ml_line_count; retval = readfile(read_stdin ? NULL : curbuf->b_ffname, read_stdin ? NULL : curbuf->b_fname, - line_count, (linenr_T)0, (linenr_T)MAXLNUM, eap, + line_count, 0, (linenr_T)MAXLNUM, eap, flags | READ_BUFFER, silent); if (retval == OK) { // Delete the binary lines. while (--line_count >= 0) { - ml_delete((linenr_T)1, false); + ml_delete(1, false); } } else { // Delete the converted lines. @@ -165,7 +165,7 @@ static int read_buffer(int read_stdin, exarg_T *eap, int flags) // Set or reset 'modified' before executing autocommands, so that // it can be changed there. if (!readonlymode && !buf_is_empty(curbuf)) { - changed(); + changed(curbuf); } else if (retval != FAIL) { unchanged(curbuf, false, true); } @@ -176,20 +176,22 @@ static int read_buffer(int read_stdin, exarg_T *eap, int flags) return retval; } -/// Ensure buffer "buf" is loaded. Does not trigger the swap-exists action. -void buffer_ensure_loaded(buf_T *buf) +/// Ensure buffer "buf" is loaded. +bool buf_ensure_loaded(buf_T *buf) { if (buf->b_ml.ml_mfp != NULL) { - return; + // already open (common case) + return true; } aco_save_T aco; // Make sure the buffer is in a window. aucmd_prepbuf(&aco, buf); - swap_exists_action = SEA_NONE; - open_buffer(false, NULL, 0); + // status can be OK or NOTDONE (which also means ok/done) + int status = open_buffer(false, NULL, 0); aucmd_restbuf(&aco); + return (status != FAIL); } /// Open current buffer, that is: open the memfile and read the file into @@ -205,7 +207,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) int flags = flags_arg; int retval = OK; bufref_T old_curbuf; - long old_tw = curbuf->b_p_tw; + OptInt old_tw = curbuf->b_p_tw; int read_fifo = false; bool silent = shortmess(SHM_FILEINFO); @@ -249,6 +251,11 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) return FAIL; } + // Do not sync this buffer yet, may first want to read the file. + if (curbuf->b_ml.ml_mfp != NULL) { + curbuf->b_ml.ml_mfp->mf_dirty = MF_DIRTY_YES_NOSYNC; + } + // The autocommands in readfile() may change the buffer, but only AFTER // reading the file. set_bufref(&old_curbuf, curbuf); @@ -269,7 +276,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) int save_bin = curbuf->b_p_bin; int perm; - perm = os_getperm((const char *)curbuf->b_ffname); + perm = os_getperm(curbuf->b_ffname); if (perm >= 0 && (0 || S_ISFIFO(perm) || S_ISSOCK(perm) # ifdef OPEN_CHR_FILES @@ -285,7 +292,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) #endif retval = readfile(curbuf->b_ffname, curbuf->b_fname, - (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap, + 0, 0, (linenr_T)MAXLNUM, eap, flags | READ_NEW | (read_fifo ? READ_FIFO : 0), silent); #ifdef UNIX if (read_fifo) { @@ -308,8 +315,8 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) // it possible to retry when 'fileformat' or 'fileencoding' was // guessed wrong. curbuf->b_p_bin = true; - retval = readfile(NULL, NULL, (linenr_T)0, - (linenr_T)0, (linenr_T)MAXLNUM, NULL, + retval = readfile(NULL, NULL, 0, + 0, (linenr_T)MAXLNUM, NULL, flags | (READ_NEW + READ_STDIN), silent); curbuf->b_p_bin = save_bin; if (retval == OK) { @@ -317,6 +324,12 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) } } + // Can now sync this buffer in ml_sync_all(). + if (curbuf->b_ml.ml_mfp != NULL + && curbuf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES_NOSYNC) { + curbuf->b_ml.ml_mfp->mf_dirty = MF_DIRTY_YES; + } + // if first time loading this buffer, init b_chartab[] if (curbuf->b_flags & BF_NEVERLOADED) { (void)buf_init_chartab(curbuf, false); @@ -333,7 +346,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL) || modified_was_set // ":set modified" used in autocmd || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)) { - changed(); + changed(curbuf); } else if (retval != FAIL && !read_stdin && !read_fifo) { unchanged(curbuf, false, true); } @@ -342,6 +355,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) // Set last_changedtick to avoid triggering a TextChanged autocommand right // after it was added. curbuf->b_last_changedtick = buf_get_changedtick(curbuf); + curbuf->b_last_changedtick_i = buf_get_changedtick(curbuf); curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf); // require "!" to overwrite the file, because it wasn't read completely @@ -409,8 +423,8 @@ bool bufref_valid(bufref_T *bufref) FUNC_ATTR_PURE { return bufref->br_buf_free_count == buf_free_count - ? true - : buf_valid(bufref->br_buf) && bufref->br_fnum == bufref->br_buf->b_fnum; + ? true + : buf_valid(bufref->br_buf) && bufref->br_fnum == bufref->br_buf->b_fnum; } /// Check that "buf" points to a valid buffer in the buffer list. @@ -465,7 +479,7 @@ static bool can_unload_buffer(buf_T *buf) /// Possible values: /// 0 buffer becomes hidden /// DOBUF_UNLOAD buffer is unloaded -/// DOBUF_DELETE buffer is unloaded and removed from buffer list +/// DOBUF_DEL buffer is unloaded and removed from buffer list /// DOBUF_WIPE buffer is unloaded and really deleted /// When doing all but the first one on the current buffer, the /// caller should get a new buffer very soon! @@ -735,12 +749,11 @@ void buf_clear_file(buf_T *buf) void buf_clear(void) { linenr_T line_count = curbuf->b_ml.ml_line_count; + extmark_free_all(curbuf); // delete any extmarks while (!(curbuf->b_ml.ml_flags & ML_EMPTY)) { - ml_delete((linenr_T)1, false); + ml_delete(1, false); } deleted_lines_mark(1, line_count); // prepare for display - ml_close(curbuf, true); // free memline_T - buf_clear_file(curbuf); } /// buf_freeall() - free all things allocated for a buffer that are related to @@ -834,7 +847,7 @@ void buf_freeall(buf_T *buf, int flags) /// itself (not the file, that must have been done already). static void free_buffer(buf_T *buf) { - pmap_del(handle_T)(&buffer_handles, buf->b_fnum); + pmap_del(int)(&buffer_handles, buf->b_fnum, NULL); buf_free_count++; // b:changedtick uses an item in buf_T. free_buffer_stuff(buf, kBffClearWinInfo); @@ -848,9 +861,9 @@ static void free_buffer(buf_T *buf) xfree(buf->b_prompt_text); callback_free(&buf->b_prompt_callback); callback_free(&buf->b_prompt_interrupt); - clear_fmark(&buf->b_last_cursor); - clear_fmark(&buf->b_last_insert); - clear_fmark(&buf->b_last_change); + clear_fmark(&buf->b_last_cursor, 0); + clear_fmark(&buf->b_last_insert, 0); + clear_fmark(&buf->b_last_change, 0); for (size_t i = 0; i < NMARKS; i++) { free_fmark(buf->b_namedm[i]); } @@ -906,7 +919,6 @@ static void free_buffer_stuff(buf_T *buf, int free_flags) buf_init_changedtick(buf); } uc_clear(&buf->b_ucmds); // clear local user commands - buf_delete_signs(buf, "*"); // delete any signs extmark_free_all(buf); // delete any extmarks map_clear_mode(buf, MAP_ALL_MODES, true, false); // clear local mappings map_clear_mode(buf, MAP_ALL_MODES, true, true); // clear local abbrevs @@ -918,10 +930,14 @@ static void free_buffer_stuff(buf_T *buf, int free_flags) /// Go to another buffer. Handles the result of the ATTENTION dialog. void goto_buffer(exarg_T *eap, int start, int dir, int count) { + const int save_sea = swap_exists_action; + bufref_T old_curbuf; set_bufref(&old_curbuf, curbuf); - swap_exists_action = SEA_DIALOG; + if (swap_exists_action == SEA_NONE) { + swap_exists_action = SEA_DIALOG; + } (void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO, start, dir, count, eap->forceit); @@ -934,7 +950,7 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count) // Quitting means closing the split window, nothing else. win_close(curwin, true, false); - swap_exists_action = SEA_NONE; + swap_exists_action = save_sea; swap_exists_did_quit = true; // Restore the error/interrupt/exception state if not discarded by a @@ -953,7 +969,7 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count) void handle_swap_exists(bufref_T *old_curbuf) { cleanup_T cs; - long old_tw = curbuf->b_p_tw; + OptInt old_tw = curbuf->b_p_tw; buf_T *buf; if (swap_exists_action == SEA_QUIT) { @@ -972,7 +988,7 @@ void handle_swap_exists(bufref_T *old_curbuf) || old_curbuf->br_buf == curbuf) { // Block autocommands here because curwin->w_buffer is NULL. block_autocmds(); - buf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED); + buf = buflist_new(NULL, NULL, 1, BLN_CURBUF | BLN_LISTED); unblock_autocmds(); } else { buf = old_curbuf->br_buf; @@ -1005,7 +1021,7 @@ void handle_swap_exists(bufref_T *old_curbuf) // new aborting error, interrupt, or uncaught exception. leave_cleanup(&cs); } - swap_exists_action = SEA_NONE; // -V519 + swap_exists_action = SEA_NONE; } /// do_bufdel() - delete or unload buffer(s) @@ -1027,9 +1043,8 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b { int do_current = 0; // delete current buffer? int deleted = 0; // number of buffers deleted - char *errormsg = NULL; // return value + char *errormsg = NULL; // return value int bnr; // buffer number - char *p; if (addr_count == 0) { (void)do_buffer(command, DOBUF_CURRENT, FORWARD, 0, forceit); @@ -1066,7 +1081,7 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b break; } if (!ascii_isdigit(*arg)) { - p = skiptowhite_esc(arg); + char *p = skiptowhite_esc(arg); bnr = buflist_findpat(arg, p, command == DOBUF_WIPE, false, false); if (bnr < 0) { // failed break; @@ -1085,22 +1100,22 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b if (deleted == 0) { if (command == DOBUF_UNLOAD) { - STRCPY(IObuff, _("E515: No buffers were unloaded")); + xstrlcpy(IObuff, _("E515: No buffers were unloaded"), IOSIZE); } else if (command == DOBUF_DEL) { - STRCPY(IObuff, _("E516: No buffers were deleted")); + xstrlcpy(IObuff, _("E516: No buffers were deleted"), IOSIZE); } else { - STRCPY(IObuff, _("E517: No buffers were wiped out")); + xstrlcpy(IObuff, _("E517: No buffers were wiped out"), IOSIZE); } errormsg = IObuff; } else if (deleted >= p_report) { if (command == DOBUF_UNLOAD) { - smsg(NGETTEXT("%d buffer unloaded", "%d buffers unloaded", deleted), + smsg(0, NGETTEXT("%d buffer unloaded", "%d buffers unloaded", deleted), deleted); } else if (command == DOBUF_DEL) { - smsg(NGETTEXT("%d buffer deleted", "%d buffers deleted", deleted), + smsg(0, NGETTEXT("%d buffer deleted", "%d buffers deleted", deleted), deleted); } else { - smsg(NGETTEXT("%d buffer wiped out", "%d buffers wiped out", deleted), + smsg(0, NGETTEXT("%d buffer wiped out", "%d buffers wiped out", deleted), deleted); } } @@ -1113,7 +1128,6 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b /// Used when it is wiped out and it's the last buffer. static int empty_curbuf(int close_others, int forceit, int action) { - int retval; buf_T *buf = curbuf; if (action == DOBUF_UNLOAD) { @@ -1146,8 +1160,7 @@ static int empty_curbuf(int close_others, int forceit, int action) } setpcmark(); - retval = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, - forceit ? ECMD_FORCEIT : 0, curwin); + int retval = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, forceit ? ECMD_FORCEIT : 0, curwin); // do_ecmd() may create a new buffer, then we have to delete // the old one. But do_ecmd() may have done that already, check @@ -1404,7 +1417,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) if (buf == NULL) { // No previous buffer, Try 2'nd approach forward = true; buf = curbuf->b_next; - for (;;) { + while (true) { if (buf == NULL) { if (!forward) { // tried both directions break; @@ -1460,16 +1473,11 @@ int do_buffer(int action, int start, int dir, int count, int forceit) // make "buf" the current buffer if (action == DOBUF_SPLIT) { // split window first - // If 'switchbuf' contains "useopen": jump to first window containing - // "buf" if one exists - if ((swb_flags & SWB_USEOPEN) && buf_jump_open_win(buf)) { - return OK; - } - // If 'switchbuf' contains "usetab": jump to first window in any tab - // page containing "buf" if one exists - if ((swb_flags & SWB_USETAB) && buf_jump_open_tab(buf)) { + // If 'switchbuf' is set jump to the window containing "buf". + if (swbuf_goto_win_with_buf(buf) != NULL) { return OK; } + if (win_split(0, 0) == FAIL) { return FAIL; } @@ -1525,7 +1533,7 @@ void set_curbuf(buf_T *buf, int action) buf_T *prevbuf; int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL || action == DOBUF_WIPE); - long old_tw = curbuf->b_p_tw; + OptInt old_tw = curbuf->b_p_tw; setpcmark(); if ((cmdmod.cmod_flags & CMOD_KEEPALT) == 0) { @@ -1676,7 +1684,7 @@ void enter_buffer(buf_T *buf) maketitle(); // when autocmds didn't change it if (curwin->w_topline == 1 && !curwin->w_topline_was_set) { - scroll_cursor_halfway(false); // redisplay at correct position + scroll_cursor_halfway(false, false); // redisplay at correct position } // Change directories when the 'acd' option is set. @@ -1688,7 +1696,7 @@ void enter_buffer(buf_T *buf) // May need to set the spell language. Can only do this after the buffer // has been properly setup. if (!curbuf->b_help && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) { - (void)did_set_spelllang(curwin); + (void)parse_spelllang(curwin); } curbuf->b_last_used = time(NULL); @@ -1791,7 +1799,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) xfree(ffname); if (lnum != 0) { buflist_setfpos(buf, (flags & BLN_NOCURWIN) ? NULL : curwin, - lnum, (colnr_T)0, false); + lnum, 0, false); } if ((flags & BLN_NOOPT) == 0) { // Copy the options now, if 'cpo' doesn't have 's' and not done already. @@ -1836,7 +1844,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) buf = xcalloc(1, sizeof(buf_T)); // init b: variables buf->b_vars = tv_dict_alloc(); - buf->b_signcols.valid = false; + buf->b_signcols.sentinel = 0; init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE); buf_init_changedtick(buf); } @@ -1871,12 +1879,12 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) lastbuf = buf; buf->b_fnum = top_file_num++; - pmap_put(handle_T)(&buffer_handles, buf->b_fnum, buf); + pmap_put(int)(&buffer_handles, buf->b_fnum, buf); if (top_file_num < 0) { // wrap around (may cause duplicates) emsg(_("W14: Warning: List of file names overflow")); if (emsg_silent == 0 && !in_assert_fails) { ui_flush(); - os_delay(3001L, true); // make sure it is noticed + os_delay(3001, true); // make sure it is noticed } top_file_num = 1; } @@ -1905,7 +1913,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) buf->b_flags |= BF_DUMMY; } buf_clear_file(buf); - clrallmarks(buf); // clear marks + clrallmarks(buf, 0); // clear marks fmarks_check_names(buf); // check file marks for this file buf->b_p_bl = (flags & BLN_LISTED) ? true : false; // init 'buflisted' kv_destroy(buf->update_channels); @@ -2037,12 +2045,11 @@ void free_buf_options(buf_T *buf, int free_p_ff) /// Return FAIL for failure, OK for success. int buflist_getfile(int n, linenr_T lnum, int options, int forceit) { - buf_T *buf; win_T *wp = NULL; fmark_T *fm = NULL; colnr_T col; - buf = buflist_findnr(n); + buf_T *buf = buflist_findnr(n); if (buf == NULL) { if ((options & GETF_ALT) && n == 0) { emsg(_(e_noalt)); @@ -2073,17 +2080,8 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit) } if (options & GETF_SWITCH) { - // If 'switchbuf' contains "useopen": jump to first window containing - // "buf" if one exists - if (swb_flags & SWB_USEOPEN) { - wp = buf_jump_open_win(buf); - } - - // If 'switchbuf' contains "usetab": jump to first window in any tab - // page containing "buf" if one exists - if (wp == NULL && (swb_flags & SWB_USETAB)) { - wp = buf_jump_open_tab(buf); - } + // If 'switchbuf' is set jump to the window containing "buf". + wp = swbuf_goto_win_with_buf(buf); // If 'switchbuf' contains "split", "vsplit" or "newtab" and the // current buffer isn't empty: open new tab or window @@ -2123,12 +2121,10 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit) /// Go to the last known line number for the current buffer. void buflist_getfpos(void) { - pos_T *fpos; - - fpos = &buflist_findfmark(curbuf)->mark; + pos_T *fpos = &buflist_findfmark(curbuf)->mark; curwin->w_cursor.lnum = fpos->lnum; - check_cursor_lnum(); + check_cursor_lnum(curwin); if (p_sol) { curwin->w_cursor.col = 0; @@ -2145,18 +2141,17 @@ void buflist_getfpos(void) /// @return buffer or NULL if not found buf_T *buflist_findname_exp(char *fname) { - char *ffname; buf_T *buf = NULL; // First make the name into a full path name - ffname = FullName_save(fname, + char *ffname = FullName_save(fname, #ifdef UNIX - // force expansion, get rid of symbolic links - true + // force expansion, get rid of symbolic links + true #else - false + false #endif - ); // NOLINT(whitespace/parens) + ); // NOLINT(whitespace/parens) if (ffname != NULL) { buf = buflist_findname(ffname); xfree(ffname); @@ -2206,12 +2201,6 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted, FUNC_ATTR_NONNULL_ARG(1) { int match = -1; - int find_listed; - char *pat; - char *patend; - int attempt; - char *p; - int toggledollar; if (pattern_end == pattern + 1 && (*pattern == '%' || *pattern == '#')) { if (*pattern == '%') { @@ -2232,23 +2221,24 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted, // Repeat this for finding an unlisted buffer if there was no matching // listed buffer. - pat = file_pat_to_reg_pat((char *)pattern, (char *)pattern_end, NULL, false); + char *pat = file_pat_to_reg_pat(pattern, pattern_end, NULL, false); if (pat == NULL) { return -1; } - patend = pat + strlen(pat) - 1; - toggledollar = (patend > pat && *patend == '$'); + char *patend = pat + strlen(pat) - 1; + int toggledollar = (patend > pat && *patend == '$'); // First try finding a listed buffer. If not found and "unlisted" // is true, try finding an unlisted buffer. - find_listed = true; - for (;;) { - for (attempt = 0; attempt <= 3; attempt++) { + + int find_listed = true; + while (true) { + for (int attempt = 0; attempt <= 3; attempt++) { // may add '^' and '$' if (toggledollar) { *patend = (attempt < 2) ? NUL : '$'; // add/remove '$' } - p = pat; + char *p = pat; if (*p == '^' && !(attempt & 1)) { // add/remove '^' p++; } @@ -2338,7 +2328,6 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) int count = 0; int round; char *p; - int attempt; bufmatch_T *matches = NULL; *num_file = 0; // return values in case of FAIL @@ -2366,7 +2355,7 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) fuzmatch_str_T *fuzmatch = NULL; // attempt == 0: try match with '\<', match at start of word // attempt == 1: try match without '\<', match anywhere - for (attempt = 0; attempt <= (fuzzy ? 0 : 1); attempt++) { + for (int attempt = 0; attempt <= (fuzzy ? 0 : 1); attempt++) { regmatch_T regmatch; if (!fuzzy) { if (attempt > 0 && patc == pat) { @@ -2522,7 +2511,6 @@ static char *buflist_match(regmatch_T *rmp, buf_T *buf, bool ignore_case) static char *fname_match(regmatch_T *rmp, char *name, bool ignore_case) { char *match = NULL; - char *p; // extra check for valid arguments if (name == NULL || rmp->regprog == NULL) { @@ -2531,12 +2519,12 @@ static char *fname_match(regmatch_T *rmp, char *name, bool ignore_case) // Ignore case when 'fileignorecase' or the argument is set. rmp->rm_ic = p_fic || ignore_case; - if (vim_regexec(rmp, name, (colnr_T)0)) { + if (vim_regexec(rmp, name, 0)) { match = name; } else if (rmp->regprog != NULL) { // Replace $(HOME) with '~' and try matching again. - p = home_replace_save(NULL, name); - if (vim_regexec(rmp, p, (colnr_T)0)) { + char *p = home_replace_save(NULL, name); + if (vim_regexec(rmp, p, 0)) { match = name; } xfree(p); @@ -2793,7 +2781,7 @@ void buflist_list(exarg_T *eap) for (; buf != NULL && !got_int; buf = buflist_data != NULL - ? (++p < buflist_data + buflist.ga_len ? *p : NULL) : buf->b_next) { + ? (++p < buflist_data + buflist.ga_len ? *p : NULL) : buf->b_next) { const bool is_terminal = buf->terminal; const bool job_running = buf->terminal && terminal_running(buf->terminal); @@ -2827,8 +2815,8 @@ void buflist_list(exarg_T *eap) } const int changed_char = (buf->b_flags & BF_READERR) - ? 'x' - : (bufIsChanged(buf) ? '+' : ' '); + ? 'x' + : (bufIsChanged(buf) ? '+' : ' '); int ro_char = !MODIFIABLE(buf) ? '-' : (buf->b_p_ro ? '=' : ' '); if (buf->terminal) { ro_char = channel_job_running((uint64_t)buf->b_p_channel) ? 'R' : 'F'; @@ -2860,7 +2848,7 @@ void buflist_list(exarg_T *eap) buf == curbuf ? (int64_t)curwin->w_cursor.lnum : (int64_t)buflist_findlnum(buf)); } - msg_outtrans(IObuff); + msg_outtrans(IObuff, 0); line_breakcheck(); } @@ -3034,7 +3022,7 @@ char *getaltfname(bool errmsg) /// Used by qf_init(), main() and doarglist() int buflist_add(char *fname, int flags) { - buf_T *buf = buflist_new(fname, NULL, (linenr_T)0, flags); + buf_T *buf = buflist_new(fname, NULL, 0, flags); if (buf != NULL) { return buf->b_fnum; } @@ -3153,10 +3141,8 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) char *name; int n; char *p; - char *buffer; - size_t len; - buffer = xmalloc(IOSIZE); + char *buffer = xmalloc(IOSIZE); if (fullname > 1) { // 2 CTRL-G: include buffer number vim_snprintf(buffer, IOSIZE, "buf %d: ", curbuf->b_fnum); @@ -3181,11 +3167,11 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) bool dontwrite = bt_dontwrite(curbuf); vim_snprintf_add(buffer, IOSIZE, "\"%s%s%s%s%s%s", curbufIsChanged() - ? (shortmess(SHM_MOD) ? " [+]" : _(" [Modified]")) : " ", + ? (shortmess(SHM_MOD) ? " [+]" : _(" [Modified]")) : " ", (curbuf->b_flags & BF_NOTEDITED) && !dontwrite ? _("[Not edited]") : "", (curbuf->b_flags & BF_NEW) && !dontwrite - ? new_file_message() : "", + ? _("[New]") : "", (curbuf->b_flags & BF_READERR) ? _("[Read errors]") : "", curbuf->b_p_ro @@ -3196,12 +3182,12 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) ? " " : ""); // With 32 bit longs and more than 21,474,836 lines multiplying by 100 // causes an overflow, thus for large numbers divide instead. - if (curwin->w_cursor.lnum > 1000000L) { - n = (int)(((long)curwin->w_cursor.lnum) / - ((long)curbuf->b_ml.ml_line_count / 100L)); + if (curwin->w_cursor.lnum > 1000000) { + n = ((curwin->w_cursor.lnum) / + (curbuf->b_ml.ml_line_count / 100)); } else { - n = (int)(((long)curwin->w_cursor.lnum * 100L) / - (long)curbuf->b_ml.ml_line_count); + n = ((curwin->w_cursor.lnum * 100) / + curbuf->b_ml.ml_line_count); } if (curbuf->b_ml.ml_flags & ML_EMPTY) { vim_snprintf_add(buffer, IOSIZE, "%s", _(no_lines_msg)); @@ -3219,12 +3205,12 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) (int64_t)curbuf->b_ml.ml_line_count, n); validate_virtcol(); - len = strlen(buffer); + size_t len = strlen(buffer); col_print(buffer + len, IOSIZE - len, (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); } - (void)append_arg_number(curwin, buffer, IOSIZE, !shortmess(SHM_FILE)); + (void)append_arg_number(curwin, buffer, IOSIZE); if (dont_truncate) { // Temporarily set msg_scroll to avoid the message being truncated. @@ -3232,10 +3218,10 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) msg_start(); n = msg_scroll; msg_scroll = true; - msg(buffer); + msg(buffer, 0); msg_scroll = n; } else { - p = msg_trunc_attr(buffer, false, 0); + p = msg_trunc(buffer, false, 0); if (restart_edit != 0 || (msg_scrolled && !need_wait_return)) { // Need to repeat the message after redrawing when: // - When restart_edit is set (otherwise there will be a delay @@ -3268,7 +3254,6 @@ void maketitle(void) char *icon_str = NULL; int maxlen = 0; int len; - int mustset; char buf[IOSIZE]; if (!redrawing()) { @@ -3310,8 +3295,7 @@ void maketitle(void) SPACE_FOR_FNAME + 1); buf_p += MIN(size, SPACE_FOR_FNAME); } else { - buf_p += transstr_buf((const char *)path_tail(curbuf->b_fname), - buf_p, SPACE_FOR_FNAME + 1, true); + buf_p += transstr_buf(path_tail(curbuf->b_fname), -1, buf_p, SPACE_FOR_FNAME + 1, true); } switch (bufIsChanged(curbuf) @@ -3376,7 +3360,7 @@ void maketitle(void) *buf_p = NUL; } - append_arg_number(curwin, buf_p, (int)(SPACE_FOR_ARGNR - (size_t)(buf_p - buf)), false); + append_arg_number(curwin, buf_p, (int)(SPACE_FOR_ARGNR - (size_t)(buf_p - buf))); xstrlcat(buf_p, " - NVIM", (sizeof(buf) - (size_t)(buf_p - buf))); @@ -3392,7 +3376,7 @@ void maketitle(void) #undef SPACE_FOR_ARGNR } } - mustset = value_change(title_str, &lasttitle); + int mustset = value_change(title_str, &lasttitle); if (p_icon) { icon_str = buf; @@ -3460,7 +3444,6 @@ void resettitle(void) { ui_call_set_icon(cstr_as_string(lasticon)); ui_call_set_title(cstr_as_string(lasttitle)); - ui_flush(); } #if defined(EXITFREE) @@ -3472,8 +3455,8 @@ void free_titles(void) #endif -/// Get relative cursor position in window into "buf[buflen]", in the form 99%, -/// using "Top", "Bot" or "All" when appropriate. +/// Get relative cursor position in window into "buf[buflen]", in the localized +/// percentage form like %99, 99%; using "Top", "Bot" or "All" when appropriate. void get_rel_pos(win_T *wp, char *buf, int buflen) { // Need at least 3 chars for writing. @@ -3481,8 +3464,8 @@ void get_rel_pos(win_T *wp, char *buf, int buflen) return; } - long above; // number of lines above window - long below; // number of lines below window + linenr_T above; // number of lines above window + linenr_T below; // number of lines below window above = wp->w_topline - 1; above += win_get_fill(wp, wp->w_topline) - wp->w_topfill; @@ -3497,21 +3480,31 @@ void get_rel_pos(win_T *wp, char *buf, int buflen) } else if (above <= 0) { xstrlcpy(buf, _("Top"), (size_t)buflen); } else { - vim_snprintf(buf, (size_t)buflen, "%2d%%", above > 1000000L - ? (int)(above / ((above + below) / 100L)) - : (int)(above * 100L / (above + below))); + int perc = (above > 1000000 + ? (above / ((above + below) / 100)) + : (above * 100 / (above + below))); + + char *p = buf; + size_t l = (size_t)buflen; + if (perc < 10) { + // prepend one space + buf[0] = ' '; + p++; + l--; + } + // localized percentage value + vim_snprintf(p, l, _("%d%%"), perc); } } -/// Append (file 2 of 8) to "buf[buflen]", if editing more than one file. +/// Append (2 of 8) to "buf[buflen]", if editing more than one file. /// /// @param wp window whose buffers to check /// @param[in,out] buf string buffer to add the text to /// @param buflen length of the string buffer -/// @param add_file if true, add "file" before the arg number /// /// @return true if it was appended. -bool append_arg_number(win_T *wp, char *buf, int buflen, bool add_file) +bool append_arg_number(win_T *wp, char *buf, int buflen) FUNC_ATTR_NONNULL_ALL { // Nothing to do @@ -3519,23 +3512,10 @@ bool append_arg_number(win_T *wp, char *buf, int buflen, bool add_file) return false; } - char *p = buf + strlen(buf); // go to the end of the buffer - - // Early out if the string is getting too long - if (p - buf + 35 >= buflen) { - return false; - } + const char *msg = wp->w_arg_idx_invalid ? _(" ((%d) of %d)") : _(" (%d of %d)"); - *p++ = ' '; - *p++ = '('; - if (add_file) { - STRCPY(p, "file "); - p += 5; - } - vim_snprintf(p, (size_t)(buflen - (p - buf)), - wp->w_arg_idx_invalid - ? "(%d) of %d)" - : "%d of %d)", wp->w_arg_idx + 1, ARGCOUNT); + char *p = buf + strlen(buf); // go to the end of the buffer + vim_snprintf(p, (size_t)(buflen - (p - buf)), msg, wp->w_arg_idx + 1, ARGCOUNT); return true; } @@ -3558,7 +3538,7 @@ void fname_expand(buf_T *buf, char **ffname, char **sfname) #ifdef MSWIN if (!buf->b_p_bin) { // If the file name is a shortcut file, use the file it links to. - char *rfname = os_resolve_shortcut((const char *)(*ffname)); + char *rfname = os_resolve_shortcut(*ffname); if (rfname != NULL) { xfree(*ffname); *ffname = rfname; @@ -3584,7 +3564,7 @@ void ex_buffer_all(exarg_T *eap) bool p_ea_save; int open_wins = 0; int r; - long count; // Maximum number of windows to open. + linenr_T count; // Maximum number of windows to open. int all; // When true also load inactive buffers. int had_tab = cmdmod.cmod_tab; tabpage_T *tpnext; @@ -3600,6 +3580,10 @@ void ex_buffer_all(exarg_T *eap) all = true; } + // Stop Visual mode, the cursor and "VIsual" may very well be invalid after + // switching to another buffer. + reset_VIsual_and_resel(); + setpcmark(); // Close superfluous windows (two windows for the same buffer). @@ -3607,23 +3591,30 @@ void ex_buffer_all(exarg_T *eap) if (had_tab > 0) { goto_tabpage_tp(first_tabpage, true, true); } - for (;;) { + while (true) { tpnext = curtab->tp_next; - for (wp = firstwin; wp != NULL; wp = wpnext) { - wpnext = wp->w_next; + // Try to close floating windows first + for (wp = lastwin->w_floating ? lastwin : firstwin; wp != NULL; wp = wpnext) { + wpnext = wp->w_floating + ? wp->w_prev->w_floating ? wp->w_prev : firstwin + : (wp->w_next == NULL || wp->w_next->w_floating) ? NULL : wp->w_next; if ((wp->w_buffer->b_nwindows > 1 + || wp->w_floating || ((cmdmod.cmod_split & WSP_VERT) ? wp->w_height + wp->w_hsep_height + wp->w_status_height < Rows - p_ch - tabline_height() - global_stl_height() : wp->w_width != Columns) || (had_tab > 0 && wp != firstwin)) && !ONE_WINDOW - && !(wp->w_closing - || wp->w_buffer->b_locked > 0)) { - win_close(wp, false, false); - wpnext = firstwin; // just in case an autocommand does - // something strange with windows - tpnext = first_tabpage; // start all over... + && !(wp->w_closing || wp->w_buffer->b_locked > 0) + && !is_aucmd_win(wp)) { + if (win_close(wp, false, false) == FAIL) { + break; + } + // Just in case an autocommand does something strange with + // windows: start all over... + wpnext = lastwin->w_floating ? lastwin : firstwin; + tpnext = first_tabpage; open_wins = 0; } else { open_wins++; @@ -3643,7 +3634,8 @@ void ex_buffer_all(exarg_T *eap) // // Don't execute Win/Buf Enter/Leave autocommands here. autocmd_no_enter++; - win_enter(lastwin, false); + // lastwin may be aucmd_win + win_enter(lastwin_nofloating(), false); autocmd_no_leave++; for (buf = firstbuf; buf != NULL && open_wins < count; buf = buf->b_next) { // Check if this buffer needs a window @@ -3661,7 +3653,7 @@ void ex_buffer_all(exarg_T *eap) } else { // Check if this buffer already has a window for (wp = firstwin; wp != NULL; wp = wp->w_next) { - if (wp->w_buffer == buf) { + if (!wp->w_floating && wp->w_buffer == buf) { break; } } @@ -3735,7 +3727,7 @@ void ex_buffer_all(exarg_T *eap) // Close superfluous windows. for (wp = lastwin; open_wins > count;) { r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer) - || autowrite(wp->w_buffer, false) == OK); + || autowrite(wp->w_buffer, false) == OK) && !is_aucmd_win(wp); if (!win_valid(wp)) { // BufWrite Autocommands made the window invalid, start over wp = lastwin; @@ -3802,12 +3794,10 @@ static int chk_modeline(linenr_T lnum, int flags) char *s; char *e; char *linecopy; // local copy of any modeline found - int prev; intmax_t vers; - int end; int retval = OK; - prev = -1; + int prev = -1; for (s = ml_get(lnum); *s != NUL; s++) { if (prev == -1 || ascii_isspace(prev)) { if ((prev != -1 && strncmp(s, "ex:", (size_t)3) == 0) @@ -3853,7 +3843,7 @@ static int chk_modeline(linenr_T lnum, int flags) // prepare for emsg() estack_push(ETYPE_MODELINE, "modelines", lnum); - end = false; + bool end = false; while (end == false) { s = skipwhite(s); if (*s == NUL) { @@ -4036,153 +4026,64 @@ char *buf_spname(buf_T *buf) return NULL; } -static int buf_signcols_inner(buf_T *buf, int maximum) -{ - sign_entry_T *sign; // a sign in the sign list - int signcols = 0; - int linesum = 0; - linenr_T curline = 0; - - buf->b_signcols.sentinel = 0; - - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (sign->se_lnum > curline) { - // Counted all signs, now add extmark signs - if (curline > 0) { - linesum += decor_signcols(buf, &decor_state, (int)curline - 1, (int)curline - 1, - maximum - linesum); - } - curline = sign->se_lnum; - if (linesum > signcols) { - signcols = linesum; - buf->b_signcols.sentinel = curline; - if (signcols >= maximum) { - return maximum; - } - } - linesum = 0; - } - if (sign->se_has_text_or_icon) { - linesum++; - } - } - - if (curline > 0) { - linesum += decor_signcols(buf, &decor_state, (int)curline - 1, (int)curline - 1, - maximum - linesum); - } - if (linesum > signcols) { - signcols = linesum; - if (signcols >= maximum) { - return maximum; - } - } - - // Check extmarks between signs - linesum = decor_signcols(buf, &decor_state, 0, (int)buf->b_ml.ml_line_count - 1, maximum); - - if (linesum > signcols) { - signcols = linesum; - buf->b_signcols.sentinel = curline; - if (signcols >= maximum) { - return maximum; - } - } - - return signcols; -} - -/// Invalidate the signcolumn if needed after deleting -/// signs between line1 and line2 (inclusive). -/// -/// @param buf buffer to check -/// @param line1 start of region being deleted -/// @param line2 end of region being deleted +/// Invalidate the signcolumn if needed after deleting a sign ranging from line1 to line2. void buf_signcols_del_check(buf_T *buf, linenr_T line1, linenr_T line2) { - if (!buf->b_signcols.valid) { - return; - } - - if (!buf->b_signcols.sentinel) { - buf->b_signcols.valid = false; - return; - } - linenr_T sent = buf->b_signcols.sentinel; - if (sent >= line1 && sent <= line2) { - // Only invalidate when removing signs at the sentinel line. - buf->b_signcols.valid = false; + // When removed sign overlaps the sentinel line, entire buffer needs to be checked. + buf->b_signcols.sentinel = buf->b_signcols.size = 0; } } -/// Re-calculate the signcolumn after adding a sign. -/// -/// @param buf buffer to check -/// @param added sign being added -void buf_signcols_add_check(buf_T *buf, sign_entry_T *added) +/// Invalidate the signcolumn if needed after adding a sign ranging from line1 to line2. +void buf_signcols_add_check(buf_T *buf, linenr_T line1, linenr_T line2) { - if (!buf->b_signcols.valid) { - return; - } - - if (!added || !buf->b_signcols.sentinel) { - buf->b_signcols.valid = false; + if (!buf->b_signcols.sentinel) { return; } - if (added->se_lnum == buf->b_signcols.sentinel) { + linenr_T sent = buf->b_signcols.sentinel; + if (sent >= line1 && sent <= line2) { + // If added sign overlaps sentinel line, increment without invalidating. if (buf->b_signcols.size == buf->b_signcols.max) { buf->b_signcols.max++; } buf->b_signcols.size++; - redraw_buf_later(buf, UPD_NOT_VALID); return; } - sign_entry_T *s; - - // Get first sign for added lnum - for (s = added; s->se_prev && s->se_lnum == s->se_prev->se_lnum; s = s->se_prev) {} - - // Count signs for lnum - int linesum = 1; - for (; s->se_next && s->se_lnum == s->se_next->se_lnum; s = s->se_next) { - linesum++; + if (line1 < buf->b_signcols.invalid_top) { + buf->b_signcols.invalid_top = line1; } - linesum += decor_signcols(buf, &decor_state, (int)s->se_lnum - 1, (int)s->se_lnum - 1, - SIGN_SHOW_MAX - linesum); - - if (linesum > buf->b_signcols.size) { - buf->b_signcols.size = linesum; - buf->b_signcols.max = linesum; - buf->b_signcols.sentinel = added->se_lnum; - redraw_buf_later(buf, UPD_NOT_VALID); + if (line2 > buf->b_signcols.invalid_bot) { + buf->b_signcols.invalid_bot = line2; } } -int buf_signcols(buf_T *buf, int maximum) +int buf_signcols(buf_T *buf, int max) { - // The maximum can be determined from 'signcolumn' which is window scoped so - // need to invalidate signcols if the maximum is greater than the previous - // maximum. - if (maximum > buf->b_signcols.max) { - buf->b_signcols.valid = false; - } - - if (!buf->b_signcols.valid) { - int signcols = buf_signcols_inner(buf, maximum); - // Check if we need to redraw - if (signcols != buf->b_signcols.size) { - buf->b_signcols.size = signcols; - buf->b_signcols.max = maximum; - redraw_buf_later(buf, UPD_NOT_VALID); + if (!buf->b_signs_with_text) { + buf->b_signcols.size = 0; + } else if (max <= 1 && buf->b_signs_with_text >= (size_t)max) { + buf->b_signcols.size = max; + } else { + linenr_T sent = buf->b_signcols.sentinel; + if (!sent || max > buf->b_signcols.max) { + // Recheck if the window scoped maximum 'signcolumn' is greater than the + // previous maximum or if there is no sentinel line yet. + buf->b_signcols.invalid_top = sent ? sent : 1; + buf->b_signcols.invalid_bot = sent ? sent : buf->b_ml.ml_line_count; } - buf->b_signcols.valid = true; + if (buf->b_signcols.invalid_bot) { + decor_validate_signcols(buf, max); + } } + buf->b_signcols.max = max; + buf->b_signcols.invalid_top = MAXLNUM; + buf->b_signcols.invalid_bot = 0; return buf->b_signcols.size; } @@ -4223,7 +4124,7 @@ bool buf_contents_changed(buf_T *buf) bool differ = true; // Allocate a buffer without putting it in the buffer list. - buf_T *newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); + buf_T *newbuf = buflist_new(NULL, NULL, 1, BLN_DUMMY); if (newbuf == NULL) { return true; } @@ -4236,15 +4137,19 @@ bool buf_contents_changed(buf_T *buf) aco_save_T aco; aucmd_prepbuf(&aco, newbuf); + // We don't want to trigger autocommands now, they may have nasty + // side-effects like wiping buffers + block_autocmds(); + if (ml_open(curbuf) == OK && readfile(buf->b_ffname, buf->b_fname, - (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, + 0, 0, (linenr_T)MAXLNUM, &ea, READ_NEW | READ_DUMMY, false) == OK) { // compare the two files line by line if (buf->b_ml.ml_line_count == curbuf->b_ml.ml_line_count) { differ = false; for (linenr_T lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) { - if (strcmp(ml_get_buf(buf, lnum, false), ml_get(lnum)) != 0) { + if (strcmp(ml_get_buf(buf, lnum), ml_get(lnum)) != 0) { differ = true; break; } @@ -4260,6 +4165,8 @@ bool buf_contents_changed(buf_T *buf) wipe_buffer(newbuf, false); } + unblock_autocmds(); + return differ; } @@ -4298,9 +4205,9 @@ int buf_open_scratch(handle_T bufnr, char *bufname) apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf); (void)setfname(curbuf, bufname, NULL, true); apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf); - set_option_value_give_err("bh", 0L, "hide", OPT_LOCAL); - set_option_value_give_err("bt", 0L, "nofile", OPT_LOCAL); - set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("bh", STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL); + set_option_value_give_err("bt", STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL); + set_option_value_give_err("swf", BOOLEAN_OPTVAL(false), OPT_LOCAL); RESET_BINDING(curwin); return OK; } |