www.pudn.com > c02 vc6.rar > CCrystalEditView.cpp


/////////////////////////////////////////////////////////////////////////// 
//	File:		CCrystalEditView.cpp 
//	Version:	1.0.0.0 
//	Created:	29-Dec-1998 
// 
//	Copyright:	Stcherbatchenko Andrei 
//	E-mail:		windfall@gmx.de 
// 
//	Implementation of the CCrystalEditView class, a part of the Crystal Edit - 
//	syntax coloring text editor. 
// 
//	You are free to use or modify this code to the following restrictions: 
//	- Acknowledge me somewhere in your about box, simple "Parts of code by.." 
//	will be enough. If you can't (or don't want to), contact me personally. 
//	- LEAVE THIS HEADER INTACT 
//////////////////////////////////////////////////////////////////////////// 
 
//////////////////////////////////////////////////////////////////////////// 
//	21-Feb-99 
//		Paul Selormey, James R. Twine: 
//	+	FEATURE: description for Undo/Redo actions 
//	+	FEATURE: multiple MSVC-like bookmarks 
//	+	FEATURE: 'Disable backspace at beginning of line' option 
//	+	FEATURE: 'Disable drag-n-drop editing' option 
// 
//	+	FEATURE: Auto indent 
//	+	FIX: ResetView() was overriden to provide cleanup 
//////////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "editcmd.h" 
#include "editreg.h" 
#include "CCrystalEditView.h" 
#include "CCrystalTextBuffer.h" 
#include "CEditReplaceDlg.h" 
 
#ifndef __AFXPRIV_H__ 
#pragma message("Include  in your stdafx.h to avoid this message") 
#include  
#endif 
#ifndef __AFXOLE_H__ 
#pragma message("Include  in your stdafx.h to avoid this message") 
#include  
#endif 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define DRAG_BORDER_X		5 
#define DRAG_BORDER_Y		5 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CEditDropTargetImpl class declaration 
 
class CEditDropTargetImpl : public COleDropTarget 
{ 
private: 
	CCrystalEditView *m_pOwner; 
public: 
	CEditDropTargetImpl(CCrystalEditView *pOwner) { m_pOwner = pOwner; }; 
 
	virtual DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); 
	virtual void OnDragLeave(CWnd* pWnd); 
	virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); 
	virtual BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point); 
	virtual DROPEFFECT OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint point); 
}; 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CCrystalEditView 
 
IMPLEMENT_DYNCREATE(CCrystalEditView, CCrystalTextView) 
 
CCrystalEditView::CCrystalEditView() 
{ 
	AFX_ZERO_INIT_OBJECT(CCrystalTextView); 
	m_bAutoIndent = TRUE; 
} 
 
CCrystalEditView::~CCrystalEditView() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CCrystalEditView, CCrystalTextView) 
	//{{AFX_MSG_MAP(CCrystalEditView) 
	ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) 
	ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut) 
	ON_COMMAND(ID_EDIT_CUT, OnEditCut) 
	ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste) 
	ON_COMMAND(ID_EDIT_DELETE, OnEditDelete) 
	ON_WM_CHAR() 
	ON_COMMAND(ID_EDIT_DELETE_BACK, OnEditDeleteBack) 
	ON_COMMAND(ID_EDIT_UNTAB, OnEditUntab) 
	ON_COMMAND(ID_EDIT_TAB, OnEditTab) 
	ON_COMMAND(ID_EDIT_SWITCH_OVRMODE, OnEditSwitchOvrmode) 
	ON_UPDATE_COMMAND_UI(ID_EDIT_SWITCH_OVRMODE, OnUpdateEditSwitchOvrmode) 
	ON_WM_CREATE() 
	ON_WM_DESTROY() 
	ON_COMMAND(ID_EDIT_REPLACE, OnEditReplace) 
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo) 
	ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) 
	ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo) 
	ON_COMMAND(ID_EDIT_REDO, OnEditRedo) 
	//}}AFX_MSG_MAP 
	ON_UPDATE_COMMAND_UI(ID_EDIT_INDICATOR_READ, OnUpdateIndicatorRead) 
	ON_UPDATE_COMMAND_UI(ID_INDICATOR_OVR, OnUpdateIndicatorOvr) 
	ON_UPDATE_COMMAND_UI(ID_EDIT_INDICATOR_COL, OnUpdateIndicatorCol) 
END_MESSAGE_MAP() 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CCrystalEditView message handlers 
 
void CCrystalEditView::ResetView() 
{ 
	m_bAutoIndent = TRUE; 
	m_bOvrMode = FALSE; 
	CCrystalTextView::ResetView(); 
} 
 
BOOL CCrystalEditView::QueryEditable() 
{ 
	if (m_pTextBuffer == NULL) 
		return FALSE; 
	return ! m_pTextBuffer->GetReadOnly(); 
} 
 
void CCrystalEditView::OnEditPaste()  
{ 
	Paste(); 
} 
 
void CCrystalEditView::OnUpdateEditPaste(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(TextInClipboard()); 
} 
 
void CCrystalEditView::OnUpdateEditCut(CCmdUI* pCmdUI)  
{ 
	pCmdUI->Enable(IsSelection()); 
} 
 
void CCrystalEditView::OnEditCut()  
{ 
	Cut(); 
} 
 
