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)
		    {
			rettv_dict_set(rettv, opts);
			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);
		    done = TRUE;
		}
	    }
	}

	if (need_switch_win)
	    // restore previous notion of curwin
	    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;
}
getwinvar(
    typval_T	*argvars,
    typval_T	*rettv,
    int		off)	     
{
    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)
    {
	 
	 
	 
	need_switch_win = !(tp == curtab && win == curwin);
	if (!need_switch_win
		  || switch_win(&switchwin, win, tp, TRUE) == OK)
	{
	    if (*varname == '&')
	    {
		if (varname[1] == NUL)
		{
		     
		    dict_T	*opts = get_winbuf_options(FALSE);

		    if (opts != NULL)
		    {
			rettv_dict_set(rettv, opts);
			done = TRUE;
		    }
		}
		else if (eval_option(&varname, rettv, 1) == OK)
		     
		    done = TRUE;
	    }
	    else
	    {
		 
		 
		v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
							      varname, FALSE);
		if (v != NULL)
		{
		    copy_tv(&v->di_tv, rettv);
		    done = TRUE;
		}
	    }
	}

	if (need_switch_win)
	     
	    restore_win(&switchwin, TRUE);
    }

    if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
	 
	copy_tv(&argvars[off + 2], rettv);

    --emsg_off;
}