OSDN Git Service

Plugins: Add DisassembleJVM, DisassembleIL and DisassembleNative plugin (3)
[winmerge-jp/winmerge-jp.git] / Src / GhostTextView.cpp
index 8d287ec..d16f183 100644 (file)
@@ -7,21 +7,7 @@
 //    WinMerge:  an interactive diff/merge utility
 //    Copyright (C) 1997-2000  Thingamahoochie Software
 //    Author: Dean Grimm
-//
-//    This program is free software; you can redistribute it and/or modify
-//    it under the terms of the GNU General Public License as published by
-//    the Free Software Foundation; either version 2 of the License, or
-//    (at your option) any later version.
-//
-//    This program is distributed in the hope that it will be useful,
-//    but WITHOUT ANY WARRANTY; without even the implied warranty of
-//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//    GNU General Public License for more details.
-//
-//    You should have received a copy of the GNU General Public License
-//    along with this program; if not, write to the Free Software
-//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
+//    SPDX-License-Identifier: GPL-2.0-or-later
 /////////////////////////////////////////////////////////////////////////////
 
 
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
 #endif
 
 
 IMPLEMENT_DYNCREATE (CGhostTextView, CCrystalEditViewEx)
 
+/** 
+ * @brief Constructor, initializes members.
+ */
+CGhostTextView::CGhostTextView()
+: m_pGhostTextBuffer(nullptr)
+, m_ptCursorPosPushed{}
+, m_ptSelStartPushed{}
+, m_ptSelEndPushed{}
+, m_ptAnchorPushed{}
+, m_ptDraggedTextBeginPushed{}
+, m_ptDraggedTextEndPushed{}
+, m_ptSavedCaretPosPushed{}
+, m_ptSavedSelStartPushed{}
+, m_ptSavedSelEndPushed{}
+, m_ptLastChangePushed{}
+, m_nTopSubLinePushed(0)
+, m_nOffsetCharPushed(0)
+{
+}
 
+void CGhostTextView::
+ReAttachToBuffer (CCrystalTextBuffer * pBuf /*= nullptr*/ )
+{
+       if (pBuf == nullptr)
+       {
+               pBuf = LocateTextBuffer ();
+               // ...
+       }
+       m_pGhostTextBuffer = dynamic_cast<CGhostTextBuffer*> (pBuf);
+       CCrystalEditViewEx::ReAttachToBuffer(pBuf);
+}
 
 void CGhostTextView::