BOOL CCrystalEditView::DeleteCurrentSelection() 
{ 
	if (IsSelection()) 
	{ 
		CPoint ptSelStart, ptSelEnd; 
		GetSelection(ptSelStart, ptSelEnd); 
 
		CPoint ptCursorPos = ptSelStart; 
		ASSERT_VALIDTEXTPOS(ptCursorPos); 
		SetAnchor(ptCursorPos); 
		SetSelection(ptCursorPos, ptCursorPos); 
		SetCursorPos(ptCursorPos); 
		EnsureVisible(ptCursorPos); 
 
		// [JRT]: 
		m_pTextBuffer->DeleteText(this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELSEL); 
		return TRUE; 
	} 
	return FALSE; 
} 
 
void CCrystalEditView::Paste() 
{ 
	if (! QueryEditable()) 
		return; 
	if (m_pTextBuffer == NULL) 
		return; 
 
	m_pTextBuffer->BeginUndoGroup(); 
 
	DeleteCurrentSelection(); 
 
	CString text; 
	if (GetFromClipboard(text)) 
	{ 
		CPoint ptCursorPos = GetCursorPos(); 
		ASSERT_VALIDTEXTPOS(ptCursorPos); 
		int x, y; 
		m_pTextBuffer->InsertText(this, ptCursorPos.y, ptCursorPos.x, text, y, x, CE_ACTION_PASTE); //	[JRT] 
		ptCursorPos.x = x; 
		ptCursorPos.y = y; 
		ASSERT_VALIDTEXTPOS(ptCursorPos); 
		SetAnchor(ptCursorPos); 
		SetSelection(ptCursorPos, ptCursorPos); 
		SetCursorPos(ptCursorPos); 
		EnsureVisible(ptCursorPos); 
	} 
 
	m_pTextBuffer->FlushUndoGroup(this); 
} 
 
void CCrystalEditView::Cut() 
{ 
	if (! QueryEditable()) 
		return; 
	if (m_pTextBuffer == NULL) 
		return; 
	if (! IsSelection()) 
		return; 
 
	CPoint ptSelStart, ptSelEnd; 
	GetSelection(ptSelStart, ptSelEnd); 
	CString text; 
	GetText(ptSelStart, ptSelEnd, text); 
	PutToClipboard(text); 
 
	CPoint ptCursorPos = ptSelStart; 
	ASSERT_VALIDTEXTPOS(ptCursorPos); 
	SetAnchor(ptCursorPos); 
	SetSelection(ptCursorPos, ptCursorPos); 
	SetCursorPos(ptCursorPos); 
	EnsureVisible(ptCursorPos); 
 
	m_pTextBuffer->DeleteText(this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_CUT); // [JRT] 
} 
 
void CCrystalEditView::OnEditDelete()  
{ 
	if (! QueryEditable() || m_pTextBuffer == NULL) 
		return; 
 
	CPoint ptSelStart, ptSelEnd; 
	GetSelection(ptSelStart, ptSelEnd); 
	if (ptSelStart == ptSelEnd) 
	{ 
		if (ptSelEnd.x == GetLineLength(ptSelEnd.y)) 
		{ 
			if (ptSelEnd.y == GetLineCount() - 1) 
				return; 
			ptSelEnd.y ++; 
			ptSelEnd.x = 0; 
		} 
		else 
			ptSelEnd.x ++; 
	} 
 
	CPoint ptCursorPos = ptSelStart; 
	ASSERT_VALIDTEXTPOS(ptCursorPos); 
	SetAnchor(ptCursorPos); 
	SetSelection(ptCursorPos, ptCursorPos); 
	SetCursorPos(ptCursorPos); 
	EnsureVisible(ptCursorPos); 
 
	m_pTextBuffer->DeleteText(this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE); // [JRT] 
} 
 
