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.

770 lines
17 KiB
C++

// XTPSyntaxEditLineMarksManager.cpp : implementation file
//
// 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"
// syntax editor includes
#include "XTPSyntaxEditLineMarksManager.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CXTPSyntaxEditLineMarksManager
IMPLEMENT_DYNAMIC(CXTPSyntaxEditLineMarksManager, CCmdTarget)
////////////////////////////////////////////////////////////////////////////
XTP_EDIT_LMPARAM::~XTP_EDIT_LMPARAM()
{
}
XTP_EDIT_LMPARAM::XTP_EDIT_LMPARAM()
{
Clear();
}
XTP_EDIT_LMPARAM::XTP_EDIT_LMPARAM(const XTP_EDIT_LMPARAM& rSrc)
{
*this = rSrc;
}
XTP_EDIT_LMPARAM::XTP_EDIT_LMPARAM(DWORD dwVal)
{
m_eType = xtpEditLMPT_DWORD;
m_dwValue = dwVal;
}
XTP_EDIT_LMPARAM::XTP_EDIT_LMPARAM(double dblValue)
{
m_eType = xtpEditLMPT_double;
m_dblValue = dblValue;
}
XTP_EDIT_LMPARAM::XTP_EDIT_LMPARAM(void* pPtr)
{
m_eType = xtpEditLMPT_Ptr;
*this = pPtr;
}
const XTP_EDIT_LMPARAM& XTP_EDIT_LMPARAM::operator=(const XTP_EDIT_LMPARAM& rSrc)
{
m_eType = rSrc.m_eType;
if (m_eType == xtpEditLMPT_Unknown)
{
Clear();
}
else if (m_eType == xtpEditLMPT_DWORD)
{
m_dwValue = rSrc.m_dwValue;
}
else if (m_eType == xtpEditLMPT_double)
{
m_dblValue = rSrc.m_dblValue;
}
else if (m_eType == xtpEditLMPT_Ptr)
{
m_Ptr = rSrc.m_Ptr;
}
else
{
ASSERT(FALSE);
}
return *this;
}
const XTP_EDIT_LMPARAM& XTP_EDIT_LMPARAM::operator=(DWORD dwValue)
{
m_Ptr = NULL;
m_eType = xtpEditLMPT_DWORD;
m_dwValue = dwValue;
return *this;
}
const XTP_EDIT_LMPARAM& XTP_EDIT_LMPARAM::operator=(double dblValue)
{
m_Ptr = NULL;
m_eType = xtpEditLMPT_double;
m_dblValue = dblValue;
return *this;
}
void XTP_EDIT_LMPARAM::SetPtr(void* pPtr, CXTPSyntaxEditVoidObj::TPFDeleter pfDeleter)
{
ASSERT(!pPtr || pPtr != m_Ptr);
m_eType = xtpEditLMPT_Ptr;
CXTPSyntaxEditVoidObj* pVoidObj = NULL;
if (pPtr)
{
pVoidObj = new CXTPSyntaxEditVoidObj(pPtr, pfDeleter);
}
m_Ptr = pVoidObj;
}
const XTP_EDIT_LMPARAM& XTP_EDIT_LMPARAM::operator=(void* pPtr)
{
SetPtr(pPtr, NULL);
return *this;
}
XTP_EDIT_LMPARAM::operator DWORD() const
{
if (m_eType == xtpEditLMPT_DWORD)
{
return m_dwValue;
}
ASSERT(FALSE);
return 0;
}
XTP_EDIT_LMPARAM::operator double() const
{
if (m_eType == xtpEditLMPT_double)
{
return m_dblValue;
}
else if (m_eType == xtpEditLMPT_DWORD)
{
return m_dwValue;
}
ASSERT(FALSE);
return 0;
}
XTP_EDIT_LMPARAM::operator void*() const
{
return GetPtr();
}
void* XTP_EDIT_LMPARAM::GetPtr() const
{
if (m_eType == xtpEditLMPT_Ptr)
{
return m_Ptr ? m_Ptr->GetPtr() : NULL;
}
return NULL;
}
BOOL XTP_EDIT_LMPARAM::IsValid() const
{
return m_eType == xtpEditLMPT_DWORD ||
m_eType == xtpEditLMPT_double ||
m_eType == xtpEditLMPT_Ptr;
}
void XTP_EDIT_LMPARAM::Clear()
{
m_eType = xtpEditLMPT_Unknown;
m_dwValue = 0;
m_dblValue = 0;
m_Ptr = NULL;
}
////////////////////////////////////////////////////////////////////////////
//struct XTP_EDIT_LMDATA
XTP_EDIT_LMDATA::~XTP_EDIT_LMDATA()
{
}
XTP_EDIT_LMDATA::XTP_EDIT_LMDATA()
{
m_nRow = 0;
}
XTP_EDIT_LMDATA::XTP_EDIT_LMDATA(const XTP_EDIT_LMDATA& rSrc)
{
*this = rSrc;
}
const XTP_EDIT_LMDATA& XTP_EDIT_LMDATA::operator=(const XTP_EDIT_LMDATA& rSrc)
{
m_nRow = rSrc.m_nRow;
m_Param = rSrc.m_Param;
return *this;
}
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
CXTPSyntaxEditLineMarksManager::CLineMarksList::~CLineMarksList()
{
RemoveAll();
}
int CXTPSyntaxEditLineMarksManager::CLineMarksList::FindIndex(const int nKey) const
{
const int nCount = (int)m_array.GetSize();
// binary search
int nLeftIndex = 0, nRightIndex = nCount - 1;
while (nRightIndex >= nLeftIndex)
{
XTP_EDIT_LMDATA* pLeftData = m_array.GetAt(nLeftIndex);
XTP_EDIT_LMDATA* pRightData = m_array.GetAt(nRightIndex);
if (!pLeftData || !pRightData)
break;
if (nKey == pLeftData->m_nRow)
return nLeftIndex;
if (nKey == pRightData->m_nRow)
return nRightIndex;
int nMediumIndex = (nRightIndex + nLeftIndex) / 2;
if (nMediumIndex == nRightIndex || nMediumIndex == nLeftIndex)
break;
XTP_EDIT_LMDATA* pMediumData = m_array.GetAt(nMediumIndex);
if (!pMediumData)
break;
if (nKey == pMediumData->m_nRow)
{
return nMediumIndex;
}
else if (nKey > pMediumData->m_nRow)
{
nLeftIndex = nMediumIndex;
}
else // if (nKey < pMediumData->m_nRow)
{
nRightIndex = nMediumIndex;
}
}
return -1;
}
int CXTPSyntaxEditLineMarksManager::CLineMarksList::FindLowerIndex(const int nKey) const
{
const int nCount = (int)m_array.GetSize();
if (nCount == 0)
return -1;
// binary search
int nLeftIndex = 0, nRightIndex = nCount - 1;
while (nRightIndex >= nLeftIndex)
{
int nMediumIndex = (nRightIndex + nLeftIndex) / 2;
XTP_EDIT_LMDATA* pMediumData = m_array.GetAt(nMediumIndex);
if (!pMediumData)
break;
XTP_EDIT_LMDATA* pMediumNextData = nMediumIndex + 1 < nCount ?
m_array.GetAt(nMediumIndex + 1) : NULL;
if (nKey >= pMediumData->m_nRow &&
(!pMediumNextData || (pMediumNextData && nKey < pMediumNextData->m_nRow)))
{
return nMediumIndex;
}
else if (nKey > pMediumData->m_nRow)
{
if (nLeftIndex < nMediumIndex)
nLeftIndex = nMediumIndex;
else if (nLeftIndex + 1 == nRightIndex)
nLeftIndex = nRightIndex;
else
break;
}
else
{
if (nRightIndex > nMediumIndex)
nRightIndex = nMediumIndex;
else if (nRightIndex - 1 == nLeftIndex)
nRightIndex = nLeftIndex;
else
break;
}
}
return -1;
}
int CXTPSyntaxEditLineMarksManager::CLineMarksList::FindUpperIndex(const int nKey) const
{
const int nCount = (int)m_array.GetSize();
if (nCount == 0)
return -1;
// binary search
int nLeftIndex = 0, nRightIndex = nCount - 1;
while (nRightIndex >= nLeftIndex)
{
int nMediumIndex = (nRightIndex + nLeftIndex) / 2;
XTP_EDIT_LMDATA* pMediumData = m_array.GetAt(nMediumIndex);
if (!pMediumData)
break;
XTP_EDIT_LMDATA* pMediumPrevData = nMediumIndex > 0 ?
m_array.GetAt(nMediumIndex - 1) : NULL;
if (nKey <= pMediumData->m_nRow &&
(!pMediumPrevData || (pMediumPrevData && nKey > pMediumPrevData->m_nRow)))
{
return nMediumIndex;
}
else if (nKey > pMediumData->m_nRow)
{
if (nLeftIndex < nMediumIndex)
nLeftIndex = nMediumIndex;
else if (nLeftIndex + 1 == nRightIndex)
nLeftIndex = nRightIndex;
else
break;
}
else
{
if (nRightIndex > nMediumIndex)
nRightIndex = nMediumIndex;
else if (nRightIndex - 1 == nLeftIndex)
nRightIndex = nLeftIndex;
else
break;
}
}
return -1;
}
void CXTPSyntaxEditLineMarksManager::CLineMarksList::Add(const XTP_EDIT_LMDATA& lmData)
{
int nIndex = FindUpperIndex(lmData.m_nRow);
if (nIndex < 0)
{
m_array.Add(new XTP_EDIT_LMDATA(lmData));
}
else
{
XTP_EDIT_LMDATA* pOldData = m_array.GetAt(nIndex);
if (pOldData->m_nRow == lmData.m_nRow)
{
// just copy data because the key already exists
*pOldData = lmData;
}
else
{
// insert new element for the new key
m_array.InsertAt(nIndex, new XTP_EDIT_LMDATA(lmData));
}
}
}
void CXTPSyntaxEditLineMarksManager::CLineMarksList::Remove(const int nKey)
{
int nIndex = FindIndex(nKey);
if (nIndex >= 0)
{
XTP_EDIT_LMDATA* pData = m_array.GetAt(nIndex);
if (pData)
delete pData;
m_array.RemoveAt(nIndex);
}
}
POSITION CXTPSyntaxEditLineMarksManager::CLineMarksList::FindAt(int nKey) const
{
// find a record with the specified key
INT_PTR nIndex = FindIndex(nKey);
return nIndex >= 0 ? (POSITION)(nIndex + 1) : NULL;
}
POSITION CXTPSyntaxEditLineMarksManager::CLineMarksList::FindNext(int nKey) const
{
INT_PTR nIndex = FindUpperIndex(nKey);
if (nIndex >= 0)
{
return (POSITION)(nIndex + 1);
}
return NULL;
}
POSITION CXTPSyntaxEditLineMarksManager::CLineMarksList::FindPrev(int nKey) const
{
INT_PTR nIndex = FindLowerIndex(nKey);
if (nIndex >= 0)
{
return (POSITION)(nIndex + 1);
}
return NULL;
}
void CXTPSyntaxEditLineMarksManager::CLineMarksList::RefreshLineMarks(
int nRowFrom, int nRowTo, int nRefreshType)
{
int nDiff = abs(nRowTo - nRowFrom);
BOOL bDel = (nRefreshType & xtpEditLMRefresh_Delete);
BOOL bDel_only1 = (nRefreshType & xtpEditLMRefresh_Delete_only1);
BOOL bDel_only2 = (nRefreshType & xtpEditLMRefresh_Delete_only2);
BOOL bInsertAt0 = (nRefreshType & xtpEditLMRefresh_InsertAt0);
if (nRefreshType & xtpEditLMRefresh_Delete)
nDiff *= -1;
if (nRefreshType & (xtpEditLMRefresh_Delete_only1 | xtpEditLMRefresh_Delete_only2))
nDiff = 0;
int nRowU = max(nRowTo, nRowFrom);
int nRowL = min(nRowTo, nRowFrom);
const int nCount = (int)m_array.GetSize();
CXTPSyntaxEditLineMarkPointersArray newArray;
newArray.SetSize(0, m_array.GetSize());
int nPrevDataRow = -1;
for (int nIndex = 0; nIndex < nCount; nIndex++)
{
XTP_EDIT_LMDATA* pData = m_array.GetAt(nIndex);
if (!pData)
continue;
if (pData->m_nRow < nRowL ||
pData->m_nRow == nRowL && !bDel_only1 && !bInsertAt0)
{
// does not affect refresh
newArray.Add(pData);
nPrevDataRow = pData->m_nRow;
}
else if (bDel && pData->m_nRow < nRowU ||
bDel_only1 && pData->m_nRow == nRowL ||
bDel_only2 && pData->m_nRow == nRowU)
{
// delete line mark
delete pData;
}
else
{
// refresh position
pData->m_nRow += nDiff;
if (nPrevDataRow == pData->m_nRow)
{
// delete line mark
delete pData;
}
else
{
newArray.Add(pData);
nPrevDataRow = pData->m_nRow;
}
}
}
// update data in the old array
m_array.RemoveAll();
m_array.Append(newArray);
}
void CXTPSyntaxEditLineMarksManager::CLineMarksList::RemoveAll()
{
const int nCount = (int)m_array.GetSize();
for (int i = 0; i < nCount; i++)
{
XTP_EDIT_LMDATA* pData = m_array.GetAt(i);
if (pData)
delete pData;
}
m_array.RemoveAll();
}
int CXTPSyntaxEditLineMarksManager::CLineMarksList::GetCount() const
{
return (int)m_array.GetSize();
}
POSITION CXTPSyntaxEditLineMarksManager::CLineMarksList::GetFirstLineMark() const
{
return BEFORE_START_POSITION;
}
XTP_EDIT_LMDATA* CXTPSyntaxEditLineMarksManager::CLineMarksList::GetNextLineMark(POSITION& pos) const
{
// Rule: pos == element index + 1 (because 0=NULL and mean no more elements)
// check for the beginning of the list
if (pos == BEFORE_START_POSITION)
{
pos = (POSITION)1;
}
// get data corresponding to the position
XTP_EDIT_LMDATA* pData = (INT_PTR)pos > (INT_PTR)m_array.GetSize() ? NULL : m_array.GetAt((INT_PTR)pos - 1);
// increase position
pos = (POSITION)((INT_PTR)pos + 1);
// check for the end of the array
if ((INT_PTR)pos > (INT_PTR)m_array.GetSize() )
{
//pos = (POSITION)m_array.GetSize();
pos = NULL;
}
// return the data for the initial position
return pData;
}
XTP_EDIT_LMDATA* CXTPSyntaxEditLineMarksManager::CLineMarksList::GetLineMarkAt(const POSITION pos) const
{
// Rule: pos == element index + 1 (because 0=NULL and mean no more elements)
INT_PTR nIndex = (INT_PTR)pos - 1;
if (nIndex < 0 || nIndex >= (INT_PTR)m_array.GetSize())
{
return NULL;
}
return m_array.GetAt(nIndex);
}
/////////////////////////////////////////////////////////////////////////////
CXTPSyntaxEditLineMarksManager::CLineMarksListPtr
CXTPSyntaxEditLineMarksManager::CLineMarksListsMap::GetList(LPCTSTR szMarkType) const
{
CLineMarksListPtr ptrList;
if (!m_map.Lookup(szMarkType, ptrList))
{
return NULL;
}
return ptrList;
}
CXTPSyntaxEditLineMarksManager::CLineMarksListPtr
CXTPSyntaxEditLineMarksManager::CLineMarksListsMap::AddList(LPCTSTR szMarkType)
{
CLineMarksListPtr ptrList(new CLineMarksList());
m_map.SetAt(szMarkType, ptrList);
return ptrList;
}
void CXTPSyntaxEditLineMarksManager::CLineMarksListsMap::RefreshLineMarks(
int nRowFrom, int nRowTo, int nRefreshType)
{
POSITION pos = m_map.GetStartPosition();
CString strKey;
CLineMarksListPtr ptrList;
while (pos != NULL)
{
m_map.GetNextAssoc(pos, strKey, ptrList);
if (ptrList)
ptrList->RefreshLineMarks(nRowFrom, nRowTo, nRefreshType);
}
}
/////////////////////////////////////////////////////////////////////////////
CXTPSyntaxEditLineMarksManager::CXTPSyntaxEditLineMarksManager()
{
}
CXTPSyntaxEditLineMarksManager::~CXTPSyntaxEditLineMarksManager()
{
}
void CXTPSyntaxEditLineMarksManager::AddRemoveLineMark(int nRow, const XTP_EDIT_LINEMARKTYPE lmType,
XTP_EDIT_LMPARAM* pParam)
{
if (HasRowMark(nRow, lmType))
{
DeleteLineMark(nRow, lmType);
}
else
{
SetLineMark(nRow, lmType, pParam);
}
}
void CXTPSyntaxEditLineMarksManager::SetLineMark(int nRow, const XTP_EDIT_LINEMARKTYPE lmType,
XTP_EDIT_LMPARAM* pParam)
{
// prepare data structure
XTP_EDIT_LMDATA lmData;
lmData.m_nRow = nRow;
if (pParam)
{
lmData.m_Param = *pParam;
}
// get corresponding list
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
if (!ptrList)
{
// create new list
ptrList = m_mapLists.AddList(lmType);
if (!ptrList)
return; // error happened
}
// set value
ptrList->Add(lmData);
}
void CXTPSyntaxEditLineMarksManager::DeleteLineMark(int nRow, const XTP_EDIT_LINEMARKTYPE lmType)
{
// get corresponding list
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
if (ptrList)
{
// delete line mark
ptrList->Remove(nRow);
}
}
BOOL CXTPSyntaxEditLineMarksManager::HasRowMark(int nRow, const XTP_EDIT_LINEMARKTYPE& lmType,
XTP_EDIT_LMPARAM* pParam) const
{
// get corresponding list
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
if (ptrList)
{
// Find line data
POSITION pos = ptrList->FindAt(nRow);
XTP_EDIT_LMDATA* pData = ptrList->GetLineMarkAt(pos);
if (pData)
{
ASSERT(pData->m_nRow == nRow);
if (pParam)
{
*pParam = pData->m_Param;
}
return TRUE;
}
}
return FALSE;
}
POSITION CXTPSyntaxEditLineMarksManager::GetLastLineMark(const XTP_EDIT_LINEMARKTYPE lmType) const
{
int nRow = INT_MAX - 1;
return FindPrevLineMark(nRow, lmType);
}
POSITION CXTPSyntaxEditLineMarksManager::FindPrevLineMark(int& nRow, const XTP_EDIT_LINEMARKTYPE lmType) const
{
int nPrevRow = -1;
POSITION posPrev = NULL;
// get corresponding list
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
if (ptrList)
{
// Find line data
posPrev = ptrList->FindPrev(nRow);
XTP_EDIT_LMDATA* pData = ptrList->GetLineMarkAt(posPrev);
if (pData)
{
nPrevRow = pData->m_nRow;
}
}
nRow = nPrevRow;
return posPrev;
}
POSITION CXTPSyntaxEditLineMarksManager::FindNextLineMark(int& nRow, const XTP_EDIT_LINEMARKTYPE lmType) const
{
int nNextRow = INT_MAX;
POSITION posNext = NULL;
// get corresponding list
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
if (ptrList)
{
// Find line data
posNext = ptrList->FindNext(nRow);
XTP_EDIT_LMDATA* pData = ptrList->GetLineMarkAt(posNext);
if (pData)
{
nNextRow = pData->m_nRow;
}
}
if (nNextRow == INT_MAX)
{
nNextRow = -1;
}
nRow = nNextRow;
return posNext;
}
POSITION CXTPSyntaxEditLineMarksManager::GetFirstLineMark(const XTP_EDIT_LINEMARKTYPE lmType) const
{
// get corresponding list
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
return ptrList ? ptrList->GetFirstLineMark() : NULL;
}
XTP_EDIT_LMDATA* CXTPSyntaxEditLineMarksManager::GetNextLineMark(POSITION& pos, const XTP_EDIT_LINEMARKTYPE lmType) const
{
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
return ptrList ? ptrList->GetNextLineMark(pos) : NULL;
}
void CXTPSyntaxEditLineMarksManager::RefreshLineMarks(int nRowFrom, int nRowTo, int nRefreshType)
{
m_mapLists.RefreshLineMarks(nRowFrom, nRowTo, nRefreshType);
}
void CXTPSyntaxEditLineMarksManager::RemoveAll(const XTP_EDIT_LINEMARKTYPE lmType)
{
// get corresponding list
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
if (ptrList)
ptrList->RemoveAll();
}
XTP_EDIT_LMDATA* CXTPSyntaxEditLineMarksManager::GetLineMarkAt(const POSITION pos, const XTP_EDIT_LINEMARKTYPE lmType) const
{
// get corresponding list
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
return ptrList ? ptrList->GetLineMarkAt(pos) : NULL;
}
int CXTPSyntaxEditLineMarksManager::GetCount(const XTP_EDIT_LINEMARKTYPE lmType) const
{
// get corresponding list
CLineMarksListPtr ptrList = m_mapLists.GetList(lmType);
return ptrList ? ptrList->GetCount() : 0;
}