Patch 8.2.4866
Problem: Duplicate code in "get" functions.
Solution: Use get_var_from() for getwinvar(), gettabvar(), gettabwinvar()
and getbufvar(). (closes #10335)
Files: src/evalvars.c
*** ../vim-8.2.4865/src/evalvars.c 2022-04-28 16:51:37.508460219 +0100
--- src/evalvars.c 2022-05-04 18:11:04.469394932 +0100
***************
*** 4036,4083 ****
}
/*
! * getwinvar() and gettabwinvar()
*/
static void
! getwinvar(
! typval_T *argvars,
typval_T *rettv,
! int off) // 1 for gettabwinvar()
{
- win_T *win;
- char_u *varname;
dictitem_T *v;
- tabpage_T *tp = NULL;
int done = FALSE;
switchwin_T switchwin;
int need_switch_win;
- if (off == 1)
- tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
- else
- tp = curtab;
- win = find_win_by_nr(&argvars[off], tp);
- varname = tv_get_string_chk(&argvars[off + 1]);
++emsg_off;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
! if (win != NULL && varname != NULL)
{
// Set curwin to be our win, temporarily. Also set the tabpage,
// otherwise the window is not valid. Only do this when needed,
// autocommands get blocked.
! need_switch_win = !(tp == curtab && win == curwin);
! if (!need_switch_win
! || switch_win(&switchwin, win, tp, TRUE) == OK)
{
! if (*varname == '&')
{
if (varname[1] == NUL)
{
// get all window-local options in a dict
! dict_T *opts = get_winbuf_options(FALSE);
if (opts != NULL)
{
--- 4036,4088 ----
}
/*
! * Implements the logic to retrieve local variable and option values.
! * Used by "getwinvar()" "gettabvar()" "gettabwinvar()" "getbufvar()".
*/
static void
! get_var_from(
! char_u *varname,
typval_T *rettv,
! typval_T *deftv, // Default value if not found.
! int htname, // 't'ab, 'w'indow or 'b'uffer local.
! tabpage_T *tp, // can be NULL
! win_T *win,
! buf_T *buf) // Ignored if htname is not 'b'.
{
dictitem_T *v;
int done = FALSE;
switchwin_T switchwin;
int need_switch_win;
++emsg_off;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
! if (varname != NULL && tp != NULL && win != NULL
! && (htname != 'b' || buf != NULL))
{
// Set curwin to be our win, temporarily. Also set the tabpage,
// otherwise the window is not valid. Only do this when needed,
// autocommands get blocked.
! // If we have a buffer reference avoid the switching, we're saving and
! // restoring curbuf directly.
! need_switch_win = !(tp == curtab && win == curwin) || (buf != NULL);
! if (!need_switch_win || switch_win(&switchwin, win, tp, TRUE) == OK)
{
! // Handle options. There are no tab-local options.
! if (*varname == '&' && htname != 't')
{
+ buf_T *save_curbuf = curbuf;
+
+ // Change curbuf so the option is read from the correct buffer.
+ if (buf != NULL && htname == 'b')
+ curbuf = buf;
+
if (varname[1] == NUL)
{
// get all window-local options in a dict
! dict_T *opts = get_winbuf_options(htname == 'b');
if (opts != NULL)
{
***************
*** 4085,4100 ****
done = TRUE;
}
}
! else if (eval_option(&varname, rettv, 1) == OK)
! // window-local-option
done = TRUE;
}
else
{
// Look up the variable.
! // Let getwinvar({nr}, "") return the "w:" dictionary.
! v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
! varname, FALSE);
if (v != NULL)
{
copy_tv(&v->di_tv, rettv);
--- 4090,4126 ----
done = TRUE;
}
}
! else if (eval_option(&varname, rettv, TRUE) == OK)
! // Local option
done = TRUE;
+
+ curbuf = save_curbuf;
+ }
+ else if (*varname == NUL)
+ {
+ // Empty string: return a dict with all the local variables.
+ if (htname == 'b')
+ v = &buf->b_bufvar;
+ else if (htname == 'w')
+ v = &win->w_winvar;
+ else
+ v = &tp->tp_winvar;
+ copy_tv(&v->di_tv, rettv);
+ done = TRUE;
}
else
{
+ hashtab_T *ht;
+
+ if (htname == 'b')
+ ht = &buf->b_vars->dv_hashtab;
+ else if (htname == 'w')
+ ht = &win->w_vars->dv_hashtab;
+ else
+ ht = &tp->tp_vars->dv_hashtab;
+
// Look up the variable.
! v = find_var_in_ht(ht, htname, varname, FALSE);
if (v != NULL)
{
copy_tv(&v->di_tv, rettv);
***************
*** 4108,4121 ****
restore_win(&switchwin, TRUE);
}
! if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
! // use the default return value
! copy_tv(&argvars[off + 2], rettv);
--emsg_off;
}
/*
* Set option "varname" to the value of "varp" for the current buffer/window.
*/
static void
--- 4134,4170 ----
restore_win(&switchwin, TRUE);
}
! if (!done && deftv->v_type != VAR_UNKNOWN)
! // use the default value
! copy_tv(deftv, rettv);
--emsg_off;
}
/*
+ * getwinvar() and gettabwinvar()
+ */
+ static void
+ getwinvar(
+ typval_T *argvars,
+ typval_T *rettv,
+ int off) // 1 for gettabwinvar()
+ {
+ char_u *varname;
+ tabpage_T *tp;
+ win_T *win;
+
+ if (off == 1)
+ tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
+ else
+ tp = curtab;
+ win = find_win_by_nr(&argvars[off], tp);
+ varname = tv_get_string_chk(&argvars[off + 1]);
+
+ get_var_from(varname, rettv, &argvars[off + 2], 'w', tp, win, NULL);
+ }
+
+ /*
* Set option "varname" to the value of "varp" for the current buffer/window.
*/
static void
***************
*** 4444,4457 ****
void
f_gettabvar(typval_T *argvars, typval_T *rettv)
{
- switchwin_T switchwin;
- tabpage_T *tp;
- dictitem_T *v;
char_u *varname;
! int done = FALSE;
!
! rettv->v_type = VAR_STRING;
! rettv->vval.v_string = NULL;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
--- 4493,4501 ----
void
f_gettabvar(typval_T *argvars, typval_T *rettv)
{
char_u *varname;
! tabpage_T *tp;
! win_T *win = NULL;
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
***************
*** 4460,4489 ****
varname = tv_get_string_chk(&argvars[1]);
tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
! if (tp != NULL && varname != NULL)
! {
! // Set tp to be our tabpage, temporarily. Also set the window to the
! // first window in the tabpage, otherwise the window is not valid.
! if (switch_win(&switchwin,
! tp == curtab || tp->tp_firstwin == NULL ? firstwin
! : tp->tp_firstwin, tp, TRUE) == OK)
! {
! // look up the variable
! // Let gettabvar({nr}, "") return the "t:" dictionary.
! v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
! if (v != NULL)
! {
! copy_tv(&v->di_tv, rettv);
! done = TRUE;
! }
! }
! // restore previous notion of curwin
! restore_win(&switchwin, TRUE);
! }
!
! if (!done && argvars[2].v_type != VAR_UNKNOWN)
! copy_tv(&argvars[2], rettv);
}
/*
--- 4504,4514 ----
varname = tv_get_string_chk(&argvars[1]);
tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
! if (tp != NULL)
! win = tp == curtab || tp->tp_firstwin == NULL ? firstwin
! : tp->tp_firstwin;
! get_var_from(varname, rettv, &argvars[2], 't', tp, win, NULL);
}
/*
***************
*** 4521,4530 ****
void
f_getbufvar(typval_T *argvars, typval_T *rettv)
{
- buf_T *buf;
char_u *varname;
! dictitem_T *v;
! int done = FALSE;
if (in_vim9script()
&& (check_for_buffer_arg(argvars, 0) == FAIL
--- 4546,4553 ----
void
f_getbufvar(typval_T *argvars, typval_T *rettv)
{
char_u *varname;
! buf_T *buf;
if (in_vim9script()
&& (check_for_buffer_arg(argvars, 0) == FAIL
***************
*** 4534,4589 ****
varname = tv_get_string_chk(&argvars[1]);
buf = tv_get_buf_from_arg(&argvars[0]);
! rettv->v_type = VAR_STRING;
! rettv->vval.v_string = NULL;
!
! if (buf != NULL && varname != NULL)
! {
! if (*varname == '&')
! {
! buf_T *save_curbuf = curbuf;
!
! // set curbuf to be our buf, temporarily
! curbuf = buf;
!
! if (varname[1] == NUL)
! {
! // get all buffer-local options in a dict
! dict_T *opts = get_winbuf_options(TRUE);
!
! if (opts != NULL)
! {
! rettv_dict_set(rettv, opts);
! done = TRUE;
! }
! }
! else if (eval_option(&varname, rettv, TRUE) == OK)
! // buffer-local-option
! done = TRUE;
!
! // restore previous notion of curbuf
! curbuf = save_curbuf;
! }
! else
! {
! // Look up the variable.
! if (*varname == NUL)
! // Let getbufvar({nr}, "") return the "b:" dictionary.
! v = &buf->b_bufvar;
! else
! v = find_var_in_ht(&buf->b_vars->dv_hashtab, 'b',
! varname, FALSE);
! if (v != NULL)
! {
! copy_tv(&v->di_tv, rettv);
! done = TRUE;
! }
! }
! }
!
! if (!done && argvars[2].v_type != VAR_UNKNOWN)
! // use the default value
! copy_tv(&argvars[2], rettv);
}
/*
--- 4557,4563 ----
varname = tv_get_string_chk(&argvars[1]);
buf = tv_get_buf_from_arg(&argvars[0]);
! get_var_from(varname, rettv, &argvars[2], 'b', curtab, curwin, buf);
}
/*
*** ../vim-8.2.4865/src/version.c 2022-05-04 17:51:38.374012790 +0100
--- src/version.c 2022-05-04 18:12:39.497343337 +0100
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 4866,
/**/
--
From "know your smileys":
:.-( Crying
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///