/////////////////////////////////////////////////////////////////////////////
-//
// WinMerge: An interactive diff/merge utility
// Copyright (C) 1997 Dean P. Grimm
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
+// SPDX-License-Identifier: GPL-2.0-or-later
/////////////////////////////////////////////////////////////////////////////
-
/**
* @file MergeCmdLineInfo.cpp
*
*
*/
-// ID line follows -- this is updated by SVN
-// $Id: MergeCmdLineInfo.cpp 6940 2009-08-01 17:29:01Z kimmov $
+#include "pch.h"
#include "MergeCmdLineInfo.h"
-#include <cstring>
-#include <algorithm>
#include "Constants.h"
#include "Paths.h"
#include "OptionsDef.h"
+#include "unicoder.h"
// MergeCmdLineInfo
* @param [out] flag Tells whether param is the name of a flag.
* @return Points to the remaining portion of the command line.
*/
-const TCHAR *MergeCmdLineInfo::EatParam(const TCHAR *p, String ¶m, bool *flag)
+const TCHAR *MergeCmdLineInfo::EatParam(const TCHAR *p, String ¶m, bool *flag /*= nullptr*/)
{
- if (p && *(p += _tcsspn(p, _T(" \t\r\n"))) == _T('\0'))
- p = 0;
+ if (p != nullptr && *(p += _tcsspn(p, _T(" \t\r\n"))) == _T('\0'))
+ p = nullptr;
const TCHAR *q = p;
- if (q)
+ if (q != nullptr)
{
TCHAR c = *q;
bool quoted = false;
else
{
*flag = false;
- flag = 0;
+ flag = nullptr;
}
}
param.assign(p ? p : _T(""), q - p);
- if (q > p && flag)
+ if (q > p && flag != nullptr)
{
- param = string_makelower(param);
+ param = strutils::makelower(param);
}
// Strip any leading or trailing whitespace or quotes
param.erase(0, param.find_first_not_of(_T(" \t\r\n\"")));
* @param [in] value Default value in case none is specified.
* @return Points to the remaining portion of the command line.
*/
-const TCHAR *MergeCmdLineInfo::SetOption(const TCHAR *q, const TCHAR *key, const TCHAR *value)
+const TCHAR *MergeCmdLineInfo::SetOption(const TCHAR *q, const String& key, const TCHAR *value)
{
String s;
if (*q == _T(':'))
q = EatParam(q, s);
value = s.c_str() + 1;
}
-// GetOptionsMgr()->SaveOption(key, value);
+ m_Options.insert_or_assign(key, value);
+ return q;
+}
+
+const TCHAR *MergeCmdLineInfo::SetConfig(const TCHAR *q)
+{
+ String s;
+ if (*q == ':')
+ ++q;
+ q = EatParam(q, s);
+ size_t pos = s.find_first_of('=');
+ if (pos != String::npos)
+ {
+ String key = s.substr(0, pos);
+ String value = s.c_str() + pos + 1;
+ m_Options.insert_or_assign(key, value);
+ }
return q;
}
/**
- * @brief ClearCaseCmdLineParser's constructor.
+ * @brief MergeCmdLineParser's constructor.
* @param [in] q Points to the beginning of the command line.
*/
MergeCmdLineInfo::MergeCmdLineInfo(const TCHAR *q):
m_nCmdShow(SHOWNORMAL),
- m_bClearCaseTool(false),
m_bEscShutdown(false),
m_bExitIfNoDiff(Disabled),
m_bRecurse(false),
m_bNonInteractive(false),
- m_bSingleInstance(false),
+ m_nSingleInstance(),
m_bShowUsage(false),
+ m_bNoPrefs(false),
m_nCodepage(0),
+ m_bSelfCompare(false),
m_dwLeftFlags(FFILEOPEN_NONE),
m_dwMiddleFlags(FFILEOPEN_NONE),
m_dwRightFlags(FFILEOPEN_NONE)
{
- // Rational ClearCase has a weird way of executing external
- // tools which replace the build-in ones. It also doesn't allow
- // you to define which parameters to send to the executable.
- // So, in order to run as an external tool, WinMerge should do:
- // if argv[0] is "xcompare" then it "knows" that it was
- // executed from ClearCase. In this case, it should read and
- // parse ClearCase's command line parameters and not the
- // "regular" parameters. More information can be found in
- // C:\Program Files\Rational\ClearCase\lib\mgrs\mgr_info.h file.
String exeName;
q = EatParam(q, exeName);
- if (exeName == _T("compare") || exeName == _T("xcompare"))
- {
- ParseClearCaseCmdLine(q, _T("<No Base>"));
- }
- else if (exeName == _T("merge") || exeName == _T("xmerge"))
- {
- ParseClearCaseCmdLine(q, _T(""));
- }
- else
- {
- ParseWinMergeCmdLine(q);
- }
-}
-
-/**
- * @brief Parse a command line passed in from ClearCase.
- * @param [in] p Points into the command line.
- */
-void MergeCmdLineInfo::ParseClearCaseCmdLine(const TCHAR *q, const TCHAR *basedesc)
-{
- String sBaseFile; /**< Base file path. */
- String sBaseDesc = basedesc; /**< Base file description. */
- String sOutFile; /**< Out file path. */
- m_bClearCaseTool = true;
- String param;
- bool flag;
- while ((q = EatParam(q, param, &flag)) != 0)
- {
- if (!flag)
- {
- // Not a flag
- param = paths_GetLongPath(param);
- m_Files.SetPath(m_Files.GetSize(), param);
- if (param == m_sLeftDesc)
- m_dwLeftFlags &= ~FFILEOPEN_READONLY;
- if (param == m_sRightDesc)
- m_dwRightFlags &= ~FFILEOPEN_READONLY;
- }
- else if (param == _T("base"))
- {
- // -base is followed by common ancestor file description.
- q = EatParam(q, sBaseFile);
- }
- else if (param == _T("out"))
- {
- // -out is followed by merge's output file name.
- q = EatParam(q, sOutFile);
- }
- else if (param == _T("fname"))
- {
- // -fname is followed by file description.
- if (sBaseDesc.empty())
- q = EatParam(q, sBaseDesc);
- else if (m_sLeftDesc.empty())
- {
- q = EatParam(q, m_sLeftDesc);
- m_dwLeftFlags |= FFILEOPEN_READONLY;
- }
- else if (m_sRightDesc.empty())
- {
- q = EatParam(q, m_sRightDesc);
- m_dwRightFlags |= FFILEOPEN_READONLY;
- }
- else
- q = EatParam(q, param); // ignore excess arguments
- }
- }
- if (!sOutFile.empty())
- {
- String path = paths_GetLongPath(sOutFile);
- m_sOutputpath = path;
- }
+ ParseWinMergeCmdLine(q);
}
/**
m_dwLeftFlags |= FFILEOPEN_CMDLINE;
else if (ord == 1)
m_dwRightFlags |= FFILEOPEN_CMDLINE;
+ else if (ord == 2)
+ m_dwMiddleFlags |= FFILEOPEN_CMDLINE;
- if (!paths_IsURLorCLSID(path))
+ if (!paths::IsURLorCLSID(path))
{
// Convert paths given in Linux-style ('/' as separator) given from
// Cygwin to Windows style ('\' as separator)
- string_replace(param, _T("/"), _T("\\"));
+ strutils::replace(param, _T("/"), _T("\\"));
// If shortcut, expand it first
- if (paths_IsShortcut(param))
- param = ExpandShortcut(param);
- param = paths_GetLongPath(param);
+ if (paths::IsShortcut(param))
+ param = paths::ExpandShortcut(param);
+ param = paths::GetLongPath(param);
m_Files.SetPath(m_Files.GetSize(), param);
}
else
// -o "outputfilename"
q = EatParam(q, m_sOutputpath);
}
+ else if (param == _T("or"))
+ {
+ // -or "reportfilename"
+ q = EatParam(q, m_sReportFile);
+ }
else if (param == _T("dl"))
{
// -dl "desc" - description for left file
// -f "mask" - file filter mask ("*.h *.cpp")
q = EatParam(q, m_sFileFilter);
}
+ else if (param == _T("m"))
+ {
+ // -m "method" - compare method
+ q = EatParam(q, param);
+ param = strutils::makelower(param);
+ strutils::replace(param, _T("and"), _T(""));
+ strutils::replace(param, _T("contents"), _T(""));
+ strutils::replace(param, _T("modified"), _T(""));
+ strutils::replace(param, _T(" "), _T(""));
+ if (param == _T("full"))
+ m_nCompMethod = CompareMethodType::CONTENT;
+ else if (param == _T("quick"))
+ m_nCompMethod = CompareMethodType::QUICK_CONTENT;
+ else if (param == _T("binary"))
+ m_nCompMethod = CompareMethodType::BINARY_CONTENT;
+ else if (param == _T("date"))
+ m_nCompMethod = CompareMethodType::DATE;
+ else if (param == _T("sizedate") || param == _T("datesize"))
+ m_nCompMethod = CompareMethodType::DATE_SIZE;
+ else if (param == _T("size"))
+ m_nCompMethod = CompareMethodType::SIZE;
+ else
+ m_sErrorMessages.push_back(_T("Unknown compare method '") + param + _T("' specified"));
+ }
else if (param == _T("r"))
{
// -r to compare recursively
m_bRecurse = true;
}
+ else if (param == _T("s-"))
+ {
+ // -s- to not allow only one instance
+ m_nSingleInstance = 0;
+ }
+ else if (param == _T("sw"))
+ {
+ // -sw to allow only one instance and wait for the instance to terminate
+ m_nSingleInstance = 2;
+ }
else if (param == _T("s"))
{
// -s to allow only one instance
- m_bSingleInstance = true;
+ if (*q == ':')
+ {
+ q = EatParam(q + 1, param);
+ m_nSingleInstance = _ttoi(param.c_str());
+ }
+
+ else
+ m_nSingleInstance = 1;
}
else if (param == _T("noninteractive"))
{
else if (param == _T("noprefs"))
{
// -noprefs means do not load or remember options (preferences)
- // Turn off serializing to registry.
-// GetOptionsMgr()->SetSerializing(false);
- // Load all default settings.
-// theApp.ResetOptions();
+ m_bNoPrefs = true;
+ }
+ else if (param == _T("self-compare"))
+ {
+ // -self-compare means compare a specified file with a copy of the file
+ m_bSelfCompare = true;
}
else if (param == _T("minimize"))
{
// Get prediffer if specified (otherwise prediffer will be blank, which is default)
q = EatParam(q, m_sPreDiffer);
}
+ else if (param == _T("unpacker"))
+ {
+ // Get unpacker if specified (otherwise unpacker will be blank, which is default)
+ q = EatParam(q, m_sUnpacker);
+ }
else if (param == _T("wl"))
{
// -wl to open left path as read-only
{
String codepage;
q = EatParam(q, codepage);
- try { m_nCodepage = string_stoi(codepage); } catch (...) { /* FIXME: */ }
+ m_nCodepage = atoi(ucr::toUTF8(codepage).c_str());
}
else if (param == _T("ignorews"))
{
{
q = SetOption(q, OPT_CMP_IGNORE_EOL);
}
+ else if (param == _T("ignorecodepage"))
+ {
+ q = SetOption(q, OPT_CMP_IGNORE_CODEPAGE);
+ }
+ else if (param == _T("ignorecomments"))
+ {
+ q = SetOption(q, OPT_CMP_FILTER_COMMENTLINES);
+ }
+ else if (param == _T("cfg") || param == _T("config"))
+ {
+ q = SetConfig(q);
+ }
+ else
+ {
+ m_sErrorMessages.push_back(_T("Unknown option '/") + param + _T("'"));
+ }
}
// If "compare file dir" make it "compare file dir\file".
if (m_Files.GetSize() >= 2)
{
- PATH_EXISTENCE p1 = paths_DoesPathExist(m_Files[0]);
- PATH_EXISTENCE p2 = paths_DoesPathExist(m_Files[1]);
+ paths::PATH_EXISTENCE p1 = paths::DoesPathExist(m_Files[0]);
+ paths::PATH_EXISTENCE p2 = paths::DoesPathExist(m_Files[1]);
- if ((p1 == IS_EXISTING_FILE) && (p2 == IS_EXISTING_DIR))
+ if ((p1 == paths::IS_EXISTING_FILE) && (p2 == paths::IS_EXISTING_DIR))
{
- m_Files[1] = paths_ConcatPath(m_Files[1], paths_FindFileName(m_Files[0]));
+ m_Files[1] = paths::ConcatPath(m_Files[1], paths::FindFileName(m_Files[0]));
}
}
if (m_bShowUsage)