OSDN Git Service

Patch #1880711
authorJochen Tucht <jtuc@users.sourceforge.net>
Thu, 31 Jan 2008 21:08:06 +0000 (21:08 +0000)
committerJochen Tucht <jtuc@users.sourceforge.net>
Thu, 31 Jan 2008 21:08:06 +0000 (21:08 +0000)
16 files changed:
Src/GhostTextBuffer.cpp
Src/GhostTextBuffer.h
Src/GhostTextView.cpp
Src/MergeDoc.cpp
Src/MergeDoc.h
Src/MergeDocLineDiffs.cpp
Src/MergeEditView.cpp
Src/editlib/ccrystaleditview.cpp
Src/editlib/ccrystaleditview.h
Src/editlib/ccrystaltextbuffer.cpp
Src/editlib/ccrystaltextbuffer.h
Src/editlib/ccrystaltextview.cpp
Src/editlib/ccrystaltextview.h
Src/editlib/ccrystaltextview2.cpp
Src/editlib/ceditreplacedlg.cpp
Src/editlib/crystalparser.cpp

index 88a2359..91abc91 100644 (file)
@@ -228,8 +228,7 @@ void CGhostTextBuffer::GetTextWithoutEmptys(int nStartLine, int nStartChar,
                        }
                }
        }
-       pszBuf[0] = 0;
-       text.ReleaseBuffer();
+       text.ReleaseBuffer(pszBuf - text);
        text.FreeExtra();
 }
 
@@ -239,16 +238,17 @@ void CGhostTextBuffer::GetTextWithoutEmptys(int nStartLine, int nStartChar,
 
 
 void CGhostTextBuffer::SUndoRecord::
-SetText (LPCTSTR pszText)
+SetText (LPCTSTR pszText, int nLength)
 {
        FreeText();
-       if (pszText != NULL && pszText[0] != _T ('\0'))
+       if (nLength)
        {
-               int nLength = (int) _tcslen (pszText);
                if (nLength > 1)
                {
-                       m_pszText = new TCHAR[(nLength + 1) * sizeof (TCHAR)];
-                       _tcscpy (m_pszText, pszText);
+                       m_pszText = (TextBuffer *)malloc(sizeof(TextBuffer) + nLength * sizeof(TCHAR));
+                       m_pszText->size = nLength;
+                       memcpy(m_pszText->data, pszText, nLength * sizeof(TCHAR));
+                       m_pszText->data[nLength] = _T('?'); // debug sentinel
                }
                else
                {
@@ -264,7 +264,7 @@ FreeText ()
        // Check if m_pszText is a pointer by removing bits having
        // possible char value
        if (((INT_PTR)m_pszText >> 16) != 0)
-               delete[] m_pszText;
+               free(m_pszText);
        m_pszText = NULL;
 }
 
@@ -328,7 +328,7 @@ Undo (CCrystalTextView * pSource, CPoint & ptCursorPos)
                                        (apparent_ptEndPos.x <= m_aLines[apparent_ptEndPos.y].m_nLength))
                        {
                                GetTextWithoutEmptys (apparent_ptStartPos.y, apparent_ptStartPos.x, apparent_ptEndPos.y, apparent_ptEndPos.x, text);
-                               if (_tcscmp(text, ur.GetText()) == 0)
+                               if (text.GetLength() == ur.GetTextLength() && memcmp(text, ur.GetText(), text.GetLength() * sizeof(TCHAR)) == 0)
                                {
                                        VERIFY (CCrystalTextBuffer::DeleteText (pSource, 
                                                apparent_ptStartPos.y, apparent_ptStartPos.x, apparent_ptEndPos.y, apparent_ptEndPos.x,
@@ -377,7 +377,7 @@ Undo (CCrystalTextView * pSource, CPoint & ptCursorPos)
                {
                        int nEndLine, nEndChar;
                        VERIFY(CCrystalTextBuffer::InsertText (pSource, 
-                               apparent_ptStartPos.y, apparent_ptStartPos.x, ur.GetText (), nEndLine, nEndChar, 
+                               apparent_ptStartPos.y, apparent_ptStartPos.x, ur.GetText (), ur.GetTextLength (), nEndLine, nEndChar, 
                                0, FALSE));
                        ptCursorPos = m_ptLastChange;
 
@@ -489,7 +489,7 @@ Redo (CCrystalTextView * pSource, CPoint & ptCursorPos)
                {
                        int nEndLine, nEndChar;
                        VERIFY(InsertText (pSource, apparent_ptStartPos.y, apparent_ptStartPos.x,
-                               ur.GetText(), nEndLine, nEndChar, 0, FALSE));
+                               ur.GetText(), ur.GetTextLength(), nEndLine, nEndChar, 0, FALSE));
                        ptCursorPos = m_ptLastChange;
                }
                else
@@ -497,7 +497,7 @@ Redo (CCrystalTextView * pSource, CPoint & ptCursorPos)
 #ifdef _ADVANCED_BUGCHECK
                        CString text;
                        GetTextWithoutEmptys (apparent_ptStartPos.y, apparent_ptStartPos.x, apparent_ptEndPos.y, apparent_ptEndPos.x, text);
-                       ASSERT (lstrcmp (text, ur.GetText ()) == 0);
+                       ASSERT(text.GetLength() == ur.GetTextLength() && memcmp(text, ur.GetText(), text.GetLength() * sizeof(TCHAR)) == 0);
 #endif
                        VERIFY(DeleteText(pSource, apparent_ptStartPos.y, apparent_ptStartPos.x, 
                                apparent_ptEndPos.y, apparent_ptEndPos.x, 0, FALSE));
@@ -549,7 +549,7 @@ FlushUndoGroup (CCrystalTextView * pSource)
 
 /** The CPoint received parameters are apparent (on screen) line numbers */
 void CGhostTextBuffer::
-AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos, LPCTSTR pszText, int nRealLinesChanged, int nActionType, CDWordArray *paSavedRevisonNumbers)
+AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos, LPCTSTR pszText, int cchText, int nRealLinesChanged, int nActionType, CDWordArray *paSavedRevisonNumbers)
 {
        //  Forgot to call BeginUndoGroup()?
        ASSERT (m_bUndoGroup);
@@ -618,7 +618,7 @@ AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos,
                ur.m_nRealLinesCreated = nRealLinesChanged;
        else
                ur.m_nRealLinesInDeletedBlock = nRealLinesChanged;
-       ur.SetText (pszText);
+       ur.SetText (pszText, cchText);
        ur.m_paSavedRevisonNumbers = paSavedRevisonNumbers;
 
        m_aUndoBuf.Add (ur);
@@ -641,7 +641,7 @@ AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos,
  * is preserved with real line number during Rescan (m_ptCursorPos, m_ptLastChange for example)
  */
 BOOL CGhostTextBuffer::
-InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText,
+InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int cchText,
             int &nEndLine, int &nEndChar, int nAction, BOOL bHistory /*=TRUE*/)
 {
        BOOL bGroupFlag = FALSE;
@@ -659,7 +659,7 @@ InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText,
        paSavedRevisonNumbers->SetSize(1);
        (*paSavedRevisonNumbers)[0] = m_aLines[nLine].m_dwRevisionNumber;
 
-       if (!CCrystalTextBuffer::InsertText (pSource, nLine, nPos, pszText, nEndLine, nEndChar, nAction, bHistory))
+       if (!CCrystalTextBuffer::InsertText (pSource, nLine, nPos, pszText, cchText, nEndLine, nEndChar, nAction, bHistory))
        {
                delete paSavedRevisonNumbers;
                return FALSE;
@@ -742,7 +742,7 @@ InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText,
        ASSERT (  m_nUndoPosition > 0);
        m_nUndoPosition --;
        AddUndoRecord (TRUE, CPoint (nPos, nLine), CPoint (nEndChar, nEndLine),
-                 pszText, nRealLinesCreated, nAction, paSavedRevisonNumbers);
+                 pszText, cchText, nRealLinesCreated, nAction, paSavedRevisonNumbers);
 
        if (bGroupFlag)
                FlushUndoGroup (pSource);
@@ -834,7 +834,7 @@ DeleteText (CCrystalTextView * pSource, int nStartLine, int nStartChar,
        ASSERT (  m_nUndoPosition > 0);
        m_nUndoPosition --;
        AddUndoRecord (FALSE, CPoint (nStartChar, nStartLine), CPoint (0, -1),
-                 sTextToDelete, nRealLinesInDeletedBlock, nAction, paSavedRevisonNumbers);
+                 sTextToDelete, sTextToDelete.GetLength(), nRealLinesInDeletedBlock, nAction, paSavedRevisonNumbers);
 
        if (bGroupFlag)
                FlushUndoGroup (pSource);
index 38ea7d4..400ab99 100644 (file)
@@ -122,12 +122,15 @@ private :
                // of any pointer will be != 0. So we can store 1 character strings without
                // allocating memory.
                //
-
+               struct TextBuffer
+               {
+                       int size;
+                       TCHAR data[1];
+               };
                union
                {
-                       TCHAR *m_pszText;     // For cases when we have > 1 character strings
-
-                       TCHAR m_szText[2];    // For single-character strings
+                       TextBuffer *m_pszText; // For cases when we have > 1 character strings
+                       TCHAR m_szText[2];     // For single-character strings
 
                };
 
@@ -155,7 +158,7 @@ public :
                        m_redo_ptEndPos_nGhost = src.m_redo_ptEndPos_nGhost;
                        m_nRealLinesCreated = src.m_nRealLinesCreated;
                        m_nRealLinesInDeletedBlock = src.m_nRealLinesInDeletedBlock;
-                       SetText(src.GetText());
+                       SetText(src.GetText(), src.GetTextLength());
                        INT_PTR size = src.m_paSavedRevisonNumbers->GetSize();
                        if (!m_paSavedRevisonNumbers)
                                m_paSavedRevisonNumbers = new CDWordArray();
@@ -172,7 +175,7 @@ public :
                                delete m_paSavedRevisonNumbers;
                }
 
-               void SetText (LPCTSTR pszText);
+               void SetText (LPCTSTR pszText, int cchText);
                void FreeText ();
 
                LPCTSTR GetText () const
@@ -181,9 +184,15 @@ public :
                        // Check if m_pszText is a pointer by removing bits having
                        // possible char value
                        if (((INT_PTR)m_pszText >> 16) != 0)
-                               return m_pszText;
+                               return m_pszText->data;
                        return m_szText;
-               };
+               }
+               int GetTextLength () const
+               {
+                       if (((INT_PTR)m_pszText >> 16) != 0)
+                               return m_pszText->size;
+                       return 1;
+               }
        };
 
 #pragma pack(pop)