-AttachToBuffer (CCrystalTextBuffer * pBuf /*= NULL*/ )
+AttachToBuffer (CCrystalTextBuffer * pBuf /*= nullptr*/ )
 {
-       if (pBuf == NULL)
+       if (pBuf == nullptr)
        {
                pBuf = LocateTextBuffer ();
                // ...
@@ -55,18 +69,10 @@ AttachToBuffer (CCrystalTextBuffer * pBuf /*= NULL*/ )
 void CGhostTextView::
 DetachFromBuffer ()
 {
-       if (m_pGhostTextBuffer != NULL)
-               m_pGhostTextBuffer = NULL;
+       m_pGhostTextBuffer = nullptr;
        CCrystalEditViewEx::DetachFromBuffer();
 }
 
-
-
-
-
-
-
-
 void CGhostTextView::popPosition(SCursorPushed Ssrc, CPoint & pt)
 {
        pt.x = Ssrc.x;
@@ -78,16 +84,20 @@ void CGhostTextView::popPosition(SCursorPushed Ssrc, CPoint & pt)
                pt.y = GetLineCount()-1;
                pt.x = GetLineLength(pt.y);
        }
+       if (pt.y < 0)
+               pt.y = 0;
 }
 
 void CGhostTextView::pushPosition(SCursorPushed & Sdest, CPoint pt)
 {
        Sdest.x = pt.x;
-       Sdest.y = m_pGhostTextBuffer->ComputeRealLineAndGhostAdjustment(pt.y, Sdest.nToFirstReal);
+       if (m_pGhostTextBuffer)
+               Sdest.y = m_pGhostTextBuffer->ComputeRealLineAndGhostAdjustment(pt.y, Sdest.nToFirstReal);
+       else
+               Sdest.y = pt.y;
 }
 
-void CGhostTextView::
-PopCursors ()
+void CGhostTextView::PopCursors ()
 {
        CPoint ptCursorLast = m_ptCursorLast;
        popPosition(m_ptCursorPosPushed, ptCursorLast);
@@ -106,19 +116,19 @@ PopCursors ()
        // SetSelection (ptCursorLast, ptCursorLast);
        // SetAnchor (ptCursorLast);
 
-       if (m_bDraggingText == TRUE)
+       if (m_bDraggingText)
        {
                popPosition(m_ptDraggedTextBeginPushed, m_ptDraggedTextBegin);
                ASSERT_VALIDTEXTPOS(m_ptDraggedTextBegin);
                popPosition(m_ptDraggedTextEndPushed, m_ptDraggedTextEnd);
                ASSERT_VALIDTEXTPOS(m_ptDraggedTextEnd);
        }
-       if (m_bDropPosVisible == TRUE)
+       if (m_bDropPosVisible)
        {
                popPosition(m_ptSavedCaretPosPushed, m_ptSavedCaretPos);
                ASSERT_VALIDTEXTPOS(m_ptSavedCaretPos);
        }
-       if (m_bSelectionPushed == TRUE)
+       if (m_bSelectionPushed)
        {
                popPosition(m_ptSavedSelStartPushed, m_ptSavedSelStart);
                ASSERT_VALIDTEXTPOS(m_ptSavedSelStart);
@@ -135,29 +145,47 @@ PopCursors ()
                ASSERT_VALIDTEXTPOS(ptLastChange);
        }
        m_pGhostTextBuffer->RestoreLastChangePos(ptLastChange);
+
+       // restore the scrolling position
+       m_nTopSubLine = m_nTopSubLinePushed;
+       if (m_nTopSubLine >= GetSubLineCount())
+               m_nTopSubLine = GetSubLineCount() - 1;
+       if (m_nTopSubLine < 0)
+               m_nTopSubLine = 0;
+       int nDummy;
+       GetLineBySubLine( m_nTopSubLine, m_nTopLine, nDummy );
+       const int nMaxLineLength = GetMaxLineLength(m_nTopLine, GetScreenLines());
+       m_nOffsetChar = (m_nOffsetCharPushed < nMaxLineLength) ? m_nOffsetCharPushed : nMaxLineLength;
+    RecalcVertScrollBar(true);
+    InvalidateHorzScrollBar();
 }
 
-void CGhostTextView::
-PushCursors ()
+void CGhostTextView::PushCursors ()
 {
        pushPosition(m_ptCursorPosPushed, m_ptCursorPos);
        pushPosition(m_ptSelStartPushed, m_ptSelStart);
        pushPosition(m_ptSelEndPushed, m_ptSelEnd);
        pushPosition(m_ptAnchorPushed, m_ptAnchor);
-       if (m_bDraggingText == TRUE)
+       if (m_bDraggingText)
        {
                pushPosition(m_ptDraggedTextBeginPushed, m_ptDraggedTextBegin);
                pushPosition(m_ptDraggedTextEndPushed, m_ptDraggedTextEnd);
        }
-       if (m_bDropPosVisible == TRUE)
+       if (m_bDropPosVisible)
+       {
                pushPosition(m_ptSavedCaretPosPushed, m_ptSavedCaretPos);
-       if (m_bSelectionPushed == TRUE)
+       }
+       if (m_bSelectionPushed)
        {
                pushPosition(m_ptSavedSelStartPushed, m_ptSavedSelStart);
                pushPosition(m_ptSavedSelEndPushed, m_ptSavedSelEnd);
        }
 
-       pushPosition(m_ptLastChangePushed, m_pGhostTextBuffer->GetLastChangePos());
+       pushPosition(m_ptLastChangePushed, m_pGhostTextBuffer ? m_pGhostTextBuffer->GetLastChangePos() : CPoint{0, 0});
+
+       // and top line positions
+       m_nTopSubLinePushed = m_nTopSubLine;
+       m_nOffsetCharPushed = m_nOffsetChar;
 }
 
 
@@ -165,6 +193,8 @@ PushCursors ()
 
 int CGhostTextView::ComputeRealLine (int nApparentLine) const
 {
+       if (m_pGhostTextBuffer == nullptr)
+               return 0;
        return m_pGhostTextBuffer->ComputeRealLine(nApparentLine);
 }
 
@@ -173,32 +203,89 @@ int CGhostTextView::ComputeApparentLine (int nRealLine) const
        return m_pGhostTextBuffer->ComputeApparentLine(nRealLine);
 }
 
