#include "MergeLineFlags.h"
#include "FileOrFolderSelect.h"
#include "LineFiltersList.h"
-#include "TokenPairList.h"
+#include "SubstitutionFiltersList.h"
#include "TempFile.h"
#include "codepage_detect.h"
#include "SelectUnpackerDlg.h"
, 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);
m_diffWrapper.SetFilterList(_T(""));
}
- if (GetOptionsMgr()->GetBool(OPT_IGNORED_SUBSTITUTIONS_ARE_ENABLED) && theApp.m_pTokensForIs)
+ if (theApp.m_pSubstitutionFiltersList && theApp.m_pSubstitutionFiltersList->GetEnabled())
{
- m_diffWrapper.SetIgnoredSubstitutionsList(theApp.m_pTokensForIs.get());
+ m_diffWrapper.SetSubstitutionList(theApp.m_pSubstitutionFiltersList->MakeSubstitutionList());
}
else
{
- m_diffWrapper.SetIgnoredSubstitutionsList(nullptr);
+ m_diffWrapper.SetSubstitutionList(nullptr);
}
if (GetView(0, 0)->m_CurSourceDef->type != 0)
FlushAndRescan();
}
+void CMergeDoc::CopyMultiplePartialList(int srcPane, int dstPane, int firstDiff, int lastDiff,
+ int firstLineDiff, int lastLineDiff)
+{
+ lastDiff = min(m_diffList.GetSize() - 1, lastDiff);
+ firstDiff = max(0, firstDiff);
+ if (firstDiff > lastDiff)
+ return;
+
+ RescanSuppress suppressRescan(*this);
+
+ bool bGroupWithPrevious = false;
+ if (firstLineDiff <= 0 && lastLineDiff == -1)
+ {
+ if (!ListCopy(srcPane, dstPane, -1, bGroupWithPrevious, true))
+ return; // sync failure
+ }
+ else
+ {
+ if (!PartialListCopy(srcPane, dstPane, lastDiff,
+ (firstDiff == lastDiff) ? firstLineDiff : 0, lastLineDiff, bGroupWithPrevious, true))
+ return; // sync failure
+ }
+
+
+ SetEditedAfterRescan(dstPane);
+
+ int nGroup = GetActiveMergeView()->m_nThisGroup;
+ CMergeEditView *pViewSrc = m_pView[nGroup][srcPane];
+ CMergeEditView *pViewDst = m_pView[nGroup][dstPane];
+ CPoint currentPosSrc = pViewSrc->GetCursorPos();
+ currentPosSrc.x = 0;
+ CPoint currentPosDst = pViewDst->GetCursorPos();
+ currentPosDst.x = 0;
+
+ CPoint pt(0, 0);
+ pViewDst->SetCursorPos(pt);
+ pViewDst->SetNewSelection(pt, pt, false);
+ pViewDst->SetNewAnchor(pt);
+
+ // copy from bottom up is more efficient
+ for (int i = lastDiff - 1; i >= firstDiff; --i)
+ {
+ if (m_diffList.IsDiffSignificant(i))
+ {
+ SetCurrentDiff(i);
+ const DIFFRANGE *pdi = m_diffList.DiffRangeAt(i);
+ if (currentPosDst.y > pdi->dend)
+ {
+ if (pdi->blank[dstPane] >= 0)
+ currentPosDst.y -= pdi->dend - pdi->blank[dstPane] + 1;
+ else if (pdi->blank[srcPane] >= 0)
+ currentPosDst.y -= pdi->dend - pdi->blank[srcPane] + 1;
+ }
+ // Group merge with previous (merge undo data to one action)
+ bGroupWithPrevious = true;
+ if (i > firstDiff || firstLineDiff <= 0)
+ {
+ if (!ListCopy(srcPane, dstPane, -1, bGroupWithPrevious, false))
+ break; // sync failure
+ }
+ else
+ {
+ if (!PartialListCopy(srcPane, dstPane, firstDiff, firstLineDiff, -1, bGroupWithPrevious, false))
+ break; // sync failure
+ }
+ }
+ }
+
+ ForEachView(dstPane, [currentPosDst](auto& pView) {
+ pView->SetCursorPos(currentPosDst);
+ pView->SetNewSelection(currentPosDst, currentPosDst, false);
+ pView->SetNewAnchor(currentPosDst);
+ });
+
+ suppressRescan.Clear(); // done suppress Rescan
+ FlushAndRescan();
+}
+
enum MergeResult { NoMergeNeeded, Merged, Conflict };
template<class Type>
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);
return true;
}
+bool CMergeDoc::PartialListCopy(int srcPane, int dstPane, int nDiff, int firstLine, int lastLine /*= -1*/,
+ bool bGroupWithPrevious /*= false*/, bool bUpdateView /*= true*/)
+{
+ int nGroup = GetActiveMergeView()->m_nThisGroup;
+ CMergeEditView *pViewSrc = m_pView[nGroup][srcPane];
+ CMergeEditView *pViewDst = m_pView[nGroup][dstPane];
+ CCrystalTextView *pSource = bUpdateView ? pViewDst : nullptr;
+
+ // suppress Rescan during this method
+ // (Not only do we not want to rescan a lot of times, but
+ // it will wreck the line status array to rescan as we merge)
+ RescanSuppress suppressRescan(*this);
+
+ DIFFRANGE cd;
+ VERIFY(m_diffList.GetDiff(nDiff, cd));
+ CDiffTextBuffer& sbuf = *m_ptBuf[srcPane];
+ CDiffTextBuffer& dbuf = *m_ptBuf[dstPane];
+ bool bSrcWasMod = sbuf.IsModified();
+ const int cd_dbegin = (firstLine > cd.dbegin) ? firstLine : cd.dbegin;
+ const int cd_dend = cd.dend;
+ const int cd_blank = cd.blank[srcPane];
+ bool bInSync = SanityCheckDiff(cd);
+
+ if (!bInSync)
+ {
+ LangMessageBox(IDS_VIEWS_OUTOFSYNC, MB_ICONSTOP);
+ return false; // abort copying
+ }
+
+ // If we remove whole diff from current view, we must fix cursor
+ // position first. Normally we would move to end of previous line,
+ // but we want to move to begin of that line for usability.
+ if (bUpdateView)
+ {
+ CPoint currentPos = pViewDst->GetCursorPos();
+ currentPos.x = 0;
+ if (currentPos.y > cd_dend)
+ {
+ if (cd.blank[dstPane] >= 0)
+ currentPos.y -= cd_dend - cd.blank[dstPane] + 1;
+ else if (cd.blank[srcPane] >= 0)
+ currentPos.y -= cd_dend - cd.blank[srcPane] + 1;
+ }
+ ForEachView(dstPane, [currentPos](auto& pView) { pView->SetCursorPos(currentPos); });
+ }
+
+ // if the current diff contains missing lines, remove them from both sides
+ int limit = ((lastLine < 0) || (lastLine > cd_dend)) ? cd_dend : lastLine;
+
+ // curView is the view which is changed, so the opposite of the source view
+ dbuf.BeginUndoGroup(bGroupWithPrevious);
+ if ((cd_blank >= 0) && (cd_dbegin >= cd_blank))
+ {
+ // text was missing, so delete rest of lines on both sides
+ // delete only on destination side since rescan will clear the other side
+ if (limit+1 < dbuf.GetLineCount())
+ {
+ dbuf.DeleteText(pSource, cd_dbegin, 0, limit+1, 0, CE_ACTION_MERGE);
+ }
+ else
+ {
+ // To removing EOL chars of last line, deletes from the end of the line (cd_blank - 1).
+ ASSERT(cd_dbegin > 0);
+ dbuf.DeleteText(pSource, cd_dbegin-1, dbuf.GetLineLength(cd_dbegin-1), limit, dbuf.GetLineLength(limit), CE_ACTION_MERGE);
+ }
+
+ limit = cd_dbegin-1;
+ dbuf.FlushUndoGroup(pSource);
+ dbuf.BeginUndoGroup(true);
+ }
+
+ // copy the selected text over
+ if (cd_dbegin <= limit)
+ {
+ // text exists on left side, so just replace
+ dbuf.ReplaceFullLines(dbuf, sbuf, pSource, cd_dbegin, limit, CE_ACTION_MERGE);
+ dbuf.FlushUndoGroup(pSource);
+ dbuf.BeginUndoGroup(true);
+ }
+ dbuf.FlushUndoGroup(pSource);
+
+ // remove the diff
+ SetCurrentDiff(-1);
+
+ // reset the mod status of the source view because we do make some
+ // changes, but none that concern the source text
+ sbuf.SetModified(bSrcWasMod);
+
+ suppressRescan.Clear(); // done suppress Rescan
+ FlushAndRescan();
+ return true;
+}
+
bool CMergeDoc::WordListCopy(int srcPane, int dstPane, int nDiff, int firstWordDiff, int lastWordDiff,
const std::vector<int> *pWordDiffIndice, bool bGroupWithPrevious /*= false*/, bool bUpdateView /*= true*/)
{
{
m_ptBuf[index]->FreeAll();
loadSuccess = LoadFile(filename.c_str(), index, readOnly,
- GuessCodepageEncoding(filename, GetOptionsMgr()->GetInt(OPT_CP_DETECT), -1));
+ codepage_detect::Guess(filename, GetOptionsMgr()->GetInt(OPT_CP_DETECT), -1));
}
}
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();
}
}
- // 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;
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);
}
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);
+ GetMainFrame()->ShowMergeDoc(nID, m_pDirDoc, m_nBuffers, fileloc, dwFlags, m_strDesc);
GetParentFrame()->ShowWindow(SW_RESTORE);
GetParentFrame()->DestroyWindow();
}