}
};
+struct CurrentWordDiff
+{
+ int nDiff;
+ size_t nWordDiff;
+ int nPane;
+ CPoint ptStart;
+ CPoint ptEnd;
+};
+
struct DiffFileInfo;
class CMergeEditView;
class PackingInfo;
int RightLineInMovedBlock(int pane, int line);
int LeftLineInMovedBlock(int pane, int line);
void SetEditedAfterRescan(int nBuffer);
- bool IsEditedAfterRescan(int nBuffer) { return m_bEditAfterRescan[nBuffer]; }
+ bool IsEditedAfterRescan(int nBuffer = -1) const;
void SetUnpacker(const PackingInfo * infoUnpacker);
void SetPrediffer(const PrediffingInfo * infoPrediffer);
void FlushAndRescan(bool bForced = false);
void SetCurrentDiff(int nDiff);
int GetCurrentDiff() const { return m_nCurDiff; }
+ const CurrentWordDiff& GetCurrentWordDiff() const { return m_CurWordDiff; }
+ bool EqualCurrentWordDiff(int nBuffer, const CPoint& ptStart, const CPoint& ptEnd) const
+ {
+ return (m_CurWordDiff.nPane == nBuffer && m_CurWordDiff.ptStart == ptStart && m_CurWordDiff.ptEnd == ptEnd);
+ }
virtual ~CMergeDoc();
void SetDetectMovedBlocks(bool bDetectMovedBlocks);
bool IsMixedEOL(int nBuffer) const;
// Implementation data
protected:
int m_nCurDiff; /**< Selected diff, 0-based index, -1 if no diff selected */
+ CurrentWordDiff m_CurWordDiff;
CMergeEditView * m_pView[3][3]; /**< Pointer to left/middle/right view */
CLocationView * m_pLocationView; /**< Pointer to locationview */
CDirDoc * m_pDirDoc;
HighlightDiffRect(m_pView[pView->m_nThisGroup][nBuffer], rc[nBuffer]);
}
+static inline bool IsDiffPerLine(bool bTableEditing, const DIFFRANGE& cd)
+{
+ const int LineLimit = 20;
+ return (bTableEditing || (cd.dend - cd.dbegin > LineLimit)) ? true : false;
+}
/**
* @brief Returns rectangles to highlight in both views (to show differences in line specified)
for (file = 0; file < m_nBuffers; file++)
rc[file].top = -1;
+ const int nActivePane = pView->m_nThisPane;
+ if (m_diffList.GetSize() == 0 || IsEditedAfterRescan())
+ return;
+
CPoint ptStart, ptEnd;
pView->GetSelection(ptStart, ptEnd);
- vector<WordDiff> worddiffs = GetWordDiffArray(ptStart.y);
-
- if (worddiffs.empty())
- return;
-
- int nActivePane = pView->m_nThisPane;
+ const int nLineCount = m_ptBuf[nActivePane]->GetLineCount();
+ size_t nWordDiff = 0;
+ DIFFRANGE di;
+ vector<WordDiff> worddiffs;
+ int nDiff = m_diffList.LineToDiff(ptStart.y);
+ if (nDiff != -1)
+ worddiffs = GetWordDiffArrayInDiffBlock(nDiff);
- std::vector<WordDiff>::iterator it;
- for (it = worddiffs.begin(); it != worddiffs.end(); ++it)
+ if (!worddiffs.empty())
{
- if ((*it).beginline[nActivePane] <= ptStart.y && ptStart.y <= (*it).endline[nActivePane])
+ bool bGoToNextWordDiff = true;
+ if (EqualCurrentWordDiff(nActivePane, ptStart, ptEnd))
{
- int begin = ((*it).beginline[nActivePane] < ptStart.y) ? 0 : (*it).begin[nActivePane];
- int end = ((*it).endline[nActivePane] > ptStart.y) ? m_ptBuf[nActivePane]->GetLineLength(ptStart.y) : (*it).end[nActivePane];
- if (begin <= ptStart.x && ptStart.x <= end)
- break;
+ nWordDiff = m_CurWordDiff.nWordDiff;
+ }
+ else
+ {
+ if (!bReversed)
+ {
+ for (nWordDiff = 0; nWordDiff < worddiffs.size(); ++nWordDiff)
+ {
+ auto& worddiff = worddiffs[nWordDiff];
+ if (worddiff.beginline[nActivePane] <= ptStart.y && ptStart.y <= worddiff.endline[nActivePane])
+ {
+ int begin = (worddiff.beginline[nActivePane] < ptStart.y) ? 0 : worddiff.begin[nActivePane];
+ int end = (worddiff.endline[nActivePane] > ptStart.y) ? m_ptBuf[nActivePane]->GetLineLength(ptStart.y) : worddiff.end[nActivePane];
+ if (ptStart.x <= begin || (begin <= ptStart.x && ptStart.x <= end))
+ {
+ bGoToNextWordDiff = false;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (nWordDiff = worddiffs.size() - 1; nWordDiff != static_cast<size_t>(-1); --nWordDiff)
+ {
+ auto& worddiff = worddiffs[nWordDiff];
+ if (worddiff.beginline[nActivePane] <= ptStart.y && ptStart.y <= worddiff.endline[nActivePane])
+ {
+ int begin = (worddiff.beginline[nActivePane] < ptStart.y) ? 0 : worddiff.begin[nActivePane];
+ int end = (worddiff.endline[nActivePane] > ptStart.y) ? m_ptBuf[nActivePane]->GetLineLength(ptStart.y) : worddiff.end[nActivePane];
+ if (ptStart.x >= end || (begin <= ptStart.x && ptStart.x <= end))
+ {
+ bGoToNextWordDiff = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (bGoToNextWordDiff)
+ {
+ if (!bReversed)
+ {
+ if (nWordDiff < worddiffs.size())
+ ++nWordDiff;
+
+ if (nWordDiff == worddiffs.size())
+ {
+ m_diffList.GetDiff(nDiff, di);
+ ptStart.y = (di.dend + 1) % nLineCount;
+ worddiffs.clear();
+ }
+ }
+ else
+ {
+ if (nWordDiff == 0)
+ {
+ m_diffList.GetDiff(nDiff, di);
+ ptStart.y = (di.dbegin - 1) % nLineCount;
+ worddiffs.clear();
+ }
+ else
+ --nWordDiff;
+ }
}
}
-
- if (!bReversed)
- {
- if (it != worddiffs.end())
- ++it;
-
- if (it == worddiffs.end())
- it = worddiffs.begin();
- }
- else
+ if (worddiffs.empty())
{
- if (it == worddiffs.begin() || it == worddiffs.end())
- it = worddiffs.end() - 1;
+ if (!bReversed)
+ {
+ nDiff = m_diffList.LineToDiff(ptStart.y);
+ if (nDiff == -1)
+ {
+ m_diffList.GetNextDiff(ptStart.y, nDiff);
+ if (nDiff == -1)
+ nDiff = 0;
+ }
+ else
+ {
+ nDiff = (nDiff + 1) % m_diffList.GetSize();
+ }
+ worddiffs = GetWordDiffArrayInDiffBlock(nDiff);
+ nWordDiff = 0;
+ }
else
- --it;
+ {
+ nDiff = m_diffList.LineToDiff(ptStart.y);
+ if (nDiff == -1)
+ {
+ m_diffList.GetPrevDiff(ptStart.y, nDiff);
+ if (nDiff == -1)
+ nDiff = m_diffList.GetSize() - 1;
+ }
+ else
+ {
+ nDiff = (nDiff - 1) % m_diffList.GetSize();
+ }
+ worddiffs = GetWordDiffArrayInDiffBlock(nDiff);
+ nWordDiff = worddiffs.size() - 1;
+ }
+ if (worddiffs.empty())
+ {
+ if (nDiff == -1)
+ return;
+ for (file = 0; file < m_nBuffers; file++)
+ {
+ rc[file].left = 0;
+ rc[file].top = di.dbegin;
+ rc[file].right = 0;
+ if (di.dbegin < nLineCount - 1)
+ rc[file].bottom = di.dbegin + 1;
+ else
+ rc[file].bottom = di.dbegin;
+ }
+ nWordDiff = static_cast<size_t>(-1);
+ }
}
- for (file = 0; file < m_nBuffers; file++)
+ if (nWordDiff != static_cast<size_t>(-1))
{
- rc[file].left = (*it).begin[file];
- rc[file].top = (*it).beginline[file];
- rc[file].right =(*it).end[file];
- rc[file].bottom = (*it).endline[file];
+ auto& worddiff = worddiffs[nWordDiff];
+ for (file = 0; file < m_nBuffers; file++)
+ {
+ rc[file].left = worddiff.begin[file];
+ rc[file].top = worddiff.beginline[file];
+ rc[file].right = worddiff.end[file];
+ rc[file].bottom = worddiff.endline[file];
+ }
}
+
+ m_CurWordDiff.nPane = nActivePane;
+ m_CurWordDiff.ptStart.x = rc[nActivePane].left;
+ m_CurWordDiff.ptStart.y = rc[nActivePane].top;
+ m_CurWordDiff.ptEnd.x = rc[nActivePane].right;
+ m_CurWordDiff.ptEnd.y = rc[nActivePane].bottom;
+ m_CurWordDiff.nDiff = nDiff;
+ m_CurWordDiff.nWordDiff = nWordDiff;
}
void CMergeDoc::ClearWordDiffCache(int nDiff/* = -1 */)
std::vector<WordDiff> CMergeDoc::GetWordDiffArrayInDiffBlock(int nDiff)
{
DIFFRANGE cd;
- const int LineLimit = 20;
m_diffList.GetDiff(nDiff, cd);
- bool diffPerLine = (cd.dend - cd.dbegin > LineLimit) ? true : false;
+ bool diffPerLine = IsDiffPerLine(m_ptBuf[0]->GetTableEditing(), cd);
if (!diffPerLine)
return GetWordDiffArray(cd.dbegin);
m_diffWrapper.GetOptions(&diffOptions);
String str[3];
std::unique_ptr<int[]> nOffsets[3];
- const int LineLimit = 20;
- bool diffPerLine = (cd.dend - cd.dbegin > LineLimit) ? true : false;
+ bool diffPerLine = IsDiffPerLine(m_ptBuf[0]->GetTableEditing(), cd);
int nLineBegin, nLineEnd;
if (!diffPerLine)
wd.beginline[file] = nLine;
wd.begin[file] = it->begin[file] - nOffsets[file][nLine-nLineBegin];
if (m_ptBuf[file]->GetLineLength(nLine) < wd.begin[file])
- wd.begin[file] = m_ptBuf[file]->GetLineLength(nLine);
+ {
+ if (wd.beginline[file] < m_ptBuf[file]->GetLineCount() - 1)
+ {
+ wd.begin[file] = 0;
+ wd.beginline[file]++;
+ }
+ else
+ {
+ wd.begin[file] = m_ptBuf[file]->GetLineLength(nLine);
+ }
+ }
for (; nLine < nLineEnd; nLine++)
{
wd.endline[file] = nLine;
wd.end[file] = it->end[file] + 1 - nOffsets[file][nLine-nLineBegin];
if (m_ptBuf[file]->GetLineLength(nLine) < wd.end[file])
- wd.end[file] = m_ptBuf[file]->GetLineLength(nLine);
+ {
+ if (wd.endline[file] < m_ptBuf[file]->GetLineCount() - 1)
+ {
+ wd.end[file] = 0;
+ wd.endline[file]++;
+ }
+ else
+ {
+ wd.end[file] = m_ptBuf[file]->GetLineLength(nLine);
+ }
+ }
}
wd.op = it->op;
ON_COMMAND(ID_REFRESH, OnRefresh)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
ON_COMMAND(ID_SELECTLINEDIFF, OnSelectLineDiff<false>)
- ON_UPDATE_COMMAND_UI(ID_SELECTPREVLINEDIFF, OnUpdateSelectLineDiff)
+ ON_UPDATE_COMMAND_UI(ID_SELECTLINEDIFF, OnUpdateSelectLineDiff)
ON_COMMAND(ID_SELECTPREVLINEDIFF, OnSelectLineDiff<true>)
ON_UPDATE_COMMAND_UI(ID_SELECTPREVLINEDIFF, OnUpdateSelectLineDiff)
ON_WM_CONTEXTMENU()
{
DIFFRANGE di;
- if (ptStart != ptEnd)
+ if (pd->EqualCurrentWordDiff(m_nThisPane, ptStart, ptEnd))
+ {
+ firstWordDiff = lastWordDiff = pd->GetCurrentWordDiff().nWordDiff;
+ }
+ else if (ptStart != ptEnd)
{
VERIFY(pd->m_diffList.GetDiff(firstDiff, di));
if (lastLineIsNotInDiff && (firstLineIsNotInDiff || (di.dbegin == firstLine && ptStart.x == 0)))
}
}
- if (IsSelection())
+ CPoint ptStart, ptEnd;
+ GetSelection(ptStart, ptEnd);
+ if (IsSelection() || pDoc->EqualCurrentWordDiff(srcPane, ptStart, ptEnd))
{
if (!m_bRectangularSelection)
{
// If one or more diffs inside selection OR
// there is an active diff OR
// cursor is inside diff
- if (IsSelection())
+ CPoint ptStart, ptEnd;
+ GetSelection(ptStart, ptEnd);
+ if (IsSelection() || GetDocument()->EqualCurrentWordDiff(m_nThisPane, ptStart, ptEnd))
{
if (m_bCurrentLineIsDiff || (m_pTextBuffer->GetLineFlags(m_ptSelStart.y) & LF_NONTRIVIAL_DIFF) != 0)
{
/// Enable select difference menuitem if current line is inside difference.
void CMergeEditView::OnUpdateSelectLineDiff(CCmdUI* pCmdUI)
{
- int line = GetCursorPos().y;
- bool enable = ((GetLineFlags(line) & (LF_DIFF | LF_GHOST)) != 0);
- if (GetDocument()->IsEditedAfterRescan(m_nThisPane))
- enable = false;
- pCmdUI->Enable(enable);
+ pCmdUI->Enable(!GetDocument()->IsEditedAfterRescan());
}
/**