//+-------------------------------------------------------------------------
//
//  Microsoft Windows
//
//  Copyright (C) Microsoft Corporation, 1997 - 1999
//
//  File:       options.h
//
//--------------------------------------------------------------------------

#ifndef _INC_CSCUI_OPTIONS_H
#define _INC_CSCUI_OPTIONS_H
///////////////////////////////////////////////////////////////////////////////
/*  File: options.h

    Description: 
            

    Revision History:

    Date        Description                                          Programmer
    --------    ---------------------------------------------------  ----------
    04/15/98    Initial creation.                                    BrianAu
*/
///////////////////////////////////////////////////////////////////////////////
#ifndef _WINDOWS_
#   include <windows.h>
#endif

#ifndef _INC_CSCVIEW_CONFIG_H
#   include "config.h"
#endif

#ifndef _INC_CSCUI_UIHELP_H
#   include "uihelp.h"
#endif

#ifndef _INC_MATH
#   include <math.h>
#endif

#ifndef _INC_CSCUI_PURGE_H
#   include "purge.h"
#endif

#include "resource.h"

//
// The "Advanced" dialog invoked from the "Advanced" button on the 
// "Offline Files" prop page.
//
class CAdvOptDlg
{
    public:
        enum 
        {
            //
            // Listview subitem IDs.
            // 
            iLVSUBITEM_SERVER = 0,
            iLVSUBITEM_ACTION = 1
        };

        CAdvOptDlg(HINSTANCE hInstance, 
                   HWND hwndParent)
            : m_hInstance(hInstance),
              m_hwndParent(hwndParent),
              m_hwndDlg(NULL),
              m_hwndLV(NULL),
              m_iLastColSorted(-1),
              m_bSortAscending(true),
              m_bNoConfigGoOfflineAction(false) { }

        int Run(void);

    protected:
        BOOL OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lInitParam);
        BOOL OnNotify(HWND hDlg, int idCtl, LPNMHDR pnmhdr);
        BOOL OnCommand(HWND hDlg, WORD wNotifyCode, WORD wID, HWND hwndCtl);
        BOOL OnDestroy(HWND hDlg);
        BOOL OnContextMenu(WPARAM wParam, LPARAM lParam);
        BOOL OnHelp(HWND hDlg, LPHELPINFO pHelpInfo);

    private:
        //
        // Structure to associate a radio button with an offline action code.
        //
        struct CtlActions
        {
            UINT                    idRbn;
            CConfig::OfflineAction action;
        };

        //
        // Class to describe the state of controls in the dialog.  Used to 
        // determine if user has changed anything.
        //
        class PgState
        {
            public:
                PgState(void)
                    : m_DefaultGoOfflineAction(CConfig::eGoOfflineSilent),
                      m_hdpaCustomGoOfflineActions(DPA_Create(4)) { }

                ~PgState(void);

                void SetDefGoOfflineAction(CConfig::OfflineAction action)
                    { m_DefaultGoOfflineAction = action; }

                CConfig::OfflineAction GetDefGoOfflineAction(void) const
                    { return m_DefaultGoOfflineAction; }

                void SetCustomGoOfflineActions(HWND hwndLV);

                HDPA GetCustomGoOfflineActions(void) const
                    { return m_hdpaCustomGoOfflineActions; }

                bool operator == (const PgState& rhs) const;

                bool operator != (const PgState& rhs) const
                    { return !(*this == rhs); }

            private:
                CConfig::OfflineAction  m_DefaultGoOfflineAction;
                HDPA                    m_hdpaCustomGoOfflineActions;
        };

        HINSTANCE    m_hInstance;
        HWND         m_hwndParent;
        HWND         m_hwndDlg;
        HWND         m_hwndLV;
        int          m_iLastColSorted;
        PgState      m_state;         // State on creation.
        bool         m_bSortAscending;
        bool         m_bNoConfigGoOfflineAction;

        static const CtlActions m_rgCtlActions[CConfig::eNumOfflineActions];
        static const DWORD m_rgHelpIDs[];

        static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
        void ApplySettings(void);
        void EnableCtls(HWND hwnd);
        void CreateListColumns(HWND hwndList);
        void OnLVN_GetDispInfo(LV_DISPINFO *plvdi);
        void OnLVN_ColumnClick(NM_LISTVIEW *pnmlv);
        void OnLVN_ItemChanged(NM_LISTVIEW *pnmlv);
        void OnLVN_KeyDown(NMLVKEYDOWN *plvkd);
        void OnContextMenuItemSelected(int idMenuItem);
        static int CALLBACK CompareLVItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
        void GetPageState(PgState *pps);
        CConfig::OfflineAction GetCurrentGoOfflineAction(void) const;
        void AddCustomGoOfflineAction(LPCTSTR pszServer, CConfig::OfflineAction action);
        void ReplaceCustomGoOfflineAction(CConfig::CustomGOA *pGOA, int iItem, CConfig::OfflineAction action);
        void OnAddCustomGoOfflineAction(void);
        void OnEditCustomGoOfflineAction(void);
        void OnDeleteCustomGoOfflineAction(void);
        int CountSelectedListviewItems(int *pcSetByPolicy);
        void DeleteSelectedListviewItems(void);
        void SetSelectedListviewItemsAction(CConfig::OfflineAction action);
        void FocusOnSomethingInListview(void);
        int GetFirstSelectedLVItemRect(RECT *prc);
        bool IsCustomActionListviewEnabled(void) const
            { return boolify(IsWindowEnabled(GetDlgItem(m_hwndDlg, IDC_GRP_CUSTGOOFFLINE))); }
        static DWORD CheckNetServer(LPCTSTR pszServer);
        static int AddGOAToListView(HWND hwndLV, int iItem, const CConfig::CustomGOA& goa);
        static CConfig::CustomGOA *FindGOAInListView(HWND hwndLV, LPCTSTR pszServer, int *piItem);
        static CConfig::CustomGOA *GetListviewObject(HWND hwndLV, int iItem);

        //
        // PgState calls GetListviewObject.
        //
        friend void PgState::SetCustomGoOfflineActions(HWND);
};

