OSDN Git Service

crystaledit: Use GetProfile*()/WriteProfile*() to read and write the registry wheneve...
[winmerge-jp/winmerge-jp.git] / Src / GhostTextBuffer.cpp
index f7139a3..99806a3 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
 /////////////////////////////////////////////////////////////////////////////
 /** 
  * @file  GhostTextBuffer.cpp
@@ -75,7 +61,7 @@ bool CGhostTextBuffer::InternalInsertGhostLine (CCrystalTextView * pSource,
        context.m_ptEnd.y = nLine + 1;
 
        CCrystalTextBuffer::InsertLine (_T(""), 0, nLine);
-       if (pSource != NULL)
+       if (pSource != nullptr)
                UpdateViews (pSource, &context, UPDATE_HORZRANGE | UPDATE_VERTRANGE, nLine);
 
        return true;
@@ -112,7 +98,7 @@ bool CGhostTextBuffer::InternalDeleteGhostLine (CCrystalTextView * pSource,
        vector<LineInfo>::iterator iterEnd = iterBegin + nCount;
        m_aLines.erase(iterBegin, iterEnd);
 
-       if (pSource != NULL)
+       if (pSource != nullptr)
        {
                CDeleteContext context;
                context.m_ptStart.y = nLine;
@@ -123,7 +109,7 @@ bool CGhostTextBuffer::InternalDeleteGhostLine (CCrystalTextView * pSource,
                if (nLine == GetLineCount())
                        nLine--;
                // The last parameter is optimization  
-               //   - don't recompute lines preceeding the removed line.
+               //   - don't recompute lines preceding the removed line.
                UpdateViews (pSource, &context, UPDATE_HORZRANGE | UPDATE_VERTRANGE,
                                nLine);
        }
@@ -135,18 +121,18 @@ bool CGhostTextBuffer::InternalDeleteGhostLine (CCrystalTextView * pSource,
  * @brief Get text of specified lines (ghost lines will not contribute to text).
  * 
  * @param nCrlfStyle determines the EOL type in the returned buffer.
- * If nCrlfStyle equals CRLF_STYLE_AUTOMATIC, we read the EOL from the line buffer
+ * If nCrlfStyle equals CRLFSTYLE::AUTOMATIC, we read the EOL from the line buffer
  * 
  * @note This function has its base in CrystalTextBuffer
  * CrystalTextBuffer::GetTextWithoutEmptys() is for a buffer with no ghost lines.
  * CrystalTextBuffer::GetText() returns text including ghost lines.
  * These two base functions never read the EOL from the line buffer, they
- * use CRLF_STYLE_DOS when nCrlfStyle equals CRLF_STYLE_AUTOMATIC.
+ * use CRLFSTYLE::DOS when nCrlfStyle equals CRLFSTYLE::AUTOMATIC.
  */
 void CGhostTextBuffer::                        /* virtual override */
 GetTextWithoutEmptys(int nStartLine, int nStartChar, 
                  int nEndLine, int nEndChar, 
-                 CString &text, CRLFSTYLE nCrlfStyle /*= CRLF_STYLE_AUTOMATIC */,
+                 CString &text, CRLFSTYLE nCrlfStyle /*= CRLFSTYLE::AUTOMATIC */,
                  bool bExcludeInvisibleLines /*= true*/) const
 {
        const size_t lines = m_aLines.size();
@@ -166,7 +152,7 @@ GetTextWithoutEmptys(int nStartLine, int nStartChar,
                nBufSize += (GetFullLineLength(i) + 2); // in case we insert EOLs
        LPTSTR pszBuf = text.GetBuffer(nBufSize);
 
-       if (nCrlfStyle != CRLF_STYLE_AUTOMATIC)
+       if (nCrlfStyle != CRLFSTYLE::AUTOMATIC)
        {
                // we must copy this EOL type only
                const CString sEol = GetStringEol (nCrlfStyle);
@@ -216,7 +202,7 @@ GetTextWithoutEmptys(int nStartLine, int nStartChar,
                                // (If this happens, editor probably has bug)
                                ASSERT(false);
                                CString sEol = GetStringEol (nCrlfStyle);
-                               CopyMemory(pszBuf, sEol, sEol.GetLength());
+                               CopyMemory(pszBuf, sEol, sEol.GetLength() * sizeof(TCHAR));
                                pszBuf += sEol.GetLength();
                        }
                }
@@ -273,7 +259,16 @@ InsertText (CCrystalTextView * pSource, int nLine,
                if (i >= 0 && !m_aLines[i].HasEol())
                        CCrystalTextBuffer::InsertText(pSource, i, GetLineLength(i), text, text.GetLength(), nEndLine, nEndChar, 0, bHistory);
                else if (!LineInfo::IsEol(pszText[cchText - 1]))
-                       CCrystalTextBuffer::InsertText(pSource, nLine, 0, text, text.GetLength(), nEndLine, nEndChar, 0, bHistory);
+               {
+                       auto findRealLine = [&](int nLine) {
+                               for (; nLine < GetLineCount(); ++nLine) { if ((GetLineFlags(nLine) & LF_GHOST) == 0) break; }
+                               if (nLine == GetLineCount())
+                                       return -1;
+                               return nLine;
+                       };
+                       if (findRealLine(nLine) != -1)
+                               CCrystalTextBuffer::InsertText(pSource, nLine, 0, text, text.GetLength(), nEndLine, nEndChar, 0, bHistory);
+               }
        }
 
        if (!CCrystalTextBuffer::InsertText (pSource, nLine, nPos, pszText,
@@ -299,7 +294,7 @@ InsertText (CCrystalTextView * pSource, int nLine,
                //      file.  Later (below), the Ghost status of both the first and last inserted 
                //      lines will get straightened out, with the trailing Ghost line becomming  
                //      a NULL line.
-               if ((GetLineFlags(nLine) & LF_GHOST) == 0)      // first line still marked GHOST
+               if ((GetLineFlags(nLine) & LF_GHOST) != 0)      // first line still marked GHOST
                        bSpecialLastLineHandling = false;
                else
                        bDiscrepancyInInsertedLines = false;
@@ -354,7 +349,7 @@ InsertText (CCrystalTextView * pSource, int nLine,
                
        if (bSpecialLastLineHandling)
        {
-               // By setting the last line (in this special case, see above) to NULL
+               // By setting the last line (in this special case, see above) to `nullptr`
                //      the line will eventually be removed or become an actual LF_GHOST line.
                int nLastLine = GetLineCount()-1;
                ASSERT(m_aLines[nLastLine].FullLength() == 0);
@@ -415,43 +410,13 @@ bool CGhostTextBuffer::                   /* virtual override */
 DeleteText2 (CCrystalTextView * pSource, int nStartLine, int nStartChar,
             int nEndLine, int nEndChar, int nAction /*= CE_ACTION_UNKNOWN*/, bool bHistory /*= true*/)
 {
-       if ((GetLineFlags(nEndLine) & LF_GHOST) == 0)
+       int const nLineCount = GetLineCount();
+       while (nEndLine < nLineCount - 1 && GetLineFlags(nEndLine) & LF_GHOST)
+               ++nEndLine;
+       if (!CCrystalTextBuffer::DeleteText2(pSource, nStartLine, nStartChar,
+               nEndLine, nEndChar, nAction, bHistory))
        {
-               if (!CCrystalTextBuffer::DeleteText2(pSource, nStartLine, nStartChar,
-                       nEndLine, nEndChar, nAction, bHistory))
-               {
-                       return false;
-               }
-       }
-       else
-       {
-               // if the last line in selection to be deleted is a ghost line, 
-               // the EOL of last real line in selection should not be deleted.
-               // Otherwise, a line with no EOL will appear.
-               int nEndLine2 = nEndLine;
-               int nEndChar2 = nEndChar;
-               for (; nEndLine2 >= nStartLine; --nEndLine2)
-               {
-                       if ((GetLineFlags(nEndLine2) & LF_GHOST) == 0)
-                               break;
-               }
-               if (nStartLine <= nEndLine2)
-               {
-                       if(nEndLine2 != nEndLine)
-                               nEndChar2 = GetLineLength(nEndLine2);
-                       if (!CCrystalTextBuffer::DeleteText2(pSource, nStartLine, nStartChar,
-                               nEndLine2, nEndChar2, nAction, bHistory))
-                       {
-                               return false;
-                       }
-                       InternalDeleteGhostLine(pSource, nStartLine + 1, nEndLine - (nEndLine2 + 1) + 1);
-               }
-               else
-               {
-                       if (bHistory && m_nUndoPosition < static_cast<int>(m_aUndoBuf.size()))
-                               m_aUndoBuf.resize(m_nUndoPosition);
-                       InternalDeleteGhostLine(pSource, nEndLine2 + 1, nEndLine - (nEndLine2 + 1));
-               }
+               return false;
        }
 
        if (nStartChar != 0 || nEndChar != 0)
@@ -816,30 +781,64 @@ OnNotifyLineHasBeenEdited(int nLine)
        return;
 }
 
-static int CountEol(LPCTSTR pszText, size_t cchText)
+void CGhostTextBuffer::
+CountEolAndLastLineLength(const CPoint& ptStartPos, LPCTSTR pszText, size_t cchText, int &nLastLineLength, int &nEol)
 {
-       int nEol = 0;
-       for (size_t nTextPos = 0; nTextPos < cchText; ++nTextPos)
+       nLastLineLength = 0;
+       nEol = 0;
+       if (m_bTableEditing && m_bAllowNewlinesInQuotes)
+       {
+               bool bInQuote = false;
+               const TCHAR* pszLine = m_aLines[ptStartPos.y].GetLine();
+               for (int j = 0; j < ptStartPos.x; ++j)
+               {
+                       if (pszLine[j] == m_cFieldEnclosure)
+                               bInQuote = !bInQuote;
+               }
+               for (size_t nTextPos = 0; nTextPos < cchText; ++nTextPos)
+               {
+                       if (pszText[nTextPos] == m_cFieldEnclosure)
+                               bInQuote = !bInQuote;
+                       if (!bInQuote && LineInfo::IsEol(pszText[nTextPos]))
+                       {
+                               if (nTextPos + 1 < cchText && LineInfo::IsDosEol(&pszText[nTextPos]))
+                                       ++nTextPos;
+                               ++nEol;
+                               nLastLineLength = 0;
+                       }
+                       else
+                               ++nLastLineLength;
+               }
+       }
+       else
        {
-               if (LineInfo::IsEol(pszText[nTextPos]))
+               for (size_t nTextPos = 0; nTextPos < cchText; ++nTextPos)
                {
-                       if (nTextPos + 1 < cchText && LineInfo::IsDosEol(&pszText[nTextPos]))
-                               ++nTextPos;
-                       ++nEol;
+                       if (LineInfo::IsEol(pszText[nTextPos]))
+                       {
+                               if (nTextPos + 1 < cchText && LineInfo::IsDosEol(&pszText[nTextPos]))
+                                       ++nTextPos;
+                               ++nEol;
+                               nLastLineLength = 0;
+                       }
+                       else
+                               ++nLastLineLength;
                }
        }
-       return nEol;
 }
 
-
 void CGhostTextBuffer::                        /* virtual override */
 AddUndoRecord(bool bInsert, const CPoint & ptStartPos,
        const CPoint & ptEndPos, LPCTSTR pszText, size_t cchText,
        int nActionType /*= CE_ACTION_UNKNOWN*/,
-       CDWordArray *paSavedRevisionNumbers)
+       CDWordArray *paSavedRevisionNumbers /*= nullptr*/)
 {
        CPoint real_ptStartPos(ptStartPos.x, ComputeRealLine(ptStartPos.y));
-       CPoint real_ptEndPos(ptEndPos.x, real_ptStartPos.y + CountEol(pszText, cchText));
+       int nLastLineLength, nEol;
+       CountEolAndLastLineLength(ptStartPos, pszText, cchText, nLastLineLength, nEol);
+       CPoint real_ptEndPos(ptEndPos.x, real_ptStartPos.y + nEol);
+       if (ptEndPos.x == 0 && cchText > 0 && !LineInfo::IsEol(pszText[cchText - 1]))
+               real_ptEndPos.x = nLastLineLength;
        CCrystalTextBuffer::AddUndoRecord(bInsert, real_ptStartPos, real_ptEndPos, pszText,
                cchText, nActionType, paSavedRevisionNumbers);
 }
@@ -869,7 +868,7 @@ UndoInsert(CCrystalTextView * pSource, CPoint & ptCursorPos, const CPoint appare
     {
                //  Try to ensure that we are undoing correctly...
                //  Just compare the text as it was before Undo operation
-        GetTextWithoutEmptys (apparent_ptStartPos.y, apparent_ptStartPos.x, apparent_ptEndPos.y, apparent_ptEndPos.x, text, CRLF_STYLE_AUTOMATIC, false);
+        GetTextWithoutEmptys (apparent_ptStartPos.y, apparent_ptStartPos.x, apparent_ptEndPos.y, apparent_ptEndPos.x, text, CRLFSTYLE::AUTOMATIC, false);
         if (static_cast<size_t>(text.GetLength()) == ur.GetTextLength() && memcmp(text, ur.GetText(), text.GetLength() * sizeof(TCHAR)) == 0)
         {
                        if (CCrystalTextBuffer::UndoInsert(pSource, ptCursorPos, apparent_ptStartPos, apparent_ptEndPos, ur))
@@ -887,7 +886,7 @@ UndoInsert(CCrystalTextView * pSource, CPoint & ptCursorPos, const CPoint appare
                        CPoint apparentEnd2 = apparent_ptEndPos;
                        apparentEnd2.x = static_cast<LONG>(m_aLines[apparentEnd2.y].FullLength());
                        text.Empty();
-                       GetTextWithoutEmptys(apparent_ptStartPos.y, apparent_ptStartPos.x, apparent_ptEndPos.y, apparentEnd2.x, text, CRLF_STYLE_AUTOMATIC, false);
+                       GetTextWithoutEmptys(apparent_ptStartPos.y, apparent_ptStartPos.x, apparent_ptEndPos.y, apparentEnd2.x, text, CRLFSTYLE::AUTOMATIC, false);
                        if (static_cast<size_t>(text.GetLength()) == ur.GetTextLength() && memcmp(text, ur.GetText(), text.GetLength() * sizeof(TCHAR)) == 0)
                        {
                                if (CCrystalTextBuffer::UndoInsert(pSource, ptCursorPos, apparent_ptStartPos, apparentEnd2, ur))