From c59e8b7d499e20f04189136a0e824cc5c6283145 Mon Sep 17 00:00:00 2001 From: Jochen Tucht Date: Thu, 31 Jan 2008 21:08:06 +0000 Subject: [PATCH] Patch #1880711 --- Src/GhostTextBuffer.cpp | 36 +++++----- Src/GhostTextBuffer.h | 29 +++++--- Src/GhostTextView.cpp | 9 ++- Src/MergeDoc.cpp | 32 ++++----- Src/MergeDoc.h | 4 +- Src/MergeDocLineDiffs.cpp | 8 +-- Src/MergeEditView.cpp | 10 +-- Src/editlib/ccrystaleditview.cpp | 75 ++++++++++---------- Src/editlib/ccrystaleditview.h | 2 +- Src/editlib/ccrystaltextbuffer.cpp | 109 +++++++++++----------------- Src/editlib/ccrystaltextbuffer.h | 36 ++++++---- Src/editlib/ccrystaltextview.cpp | 142 ++++++++++++++++++++++++------------- Src/editlib/ccrystaltextview.h | 2 +- Src/editlib/ccrystaltextview2.cpp | 41 +++++++---- Src/editlib/ceditreplacedlg.cpp | 4 +- Src/editlib/crystalparser.cpp | 7 +- 16 files changed, 303 insertions(+), 243 deletions(-) diff --git a/Src/GhostTextBuffer.cpp b/Src/GhostTextBuffer.cpp index 88a2359d2..91abc9139 100644 --- a/Src/GhostTextBuffer.cpp +++ b/Src/GhostTextBuffer.cpp @@ -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); diff --git a/Src/GhostTextBuffer.h b/Src/GhostTextBuffer.h index 38ea7d488..400ab99eb 100644 --- a/Src/GhostTextBuffer.h +++ b/Src/GhostTextBuffer.h @@ -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); diff --git a/Src/GhostTextView.cpp b/Src/GhostTextView.cpp index d4f27bed5..6f62475b5 100644 --- a/Src/GhostTextView.cpp +++ b/Src/GhostTextView.cpp @@ -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; diff --git a/Src/MergeDoc.cpp b/Src/MergeDoc.cpp index c775cee35..4e3e029c0 100644 --- a/Src/MergeDoc.cpp +++ b/Src/MergeDoc.cpp @@ -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); } /** diff --git a/Src/MergeDoc.h b/Src/MergeDoc.h index 4c6fc7b0e..4cc57a264 100644 --- a/Src/MergeDoc.h +++ b/Src/MergeDoc.h @@ -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, diff --git a/Src/MergeDocLineDiffs.cpp b/Src/MergeDocLineDiffs.cpp index 154658711..f7caedfb9 100644 --- a/Src/MergeDocLineDiffs.cpp +++ b/Src/MergeDocLineDiffs.cpp @@ -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) { diff --git a/Src/MergeEditView.cpp b/Src/MergeEditView.cpp index c8c0dbfc9..b9233a9e4 100644 --- a/Src/MergeEditView.cpp +++ b/Src/MergeEditView.cpp @@ -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) diff --git a/Src/editlib/ccrystaleditview.cpp b/Src/editlib/ccrystaleditview.cpp index e170f3f5f..2ba118551 100644 --- a/Src/editlib/ccrystaleditview.cpp +++ b/Src/editlib/ccrystaleditview.cpp @@ -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; diff --git a/Src/editlib/ccrystaleditview.h b/Src/editlib/ccrystaleditview.h index 5d031b3b8..d53d52188 100644 --- a/Src/editlib/ccrystaleditview.h +++ b/Src/editlib/ccrystaleditview.h @@ -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); diff --git a/Src/editlib/ccrystaltextbuffer.cpp b/Src/editlib/ccrystaltextbuffer.cpp index 6814d7e77..7eab2d7c3 100644 --- a/Src/editlib/ccrystaltextbuffer.cpp +++ b/Src/editlib/ccrystaltextbuffer.cpp @@ -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); diff --git a/Src/editlib/ccrystaltextbuffer.h b/Src/editlib/ccrystaltextbuffer.h index 1075e53a8..39fcdbd4b 100644 --- a/Src/editlib/ccrystaltextbuffer.h +++ b/Src/editlib/ccrystaltextbuffer.h @@ -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 diff --git a/Src/editlib/ccrystaltextview.cpp b/Src/editlib/ccrystaltextview.cpp index b220e1769..1d54b1351 100644 --- a/Src/editlib/ccrystaltextview.cpp +++ b/Src/editlib/ccrystaltextview.cpp @@ -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(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; diff --git a/Src/editlib/ccrystaltextview.h b/Src/editlib/ccrystaltextview.h index fc0157c5c..eeb7a69d8 100644 --- a/Src/editlib/ccrystaltextview.h +++ b/Src/editlib/ccrystaltextview.h @@ -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 diff --git a/Src/editlib/ccrystaltextview2.cpp b/Src/editlib/ccrystaltextview2.cpp index 64fd8f854..4091d67a7 100644 --- a/Src/editlib/ccrystaltextview2.cpp +++ b/Src/editlib/ccrystaltextview2.cpp @@ -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; } diff --git a/Src/editlib/ceditreplacedlg.cpp b/Src/editlib/ceditreplacedlg.cpp index d89647f7f..a4d129e41 100644 --- a/Src/editlib/ceditreplacedlg.cpp +++ b/Src/editlib/ceditreplacedlg.cpp @@ -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) diff --git a/Src/editlib/crystalparser.cpp b/Src/editlib/crystalparser.cpp index 8081f1cee..0e95e348f 100644 --- a/Src/editlib/crystalparser.cpp +++ b/Src/editlib/crystalparser.cpp @@ -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 ) -- 2.11.0