//
// The "Offline Files" property sheet page.
//
class COfflineFilesPage
{
    public:
        COfflineFilesPage(HINSTANCE hInstance, LPUNKNOWN pUnkOuter)
            : m_hInstance(hInstance),
              m_hwndDlg(NULL),
              m_pUnkOuter(pUnkOuter),
              m_hwndSlider(NULL),
              m_hwndEncryptTooltip(NULL),
              m_pfnOldPropSheetWndProc(NULL),
              m_pfnOldEncryptionTooltipWndProc(NULL),
              m_bUserHasMachineAccess(false),
              m_bCscVolSupportsEncryption(false),
              m_bApplyingSettings(false),
              m_bFirstActivate(true),
              m_iSliderMax(0),
              m_llAvailableDiskSpace(0) { }

        UINT GetDlgTemplateID(void) const
            { return IDD_CSC_OPTIONS; }

        LPFNPSPCALLBACK GetCallbackFuncPtr(void) const
            { return PageCallback; }

        DLGPROC GetDlgProcPtr(void) const
            { return DlgProc; }

        //
        // This is called by the "Advanced" page to determine if controls can
        // be enabled or not.
        //
        bool IsCscEnabledChecked(void) const
            { return m_hwndDlg && BST_CHECKED == IsDlgButtonChecked(m_hwndDlg, IDC_CBX_ENABLE_CSC); }

    protected:
        BOOL OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lInitParam);
        BOOL OnNotify(HWND hDlg, int idCtl, LPNMHDR pnmhdr);
        BOOL OnCommand(HWND hDlg, WORD wNotifyCode, WORD wID, HWND hwndCtl);
        BOOL OnDestroy(HWND hDlg);
        BOOL OnContextMenu(HWND hwndItem, int xPos, int yPos);
        BOOL ApplySettings(HWND hDlg, bool bPropSheetClosing);
        BOOL OnHelp(HWND hDlg, LPHELPINFO pHelpInfo);
        BOOL OnSettingChange(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);

    private:
        class PgState
        {
            public:
                PgState(void)
                    : m_bCscEnabled(false),
                      m_bFullSyncAtLogoff(false),
                      m_bFullSyncAtLogon(false),
                      m_bLinkOnDesktop(false),
                      m_bReminders(false),
                      m_iEncrypted(BST_UNCHECKED),
                      m_iReminderFreq(0),
                      m_iSliderPos(0) { }

                void SetCscEnabled(bool bCscEnabled)
                    { m_bCscEnabled = bCscEnabled; }

                bool GetCscEnabled(void) const
                    { return m_bCscEnabled; }

                void SetFullSyncAtLogon(bool bFullSync)
                    { m_bFullSyncAtLogon = bFullSync; }

                bool GetFullSyncAtLogon(void) const
                    { return m_bFullSyncAtLogon; }

                void SetFullSyncAtLogoff(bool bFullSync)
                    { m_bFullSyncAtLogoff = bFullSync; }

                bool GetFullSyncAtLogoff(void) const
                    { return m_bFullSyncAtLogoff; }

                void SetEncrypted(int iEncrypted)
                    { m_iEncrypted = iEncrypted; }

                int GetEncrypted(void) const
                    { return m_iEncrypted; }

                void SetSliderPos(int iSliderPos)
                    { m_iSliderPos = iSliderPos; }

                int GetSliderPos(void) const
                    { return m_iSliderPos; }

                void SetRemindersEnabled(bool bEnabled)
                    { m_bReminders = bEnabled; }

                bool GetRemindersEnabled(void) const
                    { return m_bReminders; }

                void SetReminderFreq(int iMinutes)
                    { m_iReminderFreq = iMinutes; }

                int GetReminderFreq(void) const
                    { return m_iReminderFreq; }

                void SetLinkOnDesktop(bool bEnabled)
                    { m_bLinkOnDesktop = bEnabled; }

                bool GetLinkOnDesktop(void) const
                    { return m_bLinkOnDesktop; }

                bool operator == (const PgState& rhs) const
                    { return (m_bCscEnabled       == rhs.m_bCscEnabled &&
                              m_bFullSyncAtLogoff == rhs.m_bFullSyncAtLogoff &&
                              m_bFullSyncAtLogon  == rhs.m_bFullSyncAtLogon &&
                              m_bLinkOnDesktop    == rhs.m_bLinkOnDesktop && 
                              m_iEncrypted        == rhs.m_iEncrypted &&
                              m_iSliderPos        == rhs.m_iSliderPos &&
                              m_bReminders        == rhs.m_bReminders &&
                              m_iReminderFreq     == rhs.m_iReminderFreq); }

                bool operator != (const PgState& rhs) const
                    { return !(*this == rhs); }

            private:
                bool m_bCscEnabled;
                bool m_bFullSyncAtLogon;
                bool m_bFullSyncAtLogoff;
                bool m_bLinkOnDesktop;
                bool m_bReminders;
                int  m_iEncrypted;  // BST_CHECKED, BST_UNCHECKED, BST_INDETERMINATE
                int  m_iSliderPos;
                int  m_iReminderFreq;
        };

        class CConfigItems
        {
            public:
                CConfigItems(void) { ZeroMemory(m_rgItems, sizeof(m_rgItems)); }

                void Load(void);

                CConfig::SyncAction SyncAtLogoff(void) const
                    { return CConfig::SyncAction(m_rgItems[iCFG_SYNCATLOGOFF].dwValue); }
                CConfig::SyncAction SyncAtLogon(void) const
                    { return CConfig::SyncAction(m_rgItems[iCFG_SYNCATLOGON].dwValue); }
                bool NoConfigCache(void) const
                    { return boolify(m_rgItems[iCFG_NOCONFIGCACHE].dwValue); }
                bool NoConfigSyncAtLogoff(void) const
                    { return m_rgItems[iCFG_SYNCATLOGOFF].bSetByPolicy; }
                bool NoConfigSyncAtLogon(void) const
                    { return m_rgItems[iCFG_SYNCATLOGON].bSetByPolicy; }
                bool NoReminders(void) const
                    { return boolify(m_rgItems[iCFG_NOREMINDERS].dwValue); }
                bool NoConfigReminders(void) const
                    { return m_rgItems[iCFG_NOREMINDERS].bSetByPolicy; }
                bool NoConfigCacheSize(void) const
                    { return m_rgItems[iCFG_DEFCACHESIZE].bSetByPolicy; }
                bool NoCacheViewer(void) const
                    { return boolify(m_rgItems[iCFG_NOCACHEVIEWER].dwValue); }
                bool NoConfigCscEnabled(void) const
                    { return boolify(m_rgItems[iCFG_CSCENABLED].bSetByPolicy); }
                bool NoConfigReminderFreqMinutes(void) const
                    { return boolify(m_rgItems[iCFG_REMINDERFREQMINUTES].bSetByPolicy); }
                int ReminderFreqMinutes(void) const
                    { return int(m_rgItems[iCFG_REMINDERFREQMINUTES].dwValue); }
                bool EncryptCache(void) const
                    { return boolify(m_rgItems[iCFG_ENCRYPTCACHE].dwValue); }
                bool NoConfigEncryptCache(void) const
                    { return boolify(m_rgItems[iCFG_ENCRYPTCACHE].bSetByPolicy); }

            private:
                struct ConfigItem
                {
                    DWORD dwValue;
                    bool bSetByPolicy;
                };

                enum eConfigItems
                {
                    iCFG_NOCONFIGCACHE,
                    iCFG_SYNCATLOGOFF,
                    iCFG_SYNCATLOGON,
                    iCFG_NOREMINDERS,
                    iCFG_DEFCACHESIZE,
                    iCFG_NOCACHEVIEWER,
                    iCFG_CSCENABLED,
                    iCFG_REMINDERFREQMINUTES,
                    iCFG_ENCRYPTCACHE,
                    MAX_CONFIG_ITEMS
                };

                ConfigItem m_rgItems[MAX_CONFIG_ITEMS];
        };


        HINSTANCE    m_hInstance;
        HWND         m_hwndDlg;
        LPUNKNOWN    m_pUnkOuter;
        HWND         m_hwndSlider;
        HWND         m_hwndEncryptTooltip;
        int          m_iSliderMax;
        LONGLONG     m_llAvailableDiskSpace;
        PgState      m_state;
        CConfigItems m_config;
        TCHAR        m_szEncryptTooltipBody[MAX_PATH];
        WNDPROC      m_pfnOldPropSheetWndProc;
        WNDPROC      m_pfnOldEncryptionTooltipWndProc;
        bool         m_bUserHasMachineAccess;
        bool         m_bCscVolSupportsEncryption;
        bool         m_bApplyingSettings;
        bool         m_bFirstActivate;
        static const DWORD m_rgHelpIDs[];

        static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
        static UINT CALLBACK PageCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
        static BOOL CALLBACK PurgeCacheCallback(CCachePurger *pPurger);
        static DWORD CALLBACK EncryptDecryptCallback(LPCWSTR lpszName, DWORD dwStatus, DWORD dwHintFlags,
                                                     DWORD dwPinCount, WIN32_FIND_DATAW *pFind32, DWORD dwReason,
                                                     DWORD dwParam1, DWORD dwParam2, DWORD_PTR dwContext);
        static LRESULT CALLBACK PropSheetSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
        static LRESULT CALLBACK EncryptionTooltipSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

        void OnDeleteCache(void);
        void OnFormatCache(void);
        void EnableCtls(HWND hwnd);
        void InitSlider(HWND hwndDlg, LONGLONG llMaxDiskSpace, LONGLONG llUsedDiskSpace);
        void OnHScroll(HWND hwndDlg, HWND hwndCtl, int iCode, int iPos);
        void SetCacheSizeDisplay(HWND hwndCtl, int iThumbPos);
        void EncryptOrDecryptCache(bool bEncrypt, bool bPropSheetClosing);
        void CreateEncryptionTooltip(void);
        void ShowEncryptionTooltip(bool bEncrypted);
        void HideEncryptionTooltip(void);
        void TrackEncryptionTooltip(void);
        void UpdateEncryptionCheckbox(void);
        void UpdateEncryptionTooltipBalloon(void);
        void UpdateEncryptionCheckboxOrBalloon(bool bCheckbox);
        void OnTTN_GetDispInfo(LPNMTTDISPINFO pttdi);
        double Fx(double x);
        double Fy(double y);
        double Rx(double x);
        LONGLONG DiskSpaceAtThumb(int t);
        int ThumbAtPctDiskSpace(double pct);
        void GetPageState(PgState *pps);
        void HandlePageStateChange(void);
        bool IsLinkOnDesktop(LPTSTR pszPathOut = NULL, UINT cchPathOut = 0);
        bool EnableOrDisableCsc(bool bEnable, bool *pbReboot, DWORD *pdwError);
        bool DisableForTerminalServer(void);
        HRESULT _ApplyEnabledSetting(RegKey& keyLM, RegKey& keyCU, const PgState& pgstNow, bool *pbUpdateSysTrayUI);
        HRESULT _ApplySyncAtLogoffSetting(RegKey& keyLM, RegKey& keyCU, const PgState& pgstNow);
        HRESULT _ApplySyncAtLogonSetting(RegKey& keyLM, RegKey& keyCU, const PgState& pgstNow);
        HRESULT _ApplyReminderSettings(RegKey& keyLM, RegKey& keyCU, const PgState& pgstNow);
        HRESULT _ApplyFolderLinkSetting(RegKey& keyLM, RegKey& keyCU, const PgState& pgstNow);
        HRESULT _ApplyCacheSizeSetting(RegKey& keyLM, RegKey& keyCU, const PgState& pgstNow);
        HRESULT _ApplyEncryptionSetting(RegKey& keyLM, RegKey& keyCU, const PgState& pgstNow, bool bPropSheetClosing, bool *pbPerformed);
};


