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.

8678 lines
205 KiB
C++

// XTPSyntaxEditCtrl.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"
#include "Resource.h"
#include <imm.h>
#include <math.h>
// common includes
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPImageManager.h"
#include "Common/XTPNotifyConnection.h"
#include "Common/XTPSmartPtrInternalT.h"
#include "Common/XTPVC80Helpers.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPResourceManager.h"
// syntax editor includes
#include "XTPSyntaxEditDefines.h"
#include "XTPSyntaxEditStruct.h"
#include "XTPSyntaxEditDrawTextProcessor.h"
#include "XTPSyntaxEditSelection.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"
#include "XTPSyntaxEditToolTipCtrl.h"
#include "XTPSyntaxEditAutoCompleteWnd.h"
#include "XTPSyntaxEditCtrl.h"
#include "XTPSyntaxEditPaintManager.h"
using namespace XTPSyntaxEditLexAnalyser;
#define XTP_IDC_EDIT_DRAG_MOVE 0xE12D
#define XTP_IDC_EDIT_DRAG_COPY 0xE12E
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////////////////////////////////////////////////////////////
// Imm
class CXTPSyntaxEditCtrl::CImmWrapper
{
public:
CImmWrapper();
virtual ~CImmWrapper();
public:
BOOL ImmIsIME(HKL hKL = NULL);
XTP_HIMC ImmGetContext(HWND hWnd);
BOOL ImmReleaseContext(HWND hWnd, XTP_HIMC hIMC);
BOOL ImmSetCompositionWindow(XTP_HIMC hIMC, COMPOSITIONFORM* pCompForm);
BOOL ImmSetCompositionFont(XTP_HIMC hIMC, LOGFONT* plfFont);
public:
typedef BOOL (WINAPI *PFN_ImmIsIME)(HKL);
typedef XTP_HIMC (WINAPI *PFN_ImmGetContext)(HWND);
typedef BOOL (WINAPI *PFN_ImmReleaseContext)(HWND, XTP_HIMC);
typedef BOOL (WINAPI *PFN_ImmSetCompositionFont)(XTP_HIMC, LPLOGFONT); // A/W
typedef BOOL (WINAPI *PFN_ImmSetCompositionWindow)(XTP_HIMC, COMPOSITIONFORM*);
protected:
HMODULE m_hImmDll; // Handle to the imm32 dll.
PFN_ImmIsIME m_pfnImmIsIME;
PFN_ImmGetContext m_pfnImmGetContext;
PFN_ImmReleaseContext m_pfnImmReleaseContext;
PFN_ImmSetCompositionFont m_pfnImmSetCompositionFont;
PFN_ImmSetCompositionWindow m_pfnImmSetCompositionWindow;
};
/////////////////////////////////////////////////////////////////////////////
//class _XTP_EXT_CLASS CXTPImmWrapper
#ifdef _UNICODE
#define XTP_PROC_NAME_AW(procName) procName "W"
#else
#define XTP_PROC_NAME_AW(procName) procName "A"
#endif
#define XTP_IMM_FNCALL(fnName, errRetVal) \
if (!m_pfn##fnName) \
return errRetVal; \
return m_pfn##fnName
CXTPSyntaxEditCtrl::CImmWrapper::CImmWrapper()
{
m_hImmDll = ::LoadLibrary(_T("imm32.dll"));
if (m_hImmDll)
{
m_pfnImmIsIME = (PFN_ImmIsIME)GetProcAddress(m_hImmDll, "ImmIsIME");
m_pfnImmGetContext = (PFN_ImmGetContext)GetProcAddress(m_hImmDll, "ImmGetContext");
m_pfnImmReleaseContext = (PFN_ImmReleaseContext)GetProcAddress(m_hImmDll, "ImmReleaseContext");
m_pfnImmSetCompositionFont = (PFN_ImmSetCompositionFont)GetProcAddress(m_hImmDll, XTP_PROC_NAME_AW("ImmSetCompositionFont"));
m_pfnImmSetCompositionWindow = (PFN_ImmSetCompositionWindow)GetProcAddress(m_hImmDll, "ImmSetCompositionWindow");
}
else
{
m_pfnImmIsIME = NULL;
m_pfnImmGetContext = NULL;
m_pfnImmReleaseContext = NULL;
m_pfnImmSetCompositionFont = NULL;
m_pfnImmSetCompositionWindow = NULL;
}
}
CXTPSyntaxEditCtrl::CImmWrapper::~CImmWrapper()
{
if (m_hImmDll)
{
::FreeLibrary(m_hImmDll);
}
}
BOOL CXTPSyntaxEditCtrl::CImmWrapper::ImmIsIME(HKL hKL)
{
ASSERT(m_pfnImmIsIME);
if (!m_pfnImmIsIME)
return FALSE;
if (hKL == NULL)
hKL = ::GetKeyboardLayout(0);
return m_pfnImmIsIME(hKL);
}
XTP_HIMC CXTPSyntaxEditCtrl::CImmWrapper::ImmGetContext(HWND hWnd)
{
ASSERT(m_pfnImmGetContext);
XTP_IMM_FNCALL(ImmGetContext, NULL)(hWnd);
}
BOOL CXTPSyntaxEditCtrl::CImmWrapper::ImmReleaseContext(HWND hWnd, XTP_HIMC hIMC)
{
ASSERT(m_pfnImmReleaseContext);
XTP_IMM_FNCALL(ImmReleaseContext, FALSE)(hWnd, hIMC);
}
BOOL CXTPSyntaxEditCtrl::CImmWrapper::ImmSetCompositionWindow(XTP_HIMC hIMC, COMPOSITIONFORM* pCompForm)
{
ASSERT(m_pfnImmReleaseContext);
XTP_IMM_FNCALL(ImmSetCompositionWindow, FALSE)(hIMC, pCompForm);
}
BOOL CXTPSyntaxEditCtrl::CImmWrapper::ImmSetCompositionFont(XTP_HIMC hIMC, LOGFONT* plfFont)
{
ASSERT(m_pfnImmReleaseContext);
XTP_IMM_FNCALL(ImmSetCompositionFont, FALSE)(hIMC, plfFont);
}
/////////////////////////////////////////////////////////////////////////////
namespace XTPSyntaxEditLexAnalyser
{
CString DBG_TraceTB_StartEndCls(CXTPSyntaxEditLexTextBlock* pTB);
}
class CXTPSyntaxEditCtrl::CTextSearchCache
{
public:
CTextSearchCache();
void Update(int nCurrTopRow);
int nForTopRow;
CXTPSyntaxEditLexTextBlockPtr ptrTBStart;
};
//===========================================================================
// CXTPSyntaxEditCtrl::CScreenSearchBlock
//===========================================================================
class CXTPSyntaxEditCtrl::CScreenSearchBlock
{
public:
CScreenSearchBlock();
virtual ~CScreenSearchBlock();
CScreenSearchBlock(const CScreenSearchBlock& rSrc);
int nRowStart;
int nRowEnd;
DWORD dwLastAccessTime;
CXTPSyntaxEditLexTextBlockPtr ptrTBFirst;
};
//===========================================================================
// CXTPSyntaxEditCtrl::CScreenSearchCache
//===========================================================================
class CXTPSyntaxEditCtrl::CScreenSearchCache : public CArray<CXTPSyntaxEditCtrl::CScreenSearchBlock, CXTPSyntaxEditCtrl::CScreenSearchBlock&>
{
typedef CArray<CXTPSyntaxEditCtrl::CScreenSearchBlock, CXTPSyntaxEditCtrl::CScreenSearchBlock&> Base;
public:
DWORD m_dwLastRemoveOldTime;
CScreenSearchCache();
virtual ~CScreenSearchCache();
void RemoveAll();
void RemoveAt(int nIndex);
void RemoveOld(int nTimeOut_sec);
};
const int MARGIN_LENGTH = 20;
const int NODES_WIDTH = 10;
const int TEXT_LEFT_OFFSET = 4;
const UINT TIMER_SELECTION_ID = 100;
const UINT TIMER_SELECTION_TIME = 50;
const UINT TIMER_REDRAW_WHEN_PARSE = 200;
const UINT TIMER_AUTOSCROLL_ID = 110;
const UINT TIMER_AUTOSCROLL_TIME = 120;
enum XTPSyntaxEditFlags
{
xtpEditRedraw = 0x0001,
xtpEditForceRedraw = 0x0002,
xtpEditTextAsBlock = 0x0004,
xtpEditDispCol = 0x0008,
};
//////////////////////////////////////////////////////////////////////////
// CXTPSyntaxEditOptions
CXTPSyntaxEditOptions::CXTPSyntaxEditOptions()
: m_bSyntaxColor(TRUE)
, m_bAutoIndent(TRUE)
, m_bSelMargin(TRUE)
, m_bLineNumbers(TRUE)
, m_bWideCaret(TRUE)
, m_bTabWithSpace(FALSE)
, m_bDrawNodes(TRUE)
, m_bEnableWhiteSpace(FALSE)
{
m_bReadOnly = FALSE;
m_bVirtualSpace = FALSE;
m_bHideCaret = FALSE;
m_bViewOnly = FALSE;
m_bEnableEditAccelerators = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CXTPSyntaxEditCtrl
CXTPSyntaxEditCtrl::CXTPSyntaxEditCtrl()
: m_bVertScrollBar(TRUE)
, m_bHorzScrollBar(TRUE)
, m_bDragging(FALSE)
, m_bDroppable(FALSE)
, m_bTokensLoaded(FALSE)
, m_bIsScrollingEndRow(FALSE)
, m_bRightButtonDrag(FALSE)
, m_bIsSmartIndent(TRUE)
, m_bEnableOleDrag(FALSE)
, m_bCaseSensitive(TRUE)
, m_bScrolling(FALSE)
, m_bFocused(FALSE)
, m_bIsActive(FALSE)
, m_nTopCalculatedRow(-1)
, m_nBottomCalculatedRow(-1)
, m_nTopRow(1)
, m_nCurrentCol(1)
, m_nCurrentDocumentRow(1)
, m_nDispCol(1)
, m_nAutoIndentCol(0)
, m_nMarginLength(MARGIN_LENGTH)
, m_nLineNumLength(0)
, m_nNodesWidth(NODES_WIDTH)
, m_nEditbarLength(MARGIN_LENGTH + NODES_WIDTH)
, m_nCollapsedTextRowsCount(0)
, m_nWheelScroll(4)
, m_nAverageLineLen(XTP_EDIT_AVELINELEN)
, m_dwInsertPos(0)
, m_dwLastRedrawTime(0)
, m_ptPrevMouse(CPoint(0, 0))
, m_pBuffer(NULL)
, m_pParentWnd(NULL)
{
m_pOptions = new CXTPSyntaxEditOptions();
m_pSelection = new CXTPSyntaxEditSelection();
m_pDrawTextProcessor = new CXTPSyntaxEditDrawTextProcessor();
m_pSink = new CXTPNotifySink();
m_pSelection->m_pOwnerCtrl = this;
m_bCreateScrollbarOnParent = TRUE;
m_bAllowExpandCollapse = TRUE;
m_bActivateOnFocus = FALSE;
m_pImmWrapper = new CImmWrapper();
#ifndef _UNICODE
m_chPrevLeadByte = 0;
#endif
m_bIMEsupported = FALSE;
m_pPaintManeger = new CXTPSyntaxEditPaintManager();
GetRegValues();
RegisterWindowClass();
m_strDefaultCfgFilePath = GetModulePath() + XTP_EDIT_LEXPARSER_CFG_FILENAME;
m_nHScrollMaxWidth = 0;
m_bWndCreateInProgress = FALSE;
m_dwAutoScrollDirection = 0;
m_bDisableRedraw = FALSE;
m_pToolTip = new CXTPSyntaxEditToolTipCtrl();
m_pAutoComplete = new CXTPSyntaxEditAutoCompleteWnd();
m_fcCollapsable = new CTextSearchCache();
m_fcRowColors = new CTextSearchCache();
m_arOnScreenSchCache = new CScreenSearchCache();
m_pBuffer = new CXTPSyntaxEditBufferManager;
m_bUseMonitor = TRUE;
m_bConfigFileMode = TRUE;
m_sCustomTitle.Empty();
}
CXTPSyntaxEditCtrl::~CXTPSyntaxEditCtrl()
{
if (m_pBuffer && m_pBuffer->GetLexParser())
m_pBuffer->GetLexParser()->CloseParseThread();
m_pSink->UnadviseAll();
m_arOnScreenSchCache->RemoveAll();
CMDTARGET_RELEASE(m_pBuffer);
DestroyWindow();
CMDTARGET_RELEASE(m_pPaintManeger);
SAFE_DELETE(m_pToolTip);
SAFE_DELETE(m_pAutoComplete);
SAFE_DELETE(m_fcCollapsable);
SAFE_DELETE(m_fcRowColors);
SAFE_DELETE(m_arOnScreenSchCache);
SAFE_DELETE(m_pImmWrapper);
SAFE_DELETE(m_pSelection);
SAFE_DELETE(m_pDrawTextProcessor);
CMDTARGET_RELEASE(m_pOptions);
m_pSink->Delete();
}
void CXTPSyntaxEditCtrl::OnFinalRelease()
{
CWnd::OnFinalRelease();
}
IMPLEMENT_DYNAMIC(CXTPSyntaxEditCtrl, CWnd)
BEGIN_MESSAGE_MAP(CXTPSyntaxEditCtrl, CWnd)
//{{AFX_MSG_MAP(CXTPSyntaxEditCtrl)
ON_WM_PAINT()
ON_WM_SETCURSOR()
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_KEYDOWN()
ON_WM_SYSKEYDOWN()
ON_WM_CHAR()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_SETFOCUS()
ON_WM_NCACTIVATE()
ON_WM_MOUSEACTIVATE()
ON_WM_KEYUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_ERASEBKGND()
ON_WM_CONTEXTMENU()
ON_WM_TIMER()
ON_WM_KILLFOCUS()
ON_WM_SHOWWINDOW()
ON_WM_ACTIVATE()
ON_WM_MOUSEWHEEL()
ON_WM_GETDLGCODE()
ON_WM_DESTROY()
ON_COMMAND(XTP_IDC_EDIT_DRAG_COPY, OnDragCopy)
ON_COMMAND(XTP_IDC_EDIT_DRAG_MOVE, OnDragMove)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_SETTEXT, OnSetText)
ON_MESSAGE(WM_GETTEXT, OnGetText)
ON_MESSAGE(WM_GETTEXTLENGTH, OnGetTextLen)
ON_MESSAGE(WM_GETFONT, OnGetFont)
ON_MESSAGE(WM_SETFONT, OnSetFont)
ON_MESSAGE(WM_INPUTLANGCHANGE, OnInputLanguage)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXTPSyntaxEditCtrl message handlers
BOOL CXTPSyntaxEditCtrl::GetRegValues()
{
CWinApp* pWinApp = AfxGetApp();
if (pWinApp != NULL)
{
m_bVertScrollBar = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_VSCROLLBAR, m_bVertScrollBar);
m_bHorzScrollBar = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_HSCROLLBAR, m_bHorzScrollBar);
m_pOptions->m_bSyntaxColor = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_SYNTAXCOLOR, m_pOptions->m_bSyntaxColor);
m_pOptions->m_bAutoIndent = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_AUTOINDENT, m_pOptions->m_bAutoIndent);
m_pOptions->m_bSelMargin = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_SELMARGIN, m_pOptions->m_bSelMargin);
m_pOptions->m_bLineNumbers = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_LINENUMBERS, m_pOptions->m_bLineNumbers);
m_pOptions->m_bWideCaret = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_WIDECARET, m_pOptions->m_bWideCaret);
m_pOptions->m_bTabWithSpace = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_TABWITHSPACE, m_pOptions->m_bTabWithSpace);
m_pOptions->m_bVirtualSpace = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_VIRTUALSPACE, m_pOptions->m_bVirtualSpace);
m_pOptions->m_bDrawNodes = pWinApp->GetProfileInt(XTP_EDIT_REG_SETTINGS, XTP_EDIT_REG_COLLAPSIBLENODES, m_pOptions->m_bDrawNodes);
return TRUE;
}
return FALSE;
}
BOOL CXTPSyntaxEditCtrl::SetValueInt(LPCTSTR lpszValue, int nNewValue, int& nRefValue, BOOL bUpdateReg)
{
nRefValue = nNewValue;
if (bUpdateReg)
{
CWinApp* pWinApp = AfxGetApp();
if (pWinApp != NULL)
{
if (pWinApp->WriteProfileInt(XTP_EDIT_REG_SETTINGS, lpszValue, nNewValue))
return TRUE;
}
return FALSE;
}
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::SetValueBool(LPCTSTR lpszValue, BOOL bNewValue, BOOL& bRefValue, BOOL bUpdateReg)
{
bRefValue = bNewValue;
if (bUpdateReg)
{
CWinApp* pWinApp = AfxGetApp();
if (pWinApp != NULL)
{
if (pWinApp->WriteProfileInt(XTP_EDIT_REG_SETTINGS, lpszValue, (int)bNewValue))
return TRUE;
}
return FALSE;
}
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::SetAutoIndent(BOOL bAutoIndent, BOOL bUpdateReg/*=FALSE*/)
{
if (!SetValueBool(XTP_EDIT_REG_AUTOINDENT, bAutoIndent, m_pOptions->m_bAutoIndent, bUpdateReg))
return FALSE;
return TRUE;
}
void CXTPSyntaxEditCtrl::OnPaint()
{
DWORD dwStartTime = ::GetTickCount();
CPaintDC dc(this); // device context for painting
CXTPClientRect rcClient(this);
//if ((!m_bChanged || m_bDisableRedraw) && m_bmpCache.GetSafeHandle() != 0)
if (m_bDisableRedraw && m_bmpCache.GetSafeHandle() != 0)
{
CXTPCompatibleDC memDC(&dc, &m_bmpCache);
dc.BitBlt(0, 0, rcClient.right, rcClient.bottom, &memDC, 0, 0, SRCCOPY);
}
else
{
CDC memDC;
memDC.CreateCompatibleDC(&dc);
if (!m_bmpCache.m_hObject)
m_bmpCache.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
CXTPBitmapDC autoBitmap(&memDC, &m_bmpCache);
#ifdef _DEBUG
memDC.FillSolidRect(rcClient, 0xFF);
#endif
Draw(&memDC, rcClient);
if (!IsWindowEnabled())
{
XTPImageManager()->DisableBitmap(memDC, rcClient, XTP_EDIT_DISABLED_COLOR_LIGHT, XTP_EDIT_DISABLED_COLOR_DARK);
}
dc.BitBlt(0, 0, rcClient.right, rcClient.bottom, &memDC, 0, 0, SRCCOPY);
//m_bChanged = FALSE;
// Draw caret
CSize szCaret;
szCaret.cx = GetWideCaret() ? m_pDrawTextProcessor->GetTextMetrics().tmAveCharWidth : 2;
szCaret.cy = m_pDrawTextProcessor->GetRowHeight();
BOOL bVirtSpace = _IsVirtualSpaceActive() || m_nAutoIndentCol;
int nCol = m_nDispCol - 1;
BOOL bHideCaret = m_pOptions->m_bHideCaret || !m_bFocused;
CPoint ptCaret = m_pDrawTextProcessor->SetCaretPos(this, szCaret, max(0, GetCurrentVisibleRow() - 1), nCol,
bHideCaret, bVirtSpace);
// IME Support
if (m_bIMEsupported)
{
XTP_HIMC hIMC = m_pImmWrapper->ImmGetContext(m_hWnd);
if (hIMC)
{
COMPOSITIONFORM compForm;
::ZeroMemory(&compForm, sizeof(compForm));
compForm.dwStyle = CFS_POINT; //CFS_FORCE_POSITION
compForm.ptCurrentPos = ptCaret;
VERIFY(m_pImmWrapper->ImmSetCompositionWindow(hIMC, &compForm));
VERIFY(m_pImmWrapper->ImmReleaseContext(m_hWnd, hIMC));
}
}
}
DWORD dwEndTime = ::GetTickCount();
m_aveRedrawScreenTime.AddValue(::labs(dwEndTime - dwStartTime));
//TRACE(_T("aveRedrawScreenTime = %d ms \n"), (int)m_aveRedrawScreenTime.GetAverageValue(0));
}
AFX_STATIC void AFX_CDECL XTPSECollapsedBlockDeleteFn(void* pPtr)
{
XTP_EDIT_COLLAPSEDBLOCK* pBlock = (XTP_EDIT_COLLAPSEDBLOCK*)pPtr;
SAFE_DELETE(pBlock);
}
void CXTPSyntaxEditCtrl::Draw(CDC *pDC, const CRect& rcRect)
{
ASSERT(pDC);
if (!pDC)
return;
pDC->SetBkMode(TRANSPARENT);
// calculate rects
CRect rcBookMarks, rcLineNum, rcNodes, rcText;
CalcEditRects(&rcBookMarks, &rcLineNum, &rcNodes, &rcText, &rcRect);
// set text rect
m_pDrawTextProcessor->SetTextRect(rcText);
m_pDrawTextProcessor->SetTabSize(GetTabSize());
// Set Row Height
m_pDrawTextProcessor->RecalcRowHeight(pDC, GetPaintManager()->GetFont());
//--------------------------------------------------
m_fcCollapsable->Update(m_nTopRow);
m_fcRowColors->Update(m_nTopRow);
//-------------------
int nRowHeight = max(1, m_pDrawTextProcessor->GetRowHeight());
int nLinesCount = rcRect.Height() / nRowHeight + ((rcRect.Height() % nRowHeight) ? 1 : 0);
int nSkipLines = 0;
m_nCollapsedTextRowsCount = 0;
m_mapInternalRowBkColor.RemoveAll();
m_mapInternalRowForeColor.RemoveAll();
for (int nLine = 0; nLine < nLinesCount;)
{
int nTextRow = m_nTopRow + nLine + nSkipLines;
int nCollapsedRowsCount = 0;
DWORD dwCollapcedType = ProcessCollapsedRowsBeroreDraw(nTextRow, nCollapsedRowsCount);
nSkipLines += nCollapsedRowsCount;
//if (nCollapsedRowsCount)
// continue;
// Draw Line attributes (bookmark, number, node)
int nLineY0 = rcRect.top + m_pDrawTextProcessor->GetRowHeight() * nLine;
int nLineY1 = nLineY0 + m_pDrawTextProcessor->GetRowHeight();
if (GetSelMargin())
{
CRect rcLMark(rcBookMarks);
rcLMark.top = nLineY0;
rcLMark.bottom = nLineY1;
GetPaintManager()->DrawLineMarks(pDC, rcLMark, nTextRow, this);
}
if (GetLineNumbers())
{
CRect rcLNum(rcLineNum);
rcLNum.top = nLineY0;
rcLNum.bottom = nLineY1;
GetPaintManager()->DrawLineNumber(pDC, rcLNum, nTextRow, this);
}
if (GetCollapsibleNodes())
{
CRect rcNode, rcNodeFull;
GetLineNodeRect(nLine, rcNode, &rcNodeFull);
GetPaintManager()->DrawLineNode(pDC, rcNode, rcNodeFull, dwCollapcedType, nTextRow, this);
}
else
{
CRect rcGap(rcLineNum);
rcGap.top = nLineY0;
rcGap.bottom = nLineY1;
rcGap.left = rcLineNum.right;
rcGap.right = rcText.left;
pDC->FillSolidRect(&rcGap, GetPaintManager()->GetBackColorEx(this));
}
// D R A W T E X T /////////////////////////////////////////////
CRect rcTextLine(rcText);
rcTextLine.top = nLineY0;
rcTextLine.bottom = nLineY1;
GetPaintManager()->DrawLineTextEx(pDC, rcTextLine, nTextRow, nLine, this);
nLine++;
}
//---------------------------------------------------------------------------
GetPaintManager()->DrawCollapsedTextMarks(this, pDC);
//---------------------------------------------------------------------------
}
int CXTPSyntaxEditCtrl::PrintPage(CDC *pDC, const CRect& rcRect, int nFlags) // returns printed rows count
{
int nPrintedRowsCount = 0;
ASSERT(pDC);
if (!pDC)
return 0;
BOOL bSelMargin_orig = m_pOptions->m_bSelMargin;
m_pOptions->m_bSelMargin = FALSE;
CalculateEditbarLength(pDC);
pDC->SetBkMode(TRANSPARENT);
// calculate rects
CRect rcBookMarks, rcLineNum, rcNodes, rcText;
CalcEditRects(&rcBookMarks, &rcLineNum, &rcNodes, &rcText, &rcRect);
// set text rect
m_pDrawTextProcessor->SetTextRect(rcText);
m_pDrawTextProcessor->SetTabSize(GetTabSize());
// Set Row Height
m_pDrawTextProcessor->RecalcRowHeight(pDC, GetPaintManager()->GetFont());
//--------------------------------------------------
m_fcCollapsable->Update(m_nTopRow);
m_fcRowColors->Update(m_nTopRow);
//-------------------
int nRowHeight = max(1, m_pDrawTextProcessor->GetRowHeight());
int nLinesCount = rcRect.Height() / nRowHeight + ((rcRect.Height() % nRowHeight) ? 1 : 0);
int nSkipLines = 0;
m_nCollapsedTextRowsCount = 0;
int nNextLineY = 0;
m_mapInternalRowBkColor.RemoveAll();
m_mapInternalRowForeColor.RemoveAll();
for (int nLine = 0;
nLine < nLinesCount && nNextLineY + nRowHeight < rcText.Height();
nPrintedRowsCount++)
{
int nTextRow = m_nTopRow + nLine + nSkipLines;
int nCollapsedRowsCount = 0;
ProcessCollapsedRowsBeroreDraw(nTextRow, nCollapsedRowsCount);
nSkipLines += nCollapsedRowsCount;
// Draw Line attributes (bookmark, number, node)
int nLineY0 = rcRect.top + nNextLineY; //m_pDrawTextProcessor->GetRowHeight() * nLine;
int nLineY1 = nLineY0 + m_pDrawTextProcessor->GetRowHeight();
CRect rcTextLine(rcText);
rcTextLine.top = nLineY0;
rcTextLine.bottom = nLineY1;
// calculate is enough vertical space to print all line text
int nLineHeight = GetPaintManager()->PrintLineTextEx(pDC, rcTextLine, nTextRow, nLine,
this, nFlags);
if (nLineHeight < 0)
break;
// if (GetSelMargin())
// {
// CRect rcLMark(rcBookMarks);
// rcLMark.top = nLineY0;
// rcLMark.bottom = nLineY1;
// GetPaintManager()->DrawLineMarks(pDC, rcLMark, nTextRow, this);
// }
if (GetLineNumbers() && (nFlags & DT_CALCRECT) == 0)
{
CRect rcLNum(rcLineNum);
rcLNum.top = nLineY0;
rcLNum.bottom = nLineY1;
GetPaintManager()->DrawLineNumber(pDC, rcLNum, nTextRow, this);
}
// if (m_bDrawNodes)
// {
// CRect rcNode, rcNodeFull;
// GetLineNodeRect(nLine, rcNode, &rcNodeFull);
// GetPaintManager()->DrawLineNode(pDC, rcNode, rcNodeFull, dwCollapcedType, this);
// }
// D R A W T E X T /////////////////////////////////////////////
// if ((nFlags & DT_CALCRECT) == 0)
// nLineHeight = GetPaintManager()->PrintLineTextEx(pDC, rcTextLine, nTextRow,
// nLine, this, nFlags);
nNextLineY += nLineHeight;
nLine++;
}
//---------------------------------------------------------------------------
GetPaintManager()->DrawCollapsedTextMarks(this, pDC);
//---------------------------------------------------------------------------
m_pOptions->m_bSelMargin = bSelMargin_orig;
return nPrintedRowsCount;
}
void CXTPSyntaxEditCtrl::UpdateRowInfoInternally(int nTextRow)
{
CClientDC wndDC(this);
CDC memDC;
memDC.CreateCompatibleDC(&wndDC);
int nDispRow = GetVisibleRow(nTextRow) - 1;
if (nDispRow > m_pDrawTextProcessor->GetRowsCount(TRUE) + 10)
nDispRow = m_pDrawTextProcessor->GetRowsCount(TRUE) + 10;
CRect rcTextLine;
CalcEditRects(NULL, NULL, NULL, &rcTextLine);
int nCollapsedRowsCount = 0;
ProcessCollapsedRowsBeroreDraw(nTextRow, nCollapsedRowsCount); // to update collapsed block info.
GetPaintManager()->DrawLineTextEx(&memDC, rcTextLine, nTextRow, nDispRow, this);
}
DWORD CXTPSyntaxEditCtrl::ProcessCollapsedRowsBeroreDraw(int nTextRow, int& rnSkipRowsCount)
{
rnSkipRowsCount = 0;
if (nTextRow > GetRowCount())
return XTP_EDIT_ROWNODE_NOTHING;
XTP_EDIT_LMPARAM LMCoParam;
BOOL bIsRowCollapsed = HasRowMark(nTextRow, xtpEditLMT_Collapsed, &LMCoParam);
// retrieve row nodes
CXTPSyntaxEditRowsBlockArray arCoBlocks;
DWORD dwType = XTP_EDIT_ROWNODE_NOTHING;
GetCollapsableBlocksInfo(nTextRow, arCoBlocks);
BOOL bCollapsedProcessed = FALSE;
int nCount = (int)arCoBlocks.GetSize();
//-----------------------------------------
if (bIsRowCollapsed && nCount == 0)
{
GetLineMarksManager()->DeleteLineMark(nTextRow, xtpEditLMT_Collapsed);
}
//-----------------------------------------
for (int i = 0; i < nCount; i++)
{
XTP_EDIT_ROWSBLOCK coBlk = arCoBlocks[i];
if (coBlk.lcStart.nLine == nTextRow)
{
if (bIsRowCollapsed && !bCollapsedProcessed)
{
XTP_EDIT_COLLAPSEDBLOCK* pCoDrawBlk;
pCoDrawBlk = (XTP_EDIT_COLLAPSEDBLOCK*)LMCoParam.GetPtr();
if (!pCoDrawBlk)
{
pCoDrawBlk = new XTP_EDIT_COLLAPSEDBLOCK;
LMCoParam.SetPtr(pCoDrawBlk, XTPSECollapsedBlockDeleteFn);
}
pCoDrawBlk->collBlock = coBlk;
GetLineMarksManager()->SetLineMark(nTextRow,
xtpEditLMT_Collapsed, &LMCoParam);
m_arCollapsedTextRows.SetAtGrow(m_nCollapsedTextRowsCount, nTextRow);
m_nCollapsedTextRowsCount++;
bCollapsedProcessed = TRUE;
rnSkipRowsCount = max(1, coBlk.lcEnd.nLine - coBlk.lcStart.nLine);
dwType |= XTP_EDIT_ROWNODE_COLLAPSED;
}
else
{
dwType |= XTP_EDIT_ROWNODE_EXPANDED;
}
}
BOOL bLastLineEnd = coBlk.lcEnd.nLine > nTextRow && nTextRow == GetRowCount();
if (coBlk.lcEnd.nLine == nTextRow || bLastLineEnd)
{
dwType |= XTP_EDIT_ROWNODE_ENDMARK;
}
if (coBlk.lcStart.nLine < nTextRow)
{
dwType |= XTP_EDIT_ROWNODE_NODEUP;
}
if (coBlk.lcEnd.nLine > nTextRow && !bCollapsedProcessed && !bLastLineEnd)
{
dwType |= XTP_EDIT_ROWNODE_NODEDOWN;
}
// check whether to skip the row
if ((coBlk.lcStart.nLine < nTextRow) &&
(coBlk.lcEnd.nLine >= nTextRow))
{
if (HasRowMark(coBlk.lcStart.nLine, xtpEditLMT_Collapsed))
{
rnSkipRowsCount = max(1, coBlk.lcEnd.nLine - nTextRow);
}
}
}
return dwType;
}
CRect CXTPSyntaxEditCtrl::CalcEditRects(CRect* prcBookMarks, CRect* prcLineNum, CRect* prcNodes, CRect* prcText,
const CRect* prcClient) const
{
CRect rcClient(0, 0, 100, 100);
if (prcClient)
rcClient = *prcClient;
else if (m_hWnd)
GetClientRect(&rcClient);
// calculate rects
CRect rcBookMarks = rcClient;
rcBookMarks.right = rcBookMarks.left + (GetSelMargin() ? m_nMarginLength : 0);
CRect rcLineNum = rcClient;
rcLineNum.left = rcBookMarks.right;
rcLineNum.right = rcLineNum.left + (GetLineNumbers() ? m_nLineNumLength : 0);
CRect rcNodes = rcClient;
rcNodes.left = rcLineNum.right;
rcNodes.right = rcNodes.left + (GetCollapsibleNodes() ? m_nNodesWidth : 0);
CRect rcText = rcClient;
rcText.left += m_nEditbarLength;
//--------------------------------------------
if (prcBookMarks)
*prcBookMarks = rcBookMarks;
if (prcLineNum)
*prcLineNum = rcLineNum;
if (prcNodes)
*prcNodes = rcNodes;
if (prcText)
*prcText = rcText;
return rcClient;
}
BOOL CXTPSyntaxEditCtrl::RegisterWindowClass(HINSTANCE hInstance /*= NULL*/)
{
return XTPDrawHelpers()->RegisterWndClass(hInstance,
XTP_EDIT_CLASSNAME_EDITCTRL, CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS);
}
BOOL CXTPSyntaxEditCtrl::PreCreateWindow(CREATESTRUCT& )
{
m_bWndCreateInProgress = TRUE;
return TRUE;
}
void CXTPSyntaxEditCtrl::PreSubclassWindow()
{
if (!m_bWndCreateInProgress)
{
// process only for SubclassWindow call
DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
m_bVertScrollBar = 0 != (dwStyle & WS_VSCROLL);
m_bHorzScrollBar = 0 != (dwStyle & WS_HSCROLL);
m_pParentWnd = GetParent();
_InitEditControl();
}
}
int CXTPSyntaxEditCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
m_bWndCreateInProgress = FALSE;
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!_InitEditControl())
return -1;
return 0;
}
void CXTPSyntaxEditCtrl::OnDestroy()
{
if (m_pToolTip->GetSafeHwnd())
m_pToolTip->DestroyWindow();
if (m_pAutoComplete->GetSafeHwnd())
m_pAutoComplete->DestroyWindow();
m_pSink->UnadviseAll();
CWnd::OnDestroy();
}
BOOL CXTPSyntaxEditCtrl::Create(CWnd* pParentWnd, BOOL bHorzScroll, BOOL bVertScroll,
CXTPSyntaxEditBufferManager *pBuffer,
CCreateContext *lpCS, UINT nID)
{
if (pBuffer)
{
CMDTARGET_ADDREF(pBuffer);
CMDTARGET_RELEASE(m_pBuffer);
m_pBuffer = pBuffer;
}
//-------------------------------------------
m_bVertScrollBar = bVertScroll;
m_bHorzScrollBar = bHorzScroll;
DWORD dwStyle = (WS_CHILD | WS_VISIBLE);
if (m_bVertScrollBar && !IsCreateScrollbarOnParent())
dwStyle |= WS_VSCROLL;
if (m_bHorzScrollBar && !IsCreateScrollbarOnParent())
dwStyle |= WS_HSCROLL;
//-------------------------------------------
ASSERT_VALID(pParentWnd); // must be valid.
m_pParentWnd = pParentWnd;
BOOL bCreate = CWnd::CreateEx(WS_EX_ACCEPTFILES, XTP_EDIT_CLASSNAME_EDITCTRL, NULL,
dwStyle, CRect(0, 0, 100, 100), m_pParentWnd, nID, (LPVOID)lpCS);
if (!bCreate)
{
TRACE0("Failed to create edit window.\n");
}
return bCreate;
}
BOOL CXTPSyntaxEditCtrl::_InitEditControl()
{
// create tip window
VERIFY(m_pToolTip->Create(this));
// Create AutoComplete window.
VERIFY(m_pAutoComplete->Create(this));
CRect rcText(0, 0, 3000, 2000);
m_pDrawTextProcessor->SetTextRect(rcText);
m_pDrawTextProcessor->SetTabSize(GetTabSize());
// create data manager if need
//if (!m_pBuffer)
// m_pBuffer = new CXTPSyntaxEditBufferManager;
CXTPSyntaxEditConfigurationManager* pMan = GetLexConfigurationManager();
if (pMan)
{
pMan->m_bUseMonitor = m_bUseMonitor;
pMan->m_bConfigFileMode = m_bConfigFileMode;
pMan->m_sIniSet = m_sIniSet;
if (!m_bConfigFileMode
&& !m_strSyntaxScheme.IsEmpty()
&& !m_strColorScheme.IsEmpty())
{
pMan->SetSyntaxAndColorScheme(&m_strSyntaxScheme, &m_strColorScheme);
}
}
if (!m_pBuffer)
return FALSE;
if (GetConfigFile().IsEmpty())
{
CString csCfgFilePath = GetDefaultCfgFilePath();
if (!SetConfigFile(csCfgFilePath))
{
// TRACE1("\n*** Could not locate config file '%s'.\n\n", (LPCTSTR)csCfgFilePath);
}
}
_UpdateIMEStatus();
SetCurCaretPos(1, 1, FALSE, FALSE);
// Advise to events
m_pSink->UnadviseAll();
CXTPNotifyConnection* ptrConnParser = m_pBuffer->GetLexParser()->GetConnection();
ASSERT(ptrConnParser);
if (ptrConnParser)
{
m_pSink->Advise(ptrConnParser, xtpEditOnParserStarted, CreateNotfySinkClassDelegate(this, &CXTPSyntaxEditCtrl::OnParseEvent));
m_pSink->Advise(ptrConnParser, xtpEditOnTextBlockParsed, CreateNotfySinkClassDelegate(this, &CXTPSyntaxEditCtrl::OnParseEvent));
m_pSink->Advise(ptrConnParser, xtpEditOnParserEnded, CreateNotfySinkClassDelegate(this, &CXTPSyntaxEditCtrl::OnParseEvent));
}
CXTPNotifyConnection* ptrConnBufMan = m_pBuffer->GetConnection();
ASSERT(ptrConnBufMan);
if (ptrConnBufMan)
{
m_pSink->Advise(ptrConnBufMan, xtpEditClassSchWasChanged, CreateNotfySinkClassDelegate(this, &CXTPSyntaxEditCtrl::OnLexCfgWasChanged));
m_pSink->Advise(ptrConnBufMan, xtpEditThemeWasChanged, CreateNotfySinkClassDelegate(this, &CXTPSyntaxEditCtrl::OnLexCfgWasChanged));
m_pSink->Advise(ptrConnBufMan, xtpEditAllConfigWasChanged, CreateNotfySinkClassDelegate(this, &CXTPSyntaxEditCtrl::OnLexCfgWasChanged));
}
return TRUE;
}
UINT CXTPSyntaxEditCtrl::OnGetDlgCode()
{
return DLGC_WANTTAB | DLGC_WANTARROWS | DLGC_WANTCHARS | DLGC_WANTALLKEYS;
}
BOOL CXTPSyntaxEditCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
UNREFERENCED_PARAMETER(pWnd);
UNREFERENCED_PARAMETER(nHitTest);
UNREFERENCED_PARAMETER(message);
CPoint pt;
::GetCursorPos(&pt);
ScreenToClient(&pt);
CXTPClientRect rcClient(this);
CRect rcText(rcClient);
rcText.left += m_nEditbarLength;
CRect rcBookmark(0, 0, GetSelMargin() ? m_nMarginLength : 0, rcClient.Height());
CRect rcLineNumAndNodes(rcBookmark.right, 0, m_nEditbarLength, rcClient.Height());
CXTPEmptyRect rcNode;
int nRow = 0, nCol = 0, nDispRow = 0;
RowColFromPoint(pt, &nRow, &nCol, &nDispRow);
if (GetCollapsibleNodes())
{
// calculate node icon rect
DWORD dwType = XTP_EDIT_ROWNODE_NOTHING;
if (GetRowNodes(nRow, dwType) && (dwType & (XTP_EDIT_ROWNODE_COLLAPSED | XTP_EDIT_ROWNODE_EXPANDED)) )
{
GetLineNodeRect(nDispRow-1, rcNode);
}
}
if (m_bDragging)
{
if (rcClient.PtInRect(pt))
{
if ((::GetKeyState(VK_CONTROL) & KF_UP) == 0)
{
SetCursor(GetPaintManager()->GetCurMove());
return TRUE;
}
else
{
SetCursor(GetPaintManager()->GetCurCopy());
return TRUE;
}
}
else
{
SetCursor(GetPaintManager()->GetCurNO());
return TRUE;
}
}
else if (rcText.PtInRect(pt))
{
if (m_pSelection->IsInSel_str(nRow, nCol-1) && !m_pSelection->bSelectingRunning
|| m_bRightButtonDrag)
{
SetCursor(GetPaintManager()->GetCurArrow());
return TRUE;
}
else
{
if (!GetBlockFromPt(pt))
{
SetCursor(GetPaintManager()->GetCurIBeam());
return TRUE;
}
}
}
else if (rcBookmark.PtInRect(pt))
{
SetCursor(GetPaintManager()->GetCurArrow());
return TRUE;
}
else if (rcNode.PtInRect(pt))
{
SetCursor(GetPaintManager()->GetCurArrow());
return TRUE;
}
else if (rcLineNumAndNodes.PtInRect(pt))
{
SetCursor(GetPaintManager()->GetCurLine());
return TRUE;
}
SetCursor(GetPaintManager()->GetCurArrow());
return TRUE;
}
LRESULT CXTPSyntaxEditCtrl::OnSetText(WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(wParam);
LPCTSTR szText = (LPCTSTR)lParam;
SetText(szText);
return (LRESULT)TRUE;
}
LRESULT CXTPSyntaxEditCtrl::OnGetTextLen(WPARAM, LPARAM)
{
if (!GetEditBuffer())
return 0;
int nTextSize = 0;
int nRowsCount = GetRowCount();
for (int i = 1; i <= nRowsCount; i++)
{
nTextSize += GetEditBuffer()->GetLineTextLength(i, i < nRowsCount);
}
return (LRESULT)nTextSize;
}
LRESULT CXTPSyntaxEditCtrl::OnGetText(WPARAM wBufferSize, LPARAM lpBuffer)
{
if (wBufferSize == 0)
return OnGetTextLen(0, 0);
CMemFile memFile;
if (!GetText(memFile, (int)wBufferSize))
return 0;
void* pTextData = NULL;
void* pTextEnd = NULL;
UINT uBufferB = memFile.GetBufferPtr(CFile::bufferRead, (UINT)wBufferSize, &pTextData, &pTextEnd);
LPTSTR pDest = (LPTSTR)lpBuffer;
STRNCPY_S(pDest, wBufferSize, (LPCTSTR)pTextData, wBufferSize - 1);
pDest[wBufferSize-1] = _T('\0');
int nTextSize = (int)uBufferB/sizeof(TCHAR) - sizeof(TCHAR);
nTextSize = max(0, nTextSize);
nTextSize = min(nTextSize, (int)wBufferSize);
//ASSERT(nTextSize == (int)_tcslen(pDest));
return (LRESULT)nTextSize;
}
CString CXTPSyntaxEditCtrl::GetText(int nMaxLen) const
{
CMemFile memFile;
if (!GetText(memFile, nMaxLen))
return _T("");
void* pTextData = NULL;
void* pTextEnd = NULL;
memFile.GetBufferPtr(CFile::bufferRead, (UINT)nMaxLen, &pTextData, &pTextEnd);
if (pTextEnd)
{
TCHAR* pEnd = (TCHAR*)pTextEnd;
*(pEnd - 1) = _T('\0');
}
return CString((LPCTSTR)pTextData);
}
BOOL CXTPSyntaxEditCtrl::GetText(CMemFile& memFile, int nMaxLen) const
{
if (!GetEditBuffer())
return FALSE;
CArchive ar(&memFile, CArchive::store);
BOOL bUnicode = (sizeof(TCHAR) == 2);
if (nMaxLen > 0)
nMaxLen = nMaxLen * sizeof(TCHAR);
GetEditBuffer()->SerializeEx(ar, bUnicode, FALSE, (UINT)-1, NULL, nMaxLen);
ar << (TCHAR)0;
ar.Close();
memFile.SeekToBegin();
return TRUE;
}
void CXTPSyntaxEditCtrl::SetText(LPCTSTR pcszText)
{
if (!GetEditBuffer() || !pcszText)
{
ASSERT(FALSE);
return;
}
int nStrLenB = (int)_tcslen(pcszText) * sizeof(TCHAR);
CMemFile memFile((BYTE*)pcszText, nStrLenB);
memFile.SeekToBegin();
CArchive ar(&memFile, CArchive::load);
BOOL bUnicode = (sizeof(TCHAR) == 2);
GetEditBuffer()->SerializeEx(ar, bUnicode);
//---------------------------------------
RefreshColors();
RecalcScrollBars();
Invalidate(FALSE);
}
void CXTPSyntaxEditCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
UNREFERENCED_PARAMETER(pScrollBar); UNREFERENCED_PARAMETER(nPos);
SCROLLINFO info;
ZeroMemory(&info, sizeof(SCROLLINFO));
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_ALL;
GetScrollInfo(SB_HORZ, &info);
int nStep = m_pDrawTextProcessor->GetTextMetrics().tmAveCharWidth;
int nCurrPos = m_pDrawTextProcessor->GetScrollXOffset(); //GetScrollPos(SB_HORZ);
switch (nSBCode)
{
case SB_LINELEFT:
nCurrPos -= nStep;
break;
case SB_LINERIGHT:
nCurrPos += nStep;
break;
case SB_PAGELEFT:
nCurrPos -= info.nPage;
break;
case SB_PAGERIGHT:
nCurrPos += info.nPage;
break;
case SB_LEFT:
nCurrPos = info.nMin;
break;
case SB_RIGHT:
nCurrPos = info.nMax;
case SB_ENDSCROLL:
return;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
{
nCurrPos = nPos;
int nDelta = ((nCurrPos % nStep) >= nStep/2 ? 1 : 0);
nCurrPos = (nCurrPos / nStep + nDelta) * nStep;
ASSERT(nCurrPos <= info.nMax);
}
break;
default:
break;
}
nCurrPos = max(0, nCurrPos);
SetScrollPos(SB_HORZ, nCurrPos);
m_pDrawTextProcessor->SetScrollXOffset(nCurrPos);
if (m_bFocused)
{
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, FALSE);
}
Invalidate(FALSE);
UpdateWindow();
}
void CXTPSyntaxEditCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
UNREFERENCED_PARAMETER(nPos);
UNREFERENCED_PARAMETER(pScrollBar);
SCROLLINFO info;
ZeroMemory(&info, sizeof(SCROLLINFO));
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_ALL;
GetScrollInfo(SB_VERT, &info);
int iMin = 0, iMax = 0;
GetScrollRange(SB_VERT, &iMin, &iMax);
int iPos = GetScrollPos(SB_VERT);
BOOL bChanged = FALSE;
switch (nSBCode) {
case SB_LINEDOWN:
bChanged = ShiftCurrentVisibleRowDown(1);
if (bChanged)
SetScrollPos(SB_VERT, iPos + 1);
break;
case SB_LINEUP:
bChanged = ShiftCurrentVisibleRowUp(1);
if (bChanged)
SetScrollPos(SB_VERT, iPos - 1);
break;
case SB_PAGEUP:
bChanged = ShiftCurrentVisibleRowUp(info.nPage);
if (bChanged)
SetScrollPos(SB_VERT, max(1, iPos - info.nPage));
break;
case SB_PAGEDOWN:
bChanged = ShiftCurrentVisibleRowDown(info.nPage);
if (bChanged)
SetScrollPos(SB_VERT, (iPos + info.nPage));
break;
case SB_TOP:
SetScrollPos(SB_VERT, iMin);
SetCurrentDocumentRow(iMin);
m_nCurrentCol = m_nDispCol = 1;
bChanged = TRUE;
break;
case SB_BOTTOM:
SetScrollPos(SB_VERT, iMax);
SetCurrentDocumentRow(iMax);
m_nCurrentCol = m_nDispCol = 1;
bChanged = TRUE;
break;
case SB_THUMBTRACK:
{
SCROLLINFO si;
ZeroMemory(&si, sizeof(SCROLLINFO));
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_TRACKPOS;
if (GetScrollInfo(SB_VERT, &si))
{
int nShift = si.nTrackPos - GetVisibleRowsCount(m_nTopRow);
if (nShift > 0)
{
bChanged = ShiftCurrentVisibleRowDown(nShift);
}
else if (nShift < 0)
{
bChanged = ShiftCurrentVisibleRowUp(-nShift);
}
SetScrollPos(SB_VERT, si.nTrackPos);
}
}
break;
case SB_ENDSCROLL:
return;
default:
break;
}
int nTopDocRow = GetDocumentRow(1);
int nBottomDocRow = GetDocumentRow(GetRowPerPage());
int nCurDocRow = GetCurrentDocumentRow();
if (nCurDocRow >= nTopDocRow && nCurDocRow <= nBottomDocRow)
{
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, FALSE);
}
if (bChanged)
{
Invalidate(FALSE);
UpdateWindow();
}
RecalcScrollBars();
}
void CXTPSyntaxEditCtrl::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CXTPSmartPtrInternalT<CCmdTarget> ptrThisLock(this, TRUE);
#ifdef XTP_SYNTAXEDIT_SITENOTIFY_KEY
if (!XTP_SYNTAXEDIT_SITENOTIFY_KEY(this, TRUE, nChar))
return;
#endif
if (nChar == 0)
{
return;
}
CWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
}
void CXTPSyntaxEditCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CXTPSmartPtrInternalT<CCmdTarget> ptrThisLock(this, TRUE);
#ifdef XTP_SYNTAXEDIT_SITENOTIFY_KEY
if (!XTP_SYNTAXEDIT_SITENOTIFY_KEY(this, TRUE, nChar))
return;
#endif
if (nChar == 0)
{
return;
}
m_pToolTip->Hide();
if (m_bDragging || m_bRightButtonDrag || m_pSelection->bSelectingRunning /* || m_bSelectionStarted*/)
{
OnSetCursor(0, 0, 0);
return;
}
BOOL bCtrlKey = (::GetKeyState(VK_CONTROL) & KF_UP) != 0;
BOOL bShiftKey = (::GetKeyState(VK_SHIFT) & KF_UP) != 0;
BOOL bUpdateAll = FALSE;
int nTopRow_prev = m_nTopRow;
int nDispCol_prev = m_nDispCol;
int nTextRow_prev = GetCurrentDocumentRow();
int nRowCount_prev = GetRowCount();
CXTPSyntaxEditSelection selData_prev = *m_pSelection;
switch (nChar)
{
case VK_UP:
m_nAutoIndentCol = 0;
if (GetCurrentDocumentRow() < 1)
{
// Do nothing
}
else if (bCtrlKey)
{
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol) ;
ShiftCurrentVisibleRowUp(1, TRUE);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE);
}
else if (GetCurrentDocumentRow() >= 1)
{
if (!m_pSelection->IsSelExist())
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (!bShiftKey)
{
m_pSelection->Reset_disp(m_pSelection->GetNormalStart_disp().nLine,
m_nDispCol); //m_pSelection->GetNormalEnd_disp().nCol);
SetCurCaretPos(m_pSelection->GetNormalStart_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol, FALSE);
}
MoveCurrentVisibleRowUp(1);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE);
if (bShiftKey)
m_pSelection->SetEnd_disp(GetCurrentDocumentRow(), m_nDispCol);
else
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
}
break;
case VK_DOWN:
m_nAutoIndentCol = 0;
if (bCtrlKey)
{
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol) ;
ShiftCurrentVisibleRowDown(1, TRUE);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE);
}
else if (GetCurrentDocumentRow() <= GetRowCount())
{
if (!m_pSelection->IsSelExist())
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (!bShiftKey)
{
m_pSelection->Reset_disp(m_pSelection->GetNormalEnd_disp().nLine,
m_nDispCol); //m_pSelection->GetNormalEnd_disp().nCol);
SetCurCaretPos(m_pSelection->GetNormalStart_str().nLine,
m_pSelection->GetNormalEnd_disp().nCol, FALSE, TRUE);
}
MoveCurrentVisibleRowDown(1);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE/*, FALSE*/);
if (bShiftKey)
m_pSelection->SetEnd_disp(GetCurrentDocumentRow(), m_nDispCol);
else
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
}
break;
case VK_LEFT:
m_nAutoIndentCol = 0;
if (!m_pSelection->IsSelExist())
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (!bShiftKey && m_pSelection->IsSelExist())
{
// move cursor to the selection begin
m_pSelection->Reset_disp(m_pSelection->GetNormalStart_disp().nLine,
m_pSelection->GetNormalStart_disp().nCol);
SetCurCaretPos(m_pSelection->GetNormalStart_disp().nLine,
m_pSelection->GetNormalStart_disp().nCol, FALSE/*, FALSE*/);
break;
}
if (!bCtrlKey)
{
int nCurDocRow = GetCurrentDocumentRow();
if ((nCurDocRow > 1 && m_nCurrentCol >= 1) ||
(nCurDocRow == 1 && m_nCurrentCol > 1))
{
m_nCurrentCol--;
}
if (m_nCurrentCol < 1 && nCurDocRow > 1)
{
if (_IsVirtualSpaceActive())
m_nCurrentCol = 1;
else
MoveCurrentVisibleRowUp(1);
}
LPCTSTR szText = GetLineText(GetCurrentDocumentRow());
if (m_nCurrentCol < 1)
m_nCurrentCol = (int)_tcsclen(szText) + 1;
m_nDispCol = CalcDispCol(szText, m_nCurrentCol);
}
else
{
// This will modify Current Row, m_nCurrentCol, m_nDispCol
FindWord(XTP_EDIT_FINDWORD_PREV);
}
if (bShiftKey)
m_pSelection->SetEnd_disp(GetCurrentDocumentRow(), m_nDispCol);
else
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
break;
case VK_RIGHT:
m_nAutoIndentCol = 0;
if (!m_pSelection->IsSelExist())
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (!bShiftKey && m_pSelection->IsSelExist())
{
// move cursor to the end of the selection
m_pSelection->Reset_disp(m_pSelection->GetNormalEnd_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol);
SetCurCaretPos(m_pSelection->GetNormalStart_str().nLine,
m_pSelection->GetNormalEnd_disp().nCol, FALSE/*, FALSE*/);
break;
}
if (!bCtrlKey)
{
int nCurDocRow = GetCurrentDocumentRow();
LPCTSTR szText = GetLineText(nCurDocRow);
const int nTextLen = (int)_tcsclen(szText);
if (m_nCurrentCol > nTextLen && (nCurDocRow < GetRowCount()) && !_IsVirtualSpaceActive())
{
MoveCurrentVisibleRowDown(1);
m_nCurrentCol = 1;
}
else if (m_nCurrentCol <= nTextLen || _IsVirtualSpaceActive())
{
m_nCurrentCol++;
}
m_nDispCol = CalcDispCol(szText, m_nCurrentCol);
}
else
{
FindWord(XTP_EDIT_FINDWORD_NEXT);
}
if (bShiftKey)
m_pSelection->SetEnd_disp(GetCurrentDocumentRow(), m_nDispCol);
else
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
break;
case VK_HOME:
m_nAutoIndentCol = 0;
if (!m_pSelection->IsSelExist())
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (!bShiftKey && m_pSelection->IsSelExist())
{
// move cursor to the selection begin
m_pSelection->Reset_disp(m_pSelection->GetNormalStart_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol);
SetCurCaretPos(m_pSelection->GetNormalStart_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol, FALSE/*, FALSE*/);
}
if (bCtrlKey)
{
SetCurrentDocumentRow(1);
EnsureVisibleRow(1);
SetCurCaretPos(1, 1, FALSE/*, FALSE*/);
}
else
{
LPCTSTR szText = GetLineText(GetCurrentDocumentRow());
// find number of tabs and spaces from the left
int iCol = 1;
LPCTSTR szPtr = szText;
while (szPtr)
{
if (*szPtr == _T('\t') || *szPtr == _T(' '))
iCol++;
else
break;
szPtr = _tcsinc(szPtr);
}
if (m_nCurrentCol == iCol)
{
//m_nCurrentCol = 1;
//m_nDispCol = 1;
SetCurCaretPos(GetCurrentDocumentRow(), 1, FALSE/*, FALSE*/);
}
else
{
m_nDispCol = CalcDispCol(szText, iCol);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE/*, FALSE*/);
}
}
if (bShiftKey)
m_pSelection->SetEnd_disp(GetCurrentDocumentRow(), m_nDispCol);
else
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
break;
case VK_END:
{
m_nAutoIndentCol = 0;
if (!m_pSelection->IsSelExist())
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (!bShiftKey && m_pSelection->IsSelExist())
{
// move cursor to the end of the selection
m_pSelection->Reset_disp(m_pSelection->GetNormalEnd_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol);
SetCurCaretPos(m_pSelection->GetNormalStart_str().nLine,
m_pSelection->GetNormalEnd_disp().nCol, FALSE/*, FALSE*/);
}
if (bCtrlKey)
{
SetCurrentDocumentRow(GetRowCount());
EnsureVisibleRow(GetRowCount());
}
LPCTSTR szText = GetLineText(GetCurrentDocumentRow());
int nLenC = (int)_tcsclen(szText);
SetCurCaretPos(GetCurrentDocumentRow(), CalcDispCol(szText, nLenC + 1),
FALSE/*, FALSE*/);
}
if (bShiftKey)
m_pSelection->SetEnd_disp(GetCurrentDocumentRow(), m_nDispCol);
else
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
break;
case VK_PRIOR:
m_nAutoIndentCol = 0;
{
if (!m_pSelection->IsSelExist())
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (!bShiftKey && m_pSelection->IsSelExist())
{
// move cursor to the selection begin
m_pSelection->Reset_disp(m_pSelection->GetNormalStart_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol);
SetCurCaretPos(m_pSelection->GetNormalStart_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol, FALSE/*, FALSE*/);
}
int iRowPerPage = GetRowPerPage();
if ((m_nTopRow - iRowPerPage) < 1)
{
SetCurrentDocumentRow(1);
EnsureVisibleRow(1);
}
else
{
MoveCurrentVisibleRowUp(iRowPerPage);
}
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE/*, FALSE*/);
if (bShiftKey)
m_pSelection->SetEnd_disp(GetCurrentDocumentRow(), m_nDispCol);
else
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
}
break;
case VK_NEXT:
m_nAutoIndentCol = 0;
{
if (!m_pSelection->IsSelExist())
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (!bShiftKey && m_pSelection->IsSelExist())
{
// move cursor to the end of the selection
m_pSelection->Reset_disp(m_pSelection->GetNormalEnd_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol);
SetCurCaretPos(m_pSelection->GetNormalStart_str().nLine,
m_pSelection->GetNormalEnd_disp().nCol, FALSE/*, FALSE*/);
}
int iRowPerPage = GetRowPerPage();
if ((m_nTopRow + iRowPerPage) > GetRowCount())
{
SetCurrentDocumentRow(GetRowCount());
EnsureVisibleRow(GetRowCount());
}
else
{
MoveCurrentVisibleRowDown(iRowPerPage);
}
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE/*, FALSE*/);
if (bShiftKey)
m_pSelection->SetEnd_disp(GetCurrentDocumentRow(), m_nDispCol);
else
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
}
break;
case VK_DELETE:
{
BOOL bDeleted = TRUE;
if (m_pSelection->IsSelExist() && !bCtrlKey)
{
bDeleted = DeleteSelection();
}
else if (!bCtrlKey)
{
if (GetAutoIndent() && m_nAutoIndentCol > 0)
{
CString strInsertText(
CString(_T('\t'), m_nInsertTabCount) +
CString(_T(' '), m_nInsertSpaceCount));
int iNewDispCol = (m_nInsertTabCount * GetTabSize()) + m_nInsertSpaceCount + 1;
int iNewCol = m_nInsertTabCount + m_nInsertSpaceCount + 1;
//**----------------------
OnBeforeEditChanged(GetCurrentDocumentRow(), 1);
m_pBuffer->InsertText(strInsertText, GetCurrentDocumentRow(), 1);
OnEditChanged(GetCurrentDocumentRow(), 1, GetCurrentDocumentRow(), iNewCol, xtpEditActInsert);
//**----------------------
m_nCurrentCol = iNewCol;
m_nDispCol = iNewDispCol;
m_nAutoIndentCol = 0;
}
bDeleted = DeleteChar(GetCurrentDocumentRow(), m_nCurrentCol, xtpEditDelPosAfter);
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
}
else
{
BOOL bSelectionExist = m_pSelection->IsSelExist();
int nDelFlags = 0;
if (bSelectionExist)
{
nDelFlags |= xtpEditForceRedraw;
DeleteSelection();
}
int iStartRow = GetCurrentDocumentRow();
int iStartCol = m_nCurrentCol;
FindWord(XTP_EDIT_FINDWORD_NEXT);
int iEndRow = GetCurrentDocumentRow();
int iEndCol = m_nCurrentCol;
DeleteBuffer(iStartRow, iStartCol, iEndRow, iEndCol, nDelFlags);
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (bSelectionExist)
m_pBuffer->GetUndoRedoManager()->ChainLastCommand();
}
bUpdateAll = TRUE;
m_nAutoIndentCol = 0;
}
break;
case VK_BACK:
if (m_nAutoIndentCol > 0)
{
if (m_nInsertSpaceCount == 0)
m_nInsertTabCount--;
else
m_nInsertSpaceCount--;
if (m_nInsertTabCount || m_nInsertSpaceCount)
{
m_nAutoIndentCol = (m_nInsertTabCount * GetTabSize()) + m_nInsertSpaceCount + 1;
m_nDispCol = m_nAutoIndentCol;
}
else
{
m_nAutoIndentCol = 0;
m_nDispCol = 1;
}
}
else if (!bCtrlKey)
{
if (m_pSelection->IsSelExist())
{
DeleteSelection();
}
else
{
DeleteChar(GetCurrentDocumentRow(), m_nCurrentCol, xtpEditDelPosBefore);
}
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
}
else
{
BOOL bSelectionExist = m_pSelection->IsSelExist();
if (bSelectionExist)
{
DeleteSelection();
}
int iStartRow = GetCurrentDocumentRow();
int iStartCol = m_nCurrentCol;
FindWord(XTP_EDIT_FINDWORD_PREV);
int iEndRow = GetCurrentDocumentRow();
int iEndCol = m_nCurrentCol;
DeleteBuffer(iStartRow, iStartCol, iEndRow, iEndCol);
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
if (bSelectionExist)
m_pBuffer->GetUndoRedoManager()->ChainLastCommand();
}
bUpdateAll = TRUE;
break;
case VK_INSERT:
{
NotifyParent(XTP_EDIT_NM_INSERTKEY);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE/*, FALSE*/);
SetOverwriteMode(!m_pBuffer->GetOverwriteFlag());
}
break;
case VK_SPACE:
if (bCtrlKey)
{
CPoint pt(CWnd::GetCaretPos());
pt.y += m_pDrawTextProcessor->GetRowHeight();
ClientToScreen(&pt);
CString strText(GetLineText(GetCurrentDocumentRow()));
int nTextPos = m_nCurrentCol - 2;
CString strSearch;
//NON-COVERED CASE <<
if (m_pAutoComplete->m_strDelims.IsEmpty())
m_pAutoComplete->m_strDelims = _T(" \t");
//NON-COVERED CASE <<
while (strText.GetLength() > 0 && nTextPos >= 0 && m_pAutoComplete->m_strDelims.Find(strText.GetAt(nTextPos)) < 0)
{
strSearch = strText.GetAt(nTextPos--) + strSearch;
}
SetAutoCompleteList();
m_pAutoComplete->Show(pt, strSearch);
}
break;
}
BOOL bChanged = nTopRow_prev != m_nTopRow || nDispCol_prev != m_nDispCol ||
nTextRow_prev != GetCurrentDocumentRow() || nRowCount_prev != GetRowCount() ||
selData_prev != *m_pSelection;
if (bChanged)
{
int nCurDocRow = GetCurrentDocumentRow();
SetCurCaretPos(nCurDocRow, m_nDispCol);
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
Invalidate(FALSE);
UpdateWindow();
if (nTopRow_prev != m_nTopRow)
RecalcScrollBars();
DWORD dwUpdate = (XTP_EDIT_UPDATE_HORZ|XTP_EDIT_UPDATE_VERT);
if (bUpdateAll)
dwUpdate |= XTP_EDIT_UPDATE_DIAG;
UpdateScrollPos(dwUpdate);
}
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CXTPSyntaxEditCtrl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (m_bDragging || m_bRightButtonDrag)
{
OnSetCursor(0, 0, 0);
return;
}
NotifySelInit();
BOOL bAltKey = (::GetKeyState(VK_MENU) & KF_UP) != 0;
BOOL bCtrlKey = (::GetKeyState(VK_CONTROL) & KF_UP) != 0;
BOOL bShiftKey = (::GetKeyState(VK_SHIFT) & KF_UP) != 0;
CString strCurCRLF = m_pBuffer->GetCurCRLF();
LPCTSTR szCurCRLF = strCurCRLF;
BOOL bProcessed = FALSE;
if (nChar == VK_TAB && !bCtrlKey)
{
if (bShiftKey)
bProcessed = DecreaseIndent();
else
bProcessed = IncreaseIndent();
}
if (!bProcessed && (bCtrlKey && !bAltKey) && nChar == 0x0C) // 0x0C is 'l' or 'L'
{
// Delete the entire line or the selection
DeleteSelectedLines(GetCurrentDocumentRow());
}
else if (nChar != VK_BACK && nChar != VK_ESCAPE && !(bCtrlKey && !bAltKey) && !bProcessed)
{
if (!CanEditDoc())
{
return;
}
BOOL bModified = FALSE;
//**----------------------
OnBeforeEditChanged(GetCurrentDocumentRow(), m_nCurrentCol);
//**----------------------
int nChainActionCount = 1;
BOOL bRedraw = FALSE;
BOOL bPrevOverwriteMode = m_pBuffer->GetOverwriteFlag();
if (m_pSelection->IsSelExist())
{
if (!m_pBuffer->GetOverwriteFlag() || (m_pBuffer->GetOverwriteFlag() && nChar != VK_RETURN))
{
BOOL bRes = DeleteSelection();
bModified |= bRes;
nChainActionCount = 2;
bRedraw = TRUE;
m_pBuffer->SetOverwriteFlag(FALSE);
}
}
TCHAR szText[3];
szText[0] = (TCHAR)nChar;
szText[1] = NULL;
// DBCS Support (specially for IME)
#ifndef _UNICODE
//if (m_bIsImeEnabled)
if (isleadbyte((int)nChar) && m_chPrevLeadByte == 0)
{
// do not process lead byte. just remember it and exit.
m_chPrevLeadByte = (BYTE)nChar;
return;
}
if (m_chPrevLeadByte)
{
szText[0] = (TCHAR)m_chPrevLeadByte;
szText[1] = (TCHAR)nChar;
szText[2] = NULL;
}
m_chPrevLeadByte = 0;
#endif
if (nChar == _T('\r'))
{
lstrcpy(szText, szCurCRLF);
szText[2] = NULL;
// here we should expand collapsed block if we are on it
if (GetLineMarksManager()->HasRowMark(GetCurrentDocumentRow(), xtpEditLMT_Collapsed))
{
GetLineMarksManager()->DeleteLineMark(GetCurrentDocumentRow(), xtpEditLMT_Collapsed);
}
}
int iNewDispCol = m_nDispCol;
int iNewCol = m_nCurrentCol;
int iNewRow = GetCurrentDocumentRow();
int iEditRowFrom = iNewRow;
int iEditRowTo = iNewRow;
CString strTextToIns;
// Create text to insert
BOOL bCanProcess =
CreateInsertText(szText,
strTextToIns,
iNewRow,
iNewCol,
iNewDispCol,
iEditRowFrom,
iEditRowTo,
nChainActionCount);
BOOL bGroupInsMode = FALSE;
if (!bPrevOverwriteMode)
{
static LPCTSTR szSeps = _T(" [{()}];.,\t\r\n\"");
if (_tcschr(szSeps, (TCHAR)nChar))
bGroupInsMode = FALSE;
else
bGroupInsMode = TRUE;
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(bGroupInsMode);
}
else
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
if (bCanProcess)
{
int nInsCol = m_nCurrentCol;
if (nChar == VK_RETURN && m_nAutoIndentCol)
nInsCol = min(m_nCurrentCol, m_pBuffer->GetLineTextLengthC(GetCurrentDocumentRow()) + 1);
BOOL bInsRes = m_pBuffer->InsertText(strTextToIns, GetCurrentDocumentRow(), nInsCol, TRUE);
bModified |= bInsRes;
if (nChainActionCount > 1)
{
m_pBuffer->GetUndoRedoManager()->ChainLastCommand();
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_TYPING);
}
}
//m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
m_pBuffer->SetOverwriteFlag(bPrevOverwriteMode);
//**----------------------
OnEditChanged(GetCurrentDocumentRow(), m_nCurrentCol, iNewRow, iNewCol, xtpEditActInsert);
//**----------------------
BOOL bInsAt0 = (m_nCurrentCol == 1) || GetLineText(GetCurrentDocumentRow()).GetLength() == 0;
m_nCurrentCol = iNewCol;
m_nDispCol = iNewDispCol;
SetCurrentDocumentRow(iNewRow);
BOOL bNewRow = FALSE;
if (nChar == VK_RETURN)
bNewRow = TRUE;
UINT nAction = XTP_EDIT_EDITACTION_MODIFYROW;
if (bNewRow)
nAction |= XTP_EDIT_EDITACTION_INSERTROW;
if (bNewRow && bInsAt0)
nAction |= XTP_EDIT_EDITACTION_INSERTROW_NEW;
NotifyEditChanged(iEditRowFrom, iEditRowTo, nAction);
// if (nChar == VK_RETURN)
// {
// DoAutoIndentIfNeed(nDispCol_prev);
// }
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
RecalcScrollBars();
Invalidate(FALSE);
UpdateWindow();
UpdateScrollPos();
if (bModified)
SetDocModified();
}
else if (!bProcessed && nChar == VK_ESCAPE)
{
Unselect();
UpdateScrollPos();
}
// AutoComplete Processing
if (m_pAutoComplete->IsOpenTag((TCHAR)nChar))
{
CPoint pt(CWnd::GetCaretPos());
pt.y += m_pDrawTextProcessor->GetRowHeight();
ClientToScreen(&pt);
SetAutoCompleteList();
m_pAutoComplete->Show(pt);
}
CWnd::OnChar(nChar, nRepCnt, nFlags);
}
void CXTPSyntaxEditCtrl::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CXTPSmartPtrInternalT<CCmdTarget> ptrThisLock(this, TRUE);
#ifdef XTP_SYNTAXEDIT_SITENOTIFY_KEY
if (!XTP_SYNTAXEDIT_SITENOTIFY_KEY(this, FALSE, nChar))
return;
#endif
if (nChar == 0)
{
return;
}
if (m_bDragging)
{
OnSetCursor(0, 0, 0);
return;
}
CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
}
void CXTPSyntaxEditCtrl::SetCurPos(int nTextRow, int nDispCol, BOOL bRemainSelected, BOOL bForceVisible)
{
if (nTextRow > GetRowCount())
nTextRow = GetRowCount();
//reset autoindent
m_nAutoIndentCol = 0;
CString strText = GetLineText(nTextRow);
// validate col
m_nCurrentCol = CalcAbsCol(strText, nDispCol);
m_nDispCol = CalcDispCol(strText, m_nCurrentCol);
if (!bRemainSelected && m_pSelection->IsSelExist())
{
m_pSelection->Reset_disp(nTextRow, m_nDispCol);
}
SetCurCaretPos(nTextRow, m_nDispCol, TRUE, bForceVisible);
if (::IsWindow(m_hWnd) || m_hWnd)
{
Invalidate(FALSE);
UpdateWindow();
}
else
InvalidateAll();
UpdateScrollPos(XTP_EDIT_UPDATE_HORZ|XTP_EDIT_UPDATE_VERT);
}
void CXTPSyntaxEditCtrl::SetCurCaretPos(int nTextRow, int nDispCol, BOOL bRowColNotify, BOOL bEnsureVisible)
{
if (!::IsWindow(m_hWnd) || !m_hWnd)
return;
if (bEnsureVisible)
_EnsureVisible(nTextRow, nDispCol);
int nDispRow = GetVisibleRow(nTextRow);
if (nDispRow > m_pDrawTextProcessor->GetRowsCount(TRUE) + 10)
nDispRow = m_pDrawTextProcessor->GetRowsCount(TRUE) + 10;
if (m_nAutoIndentCol > 0)
nDispCol = m_nAutoIndentCol;
int nCol = max(0, nDispCol - 1);
m_nDispCol = nCol + 1;
m_nCurrentCol = CalcAbsCol(nTextRow, m_nDispCol);
SetCurrentDocumentRow(nTextRow);
if (bRowColNotify)
NotifyCurRowCol(GetCurrentDocumentRow(), m_nDispCol);
Invalidate(FALSE);
//TRACE(_T("CXTPSyntaxEditCtrl::SetCurCaretPos(%d, %d) \n"), nDispRow, nDispCol);
}
void CXTPSyntaxEditCtrl::_EnsureVisible(int nTextRow, int nDispCol/*, BOOL bRedraw*/)
{
BOOL bVScrolled = EnsureVisibleRow(nTextRow);
nDispCol = nDispCol;
if (m_nAutoIndentCol > 0)
nDispCol = m_nAutoIndentCol;
int nDispRow = GetVisibleRow(nTextRow);
BOOL bHScrolled = EnsureVisibleCol(nDispRow, nDispCol);
// BOOL bVirtSpace = _IsVirtualSpaceActive() || m_nAutoIndentCol;
// m_nCurrentCol = m_pDrawTextProcessor->DispPosToStrPos(nDispRow - 1, m_nDispCol-1, bVirtSpace) + 1;
if (bVScrolled || bHScrolled /*|| bRedraw*/)
{
Invalidate(FALSE);
}
}
BOOL CXTPSyntaxEditCtrl::EnsureVisibleRow(int nTextRow)
{
int nPrevTopRow = m_nTopRow;
int nDispRowsCount = m_pDrawTextProcessor->GetRowsCount(FALSE);
int nCurPageMaxTextRow = GetDocumentRow(nDispRowsCount);
if (nDispRowsCount == 0)
{
return FALSE;
}
if (nTextRow > nCurPageMaxTextRow)
{
m_nTopRow += nTextRow - nCurPageMaxTextRow;
}
else if (nTextRow < m_nTopRow)
{
m_nTopRow = max (1, nTextRow);
}
if (GetVertScrollBar() /*&& nPrevTopRow != m_nTopRow*/)
{
BOOL bEnableVertScrl = (CalculateVisibleRow(1, GetRowCount()) > nDispRowsCount);
EnableScrollBarCtrl(SB_VERT, bEnableVertScrl);
if (bEnableVertScrl)
SetScrollPos(SB_VERT, CalculateVisibleRow(1, m_nTopRow));
}
return nPrevTopRow != m_nTopRow;
}
BOOL CXTPSyntaxEditCtrl::EnsureVisibleCol(int nDispRow, int nDispCol)
{
int nTextRow = GetDocumentRow(nDispRow);
UpdateRowInfoInternally(nTextRow);
int nColWidth = 0;
int nColPos = m_pDrawTextProcessor->GetColPosX(nDispRow - 1, nDispCol, &nColWidth, IsEnabledVirtualSpace());
int nOffsetX = m_pDrawTextProcessor->GetScrollXOffset();
CRect rcText = m_pDrawTextProcessor->GetTextRect();
int nNewScrollOffset = -1;
if (nColPos - max(14, nColWidth * 2) < rcText.left)
{
nNewScrollOffset = max(0, nOffsetX - (rcText.left - nColPos )- nColWidth * 15);
}
else if (nColPos + nColWidth >= rcText.right)
{
nNewScrollOffset = nOffsetX + (nColPos + nColWidth) - rcText.right + min(rcText.Width()/3, nColWidth * 15);
}
if (nNewScrollOffset >= 0)
{
SetScrollPos(SB_HORZ, nNewScrollOffset);
m_pDrawTextProcessor->SetScrollXOffset(nNewScrollOffset);
}
return nNewScrollOffset >= 0;
}
int CXTPSyntaxEditCtrl::CalcDispCol(int nTextRow, int nActualCol) const
{
CString strLine = GetLineText(nTextRow);
return CalcDispCol(strLine, nActualCol);
}
int CXTPSyntaxEditCtrl::CalcAbsCol(int nTextRow, int nDispCol) const
{
CString strLine = GetLineText(nTextRow);
return CalcAbsCol(strLine, nDispCol);
}
int CXTPSyntaxEditCtrl::CalcDispCol(LPCTSTR szText, int nActualCol) const
{
int iDispCol = 0;
int nAbsCol = 1;
for (LPCTSTR pcszChar = szText; pcszChar && *pcszChar; pcszChar = _tcsinc(pcszChar))
{
if (nAbsCol >= nActualCol)
break;
if (*pcszChar == _T('\t'))
{
// Now calculate tab size
iDispCol += (GetTabSize() - (iDispCol % GetTabSize()));
}
#ifdef XTP_FIXED
else if (isleadbyte( *pcszChar ))
// multi byte character : DisplayLength 2
iDispCol += 2;
#endif
else
iDispCol++;
nAbsCol++;
}
iDispCol++;
if (nAbsCol < nActualCol)
{
if (_IsVirtualSpaceActive())
iDispCol += nActualCol - nAbsCol;
else
iDispCol++;
}
return iDispCol;
}
int CXTPSyntaxEditCtrl::CalcAbsCol(LPCTSTR szText, int iDispCol) const
{
int nAbsCol = 0;
int nDispColCalc = 0;
for (LPCTSTR pcszChar = szText; pcszChar && *pcszChar; pcszChar = _tcsinc(pcszChar))
{
if (nDispColCalc >= iDispCol)
break;
//if (szText[i] == _T('\t'))
if (*pcszChar == _T('\t'))
nDispColCalc += (GetTabSize() - (nDispColCalc % GetTabSize()));
#ifdef XTP_FIXED
else if (isleadbyte( *pcszChar ))
// multi byte character : DisplayLength 2
nDispColCalc += 2;
#endif
else
nDispColCalc++;
nAbsCol++;
}
if (nDispColCalc < iDispCol)
{
if (_IsVirtualSpaceActive())
nAbsCol += iDispCol - nDispColCalc;
else
nAbsCol++;
}
if (nAbsCol == 0)
nAbsCol = 1;
return nAbsCol;
}
int CXTPSyntaxEditCtrl::CalcValidDispCol(LPCTSTR szText, int iCol) const
{
int iDispCol = 0;
for (LPCTSTR pcszChar = szText; pcszChar && *pcszChar; pcszChar = _tcsinc(pcszChar))
{
if (iDispCol >= iCol-1)
break;
if (*pcszChar == _T('\t'))
{
// Now calculate tab size
iDispCol += (GetTabSize() - (iDispCol % GetTabSize()));
}
#ifdef XTP_FIXED
else if (isleadbyte(*pcszChar))
// multi byte character : DisplayLength 2
iDispCol += 2;
#endif
else
iDispCol++;
}
return ++iDispCol;
}
int CXTPSyntaxEditCtrl::CalcMaximumWidth(LPCTSTR szText)
{
int iMaxWidth = 1;
for (LPCTSTR pcszChar = szText; pcszChar && *pcszChar; pcszChar = _tcsinc(pcszChar))
{
if (*pcszChar == _T('\t'))
{
// Now calculate tab size
iMaxWidth += ((GetTabSize() + 1) - (iMaxWidth - ((iMaxWidth / GetTabSize()) * GetTabSize())));
}
#ifdef XTP_FIXED
else if (isleadbyte(*pcszChar))
// multi byte character : DisplayLength 2
iMaxWidth += 2;
#endif
else
iMaxWidth++;
}
return iMaxWidth;
}
void CXTPSyntaxEditCtrl::GetLineNodeRect(int nRow, CRect& rcNode, CRect* prcNodeFull) const
{
// calculate node rect
CRect rcNodes, rcText;
CalcEditRects(NULL, NULL, &rcNodes, &rcText);
int nRowHeight = m_pDrawTextProcessor->GetRowHeight();
int nYPos = rcNodes.top + nRow * nRowHeight;
rcNode = rcNodes;
rcNode.top = nYPos + (nRowHeight - m_nNodesWidth) / 2;
rcNode.bottom = rcNode.top + m_nNodesWidth - 1;
if (prcNodeFull)
{
prcNodeFull->left = rcNodes.left;
prcNodeFull->right = rcText.left;
prcNodeFull->top = nYPos;
prcNodeFull->bottom = nYPos + nRowHeight;
}
}
BOOL CXTPSyntaxEditCtrl::ProcessCollapsedTextEx(CDC* pDC, XTP_EDIT_COLLAPSEDBLOCK* pCoDrawBlk,
const XTP_EDIT_TEXTBLOCK& txtBlk,
CRect& rcCoBlk)
{
if (!pCoDrawBlk)
{
ASSERT(FALSE);
return FALSE;
}
if (txtBlk.nPos < pCoDrawBlk->collBlock.lcStart.nCol)
{
return FALSE;
}
ProcessCollapsedText(pDC, pCoDrawBlk, rcCoBlk);
return TRUE;
}
void CXTPSyntaxEditCtrl::ProcessCollapsedText(CDC* pDC, XTP_EDIT_COLLAPSEDBLOCK* pCoDrawBlk,
CRect& rcCoBlk)
{
CString strText = pCoDrawBlk->collBlock.strCollapsedText; // "[..]"
CXTPFontDC fontDC(pDC, GetPaintManager()->GetFont());
rcCoBlk.right = rcCoBlk.left + pDC->GetTextExtent(strText).cx + 3;
pCoDrawBlk->rcCollMark = rcCoBlk;
}
CString CXTPSyntaxEditCtrl::GetCollapsedText(XTP_EDIT_COLLAPSEDBLOCK* pCoDrawBlk, int nMaxLinesCount) const
{
if (!pCoDrawBlk || !m_pBuffer)
{
ASSERT(FALSE);
return _T("");
}
CString strCoText;
int nLine1 = pCoDrawBlk->collBlock.lcStart.nLine;
int nLine2 = pCoDrawBlk->collBlock.lcEnd.nLine;
int nLine2max = min(nLine2, nLine1 + nMaxLinesCount-1);
int nCol1 = pCoDrawBlk->collBlock.lcStart.nCol;
int nCol2 = pCoDrawBlk->collBlock.lcEnd.nCol;
for (int nLine = nLine1; nLine <= nLine2max; nLine++)
{
CString strTmp = m_pBuffer->GetLineText(nLine);
int nTextLen = strTmp.GetLength();
if (nTextLen)
{
if (nLine == nLine2)
{
ASSERT(nCol2 < nTextLen+2);
nCol2 = max(0, min(nCol2, nTextLen-1));
strTmp = strTmp.Left(nCol2+1);
}
if (nLine == nLine1)
{
nTextLen = strTmp.GetLength();
ASSERT(nCol1 < nTextLen+2);
if (nCol1 < nTextLen)
{
strTmp = strTmp.Mid(nCol1);
}
else
{
strTmp.Empty();
}
}
}
if (!strCoText.IsEmpty())
{
strCoText += _T("\r\n");
}
strCoText += strTmp;
}
return strCoText;
}
int CXTPSyntaxEditCtrl::ExpandChars(CDC* pDC, LPCTSTR pszChars, int nCurPos, CString& strBuffer)
{
int nTabSize = GetTabSize();
const int nLength = (int)_tcslen(pszChars);
if (nLength == 0)
return 0;
int nActualOffset = nCurPos;
int I;
for (I = 0; I < nLength; I++)
{
if (pszChars[I] == _T('\t'))
nActualOffset += (nTabSize - nActualOffset % nTabSize);
else
nActualOffset ++;
}
int nActualLength = nActualOffset - nCurPos;
for (I = 0; I < nLength; I++)
{
if (pszChars[I] == _T('\t'))
{
int nSpaces = nTabSize - (nCurPos % nTabSize);
BOOL bFirstChar = TRUE;
while (nSpaces > 0)
{
if (bFirstChar && IsEnabledWhiteSpace() && !pDC->IsPrinting())
{
strBuffer += (TCHAR)(unsigned char)0xBB;
bFirstChar = FALSE;
}
else
strBuffer += _T(' ');
nSpaces--;
nCurPos++;
}
}
else
{
if (IsEnabledWhiteSpace() && pszChars[I] == _T(' ') && !pDC->IsPrinting())
strBuffer += (TCHAR)(unsigned char)0xB7;
else
strBuffer += pszChars[I];
nCurPos++;
}
}
return nActualLength;
}
void CXTPSyntaxEditCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
if (IsViewOnly() && !m_bAllowExpandCollapse)
return;
if (!IsViewOnly())
{
SetFocus();
// Manage AutoCompleteView
if (m_pAutoComplete->IsActive())
{
CRect rcACcomplete;
m_pAutoComplete->GetWindowRect(&rcACcomplete);
ScreenToClient(&rcACcomplete);
if (rcACcomplete.PtInRect(point))
return;
else
m_pAutoComplete->Hide();
}
m_bDragging = FALSE;
m_bRightButtonDrag = FALSE;
m_nAutoIndentCol = 0;
m_pSelection->bSelectingRunning = FALSE;
if (m_pSelection->IsSelExist())
Invalidate(FALSE);
NotifySelInit();
SetCapture();
}
BOOL bCtrlKey = (::GetKeyState(VK_CONTROL) & KF_UP) != 0;
BOOL bShiftKey = (::GetKeyState(VK_SHIFT) & KF_UP) != 0;
BOOL bAltKey = (::GetKeyState(VK_MENU) & KF_UP) != 0;
CXTPClientRect rcClient(this);
CRect rcBookmark, rcLineNum, rcNodes, rcText;
rcClient.bottom = rcClient.top + m_pDrawTextProcessor->GetRowHeight() * m_pDrawTextProcessor->GetRowsCount(FALSE);
CalcEditRects(&rcBookmark, &rcLineNum, &rcNodes, &rcText, &rcClient);
CRect rcLineNumAndNodes(rcLineNum);
rcLineNumAndNodes.right = rcNodes.right;
int nNewRow = 0, nNewCol = 0, nNewDispRow = 0, nNewDispCol = 0;
RowColFromPoint(point, &nNewRow, &nNewCol, &nNewDispRow, &nNewDispCol);
BOOL bSelFromLeftBar = rcLineNumAndNodes.PtInRect(point);
// TRACE(_T("*** OnLButtonDown. RowColFromPoint: nNewRow=%d, nNewCol=%d, nNewDispRow=%d, nNewDispCol=%d \n"),
// nNewRow, nNewCol, nNewDispRow, nNewDispCol);
if (!IsViewOnly())
{
if (GetCurrentDocumentRow() != nNewRow || m_nDispCol != nNewDispCol)
{
// reset undo buffer group mode processing
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
}
if (rcBookmark.PtInRect(point))
{
m_pSelection->Reset_disp(nNewRow, nNewDispCol);
if (!NotifyMarginLBtnClick(nNewRow, nNewDispRow))
{
AddRemoveBreakPoint(nNewRow);
SetCurPos(nNewRow, 1);
}
CWnd::OnLButtonDown(nFlags, point);
NotifyMouseEvent(XTP_EDIT_NM_LBUTTONDOWN, nFlags, point);
return;
}
}
if (!IsViewOnly() || (IsViewOnly() && m_bAllowExpandCollapse))
{
if (GetCollapsibleNodes() && rcNodes.PtInRect(point))
{
CXTPEmptyRect rcNode;
DWORD dwType = XTP_EDIT_ROWNODE_NOTHING;
if (GetRowNodes(nNewRow, dwType) && (dwType & (XTP_EDIT_ROWNODE_COLLAPSED | XTP_EDIT_ROWNODE_EXPANDED)))
{
GetLineNodeRect(nNewDispRow-1, rcNode);
}
if (rcNode.PtInRect(point) && m_pBuffer)
{
m_pSelection->Reset_disp(m_pSelection->GetEnd_disp().nLine, m_pSelection->GetEnd_disp().nCol);
// expand/collapse a node
CollapseExpandBlock(nNewRow);
SetCurPos(nNewRow, 1);
CWnd::OnLButtonDown(nFlags, point);
NotifyMouseEvent(XTP_EDIT_NM_LBUTTONDOWN, nFlags, point);
return;
}
}
}
if (!IsViewOnly())
{
if (rcText.PtInRect(point) && m_pSelection->IsInSel_disp(nNewRow, nNewDispCol))
{
m_pSelection->bSelectingRunning = FALSE;
if (!m_bEnableOleDrag)
m_bDragging = TRUE;
else
NotifyParent(XTP_EDIT_NM_STARTOLEDRAG);
CWnd::OnLButtonDown(nFlags, point);
NotifyMouseEvent(XTP_EDIT_NM_LBUTTONDOWN, nFlags, point);
return;
}
if (bAltKey)
{
m_pSelection->Reset_disp(nNewRow, nNewDispCol);
m_pSelection->bSelectingRunning = TRUE;
m_pSelection->bBlockSelectionMode = TRUE;
}
else if (bShiftKey)
{
m_pSelection->SetEnd_disp(nNewRow, nNewDispCol);
m_pSelection->bSelectingRunning = TRUE;
m_pSelection->bBlockSelectionMode = FALSE;
m_pSelection->bWordSelectionMode = bCtrlKey;
}
else
{
m_pSelection->Reset_disp(nNewRow, nNewDispCol);
m_pSelection->bSelectingRunning = TRUE;
m_pSelection->bWordSelectionMode = bCtrlKey;
if (bSelFromLeftBar)
m_pSelection->nSelStartTextRowFromLeftBar = m_pSelection->GetStart_str().nLine;
}
// TRACE(_T("Selection: (row=%d, strPos=%d, DispCol=%d)-(row=%d, strPos=%d, DispCol=%d) \n"),
// m_pSelection->GetStart_str().nLine, m_pSelection->GetStart_str().nCol, m_pSelection->GetStart_disp().nCol,
// m_pSelection->GetEnd_str().nLine, m_pSelection->GetEnd_str().nCol, m_pSelection->GetEnd_disp().nCol);
if (m_pSelection->bWordSelectionMode)
{
XTP_EDIT_LINECOL lcWord1, lcWord2;
BOOL bOverSpace = FALSE;
UINT nFindDir = m_pSelection->IsSelNormal() ? XTP_EDIT_FINDWORD_NEXT : XTP_EDIT_FINDWORD_PREV;
BOOL bFind = FindWordEx_str(nFindDir, m_pSelection->GetEnd_str(), lcWord1, lcWord2, bOverSpace);
// TRACE(_T("1-FindWordEx_str = %d (%d, %d - %d, %d)"), bFind,
// lcWord1.nLine, lcWord1.nCol, lcWord2.nLine, lcWord2.nCol);
if (bFind && lcWord1.IsValidData() && lcWord1 != m_pSelection->GetNormalStart_str())
{
if (m_pSelection->IsSelNormal())
m_pSelection->SetStart_str(lcWord1.nLine, lcWord1.nCol-1);
else
m_pSelection->SetEnd_str(lcWord1.nLine, lcWord1.nCol-1);
}
if (lcWord2.IsValidData() && lcWord2 != m_pSelection->GetNormalEnd_str())
{
if (m_pSelection->IsSelNormal())
m_pSelection->SetEnd_str(lcWord2.nLine, lcWord2.nCol-1);
else
m_pSelection->SetStart_str(lcWord2.nLine, lcWord2.nCol-1);
}
}
SetCurrentDocumentRow(nNewRow);
m_nDispCol = m_pSelection->GetEnd_disp().nCol;
m_nCurrentCol = m_pSelection->GetEnd_str().nCol + 1;
SetCurCaretPos(m_pSelection->GetEnd_disp().nLine, m_nDispCol, TRUE, FALSE);
if (m_pSelection->bSelectingRunning)
SetTimer(TIMER_SELECTION_ID, TIMER_SELECTION_TIME, NULL);
Invalidate(FALSE);
CWnd::OnLButtonDown(nFlags, point);
NotifyMouseEvent(XTP_EDIT_NM_LBUTTONDOWN, nFlags, point);
}
}
void CXTPSyntaxEditCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
if (IsViewOnly())
return;
KillTimer(TIMER_SELECTION_ID);
int nRow = ProcessCollapsedBlockDblClick(point);
if (nRow > 0)
{
// close tooltip.
ShowCollapsedToolTip(CPoint(0, 0));
}
else
{
// Select the word
SelectWord(point);
}
CWnd::OnLButtonDblClk(nFlags, point);
NotifyMouseEvent(XTP_EDIT_NM_LBUTTONDBLCLICK, nFlags, point);
}
void CXTPSyntaxEditCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
if (IsViewOnly())
return;
if (!GetCapture() || GetCapture() != this || GetFocus() != this)
return;
if (GetCapture() == this)
ReleaseCapture();
int nNewRow = 0, nNewCol = 0, nNewDispRow = 0, nNewDispCol = 0;
BOOL bRowCol = RowColFromPoint(point, &nNewRow, &nNewCol, &nNewDispRow, &nNewDispCol);
if (bRowCol && m_pSelection->IsInSel_disp(nNewRow, nNewDispCol) &&
!m_pSelection->bSelectingRunning && !m_bDragging) // dragging
{
m_pSelection->Reset_disp(m_pSelection->GetStart_disp().nLine, m_pSelection->GetStart_disp().nCol);
}
else
{
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, FALSE);
}
m_pSelection->bSelectingRunning = FALSE;
KillTimer(TIMER_SELECTION_ID);
m_dwAutoScrollDirection = 0;
KillTimer(TIMER_AUTOSCROLL_ID);
//-----------------------------------------------------------------------
if (m_bDragging)
{
if (m_bDroppable)
{
BOOL bCtrlKey = (::GetKeyState(VK_CONTROL) & KF_UP) != 0;
CopyOrMoveText(bCtrlKey);
}
else
{
m_pSelection->Reset_disp(GetCurrentDocumentRow(), m_nDispCol);
}
}
m_bDragging = FALSE;
m_bDroppable = FALSE;
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
Invalidate(FALSE);
UpdateWindow();
CWnd::OnLButtonUp(nFlags, point);
NotifyMouseEvent(XTP_EDIT_NM_LBUTTONUP, nFlags, point);
}
void CXTPSyntaxEditCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if (IsViewOnly())
return;
if (m_bDragging || m_bRightButtonDrag)
{
m_bDragging = TRUE;
CXTPClientRect rcWnd(this);
if (rcWnd.PtInRect(point))
{
int nNewRow = 0, nNewCol = 0, nNewDispCol = 0;
RowColFromPoint(point, &nNewRow, &nNewCol, NULL, &nNewDispCol);
//TRACE(_T("DropPOS: nNewRow=%d, nNewCol=%d, nNewDispCol=%d \n"), nNewRow, nNewCol, nNewDispCol);
if (nNewRow != m_ptDropPos.y || nNewDispCol != m_ptDropPos.x)
{
m_nDispCol = nNewDispCol;
m_ptDropPos.x = m_nDispCol;
m_ptDropPos.y = nNewRow;
//SetCurrentDocumentRow(nNewRow);
SetCurCaretPos(m_ptDropPos.y, m_ptDropPos.x, FALSE, FALSE);
}
m_bDroppable = !m_pSelection->IsInSel_disp(m_ptDropPos.y, m_ptDropPos.x);
OnSetCursor(0, 0, 0);
}
else
{
m_bDroppable = FALSE;
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO));
}
}
// else if (m_pSelection->bSelectingRunning)
// {
// OnTimer(TIMER_SELECTION_ID);
// }
ShowCollapsedToolTip(point);
CWnd::OnMouseMove(nFlags, point);
NotifyMouseEvent(XTP_EDIT_NM_MOUSEMOVE, nFlags, point);
}
XTP_EDIT_COLLAPSEDBLOCK* CXTPSyntaxEditCtrl::GetBlockFromPt(const CPoint& ptMouse) const
{
// enumerate all collapsed blocks coordinates
// to find the one where mouse into
XTP_EDIT_COLLAPSEDBLOCK* pCoDrawBlk = NULL;
XTP_EDIT_LMPARAM LMCoParam;
int nActualRow = 0;
for (int i = 0; i < m_nCollapsedTextRowsCount; i++)
{
int nRow = m_arCollapsedTextRows[i];
if (nRow <= nActualRow)
{
continue;
}
if (!HasRowMark(nRow, xtpEditLMT_Collapsed, &LMCoParam))
{
continue;
}
// get count of collapsed rows under this row
int nHiddenRows = 0;
if (!GetCollapsedBlockLen(nRow, nHiddenRows))
{
continue;
}
nActualRow = nRow + nHiddenRows;
// get collapsed block pointer
pCoDrawBlk = (XTP_EDIT_COLLAPSEDBLOCK*)LMCoParam.GetPtr();
if (!pCoDrawBlk)
{
ASSERT(FALSE);
continue;
}
CRect crCollapsed(pCoDrawBlk->rcCollMark);
if (crCollapsed.PtInRect(ptMouse))
{
return pCoDrawBlk;
}
}
return NULL;
}
int CXTPSyntaxEditCtrl::ProcessCollapsedBlockDblClick(const CPoint& ptMouse)
{
// Find required collapsed block by coordinates
XTP_EDIT_COLLAPSEDBLOCK* pCoDrawBlk = GetBlockFromPt(ptMouse);
if (pCoDrawBlk)
{
int nRow = pCoDrawBlk->collBlock.lcStart.nLine;
CollapseExpandBlock(nRow);
return nRow;
}
return 0;
}
AFX_STATIC CString AFX_CDECL TrimLeftIndent(const CString& csText)
{
CString csTrimmedText(csText);
int nLastLine = csTrimmedText.ReverseFind('\n');
CString csTrimText(csTrimmedText.Right(csTrimmedText.GetLength() - nLastLine).SpanIncluding(_T("\n \t")));
csTrimmedText.Replace(csTrimText, _T("\n"));
return csTrimmedText;
}
void CXTPSyntaxEditCtrl::ShowCollapsedToolTip(const CPoint& ptMouse)
{
if (ptMouse == m_ptPrevMouse)
{
return;
}
// Find required collapsed block by coordinates
XTP_EDIT_COLLAPSEDBLOCK* pCoDrawBlk = GetBlockFromPt(ptMouse);
if (pCoDrawBlk)
{
m_ptPrevMouse = ptMouse;
// set tooltip rect
CRect rcTip(ptMouse, ptMouse);
rcTip.right += 200;
rcTip.bottom += 200;
rcTip += CSize(18, 18);
ClientToScreen(&rcTip);
m_pToolTip->SetHoverRect(rcTip);
// set tooltip text
CString strToolText(GetCollapsedText(pCoDrawBlk));
m_pToolTip->Activate(TrimLeftIndent(strToolText));
}
// Then Hide Tip if it is displayed for some other block
if (ptMouse != m_ptPrevMouse)
{
m_pToolTip->Hide();
}
}
void CXTPSyntaxEditCtrl::OnRButtonDown(UINT nFlags, CPoint point)
{
m_bDragging = FALSE;
m_nAutoIndentCol = 0;
KillTimer(TIMER_SELECTION_ID);
int iRow, iCol;
RowColFromPoint(point, &iRow, &iCol);
// if (!m_pSelection->IsSelExist() || !m_pSelection->IsInSel_str(iRow, iCol))
if (!m_pSelection->IsSelExist()
|| !m_pSelection->IsInSel_str(iRow, iCol-1))
// iCol-1: otherwise selection was cleared with click on the last character
// but retained when clicking one character in front of the selection!
{
LPCTSTR szLineText = GetLineText(iRow);
//SetCurrentDocumentRow(iRow);
m_nDispCol = CalcDispCol(szLineText, iCol);
m_nCurrentCol = CalcAbsCol(szLineText, iCol);
SetCurCaretPos(iRow, m_nDispCol);
//Unselect();
m_pSelection->Reset_disp(iRow, m_nDispCol);
NotifySelInit();
}
SetCapture();
if (m_pSelection->IsSelExist() && m_pSelection->IsInSel_str(iRow, iCol))
{
m_bRightButtonDrag = TRUE;
if (m_bEnableOleDrag)
{
NotifyParent(XTP_EDIT_NM_STARTOLEDRAG);
}
}
// if (!m_pSelection->IsSelExist() && !m_bEnableOleDrag)
// {
// RowColFromPoint(point, &iRow, &iCol);
// // SetCurPos will determine valid column
// SetCurPos(iRow, iCol);
// }
CWnd::OnRButtonDown(nFlags, point);
NotifyMouseEvent(XTP_EDIT_NM_RBUTTONDOWN, nFlags, point);
}
void CXTPSyntaxEditCtrl::OnRButtonUp(UINT nFlags, CPoint point)
{
CWnd::OnRButtonUp(nFlags, point);
NotifyMouseEvent(XTP_EDIT_NM_RBUTTONUP, nFlags, point);
}
void CXTPSyntaxEditCtrl::Scroll(int x, int y)
{
m_bScrolling = TRUE;
if (y > 0)
ShiftCurrentVisibleRowDown(y);
else if (y < 0)
ShiftCurrentVisibleRowUp(-y);
if (x)
{
SCROLLINFO info;
ZeroMemory(&info, sizeof(SCROLLINFO));
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_ALL;
GetScrollInfo(SB_HORZ, &info);
int nStep = m_pDrawTextProcessor->GetTextMetrics().tmAveCharWidth;
int nCurrPos = m_pDrawTextProcessor->GetScrollXOffset();
nCurrPos += x * nStep;
nCurrPos = max(0, nCurrPos);
// TRACE(_T("SCROLL.X. from %d -> %d \n"), (int)m_pDrawTextProcessor->GetScrollXOffset(), nCurrPos);
SetScrollPos(SB_HORZ, nCurrPos);
m_pDrawTextProcessor->SetScrollXOffset(nCurrPos);
}
//RecalcVertScrollPos();
//RecalcHorzScrollPos();
Invalidate(FALSE);
UpdateWindow();
RecalcScrollBars();
int nTopDocRow = GetDocumentRow(1);
int nBottomDocRow = GetDocumentRow(GetRowPerPage());
int nCurDocRow = GetCurrentDocumentRow();
if (nCurDocRow >= nTopDocRow && nCurDocRow <= nBottomDocRow)
{
SetCurCaretPos(nCurDocRow, m_nDispCol, FALSE, FALSE);
}
DWORD dwUpdate = 0;
if (y != 0)
dwUpdate |= XTP_EDIT_UPDATE_HORZ;
if (x != 0)
dwUpdate |= XTP_EDIT_UPDATE_VERT;
if (dwUpdate != 0)
UpdateScrollPos(dwUpdate);
m_bScrolling = FALSE;
}
BOOL CXTPSyntaxEditCtrl::RowColFromPoint(CPoint pt, int *pRow, int *pCol,
int *pDispRow, int *pDispCol, BOOL bVirtualSpace)
{
if (bVirtualSpace < 0)
bVirtualSpace = _IsVirtualSpaceActive();
int nDispRow0 = 0, nDispCol0 = 0;
if (!m_pDrawTextProcessor->HitTestRow(pt.y, nDispRow0))
{
nDispRow0 = pt.y < m_pDrawTextProcessor->GetTextRect().top ? 0 : m_pDrawTextProcessor->GetRowsCount(FALSE) - 1;
}
int nRow = GetDocumentRow(nDispRow0 + 1);
if (nRow < 1 || nRow > GetRowCount())
nRow = nRow < 1 ? 1 : GetRowCount();
nDispRow0 = GetVisibleRow(nRow) - 1;
UpdateRowInfoInternally(nRow); // to ensure than x positions are valid
BOOL bRet = m_pDrawTextProcessor->ColFromXPos(nDispRow0, pt.x, nDispCol0, bVirtualSpace);
if (!bRet)
{
if (pt.x < m_pDrawTextProcessor->GetTextRect().left)
{
nDispCol0 = 0;
}
else if (pt.x > m_pDrawTextProcessor->GetTextRect().right)
{
int nX1 = max(0, m_pDrawTextProcessor->GetTextRect().right - 1);
m_pDrawTextProcessor->ColFromXPos(nDispRow0, nX1, nDispCol0, bVirtualSpace);
}
}
int nCol0 = m_pDrawTextProcessor->DispPosToStrPos(nDispRow0, nDispCol0, bVirtualSpace);
// to align to TABs positions
nDispCol0 = m_pDrawTextProcessor->StrPosToDispPos(nDispRow0, nCol0, bVirtualSpace);
if (pRow)
*pRow = nRow;
if (pCol)
*pCol = nCol0 + 1;
if (pDispRow)
*pDispRow = nDispRow0 + 1;
if (pDispCol)
*pDispCol = nDispCol0 + 1;
return bRet;
}
void CXTPSyntaxEditCtrl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
if (m_bmpCache.m_hObject)
m_bmpCache.DeleteObject();
if (!GetPaintManager()->GetFont()->GetSafeHandle())
return;
CRect rcText;
CalcEditRects(NULL, NULL, NULL, &rcText);
m_pDrawTextProcessor->SetTextRect(rcText);
RecalcVertScrollPos();
Invalidate(FALSE);
UpdateWindow();
RecalcHorzScrollPos();
}
int CXTPSyntaxEditCtrl::GetScrollPos(int nBar) const
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
return pParentWnd->GetScrollPos(nBar);
}
return CWnd::GetScrollPos(nBar);
}
void CXTPSyntaxEditCtrl::GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
pParentWnd->GetScrollRange(nBar, lpMinPos, lpMaxPos);
}
else
{
CWnd::GetScrollRange(nBar, lpMinPos, lpMaxPos);
}
}
void CXTPSyntaxEditCtrl::ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect, LPCRECT lpClipRect)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
pParentWnd->ScrollWindow(xAmount, yAmount, lpRect, lpClipRect);
}
else
{
CWnd::ScrollWindow(xAmount, yAmount, lpRect, lpClipRect);
}
}
int CXTPSyntaxEditCtrl::ScrollWindowEx(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, CRgn *prgnUpdate, LPRECT lpRectUpdate, UINT flags)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
return pParentWnd->ScrollWindowEx(dx, dy, lpRectScroll, lpRectClip, prgnUpdate, lpRectUpdate, flags);
}
return CWnd::ScrollWindowEx(dx, dy, lpRectScroll, lpRectClip, prgnUpdate, lpRectUpdate, flags);
}
BOOL CXTPSyntaxEditCtrl::GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, UINT nMask)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
return pParentWnd->GetScrollInfo(nBar, lpScrollInfo, nMask);
}
return CWnd::GetScrollInfo(nBar, lpScrollInfo, nMask);
}
int CXTPSyntaxEditCtrl::GetScrollLimit(int nBar)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
return pParentWnd->GetScrollLimit(nBar);
}
return CWnd::GetScrollLimit(nBar);
}
BOOL CXTPSyntaxEditCtrl::SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
return pParentWnd->SetScrollInfo(nBar, lpScrollInfo, bRedraw);
}
return CWnd::SetScrollInfo(nBar, lpScrollInfo, bRedraw);
}
int CXTPSyntaxEditCtrl::SetScrollPos(int nBar, int nPos, BOOL bRedraw)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
return pParentWnd->SetScrollPos(nBar, nPos, bRedraw);
}
return CWnd::SetScrollPos(nBar, nPos, bRedraw);
}
void CXTPSyntaxEditCtrl::SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
pParentWnd->SetScrollRange(nBar, nMinPos, nMaxPos, bRedraw);
}
else
{
CWnd::SetScrollRange(nBar, nMinPos, nMaxPos, bRedraw);
}
}
void CXTPSyntaxEditCtrl::ShowScrollBar(UINT nBar, BOOL bShow)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
pParentWnd->ShowScrollBar(nBar, bShow);
}
else
{
CWnd::ShowScrollBar(nBar, bShow);
}
}
void CXTPSyntaxEditCtrl::EnableScrollBarCtrl(int nBar, BOOL bEnable)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
pParentWnd->EnableScrollBarCtrl(nBar, bEnable);
DWORD dwScrollBar = (nBar == SB_HORZ) ? WS_HSCROLL : 0;
dwScrollBar |= (nBar == SB_VERT) ? WS_VSCROLL : 0;
dwScrollBar |= (nBar == SB_BOTH) ? (WS_HSCROLL | WS_VSCROLL) : 0;
_EnableScrollBarNotify((DWORD)dwScrollBar, bEnable ? (DWORD)dwScrollBar : 0);
}
else
{
CWnd::EnableScrollBarCtrl(nBar, bEnable);
}
}
CScrollBar* CXTPSyntaxEditCtrl::GetScrollBarCtrl(int nBar) const
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
return pParentWnd->GetScrollBarCtrl(nBar);
}
return CWnd::GetScrollBarCtrl(nBar);
}
void CXTPSyntaxEditCtrl::RepositionBars(UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver, UINT nFlag, LPRECT lpRectParam, LPCRECT lpRectClient, BOOL bStretch)
{
CWnd* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && IsCreateScrollbarOnParent())
{
pParentWnd->RepositionBars(nIDFirst, nIDLast, nIDLeftOver, nFlag, lpRectParam, lpRectClient, bStretch);
}
else
{
CWnd::RepositionBars(nIDFirst, nIDLast, nIDLeftOver, nFlag, lpRectParam, lpRectClient, bStretch);
}
}
BOOL CXTPSyntaxEditCtrl::DeleteSelection()
{
if (!m_pSelection->IsSelExist())
return TRUE;
int nFlags = (m_pSelection->bBlockSelectionMode ? xtpEditTextAsBlock : 0) | xtpEditDispCol;
if (!DeleteBuffer(m_pSelection->GetNormalStart_disp().nLine, m_pSelection->GetNormalStart_disp().nCol,
m_pSelection->GetNormalEnd_disp().nLine, m_pSelection->GetNormalEnd_disp().nCol,
nFlags))
{
return FALSE;
}
m_pSelection->Reset_disp(m_pSelection->GetNormalStart_disp().nLine, m_pSelection->GetNormalStart_disp().nCol);
SetCurrentDocumentRow(m_pSelection->GetNormalStart_disp().nLine);
EnsureVisibleRow(GetCurrentDocumentRow());
SetCurCaretPos(GetCurrentDocumentRow(), m_pSelection->GetStart_disp().nCol);
Invalidate(FALSE);
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::DeleteBuffer(int iRowFrom, int iColFrom, int iRowTo, int iColTo,
int nFlags )
{
int iTempRow1 = iRowFrom, iTempRow2 = iRowTo;
int iTempCol1 = iColFrom, iTempCol2 = iColTo;
if (iTempRow2 < iTempRow1)
{
iRowFrom = iTempRow2;
iColFrom = iTempCol2;
iRowTo = iTempRow1;
iColTo = iTempCol1;
}
else if (iTempRow1 == iTempRow2)
{
iColFrom = min(iTempCol1, iTempCol2);
iColTo = max(iTempCol1, iTempCol2);
}
if ((nFlags & xtpEditTextAsBlock) &&
(iColTo < iColFrom))
{
// swap them
int nTemp = iColTo;
iColTo = iColFrom;
iColFrom = nTemp;
}
if (!CanEditDoc())
{
return FALSE;
}
BOOL bDispCol = (nFlags & xtpEditDispCol) != 0;
int nColFrom_str = bDispCol ? CalcAbsCol(iRowFrom, iColFrom) : iColFrom;
int nColTo_str = bDispCol ? CalcAbsCol(iRowTo, iColTo) : iColTo;
//**----------------------
OnBeforeEditChanged(iRowFrom, nColFrom_str);
//**----------------------
ASSERT((nFlags & xtpEditTextAsBlock) && bDispCol || !(nFlags & xtpEditTextAsBlock));
if ((nFlags & xtpEditTextAsBlock) && iRowFrom != iRowTo)
{
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(TRUE);
for (int i = iRowFrom; i <= iRowTo; i++)
{
m_pBuffer->DeleteText(i, iColFrom, i, iColTo, TRUE, bDispCol);
}
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_DELETE_TEXT_BLOCK);
}
else
{
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
m_pBuffer->DeleteText(iRowFrom, iColFrom, iRowTo, iColTo, TRUE, bDispCol);
}
LPCTSTR szLineText = GetLineText(iRowFrom);
SetCurrentDocumentRow(iRowFrom);
m_nCurrentCol = nColFrom_str;
m_nDispCol = CalcDispCol(szLineText, m_nCurrentCol);
//**----------------------
OnEditChanged(iRowFrom, nColFrom_str, iRowTo, nColTo_str, xtpEditActDelete);
//**----------------------
UINT uFlags = XTP_EDIT_EDITACTION_DELETEROW | XTP_EDIT_EDITACTION_MODIFYROW;
NotifyEditChanged(iRowFrom, iRowTo, uFlags);
SetDocModified();
RecalcScrollBars();
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
if (nFlags & xtpEditRedraw)
{
Invalidate(FALSE);
UpdateWindow();
}
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::DeleteChar(int iRow, int iCol, XTPSyntaxEditDeletePos pos)
{
CString strText;
int iRowTo = iRow, iColTo = iCol;
if (pos == xtpEditDelPosAfter) // If deleting using DEL key
{
GetLineText(iRow, strText);
int nLineLen = (int)_tcsclen(strText);
if (iCol > nLineLen)
{
iRowTo = iRow + 1;
iColTo = 1;
if (iRowTo > GetRowCount())
return FALSE;
int nColFrom = nLineLen + 1;
int nAdditionalTabs = 0;
int nDispCol2 = CalcDispCol(strText, iCol);
int nDispCol0 = CalcDispCol(strText, nColFrom);
int nDC = nDispCol0 + GetTabSize() - (nDispCol0 -1) % GetTabSize();
if (nDC <= nDispCol2)
nAdditionalTabs++;
else
nDC = nDispCol0;
for (; nDC + GetTabSize() <= nDispCol2; nDC += GetTabSize())
nAdditionalTabs++;
int nAdditionalSpaces = max(0, nDispCol2 - nDC);
CString strTabs = CString(_T('\t'), nAdditionalTabs) + CString(_T(' '), nAdditionalSpaces);
//**----------------------
OnBeforeEditChanged(iRow, nColFrom);
XTP_EDIT_LINECOL lcFinal;
m_pBuffer->InsertText(strTabs, iRow, nColFrom, TRUE, &lcFinal);
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_FORMAT);
OnEditChanged(iRow, nColFrom, iRow, lcFinal.nCol, xtpEditActInsert);
//**----------------------
iCol = lcFinal.nCol;
}
else
iColTo++;
}
else // If deleting using back space
{
if (iCol == 1)
{
if (iRow > 1)
{
iRow--;
// if we are in the end of collapsed block, expand it...
CXTPSyntaxEditRowsBlockArray arCoBlocks;
GetCollapsableBlocksInfo(iRow, arCoBlocks);
int nCount = (int)arCoBlocks.GetSize();
for (int i = 0; i < nCount; i++)
{
XTP_EDIT_ROWSBLOCK coBlk = arCoBlocks[i];
if (coBlk.lcEnd.nLine == iRow) // Expand!
{
if (HasRowMark(coBlk.lcStart.nLine, xtpEditLMT_Collapsed))
GetLineMarksManager()->DeleteLineMark(coBlk.lcStart.nLine, xtpEditLMT_Collapsed);
}
}
//GetLineText(iRow, strText);
//iCol = (int)_tcsclen(strText) + 1;
iCol = m_pBuffer->GetLineTextLengthC(iRow) + 1;
}
else
return FALSE;
}
else
iCol--;
}
if (!DeleteBuffer(iRow, iCol, iRowTo, iColTo))
return FALSE;
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::DoUndoRedo(int nActionsCount, BOOL bUndoRedo)
{
CWaitCursor wait;
if (!CanEditDoc())
return FALSE;
CXTPSyntaxEditUndoRedoManager* pUndoMgr = m_pBuffer->GetUndoRedoManager();
if (!pUndoMgr)
return FALSE;
m_pSelection->Reset_disp(m_pSelection->GetEnd_disp().nLine, m_pSelection->GetEnd_disp().nCol);
m_nAutoIndentCol = 0;
int nCurDocRow = GetCurrentDocumentRow();
XTP_EDIT_LINECOL lcTotalFrom = XTP_EDIT_LINECOL::MAXPOS;
XTP_EDIT_LINECOL lcTotalTo = XTP_EDIT_LINECOL::MINPOS;
for (int nAction = 0; nAction < nActionsCount; nAction++)
{
XTP_EDIT_LINECOL lcFrom, lcTo;
// perform undo
int nEditAction = bUndoRedo ?
pUndoMgr->DoUndo(lcFrom, lcTo, this) :
pUndoMgr->DoRedo(lcFrom, lcTo, this);
// perform some total calculations
lcTotalFrom = min(lcTotalFrom, lcFrom);
lcTotalTo = max(lcTotalTo, lcTo);
// TODO: ???????????????????????????????????
// send update notifications
// Commented out to eliminate double call of OnEditChanged that
// leads to improper calculation of collapsible blocks borders
// if (nEditAction & XTP_EDIT_EDITACTION_INSERTTEXT)
// {
// OnEditChanged(lcFrom, lcTo, xtpEditActInsert);
// }
// else if (nEditAction & XTP_EDIT_EDITACTION_DELETETEXT)
// {
// OnEditChanged(lcFrom, lcTo, xtpEditActDelete);
// }
NotifyEditChanged(lcFrom.nLine, lcTo.nLine, nEditAction);
}
int nRowsAffected = lcTotalTo.nLine - lcTotalFrom.nLine;
m_nDispCol = CalcDispCol(GetCurrentDocumentRow(), m_nCurrentCol);
RecalcScrollBars();
if (GetCurrentDocumentRow() > GetRowCount())
{
SetCurrentDocumentRow(GetRowCount());
m_nCurrentCol = m_nDispCol = 1;
}
nCurDocRow = GetCurrentDocumentRow();
if (nActionsCount > 1)
{
ValidateCol(nCurDocRow, m_nDispCol, m_nCurrentCol);
SetCurCaretPos(nCurDocRow, m_nDispCol, FALSE/*, FALSE*/);
}
nCurDocRow = GetCurrentDocumentRow();
if ((nCurDocRow > 0 && m_nCurrentCol > 0) ||
!(nRowsAffected == 0 && nActionsCount == 1))
{
SetCurCaretPos(nCurDocRow, m_nDispCol);
}
Invalidate(FALSE);
UpdateWindow();
UpdateScrollPos();
SetDocModified(m_pBuffer->IsModified());
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::Undo(int nActionsCount)
{
if (CanUndo())
{
return DoUndoRedo(nActionsCount, TRUE);
}
return FALSE;
}
BOOL CXTPSyntaxEditCtrl::Redo(int nActionsCount)
{
if (CanRedo())
{
return DoUndoRedo(nActionsCount, FALSE);
}
return FALSE;
}
BOOL CXTPSyntaxEditCtrl::CanUndo() const
{
if (m_pBuffer && m_pBuffer->GetUndoRedoManager())
return CanEditDoc() && m_pBuffer->GetUndoRedoManager()->CanUndo();
return FALSE;
}
BOOL CXTPSyntaxEditCtrl::CanRedo() const
{
if (m_pBuffer && m_pBuffer->GetUndoRedoManager())
return CanEditDoc() && m_pBuffer->GetUndoRedoManager()->CanRedo();
return FALSE;
}
void CXTPSyntaxEditCtrl::Cut()
{
if (IsViewOnly())
return;
if (m_pSelection->IsSelExist())
{
Copy();
DeleteSelection();
UpdateWindow();
}
}
void CXTPSyntaxEditCtrl::Copy()
{
if (IsViewOnly())
return;
if (!m_pSelection->IsSelExist())
return;
CWaitCursor wait;
if (!OpenClipboard())
{
#ifdef _DEBUG
LPVOID lpMsgBuf;
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
::GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
AfxMessageBox((LPCTSTR)lpMsgBuf, MB_OK | MB_ICONINFORMATION );
// Free the buffer.
::LocalFree( lpMsgBuf );
#endif
return;
}
// prepare clipboard
::EmptyClipboard();
// retrieve the text string from buffer
CMemFile file(CalcAveDataSize(m_pSelection->GetNormalStart_str().nLine,
m_pSelection->GetNormalEnd_str().nLine));
BOOL bRes = m_pBuffer->GetBuffer(m_pSelection->GetNormalStart_disp(),
m_pSelection->GetNormalEnd_disp(), file,
m_pSelection->bBlockSelectionMode, TRUE);
if (!bRes)
return;
// Copy the buffer to clipboard
DWORD dwBytes = (DWORD)file.GetLength();
BYTE *pBytes = file.Detach();
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, dwBytes + sizeof(TCHAR));
if (!hMem)
return;
LPVOID lpSource = (LPVOID)::GlobalLock(hMem);
if (!lpSource)
return;
MEMCPY_S(lpSource, pBytes, dwBytes);
::ZeroMemory(((BYTE *)lpSource + dwBytes), sizeof(TCHAR));
free(pBytes);
UINT uCodePage = m_pBuffer->GetCodePage();
#ifdef _UNICODE
// Determine the byte requirement
int nLen = ::WideCharToMultiByte(uCodePage, 0, (LPWSTR)lpSource, -1, NULL, 0, NULL, NULL);
HGLOBAL hMBCSMem = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (nLen + 2)); // Maximum number of bytes is dwBytes
if (!hMBCSMem)
{
CloseClipboard();
return;
}
LPSTR lpMBCSSource = (LPSTR)::GlobalLock(hMBCSMem);
if (!lpMBCSSource)
return;
int nBytes = ::WideCharToMultiByte(uCodePage, 0, (LPWSTR)lpSource, -1, lpMBCSSource, nLen, NULL, NULL);
ASSERT(nBytes <= (int)dwBytes);
lpMBCSSource[nBytes] = _T('\0');
::GlobalUnlock(hMem);
::GlobalUnlock(hMBCSMem);
// lpSource is Unicode text
::SetClipboardData(CF_UNICODETEXT, hMem);
::SetClipboardData(CF_TEXT, hMBCSMem);
::SetClipboardData(CF_OEMTEXT, hMBCSMem);
#else
int nUBytes = (dwBytes + 2) * sizeof(WCHAR);
HGLOBAL hUnicodeMem = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, nUBytes);
if (!hUnicodeMem)
{
CloseClipboard();
return;
}
LPWSTR lpWSource = (LPWSTR)::GlobalLock(hUnicodeMem);
if (!lpWSource)
{
CloseClipboard();
return;
}
int nLen = ::MultiByteToWideChar(uCodePage, 0, (LPCSTR)lpSource, -1, lpWSource, nUBytes);
ASSERT(nLen <= (int)(nUBytes / sizeof(WCHAR)));
lpWSource[nLen] = _T('\0');
::GlobalUnlock(hMem);
::GlobalUnlock(hUnicodeMem);
// lpSource is MBCS text
::SetClipboardData(CF_TEXT, hMem);
::SetClipboardData(CF_OEMTEXT, hMem);
::SetClipboardData(CF_UNICODETEXT, hUnicodeMem);
#endif
if (m_pSelection->bBlockSelectionMode)
{
HGLOBAL hMem_BLK = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, 1);
if (!hMem_BLK)
{
CloseClipboard();
return;
}
BYTE* pMem_BLK = (BYTE*)::GlobalLock(hMem_BLK);
if (pMem_BLK)
{
*pMem_BLK = 1;
}
::GlobalUnlock(hMem_BLK);
CLIPFORMAT uCF_MSDEVColumnSelect = (CLIPFORMAT)::RegisterClipboardFormat(XTP_EDIT_CFMSDEVCOLSEL);
::SetClipboardData(uCF_MSDEVColumnSelect, hMem_BLK);
}
CloseClipboard();
}
void CXTPSyntaxEditCtrl::Paste()
{
CWaitCursor wait;
if (!OpenClipboard())
return;
BOOL bCBTextIsBlock = FALSE;
CLIPFORMAT uCF_MSDEVColumnSelect = (CLIPFORMAT)::RegisterClipboardFormat(XTP_EDIT_CFMSDEVCOLSEL);
HANDLE hMem_TextBlok = ::GetClipboardData(uCF_MSDEVColumnSelect);
if (hMem_TextBlok)
{
int nSize = (int)::GlobalSize(hMem_TextBlok);
BYTE* arColBlk = (BYTE*)::GlobalLock(hMem_TextBlok);
if (arColBlk && nSize)
{
bCBTextIsBlock = TRUE;
//TRACE(_T("MSDEVColumnSelect data [size=%d] = %d \n"), nSize, (int)arColBlk[0]);
}
}
#ifdef _UNICODE
HANDLE hMem = ::GetClipboardData(CF_UNICODETEXT);
#else
HANDLE hMem = ::GetClipboardData(CF_TEXT);
#endif
if (!hMem)
{
return;
}
LPTSTR szData = (LPTSTR)::GlobalLock(hMem);
BOOL bReplace = GetTabWithSpace();
BOOL bOverwrite = m_pBuffer->GetOverwriteFlag();
SetTabWithSpace(FALSE);
m_pBuffer->SetOverwriteFlag(FALSE);
if (bCBTextIsBlock)
{
InsertTextBlock(szData, GetCurrentDocumentRow(), m_nCurrentCol, m_pSelection->IsSelExist());
}
else
{
InsertString(szData, GetCurrentDocumentRow(), m_nCurrentCol, m_pSelection->IsSelExist());
}
SetTabWithSpace(bReplace);
m_pBuffer->SetOverwriteFlag(bOverwrite);
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_PASTE);
::GlobalUnlock(hMem);
CloseClipboard();
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
SetDocModified();
UpdateScrollPos(XTP_EDIT_UPDATE_HORZ|XTP_EDIT_UPDATE_VERT);
UpdateWindow();
}
void CXTPSyntaxEditCtrl::SetRowText(int nRow, LPCTSTR pcszText, BOOL bCanUndo)
{
if (!m_pBuffer)
return;
int nRowLen = m_pBuffer->GetLineTextLengthC(nRow, FALSE);
if (nRowLen)
{
//**----------------------
OnBeforeEditChanged(nRow, 1);
//**----------------------
if (bCanUndo)
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
m_pBuffer->DeleteText(nRow, 1, nRow, nRowLen + 1, bCanUndo, FALSE);
//**----------------------
OnEditChanged(nRow, 1, nRow + 1, 1, xtpEditActDelete);
//**----------------------
}
//**----------------------
OnBeforeEditChanged(nRow, 1);
//**----------------------
if (bCanUndo)
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
//XTP_EDIT_LINECOL finalLC;
m_pBuffer->InsertText(pcszText, nRow, 1, bCanUndo);//finalLC);
//**----------------------
OnEditChanged(nRow, 1, nRow + 1, 1, xtpEditActInsert);
//**----------------------
NotifyEditChanged(nRow, nRow, XTP_EDIT_EDITACTION_MODIFYROW);
}
void CXTPSyntaxEditCtrl::InsertRow(int nRow, LPCTSTR pcszText, BOOL bCanUndo)
{
if (!m_pBuffer)
return;
CString strLine = pcszText;
strLine += m_pBuffer->GetCurCRLF();
//**----------------------
OnBeforeEditChanged(nRow, 1);
//**----------------------
if (bCanUndo)
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
//XTP_EDIT_LINECOL finalLC;
m_pBuffer->InsertText(pcszText, nRow, 1, bCanUndo);//finalLC);
//**----------------------
OnEditChanged(nRow, 1, nRow + 1, 1, xtpEditActInsert);
//**----------------------
NotifyEditChanged(nRow, nRow, XTP_EDIT_EDITACTION_INSERTROW);
}
void CXTPSyntaxEditCtrl::RemoveRow(int nRow, BOOL bCanUndo)
{
if (!m_pBuffer)
return;
//**----------------------
OnBeforeEditChanged(nRow, 1);
//**----------------------
if (bCanUndo)
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
m_pBuffer->RemoveLine(nRow, bCanUndo);
//**----------------------
OnEditChanged(nRow, 1, nRow + 1, 1, xtpEditActDelete);
//**----------------------
NotifyEditChanged(nRow, nRow, XTP_EDIT_EDITACTION_DELETEROW);
}
void CXTPSyntaxEditCtrl::OnSetFocus(CWnd* pOldWnd)
{
CXTPSmartPtrInternalT<CCmdTarget> ptrThisLock(this, TRUE);
// TRACE (_T("CXTPSyntaxEditCtrl::OnSetFocus. this=%x, pOldWnd=%x \n"), this, pOldWnd);
::DestroyCaret();
m_bFocused = TRUE;
Invalidate(FALSE);
RestoreCursor();
NotifyCurRowCol(GetCurrentDocumentRow(), m_nDispCol);
if (m_bActivateOnFocus)
SetActive(TRUE);
UpdateWindow();
CWnd::OnSetFocus(pOldWnd);
#ifdef XTP_SYNTAXEDIT_SITENOTIFY_ONFOCUS
XTP_SYNTAXEDIT_SITENOTIFY_ONFOCUS(this, this, TRUE)
#endif
}
void CXTPSyntaxEditCtrl::OnKillFocus(CWnd* pNewWnd)
{
CXTPSmartPtrInternalT<CCmdTarget> ptrThisLock(this, TRUE);
CWnd::OnKillFocus(pNewWnd);
::DestroyCaret();
m_pAutoComplete->Hide();
m_bFocused = FALSE;
if (m_bActivateOnFocus)
SetActive(FALSE);
Invalidate(FALSE);
#ifdef XTP_SYNTAXEDIT_SITENOTIFY_ONFOCUS
XTP_SYNTAXEDIT_SITENOTIFY_ONFOCUS(this, this, FALSE)
#endif
}
BOOL CXTPSyntaxEditCtrl::OnNcActivate(BOOL bActive)
{
return CWnd::OnNcActivate(bActive);
}
int CXTPSyntaxEditCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
// SetFocus();
return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
}
BOOL CXTPSyntaxEditCtrl::IsSelectionExist() const
{
return m_pSelection->IsSelExist();
}
void CXTPSyntaxEditCtrl::SelectAll()
{
int nLastRow = GetRowCount();
LPCTSTR szLineText = GetLineText(nLastRow);
const int nEndCol = (int)_tcsclen(szLineText) + 1;
SetCurrentDocumentRow(nLastRow);
m_nCurrentCol = nEndCol;
m_nDispCol = CalcDispCol(szLineText, m_nCurrentCol);
m_pSelection->Reset_disp(1, 1);
m_pSelection->SetEnd_disp(nLastRow, m_nDispCol);
m_nAutoIndentCol = 0;
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
}
void CXTPSyntaxEditCtrl::SetFontIndirect(LPLOGFONT pLogfont, BOOL bUpdateReg/*=FALSE*/)
{
GetPaintManager()->CreateFontIndirect(pLogfont, bUpdateReg);
CWindowDC dc(NULL);
CXTPFontDC fontDC(&dc, GetPaintManager()->GetFont());
m_pDrawTextProcessor->RecalcRowHeight(&dc, GetPaintManager()->GetFont());
if (m_hWnd && ::IsWindow(m_hWnd))
{
//m_pToolTip->SetFont(GetPaintManager()->GetFontToolTip());
CalculateEditbarLength();
Invalidate(FALSE);
_UpdateIMEStatus();
}
}
void CXTPSyntaxEditCtrl::_UpdateIMEStatus()
{
m_bIMEsupported = m_pImmWrapper->ImmIsIME();
if (!m_bIMEsupported || !m_hWnd || !::IsWindow(m_hWnd))
return;
// IME Support
XTP_HIMC hIMC = m_pImmWrapper->ImmGetContext(m_hWnd);
if (hIMC)
{
LOGFONT lfFont;
::ZeroMemory(&lfFont, sizeof(lfFont));
BOOL bFont = GetPaintManager()->GetFont()->GetLogFont(&lfFont);
ASSERT(bFont);
if (bFont)
{
VERIFY(m_pImmWrapper->ImmSetCompositionFont(hIMC, &lfFont));
}
VERIFY(m_pImmWrapper->ImmReleaseContext(m_hWnd, hIMC));
}
}
LRESULT CXTPSyntaxEditCtrl::OnGetFont(WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam);
return (LRESULT)GetPaintManager()->GetFont()->GetSafeHandle();
}
LRESULT CXTPSyntaxEditCtrl::OnSetFont(WPARAM wParam, LPARAM lParam)
{
HFONT hFont = (HFONT)wParam;
LOGFONT lfFont;
LOGFONT *pLF = NULL; // set the default font if hFont == NULL
if (hFont)
{
::ZeroMemory(&lfFont, sizeof(LOGFONT));
if (!::GetObject(hFont, sizeof(LOGFONT), &lfFont))
{
ASSERT(FALSE);
return 0;
}
pLF = &lfFont;
}
SetFontIndirect(pLF, FALSE);
if (LOWORD(lParam))
UpdateWindow();
//Default();
return 0;
}
LRESULT CXTPSyntaxEditCtrl::OnInputLanguage(WPARAM, LPARAM)
{
_UpdateIMEStatus();
if (m_bIMEsupported)
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, FALSE);
Default();
return 1;
}
void CXTPSyntaxEditCtrl::SetDocModified(BOOL bModified)
{
XTP_EDIT_NMHDR_DOCMODIFIED dm;
// NMHDR codes
dm.nmhdr.code = XTP_EDIT_NM_SETDOCMODIFIED;
dm.nmhdr.hwndFrom = m_hWnd;
dm.nmhdr.idFrom = GetDlgCtrlID();
// modified flag
dm.bModified = bModified;
// Notify the parent window
if (::IsWindow(m_pParentWnd->GetSafeHwnd()))
{
m_pParentWnd->SendMessage(
WM_NOTIFY, (WPARAM)dm.nmhdr.idFrom, (LPARAM)&dm);
}
}
void CXTPSyntaxEditCtrl::InsertString(LPCTSTR szText, int iRow, int iCol, BOOL bDeleteSelection)
{
if (!CanEditDoc())
return;
int nPrevRow = GetCurrentDocumentRow();
if (nPrevRow != iRow)
SetCurrentDocumentRow(iRow);
m_nCurrentCol = iCol;
if (bDeleteSelection)
DeleteSelection();
// At first determine what type of CRLF it has
const int nTextLen = (int)_tcsclen(szText);
if (nTextLen == 0)
return;
int nRowFrom = GetCurrentDocumentRow();
int nColFrom = m_nCurrentCol;
//**----------------------
OnBeforeEditChanged(nRowFrom, nColFrom);
//**----------------------
if (GetAutoIndent() && m_nAutoIndentCol > 0)
{
CString strInsertText(
CString(_T('\t'), m_nInsertTabCount) +
CString(_T(' '), m_nInsertSpaceCount));
m_pBuffer->InsertText(strInsertText, GetCurrentDocumentRow(), m_nCurrentCol);
m_nCurrentCol = m_nInsertTabCount + m_nInsertSpaceCount + 1;
m_nAutoIndentCol = 0;
}
XTP_EDIT_LINECOL finalLC;
BOOL bInsRes = m_pBuffer->InsertText(szText, GetCurrentDocumentRow(),
m_nCurrentCol, TRUE, &finalLC);
if (bDeleteSelection)
m_pBuffer->GetUndoRedoManager()->ChainLastCommand();
if (bInsRes)
{
SetCurrentDocumentRow(finalLC.nLine);
m_nCurrentCol = finalLC.nCol;
m_nDispCol = CalcDispCol(GetLineText(finalLC.nLine), m_nCurrentCol);
}
RecalcScrollBars();
UINT nAction = XTP_EDIT_EDITACTION_MODIFYROW;
int nCurDocRow = GetCurrentDocumentRow();
if (nCurDocRow > nPrevRow)
nAction |= XTP_EDIT_EDITACTION_INSERTROW;
//**----------------------
OnEditChanged(nRowFrom, nColFrom, nCurDocRow, m_nCurrentCol, xtpEditActInsert);
//**----------------------
NotifyEditChanged(nPrevRow, nCurDocRow, nAction);
SetCurCaretPos(nCurDocRow, m_nDispCol, FALSE/*, FALSE*/);
}
void CXTPSyntaxEditCtrl::InsertTextBlock(LPCTSTR szText, int iRow, int iCol, BOOL bDeleteSelection)
{
if (!CanEditDoc())
return;
int nPrevRow = GetCurrentDocumentRow();
if (nPrevRow != iRow)
{
SetCurrentDocumentRow(iRow);
}
m_nCurrentCol = iCol;
if (bDeleteSelection)
{
DeleteSelection();
}
// At first determine what type of CRLF it has
const int nTextLen = (int)_tcsclen(szText);
if (nTextLen == 0)
return;
int nRowFrom = GetCurrentDocumentRow();
int nColFrom = m_nCurrentCol;
//**----------------------
OnBeforeEditChanged(nRowFrom, nColFrom);
//**----------------------
XTP_EDIT_LINECOL finalLC;
BOOL bInsRes = m_pBuffer->InsertTextBlock(szText, GetCurrentDocumentRow(),
iCol, TRUE, &finalLC);
UNREFERENCED_PARAMETER(bInsRes);
if (bDeleteSelection)
m_pBuffer->GetUndoRedoManager()->ChainLastCommand();
RecalcScrollBars();
UINT nAction = XTP_EDIT_EDITACTION_MODIFYROW;
int nCurDocRow = GetCurrentDocumentRow();
if (nCurDocRow > nPrevRow)
nAction |= XTP_EDIT_EDITACTION_INSERTROW;
//**----------------------
OnEditChanged(nRowFrom, nColFrom, nCurDocRow, m_nCurrentCol, xtpEditActInsert);
//**----------------------
NotifyEditChanged(nPrevRow, nCurDocRow, nAction);
SetCurCaretPos(nCurDocRow, m_nDispCol, FALSE/*, FALSE*/);
}
void CXTPSyntaxEditCtrl::UpdateScrollPos(DWORD dwUpdate/* = XTP_EDIT_UPDATE_ALL*/)
{
if (!::IsWindow(m_hWnd))
return;
XTP_EDIT_NMHDR_SETSCROLLPOS ssp;
// NMHDR codes
ssp.nmhdr.code = XTP_EDIT_NM_UPDATESCROLLPOS;
ssp.nmhdr.hwndFrom = m_hWnd;
ssp.nmhdr.idFrom = GetDlgCtrlID();
// Update flag
ssp.dwUpdate = dwUpdate;
// Notify the parent window
if (::IsWindow(m_pParentWnd->GetSafeHwnd()))
{
m_pParentWnd->SendMessage(
WM_NOTIFY, (WPARAM)ssp.nmhdr.idFrom, (LPARAM)&ssp);
}
}
void CXTPSyntaxEditCtrl::_EnableScrollBarNotify(DWORD dwScrollBar, DWORD dwState)
{
ASSERT(dwScrollBar != 0 && (dwScrollBar & (WS_VSCROLL|WS_HSCROLL)) != 0);
XTP_EDIT_NMHDR_ENABLESCROLLBAR nmEScroll;
// NMHDR codes
nmEScroll.nmhdr.code = XTP_EDIT_NM_ENABLESCROLLBAR;
nmEScroll.nmhdr.hwndFrom = m_hWnd;
nmEScroll.nmhdr.idFrom = GetDlgCtrlID();
// Update flag
nmEScroll.dwScrollBar = dwScrollBar;
nmEScroll.dwState = dwState;
// Notify the parent window
if (::IsWindow(m_pParentWnd->GetSafeHwnd()))
{
m_pParentWnd->SendMessage(
WM_NOTIFY, (WPARAM)nmEScroll.nmhdr.idFrom, (LPARAM)&nmEScroll);
}
}
void CXTPSyntaxEditCtrl::SetOverwriteMode(BOOL bOverwriteMode)
{
if (bOverwriteMode != m_pBuffer->GetOverwriteFlag() )
{
m_pBuffer->SetOverwriteFlag(bOverwriteMode);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE/*, FALSE*/);
}
}
BOOL CXTPSyntaxEditCtrl::OnEraseBkgnd(CDC* pDC)
{
UNREFERENCED_PARAMETER(pDC);
return TRUE;
}
XTP_EDIT_LINECOL CXTPSyntaxEditCtrl::_SubtractSelSizeFromPos(XTP_EDIT_LINECOL lcDispPos)
{
XTP_EDIT_LINECOL lcStart = m_pSelection->GetNormalStart_disp();
XTP_EDIT_LINECOL lcEnd = m_pSelection->GetNormalEnd_disp();
if (lcDispPos <= lcStart)
return lcDispPos;
if (lcDispPos < lcEnd && !m_pSelection->bBlockSelectionMode)
{
ASSERT(FALSE);
lcDispPos = lcEnd;
}
if (m_pSelection->bBlockSelectionMode)
{
if (lcDispPos.nLine >= lcStart.nLine && lcDispPos.nLine <= lcEnd.nLine)
{
if (lcDispPos.nCol >= lcEnd.nCol)
lcDispPos.nCol -= lcEnd.nCol - lcStart.nCol;
}
}
else
{
if (lcEnd.nLine != lcStart.nLine)
lcDispPos.nLine -= lcEnd.nLine - lcStart.nLine;
if (lcEnd.nLine == lcDispPos.nLine)
{
if (lcEnd.nLine == lcStart.nLine)
{
ASSERT(lcDispPos.nCol >= lcEnd.nCol);
lcDispPos.nCol -= lcEnd.nCol - lcStart.nCol;
}
else
{
lcDispPos.nCol -= lcEnd.nCol;
}
}
}
return lcDispPos;
}
void CXTPSyntaxEditCtrl::CopyOrMoveText(BOOL bCopy)
{
if (!m_pSelection->IsSelExist() || m_pSelection->IsInSel_disp(m_ptDropPos.y, m_ptDropPos.x))
return;
CMemFile memfile(CalcAveDataSize(m_pSelection->GetNormalStart_str().nLine,
m_pSelection->GetNormalEnd_str().nLine));
BOOL bRes = m_pBuffer->GetBuffer(m_pSelection->GetNormalStart_disp(),
m_pSelection->GetNormalEnd_disp(), memfile,
m_pSelection->bBlockSelectionMode);
if (!bRes)
return;
memfile.Write((const void *)_T("\0"), sizeof(TCHAR));
BYTE *pBytes = memfile.Detach();
CString strDropText = (LPTSTR)pBytes;
free(pBytes);
// First insert the text
if (m_ptDropPos.y > GetRowCount())
m_ptDropPos.y = GetRowCount();
XTP_EDIT_LINECOL lcDropPos_disp = XTP_EDIT_LINECOL::MakeLineCol(m_ptDropPos.y, m_ptDropPos.x);
BOOL bBlockSelectionMode = m_pSelection->bBlockSelectionMode;
if (!bCopy)
{
if (!(lcDropPos_disp < m_pSelection->GetNormalStart_disp()))
{
lcDropPos_disp = _SubtractSelSizeFromPos(lcDropPos_disp);
}
DeleteSelection(); // reset current selection
}
CString strText;
m_pBuffer->GetLineText(lcDropPos_disp.nLine, strText);
int nAbsDropCol = CalcAbsCol(strText, lcDropPos_disp.nCol);
//**----------------------
OnBeforeEditChanged(lcDropPos_disp.nLine, nAbsDropCol);
//**----------------------
BOOL bReplace = GetTabWithSpace();
SetTabWithSpace(FALSE);
XTP_EDIT_LINECOL finalLC;
BOOL bInsRes = FALSE;
if (bBlockSelectionMode)
{
bInsRes = m_pBuffer->InsertTextBlock(strDropText, lcDropPos_disp.nLine, nAbsDropCol,
TRUE, &finalLC);
}
else
{
bInsRes = m_pBuffer->InsertText(strDropText, lcDropPos_disp.nLine, nAbsDropCol,
TRUE, &finalLC);
}
SetTabWithSpace(bReplace);
if (!bCopy)
{
m_pBuffer->GetUndoRedoManager()->ChainLastCommand();
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_MOVE);
}
else
{
// It's a drag copy
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_COPY);
}
m_pSelection->Reset_str(lcDropPos_disp.nLine, nAbsDropCol - 1);
m_pSelection->SetEnd_str(finalLC.nLine, finalLC.nCol - 1);
m_pSelection->bBlockSelectionMode = bBlockSelectionMode;
int nRowFrom = m_pSelection->GetNormalStart_str().nLine;
int nRowTo = m_pSelection->GetNormalEnd_str().nLine;
//**----------------------
OnEditChanged(nRowFrom, m_pSelection->GetNormalStart_str().nCol + 1,
nRowTo, m_pSelection->GetNormalEnd_str().nCol + 1, xtpEditActInsert);
//**----------------------
CalculateEditbarLength();
SetCurCaretPos(m_pSelection->GetEnd_disp().nLine, m_pSelection->GetEnd_disp().nCol);
SetDocModified();
//**----------------------
// OnEditChanged(nRowFrom, m_pSelection->GetNormalStart_str().nCol,
// nRowTo, m_pSelection->GetNormalEnd_str().nCol, xtpEditActInsert);
//**----------------------
UINT nAction = (XTP_EDIT_EDITACTION_MODIFYROW | XTP_EDIT_EDITACTION_INSERTROW);
NotifyEditChanged(nRowFrom, nRowTo, nAction);
}
void CXTPSyntaxEditCtrl::OnContextMenu(CWnd* pWnd, CPoint point)
{
if (GetCapture() == this)
{
ReleaseCapture();
}
if (m_bRightButtonDrag && m_bDragging && m_bDroppable)
{
HandleDrop(FALSE);
}
else
{
CXTPClientRect rcWnd(this);
ClientToScreen(&rcWnd);
m_bDragging = FALSE;
if (point.x < 0 || point.y < 0) //keyboard ContextMenu button pressed
{
::GetCaretPos(&point);
ClientToScreen(&point);
if (point.x < 0 || point.y < 0)
point = rcWnd.CenterPoint();
}
if (m_pParentWnd && rcWnd.PtInRect(point))
{
CWnd::HideCaret();
m_pParentWnd->SendMessage(WM_CONTEXTMENU, (WPARAM)pWnd->GetSafeHwnd(), (LPARAM)MAKELONG(point.x, point.y));
CWnd::ShowCaret();
Invalidate(FALSE);
UpdateWindow();
}
}
m_bRightButtonDrag = FALSE;
}
void CXTPSyntaxEditCtrl::OnDragCopy()
{
CopyOrMoveText(TRUE);
m_bRightButtonDrag = FALSE;
}
void CXTPSyntaxEditCtrl::OnDragMove()
{
CopyOrMoveText(FALSE);
m_bRightButtonDrag = FALSE;
}
void CXTPSyntaxEditCtrl::RestoreCursor()
{
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, FALSE);
}
void CXTPSyntaxEditCtrl::SetInternalRowBkColor(int nRow, COLORREF crBack)
{
m_mapInternalRowBkColor[nRow] = crBack;
}
void CXTPSyntaxEditCtrl::SetInternalRowColor(int nRow, COLORREF clrFront)
{
m_mapInternalRowForeColor[nRow] = clrFront;
}
void CXTPSyntaxEditCtrl::SetRowBkColor(int nRow, COLORREF crBack)
{
CXTPSyntaxEditRowColorMap& mapRowBkColor = m_pOptions->m_mapRowBkColor;
if (nRow == -1)
{
if (mapRowBkColor.GetCount() == 0)
return;
mapRowBkColor.RemoveAll();
}
else
{
if (crBack == RGB(255, 255, 255) || crBack == COLORREF_NULL)
mapRowBkColor.RemoveKey(nRow);
else
mapRowBkColor[nRow] = crBack;
}
InvalidateAll();
}
void CXTPSyntaxEditCtrl::SetRowColor(int nRow, COLORREF clrFront)
{
CXTPSyntaxEditRowColorMap& mapRowColor = m_pOptions->m_mapRowForeColor;
if (nRow == -1)
{
if (mapRowColor.GetCount() == 0)
return;
mapRowColor.RemoveAll();
}
else
{
if (clrFront == RGB(0, 0, 0) || clrFront == COLORREF_NULL)
mapRowColor.RemoveKey(nRow);
else
mapRowColor[nRow] = clrFront;
}
InvalidateAll();
}
COLORREF CXTPSyntaxEditCtrl::GetRowColor(int nRow) const
{
COLORREF clrFront;
if (m_mapInternalRowForeColor.Lookup(nRow, clrFront))
{
return clrFront;
}
if (m_pOptions->m_mapRowForeColor.Lookup(nRow, clrFront))
{
return clrFront;
}
return COLORREF_NULL;
}
COLORREF CXTPSyntaxEditCtrl::GetRowBkColor(int nRow) const
{
COLORREF crBack;
if (m_mapInternalRowBkColor.Lookup(nRow, crBack))
{
return crBack;
}
if (m_pOptions->m_mapRowBkColor.Lookup(nRow, crBack))
{
return crBack;
}
return COLORREF_NULL;
}
const CXTPSyntaxEditCtrl& CXTPSyntaxEditCtrl::operator=(const CXTPSyntaxEditCtrl& src)
{
if (::IsWindow(src.m_hWnd))
{
SetCurrentDocumentRow(src.m_nCurrentDocumentRow);
m_nCurrentCol = src.m_nCurrentCol;
m_nDispCol = src.m_nDispCol;
}
CalculateEditbarLength();
CMDTARGET_RELEASE(m_pOptions);
m_pOptions = src.m_pOptions;
CMDTARGET_ADDREF(m_pOptions);
RecalcScrollBars();
SetScrollPos(SB_HORZ, 0);
m_pDrawTextProcessor->SetScrollXOffset(0);
SetPaintManager(src.GetPaintManager());
CMDTARGET_ADDREF(m_pPaintManeger);
return *this;
}
CWnd * CXTPSyntaxEditCtrl::GetEffectiveParent() const
{
CWnd *pScrollWnd = GetParent();
if (GetParent())
{
pScrollWnd = GetParent();
if (!IsKindOf(RUNTIME_CLASS(CSplitterWnd)))
{
pScrollWnd = GetParent();
}
}
else
{
pScrollWnd = const_cast<CXTPSyntaxEditCtrl *>(this);
}
return pScrollWnd;
}
DWORD CXTPSyntaxEditCtrl::GetAutoscrollDirection(int* pnCols, int* pnRows)
{
CPoint ptCursor;
GetCursorPos(&ptCursor);
ScreenToClient(&ptCursor);
CRect rcText = m_pDrawTextProcessor->GetTextRect();
int nAutoZoneY = min(m_pDrawTextProcessor->GetRowHeight(), rcText.Height()/4);
int nAutoZoneX2 = min(m_pDrawTextProcessor->GetTextMetrics().tmAveCharWidth, rcText.Width()/4);
DWORD dwDirection = 0;
int nScrollX = 0, nScrollY = 0;
if (ptCursor.y < rcText.top + nAutoZoneY)
{
dwDirection += xtpTop;
nScrollY = -1 - (rcText.top + nAutoZoneY - ptCursor.y) / (nAutoZoneY / 2);
}
if (ptCursor.y > rcText.bottom - nAutoZoneY)
{
dwDirection += xtpBottom;
nScrollY = 1 + (ptCursor.y - rcText.bottom + nAutoZoneY) / (nAutoZoneY / 2);
}
if (ptCursor.x < rcText.left)
{
dwDirection += xtpLeft;
nScrollX = -1 - (rcText.left - ptCursor.x) / (nAutoZoneX2 / 2);
}
if (ptCursor.x > rcText.right - nAutoZoneX2)
{
dwDirection += xtpRight;
nScrollX = 1 + (ptCursor.x - rcText.right + nAutoZoneX2) / (nAutoZoneX2 / 2);
}
if (pnCols)
*pnCols = nScrollX;
if (pnRows)
*pnRows = nScrollY;
return dwDirection;
}
void CXTPSyntaxEditCtrl::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == TIMER_AUTOSCROLL_ID)
{
int nScrollX = 0, nScrollY = 0;
m_dwAutoScrollDirection = GetAutoscrollDirection(&nScrollX, &nScrollY);
if (nScrollX || nScrollY)
{
Scroll(nScrollX, nScrollY);
OnTimer(TIMER_SELECTION_ID);
//UpdateWindow();
}
BOOL bLButton = (::GetKeyState(VK_LBUTTON) & KF_UP) == KF_UP;
if (!m_dwAutoScrollDirection || !bLButton)
{
m_dwAutoScrollDirection = 0;
KillTimer(TIMER_AUTOSCROLL_ID);
}
}
else if (nIDEvent == TIMER_SELECTION_ID)
{
if ((::GetKeyState(VK_LBUTTON) & KF_UP) == 0)
{
m_pSelection->bSelectingRunning = FALSE;
KillTimer(TIMER_SELECTION_ID);
return;
}
CPoint ptCursor;
GetCursorPos(&ptCursor);
ScreenToClient(&ptCursor);
BOOL bIsAutoScrollTimer = !!m_dwAutoScrollDirection;
m_dwAutoScrollDirection = GetAutoscrollDirection();
if (m_dwAutoScrollDirection)
{
if (!bIsAutoScrollTimer)
SetTimer(TIMER_AUTOSCROLL_ID, TIMER_AUTOSCROLL_TIME, NULL);
}
else
{
m_dwAutoScrollDirection = 0;
KillTimer(TIMER_AUTOSCROLL_ID);
}
//-------------------------------------------------------------------
CRect rcBookmark, rcLineNum, rcNodes, rcText;
CalcEditRects(&rcBookmark, &rcLineNum, &rcNodes, &rcText);
CRect rcLineNumAndNodes(rcLineNum);
rcLineNumAndNodes.right = rcNodes.right;
int nNewRow = 0, nNewCol = 0, nNewDispRow = 0, nNewDispCol = 0;
BOOL bVirtualSpace = m_pSelection->IsbBlockSelectionMode() ? TRUE : -1;
RowColFromPoint(ptCursor, &nNewRow, &nNewCol, &nNewDispRow, &nNewDispCol, bVirtualSpace);
BOOL bSelFromLeftBar = rcLineNumAndNodes.PtInRect(ptCursor);
if (bSelFromLeftBar && m_pSelection->nSelStartTextRowFromLeftBar)
{
if (nNewRow >= m_pSelection->nSelStartTextRowFromLeftBar)
{
nNewRow++;
m_pSelection->SetStart_str(m_pSelection->nSelStartTextRowFromLeftBar, 0);
}
else
{
m_pSelection->SetStart_str(m_pSelection->nSelStartTextRowFromLeftBar+1, 0);
}
}
int nEndRow_prev = m_pSelection->GetEnd_disp().nLine;
int nEndDispCol_prev = m_pSelection->GetEnd_disp().nCol;
if (nEndRow_prev != nNewRow || nEndDispCol_prev != nNewDispCol)
{
// TRACE(_T("OnTimer.sel. RowColFromPoint: nNewRow=%d, nNewCol=%d, nNewDispRow=%d, nNewDispCol=%d \n"),
// nNewRow, nNewCol, nNewDispRow, nNewDispCol);
m_pSelection->SetEnd_disp(nNewRow, nNewDispCol);
if (m_pSelection->bWordSelectionMode)
{
XTP_EDIT_LINECOL lcWord1, lcWord2;
BOOL bOverSpace = FALSE;
UINT nFindDir = m_pSelection->IsSelNormal() ? XTP_EDIT_FINDWORD_NEXT : XTP_EDIT_FINDWORD_PREV;
BOOL bFind = FindWordEx_str(nFindDir, m_pSelection->GetEnd_str(), lcWord1, lcWord2, bOverSpace);
//TRACE(_T("2-FindWordEx_str = %d (%d, %d - %d, %d)"), bFind,
// lcWord1.nLine, lcWord1.nCol, lcWord2.nLine, lcWord2.nCol);
XTP_EDIT_LINECOL& lcWordEnd = m_pSelection->IsSelNormal() ? lcWord2 : lcWord1;
lcWordEnd.nCol--;
if (bFind && lcWordEnd.IsValidData() && lcWordEnd != m_pSelection->GetEnd_str())
{
m_pSelection->SetEnd_str(lcWordEnd.nLine, lcWordEnd.nCol);
}
}
SetCurrentDocumentRow(nNewRow);
m_nDispCol = m_pSelection->GetEnd_disp().nCol;
m_nCurrentCol = m_pSelection->GetEnd_str().nCol + 1;
int nCaretLine = m_pSelection->GetEnd_disp().nLine;
if (bSelFromLeftBar && m_pSelection->GetEnd_disp() >= m_pSelection->GetStart_disp())
nCaretLine = max(1, nCaretLine - 1);
SetCurCaretPos(nCaretLine, m_nDispCol, FALSE, FALSE);
//TRACE(_T("Selection: (row=%d, strPos=%d, DispCol=%d)-(row=%d, strPos=%d, DispCol=%d) \n"),
// m_pSelection->GetStart_str().nLine, m_pSelection->GetStart_str().nCol, m_pSelection->GetStart_disp().nCol,
// m_pSelection->GetEnd_str().nLine, m_pSelection->GetEnd_str().nCol, m_pSelection->GetEnd_disp().nCol);
Invalidate(FALSE);
UpdateWindow();
}
}
else if (nIDEvent == TIMER_REDRAW_WHEN_PARSE)
{
KillTimer(TIMER_REDRAW_WHEN_PARSE);
Invalidate(FALSE);
UpdateWindow();
}
}
BOOL CXTPSyntaxEditCtrl::Select(int nRow1, int nDispCol1, int nRow2, int nDispCol2, BOOL bRedraw)
{
if (nRow1 < 1 || nRow1 > GetRowCount())
return FALSE;
if (nRow2 < 1 || nRow2 > GetRowCount())
return FALSE;
m_pSelection->Reset_disp(nRow1, nDispCol1);
m_pSelection->SetEnd_disp(nRow2, nDispCol2);
SetCurrentDocumentRow(m_pSelection->GetNormalEnd_disp().nLine);
m_nDispCol = m_pSelection->GetNormalEnd_disp().nCol;
m_nCurrentCol = m_pSelection->GetNormalEnd_str().nCol + 1;
if (bRedraw)
{
Invalidate(FALSE);
}
return TRUE;
}
void CXTPSyntaxEditCtrl::Unselect()
{
if (m_pSelection->IsSelExist())
{
m_pSelection->Reset_disp(m_pSelection->GetEnd_disp().nLine,
m_pSelection->GetEnd_disp().nCol);
Invalidate(FALSE);
}
}
BOOL CXTPSyntaxEditCtrl::ReplaceSel(LPCTSTR szNewText)
{
if (m_pSelection->IsSelExist())
{
SetCurrentDocumentRow(m_pSelection->GetNormalStart_disp().nLine);
m_nDispCol = m_pSelection->GetNormalStart_disp().nCol;
m_nCurrentCol = m_pSelection->GetNormalStart_str().nCol + 1; //CalcAbsCol(GetLineText(m_pSelection->GetNormalStart_disp().nLine), m_nDispCol);
}
BOOL bOverwriteMode = m_pBuffer->GetOverwriteFlag();
m_pBuffer->SetOverwriteFlag(FALSE);
InsertString(szNewText, GetCurrentDocumentRow(), m_nCurrentCol, TRUE);
m_pBuffer->SetOverwriteFlag(bOverwriteMode);
return TRUE;
}
int CXTPSyntaxEditCtrl::ReplaceAll(LPCTSTR szFindText, LPCTSTR szReplaceText,
BOOL bMatchWholeWord, BOOL bMatchCase)
{
int nMatchFound = 0;
if (_tcsclen(szFindText) == 0)
{
return 0;
}
int iTopRow = GetTopRow();
int iCurRow = GetCurRow();
int iCurCol = GetCurCol();
SetCurPos(1, 1, FALSE, FALSE);
CWaitCursor wait;
BOOL bFirst = TRUE;
while (GetCurRow() <= GetRowCount())
{
BOOL bFound = Find(szFindText,
bMatchWholeWord, bMatchCase,
TRUE, FALSE);
if (bFound)
{
ReplaceSel(szReplaceText);
if (!bFirst)
GetEditBuffer()->GetUndoRedoManager()->ChainLastCommand();
}
else
break;
bFirst = FALSE;
nMatchFound++;
}
if (!bFirst)
GetEditBuffer()->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_REPLACE_ALL);
SetTopRow(iTopRow);
SetCurPos(iCurRow, iCurCol);
return nMatchFound;
}
BOOL CXTPSyntaxEditCtrl::Find(LPCTSTR szText, BOOL bMatchWholeWord, BOOL bMatchCase, BOOL bSearchDown,
BOOL bRedraw, int nStartRow, int nStartCol)
{
// First check the current row
CString strLineText;
int iStartCol = m_nCurrentCol;
int iStartRow = GetCurrentDocumentRow();
int nTopRow = m_nTopRow;
int nBottomRow = GetDocumentRow(GetRowPerPage());
if (m_pSelection->IsSelExist())
{
if (bSearchDown)
{
iStartCol = m_pSelection->GetNormalEnd_str().nCol + 1; // m_ptEndSel.x;
iStartRow = m_pSelection->GetNormalEnd_str().nLine; // m_ptEndSel.y;
}
else
{
iStartCol = m_pSelection->GetNormalStart_str().nCol + 1; // m_ptStartSel.x;
iStartRow = m_pSelection->GetNormalStart_str().nLine; // m_ptStartSel.y;
}
}
iStartCol = nStartCol < 0 ? iStartCol : nStartCol;
iStartRow = nStartRow < 0 ? iStartRow : nStartRow;
m_pBuffer->GetLineText(iStartRow, strLineText);
BOOL bResult = MatchText(iStartRow, strLineText, szText, iStartCol, bMatchWholeWord, bMatchCase, bSearchDown, bRedraw);
if (bResult)
return TRUE;
if (bSearchDown)
{
for (int i = (iStartRow + 1); i <= GetRowCount(); i++)
{
m_pBuffer->GetLineText(i, strLineText);
bResult = MatchText(i, strLineText, szText, 0, bMatchWholeWord, bMatchCase, TRUE, bRedraw);
if (bResult)
break;
}
}
else
{
for (int i = (iStartRow - 1); i >= 1; i--)
{
m_pBuffer->GetLineText(i, strLineText);
bResult = MatchText(i, strLineText, szText, (int)_tcsclen(strLineText) + 1, bMatchWholeWord, bMatchCase, FALSE, bRedraw);
if (bResult)
break;
}
}
if (bResult)
{
if (m_pSelection->GetStart_str().nLine > nBottomRow)
{
ShiftCurrentVisibleRowDown(2 * GetRowPerPage() / 3);
}
else if (m_pSelection->GetStart_str().nLine < nTopRow)
{
ShiftCurrentVisibleRowUp(GetRowPerPage() / 3);
}
SetCurCaretPos(m_pSelection->GetNormalEnd_disp().nLine, m_pSelection->GetNormalEnd_disp().nCol);
}
return bResult;
}
BOOL CXTPSyntaxEditCtrl::MatchText(int nRow, LPCTSTR szLineText, LPCTSTR szMatchText, int nStartPos, BOOL bMatchWholeWord, BOOL bMatchCase, BOOL bSearchForward, BOOL bRedraw)
{
BOOL bMatched = FALSE;
#ifdef XTP_FIXED
const int nLen = (int) _tcslen(szLineText);
const int nSearchLen = (int) _tcslen(szMatchText);
#else
const int nLen = (int) _tcsclen(szLineText);
const int nSearchLen = (int) _tcsclen(szMatchText);
#endif
static LPCTSTR szSeps = _T("() \t<>{}:;,.=%\"'!@#$^&*-\\|[]/?");
#ifdef XTP_FIXED
int count = 0;
int temp = 0;
for (count = 0; count < nStartPos - 1; count ++)
{
if (isleadbyte( szLineText[temp] ))
temp += 2;
else
temp++;
}
nStartPos = temp;
#endif
if (bSearchForward)
{
for (int i = nStartPos; i <= (nLen - nSearchLen + 1); i++)
{
int nFound = -1;
if (bMatchCase)
nFound = _tcsncmp((szLineText + i - 1), szMatchText, nSearchLen);
else
nFound = _tcsnicmp((szLineText + i - 1), szMatchText, nSearchLen);
bMatched = (nFound == 0);
if (bMatchWholeWord && nFound == 0)
{
BOOL bSepAfter = FALSE;
BOOL bSepBefore = FALSE;
if ((i - 1 + nSearchLen) >= nLen)
{
bSepAfter = TRUE;
}
else
{
LPCTSTR pcszTextAfter = (szLineText + i - 1) + nSearchLen;
bSepAfter = (_tcschr(szSeps, *pcszTextAfter) != 0);
}
if (i == 1)
bSepBefore = TRUE;
else
bSepBefore = (_tcschr(szSeps, *(szLineText + i - 2)) != 0);
if (!bSepAfter || !bSepBefore)
bMatched = FALSE;
}
if (bMatched)
{
#ifdef XTP_FIXED
LPTSTR buffer = (LPTSTR)malloc( sizeof( TCHAR ) * ( nLen + 1 ) );
memcpy( buffer, szLineText, sizeof( TCHAR ) * ( nLen + 1 ) );
buffer[nLen] = '\0';
buffer[i + nSearchLen - 1] = '\0';
int nDispCol2 = _tcsclen( buffer );
buffer[i - 1] = '\0';
int nDispCol1 = _tcsclen( buffer );
nDispCol1 = CalcDispCol(szLineText, nDispCol1 + 1 );
nDispCol2 = CalcDispCol(szLineText, nDispCol2 + 1 );
Select(nRow, nDispCol1, nRow, nDispCol2, bRedraw);
free( buffer );
#else
int nDispCol1 = CalcDispCol(szLineText, i);
int nDispCol2 = CalcDispCol(szLineText, (i + nSearchLen));
Select(nRow, nDispCol1, nRow, nDispCol2, bRedraw);
#endif
m_nDispCol = nDispCol2;
m_nCurrentCol = (i + nSearchLen);
SetCurCaretPos(m_pSelection->GetNormalEnd_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol, FALSE/*, FALSE*/);
break;
}
}
}
else
{
for (int i = (nStartPos-nSearchLen); i >= 1 ; i--)
{
int nFound = -1;
if (bMatchCase)
nFound = _tcsncmp((szLineText + i - 1), szMatchText, nSearchLen);
else
nFound = _tcsnicmp((szLineText + i - 1), szMatchText, nSearchLen);
bMatched = (nFound == 0);
if (bMatchWholeWord && nFound == 0)
{
BOOL bSepAfter = FALSE;
BOOL bSepBefore = FALSE;
if ((i - 1 + nSearchLen) >= nLen)
{
bSepAfter = TRUE;
}
else
{
LPCTSTR pcszTextAfter = (szLineText + i - 1) + nSearchLen;
bSepAfter = (_tcschr(szSeps, *pcszTextAfter) != 0);
}
if (i == 1)
bSepBefore = TRUE;
else
bSepBefore = (_tcschr(szSeps, *(szLineText + i - 2)) != 0);
if (!bSepAfter || !bSepBefore)
bMatched = FALSE;
}
if (bMatched)
{
LPTSTR buffer = (LPTSTR)malloc( sizeof(TCHAR) * (nLen + 1) );
memcpy( buffer, szLineText, sizeof(TCHAR) * (nLen + 1) );
buffer[nLen] = '\0';
buffer[i + nSearchLen - 1] = '\0';
int nDispCol2 = (int) _tcsclen( buffer );
buffer[i - 1] = '\0';
int nDispCol1 = (int) _tcsclen( buffer );
nDispCol1 = CalcDispCol(szLineText, nDispCol1 + 1 );
nDispCol2 = CalcDispCol(szLineText, nDispCol2 + 1 );
Select(nRow, nDispCol1, nRow, nDispCol2, bRedraw);
free( buffer );
m_nDispCol = nDispCol1;
m_nCurrentCol = i;
SetCurCaretPos(m_pSelection->GetNormalEnd_disp().nLine,
m_pSelection->GetNormalEnd_disp().nCol, FALSE/*, FALSE*/);
break;
}
}
}
return bMatched;
}
void CXTPSyntaxEditCtrl::ShowHScrollBar(BOOL bShow)
{
ShowScrollBar(SB_HORZ, bShow);
}
void CXTPSyntaxEditCtrl::SelectWord(CPoint point)
{
int nRow = 0, nCol = 0;
if (!RowColFromPoint(point, &nRow, &nCol))
return;
XTP_EDIT_LINECOL lcWord1, lcWord2;
BOOL bOverSpace = FALSE;
UINT nFindDir = XTP_EDIT_FINDWORD_NEXT;
BOOL bFind = FindWordEx(nFindDir, nRow, nCol, lcWord1, lcWord2, bOverSpace);
if (bFind && lcWord1.IsValidData() && lcWord2.IsValidData() && !bOverSpace)
{
m_pSelection->SetStart_str(lcWord1.nLine, lcWord1.nCol-1);
m_pSelection->SetEnd_str(lcWord2.nLine, lcWord2.nCol-1);
SetCurCaretPos(m_pSelection->GetEnd_disp().nLine,
m_pSelection->GetEnd_disp().nCol);
Invalidate(FALSE);
UpdateWindow();
}
}
void CXTPSyntaxEditCtrl::FindWord(UINT nFindWhat)
{
XTP_EDIT_LINECOL lcWord1, lcWord2;
BOOL bOverSpace;
BOOL bFind = FindWordEx(nFindWhat, GetCurrentDocumentRow(), m_nCurrentCol,
lcWord1, lcWord2, bOverSpace);
XTP_EDIT_LINECOL& lcWordEnd = (nFindWhat == XTP_EDIT_FINDWORD_NEXT) ? lcWord2 : lcWord1;
if (!bFind || !lcWordEnd.IsValidData())
return;
int nDispCol = CalcDispCol(lcWordEnd.nLine, lcWordEnd.nCol);
SetCurCaretPos(lcWordEnd.nLine, nDispCol);
}
BOOL CXTPSyntaxEditCtrl::FindWordEx_str(UINT nFindWhat, XTP_EDIT_LINECOL lcPos_str,
XTP_EDIT_LINECOL& rlcWordStart, XTP_EDIT_LINECOL& rlcWordEnd, BOOL& rbOverSpace)
{
return FindWordEx(nFindWhat, lcPos_str.nLine, lcPos_str.nCol + 1, rlcWordStart,
rlcWordEnd, rbOverSpace);
}
BOOL CXTPSyntaxEditCtrl::FindWordEx(UINT nFindWhat, int nTextRow, int nCol,
XTP_EDIT_LINECOL& rlcWordStart, XTP_EDIT_LINECOL& rlcWordEnd, BOOL& rbOverSpace)
{
// set word invalid borders
rlcWordStart = rlcWordEnd = XTP_EDIT_LINECOL::MINPOS;
rbOverSpace = FALSE;
CString strLineText;
const TCHAR* pCh = NULL;
// Volker Elies: added '+' character
const TCHAR szSeps[] = _T("[]{}()<>.,;:!?=*&%@^#-+\"\'/");
// const TCHAR szSepsAll[] = _T("[]{}()<>.,;:!?=*&%@^#-\"\'/\n\r\t ");
const TCHAR szSpaceSeps[] = _T(" \t");
const TCHAR szNLSeps[] = _T("\r\n");
int nDir = nFindWhat == XTP_EDIT_FINDWORD_PREV ? -1 : 1;
nCol = min(nCol-1, GetEditBuffer()->GetLineTextLengthC(nTextRow));
XTP_EDIT_LINECOL lcPosStart = XTP_EDIT_LINECOL::MakeLineCol(nTextRow, max(0, nCol));
CXTPSyntaxEditTextIterator txtIter(GetEditBuffer());
BOOL bSeek = txtIter.SeekPos(lcPosStart);
if (!bSeek)
return FALSE;
pCh = (nDir < 0) ? txtIter.SeekPrev() : txtIter.GetText(2);
if (!pCh)
return FALSE;
// Is over space/tab
BOOL bOverSpace = !!_tcschr(szSpaceSeps, *pCh);
BOOL bOverNL = !!_tcschr(szNLSeps, *pCh);
rbOverSpace = (bOverSpace || bOverNL);
if (!pCh)
return FALSE;
BOOL bStartCharSep = !!_tcschr(szSeps, *pCh);
if (rbOverSpace && nDir < 0)
{
while (pCh && (_tcschr(szSpaceSeps, *pCh) ||
!bOverSpace && _tcschr(szNLSeps, *pCh)) )
{
rlcWordEnd = txtIter.GetPosLC();
pCh = txtIter.SeekPrev();
}
if (!pCh || rlcWordEnd.nCol == 0 || bOverNL)
{
rlcWordEnd.nCol++;
rlcWordStart = rlcWordEnd;
return TRUE;
}
bStartCharSep = !!_tcschr(szSeps, *pCh);
}
if (rbOverSpace && nDir > 0) // one word border find - find the other one
{
XTP_EDIT_LINECOL& rlc1 = (nDir < 0) ? rlcWordEnd : rlcWordStart;
XTP_EDIT_LINECOL& rlc2 = (nDir < 0) ? rlcWordStart : rlcWordEnd;
rlc1 = txtIter.GetPosLC();
rlc2 = txtIter.GetPosLC();
while (pCh && (_tcschr(szSpaceSeps, *pCh) ||
_tcschr(szNLSeps, *pCh)) )
{
pCh = (nDir < 0) ? txtIter.SeekPrev() : txtIter.SeekNext(1, 2);
rlc2 = txtIter.GetPosLC();
}
}
else //find 2 word borders
{
rlcWordStart = txtIter.GetPosLC();
while (pCh && !((bStartCharSep == (!_tcschr(szSeps, *pCh))) ||
_tcschr(szSpaceSeps, *pCh) || _tcschr(szNLSeps, *pCh)))
{
rlcWordStart = txtIter.GetPosLC();
pCh = txtIter.SeekPrev();
}
pCh = txtIter.SeekNext(1, 2);
rlcWordEnd = txtIter.GetPosLC();
while (pCh && !(bStartCharSep == !_tcschr(szSeps, *pCh) ||
_tcschr(szSpaceSeps, *pCh) || _tcschr(szNLSeps, *pCh))
)
{
pCh = txtIter.SeekNext(1, 2);
rlcWordEnd = txtIter.GetPosLC();
}
if (rlcWordEnd > txtIter.GetPosLC_last(FALSE))
rlcWordEnd = txtIter.GetPosLC_last(FALSE);
}
rlcWordStart.nCol++;
rlcWordEnd.nCol++;
return TRUE;
}
void CXTPSyntaxEditCtrl::DeleteSelectedLines(int iForceDeleteRow)
{
int iLineFrom, iLineTo;
int iColTo = 1;
if (m_pSelection->IsSelExist())
{
iLineFrom = m_pSelection->GetNormalStart_str().nLine;
iLineTo = m_pSelection->GetNormalEnd_str().nLine;;
}
else
{
iLineFrom = iForceDeleteRow;
iLineTo = iLineFrom + 1;
}
if (iLineTo > GetRowCount())
{
iLineTo = GetRowCount();
const int iLen = (int)_tcsclen(GetLineText(iLineTo));
if (iLen == 0 && (iLineTo < 1 || iLineTo < iLineFrom))
iColTo = 1;
else
iColTo = iLen + 1;
if (iLineFrom == iLineTo && iColTo == 1 && iLen == 0) // Nothing to delete
return;
}
m_pSelection->Reset_disp(iLineFrom, 1);
int nFlags = xtpEditLMRefresh_Delete | xtpEditLMRefresh_Delete_only1;
if (iColTo > 1)
nFlags |= xtpEditLMRefresh_Delete_only2;
GetLineMarksManager()->RefreshLineMarks(iLineFrom, iLineTo, nFlags);
DeleteBuffer(iLineFrom, 1, iLineTo, iColTo);
}
BOOL CXTPSyntaxEditCtrl::IncreaseIndent()
{
if (!m_pSelection->IsSelExist() ||
(m_pSelection->GetStart_disp().nLine == m_pSelection->GetEnd_disp().nLine &&
m_pSelection->GetStart_disp().nLine < GetRowCount()))
{
if (!m_pBuffer->GetOverwriteFlag())
return FALSE;
CString strLineText = GetLineText(GetCurrentDocumentRow());
const int iLineLen = (int)_tcsclen(strLineText);
int iMaxDispCol = CalcDispCol(strLineText, (iLineLen + 1));
if (m_nDispCol >= iMaxDispCol)
return FALSE;
if (m_nCurrentCol > (iLineLen + 1))
m_nCurrentCol = (iLineLen + 1);
m_nDispCol += (GetTabSize() - (m_nDispCol % GetTabSize())); // Align by tab size
if (m_nDispCol < 1)
m_nDispCol = 1;
m_nDispCol = CalcValidDispCol(strLineText, m_nDispCol);
m_nCurrentCol = CalcAbsCol(strLineText, m_nDispCol);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
return TRUE;
}
int iRowFrom = m_pSelection->GetNormalStart_str().nLine;
int iRowTo = m_pSelection->GetNormalEnd_str().nLine;
int iColTo = m_pSelection->GetNormalEnd_str().nCol;
int iColTo2 = m_pSelection->GetStart_disp().nCol;
if (iColTo == 0 && iColTo2 == 1 && iRowTo > iRowFrom)
iRowTo--;
if (!CanEditDoc())
return FALSE;
BOOL bModified = FALSE;
// First insert tabs in front
// If overwrite flag is not set
if (!m_pBuffer->GetOverwriteFlag())
{
const CString strText(GetTabWithSpace() ? CString((TCHAR)(' '), GetTabSize()) : _T("\x09"));
for (int i = iRowFrom; i <= iRowTo; i++)
{
//**----------------------
OnBeforeEditChanged(i, 1);
//**----------------------
m_pBuffer->InsertText(strText, i, 1);
bModified = TRUE;
if (i > iRowFrom)
{
m_pBuffer->GetUndoRedoManager()->ChainLastCommand();
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_INDENTATION);
}
//**----------------------
OnEditChanged(i, 1, i, 2, xtpEditActInsert);
//**----------------------
}
if (bModified)
{
NotifyEditChanged(iRowFrom, iRowTo, XTP_EDIT_EDITACTION_MODIFYROW);
}
}
// Select the lines
m_pSelection->Reset_disp(iRowFrom, 1);
m_pSelection->SetEnd_disp(iRowTo + 1, 1);
if (bModified)
SetDocModified();
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
UpdateWindow();
UpdateScrollPos();
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::DecreaseIndent()
{
if (!m_pSelection->IsSelExist())
{
if (m_nCurrentCol < 1)
m_nCurrentCol = 1;
LPCTSTR szLineText = GetLineText(GetCurrentDocumentRow());
int iAddFactor = 1;
if ((m_nDispCol - 1) % GetTabSize())
iAddFactor = 0;
m_nDispCol = 1 + ((((m_nDispCol - 1) / GetTabSize()) - iAddFactor) * GetTabSize()); // Align by tab size
if (m_nDispCol < 1)
m_nDispCol = 1;
m_nDispCol = CalcValidDispCol(szLineText, m_nDispCol);
m_nCurrentCol = CalcAbsCol(szLineText, m_nDispCol);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
return TRUE;
}
int iRowFrom = m_pSelection->GetNormalStart_str().nLine;
int iRowTo = m_pSelection->GetNormalEnd_str().nLine;
int iColTo = m_pSelection->GetNormalEnd_str().nCol;
int iColTo2 = m_pSelection->GetStart_disp().nCol;
if (iColTo == 0 && iColTo2 == 1 && iRowTo > iRowFrom)
iRowTo--;
if (!CanEditDoc())
return FALSE;
CString strLineText;
BOOL bFrontDeleted = FALSE;
BOOL bModified = FALSE;
// First tabs or blank spaces from front
for (int i = iRowFrom; i <= iRowTo; i++)
{
GetLineText(i, strLineText);
const int iLen = (int)_tcsclen(strLineText);
if (iLen == 0)
continue;
//**----------------------
OnBeforeEditChanged(i, 1);
//**----------------------
if (strLineText.GetAt(0) == _T('\t'))
{
m_pBuffer->DeleteText(i, 1, i, 2);
bFrontDeleted = TRUE;
bModified = TRUE;
}
else
{
// No tab found in the front
// try to find blank spaces
int iSpaceCount = 0;
for (int iCol = 0; iCol < GetTabSize() && iCol < iLen; iCol++)
{
if (strLineText.GetAt(iCol) == 0x20)
iSpaceCount++;
else
break;
}
if (iSpaceCount)
{
m_pBuffer->DeleteText(i, 1, i, (iSpaceCount + 1));
bFrontDeleted = TRUE;
bModified = TRUE;
}
}
if (bFrontDeleted)
{
m_pBuffer->GetUndoRedoManager()->ChainLastCommand();
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_INDENT_DECREASE);
}
//**----------------------
OnEditChanged(i, 1, i, 1, xtpEditActDelete);
//**----------------------
}
if (bModified)
{
NotifyEditChanged(iRowFrom, iRowTo, XTP_EDIT_EDITACTION_MODIFYROW);
}
// Select the lines
m_pSelection->Reset_disp(iRowFrom, 1);
m_pSelection->SetEnd_disp(iRowTo + 1, 1);
if (bModified)
SetDocModified();
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
UpdateWindow();
UpdateScrollPos();
return TRUE;
}
void CXTPSyntaxEditCtrl::RecalcScrollBars()
{
_RecalcScrollBars();
CalculateEditbarLength();
}
void CXTPSyntaxEditCtrl::RedrawScrollBar(int nBar)
{
CScrollBar* pScrollBar = GetScrollBarCtrl(nBar);
if (pScrollBar)
{
SAFE_INVALIDATE(pScrollBar);
}
else
{
if (m_hWnd) SendMessage(WM_NCPAINT);
}
}
void CXTPSyntaxEditCtrl::_RecalcHScrollMaxWidth()
{
CRect rcText = m_pDrawTextProcessor->GetTextRect();
int nPageX = rcText.Width();
int nMaxX = m_pDrawTextProcessor->GetRowsMaxWidth();
nMaxX += max(nPageX/4, m_pDrawTextProcessor->GetTextMetrics().tmAveCharWidth * 20);
nMaxX = max(nMaxX, rcText.Width() * 2);
m_nHScrollMaxWidth = max(nMaxX, m_nHScrollMaxWidth);
}
void CXTPSyntaxEditCtrl::_RecalcScrollBars()
{
if (!GetPaintManager()->GetFont()->GetSafeHandle())
return;
if (!m_hWnd || !::IsWindow(m_hWnd))
return;
// create scroll bar info
SCROLLINFO info;
ZeroMemory(&info, sizeof(SCROLLINFO));
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_ALL;
int nVisRows = GetVisibleRowsCount();
CRect rcText = m_pDrawTextProcessor->GetTextRect();
int nPageX = rcText.Width();
int nPageY = m_pDrawTextProcessor->GetRowsCount(FALSE);
_RecalcHScrollMaxWidth();
if (GetRowCount() <= 0)
{
if (GetVertScrollBar())
{
GetScrollInfo(SB_VERT, &info);
info.cbSize = sizeof(info);
info.fMask = SIF_PAGE | SIF_RANGE;
info.nPage = nPageY;
info.nMax= nPageY;
SetScrollInfo(SB_VERT, &info);
EnableScrollBarCtrl(SB_VERT, FALSE);
}
if (GetHorzScrollBar())
{
info.fMask = SIF_ALL;
GetScrollInfo(SB_HORZ, &info);
info.nMax = m_nHScrollMaxWidth;
info.nPage = nPageX;
info.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_RANGE;
SetScrollInfo(SB_HORZ, &info);
}
if (GetVertScrollBar() && m_bVertScrollBarEnabled)
{
m_bVertScrollBarEnabled = FALSE;
RedrawScrollBar(SB_VERT);
}
}
else
{
if (GetHorzScrollBar())
{
info.fMask = SIF_ALL;
GetScrollInfo(SB_HORZ, &info);
info.nMin = 0;
info.nMax = max(m_nHScrollMaxWidth, info.nMax);
info.nPage = nPageX;
info.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
SetScrollInfo(SB_HORZ, &info);
EnableScrollBarCtrl(SB_HORZ);
}
//---------------------------------------
if (GetVertScrollBar())
{
info.fMask = SIF_ALL;
GetScrollInfo(SB_VERT, &info);
int nMaxRowInPage = GetRowPerPage();
BOOL bVertScrl = (nVisRows >= nMaxRowInPage);
if (bVertScrl)
{
int nVisRow = GetVisibleRowsCount(m_nTopRow);
info.nMin = 1;
info.nMax = nVisRows;
info.nPage = nPageY;
info.nPos = nVisRow;
info.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
SetScrollInfo(SB_VERT, &info);
}
else
{
m_nTopRow = 1;
Invalidate(FALSE);
}
EnableScrollBarCtrl(SB_VERT, bVertScrl);
if (m_bVertScrollBarEnabled != bVertScrl)
{
m_bVertScrollBarEnabled = bVertScrl;
RedrawScrollBar(SB_VERT);
}
}
}
if (GetCurrentDocumentRow() > GetRowCount())
SetCurCaretPos(GetRowCount(), m_nDispCol);
}
void CXTPSyntaxEditCtrl::RecalcVertScrollPos()
{
if (!::IsWindow(m_hWnd))
return;
if (!GetPaintManager()->GetFont()->GetSafeHandle())
return;
if (!GetVertScrollBar())
return;
int nPageRows = GetRowPerPage();
int nTotalVisRows = GetVisibleRowsCount();
BOOL bVertScrl = (nTotalVisRows >= nPageRows);
if (bVertScrl)
{
int nVisRow = GetVisibleRowsCount(m_nTopRow);
SCROLLINFO si;
ZeroMemory(&si, sizeof(SCROLLINFO));
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
si.nMin = 1;
si.nMax = nTotalVisRows;
si.nPage = nPageRows;
si.nPos = nVisRow;
VERIFY(SetScrollInfo(SB_VERT, &si));
}
else
{
m_nTopRow = 1;
Invalidate(FALSE);
}
EnableScrollBarCtrl(SB_VERT, bVertScrl);
}
void CXTPSyntaxEditCtrl::RecalcHorzScrollPos()
{
if (!::IsWindow(m_hWnd))
return;
if (!GetPaintManager()->GetFont()->GetSafeHandle())
return;
if (!GetHorzScrollBar())
return;
_RecalcHScrollMaxWidth();
int nPos = GetScrollPos(SB_HORZ);
SCROLLINFO si;
ZeroMemory(&si, sizeof(SCROLLINFO));
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
si.nMin = 0;
si.nMax = si.nMax = max(m_nHScrollMaxWidth, si.nMax);
si.nPage = m_pDrawTextProcessor->GetTextRect().Width();
si.nPos = nPos;
VERIFY(SetScrollInfo(SB_HORZ, &si, FALSE));
}
void CXTPSyntaxEditCtrl::NotifyCurRowCol(int iRow, int iCol) const
{
// Notify the parent class that position has been changed
XTP_EDIT_NMHDR_ROWCOLCHANGED src;
// NMHDR codes
src.nmhdr.code = XTP_EDIT_NM_ROWCOLCHANGED;
src.nmhdr.hwndFrom = m_hWnd;
src.nmhdr.idFrom = GetDlgCtrlID();
// Row col specific codes
src.nRow = iRow;
src.nCol = iCol;
// Notify the parent window
if (::IsWindow(m_pParentWnd->GetSafeHwnd()))
{
m_pParentWnd->SendMessage(
WM_NOTIFY, (WPARAM)src.nmhdr.idFrom, (LPARAM)&src);
}
}
void CXTPSyntaxEditCtrl::ValidateCol(const int nRow, int &nCol, int& nAbsCol)
{
CString strText;
GetLineText(nRow, strText);
nCol = CalcValidDispCol(strText, nCol);
nAbsCol = CalcAbsCol(strText, nCol);
}
void CXTPSyntaxEditCtrl::EnableOleDrag(BOOL bEnableDrag)
{
m_bEnableOleDrag = bEnableDrag;
}
HGLOBAL CXTPSyntaxEditCtrl::GetSelectionBuffer(UINT nFormat)
{
if (!m_pSelection->IsSelExist())
return NULL;
if (nFormat != CF_TEXT && nFormat != CF_UNICODETEXT)
return NULL;
CMemFile file(CalcAveDataSize(m_pSelection->GetNormalStart_str().nLine,
m_pSelection->GetNormalEnd_str().nLine));
BOOL bRes = m_pBuffer->GetBuffer(m_pSelection->GetNormalStart_disp(),
m_pSelection->GetNormalEnd_disp(), file,
m_pSelection->bBlockSelectionMode, TRUE);
if (!bRes)
return NULL;
file.Seek(0, CFile::end);
file.Write(_T("\0"), sizeof(TCHAR));
int nLen = (int)file.GetLength();
BYTE *pBytes = file.Detach();
UINT uCodePage = m_pBuffer->GetCodePage();
#ifdef _UNICODE
// If Unicode defined then for CF_TEXT conversion is needed
if (nFormat == CF_TEXT)
{
nLen = ::WideCharToMultiByte(uCodePage, 0, (LPWSTR)pBytes, -1, NULL, 0, NULL, NULL);
}
#else
if (nFormat == CF_UNICODETEXT)
{
nLen = ::MultiByteToWideChar(uCodePage, 0, (LPCSTR)pBytes, -1, NULL, 0);
nLen *= sizeof(wchar_t);
}
#endif
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, nLen);
if (!hMem)
return 0;
void *pText = ::GlobalLock(hMem);
#ifdef _UNICODE
if (nFormat == CF_UNICODETEXT)
MEMCPY_S(pText, pBytes, nLen);
else
{
::WideCharToMultiByte(uCodePage, 0, (LPWSTR)pBytes, -1, (LPSTR)pText, nLen, NULL, NULL);
}
#else
if (nFormat == CF_TEXT)
MEMCPY_S(pText, pBytes, nLen);
else
{
::MultiByteToWideChar(uCodePage, 0, (LPSTR)pBytes, -1, (LPWSTR)pText, (nLen / sizeof(wchar_t)));
}
#endif
::GlobalUnlock(hMem);
::free(pBytes);
return hMem;
}
int CXTPSyntaxEditCtrl::GetSelectionText(CString &strText)
{
if (!m_pSelection->IsSelExist())
return 0;
CMemFile file(CalcAveDataSize(m_pSelection->GetNormalStart_str().nLine,
m_pSelection->GetNormalEnd_str().nLine));
BOOL bRes = m_pBuffer->GetBuffer(m_pSelection->GetNormalStart_disp(),
m_pSelection->GetNormalEnd_disp(), file,
m_pSelection->bBlockSelectionMode, TRUE);
if (!bRes)
return 0;
file.Write((LPVOID)_T("\0"), sizeof(TCHAR));
int iLen = (int)file.GetLength();
BYTE *pBytes = file.Detach();
strText = (LPTSTR)pBytes;
free(pBytes);
return iLen;
}
void CXTPSyntaxEditCtrl::SetDropPos(int iRow, int iCol)
{
m_ptDropPos.y = iRow;
m_ptDropPos.x = iCol;
}
void CXTPSyntaxEditCtrl::OnShowWindow(BOOL bShow, UINT nStatus)
{
CWnd::OnShowWindow(bShow, nStatus);
}
void CXTPSyntaxEditCtrl::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
CWnd::OnActivate(nState, pWndOther, bMinimized);
SetActive(nState != WA_INACTIVE);
}
void CXTPSyntaxEditCtrl::SetActive(BOOL bIsActive)
{
m_bIsActive = bIsActive;
if (::IsWindow(m_hWnd))
{
RedrawWindow();
}
}
void CXTPSyntaxEditCtrl::HandleDrop(BOOL bCopy)
{
if (!CanEditDoc())
return;
if (!m_bRightButtonDrag)
CopyOrMoveText(bCopy);
else
{
CMenu menu;
menu.CreatePopupMenu();
CString csMenuText;
XTPResourceManager()->LoadString(&csMenuText, XTP_IDS_EDIT_MOVE_HERE);
menu.AppendMenu(MF_STRING, XTP_IDC_EDIT_DRAG_MOVE, csMenuText);
XTPResourceManager()->LoadString(&csMenuText, XTP_IDS_EDIT_COPY_HERE);
menu.AppendMenu(MF_STRING, XTP_IDC_EDIT_DRAG_COPY, csMenuText);
menu.AppendMenu(MF_SEPARATOR);
XTPResourceManager()->LoadString(&csMenuText, XTP_IDS_EDIT_CANCEL);
menu.AppendMenu(MF_STRING, IDCANCEL, csMenuText);
CPoint pt;
GetCursorPos(&pt);
int nID = menu.TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_NONOTIFY|TPM_RETURNCMD, pt.x, pt.y, this);
if (nID == XTP_IDC_EDIT_DRAG_MOVE || nID == XTP_IDC_EDIT_DRAG_COPY)
CopyOrMoveText(nID == XTP_IDC_EDIT_DRAG_COPY);
}
m_bRightButtonDrag = FALSE;
m_bDragging = FALSE;
}
void CXTPSyntaxEditCtrl::ShowDefaultContextMenu()
{
CPoint ptCur;
GetCursorPos(&ptCur);
OnContextMenu(this, ptCur);
}
void CXTPSyntaxEditCtrl::EnableWhiteSpace(BOOL bShow)
{
m_pOptions->m_bEnableWhiteSpace = bShow;
InvalidateAll();
}
void CXTPSyntaxEditCtrl::EnableVirtualSpace(BOOL bEnable, BOOL bUpdateReg)
{
SetValueBool(XTP_EDIT_REG_VIRTUALSPACE, bEnable, m_pOptions->m_bVirtualSpace, bUpdateReg);
}
void CXTPSyntaxEditCtrl::SetCollapsibleNodes(BOOL bDrawNodes, BOOL bUpdateReg)
{
SetValueBool(XTP_EDIT_REG_COLLAPSIBLENODES, bDrawNodes, m_pOptions->m_bDrawNodes, bUpdateReg);
CalculateEditbarLength();
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, TRUE);
if (!GetCollapsibleNodes())
ExpandAll();
else
InvalidateAll();
}
BOOL CXTPSyntaxEditCtrl::SetTabWithSpace(BOOL bTabWithSpace, BOOL bUpdateReg/*=FALSE*/)
{
if (!SetValueBool(XTP_EDIT_REG_TABWITHSPACE, bTabWithSpace, m_pOptions->m_bTabWithSpace, bUpdateReg))
return FALSE;
return TRUE;
}
void CXTPSyntaxEditCtrl::NotifySelInit() const
{
NotifyParent(XTP_EDIT_NM_SELINIT);
}
BOOL CXTPSyntaxEditCtrl::SetTabSize(int nTabSize, BOOL bUpdateReg)
{
if (!m_pBuffer->SetTabSize(nTabSize, bUpdateReg))
return FALSE;
m_pDrawTextProcessor->SetTabSize(nTabSize);
CString strText;
GetLineText(GetCurrentDocumentRow(), strText);
m_nDispCol = CalcDispCol(strText, m_nCurrentCol);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, FALSE);
return TRUE;
}
int CXTPSyntaxEditCtrl::GetTabSize() const
{
return m_pBuffer ? m_pBuffer->GetTabSize() : 4;
}
BOOL CXTPSyntaxEditCtrl::SetSyntaxColor(BOOL bSyntaxColor, BOOL bUpdateReg)
{
if (!SetValueBool(XTP_EDIT_REG_SYNTAXCOLOR, bSyntaxColor, m_pOptions->m_bSyntaxColor, bUpdateReg))
return FALSE;
m_arOnScreenSchCache->RemoveAll();
m_pBuffer->EnableParser(bSyntaxColor);
return TRUE;
}
LRESULT CXTPSyntaxEditCtrl::NotifyParent(UINT uCode) const
{
if (!m_pParentWnd)
return -1;
ASSERT_VALID(m_pParentWnd);
if (::IsWindow(m_pParentWnd->GetSafeHwnd()))
{
NMHDR hdr;
hdr.hwndFrom = m_hWnd;
hdr.code = uCode;
hdr.idFrom = GetDlgCtrlID();
return m_pParentWnd->SendMessage(
WM_NOTIFY, (WPARAM)hdr.idFrom, (LPARAM)&hdr);
}
return -1;
}
LRESULT CXTPSyntaxEditCtrl::NotifyMouseEvent(UINT uCode, UINT nFlags, const CPoint& point) const
{
UNREFERENCED_PARAMETER(nFlags);
ASSERT_VALID(GetParent());
if (::IsWindow(GetParent()->GetSafeHwnd()))
{
NMMOUSE hdrMouse;
::ZeroMemory(&hdrMouse, sizeof(hdrMouse));
hdrMouse.hdr.hwndFrom = m_hWnd;
hdrMouse.hdr.code = uCode;
hdrMouse.hdr.idFrom = GetDlgCtrlID();
hdrMouse.pt = point;
return GetParent()->SendMessage(WM_NOTIFY, (WPARAM)hdrMouse.hdr.idFrom,
(LPARAM)&hdrMouse);
}
return -1;
}
BOOL CXTPSyntaxEditCtrl::SetSelMargin(BOOL bSelMargin, BOOL bUpdateReg)
{
if (!SetValueBool(XTP_EDIT_REG_SELMARGIN, bSelMargin, m_pOptions->m_bSelMargin, bUpdateReg))
return FALSE;
CalculateEditbarLength();
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, FALSE);
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::SetScrollBars(BOOL bHorzSBar, BOOL bVertSBar, BOOL bUpdateReg/*=FALSE*/)
{
if (!SetValueBool(XTP_EDIT_REG_HSCROLLBAR, bHorzSBar, m_bHorzScrollBar, bUpdateReg))
return FALSE;
if (!SetValueBool(XTP_EDIT_REG_VSCROLLBAR, bVertSBar, m_bVertScrollBar, bUpdateReg))
return FALSE;
DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE) & ~(WS_HSCROLL|WS_VSCROLL);
if (bHorzSBar && !IsCreateScrollbarOnParent())
dwStyle |= WS_HSCROLL;
if (bVertSBar && !IsCreateScrollbarOnParent())
dwStyle |= WS_VSCROLL;
EnableScrollBarCtrl(SB_HORZ, m_bHorzScrollBar);
EnableScrollBarCtrl(SB_VERT, m_bVertScrollBar);
::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::CanEditDoc() const
{
if(!m_hWnd)
return FALSE;
if (IsReadOnly())
return FALSE;
BOOL bCancel = (BOOL)NotifyParent(XTP_EDIT_NM_EDITCHANGING);
return !bCancel;
}
void CXTPSyntaxEditCtrl::NotifyEditChanged(int iRowFrom, int iRowTo, UINT nActions)
{
XTP_EDIT_NMHDR_EDITCHANGED sec;
sec.nmhdr.code = XTP_EDIT_NM_EDITCHANGED;
sec.nmhdr.hwndFrom = m_hWnd;
sec.nmhdr.idFrom = GetDlgCtrlID();
sec.nRowFrom = iRowFrom;
sec.nRowTo = iRowTo;
sec.nAction = nActions;
RefreshLineMarks(&sec);
// Notify the parent window
if (::IsWindow(m_pParentWnd->GetSafeHwnd()))
{
m_pParentWnd->SendMessage(
WM_NOTIFY, (WPARAM)sec.nmhdr.idFrom, (LPARAM)&sec);
}
}
BOOL CXTPSyntaxEditCtrl::CreateInsertText(LPTSTR szText,
CString& strTextToIns,
int& iNewRow,
int& iNewCol,
int& iNewDispCol,
int& iEditRowFrom,
int& iEditRowTo,
int& iChainActionCount)
{
// As this function will always be called by OnChar
// We can assume szText will contain only one character
// or the CRLF
int nCurDocRow = GetCurrentDocumentRow();
CString strLineText;
GetLineText(nCurDocRow, strLineText);
int nLineLenC = (int)_tcsclen(strLineText);
BOOL bTextCRLF = m_pBuffer->IsTextCRLF(szText);
BOOL bProcess = TRUE;
if (!bTextCRLF)
{
if (szText[0] == _T('\t') && !GetTabWithSpace() &&
m_nCurrentCol > 1 && nLineLenC > 0)
{
int nAlign = (m_nDispCol-1) % GetTabSize();
iNewDispCol = m_nDispCol - nAlign + GetTabSize();
int nDispCol = CalcDispCol(strLineText, nLineLenC + 1);
int nCurCol = m_nCurrentCol;
if (nDispCol < m_nDispCol)
{
nCurCol = nLineLenC+1;
}
else
{
nDispCol = m_nDispCol;
}
int nCharsToCheck = nCurCol-1;
if (nCharsToCheck)
{
LPCTSTR pCheck = _tcsninc((LPCTSTR)strLineText, max(0, nCurCol - 1 - 1));
int nBlanks;
for (nBlanks = 0; pCheck && nBlanks < nCharsToCheck; nBlanks++)
{
if (!pCheck || *pCheck != _T(' '))
break;
pCheck = _tcsdec((LPCTSTR)strLineText, pCheck);
}
if (nBlanks > 0)
{
int nAdditionalTabs = 0;
int nDC = m_nDispCol - nBlanks;
nDC += GetTabSize() - nDC % GetTabSize();
for (; nDC < m_nDispCol; nDC += GetTabSize())
{
nAdditionalTabs++;
}
m_pBuffer->SetOverwriteFlag(FALSE);
nCurDocRow = GetCurrentDocumentRow();
//**----------------------
OnBeforeEditChanged(nCurDocRow, nCurCol - nBlanks);
m_pBuffer->DeleteText(nCurDocRow, nCurCol - nBlanks, nCurDocRow, nCurCol);
OnEditChanged(nCurDocRow, nCurCol - nBlanks, nCurDocRow, nCurCol, xtpEditActDelete);
//**----------------------
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_FORMAT);
m_nDispCol -= nBlanks;
m_nCurrentCol -= nBlanks;
iChainActionCount = 2;
GetLineText(nCurDocRow, strLineText);
nLineLenC = (int)_tcsclen(strLineText);
if (nAdditionalTabs)
{
strTextToIns += CString(_T('\t'), nAdditionalTabs);
}
}
}
}
else
{
//iNewDispCol = m_nDispCol + (szText[0] == 0x09 ? GetTabSize() : 1);
//iNewCol = m_nCurrentCol + (szText[0] == 0x09 ? (GetTabWithSpace() ? GetTabSize() : 1) : 1);
//if (GetAutoIndent() && m_nAutoIndentCol > 0)
//{
// strTextToIns += CString(_T('\t'), m_nInsertTabCount) +
// CString(_T(' '), m_nInsertSpaceCount);
// m_nDispCol = 1;
// m_nCurrentCol = 1;
//}
if (szText[0] == _T('\t'))
{
// Align to the next tab position
int nAlign = (m_nDispCol-1) % GetTabSize();
iNewDispCol = m_nDispCol - nAlign + GetTabSize();
if (GetTabWithSpace())
{
int spaceCnt = GetTabSize() - nAlign;
strTextToIns += CString(_T(' '), spaceCnt);
szText++; // Skip tab, spaces are displayed
iNewCol = m_nCurrentCol + spaceCnt;
}
else
iNewCol = m_nCurrentCol + 1;
}
else
{
#ifdef XTP_FIXED
iNewDispCol = m_nDispCol + ( isleadbyte( szText[0] ) ? 2 : 1 );
#else
iNewDispCol = m_nDispCol + 1;
#endif
iNewCol = m_nCurrentCol + 1;
}
if (GetAutoIndent() && m_nAutoIndentCol > 0)
{
if (GetTabWithSpace())
strTextToIns += CString(_T(' '), m_nInsertTabCount * GetTabSize());
else
strTextToIns += CString(_T('\t'), m_nInsertTabCount);
strTextToIns += CString(_T(' '), m_nInsertSpaceCount);
m_nDispCol = 1;
m_nCurrentCol = 1;
}
}
iNewRow = GetCurrentDocumentRow();
strTextToIns += szText;
m_nAutoIndentCol = 0;
m_nInsertTabCount = 0;
m_nInsertSpaceCount = 0;
}
else if (bTextCRLF)
{
// Enter pressed
nCurDocRow = GetCurrentDocumentRow();
iNewRow = nCurDocRow + 1;
iNewCol = iNewDispCol = 1;
iEditRowFrom = nCurDocRow;
iEditRowTo = iEditRowFrom + 1;
strTextToIns = szText;
if (!GetAutoIndent())
return TRUE;
BOOL bInsertMid = (m_nCurrentCol <= nLineLenC);
DoAutoIndentIfNeed(GetCurrentDocumentRow(), m_nDispCol);
if (m_nAutoIndentCol > 0 && bInsertMid)
{
CString strTabs;
FillTabs(strTabs, m_nAutoIndentCol);
strTextToIns += strTabs;
iNewDispCol = m_nAutoIndentCol;
iNewCol = (int)_tcsclen(strTabs);
m_nAutoIndentCol = 0;
}
}
return bProcess;
}
void CXTPSyntaxEditCtrl::DoAutoIndentIfNeed(int nBaseDocRow, int nDispCol_prev)
{
if (!GetAutoIndent())
return;
m_nAutoIndentCol = 0;
if (nDispCol_prev == 1)
return;
CString strTempLineText;
BOOL bFound = FALSE;
GetLineText(nBaseDocRow, strTempLineText);
LPCTSTR pChar = (LPCTSTR)strTempLineText;
for (; pChar && *pChar; pChar = _tcsinc(pChar))
{
if (*pChar == _T('\t'))
{
m_nAutoIndentCol += (GetTabSize() - (m_nAutoIndentCol % GetTabSize()));
}
else if (*pChar == 0x20)
{
m_nAutoIndentCol++;
}
else
{
bFound = TRUE;
break;
}
}
if (!bFound && nDispCol_prev > 1)
{
bFound = TRUE;
m_nAutoIndentCol = nDispCol_prev - 1;
}
if (nDispCol_prev > 1 && m_nAutoIndentCol > nDispCol_prev - 1)
m_nAutoIndentCol = nDispCol_prev - 1;
if (bFound)
{
m_nInsertTabCount = m_nAutoIndentCol / GetTabSize();
m_nInsertSpaceCount = m_nAutoIndentCol % GetTabSize();
m_nAutoIndentCol++;
}
else
{
m_nAutoIndentCol = 0;
m_nInsertTabCount = 0;
m_nInsertSpaceCount = 0;
}
}
void CXTPSyntaxEditCtrl::FillTabs(CString &rstrTextToIns, int nDispColl)
{
int nTabsCount = GetTabWithSpace() ? 0 : (nDispColl-1) / GetTabSize();
int nSpaceCount = nDispColl - nTabsCount * GetTabSize() - 1;
if (nTabsCount)
{
CString strTabs(_T('\t'), nTabsCount);
rstrTextToIns += strTabs;
}
if (nSpaceCount)
{
CString strSpaces(_T(' '), nSpaceCount);
rstrTextToIns += strSpaces;
}
}
BOOL CXTPSyntaxEditCtrl::IsRowVisible(int iRow) const
{
if (iRow > GetRowCount() || iRow < 1)
return FALSE;
int iMaxRowInPage = GetRowPerPage();
return (iRow >= m_nTopRow && iRow <= (m_nTopRow + iMaxRowInPage));
}
BOOL CXTPSyntaxEditCtrl::LowercaseSelection()
{
return DoChangeSelectionCase(FALSE);
}
BOOL CXTPSyntaxEditCtrl::UppercaseSelection()
{
return DoChangeSelectionCase(TRUE);
}
BOOL CXTPSyntaxEditCtrl::DoChangeSelectionCase(BOOL bUpper)
{
if (!m_pSelection->IsSelExist())
return FALSE;
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(TRUE);
int nRowStrat = m_pSelection->GetNormalStart_disp().nLine;
int nRowEnd = m_pSelection->GetNormalEnd_disp().nLine;
for (int nRow = nRowStrat; nRow <= nRowEnd; nRow++)
{
int nVisFrom = 0;
int nVisTo = INT_MAX;
if (m_pSelection->bBlockSelectionMode || nRow == nRowStrat)
nVisFrom = m_pSelection->GetNormalStart_disp().nCol;
if (m_pSelection->bBlockSelectionMode || nRow == nRowEnd)
nVisTo = m_pSelection->GetNormalEnd_disp().nCol;
m_pBuffer->ChangeCase(nRow, nVisFrom, nVisTo, bUpper);
}
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(XTP_IDS_EDIT_CASE);
InvalidateRows(nRowStrat, nRowEnd);
Invalidate(FALSE);
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::DoChangeSelectionTabify(BOOL bTabify)
{
if (!IsSelectionExist())
return FALSE;
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(TRUE);
int nRowStrat = m_pSelection->GetNormalStart_disp().nLine;
int nRowEnd = m_pSelection->GetNormalEnd_disp().nLine;
for (int nRow = nRowStrat; nRow <= nRowEnd; nRow++)
{
int nVisFrom = 0;
int nVisTo = INT_MAX;
if (m_pSelection->bBlockSelectionMode || nRow == nRowStrat)
nVisFrom = m_pSelection->GetNormalStart_disp().nCol;
if (m_pSelection->bBlockSelectionMode || nRow == nRowEnd)
nVisTo = m_pSelection->GetNormalEnd_disp().nCol;
m_pBuffer->ChangeTabification(nRow, nVisFrom, nVisTo, bTabify);
}
m_pBuffer->GetUndoRedoManager()->SetGroupInsertMode(FALSE);
m_pBuffer->GetUndoRedoManager()->SetLastCommandText(bTabify ? XTP_IDS_EDIT_TABIFY : XTP_IDS_EDIT_UNTABIFY);
InvalidateRows(nRowStrat, nRowEnd);
Invalidate(FALSE);
return TRUE;
}
BOOL CXTPSyntaxEditCtrl::TabifySelection()
{
return DoChangeSelectionTabify(TRUE);
}
BOOL CXTPSyntaxEditCtrl::UnTabifySelection()
{
return DoChangeSelectionTabify(FALSE);
}
BOOL CXTPSyntaxEditCtrl::SetLineNumbers(BOOL bLineNumbers, BOOL bUpdateReg/*=FALSE*/)
{
if (m_pOptions->m_bLineNumbers == bLineNumbers)
return TRUE;
if (!SetValueBool(XTP_EDIT_REG_LINENUMBERS, bLineNumbers, m_pOptions->m_bLineNumbers, bUpdateReg))
return FALSE;
CalculateEditbarLength();
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, TRUE);
InvalidateAll();
return TRUE;
}
void CXTPSyntaxEditCtrl::CalculateEditbarLength(CDC* pDC)
{
if (!m_hWnd)
return;
int nPrvEditbarLength = m_nEditbarLength;
// gutter
m_nEditbarLength = GetSelMargin() ? m_nMarginLength : 0;
// line numbers
m_nLineNumLength = 0;
if (GetLineNumbers())
{
int nMaxPageRow = GetRowCount();
if (pDC && pDC->IsPrinting())
nMaxPageRow = GetTopRow() + GetRowPerPage();
int nRowNumLen = (nMaxPageRow > 9 ? (int)log10l(nMaxPageRow) : 0) + 1;
CString sLineNumberFormat(GetPaintManager()->m_sLineNumberFormat);
if (!sLineNumberFormat.IsEmpty())
{
sLineNumberFormat.Replace(_T("%"), _T(""));
sLineNumberFormat.Replace(_T("d"), _T(""));
nRowNumLen = max(_ttoi(sLineNumberFormat), nRowNumLen);
}
CWindowDC dc(NULL);
CXTPFontDC fontDC(&dc, GetPaintManager()->GetFontLineNumber());
TEXTMETRIC tm;
VERIFY(dc.GetTextMetrics(&tm));
m_nLineNumLength = (nRowNumLen + 1) * (tm.tmAveCharWidth) + 2;
m_nEditbarLength += m_nLineNumLength;
}
// collapsible nodes area
if (GetCollapsibleNodes())
{
m_nEditbarLength += m_nNodesWidth;
}
if (GetSelMargin() || GetLineNumbers() || GetCollapsibleNodes())
m_nEditbarLength += TEXT_LEFT_OFFSET;
// update window if necessary
if (nPrvEditbarLength != m_nEditbarLength && (!pDC || !pDC->IsPrinting()))
{
CRect rcText;
CalcEditRects(NULL, NULL, NULL, &rcText);
m_pDrawTextProcessor->SetTextRect(rcText);
_RecalcScrollBars();
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, FALSE);
Invalidate(FALSE);
}
}
void CXTPSyntaxEditCtrl::AddRemoveBookmark(int nRow)
{
if (GetLineMarksManager())
{
GetLineMarksManager()->AddRemoveLineMark(nRow, xtpEditLMT_Bookmark);
}
RedrawLineMarks();
}
void CXTPSyntaxEditCtrl::AddRemoveBreakPoint(int nRow)
{
if (GetLineMarksManager())
{
GetLineMarksManager()->AddRemoveLineMark(nRow, xtpEditLMT_Breakpoint);
}
RedrawLineMarks();
}
void CXTPSyntaxEditCtrl::CollapseExpandBlock(int nRow)
{
CXTPSyntaxEditLineMarksManager* pMgr = GetLineMarksManager();
if (!pMgr)
return;
// nLineEnd: adjust also column, for example when collapsing to the string of lower length
int nLineEnd = m_nCurrentCol; //m_nDispCol;
if (pMgr->HasRowMark(nRow, xtpEditLMT_Collapsed))
{
// try expand
pMgr->DeleteLineMark(nRow, xtpEditLMT_Collapsed);
}
else
{
// try collapse
XTP_EDIT_LMPARAM LMCoParam;
CXTPSyntaxEditRowsBlockArray arCoBlocks;
GetCollapsableBlocksInfo(nRow, arCoBlocks);
int nCount = (int)arCoBlocks.GetSize();
for (int i = 0; i < nCount; i++)
{
XTP_EDIT_ROWSBLOCK coBlk = arCoBlocks[i];
if (coBlk.lcStart.nLine == nRow)
{
XTP_EDIT_COLLAPSEDBLOCK* pCoDrawBlk = (XTP_EDIT_COLLAPSEDBLOCK*)LMCoParam.GetPtr();
if (!pCoDrawBlk)
{
pCoDrawBlk = new XTP_EDIT_COLLAPSEDBLOCK;
if (!pCoDrawBlk)
{
return;
}
LMCoParam.SetPtr(pCoDrawBlk, XTPSECollapsedBlockDeleteFn);
}
pCoDrawBlk->collBlock = coBlk;
pMgr->SetLineMark(nRow, xtpEditLMT_Collapsed, &LMCoParam);
m_arCollapsedTextRows.SetAtGrow(m_nCollapsedTextRowsCount, nRow);
nLineEnd = min(nLineEnd, pCoDrawBlk->collBlock.lcEnd.nCol);
m_nCollapsedTextRowsCount++;
}
}
}
SetCurrentDocumentRow(nRow);
m_nDispCol = nLineEnd + 1;
SetCurCaretPos(nRow, m_nDispCol);
Invalidate(FALSE);
RecalcScrollBars();
}
void CXTPSyntaxEditCtrl::DeleteBookmark(int nRow)
{
if (GetLineMarksManager())
{
GetLineMarksManager()->DeleteLineMark(nRow, xtpEditLMT_Bookmark);
}
}
void CXTPSyntaxEditCtrl::PrevBookmark()
{
CXTPSyntaxEditLineMarksManager* pMgr = GetLineMarksManager();
if (!pMgr)
{
ASSERT(FALSE);
return;
}
int nRow = GetCurRow();
int nVisRow = GetCurrentVisibleRow();
int nPrevRow = nRow;
do {
pMgr->FindPrevLineMark(--nPrevRow, xtpEditLMT_Bookmark);
} while (nPrevRow > 0 && GetVisibleRow(nPrevRow) == nVisRow);
if (nPrevRow < 0)
{
POSITION posLast = pMgr->GetLastLineMark(xtpEditLMT_Bookmark);
XTP_EDIT_LMDATA* pData = pMgr->GetLineMarkAt(posLast, xtpEditLMT_Bookmark);
nPrevRow = pData ? pData->m_nRow : -1;
}
if (GetVisibleRow(nPrevRow) == nVisRow)
{
nPrevRow = -1;
}
if (nPrevRow >= 0)
{
SetCurPos(nPrevRow, 1);
Invalidate(FALSE);
}
}
void CXTPSyntaxEditCtrl::NextBookmark()
{
CXTPSyntaxEditLineMarksManager* pMgr = GetLineMarksManager();
if (!pMgr)
{
ASSERT(FALSE);
return;
}
int nRow = GetCurRow();
int nVisRow = GetCurrentVisibleRow();
// move down to the next bookmark after the current collapsed block area
int nNextRow = nRow;
do {
pMgr->FindNextLineMark(++nNextRow, xtpEditLMT_Bookmark);
} while (nNextRow > 0 && GetVisibleRow(nNextRow) == nVisRow);
if (nNextRow < 0)
{
// find first line mark
POSITION posFirst = pMgr->GetFirstLineMark(xtpEditLMT_Bookmark);
XTP_EDIT_LMDATA* pData = pMgr->GetNextLineMark(posFirst, xtpEditLMT_Bookmark);
nNextRow = pData ? pData->m_nRow : -1;
}
if (GetVisibleRow(nNextRow) == nVisRow)
{
nNextRow = -1;
}
if (nNextRow >= 0)
{
SetCurPos(nNextRow, 1);
Invalidate(FALSE);
}
}
BOOL CXTPSyntaxEditCtrl::HasRowMark(int nRow, const XTP_EDIT_LINEMARKTYPE& lmType,
XTP_EDIT_LMPARAM* pParam) const
{
if (GetLineMarksManager())
{
return GetLineMarksManager()->HasRowMark(nRow, lmType, pParam);
}
return FALSE;
}
void CXTPSyntaxEditCtrl::DeleteBreakpoint(int nRow)
{
if (GetLineMarksManager())
{
GetLineMarksManager()->DeleteLineMark(nRow, xtpEditLMT_Breakpoint);
}
}
void CXTPSyntaxEditCtrl::RefreshLineMarks(XTP_EDIT_NMHDR_EDITCHANGED* pEditChanged)
{
if (!GetLineMarksManager())
{
ASSERT(FALSE);
return ;
}
int eRefreshType = xtpEditLMRefresh_Unknown;
if (pEditChanged->nAction & XTP_EDIT_EDITACTION_DELETEROW)
{
eRefreshType = xtpEditLMRefresh_Delete;
}
else if (pEditChanged->nAction & XTP_EDIT_EDITACTION_INSERTROW)
{
eRefreshType = xtpEditLMRefresh_Insert;
if (pEditChanged->nAction & XTP_EDIT_EDITACTION_INSERTROW_NEW)
eRefreshType |= xtpEditLMRefresh_InsertAt0;
}
else
{
return;
}
GetLineMarksManager()->RefreshLineMarks(pEditChanged->nRowFrom,
pEditChanged->nRowTo, eRefreshType);
RedrawLineMarks();
}
void CXTPSyntaxEditCtrl::InvalidateAll()
{
CView* pParentWnd = DYNAMIC_DOWNCAST(CView, m_pParentWnd);
if (pParentWnd != NULL && pParentWnd->GetDocument() != NULL)
{
pParentWnd->GetDocument()->UpdateAllViews(NULL, xtpEditHintInvalidate);
}
else
{
if (m_hWnd) Invalidate(FALSE);
}
}
void CXTPSyntaxEditCtrl::RedrawLineMarks()
{
InvalidateAll();
}
BOOL CXTPSyntaxEditCtrl::HasBookmarks() const
{
CXTPSyntaxEditLineMarksManager* pMgr = GetLineMarksManager();
if (pMgr)
{
int nCount = pMgr->GetCount(xtpEditLMT_Bookmark);
return nCount > 0;
}
return FALSE;
}
BOOL CXTPSyntaxEditCtrl::HasBreakpoints() const
{
CXTPSyntaxEditLineMarksManager* pMgr = GetLineMarksManager();
if (pMgr)
{
int nCount = pMgr->GetCount(xtpEditLMT_Breakpoint);
return nCount > 0;
}
return FALSE;
}
CXTPSyntaxEditLineMarksManager* CXTPSyntaxEditCtrl::GetLineMarksManager() const
{
ASSERT(m_pBuffer);
return m_pBuffer ? m_pBuffer->GetLineMarksManager() : NULL;
}
CString CXTPSyntaxEditCtrl::GetModulePath()
{
TCHAR zsFileName[_MAX_PATH];
//DWORD dwRes = ::GetModuleFileName(NULL, zsFileName, _MAX_PATH);
DWORD dwRes = ::GetModuleFileName(AfxGetInstanceHandle(), zsFileName, _MAX_PATH);
ASSERT(dwRes);
CString csFilePath = zsFileName;
int nFLs = csFilePath.ReverseFind(_T('\\'));
if (nFLs > 0)
{
csFilePath.ReleaseBuffer(nFLs + 1);
}
return csFilePath;
}
CString CXTPSyntaxEditCtrl::GetDefaultCfgFilePath()
{
return m_strDefaultCfgFilePath;
}
void CXTPSyntaxEditCtrl::RefreshColors()
{
if (!::IsWindow(m_hWnd) || !m_hWnd)
return;
m_arOnScreenSchCache->RemoveAll();
if (!m_pBuffer)
{
ASSERT(FALSE);
return;
}
if (GetSyntaxColor())
{
XTP_EDIT_LINECOL pos1_0 = {1, 0};
BOOL bParseInThread = m_pBuffer->GetLexParser()->GetSchemaOptions(
m_pBuffer->GetFileExt() )->m_bFirstParseInSeparateThread;
if (bParseInThread)
{
m_pBuffer->GetLexParser()->StartParseInThread(m_pBuffer, &pos1_0, NULL, 0, TRUE);
}
else
{
CXTPSyntaxEditLexTextSchema* ptrTextSch = m_pBuffer->GetLexParser()->GetTextSchema();
if (ptrTextSch)
{
CXTPSyntaxEditTextIterator txtIter(m_pBuffer);
ptrTextSch->RunParseUpdate(TRUE, &txtIter, &pos1_0, NULL);
}
}
}
else
{
GetLineMarksManager()->RemoveAll(xtpEditLMT_Collapsed);
}
// Load data into AC
SetAutoCompleteList();
Invalidate(FALSE);
}
CString CXTPSyntaxEditCtrl::GetConfigFile() const
{
if (!m_pBuffer)
return _T("");
return m_pBuffer->GetConfigFile();
}
BOOL CXTPSyntaxEditCtrl::SetConfigFile(LPCTSTR szPath, BOOL bConfigFileMode)
{
m_strDefaultCfgFilePath = szPath;
//m_bConfigFileMode = bConfigFileMode;
if (!bConfigFileMode)
{
m_bUseMonitor = FALSE;
m_bConfigFileMode = FALSE;
}
if (!m_pBuffer)
return FALSE;
if (m_bConfigFileMode && !FILEEXISTS_S(szPath))
return FALSE;
m_pBuffer->SetConfigFile(szPath);
return TRUE;
}
CString CXTPSyntaxEditCtrl::GetCurrentTheme() const
{
if (!m_pBuffer || !m_pBuffer->GetLexConfigurationManager() || !GetSyntaxColor())
{
static CString strEmpty;
return strEmpty;
}
return m_pBuffer->GetLexConfigurationManager()->GetCurrentTheme();
}
CStringArray& CXTPSyntaxEditCtrl::GetThemes()
{
if (!m_pBuffer || !m_pBuffer->GetLexConfigurationManager())
{
static CStringArray s_ar;
return s_ar;
}
return m_pBuffer->GetLexConfigurationManager()->GetThemeManager().GetThemes();
}
void CXTPSyntaxEditCtrl::ApplyTheme(CString strTheme)
{
if (!m_pBuffer || !m_pBuffer->GetLexConfigurationManager() || !GetSyntaxColor())
{
return;
}
CXTPSyntaxEditLexTextSchema* ptrTextSch = m_pBuffer->GetLexParser()->GetTextSchema();
m_pBuffer->GetLexConfigurationManager()->SetTheme(strTheme, ptrTextSch);
m_arOnScreenSchCache->RemoveAll();
Invalidate(FALSE);
UpdateWindow();
}
void CXTPSyntaxEditCtrl::OnBeforeEditChanged(int nRow, int nCol)
{
UNREFERENCED_PARAMETER(nRow); UNREFERENCED_PARAMETER(nCol);
if (GetSyntaxColor())
{
m_pBuffer->GetLexParser()->OnBeforeEditChanged();
}
}
void CXTPSyntaxEditCtrl::OnEditChanged(const XTP_EDIT_LINECOL& LCFrom,
const XTP_EDIT_LINECOL& LCTo, int eEditAction)
{
OnEditChanged(LCFrom.nLine, LCFrom.nCol, LCTo.nLine, LCTo.nCol, eEditAction);
}
void CXTPSyntaxEditCtrl::OnEditChanged(int nRowFrom, int nColFrom,
int nRowTo, int nColTo, int eEditAction)
{
InvalidateRows(nRowFrom);
if (GetSyntaxColor())
{
XTP_EDIT_LINECOL posFrom = {nRowFrom, max(0, nColFrom-1) };
XTP_EDIT_LINECOL posTo = {nRowTo, max(0, nColTo-1) };
m_pBuffer->GetLexParser()->OnEditChanged(posFrom, posTo, eEditAction, m_pBuffer);
}
}
BOOL CXTPSyntaxEditCtrl::NotifyParseEvent(XTP_NOTIFY_CODE code, WPARAM wParam, LPARAM lParam)
{
// Notify the parent class that position has been changed
XTP_EDIT_NMHDR_PARSEEVENT pe;
// NMHDR codes
pe.nmhdr.code = XTP_EDIT_NM_PARSEEVENT;
pe.nmhdr.hwndFrom = m_hWnd;
pe.nmhdr.idFrom = GetDlgCtrlID();
// notification event code.
pe.code = code;
pe.wParam = wParam;
pe.lParam = lParam;
// Notify the parent window
if (::IsWindow(m_pParentWnd->GetSafeHwnd()))
{
return (BOOL)m_pParentWnd->SendMessage(
WM_NOTIFY, (WPARAM)pe.nmhdr.idFrom, (LPARAM)&pe);
}
return FALSE;
}
void CXTPSyntaxEditCtrl::OnParseEvent(XTP_NOTIFY_CODE code, WPARAM wParam, LPARAM lParam)
{
NotifyParseEvent(code, wParam, lParam);
//-----------------------------------------------------------------------
int nRSFactor = 3;
int nAveRedrawTime = m_aveRedrawScreenTime.GetAverageValue(333);
int nUpdateTimeOut = max(1000, nAveRedrawTime * nRSFactor);
BOOL bRedraw = FALSE;
BOOL bRedrawTimeOut = TRUE;
if (code == xtpEditOnParserStarted)
{
DWORD dwTime = ::GetTickCount();
m_dwLastRedrawTime = dwTime;
}
else if (code == xtpEditOnTextBlockParsed)
{
CXTPSyntaxEditLexTextBlock* pTBended = (CXTPSyntaxEditLexTextBlock*)wParam;
DWORD dwTime = ::GetTickCount();
bRedrawTimeOut = labs(dwTime - m_dwLastRedrawTime) >= nUpdateTimeOut;
if (bRedrawTimeOut)
{
m_dwLastRedrawTime = dwTime;
}
if (pTBended)
{
int nDispMax = GetRowPerPage() - 1;
int nBottomRow = GetDocumentRow(nDispMax+5);
if (!(pTBended->m_PosStartLC.nLine > nBottomRow ||
pTBended->m_PosEndLC.nLine < m_nTopRow) )
{
bRedraw = TRUE;
}
ClearOnScreenSchCache(pTBended->m_PosStartLC.nLine);
}
}
else if (code == xtpEditOnParserEnded)
{
bRedraw = TRUE;
}
//-----------------------------
if (bRedraw)
{
KillTimer(TIMER_REDRAW_WHEN_PARSE);
if (bRedrawTimeOut)
{
Invalidate(FALSE);
UpdateWindow();
}
else
{
SetTimer(TIMER_REDRAW_WHEN_PARSE, nUpdateTimeOut*5, NULL);
}
}
}
//////////////////////////////////////////////////////////////////////////
// Row / col functions
void CXTPSyntaxEditCtrl::SetTopRow(int nRow)
{
if (nRow < 1)
m_nTopRow = 1;
else if (nRow > GetRowCount())
m_nTopRow = max (1, GetRowCount());
else
m_nTopRow = max (1, nRow);
}
int CXTPSyntaxEditCtrl::GetCurRow() const
{
return GetCurrentDocumentRow();
}
void CXTPSyntaxEditCtrl::GoToRow(int iRow, BOOL bSelectRow/* = FALSE*/)
{
CString csLineText = GetLineText(iRow);
m_nCurrentCol = 1;
m_nDispCol = 1;
if (bSelectRow)
{
m_pSelection->Reset_disp(iRow, 1);
m_pSelection->SetEnd_disp(iRow+1, 1);
SetCurrentDocumentRow(iRow);
Invalidate(FALSE);
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, TRUE, TRUE);
//SetTimer(TIMER_SELECTION_ID, TIMER_SELECTION_TIME, NULL);
}
else
{
SetCurrentDocumentRow(iRow);
SetCurPos(iRow, 1);
}
}
int CXTPSyntaxEditCtrl::GetCurrentVisibleRow()
{
return GetVisibleRow(GetCurrentDocumentRow());
}
int CXTPSyntaxEditCtrl::GetCurrentDocumentRow() const
{
return m_nCurrentDocumentRow;
}
void CXTPSyntaxEditCtrl::SetCurrentDocumentRow(int nRow)
{
if (nRow > GetRowCount())
nRow = GetRowCount();
if (nRow < 1)
nRow = 1;
m_nCurrentDocumentRow = nRow;
}
int CXTPSyntaxEditCtrl::GetDocumentRow(int nVisibleRow)
{
return CalculateDocumentRow(m_nTopRow, nVisibleRow);
}
int CXTPSyntaxEditCtrl::CalculateDocumentRow(int nStartDocumentRow, int nRowDelta)
{
int nDocRow = nStartDocumentRow + nRowDelta - 1;
int nNextCollapsedRow = nStartDocumentRow - 1;
POSITION pos = GetLineMarksManager()->FindNextLineMark(nNextCollapsedRow, xtpEditLMT_Collapsed);
while (pos != NULL)
{
XTP_EDIT_LMDATA* pData = GetLineMarksManager()->GetNextLineMark(pos, xtpEditLMT_Collapsed);
if (pData && pData->m_nRow >= nNextCollapsedRow) // mark should be not within previous collapsed block
{
if (pData->m_nRow >= nDocRow) // finish if mark is greater then row to calculate for
break;
XTP_EDIT_COLLAPSEDBLOCK* pCoDBlk = (XTP_EDIT_COLLAPSEDBLOCK*)pData->m_Param.GetPtr();
if (!pCoDBlk)
continue;
int nHiddenRows = pCoDBlk->collBlock.lcEnd.nLine - pCoDBlk->collBlock.lcStart.nLine;
nDocRow += nHiddenRows;
nNextCollapsedRow = pData->m_nRow + nHiddenRows;
}
}
return nDocRow;
}
int CXTPSyntaxEditCtrl::GetVisibleRow(int nDocumentRow)
{
return CalculateVisibleRow(m_nTopRow, nDocumentRow);
}
int CXTPSyntaxEditCtrl::CalculateVisibleRow(int nStartDocumentRow, int nDocumentRow)
{
int nVisRow = nDocumentRow - nStartDocumentRow + 1;
int nNextCollapsedRow = nStartDocumentRow - 1;
const int nRowCount = GetRowCount();
POSITION pos = GetLineMarksManager()->FindNextLineMark(nNextCollapsedRow, xtpEditLMT_Collapsed);
while (pos != NULL)
{
XTP_EDIT_LMDATA* pData = GetLineMarksManager()->GetNextLineMark(pos, xtpEditLMT_Collapsed);
if (pData && pData->m_nRow >= nNextCollapsedRow) // mark should be not within previous collapsed block
{
if (pData->m_nRow >= nDocumentRow) // finish if mark is greater then row to calculate for
break;
XTP_EDIT_COLLAPSEDBLOCK* pCoDBlk = (XTP_EDIT_COLLAPSEDBLOCK*)pData->m_Param.GetPtr();
if (!pCoDBlk)
continue;
int nHiddenRows = min(nRowCount, pCoDBlk->collBlock.lcEnd.nLine) -
pCoDBlk->collBlock.lcStart.nLine;
nVisRow -= nHiddenRows;
nNextCollapsedRow = pData->m_nRow + nHiddenRows;
}
}
return max(nVisRow, 1);
}
int CXTPSyntaxEditCtrl::MoveCurrentVisibleRowUp(int nCount)
{
int nOldVisRow = GetCurrentVisibleRow();
int nOldDocRow = GetCurrentDocumentRow();
int nNewVisRow = nOldVisRow - nCount;
// do not shift a window up
if (nNewVisRow > 0)
{
SetCurrentDocumentRow(GetDocumentRow(nNewVisRow));
return nNewVisRow;
}
// find global visible row index
int nVisRow = CalculateVisibleRow(1, nOldDocRow);
int nTargetDocRow = CalculateDocumentRow(1, max(nVisRow - nCount, 1));
int nDocDiff = nOldDocRow - nTargetDocRow;
nDocDiff = min(nDocDiff, m_nTopRow - 1);
nOldDocRow -= nDocDiff;
m_nCurrentDocumentRow -= nDocDiff;
m_nTopRow -= nDocDiff;
nNewVisRow = nOldVisRow - nDocDiff + GetRowPerPage();
return GetCurrentVisibleRow();
}
int CXTPSyntaxEditCtrl::MoveCurrentVisibleRowDown(int nCount)
{
int nOldRow = GetCurrentVisibleRow();
int nNewDocRow = min(GetDocumentRow(nOldRow + nCount), GetRowCount());
SetCurrentDocumentRow(nNewDocRow);
int nMaxVisRow = GetRowPerPage();
int nMaxDocRow = GetDocumentRow(nMaxVisRow);
if (nNewDocRow > nMaxDocRow)
{
m_nTopRow = max (1, GetDocumentRow(nCount + 1));
}
return GetCurrentVisibleRow();
}
int CXTPSyntaxEditCtrl::GetRowPerPage() const
{
return m_pDrawTextProcessor->GetRowsCount(FALSE);
}
int CXTPSyntaxEditCtrl::GetVisibleRowsCount(int nMaxDocRow)
{
if (nMaxDocRow < 0)
nMaxDocRow = GetRowCount();
int nVisRow = nMaxDocRow;
CXTPSyntaxEditLineMarksManager* pMgr = GetLineMarksManager();
if (pMgr)
{
int nNextCollapsedRow = -1;
POSITION pos = pMgr->GetFirstLineMark(xtpEditLMT_Collapsed);
while (pos != NULL)
{
XTP_EDIT_LMDATA* pData = pMgr->GetNextLineMark(pos, xtpEditLMT_Collapsed);
if (pData && pData->m_nRow >= nNextCollapsedRow) // mark should be not within previous collapsed block
{
if (pData->m_nRow >= nMaxDocRow) // finish if mark is greater then row to calculate for
break;
XTP_EDIT_COLLAPSEDBLOCK* pCoDBlk = (XTP_EDIT_COLLAPSEDBLOCK*)pData->m_Param.GetPtr();
if (!pCoDBlk)
continue;
int nHiddenRows = pCoDBlk->collBlock.lcEnd.nLine - pCoDBlk->collBlock.lcStart.nLine;
nVisRow -= nHiddenRows;
nNextCollapsedRow = pData->m_nRow + nHiddenRows;
}
}
}
return nVisRow;
}
BOOL CXTPSyntaxEditCtrl::ShiftCurrentVisibleRowUp(int nCount, BOOL bChangeCaret)
{
BOOL bChanged = FALSE;
if (m_nTopRow > 1)
{
int nOldTopRow = m_nTopRow;
int nDocRow = GetCurrentDocumentRow(); // store old document row
SetCurrentDocumentRow(GetDocumentRow(1)); // move to first visible row
MoveCurrentVisibleRowUp(nCount); // move nCount row up
// move to old document row
int nBottomDocRow = GetDocumentRow(GetRowPerPage());
if (bChangeCaret)
nDocRow = min(nDocRow, nBottomDocRow);
SetCurrentDocumentRow(nDocRow);
if (nDocRow > nBottomDocRow)
CWnd::HideCaret();
if (nOldTopRow != m_nTopRow)
bChanged = TRUE;
}
return bChanged;
}
BOOL CXTPSyntaxEditCtrl::ShiftCurrentVisibleRowDown(int nCount, BOOL bChangeCaret)
{
BOOL bChanged = FALSE;
if (m_nTopRow < GetRowCount())
{
int nOldTopRow = m_nTopRow;
int nDocRow = GetCurrentDocumentRow();
int nLastVisRow = GetRowPerPage();
SetCurrentDocumentRow(GetDocumentRow(nLastVisRow));
MoveCurrentVisibleRowDown(nCount);
int nTopDocRow = GetDocumentRow(1);
if (bChangeCaret)
nDocRow = max(nDocRow, nTopDocRow);
SetCurrentDocumentRow(nDocRow);
if (nDocRow < nTopDocRow)
CWnd::HideCaret();
if (nOldTopRow != m_nTopRow)
bChanged = TRUE;
}
return bChanged;
}
BOOL CXTPSyntaxEditCtrl::GetCollapsedBlockLen(int nStartRow, int& rnLen) const
{
rnLen = 0;
XTP_EDIT_LMPARAM LMCoParam;
BOOL bIsCollapsed = HasRowMark(nStartRow, xtpEditLMT_Collapsed, &LMCoParam);
if (!bIsCollapsed)
{
return FALSE;
}
XTP_EDIT_COLLAPSEDBLOCK* pCoDBlk = (XTP_EDIT_COLLAPSEDBLOCK*)LMCoParam.GetPtr();
if (!pCoDBlk)
{
ASSERT(FALSE);
return FALSE;
}
rnLen = pCoDBlk->collBlock.lcEnd.nLine - pCoDBlk->collBlock.lcStart.nLine;
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
// Line text internal functions
CString CXTPSyntaxEditCtrl::GetLineText(int nRow, BOOL bAddCRLF, int iCRLFStyle) const
{
CString strResult;
GetLineText(nRow, strResult, bAddCRLF, iCRLFStyle);
return strResult;
}
void CXTPSyntaxEditCtrl::GetLineText(int nRow, CString& strBuffer, BOOL bAddCRLF, int iCRLFStyle) const
{
m_pBuffer->GetLineText(nRow, strBuffer, bAddCRLF, iCRLFStyle);
XTP_EDIT_LMPARAM LMCoParam;
BOOL bIsCollapsed = HasRowMark(nRow, xtpEditLMT_Collapsed, &LMCoParam);
if (bIsCollapsed)
{
XTP_EDIT_COLLAPSEDBLOCK* pCoDBlk = (XTP_EDIT_COLLAPSEDBLOCK*)LMCoParam.GetPtr();
if (!pCoDBlk)
{
ASSERT(FALSE);
return;
}
if (strBuffer.GetLength() > pCoDBlk->collBlock.lcStart.nCol)
{
strBuffer.SetAt(pCoDBlk->collBlock.lcStart.nCol, 0);
}
}
}
void CXTPSyntaxEditCtrl::SetAutoCompleteList()
{
CXTPSyntaxEditLexTokensDefArray arTokens;
m_pBuffer->GetLexParser()->GetTokensForAutoCompleate(arTokens, FALSE);
CXTPSyntaxEditACDataArray arrData;
CXTPSyntaxEditLexTokensDef TokenDef;
int nTokensDef = (int)arTokens.GetSize();
if (!nTokensDef)
return;
for (int nTokenDef = 0; nTokenDef < nTokensDef; nTokenDef++)
{
TokenDef = (arTokens.GetAt(nTokenDef));
int nTags = (int)TokenDef.m_arTokens.GetSize();
for (int nTag = 0; nTag < nTags; nTag++)
{
CString sDef = TokenDef.m_arTokens.GetAt(nTag);
arrData.Add(new XTP_EDIT_ACDATA(0, sDef));
//arrData.Add(new XTP_EDIT_ACDATA(0, TokenDef.m_arTokens.GetAt(nTag)));
}
int nDelims = (int)TokenDef.m_arStartSeps.GetSize();
int nDelim;
for (nDelim = 0; nDelim < nDelims; nDelim++)
{
if (m_pAutoComplete->m_strDelims.Find(TokenDef.m_arStartSeps.GetAt(nDelim)) < 0)
m_pAutoComplete->m_strDelims += TokenDef.m_arStartSeps.GetAt(nDelim);
}
nDelims = (int)TokenDef.m_arEndSeps.GetSize();
for (nDelim = 0; nDelim < nDelims; nDelim++)
{
if (m_pAutoComplete->m_strDelims.Find(TokenDef.m_arEndSeps.GetAt(nDelim)) < 0)
m_pAutoComplete->m_strDelims += TokenDef.m_arEndSeps.GetAt(nDelim);
}
}
m_pAutoComplete->SetList(arrData);
}
BOOL CXTPSyntaxEditCtrl::PreTranslateMessage(MSG* pMsg)
{
if (m_pAutoComplete->IsActive())
{
switch (pMsg->message)
{
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
case WM_DEADCHAR:
{
m_pAutoComplete->SendMessage(
pMsg->message, pMsg->wParam, pMsg->lParam);
}
break;
}
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_SPACE:
case VK_PRIOR:
case VK_NEXT:
case VK_END:
case VK_HOME:
case VK_LEFT:
case VK_UP:
case VK_RIGHT:
case VK_DOWN:
case VK_SELECT:
case VK_PRINT:
case VK_EXECUTE:
case VK_SNAPSHOT:
case VK_INSERT:
case VK_DELETE:
case VK_HELP:
case VK_RETURN:
{
return TRUE;
}
}
}
}
else if (IsEnabledEditAccelerators() &&
(pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN))
{
BOOL bAltKey = (::GetKeyState(VK_MENU) & KF_UP) != 0;
BOOL bCtrlKey = (::GetKeyState(VK_CONTROL) & KF_UP) != 0;
BOOL bShiftKey = (::GetKeyState(VK_SHIFT) & KF_UP) != 0;
BOOL bAlt = bAltKey && !bCtrlKey && !bShiftKey;
BOOL bCtrl = bCtrlKey && !bAltKey && !bShiftKey;
BOOL bShift = bShiftKey && !bAltKey && !bCtrlKey;
BOOL bCtrlShift = bCtrlKey && bShiftKey && !bAltKey;
BOOL bProcessed = TRUE;
if (bCtrlKey && pMsg->wParam == (BYTE)'X')
{
if (IsSelectionExist() && CanEditDoc())
Cut();
}
else if (bCtrl && pMsg->wParam == (BYTE)'C' ||
bCtrl && pMsg->wParam == VK_INSERT)
{
if (IsSelectionExist())
Copy();
}
else if (bCtrl && pMsg->wParam == (BYTE)'V' ||
bShift && pMsg->wParam == VK_INSERT)
{
if (CanEditDoc())
Paste();
}
else if (bAlt && pMsg->wParam == VK_BACK ||
bCtrl && pMsg->wParam == (BYTE)'Z')
{
if (CanUndo())
Undo();
}
else if (bCtrl && pMsg->wParam == (BYTE)'Y' ||
bCtrlShift && pMsg->wParam == (BYTE)'Z')
{
if (CanRedo())
Redo();
}
else if (bCtrl && pMsg->wParam == (BYTE)'A')
{
SelectAll();
}
else
{
bProcessed = FALSE;
}
if (bProcessed)
return TRUE;
}
return CWnd::PreTranslateMessage(pMsg);
}
BOOL CXTPSyntaxEditCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
if (m_pAutoComplete->IsActive())
{
return (BOOL)m_pAutoComplete->SendMessage(WM_MOUSEWHEEL,
MAKEWPARAM(nFlags, zDelta), MAKELPARAM(pt.x, pt.y));
//CXTPWindowRect rcWndAC(&m_wndAutoComplete);
//if (rcWndAC.PtInRect(pt))
// return (BOOL)m_pAutoComplete->SendMessage(WM_MOUSEWHEEL, MAKEWPARAM(nFlags, zDelta), MAKELPARAM(pt.x, pt.y));
//else
// m_pAutoComplete->Hide();
}
m_pToolTip->Hide();
if (zDelta < 0)
Scroll(0, m_nWheelScroll);
else
Scroll(0, -m_nWheelScroll);
return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}
void CXTPSyntaxEditCtrl::CollapseAll()
{
CXTPSyntaxEditLineMarksManager* pMgr = GetLineMarksManager();
if (!pMgr)
return;
CWaitCursor _WC;
CXTPSyntaxEditRowsBlockArray arCoBlocks;
GetCollapsableBlocksInfo(-1, arCoBlocks);
for (int nRow = 0; nRow < GetRowCount(); nRow++)
{
XTP_EDIT_LMPARAM LMCoParam;
int toRemove = -1;
int nCount = (int)arCoBlocks.GetSize();
for (int i = 0; i < nCount; i++)
{
XTP_EDIT_ROWSBLOCK coBlk = arCoBlocks[i];
if (coBlk.lcStart.nLine == nRow)
{
XTP_EDIT_COLLAPSEDBLOCK* pCoDrawBlk = (XTP_EDIT_COLLAPSEDBLOCK*)LMCoParam.GetPtr();
if (!pCoDrawBlk)
{
pCoDrawBlk = new XTP_EDIT_COLLAPSEDBLOCK;
if (!pCoDrawBlk)
{
return;
}
LMCoParam.SetPtr(pCoDrawBlk, XTPSECollapsedBlockDeleteFn);
}
pCoDrawBlk->collBlock = coBlk;
pMgr->SetLineMark(nRow, xtpEditLMT_Collapsed, &LMCoParam);
m_arCollapsedTextRows.SetAtGrow(m_nCollapsedTextRowsCount, nRow);
m_nCollapsedTextRowsCount++;
if (toRemove < 0)
toRemove = i;
}
}
if (toRemove >= 0)
arCoBlocks.RemoveAt(0, toRemove+1);
}
// refresh picture
SetCurCaretPos(GetCurrentDocumentRow(), 1);
UpdateWindow();
RecalcScrollBars();
UpdateScrollPos();
}
void CXTPSyntaxEditCtrl::ExpandAll()
{
CXTPSyntaxEditLineMarksManager* pMgr = GetLineMarksManager();
if (!pMgr)
return;
CWaitCursor _WC;
pMgr->RemoveAll(xtpEditLMT_Collapsed);
// refresh picture
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol);
if (::IsWindow(m_hWnd))
UpdateWindow();
RecalcScrollBars();
UpdateScrollPos();
}
void CXTPSyntaxEditCtrl::GetRowColors(int nTextRow, int nColFrom, int nColTo,
const XTP_EDIT_COLORVALUES& clrDefault,
CXTPSyntaxEditTextBlockList* rBlocks)
{
if (!GetSyntaxColor())
return;
CXTPSyntaxEditLexTextSchema* ptrTxtSch = m_pBuffer->GetLexParser()->GetTextSchema();
if (ptrTxtSch)
{
CXTPSyntaxEditLexTextBlock* pScreenSchFirstTB = GetOnScreenSch(nTextRow);
//CXTPSyntaxEditLexTextBlock* pScreenSchFirstTB = ptrTxtSch->GetBlocks();
if (pScreenSchFirstTB)
{
CXTPSyntaxEditTextIterator txtIter(GetEditBuffer());
ptrTxtSch->GetRowColors(&txtIter, nTextRow, nColFrom, nColTo,
clrDefault, rBlocks, NULL, pScreenSchFirstTB);
}
}
}
void CXTPSyntaxEditCtrl::GetCollapsableBlocksInfo(int nTextRow,
CXTPSyntaxEditRowsBlockArray& rarCoBlocks) const
{
rarCoBlocks.RemoveAll();
if (GetSyntaxColor())
{
CXTPSyntaxEditLexTextSchema* ptrTxtSch = m_pBuffer->GetLexParser()->GetTextSchema();
if (ptrTxtSch)
ptrTxtSch->GetCollapsableBlocksInfo(nTextRow, rarCoBlocks, &m_fcCollapsable->ptrTBStart);
}
}
CXTPSyntaxEditLexTextBlock* CXTPSyntaxEditCtrl::GetOnScreenSch(int nForRow)
{
int nLifeTime = m_pBuffer->GetLexParser()->GetSchemaOptions(
m_pBuffer->GetFileExt())->m_dwOnScreenSchCacheLifeTime_sec;
m_arOnScreenSchCache->RemoveOld(nLifeTime);
//========================================================================
int nCount = (int)m_arOnScreenSchCache->GetSize();
int i;
for (i = 0; i < nCount; i++)
{
CScreenSearchBlock& rSchBlk = m_arOnScreenSchCache->ElementAt(i);
if (nForRow >= rSchBlk.nRowStart && nForRow <= rSchBlk.nRowEnd)
{
rSchBlk.dwLastAccessTime = ::GetTickCount();
return rSchBlk.ptrTBFirst;
}
}
//---------------------------------------------------------------------------
CXTPSyntaxEditLexTextSchema* ptrTxtSch = m_pBuffer->GetLexParser()->GetTextSchema();
if (ptrTxtSch)
{
int nRowPerPage = GetRowPerPage()+1;
CScreenSearchBlock schBlkNew;
schBlkNew.nRowStart = nForRow;
schBlkNew.nRowEnd = nForRow + nRowPerPage;
//--------------------------------------------------------------------
int nRowStartMin = 1;
// 1. search next on screen region
nCount = (int)m_arOnScreenSchCache->GetSize();
for (i = 0; i < nCount; i++)
{
const CScreenSearchBlock& rSchBlk = m_arOnScreenSchCache->ElementAt(i);
if (rSchBlk.nRowStart > schBlkNew.nRowStart && rSchBlk.nRowStart <= schBlkNew.nRowEnd)
{
schBlkNew.nRowEnd = rSchBlk.nRowStart-1;
}
if (rSchBlk.nRowEnd+1 > nRowStartMin && rSchBlk.nRowEnd+1 < nForRow)
{
nRowStartMin = rSchBlk.nRowEnd+1;
}
}
//--------------------------------------------------------------------
// 2. search next collapsed block start
for (i = 0; i < m_nCollapsedTextRowsCount; i++)
{
int nCoStartRow = m_arCollapsedTextRows[i];
if (nCoStartRow >= schBlkNew.nRowStart && nCoStartRow < schBlkNew.nRowEnd)
{
schBlkNew.nRowEnd = nCoStartRow;
}
}
//===========================
if (schBlkNew.nRowEnd - schBlkNew.nRowStart < nRowPerPage/2)
{
schBlkNew.nRowStart = max(schBlkNew.nRowStart-nRowPerPage, nRowStartMin);
}
//--------------------------------------------------------------------
CXTPSyntaxEditTextIterator txtIter(m_pBuffer);
BOOL bParseRes = ptrTxtSch->RunParseOnScreen(&txtIter, schBlkNew.nRowStart,
schBlkNew.nRowEnd, schBlkNew.ptrTBFirst);
if (bParseRes)
{
schBlkNew.dwLastAccessTime = ::GetTickCount();
m_arOnScreenSchCache->Add(schBlkNew);
return schBlkNew.ptrTBFirst;
}
}
return NULL;
}
void CXTPSyntaxEditCtrl::InvalidateRows(int nRowFrom, int nRowTo)
{
int nCountVDR = (int)m_arValidDispRows.GetSize();
//-* Invalidate ALL ------------------------------------------------------
if (nRowFrom < 0 && nRowTo < 0)
{
m_arOnScreenSchCache->RemoveAll();
for (int i = 0; i < nCountVDR; i++) {
m_arValidDispRows.SetAtGrow(i, 0);
}
return ;
}
//-* Invalidate Part -----------------------------------------------------
int nRow1 = nRowFrom;
int nRow2 = nRowTo;
if (nRow1 < 0)
{
nRow1 = m_nTopRow;
}
if (nRow2 < nRow1)
{
nRow2 = GetDocumentRow(GetRowPerPage());
}
int nDispRow1= CalculateVisibleRow(m_nTopRow, nRow1);
int nDispRow2 = CalculateVisibleRow(m_nTopRow, nRow2);
int nI1 = max(min(nDispRow1, 1000), 0);
int nI2 = max(min(nDispRow2, 1000), nCountVDR-1);
for (int i = nI1; i <= nI2; i++)
{
m_arValidDispRows.SetAtGrow(i, 0);
}
//===========================================================================
ClearOnScreenSchCache(nRowFrom);
}
void CXTPSyntaxEditCtrl::ClearOnScreenSchCache(int nRowFrom)
{
//-* clear ALL ------------------------------------------------------
if (nRowFrom < 0)
{
m_arOnScreenSchCache->RemoveAll();
return ;
}
//===========================================================================
int nCountSSC = (int)m_arOnScreenSchCache->GetSize();
for (int i = nCountSSC-1; i >= 0; i--)
{
CScreenSearchBlock& rSchBlk = m_arOnScreenSchCache->ElementAt(i);
BOOL bRemove = FALSE;
if (nRowFrom >= rSchBlk.nRowStart && nRowFrom <= rSchBlk.nRowEnd)
{
rSchBlk.nRowEnd = nRowFrom-1;
bRemove = !(rSchBlk.nRowStart <= rSchBlk.nRowEnd);
}
else if (nRowFrom < rSchBlk.nRowStart)
{
bRemove = TRUE;
}
//-------------------------------------
if (bRemove)
{
m_arOnScreenSchCache->RemoveAt(i);
}
else
{
ASSERT(m_arOnScreenSchCache->ElementAt(i).nRowStart == rSchBlk.nRowStart);
ASSERT(m_arOnScreenSchCache->ElementAt(i).nRowEnd == rSchBlk.nRowEnd);
}
}
}
void CXTPSyntaxEditCtrl::SetRowValid(int nDispRow)
{
ASSERT(nDispRow < 1000);
m_arValidDispRows.SetAtGrow(nDispRow, 1);
}
BOOL CXTPSyntaxEditCtrl::IsRowValid(int nDispRow) const
{
int nCount = (int)m_arValidDispRows.GetSize();
if (nDispRow > 0 && nDispRow < nCount)
{
int nValid = m_arValidDispRows[nDispRow];
return (nValid != 0);
}
return FALSE;
}
const CStringList& CXTPSyntaxEditCtrl::GetUndoTextList()
{
return m_pBuffer->GetUndoRedoManager()->GetUndoTextList();
}
const CStringList& CXTPSyntaxEditCtrl::GetRedoTextList()
{
return m_pBuffer->GetUndoRedoManager()->GetRedoTextList();
}
void CXTPSyntaxEditCtrl::OnLexCfgWasChanged(XTP_NOTIFY_CODE code, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam);
if (code == xtpEditAllConfigWasChanged ||
code == xtpEditClassSchWasChanged ||
code == xtpEditThemeWasChanged)
{
m_arOnScreenSchCache->RemoveAll();
Invalidate(FALSE);
}
else
{
ASSERT(FALSE);
}
}
BOOL CXTPSyntaxEditCtrl::GetRowNodes(int nRow, DWORD& dwType) const
{
dwType = XTP_EDIT_ROWNODE_NOTHING;
// retrieve row nodes
CXTPSyntaxEditRowsBlockArray arCoBlocks;
GetCollapsableBlocksInfo(nRow, arCoBlocks);
int nCount = (int)arCoBlocks.GetSize();
for (int i = 0; i < nCount; i++)
{
XTP_EDIT_ROWSBLOCK coBlk = arCoBlocks[i];
if (coBlk.lcStart.nLine == nRow)
{
if (HasRowMark(coBlk.lcStart.nLine, xtpEditLMT_Collapsed))
{
dwType |= XTP_EDIT_ROWNODE_COLLAPSED;
}
else
{
dwType |= XTP_EDIT_ROWNODE_EXPANDED;
}
}
if (coBlk.lcEnd.nLine == nRow)
{
dwType |= XTP_EDIT_ROWNODE_ENDMARK;
}
if (coBlk.lcStart.nLine < nRow)
{
dwType |= XTP_EDIT_ROWNODE_NODEUP;
}
if (coBlk.lcEnd.nLine > nRow && (dwType & XTP_EDIT_ROWNODE_COLLAPSED))
{
dwType |= XTP_EDIT_ROWNODE_NODEDOWN;
}
}
return (dwType != XTP_EDIT_ROWNODE_NOTHING);
}
BOOL CXTPSyntaxEditCtrl::NotifyMarginLBtnClick(int nRow, int nDispRow) const
{
// Notify the parent class that position has been changed
XTP_EDIT_NMHDR_MARGINCLICKED somc;
// NMHDR codes
somc.nmhdr.code = XTP_EDIT_NM_MARGINCLICKED;
somc.nmhdr.hwndFrom = m_hWnd;
somc.nmhdr.idFrom = GetDlgCtrlID();
// Row col specific codes
somc.nRow = nRow;
somc.nDispRow = nDispRow;
// Notify the parent window
if (::IsWindow(m_pParentWnd->GetSafeHwnd()))
{
return (BOOL)m_pParentWnd->SendMessage(
WM_NOTIFY, (WPARAM)somc.nmhdr.idFrom, (LPARAM)&somc);
}
return FALSE;
}
UINT CXTPSyntaxEditCtrl::CalcAveDataSize(int nRowStart, int nRowEnd)
{
UINT uSize = m_nAverageLineLen * abs(nRowStart - nRowEnd);
uSize = (uSize / 1024 + 1) * 1024;
return uSize;
}
BOOL CXTPSyntaxEditCtrl::GetWideCaret() const
{
return m_pOptions->m_bWideCaret && m_pBuffer && m_pBuffer->GetOverwriteFlag();
}
CXTPSyntaxEditSelection& CXTPSyntaxEditCtrl::GetSelection()
{
return *m_pSelection;
}
CXTPSyntaxEditDrawTextProcessor& CXTPSyntaxEditCtrl::GetDrawTextProcessor()
{
return *m_pDrawTextProcessor;
}
BOOL CXTPSyntaxEditCtrl::SetWideCaret(BOOL bWideCaret, BOOL bUpdateReg/*=FALSE*/)
{
if (m_pOptions->m_bWideCaret != bWideCaret)
{
if (!SetValueBool(XTP_EDIT_REG_WIDECARET, bWideCaret, m_pOptions->m_bWideCaret, bUpdateReg))
return FALSE;
SetCurCaretPos(GetCurrentDocumentRow(), m_nDispCol, FALSE, FALSE);
}
return TRUE;
}
void CXTPSyntaxEditCtrl::SetPaintManager(CXTPSyntaxEditPaintManager* pPaintManager)
{
ASSERT(pPaintManager);
if (pPaintManager)
{
CMDTARGET_RELEASE(m_pPaintManeger);
m_pPaintManeger = pPaintManager;
}
}
//===========================================================================
// CXTPSyntaxEditCtrl::CTextSearchCache
//===========================================================================
CXTPSyntaxEditCtrl::CTextSearchCache::CTextSearchCache()
{
nForTopRow = 0;
}
void CXTPSyntaxEditCtrl::CTextSearchCache::Update(int nCurrTopRow)
{
if (nCurrTopRow != nForTopRow)
{
ptrTBStart = NULL;
nForTopRow = nCurrTopRow;
}
}
//===========================================================================
// CXTPSyntaxEditCtrl::CScreenSearchBlock
//===========================================================================
CXTPSyntaxEditCtrl::CScreenSearchBlock::CScreenSearchBlock()
{
nRowStart = nRowEnd = 0;
dwLastAccessTime = 0;
}
CXTPSyntaxEditCtrl::CScreenSearchBlock::CScreenSearchBlock(const CScreenSearchBlock& rSrc)
{
nRowStart = rSrc.nRowStart;
nRowEnd = rSrc.nRowEnd;
ptrTBFirst = rSrc.ptrTBFirst;
dwLastAccessTime = rSrc.dwLastAccessTime;
}
CXTPSyntaxEditCtrl::CScreenSearchBlock::~CScreenSearchBlock()
{
}
//===========================================================================
// CXTPSyntaxEditCtrl::CScreenSearchCache
//===========================================================================
CXTPSyntaxEditCtrl::CScreenSearchCache::CScreenSearchCache()
{
m_dwLastRemoveOldTime = 0;
}
CXTPSyntaxEditCtrl::CScreenSearchCache::~CScreenSearchCache()
{
RemoveAll();
}
void CXTPSyntaxEditCtrl::CScreenSearchCache::RemoveAll()
{
for (int i = 0; i < (int)GetSize(); i++)
{
CScreenSearchBlock& rSchBlk = ElementAt(i);
CXTPSyntaxEditLexTextSchema::Close(rSchBlk.ptrTBFirst);
}
Base::RemoveAll();
}
void CXTPSyntaxEditCtrl::CScreenSearchCache::RemoveAt(int nIndex)
{
CScreenSearchBlock& rSchBlk = ElementAt(nIndex);
CXTPSyntaxEditLexTextSchema::Close(rSchBlk.ptrTBFirst);
Base::RemoveAt(nIndex);
}
void CXTPSyntaxEditCtrl::CScreenSearchCache::RemoveOld(int nTimeOut_sec)
{
int nTimeOut_ms = nTimeOut_sec * 1000;
DWORD dwTime = ::GetTickCount();
int cnCheckTimeOut_ms = min(nTimeOut_sec, 10*1000);
if (nTimeOut_sec == 0 || nTimeOut_sec == -1 ||
labs(dwTime - m_dwLastRemoveOldTime) < cnCheckTimeOut_ms)
{
return;
}
//================================================================
m_dwLastRemoveOldTime = dwTime;
for (int i = (int)GetSize() - 1; i >= 0; i--)
{
CScreenSearchBlock& rSchBlk = ElementAt(i);
if (labs(dwTime - rSchBlk.dwLastAccessTime) >= nTimeOut_ms)
{
CXTPSyntaxEditLexTextSchema::Close(rSchBlk.ptrTBFirst);
Base::RemoveAt(i);
}
}
}
//===========================================================================
// CXTPSyntaxEditCtrl::CAverageVal
//===========================================================================
CXTPSyntaxEditCtrl::CAverageVal::CAverageVal(int nDataSize/* = 100*/)
{
m_nDataSize = max(1, nDataSize);
m_nNextIndex = 0;
}
void CXTPSyntaxEditCtrl::CAverageVal::AddValue(UINT uVal)
{
m_arData.SetAtGrow(m_nNextIndex, uVal);
m_nNextIndex = (m_nNextIndex+1) % m_nDataSize;
}
UINT CXTPSyntaxEditCtrl::CAverageVal::GetAverageValue(UINT uDefaultIfNoData/* = 0*/)
{
int nCount = (int)m_arData.GetSize();
if (nCount <= 0)
return uDefaultIfNoData;
UINT uSumm = 0;
for (int i = 0; i < nCount; i++)
uSumm += m_arData[i];
UINT uAveVal = uSumm / nCount;
return uAveVal;
}
int CXTPSyntaxEditCtrl::GetRowCount() const
{
return m_pBuffer ? m_pBuffer->GetRowCount() : 0;
}
CXTPSyntaxEditConfigurationManager* CXTPSyntaxEditCtrl::GetLexConfigurationManager() const
{
return m_pBuffer? m_pBuffer->GetLexConfigurationManager(): NULL;
}
void CXTPSyntaxEditCtrl::ReloadSyntaxConfigFileMode()
{
CXTPSyntaxEditConfigurationManager* pMan = GetLexConfigurationManager();
if (pMan)
{
pMan->m_bConfigFileMode = TRUE;
pMan->m_bUseMonitor = TRUE;
pMan->m_sIniSet = _T("");
}
m_bUseMonitor = TRUE;
m_bConfigFileMode = TRUE;
}
void CXTPSyntaxEditCtrl::ReloadSyntaxStringMode()
{
if (GetEditBuffer())
{
if (m_sPassedIniSet.IsEmpty())
m_sIniSet = _T("[Schemes]\r\nCPP\r\n[Themes]\r\nDefault\r\nAlternative\r\n");
else
m_sIniSet = m_sPassedIniSet;
CXTPSyntaxEditConfigurationManager* pMan = GetLexConfigurationManager();
if (pMan)
{
pMan->m_bConfigFileMode = FALSE;
pMan->m_bUseMonitor = FALSE;
pMan->m_sIniSet = m_sIniSet;
}
m_bUseMonitor = FALSE;
m_bConfigFileMode = FALSE;
SetConfigFile(_T(""), FALSE);
}
}
void CXTPSyntaxEditCtrl::SetSyntaxAndColorScheme(CString sSyntaxScheme, CString sColorScheme,
BOOL bScheme /*FALSE*/, BOOL bColors /*FALSE*/)
{
if (!sSyntaxScheme.IsEmpty() && !sColorScheme.IsEmpty())
{
if (m_sPassedIniSet.IsEmpty())
m_sIniSet = _T("[Schemes]\r\nCPP\r\n[Themes]\r\nDefault\r\nAlternative\r\n");
else
m_sIniSet = m_sPassedIniSet;
m_strSyntaxScheme = sSyntaxScheme;
m_strColorScheme = sColorScheme;
if (bScheme)
{
CXTPSyntaxEditStringDlg dlg;
dlg.m_Syntax = m_strSyntaxScheme;
if (dlg.DoModal() == IDOK)
m_strSyntaxScheme = dlg.m_Syntax;
}
if (bColors)
{
CXTPSyntaxEditStringDlg dlg;
dlg.m_Syntax = m_strColorScheme;
if (dlg.DoModal() == IDOK)
m_strColorScheme = dlg.m_Syntax;
}
m_bUseMonitor = FALSE;
m_bConfigFileMode = FALSE;
CXTPSyntaxEditConfigurationManager* pMan = GetLexConfigurationManager();
if (pMan)
{
pMan->p_sSyntaxScheme = &m_strSyntaxScheme;
pMan->p_sColorScheme = &m_strColorScheme;
pMan->m_bConfigFileMode = FALSE;
pMan->m_bUseMonitor = FALSE;
pMan->m_sIniSet = m_sIniSet;
SetConfigFile(_T(""), FALSE);
}
}
}
#ifndef IDC_SYNTAX_EDIT
#define IDC_SYNTAX_EDIT 1009
#endif
// CXTPSyntaxEditStringDlg dialog
IMPLEMENT_DYNAMIC(CXTPSyntaxEditStringDlg, CDialog)
CXTPSyntaxEditStringDlg::CXTPSyntaxEditStringDlg(CWnd* pParent) : CDialog()
{
UNREFERENCED_PARAMETER(pParent);
}
CXTPSyntaxEditStringDlg::~CXTPSyntaxEditStringDlg()
{
}
void CXTPSyntaxEditStringDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SYNTAX_EDIT, m_edit);
}
BEGIN_MESSAGE_MAP(CXTPSyntaxEditStringDlg, CDialog)
ON_WM_SIZE()
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
END_MESSAGE_MAP()
void CXTPSyntaxEditStringDlg::OnOK()
{
m_edit.GetWindowText(m_Syntax);
CDialog::OnOK();
}
BOOL CXTPSyntaxEditStringDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_edit.SetWindowText(m_Syntax);
return TRUE;
}
void CXTPSyntaxEditStringDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if (GetDlgItem(IDC_SYNTAX_EDIT))
{
int H = 35;
CRect rc;
CWnd* pWnd = GetDlgItem(IDC_SYNTAX_EDIT);
pWnd->MoveWindow(0, 0, cx, cy - H - 5);
pWnd = GetDlgItem(ID_EDIT_CUT);
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
pWnd->MoveWindow(rc.left, cy - H, rc.Width(), rc.Height());
pWnd = GetDlgItem(ID_EDIT_COPY);
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
pWnd->MoveWindow(rc.left, cy - H, rc.Width(), rc.Height());
pWnd = GetDlgItem(ID_EDIT_PASTE);
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
pWnd->MoveWindow(rc.left, cy - H, rc.Width(), rc.Height());
pWnd = GetDlgItem(ID_EDIT_UNDO);
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
pWnd->MoveWindow(rc.left, cy - H, rc.Width(), rc.Height());
pWnd = GetDlgItem(IDOK);
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
pWnd->MoveWindow(rc.left, cy - H, rc.Width(), rc.Height());
pWnd = GetDlgItem(IDCANCEL);
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
pWnd->MoveWindow(rc.left, cy - H, rc.Width(), rc.Height());
}
}
INT_PTR CXTPSyntaxEditStringDlg::DoModal()
{
BYTE DlgTempl[]=
{
0X01, 0X00, 0XFF, 0XFF, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X48, 0X00, 0XCC, 0X80,
0X07, 0X00, 0X00, 0X00, 0X00, 0X00, 0X78, 0X01, 0X2B, 0X01, 0X00, 0X00, 0X00, 0X00, 0X43, 0X00,
0X6F, 0X00, 0X6E, 0X00, 0X74, 0X00, 0X65, 0X00, 0X6E, 0X00, 0X74, 0X00, 0X20, 0X00, 0X65, 0X00,
0X64, 0X00, 0X69, 0X00, 0X74, 0X00, 0X6F, 0X00, 0X72, 0X00, 0X00, 0X00, 0X08, 0X00, 0X90, 0X01,
0X00, 0X01, 0X4D, 0X00, 0X53, 0X00, 0X20, 0X00, 0X53, 0X00, 0X68, 0X00, 0X65, 0X00, 0X6C, 0X00,
0X6C, 0X00, 0X20, 0X00, 0X44, 0X00, 0X6C, 0X00, 0X67, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X01, 0X00, 0X01, 0X50, 0X01, 0X01, 0X18, 0X01, 0X32, 0X00, 0X0E, 0X00,
0X01, 0X00, 0X00, 0X00, 0XFF, 0XFF, 0X80, 0X00, 0X4F, 0X00, 0X4B, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X01, 0X50, 0X40, 0X01, 0X18, 0X01,
0X32, 0X00, 0X0E, 0X00, 0X02, 0X00, 0X00, 0X00, 0XFF, 0XFF, 0X80, 0X00, 0X43, 0X00, 0X61, 0X00,
0X6E, 0X00, 0X63, 0X00, 0X65, 0X00, 0X6C, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X84, 0X10, 0XB1, 0X50, 0X00, 0X00, 0X01, 0X00, 0X77, 0X01, 0X11, 0X01,
0XF1, 0X03, 0X00, 0X00, 0XFF, 0XFF, 0X81, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X01, 0X50, 0X05, 0X00, 0X18, 0X01, 0X32, 0X00, 0X0E, 0X00,
0X23, 0XE1, 0X00, 0X00, 0XFF, 0XFF, 0X80, 0X00, 0X43, 0X00, 0X75, 0X00, 0X74, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X01, 0X50,
0X44, 0X00, 0X18, 0X01, 0X32, 0X00, 0X0E, 0X00, 0X22, 0XE1, 0X00, 0X00, 0XFF, 0XFF, 0X80, 0X00,
0X43, 0X00, 0X6F, 0X00, 0X70, 0X00, 0X79, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X01, 0X50, 0X83, 0X00, 0X18, 0X01, 0X32, 0X00, 0X0E, 0X00,
0X25, 0XE1, 0X00, 0X00, 0XFF, 0XFF, 0X80, 0X00, 0X50, 0X00, 0X61, 0X00, 0X73, 0X00, 0X74, 0X00,
0X65, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X01, 0X50, 0XC2, 0X00, 0X18, 0X01, 0X32, 0X00, 0X0E, 0X00, 0X2B, 0XE1, 0X00, 0X00,
0XFF, 0XFF, 0X80, 0X00, 0X55, 0X00, 0X6E, 0X00, 0X64, 0X00, 0X6F, 0X00, 0X00, 0X00, 0X00, 0X00};
InitModalIndirect((LPCDLGTEMPLATE)&DlgTempl, NULL);
return CDialog::DoModal();
}
void CXTPSyntaxEditStringDlg::OnEditCopy()
{
m_edit.Copy();
}
void CXTPSyntaxEditStringDlg::OnEditCut()
{
m_edit.Cut();
}
void CXTPSyntaxEditStringDlg::OnEditClear()
{
m_edit.Clear();
}
void CXTPSyntaxEditStringDlg::OnEditPaste()
{
m_edit.Paste();
}
void CXTPSyntaxEditStringDlg::OnEditSelectAll()
{
m_edit.SetSel(0, -1);
}
void CXTPSyntaxEditStringDlg::OnEditUndo()
{
m_edit.Undo();
}