void CCrystalEditView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	CCrystalTextView::OnChar(nChar, nRepCnt, nFlags); 
 
	if ((::GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0 || 
			(::GetAsyncKeyState(VK_RBUTTON) & 0x8000) != 0) 
		return; 
 
	BOOL bTranslated = FALSE; 
	if (nChar == VK_RETURN) 
	{ 
		if (m_bOvrMode) 
		{ 
			CPoint ptCursorPos = GetCursorPos(); 
			ASSERT_VALIDTEXTPOS(ptCursorPos); 
			if (ptCursorPos.y < GetLineCount() - 1) 
			{ 
				ptCursorPos.x = 0; 
				ptCursorPos.y++; 
 
				ASSERT_VALIDTEXTPOS(ptCursorPos); 
				SetSelection(ptCursorPos, ptCursorPos); 
				SetAnchor(ptCursorPos); 
				SetCursorPos(ptCursorPos); 
				EnsureVisible(ptCursorPos); 
				return; 
			} 
		} 
 
		m_pTextBuffer->BeginUndoGroup(); 
 
		if (QueryEditable() && m_pTextBuffer != NULL) 
		{ 
			DeleteCurrentSelection(); 
 
			CPoint ptCursorPos = GetCursorPos(); 
			ASSERT_VALIDTEXTPOS(ptCursorPos); 
			const static TCHAR pszText[3] = _T("\r\n"); 
 
			int x, y; 
			m_pTextBuffer->InsertText(this, ptCursorPos.y, ptCursorPos.x, pszText, y, x, CE_ACTION_TYPING); //	[JRT] 
			ptCursorPos.x = x; 
			ptCursorPos.y = y; 
			ASSERT_VALIDTEXTPOS(ptCursorPos); 
			SetSelection(ptCursorPos, ptCursorPos); 
			SetAnchor(ptCursorPos); 
			SetCursorPos(ptCursorPos); 
			EnsureVisible(ptCursorPos); 
		} 
 
		m_pTextBuffer->FlushUndoGroup(this); 
		return; 
	} 
 
	if (nChar > 31) 
	{ 
		if (QueryEditable() && m_pTextBuffer != NULL) 
		{ 
			m_pTextBuffer->BeginUndoGroup(nChar != _T(' ')); 
 
			CPoint ptSelStart, ptSelEnd; 
			GetSelection(ptSelStart, ptSelEnd); 
			CPoint ptCursorPos; 
			if (ptSelStart != ptSelEnd) 
			{ 
				ptCursorPos = ptSelStart; 
				DeleteCurrentSelection(); 
			} 
			else 
			{ 
				ptCursorPos = GetCursorPos(); 
				if (m_bOvrMode && ptCursorPos.x < GetLineLength(ptCursorPos.y)) 
					m_pTextBuffer->DeleteText(this, ptCursorPos.y, ptCursorPos.x, ptCursorPos.y, ptCursorPos.x + 1, CE_ACTION_TYPING); // [JRT] 
			} 
 
			ASSERT_VALIDTEXTPOS(ptCursorPos); 
 
			char pszText[2]; 
			pszText[0] = (char) nChar; 
			pszText[1] = 0; 
 
			int x, y; 
			USES_CONVERSION; 
			m_pTextBuffer->InsertText(this, ptCursorPos.y, ptCursorPos.x, A2T(pszText), y, x, CE_ACTION_TYPING); // [JRT] 
			ptCursorPos.x = x; 
			ptCursorPos.y = y; 
			ASSERT_VALIDTEXTPOS(ptCursorPos); 
			SetSelection(ptCursorPos, ptCursorPos); 
			SetAnchor(ptCursorPos); 
			SetCursorPos(ptCursorPos); 
			EnsureVisible(ptCursorPos); 
 
			m_pTextBuffer->FlushUndoGroup(this); 
		} 
	} 
} 
 
 
// 
//	[JRT]: Added Support For "Disable Backspace At Start Of Line" 
// 
void CCrystalEditView::OnEditDeleteBack()  
{ 
	if (IsSelection()) 
	{ 
		OnEditDelete(); 
		return; 
	} 
 
	if (! QueryEditable() || m_pTextBuffer == NULL) 
		return; 
 
	CPoint ptCursorPos = GetCursorPos(); 
	CPoint ptCurrentCursorPos = ptCursorPos; 
	bool	bDeleted = false; 
 
	if( !( ptCursorPos.x ) )							// If At Start Of Line 
	{ 
		if( !m_bDisableBSAtSOL )						// If DBSASOL Is Disabled 
		{ 
			if( ptCursorPos.y > 0 )						// If Previous Lines Available 
			{ 
				ptCursorPos.y--;						// Decrement To Previous Line 
				ptCursorPos.x = GetLineLength( 
						ptCursorPos.y );				// Set Cursor To End Of Previous Line 
				bDeleted = true;						// Set Deleted Flag 
			} 
		} 
	} 
	else												// If Caret Not At SOL 
	{ 
		ptCursorPos.x--;								// Decrement Position 
		bDeleted = true;								// Set Deleted Flag 
	} 
/* 
	if (ptCursorPos.x == 0) 
	{ 
		if (ptCursorPos.y == 0) 
			return; 
		ptCursorPos.y --; 
		ptCursorPos.x = GetLineLength(ptCursorPos.y); 
	} 
	else 
		ptCursorPos.x --; 
*/ 
	ASSERT_VALIDTEXTPOS(ptCursorPos); 
	SetAnchor(ptCursorPos); 
	SetSelection(ptCursorPos, ptCursorPos); 
	SetCursorPos(ptCursorPos); 
	EnsureVisible(ptCursorPos); 
 
	if (bDeleted) 
	{ 
		m_pTextBuffer->DeleteText(this, ptCursorPos.y, ptCursorPos.x, ptCurrentCursorPos.y, ptCurrentCursorPos.x, CE_ACTION_BACKSPACE); // [JRT] 
	} 
	return; 
} 
 