class COfflineFilesSheet
{
    public:
        static DWORD CreateAndRun(HINSTANCE hInstance,
                                  HWND hwndParent,
                                  LONG *pDllRefCount,
                                  BOOL bAsync=TRUE);

    private:
        //
        // Increase this if more pages are required.
        // Currently, we only need the "Offline Files" page.
        //
        enum { MAXPAGES = 1 };

        HINSTANCE m_hInstance;
        HWND      m_hwndParent;
        LONG     *m_pDllRefCount;

        //
        // Trivial class for passing parameters to share dialog thread proc.
        //
        class ThreadParams
        {
            public:
                ThreadParams(HWND hwndParent, LONG *pDllRefCount)
                    : m_hwndParent(hwndParent),
                      m_hInstance(NULL),
                      m_pDllRefCount(pDllRefCount) { }
    
                HWND      m_hwndParent;
                HINSTANCE m_hInstance;
                LONG     *m_pDllRefCount;
  
                void SetModuleHandle(HINSTANCE hInstance)
                    { m_hInstance = hInstance; }
        };

        COfflineFilesSheet(HINSTANCE hInstance,
                           LONG *pDllRefCount,
                           HWND hwndParent);

        ~COfflineFilesSheet(void);

        DWORD Run(void);
        static UINT WINAPI ThreadProc(LPVOID pvParam);
        static BOOL CALLBACK AddPropSheetPage(HPROPSHEETPAGE hpage, LPARAM lParam);
};


