You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1812 lines
42 KiB
C++

2 years ago
// XTPSyntaxEditBufferManager.cpp
//
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME SYNTAX EDIT LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
// common includes
#include "Common/XTPColorManager.h"
#include "Common/XTPNotifyConnection.h"
#include "Common/XTPSmartPtrInternalT.h"
#include "Common/XTPVC80Helpers.h"
// syntax editor includes
#include "XTPSyntaxEditDefines.h"
#include "XTPSyntaxEditStruct.h"
#include "XTPSyntaxEditUndoManager.h"
#include "XTPSyntaxEditLineMarksManager.h"
#include "XTPSyntaxEditLexPtrs.h"
#include "XTPSyntaxEditTextIterator.h"
#include "XTPSyntaxEditSectionManager.h"
#include "XTPSyntaxEditLexParser.h"
#include "XTPSyntaxEditLexColorFileReader.h"
#include "XTPSyntaxEditBufferManager.h"
using namespace XTPSyntaxEditLexAnalyser;
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CXTPSyntaxEditBufferManager, CCmdTarget)
//===========================================================================
// CRLF styles
static const char *g_pcszCRLFStyles[] =
{
"\x0D\x0A", // DOS/Windows style
"\x0A\x0D", // UNIX style
"\x0A" // Macintosh style
};
static const WCHAR *g_pcszCRLFStylesW[] =
{
L"\x0D\x0A", // DOS/Windows style
L"\x0A\x0D", // UNIX style
L"\x0A" // Macintosh style
};
//===========================================================================
// CXTPSyntaxEditBufferManager
//===========================================================================
CXTPSyntaxEditConfigurationManagerPtr CXTPSyntaxEditBufferManager::s_ptrLexConfigurationManager_Default;
LONG CXTPSyntaxEditBufferManager::s_dwLexConfigurationManager_DefaultRefs = 0;
//===========================================================================
template <class _TFileChar>
inline _TFileChar* _T_GetCRLF(int nCRLFLenStyle, _TFileChar c = 0)
{
UNREFERENCED_PARAMETER(c);
_TFileChar** ppStyles = NULL;
if (sizeof(_TFileChar) == 1)
{
ppStyles = (_TFileChar**) g_pcszCRLFStyles;
}
else
{
ASSERT(sizeof(_TFileChar) == 2);
ppStyles = (_TFileChar**) g_pcszCRLFStylesW;
}
if (nCRLFLenStyle < 0 || nCRLFLenStyle >= _countof(g_pcszCRLFStyles))
{
ASSERT(FALSE);
nCRLFLenStyle = 0;
}
return ppStyles[nCRLFLenStyle];
}
template <class _TFileChar>
inline int _T_StrLen(_TFileChar* pStr)
{
if (sizeof(_TFileChar) == 1)
{
return (int) strlen((CHAR*) pStr);
}
ASSERT(sizeof(_TFileChar) == 2);
return (int) wcslen((WCHAR*) pStr);
}
CString GetFileExtention(CFile* pFile)
{
TCHAR szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFileName[_MAX_FNAME], szExt[_MAX_EXT];
szDrive[0] = _T('\0');
szDir[0] = _T('\0');
szFileName[0] = _T('\0');
szExt[0] = _T('\0');
SPLITPATH_S(pFile->GetFileName(), szDrive, szDir, szFileName, szExt);
return szExt;
}
//---------------------------------------------------------------------------
int _cdecl _Compare_BYTE(const void* pb1, const void* pb2)
{
if ( *((BYTE*) pb1) > *((BYTE*) pb2) )
return 1;
if ( *((BYTE*) pb2) > *((BYTE*) pb1) )
return -1;
return 0;
}
BOOL _IsUnicodeFile_heuristic(CFile *pFile)
{
pFile->SeekToBegin();
const int cnBufferSize = 1024;
BYTE arData[cnBufferSize];
BYTE arData0[cnBufferSize / 2];
BYTE arData1[cnBufferSize / 2];
UINT uDataSize = pFile->Read(arData, cnBufferSize);
pFile->SeekToBegin();
UINT uDataXcount = uDataSize / 2;
UINT i;
for (i = 0; i < uDataXcount; i++)
{
arData0[i] = arData[i * 2];
arData1[i] = arData[i * 2 + 1];
if ((arData0[i] == 0xA || arData0[i] == 0xD) && arData1[i] == 0)
return TRUE;
}
qsort(arData0, uDataXcount, sizeof(BYTE), _Compare_BYTE);
qsort(arData1, uDataXcount, sizeof(BYTE), _Compare_BYTE);
int nVariation0 = 0;
int nVariation1 = 0;
int nSmallNumbers1 = 0;
for (i = 1; i < uDataXcount; i++)
{
if (arData0[i] != arData0[i - 1])
nVariation0++;
}
for (i = 1; i < uDataXcount; i++)
{
if (arData1[i] != arData1[i - 1])
nVariation1++;
if (arData1[i] < 9)
nSmallNumbers1++;
}
if (uDataXcount < 10)
return nVariation0 > nVariation1 || nSmallNumbers1;
int nVariationDiff = nVariation0 * 100 / max(1, nVariation1);
int nSmallNumbersPc = nSmallNumbers1 * 100 / max(1, uDataXcount);
return nVariationDiff > 150 || nSmallNumbersPc > 3;
}
BOOL IsUnicodeFile(CFile *pFile)
{
pFile->SeekToBegin();
WORD wPrefix;
UINT uReaded = pFile->Read(&wPrefix, 2);
if (uReaded == 2 && wPrefix == 0xFEFF)
{
return TRUE;
}
#ifdef XTP_FIXED
// fail it with multi byte text.
// disable this method.
#else
DWORD_PTR dwFileSize = (DWORD_PTR) pFile->GetLength();
if (dwFileSize % 2 == 0)
{
return _IsUnicodeFile_heuristic(pFile);
}
#endif
pFile->SeekToBegin();
return FALSE;
}
//===========================================================================
template <class _TFileChar>
inline int _T_GetCRLFStyle(_TFileChar chEOL1, _TFileChar chEOL2, int* pnCRLFLen)
{
int nCRLFLen = 1;
int nCRLFStyle = xtpEditCRLFStyleUnknown;
if (chEOL1 == 13)
{
//ASSERT(chEOL2 == 10); // incorrect text - reversed DOS CRLF style
nCRLFLen = chEOL2 == 10 ? 2 : 1;
nCRLFStyle = xtpEditCRLFStyleDos;
}
else if (chEOL1 == 10)
{
if (chEOL2 == 13)
{
nCRLFLen = 2;
nCRLFStyle = xtpEditCRLFStyleUnix;
}
else
{
nCRLFLen = 1;
nCRLFStyle = xtpEditCRLFStyleMac;
}
}
if (pnCRLFLen)
{
*pnCRLFLen = nCRLFLen;
}
return nCRLFStyle;
}
template <class _TFileChar, int _cnMaxStr2_chars>
inline void _T_StrAdd(CString& rStr, _TFileChar* pStr2, UINT uCodePage)
{
if (sizeof(TCHAR) == 2 && sizeof(_TFileChar) == 1)
{
const int cnBuf2Size = _cnMaxStr2_chars+1;
WCHAR szBuf2[cnBuf2Size];
::ZeroMemory(szBuf2, sizeof(szBuf2));
int nLen = MultiByteToWideChar(uCodePage, 0, (LPCSTR)pStr2, -1, szBuf2, cnBuf2Size-1);
ASSERT(nLen <= cnBuf2Size-1);
rStr += szBuf2;
}
else
{
//ASSERT(sizeof(TCHAR) == sizeof(_TFileChar));
UNREFERENCED_PARAMETER(uCodePage);
rStr += pStr2;
}
}
//===========================================================================
template <class _TFileChar>
BOOL _T_ReadStringFromFile(CFile *pFile, CString& rstrString, int& rnCRLFStyle,
UINT uCodePage, _TFileChar c = 0)
{
UNREFERENCED_PARAMETER(c);
ASSERT(pFile);
if (!pFile)
return FALSE;
rstrString.Empty();
rnCRLFStyle = -1;
const int cnBuffSize = 128; //512;
_TFileChar pBuff[cnBuffSize + 10];
UINT uFileSize = (UINT)pFile->GetLength();
while ((UINT)pFile->GetPosition() < uFileSize)
{
UINT uReadSizeB = (cnBuffSize) * sizeof(_TFileChar);
UINT uBufDataCountB = pFile->Read(pBuff, uReadSizeB);
if (!uBufDataCountB)
{
ASSERT(FALSE);
break;
}
ASSERT(uBufDataCountB % sizeof(_TFileChar) == 0);
int nBufDataLen = uBufDataCountB / sizeof(_TFileChar);
pBuff[nBufDataLen] = _T('\0');
int nBufStrLen = _T_StrLen(pBuff);
ASSERT(nBufStrLen <= nBufDataLen);
_TFileChar* pEOL = NULL;
if (sizeof(_TFileChar) == 1)
{
#ifdef _MBCS
pEOL = (_TFileChar*) _mbspbrk((BYTE*) pBuff, (BYTE*)"\x0A\x0D");
#else
pEOL = (_TFileChar*) strpbrk((char*) pBuff, "\x0A\x0D");
#endif
}
else
{
pEOL = (_TFileChar*) wcspbrk((wchar_t*)pBuff, L"\x0A\x0D");
}
BOOL bEOL_badFormat = FALSE;
// check bad case: when zero char is rather then readed buffer end
if (!pEOL && nBufStrLen < nBufDataLen)
{
pEOL = pBuff + nBufStrLen;
bEOL_badFormat = TRUE;
}
//---------------------------------
if (!pEOL)
{
_T_StrAdd<_TFileChar, cnBuffSize>(rstrString, pBuff, uCodePage);
continue;
}
_TFileChar chEOL1 = pEOL[0];
_TFileChar chEOL2 = pEOL[1];
*pEOL = 0;
_T_StrAdd<_TFileChar, cnBuffSize>(rstrString, pBuff, uCodePage);
if (!bEOL_badFormat && chEOL2 == 0 && (chEOL1 == 10 || chEOL1 == 13))
{
// buffer ended on the middle of CRLF ?
// read one more char to be sure in CRLF style.
if (uReadSizeB == uBufDataCountB && (UINT)pFile->GetPosition() < uFileSize)
{
_TFileChar* pBufTail = pBuff + uBufDataCountB/sizeof(_TFileChar);
UINT uReadedB = pFile->Read(pBufTail, sizeof(_TFileChar));
pBufTail[1] = 0;
chEOL2 = pBufTail[0];
uReadSizeB += uReadedB;
uBufDataCountB += uReadedB;
}
}
int nCRLFLen = 1;
if (!bEOL_badFormat)
{
rnCRLFStyle = _T_GetCRLFStyle<_TFileChar>(chEOL1, chEOL2, &nCRLFLen);
ASSERT(rnCRLFStyle != xtpEditCRLFStyleUnknown);
}
int nEolPos = int(pEOL - pBuff);
int nSeekBack = (nEolPos + nCRLFLen)*sizeof(_TFileChar) - uBufDataCountB;
pFile->Seek(nSeekBack, CFile::current);
return TRUE;
}
return rstrString.GetLength() > 0;
}
//===========================================================================
template <class _TFileChar, class _TFile >
int _T_WriteStringToFile(_TFile *pFile, LPCTSTR pszString, int nCRLFStyle,
UINT uCodePage, CByteArray* parBuffer = NULL, _TFileChar c = 0)
{
UNREFERENCED_PARAMETER(c);
CByteArray arBufferInt;
if (!parBuffer)
{
parBuffer = &arBufferInt;
}
int nStrLen = (int)_tcslen(pszString);
BYTE* pFileBuffer = NULL;
int nFileBufferLenB = 0;
//------------------------------------------------------------------------
if (sizeof(TCHAR) == sizeof(_TFileChar))
{
pFileBuffer = (BYTE*)pszString;
nFileBufferLenB = nStrLen * sizeof(_TFileChar);
}
else
{
int nNeedBufSizeB = nStrLen * 2 + 30;
if (parBuffer->GetSize() < nNeedBufSizeB)
{
parBuffer->SetSize(nNeedBufSizeB + 256);
}
pFileBuffer = parBuffer->GetData();
ASSERT(parBuffer->GetSize() >= nNeedBufSizeB);
ZeroMemory(pFileBuffer, nNeedBufSizeB);
if (sizeof(TCHAR) == 2 && sizeof(_TFileChar) == 1)
{
int nMBCStextLen = WideCharToMultiByte(uCodePage, 0,
(LPCWSTR)pszString, -1,
(LPSTR)pFileBuffer, nNeedBufSizeB, NULL, NULL);
nFileBufferLenB = max(nMBCStextLen - 1, 0);
}
else if (sizeof(TCHAR) == 1 && sizeof(_TFileChar) == 2)
{
int nWtextLen = MultiByteToWideChar(uCodePage, 0,
(LPCSTR)pszString, -1,
(LPWSTR)pFileBuffer, nNeedBufSizeB/2);
nFileBufferLenB = max(nWtextLen - 1, 0) * 2;
}
else
{
ASSERT(FALSE);
return 0;
}
}
//------------------------------------------------------------------------
if (nFileBufferLenB > 0)
{
pFile->Write(pFileBuffer, nFileBufferLenB);
}
if (nCRLFStyle >= 0)
{
_TFileChar* tszCRLF = _T_GetCRLF<_TFileChar>(nCRLFStyle);
int nCRLFlenB = _T_StrLen(tszCRLF) * sizeof(_TFileChar);
pFile->Write(tszCRLF, nCRLFlenB);
nFileBufferLenB += nCRLFlenB;
}
return nFileBufferLenB;
}
//===========================================================================
AFX_INLINE BOOL ReadStringFromFileEx(CFile *pFile, CString& rstrString, int& rnCRLFStyle,
UINT uCodePage, BOOL bUnicode)
{
if (bUnicode)
{
return _T_ReadStringFromFile<WCHAR>(pFile, rstrString, rnCRLFStyle, uCodePage);
}
return _T_ReadStringFromFile<CHAR>(pFile, rstrString, rnCRLFStyle, uCodePage);
}
template <class _TFile >
AFX_INLINE int _T_WriteStringToFileEx(_TFile *pFile, LPCTSTR pszString, int nCRLFStyle,
UINT uCodePage, CByteArray* parBuffer, BOOL bUnicode)
{
if (bUnicode)
{
return _T_WriteStringToFile<WCHAR>(pFile, pszString, nCRLFStyle, uCodePage, parBuffer);
}
return _T_WriteStringToFile<CHAR>(pFile, pszString, nCRLFStyle, uCodePage, parBuffer);
}
//===========================================================================
CXTPSyntaxEditBufferManager::CXTPSyntaxEditBufferManager()
{
m_pConnection = new CXTPNotifyConnection();
m_pLexParser = new CXTPSyntaxEditLexParser();
m_bOverwrite = FALSE;
m_nCodePage = CP_ACP;
m_bUnicodeFileFormat = FALSE;
m_nTabSize = 4;
m_iCRLFStyle = xtpEditCRLFStyleDos;
m_nAverageLineLen = XTP_EDIT_AVELINELEN;
m_pLexConfigManSinkMT = new CXTPNotifySinkMT();
m_pLineMarksManager = new CXTPSyntaxEditLineMarksManager();
m_pUndoRedoManager = new CXTPSyntaxEditUndoRedoManager();
m_bIsParserEnabled = TRUE;
if (!s_ptrLexConfigurationManager_Default)
{
s_ptrLexConfigurationManager_Default = new CXTPSyntaxEditConfigurationManager();
}
if (s_ptrLexConfigurationManager_Default)
{
SetLexConfigurationManager(s_ptrLexConfigurationManager_Default);
s_dwLexConfigurationManager_DefaultRefs++;
}
CWinApp* pWinApp = AfxGetApp();
if (pWinApp)
{
m_nTabSize = pWinApp->GetProfileInt(
XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_TABSIZE, m_nTabSize);
}
}
CXTPSyntaxEditBufferManager::~CXTPSyntaxEditBufferManager()
{
Close();
if (s_dwLexConfigurationManager_DefaultRefs)
{
s_dwLexConfigurationManager_DefaultRefs--;
if (s_dwLexConfigurationManager_DefaultRefs == 0)
{
s_ptrLexConfigurationManager_Default->Close();
s_ptrLexConfigurationManager_Default = NULL;
}
}
CMDTARGET_RELEASE(m_pLexParser);
CMDTARGET_RELEASE(m_pConnection);
SAFE_DELETE(m_pLineMarksManager);
SAFE_DELETE(m_pUndoRedoManager);
m_pLexConfigManSinkMT->Delete();
}
void CXTPSyntaxEditBufferManager::Close()
{
m_pLexConfigManSinkMT->UnadviseAll();
m_pLexParser->Close();
CleanUp();
}
void CXTPSyntaxEditBufferManager::CleanUp()
{
m_Strings.RemoveAllStrs();
m_pUndoRedoManager->Clear();
//m_strFileExt.Empty();
}
void CXTPSyntaxEditBufferManager::Load(CFile *pFile, LPCTSTR pcszFileExt)
{
CArchive ar(pFile, CArchive::load);
SerializeEx(ar, -1, FALSE, m_nCodePage, pcszFileExt);
}
void CXTPSyntaxEditBufferManager::Serialize(CArchive &ar)
{
BOOL bUnicode = ar.IsStoring() ? m_bUnicodeFileFormat : -1;
SerializeEx(ar, bUnicode, TRUE, m_nCodePage, NULL);
if (ar.IsStoring())
m_pUndoRedoManager->MarkSaved();
}
void CXTPSyntaxEditBufferManager::SerializeEx(CArchive &ar, BOOL bUnicode, BOOL bWriteUnicodeFilePrefix,
UINT nCodePage, LPCTSTR pcszFileExt, int nDataSizeLimit)
{
if (m_bIsParserEnabled)
{
m_pLexParser->StopParseInThread();
}
if (nCodePage != (UINT)-1)
m_nCodePage = nCodePage;
CFile* pFile = ar.GetFile();
if (ar.IsLoading())
{
CleanUp();
// IsUnicodeFile is take care about start text offset
//pFile->Seek(m_bUnicodeFileFormat ? 2 : 0, CFile::begin);
//
if (bUnicode < 0)
m_bUnicodeFileFormat = IsUnicodeFile(pFile);
else
m_bUnicodeFileFormat = (bUnicode > 0);
CString strString;
int nCRLFStyle = -1;
int nCRLFLastLineStyle = -1;
BOOL bSETeol = TRUE;
int nRow = 1;
while (ReadStringFromFileEx(pFile, strString, nCRLFStyle, m_nCodePage, m_bUnicodeFileFormat))
{
m_Strings.SetAtGrowStr(nRow, strString);
if (bSETeol && nCRLFStyle >= 0)
{
SetCRLFStyle(nCRLFStyle);
bSETeol = FALSE;
}
nCRLFLastLineStyle = nCRLFStyle;
nRow++;
}
if (nCRLFLastLineStyle >= 0)
{
m_Strings.SetAtGrowStr(nRow, _T(""));
}
CString strExt = pcszFileExt ? pcszFileExt : GetFileExtention(pFile);
if (!strExt.IsEmpty())
SetFileExt(strExt);
}
else if (ar.IsStoring())
{
if (bUnicode == -1)
bUnicode = m_bUnicodeFileFormat;
if ((bUnicode) && bWriteUnicodeFilePrefix)
{
ar << (BYTE)255;
ar << (BYTE)254;
}
CByteArray arBuffer;
int nCRLFStyle = GetCurCRLFType();
int nDataSize = 0;
int nRowsCount = m_Strings.GetCount();
for (int i = 1; i < nRowsCount; i++)
{
CString strLine = m_Strings.GetStr(i);
if (i == nRowsCount-1)
{ // last line
nCRLFStyle = -1;// do not write CRLF
}
int nWrittenBytes = _T_WriteStringToFileEx(&ar, strLine, nCRLFStyle,
m_nCodePage, &arBuffer, bUnicode);
nDataSize += nWrittenBytes;
if (nDataSizeLimit > 0 && nDataSize > nDataSizeLimit)
break;
}
//---------------
CString strExt = pcszFileExt ? pcszFileExt : GetFileExtention(pFile);
if (!strExt.IsEmpty())
SetFileExt(strExt);
}
}
void CXTPSyntaxEditBufferManager::SetLexConfigurationManager(
CXTPSyntaxEditConfigurationManager* pMan)
{
m_pLexConfigManSinkMT->UnadviseAll();
m_ptrLexConfigurationManager.SetPtr(pMan, TRUE);
if (pMan)
{
CXTPNotifyConnection* ptrConn = pMan->GetConnection();
ASSERT(ptrConn);
if (ptrConn)
{
m_pLexConfigManSinkMT->Advise(ptrConn, xtpEditClassSchWasChanged, CreateNotfySinkClassDelegate(this, &CXTPSyntaxEditBufferManager::OnLexConfigManEventHandler));
m_pLexConfigManSinkMT->Advise(ptrConn, xtpEditThemeWasChanged, CreateNotfySinkClassDelegate(this, &CXTPSyntaxEditBufferManager::OnLexConfigManEventHandler));
m_pLexConfigManSinkMT->Advise(ptrConn, xtpEditAllConfigWasChanged, CreateNotfySinkClassDelegate(this, &CXTPSyntaxEditBufferManager::OnLexConfigManEventHandler));
}
}
}
void CXTPSyntaxEditBufferManager::OnLexConfigManEventHandler(XTP_NOTIFY_CODE Event,
WPARAM wParam, LPARAM lParam)
{
if (!m_bIsParserEnabled)
{
return;
}
if (Event == xtpEditClassSchWasChanged || Event == xtpEditAllConfigWasChanged)
{
CXTPSyntaxEditTextSchema* ptrNewTxtSch = NULL;
BOOL bSetTxtSch = FALSE;
if (Event == xtpEditClassSchWasChanged)
{
// wParam = LPCTSTR - Schema name;
// lParam = CXTPSyntaxEditLexTextSchema* New text schema pointer
// or NULL if schema was removed.
CXTPSyntaxEditLexTextSchema* pTxtSch = (CXTPSyntaxEditLexTextSchema*)lParam;
if (pTxtSch)
{
if (pTxtSch->IsFileExtSupported(m_strFileExt) )
{
ptrNewTxtSch = pTxtSch;
bSetTxtSch = TRUE;
}
else
{
CXTPSyntaxEditLexTextSchema* ptrTxtSch_current = m_pLexParser->GetTextSchema();
CString strName_current = ptrTxtSch_current ? ptrTxtSch_current->GetSchName() : _T("");
CString strName_New = pTxtSch->GetSchName();
if (strName_current.CompareNoCase(strName_New) == 0)
{
//such file ext is no longer supported by this schema
ptrNewTxtSch = NULL;
bSetTxtSch = TRUE;
}
}
}
else
{
ptrNewTxtSch = GetMasterTextSchema(m_strFileExt);
bSetTxtSch = !ptrNewTxtSch;
}
}
if (Event == xtpEditAllConfigWasChanged)
{
ptrNewTxtSch = GetMasterTextSchema(m_strFileExt);
bSetTxtSch = TRUE;
}
//====================================================================
if (bSetTxtSch)
{
m_pLexParser->SetTextSchema(ptrNewTxtSch);
if (ptrNewTxtSch)
{
XTP_EDIT_LINECOL pos1_0 = {1, 0};
BOOL bParseInThread = m_pLexParser->GetSchemaOptions(
GetFileExt())->m_bConfigChangedReparceInSeparateThread;
if (bParseInThread)
{
m_pLexParser->StartParseInThread(this, &pos1_0, NULL, 0, TRUE);
}
else
{
CXTPSyntaxEditLexTextSchema* ptrTextSch = m_pLexParser->GetTextSchema();
if (ptrTextSch)
{
CXTPSyntaxEditTextIterator txtIter(this);
ptrTextSch->RunParseUpdate(TRUE, &txtIter, &pos1_0, NULL);
}
}
}
m_pConnection->SendEvent(Event, wParam, lParam);
}
}
if (Event == xtpEditThemeWasChanged)
{
// wParam = LPCTSTR - Theme name;
// lParam = CXTPSyntaxEditColorTheme* New theme pointer
// or NULL if theme was removed.
CXTPSyntaxEditColorTheme* pNewTheme = (CXTPSyntaxEditColorTheme*)lParam;
CXTPSyntaxEditLexTextSchema* ptrTxtSch = m_pLexParser->GetTextSchema();
if (ptrTxtSch)
{
ptrTxtSch->ApplyTheme(pNewTheme);
m_pConnection->SendEvent(Event, wParam, lParam);
}
}
}
BOOL CXTPSyntaxEditBufferManager::InsertText(LPCTSTR szText, int nRow, int nCol,
BOOL bCanUndo, XTP_EDIT_LINECOL* pFinalLC)
{
int nStrLenB = (int)_tcslen(szText) * sizeof(TCHAR);
CMemFile memFile((BYTE*)szText, nStrLenB);
CString strString;
CString strReplased;
int nLastLineEOLstyle = -1;
CString strRow1, strRow2;
memFile.SeekToBegin();
// process first row (cut and concatenate)
if (_T_ReadStringFromFile<TCHAR>(&memFile, strString, nLastLineEOLstyle, m_nCodePage))
{
strRow1 = m_Strings.GetStr(nRow);
//int nLen = strRow1.GetLength();
int nLenC = (int)_tcsclen(strRow1);
if (nCol-1 < nLenC)
{
int nPosX = (int)_tcsnbcnt(strRow1, nCol-1);
strRow2 = strRow1.Mid(nPosX);
strRow1 = strRow1.Left(nPosX);
strRow1 += strString;
if (m_bOverwrite)
{
int nReplaceLen = min(strString.GetLength(), strRow2.GetLength());
strReplased = strRow2.Left(nReplaceLen);
strRow2.Delete(0, nReplaceLen);
}
m_Strings.SetAtGrowStr(nRow, strRow1);
}
else
{
m_Strings.InsertText(nRow, nCol-1, strString, TRUE);
}
}
// process middle rows (insert them)
int nCRLFStyleX = -1;
int r = nRow + 1;
while (_T_ReadStringFromFile<TCHAR>(&memFile, strString, nCRLFStyleX, m_nCodePage))
{
m_Strings.InsertStr(r, strString);
r++;
nLastLineEOLstyle = nCRLFStyleX;
}
// process last row (concatenate)
int nRowTo = nRow;
int nColTo = nCol+1;
if (nLastLineEOLstyle >= 0)
{
m_Strings.InsertStr(r, strRow2);
nRowTo = r;
nColTo = (int)_tcsclen(strString) + 1;
}
else
{
strString = m_Strings.GetStr(r-1);
nRowTo = r-1;
nColTo = (int)_tcsclen(strString) + 1;
strString += strRow2;
m_Strings.SetAtGrowStr(r-1, strString);
}
//===========================================================================
if (pFinalLC)
{
pFinalLC->nLine = nRowTo;
pFinalLC->nCol = nColTo;
}
if (bCanUndo)
{
if (!m_bOverwrite || strReplased == "") // By Leva: added 2nd condition to eliminate undo bug
{
m_pUndoRedoManager->AddCommand(new CXTPSyntaxEditInsertStringCommand(this,
szText,
XTP_EDIT_LINECOL::MakeLineCol(nRow, nCol),
XTP_EDIT_LINECOL::MakeLineCol(nRowTo, nColTo)) );
}
else
{
m_pUndoRedoManager->SetGroupInsertMode(FALSE);
m_pUndoRedoManager->AddCommand(new CXTPSyntaxEditReplaceStringCommand(this,
szText, strReplased,
XTP_EDIT_LINECOL::MakeLineCol(nRow, nCol),
XTP_EDIT_LINECOL::MakeLineCol(nRowTo, nColTo)) );
}
}
return TRUE;
}
BOOL CXTPSyntaxEditBufferManager::InsertTextBlock(LPCTSTR szText, int nRow,
int nCol, BOOL bCanUndo, XTP_EDIT_LINECOL* pFinalLC)
{
int nStrLenB = (int)_tcslen(szText) * sizeof(TCHAR);
CMemFile memFile((BYTE*)szText, nStrLenB);
memFile.SeekToBegin();
CString strString;
int nEndPos = 0;
int nCRLFStyleX = -1;
int r = nRow;
int nDispCol = StrPosToCol(nRow, nCol-1);
if (bCanUndo)
{
m_pUndoRedoManager->SetGroupInsertMode(TRUE);
}
while (_T_ReadStringFromFile<TCHAR>(&memFile, strString, nCRLFStyleX, m_nCodePage))
{
CString strRow = m_Strings.GetStr(r);
int nRowLen = (int)_tcsclen(strRow);
int nRowCols = StrPosToCol(r, nRowLen);
int nPos = ColToStrPos(r, nDispCol);
if (nRowCols < nDispCol)
{
nPos = nRowLen + (nDispCol - nRowCols);
}
m_Strings.InsertText(r, nPos, strString, TRUE);
//--------------------------------------------------------------------
nEndPos = nPos + strString.GetLength();
if (bCanUndo)
{
XTP_EDIT_LINECOL posFrom = {r, nPos+1};
XTP_EDIT_LINECOL posTo = {r, nEndPos+1};
m_pUndoRedoManager->AddCommand(new CXTPSyntaxEditInsertStringCommand(this,
strString, posFrom, posTo) );
}
//--------------------------------------------------------------------
r++;
}
if (bCanUndo)
{
m_pUndoRedoManager->SetGroupInsertMode(FALSE);
}
//===========================================================================
if (pFinalLC)
{
pFinalLC->nLine = r-1;
pFinalLC->nCol = nEndPos+1;
}
return TRUE;
}
void CXTPSyntaxEditBufferManager::GetLineText(int nLine, CString& strText,
BOOL bAddCRLF, int nCRLFStyle)
{
strText = GetLineText(nLine, bAddCRLF, nCRLFStyle);
}
CString CXTPSyntaxEditBufferManager::GetLineText(int nLine, BOOL bAddCRLF, int nCRLFStyle) const
{
CString strText = m_Strings.GetStr(nLine);
if (bAddCRLF)
{
strText += GetCRLF(nCRLFStyle);
}
return strText;
}
int CXTPSyntaxEditBufferManager::GetLineTextLength(int nLine, BOOL bAddCRLF, int nCRLFStyle) const
{
int nLen = m_Strings.GetStrLen(nLine);
if (bAddCRLF)
{
int nEOLlen = (int)_tcslen(GetCRLF(nCRLFStyle));
nLen += nEOLlen;
}
return nLen;
}
int CXTPSyntaxEditBufferManager::GetLineTextLengthC(int nLine, BOOL bAddCRLF, int nCRLFStyle) const
{
int nLen = m_Strings.GetStrLenC(nLine);
if (bAddCRLF)
{
int nEOLlen = (int)_tcsclen(GetCRLF(nCRLFStyle));
nLen += nEOLlen;
}
return nLen;
}
int CXTPSyntaxEditBufferManager::GetMaxLineTextLength() const
{
return CalcMaxLineTextLength();
}
int CXTPSyntaxEditBufferManager::CalcMaxLineTextLength(int nLineFrom, int nLineTo, BOOL bExpandTabs) const
{
nLineFrom = min(max(1, nLineFrom), GetRowCount());
nLineTo = nLineTo < 0 ? GetRowCount() : min(nLineTo, GetRowCount());
if (nLineFrom >= m_Strings.GetCount() || nLineTo >= m_Strings.GetCount() )
{
return 0;
}
int nTabSize = GetTabSize();
int nMAXlen = 0;
for (int i = nLineFrom; i <= nLineTo; i++)
{
CString* pCStrData = m_Strings.GetStrDataC(i);
if (!pCStrData)
continue;
int nLen = pCStrData->GetLength();
if (bExpandTabs)
{
LPCTSTR pcszString = (LPCTSTR)(*pCStrData);
int nOffset = 0;
for (int k = 0; k < nLen; k++)
{
if (pcszString[k] == _T('\t'))
nOffset += (nTabSize - nOffset % nTabSize);
else
nOffset++;
}
nLen = nOffset;
}
if (nLen > nMAXlen)
nMAXlen = nLen;
}
return nMAXlen;
}
BOOL CXTPSyntaxEditBufferManager::DeleteText(int nRowFrom, int nColFrom,
int nRowTo, int nColTo, BOOL bCanUndo, BOOL bDispCol)
{
ASSERT(nColFrom >= 1 && nColTo >= 1);
if (bCanUndo)
{
int nPos1 = bDispCol ? nColFrom : StrPosToCol(nRowFrom, nColFrom - 1); // By Leva: moved -1 into brackets
int nPos2 = bDispCol ? nColTo : StrPosToCol(nRowTo, nColTo - 1); // By Leva: moved -1 into brackets
CMemFile file(CalcAveDataSize(nRowFrom, nRowTo));
if (GetBuffer(nRowFrom, nPos1, nRowTo, nPos2, file))
{
TCHAR szNull = NULL;
file.SeekToEnd();
file.Write((const BYTE *)&szNull, sizeof(TCHAR));
BYTE *pBytes = file.Detach();
m_pUndoRedoManager->AddCommand(new CXTPSyntaxEditDeleteStringCommand(this, (LPCTSTR)pBytes,
XTP_EDIT_LINECOL::MakeLineCol(nRowFrom, bDispCol ? ColToStrPos(nRowFrom, nColFrom)+1 : nColFrom),
XTP_EDIT_LINECOL::MakeLineCol(nRowTo, bDispCol ? ColToStrPos(nRowTo, nColTo)+1 : nColTo)) );
free(pBytes);
}
}
BOOL bResult = FALSE;
if (nRowFrom < nRowTo)
{
// Process nRowFrom
int nStrLenR1 = m_Strings.GetStrLenC(nRowFrom);
int nStrPos = bDispCol ? ColToStrPos(nRowFrom, nColFrom) : nColFrom-1;
int nCount = nStrLenR1 - nStrPos;
if (nStrLenR1 && nCount > 0)
{
ASSERT(nStrPos >=0);
bResult = m_Strings.DeleteText(nRowFrom, nStrPos, nCount);
ASSERT(bResult);
}
// Process nRowTo
int nStrLenR2 = m_Strings.GetStrLenC(nRowTo);
nStrPos = 0;
nCount = bDispCol ? ColToStrPos(nRowTo, nColTo) : nColTo-1;
if (nStrLenR2 && nCount > 0)
{
ASSERT(nStrPos >=0);
bResult = m_Strings.DeleteText(nRowTo, nStrPos, nCount);
ASSERT(bResult);
}
// Concatenate row <from> and row <to>
CString strRowNew = m_Strings.GetStr(nRowFrom);
CString strRow2 = m_Strings.GetStr(nRowTo);
strRowNew += strRow2;
m_Strings.SetAtGrowStr(nRowFrom, strRowNew);
for (int r = nRowTo; r > nRowFrom; r--)
{
bResult = m_Strings.RemoveStr(r);
//ASSERT(bResult);
}
}
else
{
ASSERT(nRowFrom == nRowTo);
int nPos1 = bDispCol ? ColToStrPos(nRowFrom, nColFrom) : nColFrom-1;
int nPos2 = bDispCol ? ColToStrPos(nRowTo, nColTo) : nColTo-1;
int nCount = abs(nPos2 - nPos1); //abs(nColTo - nColFrom);
if (nCount)
{
bResult = m_Strings.DeleteText(nRowFrom, min(nPos1, nPos2), nCount);
}
}
return bResult;
}
BOOL CXTPSyntaxEditBufferManager::RemoveLine(int nRow, BOOL bCanUndo, int nRowsCount)
{
int nRowEnd = min(GetRowCount() + 1, nRow + nRowsCount);
if (bCanUndo)
{
CMemFile file(CalcAveDataSize(nRow, nRowEnd));
if (GetBuffer(nRow, 1, nRowEnd, 1, file))
{
TCHAR szNull = _T('\0');
file.SeekToEnd();
file.Write((const BYTE *)&szNull, sizeof(TCHAR));
BYTE *pBytes = file.Detach();
m_pUndoRedoManager->AddCommand(new CXTPSyntaxEditDeleteStringCommand(this, (LPCTSTR)pBytes,
XTP_EDIT_LINECOL::MakeLineCol(nRow, 1),
XTP_EDIT_LINECOL::MakeLineCol(nRowEnd, 1)) );
free(pBytes);
}
}
BOOL bResult = FALSE;
for (int r = nRowEnd - 1; r >= nRow; r--)
{
BOOL b = m_Strings.RemoveStr(r);
bResult |= b;
}
return bResult;
}
BOOL CXTPSyntaxEditBufferManager::GetBuffer(
int row1, int col1, int row2, int col2,
CMemFile& file, BOOL bColumnSelection, BOOL bForceDOSStyleCRLF)
{
int nTempRow1 = row1, nTempRow2 = row2;
int nTempCol1 = col1, nTempCol2 = col2;
if (nTempRow2 < nTempRow1)
{
row1 = nTempRow2;
col1 = nTempCol2;
row2 = nTempRow1;
col2 = nTempCol1;
}
if (nTempRow1 == nTempRow2 || bColumnSelection)
{
col1 = min(nTempCol1, nTempCol2);
col2 = max(nTempCol1, nTempCol2);
}
BOOL bStart = TRUE;
BOOL bEnd = FALSE;
int nStartPos = 0, nEndPos = 0;
int nSizeCopy = 0;
int nNewCRLFStyle = (bForceDOSStyleCRLF) ? xtpEditCRLFStyleDos : m_iCRLFStyle;
const CString strCRLF(GetCRLF(nNewCRLFStyle));
for (int i = row1; i <= row2; i++)
{
if (i == row2)
bEnd = TRUE;
CString strBuffer;
GetLineText(i, strBuffer);
const int nLineLen = (int)_tcslen(strBuffer);
nStartPos = min(bStart || bColumnSelection ? ColToStrPos(i, col1) : 0, nLineLen);
nEndPos = min(bEnd || bColumnSelection ? ColToStrPos(i, col2) : nLineLen, nLineLen);
if (bStart || bColumnSelection)
nStartPos = (int)_tcsnbcnt(strBuffer, nStartPos);
if (bEnd || bColumnSelection)
nEndPos = (int)_tcsnbcnt(strBuffer, nEndPos);
nSizeCopy = abs(nEndPos - nStartPos) * sizeof(TCHAR);
if (nSizeCopy > 0)
file.Write((LPVOID)((LPCTSTR)strBuffer + nStartPos), nSizeCopy);
if (bColumnSelection)
{
// add spaces for the free size of the column block
int nAddSpaces = abs(col2 - col1) -
(int)_tcsnccnt((LPCTSTR)strBuffer + nStartPos, abs(nEndPos - nStartPos));
if (nAddSpaces > 0)
{
const CString strSpaces(_T(' '), nAddSpaces);
file.Write((LPVOID)(LPCTSTR)strSpaces, nAddSpaces * sizeof(TCHAR));
}
}
if (row1 != row2 && i != row2 || bColumnSelection)
{
// add end of the line
file.Write((LPVOID)(LPCTSTR)strCRLF, strCRLF.GetLength() * sizeof(TCHAR));
}
bStart = FALSE;
}
return TRUE;
}
void CXTPSyntaxEditBufferManager::SetOverwriteFlag(BOOL bOverwrite)
{
m_bOverwrite = bOverwrite;
}
BOOL CXTPSyntaxEditBufferManager::IsTextCRLF(LPCTSTR szCompText, BOOL bFindReverse) const
{
CString strCRLF(g_pcszCRLFStyles[m_iCRLFStyle]);
LPCTSTR szCurCRLF = (LPCTSTR)strCRLF;
LPCTSTR szTextToCompare = szCompText;
int nCRLFSize = lstrlen(szCurCRLF);
if (bFindReverse)
szTextToCompare = (szCompText - (nCRLFSize - 1));
BOOL bIsCRLF = (_tcsncmp(szTextToCompare, szCurCRLF, nCRLFSize) == 0);
return bIsCRLF;
}
#ifdef _UNICODE
BOOL CXTPSyntaxEditBufferManager::IsTextCRLF(LPCSTR szCompText, BOOL bFindReverse) const
{
LPCSTR szCurCRLF = (LPCSTR)g_pcszCRLFStyles[m_iCRLFStyle];
LPCSTR szTextToCompare = szCompText;
int nCRLFSize = (int)strlen(szCurCRLF);
if (bFindReverse)
szTextToCompare = (szCompText - (nCRLFSize - 1));
BOOL bIsCRLF = (strncmp(szTextToCompare, szCurCRLF, nCRLFSize) == 0);
return bIsCRLF;
}
#endif
CString CXTPSyntaxEditBufferManager::GetCurCRLF() const
{
return GetCRLF();
}
LPCTSTR CXTPSyntaxEditBufferManager::GetCRLF(int nCRLFStyle) const
{
ASSERT(m_iCRLFStyle >= 0 && m_iCRLFStyle < _countof(g_pcszCRLFStyles));
int nCRLFidx = m_iCRLFStyle;
if (nCRLFStyle >= 0 && nCRLFStyle < _countof(g_pcszCRLFStyles))
{
nCRLFidx = nCRLFStyle;
}
return _T_GetCRLF<TCHAR>(nCRLFidx);
}
void CXTPSyntaxEditBufferManager::SetCRLFStyle(int nCRLFStyle)
{
if (nCRLFStyle >= 0 && nCRLFStyle < _countof(g_pcszCRLFStyles))
{
m_iCRLFStyle = nCRLFStyle;
}
else
{
ASSERT(FALSE);
}
}
BOOL CXTPSyntaxEditBufferManager::SetTabSize(int nTabSize, BOOL bUpdateReg/*=FALSE*/)
{
m_nTabSize = nTabSize;
if (bUpdateReg)
{
CWinApp* pWinApp = AfxGetApp();
if (pWinApp != NULL)
{
if (pWinApp->WriteProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_TABSIZE, nTabSize))
return TRUE;
}
return FALSE;
}
return TRUE;
}
int CXTPSyntaxEditBufferManager::GetRowCount() const
{
return m_Strings.GetCount() ? ((int)m_Strings.GetCount() - 1) : 0;
}
BOOL CXTPSyntaxEditBufferManager::IsModified() const
{
return m_pUndoRedoManager->IsModified();
}
void CXTPSyntaxEditBufferManager::SetFileExt(const CString& strExt)
{
if (!m_strFileExt.IsEmpty() && m_strFileExt.CompareNoCase(strExt) == 0)
return;
m_strFileExt = strExt;
if (m_bIsParserEnabled)
{
CXTPSyntaxEditTextSchema* ptrMasterTxtSch = GetMasterTextSchema(strExt);
m_pLexParser->SetTextSchema(ptrMasterTxtSch);
}
}
CString CXTPSyntaxEditBufferManager::GetConfigFile() const
{
if (!m_ptrLexConfigurationManager)
return _T("");
return m_ptrLexConfigurationManager->GetConfigFile();
}
BOOL CXTPSyntaxEditBufferManager::SetConfigFile(LPCTSTR szPath)
{
if (!m_ptrLexConfigurationManager)
return FALSE;
if (m_ptrLexConfigurationManager->m_bConfigFileMode
&& CString(szPath).IsEmpty())
return FALSE;
CString strCfgFile0 = m_ptrLexConfigurationManager->GetConfigFile();
if (!m_ptrLexConfigurationManager->m_bConfigFileMode)
m_ptrLexConfigurationManager->ReloadConfig(_T(""));
else if (strCfgFile0.CompareNoCase(szPath) != 0)
m_ptrLexConfigurationManager->ReloadConfig(szPath);
return TRUE;
}
void CXTPSyntaxEditBufferManager::SetCodePage(UINT uCodePage)
{
m_nCodePage = uCodePage;
}
CXTPSyntaxEditTextSchema* CXTPSyntaxEditBufferManager::GetMasterTextSchema(const CString& strExt) const
{
if (!m_ptrLexConfigurationManager)
return NULL;
CXTPSyntaxEditTextSchemaPtr ptrMasterSch;
ptrMasterSch = m_ptrLexConfigurationManager->GetTextSchemesManager().FindSchema(strExt);
return ptrMasterSch;
}
UINT CXTPSyntaxEditBufferManager::CalcAveDataSize(int nRowStart, int nRowEnd)
{
UINT uSize = m_nAverageLineLen * abs(nRowStart - nRowEnd);
uSize = (uSize / 1024 + 1) * 1024;
return uSize;
}
void CXTPSyntaxEditBufferManager::EnableParser(BOOL bEnable)
{
if (m_bIsParserEnabled == bEnable)
return;
m_bIsParserEnabled = bEnable;
if (m_bIsParserEnabled)
{
CXTPSyntaxEditTextSchema* ptrMasterTxtSch = GetMasterTextSchema(m_strFileExt);
m_pLexParser->SetTextSchema(ptrMasterTxtSch);
XTP_EDIT_LINECOL pos1_0 = {1, 0};
BOOL bParseInThread = m_pLexParser->GetSchemaOptions(
GetFileExt())->m_bConfigChangedReparceInSeparateThread;
if (bParseInThread)
{
m_pLexParser->StartParseInThread(this, &pos1_0, NULL, 0, TRUE);
}
else
{
CXTPSyntaxEditLexTextSchema* ptrTextSch = m_pLexParser->GetTextSchema();
if (ptrTextSch)
{
CXTPSyntaxEditTextIterator txtIter(this);
ptrTextSch->RunParseUpdate(TRUE, &txtIter, &pos1_0, NULL);
}
}
}
else
{
m_pLexParser->SetTextSchema(NULL);
}
}
int CXTPSyntaxEditBufferManager::ColToStrPos(int nLine, int nDispCol) const
{
int nStrPos = 0;
int nCol = 0;
const CString strText = m_Strings.GetStr(nLine);
#ifdef XTP_FIXED
// use ByteLength insted of Text length.
int nChars = (int) _tcslen(strText);
#else
int nChars = (int) _tcsclen(strText);
#endif
LPCTSTR pChar = strText;
int nTabSize = GetTabSize();
for (int i = 0; *pChar != 0 && i < nChars && (nCol+1) < nDispCol; i++)
{
if (*pChar == _T('\t'))
{
nCol += nTabSize - (nCol % nTabSize);
}
else
{
nCol++;
}
if (isleadbyte(*pChar))
{
i ++;
#ifdef XTP_FIXED
nCol++;
#endif
}
pChar = _tcsinc(pChar);
nStrPos++;
}
// support VirtualSpace by default
//m_bVirtualSpace
if (nCol + 1 < nDispCol)
nStrPos += nDispCol - nCol - 1;
return nStrPos;
}
int CXTPSyntaxEditBufferManager::StrPosToCol(int nLine, int nStrPos) const
{
int nDispCol = 1;
const CString strText = m_Strings.GetStr(nLine);
LPCTSTR pChar = strText;
int nTabSize = GetTabSize();
int i;
for (i = 0; *pChar != 0 && i < nStrPos;)
{
if (*pChar == _T('\t'))
{
nDispCol += nTabSize - ((nDispCol-1) % nTabSize);
}
else
{
nDispCol++;
}
#ifdef XTP_FIXED
// multi byte character : DisplayLength 2
if (isleadbyte( *pChar ))
nDispCol ++;
#endif
pChar = _tcsinc(pChar);
i++;
}
// support VirtualSpace by default
//m_bVirtualSpace
if (i < nStrPos)
nDispCol += nStrPos - i;
return nDispCol;
}
void CXTPSyntaxEditBufferManager::ChangeCase(int nRow, int nDispFrom, int nDispTo, BOOL bUpper, BOOL bCanUndo)
{
CString strText(m_Strings.GetStr(nRow));
int nFrom = (int)_tcsnbcnt(strText, ColToStrPos(nRow, nDispFrom));
int nTo = strText.GetLength();
if (nDispTo <= strText.GetLength() * GetTabSize())
nTo = (int)_tcsnbcnt(strText, ColToStrPos(nRow, nDispTo));
CString strOriginal = strText.Mid(nFrom, nTo - nFrom);
CString strChanged(strOriginal);
// upper/lower text at row nRow from nFrom to nTo
if (bUpper)
strChanged.MakeUpper();
else
strChanged.MakeLower();
for (int i = nFrom; i < nTo; ++i)
strText.SetAt(i, strChanged[i-nFrom]);
m_Strings.SetAtGrowStr(nRow, strText);
if (bCanUndo)
{
m_pUndoRedoManager->AddCommand(new CXTPSyntaxEditReplaceStringCommand(this,
strChanged, strOriginal,
XTP_EDIT_LINECOL::MakeLineCol(nRow, nFrom + 1),
XTP_EDIT_LINECOL::MakeLineCol(nRow, nTo + 1)) );
}
}
void CXTPSyntaxEditBufferManager::ChangeTabification(int nRow, int nDispFrom, int nDispTo, BOOL bTabify, BOOL bCanUndo)
{
CString strText(m_Strings.GetStr(nRow));
const int nTextLen = (int)_tcsclen(strText);
int nFrom = ColToStrPos(nRow, nDispFrom);
int nTo = ColToStrPos(nRow, nDispTo);
const int nTabSize = GetTabSize();
const CString strTab(_T(' '), nTabSize);
CString strOriginal = strText.Mid(nFrom, nTo - nFrom);
CString strChanged(strOriginal);
// upper/lower text at row nRow from nFrom to nTo
if (bTabify)
{
strChanged.Replace(strTab, _T("\x09"));
}
else
{
strChanged.Replace(_T("\x09"), strTab);
}
strText = strText.Left(nFrom) + strChanged + strText.Right(nTextLen - nTo);
m_Strings.SetAtGrowStr(nRow, strText);
if (bCanUndo)
{
m_pUndoRedoManager->AddCommand(new CXTPSyntaxEditDeleteStringCommand(this,
strOriginal,
XTP_EDIT_LINECOL::MakeLineCol(nRow, nFrom + 1),
XTP_EDIT_LINECOL::MakeLineCol(nRow, nTo + 1)) );
m_pUndoRedoManager->AddCommand(new CXTPSyntaxEditInsertStringCommand(this,
strChanged,
XTP_EDIT_LINECOL::MakeLineCol(nRow, nFrom + 1),
XTP_EDIT_LINECOL::MakeLineCol(nRow, nFrom + (int)_tcsclen(strChanged) + 1)) );
}
}
////////////////////////////////////////////////////////////////////////////
//class CXTPSyntaxEditStringsManager
CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::CXTPSyntaxEditStringsManager()
{
}
CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::~CXTPSyntaxEditStringsManager()
{
}
int CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::GetCount() const
{
return (int)m_arStrings.GetSize();
}
CString CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::GetStr(int nRow) const
{
CString* pCStr = GetStrDataC(nRow);
if (pCStr)
return *pCStr;
return _T("");
}
int CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::GetStrLen(int nRow) const
{
CString* pCStr = GetStrDataC(nRow);
if (!pCStr)
return 0;
int nLen = pCStr->GetLength();
return nLen;
}
int CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::GetStrLenC(int nRow) const
{
CString* pCStr = GetStrDataC(nRow);
if (!pCStr)
return 0;
int nLenC = (int)_tcsclen(*pCStr);
return nLenC;
}
void CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::SetAtGrowStr(int nRow, LPCTSTR pcszText)
{
CString* pCStr = GetStrData(nRow, TRUE);
if (!pCStr)
return;
*pCStr = pcszText;
}
void CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::SetAtGrowStr(int nRow,
const CString& strText)
{
CString* pCStr = GetStrData(nRow, TRUE);
if (!pCStr)
return;
*pCStr = strText;
}
void CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::InsertStr(int nRow,
const CString& strText)
{
if (nRow >=0 && nRow < m_arStrings.GetSize() )
{
CString* pCStr = new CString(strText);
m_arStrings.InsertAt(nRow, pCStr);
}
else
{
SetAtGrowStr(nRow, strText);
}
}
BOOL CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::RemoveStr(int nRow)
{
if (nRow >=0 && nRow < m_arStrings.GetSize() )
{
CString* pCStr = m_arStrings[nRow];
m_arStrings.RemoveAt(nRow);
if (pCStr)
delete pCStr;
return TRUE;
}
return FALSE;
}
CString* CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::GetStrDataC(int nRow) const
{
CString* pCStr = NULL;
if (nRow >=0 && nRow < m_arStrings.GetSize() )
pCStr = m_arStrings[nRow];
return pCStr;
}
CString* CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::
GetStrData(int nRow, BOOL bGrowArrayIfNeed)
{
CString* pCStr = NULL;
if (nRow >=0 && nRow < m_arStrings.GetSize() )
pCStr = m_arStrings[nRow];
else if (bGrowArrayIfNeed)
m_arStrings.SetSize(nRow+1);
else
return NULL;
if (!pCStr)
{
pCStr = new CString();
m_arStrings[nRow] = pCStr;
}
return pCStr;
}
BOOL CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::InsertText(int nRow, int nPos,
LPCTSTR pcszText, BOOL bGrowArrayIfNeed,
TCHAR chLeftSpaceFiller)
{
ASSERT(nPos >= 0 && pcszText);
CString* pCStr = GetStrData(nRow, bGrowArrayIfNeed);
if (!pCStr || !pcszText && nPos < 0)
return FALSE;
int nStrLenC = (int)_tcsclen(*pCStr);
int nFillCount = nPos > nStrLenC ? nPos - nStrLenC : 0;
int nInsPos = (int)_tcsnbcnt(*pCStr, nPos);
if (nFillCount)
{
if (chLeftSpaceFiller != _T('\0'))
{
CString strFill(chLeftSpaceFiller, nFillCount);
*pCStr += strFill;
nInsPos = (int)_tcsnbcnt(*pCStr, nPos);
}
else
{
nInsPos = pCStr->GetLength();
}
}
pCStr->Insert(nInsPos, pcszText);
return TRUE;
}
BOOL CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::
DeleteText(int nRow, int nPos, int nCount)
{
ASSERT(nPos >= 0 && nCount > 0);
CString* pCStr = GetStrData(nRow, FALSE);
if (!pCStr || nPos < 0 || nCount <= 0)
return FALSE;
int nStrLen0 = pCStr->GetLength();
int nPosX = (int)_tcsnbcnt(*pCStr, nPos);
if (nPosX >= nStrLen0)
return FALSE;
int nStrLenC = (int)_tcsclen(*pCStr);
if (nCount > nStrLenC - nPos)
nCount = nStrLenC - nPos;
int nCountX = (int)_tcsnbcnt(((LPCTSTR)*pCStr) + nPosX, nCount);
pCStr->Delete(nPosX, nCountX);
return TRUE;
}
void CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::RemoveAllStrs()
{
m_arStrings.RemoveAll();
}
////////////////////////////////////////////////////////////////////////////
//class CStringPtrArray : public CArray<CString*, CString*>
CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::
CStringPtrArray::CStringPtrArray()
{
}
CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::
CStringPtrArray::~CStringPtrArray()
{
RemoveAll();
}
void CXTPSyntaxEditBufferManager::CXTPSyntaxEditStringsManager::
CStringPtrArray::RemoveAll()
{
int nCount = (int)GetSize();
for (int i = 0; i < nCount; i++)
{
CString* pCStr = GetAt(i);
if (pCStr)
{
SetAt(i, NULL);
delete pCStr;
}
}
TBase::RemoveAll();
}