--- /dev/null
+/**
+ * @file CIniOptionsMgr.cpp
+ *
+ * @brief Implementation of Ini file Options management class.
+ *
+ */
+
+#include "pch.h"
+#include "CIniOptionsMgr.h"
+#include "OptionsMgr.h"
+#include <Windows.h>
+#include <codecvt>
+#include <filesystem>
+#include <string>
+#include <fstream>
+
+using std::filesystem::current_path;
+
+LPCWSTR CIniOptionsMgr::lpFilePath = NULL;
+
+LPCWSTR lpAppName = TEXT("WinMerge");
+LPCWSTR lpFileName = TEXT("\\winmerge.ini");
+
+CIniOptionsMgr::CIniOptionsMgr()
+{
+ InitializeCriticalSection(&m_cs);
+}
+
+CIniOptionsMgr::~CIniOptionsMgr()
+{
+ DeleteCriticalSection(&m_cs);
+ delete[] CIniOptionsMgr::lpFilePath;
+}
+
+/**
+ * @brief Checks wheter INI file exists.
+ * @return TRUE if INI file exist,
+ * FALSE otherwise.
+ */
+bool CIniOptionsMgr::CheckIfIniFileExist()
+{
+ std::ifstream f(GetFilePath());
+ return f.good();
+}
+
+/**
+ * @brief Get path to INI file.
+ * @return path to INI file
+ */
+LPCWSTR CIniOptionsMgr::GetFilePath()
+{
+ if (CIniOptionsMgr::lpFilePath == NULL)
+ {
+ // create path
+ std::filesystem::path p = current_path();
+ p += lpFileName;
+
+ // change type
+ std::wstring str = p.wstring();
+ size_t length = str.length() + 1;
+ wchar_t* strCp = new wchar_t[length];
+ wcscpy_s(strCp, length, str.c_str());
+
+ // set path
+ CIniOptionsMgr::lpFilePath = strCp;
+ }
+
+ return CIniOptionsMgr::lpFilePath;
+}
+
+int CIniOptionsMgr::InitOption(const String& name, const varprop::VariantValue& defaultValue)
+{
+ // Check type & bail if null
+ int valType = defaultValue.GetType();
+ if (valType == varprop::VT_NULL)
+ return COption::OPT_ERR;
+
+ // If we're not loading & saving options, bail
+ if (!m_serializing)
+ return AddOption(name, defaultValue);
+
+ EnterCriticalSection(&m_cs);
+
+ // check if value exist
+ String textValue = ReadValueFromFile(name);
+ bool found = textValue.size() != 0;
+
+ // Actually save value into our in-memory options table
+ int retVal = AddOption(name, defaultValue);
+
+ // Update registry if successfully saved to in-memory table
+ if (retVal == COption::OPT_OK)
+ {
+ if (found)
+ {
+ varprop::VariantValue value(defaultValue);
+ retVal = ParseValue(name, textValue, value);
+ if (retVal == COption::OPT_OK)
+ {
+ retVal = Set(name, value);
+ }
+ }
+ }
+
+ LeaveCriticalSection(&m_cs);
+ return retVal;
+}
+
+int CIniOptionsMgr::InitOption(const String& name, const String& defaultValue)
+{
+ varprop::VariantValue defValue;
+ defValue.SetString(defaultValue);
+ return InitOption(name, defValue);
+}
+
+int CIniOptionsMgr::InitOption(const String& name, const TCHAR* defaultValue)
+{
+ return InitOption(name, String(defaultValue));
+}
+
+int CIniOptionsMgr::InitOption(const String& name, int defaultValue, bool serializable)
+{
+ varprop::VariantValue defValue;
+ int retVal = COption::OPT_OK;
+
+ defValue.SetInt(defaultValue);
+ if (serializable)
+ retVal = InitOption(name, defValue);
+ else
+ AddOption(name, defValue);
+ return retVal;
+}
+
+int CIniOptionsMgr::InitOption(const String& name, bool defaultValue)
+{
+ varprop::VariantValue defValue;
+ defValue.SetBool(defaultValue);
+ return InitOption(name, defValue);
+}
+
+int CIniOptionsMgr::SaveOption(const String& name)
+{
+ if (!m_serializing) return COption::OPT_OK;
+
+ varprop::VariantValue value;
+ int retVal = COption::OPT_OK;
+
+ value = Get(name);
+ int valType = value.GetType();
+ if (valType == varprop::VT_NULL)
+ retVal = COption::OPT_NOTFOUND;
+
+ if (retVal == COption::OPT_OK)
+ {
+ if (valType == varprop::VT_STRING)
+ {
+ String strVal = value.GetString();
+ LPCWSTR text = strVal.c_str();
+ WritePrivateProfileString(lpAppName, name.c_str(), text, GetFilePath());
+ }
+ else if (valType == varprop::VT_INT)
+ {
+ DWORD dwordVal = value.GetInt();
+ String strVal = strutils::to_str(dwordVal);
+ LPCWSTR text = strVal.c_str();
+ WritePrivateProfileString(lpAppName, name.c_str(), text, GetFilePath());
+ }
+ else if (valType == varprop::VT_BOOL)
+ {
+ DWORD dwordVal = value.GetBool() ? 1 : 0;
+ String strVal = strutils::to_str(dwordVal);
+ LPCWSTR text = strVal.c_str();
+ WritePrivateProfileString(lpAppName, name.c_str(), text, GetFilePath());
+ }
+ else
+ {
+ retVal = COption::OPT_UNKNOWN_TYPE;
+ }
+ }
+ return retVal;
+}
+
+/**
+ * @brief Set new value for option and save option to file
+ */
+int CIniOptionsMgr::SaveOption(const String& name, const varprop::VariantValue& value)
+{
+ int retVal = Set(name, value);
+ if (retVal == COption::OPT_OK)
+ retVal = SaveOption(name);
+ return retVal;
+}
+
+/**
+ * @brief Set new string value for option and save option to file
+ */
+int CIniOptionsMgr::SaveOption(const String& name, const String& value)
+{
+ varprop::VariantValue val;
+ val.SetString(value);
+ int retVal = Set(name, val);
+ if (retVal == COption::OPT_OK)
+ retVal = SaveOption(name);
+ return retVal;
+}
+
+/**
+ * @brief Set new string value for option and save option to file
+ */
+int CIniOptionsMgr::SaveOption(const String& name, const TCHAR* value)
+{
+ return SaveOption(name, String(value));
+}
+
+int CIniOptionsMgr::SaveOption(const String& name, int value)
+{
+ varprop::VariantValue val;
+ val.SetInt(value);
+ int retVal = Set(name, val);
+ if (retVal == COption::OPT_OK)
+ retVal = SaveOption(name);
+ return retVal;
+}
+
+int CIniOptionsMgr::SaveOption(const String& name, bool value)
+{
+ varprop::VariantValue val;
+ val.SetBool(value);
+ int retVal = Set(name, val);
+ if (retVal == COption::OPT_OK)
+ retVal = SaveOption(name);
+ return retVal;
+}
+
+int CIniOptionsMgr::RemoveOption(const String& name)
+{
+ int retVal = COption::OPT_OK;
+
+ String strPath;
+ String strValueName;
+
+ SplitName(name, strPath, strValueName);
+
+ if (!strValueName.empty())
+ {
+ retVal = COptionsMgr::RemoveOption(name);
+ }
+ else
+ {
+ for (auto it = m_optionsMap.begin(); it != m_optionsMap.end(); )
+ {
+ if (it->first.find(strPath) == 0)
+ it = m_optionsMap.erase(it);
+ else
+ ++it;
+ }
+ retVal = COption::OPT_OK;
+ }
+
+ EnterCriticalSection(&m_cs);
+
+ WritePrivateProfileString(lpAppName, name.c_str(), NULL, GetFilePath());
+
+ LeaveCriticalSection(&m_cs);
+
+ return retVal;
+}
+
+int CIniOptionsMgr::ExportOptions(const String& filename, const bool bHexColor) const
+{
+ if (std::filesystem::copy_file(CIniOptionsMgr::GetFilePath(), filename))
+ {
+ return COption::OPT_OK;
+ }
+ else
+ {
+ return COption::OPT_ERR;
+ }
+}
+
+int CIniOptionsMgr::ImportOptions(const String& filename)
+{
+ if (std::filesystem::copy_file(filename, CIniOptionsMgr::GetFilePath()))
+ {
+ return COption::OPT_OK;
+ }
+ else
+ {
+ return COption::OPT_ERR;
+ }
+}
+
+String CIniOptionsMgr::ReadValueFromFile(const String& name)
+{
+ const int size = 100;
+ LPWSTR buffor = new TCHAR[size];
+ DWORD result = GetPrivateProfileString(lpAppName, name.c_str(), NULL, buffor, size, GetFilePath());
+ return buffor;
+}
+
+int CIniOptionsMgr::ParseValue(const String& strName, String& textValue, varprop::VariantValue& value)
+{
+ int valType = value.GetType();
+ int retVal = COption::OPT_OK;
+
+ if (valType == varprop::VT_STRING)
+ {
+ value.SetString(textValue);
+ retVal = Set(strName, value);
+ }
+ else if (valType == varprop::VT_INT)
+ {
+ value.SetInt(std::stoi(textValue));
+ retVal = Set(strName, value);
+ }
+ else if (valType == varprop::VT_BOOL)
+ {
+ value.SetBool(textValue[0] == '1' ? true : false);
+ retVal = Set(strName, value);
+ }
+ else
+ retVal = COption::OPT_WRONG_TYPE;
+
+ return retVal;
+}
+
+/**
+ * @brief Split option name to path (in registry) and
+ * valuename (in registry).
+ *
+ * Option names are given as "full path", e.g. "Settings/AutomaticRescan".
+ * This function splits that to path "Settings/" and valuename
+ * "AutomaticRescan".
+ * @param [in] strName Option name
+ * @param [out] srPath Path (key) in registry
+ * @param [out] strValue Value in registry
+ */
+void CIniOptionsMgr::SplitName(const String& strName, String& strPath,
+ String& strValue) const
+{
+ size_t pos = strName.rfind('/');
+ if (pos != String::npos)
+ {
+ size_t len = strName.length();
+ strValue = strName.substr(pos + 1, len - pos - 1); //Right(len - pos - 1);
+ strPath = strName.substr(0, pos); //Left(pos);
+ }
+ else
+ {
+ strValue = strName;
+ strPath.erase();
+ }
+}
\ No newline at end of file
// Author: Dean Grimm
// SPDX-License-Identifier: GPL-2.0-or-later
/////////////////////////////////////////////////////////////////////////////
-/**
+/**
* @file Merge.cpp
*
* @brief Defines the class behaviors for the application.
#include "OptionsMgr.h"
#include "OptionsInit.h"
#include "RegOptionsMgr.h"
+#include "CIniOptionsMgr.h"
#include "OpenDoc.h"
#include "OpenFrm.h"
#include "OpenView.h"
, m_mainThreadScripts(nullptr)
, m_nLastCompareResult(0)
, m_bNonInteractive(false)
-, m_pOptions(new CRegOptionsMgr())
+, m_pOptions(CreateOptionManager())
, m_pGlobalFileFilter(new FileFilterHelper())
, m_nActiveOperations(0)
, m_pLangDlg(new CLanguageSelect())
// Place all significant initialization in InitInstance
}
+/**
+ * @brief Chose which options manager should be initialized.
+ * @return IniOptionsMgr if initial config file exists,
+ * CRegOptionsMgr otherwise.
+ */
+COptionsMgr *CreateOptionManager()
+{
+ if (CIniOptionsMgr::CheckIfIniFileExist())
+ {
+ return new CIniOptionsMgr();
+ }
+ else
+ {
+ return new CRegOptionsMgr();
+ }
+}
+
CMergeApp::~CMergeApp()
{
strdiff::Close();
// Create exclusion mutex name
TCHAR szDesktopName[MAX_PATH] = _T("Win9xDesktop");
DWORD dwLengthNeeded;
- GetUserObjectInformation(GetThreadDesktop(GetCurrentThreadId()), UOI_NAME,
+ GetUserObjectInformation(GetThreadDesktop(GetCurrentThreadId()), UOI_NAME,
szDesktopName, sizeof(szDesktopName), &dwLengthNeeded);
TCHAR szMutexName[MAX_PATH + 40];
// Combine window class name and desktop name to form a unique mutex name.
* good place to do cleanups.
* @return Application's exit value (returned from WinMain()).
*/
-int CMergeApp::ExitInstance()
+int CMergeApp::ExitInstance()
{
charsets_cleanup();
// Create the message box dialog.
CMessageBoxDialog dlgMessage(pParentWnd, lpszPrompt, _T(""), nType | MB_RIGHT_ALIGN,
nIDPrompt);
-
+
if (m_pMainWnd->IsIconic())
m_pMainWnd->ShowWindow(SW_RESTORE);
return idle;
}
-BOOL CMergeApp::OnIdle(LONG lCount)
+BOOL CMergeApp::OnIdle(LONG lCount)
{
if (CWinApp::OnIdle(lCount))
return TRUE;
if (m_bNonInteractive && IsReallyIdle())
m_pMainWnd->PostMessage(WM_CLOSE, 0, 0);
- static_cast<CRegOptionsMgr *>(GetOptionsMgr())->CloseKeys();
+ if (typeid(*GetOptionsMgr()) == typeid(CRegOptionsMgr))
+ {
+ static_cast<CRegOptionsMgr*>(GetOptionsMgr())->CloseKeys();
+ }
return FALSE;
}
{
DWORD dwFlags[3] = {cmdInfo.m_dwLeftFlags, cmdInfo.m_dwRightFlags, FFILEOPEN_NONE};
bCompared = pMainFrame->DoFileOpen(&cmdInfo.m_Files,
- dwFlags, strDesc, cmdInfo.m_sReportFile, cmdInfo.m_bRecurse, nullptr,
+ dwFlags, strDesc, cmdInfo.m_sReportFile, cmdInfo.m_bRecurse, nullptr,
cmdInfo.m_sPreDiffer, infoUnpacker.get());
}
}
String path;
String filename;
String ext;
-
+
paths::SplitFilename(paths::GetLongPath(pszPath), &path, &filename, &ext);
// Determine backup folder
{
success = !!CopyFileW(TFile(pszPath).wpath().c_str(), TFile(bakPath).wpath().c_str(), FALSE);
}
-
+
if (!success)
{
String msg = strutils::format_string1(
if (bFileExists && bFileRO)
{
UINT userChoice = 0;
-
+
// Don't ask again if its already asked
if (bApplyToAll)
userChoice = IDYES;
CFile::SetStatus(strSavePath.c_str(), status);
nRetVal = IDYES;
break;
-
+
// Save to new filename (single) /skip this item (multiple)
case IDNO:
if (!bMultiFile)
return true;
}
-/**
+/**
* @brief Read project and perform comparison specified
* @param [in] sProject Full path to project file.
* @return `true` if loading project file and starting compare succeeded.
ProjectFile project;
if (!LoadProjectFile(sProject, project))
return false;
-
+
bool rtn = true;
for (auto& projItem : project.Items())
{
*/
void CMergeApp::AddToRecentProjectsMRU(LPCTSTR sPathName)
{
- // sPathName will be added to the top of the MRU list.
+ // sPathName will be added to the top of the MRU list.
// If sPathName already exists in the MRU list, it will be moved to the top
if (m_pRecentFileList != nullptr) {
m_pRecentFileList->Add(sPathName);