class CscOptPropSheetExt : public IShellExtInit, IShellPropSheetExt
{
    public:
        CscOptPropSheetExt(HINSTANCE hInstance, LONG *pDllRefCnt);
        ~CscOptPropSheetExt(void);

        //
        // IUnknown
        //
        STDMETHODIMP         QueryInterface(REFIID, void **);
        STDMETHODIMP_(ULONG) AddRef(void);
        STDMETHODIMP_(ULONG) Release(void);
        //
        // IShellExtInit method
        //
        STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);
        //
        // IShellPropSheetExt
        //
        STDMETHODIMP AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam);
        STDMETHODIMP ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
            { return E_NOTIMPL; }

        //
        // Change this if you add or remove any prop pages from this prop sheet ext.
        //
        enum { NUMPAGES = 2 };

    private:
        LONG               m_cRef;
        HINSTANCE          m_hInstance;
        LONG              *m_pDllRefCnt;
        COfflineFilesPage *m_pOfflineFoldersPg;

        HRESULT AddPage(LPFNADDPROPSHEETPAGE lpfnAddPage, 
                        LPARAM lParam, 
                        const COfflineFilesPage& pg,
                        HPROPSHEETPAGE *phPage);
};


class CustomGOAAddDlg
{
    public:
        CustomGOAAddDlg(HINSTANCE hInstance, 
                        HWND hwndParent, 
                        LPTSTR pszServer,
                        UINT cchServer,
                        CConfig::OfflineAction *pAction);
        int Run(void);

    private:
        //
        // Structure to associate a radio button with an offline action code.
        //
        struct CtlActions
        {
            UINT                   idRbn;
            CConfig::OfflineAction action;
        };
        HINSTANCE m_hInstance;
        HWND      m_hwndParent;
        HWND      m_hwndDlg;
        HWND      m_hwndEdit;
        LPTSTR    m_pszServer;  // Output.
        UINT      m_cchServer;
        CConfig::OfflineAction *m_pAction;
        static const CtlActions m_rgCtlActions[CConfig::eNumOfflineActions];
        static const DWORD m_rgHelpIDs[];