void CCrystalEditView::OnEditTab()  
{ 
	if (! QueryEditable() || m_pTextBuffer == NULL) 
		return; 
 
	BOOL bTabify = FALSE; 
	CPoint ptSelStart, ptSelEnd; 
	if (IsSelection()) 
	{ 
		GetSelection(ptSelStart, ptSelEnd); 
		bTabify = ptSelStart.y != ptSelEnd.y; 
	} 
 
	if (bTabify) 
	{ 
		m_pTextBuffer->BeginUndoGroup(); 
 
		int nStartLine = ptSelStart.y; 
		int nEndLine = ptSelEnd.y; 
		ptSelStart.x = 0; 
		if (ptSelEnd.x > 0) 
		{ 
			if (ptSelEnd.y == GetLineCount() - 1) 
			{ 
				ptSelEnd.x = GetLineLength(ptSelEnd.y); 
			} 
			else 
			{ 
				ptSelEnd.x = 0; 
				ptSelEnd.y ++; 
			} 
		} 
		else 
			nEndLine --; 
		SetSelection(ptSelStart, ptSelEnd); 
		SetCursorPos(ptSelEnd); 
		EnsureVisible(ptSelEnd); 
 
		//	Shift selection to right 
		m_bHorzScrollBarLocked = TRUE; 
		static const TCHAR pszText[] = _T("\t"); 
		for (int L = nStartLine; L <= nEndLine; L ++) 
		{ 
			int x, y; 
			m_pTextBuffer->InsertText(this, L, 0, pszText, y, x, CE_ACTION_INDENT); //	[JRT] 
		} 
		m_bHorzScrollBarLocked = FALSE; 
		RecalcHorzScrollBar(); 
 
		m_pTextBuffer->FlushUndoGroup(this); 
		return; 
	} 
 
	if (m_bOvrMode) 
	{ 
		CPoint ptCursorPos = GetCursorPos(); 
		ASSERT_VALIDTEXTPOS(ptCursorPos); 
 
		int nLineLength = GetLineLength(ptCursorPos.y); 
		LPCTSTR pszLineChars = GetLineChars(ptCursorPos.y); 
		if (ptCursorPos.x < nLineLength) 
		{ 
			int nTabSize = GetTabSize(); 
			int nChars = nTabSize - CalculateActualOffset(ptCursorPos.y, ptCursorPos.x) % nTabSize; 
			ASSERT(nChars > 0 && nChars <= nTabSize); 
 
			while (nChars > 0) 
			{ 
				if (ptCursorPos.x == nLineLength) 
					break; 
				if (pszLineChars[ptCursorPos.x] == _T('\t')) 
				{ 
					ptCursorPos.x ++; 
					break; 
				} 
				ptCursorPos.x ++; 
				nChars --; 
			} 
			ASSERT(ptCursorPos.x <= nLineLength); 
			ASSERT_VALIDTEXTPOS(ptCursorPos); 
 
			SetSelection(ptCursorPos, ptCursorPos); 
			SetAnchor(ptCursorPos); 
			SetCursorPos(ptCursorPos); 
			EnsureVisible(ptCursorPos); 
			return; 
		} 
	} 
 
	m_pTextBuffer->BeginUndoGroup(); 
 
	DeleteCurrentSelection(); 
 
	CPoint ptCursorPos = GetCursorPos(); 
	ASSERT_VALIDTEXTPOS(ptCursorPos); 
 
	static const TCHAR pszText[] = _T("\t"); 
	int x, y; 
	m_pTextBuffer->InsertText(this, ptCursorPos.y, ptCursorPos.x, pszText, y, x, CE_ACTION_TYPING); //	[JRT] 
	ptCursorPos.x = x; 
	ptCursorPos.y = y; 
	ASSERT_VALIDTEXTPOS(ptCursorPos); 
	SetSelection(ptCursorPos, ptCursorPos); 
	SetAnchor(ptCursorPos); 
	SetCursorPos(ptCursorPos); 
	EnsureVisible(ptCursorPos); 
 
	m_pTextBuffer->FlushUndoGroup(this); 
} 
 
void CCrystalEditView::OnEditUntab()  
{ 
	if (! QueryEditable() || m_pTextBuffer == NULL) 
		return; 
 
	BOOL bTabify = FALSE; 
	CPoint ptSelStart, ptSelEnd; 
	if (IsSelection()) 
	{ 
		GetSelection(ptSelStart, ptSelEnd); 
		bTabify = ptSelStart.y != ptSelEnd.y; 
	} 
 
	if (bTabify) 
	{ 
		m_pTextBuffer->BeginUndoGroup(); 
 
		CPoint ptSelStart, ptSelEnd; 
		GetSelection(ptSelStart, ptSelEnd); 
		int nStartLine = ptSelStart.y; 
		int nEndLine = ptSelEnd.y; 
		ptSelStart.x = 0; 
		if (ptSelEnd.x > 0) 
		{ 
			if (ptSelEnd.y == GetLineCount() - 1) 
			{ 
				ptSelEnd.x = GetLineLength(ptSelEnd.y); 
			} 
			else 
			{ 
				ptSelEnd.x = 0; 
				ptSelEnd.y ++; 
			} 
		} 
		else 
			nEndLine --; 
		SetSelection(ptSelStart, ptSelEnd); 
		SetCursorPos(ptSelEnd); 
		EnsureVisible(ptSelEnd); 
 
		//	Shift selection to left 
		m_bHorzScrollBarLocked = TRUE; 
		for (int L = nStartLine; L <= nEndLine; L ++) 
		{ 
			int nLength = GetLineLength(L); 
			if (nLength > 0) 
			{ 
				LPCTSTR pszChars = GetLineChars(L); 
				int nPos = 0, nOffset = 0; 
				while (nPos < nLength) 
				{ 
					if (pszChars[nPos] == _T(' ')) 
					{ 
						nPos ++; 
						if (++ nOffset >= GetTabSize()) 
							break; 
					} 
					else 
					{ 
						if (pszChars[nPos] == _T('\t')) 
							nPos ++; 
						break; 
					} 
				} 
 
				if (nPos > 0) 
					m_pTextBuffer->DeleteText(this, L, 0, L, nPos, CE_ACTION_INDENT); // [JRT] 
			} 
		} 
		m_bHorzScrollBarLocked = FALSE; 
		RecalcHorzScrollBar(); 
 
		m_pTextBuffer->FlushUndoGroup(this); 
	} 
	else 
	{ 
		CPoint ptCursorPos = GetCursorPos(); 
		ASSERT_VALIDTEXTPOS(ptCursorPos); 
		if (ptCursorPos.x > 0) 
		{ 
			int nTabSize = GetTabSize(); 
			int nOffset = CalculateActualOffset(ptCursorPos.y, ptCursorPos.x); 
			int nNewOffset = nOffset / nTabSize * nTabSize; 
			if (nOffset == nNewOffset && nNewOffset > 0) 
				nNewOffset -= nTabSize; 
			ASSERT(nNewOffset >= 0); 
 
			LPCTSTR pszChars = GetLineChars(ptCursorPos.y); 
			int nCurrentOffset = 0; 
			int I = 0; 
			while (nCurrentOffset < nNewOffset) 
			{ 
				if (pszChars[I] == _T('\t')) 
					nCurrentOffset = nCurrentOffset / nTabSize * nTabSize + nTabSize; 
				else 
					nCurrentOffset ++; 
				I ++; 
			} 
 
			ASSERT(nCurrentOffset == nNewOffset); 
 
			ptCursorPos.x = I; 
			ASSERT_VALIDTEXTPOS(ptCursorPos); 
			SetSelection(ptCursorPos, ptCursorPos); 
			SetAnchor(ptCursorPos); 
			SetCursorPos(ptCursorPos); 
			EnsureVisible(ptCursorPos); 
		} 
	} 
} 
 
