OSDN Git Service

Add "Copy Selected Line(s) to/from Left/Right" feature ( #463) (#642)
authorelsonwei <elson.wei@gmail.com>
Sun, 21 Feb 2021 23:36:19 +0000 (07:36 +0800)
committerGitHub <noreply@github.com>
Sun, 21 Feb 2021 23:36:19 +0000 (08:36 +0900)
Src/Merge.rc
Src/MergeDoc.cpp
Src/MergeDoc.h
Src/MergeEditView.cpp
Src/MergeEditView.h
Src/resource.h

index e06e1c3..1f1b079 100644 (file)
@@ -71,6 +71,11 @@ BEGIN
         MENUITEM "Copy &from Left",             ID_COPY_FROM_LEFT\r
         MENUITEM "Copy fro&m Right",            ID_COPY_FROM_RIGHT\r
         MENUITEM SEPARATOR\r
+        MENUITEM "Copy Selected Line(s) to Right", ID_LINES_L2R\r
+        MENUITEM "Copy Selected Line(s) to Left", ID_LINES_R2L\r
+        MENUITEM "Copy Selected Line(s) from Left", ID_COPY_LINES_FROM_LEFT\r
+        MENUITEM "Copy Selected Line(s) from Right", ID_COPY_LINES_FROM_RIGHT\r
+        MENUITEM SEPARATOR\r
         MENUITEM "&Select Line Difference\tF4", ID_SELECTLINEDIFF\r
         MENUITEM "Add this change to Substitution &Filters", ID_ADD_TO_IGNORED_SUBSTITUTIONS\r
         MENUITEM SEPARATOR\r
index 5199f78..5832a0f 100644 (file)
@@ -827,7 +827,6 @@ void CMergeDoc::CopyAllList(int srcPane, int dstPane)
  * @param [in] firstDiff First diff copied (0-based index)
  * @param [in] lastDiff Last diff copied (0-based index)
  */
-void CMergeDoc::CopyMultipleList(int srcPane, int dstPane, int firstDiff, int lastDiff, int firstWordDiff, int lastWordDiff)
 {
 #ifdef _DEBUG
        if (firstDiff > lastDiff)
@@ -917,6 +916,84 @@ void CMergeDoc::CopyMultipleList(int srcPane, int dstPane, int firstDiff, int la
        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>
@@ -1212,6 +1289,99 @@ bool CMergeDoc::ListCopy(int srcPane, int dstPane, int nDiff /* = -1*/,
        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*/)
 {
index 3160ded..698dc8f 100644 (file)
@@ -171,9 +171,11 @@ public:
        bool Undo();
        void CopyAllList(int srcPane, int dstPane);
        void CopyMultipleList(int srcPane, int dstPane, int firstDiff, int lastDiff, int firstWordDiff = -1, int lastWordDiff = -1);
+       void CopyMultiplePartialList(int srcPane, int dstPane, int firstDiff, int lastDiff, int firstLineDiff = -1, int lastLineDiff = -1);
        void DoAutoMerge(int dstPane);
        bool SanityCheckDiff(DIFFRANGE dr) const;
        bool WordListCopy(int srcPane, int dstPane, int nDiff, int nFirstWordDiff, int nLastWordDiff, const std::vector<int> *pWordDiffIndice, bool bGroupWithPrevious = false, bool bUpdateView = true);
+       bool PartialListCopy(int srcPane, int dstPane, int nDiff, int firstLine, int lastLine = -1, bool bGroupWithPrevious = false, bool bUpdateView = true);
        bool ListCopy(int srcPane, int dstPane, int nDiff = -1, bool bGroupWithPrevious = false, bool bUpdateView = true);
        bool TrySaveAs(String& strPath, int &nLastErrorCode, String & sError,
                int nBuffer, PackingInfo * pInfoTempUnpacker);
index 0f62045..5db4e10 100644 (file)
@@ -138,12 +138,20 @@ BEGIN_MESSAGE_MAP(CMergeEditView, CCrystalEditViewEx)
        ON_UPDATE_COMMAND_UI(ID_AUTO_MERGE, OnUpdateAutoMerge)
        ON_COMMAND(ID_L2R, OnL2r)
        ON_UPDATE_COMMAND_UI(ID_L2R, OnUpdateL2r)
+       ON_COMMAND(ID_LINES_L2R, OnLinesL2r)
+       ON_UPDATE_COMMAND_UI(ID_LINES_L2R, OnUpdateLinesL2r)
        ON_COMMAND(ID_R2L, OnR2l)
        ON_UPDATE_COMMAND_UI(ID_R2L, OnUpdateR2l)
+       ON_COMMAND(ID_LINES_R2L, OnLinesR2l)
+       ON_UPDATE_COMMAND_UI(ID_LINES_R2L, OnUpdateLinesR2l)
        ON_COMMAND(ID_COPY_FROM_LEFT, OnCopyFromLeft)
        ON_UPDATE_COMMAND_UI(ID_COPY_FROM_LEFT, OnUpdateCopyFromLeft)
+       ON_COMMAND(ID_COPY_LINES_FROM_LEFT, OnCopyLinesFromLeft)
+       ON_UPDATE_COMMAND_UI(ID_COPY_LINES_FROM_LEFT, OnUpdateCopyLinesFromLeft)
        ON_COMMAND(ID_COPY_FROM_RIGHT, OnCopyFromRight)
        ON_UPDATE_COMMAND_UI(ID_COPY_FROM_RIGHT, OnUpdateCopyFromRight)
+       ON_COMMAND(ID_COPY_LINES_FROM_RIGHT, OnCopyLinesFromRight)
+       ON_UPDATE_COMMAND_UI(ID_COPY_LINES_FROM_RIGHT, OnUpdateCopyLinesFromRight)
        ON_COMMAND(ID_ADD_SYNCPOINT, OnAddSyncPoint)
        ON_COMMAND(ID_CLEAR_SYNCPOINTS, OnClearSyncPoints)
        ON_UPDATE_COMMAND_UI(ID_CLEAR_SYNCPOINTS, OnUpdateClearSyncPoints)
@@ -497,6 +505,42 @@ void CMergeEditView::GetFullySelectedDiffs(int & firstDiff, int & lastDiff, int
        ASSERT(firstDiff != -1 ? firstWordDiff != -1 : true);
 }
 
+void CMergeEditView::GetSelectedDiffs(int & firstDiff, int & lastDiff)
+{
+       firstDiff = -1;
+       lastDiff = -1;
+
+       CMergeDoc *pd = GetDocument();
+       const int nDiffs = pd->m_diffList.GetSignificantDiffs();
+       if (nDiffs == 0)
+               return;
+
+       int firstLine, lastLine;
+       CPoint ptStart, ptEnd;
+       GetSelection(ptStart, ptEnd);
+       firstLine = ptStart.y;
+       lastLine = ptEnd.y;
+
+       firstDiff = pd->m_diffList.LineToDiff(firstLine);
+       if (firstDiff == -1)
+       {
+               firstDiff = pd->m_diffList.NextSignificantDiffFromLine(firstLine);
+               if (firstDiff == -1)
+                       return;
+       }
+       lastDiff = pd->m_diffList.LineToDiff(lastLine);
+       if (lastDiff == -1)
+               lastDiff = pd->m_diffList.PrevSignificantDiffFromLine(lastLine);
+       if (lastDiff < firstDiff)
+       {
+               firstDiff = -1;
+               return;
+       }
+
+       ASSERT(firstDiff == -1 ? (lastDiff  == -1) : true);
+       ASSERT(lastDiff  == -1 ? (firstDiff == -1) : true);
+}
+
 std::map<int, std::vector<int>> CMergeEditView::GetColumnSelectedWordDiffIndice()
 {
        CMergeDoc *pDoc = GetDocument();
@@ -1864,7 +1908,7 @@ void CMergeEditView::OnRButtonDown(UINT nFlags, CPoint point)
        DeselectDiffIfCursorNotInCurrentDiff();
 }
 
-void CMergeEditView::OnX2Y(int srcPane, int dstPane)
+void CMergeEditView::OnX2Y(int srcPane, int dstPane, bool selectedLineOnly)
 {
        // Check that right side is not readonly
        if (IsReadOnly(dstPane))
@@ -1890,23 +1934,36 @@ void CMergeEditView::OnX2Y(int srcPane, int dstPane)
        {
                if (!m_bRectangularSelection)
                {
-                       int firstDiff, lastDiff, firstWordDiff, lastWordDiff;
-                       GetFullySelectedDiffs(firstDiff, lastDiff, firstWordDiff, lastWordDiff);
-                       if (firstDiff != -1 && lastDiff != -1)
+                       if (selectedLineOnly)
                        {
-                               CWaitCursor waitstatus;
-                               
-                               // Setting CopyFullLine (OPT_COPY_FULL_LINE)
-                               // restore old copy behaviour (always copy "full line" instead of "selected text only"), with a hidden option
-                               if (GetOptionsMgr()->GetBool(OPT_COPY_FULL_LINE))
+                               int firstDiff, lastDiff;
+                               GetSelectedDiffs(firstDiff, lastDiff);
+                               if (firstDiff != -1 && lastDiff != -1)
                                {
-                                       // old behaviour: copy full line
-                                       pDoc->CopyMultipleList(srcPane, dstPane, firstDiff, lastDiff);
+                                       CWaitCursor waitstatus;
+                                       pDoc->CopyMultiplePartialList(srcPane, dstPane, firstDiff, lastDiff, ptStart.y, ptEnd.y);
                                }
-                               else
+                       }
+                       else
+                       {
+                               int firstDiff, lastDiff, firstWordDiff, lastWordDiff;
+                               GetFullySelectedDiffs(firstDiff, lastDiff, firstWordDiff, lastWordDiff);
+                               if (firstDiff != -1 && lastDiff != -1)
                                {
-                                       // new behaviour: copy selected text only
-                                       pDoc->CopyMultipleList(srcPane, dstPane, firstDiff, lastDiff, firstWordDiff, lastWordDiff);
+                                       CWaitCursor waitstatus;
+                                       
+                                       // Setting CopyFullLine (OPT_COPY_FULL_LINE)
+                                       // restore old copy behaviour (always copy "full line" instead of "selected text only"), with a hidden option
+                                       if (GetOptionsMgr()->GetBool(OPT_COPY_FULL_LINE))
+                                       {
+                                               // old behaviour: copy full line
+                                               pDoc->CopyMultipleList(srcPane, dstPane, firstDiff, lastDiff);
+                                       }
+                                       else
+                                       {
+                                               // new behaviour: copy selected text only
+                                               pDoc->CopyMultipleList(srcPane, dstPane, firstDiff, lastDiff, firstWordDiff, lastWordDiff);
+                                       }
                                }
                        }
                }
@@ -1923,8 +1980,16 @@ void CMergeEditView::OnX2Y(int srcPane, int dstPane)
        }
        else if (currentDiff != -1 && pDoc->m_diffList.IsDiffSignificant(currentDiff))
        {
-               CWaitCursor waitstatus;
-               pDoc->ListCopy(srcPane, dstPane, currentDiff);
+               if (selectedLineOnly)
+               {
+                       CWaitCursor waitstatus;
+                       pDoc->PartialListCopy(srcPane, dstPane, currentDiff, ptStart.y, ptEnd.y);
+               }
+               else
+               {
+                       CWaitCursor waitstatus;
+                       pDoc->ListCopy(srcPane, dstPane, currentDiff);
+               }
        }
 }
 
@@ -1988,6 +2053,18 @@ void CMergeEditView::OnUpdateL2r(CCmdUI* pCmdUI)
        OnUpdateX2Y(m_nThisPane < GetDocument()->m_nBuffers - 1 ? m_nThisPane + 1 : GetDocument()->m_nBuffers - 1, pCmdUI);
 }
 
+void CMergeEditView::OnLinesL2r()
+{
+       int dstPane = (m_nThisPane < GetDocument()->m_nBuffers - 1) ? m_nThisPane + 1 : GetDocument()->m_nBuffers - 1;
+       int srcPane = dstPane - 1;
+       OnX2Y(srcPane, dstPane, true);
+}
+
+void CMergeEditView::OnUpdateLinesL2r(CCmdUI* pCmdUI)
+{
+       OnUpdateX2Y(m_nThisPane < GetDocument()->m_nBuffers - 1 ? m_nThisPane + 1 : GetDocument()->m_nBuffers - 1, pCmdUI);
+}
+
 /**
  * @brief Copy diff from right pane to left pane
  *
@@ -2014,6 +2091,18 @@ void CMergeEditView::OnUpdateR2l(CCmdUI* pCmdUI)
        OnUpdateX2Y(m_nThisPane > 0 ? m_nThisPane - 1 : 0, pCmdUI);
 }
 
+void CMergeEditView::OnLinesR2l()
+{
+       int dstPane = (m_nThisPane > 0) ? m_nThisPane - 1 : 0;
+       int srcPane = dstPane + 1;
+       OnX2Y(srcPane, dstPane, true);
+}
+
+void CMergeEditView::OnUpdateLinesR2l(CCmdUI* pCmdUI)
+{
+       OnUpdateX2Y(m_nThisPane > 0 ? m_nThisPane - 1 : 0, pCmdUI);
+}
+
 void CMergeEditView::OnCopyFromLeft()
 {
        int dstPane = m_nThisPane;
@@ -2033,6 +2122,25 @@ void CMergeEditView::OnUpdateCopyFromLeft(CCmdUI* pCmdUI)
                OnUpdateX2Y(dstPane, pCmdUI);
 }
 
+void CMergeEditView::OnCopyLinesFromLeft()
+{
+       int dstPane = m_nThisPane;
+       int srcPane = dstPane - 1;
+       if (srcPane < 0)
+               return;
+       OnX2Y(srcPane, dstPane, true);
+}
+
+void CMergeEditView::OnUpdateCopyLinesFromLeft(CCmdUI* pCmdUI)
+{
+       int dstPane = m_nThisPane;
+       int srcPane = dstPane - 1;
+       if (srcPane < 0)
+               pCmdUI->Enable(false);
+       else
+               OnUpdateX2Y(dstPane, pCmdUI);
+}
+
 void CMergeEditView::OnCopyFromRight()
 {
        int dstPane = m_nThisPane;
@@ -2052,6 +2160,25 @@ void CMergeEditView::OnUpdateCopyFromRight(CCmdUI* pCmdUI)
                OnUpdateX2Y(dstPane, pCmdUI);
 }
 
+void CMergeEditView::OnCopyLinesFromRight()
+{
+       int dstPane = m_nThisPane;
+       int srcPane = dstPane + 1;
+       if (srcPane >= GetDocument()->m_nBuffers)
+               return;
+       OnX2Y(srcPane, dstPane, true);
+}
+
+void CMergeEditView::OnUpdateCopyLinesFromRight(CCmdUI* pCmdUI)
+{
+       int dstPane = m_nThisPane;
+       int srcPane = dstPane + 1;
+       if (srcPane >= GetDocument()->m_nBuffers)
+               pCmdUI->Enable(false);
+       else
+               OnUpdateX2Y(dstPane, pCmdUI);
+}
+
 /**
  * @brief Copy all diffs from right pane to left pane
  */
@@ -2988,11 +3115,15 @@ void CMergeEditView::OnContextMenu(CWnd* pWnd, CPoint point)
        {
                menu.RemoveMenu(ID_COPY_FROM_RIGHT, MF_BYCOMMAND);
                menu.RemoveMenu(ID_COPY_FROM_LEFT, MF_BYCOMMAND);
+               menu.RemoveMenu(ID_COPY_LINES_FROM_RIGHT, MF_BYCOMMAND);
+               menu.RemoveMenu(ID_COPY_LINES_FROM_LEFT, MF_BYCOMMAND);
        }
        if (m_nThisPane == GetDocument()->m_nBuffers - 1)
        {
                menu.RemoveMenu(ID_COPY_FROM_LEFT, MF_BYCOMMAND);
                menu.RemoveMenu(ID_COPY_FROM_RIGHT, MF_BYCOMMAND);
+               menu.RemoveMenu(ID_COPY_LINES_FROM_RIGHT, MF_BYCOMMAND);
+               menu.RemoveMenu(ID_COPY_LINES_FROM_LEFT, MF_BYCOMMAND);
        }
 
        // Remove "Go to Moved Line Between Middle and Right" if in 2-way file comparison.
index e2cd3ea..d567373 100644 (file)
@@ -114,6 +114,7 @@ public:
        const CCrystalTextBuffer *LocateTextBuffer () const { return const_cast<CMergeEditView *>(this)->LocateTextBuffer(); };
        void GetFullySelectedDiffs(int & firstDiff, int & lastDiff);
        void GetFullySelectedDiffs(int & firstDiff, int & lastDiff, int & firstWordDiff,  int & lastWordDiff, const CPoint *pptStart = nullptr, const CPoint *ppEnd = nullptr);
+       void GetSelectedDiffs(int & firstDiff, int & lastDiff);
        std::map<int, std::vector<int>> GetColumnSelectedWordDiffIndice();
        CString GetSelectedText();
        CString GetLineText(int idx);
@@ -260,16 +261,24 @@ protected:
        afx_msg void OnUpdateAllRight(CCmdUI* pCmdUI);
        afx_msg void OnAutoMerge();
        afx_msg void OnUpdateAutoMerge(CCmdUI* pCmdUI);
-       afx_msg void OnX2Y(int srcPane, int dstPane);
+       afx_msg void OnX2Y(int srcPane, int dstPane, bool selectedLineOnly = false);
        afx_msg void OnUpdateX2Y(int dstPane, CCmdUI* pCmdUI);
        afx_msg void OnL2r();
        afx_msg void OnUpdateL2r(CCmdUI* pCmdUI);
+       afx_msg void OnLinesL2r();
+       afx_msg void OnUpdateLinesL2r(CCmdUI* pCmdUI);
        afx_msg void OnR2l();
        afx_msg void OnUpdateR2l(CCmdUI* pCmdUI);
+       afx_msg void OnLinesR2l();
+       afx_msg void OnUpdateLinesR2l(CCmdUI* pCmdUI);
        afx_msg void OnCopyFromLeft();
        afx_msg void OnUpdateCopyFromLeft(CCmdUI* pCmdUI);
+       afx_msg void OnCopyLinesFromLeft();
+       afx_msg void OnUpdateCopyLinesFromLeft(CCmdUI* pCmdUI);
        afx_msg void OnCopyFromRight();
        afx_msg void OnUpdateCopyFromRight(CCmdUI* pCmdUI);
+       afx_msg void OnCopyLinesFromRight();
+       afx_msg void OnUpdateCopyLinesFromRight(CCmdUI* pCmdUI);
        afx_msg void OnAddSyncPoint();
        afx_msg void OnClearSyncPoints();
        afx_msg void OnUpdateClearSyncPoints(CCmdUI* pCmdUI);
index 3405b3b..8200641 100644 (file)
 #define IDS_OCRRESULT_TEXTONLY          34186\r
 #define IDS_OCRRESULT_POS_LINE          34187\r
 #define IDS_OCRRESULT_POS_WORD          34188\r
+#define ID_LINES_R2L                    34190\r
+#define ID_LINES_L2R                    34191\r
+#define ID_COPY_LINES_FROM_LEFT         34192\r
+#define ID_COPY_LINES_FROM_RIGHT        34193\r
 \r
 // Next default values for new objects\r
 // \r