        static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
        BOOL OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lInitParam);
        BOOL OnCommand(HWND hDlg, WORD wNotifyCode, WORD wID, HWND hwndCtl);
        BOOL OnDestroy(HWND hDlg);
        BOOL OnHelp(HWND hDlg, LPHELPINFO pHelpInfo);
        BOOL OnContextMenu(HWND hwndItem, int xPos, int yPos);
        void BrowseForServer(HWND hDlg, LPTSTR pszServer, UINT cchServer);
        void GetActionInfo(LPTSTR pszServer, UINT cchServer, CConfig::OfflineAction *pAction);
        bool CheckServerNameEntered(void);
        void GetEnteredServerName(LPTSTR pszServer, UINT cchServer, bool bTrimLeadingJunk);
};

class CustomGOAEditDlg
{
    public:
        CustomGOAEditDlg(HINSTANCE hInstance, 
                         HWND hwndParent, 
                         LPCTSTR pszServer, 
                         CConfig::OfflineAction *pAction);
        int Run(void);

    private:
        //
        // Structure to associate a radio button with an offline action code.
        //
        struct CtlActions
        {
            UINT                   idRbn;
            CConfig::OfflineAction action;
        };
        HINSTANCE m_hInstance;
        HWND      m_hwndParent;
        HWND      m_hwndDlg;
        TCHAR     m_szServer[MAX_PATH];
        CConfig::OfflineAction *m_pAction;
        static const CtlActions m_rgCtlActions[CConfig::eNumOfflineActions];
        static const DWORD m_rgHelpIDs[];

        static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
        BOOL OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lInitParam);
        BOOL OnCommand(HWND hDlg, WORD wNotifyCode, WORD wID, HWND hwndCtl);
        BOOL OnDestroy(HWND hDlg);
        BOOL OnHelp(HWND hDlg, LPHELPINFO pHelpInfo);
        BOOL OnContextMenu(HWND hwndItem, int xPos, int yPos);
        void GetActionInfo(CConfig::OfflineAction *pAction);
};



//-----------------------------------------------------------------------------
// Inline functions.
//-----------------------------------------------------------------------------
//
// This is the "gain" function for the slider and resulting value.
// Pass in a true position of the slider thumb and you get back 
// a scaled value for the thumb.  To change the gain, change
// this function.  Remember to change Fy() also.
//
inline double
COfflineFilesPage::Fx(
    double x
    )
{
    return (x * x) / 2.0;
}


//
// This is the "gain" function for the slider solved for 'y'.
// Pass in a virtual position for the thumb and you get back
// a true thumb position.
//
inline double
COfflineFilesPage::Fy(
    double y
    )
{
    return sqrt(2.0 * y);
}

//
// Ratio used to calculate the disk space value for a given
// true thumb position.  Give it a true thumb position between
// 0 and 100 and it will return a number between 0.0 and 1.0 that
// can be used to find the disk space.
// 
// DiskSpace = DiskSpaceMax * Rx(thumb)
//
inline double
COfflineFilesPage::Rx(
    double x
    )
{
    double denominator = Fx(m_iSliderMax);
    if (0.00001 < denominator)
        return Fx(x) / denominator;
    else
        return 1.0;
}

//
// Calculates the disk space value at a particular position of the
// slider thumb for values of 't' between 0 and 100.
//
inline LONGLONG
COfflineFilesPage::DiskSpaceAtThumb(
    int t
    )
{
    return LONGLONG(double(m_llAvailableDiskSpace) * Rx(t));
}

//
// Calculates the true thumb position for a given disk space
// percent value between 0.0 and 1.0.
// The expression breaks down as follows:
// 
//      double MaxVirtualThumb = Fx(m_iSliderMax);
//      double VirtualThumb    = MaxVirtualThumb * pct;
//      double TrueThumb       = Fy(VirtualThumb);
//
//      return round(TrueThumb);  // "round" used for illustration only.
//
inline int
COfflineFilesPage::ThumbAtPctDiskSpace(
    double pct
    )
{
    double t  = Fy(Fx(m_iSliderMax) * pct);
    double ft = floor(t);
    if (0.5 < t - ft)
    {
        //
        // Since the thumb position must be a whole number,
        // round up if necessary.  Typecast from double to int
        // merely truncates at the decimal point.
        //
        ft += 1.0;
    }
    return int(ft);
}


#endif // _INC_CSCUI_OPTIONS_H
