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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220504171320.CEA181C19BB%40moolenaar.net.

Raspunde prin e-mail lui