@@ -205,7 +214,7 @@ protected:
 
        // [JRT] Support For Descriptions On Undo/Redo Actions
        virtual void AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos,
-                              LPCTSTR pszText, int nRealLinesChanged, int nActionType = CE_ACTION_UNKNOWN, CDWordArray *paSavedRevisonNumbers = NULL);
+                              LPCTSTR pszText, int cchText, int nRealLinesChanged, int nActionType = CE_ACTION_UNKNOWN, CDWordArray *paSavedRevisonNumbers = NULL);
 
 private:
        // A RealityBlock is a block of lines with no ghost lines
@@ -233,7 +242,7 @@ public :
 
 
        // Text modification functions
-       virtual BOOL InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar, int nAction = CE_ACTION_UNKNOWN, BOOL bHistory =TRUE);
+       virtual BOOL InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int cchText, int &nEndLine, int &nEndChar, int nAction = CE_ACTION_UNKNOWN, BOOL bHistory =TRUE);
        virtual BOOL DeleteText (CCrystalTextView * pSource, int nStartLine, int nStartPos, int nEndLine, int nEndPos, int nAction = CE_ACTION_UNKNOWN, BOOL bHistory =TRUE);
        BOOL InsertGhostLine (CCrystalTextView * pSource, int nLine);
 
index d4f27be..6f62475 100644 (file)
@@ -213,13 +213,16 @@ HGLOBAL CGhostTextView::PrepareDragData ()
 
        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));
+       int cchText = text.GetLength();
+       SIZE_T cbData = (cchText + 1) * sizeof(TCHAR);
+       HGLOBAL hData =::GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, cbData);
        if (hData == NULL)
                return NULL;
+       ::GlobalReAlloc(hData, cbData, 0);
+       ASSERT(::GlobalSize(hData) == cbData);
 
        LPTSTR pszData = (LPTSTR)::GlobalLock (hData);
-       _tcscpy (pszData, text.GetBuffer (0));
-       text.ReleaseBuffer ();
+       memcpy (pszData, text, cbData);
        ::GlobalUnlock (hData);
 
        m_ptDraggedTextBegin = m_ptDrawSelStart;
index c775cee..4e3e029 100644 (file)
@@ -690,15 +690,17 @@ void CMergeDoc::CDiffTextBuffer::SetModified(BOOL bModified /*= TRUE*/)
 
 BOOL CMergeDoc::CDiffTextBuffer::GetFullLine(int nLineIndex, CString &strLine)
 {
-       if (!GetFullLineLength(nLineIndex))
+       int cchText = GetFullLineLength(nLineIndex);
+       if (cchText == 0)
                return FALSE;
-       strLine = GetLineChars(nLineIndex);
+       LPTSTR pchText = strLine.GetBufferSetLength(cchText);
+       memcpy(pchText, GetLineChars(nLineIndex), cchText * sizeof(TCHAR));
        return TRUE;
 }
 
