OSDN Git Service

- Fix the problem that pressing the F4 key did not always move to the next word diff.
authorTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sun, 9 Aug 2020 04:08:34 +0000 (13:08 +0900)
committerTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sun, 9 Aug 2020 04:08:34 +0000 (13:08 +0900)
- Move to the word diff at the beginning of the next diff block when pressing F4 on a line that has no differences, .
- Extend F4 key movement range from a diff block to the whole file

Src/MergeDoc.cpp
Src/MergeDoc.h
Src/MergeDocLineDiffs.cpp
Src/MergeEditView.cpp

index 9c92433..8965406 100644 (file)
@@ -121,6 +121,7 @@ END_MESSAGE_MAP()
 CMergeDoc::CMergeDoc()
 : m_bEnableRescan(true)
 , m_nCurDiff(-1)
+, m_CurWordDiff{ -1, static_cast<size_t>(-1), -1 }
 , m_pDirDoc(nullptr)
 , m_bMixedEol(false)
 , m_pInfoUnpacker(new PackingInfo)
@@ -144,7 +145,6 @@ CMergeDoc::CMergeDoc()
                m_bEditAfterRescan[nBuffer] = false;
        }
 
-       m_nCurDiff=-1;
        m_bEnableRescan = true;
        // COleDateTime m_LastRescan
        curUndo = undoTgt.begin();
@@ -356,6 +356,7 @@ int CMergeDoc::Rescan(bool &bBinary, IDENTLEVEL &identical,
        // Clear diff list
        m_diffList.Clear();
        m_nCurDiff = -1;
+       m_CurWordDiff = { -1, static_cast<size_t>(-1), -1 };
        // Clear moved lines lists
        if (m_diffWrapper.GetDetectMovedBlocks())
        {
@@ -3075,6 +3076,20 @@ void CMergeDoc::SetEditedAfterRescan(int nBuffer)
        m_bEditAfterRescan[nBuffer] = true;
 }
 
+bool CMergeDoc::IsEditedAfterRescan(int nBuffer) const
+{
+       if (nBuffer >= 0 && nBuffer < m_nBuffers)
+               return m_bEditAfterRescan[nBuffer];
+
+       for (nBuffer = 0; nBuffer < m_nBuffers; ++nBuffer)
+       {
+               if (m_bEditAfterRescan[nBuffer])
+                       return true;
+       }
+
+       return false;
+}
+
 /**
  * @brief Update document filenames to title
  */
index 3e315cf..6ceb33f 100644 (file)
@@ -104,6 +104,15 @@ struct WordDiff {
        }
 };
 
+struct CurrentWordDiff
+{
+       int nDiff;
+       size_t nWordDiff;
+       int nPane;
+       CPoint ptStart;
+       CPoint ptEnd;
+};
+
 struct DiffFileInfo;
 class CMergeEditView;
 class PackingInfo;
@@ -173,7 +182,7 @@ public:
        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);
@@ -272,6 +281,11 @@ public:
        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;
@@ -306,6 +320,7 @@ private:
 // 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;
index 3f96cbc..9bbb07e 100644 (file)
@@ -66,6 +66,11 @@ void CMergeDoc::Showlinediff(CMergeEditView *pView, bool bReversed)
                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)
@@ -76,51 +81,163 @@ void CMergeDoc::Computelinediff(CMergeEditView *pView, CRect rc[], bool bReverse
        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 */)
@@ -140,10 +257,9 @@ 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);
 
@@ -190,8 +306,7 @@ std::vector<WordDiff> CMergeDoc::GetWordDiffArray(int nLineIndex)
        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)
@@ -246,7 +361,17 @@ std::vector<WordDiff> CMergeDoc::GetWordDiffArray(int nLineIndex)
                        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++)
                        {
@@ -256,7 +381,17 @@ std::vector<WordDiff> CMergeDoc::GetWordDiffArray(int nLineIndex)
                        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;
 
index ca62b92..c046aff 100644 (file)
@@ -152,7 +152,7 @@ BEGIN_MESSAGE_MAP(CMergeEditView, CCrystalEditViewEx)
        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()
@@ -393,7 +393,11 @@ void CMergeEditView::GetFullySelectedDiffs(int & firstDiff, int & lastDiff, int
        {
                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)))
@@ -1847,7 +1851,9 @@ void CMergeEditView::OnX2Y(int srcPane, int dstPane)
                }
        }
 
-       if (IsSelection())
+       CPoint ptStart, ptEnd;
+       GetSelection(ptStart, ptEnd);
+       if (IsSelection() || pDoc->EqualCurrentWordDiff(srcPane, ptStart, ptEnd))
        {
                if (!m_bRectangularSelection)
                {
@@ -1885,7 +1891,9 @@ void CMergeEditView::OnUpdateX2Y(int dstPane, CCmdUI* pCmdUI)
                // 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)
                        {
@@ -2640,11 +2648,7 @@ void CMergeEditView::OnSelectLineDiff()
 /// 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());
 }
 
 /**