void CCrystalEditView::OnUpdateIndicatorCol(CCmdUI* pCmdUI) 
{ 
	pCmdUI->Enable(FALSE); 
} 
 
void CCrystalEditView::OnUpdateIndicatorOvr(CCmdUI* pCmdUI) 
{ 
	pCmdUI->Enable(m_bOvrMode); 
} 
 
void CCrystalEditView::OnUpdateIndicatorRead(CCmdUI* pCmdUI) 
{ 
	if (m_pTextBuffer == NULL) 
		pCmdUI->Enable(FALSE); 
	else 
		pCmdUI->Enable(m_pTextBuffer->GetReadOnly()); 
} 
 
void CCrystalEditView::OnEditSwitchOvrmode()  
{ 
	m_bOvrMode = ! m_bOvrMode; 
} 
 
void CCrystalEditView::OnUpdateEditSwitchOvrmode(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_bOvrMode ? 1 : 0); 
} 
 
DROPEFFECT CEditDropTargetImpl::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) 
{ 
	if (! pDataObject->IsDataAvailable(CF_TEXT)) 
	{ 
		m_pOwner->HideDropIndicator(); 
		return DROPEFFECT_NONE; 
	} 
	m_pOwner->ShowDropIndicator(point); 
	if (dwKeyState & MK_CONTROL) 
		return DROPEFFECT_COPY; 
	return DROPEFFECT_MOVE; 
} 
 
void CEditDropTargetImpl::OnDragLeave(CWnd* pWnd) 
{ 
	m_pOwner->HideDropIndicator(); 
} 
 
DROPEFFECT CEditDropTargetImpl::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) 
{ 
/* 
	if (! pDataObject->IsDataAvailable(CF_TEXT)) 
	{ 
		m_pOwner->HideDropIndicator(); 
		return DROPEFFECT_NONE; 
	} 
*/ 
	// 
	// [JRT] 
	// 
	bool bDataSupported = false; 
 
	if ((!m_pOwner) ||									// If No Owner  
			(!( m_pOwner->QueryEditable())) ||			// Or Not Editable 
			(m_pOwner->GetDisableDragAndDrop()))		// Or Drag And Drop Disabled 
	{ 
		m_pOwner -> HideDropIndicator();					// Hide Drop Caret 
		return DROPEFFECT_NONE;							    // Return DE_NONE 
	} 
//	if ((pDataObject->IsDataAvailable( CF_TEXT ) ) ||	    // If Text Available 
//			( pDataObject -> IsDataAvailable( xxx ) ) ||	// Or xxx Available 
//			( pDataObject -> IsDataAvailable( yyy ) ) )		// Or yyy Available 
	if (pDataObject->IsDataAvailable(CF_TEXT))		  	    // If Text Available 
	{ 
		bDataSupported = true;								// Set Flag 
	} 
	if (!bDataSupported)									// If No Supported Formats Available 
	{ 
		m_pOwner->HideDropIndicator();					    // Hide Drop Caret 
		return DROPEFFECT_NONE;						   	    // Return DE_NONE 
	} 
	m_pOwner->ShowDropIndicator(point); 
	if (dwKeyState & MK_CONTROL) 
		return DROPEFFECT_COPY; 
	return DROPEFFECT_MOVE; 
} 
 
BOOL CEditDropTargetImpl::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) 
{ 
	// 
	// [JRT] 			( m_pOwner -> GetDisableDragAndDrop() ) )		// Or Drag And Drop Disabled 
	// 
	bool bDataSupported = false; 
 
	m_pOwner->HideDropIndicator();						// Hide Drop Caret 
	if ((!m_pOwner) ||									// If No Owner  
			(!( m_pOwner->QueryEditable())) ||			// Or Not Editable 
			(m_pOwner->GetDisableDragAndDrop()))		// Or Drag And Drop Disabled 
	{ 
		return DROPEFFECT_NONE;							// Return DE_NONE 
	} 
//	if( ( pDataObject -> IsDataAvailable( CF_TEXT ) ) ||	// If Text Available 
//			( pDataObject -> IsDataAvailable( xxx ) ) ||	// Or xxx Available 
//			( pDataObject -> IsDataAvailable( yyy ) ) )		// Or yyy Available 
	if (pDataObject->IsDataAvailable(CF_TEXT))			    // If Text Available 
	{ 
		bDataSupported = true;								// Set Flag 
	} 
	if (!bDataSupported)									// If No Supported Formats Available 
	{ 
		return DROPEFFECT_NONE;							    // Return DE_NONE 
	} 
	return (m_pOwner->DoDropText(pDataObject, point));	    // Return Result Of Drop 
} 
 
DROPEFFECT CEditDropTargetImpl::OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint point) 
{ 
	ASSERT(m_pOwner == pWnd); 
	m_pOwner->DoDragScroll(point); 
 
	if (dwKeyState & MK_CONTROL) 
		return DROPEFFECT_COPY; 
	return DROPEFFECT_MOVE; 
} 
 
