diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/buffer.c | 3 | ||||
-rw-r--r-- | src/nvim/buffer.c | 21 | ||||
-rw-r--r-- | src/nvim/buffer.h | 23 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/eval.c | 143 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 2 | ||||
-rw-r--r-- | src/nvim/main.c | 4 | ||||
-rw-r--r-- | src/nvim/memline.c | 4 | ||||
-rw-r--r-- | src/nvim/misc1.c | 5 |
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); } /* |