-void CGhostTextView::GetTextWithoutEmptys (int nStartLine, int nStartChar, int nEndLine, int nEndChar, CString &text, int nCrlfStyle /*=CRLF_STYLE_AUTOMATIC*/ )
+void CGhostTextView::GetTextWithoutEmptys (int nStartLine, int nStartChar,
+               int nEndLine, int nEndChar, CString &text,
+               CRLFSTYLE nCrlfStyle /*= CRLFSTYLE::AUTOMATIC*/,
+               bool bExcludeInvisibleLines /*= true*/)
 {
-  if (m_pGhostTextBuffer != NULL)
-    m_pGhostTextBuffer->GetTextWithoutEmptys (nStartLine, nStartChar, nEndLine, nEndChar, text, nCrlfStyle);
+  if (m_pGhostTextBuffer != nullptr)
+    m_pGhostTextBuffer->GetTextWithoutEmptys (nStartLine, nStartChar, nEndLine, nEndChar, text, nCrlfStyle, bExcludeInvisibleLines);
   else
     text = _T ("");
 }
 
+void CGhostTextView::GetTextWithoutEmptysInColumnSelection (CString & text, bool bExcludeInvisibleLines /*= true*/)
+{
+       if (m_pGhostTextBuffer == nullptr)
+       {
+               text = _T ("");
+               return;
+       }
+
+       PrepareSelBounds ();
+
+       CString sEol = m_pGhostTextBuffer->GetStringEol (CRLFSTYLE::DOS);
+
+       int nBufSize = 1;
+       for (int L = m_ptDrawSelStart.y; L <= m_ptDrawSelEnd.y; L++)
+               nBufSize += GetLineLength (L) + sEol.GetLength ();
+       LPTSTR pszBuf = text.GetBuffer (nBufSize);
+
+       for (int I = m_ptDrawSelStart.y; I <= m_ptDrawSelEnd.y; I++)
+       {
+               // exclude ghost lines
+               if ((GetLineFlags(I) & LF_GHOST) || (bExcludeInvisibleLines && (GetLineFlags(I) & LF_INVISIBLE)))
+                       continue;
+
+               int nSelLeft, nSelRight;
+               GetColumnSelection (I, nSelLeft, nSelRight);
+               memcpy (pszBuf, GetLineChars (I) + nSelLeft, sizeof (TCHAR) * (nSelRight - nSelLeft));
+               pszBuf += (nSelRight - nSelLeft);
+               memcpy (pszBuf, sEol, sizeof (TCHAR) * sEol.GetLength ());
+               pszBuf += sEol.GetLength ();
+       }
+       pszBuf[0] = 0;
+       text.ReleaseBuffer ();
+       text.FreeExtra ();
+}
+
 HGLOBAL CGhostTextView::PrepareDragData ()
 {
        PrepareSelBounds ();
        if (m_ptDrawSelStart == m_ptDrawSelEnd)
-               return NULL;
+               return nullptr;
 
        CString text;
        GetTextWithoutEmptys (m_ptDrawSelStart.y, m_ptDrawSelStart.x, m_ptDrawSelEnd.y, m_ptDrawSelEnd.x, text);
-       HGLOBAL hData =::GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, (_tcslen (text)+1)*sizeof(TCHAR));
-       if (hData == NULL)
-               return NULL;
+       int cchText = text.GetLength();
+       SIZE_T cbData = (cchText + 1) * sizeof(TCHAR);
+       HGLOBAL hData =::GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, cbData);
+       if (hData == nullptr)
+               return nullptr;
 
        LPTSTR pszData = (LPTSTR)::GlobalLock (hData);
-       _tcscpy (pszData, text.GetBuffer (0));
-       text.ReleaseBuffer ();
+       if (pszData != nullptr)
+               memcpy (pszData, text, cbData);
        ::GlobalUnlock (hData);
 
        m_ptDraggedTextBegin = m_ptDrawSelStart;
        m_ptDraggedTextEnd = m_ptDrawSelEnd;
        return hData;
 }
+
+/**
+ * @brief Draw selection margin. 
+ * @param [in] pdc         Pointer to draw context.
+ * @param [in] rect        The rectangle to draw.
+ * @param [in] nLineIndex  Index of line in view.
+ * @param [in] nLineNumber Line number to display. if -1, it's not displayed.
+ */
+void CGhostTextView::DrawMargin (const CRect & rect, int nLineIndex, int nLineNumber)
+{
+       int nRealLineNumber;
+       if (nLineIndex < 0 || GetLineFlags(nLineIndex) & LF_GHOST)
+               nRealLineNumber = -1;
+       else
+               nRealLineNumber = ComputeRealLine(nLineIndex) + 1;
+       CCrystalTextView::DrawMargin(rect, nLineIndex, nRealLineNumber);
+}