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.
976 lines
21 KiB
C++
976 lines
21 KiB
C++
// XTPSyntaxEditAutoCompleteWnd.cpp: implementation of the CXTPSyntaxEditAutoCompleteWnd 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"
|
|
#include "Resource.h"
|
|
|
|
// common includes
|
|
#include "Common/XTPDrawHelpers.h"
|
|
#include "Common/XTPSmartPtrInternalT.h"
|
|
#include "Common/XTPSystemHelpers.h"
|
|
#include "Common/XTPColorManager.h"
|
|
|
|
// syntax editor includes
|
|
#include "XTPSyntaxEditDefines.h"
|
|
#include "XTPSyntaxEditStruct.h"
|
|
#include "XTPSyntaxEditAutoCompleteWnd.h"
|
|
#include "XTPSyntaxEditCtrl.h"
|
|
#include "XTPSyntaxEditDrawTextProcessor.h"
|
|
|
|
#include <search.h>
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define XTP_SYNTAXEDIT_AUTOCOMPLETE_HEIGHT_MAX 160
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPSyntaxEditAutoCompleteWnd, CWnd)
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_WM_MOUSEWHEEL()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_CHAR()
|
|
ON_WM_VSCROLL()
|
|
ON_WM_SETCURSOR()
|
|
ON_WM_PAINT()
|
|
END_MESSAGE_MAP()
|
|
|
|
CXTPSyntaxEditAutoCompleteWnd::CXTPSyntaxEditAutoCompleteWnd()
|
|
{
|
|
RegisterWindowClass();
|
|
|
|
m_strSearch = _T("");
|
|
m_pParentWnd = NULL;
|
|
m_nLineHeight = 0;
|
|
m_nLines = 0;
|
|
m_nWndHeight = 0;
|
|
m_nWndWidth = 160;
|
|
m_nHighLightLine = -1;
|
|
m_nFirstDisplayedStr = 0;
|
|
m_nBordersHeight = 0;
|
|
m_bActive = FALSE;
|
|
m_bFixedBottom = FALSE;
|
|
|
|
m_strDelims = _T("");
|
|
VERIFY( m_ilACGlyphs.Create(XTP_IDB_EDIT_GLYPHS, 16, 16, RGB(255, 255, 255)) );
|
|
}
|
|
|
|
CXTPSyntaxEditAutoCompleteWnd::~CXTPSyntaxEditAutoCompleteWnd()
|
|
{
|
|
RemoveAll();
|
|
DestroyWindow();
|
|
}
|
|
|
|
BOOL CXTPSyntaxEditAutoCompleteWnd::RegisterWindowClass(HINSTANCE hInstance /*= NULL*/)
|
|
{
|
|
WNDCLASS wndcls;
|
|
if (hInstance == NULL) hInstance = AfxGetInstanceHandle();
|
|
|
|
if (!(::GetClassInfo(hInstance, XTP_EDIT_CLASSNAME_AUTOCOMPLETEWND, &wndcls)))
|
|
{
|
|
// otherwise we need to register a new class
|
|
wndcls.style = CS_SAVEBITS | CS_DBLCLKS;
|
|
wndcls.lpfnWndProc = ::DefWindowProc;
|
|
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
|
|
wndcls.hInstance = hInstance;
|
|
wndcls.hIcon = NULL;
|
|
wndcls.hCursor = ::LoadCursor(NULL, IDC_ARROW);
|
|
wndcls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wndcls.lpszMenuName = NULL;
|
|
wndcls.lpszClassName = XTP_EDIT_CLASSNAME_AUTOCOMPLETEWND;
|
|
|
|
if (!AfxRegisterClass(&wndcls))
|
|
{
|
|
AfxThrowResourceException();
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPSyntaxEditAutoCompleteWnd::Create(CWnd* pParentWnd)
|
|
{
|
|
if (!CWnd::CreateEx(WS_EX_TOOLWINDOW, XTP_EDIT_CLASSNAME_AUTOCOMPLETEWND, NULL,
|
|
WS_CHILD | WS_DLGFRAME | WS_VSCROLL | WS_DISABLED, CRect(0, 0, 160, 160),
|
|
GetDesktopWindow(), NULL))
|
|
{
|
|
TRACE0("Failed to create Auto Complete View.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
CXTPClientRect rcClient(this);
|
|
CXTPWindowRect rcWin(this);
|
|
m_nBordersHeight = (rcWin.Height()-rcClient.Height());
|
|
m_pParentWnd = DYNAMIC_DOWNCAST(CXTPSyntaxEditCtrl, pParentWnd);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::Show(CPoint pt, CString strSearch)
|
|
{
|
|
if (Filter(strSearch) < 1)
|
|
return;
|
|
|
|
m_nFirstDisplayedStr = 0;
|
|
int nSearch = Search(strSearch);
|
|
m_nHighLightLine = nSearch;
|
|
|
|
//<<>>Forum Proposal
|
|
m_bHighLight = (m_nHighLightLine >= 0);
|
|
//<<>>
|
|
ScrollTo(nSearch);
|
|
|
|
RefreshMetrics();
|
|
|
|
AdjusLayout();
|
|
|
|
CRect rcWnd(pt.x - 21, pt.y, pt.x - 21 + m_nWndWidth, pt.y + m_nWndHeight);
|
|
|
|
if (GetParent())
|
|
GetParent()->ClientToScreen(&rcWnd);
|
|
|
|
_AdjustWndRect(rcWnd);
|
|
|
|
if (GetParent())
|
|
GetParent()->ScreenToClient(&rcWnd);
|
|
|
|
//SetWindowPos(NULL, pt.x - 21, pt.y, m_nWndWidth, m_nWndHeight, SWP_SHOWWINDOW);
|
|
SetWindowPos(NULL, rcWnd.left, rcWnd.top, rcWnd.Width(), rcWnd.Height(), SWP_SHOWWINDOW);
|
|
|
|
BOOL bVScrollEnabled = AdjusLayout(rcWnd.Height());
|
|
|
|
ShowScrollBar(SB_VERT, bVScrollEnabled);
|
|
|
|
RedrawWindow();
|
|
|
|
EnableWindow(TRUE);
|
|
SetFocus();
|
|
|
|
m_bActive = TRUE;
|
|
int nSearchLen = strSearch.GetLength();
|
|
m_bFilteredMode = nSearchLen > 0;
|
|
m_nStartReplacePos = m_pParentWnd->GetCurCol() - nSearchLen;
|
|
m_nEndReplacePos = m_nStartReplacePos + nSearchLen;
|
|
m_strSearch = strSearch;
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::_AdjustWndRect(CRect& rc)
|
|
{
|
|
CRect rcWorkArea = XTPMultiMonitor()->GetWorkArea(); //from cursor point
|
|
//CRect rcWorkArea = XTPMultiMonitor()->GetWorkArea(this);
|
|
m_bFixedBottom = rc.bottom > rcWorkArea.bottom;
|
|
|
|
if (m_bFixedBottom)
|
|
{
|
|
int nNewTop = rc.top - m_nWndHeight -
|
|
m_pParentWnd->GetDrawTextProcessor().GetRowHeight();
|
|
rc.top = max(rcWorkArea.top, nNewTop);
|
|
rc.bottom = min(rcWorkArea.bottom, rc.top + m_nWndHeight);
|
|
|
|
m_bFixedBottom = TRUE;
|
|
}
|
|
|
|
if (rc.right > rcWorkArea.right)
|
|
{
|
|
int nOffsetX = rc.right - rcWorkArea.right;
|
|
rc.left = max(rcWorkArea.left, rc.left - nOffsetX);
|
|
rc.right = rcWorkArea.right;
|
|
}
|
|
|
|
if (rc.left < rcWorkArea.left)
|
|
{
|
|
int nOffsetX = rcWorkArea.left - rc.left;
|
|
rc.right = rc.right + nOffsetX;
|
|
rc.left = rcWorkArea.left;
|
|
}
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::SetWndWidth(int nWidth)
|
|
{
|
|
m_nWndWidth = nWidth;
|
|
|
|
if (m_hWnd)
|
|
{
|
|
CXTPWindowRect rcWnd(this);
|
|
if (GetParent())
|
|
GetParent()->ScreenToClient(&rcWnd);
|
|
rcWnd.right = rcWnd.left + m_nWndWidth;
|
|
|
|
MoveWindow(&rcWnd);
|
|
|
|
AdjusLayout(rcWnd.Height());
|
|
|
|
RedrawWindow();
|
|
}
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::UpdateFilteredList()
|
|
{
|
|
int nIdx = Search(m_strSearch);
|
|
if (nIdx >=0)
|
|
{
|
|
Filter(m_strSearch);
|
|
|
|
m_nFirstDisplayedStr = 0;
|
|
nIdx = Search(m_strSearch);
|
|
|
|
m_nHighLightLine = nIdx;
|
|
|
|
AdjusLayout();
|
|
|
|
ScrollTo(nIdx);
|
|
|
|
CXTPWindowRect rcWnd(this);
|
|
CRect rcWorkArea = XTPMultiMonitor()->GetWorkArea(this);
|
|
|
|
if (m_bFixedBottom)
|
|
rcWnd.top = rcWnd.bottom - m_nWndHeight;
|
|
else
|
|
rcWnd.bottom = min(rcWorkArea.bottom, rcWnd.top + m_nWndHeight);
|
|
|
|
if (GetParent())
|
|
GetParent()->ScreenToClient(&rcWnd);
|
|
|
|
MoveWindow(&rcWnd);
|
|
|
|
AdjusLayout(rcWnd.Height());
|
|
|
|
RedrawWindow();
|
|
}
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
|
|
CWnd::OnLButtonDown(nFlags, point);
|
|
|
|
int nHitLine = HitTest(point);
|
|
if (nHitLine > -1)
|
|
{ m_bHighLight = TRUE;
|
|
m_nHighLightLine = m_nFirstDisplayedStr + nHitLine;
|
|
RedrawWindow();
|
|
}
|
|
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::OnRButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
CWnd::OnRButtonDown(nFlags, point);
|
|
int nHitLine = HitTest(point);
|
|
if (nHitLine > -1)
|
|
{
|
|
m_nHighLightLine = m_nFirstDisplayedStr + nHitLine;
|
|
RedrawWindow();
|
|
}
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
CWnd::OnLButtonDblClk(nFlags, point);
|
|
m_bHighLight = TRUE;
|
|
ReturnSelected(FALSE);
|
|
Hide();
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
int nDataMax = (int)m_arrACDataFiltered.GetSize();
|
|
int nPage = m_nLines - 1;
|
|
int nLastDisp = m_nFirstDisplayedStr + nPage;
|
|
m_bHighLight = TRUE;
|
|
switch (nChar)
|
|
{
|
|
case VK_UP:
|
|
m_nHighLightLine -= nRepCnt;
|
|
|
|
if (m_nHighLightLine >= 0)
|
|
{
|
|
if (m_nFirstDisplayedStr > m_nHighLightLine && ScrollTo(m_nHighLightLine))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr, TRUE);
|
|
}
|
|
|
|
RedrawWindow();
|
|
}
|
|
else
|
|
{
|
|
m_nHighLightLine = 0;
|
|
}
|
|
|
|
break;
|
|
case VK_DOWN:
|
|
m_nHighLightLine += nRepCnt;
|
|
if (m_nHighLightLine < nDataMax)
|
|
{
|
|
int nL = m_nLines - 1;
|
|
nLastDisp = m_nFirstDisplayedStr + nL;
|
|
if (nLastDisp < m_nHighLightLine)
|
|
{
|
|
if (ScrollTo(m_nHighLightLine - nL))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr, TRUE);
|
|
}
|
|
}
|
|
|
|
RedrawWindow();
|
|
}
|
|
else
|
|
{
|
|
m_nHighLightLine = nDataMax - 1;
|
|
}
|
|
break;
|
|
case VK_PRIOR:
|
|
if (m_nFirstDisplayedStr < m_nHighLightLine)
|
|
{
|
|
m_nHighLightLine = m_nFirstDisplayedStr;
|
|
}
|
|
else
|
|
{
|
|
if (m_nHighLightLine > 0)
|
|
m_nHighLightLine = max(0, m_nHighLightLine - m_nLines + 1);
|
|
else
|
|
m_nHighLightLine -= m_nLines + 1;
|
|
}
|
|
|
|
if (m_nHighLightLine >= 0)
|
|
{
|
|
if (m_nFirstDisplayedStr > m_nHighLightLine && ScrollTo(m_nHighLightLine))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr, TRUE);
|
|
}
|
|
|
|
RedrawWindow();
|
|
}
|
|
else
|
|
{
|
|
m_nHighLightLine = 0;
|
|
}
|
|
break;
|
|
case VK_NEXT:
|
|
|
|
if (m_nFirstDisplayedStr + nPage > m_nHighLightLine)
|
|
{
|
|
m_nHighLightLine = m_nFirstDisplayedStr + nPage;
|
|
}
|
|
else
|
|
{
|
|
if (m_nHighLightLine < nDataMax)
|
|
m_nHighLightLine = min(nDataMax - 1, m_nHighLightLine + nPage);
|
|
else
|
|
m_nHighLightLine += nPage;
|
|
}
|
|
|
|
if (m_nHighLightLine < nDataMax)
|
|
{
|
|
if (nLastDisp < m_nHighLightLine)
|
|
{
|
|
if (ScrollTo(m_nHighLightLine - nPage))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr, TRUE);
|
|
}
|
|
}
|
|
|
|
RedrawWindow();
|
|
}
|
|
else
|
|
{
|
|
m_nHighLightLine = nDataMax - 1;
|
|
}
|
|
|
|
break;
|
|
case VK_END:
|
|
if (m_nHighLightLine != nDataMax - 1 && ScrollTo(nDataMax - m_nLines))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr, TRUE);
|
|
m_nHighLightLine = nDataMax - 1;
|
|
RedrawWindow();
|
|
}
|
|
break;
|
|
case VK_HOME:
|
|
if (m_nHighLightLine != 0 && ScrollTo(0))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr, TRUE);
|
|
m_nHighLightLine = 0;
|
|
RedrawWindow();
|
|
}
|
|
break;
|
|
case VK_BACK:
|
|
|
|
m_nEndReplacePos--;
|
|
if (m_strSearch.GetLength() > 0)
|
|
m_strSearch = m_strSearch.Left(m_strSearch.GetLength() - 1);
|
|
|
|
if (m_nStartReplacePos >= m_nEndReplacePos)
|
|
{
|
|
Hide();
|
|
m_pParentWnd->SendMessage(WM_LBUTTONUP, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
UpdateFilteredList();
|
|
}
|
|
break;
|
|
case VK_LEFT :
|
|
case VK_RIGHT :
|
|
case VK_MENU :
|
|
case VK_CONTROL:
|
|
case VK_ESCAPE:
|
|
Hide();
|
|
break;
|
|
|
|
case VK_RETURN:
|
|
case VK_SPACE:
|
|
ReturnSelected(FALSE);
|
|
Hide();
|
|
break;
|
|
|
|
}
|
|
|
|
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (IsCloseTag((TCHAR)nChar))
|
|
{
|
|
ReturnSelected(FALSE);
|
|
Hide();
|
|
}
|
|
|
|
if (isalnum((TCHAR)nChar) || (TCHAR)nChar == _T('_')) //<<>>
|
|
{
|
|
m_nEndReplacePos++;
|
|
m_strSearch += (TCHAR)nChar;
|
|
|
|
UpdateFilteredList();
|
|
|
|
int nFound = Search(m_strSearch);
|
|
if (nFound >= 0)
|
|
{
|
|
m_nHighLightLine = nFound;
|
|
m_bHighLight = TRUE;
|
|
if (m_nFirstDisplayedStr > m_nHighLightLine)
|
|
{
|
|
if (ScrollTo(m_nHighLightLine))
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr, TRUE);
|
|
}
|
|
if (m_nFirstDisplayedStr + m_nLines <= m_nHighLightLine)
|
|
{
|
|
if (ScrollTo(m_nHighLightLine - m_nLines + 1))
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr, TRUE);
|
|
}
|
|
RedrawWindow();
|
|
CString sTxt = m_arrACDataFiltered.GetAt(m_nHighLightLine)->m_strText;
|
|
if (m_bFilteredMode && sTxt.CompareNoCase(m_strSearch) == 0)
|
|
{
|
|
int nCnt = (int) m_arrACDataFiltered.GetSize();
|
|
if (nCnt == 1)
|
|
{
|
|
ReturnSelected(TRUE);
|
|
Hide();
|
|
}
|
|
}
|
|
}
|
|
else if (m_bFilteredMode)
|
|
{
|
|
Hide();
|
|
}
|
|
else
|
|
{
|
|
m_bHighLight = FALSE;
|
|
RedrawWindow();
|
|
}
|
|
}
|
|
|
|
CWnd::OnChar(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
|
{
|
|
UNREFERENCED_PARAMETER(nPos);
|
|
UNREFERENCED_PARAMETER(pScrollBar);
|
|
|
|
SCROLLINFO info;
|
|
GetScrollInfo(SB_VERT, &info);
|
|
|
|
switch (nSBCode) {
|
|
case SB_LINEDOWN:
|
|
if (ScrollTo(m_nFirstDisplayedStr + 1))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr);
|
|
RedrawWindow();
|
|
}
|
|
|
|
break;
|
|
case SB_LINEUP:
|
|
if (ScrollTo(m_nFirstDisplayedStr - 1))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr);
|
|
RedrawWindow();
|
|
}
|
|
|
|
break; case SB_PAGEDOWN:
|
|
if (ScrollTo(m_nFirstDisplayedStr + m_nLines - 1))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr);
|
|
RedrawWindow();
|
|
}
|
|
break;
|
|
case SB_PAGEUP:
|
|
if (ScrollTo(m_nFirstDisplayedStr - m_nLines + 1))
|
|
{
|
|
SetScrollPos(SB_VERT, m_nFirstDisplayedStr);
|
|
RedrawWindow();
|
|
}
|
|
break;
|
|
case SB_TOP:
|
|
SetScrollPos(SB_VERT, info.nMin);
|
|
RedrawWindow();
|
|
break;
|
|
case SB_BOTTOM:
|
|
SetScrollPos(SB_VERT, info.nMax);
|
|
RedrawWindow();
|
|
break;
|
|
case SB_THUMBTRACK:
|
|
{
|
|
SCROLLINFO si;
|
|
ZeroMemory(&si, sizeof(SCROLLINFO));
|
|
si.cbSize = sizeof(SCROLLINFO);
|
|
si.fMask = SIF_TRACKPOS;
|
|
|
|
if (GetScrollInfo(SB_VERT, &si))
|
|
{
|
|
if (si.nTrackPos != m_nFirstDisplayedStr && ScrollTo(si.nTrackPos))
|
|
{
|
|
SetScrollPos(SB_VERT, si.nTrackPos);
|
|
RedrawWindow();
|
|
}
|
|
|
|
}
|
|
}
|
|
break;
|
|
case SB_ENDSCROLL:
|
|
return;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
BOOL CXTPSyntaxEditAutoCompleteWnd::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
|
|
{
|
|
int nCount = labs(zDelta) / WHEEL_DELTA;
|
|
for (int i = 0; i < nCount; i++)
|
|
{
|
|
SendMessage(WM_VSCROLL, (WPARAM)(zDelta > 0 ? SB_LINEUP : SB_LINEDOWN));
|
|
}
|
|
|
|
return CWnd::OnMouseWheel(nFlags, zDelta, pt);
|
|
}
|
|
|
|
BOOL CXTPSyntaxEditAutoCompleteWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
{
|
|
UNREFERENCED_PARAMETER(message);
|
|
UNREFERENCED_PARAMETER(nHitTest);
|
|
UNREFERENCED_PARAMETER(pWnd);
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPSyntaxEditAutoCompleteWnd::AdjusLayout(int nHeightMax)
|
|
{
|
|
|
|
CWindowDC dc(NULL);
|
|
CXTPFontDC fontDC(&dc, &m_fontBasic);
|
|
|
|
int nDataLines = (int)m_arrACDataFiltered.GetSize();
|
|
m_nLineHeight = dc.GetTextExtent(_T("A"), 1).cy + 6;
|
|
|
|
if (nHeightMax <= 0)
|
|
nHeightMax = XTP_SYNTAXEDIT_AUTOCOMPLETE_HEIGHT_MAX;
|
|
|
|
if (nDataLines * m_nLineHeight < nHeightMax)
|
|
{
|
|
m_nLines = nDataLines;
|
|
}
|
|
else
|
|
{
|
|
m_nLines = (int) nHeightMax / m_nLineHeight;
|
|
}
|
|
|
|
BOOL bVScrollEnabled = nDataLines > m_nLines;
|
|
|
|
ShowScrollBar(SB_VERT, bVScrollEnabled);
|
|
EnableScrollBarCtrl(SB_VERT, bVScrollEnabled);
|
|
|
|
//--------------------------------------------------
|
|
m_nWndHeight = m_nLines * m_nLineHeight + m_nBordersHeight;
|
|
|
|
CXTPClientRect rcClient(this);
|
|
|
|
CRect rc(0, 0, rcClient.Width(), m_nLineHeight);
|
|
m_arrGrid.RemoveAll();
|
|
|
|
for (int nLine = 0; nLine < m_nLines; nLine++)
|
|
{
|
|
m_arrGrid.Add(rc);
|
|
rc.OffsetRect(0, m_nLineHeight);
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
if (bVScrollEnabled)
|
|
{
|
|
SCROLLINFO scrollInfo;
|
|
|
|
scrollInfo.cbSize = sizeof(SCROLLINFO);
|
|
scrollInfo.fMask = SIF_ALL;
|
|
scrollInfo.nMin = 0;
|
|
scrollInfo.nMax = max(0, nDataLines-1);
|
|
scrollInfo.nPage = m_nLines;
|
|
scrollInfo.nPos = m_nFirstDisplayedStr;
|
|
|
|
SetScrollInfo(SB_VERT, &scrollInfo, FALSE);
|
|
}
|
|
|
|
return bVScrollEnabled;
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::OnPaint()
|
|
{
|
|
CPaintDC dc(this);
|
|
CXTPFontDC fontDC(&dc, &m_fontBasic);
|
|
|
|
CRect rc;
|
|
CRect rcText;
|
|
CString str;
|
|
|
|
int nData = 0;
|
|
int nHighLightedLine = m_nHighLightLine - m_nFirstDisplayedStr;
|
|
|
|
for (int nLine = 0; nLine < m_nLines; nLine++)
|
|
{
|
|
rc.CopyRect(m_arrGrid.GetAt(nLine));
|
|
|
|
int nIcon = min(m_arrACDataFiltered.GetAt(nData)->m_nIcon, m_ilACGlyphs.GetImageCount() - 1);
|
|
m_ilACGlyphs.Draw(&dc, nIcon, CPoint(rc.left, rc.top), ILD_NORMAL);
|
|
rc.DeflateRect(19, 0, 0, 0);
|
|
|
|
if (nLine == nHighLightedLine && m_bHighLight)
|
|
{
|
|
dc.FillSolidRect(rc.left, rc.top, rc.Width(), rc.Height(), m_clrHighLight);
|
|
dc.SetTextColor(m_clrHighLightText);
|
|
}
|
|
else
|
|
{
|
|
dc.SetTextColor(m_clrWindowText);
|
|
dc.FillSolidRect(rc.left, rc.top, rc.Width(), rc.Height(), m_clrWindow);
|
|
}
|
|
|
|
rcText.CopyRect(rc);
|
|
rcText.DeflateRect(2, 3, 2, 3);
|
|
nData = m_nFirstDisplayedStr + nLine;
|
|
|
|
dc.TextOut(rcText.left, rcText.top, m_arrACDataFiltered.GetAt(nData)->m_strText);
|
|
|
|
if (nLine == nHighLightedLine)
|
|
{
|
|
dc.DrawFocusRect(rc);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::RefreshMetrics()
|
|
{
|
|
m_fontBasic.CreateStockObject(DEFAULT_GUI_FONT);
|
|
m_clrHighLight = GetSysColor(COLOR_HIGHLIGHT);
|
|
m_clrWindow = GetSysColor(COLOR_WINDOW);
|
|
m_clrWindowText = GetSysColor(COLOR_WINDOWTEXT);
|
|
m_clrHighLightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
|
|
}
|
|
|
|
int CXTPSyntaxEditAutoCompleteWnd::HitTest(CPoint ptTest) const
|
|
{
|
|
int nHitLine = -1;
|
|
for (int nLine = 0; nLine < m_nLines; nLine++)
|
|
{
|
|
if (m_arrGrid.GetAt(nLine).PtInRect(ptTest))
|
|
{
|
|
nHitLine = nLine;
|
|
}
|
|
}
|
|
|
|
return nHitLine;
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::SetList(CXTPSyntaxEditACDataArray& parrData)
|
|
{
|
|
RemoveAll();
|
|
m_arrACData.Copy(parrData);
|
|
Sort();
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::SetCloseTags(CString strCloseTags)
|
|
{
|
|
m_strCloseTags = strCloseTags;
|
|
}
|
|
|
|
BOOL CXTPSyntaxEditAutoCompleteWnd::IsCloseTag(CString strToTest)
|
|
{
|
|
BOOL bTagFound = FALSE;
|
|
if (strToTest == _T("~"))
|
|
return bTagFound;
|
|
|
|
m_strTmpCloseTag += strToTest;
|
|
int nTmpLen = m_strTmpCloseTag.GetLength();
|
|
int nFound = -1;
|
|
if ((nFound = m_strCloseTags.Find(m_strTmpCloseTag)) >=0)
|
|
{
|
|
if (nFound+nTmpLen == m_strCloseTags.GetLength())
|
|
{
|
|
bTagFound = TRUE;
|
|
}
|
|
else
|
|
{
|
|
TCHAR ch = m_strCloseTags.GetAt(nFound + nTmpLen);
|
|
if (ch == _T('~'))
|
|
{
|
|
bTagFound = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_strTmpCloseTag = _T("");
|
|
}
|
|
|
|
return bTagFound;
|
|
}
|
|
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::SetOpenTags(CString strOpenTags)
|
|
{
|
|
m_strOpenTags = strOpenTags;
|
|
}
|
|
|
|
BOOL CXTPSyntaxEditAutoCompleteWnd::IsOpenTag(CString strToTest)
|
|
{
|
|
|
|
BOOL bTagFound = FALSE;
|
|
if (strToTest == _T("~"))
|
|
return bTagFound;
|
|
|
|
m_strTmpOpenTag += strToTest;
|
|
int nTmpLen = m_strTmpOpenTag.GetLength();
|
|
int nFound = -1;
|
|
if ((nFound = m_strOpenTags.Find(m_strTmpOpenTag)) >=0 )
|
|
{
|
|
if (nFound + nTmpLen == m_strOpenTags.GetLength())
|
|
{
|
|
bTagFound = TRUE;
|
|
}
|
|
else
|
|
{
|
|
TCHAR ch = m_strOpenTags.GetAt(nFound + nTmpLen);
|
|
if (ch == _T('~'))
|
|
{
|
|
bTagFound = TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
m_strTmpOpenTag = _T("");
|
|
}
|
|
|
|
return bTagFound;
|
|
}
|
|
|
|
BOOL CXTPSyntaxEditAutoCompleteWnd::ScrollTo(int nNewLine)
|
|
{
|
|
BOOL bScrollRequestCompleted = FALSE;
|
|
|
|
if (nNewLine + m_nLines <= m_arrACDataFiltered.GetSize() && nNewLine >= 0)
|
|
{
|
|
bScrollRequestCompleted = TRUE;
|
|
m_nFirstDisplayedStr = nNewLine;
|
|
}
|
|
|
|
return bScrollRequestCompleted;
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::ReturnSelected(BOOL bAdjust)
|
|
{
|
|
if (m_nHighLightLine < 0 || !m_bHighLight)
|
|
return;
|
|
|
|
int nCurrentRow = m_pParentWnd->GetCurrentDocumentRow();
|
|
|
|
CString strRet = m_arrACDataFiltered.GetAt(m_nHighLightLine)->m_strText;
|
|
|
|
if (m_strTmpCloseTag.GetLength() > 0)
|
|
{
|
|
strRet += m_strTmpCloseTag;
|
|
m_strTmpCloseTag = _T("");
|
|
}
|
|
else if (bAdjust)
|
|
{
|
|
strRet = strRet.Left(strRet.GetLength() - 1);
|
|
m_nEndReplacePos = max(m_nStartReplacePos, m_nEndReplacePos - 1);
|
|
}
|
|
|
|
m_pParentWnd->Select(nCurrentRow, m_nStartReplacePos, nCurrentRow, m_nEndReplacePos, FALSE);
|
|
m_pParentWnd->ReplaceSel(strRet);
|
|
|
|
m_pParentWnd->SetCurCaretPos(m_pParentWnd->GetCurrentDocumentRow(), m_pParentWnd->m_nDispCol);
|
|
m_pParentWnd->SetDocModified();
|
|
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::Hide()
|
|
{
|
|
if (!m_bActive)
|
|
return;
|
|
|
|
m_bActive = FALSE;
|
|
EnableWindow(FALSE);
|
|
ShowWindow(SW_HIDE);
|
|
m_bFilteredMode = FALSE;
|
|
m_pParentWnd->PostMessage(WM_LBUTTONUP, 0, 0);
|
|
RedrawWindow();
|
|
}
|
|
|
|
int CXTPSyntaxEditAutoCompleteWnd::CompareACData(const XTP_EDIT_ACDATA** p1, const XTP_EDIT_ACDATA** p2)
|
|
{
|
|
const XTP_EDIT_ACDATA* pData1 = *p1;
|
|
const XTP_EDIT_ACDATA* pData2 = *p2;
|
|
return _tcsicmp((LPCTSTR)pData1->m_strText, (LPCTSTR)pData2->m_strText);
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::Sort()
|
|
{
|
|
int nCount = (int)m_arrACData.GetSize();
|
|
if (nCount > 1)
|
|
{
|
|
typedef int (_cdecl *GENERICCOMPAREFUNC)(const void *, const void*);
|
|
qsort(m_arrACData.GetData(), nCount, sizeof(XTP_EDIT_ACDATA*), (GENERICCOMPAREFUNC)CompareACData);
|
|
}
|
|
}
|
|
|
|
int CXTPSyntaxEditAutoCompleteWnd::CompareACDataToSearch(const XTP_EDIT_ACDATA** ppKey, const XTP_EDIT_ACDATA** ppElem)
|
|
{
|
|
int nKeyLength = (*ppKey)->m_strText.GetLength();
|
|
return (*ppElem)->m_strText.Left(nKeyLength).CompareNoCase((*ppKey)->m_strText);
|
|
}
|
|
|
|
int CXTPSyntaxEditAutoCompleteWnd::Search(CString strSearch)
|
|
{
|
|
int nFirstOccurrence = -1;
|
|
if (strSearch.GetLength() == 0)
|
|
return 0;
|
|
|
|
XTP_EDIT_ACDATA* key = new XTP_EDIT_ACDATA(0, strSearch);
|
|
|
|
XTP_EDIT_ACDATA** pFirst = &m_arrACDataFiltered[0];
|
|
UINT nNum = (UINT)m_arrACDataFiltered.GetSize();
|
|
typedef int (_cdecl *GENERICCOMPAREFUNC)(const void *, const void*);
|
|
|
|
XTP_EDIT_ACDATA** pRez = (XTP_EDIT_ACDATA**)_lfind(&key,
|
|
pFirst, &nNum, sizeof(XTP_EDIT_ACDATA*), (GENERICCOMPAREFUNC)CompareACDataToSearch);
|
|
|
|
delete key;
|
|
|
|
if (pRez)
|
|
{
|
|
nFirstOccurrence = (LONG)((LONG_PTR)pRez - (LONG_PTR)pFirst)/sizeof(XTP_EDIT_ACDATA*);
|
|
}
|
|
|
|
return nFirstOccurrence;
|
|
}
|
|
|
|
int CXTPSyntaxEditAutoCompleteWnd::Filter(CString strSearch)
|
|
{
|
|
int nFound = 0;
|
|
m_arrACDataFiltered.RemoveAll();
|
|
if (strSearch.GetLength() == 0)
|
|
{
|
|
m_arrACDataFiltered.Copy(m_arrACData);
|
|
return (int)m_arrACDataFiltered.GetSize();
|
|
}
|
|
|
|
|
|
|
|
if (!m_arrACData.GetSize())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
XTP_EDIT_ACDATA* key = new XTP_EDIT_ACDATA(0, strSearch);
|
|
XTP_EDIT_ACDATA** pFirst = &m_arrACData[0];
|
|
XTP_EDIT_ACDATA** pNext = NULL;
|
|
UINT nNum = (UINT)m_arrACData.GetSize();
|
|
typedef int (_cdecl *GENERICCOMPAREFUNC)(const void *, const void*);
|
|
while (nNum > 0)
|
|
{
|
|
pNext = (XTP_EDIT_ACDATA**)_lfind(&key,
|
|
pFirst, &nNum, sizeof(XTP_EDIT_ACDATA*), (GENERICCOMPAREFUNC)CompareACDataToSearch);
|
|
|
|
if (pNext)
|
|
{
|
|
nNum -= (LONG) ((LONG_PTR)pNext - (LONG_PTR)pFirst)/sizeof(XTP_EDIT_ACDATA*);
|
|
pFirst = pNext;
|
|
nNum --;
|
|
pFirst++;
|
|
m_arrACDataFiltered.Add(*pNext);
|
|
nFound++;
|
|
}
|
|
else
|
|
{
|
|
nNum --;
|
|
pFirst++;
|
|
}
|
|
}
|
|
|
|
delete key;
|
|
|
|
return nFound;
|
|
}
|
|
|
|
void CXTPSyntaxEditAutoCompleteWnd::RemoveAll()
|
|
{
|
|
int nDataLines = (int)m_arrACData.GetSize();
|
|
m_arrACDataFiltered.RemoveAll();
|
|
XTP_EDIT_ACDATA* pACData = NULL;
|
|
for (int nDataLine = 0; nDataLine < nDataLines; nDataLine++)
|
|
{
|
|
pACData = m_arrACData.GetAt(nDataLine); ASSERT(pACData);
|
|
delete pACData;
|
|
}
|
|
m_arrACData.RemoveAll();
|
|
}
|