void CCrystalEditView::DoDragScroll(const CPoint &point) 
{ 
	CRect rcClientRect; 
	GetClientRect(rcClientRect); 
	if (point.y < rcClientRect.top + DRAG_BORDER_Y) 
	{ 
		HideDropIndicator(); 
		ScrollUp(); 
		UpdateWindow(); 
		ShowDropIndicator(point); 
		return; 
	} 
	if (point.y >= rcClientRect.bottom - DRAG_BORDER_Y) 
	{ 
		HideDropIndicator(); 
		ScrollDown(); 
		UpdateWindow(); 
		ShowDropIndicator(point); 
		return; 
	} 
	if (point.x < rcClientRect.left + GetMarginWidth() + DRAG_BORDER_X) 
	{ 
		HideDropIndicator(); 
		ScrollLeft(); 
		UpdateWindow(); 
		ShowDropIndicator(point); 
		return; 
	} 
	if (point.x >= rcClientRect.right - DRAG_BORDER_X) 
	{ 
		HideDropIndicator(); 
		ScrollRight(); 
		UpdateWindow(); 
		ShowDropIndicator(point); 
		return; 
	} 
} 
 
BOOL CCrystalEditView::DoDropText(COleDataObject *pDataObject, const CPoint &ptClient) 
{ 
	HGLOBAL hData = pDataObject->GetGlobalData(CF_TEXT); 
	if (hData == NULL) 
		return FALSE; 
 
	CPoint ptDropPos = ClientToText(ptClient); 
	if (IsDraggingText() && IsInsideSelection(ptDropPos)) 
	{ 
		SetAnchor(ptDropPos); 
		SetSelection(ptDropPos, ptDropPos); 
		SetCursorPos(ptDropPos); 
		EnsureVisible(ptDropPos); 
		return FALSE; 
	} 
 
	LPSTR pszText = (LPSTR) ::GlobalLock(hData); 
	if (pszText == NULL) 
		return FALSE; 
 
	int x, y; 
	USES_CONVERSION; 
	m_pTextBuffer->InsertText(this, ptDropPos.y, ptDropPos.x, A2T(pszText), y, x, CE_ACTION_DRAGDROP); //	[JRT] 
	CPoint ptCurPos(x, y); 
	ASSERT_VALIDTEXTPOS(ptCurPos); 
	SetAnchor(ptDropPos); 
	SetSelection(ptDropPos, ptCurPos); 
	SetCursorPos(ptCurPos); 
	EnsureVisible(ptCurPos); 
 
	::GlobalUnlock(hData); 
	return TRUE; 
} 
 
int CCrystalEditView::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CCrystalTextView::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	 
	ASSERT(m_pDropTarget == NULL); 
	m_pDropTarget = new CEditDropTargetImpl(this); 
	if (! m_pDropTarget->Register(this)) 
	{ 
		TRACE0("Warning: Unable to register drop target for CCrystalEditView.\n"); 
		delete m_pDropTarget; 
		m_pDropTarget = NULL; 
	} 
 
	return 0; 
} 
 
void CCrystalEditView::OnDestroy()  
{ 
	if (m_pDropTarget != NULL) 
	{ 
		m_pDropTarget->Revoke(); 
		delete m_pDropTarget; 
		m_pDropTarget = NULL; 
	} 
 
	CCrystalTextView::OnDestroy(); 
} 
 
void CCrystalEditView::ShowDropIndicator(const CPoint &point) 
{ 
	if (! m_bDropPosVisible) 
	{ 
		HideCursor(); 
		m_ptSavedCaretPos = GetCursorPos(); 
		m_bDropPosVisible = TRUE; 
		::CreateCaret(m_hWnd, (HBITMAP) 1, 2, GetLineHeight()); 
	} 
	m_ptDropPos = ClientToText(point); 
	if (m_ptDropPos.x >= m_nOffsetChar) 
	{ 
		SetCaretPos(TextToClient(m_ptDropPos)); 
		ShowCaret(); 
	} 
	else 
	{ 
		HideCaret(); 
	} 
} 
 
void CCrystalEditView::HideDropIndicator() 
{ 
	if (m_bDropPosVisible) 
	{ 
		SetCursorPos(m_ptSavedCaretPos); 
		ShowCursor(); 
		m_bDropPosVisible = FALSE; 
	} 
} 
 
DROPEFFECT CCrystalEditView::GetDropEffect() 
{ 
	return DROPEFFECT_COPY | DROPEFFECT_MOVE; 
} 
 
void CCrystalEditView::OnDropSource(DROPEFFECT de) 
{ 
	if (! IsDraggingText()) 
		return; 
 
	ASSERT_VALIDTEXTPOS(m_ptDraggedTextBegin); 
	ASSERT_VALIDTEXTPOS(m_ptDraggedTextEnd); 
 
	if (de == DROPEFFECT_MOVE) 
	{ 
		m_pTextBuffer->DeleteText(this, m_ptDraggedTextBegin.y, m_ptDraggedTextBegin.x, m_ptDraggedTextEnd.y,  
			m_ptDraggedTextEnd.x, CE_ACTION_DRAGDROP); // [JRT] 
	} 
} 
 
void CCrystalEditView::UpdateView(CCrystalTextView *pSource, CUpdateContext *pContext, DWORD dwFlags, int nLineIndex /*= -1*/) 
{ 
	CCrystalTextView::UpdateView(pSource, pContext, dwFlags, nLineIndex); 
 
	if (m_bSelectionPushed && pContext != NULL) 
	{ 
		pContext->RecalcPoint(m_ptSavedSelStart); 
		pContext->RecalcPoint(m_ptSavedSelEnd); 
		ASSERT_VALIDTEXTPOS(m_ptSavedSelStart); 
		ASSERT_VALIDTEXTPOS(m_ptSavedSelEnd); 
	} 
} 
 