-void CMergeDoc::CDiffTextBuffer::AddUndoRecord(BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos, LPCTSTR pszText, int nLinesToValidate, int nActionType /*= CE_ACTION_UNKNOWN*/, CDWordArray *paSavedRevisonNumbers)
+void CMergeDoc::CDiffTextBuffer::AddUndoRecord(BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos, LPCTSTR pszText, int cchText, int nLinesToValidate, int nActionType /*= CE_ACTION_UNKNOWN*/, CDWordArray *paSavedRevisonNumbers)
 {
-       CGhostTextBuffer::AddUndoRecord(bInsert, ptStartPos, ptEndPos, pszText, nLinesToValidate, nActionType, paSavedRevisonNumbers);
+       CGhostTextBuffer::AddUndoRecord(bInsert, ptStartPos, ptEndPos, pszText, cchText, nLinesToValidate, nActionType, paSavedRevisonNumbers);
        if (m_aUndoBuf[m_nUndoPosition - 1].m_dwFlags & UNDO_BEGINGROUP)
        {
                m_pOwnerDoc->undoTgt.erase(m_pOwnerDoc->curUndo, m_pOwnerDoc->undoTgt.end());
@@ -1700,7 +1702,6 @@ int CMergeDoc::CDiffTextBuffer::LoadFromFile(LPCTSTR pszFileNameInit,
                do {
                        bool lossy=false;
                        done = !pufile->ReadString(sline, eol, &lossy);
-                       EscapeControlChars(sline);
 
                        // if last line had no eol, we can quit
                        if (done && preveol.IsEmpty())
@@ -1906,14 +1907,14 @@ int CMergeDoc::CDiffTextBuffer::SaveToFile (LPCTSTR pszFileName,
                else
                        sLine = _T("");
 
+               if (bTempFile)
+                       EscapeControlChars(sLine);
                // last real line ?
                if (line == ApparentLastRealLine())
                {
                        // last real line is never EOL terminated
                        ASSERT (_tcslen(GetLineEol(line)) == 0);
                        // write the line and exit loop
-                       if (!bTempFile)
-                               UnescapeControlChars(sLine);
                        file.WriteString(sLine);
                        break;
                }
@@ -1931,8 +1932,6 @@ int CMergeDoc::CDiffTextBuffer::SaveToFile (LPCTSTR pszFileName,
                }
 
                // write this line to the file (codeset or unicode conversions are done there)
-               if (!bTempFile)
-                       UnescapeControlChars(sLine);
                file.WriteString(sLine);
        }
        file.Close();
@@ -2012,13 +2011,13 @@ int CMergeDoc::CDiffTextBuffer::SaveToFile (LPCTSTR pszFileName,
 }
 
 /// Replace text of line (no change to eol)
-void CMergeDoc::CDiffTextBuffer::ReplaceLine(CCrystalTextView * pSource, int nLine, const CString &strText, int nAction /*=CE_ACTION_UNKNOWN*/)
+void CMergeDoc::CDiffTextBuffer::ReplaceLine(CCrystalTextView * pSource, int nLine, LPCTSTR pchText, int cchText, int nAction /*=CE_ACTION_UNKNOWN*/)
 {
        if (GetLineLength(nLine)>0)
                DeleteText(pSource, nLine, 0, nLine, GetLineLength(nLine), nAction);
-       int endl,endc;
-       if (! strText.IsEmpty())
-               InsertText(pSource, nLine, 0, strText, endl,endc, nAction);
+       int endl, endc;
+       if (cchText)
+               InsertText(pSource, nLine, 0, pchText, cchText, endl, endc, nAction);
 }
 
 /// Return pointer to the eol chars of this string, or pointer to empty string if none
@@ -2039,8 +2038,7 @@ void CMergeDoc::CDiffTextBuffer::ReplaceFullLine(CCrystalTextView * pSource, int
                // (optimization) eols are the same, so just replace text inside line
                // we must clean strText from its eol...
                int eolLength = _tcslen(getEol(strText));
-               CString strTextWithoutEol = strText.Left(strText.GetLength() - eolLength);
-               ReplaceLine(pSource, nLine, strTextWithoutEol, nAction);
+               ReplaceLine(pSource, nLine, strText, strText.GetLength() - eolLength, nAction);
                return;
        }
 
@@ -2051,8 +2049,8 @@ void CMergeDoc::CDiffTextBuffer::ReplaceFullLine(CCrystalTextView * pSource, int
        if (GetFullLineLength(nLine))
                DeleteText(pSource, nLine, 0, nLine+1, 0, nAction); 
        int endl,endc;
-       if (! strText.IsEmpty())
-               InsertText(pSource, nLine, 0, strText, endl,endc, nAction);
+       if (int cchText = strText.GetLength())
+               InsertText(pSource, nLine, 0, strText, cchText, endl,endc, nAction);
 }
 
 /**
index 4c6fc7b..4cc57a2 100644 (file)
@@ -163,9 +163,9 @@ private :
 public :
                void SetTempPath(String path);
                virtual void AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos,
-                       LPCTSTR pszText, int nLinesToValidate, int nActionType = CE_ACTION_UNKNOWN, CDWordArray *paSavedRevisonNumbers = NULL);
+                       LPCTSTR pszText, int cchText, int nLinesToValidate, int nActionType = CE_ACTION_UNKNOWN, CDWordArray *paSavedRevisonNumbers = NULL);
                bool curUndoGroup();
-               void ReplaceLine(CCrystalTextView * pSource, int nLine, const CString& strText, int nAction =CE_ACTION_UNKNOWN);
+               void ReplaceLine(CCrystalTextView * pSource, int nLine, LPCTSTR pchText, int cchText, int nAction =CE_ACTION_UNKNOWN);
                void ReplaceFullLine(CCrystalTextView * pSource, int nLine, const CString& strText, int nAction =CE_ACTION_UNKNOWN);
 
                int LoadFromFile(LPCTSTR pszFileName, PackingInfo * infoUnpacker,
index 1546587..f7caedf 100644 (file)
@@ -190,8 +190,8 @@ void CMergeDoc::Computelinediff(CCrystalTextView * pView1, CCrystalTextView * pV
        DIFFOPTIONS diffOptions = {0};
        m_diffWrapper.GetOptions(&diffOptions);
 
-       CString str1 = pView1->GetLineChars(line);
-       CString str2 = pView2->GetLineChars(line);
+       CString str1(pView1->GetLineChars(line), pView1->GetFullLineLength(line));
+       CString str2(pView2->GetLineChars(line), pView2->GetFullLineLength(line));
 
        if (diffOptions.bIgnoreEol)
        {
@@ -315,8 +315,8 @@ void CMergeDoc::GetWordDiffArray(int nLineIndex, wdiffarray *pworddiffs)
        DIFFOPTIONS diffOptions = {0};
        m_diffWrapper.GetOptions(&diffOptions);
 
-       CString str1 = m_pView[0]->GetLineChars(nLineIndex);
-       CString str2 = m_pView[1]->GetLineChars(nLineIndex);
+       CString str1(m_pView[0]->GetLineChars(nLineIndex), m_pView[0]->GetFullLineLength(nLineIndex));
+       CString str2(m_pView[1]->GetLineChars(nLineIndex), m_pView[1]->GetFullLineLength(nLineIndex));
 
        if (diffOptions.bIgnoreEol)
        {
index c8c0dbf..b9233a9 100644 (file)
@@ -688,7 +688,7 @@ void CMergeEditView::OnEditCopy()
        buffer->GetTextWithoutEmptys(ptSelStart.y, ptSelStart.x,
                ptSelEnd.y, ptSelEnd.x, text);
 
-       PutToClipboard(text);
+       PutToClipboard(text, text.GetLength());
 }
 
 /**
@@ -719,7 +719,7 @@ void CMergeEditView::OnEditCut()
        pDoc->m_ptBuf[m_nThisPane]->GetTextWithoutEmptys(ptSelStart.y, ptSelStart.x,
                ptSelEnd.y, ptSelEnd.x, text);
 
-       PutToClipboard(text);
+       PutToClipboard(text, text.GetLength());
 
        CPoint ptCursorPos = ptSelStart;
        ASSERT_VALIDTEXTPOS(ptCursorPos);
@@ -2320,7 +2320,7 @@ void CMergeEditView::OnScripts(UINT nID )
        BOOL bChanged = TextTransform_Interactive(text, L"EDITOR_SCRIPT", nID - ID_SCRIPT_FIRST);
        if (bChanged)
                // now replace the text
-               ReplaceSelection(text, 0);
+               ReplaceSelection(text, text.GetLength(), 0);
 }
 
 /**
@@ -2667,8 +2667,8 @@ void CMergeEditView::OnEditCopyLineNumbers()
                strText += sSpaces;
                strNumLine.Format(_T("%d: %s"), line + 1, strLine);
                strText += strNumLine;
-       }
-       PutToClipboard(strText);
+       }
+       PutToClipboard(strText, strText.GetLength());
 }
 
 void CMergeEditView::OnUpdateEditCopyLinenumbers(CCmdUI* pCmdUI)
index e170f3f..2ba1185 100644 (file)
@@ -338,7 +338,7 @@ Paste ()
       ASSERT_VALIDTEXTPOS (ptCursorPos);
       
       int x, y;
-      m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, y, x, CE_ACTION_PASTE);  //  [JRT]
+      m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, text.GetLength(), y, x, CE_ACTION_PASTE);  //  [JRT]
 
       ptCursorPos.x = x;
       ptCursorPos.y = y;
@@ -366,7 +366,7 @@ Cut ()
   GetSelection (ptSelStart, ptSelEnd);
   CString text;
   GetText (ptSelStart, ptSelEnd, text);
-  PutToClipboard (text);
+  PutToClipboard (text, text.GetLength());
 
   CPoint ptCursorPos = ptSelStart;
   ASSERT_VALIDTEXTPOS (ptCursorPos);
@@ -485,9 +485,10 @@ OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
             ptCursorPos = GetCursorPos ();
           ASSERT_VALIDTEXTPOS (ptCursorPos);
           LPCTSTR pszText = m_pTextBuffer->GetDefaultEol();
+          int cchText = _tcslen(pszText);
 
           int x, y;
-          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, y, x, CE_ACTION_TYPING);  //  [JRT]
+          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, cchText, y, x, CE_ACTION_TYPING);  //  [JRT]
 
           ptCursorPos.x = x;
           ptCursorPos.y = y;
@@ -501,12 +502,10 @@ OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
       m_pTextBuffer->FlushUndoGroup (this);
       return;
     }
-
-  if (nChar > 31)
+  // Accept control characters other than [\t\n\r] through Alt-Numpad
+  if (nChar > 31
+  || GetKeyState(VK_CONTROL) >= 0 && nChar != 9 && nChar != 10 && nChar != 13)
     {
-      // If CTRL is pressed, turn space into control char escape sequence leadin
-      if (nChar == VK_SPACE && GetKeyState(VK_CONTROL) < 0)
-        nChar = 15;
       if (QueryEditable () && m_pTextBuffer != NULL)
         {
           m_pTextBuffer->BeginUndoGroup (m_bMergeUndo);
@@ -547,7 +546,7 @@ OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
           pszText[1] = 0;
 
           int x, y;
-          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, y, x, CE_ACTION_TYPING);    // [JRT]
+          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, 1, y, x, CE_ACTION_TYPING);    // [JRT]
 
           ptCursorPos.x = x;
           ptCursorPos.y = y;
@@ -718,7 +717,7 @@ OnEditTab ()
       for (int L = nStartLine; L <= nEndLine; L++)
         {
           int x, y;
-          m_pTextBuffer->InsertText (this, L, 0, pszText, y, x, CE_ACTION_INDENT);  //  [JRT]
+          m_pTextBuffer->InsertText (this, L, 0, pszText, _tcslen(pszText), y, x, CE_ACTION_INDENT);  //  [JRT]
 
         }
       m_bHorzScrollBarLocked = FALSE;
@@ -785,12 +784,12 @@ OnEditTab ()
 
       // [JRT]:
       m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_TYPING);
-      m_pTextBuffer->InsertText( this, ptSelStart.y, ptSelStart.x, pszText, y, x, CE_ACTION_TYPING );
+      m_pTextBuffer->InsertText( this, ptSelStart.y, ptSelStart.x, pszText, _tcslen(pszText), y, x, CE_ACTION_TYPING );
     }
   // No selection, add tab
   else
     {
-      m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, y, x, CE_ACTION_TYPING);  //  [JRT]
+      m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, _tcslen(pszText), y, x, CE_ACTION_TYPING);  //  [JRT]
     }
 
   ptCursorPos.x = x;
@@ -1123,6 +1122,10 @@ DoDropText (COleDataObject * pDataObject, const CPoint & ptClient)
       return FALSE;
     }
 
+  SIZE_T cbData = ::GlobalSize (hData);
+  int cchText = cbData / sizeof(TCHAR) - 1;
+  if (cchText < 0)
+    return FALSE;
   LPTSTR pszText = (LPTSTR)::GlobalLock (hData);
   if (pszText == NULL)
     return FALSE;
@@ -1138,7 +1141,7 @@ DoDropText (COleDataObject * pDataObject, const CPoint & ptClient)
     } 
 
   int x, y;
-  m_pTextBuffer->InsertText (this, ptDropPos.y, ptDropPos.x, pszText, y, x, CE_ACTION_DRAGDROP);  //   [JRT]
+  m_pTextBuffer->InsertText (this, ptDropPos.y, ptDropPos.x, pszText, cchText, y, x, CE_ACTION_DRAGDROP);  //   [JRT]
 
   CPoint ptCurPos (x, y);
   ASSERT_VALIDTEXTPOS (ptCurPos);
@@ -1360,13 +1363,11 @@ OnEditReplace ()
 }
 
 BOOL CCrystalEditView::
-ReplaceSelection (LPCTSTR pszNewText, DWORD dwFlags)
+ReplaceSelection (LPCTSTR pszNewText, int cchNewText, DWORD dwFlags)
 {
-  if (!pszNewText)
-    pszNewText = _T ("");
-
-  if (!lstrlen(pszNewText))
+  if (!cchNewText)
     return DeleteCurrentSelection();
+  ASSERT(pszNewText);
 
   m_pTextBuffer->BeginUndoGroup();
 
@@ -1404,15 +1405,15 @@ ReplaceSelection (LPCTSTR pszNewText, DWORD dwFlags)
             }
           else
             text.Empty ();
-          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, y, x, CE_ACTION_REPLACE);  //  [JRT+FRD]
+          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, text.GetLength(), y, x, CE_ACTION_REPLACE);  //  [JRT+FRD]
           if (lpszNewStr)
             free(lpszNewStr);
         }
     }
   else
     {
-      m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszNewText, y, x, CE_ACTION_REPLACE);  //  [JRT]
-      m_nLastReplaceLen = _tcslen (pszNewText);
+      m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszNewText, cchNewText, y, x, CE_ACTION_REPLACE);  //  [JRT]
+      m_nLastReplaceLen = cchNewText;
     }
 
   CPoint ptEndOfBlock = CPoint (x, y);
@@ -1669,7 +1670,7 @@ OnEditOperation (int nAction, LPCTSTR pszText)
               // m_pTextBuffer->BeginUndoGroup ();
               int x, y;
               m_pTextBuffer->InsertText (NULL, ptCursorPos.y, ptCursorPos.x,
-                                         pszInsertStr, y, x, CE_ACTION_AUTOINDENT);
+                                         pszInsertStr, nPos, y, x, CE_ACTION_AUTOINDENT);
               CPoint pt (x, y);
               SetCursorPos (pt);
               SetSelection (pt, pt);
@@ -1703,7 +1704,7 @@ OnEditOperation (int nAction, LPCTSTR pszText)
                   // m_pTextBuffer->BeginUndoGroup ();
                   int x, y;
                   m_pTextBuffer->InsertText (NULL, ptCursorPos.y, ptCursorPos.x,
-                                             pszInsertStr, y, x, CE_ACTION_AUTOINDENT);
+                                             pszInsertStr, nPos, y, x, CE_ACTION_AUTOINDENT);
                   CPoint pt (x, y);
                   SetCursorPos (pt);
                   SetSelection (pt, pt);
@@ -1726,7 +1727,7 @@ OnEditOperation (int nAction, LPCTSTR pszText)
               // m_pTextBuffer->BeginUndoGroup ();
               int x, y;
               m_pTextBuffer->InsertText (NULL, ptCursorPos.y, ptCursorPos.x - 1,
-                                         pszInsertStr, y, x, CE_ACTION_AUTOINDENT);
+                                         pszInsertStr, 1, y, x, CE_ACTION_AUTOINDENT);
               ptCursorPos.x = x + 1;
               ptCursorPos.y = y;
               SetCursorPos (ptCursorPos);
@@ -1772,7 +1773,7 @@ OnEditOperation (int nAction, LPCTSTR pszText)
               // m_pTextBuffer->BeginUndoGroup ();
               int x, y;
               m_pTextBuffer->InsertText (NULL, ptCursorPos.y, ptCursorPos.x - 1,
-                                         pszInsertStr, y, x, CE_ACTION_AUTOINDENT);
+                                         pszInsertStr, nPos, y, x, CE_ACTION_AUTOINDENT);
               CPoint pt (x + 1, y);
               SetCursorPos (pt);
               SetSelection (pt, pt);
@@ -1866,7 +1867,7 @@ OnEditAutoComplete ()
             {
               m_pTextBuffer->BeginUndoGroup ();
               int x, y;
-              m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x + nLength, sText, y, x, CE_ACTION_AUTOCOMPLETE);
+              m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x + nLength, sText, sText.GetLength(), y, x, CE_ACTION_AUTOCOMPLETE);
               ptCursorPos.x = x;
               ptCursorPos.y = y;
               SetCursorPos (ptCursorPos);
@@ -1918,7 +1919,7 @@ OnEditAutoExpand ()
           LPTSTR pszSlash = _tcschr (pszExpand, _T ('\\'));
           if (!pszSlash)
             {
-              m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, y, x, CE_ACTION_AUTOEXPAND);
+              m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, _tcslen(pszExpand), y, x, CE_ACTION_AUTOEXPAND);
               ptCursorPos.x = x;
               ptCursorPos.y = y;
               ASSERT_VALIDTEXTPOS (ptCursorPos);
@@ -1931,7 +1932,7 @@ OnEditAutoExpand ()
               *pszSlash++ = _T ('\0');
               for(;;)
                 {
-                  m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, y, x, CE_ACTION_AUTOEXPAND);
+                  m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, _tcslen(pszExpand), y, x, CE_ACTION_AUTOEXPAND);
                   ptCursorPos.x = x;
                   ptCursorPos.y = y;
                   ASSERT_VALIDTEXTPOS (ptCursorPos);
@@ -1947,7 +1948,7 @@ OnEditAutoExpand ()
                       case _T ('n'):
                         {
                           const static TCHAR szText[3] = _T ("\r\n");
-                          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, y, x, CE_ACTION_AUTOEXPAND);  //  [JRT]
+                          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, _tcslen(szText), y, x, CE_ACTION_AUTOEXPAND);  //  [JRT]
                           ptCursorPos.x = x;
                           ptCursorPos.y = y;
                           ASSERT_VALIDTEXTPOS (ptCursorPos);
@@ -2046,7 +2047,7 @@ OnEditAutoExpand ()
                                 szText[i] = ' ';
                               szText[nChars] = '\0';
                             }
-                          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, y, x, CE_ACTION_AUTOEXPAND);  //  [JRT]
+                          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, _tcslen(szText), y, x, CE_ACTION_AUTOEXPAND);  //  [JRT]
                           ptCursorPos.x = x;
                           ptCursorPos.y = y;
                           ASSERT_VALIDTEXTPOS (ptCursorPos);
@@ -2114,7 +2115,7 @@ OnEditLowerCase ()
         }
 
       int x, y;
-      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_LOWERCASE);
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_LOWERCASE);
 
       ASSERT_VALIDTEXTPOS (ptCursorPos);
       SetAnchor (ptCursorPos);
@@ -2162,7 +2163,7 @@ OnEditUpperCase ()
         }
 
       int x, y;
-      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_UPPERCASE);
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_UPPERCASE);
 
       ASSERT_VALIDTEXTPOS (ptCursorPos);
       SetAnchor (ptCursorPos);
@@ -2214,7 +2215,7 @@ OnEditSwapCase ()
         }
 
       int x, y;
-      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_SWAPCASE);
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_SWAPCASE);
 
       ASSERT_VALIDTEXTPOS (ptCursorPos);
       SetAnchor (ptCursorPos);
@@ -2279,7 +2280,7 @@ OnEditCapitalize ()
         }
 
       int x, y;
-      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_CAPITALIZE);
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_CAPITALIZE);
 
       ASSERT_VALIDTEXTPOS (ptCursorPos);
       SetAnchor (ptCursorPos);
@@ -2348,7 +2349,7 @@ OnEditSentence ()
         }
 
       int x, y;
-      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_SENTENCIZE);
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_SENTENCIZE);
 
       ASSERT_VALIDTEXTPOS (ptCursorPos);
       SetAnchor (ptCursorPos);
@@ -2441,7 +2442,7 @@ int CCrystalEditView::SpellNotify (int nEvent, struct SpellData_t *pdata)
           {
             pView->GetSelection (ptStartPos, ptEndPos);
             pView->m_pTextBuffer->DeleteText (pView, ptStartPos.y, ptStartPos.x, ptEndPos.y, ptEndPos.x, CE_ACTION_SPELL);
-            pView->m_pTextBuffer->InsertText (pView, ptStartPos.y, ptStartPos.x, pdata->pszWord, y, x, CE_ACTION_SPELL);
+            pView->m_pTextBuffer->InsertText (pView, ptStartPos.y, ptStartPos.x, pdata->pszWord, _tcslen(pdata->pszWord), y, x, CE_ACTION_SPELL);
             ptEndPos.x = x;
             ptEndPos.y = y;
             pView->SetAnchor (ptEndPos);
@@ -2571,7 +2572,7 @@ OnToolsCharCoding ()
           m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_RECODE);
 
           int x, y;
-          m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, pszNew, y, x, CE_ACTION_RECODE);
+          m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, pszNew, _tcslen(pszNew), y, x, CE_ACTION_RECODE);
 
           if (IsValidTextPos (ptCursorPos))
             ptCursorPos.x = 0;
index 5d031b3..d53d521 100644 (file)
@@ -120,7 +120,7 @@ public :
     virtual BOOL QueryEditable ();
     virtual void UpdateView (CCrystalTextView * pSource, CUpdateContext * pContext, DWORD dwFlags, int nLineIndex = -1);
 
-    BOOL ReplaceSelection (LPCTSTR pszNewText, DWORD dwFlags);
+    BOOL ReplaceSelection (LPCTSTR pszNewText, int cchNewText, DWORD dwFlags);
 
     virtual void OnEditOperation (int nAction, LPCTSTR pszText);
 
index 6814d7e..7eab2d7 100644 (file)
@@ -93,16 +93,17 @@ int CCrystalTextBuffer::m_nDefaultEncoding = -1;
 // CCrystalTextBuffer::SUndoRecord
 
 void CCrystalTextBuffer::SUndoRecord::
-SetText (LPCTSTR pszText)
+SetText (LPCTSTR pszText, int nLength)
 {
   FreeText();
-  if (pszText != NULL && pszText[0] != _T ('\0'))
+  if (nLength)
     {
-      int nLength = (int) _tcslen (pszText);
       if (nLength > 1)
         {
-          m_pszText = new TCHAR[(nLength + 1) * sizeof (TCHAR)];
-          _tcscpy (m_pszText, pszText);
+          m_pszText = (TextBuffer *)malloc(sizeof(TextBuffer) + nLength * sizeof(TCHAR));
+          m_pszText->size = nLength;
+          memcpy(m_pszText->data, pszText, nLength * sizeof(TCHAR));
+          m_pszText->data[nLength] = _T('?'); // debug sentinel
         }
       else
         {
@@ -118,7 +119,7 @@ FreeText ()
   // Check if m_pszText is a pointer by removing bits having
   // possible char value
   if (((INT_PTR)m_pszText >> 16) != 0)
-    delete[] m_pszText;
+    free(m_pszText);
   m_pszText = NULL;
 }
 
@@ -227,13 +228,7 @@ static bool isdoseol(LPCTSTR sz)
  */
 void CCrystalTextBuffer::InsertLine (LPCTSTR pszLine, int nLength /*= -1*/ , int nPosition /*= -1*/, int nCount /*= 1*/ )
 {
-  if (nLength == -1)
-    {
-      if (pszLine == NULL)
-        nLength = 0;
-      else
-        nLength = (int) _tcslen (pszLine);
-    }
+  ASSERT(nLength != -1);
 
   SLineInfo li;
   li.m_nLength = nLength;
@@ -266,7 +261,7 @@ void CCrystalTextBuffer::InsertLine (LPCTSTR pszLine, int nLength /*= -1*/ , int
   for (int ic = 1; ic < nCount; ic++) 
   {
     m_aLines[nPosition+ic].m_pcLine = new TCHAR[li.m_nMax];
-    _tcscpy(m_aLines[nPosition+ic].m_pcLine, li.m_pcLine);
+    memcpy(m_aLines[nPosition+ic].m_pcLine, li.m_pcLine, li.m_nMax * sizeof(TCHAR));
   }
 
 #ifdef _DEBUG
@@ -283,12 +278,7 @@ void CCrystalTextBuffer::InsertLine (LPCTSTR pszLine, int nLength /*= -1*/ , int
 void CCrystalTextBuffer::
 AppendLine (int nLineIndex, LPCTSTR pszChars, int nLength /*= -1*/ )
 {
-  if (nLength == -1)
-    {
-      if (pszChars == NULL)
-        return;
-      nLength = (int) _tcslen (pszChars);
-    }
+  ASSERT(nLength != -1);
 
   if (nLength == 0)
     return;
@@ -306,7 +296,7 @@ AppendLine (int nLineIndex, LPCTSTR pszChars, int nLength /*= -1*/ )
       delete[] li.m_pcLine;
       li.m_pcLine = pcNewBuf;
     }
-  memcpy (li.m_pcLine + li.m_nLength, pszChars, sizeof (TCHAR) * (nLength+1));
+  memcpy (li.m_pcLine + li.m_nLength, pszChars, sizeof (TCHAR) * nLength);
   li.m_nLength += nLength;
   li.m_pcLine[li.m_nLength] = '\0';
   // Did line gain eol ? (We asserted above that it had none at start)
@@ -402,7 +392,7 @@ InitNew (int nCrlfStyle /*= CRLF_STYLE_DOS*/ )
   ASSERT (!m_bInit);
   ASSERT (m_aLines.GetSize () == 0);
   ASSERT (nCrlfStyle >= 0 && nCrlfStyle <= 2);
-  InsertLine (_T (""));
+  InsertLine (_T (""), 0);
   m_bInit = TRUE;
   m_bReadOnly = FALSE;
   m_nCRLFMode = nCrlfStyle;
@@ -979,7 +969,7 @@ void CCrystalTextBuffer::GetTextWithoutEmptys(int nStartLine, int nStartChar,
                  int nEndLine, int nEndChar, 
                  CString &text, int nCrlfStyle /* CRLF_STYLE_AUTOMATIC */)
 {
-  CString sEol = GetStringEol (nCrlfStyle);
+  LPCTSTR sEol = GetStringEol (nCrlfStyle);
   GetText(nStartLine, nStartChar, nEndLine, nEndChar, text, sEol);
 }
 
@@ -1046,8 +1036,7 @@ GetText (int nStartLine, int nStartChar, int nEndLine, int nEndChar, CString & t
       memcpy (pszBuf, m_aLines[nStartLine].m_pcLine + nStartChar, sizeof (TCHAR) * nCount);
       pszBuf += nCount;
     }
-  pszBuf[0] = 0;
-  text.ReleaseBuffer ();
+  text.ReleaseBuffer (pszBuf - text);
   text.FreeExtra ();
 }
 
@@ -1142,12 +1131,7 @@ InternalDeleteText (CCrystalTextView * pSource, int nStartLine, int nStartChar,
     {
       // delete multiple lines
       int nRestCount = m_aLines[nEndLine].FullLength() - nEndChar;
-      CString sTail;
-      if (nRestCount > 0)
-        {
-          sTail = m_aLines[nEndLine].m_pcLine + nEndChar;
-          ASSERT(sTail.GetLength() == nRestCount);
-        }
+      CString sTail(m_aLines[nEndLine].m_pcLine + nEndChar, nRestCount);
 
       int nDelCount = nEndLine - nStartLine;
       for (int L = nStartLine + 1; L <= nEndLine; L++)
@@ -1160,11 +1144,11 @@ InternalDeleteText (CCrystalTextView * pSource, int nStartLine, int nStartChar,
       m_aLines[nStartLine].m_nEolChars = 0;
       if (nRestCount > 0)
         {
-          AppendLine (nStartLine, sTail, nRestCount);
+          AppendLine (nStartLine, sTail, sTail.GetLength());
         }
 
-    if (pSource!=NULL)
-    UpdateViews (pSource, &context, UPDATE_HORZRANGE | UPDATE_VERTRANGE, nStartLine);
+      if (pSource!=NULL)
+        UpdateViews (pSource, &context, UPDATE_HORZRANGE | UPDATE_VERTRANGE, nStartLine);
     }
 
   if (!m_bModified)
@@ -1190,16 +1174,15 @@ StripTail (int i, int bytes)
   // Must not take off more than exist
   ASSERT(offset >= 0);
 
-  CString str = li.m_pcLine + offset;
   li.m_nLength = offset;
   li.m_nEolChars = 0;
-  return str;
+  return CString(li.m_pcLine + offset, bytes);
 }
 
 
 // InternalInsertText uses only apparent line numbers
 BOOL CCrystalTextBuffer::
-InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar)
+InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int cchText, int &nEndLine, int &nEndChar)
 {
   ASSERT (m_bInit);             //  Text buffer not yet initialized.
   //  You must call InitNew() or LoadFromFile() first!
@@ -1230,18 +1213,16 @@ InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR psz
       int haseol = 0;
       nTextPos = 0;
       // advance to end of line
-      while (pszText[nTextPos] && !iseol(pszText[nTextPos]))
+      while (nTextPos < cchText && !iseol(pszText[nTextPos]))
         nTextPos++;
       // advance after EOL of line
-      if (isdoseol(&pszText[nTextPos]))
-        {
-          haseol = 1;
-          nTextPos += 2;
-        }
-      else if (iseol(pszText[nTextPos]))
+      if (nTextPos < cchText)
         {
           haseol = 1;
+          LPCTSTR eol = &pszText[nTextPos];
           nTextPos++;
+          if (nTextPos < cchText && isdoseol(eol))
+            nTextPos++;
         }
 
       // The first line of the new text is appended to the start line
@@ -1257,7 +1238,7 @@ InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR psz
         }
 
 
-      if (pszText[nTextPos] == 0)
+      if (nTextPos == cchText)
         {
           // we just finished our insert
           // now we have to reattach the tail
@@ -1275,7 +1256,7 @@ InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR psz
             {
               if (haseol)
               {
-                InsertLine(sTail, -1, nEndLine);
+                InsertLine(sTail, sTail.GetLength(), nEndLine);
                 nInsertedLines ++;
               }
               else
@@ -1286,7 +1267,7 @@ InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR psz
               // We left cursor after last screen line
               // which is an illegal cursor position
               // so manufacture a new trailing line
-              InsertLine(_T(""));
+              InsertLine(_T(""), 0);
               nInsertedLines ++;
             }
           break;
@@ -1294,6 +1275,7 @@ InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR psz
 
       ++nCurrentLine;
       pszText += nTextPos;
+      cchText -= nTextPos;
     }
 
   // Compute the context : all positions after context.m_ptBegin are
@@ -1500,7 +1482,7 @@ Undo (CCrystalTextView * pSource, CPoint & ptCursorPos)
       else
         {
           int nEndLine, nEndChar;
-          VERIFY (InternalInsertText (pSource, apparent_ptStartPos.y, apparent_ptStartPos.x, ur.GetText (), nEndLine, nEndChar));
+          VERIFY (InternalInsertText (pSource, apparent_ptStartPos.y, apparent_ptStartPos.x, ur.GetText (), ur.GetTextLength (), nEndLine, nEndChar));
           ptCursorPos = m_ptLastChange;
 
         }
@@ -1550,7 +1532,7 @@ Redo (CCrystalTextView * pSource, CPoint & ptCursorPos)
         {
           int nEndLine, nEndChar;
           VERIFY(InsertText (pSource, apparent_ptStartPos.y, apparent_ptStartPos.x,
-            ur.GetText(), nEndLine, nEndChar, 0, FALSE));
+            ur.GetText(), ur.GetTextLength(), nEndLine, nEndChar, 0, FALSE));
           ptCursorPos = m_ptLastChange;
         }
       else
@@ -1581,7 +1563,7 @@ Redo (CCrystalTextView * pSource, CPoint & ptCursorPos)
 //  [JRT] Support For Descriptions On Undo/Redo Actions
 // the CPoint parameters are apparent (on screen) line numbers
 void CCrystalTextBuffer::
-AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos, LPCTSTR pszText, int nActionType, CDWordArray *paSavedRevisonNumbers)
+AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos, LPCTSTR pszText, int cchText, int nActionType, CDWordArray *paSavedRevisonNumbers)
 {
   //  Forgot to call BeginUndoGroup()?
   ASSERT (m_bUndoGroup);
@@ -1644,7 +1626,7 @@ AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos,
     }
   ur.m_ptStartPos = ptStartPos;
   ur.m_ptEndPos = ptEndPos;
-  ur.SetText (pszText);
+  ur.SetText (pszText, cchText);
   ur.m_paSavedRevisonNumbers = paSavedRevisonNumbers;
 
   m_aUndoBuf.Add (ur);
@@ -1653,13 +1635,7 @@ AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos,
   ASSERT (m_aUndoBuf.GetSize () <= m_nUndoBufSize);
 }
 
