aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r--src/nvim/buffer.c558
1 files changed, 296 insertions, 262 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 8a594dea92..f6c7229485 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -32,6 +32,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_updates.h"
#include "nvim/change.h"
@@ -39,28 +40,30 @@
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/cursor.h"
-#include "nvim/decoration.h"
#include "nvim/diff.h"
#include "nvim/digraph.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
-#include "nvim/eval/typval_defs.h"
+#include "nvim/eval/typval.h"
#include "nvim/eval/vars.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
+#include "nvim/ex_eval_defs.h"
#include "nvim/ex_getln.h"
#include "nvim/extmark.h"
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/help.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
@@ -68,26 +71,33 @@
#include "nvim/map_defs.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memfile_defs.h"
+#include "nvim/memline.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_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.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/regexp_defs.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/search.h"
#include "nvim/spell.h"
#include "nvim/state_defs.h"
@@ -95,7 +105,6 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
-#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/usercmd.h"
@@ -133,7 +142,7 @@ int get_highest_fnum(void)
/// @param read_stdin read file from stdin, otherwise fifo
/// @param eap for forced 'ff' and 'fenc' or NULL
/// @param flags extra flags for readfile()
-static int read_buffer(int read_stdin, exarg_T *eap, int flags)
+static int read_buffer(bool read_stdin, exarg_T *eap, int flags)
{
int retval = OK;
bool silent = shortmess(SHM_FILEINFO);
@@ -202,13 +211,13 @@ bool buf_ensure_loaded(buf_T *buf)
/// @param flags_arg extra flags for readfile()
///
/// @return FAIL for failure, OK otherwise.
-int open_buffer(int read_stdin, exarg_T *eap, int flags_arg)
+int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg)
{
int flags = flags_arg;
int retval = OK;
bufref_T old_curbuf;
OptInt old_tw = curbuf->b_p_tw;
- int read_fifo = false;
+ bool read_fifo = false;
bool silent = shortmess(SHM_FILEINFO);
// The 'readonly' flag is only set when BF_NEVERLOADED is being reset.
@@ -274,16 +283,14 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg)
if (curbuf->b_ffname != NULL) {
#ifdef UNIX
int save_bin = curbuf->b_p_bin;
- int perm;
-
- perm = os_getperm(curbuf->b_ffname);
+ int perm = os_getperm(curbuf->b_ffname);
if (perm >= 0 && (0 || S_ISFIFO(perm)
|| S_ISSOCK(perm)
# ifdef OPEN_CHR_FILES
|| (S_ISCHR(perm)
&& is_dev_fd_file(curbuf->b_ffname))
# endif
- )) { // NOLINT(whitespace/parens)
+ )) {
read_fifo = true;
}
if (read_fifo) {
@@ -303,9 +310,9 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg)
}
#endif
- // Help buffer is filtered.
+ // Help buffer: populate *local-additions* in help.txt
if (bt_help(curbuf)) {
- fix_help_buffer();
+ get_local_additions();
}
} else if (read_stdin) {
int save_bin = curbuf->b_p_bin;
@@ -332,7 +339,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg)
// if first time loading this buffer, init b_chartab[]
if (curbuf->b_flags & BF_NEVERLOADED) {
- (void)buf_init_chartab(curbuf, false);
+ buf_init_chartab(curbuf, false);
parse_cino(curbuf);
}
@@ -836,8 +843,9 @@ void buf_freeall(buf_T *buf, int flags)
ml_close(buf, true); // close and delete the memline/memfile
buf->b_ml.ml_line_count = 0; // no lines in buffer
if ((flags & BFA_KEEP_UNDO) == 0) {
- u_blockfree(buf); // free the memory allocated for undo
- u_clearall(buf); // reset all undo information
+ // free the memory allocated for undo
+ // and reset all undo information
+ u_clearallandblockfree(buf);
}
syntax_clear(&buf->b_s); // reset syntax info
buf->b_flags &= ~BF_READERR; // a read error is no longer relevant
@@ -938,8 +946,8 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count)
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);
+ do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
+ start, dir, count, eap->forceit);
if (swap_exists_action == SEA_QUIT && *eap->cmd == 's') {
cleanup_T cs;
@@ -1047,7 +1055,7 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b
int bnr; // buffer number
if (addr_count == 0) {
- (void)do_buffer(command, DOBUF_CURRENT, FORWARD, 0, forceit);
+ do_buffer(command, DOBUF_CURRENT, FORWARD, 0, forceit);
} else {
if (addr_count == 2) {
if (*arg) { // both range and argument is not allowed
@@ -1126,7 +1134,7 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b
/// Make the current buffer empty.
/// Used when it is wiped out and it's the last buffer.
-static int empty_curbuf(int close_others, int forceit, int action)
+static int empty_curbuf(bool close_others, int forceit, int action)
{
buf_T *buf = curbuf;
@@ -1176,6 +1184,32 @@ static int empty_curbuf(int close_others, int forceit, int action)
return retval;
}
+/// Remove every jump list entry referring to a given buffer.
+/// This function will also adjust the current jump list index.
+void buf_remove_from_jumplist(buf_T *deleted_buf)
+{
+ // Remove all jump list entries that match the deleted buffer.
+ for (int i = curwin->w_jumplistlen - 1; i >= 0; i--) {
+ buf_T *buf = buflist_findnr(curwin->w_jumplist[i].fmark.fnum);
+
+ if (buf == deleted_buf) {
+ // Found an entry that we want to delete.
+ curwin->w_jumplistlen -= 1;
+
+ // If the current jump list index behind the entry we want to
+ // delete, move it back by one.
+ if (curwin->w_jumplistidx > i && curwin->w_jumplistidx > 0) {
+ curwin->w_jumplistidx -= 1;
+ }
+
+ // Actually remove the entry from the jump list.
+ for (int d = i; d < curwin->w_jumplistlen; d++) {
+ curwin->w_jumplist[d] = curwin->w_jumplist[d + 1];
+ }
+ }
+ }
+}
+
/// Implementation of the commands for the buffer list.
///
/// action == DOBUF_GOTO go to specified buffer
@@ -1198,8 +1232,9 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
{
buf_T *buf;
buf_T *bp;
- int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
- || action == DOBUF_WIPE);
+ bool update_jumplist = true;
+ bool unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
+ || action == DOBUF_WIPE);
switch (start) {
case DOBUF_FIRST:
@@ -1355,7 +1390,11 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
// If the buffer to be deleted is not the current one, delete it here.
if (buf != curbuf) {
+ // Remove the buffer to be deleted from the jump list.
+ buf_remove_from_jumplist(buf);
+
close_windows(buf, false);
+
if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) {
close_buffer(NULL, buf, action, false, false);
}
@@ -1375,42 +1414,53 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)) {
buf = au_new_curbuf.br_buf;
} else if (curwin->w_jumplistlen > 0) {
- int jumpidx;
-
- jumpidx = curwin->w_jumplistidx - 1;
- if (jumpidx < 0) {
- jumpidx = curwin->w_jumplistlen - 1;
- }
+ // Remove the current buffer from the jump list.
+ buf_remove_from_jumplist(curbuf);
+
+ // It's possible that we removed all jump list entries, in that case we need to try another
+ // approach
+ if (curwin->w_jumplistlen > 0) {
+ // If the index is the same as the length, the current position was not yet added to the jump
+ // list. So we can safely go back to the last entry and search from there.
+ if (curwin->w_jumplistidx == curwin->w_jumplistlen) {
+ curwin->w_jumplistidx = curwin->w_jumplistlen - 1;
+ }
- forward = jumpidx;
- while (jumpidx != curwin->w_jumplistidx) {
- buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
- if (buf != NULL) {
- // Skip current and unlisted bufs. Also skip a quickfix
- // buffer, it might be deleted soon.
- if (buf == curbuf || !buf->b_p_bl || bt_quickfix(buf)) {
- buf = NULL;
- } else if (buf->b_ml.ml_mfp == NULL) {
- // skip unloaded buf, but may keep it for later
- if (bp == NULL) {
- bp = buf;
+ int jumpidx = curwin->w_jumplistidx;
+
+ forward = jumpidx;
+ do {
+ buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
+
+ if (buf != NULL) {
+ // Skip unlisted bufs. Also skip a quickfix
+ // buffer, it might be deleted soon.
+ if (!buf->b_p_bl || bt_quickfix(buf)) {
+ buf = NULL;
+ } else if (buf->b_ml.ml_mfp == NULL) {
+ // skip unloaded buf, but may keep it for later
+ if (bp == NULL) {
+ bp = buf;
+ }
+ buf = NULL;
}
- buf = NULL;
}
- }
- if (buf != NULL) { // found a valid buffer: stop searching
- break;
- }
- // advance to older entry in jump list
- if (!jumpidx && curwin->w_jumplistidx == curwin->w_jumplistlen) {
- break;
- }
- if (--jumpidx < 0) {
- jumpidx = curwin->w_jumplistlen - 1;
- }
- if (jumpidx == forward) { // List exhausted for sure
- break;
- }
+ if (buf != NULL) { // found a valid buffer: stop searching
+ curwin->w_jumplistidx = jumpidx;
+ update_jumplist = false;
+ break;
+ }
+ // advance to older entry in jump list
+ if (!jumpidx && curwin->w_jumplistidx == curwin->w_jumplistlen) {
+ break;
+ }
+ if (--jumpidx < 0) {
+ jumpidx = curwin->w_jumplistlen - 1;
+ }
+ if (jumpidx == forward) { // List exhausted for sure
+ break;
+ }
+ } while (jumpidx != curwin->w_jumplistidx);
}
}
@@ -1506,7 +1556,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
}
// Go to the other buffer.
- set_curbuf(buf, action);
+ set_curbuf(buf, action, update_jumplist);
if (action == DOBUF_SPLIT) {
RESET_BINDING(curwin); // reset 'scrollbind' and 'cursorbind'
@@ -1528,14 +1578,18 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
/// DOBUF_UNLOAD unload it
/// DOBUF_DEL delete it
/// DOBUF_WIPE wipe it out
-void set_curbuf(buf_T *buf, int action)
+void set_curbuf(buf_T *buf, int action, bool update_jumplist)
{
buf_T *prevbuf;
int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
|| action == DOBUF_WIPE);
OptInt old_tw = curbuf->b_p_tw;
+ const int last_winid = get_last_winid();
+
+ if (update_jumplist) {
+ setpcmark();
+ }
- setpcmark();
if ((cmdmod.cmod_flags & CMOD_KEEPALT) == 0) {
curwin->w_alt_fnum = curbuf->b_fnum; // remember alternate file
}
@@ -1559,7 +1613,11 @@ void set_curbuf(buf_T *buf, int action)
if (prevbuf == curwin->w_buffer) {
reset_synblock(curwin);
}
- if (unload) {
+ // autocommands may have opened a new window
+ // with prevbuf, grr
+ if (unload
+ || (last_winid != get_last_winid()
+ && strchr("wdu", prevbuf->b_p_bh[0]) != NULL)) {
close_windows(prevbuf, false);
}
if (bufref_valid(&prevbufref) && !aborting()) {
@@ -1589,6 +1647,11 @@ void set_curbuf(buf_T *buf, int action)
// If curwin->w_buffer is null, enter_buffer() will make it valid again
bool valid = buf_valid(buf);
if ((valid && buf != curbuf && !aborting()) || curwin->w_buffer == NULL) {
+ // autocommands changed curbuf and we will move to another
+ // buffer soon, so decrement curbuf->b_nwindows
+ if (curbuf != NULL && prevbuf != curbuf) {
+ curbuf->b_nwindows--;
+ }
// If the buffer is not valid but curwin->w_buffer is NULL we must
// enter some buffer. Using the last one is hopefully OK.
if (!valid) {
@@ -1666,7 +1729,7 @@ void enter_buffer(buf_T *buf)
need_fileinfo = true; // display file info after redraw
}
// check if file changed
- (void)buf_check_timestamp(curbuf);
+ buf_check_timestamp(curbuf);
curwin->w_topline = 1;
curwin->w_topfill = 0;
@@ -1691,12 +1754,12 @@ void enter_buffer(buf_T *buf)
do_autochdir();
if (curbuf->b_kmap_state & KEYMAP_INIT) {
- (void)keymap_init();
+ keymap_init();
}
// 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)parse_spelllang(curwin);
+ parse_spelllang(curwin);
}
curbuf->b_last_used = time(NULL);
@@ -1844,7 +1907,6 @@ 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.sentinel = 0;
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
buf_init_changedtick(buf);
}
@@ -1963,7 +2025,7 @@ bool curbuf_reusable(void)
/// Free the memory for the options of a buffer.
/// If "free_p_ff" is true also free 'fileformat', 'buftype' and
/// 'fileencoding'.
-void free_buf_options(buf_T *buf, int free_p_ff)
+void free_buf_options(buf_T *buf, bool free_p_ff)
{
if (free_p_ff) {
clear_string_option(&buf->b_p_fenc);
@@ -2151,7 +2213,7 @@ buf_T *buflist_findname_exp(char *fname)
#else
false
#endif
- ); // NOLINT(whitespace/parens)
+ );
if (ffname != NULL) {
buf = buflist_findname(ffname);
xfree(ffname);
@@ -2226,7 +2288,7 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted,
return -1;
}
char *patend = pat + strlen(pat) - 1;
- int toggledollar = (patend > pat && *patend == '$');
+ bool toggledollar = (patend > pat && *patend == '$');
// First try finding a listed buffer. If not found and "unlisted"
// is true, try finding an unlisted buffer.
@@ -2325,10 +2387,8 @@ static int buf_time_compare(const void *s1, const void *s2)
/// @return OK if matches found, FAIL otherwise.
int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
{
- int count = 0;
- int round;
- char *p;
bufmatch_T *matches = NULL;
+ bool to_free = false;
*num_file = 0; // return values in case of FAIL
*file = NULL;
@@ -2340,125 +2400,115 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
const bool fuzzy = cmdline_fuzzy_complete(pat);
char *patc = NULL;
+ fuzmatch_str_T *fuzmatch = NULL;
+ regmatch_T regmatch;
+
// Make a copy of "pat" and change "^" to "\(^\|[\/]\)" (if doing regular
// expression matching)
if (!fuzzy) {
- if (*pat == '^') {
- patc = xmalloc(strlen(pat) + 11);
- STRCPY(patc, "\\(^\\|[\\/]\\)");
- STRCPY(patc + 11, pat + 1);
+ if (*pat == '^' && pat[1] != NUL) {
+ patc = xstrdup(pat + 1);
+ to_free = true;
+ } else if (*pat == '^') {
+ patc = "";
} else {
patc = pat;
}
+ regmatch.regprog = vim_regcomp(patc, RE_MAGIC);
}
- fuzmatch_str_T *fuzmatch = NULL;
- // attempt == 0: try match with '\<', match at start of word
- // attempt == 1: try match without '\<', match anywhere
- for (int attempt = 0; attempt <= (fuzzy ? 0 : 1); attempt++) {
- regmatch_T regmatch;
- if (!fuzzy) {
- if (attempt > 0 && patc == pat) {
- break; // there was no anchor, no need to try again
+ int count = 0;
+ int score = 0;
+ // round == 1: Count the matches.
+ // round == 2: Build the array to keep the matches.
+ for (int round = 1; round <= 2; round++) {
+ count = 0;
+ FOR_ALL_BUFFERS(buf) {
+ if (!buf->b_p_bl) { // skip unlisted buffers
+ continue;
}
- regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC);
- }
-
- int score = 0;
- // round == 1: Count the matches.
- // round == 2: Build the array to keep the matches.
- for (round = 1; round <= 2; round++) {
- count = 0;
- FOR_ALL_BUFFERS(buf) {
- if (!buf->b_p_bl) { // skip unlisted buffers
+ if (options & BUF_DIFF_FILTER) {
+ // Skip buffers not suitable for
+ // :diffget or :diffput completion.
+ if (buf == curbuf || !diff_mode_buf(buf)) {
continue;
}
- if (options & BUF_DIFF_FILTER) {
- // Skip buffers not suitable for
- // :diffget or :diffput completion.
- if (buf == curbuf || !diff_mode_buf(buf)) {
- continue;
- }
- }
+ }
- if (!fuzzy) {
- if (regmatch.regprog == NULL) {
- // invalid pattern, possibly after recompiling
- if (patc != pat) {
- xfree(patc);
- }
- return FAIL;
- }
- p = buflist_match(&regmatch, buf, p_wic);
- } else {
- p = NULL;
- // first try matching with the short file name
- if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0) {
- p = buf->b_sfname;
- }
- if (p == NULL) {
- // next try matching with the full path file name
- if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0) {
- p = buf->b_ffname;
- }
+ char *p = NULL;
+ if (!fuzzy) {
+ if (regmatch.regprog == NULL) {
+ // invalid pattern, possibly after recompiling
+ if (to_free) {
+ xfree(patc);
}
+ return FAIL;
}
-
- if (p == NULL) {
- continue;
- }
-
- if (round == 1) {
- count++;
- continue;
- }
-
- if (options & WILD_HOME_REPLACE) {
- p = home_replace_save(buf, p);
- } else {
- p = xstrdup(p);
+ p = buflist_match(&regmatch, buf, p_wic);
+ } else {
+ p = NULL;
+ // first try matching with the short file name
+ if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0) {
+ p = buf->b_sfname;
}
-
- if (!fuzzy) {
- if (matches != NULL) {
- matches[count].buf = buf;
- matches[count].match = p;
- count++;
- } else {
- (*file)[count++] = p;
+ if (p == NULL) {
+ // next try matching with the full path file name
+ if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0) {
+ p = buf->b_ffname;
}
- } else {
- fuzmatch[count].idx = count;
- fuzmatch[count].str = p;
- fuzmatch[count].score = score;
- count++;
}
}
- if (count == 0) { // no match found, break here
- break;
+
+ if (p == NULL) {
+ continue;
}
+
if (round == 1) {
- if (!fuzzy) {
- *file = xmalloc((size_t)count * sizeof(**file));
- if (options & WILD_BUFLASTUSED) {
- matches = xmalloc((size_t)count * sizeof(*matches));
- }
+ count++;
+ continue;
+ }
+
+ if (options & WILD_HOME_REPLACE) {
+ p = home_replace_save(buf, p);
+ } else {
+ p = xstrdup(p);
+ }
+
+ if (!fuzzy) {
+ if (matches != NULL) {
+ matches[count].buf = buf;
+ matches[count].match = p;
+ count++;
} else {
- fuzmatch = xmalloc((size_t)count * sizeof(fuzmatch_str_T));
+ (*file)[count++] = p;
}
+ } else {
+ fuzmatch[count].idx = count;
+ fuzmatch[count].str = p;
+ fuzmatch[count].score = score;
+ count++;
}
}
-
- if (!fuzzy) {
- vim_regfree(regmatch.regprog);
- if (count) { // match(es) found, break here
- break;
+ if (count == 0) { // no match found, break here
+ break;
+ }
+ if (round == 1) {
+ if (!fuzzy) {
+ *file = xmalloc((size_t)count * sizeof(**file));
+ if (options & WILD_BUFLASTUSED) {
+ matches = xmalloc((size_t)count * sizeof(*matches));
+ }
+ } else {
+ fuzmatch = xmalloc((size_t)count * sizeof(fuzmatch_str_T));
}
}
}
- if (!fuzzy && patc != pat) {
- xfree(patc);
+ if (!fuzzy) {
+ vim_regfree(regmatch.regprog);
+ if (to_free) {
+ xfree(patc);
+ }
}
if (!fuzzy) {
@@ -2722,7 +2772,7 @@ void get_winopts(buf_T *buf)
curwin->w_changelistidx = wip->wi_changelistidx;
}
- if (curwin->w_float_config.style == kWinStyleMinimal) {
+ if (curwin->w_config.style == kWinStyleMinimal) {
didset_window_options(curwin, false);
win_set_minimal_style(curwin);
}
@@ -2757,8 +2807,6 @@ linenr_T buflist_findlnum(buf_T *buf)
void buflist_list(exarg_T *eap)
{
buf_T *buf = firstbuf;
- int len;
- int i;
garray_T buflist;
buf_T **buflist_data = NULL;
@@ -2823,21 +2871,21 @@ void buflist_list(exarg_T *eap)
}
msg_putchar('\n');
- len = vim_snprintf(IObuff, IOSIZE - 20, "%3d%c%c%c%c%c \"%s\"",
- buf->b_fnum,
- buf->b_p_bl ? ' ' : 'u',
- buf == curbuf ? '%' : (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
- buf->b_ml.ml_mfp == NULL ? ' ' : (buf->b_nwindows == 0 ? 'h' : 'a'),
- ro_char,
- changed_char,
- NameBuff);
+ int len = vim_snprintf(IObuff, IOSIZE - 20, "%3d%c%c%c%c%c \"%s\"",
+ buf->b_fnum,
+ buf->b_p_bl ? ' ' : 'u',
+ buf == curbuf ? '%' : (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
+ buf->b_ml.ml_mfp == NULL ? ' ' : (buf->b_nwindows == 0 ? 'h' : 'a'),
+ ro_char,
+ changed_char,
+ NameBuff);
if (len > IOSIZE - 20) {
len = IOSIZE - 20;
}
// put "line 999" in column 40 or after the file name
- i = 40 - vim_strsize(IObuff);
+ int i = 40 - vim_strsize(IObuff);
do {
IObuff[len++] = ' ';
} while (--i > 0 && len < IOSIZE - 18);
@@ -3136,7 +3184,7 @@ static bool buf_same_file_id(buf_T *buf, FileID *file_id)
/// Print info about the current buffer.
///
/// @param fullname when non-zero print full path
-void fileinfo(int fullname, int shorthelp, int dont_truncate)
+void fileinfo(int fullname, int shorthelp, bool dont_truncate)
{
char *name;
int n;
@@ -3210,7 +3258,7 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate)
(int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1);
}
- (void)append_arg_number(curwin, buffer, IOSIZE);
+ append_arg_number(curwin, buffer, IOSIZE);
if (dont_truncate) {
// Temporarily set msg_scroll to avoid the message being truncated.
@@ -3253,7 +3301,6 @@ void maketitle(void)
char *title_str = NULL;
char *icon_str = NULL;
int maxlen = 0;
- int len;
char buf[IOSIZE];
if (!redrawing()) {
@@ -3278,7 +3325,7 @@ void maketitle(void)
if (*p_titlestring != NUL) {
if (stl_syntax & STL_IN_TITLE) {
build_stl_str_hl(curwin, buf, sizeof(buf), p_titlestring,
- "titlestring", 0, 0, maxlen, NULL, NULL, NULL);
+ kOptTitlestring, 0, 0, maxlen, NULL, NULL, NULL, NULL);
title_str = buf;
} else {
title_str = p_titlestring;
@@ -3376,14 +3423,14 @@ void maketitle(void)
#undef SPACE_FOR_ARGNR
}
}
- int mustset = value_change(title_str, &lasttitle);
+ bool mustset = value_change(title_str, &lasttitle);
if (p_icon) {
icon_str = buf;
if (*p_iconstring != NUL) {
if (stl_syntax & STL_IN_ICON) {
build_stl_str_hl(curwin, icon_str, sizeof(buf), p_iconstring,
- "iconstring", 0, 0, 0, NULL, NULL, NULL);
+ kOptIconstring, 0, 0, 0, NULL, NULL, NULL, NULL);
} else {
icon_str = p_iconstring;
}
@@ -3396,10 +3443,10 @@ void maketitle(void)
}
*icon_str = NUL;
// Truncate name at 100 bytes.
- len = (int)strlen(buf_p);
+ int len = (int)strlen(buf_p);
if (len > 100) {
len -= 100;
- len += utf_cp_tail_off(buf_p, buf_p + len) + 1;
+ len += utf_cp_bounds(buf_p, buf_p + len).end_off;
buf_p += len;
}
STRCPY(icon_str, buf_p);
@@ -3558,16 +3605,12 @@ bool bt_prompt(buf_T *buf)
/// Open a window for a number of buffers.
void ex_buffer_all(exarg_T *eap)
{
- buf_T *buf;
win_T *wp, *wpnext;
int split_ret = OK;
- bool p_ea_save;
int open_wins = 0;
- int r;
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;
if (eap->addr_count == 0) { // make as many windows as possible
count = 9999;
@@ -3592,7 +3635,7 @@ void ex_buffer_all(exarg_T *eap)
goto_tabpage_tp(first_tabpage, true, true);
}
while (true) {
- tpnext = curtab->tp_next;
+ tabpage_T *tpnext = curtab->tp_next;
// Try to close floating windows first
for (wp = lastwin->w_floating ? lastwin : firstwin; wp != NULL; wp = wpnext) {
wpnext = wp->w_floating
@@ -3637,7 +3680,7 @@ void ex_buffer_all(exarg_T *eap)
// 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) {
+ for (buf_T *buf = firstbuf; buf != NULL && open_wins < count; buf = buf->b_next) {
// Check if this buffer needs a window
if ((!all && buf->b_ml.ml_mfp == NULL) || !buf->b_p_bl) {
continue;
@@ -3667,7 +3710,7 @@ void ex_buffer_all(exarg_T *eap)
bufref_T bufref;
set_bufref(&bufref, buf);
// Split the window and put the buffer in it.
- p_ea_save = p_ea;
+ bool p_ea_save = p_ea;
p_ea = true; // use space from all windows
split_ret = win_split(0, WSP_ROOM | WSP_BELOW);
open_wins++;
@@ -3678,7 +3721,7 @@ void ex_buffer_all(exarg_T *eap)
// Open the buffer in this window.
swap_exists_action = SEA_DIALOG;
- set_curbuf(buf, DOBUF_GOTO);
+ set_curbuf(buf, DOBUF_GOTO, false);
if (!bufref_valid(&bufref)) {
// Autocommands deleted the buffer.
swap_exists_action = SEA_NONE;
@@ -3708,7 +3751,7 @@ void ex_buffer_all(exarg_T *eap)
os_breakcheck();
if (got_int) {
- (void)vgetc(); // only break the file loading, not the rest
+ vgetc(); // only break the file loading, not the rest
break;
}
// Autocommands deleted the buffer or aborted script processing!!!
@@ -3726,8 +3769,8 @@ 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) && !is_aucmd_win(wp);
+ bool r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
+ || autowrite(wp->w_buffer, false) == OK) && !is_aucmd_win(wp);
if (!win_valid(wp)) {
// BufWrite Autocommands made the window invalid, start over
wp = lastwin;
@@ -3800,8 +3843,8 @@ static int chk_modeline(linenr_T lnum, int flags)
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)
- || strncmp(s, "vi:", (size_t)3) == 0) {
+ if ((prev != -1 && strncmp(s, "ex:", 3) == 0)
+ || strncmp(s, "vi:", 3) == 0) {
break;
}
// Accept both "vim" and "Vim".
@@ -3866,8 +3909,8 @@ static int chk_modeline(linenr_T lnum, int flags)
// "vi:set opt opt opt: foo" -- foo not interpreted
// "vi:opt opt opt: foo" -- foo interpreted
// Accept "se" for compatibility with Elvis.
- if (strncmp(s, "set ", (size_t)4) == 0
- || strncmp(s, "se ", (size_t)3) == 0) {
+ if (strncmp(s, "set ", 4) == 0
+ || strncmp(s, "se ", 3) == 0) {
if (*e != ':') { // no terminating ':'?
break;
}
@@ -4015,6 +4058,9 @@ char *buf_spname(buf_T *buf)
if (buf->b_fname != NULL) {
return buf->b_fname;
}
+ if (buf == cmdwin_buf) {
+ return _("[Command Line]");
+ }
if (bt_prompt(buf)) {
return _("[Prompt]");
}
@@ -4026,67 +4072,6 @@ char *buf_spname(buf_T *buf)
return NULL;
}
-/// 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)
-{
- linenr_T sent = buf->b_signcols.sentinel;
- if (sent >= line1 && sent <= line2) {
- // When removed sign overlaps the sentinel line, entire buffer needs to be checked.
- buf->b_signcols.sentinel = buf->b_signcols.size = 0;
- }
-}
-
-/// 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.sentinel) {
- return;
- }
-
- 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++;
- return;
- }
-
- if (line1 < buf->b_signcols.invalid_top) {
- buf->b_signcols.invalid_top = line1;
- }
- if (line2 > buf->b_signcols.invalid_bot) {
- buf->b_signcols.invalid_bot = line2;
- }
-}
-
-int buf_signcols(buf_T *buf, int max)
-{
- 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;
- }
-
- 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;
-}
-
/// Get "buf->b_fname", use "[No Name]" if it is NULL.
char *buf_get_fname(const buf_T *buf)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
@@ -4193,6 +4178,7 @@ void wipe_buffer(buf_T *buf, bool aucmd)
/// - Always considered 'nomodified'
///
/// @param bufnr Buffer to switch to, or 0 to create a new buffer.
+/// @param bufname Buffer name, or NULL.
///
/// @see curbufIsChanged()
///
@@ -4202,12 +4188,60 @@ int buf_open_scratch(handle_T bufnr, char *bufname)
if (do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL) == FAIL) {
return FAIL;
}
- 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", 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);
+ if (bufname != NULL) {
+ apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
+ setfname(curbuf, bufname, NULL, true);
+ apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
+ }
+ set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL);
+ set_option_value_give_err(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL);
+ set_option_value_give_err(kOptSwapfile, BOOLEAN_OPTVAL(false), OPT_LOCAL);
RESET_BINDING(curwin);
return OK;
}
+
+bool buf_is_empty(buf_T *buf)
+{
+ return buf->b_ml.ml_line_count == 1 && *ml_get_buf(buf, 1) == '\0';
+}
+
+/// Increment b:changedtick value
+///
+/// Also checks b: for consistency in case of debug build.
+///
+/// @param[in,out] buf Buffer to increment value in.
+void buf_inc_changedtick(buf_T *const buf)
+ FUNC_ATTR_NONNULL_ALL
+{
+ buf_set_changedtick(buf, buf_get_changedtick(buf) + 1);
+}
+
+/// Set b:changedtick, also checking b: for consistency in debug build
+///
+/// @param[out] buf Buffer to set changedtick in.
+/// @param[in] changedtick New value.
+void buf_set_changedtick(buf_T *const buf, const varnumber_T changedtick)
+ FUNC_ATTR_NONNULL_ALL
+{
+ typval_T old_val = buf->changedtick_di.di_tv;
+
+#ifndef NDEBUG
+ dictitem_T *const changedtick_di = tv_dict_find(buf->b_vars, S_LEN("changedtick"));
+ assert(changedtick_di != NULL);
+ assert(changedtick_di->di_tv.v_type == VAR_NUMBER);
+ assert(changedtick_di->di_tv.v_lock == VAR_FIXED);
+ // For some reason formatc does not like the below.
+# ifndef UNIT_TESTING_LUA_PREPROCESSING
+ assert(changedtick_di->di_flags == (DI_FLAGS_RO|DI_FLAGS_FIX));
+# endif
+ assert(changedtick_di == (dictitem_T *)&buf->changedtick_di);
+#endif
+ buf->changedtick_di.di_tv.vval.v_number = changedtick;
+
+ if (tv_dict_is_watched(buf->b_vars)) {
+ tv_dict_watcher_notify(buf->b_vars,
+ (char *)buf->changedtick_di.di_key,
+ &buf->changedtick_di.di_tv,
+ &old_val);
+ }
+}