aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/buffer.c3
-rw-r--r--src/nvim/buffer.c21
-rw-r--r--src/nvim/buffer.h23
-rw-r--r--src/nvim/buffer_defs.h1
-rw-r--r--src/nvim/eval.c143
-rw-r--r--src/nvim/ex_cmds.c2
-rw-r--r--src/nvim/main.c4
-rw-r--r--src/nvim/memline.c4
-rw-r--r--src/nvim/misc1.c5
9 files changed, 101 insertions, 105 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index f286306a20..70246930bf 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -411,9 +411,6 @@ end:
/// Gets a buffer-scoped (b:) variable.
///
-/// @note Use nvim_buf_get_changedtick() for “variable” `b:changedtick`.
-/// This method only gets variables from b: dictionary.
-///
/// @param buffer The buffer handle
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index a471ebf06f..f2cd6adc9d 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -688,6 +688,7 @@ free_buffer_stuff (
}
vars_clear(&buf->b_vars->dv_hashtab); // free all internal variables
hash_init(&buf->b_vars->dv_hashtab);
+ buf_init_changedtick(buf);
uc_clear(&buf->b_ucmds); // clear local user commands
buf_delete_signs(buf); // delete any signs
bufhl_clear_all(buf); // delete any highligts
@@ -1436,6 +1437,25 @@ void do_autochdir(void)
static int top_file_num = 1; ///< highest file number
+/// Initialize b:changedtick and changedtick_val attribute
+///
+/// @param[out] buf Buffer to intialize for.
+static inline void buf_init_changedtick(buf_T *const buf)
+ FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
+{
+ dictitem_T *const changedtick_di = dictitem_alloc((char_u *)"changedtick");
+ // For some reason `islocked('b:changedtick')` should return 1. It does not
+ // do so for other read-only variables which are normally VAR_FIXED.
+ changedtick_di->di_flags |= DI_FLAGS_LOCK|DI_FLAGS_FIX;
+ changedtick_di->di_tv = (typval_T) {
+ .v_type = VAR_NUMBER,
+ .v_lock = VAR_FIXED,
+ .vval.v_number = buf->b_changedtick,
+ };
+ dict_add(buf->b_vars, changedtick_di);
+ buf->changedtick_val = &changedtick_di->di_tv.vval.v_number;
+}
+
/// Add a file name to the buffer list.
/// If the same file name already exists return a pointer to that buffer.
/// If it does not exist, or if fname == NULL, a new entry is created.
@@ -1530,6 +1550,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
// init b: variables
buf->b_vars = dict_alloc();
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
+ buf_init_changedtick(buf);
}
if (ffname != NULL) {
diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h
index 193c9f73d8..2633c1f9d8 100644
--- a/src/nvim/buffer.h
+++ b/src/nvim/buffer.h
@@ -5,6 +5,8 @@
#include "nvim/pos.h" // for linenr_T
#include "nvim/ex_cmds_defs.h" // for exarg_T
#include "nvim/screen.h" // for StlClickRecord
+#include "nvim/func_attr.h"
+#include "nvim/eval.h"
// Values for buflist_getfile()
enum getf_values {
@@ -79,6 +81,27 @@ static inline void restore_win_for_buf(win_T *save_curwin,
}
}
+static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
+ REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE;
+
+/// Set b_changedtick and corresponding variable
+///
+/// @param[out] buf Buffer to set changedtick in.
+/// @param[in] changedtick New value.
+static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
+{
+#ifndef NDEBUG
+ dictitem_T *const changedtick_di = dict_find(
+ buf->b_vars, (char_u *)"changedtick", sizeof("changedtick") - 1);
+ assert(changedtick_di != NULL);
+ assert(changedtick_di->di_tv.v_type == VAR_NUMBER);
+ assert(changedtick_di->di_tv.v_lock == VAR_FIXED);
+ assert(&changedtick_di->di_tv.vval.v_number == buf->changedtick_val);
+ assert(*buf->changedtick_val == (varnumber_T)buf->b_changedtick);
+#endif
+ *buf->changedtick_val = buf->b_changedtick = changedtick;
+}
+
#define WITH_BUFFER(b, code) \
do { \
win_T *save_curwin = NULL; \
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 9c5c7859ff..514ef5a437 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -500,6 +500,7 @@ struct file_buffer {
int b_changed; // 'modified': Set to true if something in the
// file has been changed and not written out.
int b_changedtick; // incremented for each change, also for undo
+ varnumber_T *changedtick_val; // Pointer to the changedtick storage inside b:
bool b_saving; /* Set to true if we are in the middle of
saving the buffer. */
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 57c2368523..4194f5fd7c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -1645,13 +1645,7 @@ static void list_glob_vars(int *first)
*/
static void list_buf_vars(int *first)
{
- char numbuf[NUMBUFLEN];
-
list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", true, first);
-
- snprintf(numbuf, sizeof(numbuf), "%d", curbuf->b_changedtick);
- list_one_var_a("b:", "changedtick", sizeof("changedtick") - 1, VAR_NUMBER,
- numbuf, first);
}
/*
@@ -1949,18 +1943,6 @@ ex_let_one (
}
/*
- * If "arg" is equal to "b:changedtick" give an error and return TRUE.
- */
-static int check_changedtick(char_u *arg)
-{
- if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13])) {
- EMSG2(_(e_readonlyvar), arg);
- return TRUE;
- }
- return FALSE;
-}
-
-/*
* Get an lval: variable, Dict item or List item that can be assigned a value
* to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
* "name.key", "name.key[expr]" etc.
@@ -2298,28 +2280,27 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch
dictitem_T *di;
if (lp->ll_tv == NULL) {
- if (!check_changedtick(lp->ll_name)) {
- cc = *endp;
- *endp = NUL;
- if (op != NULL && *op != '=') {
- typval_T tv;
-
- // handle +=, -= and .=
- di = NULL;
- if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name),
- &tv, &di, true, false) == OK) {
- if ((di == NULL
- || (!var_check_ro(di->di_flags, lp->ll_name, false)
- && !tv_check_lock(di->di_tv.v_lock, lp->ll_name, false)))
- && tv_op(&tv, rettv, op) == OK) {
- set_var(lp->ll_name, &tv, false);
- }
- clear_tv(&tv);
+ cc = *endp;
+ *endp = NUL;
+ if (op != NULL && *op != '=') {
+ typval_T tv;
+
+ // handle +=, -= and .=
+ di = NULL;
+ if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name),
+ &tv, &di, true, false) == OK) {
+ if ((di == NULL
+ || (!var_check_ro(di->di_flags, lp->ll_name, false)
+ && !tv_check_lock(di->di_tv.v_lock, lp->ll_name, false)))
+ && tv_op(&tv, rettv, op) == OK) {
+ set_var(lp->ll_name, &tv, false);
}
- } else
- set_var(lp->ll_name, rettv, copy);
- *endp = cc;
+ clear_tv(&tv);
+ }
+ } else {
+ set_var(lp->ll_name, rettv, copy);
}
+ *endp = cc;
} else if (tv_check_lock(lp->ll_newkey == NULL
? lp->ll_tv->v_lock
: lp->ll_tv->vval.v_dict->dv_lock,
@@ -2937,11 +2918,10 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit)
cc = *name_end;
*name_end = NUL;
- /* Normal name or expanded name. */
- if (check_changedtick(lp->ll_name))
- ret = FAIL;
- else if (do_unlet(lp->ll_name, forceit) == FAIL)
+ // Normal name or expanded name.
+ if (do_unlet(lp->ll_name, forceit) == FAIL) {
ret = FAIL;
+ }
*name_end = cc;
} else if ((lp->ll_list != NULL
&& tv_check_lock(lp->ll_list->lv_lock, lp->ll_name, false))
@@ -3088,20 +3068,16 @@ static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock)
*name_end = NUL;
// Normal name or expanded name.
- if (check_changedtick(lp->ll_name)) {
+ di = find_var((const char *)lp->ll_name, STRLEN(lp->ll_name), NULL, true);
+ if (di == NULL) {
ret = FAIL;
} else {
- di = find_var((const char *)lp->ll_name, STRLEN(lp->ll_name), NULL, true);
- if (di == NULL) {
- ret = FAIL;
+ if (lock) {
+ di->di_flags |= DI_FLAGS_LOCK;
} else {
- if (lock) {
- di->di_flags |= DI_FLAGS_LOCK;
- } else {
- di->di_flags &= ~DI_FLAGS_LOCK;
- }
- item_lock(&di->di_tv, deep, lock);
+ di->di_flags &= ~DI_FLAGS_LOCK;
}
+ item_lock(&di->di_tv, deep, lock);
}
*name_end = cc;
} else if (lp->ll_range) {
@@ -3301,10 +3277,6 @@ char_u *get_user_var_name(expand_T *xp, int idx)
++hi;
return cat_prefix_varname('b', hi->hi_key);
}
- if (bdone == ht->ht_used) {
- ++bdone;
- return (char_u *)"b:changedtick";
- }
/* w: variables */
ht = &curwin->w_vars->dv_hashtab;
@@ -10523,10 +10495,6 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// buffer-local-option
done = true;
}
- } else if (STRCMP(varname, "changedtick") == 0) {
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = curbuf->b_changedtick;
- done = true;
} else {
// Look up the variable.
// Let getbufvar({nr}, "") return the "b:" dictionary.
@@ -12458,31 +12426,26 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
EMSG(_(e_trailing));
else {
if (lv.ll_tv == NULL) {
- if (check_changedtick(lv.ll_name)) {
- rettv->vval.v_number = 1; // Always locked.
- } else {
- di = find_var((const char *)lv.ll_name, STRLEN(lv.ll_name), NULL,
- true);
- if (di != NULL) {
- /* Consider a variable locked when:
- * 1. the variable itself is locked
- * 2. the value of the variable is locked.
- * 3. the List or Dict value is locked.
- */
- rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
- || tv_islocked(&di->di_tv));
- }
+ di = find_var((const char *)lv.ll_name, STRLEN(lv.ll_name), NULL, true);
+ if (di != NULL) {
+ // Consider a variable locked when:
+ // 1. the variable itself is locked
+ // 2. the value of the variable is locked.
+ // 3. the List or Dict value is locked.
+ rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
+ || tv_islocked(&di->di_tv));
}
- } else if (lv.ll_range)
+ } else if (lv.ll_range) {
EMSG(_("E786: Range not allowed"));
- else if (lv.ll_newkey != NULL)
+ } else if (lv.ll_newkey != NULL) {
EMSG2(_(e_dictkey), lv.ll_newkey);
- else if (lv.ll_list != NULL)
- /* List item. */
+ } else if (lv.ll_list != NULL) {
+ // List item.
rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
- else
- /* Dictionary item. */
+ } else {
+ // Dictionary item.
rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
+ }
}
}
@@ -19335,23 +19298,13 @@ static int get_var_tv(
{
int ret = OK;
typval_T *tv = NULL;
- typval_T atv;
dictitem_T *v;
- // Check for "b:changedtick".
- if (sizeof("b:changedtick") - 1 == len
- && STRNCMP(name, "b:changedtick", len) == 0) {
- atv.v_type = VAR_NUMBER;
- atv.vval.v_number = curbuf->b_changedtick;
- tv = &atv;
- } else {
- // Check for user-defined variables.
- v = find_var(name, (size_t)len, NULL, no_autoload);
- if (v != NULL) {
- tv = &v->di_tv;
- if (dip != NULL) {
- *dip = v;
- }
+ v = find_var(name, (size_t)len, NULL, no_autoload);
+ if (v != NULL) {
+ tv = &v->di_tv;
+ if (dip != NULL) {
+ *dip = v;
}
}
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index a03878dec2..a7ef11f168 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -6138,7 +6138,7 @@ void ex_substitute(exarg_T *eap)
// restore it so that undotree() is identical before/after the preview.
curbuf->b_u_newhead = save_b_u_newhead;
curbuf->b_u_time_cur = save_b_u_time_cur;
- curbuf->b_changedtick = save_changedtick;
+ buf_set_changedtick(curbuf, save_changedtick);
}
if (buf_valid(preview_buf)) {
// XXX: Must do this *after* u_undo_and_forget(), why?
diff --git a/src/nvim/main.c b/src/nvim/main.c
index fab968836c..f962a82a74 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -577,8 +577,8 @@ void getout(int exitval)
if (buf->b_changedtick != -1) {
apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname,
buf->b_fname, FALSE, buf);
- buf->b_changedtick = -1; /* note that we did it already */
- /* start all over, autocommands may mess up the lists */
+ buf_set_changedtick(buf, -1); // note that we did it already
+ // start all over, autocommands may mess up the lists
next_tp = first_tabpage;
break;
}
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 91dab16e27..b67f550358 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -1180,7 +1180,7 @@ void ml_recover(void)
* empty. Don't set the modified flag then. */
if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL)) {
changed_int();
- ++curbuf->b_changedtick;
+ buf_set_changedtick(curbuf, curbuf->b_changedtick + 1);
}
} else {
for (idx = 1; idx <= lnum; ++idx) {
@@ -1190,7 +1190,7 @@ void ml_recover(void)
xfree(p);
if (i != 0) {
changed_int();
- ++curbuf->b_changedtick;
+ buf_set_changedtick(curbuf, curbuf->b_changedtick + 1);
break;
}
}
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index db34159f24..36087ac59c 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -51,6 +51,7 @@
#include "nvim/os/input.h"
#include "nvim/os/time.h"
#include "nvim/event/stream.h"
+#include "nvim/buffer.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "misc1.c.generated.h"
@@ -1788,7 +1789,7 @@ void changed(void)
}
changed_int();
}
- ++curbuf->b_changedtick;
+ buf_set_changedtick(curbuf, curbuf->b_changedtick + 1);
}
/*
@@ -2147,7 +2148,7 @@ unchanged (
redraw_tabline = TRUE;
need_maketitle = TRUE; /* set window title later */
}
- ++buf->b_changedtick;
+ buf_set_changedtick(buf, buf->b_changedtick + 1);
}
/*