-static BOOL HasEol(LPCTSTR szText)
-{
-  int len = (int) _tcslen(szText);
-  return (len && iseol(szText[len-1]));
-}
-
-LPCTSTR CCrystalTextBuffer::GetStringEol(int nCRLFMode) const
+LPCTSTR CCrystalTextBuffer::GetStringEol(int nCRLFMode)
 {
   switch(nCRLFMode)
   {
@@ -1669,19 +1645,14 @@ LPCTSTR CCrystalTextBuffer::GetStringEol(int nCRLFMode) const
   default: return _T("\r\n");
   }
 }
+
 LPCTSTR CCrystalTextBuffer::GetDefaultEol() const
 {
-  switch(m_nCRLFMode)
-  {
-  case CRLF_STYLE_DOS: return _T("\r\n");
-  case CRLF_STYLE_UNIX: return _T("\n");
-  case CRLF_STYLE_MAC: return _T("\r");
-  default: return _T("\r\n");
-  }
+  return GetStringEol(m_nCRLFMode);
 }
 
 BOOL CCrystalTextBuffer::
-InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText,
+InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int cchText,
             int &nEndLine, int &nEndChar, int nAction, BOOL bHistory /*=TRUE*/)
 {
   // save line revision numbers for undo
@@ -1689,7 +1660,7 @@ InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText,
   paSavedRevisonNumbers->SetSize(1);
   (*paSavedRevisonNumbers)[0] = m_aLines[nLine].m_dwRevisionNumber;
 
-  if (!InternalInsertText (pSource, nLine, nPos, pszText, nEndLine, nEndChar))
+  if (!InternalInsertText (pSource, nLine, nPos, pszText, cchText, nEndLine, nEndChar))
   {
     delete paSavedRevisonNumbers;
     return FALSE;
@@ -1717,7 +1688,7 @@ InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText,
     }
 
   AddUndoRecord (TRUE, CPoint (nPos, nLine), CPoint (nEndChar, nEndLine),
-                 pszText, nAction, paSavedRevisonNumbers);
+                 pszText, cchText, nAction, paSavedRevisonNumbers);
 
   if (bGroupFlag)
     FlushUndoGroup (pSource);