void CCrystalEditView::OnEditReplace()  
{ 
	if (! QueryEditable()) 
		return; 
 
	CWinApp *pApp = AfxGetApp(); 
	ASSERT(pApp != NULL); 
 
	CEditReplaceDlg dlg(this); 
 
	//	Take search parameters from registry 
	dlg.m_bMatchCase = pApp->GetProfileInt(REG_REPLACE_SUBKEY, REG_MATCH_CASE, FALSE); 
	dlg.m_bWholeWord = pApp->GetProfileInt(REG_REPLACE_SUBKEY, REG_WHOLE_WORD, FALSE); 
	dlg.m_sText = pApp->GetProfileString(REG_REPLACE_SUBKEY, REG_FIND_WHAT, _T("")); 
	dlg.m_sNewText = pApp->GetProfileString(REG_REPLACE_SUBKEY, REG_REPLACE_WITH, _T("")); 
 
	if (IsSelection()) 
	{ 
		GetSelection(m_ptSavedSelStart, m_ptSavedSelEnd); 
		m_bSelectionPushed = TRUE; 
 
		dlg.m_nScope = 0;	//	Replace in current selection 
		dlg.m_ptCurrentPos = m_ptSavedSelStart; 
		dlg.m_bEnableScopeSelection = TRUE; 
		dlg.m_ptBlockBegin = m_ptSavedSelStart; 
		dlg.m_ptBlockEnd = m_ptSavedSelEnd; 
	} 
	else 
	{ 
		dlg.m_nScope = 1;	//	Replace in whole text 
		dlg.m_ptCurrentPos = GetCursorPos(); 
		dlg.m_bEnableScopeSelection = FALSE; 
	} 
 
	//	Execute Replace dialog 
	m_bShowInactiveSelection = TRUE; 
	dlg.DoModal(); 
	m_bShowInactiveSelection = FALSE; 
 
	//	Restore selection 
	if (m_bSelectionPushed) 
	{ 
		SetSelection(m_ptSavedSelStart, m_ptSavedSelEnd); 
		m_bSelectionPushed = FALSE; 
	} 
 
	//	Save search parameters to registry 
	pApp->WriteProfileInt(REG_REPLACE_SUBKEY, REG_MATCH_CASE, dlg.m_bMatchCase); 
	pApp->WriteProfileInt(REG_REPLACE_SUBKEY, REG_WHOLE_WORD, dlg.m_bWholeWord); 
	pApp->WriteProfileString(REG_REPLACE_SUBKEY, REG_FIND_WHAT, dlg.m_sText); 
	pApp->WriteProfileString(REG_REPLACE_SUBKEY, REG_REPLACE_WITH, dlg.m_sNewText); 
} 
 
BOOL CCrystalEditView::ReplaceSelection(LPCTSTR pszNewText) 
{ 
	ASSERT(pszNewText != NULL); 
	if (! IsSelection()) 
		return FALSE; 
 
	DeleteCurrentSelection(); 
 
	CPoint ptCursorPos = GetCursorPos(); 
	ASSERT_VALIDTEXTPOS(ptCursorPos); 
	int x, y; 
	m_pTextBuffer->InsertText(this, ptCursorPos.y, ptCursorPos.x, pszNewText, y, x, CE_ACTION_REPLACE); //	[JRT] 
	CPoint ptEndOfBlock = CPoint(x, y); 
	ASSERT_VALIDTEXTPOS(ptCursorPos); 
	ASSERT_VALIDTEXTPOS(ptEndOfBlock); 
	SetAnchor(ptEndOfBlock); 
	SetSelection(ptCursorPos, ptEndOfBlock); 
	SetCursorPos(ptEndOfBlock); 
	EnsureVisible(ptEndOfBlock); 
	return TRUE; 
} 
 
void CCrystalEditView::OnUpdateEditUndo(CCmdUI* pCmdUI)  
{ 
	BOOL bCanUndo = m_pTextBuffer != NULL && m_pTextBuffer->CanUndo(); 
	pCmdUI->Enable(bCanUndo); 
 
	//	Since we need text only for menus... 
	if (pCmdUI->m_pMenu != NULL) 
	{ 
		//	Tune up 'resource handle' 
		HINSTANCE hOldResHandle = AfxGetResourceHandle(); 
		AfxSetResourceHandle(GetResourceHandle()); 
 
		CString menu; 
		if (bCanUndo) 
		{ 
			//	Format menu item text using the provided item description 
			CString desc; 
			m_pTextBuffer->GetUndoDescription(desc); 
			menu.Format(IDS_MENU_UNDO_FORMAT, desc); 
		} 
		else 
		{ 
			//	Just load default menu item text 
			menu.LoadString(IDS_MENU_UNDO_DEFAULT); 
		} 
 
		//	Restore original handle 
		AfxSetResourceHandle(hOldResHandle); 
 
		//	Set menu item text 
		pCmdUI->SetText(menu); 
	} 
} 
 
void CCrystalEditView::OnEditUndo()  
{ 
	if (m_pTextBuffer != NULL && m_pTextBuffer->CanUndo()) 
	{ 
		CPoint ptCursorPos; 
		if (m_pTextBuffer->Undo(ptCursorPos)) 
		{ 
			ASSERT_VALIDTEXTPOS(ptCursorPos); 
			SetAnchor(ptCursorPos); 
			SetSelection(ptCursorPos, ptCursorPos); 
			SetCursorPos(ptCursorPos); 
			EnsureVisible(ptCursorPos); 
		} 
	} 
} 
 
//	[JRT] 
void CCrystalEditView::SetDisableBSAtSOL(BOOL bDisableBSAtSOL) 
{ 
	m_bDisableBSAtSOL = bDisableBSAtSOL; 
} 
 
