#include "SubstitutionFiltersList.h"
#include "TempFile.h"
#include "codepage_detect.h"
-#include "SelectUnpackerDlg.h"
+#include "SelectPluginDlg.h"
#include "EncodingErrorBar.h"
#include "MergeCmdLineInfo.h"
#include "TFile.h"
ON_COMMAND(ID_FILE_SAVEAS_MIDDLE, OnFileSaveAsMiddle)
ON_COMMAND(ID_FILE_SAVEAS_RIGHT, OnFileSaveAsRight)
ON_UPDATE_COMMAND_UI(ID_STATUS_DIFFNUM, OnUpdateStatusNum)
- ON_UPDATE_COMMAND_UI(ID_STATUS_PLUGIN, OnUpdatePluginName)
ON_COMMAND(ID_TOOLS_GENERATEREPORT, OnToolsGenerateReport)
ON_COMMAND(ID_TOOLS_GENERATEPATCH, OnToolsGeneratePatch)
ON_COMMAND(ID_RESCAN, OnFileReload)
ON_COMMAND(ID_FILE_ENCODING, OnFileEncoding)
ON_COMMAND_RANGE(ID_VIEW_DIFFCONTEXT_ALL, ID_VIEW_DIFFCONTEXT_INVERT, OnDiffContext)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_DIFFCONTEXT_ALL, ID_VIEW_DIFFCONTEXT_INVERT, OnUpdateDiffContext)
- ON_COMMAND(ID_POPUP_OPEN_WITH_UNPACKER, OnCtxtOpenWithUnpacker)
+ ON_COMMAND(ID_OPEN_WITH_UNPACKER, OnOpenWithUnpacker)
+ ON_COMMAND(ID_APPLY_PREDIFFER, OnApplyPrediffer)
ON_BN_CLICKED(IDC_FILEENCODING, OnBnClickedFileEncoding)
ON_BN_CLICKED(IDC_PLUGIN, OnBnClickedPlugin)
ON_BN_CLICKED(IDC_HEXVIEW, OnBnClickedHexView)
ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_TEXT, OnUpdateFileRecompareAsText)
ON_COMMAND(ID_MERGE_COMPARE_TABLE, OnFileRecompareAsTable)
ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_TABLE, OnUpdateFileRecompareAsTable)
- ON_COMMAND(ID_MERGE_COMPARE_XML, OnFileRecompareAsXML)
- ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_XML, OnUpdateFileRecompareAsXML)
ON_COMMAND_RANGE(ID_MERGE_COMPARE_HEX, ID_MERGE_COMPARE_IMAGE, OnFileRecompareAs)
+ ON_COMMAND_RANGE(ID_UNPACKERS_FIRST, ID_UNPACKERS_LAST, OnFileRecompareAs)
ON_UPDATE_COMMAND_UI_RANGE(ID_SWAPPANES_SWAP23, ID_SWAPPANES_SWAP13, OnUpdateSwapContext)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
, m_CurWordDiff{ -1, static_cast<size_t>(-1), -1 }
, m_pDirDoc(nullptr)
, m_bMixedEol(false)
-, m_pInfoUnpacker(new PackingInfo)
, m_pEncodingErrorBar(nullptr)
, m_bHasSyncPoints(false)
, m_bAutoMerged(false)
, m_nGroups(0)
, m_pView{nullptr}
+, m_bAutomaticRescan(false)
{
DIFFOPTIONS options = {0};
}
m_bEnableRescan = true;
+ m_bAutomaticRescan = GetOptionsMgr()->GetBool(OPT_AUTOMATIC_RESCAN);
+
// COleDateTime m_LastRescan
curUndo = undoTgt.begin();
m_nDiffContext = GetOptionsMgr()->GetInt(OPT_DIFF_CONTEXT);
{
if (infoNewHandler != nullptr)
{
- *m_pInfoUnpacker = *infoNewHandler;
+ m_infoUnpacker = *infoNewHandler;
}
}
{
m_diffWrapper.SetPrediffer(infoPrediffer);
}
+
void CMergeDoc::GetPrediffer(PrediffingInfo * infoPrediffer)
{
m_diffWrapper.GetPrediffer(infoPrediffer);
}
+const PrediffingInfo* CMergeDoc::GetPrediffer() const
+{
+ static PrediffingInfo infoPrediffer;
+ m_diffWrapper.GetPrediffer(&infoPrediffer);
+ return &infoPrediffer;
+}
+
/////////////////////////////////////////////////////////////////////////////
// CMergeDoc serialization
static void SaveBuffForDiff(CDiffTextBuffer & buf, const String& filepath, int nStartLine, int nLines)
{
// and we don't repack the file
- PackingInfo * tempPacker = nullptr;
+ PackingInfo tempPacker(false);
// write buffer out to temporary file
String sError;
// Apply flags to lines that are trivial
PrediffingInfo infoPrediffer;
GetPrediffer(&infoPrediffer);
- if (!infoPrediffer.m_PluginName.empty())
+ if (!infoPrediffer.GetPluginPipeline().empty())
FlagTrivialLines();
// Apply flags to lines that moved, to differentiate from appeared/disappeared lines
ShowMessageBox(
strutils::format_string2(
- _T("The number of automatically merged changes: %1\nThe number of unresolved conflicts: %2"),
+ _("The number of automatically merged changes: %1\nThe number of unresolved conflicts: %2"),
strutils::format(_T("%d"), autoMergedCount),
strutils::format(_T("%d"), unresolvedConflictCount)),
MB_ICONINFORMATION);
* @sa CMergeDoc::CDiffTextBuffer::SaveToFile()
*/
bool CMergeDoc::TrySaveAs(String &strPath, int &nSaveResult, String & sError,
- int nBuffer, PackingInfo * pInfoTempUnpacker)
+ int nBuffer, PackingInfo& infoTempUnpacker)
{
String s;
String str;
// Select message based on reason function called
if (nSaveResult == SAVE_PACK_FAILED)
{
- if (m_nBuffers == 3)
- {
- str = strutils::format_string2(
- nBuffer == 0 ?
- _("Plugin '%2' cannot pack your changes to the left file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?")
- : (nBuffer == 1 ?
- _("Plugin '%2' cannot pack your changes to the middle file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?"):
- _("Plugin '%2' cannot pack your changes to the right file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?")),
- strPath, pInfoTempUnpacker->m_PluginName);
- }
- else
- {
- str = strutils::format_string2(nBuffer == 0 ? _("Plugin '%2' cannot pack your changes to the left file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?") :
- _("Plugin '%2' cannot pack your changes to the right file back into '%1'.\n\nThe original file will not be changed.\n\nDo you want to save the unpacked version to another file?"),
- strPath, pInfoTempUnpacker->m_PluginName);
- }
+ str = CMergeApp::GetPackingErrorMessage(nBuffer, m_nBuffers, strPath, infoTempUnpacker);
// replace the unpacker with a "do nothing" unpacker
- pInfoTempUnpacker->Initialize(PLUGIN_MODE::PLUGIN_MANUAL);
+ infoTempUnpacker.Initialize(false);
}
else
{
CDiffTextBuffer *pBuffer = m_ptBuf[nBuffer].get();
strSavePath = s;
nSaveResult = pBuffer->SaveToFile(strSavePath, false, sError,
- pInfoTempUnpacker);
+ infoTempUnpacker);
if (nSaveResult == SAVE_DONE)
{
}
// use a temp packer
- // first copy the m_pInfoUnpacker
+ // first copy the m_infoUnpacker
// if an error arises during packing, change and take a "do nothing" packer
- PackingInfo infoTempUnpacker = *m_pInfoUnpacker;
+ PackingInfo infoTempUnpacker = m_infoUnpacker;
bSaveSuccess = false;
strSavePath = theApp.m_strSaveAsPath;
}
- nRetVal = theApp.HandleReadonlySave(strSavePath, false, bApplyToAll);
+ nRetVal = CMergeApp::HandleReadonlySave(strSavePath, false, bApplyToAll);
if (nRetVal == IDCANCEL)
return false;
- if (!theApp.CreateBackup(false, strSavePath))
+ if (!CMergeApp::CreateBackup(false, strSavePath))
return false;
// false as long as the user is not satisfied
String sError;
if (nSaveErrorCode == SAVE_DONE)
// We have a filename, just try to save
- nSaveErrorCode = pBuffer->SaveToFile(strSavePath, false, sError, &infoTempUnpacker);
+ nSaveErrorCode = pBuffer->SaveToFile(strSavePath, false, sError, infoTempUnpacker);
if (nSaveErrorCode != SAVE_DONE)
{
// Saving failed, user may save to another location if wants to
do
- result = TrySaveAs(strSavePath, nSaveErrorCode, sError, nBuffer, &infoTempUnpacker);
+ result = TrySaveAs(strSavePath, nSaveErrorCode, sError, nBuffer, infoTempUnpacker);
while (!result);
}
String strSavePath(szPath);
// use a temp packer
- // first copy the m_pInfoUnpacker
+ // first copy the m_infoUnpacker
// if an error arises during packing, change and take a "do nothing" packer
- PackingInfo infoTempUnpacker = *m_pInfoUnpacker;
+ PackingInfo infoTempUnpacker = m_infoUnpacker;
bSaveSuccess = false;
// false as long as the user is not satisfied
// Loop until user succeeds saving or cancels
String sError;
do
- result = TrySaveAs(strSavePath, nSaveErrorCode, sError, nBuffer, &infoTempUnpacker);
+ result = TrySaveAs(strSavePath, nSaveErrorCode, sError, nBuffer, infoTempUnpacker);
while (!result);
// Saving succeeded with given/selected filename
}
/**
- * @brief Update plugin name
- * @param [in] pCmdUI UI component to update.
- */
-void CMergeDoc::OnUpdatePluginName(CCmdUI* pCmdUI)
-{
- String pluginNames;
- if (m_pInfoUnpacker && !m_pInfoUnpacker->m_PluginName.empty())
- pluginNames += m_pInfoUnpacker->m_PluginName + _T("&");
- PrediffingInfo prediffer;
- GetPrediffer(&prediffer);
- if (!prediffer.m_PluginName.empty())
- pluginNames += prediffer.m_PluginName + _T("&");
- pCmdUI->SetText(pluginNames.substr(0, pluginNames.length() - 1).c_str());
-}
-
-/**
* @brief Change number of diff context lines
*/
void CMergeDoc::OnDiffContext(UINT nID)
if (!PromptAndSaveIfNeeded(true))
return false;
- GetParentFrame()->CloseNow();
+ GetParentFrame()->DestroyWindow();
return true;
}
CRLFSTYLE nCrlfStyle = CRLFSTYLE::AUTOMATIC;
CString sOpenError;
- retVal = pBuf->LoadFromFile(sFileName, m_pInfoUnpacker.get(),
+ retVal = pBuf->LoadFromFile(sFileName, m_infoUnpacker,
m_strBothFilenames.c_str(), readOnly, nCrlfStyle, encoding, sOpenError);
// if CMergeDoc::CDiffTextBuffer::LoadFromFile failed,
loadSuccess = LoadFile(filename.c_str(), index, readOnly, encoding);
if (FileLoadResult::IsLossy(loadSuccess))
{
- m_ptBuf[index]->FreeAll();
- loadSuccess = LoadFile(filename.c_str(), index, readOnly,
- GuessCodepageEncoding(filename, GetOptionsMgr()->GetInt(OPT_CP_DETECT), -1));
+ // Determine the file encoding by looking at all the contents of the file, not just part of it
+ FileTextEncoding encodingNew = codepage_detect::Guess(filename, GetOptionsMgr()->GetInt(OPT_CP_DETECT), -1);
+ if (encoding != encodingNew)
+ {
+ m_ptBuf[index]->FreeAll();
+ loadSuccess = LoadFile(filename.c_str(), index, readOnly, encodingNew);
+ }
}
}
else
* @param bRO [in] Is left/middle/right file read-only
* @return Success/Failure/Binary (failure) per typedef enum OpenDocsResult_TYPE
* @todo Options are still read from CMainFrame, this will change
- * @sa CMainFrame::ShowMergeDoc()
+ * @sa CMainFrame::ShowTextMergeDoc()
*/
bool CMergeDoc::OpenDocs(int nFiles, const FileLocation ifileloc[],
const bool bRO[], const String strDesc[])
m_strBothFilenames.erase(m_strBothFilenames.length() - 1);
// Load files
- DWORD nSuccess[3];
+ DWORD nSuccess[3] = { FileLoadResult::FRESULT_ERROR, FileLoadResult::FRESULT_ERROR, FileLoadResult::FRESULT_ERROR };
for (nBuffer = 0; nBuffer < m_nBuffers; nBuffer++)
{
nSuccess[nBuffer] = LoadOneFile(nBuffer, fileloc[nBuffer].filepath, bRO[nBuffer], strDesc ? strDesc[nBuffer] : _T(""),
fileloc[nBuffer].encoding);
+ if (!FileLoadResult::IsOk(nSuccess[nBuffer]))
+ {
+ CMergeEditFrame* pFrame = GetParentFrame();
+ if (pFrame != nullptr)
+ {
+ // Use verify macro to trap possible error in debug.
+ VERIFY(pFrame->DestroyWindow());
+ }
+ return false;
+ }
}
SetTableProperties();
{
if (std::count(m_nBufferType, m_nBufferType + m_nBuffers, BUFFERTYPE::UNNAMED) == m_nBuffers)
{
- m_pInfoUnpacker->Initialize(PLUGIN_MODE::PLUGIN_MANUAL);
+ m_infoUnpacker.Initialize(false);
}
}
- // Bail out if either side failed
- if (std::find_if(nSuccess, nSuccess + m_nBuffers, [](DWORD d){return !FileLoadResult::IsOk(d);} ) != nSuccess + m_nBuffers)
- {
- CMergeEditFrame *pFrame = GetParentFrame();
- if (pFrame != nullptr)
- {
- // Use verify macro to trap possible error in debug.
- VERIFY(pFrame->DestroyWindow());
- }
- return false;
- }
-
// Warn user if file load was lossy (bad encoding)
int idres=0;
int nLossyBuffers = 0;
for (nBuffer = 0; nBuffer < m_nBuffers; nBuffer++)
{
- if (bFiltersEnabled && m_pInfoUnpacker->m_textType.length())
- sext[nBuffer] = m_pInfoUnpacker->m_textType;
- else
- sext[nBuffer] = GetFileExt(fileloc[nBuffer].filepath.c_str(), m_strDesc[nBuffer].c_str());
+ sext[nBuffer] = GetFileExt(m_ptBuf[nBuffer]->GetTempFileName().c_str(), m_strDesc[nBuffer].c_str());
ForEachView(nBuffer, [&](auto& pView) {
bTyped[nBuffer] = pView->SetTextType(sext[nBuffer].c_str());
if (bTyped[nBuffer])
strDesc[nBuffer] = _T("");
fileloc[nBuffer].setPath(path);
- fileloc[nBuffer].encoding = GuessCodepageEncoding(path, GetOptionsMgr()->GetInt(OPT_CP_DETECT));
+ fileloc[nBuffer].encoding = codepage_detect::Guess(path, GetOptionsMgr()->GetInt(OPT_CP_DETECT));
if (OpenDocs(m_nBuffers, fileloc, bRO, strDesc))
MoveOnLoad(nBuffer, nLineIndex);
{
DIFFOPTIONS options = {0};
+ m_bAutomaticRescan = GetOptionsMgr()->GetBool(OPT_AUTOMATIC_RESCAN);
+
m_diffWrapper.SetDetectMovedBlocks(GetOptionsMgr()->GetBool(OPT_CMP_MOVED_BLOCKS));
Options::DiffOptions::Load(GetOptionsMgr(), options);
*/
void CMergeDoc::SetTitle(LPCTSTR lpszTitle)
{
- String sTitle = (lpszTitle != nullptr) ? lpszTitle : CMergeFrameCommon::GetTitleString(m_filePaths, m_strDesc);
+ PrediffingInfo infoPrediffer;
+ GetPrediffer(&infoPrediffer);
+ String sTitle = (lpszTitle != nullptr) ? lpszTitle : CMergeFrameCommon::GetTitleString(m_filePaths, m_strDesc, &m_infoUnpacker, &infoPrediffer);
CDocument::SetTitle(sTitle.c_str());
}
}
/**
- * @brief Display unpacker dialog to user & handle user's choices
- */
-bool CMergeDoc::OpenWithUnpackerDialog()
-{
- // let the user choose a handler
- CSelectUnpackerDlg dlg(m_filePaths[0], nullptr);
- // create now a new infoUnpacker to initialize the manual/automatic flag
- PackingInfo infoUnpacker(PLUGIN_MODE::PLUGIN_AUTO);
- dlg.SetInitialInfoHandler(&infoUnpacker);
-
- if (dlg.DoModal() == IDOK)
- {
- infoUnpacker = dlg.GetInfoHandler();
- Merge7zFormatMergePluginScope scope(&infoUnpacker);
- if (HasZipSupport() && std::count_if(m_filePaths.begin(), m_filePaths.end(), ArchiveGuessFormat) == m_nBuffers)
- {
- DWORD dwFlags[3] = {FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, FFILEOPEN_NOMRU};
- GetMainFrame()->DoFileOpen(&m_filePaths, dwFlags, m_strDesc, _T(""),
- GetOptionsMgr()->GetBool(OPT_CMP_INCLUDE_SUBDIRS), nullptr, _T(""), &infoUnpacker);
- CloseNow();
- }
- else
- {
- SetUnpacker(&infoUnpacker);
- OnFileReload();
- }
- return true;
- }
- else
- {
- return false;
- }
-}
-
-/**
* @brief Reloads the opened files
*/
void CMergeDoc::OnFileReload()
DoFileEncodingDialog();
}
-void CMergeDoc::OnCtxtOpenWithUnpacker()
+void CMergeDoc::OnOpenWithUnpacker()
{
- OpenWithUnpackerDialog();
+ CSelectPluginDlg dlg(m_infoUnpacker.GetPluginPipeline(),
+ strutils::join(m_filePaths.begin(), m_filePaths.end(), _T("|")), true, false);
+ if (dlg.DoModal() != IDOK)
+ return;
+
+ if (!PromptAndSaveIfNeeded(true))
+ return;
+
+ PackingInfo infoUnpacker(dlg.GetPluginPipeline());
+ PathContext paths = m_filePaths;
+ DWORD dwFlags[3] = { FFILEOPEN_NOMRU, FFILEOPEN_NOMRU, FFILEOPEN_NOMRU };
+ String strDesc[3] = { m_strDesc[0], m_strDesc[1], m_strDesc[2] };
+ int nID = m_ptBuf[0]->GetTableEditing() ? ID_MERGE_COMPARE_TABLE : ID_MERGE_COMPARE_TEXT;
+ nID = GetOptionsMgr()->GetBool(OPT_PLUGINS_OPEN_IN_SAME_FRAME_TYPE) ? nID : -1;
+
+ if (GetMainFrame()->DoFileOpen(nID, &paths, dwFlags, strDesc, _T(""), &infoUnpacker))
+ GetParentFrame()->DestroyWindow();
+}
+
+void CMergeDoc::OnApplyPrediffer()
+{
+ PrediffingInfo prediffer;
+ GetPrediffer(&prediffer);
+ // let the user choose a handler
+ CSelectPluginDlg dlg(prediffer.GetPluginPipeline(),
+ strutils::join(m_filePaths.begin(), m_filePaths.end(), _T("|")), false, false);
+ if (dlg.DoModal() != IDOK)
+ return;
+ prediffer.SetPluginPipeline(dlg.GetPluginPipeline());
+ SetPrediffer(&prediffer);
+ FlushAndRescan(true);
+ SetTitle(nullptr);
}
void CMergeDoc::OnBnClickedFileEncoding()
if (m_pEncodingErrorBar == nullptr || m_pView[0][0] == nullptr)
return;
m_pView[0][0]->GetParentFrame()->ShowControlBar(m_pEncodingErrorBar.get(), FALSE, FALSE);
- OpenWithUnpackerDialog();
+ OnOpenWithUnpacker();
}
void CMergeDoc::OnBnClickedHexView()
void CMergeDoc::OnFileRecompareAsText()
{
m_bEnableTableEditing = false;
- PackingInfo infoUnpacker;
- SetUnpacker(&infoUnpacker);
OnFileReload();
}
void CMergeDoc::OnUpdateFileRecompareAsText(CCmdUI *pCmdUI)
{
- pCmdUI->Enable(m_pInfoUnpacker->m_PluginOrPredifferMode == PLUGIN_MODE::PLUGIN_BUILTIN_XML ||
- m_ptBuf[0]->GetTableEditing());
+ pCmdUI->Enable(m_ptBuf[0]->GetTableEditing());
}
void CMergeDoc::OnFileRecompareAsTable()
{
m_bEnableTableEditing = true;
- PackingInfo infoUnpacker;
- SetUnpacker(&infoUnpacker);
OnFileReload();
}
pCmdUI->Enable(!m_ptBuf[0]->GetTableEditing());
}
-void CMergeDoc::OnFileRecompareAsXML()
-{
- m_bEnableTableEditing = false;
- PackingInfo infoUnpacker(PLUGIN_MODE::PLUGIN_BUILTIN_XML);
- SetUnpacker(&infoUnpacker);
- OnFileReload();
-}
-
-void CMergeDoc::OnUpdateFileRecompareAsXML(CCmdUI *pCmdUI)
-{
- pCmdUI->Enable(m_pInfoUnpacker->m_PluginOrPredifferMode != PLUGIN_MODE::PLUGIN_BUILTIN_XML);
-}
-
void CMergeDoc::OnFileRecompareAs(UINT nID)
{
+ if (!PromptAndSaveIfNeeded(true))
+ return;
+
DWORD dwFlags[3] = { 0 };
FileLocation fileloc[3];
+ String strDesc[3];
+ int nBuffers = m_nBuffers;
+ CDirDoc *pDirDoc = m_pDirDoc->GetMainView() ? m_pDirDoc :
+ static_cast<CDirDoc*>(theApp.m_pDirTemplate->CreateNewDocument());
+ PackingInfo infoUnpacker(m_infoUnpacker.GetPluginPipeline());
+
for (int pane = 0; pane < m_nBuffers; pane++)
{
fileloc[pane].setPath(m_filePaths[pane]);
dwFlags[pane] |= FFILEOPEN_NOMRU | (m_ptBuf[pane]->GetReadOnly() ? FFILEOPEN_READONLY : 0);
+ strDesc[pane] = m_strDesc[pane];
}
- if (m_pEncodingErrorBar!=nullptr && m_pEncodingErrorBar->IsWindowVisible())
- m_pView[0][0]->GetParentFrame()->ShowControlBar(m_pEncodingErrorBar.get(), FALSE, FALSE);
- if (nID == ID_MERGE_COMPARE_HEX)
- GetMainFrame()->ShowHexMergeDoc(m_pDirDoc, m_nBuffers, fileloc, dwFlags, m_strDesc);
- else
- GetMainFrame()->ShowImgMergeDoc(m_pDirDoc, m_nBuffers, fileloc, dwFlags, m_strDesc);
- GetParentFrame()->ShowWindow(SW_RESTORE);
- GetParentFrame()->DestroyWindow();
+ if (ID_UNPACKERS_FIRST <= nID && nID <= ID_UNPACKERS_LAST)
+ {
+ infoUnpacker.SetPluginPipeline(CMainFrame::GetPluginPipelineByMenuId(nID, FileTransform::UnpackerEventNames, ID_UNPACKERS_FIRST));
+ nID = m_ptBuf[0]->GetTableEditing() ? ID_MERGE_COMPARE_TABLE : ID_MERGE_COMPARE_TEXT;
+ nID = GetOptionsMgr()->GetBool(OPT_PLUGINS_OPEN_IN_SAME_FRAME_TYPE) ? nID : -1;
+ }
+
+ if (GetMainFrame()->ShowMergeDoc(nID, pDirDoc, nBuffers, fileloc, dwFlags, strDesc, _T(""), &infoUnpacker))
+ GetParentFrame()->DestroyWindow();
}
// Return file extension either from file name