@@ -1764,7 +1735,7 @@ DeleteText (CCrystalTextView * pSource, int nStartLine, int nStartChar,
     }
 
   AddUndoRecord (FALSE, CPoint (nStartChar, nStartLine), CPoint (nEndChar, nEndLine),
-                 sTextToDelete, nAction, paSavedRevisonNumbers);
+                 sTextToDelete, sTextToDelete.GetLength(), nAction, paSavedRevisonNumbers);
 
   if (bGroupFlag)
     FlushUndoGroup (pSource);
index 1075e53..39fcdbd 100644 (file)
@@ -167,10 +167,14 @@ private :
         //  of any pointer will be != 0. So we can store 1 character strings without
         //  allocating memory.
         //
-
+        struct TextBuffer
+          {
+            int size;
+            TCHAR data[1];
+          };
         union
           {
-            TCHAR *m_pszText;     //  For cases when we have > 1 character strings
+            TextBuffer *m_pszText;     //  For cases when we have > 1 character strings
             TCHAR m_szText[2];    //  For single-character strings
           };
 
@@ -190,7 +194,7 @@ public :
           m_ptStartPos = src.m_ptStartPos;
           m_ptEndPos = src.m_ptEndPos;
           m_nAction = src.m_nAction;
-          SetText(src.GetText());
+          SetText(src.GetText(), src.GetTextLength());
           INT_PTR size = src.m_paSavedRevisonNumbers->GetSize();
           if (!m_paSavedRevisonNumbers)
             m_paSavedRevisonNumbers = new CDWordArray();
