📄 ccrystaltextbuffer.cpp
字号:
_wsplitpath (pszFileName, drive, dir, name, ext);
#else
_splitpath (pszFileName, drive, dir, name, ext);
#endif
_tcscpy (szTempFileDir, drive);
_tcscat (szTempFileDir, dir);
_tcscpy (szBackupFileName, pszFileName);
_tcscat (szBackupFileName, _T (".bak"));
if (::GetTempFileName (szTempFileDir, _T ("CRE"), 0, szTempFileName) == 0)
__leave;
hTempFile =::CreateFile (szTempFileName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hTempFile == INVALID_HANDLE_VALUE)
__leave;
if (nCrlfStyle == CRLF_STYLE_AUTOMATIC)
nCrlfStyle = m_nCRLFMode;
ASSERT (nCrlfStyle >= 0 && nCrlfStyle <= 2);
LPCTSTR pszCRLF = crlfs[nCrlfStyle];
int nCRLFLength = _tcslen (pszCRLF);
int nLineCount = m_aLines.GetSize ();
for (int nLine = 0; nLine < nLineCount; nLine++)
{
int nLength = m_aLines[nLine].m_nLength;
DWORD dwWrittenBytes;
if (nLength > 0)
{
LPCTSTR pszLine = m_aLines[nLine].m_pcLine;
if (m_nSourceEncoding >= 0)
{
LPTSTR pszBuf;
iconvert_new (m_aLines[nLine].m_pcLine, &pszBuf, 1, m_nSourceEncoding, m_nSourceEncoding == 15);
if (!::WriteFile (hTempFile, pszBuf, nLength, &dwWrittenBytes, NULL))
{
free (pszBuf);
__leave;
}
free (pszBuf);
}
else
if (!::WriteFile (hTempFile, pszLine, nLength, &dwWrittenBytes, NULL))
__leave;
if (nLength != (int) dwWrittenBytes)
__leave;
}
if (nLine < nLineCount - 1) // Last line must not end with CRLF
{
if (!::WriteFile (hTempFile, pszCRLF, nCRLFLength, &dwWrittenBytes, NULL))
__leave;
if (nCRLFLength != (int) dwWrittenBytes)
__leave;
}
}
::CloseHandle (hTempFile);
hTempFile = INVALID_HANDLE_VALUE;
if (m_bCreateBackupFile)
{
WIN32_FIND_DATA wfd;
hSearch =::FindFirstFile (pszFileName, &wfd);
if (hSearch != INVALID_HANDLE_VALUE)
{
// File exist - create backup file
::DeleteFile (szBackupFileName);
if (!::MoveFile (pszFileName, szBackupFileName))
__leave;
::FindClose (hSearch);
hSearch = INVALID_HANDLE_VALUE;
}
}
else
{
::DeleteFile (pszFileName);
}
// Move temporary file to target name
if (!::MoveFile (szTempFileName, pszFileName))
__leave;
if (bClearModifiedFlag)
{
SetModified (FALSE);
m_nSyncPosition = m_nUndoPosition;
}
bSuccess = TRUE;
}
__finally
{
if (hSearch != INVALID_HANDLE_VALUE)
::FindClose (hSearch);
if (hTempFile != INVALID_HANDLE_VALUE)
::CloseHandle (hTempFile);
::DeleteFile (szTempFileName);
}
return bSuccess;
}
int CCrystalTextBuffer::
GetCRLFMode ()
{
return m_nCRLFMode;
}
void CCrystalTextBuffer::
SetCRLFMode (int nCRLFMode)
{
/*ASSERT (nCRLFMode == CRLF_STYLE_DOS ||
nCRLFMode == CRLF_STYLE_UNIX ||
nCRLFMode == CRLF_STYLE_MAC);*/
if (nCRLFMode >= 0)
{
m_nCRLFMode = nCRLFMode;
}
}
int CCrystalTextBuffer::
GetLineCount ()
{
ASSERT (m_bInit); // Text buffer not yet initialized.
// You must call InitNew() or LoadFromFile() first!
return m_aLines.GetSize ();
}
int CCrystalTextBuffer::
GetLineLength (int nLine)
{
ASSERT (m_bInit); // Text buffer not yet initialized.
// You must call InitNew() or LoadFromFile() first!
return m_aLines[nLine].m_nLength;
}
LPTSTR CCrystalTextBuffer::
GetLineChars (int nLine)
{
ASSERT (m_bInit); // Text buffer not yet initialized.
// You must call InitNew() or LoadFromFile() first!
return m_aLines[nLine].m_pcLine;
}
DWORD CCrystalTextBuffer::
GetLineFlags (int nLine)
{
ASSERT (m_bInit); // Text buffer not yet initialized.
// You must call InitNew() or LoadFromFile() first!
return m_aLines[nLine].m_dwFlags;
}
static int
FlagToIndex (DWORD dwFlag)
{
int nIndex = 0;
while ((dwFlag & 1) == 0)
{
dwFlag = dwFlag >> 1;
nIndex++;
if (nIndex == 32)
return -1;
}
dwFlag = dwFlag & 0xFFFFFFFE;
if (dwFlag != 0)
return -1;
return nIndex;
}
int CCrystalTextBuffer::
FindLineWithFlag (DWORD dwFlag)
{
int nSize = m_aLines.GetSize ();
for (int L = 0; L < nSize; L++)
{
if ((m_aLines[L].m_dwFlags & dwFlag) != 0)
return L;
}
return -1;
}
int CCrystalTextBuffer::
GetLineWithFlag (DWORD dwFlag)
{
int nFlagIndex =::FlagToIndex (dwFlag);
if (nFlagIndex < 0)
{
ASSERT (FALSE); // Invalid flag passed in
return -1;
}
return FindLineWithFlag (dwFlag);
}
void CCrystalTextBuffer::
SetLineFlag (int nLine, DWORD dwFlag, BOOL bSet, BOOL bRemoveFromPreviousLine /*= TRUE*/ )
{
ASSERT (m_bInit); // Text buffer not yet initialized.
// You must call InitNew() or LoadFromFile() first!
int nFlagIndex =::FlagToIndex (dwFlag);
if (nFlagIndex < 0)
{
ASSERT (FALSE); // Invalid flag passed in
return;
}
if (nLine == -1)
{
ASSERT (!bSet);
nLine = FindLineWithFlag (dwFlag);
if (nLine == -1)
return;
bRemoveFromPreviousLine = FALSE;
}
DWORD dwNewFlags = m_aLines[nLine].m_dwFlags;
if (bSet)
dwNewFlags = dwNewFlags | dwFlag;
else
dwNewFlags = dwNewFlags & ~dwFlag;
if (m_aLines[nLine].m_dwFlags != dwNewFlags)
{
if (bRemoveFromPreviousLine)
{
int nPrevLine = FindLineWithFlag (dwFlag);
if (bSet)
{
if (nPrevLine >= 0)
{
ASSERT ((m_aLines[nPrevLine].m_dwFlags & dwFlag) != 0);
m_aLines[nPrevLine].m_dwFlags &= ~dwFlag;
UpdateViews (NULL, NULL, UPDATE_SINGLELINE | UPDATE_FLAGSONLY, nPrevLine);
}
}
else
{
ASSERT (nPrevLine == nLine);
}
}
m_aLines[nLine].m_dwFlags = dwNewFlags;
UpdateViews (NULL, NULL, UPDATE_SINGLELINE | UPDATE_FLAGSONLY, nLine);
}
}
void CCrystalTextBuffer::
GetText (int nStartLine, int nStartChar, int nEndLine, int nEndChar, CString & text, LPCTSTR pszCRLF /*= NULL*/ )
{
ASSERT (m_bInit); // Text buffer not yet initialized.
// You must call InitNew() or LoadFromFile() first!
ASSERT (nStartLine >= 0 && nStartLine < m_aLines.GetSize ());
ASSERT (nStartChar >= 0 && nStartChar <= m_aLines[nStartLine].m_nLength);
ASSERT (nEndLine >= 0 && nEndLine < m_aLines.GetSize ());
ASSERT (nEndChar >= 0 && nEndChar <= m_aLines[nEndLine].m_nLength);
ASSERT (nStartLine < nEndLine || nStartLine == nEndLine && nStartChar < nEndChar);
if (pszCRLF == NULL)
pszCRLF = crlf;
int nCRLFLength = _tcslen (pszCRLF);
ASSERT (nCRLFLength > 0);
int nBufSize = 0;
for (int L = nStartLine; L <= nEndLine; L++)
{
nBufSize += m_aLines[L].m_nLength;
nBufSize += nCRLFLength;
}
LPTSTR pszBuf = text.GetBuffer (nBufSize);
if (nStartLine < nEndLine)
{
int nCount = m_aLines[nStartLine].m_nLength - nStartChar;
if (nCount > 0)
{
memcpy (pszBuf, m_aLines[nStartLine].m_pcLine + nStartChar, sizeof (TCHAR) * nCount);
pszBuf += nCount;
}
memcpy (pszBuf, pszCRLF, sizeof (TCHAR) * nCRLFLength);
pszBuf += nCRLFLength;
for (int I = nStartLine + 1; I < nEndLine; I++)
{
nCount = m_aLines[I].m_nLength;
if (nCount > 0)
{
memcpy (pszBuf, m_aLines[I].m_pcLine, sizeof (TCHAR) * nCount);
pszBuf += nCount;
}
memcpy (pszBuf, pszCRLF, sizeof (TCHAR) * nCRLFLength);
pszBuf += nCRLFLength;
}
if (nEndChar > 0)
{
memcpy (pszBuf, m_aLines[nEndLine].m_pcLine, sizeof (TCHAR) * nEndChar);
pszBuf += nEndChar;
}
}
else
{
int nCount = nEndChar - nStartChar;
memcpy (pszBuf, m_aLines[nStartLine].m_pcLine + nStartChar, sizeof (TCHAR) * nCount);
pszBuf += nCount;
}
pszBuf[0] = 0;
text.ReleaseBuffer ();
text.FreeExtra ();
}
void CCrystalTextBuffer::
AddView (CCrystalTextView * pView)
{
m_lpViews.AddTail (pView);
}
void CCrystalTextBuffer::
RemoveView (CCrystalTextView * pView)
{
POSITION pos = m_lpViews.GetHeadPosition ();
while (pos != NULL)
{
POSITION thispos = pos;
CCrystalTextView *pvw = m_lpViews.GetNext (pos);
if (pvw == pView)
{
m_lpViews.RemoveAt (thispos);
return;
}
}
ASSERT (FALSE);
}
CCrystalTextView::TextDefinition *CCrystalTextBuffer::
RetypeViews (LPCTSTR lpszFileName)
{
POSITION pos = m_lpViews.GetHeadPosition ();
CString sNew = GetExt (lpszFileName);
CCrystalTextView::TextDefinition *def = CCrystalTextView::GetTextType (sNew);
while (pos != NULL)
{
CCrystalTextView *pView = m_lpViews.GetNext (pos);
pView->SetTextType (def);
}
return def;
}
void CCrystalTextBuffer::
UpdateViews (CCrystalTextView * pSource, CUpdateContext * pContext, DWORD dwUpdateFlags, int nLineIndex /*= -1*/ )
{
POSITION pos = m_lpViews.GetHeadPosition ();
while (pos != NULL)
{
CCrystalTextView *pView = m_lpViews.GetNext (pos);
pView->UpdateView (pSource, pContext, dwUpdateFlags, nLineIndex);
}
}
BOOL CCrystalTextBuffer::
InternalDeleteText (CCrystalTextView * pSource, int nStartLine, int nStartChar, int nEndLine, int nEndChar)
{
ASSERT (m_bInit); // Text buffer not yet initialized.
// You must call InitNew() or LoadFromFile() first!
ASSERT (nStartLine >= 0 && nStartLine < m_aLines.GetSize ());
ASSERT (nStartChar >= 0 && nStartChar <= m_aLines[nStartLine].m_nLength);
ASSERT (nEndLine >= 0 && nEndLine < m_aLines.GetSize ());
ASSERT (nEndChar >= 0 && nEndChar <= m_aLines[nEndLine].m_nLength);
ASSERT (nStartLine < nEndLine || nStartLine == nEndLine && nStartChar < nEndChar);
if (m_bReadOnly)
return FALSE;
CDeleteContext context;
context.m_ptStart.y = nStartLine;
context.m_ptStart.x = nStartChar;
context.m_ptEnd.y = nEndLine;
context.m_ptEnd.x = nEndChar;
if (nStartLine == nEndLine)
{
SLineInfo & li = m_aLines[nStartLine];
if (nEndChar < li.m_nLength)
{
memcpy (li.m_pcLine + nStartChar, li.m_pcLine + nEndChar,
sizeof (TCHAR) * (li.m_nLength - nEndChar));
}
li.m_nLength -= (nEndChar - nStartChar);
UpdateViews (pSource, &context, UPDATE_SINGLELINE | UPDATE_HORZRANGE, nStartLine);
}
else
{
int nRestCount = m_aLines[nEndLine].m_nLength - nEndChar;
LPTSTR pszRestChars = NULL;
if (nRestCount > 0)
{
pszRestChars = new TCHAR[nRestCount];
memcpy (pszRestChars, m_aLines[nEndLine].m_pcLine + nEndChar, nRestCount * sizeof (TCHAR));
}
int nDelCount = nEndLine - nStartLine;
for (int L = nStartLine + 1; L <= nEndLine; L++)
delete m_aLines[L].m_pcLine;
m_aLines.RemoveAt (nStartLine + 1, nDelCount);
// nEndLine is no more valid
m_aLines[nStartLine].m_nLength = nStartChar;
if (nRestCount > 0)
{
AppendLine (nStartLine, pszRestChars, nRestCount);
delete pszRestChars;
}
UpdateViews (pSource, &context, UPDATE_HORZRANGE | UPDATE_VERTRANGE, nStartLine);
}
if (!m_bModified)
SetModified (TRUE);
//BEGIN SW
// remember current cursor position as last editing position
m_ptLastChange = context.m_ptStart;
//END SW
return TRUE;
}
BOOL CCrystalTextBuffer::
InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar)
{
ASSERT (m_bInit); // Text buffer not yet initialized.
// You must call InitNew() or LoadFromFile() first!
ASSERT (nLine >= 0 && nLine < m_aLines.GetSize ());
ASSERT (nPos >= 0 && nPos <= m_aLines[nLine].m_nLength);
if (m_bReadOnly)
return FALSE;
CInsertContext context;
context.m_ptStart.x = nPos;
context.m_ptStart.y = nLine;
int nRestCount = m_aLines[nLine].m_nLength - nPos;
LPTSTR pszRestChars = NULL;
if (nRestCount > 0)
{
pszRestChars = new TCHAR[nRestCount];
memcpy (pszRestChars, m_aLines[nLine].m_pcLine + nPos, nRestCount * sizeof (TCHAR));
m_aLines[nLine].m_nLength = nPos;
}
int nCurrentLine = nLine;
BOOL bNewLines = FALSE;
int nTextPos;
for (;;)
{
nTextPos = 0;
while (pszText[nTextPos] != 0 && pszText[nTextPos] != _T ('\r'))
nTextPos++;
if (nCurrentLine == nLine)
{
AppendLine (nLine, pszText, nTextPos);
}
else
{
InsertLine (pszText, nTextPos, nCurrentLine);
bNewLines = TRUE;
}
if (pszText[nTextPos] == 0)
{
nEndLine = nCurrentLine;
nEndChar = m_aLines[nCurrentLine].m_nLength;
AppendLine (nCurrentLine, pszRestChars, nRestCount);
break;
}
nCurrentLine++;
nTextPos++;
if (pszText[nTextPos] == _T ('\n'))
{
nTextPos++;
}
else
{
ASSERT (FALSE); // Invalid line-end format passed
}
pszText += nTextPos;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -