}
}
}
- pszBuf[0] = 0;
- text.ReleaseBuffer();
+ text.ReleaseBuffer(pszBuf - text);
text.FreeExtra();
}
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
{
// 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;
}
(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,
{
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;
{
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
#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));
/** 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);
ur.m_nRealLinesCreated = nRealLinesChanged;
else
ur.m_nRealLinesInDeletedBlock = nRealLinesChanged;
- ur.SetText (pszText);
+ ur.SetText (pszText, cchText);
ur.m_paSavedRevisonNumbers = paSavedRevisonNumbers;
m_aUndoBuf.Add (ur);
* 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;
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;
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);
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);
// 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
};
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();
delete m_paSavedRevisonNumbers;
}
- void SetText (LPCTSTR pszText);
+ void SetText (LPCTSTR pszText, int cchText);
void FreeText ();
LPCTSTR GetText () const
// 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)
// [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
// 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);
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;
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());
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())
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;
}
}
// write this line to the file (codeset or unicode conversions are done there)
- if (!bTempFile)
- UnescapeControlChars(sLine);
file.WriteString(sLine);
}
file.Close();
}
/// 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
// (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;
}
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);
}
/**
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,
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)
{
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)
{
buffer->GetTextWithoutEmptys(ptSelStart.y, ptSelStart.x,
ptSelEnd.y, ptSelEnd.x, text);
- PutToClipboard(text);
+ PutToClipboard(text, text.GetLength());
}
/**
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);
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);
}
/**
strText += sSpaces;
strNumLine.Format(_T("%d: %s"), line + 1, strLine);
strText += strNumLine;
- }
- PutToClipboard(strText);
+ }
+ PutToClipboard(strText, strText.GetLength());
}
void CMergeEditView::OnUpdateEditCopyLinenumbers(CCmdUI* pCmdUI)
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;
GetSelection (ptSelStart, ptSelEnd);
CString text;
GetText (ptSelStart, ptSelEnd, text);
- PutToClipboard (text);
+ PutToClipboard (text, text.GetLength());
CPoint ptCursorPos = ptSelStart;
ASSERT_VALIDTEXTPOS (ptCursorPos);
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;
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);
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;
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;
// [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;
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;
}
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);
}
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();
}
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);
// 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);
// 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);
// 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);
// 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);
{
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);
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);
*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);
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);
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);
}
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);
}
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);
}
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);
}
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);
}
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);
{
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);
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;
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);
// 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
{
// 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;
}
*/
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;
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
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;
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)
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;
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);
}
memcpy (pszBuf, m_aLines[nStartLine].m_pcLine + nStartChar, sizeof (TCHAR) * nCount);
pszBuf += nCount;
}
- pszBuf[0] = 0;
- text.ReleaseBuffer ();
+ text.ReleaseBuffer (pszBuf - text);
text.FreeExtra ();
}
{
// 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++)
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)
// 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!
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
}
- if (pszText[nTextPos] == 0)
+ if (nTextPos == cchText)
{
// we just finished our insert
// now we have to reattach the tail
{
if (haseol)
{
- InsertLine(sTail, -1, nEndLine);
+ InsertLine(sTail, sTail.GetLength(), nEndLine);
nInsertedLines ++;
}
else
// 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;
++nCurrentLine;
pszText += nTextPos;
+ cchText -= nTextPos;
}
// Compute the context : all positions after context.m_ptBegin are
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;
}
{
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
// [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);
}
ur.m_ptStartPos = ptStartPos;
ur.m_ptEndPos = ptEndPos;
- ur.SetText (pszText);
+ ur.SetText (pszText, cchText);
ur.m_paSavedRevisonNumbers = paSavedRevisonNumbers;
m_aUndoBuf.Add (ur);
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)
{
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
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;
}
AddUndoRecord (TRUE, CPoint (nPos, nLine), CPoint (nEndChar, nEndLine),
- pszText, nAction, paSavedRevisonNumbers);
+ pszText, cchText, nAction, paSavedRevisonNumbers);
if (bGroupFlag)
FlushUndoGroup (pSource);
}
AddUndoRecord (FALSE, CPoint (nStartChar, nStartLine), CPoint (nEndChar, nEndLine),
- sTextToDelete, nAction, paSavedRevisonNumbers);
+ sTextToDelete, sTextToDelete.GetLength(), nAction, paSavedRevisonNumbers);
if (bGroupFlag)
FlushUndoGroup (pSource);
// 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
};
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();
delete m_paSavedRevisonNumbers;
}
- void SetText (LPCTSTR pszText);
+ void SetText (LPCTSTR pszText, int cchText);
void FreeText ();
LPCTSTR GetText () const
// 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)
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);
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
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);
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)
{
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++)
{
}
}
}
+ else if (pszChars[i] >= _T('\x00') && pszChars[i] <= _T('\x1F'))
+ {
+ AppendEscapeAdv(line, nCurPos, pszChars[i]);
+ }
else
{
line += pszChars[i];
*/
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
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
// 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;
// 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;
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]);
+ }
}
}
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;
// 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
#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
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)
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;
}
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);
PrepareSelBounds ();
CString text;
GetText (m_ptDrawSelStart, m_ptDrawSelEnd, text);
- PutToClipboard (text);
+ PutToClipboard (text, text.GetLength());
}
}
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;
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;
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;
}
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)
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)
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 )
{
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 )