@@ -207,7 +211,7 @@ public :
             delete m_paSavedRevisonNumbers;
         }
 
-        void SetText (LPCTSTR pszText);
+        void SetText (LPCTSTR pszText, int cchText);
         void FreeText ();
 
         LPCTSTR GetText () const
@@ -216,9 +220,15 @@ public :
           // Check if m_pszText is a pointer by removing bits having
           // possible char value
           if (((INT_PTR)m_pszText >> 16) != 0)
-            return m_pszText;
+            return m_pszText->data;
           return m_szText;
-        };
+        }
+        int GetTextLength () const
+        {
+          if (((INT_PTR)m_pszText >> 16) != 0)
+            return m_pszText->size;
+          return 1;
+        }
       };
 
 #pragma pack(pop)
@@ -255,19 +265,19 @@ public :
     CList < CCrystalTextView *, CCrystalTextView * >m_lpViews;
 
     //  Helper methods
-    void InsertLine (LPCTSTR pszLine, int nLength = -1, int nPosition = -1, int nCount = 1);
-    void AppendLine (int nLineIndex, LPCTSTR pszChars, int nLength = -1);
+    void InsertLine (LPCTSTR pszLine, int nLength, int nPosition = -1, int nCount = 1);
+    void AppendLine (int nLineIndex, LPCTSTR pszChars, int nLength);
     void MoveLine(int line1, int line2, int newline1);
     void SetEmptyLine(int nPosition, int nCount = 1);
 
     //  Implementation
-    BOOL InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar);
+    BOOL InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int cchText, int &nEndLine, int &nEndChar);
     BOOL InternalDeleteText (CCrystalTextView * pSource, int nStartLine, int nStartPos, int nEndLine, int nEndPos);
     CString StripTail (int i, int bytes);
 
     //  [JRT] Support For Descriptions On Undo/Redo Actions
     virtual void AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos,
-                                LPCTSTR pszText, int nActionType = CE_ACTION_UNKNOWN, CDWordArray *paSavedRevisonNumbers = NULL);
+                                LPCTSTR pszText, int cchText, int nActionType = CE_ACTION_UNKNOWN, CDWordArray *paSavedRevisonNumbers = NULL);
 
     //  Overridable: provide action description
     virtual BOOL GetActionDescription (int nAction, CString & desc);
@@ -321,15 +331,15 @@ public :
     void SetCRLFMode (int nCRLFMode);
     /// Adjust all the lines in the buffer to the buffer default EOL Mode
     virtual BOOL applyEOLMode();
-    LPCTSTR CCrystalTextBuffer::GetDefaultEol() const;
-    LPCTSTR CCrystalTextBuffer::GetStringEol(int nCRLFMode) const;
+    LPCTSTR GetDefaultEol() const;
+    static LPCTSTR GetStringEol(int nCRLFMode);
     BOOL GetReadOnly () const;
     void SetReadOnly (BOOL bReadOnly = TRUE);
 
     void SetIgnoreEol(BOOL IgnoreEol) { m_IgnoreEol = IgnoreEol; }
 
     //  Text modification functions
-    virtual BOOL InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar, int nAction = CE_ACTION_UNKNOWN, BOOL bHistory =TRUE);
+    virtual BOOL InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int cchText, int &nEndLine, int &nEndChar, int nAction = CE_ACTION_UNKNOWN, BOOL bHistory =TRUE);
     virtual BOOL DeleteText (CCrystalTextView * pSource, int nStartLine, int nStartPos, int nEndLine, int nEndPos, int nAction = CE_ACTION_UNKNOWN, BOOL bHistory =TRUE);
 
     //  Undo/Redo