void CCrystalEditView::OnEditRedo()  
{ 
	if (m_pTextBuffer != NULL && m_pTextBuffer->CanRedo()) 
	{ 
		CPoint ptCursorPos; 
		if (m_pTextBuffer->Redo(ptCursorPos)) 
		{ 
			ASSERT_VALIDTEXTPOS(ptCursorPos); 
			SetAnchor(ptCursorPos); 
			SetSelection(ptCursorPos, ptCursorPos); 
			SetCursorPos(ptCursorPos); 
			EnsureVisible(ptCursorPos); 
		} 
	} 
} 
 
void CCrystalEditView::OnUpdateEditRedo(CCmdUI* pCmdUI)  
{ 
	BOOL bCanRedo = m_pTextBuffer != NULL && m_pTextBuffer->CanRedo(); 
	pCmdUI->Enable(bCanRedo); 
 
	//	Since we need text only for menus... 
	if (pCmdUI->m_pMenu != NULL) 
	{ 
		//	Tune up 'resource handle' 
		HINSTANCE hOldResHandle = AfxGetResourceHandle(); 
		AfxSetResourceHandle(GetResourceHandle()); 
 
		CString menu; 
		if (bCanRedo) 
		{ 
			//	Format menu item text using the provided item description 
			CString desc; 
			m_pTextBuffer->GetRedoDescription(desc); 
			menu.Format(IDS_MENU_REDO_FORMAT, desc); 
		} 
		else 
		{ 
			//	Just load default menu item text 
			menu.LoadString(IDS_MENU_REDO_DEFAULT); 
		} 
 
		//	Restore original handle 
		AfxSetResourceHandle(hOldResHandle); 
 
		//	Set menu item text 
		pCmdUI->SetText(menu); 
	} 
} 
 
void CCrystalEditView::OnEditOperation(int nAction, LPCTSTR pszText) 
{ 
	if (m_bAutoIndent) 
	{ 
		//	Analyse last action... 
		if (nAction == CE_ACTION_TYPING && _tcscmp(pszText, _T("\r\n")) == 0 && ! m_bOvrMode) 
		{ 
			//	Enter stroke! 
			CPoint ptCursorPos = GetCursorPos(); 
			ASSERT(ptCursorPos.y > 0); 
 
			//	Take indentation from the previos line 
			int nLength = m_pTextBuffer->GetLineLength(ptCursorPos.y - 1); 
			LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars(ptCursorPos.y - 1); 
			int nPos = 0; 
			while (nPos < nLength && isspace(pszLineChars[nPos])) 
				nPos ++; 
 
			if (nPos > 0) 
			{ 
				//	Insert part of the previos line 
				TCHAR *pszInsertStr = (TCHAR *) _alloca(sizeof(TCHAR) * (nLength + 1)); 
				_tcsncpy(pszInsertStr, pszLineChars, nPos); 
				pszInsertStr[nPos] = 0; 
 
				int x, y; 
				m_pTextBuffer->InsertText(NULL, ptCursorPos.y, ptCursorPos.x, 
															pszInsertStr, y, x, CE_ACTION_AUTOINDENT); 
				CPoint pt(x, y); 
				SetCursorPos(pt); 
				SetSelection(pt, pt); 
				SetAnchor(pt); 
				EnsureVisible(pt); 
			} 
		} 
	} 
} 
 
 
CString CCrystalEditView::GetBgString(UINT nFlags, CPoint point) 
{ 
		CString str_bg=_T(""); 
		AdjustTextPoint(point); 
		CPoint m_point=point; 
 
		CPoint m_ptcursor,m_ptanchor; 
//		m_ptcursor=m_ptCursorPos; 
//		m_ptanchor=m_ptanchor; 
 
		m_ptcursor = ClientToText(point); 
		m_ptanchor = m_ptcursor; 
 
		CPoint ptStart, ptEnd; 
		if (m_ptcursor.y < m_ptanchor.y || 
			m_ptcursor.y == m_ptanchor.y && m_ptcursor.x < m_ptanchor.x) 
		{ 
			ptStart = WordToLeft(m_ptcursor); 
			ptEnd = WordToRight(m_ptanchor); 
		} 
		else 
		{ 
			ptStart = WordToLeft(m_ptanchor); 
			ptEnd = WordToRight(m_ptcursor); 
		} 
 
 
//		m_ptCursorPos = ptEnd; 
//		UpdateCaret(); 
//		EnsureVisible(m_ptCursorPos); 
//		SetSelection(ptStart, ptEnd); 
 
 
	if (! QueryEditable()) 
	{ 
//			m_ptCursorPos=m_ptcursor; 
//			m_ptanchor=m_ptanchor; 
 
		return str_bg; 
	} 
		if (m_pTextBuffer == NULL) 
	{ 
//			m_ptCursorPos=m_ptcursor; 
//			m_ptanchor=m_ptanchor; 
 
		return str_bg; 
	} 
//	if (! IsSelection()) 
//		return str_bg; 
 
//	CPoint ptSelStart, ptSelEnd; 
//	GetSelection(ptSelStart, ptSelEnd); 
//	CString text; 
	if(ptStart.x>=ptEnd.x) 
	{ 
//		m_ptCursorPos=m_ptcursor; 
  //   	m_ptanchor=m_ptanchor; 
		return str_bg;	 
	} 
	GetText(ptStart, ptEnd, str_bg); 
 
//	m_ptCursorPos=m_ptcursor; 
//	m_ptanchor=m_ptanchor; 
		return str_bg; 
 
}