// XTPSyntaxEditLexCfgFileReader.cpp: implementation of the CXTPSyntaxEditLexCfgFileReader class. // // 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/XTPSmartPtrInternalT.h" #include "Common/XTPResourceManager.h" #include "Common/XTPVC80Helpers.h" // syntax editor includes #include "XTPSyntaxEditDefines.h" #include "XTPSyntaxEditLexPtrs.h" #include "XTPSyntaxEditLexCfgFileReader.h" #include "XTPSyntaxEditLexColorFileReader.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef DBG_READ_TRACE #define DBG_READ_TRACE #endif namespace XTPSyntaxEditLexAnalyser { //=========================================================================== // XTP_EDIT_LEXPROPINFO //=========================================================================== XTP_EDIT_LEXPROPINFO::XTP_EDIT_LEXPROPINFO() { nLine = 0; nOffset = 0; nPropertyLen = 0; } XTP_EDIT_LEXPROPINFO::XTP_EDIT_LEXPROPINFO(const XTP_EDIT_LEXPROPINFO& rSrc) { arPropName.RemoveAll(); int i; for (i = 0; i < rSrc.arPropName.GetSize(); ++i) { arPropName.Add(rSrc.arPropName[i]); } arPropValue.RemoveAll(); for (i = 0; i < rSrc.arPropValue.GetSize(); ++i) { arPropValue.Add(rSrc.arPropValue[i]); } nLine = rSrc.nLine; nOffset = rSrc.nOffset; nPropertyLen = rSrc.nPropertyLen; } const XTP_EDIT_LEXPROPINFO& XTP_EDIT_LEXPROPINFO::operator = (const XTP_EDIT_LEXPROPINFO& rSrc) { arPropName.RemoveAll(); int i; for (i = 0; i < rSrc.arPropName.GetSize(); ++i) { arPropName.Add(rSrc.arPropName[i]); } arPropValue.RemoveAll(); for (i = 0; i < rSrc.arPropValue.GetSize(); ++i) { arPropValue.Add(rSrc.arPropValue[i]); } nLine = rSrc.nLine; nOffset = rSrc.nOffset; nPropertyLen = rSrc.nPropertyLen; return *this; } //=========================================================================== // CXTPSyntaxEditLexPropInfoArray //=========================================================================== CXTPSyntaxEditLexPropInfoArray::CXTPSyntaxEditLexPropInfoArray() { } CXTPSyntaxEditLexPropInfoArray::CXTPSyntaxEditLexPropInfoArray(const CXTPSyntaxEditLexPropInfoArray& rSrc) { RemoveAll(); for (int i = 0; i < rSrc.GetSize(); ++i) { XTP_EDIT_LEXPROPINFO info(rSrc[i]); Add(info); } } const CXTPSyntaxEditLexPropInfoArray& CXTPSyntaxEditLexPropInfoArray::operator = (const CXTPSyntaxEditLexPropInfoArray& rSrc) { RemoveAll(); for (int i = 0; i < rSrc.GetSize(); ++i) { XTP_EDIT_LEXPROPINFO info(rSrc[i]); Add(info); } return *this; } //=========================================================================== // XTP_EDIT_LEXCLASSINFO //=========================================================================== XTP_EDIT_LEXCLASSINFO::XTP_EDIT_LEXCLASSINFO() { nEndLine = 0; nStartLine = 0; } XTP_EDIT_LEXCLASSINFO::XTP_EDIT_LEXCLASSINFO(const XTP_EDIT_LEXCLASSINFO& rSrc) { arPropertyDesc.RemoveAll(); for (int i = 0; i < rSrc.arPropertyDesc.GetSize(); ++i) { XTP_EDIT_LEXPROPINFO info(rSrc.arPropertyDesc[i]); arPropertyDesc.Add(info); } nEndLine = rSrc.nEndLine; nStartLine = rSrc.nStartLine; csClassName = rSrc.csClassName; } const XTP_EDIT_LEXCLASSINFO& XTP_EDIT_LEXCLASSINFO::operator = (const XTP_EDIT_LEXCLASSINFO& rSrc) { arPropertyDesc.RemoveAll(); for (int i = 0; i < rSrc.arPropertyDesc.GetSize(); ++i) { XTP_EDIT_LEXPROPINFO info(rSrc.arPropertyDesc[i]); arPropertyDesc.Add(info); } nEndLine = rSrc.nEndLine; nStartLine = rSrc.nStartLine; csClassName = rSrc.csClassName; return *this; } //=========================================================================== // CXTPSyntaxEditLexClassInfoArray //=========================================================================== CXTPSyntaxEditLexClassInfoArray::CXTPSyntaxEditLexClassInfoArray() { m_bModified = FALSE; } CXTPSyntaxEditLexClassInfoArray::CXTPSyntaxEditLexClassInfoArray(const CXTPSyntaxEditLexClassInfoArray& rSrc) { RemoveAll(); m_bModified = rSrc.m_bModified; for (int i = 0; i < rSrc.GetSize(); ++i) { XTP_EDIT_LEXCLASSINFO info(rSrc[i]); Add(info); } } const CXTPSyntaxEditLexClassInfoArray& CXTPSyntaxEditLexClassInfoArray::operator = (const CXTPSyntaxEditLexClassInfoArray& rSrc) { RemoveAll(); m_bModified = rSrc.m_bModified; for (int i = 0; i < rSrc.GetSize(); ++i) { XTP_EDIT_LEXCLASSINFO info(rSrc[i]); Add(info); } return *this; } extern CString MakeStr(const CStringArray& rArProps, LPCTSTR strSplitter); } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// using namespace XTPSyntaxEditLexAnalyser; const CString cstrDelims(_T(" \t,")); const CString cstrEOL(_T("\r\n")); const CString cstrHex(_T("0123456789ABCDEFGabcdefg")); AFX_STATIC BOOL AFX_CDECL AfxCompareTime(const FILETIME& ft1, const FILETIME& ft2, DWORD dwTimeDiff = 500) { ULARGE_INTEGER uFT1, uFT2; uFT1.LowPart = ft1.dwLowDateTime; uFT1.HighPart = ft1.dwHighDateTime; uFT2.LowPart = ft2.dwLowDateTime; uFT2.HighPart = ft2.dwHighDateTime; ULONGLONG ullDiff = uFT1.QuadPart > uFT2.QuadPart ? uFT1.QuadPart - uFT2.QuadPart : uFT2.QuadPart - uFT1.QuadPart; //ullDiff = the number of 100-nanosecond intervals since January 1, 1601. if (ullDiff <= (dwTimeDiff*1000*1000/100)) { return TRUE; } return FALSE; } AFX_STATIC BOOL AFX_CDECL AfxOpenFile(CFile& file, LPCTSTR lpszFileName, UINT nOpenFlags) { if (nOpenFlags == CFile::modeRead) { if (!FILEEXISTS_S(lpszFileName)) { return FALSE; } } CFileException e; if (!file.Open(lpszFileName, nOpenFlags, &e)) { AfxThrowFileException(e.m_cause, e.m_lOsError, e.m_strFileName); } return TRUE; } AFX_STATIC CString AFX_CDECL AfxMakeStrES(const CStringArray& rArProps, LPCTSTR strSplitter) { CString strResult; int nCount = (int)rArProps.GetSize(); for (int i = 0; i < nCount; i++) { CString csProp = XTPSyntaxEditLexConfig()->ESToStr(rArProps[i], TRUE); if (i) { strResult += strSplitter; } CString strI = csProp; strResult += strI; } return strResult; } //////////////////////////////////////////////////////////////////////////// CXTPSyntaxEditLexCfgFileReader& AFX_CDECL CXTPSyntaxEditLexCfgFileReader::Instance() { static CXTPSyntaxEditLexCfgFileReader instance; return instance; } CXTPSyntaxEditLexCfgFileReader::CXTPSyntaxEditLexCfgFileReader() { m_csDataBuffer = XTP_EDIT_LEXCLASS_EMPTYSTR; m_nCurrLine = 0; m_nCurrLine_pos = 0; m_nCurrPos = 0; m_nEOFPos = 0; m_strToken = XTP_EDIT_LEXCLASS_EMPTYSTR; m_nTokenType = xtpEditTokType_Unknown; m_bReadNames = TRUE; m_bES = FALSE; p_sSyntaxScheme = NULL; p_sColorScheme = NULL; } CXTPSyntaxEditLexCfgFileReader::~CXTPSyntaxEditLexCfgFileReader() { CleanInfoMap(m_mapLexClassInfo); } void CXTPSyntaxEditLexCfgFileReader::CleanInfoMap(CMapStringToPtr& mapInfo) { for (POSITION pos = mapInfo.GetStartPosition(); pos;) { CString csFileName; CXTPSyntaxEditLexClassInfoArray* pInfoArray = NULL; mapInfo.GetNextAssoc(pos, csFileName, (void*&)pInfoArray); SAFE_DELETE(pInfoArray); } mapInfo.RemoveAll(); } void CXTPSyntaxEditLexCfgFileReader::CopyInfoMap(CMapStringToPtr& mapInfo) { CleanInfoMap(mapInfo); for (POSITION pos = m_mapLexClassInfo.GetStartPosition(); pos;) { // get the source data. CString csFileName; CXTPSyntaxEditLexClassInfoArray* pSource = NULL; m_mapLexClassInfo.GetNextAssoc(pos, csFileName, (void*&)pSource); // instantiate a new data pointer. CXTPSyntaxEditLexClassInfoArray* pDest = new CXTPSyntaxEditLexClassInfoArray(*pSource); // set the data. mapInfo[csFileName] = pDest; } } void CXTPSyntaxEditLexCfgFileReader::ReadSource2(const CString& csFileName, CStringArray& arBuffer) { try { arBuffer.RemoveAll(); CStdioFile file; if (AfxOpenFile(file, csFileName, CFile::modeRead)) { arBuffer.Add(_T("")); CString csBuffer; while(file.ReadString(csBuffer)) { int nLen = csBuffer.GetLength(); if (nLen && csBuffer[nLen - 1] == _T('\r')) csBuffer.Delete(nLen - 1); arBuffer.Add(csBuffer); } } } catch(CFileException* expFile) { #ifdef _DEBUG ProcessFileException(expFile); #endif expFile->Delete(); } } void CXTPSyntaxEditLexCfgFileReader::ReadSource(const CString& csFileName, BOOL bSaveInfo) { try { CFile file; if (AfxOpenFile(file, csFileName, CFile::modeRead)) { int iLen = (int)file.GetLength(); char* pszBuffer = new char[iLen + 2]; int iBytes = (int)file.Read(pszBuffer, iLen); ASSERT(iLen == iBytes); pszBuffer[iLen] = '\0'; m_csDataBuffer = pszBuffer; SAFE_DELETE_AR(pszBuffer); file.Close(); Parse(m_arLexClassInfo); if (bSaveInfo) { CString csKey = csFileName; csKey.MakeLower(); CXTPSyntaxEditLexClassInfoArray* pInfo = NULL; if (!m_mapLexClassInfo.Lookup(csKey, (void*&)pInfo)) m_mapLexClassInfo[csKey] = new CXTPSyntaxEditLexClassInfoArray(m_arLexClassInfo); else *pInfo = m_arLexClassInfo; } } } catch(CFileException* expFile) { #ifdef _DEBUG ProcessFileException(expFile); #endif expFile->Delete(); } } void CXTPSyntaxEditLexCfgFileReader::ReadStringSource(BOOL bSaveInfo, CString sPassedString, CString* pSyntaxScheme) { if (pSyntaxScheme == NULL) return; p_sSyntaxScheme = pSyntaxScheme; m_csDataBuffer = *pSyntaxScheme; Parse(m_arLexClassInfo); if (bSaveInfo) { CString csKey = _T("InternalSyntaxSet"); //CString csKey = sPassedString ; csKey.MakeLower(); CXTPSyntaxEditLexClassInfoArray* pInfo = NULL; if (!m_mapLexClassInfo.Lookup(csKey, (void*&)pInfo)) m_mapLexClassInfo[csKey] = new CXTPSyntaxEditLexClassInfoArray(m_arLexClassInfo); else *pInfo = m_arLexClassInfo; } } void CXTPSyntaxEditLexCfgFileReader::ReadSource(UINT nResourceID) { CXTPResourceManager::AssertValid(XTPResourceManager()->LoadHTML(&m_csDataBuffer, nResourceID)); } void CXTPSyntaxEditLexCfgFileReader::Parse(CXTPSyntaxEditLexClassInfoArray& arLexClassDesc) { arLexClassDesc.RemoveAll(); m_nEOFPos = m_csDataBuffer.GetLength() - 1; m_nPrevPos = 0; if (m_nEOFPos < 0) return; m_nCurrLine = 1; m_nCurrLine_pos = 0; m_nCurrPos = 0; m_strToken = XTP_EDIT_LEXCLASS_EMPTYSTR; int nTokenType = 0; while(m_nEOFPos > m_nCurrPos && m_strToken.CompareNoCase(XTP_EDIT_LEXCLASS_STARTTOKEN) != 0) { nTokenType = GetLexToken(); } if (m_strToken.CompareNoCase(XTP_EDIT_LEXCLASS_STARTTOKEN) == 0) { while(m_nEOFPos > m_nCurrPos) { XTP_EDIT_LEXCLASSINFO infoClass; ParseLexClass(infoClass); if (!infoClass.csClassName.IsEmpty()) arLexClassDesc.Add(infoClass); } } } void CXTPSyntaxEditLexCfgFileReader::ParseLexClass(XTP_EDIT_LEXCLASSINFO& infoClass) { if (m_strToken.CompareNoCase(XTP_EDIT_LEXCLASS_STARTTOKEN) == 0) { infoClass.nStartLine = m_nCurrLine; infoClass.nEndLine = 0; } int nTokenType = GetLexToken(); int nPrevToken = 0; while(m_strToken.CompareNoCase(XTP_EDIT_LEXCLASS_STARTTOKEN) != 0 && m_nEOFPos > m_nCurrPos ) { XTP_EDIT_LEXPROPINFO infoProp; if (m_strToken.CompareNoCase(XTP_EDIT_LEXCLASS_ENDTOKEN) == 0) infoClass.nEndLine = m_nCurrLine; infoProp.nLine = 0; infoProp.nPropertyLen = 0; infoProp.nOffset = 0; int nValBeginPos = 0; while(m_strToken != _T('=') && m_nEOFPos > m_nCurrPos && m_strToken.CompareNoCase(XTP_EDIT_LEXCLASS_STARTTOKEN) != 0) { if (nTokenType != xtpEditTokType_EOL && m_nEOFPos > m_nCurrPos) { if (m_strToken.CompareNoCase(XTP_EDIT_LEXCLASS_PROPNAME) == 0) infoClass.csClassName = m_strToken; else infoProp.arPropName.Add(m_strToken); infoProp.nLine = m_nCurrLine; } nTokenType = GetLexToken(); } if (m_strToken.CompareNoCase(XTP_EDIT_LEXCLASS_STARTTOKEN) != 0 && nTokenType != xtpEditTokType_EOL) { // get value's chain nTokenType = GetLexToken(); infoProp.nOffset = m_nCurrPos - m_nPrevPos - m_strToken.GetLength(); nValBeginPos = m_nCurrPos - m_strToken.GetLength(); if (nPrevToken == xtpEditTokType_Quoted) { infoProp.nOffset += 1; } if (nTokenType == xtpEditTokType_Quoted ) { infoProp.nOffset -= 1; nValBeginPos -= 1; } while(nTokenType != xtpEditTokType_EOL && m_nEOFPos > m_nCurrPos) { if (nTokenType != xtpEditTokType_EOL) { if (infoClass.csClassName.CompareNoCase(XTP_EDIT_LEXCLASS_PROPNAME) == 0) { infoClass.csClassName = m_strToken; DBG_READ_TRACE(_T("\nClass name = %s "), m_strToken); } else { m_nPrevPos = m_nCurrPos; CString str = StrToES(m_strToken, TRUE); infoProp.arPropValue.Add(str); str = ESToStr(str, TRUE); } } nPrevToken = nTokenType; nTokenType = GetLexToken(); } if (infoProp.arPropValue.GetSize() > 0) { infoProp.nPropertyLen += m_nPrevPos - nValBeginPos; if (nPrevToken == xtpEditTokType_Quoted) infoProp.nPropertyLen -= 1; infoClass.arPropertyDesc.Add(infoProp); } nTokenType = GetLexToken(); } } if (infoClass.nEndLine == 0) { int nCount = (int)infoClass.arPropertyDesc.GetSize(); if (nCount) { infoClass.nEndLine = infoClass.arPropertyDesc[nCount-1].nLine; } else { infoClass.nEndLine = infoClass.nStartLine; } } } int CXTPSyntaxEditLexCfgFileReader::GetLexToken() { int nIgnoredTokensMask = xtpEditTokType_Unknown; nIgnoredTokensMask |= xtpEditTokType_Delim; nIgnoredTokensMask |= xtpEditTokType_Comment; m_strToken = XTP_EDIT_LEXCLASS_EMPTYSTR; int nTokenType = GetToken(); if (m_strToken == _T(":")) nTokenType = xtpEditTokType_Unknown; while((nTokenType == xtpEditTokType_Unknown || nTokenType == xtpEditTokType_Delim|| nTokenType == xtpEditTokType_Comment) && m_nEOFPos > m_nCurrPos) { m_strToken = XTP_EDIT_LEXCLASS_EMPTYSTR; nTokenType = GetToken(); } if (m_strToken == _T("lexClass")) { GetToken(); } return nTokenType; } int CXTPSyntaxEditLexCfgFileReader::GetToken() { TCHAR tchCurrSymbol = _T('\0'); int nFoundedToken = 0; if (m_nCurrPos >= m_nEOFPos) { return xtpEditTokType_Unknown; } TCHAR tchCurr_0 = m_csDataBuffer.GetAt(m_nCurrPos); if (tchCurr_0 == _T('\x0A') && m_nCurrPos > m_nCurrLine_pos) { m_nCurrLine++; m_nCurrLine_pos = m_nCurrPos; } tchCurrSymbol = m_csDataBuffer.GetAt(m_nCurrPos++); switch (m_nTokenType) { case xtpEditTokType_Unknown : nFoundedToken = ProcessUnknowToken(tchCurrSymbol); if (m_nTokenType == xtpEditTokType_Unknown) { GetToken(); } break; case xtpEditTokType_Delim : nFoundedToken = ProcessDelimToken(tchCurrSymbol); break; case xtpEditTokType_Name : nFoundedToken = ProcessNameToken(tchCurrSymbol); if (m_nTokenType == xtpEditTokType_Name) { m_strToken += tchCurrSymbol; GetToken(); } break; case xtpEditTokType_Value : nFoundedToken = ProcessValueToken(tchCurrSymbol); if (m_nTokenType == xtpEditTokType_Value) { m_strToken += tchCurrSymbol; GetToken(); } break; case xtpEditTokType_Quoted : nFoundedToken = ProcessQuotedToken(tchCurrSymbol); if (m_nTokenType == xtpEditTokType_Quoted) { m_strToken += tchCurrSymbol; GetToken(); } break; case xtpEditTokType_Comment : nFoundedToken = ProcessCommentToken(tchCurrSymbol); if (m_nTokenType == xtpEditTokType_Comment) { m_strToken += tchCurrSymbol; GetToken(); } break; case xtpEditTokType_EOL : nFoundedToken = ProcessEOLToken(tchCurrSymbol); if (m_nTokenType == xtpEditTokType_EOL) { m_strToken += tchCurrSymbol; GetToken(); } break; case xtpEditTokType_Control : nFoundedToken = ProcessControlToken(tchCurrSymbol); if (m_nTokenType == xtpEditTokType_Control) { m_strToken += tchCurrSymbol; GetToken(); } break; default : nFoundedToken = ProcessUnknowToken(tchCurrSymbol); if (m_nTokenType == xtpEditTokType_Unknown) { GetToken(); } } return nFoundedToken; } int CXTPSyntaxEditLexCfgFileReader::ProcessUnknowToken(TCHAR tchCurrSymbol) { int nFoundedToken = m_nTokenType; if (_istalpha(tchCurrSymbol)) m_nTokenType = xtpEditTokType_Name; else if (tchCurrSymbol == _T('\'')) m_nTokenType = xtpEditTokType_Quoted; else if (tchCurrSymbol == _T('/')) m_nTokenType = xtpEditTokType_Comment; else if (cstrDelims.Find(tchCurrSymbol) > -1) m_nTokenType = xtpEditTokType_Delim; else if (cstrEOL.Find(tchCurrSymbol) > -1) m_nTokenType = xtpEditTokType_EOL; else if (tchCurrSymbol == _T('=')) m_nTokenType = xtpEditTokType_Control; else if (tchCurrSymbol == _T(':')) m_nTokenType = xtpEditTokType_Control; else m_nTokenType = xtpEditTokType_Value; if (nFoundedToken != m_nTokenType) m_nCurrPos--; return nFoundedToken; } int CXTPSyntaxEditLexCfgFileReader::ProcessDelimToken(TCHAR tchCurrSymbol) { return ProcessUnknowToken(tchCurrSymbol); } int CXTPSyntaxEditLexCfgFileReader::ProcessNameToken(TCHAR tchCurrSymbol) { int nFoundedToken = m_nTokenType; if (tchCurrSymbol == _T('\'')) m_nTokenType = xtpEditTokType_Quoted; else if (tchCurrSymbol == _T('/')) m_nTokenType = xtpEditTokType_Comment; else if (cstrDelims.Find(tchCurrSymbol) > -1) m_nTokenType = xtpEditTokType_Delim; else if (cstrEOL.Find(tchCurrSymbol) > -1) m_nTokenType = xtpEditTokType_EOL; else if (tchCurrSymbol == _T('=')) m_nTokenType = xtpEditTokType_Control; else if (tchCurrSymbol == _T(':')) m_nTokenType = xtpEditTokType_Control; if (nFoundedToken != m_nTokenType) m_nCurrPos--; return nFoundedToken; } int CXTPSyntaxEditLexCfgFileReader::ProcessValueToken(TCHAR tchCurrSymbol) { int nFoundedToken = m_nTokenType; if (cstrDelims.Find(tchCurrSymbol) > -1) m_nTokenType = xtpEditTokType_Delim; else if (cstrEOL.Find(tchCurrSymbol) > -1) m_nTokenType = xtpEditTokType_EOL; else if (tchCurrSymbol == _T('/')) m_nTokenType = xtpEditTokType_Comment; if (nFoundedToken != m_nTokenType) m_nCurrPos--; return nFoundedToken; } int CXTPSyntaxEditLexCfgFileReader::ProcessQuotedToken(TCHAR tchCurrSymbol) { int nFoundedToken = m_nTokenType; int nLen = m_strToken.GetLength(); if (cstrEOL.Find(tchCurrSymbol) > -1) m_nTokenType = xtpEditTokType_EOL; else if (m_nCurrPos == m_nEOFPos) m_nTokenType = xtpEditTokType_Unknown; else if (nLen == 0) return nFoundedToken; else if (m_strToken.GetAt(max(0, m_strToken.GetLength() - 1)) == _T('\\')) { return nFoundedToken; } else if (tchCurrSymbol == _T('\'')) { if (m_strToken == _T('\'')) { nFoundedToken = GetToken(); } else { m_nTokenType = xtpEditTokType_Unknown; m_strToken += tchCurrSymbol; m_nCurrPos++; } } return nFoundedToken; } int CXTPSyntaxEditLexCfgFileReader::ProcessCommentToken(TCHAR tchCurrSymbol) { int nFoundedToken = m_nTokenType; if (cstrEOL.Find(tchCurrSymbol) > -1) { m_nTokenType = xtpEditTokType_EOL; m_nCurrPos--; } return nFoundedToken; } int CXTPSyntaxEditLexCfgFileReader::ProcessEOLToken(TCHAR tchCurrSymbol) { return ProcessUnknowToken(tchCurrSymbol); } int CXTPSyntaxEditLexCfgFileReader::ProcessControlToken(TCHAR tchCurrSymbol) { return ProcessUnknowToken(tchCurrSymbol); } CXTPSyntaxEditLexClassInfoArray& CXTPSyntaxEditLexCfgFileReader::GetLexClassInfoArray() { return m_arLexClassInfo; } BOOL CXTPSyntaxEditLexCfgFileReader::WriteCfgFile(const CString& csFileName, CXTPSyntaxEditLexClassInfoArray& arLexClassDesc) { if (!arLexClassDesc.m_bModified) return FALSE; CStringArray arBuffer; CMapPtrToBool mapSavedClass; ReadSource(csFileName, FALSE); ReadSource2(csFileName, arBuffer); try { CString csTmpFileName = csFileName + _T(".tmp"); ::SetFileAttributes(csTmpFileName, FILE_ATTRIBUTE_NORMAL); ::DeleteFile(csTmpFileName); CFile file; if (!AfxOpenFile(file, csTmpFileName, CFile::modeWrite | CFile::shareExclusive | CFile::modeCreate)) return FALSE; int nLastWrittenLine = 0; // (1) Update Existing and deleted Classes int nCount = (int)m_arLexClassInfo.GetSize(); int i; for (i = 0; i < nCount; i++) { XTP_EDIT_LEXCLASSINFO& oldClassInfo = m_arLexClassInfo[i]; XTP_EDIT_LEXCLASSINFO* pNewClassInfo = FindClassDesc(arLexClassDesc, oldClassInfo.csClassName); // class was deleted; if (!pNewClassInfo) { WriteStrings(file, arBuffer, nLastWrittenLine+1, oldClassInfo.nStartLine-1); nLastWrittenLine = oldClassInfo.nEndLine; continue; } mapSavedClass[pNewClassInfo] = TRUE; CMapPtrToBool mapSavedProps; CString csOffset(_T("\t")); // (1.a) Update Existing and deleted properties int nPropsCount = (int)oldClassInfo.arPropertyDesc.GetSize(); int k; for (k = 0; k < nPropsCount; k++) { XTP_EDIT_LEXPROPINFO& oldInfoProp = oldClassInfo.arPropertyDesc[k]; WriteStrings(file, arBuffer, nLastWrittenLine+1, oldInfoProp.nLine-1); nLastWrittenLine = oldInfoProp.nLine; XTP_EDIT_LEXPROPINFO* pNewInfoProp = FindPropDesc(pNewClassInfo, &oldInfoProp, mapSavedProps); if (pNewInfoProp) { WriteProp(file, csOffset, oldInfoProp, *pNewInfoProp, arBuffer); mapSavedProps[pNewInfoProp] = TRUE; } } // (1.b) Insert new properties nPropsCount = (int)pNewClassInfo->arPropertyDesc.GetSize(); for (k = 0; k < nPropsCount; k++) { XTP_EDIT_LEXPROPINFO& newInfoProp = pNewClassInfo->arPropertyDesc[k]; bool bSaved = false; if (!mapSavedProps.Lookup((void*)&newInfoProp, bSaved) || !bSaved) { WriteProp(file, csOffset, newInfoProp); } } } //------------------------------------------------------------------------ WriteStrings(file, arBuffer, nLastWrittenLine + 1, m_nCurrLine); nLastWrittenLine = m_nCurrLine; //=========================================================================== // (2) Insert new Classes nCount = (int)arLexClassDesc.GetSize(); for (i = 0; i < nCount; i++) { XTP_EDIT_LEXCLASSINFO& newClassInfo = arLexClassDesc[i]; bool bSaved = false; if (!mapSavedClass.Lookup((void*)&newClassInfo, bSaved) || !bSaved) { WriteString(file, _T("")); WriteString(file, XTP_EDIT_LEXCLASS_STARTTOKEN); // Insert properties int nPropsCount = (int)newClassInfo.arPropertyDesc.GetSize(); for (int k = 0; k < nPropsCount; k++) { const XTP_EDIT_LEXPROPINFO& newInfoProp = newClassInfo.arPropertyDesc[k]; CString csOffset(_T("\t")); WriteProp(file, csOffset, newInfoProp); } WriteString(file, XTP_EDIT_LEXCLASS_ENDTOKEN); } } //=========================================================================== file.Close(); CString strFileName_prev = csFileName + _T(".old"); ::SetFileAttributes(strFileName_prev, FILE_ATTRIBUTE_NORMAL); ::DeleteFile(strFileName_prev); #ifdef _DEBUG //CFile::Rename(csFileName, strFileName_prev); #endif ::SetFileAttributes(csFileName, FILE_ATTRIBUTE_NORMAL); ::DeleteFile(csFileName); CFile::Rename(csTmpFileName, csFileName); m_arLexClassInfo.RemoveAll(); return TRUE; } catch(CFileException* expFile) { #ifdef _DEBUG expFile->ReportError(); //ProcessFileException(expFile); #endif expFile->Delete(); } m_arLexClassInfo.RemoveAll(); arLexClassDesc.m_bModified = FALSE; return FALSE; } BOOL CXTPSyntaxEditLexCfgFileReader::WriteCfg2String(CXTPSyntaxEditLexClassInfoArray& arLexClassDesc) { if (!arLexClassDesc.m_bModified) return FALSE; CStringArray arBuffer; CMapPtrToBool mapSavedClass; //ReadSource(csFileName, FALSE); //ReadSource2(csFileName, arBuffer); //try //{ // int nLastWrittenLine = 0; // // (1) Update Existing and deleted Classes // int nCount = (int)m_arLexClassInfo.GetSize(); // int i; // for (i = 0; i < nCount; i++) // { // XTP_EDIT_LEXCLASSINFO& oldClassInfo = m_arLexClassInfo[i]; // XTP_EDIT_LEXCLASSINFO* pNewClassInfo = FindClassDesc(arLexClassDesc, oldClassInfo.csClassName); // // class was deleted; // if (!pNewClassInfo) // { // WriteStrings(file, arBuffer, nLastWrittenLine+1, oldClassInfo.nStartLine-1); // nLastWrittenLine = oldClassInfo.nEndLine; // continue; // } // mapSavedClass[pNewClassInfo] = TRUE; // CMapPtrToBool mapSavedProps; // CString csOffset(_T("\t")); // // (1.a) Update Existing and deleted properties // int nPropsCount = (int)oldClassInfo.arPropertyDesc.GetSize(); // int k; // for (k = 0; k < nPropsCount; k++) // { // XTP_EDIT_LEXPROPINFO& oldInfoProp = oldClassInfo.arPropertyDesc[k]; // WriteStrings(file, arBuffer, nLastWrittenLine+1, oldInfoProp.nLine-1); // nLastWrittenLine = oldInfoProp.nLine; // XTP_EDIT_LEXPROPINFO* pNewInfoProp = FindPropDesc(pNewClassInfo, &oldInfoProp, mapSavedProps); // if (pNewInfoProp) // { // WriteProp(file, csOffset, oldInfoProp, *pNewInfoProp, arBuffer); // mapSavedProps[pNewInfoProp] = TRUE; // } // } // // (1.b) Insert new properties // nPropsCount = (int)pNewClassInfo->arPropertyDesc.GetSize(); // for (k = 0; k < nPropsCount; k++) // { // XTP_EDIT_LEXPROPINFO& newInfoProp = pNewClassInfo->arPropertyDesc[k]; // bool bSaved = false; // if (!mapSavedProps.Lookup((void*)&newInfoProp, bSaved) || !bSaved) // { // WriteProp(file, csOffset, newInfoProp); // } // } // } // //------------------------------------------------------------------------ // WriteStrings(file, arBuffer, nLastWrittenLine + 1, m_nCurrLine); // nLastWrittenLine = m_nCurrLine; // //=========================================================================== // // (2) Insert new Classes // nCount = (int)arLexClassDesc.GetSize(); // for (i = 0; i < nCount; i++) // { // XTP_EDIT_LEXCLASSINFO& newClassInfo = arLexClassDesc[i]; // bool bSaved = false; // if (!mapSavedClass.Lookup((void*)&newClassInfo, bSaved) || !bSaved) // { // WriteString(file, _T("")); // WriteString(file, XTP_EDIT_LEXCLASS_STARTTOKEN); // // Insert properties // int nPropsCount = (int)newClassInfo.arPropertyDesc.GetSize(); // for (int k = 0; k < nPropsCount; k++) // { // const XTP_EDIT_LEXPROPINFO& newInfoProp = newClassInfo.arPropertyDesc[k]; // CString csOffset(_T("\t")); // WriteProp(file, csOffset, newInfoProp); // } // WriteString(file, XTP_EDIT_LEXCLASS_ENDTOKEN); // } // } m_arLexClassInfo.RemoveAll(); return TRUE; } XTP_EDIT_LEXCLASSINFO* CXTPSyntaxEditLexCfgFileReader::FindClassDesc(CXTPSyntaxEditLexClassInfoArray& arInfoClass, const CString& csClassName) { if (csClassName.IsEmpty()) { ASSERT(FALSE); return NULL; } for (int i = 0; i < arInfoClass.GetSize(); i++) { if (arInfoClass[i].csClassName.CompareNoCase(csClassName) == 0) { return &arInfoClass[i]; } } return NULL; } XTP_EDIT_LEXPROPINFO* CXTPSyntaxEditLexCfgFileReader::FindPropDesc(XTP_EDIT_LEXCLASSINFO* pInfoClass, XTP_EDIT_LEXPROPINFO* pInfoProp, CMapPtrToBool& mapUsed) { if (!pInfoClass || !pInfoProp) { ASSERT(FALSE); return NULL; } int nPNameSize = (int)pInfoProp->arPropName.GetSize(); CString strPropName_src = MakeStr(pInfoProp->arPropName, _T(":")); int nCount = (int)pInfoClass->arPropertyDesc.GetSize(); for (int i = 0; i < nCount; i++) { XTP_EDIT_LEXPROPINFO* pNewInfoProp = &(*pInfoClass).arPropertyDesc[i]; ASSERT(pNewInfoProp); if (pNewInfoProp && pNewInfoProp->arPropName.GetSize() == nPNameSize) { CString strPName = MakeStr(pNewInfoProp->arPropName, _T(":")); if (strPropName_src.CompareNoCase(strPName) == 0) { bool bUsed = false; if (mapUsed.Lookup(pNewInfoProp, bUsed) && bUsed) { continue; } return pNewInfoProp; } } } return NULL; } void CXTPSyntaxEditLexCfgFileReader::WriteString(CFile& file, LPCTSTR pcszString) { int nStrLen = (int)_tcslen(pcszString); #ifdef _UNICODE CByteArray arBufferMBCS; arBufferMBCS.SetSize(nStrLen*2+4); char* pTextMBCS = (char*)arBufferMBCS.GetData(); int nNewLen = WideCharToMultiByte(CP_ACP, 0, pcszString, -1, pTextMBCS, nStrLen*2+1, NULL, NULL); nStrLen = nNewLen ? nNewLen-1 : 0; #else char* pTextMBCS = (char*)pcszString; #endif file.Write(pTextMBCS, nStrLen); file.Write("\r\n", 2); } void CXTPSyntaxEditLexCfgFileReader::WriteStrings(CFile& file, CStringArray& arBuffer, int nFrom, int nTo) { int nCount = (int)arBuffer.GetSize(); if (nFrom >= nCount || nFrom > nTo) { return; } if (nTo >= nCount) { nTo = nCount-1; } for (int nLine = nFrom; nLine <= nTo; nLine++) { CString csBuffer = arBuffer[nLine]; WriteString(file, csBuffer); } } void CXTPSyntaxEditLexCfgFileReader::WriteProp(CFile& file, CString& csOffset, const XTP_EDIT_LEXPROPINFO& newInfoProp) { CString csPropName = MakeStr(newInfoProp.arPropName, _T(":")); CString csPropValue = AfxMakeStrES(newInfoProp.arPropValue, _T(", ")); CString csPropString = csOffset + csPropName + _T(" = ") + csPropValue; WriteString(file, csPropString); } void CXTPSyntaxEditLexCfgFileReader::WriteProp(CFile& file, CString& csOffset, const XTP_EDIT_LEXPROPINFO& oldInfoProp, const XTP_EDIT_LEXPROPINFO& newInfoProp, const CStringArray& arBuffer) { if (oldInfoProp.nLine < arBuffer.GetSize()) { CString csBuffer = arBuffer[oldInfoProp.nLine]; int iIndex = csBuffer.Find(_T("=")); ASSERT(iIndex > 0); if (iIndex > 0) { csOffset = csBuffer.SpanIncluding(_T(" \t")); CString csSep = csBuffer.Mid(iIndex+1); csSep = csSep.SpanIncluding(_T(" \t")); iIndex += csSep.GetLength(); CString csNewBuffer = csBuffer; csNewBuffer.Delete(iIndex+1, oldInfoProp.nPropertyLen); CString csPropValue = AfxMakeStrES(newInfoProp.arPropValue, _T(", ")); csNewBuffer.Insert(iIndex+1, csPropValue); WriteString(file, csNewBuffer); return; } } else { ASSERT(FALSE); } WriteProp(file, csOffset, newInfoProp); } #ifdef _DEBUG void CXTPSyntaxEditLexCfgFileReader::ProcessFileException(CFileException* pExc) { CString strErrorMsg(_T(" ")); switch (pExc->m_cause) { #if (_MSC_VER > 1310) // VS2005 case CFileException::genericException : #else case CFileException::generic : #endif strErrorMsg = _T("An unspecified error occurred."); break; case CFileException::fileNotFound : strErrorMsg = _T("The file could not be located."); break; case CFileException::badPath : strErrorMsg = _T("All or part of the path is invalid."); break; case CFileException::tooManyOpenFiles : strErrorMsg = _T("The permitted number of open files was exceeded."); break; case CFileException::accessDenied : strErrorMsg = _T("The file could not be accessed."); break; case CFileException::invalidFile : strErrorMsg = _T("There was an attempt to use an invalid file handle."); break; case CFileException::removeCurrentDir : strErrorMsg = _T("The current working directory cannot be removed."); break; case CFileException::directoryFull : strErrorMsg = _T("There are no more directory entries."); break; case CFileException::badSeek : strErrorMsg = _T("There was an error trying to set the file pointer."); break; case CFileException::hardIO : strErrorMsg = _T("There was a hardware error."); break; case CFileException::sharingViolation : strErrorMsg = _T("SHARE.EXE was not loaded, or a shared region was locked."); break; case CFileException::lockViolation : strErrorMsg = _T("There was an attempt to lock a region that was already locked."); break; case CFileException::diskFull : strErrorMsg = _T("The disk is full."); break; case CFileException::endOfFile : strErrorMsg = _T("The end of file was reached."); break; default : strErrorMsg = _T("Unknown error."); } TRACE(_T("ERROR: %s File Name: %s \n"), (LPCTSTR)strErrorMsg, (LPCTSTR)pExc->m_strFileName); } #endif CString CXTPSyntaxEditLexCfgFileReader::StrToES(CString strSrc, BOOL bQuoted) { CString strRez(strSrc); strRez.TrimLeft(); strRez.TrimRight(); int nLen = strRez.GetLength(); if (nLen < 1) { return strRez; } if (bQuoted && strRez.GetAt(0) == _T('\'') && strRez.GetAt(nLen - 1) == _T('\'')) { strRez.SetAt(0, _T('\x1')); strRez.SetAt(nLen-1, _T('\x1')); } strRez.Replace(_T("\\\\"), _T("\x2")); strRez.Replace(_T("\\a"), _T("\a")); strRez.Replace(_T("\\b"), _T("\b")); strRez.Replace(_T("\\f"), _T("\f")); strRez.Replace(_T("\\n"), _T("\n")); strRez.Replace(_T("\\r"), _T("\r")); strRez.Replace(_T("\\t"), _T("\t")); strRez.Replace(_T("\\v"), _T("\v")); strRez.Replace(_T("\\'"), _T("\'")); strRez.Replace(_T("\x2"), _T("\\")); strRez.Replace(_T("\x1"), _T("\'")); return strRez; } CString CXTPSyntaxEditLexCfgFileReader::ESToStr(CString strSrc, BOOL bQuoted) { CString strRez(strSrc); strRez.TrimLeft(); strRez.TrimRight(); int nLen = strRez.GetLength(); if (nLen < 1) { return strRez; } if (bQuoted && strRez.GetAt(0) == _T('\'') && strRez.GetAt(nLen - 1) == _T('\'')) { strRez.SetAt(0, _T('\x1')); strRez.SetAt(nLen-1, _T('\x1')); } strRez.Replace(_T("\\"), _T("\x2")); strRez.Replace(_T("\a"), _T("\\a")); strRez.Replace(_T("\b"), _T("\\b")); strRez.Replace(_T("\f"), _T("\\f")); strRez.Replace(_T("\n"), _T("\\n")); strRez.Replace(_T("\r"), _T("\\r")); strRez.Replace(_T("\t"), _T("\\t")); strRez.Replace(_T("\v"), _T("\\v")); strRez.Replace(_T("\'"), _T("\\'")); strRez.Replace(_T("\x2"), _T("\\\\")); strRez.Replace(_T("\x1"), _T("\'")); return strRez; } ///////////////////////////////////////////////////////////////////////////// // CXTPSyntaxEditFileChangesMonitor // CXTPSyntaxEditFileChangesMonitor::CXTPSyntaxEditFileChangesMonitor() { m_pThread = NULL; m_evExitThread = NULL; m_pConfigMgr = NULL; } CXTPSyntaxEditFileChangesMonitor::~CXTPSyntaxEditFileChangesMonitor() { StopMonitoring(); } void CXTPSyntaxEditFileChangesMonitor::SetDefaultFolder(const CString& strPath) { m_strPath = strPath; } void CXTPSyntaxEditFileChangesMonitor::RemoveAll() { m_arFiles.RemoveAll(); } BOOL CXTPSyntaxEditFileChangesMonitor::AddMonitorFile(CString& strFilename, DWORD dwOwnerFlags) { // try open file BY_HANDLE_FILE_INFORMATION sysFileInfo; BOOL bRes = GetFileInfo(strFilename, &sysFileInfo); if (!bRes) { // try again in the default folder CString strFullFilename = m_strPath + strFilename; bRes = GetFileInfo(strFullFilename, &sysFileInfo); if (bRes) strFilename = strFullFilename; } // get complete file name if (bRes) { // get the directory for the file TCHAR szPath[_MAX_PATH]; LPTSTR lpszName; if (::GetFullPathName(strFilename, _MAX_PATH, szPath, &lpszName)) strFilename = szPath; } // Prepare file info structure CFMFileInfo fmFileInfo; fmFileInfo.m_strFileName = strFilename; fmFileInfo.m_bExists = bRes; fmFileInfo.m_dwOwnerFlags = dwOwnerFlags; if (bRes) fmFileInfo.m_sysFileInfo = sysFileInfo; // add file to the monitoring array m_arFiles.Add(fmFileInfo); return bRes; } void CXTPSyntaxEditFileChangesMonitor::StartMonitoring() { if (m_pThread) { ASSERT(FALSE); return; } ASSERT(m_evExitThread == NULL); m_evExitThread = CreateEvent(NULL, TRUE, FALSE, NULL); ASSERT(m_evExitThread); m_pThread = AfxBeginThread(ThreadMonitorProc, (LPVOID)this, THREAD_PRIORITY_LOWEST); //, 0, CREATE_SUSPENDED, NULL); if (!m_pThread) { ASSERT(FALSE); return; } } void CXTPSyntaxEditFileChangesMonitor::StopMonitoring() { if (m_pThread) { HANDLE hThread = m_pThread->m_hThread; ::SetEvent(m_evExitThread); DWORD dwThreadRes = ::WaitForSingleObject(hThread, 20*1000); if (dwThreadRes == WAIT_TIMEOUT) { ::TerminateThread(hThread, 0); //ASSERT(FALSE); TRACE(_T("ERROR! FileChangesMonitor thread was not ended by normal way. It was terminated. \n")); } ::CloseHandle(m_evExitThread); m_evExitThread = NULL; m_pThread = NULL; } RemoveAll(); } UINT CXTPSyntaxEditFileChangesMonitor::ThreadMonitorProc(LPVOID p) { try { CXTPSyntaxEditFileChangesMonitor* pFolderMonitor = (CXTPSyntaxEditFileChangesMonitor*)p; if (!pFolderMonitor) return 1; for (;;) { // Wait for notification. DWORD dwWaitStatus = WaitForSingleObject(pFolderMonitor->m_evExitThread, 3000); if (WAIT_OBJECT_0 == dwWaitStatus) { ::Sleep(100); break; } if (WAIT_TIMEOUT == dwWaitStatus) { pFolderMonitor->RefreshFiles(); } } } catch(...) { TRACE(_T("EXCEPTION in CXTPSyntaxEditFileChangesMonitor::ThreadMonitorProc\n")); } return 0; } void CXTPSyntaxEditFileChangesMonitor::RefreshFiles() { // Iterate all stored filenames int nCount = (int)m_arFiles.GetSize(); for (int i = 0; i < nCount; i++) { //CString strFilename; CFMFileInfo& rFMFileInfo = m_arFiles.ElementAt(i); // get new info for this file BY_HANDLE_FILE_INFORMATION sysFileInfo; if (GetFileInfo(rFMFileInfo.m_strFileName, &sysFileInfo) ) { // check whether file status is changed if (!AfxCompareTime(sysFileInfo.ftLastWriteTime, rFMFileInfo.m_sysFileInfo.ftLastWriteTime) || sysFileInfo.nFileSizeLow != rFMFileInfo.m_sysFileInfo.nFileSizeLow || sysFileInfo.nFileSizeHigh != rFMFileInfo.m_sysFileInfo.nFileSizeHigh || !rFMFileInfo.m_bExists) { int nCfgFlags = rFMFileInfo.m_bExists ? 0 : xtpEditCfgFileAdd; rFMFileInfo.m_sysFileInfo = sysFileInfo; rFMFileInfo.m_bExists = TRUE; // reload this file m_pConfigMgr->ReloadFile(rFMFileInfo.m_strFileName, rFMFileInfo.m_dwOwnerFlags, nCfgFlags); } } else { if (rFMFileInfo.m_bExists) { rFMFileInfo.m_bExists = FALSE; // remove this file from the collection m_pConfigMgr->ReloadFile(rFMFileInfo.m_strFileName, rFMFileInfo.m_dwOwnerFlags, xtpEditCfgFileRemove); } // try again in the default folder CString strFullFilename = m_strPath + rFMFileInfo.m_strFileName; if (GetFileInfo(strFullFilename, &sysFileInfo)) { rFMFileInfo.m_strFileName = strFullFilename; i--; } } } } BOOL CXTPSyntaxEditFileChangesMonitor::GetFileInfo(LPCTSTR pcszFilePath, BY_HANDLE_FILE_INFORMATION* pInfo) { const DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; HANDLE hFile = ::CreateFile(pcszFilePath, GENERIC_READ, dwShareMode, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return FALSE; } if (!pInfo) { return TRUE; } ZeroMemory(pInfo, sizeof(*pInfo)); BOOL bRes = GetFileInformationByHandle(hFile, pInfo); CloseHandle(hFile); return bRes; } //////////////////////////////////////////////////////////////////////////// //class CFMFileInfo CXTPSyntaxEditFileChangesMonitor::CFMFileInfo::CFMFileInfo() { ZeroMemory(&m_sysFileInfo, sizeof(m_sysFileInfo)); m_bExists = FALSE; m_dwOwnerFlags = 0; } const CXTPSyntaxEditFileChangesMonitor::CFMFileInfo& CXTPSyntaxEditFileChangesMonitor::CFMFileInfo::operator=( const CXTPSyntaxEditFileChangesMonitor::CFMFileInfo& rSrc) { m_strFileName = rSrc.m_strFileName; m_sysFileInfo = rSrc.m_sysFileInfo; m_bExists = rSrc.m_bExists; m_dwOwnerFlags = rSrc.m_dwOwnerFlags; return *this; }