index b220e17..1d54b13 100644 (file)
@@ -675,29 +675,19 @@ GetLineActualLength (int nLineIndex)
   int nLength = GetLineLength (nLineIndex);
   if (nLength > 0)
     {
-      LPCTSTR pszLine = GetLineChars (nLineIndex);
-      LPTSTR pszChars = new TCHAR[nLength + 1];
-      ASSERT( pszChars );
-      if (!pszChars)
-        return 0;              // TODO: what to do if alloc fails...???
-      memcpy (pszChars, pszLine, sizeof (TCHAR) * nLength);
-      pszChars[nLength] = 0;
-      LPTSTR pszCurrent = pszChars;
-
+      LPCTSTR pszChars = GetLineChars (nLineIndex);
       const int nTabSize = GetTabSize ();
-      int ind = 0;
-
-      while (ind < nLength)
+      int i;
+      for (i = 0; i < nLength; i++)
         {
-          if (pszCurrent[ind] == _T('\t'))
+          TCHAR c = pszChars[i];
+          if (c == _T('\t'))
             nActualLength += (nTabSize - nActualLength % nTabSize);
+          else if (c >= _T('\x00') && c <= _T('\x1F') && c != _T('\r') && c != _T('\n'))
+            nActualLength += 3;
           else
             nActualLength++;
-
-          ind++;
         }
-
-      delete[] pszChars;
     }
 
   m_pnActualLineLength->SetAt(nLineIndex, nActualLength);
@@ -875,6 +865,14 @@ static void AppendStringAdv(CString & str, int & curpos, LPCTSTR szadd)
   curpos += _tcslen(szadd);
 }
 
+/** Append escaped control char to string str, and advance position curpos */
+static void AppendEscapeAdv(CString & str, int & curpos, TCHAR c)
+{
+  int curlen = str.GetLength();
+  LPTSTR szadd = str.GetBufferSetLength(curlen + 3) + curlen;
+  curpos += wsprintf(szadd, _T("\t%02X"), static_cast<int>(c));
+}
+
 int CCrystalTextView::
 ExpandChars (LPCTSTR pszChars, int nOffset, int nCount, CString & line, int nActualOffset)
 {
@@ -893,20 +891,22 @@ ExpandChars (LPCTSTR pszChars, int nOffset, int nCount, CString & line, int nAct
   pszChars += nOffset;
   int nLength = nCount;
 
-  int nTabCount = 0;
-  int i=0;
+  int i;
   for (i = 0; i < nLength; i++)
     {
-      if (pszChars[i] == _T('\t'))
-        nTabCount++;
+      TCHAR c = pszChars[i];
+      if (c == _T('\t'))
+        nCount += nTabSize - 1;
+      else if (c >= _T('\x00') && c <= _T('\x1F') && c != _T('\r') && c != _T('\n'))
+        nCount += 2;
     }
 
   // Preallocate line buffer, to avoid reallocations as we add characters
-  line.GetBuffer(nLength + nTabCount * (nTabSize - 1) + 1); // at least this many characters
+  line.GetBuffer(nCount + 1); // at least this many characters
   line.ReleaseBuffer(0);
   int nCurPos = 0;
 
-  if (nTabCount > 0 || m_bViewTabs || m_bViewEols)
+  if (nCount > nLength || m_bViewTabs || m_bViewEols)
     {
       for (i = 0; i < nLength; i++)
         {
@@ -948,6 +948,10 @@ ExpandChars (LPCTSTR pszChars, int nOffset, int nCount, CString & line, int nAct
                     }
                  }
             }
+          else if (pszChars[i] >= _T('\x00') && pszChars[i] <= _T('\x1F'))
+            {
+              AppendEscapeAdv(line, nCurPos, pszChars[i]);
+            }
           else
             {
               line += pszChars[i];
@@ -971,6 +975,8 @@ ExpandChars (LPCTSTR pszChars, int nOffset, int nCount, CString & line, int nAct
  */
 int CCrystalTextView::GetCharWidthFromChar(TCHAR ch)
 {
+  if (ch >= _T('\x00') && ch <= _T('\x1F') && ch != '\t')
+    return GetCharWidth() * 3;
   // This assumes a fixed width font
   // But the UNICODE case handles double-wide glyphs (primarily Chinese characters)
 #ifdef _UNICODE
@@ -1028,6 +1034,7 @@ DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
       nActualOffset += ExpandChars (pszChars, nOffset, nCount, line, nActualOffset);
       const int lineLen = line.GetLength();
       const int nCharWidth = GetCharWidth();
+      const int nLineHeight = GetLineHeight();
       int nSumWidth = 0;
 
       // i the character index, from 0 to lineLen-1
@@ -1043,11 +1050,12 @@ DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
           
           // Update the position after the left clipped characters
           // stop for i = first visible character, at least partly
-          for (  ; i < lineLen; i++)
+          const int clipLeft = rcClip.left - GetCharWidth() * 2;
+          for ( ; i < lineLen; i++)
           {
             int pnWidthsCurrent = GetCharWidthFromChar(line[i]);
             ptOrigin.x += pnWidthsCurrent;
-            if (ptOrigin.x >= rcClip.left)
+            if (ptOrigin.x >= clipLeft)
             {
               ptOrigin.x -= pnWidthsCurrent;
               break;
@@ -1089,29 +1097,64 @@ DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
               // Seems that CrystalEditor's and ExtTextOut()'s charwidths aren't
               // same with some fonts and text is drawn only partially
               // if this table is not used.
-              int* pnWidths = new int[nCount];
-              for (  ; i < nCount + ibegin ; i++)
+              int* pnWidths = new int[nCount + 2];
+              for ( ; i < nCount + ibegin ; i++)
                 {
-                  pnWidths[i-ibegin] = GetCharWidthFromChar(line[i]);
-                  nSumWidth += pnWidths[i-ibegin];
+                  if (line[i] == '\t') // Escape sequence leadin?
+                  {
+                    // Substitute a space narrowed to half the width of a character cell.
+                    line.SetAt(i, ' ');
+                    nSumWidth += pnWidths[i - ibegin] = nCharWidth / 2;
+                    // 1st hex digit has normal width.
+                    nSumWidth += pnWidths[++i - ibegin] = nCharWidth;
+                    // 2nd hex digit is padded by half the width of a character cell.
+                    nSumWidth += pnWidths[++i - ibegin] = nCharWidth + nCharWidth / 2;
+                  }
+                  else
+                  {
+                    nSumWidth += pnWidths[i - ibegin] = GetCharWidthFromChar(line[i]);
+                  }
                 }
 
               if (ptOrigin.x + nSumWidth > rcClip.left)
                 {
-                   if (crText == CLR_NONE || nColorIndex & COLORINDEX_APPLYFORCE)
-                     pdc->SetTextColor(GetColor(nColorIndex));
-                   else
-                     pdc->SetTextColor(crText);
-                   if (crBkgnd == CLR_NONE || nBgColorIndex & COLORINDEX_APPLYFORCE)
-                     pdc->SetBkColor(GetColor(nBgColorIndex));
-                   else
-                     pdc->SetBkColor(crBkgnd);
-
-                   pdc->SelectObject(GetFont(GetItalic(nColorIndex),
-                       GetBold(nColorIndex)));
+                  if (crText == CLR_NONE || nColorIndex & COLORINDEX_APPLYFORCE)
+                    pdc->SetTextColor(GetColor(nColorIndex));
+                  else
+                    pdc->SetTextColor(crText);
+                  if (crBkgnd == CLR_NONE || nBgColorIndex & COLORINDEX_APPLYFORCE)
+                    pdc->SetBkColor(GetColor(nBgColorIndex));
+                  else
+                    pdc->SetBkColor(crBkgnd);
+
+                  pdc->SelectObject(GetFont(GetItalic(nColorIndex),
+                      GetBold(nColorIndex)));
                   // we are sure to have less than 4095 characters because all the chars are visible
                   VERIFY(pdc->ExtTextOut(ptOrigin.x, ptOrigin.y, ETO_CLIPPED,
                       &rcClip, LPCTSTR(line) + ibegin, nCount, pnWidths));
+                  // Draw rounded rectangles around control characters
+                  pdc->IntersectClipRect(&rcClip);
+                  HDC hDC = pdc->m_hDC;
+                  HGDIOBJ hBrush = ::GetStockObject(NULL_BRUSH);
+                  hBrush = ::SelectObject(hDC, hBrush);
+                  HGDIOBJ hPen = ::CreatePen(PS_SOLID, 1, ::GetTextColor(hDC));
+                  hPen = ::SelectObject(hDC, hPen);
+                  int x = ptOrigin.x;
+                  for (int j = 0 ; j < nCount ; ++j)
+                  {
+                    // Assume narrowed space is converted escape sequence leadin.
+                    if (line[ibegin + j] == ' ' && pnWidths[j] < nCharWidth)
+                    {
+                      ::RoundRect(hDC, x + nCharWidth / 2 - 2, ptOrigin.y + 1,
+                        x + nCharWidth / 2 + 2 * nCharWidth + 2, ptOrigin.y + nLineHeight - 1,
+                        nCharWidth / 2, nLineHeight / 2);
+                    }
+                    x += pnWidths[j];
+                  }
+                  hPen = ::SelectObject(hDC, hPen);
+                  ::DeleteObject(hPen);
+                  hBrush = ::SelectObject(hDC, hBrush);
+                  pdc->SelectClipRgn(NULL);
                 }
 
               delete [] pnWidths;
@@ -1120,12 +1163,12 @@ DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
               ptOrigin.x += nSumWidth;
 
             }
-
-        }        
-        
+        }
       // Update the final position after the right clipped characters
-      for (  ; i < lineLen; i++)
-        ptOrigin.x += GetCharWidthFromChar(line[i]);
+      for ( ; i < lineLen; i++)
+        {
+          ptOrigin.x += GetCharWidthFromChar(line[i]);
+        }
     }
 }
 
@@ -4578,13 +4621,16 @@ PrepareDragData ()
 
   CString text;
   GetText (m_ptDrawSelStart, m_ptDrawSelEnd, text);
-  HGLOBAL hData =::GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, (_tcslen (text)+1)*sizeof(TCHAR));
+  int cchText = text.GetLength();
+  SIZE_T cbData = (cchText + 1) * sizeof(TCHAR);
+  HGLOBAL hData =::GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, cbData);
   if (hData == NULL)
     return NULL;
+  ::GlobalReAlloc(hData, cbData, 0);
+  ASSERT(::GlobalSize(hData) == cbData);
 
   LPTSTR pszData = (LPTSTR)::GlobalLock (hData);
-  _tcscpy (pszData, text.GetBuffer (0));
-  text.ReleaseBuffer ();
+  memcpy (pszData, text, cbData);
   ::GlobalUnlock (hData);
 
   m_ptDraggedTextBegin = m_ptDrawSelStart;
index fc0157c..eeb7a69 100644 (file)
@@ -441,7 +441,7 @@ protected:
 
     //  Clipboard overridable
     virtual BOOL TextInClipboard ();
-    virtual BOOL PutToClipboard (LPCTSTR pszText);
+    virtual BOOL PutToClipboard (LPCTSTR pszText, int cchText);
     virtual BOOL GetFromClipboard (CString & text);
 
     //  Drag-n-drop overrideable
index 64fd8f8..4091d67 100644 (file)
@@ -63,6 +63,17 @@ static char THIS_FILE[] = __FILE__;
 
 #define CRYSTAL_TIMER_DRAGSEL   1001
 
+static LPTSTR NTAPI EnsureCharNext(LPCTSTR current)
+{
+  LPTSTR next = ::CharNext(current);
+  return next > current ? next : next + 1;
+}
+
+static LPTSTR NTAPI EnsureCharPrev(LPCTSTR start, LPCTSTR current)
+{
+  LPTSTR prev = ::CharPrev(start, current);
+  return prev < current ? prev : prev - 1;
+}
 
 /////////////////////////////////////////////////////////////////////////////
 // CCrystalTextView
@@ -158,7 +169,7 @@ MoveWordLeft (BOOL bSelect)
   LPCTSTR pszChars = GetLineChars (m_ptCursorPos.y);
   int nPos = m_ptCursorPos.x;
   int nPrevPos;
-  while (nPos > 0 && xisspace (pszChars[nPrevPos = ::CharPrev(pszChars, pszChars + nPos) - pszChars]))
+  while (nPos > 0 && xisspace (pszChars[nPrevPos = ::EnsureCharPrev(pszChars, pszChars + nPos) - pszChars]))
     nPos = nPrevPos;
 
   if (nPos > 0)
@@ -167,12 +178,12 @@ MoveWordLeft (BOOL bSelect)
       nPos = nPrevPos;
       if (xisalnum (pszChars[nPos]))
         {
-          while (nPos > 0 && (xisalnum (pszChars[nPrevPos = ::CharPrev(pszChars, pszChars + nPos) - pszChars])))
+          while (nPos > 0 && (xisalnum (pszChars[nPrevPos = ::EnsureCharPrev(pszChars, pszChars + nPos) - pszChars])))
             nPos = nPrevPos;
         }
       else
         {
-          while (nPos > 0 && !xisalnum (pszChars[nPrevPos = ::CharPrev(pszChars, pszChars + nPos) - pszChars])
+          while (nPos > 0 && !xisalnum (pszChars[nPrevPos = ::EnsureCharPrev(pszChars, pszChars + nPos) - pszChars])
                 && !xisspace (pszChars[nPrevPos]))
             nPos = nPrevPos;
         }
@@ -217,17 +228,17 @@ MoveWordRight (BOOL bSelect)
   if (xisalnum (pszChars[nPos]))
     {
       while (nPos < nLength && xisalnum (pszChars[nPos]))
-        nPos = ::CharNext(pszChars + nPos) - pszChars;
+        nPos = ::EnsureCharNext(pszChars + nPos) - pszChars;
     }
   else
     {
       while (nPos < nLength && !xisalnum (pszChars[nPos])
             && !xisspace (pszChars[nPos]))
-        nPos = ::CharNext(pszChars + nPos) - pszChars;
+        nPos = ::EnsureCharNext(pszChars + nPos) - pszChars;
     }
 
   while (nPos < nLength && xisspace (pszChars[nPos]))
-    nPos = ::CharNext(pszChars + nPos) - pszChars;
+    nPos = ::EnsureCharNext(pszChars + nPos) - pszChars;
 
   m_ptCursorPos.x = nPos;
   m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
@@ -1171,7 +1182,7 @@ Copy ()
   PrepareSelBounds ();
   CString text;
   GetText (m_ptDrawSelStart, m_ptDrawSelEnd, text);
-  PutToClipboard (text);
+  PutToClipboard (text, text.GetLength());
 }
 
 
@@ -1183,9 +1194,9 @@ TextInClipboard ()
 }
 
 BOOL CCrystalTextView::
-PutToClipboard (LPCTSTR pszText)
+PutToClipboard (LPCTSTR pszText, int cchText)
 {
-  if (pszText == NULL || _tcslen (pszText) == 0)
+  if (pszText == NULL || cchText == 0)
     return FALSE;
 
   CWaitCursor wc;
@@ -1193,11 +1204,14 @@ PutToClipboard (LPCTSTR pszText)
   if (OpenClipboard ())
     {
       EmptyClipboard ();
-      HGLOBAL hData = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, (_tcslen(pszText)+1) * sizeof(TCHAR));
+      SIZE_T cbData = (cchText + 1) * sizeof(TCHAR);
+      HGLOBAL hData = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, cbData);
       if (hData != NULL)
         {
+          GlobalReAlloc(hData, cbData, 0);
+          ASSERT(GlobalSize(hData) == cbData);
           LPTSTR pszData = (LPTSTR)::GlobalLock (hData);
-          _tcscpy (pszData, pszText);
+          memcpy (pszData, pszText, cbData);
           GlobalUnlock (hData);
           UINT fmt = GetClipTcharTextFormat();
           bOK = SetClipboardData (fmt, hData) != NULL;
@@ -1220,7 +1234,10 @@ GetFromClipboard (CString & text)
           LPTSTR pszData = (LPTSTR) GlobalLock (hData);
           if (pszData != NULL)
             {
-              text = pszData;
+              SIZE_T cbData = GlobalSize (hData);
+              int cchText = cbData / sizeof(TCHAR) - 1;
+              if (cchText >= 0)
+                memcpy(text.GetBufferSetLength(cchText), pszData, cbData);
               GlobalUnlock (hData);
               bSuccess = TRUE;
             }
index d89647f..a4d129e 100644 (file)
@@ -356,7 +356,7 @@ OnEditReplace ()
     dwSearchFlags |= FIND_REGEXP;
 
   //  We have highlighted text
-  VERIFY (m_pBuddy->ReplaceSelection (m_sNewText, dwSearchFlags));
+  VERIFY (m_pBuddy->ReplaceSelection (m_sNewText, m_sNewText.GetLength(), dwSearchFlags));
 
   //  Manually recalculate points
   if (m_bEnableScopeSelection)
@@ -425,7 +425,7 @@ OnEditReplaceAll ()
         dwSearchFlags |= FIND_REGEXP;
     
       //  We have highlighted text
-      VERIFY (m_pBuddy->ReplaceSelection (m_sNewText, dwSearchFlags));
+      VERIFY (m_pBuddy->ReplaceSelection (m_sNewText, m_sNewText.GetLength(), dwSearchFlags));
 
       //  Manually recalculate points
       if (m_bEnableScopeSelection)
index 8081f1c..0e95e34 100644 (file)
@@ -43,6 +43,11 @@ DWORD CCrystalParser::ParseLine(DWORD /*dwCookie*/,
        return 0;
 }
 
+static LPTSTR NTAPI EnsureCharNext(LPCTSTR current)
+{
+       LPTSTR next = ::CharNext(current);
+       return next > current ? next : next + 1;
+}
 
 void CCrystalParser::WrapLine( int nLineIndex, int nMaxLineWidth, int *anBreaks, int &nBreaks )
 {
@@ -59,7 +64,7 @@ void CCrystalParser::WrapLine( int nLineIndex, int nMaxLineWidth, int *anBreaks,
        int                     nLastCharBreakPos = 0;
        BOOL            bBreakable = FALSE;
 
-       for( int i = 0; i < nLineLength; i += CharNext(szLine + i) - (szLine + i) )
+       for( int i = 0; i < nLineLength; i += EnsureCharNext(szLine + i) - (szLine + i) )
        {
                // remember position of whitespace for wrap
                if( bBreakable )