git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3345 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			4234 lines
		
	
	
		
			77 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			4234 lines
		
	
	
		
			77 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/////////////////////////////////////////////////////////////////////////////
 | 
						|
// Name:        No names yet.
 | 
						|
// Purpose:     Contrib. demo
 | 
						|
// Author:      Aleksandras Gluchovas
 | 
						|
// Modified by:
 | 
						|
// Created:     03/04/1999
 | 
						|
// RCS-ID:      $Id$
 | 
						|
// Copyright:   (c) Aleksandars Gluchovas
 | 
						|
// Licence:   	GNU General Public License 
 | 
						|
/////////////////////////////////////////////////////////////////////////////
 | 
						|
//
 | 
						|
//  This program is free software; you can redistribute it and/or modify
 | 
						|
//  it under the terms of the GNU General Public License as published by
 | 
						|
//  the Free Software Foundation; either version 2 of the License, or
 | 
						|
//  (at your option) any later version.
 | 
						|
//
 | 
						|
//  This program is distributed in the hope that it will be useful,
 | 
						|
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
//  GNU General Public License for more details.
 | 
						|
//
 | 
						|
//  You should have received a copy of the GNU General Public License
 | 
						|
//  along with this program; if not, write to the Free Software
 | 
						|
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
						|
/////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
 | 
						|
// For compilers that support precompilation, includes "wx/wx.h".
 | 
						|
#include "wx/wxprec.h"
 | 
						|
 | 
						|
#ifdef __BORLANDC__
 | 
						|
#pragma hdrstop
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef WX_PRECOMP
 | 
						|
#include "wx/wx.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#include "wx/file.h"
 | 
						|
#include "wx/textdlg.h"
 | 
						|
#include "wx/clipbrd.h"
 | 
						|
#include "wx/dataobj.h"
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
#include "tdefs.h"
 | 
						|
#include "finddlg.h"
 | 
						|
 | 
						|
#include <memory.h>
 | 
						|
 | 
						|
/***** Implementation for class TBlock *****/
 | 
						|
 | 
						|
void TBlock::RecalcBlockProperties()
 | 
						|
{
 | 
						|
	char* cur = mBuf;
 | 
						|
	char* end = mBuf + mTextLen;
 | 
						|
	mRowCount = 0;
 | 
						|
 | 
						|
	while( cur < end )
 | 
						|
	{
 | 
						|
		if ( is_eol_char( *cur ) ) ++mRowCount;
 | 
						|
 | 
						|
		++cur;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/***** Implementation for class TTextIterator *****/
 | 
						|
 | 
						|
string TTextIterator::mSeparators = ",.()[]\t\\+-*/|=<>:;\t\n~?!%";
 | 
						|
 | 
						|
bool TTextIterator::IsSeparator( char ch )
 | 
						|
{
 | 
						|
	size_t sz = mSeparators.size();
 | 
						|
 | 
						|
	for( size_t i = 0; i != sz; ++i )
 | 
						|
 | 
						|
		if ( mSeparators[i] == ch ) return TRUE;
 | 
						|
 | 
						|
	return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
char* TTextIterator::GetClosestPos()
 | 
						|
{
 | 
						|
	char*  end = GetBlockEnd();
 | 
						|
	char*  cur = mpCurRowStart;
 | 
						|
	size_t col = 0;
 | 
						|
 | 
						|
	while( cur < end && col < mPos.mCol && !is_eol_char(*cur) )
 | 
						|
	{
 | 
						|
		if ( !is_DOS_eol_char( *cur ) ) ++col;
 | 
						|
		++cur;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( is_DOS_eol_char( *cur ) ) ++cur;
 | 
						|
 | 
						|
	return cur;
 | 
						|
}
 | 
						|
 | 
						|
char* TTextIterator::GotoClosestPos()
 | 
						|
{
 | 
						|
	char*  end = GetBlockEnd();
 | 
						|
	char*  cur = mpCurRowStart;
 | 
						|
	size_t col = 0;
 | 
						|
 | 
						|
	while( cur < end && col < mPos.mCol && !is_eol_char(*cur) )
 | 
						|
	{
 | 
						|
		if ( !is_DOS_eol_char( *cur ) ) ++col;
 | 
						|
		++cur;
 | 
						|
	}
 | 
						|
 | 
						|
	mPos.mCol = col;
 | 
						|
 | 
						|
	if ( is_DOS_eol_char( *cur ) ) ++cur;
 | 
						|
 | 
						|
	return cur;
 | 
						|
}
 | 
						|
 | 
						|
TTextIterator::TTextIterator()
 | 
						|
 | 
						|
	: mIsEof( FALSE )
 | 
						|
{}
 | 
						|
 | 
						|
bool TTextIterator::IsLastLine()
 | 
						|
{
 | 
						|
	TBlockIteratorT nextBlk = mBlockIter;
 | 
						|
	++nextBlk;
 | 
						|
 | 
						|
	if ( nextBlk != mEndOfListIter ) return FALSE;
 | 
						|
 | 
						|
	char* cur = mpCurRowStart;
 | 
						|
	char* end = GetBlockEnd();
 | 
						|
 | 
						|
	while( cur < end && !is_eol_char( *cur ) ) ++cur;
 | 
						|
 | 
						|
	if ( cur == end ) return TRUE;
 | 
						|
 | 
						|
	++cur;
 | 
						|
 | 
						|
	return ( cur == end );
 | 
						|
}
 | 
						|
 | 
						|
char TTextIterator::GetChar()
 | 
						|
{
 | 
						|
	char* cur = GetClosestPos();
 | 
						|
 | 
						|
	if ( is_DOS_eol_char( *cur ) ) 
 | 
						|
 | 
						|
		return *(cur+1);
 | 
						|
	else
 | 
						|
		return *cur;
 | 
						|
}
 | 
						|
 | 
						|
bool TTextIterator::IsEol()
 | 
						|
{
 | 
						|
	return is_eol_char( GetChar() ) || mIsEof;
 | 
						|
}
 | 
						|
 | 
						|
bool TTextIterator::IsEof()
 | 
						|
{
 | 
						|
	return mIsEof;
 | 
						|
}
 | 
						|
 | 
						|
int TTextIterator::GetDistFromEol()
 | 
						|
{
 | 
						|
	return 0; // TBD::
 | 
						|
}
 | 
						|
 | 
						|
void TTextIterator::NextChar()
 | 
						|
{
 | 
						|
	char* cur = GotoClosestPos();
 | 
						|
 | 
						|
	if ( cur + 1 >= GetBlockEnd() )
 | 
						|
	{
 | 
						|
		TBlockIteratorT nextBlk = mBlockIter;
 | 
						|
		++nextBlk;
 | 
						|
 | 
						|
		if ( nextBlk == mEndOfListIter )
 | 
						|
		{
 | 
						|
			if ( cur != GetBlockEnd() ) 
 | 
						|
				++mPos.mCol;	
 | 
						|
 | 
						|
			mIsEof = TRUE;
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		++mPos.mRow ;
 | 
						|
		mPos.mCol = 0;
 | 
						|
 | 
						|
		mBlockIter = nextBlk;
 | 
						|
 | 
						|
		mFirstRowInBlock = mPos.mRow;
 | 
						|
		mActualRow       = mPos.mRow;
 | 
						|
		mpCurRowStart    = (*mBlockIter).mBuf;
 | 
						|
 | 
						|
		mIsEof = ( (*mBlockIter).mTextLen == 0 );
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		if ( is_eol_char( *cur ) ) 
 | 
						|
		{
 | 
						|
			++mPos.mRow;
 | 
						|
			mPos.mCol = 0;
 | 
						|
			
 | 
						|
			mActualRow    = mPos.mRow;
 | 
						|
			mpCurRowStart = cur + 1;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			++mPos.mCol;
 | 
						|
	}
 | 
						|
 | 
						|
	mIsEof = (mpCurRowStart + mPos.mCol) == GetBlockEnd();
 | 
						|
}
 | 
						|
 | 
						|
void TTextIterator::PreviousChar()
 | 
						|
{
 | 
						|
	char* cur = GotoClosestPos();
 | 
						|
 | 
						|
	if ( cur == (*mBlockIter).mBuf )
 | 
						|
	{
 | 
						|
		TBlockIteratorT prevBlk = mBlockIter;
 | 
						|
		--prevBlk;
 | 
						|
 | 
						|
		if ( prevBlk == mEndOfListIter )
 | 
						|
		{
 | 
						|
			mIsEof = TRUE;
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		--mPos.mRow;
 | 
						|
 | 
						|
		mBlockIter = prevBlk;
 | 
						|
 | 
						|
		cur = GetBlockEnd() - 1;
 | 
						|
 | 
						|
		char* eolPos = cur;
 | 
						|
		--cur; // skip EOL
 | 
						|
		char* start = (*mBlockIter).mBuf;
 | 
						|
 | 
						|
		while( cur != start && !is_eol_char( *cur ) ) --cur; // goto start of line
 | 
						|
 | 
						|
		if ( is_eol_char( *cur ) ) ++cur;
 | 
						|
 | 
						|
		mPos.mCol     = (size_t)(eolPos - cur);
 | 
						|
		mpCurRowStart = cur;
 | 
						|
 | 
						|
		mFirstRowInBlock = mPos.mRow;
 | 
						|
		mActualRow       = mPos.mRow;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		do
 | 
						|
		{
 | 
						|
			// FIXME FIXME:: this is more then messy .... !
 | 
						|
 | 
						|
			if ( is_eol_char( *(cur-1) ) ) 
 | 
						|
			{
 | 
						|
				--cur; // goto EOL
 | 
						|
 | 
						|
				--mPos.mRow;
 | 
						|
 | 
						|
				char* eolPos = cur;
 | 
						|
				--cur; // skip EOL
 | 
						|
				char* start = (*mBlockIter).mBuf;
 | 
						|
 | 
						|
				while( cur != start && !is_eol_char( *cur ) ) --cur; // goto start of line
 | 
						|
 | 
						|
				if ( is_eol_char( *cur ) ) ++cur;
 | 
						|
 | 
						|
				mPos.mCol     = (size_t)(eolPos - cur);
 | 
						|
				mpCurRowStart = cur;
 | 
						|
 | 
						|
				if ( eolPos != cur && is_DOS_eol_char( *(eolPos-1) ) ) --mPos.mCol;
 | 
						|
				
 | 
						|
				mActualRow    = mPos.mRow;
 | 
						|
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			if ( is_DOS_eol_char( *(cur-1) ) )
 | 
						|
			{
 | 
						|
				--cur;
 | 
						|
 | 
						|
				if ( cur != (*mBlockIter).mBuf && is_eol_char( *(cur-1) ) )
 | 
						|
 | 
						|
					continue;
 | 
						|
				else
 | 
						|
				{
 | 
						|
					--mPos.mCol;
 | 
						|
					--cur;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				--mPos.mCol;
 | 
						|
				break;
 | 
						|
			}
 | 
						|
 | 
						|
		} while( 1 );
 | 
						|
	}
 | 
						|
 | 
						|
	mIsEof = (mpCurRowStart + mPos.mCol) == GetBlockEnd();
 | 
						|
}
 | 
						|
 | 
						|
void TTextIterator::NextWord()
 | 
						|
{
 | 
						|
	GotoClosestPos();
 | 
						|
 | 
						|
	// skip non-white space ahead
 | 
						|
 | 
						|
	bool wasSeparator = IsSeparator( GetChar() );
 | 
						|
 | 
						|
	while( !IsEof() )
 | 
						|
	{
 | 
						|
		char ch = GetChar();
 | 
						|
 | 
						|
		if ( ch == ' '  || 
 | 
						|
			 ch == '\t' || 
 | 
						|
			 is_eol_char(ch) ||
 | 
						|
			 wasSeparator != IsSeparator(ch) )
 | 
						|
 | 
						|
			break;
 | 
						|
 | 
						|
		NextChar();
 | 
						|
	}
 | 
						|
 | 
						|
	// skip all white stpace if any
 | 
						|
	while( !IsEof() )
 | 
						|
	{
 | 
						|
		char ch = GetChar();
 | 
						|
 | 
						|
		if ( ch != ' ' && ch != '\t' && !is_eol_char(ch) )
 | 
						|
 | 
						|
			break;
 | 
						|
 | 
						|
		NextChar();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TTextIterator::PreviousWord()
 | 
						|
{
 | 
						|
	GotoClosestPos();
 | 
						|
 | 
						|
	PreviousChar();
 | 
						|
 | 
						|
	// skip all white stpace if any
 | 
						|
	while( !IsEof() )
 | 
						|
	{
 | 
						|
		char ch = GetChar();
 | 
						|
 | 
						|
		if ( ch != ' ' && ch != '\t' && !is_eol_char(ch) )
 | 
						|
 | 
						|
			break;
 | 
						|
 | 
						|
		PreviousChar();
 | 
						|
	}
 | 
						|
 | 
						|
	bool wasSeparator = IsSeparator( GetChar() );
 | 
						|
 | 
						|
	// skip word;
 | 
						|
	while( !IsEof() )
 | 
						|
	{
 | 
						|
		char ch = GetChar();
 | 
						|
 | 
						|
		if ( ch == ' '       || 
 | 
						|
			 ch == '\t'      || 
 | 
						|
			 is_eol_char(ch) ||
 | 
						|
			 wasSeparator != IsSeparator(ch) 
 | 
						|
		   )
 | 
						|
		{
 | 
						|
			NextChar();
 | 
						|
			break;
 | 
						|
		}
 | 
						|
 | 
						|
		PreviousChar();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TTextIterator::ToEndOfLine()
 | 
						|
{
 | 
						|
	GotoClosestPos();
 | 
						|
 | 
						|
	while( !IsEof() )
 | 
						|
	{
 | 
						|
		char ch = GetChar();
 | 
						|
 | 
						|
		if ( is_eol_char( ch ) ) break;
 | 
						|
 | 
						|
		NextChar();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TTextIterator::ToStartOfLine()
 | 
						|
{
 | 
						|
	GotoClosestPos();
 | 
						|
 | 
						|
	mPos.mCol = 0;
 | 
						|
	mPos.mRow = mActualRow;
 | 
						|
}
 | 
						|
 | 
						|
size_t TTextIterator::GetLineLen()
 | 
						|
{
 | 
						|
	char* cur = mpCurRowStart;
 | 
						|
	char* end = GetBlockEnd();
 | 
						|
 | 
						|
	size_t len = 0;
 | 
						|
 | 
						|
	while( cur < end && !is_eol_char( *cur ) )
 | 
						|
	{
 | 
						|
		if ( !is_DOS_eol_char( *cur ) ) ++len;
 | 
						|
		++cur;
 | 
						|
	}
 | 
						|
 | 
						|
	return len;
 | 
						|
}
 | 
						|
 | 
						|
TPosition TTextIterator::GetPosition()
 | 
						|
{
 | 
						|
	return mPos;
 | 
						|
}
 | 
						|
 | 
						|
bool TTextIterator::IsInLastBlock()
 | 
						|
{
 | 
						|
	TBlockIteratorT next = mBlockIter;
 | 
						|
	++next;
 | 
						|
 | 
						|
	return next == mEndOfListIter;
 | 
						|
}
 | 
						|
 | 
						|
bool TTextIterator::DetectUnixText()
 | 
						|
{
 | 
						|
	char* cur = GetBlockStart();
 | 
						|
	char* end = GetBlockEnd();
 | 
						|
 | 
						|
	bool isUnixText = IS_UNIX_TEXT_BY_DEFAULT;
 | 
						|
 | 
						|
	while( cur < end ) 
 | 
						|
	{
 | 
						|
		if ( is_DOS_eol_char( *cur ) ) return FALSE;
 | 
						|
 | 
						|
		if ( is_eol_char( *cur ) ) return TRUE;
 | 
						|
 | 
						|
		++cur;
 | 
						|
	}
 | 
						|
 | 
						|
	return isUnixText;
 | 
						|
}
 | 
						|
 | 
						|
/***** Implementation for class TCppJavaHighlightListener *****/
 | 
						|
 | 
						|
void TCppJavaHighlightListener::OnTextChanged( wxTextEditorModel* pModel, 
 | 
						|
											   size_t atRow, size_t nRows, 
 | 
						|
											   TEXT_CHANGE_TYPE ct ) 
 | 
						|
{
 | 
						|
	mpModel = pModel;
 | 
						|
	
 | 
						|
	/*
 | 
						|
 | 
						|
	int state = GetStateAtRow( atRow );
 | 
						|
 | 
						|
	if ( ct == CT_INSERTED )
 | 
						|
	{
 | 
						|
		RemoveCommentTags( atRow, atRow + nRows + 1 );
 | 
						|
		GenerateTagsForRange( atRows, atRows + nRows + 1 );
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( ct == CT_DELETED )
 | 
						|
	{
 | 
						|
		RemoveCommentTags( atRow, atRow + 1 );
 | 
						|
		GenerateTagsForRange( atRows, atRows + 1 );
 | 
						|
	}
 | 
						|
	*/
 | 
						|
}
 | 
						|
 | 
						|
/***** Implementation for class wxTextEditorModel *****/
 | 
						|
 | 
						|
/*** protected methods ***/
 | 
						|
 | 
						|
size_t wxTextEditorModel::GetLineCountInRange( char* from, char* till )
 | 
						|
{
 | 
						|
	size_t nLines = 0;
 | 
						|
 | 
						|
	while( from != till )
 | 
						|
	{
 | 
						|
		if ( is_eol_char( *from ) ) ++nLines;
 | 
						|
 | 
						|
		++from;
 | 
						|
	}
 | 
						|
 | 
						|
	return nLines;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::DoInsertText( const TPosition& pos, 
 | 
						|
									  char* text, size_t len,
 | 
						|
									  TRange& actualRange )
 | 
						|
{
 | 
						|
	// FOR NOW:: very dummy imp.
 | 
						|
 | 
						|
	char* end = text + len;
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( pos );
 | 
						|
 | 
						|
	TBlock& blk = (*iter.mBlockIter);
 | 
						|
 | 
						|
	char* cur = text;
 | 
						|
 | 
						|
	char*  insertPos = iter.GotoClosestPos();
 | 
						|
	actualRange.mFrom = iter.GetPosition();
 | 
						|
 | 
						|
	if ( is_eol_char( *insertPos ) &&
 | 
						|
		 insertPos != iter.GetBlockStart()   &&
 | 
						|
		 is_DOS_eol_char( *(insertPos-1) )
 | 
						|
	   )
 | 
						|
	   --insertPos;
 | 
						|
 | 
						|
	size_t sizeAfter = (size_t)(iter.GetBlockEnd() - insertPos);
 | 
						|
 | 
						|
	size_t nLines = GetLineCountInRange( text, text + len );
 | 
						|
 | 
						|
	if ( blk.mTextLen + len < FILLED_BLOCK_LEN )
 | 
						|
	{
 | 
						|
		memmove( insertPos + len, insertPos, sizeAfter );
 | 
						|
 | 
						|
		memcpy( insertPos, text, len );
 | 
						|
 | 
						|
		blk.mTextLen += len;
 | 
						|
		
 | 
						|
 | 
						|
		blk.RecalcBlockProperties();
 | 
						|
 | 
						|
		if ( iter.IsInLastBlock() )
 | 
						|
 | 
						|
			++blk.mRowCount; // last block have always the-last-row-to-spare -
 | 
						|
		                     // the "nature" of most text editors
 | 
						|
 | 
						|
		char* endPos = insertPos + len;
 | 
						|
 | 
						|
		bool found = FALSE;
 | 
						|
 | 
						|
		/*
 | 
						|
		// OLD STUFF:: slow & buggy
 | 
						|
 | 
						|
		while( !iter.IsEof() )
 | 
						|
		{
 | 
						|
			if ( iter.GetClosestPos() == endPos )
 | 
						|
			{
 | 
						|
				actualRange.mTill = iter.GetPosition();
 | 
						|
				found = TRUE;
 | 
						|
				break;
 | 
						|
			}
 | 
						|
 | 
						|
			iter.NextChar();
 | 
						|
		}
 | 
						|
 | 
						|
		if ( !found )
 | 
						|
		{
 | 
						|
			actualRange.mTill = iter.GetPosition();
 | 
						|
			++actualRange.mTill.mCol;
 | 
						|
			
 | 
						|
			//T_ASSERT( found ); // DBG::
 | 
						|
		}
 | 
						|
		*/
 | 
						|
 | 
						|
		actualRange.mTill       = actualRange.mFrom;
 | 
						|
		actualRange.mTill.mRow += nLines;
 | 
						|
 | 
						|
		if ( nLines == 0 )
 | 
						|
 | 
						|
			actualRange.mTill.mCol = actualRange.mFrom.mCol + (len);
 | 
						|
		else
 | 
						|
		{
 | 
						|
			cur = end;
 | 
						|
 | 
						|
			while( cur != insertPos && !is_eol_char( *cur ) )
 | 
						|
 | 
						|
				--cur;
 | 
						|
 | 
						|
			if ( is_eol_char( *cur ) ) ++cur;
 | 
						|
 | 
						|
			actualRange.mTill.mCol = (int)(end - cur);
 | 
						|
		}
 | 
						|
 | 
						|
		NotifyTextChanged( pos.mRow, nLines, CT_INSERTED );
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		// TBD:::
 | 
						|
 | 
						|
		char buf[16];
 | 
						|
		sprintf( buf, "%d", FILLED_BLOCK_LEN );
 | 
						|
		string msg = "Sorry!!! Currently editor is limited to files less then ";
 | 
						|
		msg += buf;
 | 
						|
		msg += " bytes\n(the requested text length is " + 
 | 
						|
		sprintf( buf, "%d", blk.mTextLen + len );
 | 
						|
		msg += buf; 
 | 
						|
		msg += " bytes)\n Please, close this file without making any changes.";
 | 
						|
 | 
						|
		wxMessageBox( msg );
 | 
						|
 | 
						|
		GetActiveView()->SetFocus();
 | 
						|
 | 
						|
		//T_ASSERT(0); // DBG:: for now
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::DoDeleteRange( const TPosition& from, const TPosition& till,
 | 
						|
									   TRange& actualRange
 | 
						|
									 )
 | 
						|
{
 | 
						|
	// FOR NOW:: very dummy imp.
 | 
						|
 | 
						|
	TTextIterator iterFrom = CreateIterator( from );
 | 
						|
	TTextIterator iterTill = CreateIterator( till );
 | 
						|
 | 
						|
	if ( iterFrom.mBlockIter == iterTill.mBlockIter )
 | 
						|
	{
 | 
						|
		char* fromPos = iterFrom.GotoClosestPos();
 | 
						|
		char* tillPos = iterTill.GotoClosestPos();
 | 
						|
		char* blockStart = (*iterFrom.mBlockIter).mBuf;
 | 
						|
		
 | 
						|
		if ( is_eol_char( *fromPos ) &&
 | 
						|
			 fromPos != blockStart   &&
 | 
						|
			 is_DOS_eol_char( *(fromPos-1) )
 | 
						|
		   )
 | 
						|
		   --fromPos;
 | 
						|
 | 
						|
		if ( is_eol_char( *tillPos ) &&
 | 
						|
			 tillPos != blockStart   &&
 | 
						|
			 is_DOS_eol_char( *(tillPos-1) )
 | 
						|
		   )
 | 
						|
		   --tillPos;
 | 
						|
 | 
						|
		size_t len = (size_t)( tillPos -fromPos );
 | 
						|
		
 | 
						|
		size_t nLines = GetLineCountInRange( fromPos, fromPos + len );
 | 
						|
 | 
						|
		size_t sizeAfter = (size_t)(iterFrom.GetBlockEnd() - tillPos);
 | 
						|
 | 
						|
		memmove( fromPos, tillPos, sizeAfter );
 | 
						|
 | 
						|
		(*iterFrom.mBlockIter).mTextLen -= len;
 | 
						|
 | 
						|
		(*iterFrom.mBlockIter).RecalcBlockProperties();
 | 
						|
 | 
						|
		if ( iterFrom.IsInLastBlock() )
 | 
						|
 | 
						|
			++(*iterFrom.mBlockIter).mRowCount; // last block have always the-last-row-to-spare -
 | 
						|
												// the "nature" of most text editors
 | 
						|
 | 
						|
		actualRange.mFrom = iterFrom.GetPosition();
 | 
						|
		actualRange.mTill = iterTill.GetPosition();
 | 
						|
 | 
						|
		NotifyTextChanged( from.mRow, nLines, CT_DELETED );
 | 
						|
	}
 | 
						|
	else
 | 
						|
		T_ASSERT(0); // DBG:: for now
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::GetTextFromRange( const TPosition& from, const TPosition& till, 
 | 
						|
										  char** text, size_t& textLen 
 | 
						|
										)
 | 
						|
{
 | 
						|
	TTextIterator iterFrom = CreateIterator( from );
 | 
						|
	TTextIterator iterTill = CreateIterator( till );
 | 
						|
 | 
						|
	if ( iterFrom.mBlockIter == iterTill.mBlockIter )
 | 
						|
	{
 | 
						|
		char* blockStart = (*iterFrom.mBlockIter).mBuf;
 | 
						|
 | 
						|
		char* fromPos = iterFrom.GetClosestPos();
 | 
						|
		char* tillPos = iterTill.GetClosestPos();
 | 
						|
 | 
						|
		if ( is_eol_char( *fromPos ) &&
 | 
						|
			 fromPos != blockStart   &&
 | 
						|
			 is_DOS_eol_char( *(fromPos-1) )
 | 
						|
		   )
 | 
						|
		   --fromPos;
 | 
						|
 | 
						|
		if ( is_eol_char( *tillPos ) &&
 | 
						|
			 tillPos != blockStart   &&
 | 
						|
			 is_DOS_eol_char( *(tillPos-1) )
 | 
						|
		   )
 | 
						|
		   --tillPos;
 | 
						|
 | 
						|
		textLen = (size_t)( tillPos -fromPos );
 | 
						|
 | 
						|
		*text = AllocCharacters( textLen );
 | 
						|
 | 
						|
		memcpy( *text, fromPos, textLen );
 | 
						|
	}
 | 
						|
	else
 | 
						|
		T_ASSERT(0); // DBG:: for now
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::LoadTextFromFile( const wxString& fname )
 | 
						|
{
 | 
						|
	T_ASSERT( wxFile::Exists( fname ) );
 | 
						|
 | 
						|
	DeleteAllText();
 | 
						|
 | 
						|
	wxFile fl( fname );
 | 
						|
 | 
						|
	char* buf = AllocCharacters( fl.Length() );
 | 
						|
 | 
						|
	fl.Read( buf, fl.Length() );
 | 
						|
 | 
						|
	TRange result;
 | 
						|
	DoInsertText( TPosition( 0,0 ), buf, fl.Length(), result );
 | 
						|
 | 
						|
	FreeCharacters( buf );
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( TPosition( 0,0 ) );
 | 
						|
 | 
						|
	mIsUnixText = iter.DetectUnixText();
 | 
						|
 | 
						|
	ClearUndoBuffer();
 | 
						|
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::SaveTextToFile( const wxString& fname )
 | 
						|
{
 | 
						|
	wxFile fl( fname, wxFile::write );
 | 
						|
 | 
						|
	char* text = 0;
 | 
						|
	size_t len = 0;
 | 
						|
 | 
						|
	GetTextFromRange( TPosition(0,0), TPosition( GetTotalRowCount()+1,0 ), &text, len );
 | 
						|
 | 
						|
	fl.Write( text, len );
 | 
						|
	fl.Close();
 | 
						|
 | 
						|
	FreeCharacters( text );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::NotifyTextChanged( size_t atRow, size_t nRows, TEXT_CHANGE_TYPE ct )
 | 
						|
{
 | 
						|
	if ( nRows > 0  )
 | 
						|
	
 | 
						|
		MergeChange( atRow, mRowsPerPage );
 | 
						|
	else
 | 
						|
		MergeChange( atRow, 1 );
 | 
						|
 | 
						|
	// reposition bookmarsk
 | 
						|
 | 
						|
	if ( nRows > 0 )
 | 
						|
	{
 | 
						|
		if ( ct == CT_INSERTED )
 | 
						|
		{
 | 
						|
			size_t curPin = FindNextPinFrom( atRow + 1 );
 | 
						|
 | 
						|
			while( curPin != NPOS )
 | 
						|
			{
 | 
						|
				mPins[curPin]->mRow += nRows;
 | 
						|
 | 
						|
				++curPin;
 | 
						|
 | 
						|
				if ( curPin == mPins.size() ) break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else
 | 
						|
		if ( ct == CT_DELETED )
 | 
						|
		{
 | 
						|
			size_t curPin  = FindNextPinFrom( atRow + 1 );
 | 
						|
			size_t fromPin = curPin;
 | 
						|
			size_t tillRow = atRow + nRows;
 | 
						|
 | 
						|
			while( curPin != NPOS && mPins[curPin]->mRow < tillRow )
 | 
						|
			{
 | 
						|
				++curPin;
 | 
						|
 | 
						|
				if ( curPin == mPins.size() ) break;
 | 
						|
			}
 | 
						|
 | 
						|
			if ( fromPin != NPOS && nRows != 0 )
 | 
						|
			{
 | 
						|
				mPins.erase( &mPins[fromPin], &mPins[curPin] );
 | 
						|
 | 
						|
				while( curPin < mPins.size() )
 | 
						|
				{
 | 
						|
					mPins[curPin]->mRow -= nRows;
 | 
						|
					++curPin;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	// send notificaitons
 | 
						|
 | 
						|
	for( size_t i = 0; i != mChangeListeners.size(); ++i )
 | 
						|
 | 
						|
		mChangeListeners[i]->OnTextChanged( this, atRow, nRows, ct );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::NotifyTextChanged( TPosition from, TPosition till, TEXT_CHANGE_TYPE ct )
 | 
						|
{
 | 
						|
	ArrangePositions( from, till );
 | 
						|
 | 
						|
	NotifyTextChanged( from.mRow, till.mRow - from.mRow + 1, ct );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::DoExecuteNewCommand( TCommand& cmd )
 | 
						|
{
 | 
						|
	if ( cmd.mType == TCMD_INSERT )
 | 
						|
	{
 | 
						|
		cmd.mPrePos = mCursorPos;
 | 
						|
		DoInsertText( cmd.mRange.mFrom, cmd.mData, cmd.mDataLen, cmd.mRange );
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( cmd.mType == TCMD_DELETE )
 | 
						|
	{
 | 
						|
		cmd.mPrePos = mCursorPos;
 | 
						|
		DoDeleteRange( cmd.mRange.mFrom, cmd.mRange.mTill, cmd.mRange );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::DoReexecuteCommand( TCommand& cmd )
 | 
						|
{
 | 
						|
	NotifyTextChanged( mCursorPos.mRow, 1, CT_MODIFIED ); // indicate update of current cursor position
 | 
						|
 | 
						|
	if ( cmd.mType == TCMD_INSERT )
 | 
						|
	{
 | 
						|
		DoInsertText( cmd.mRange.mFrom, cmd.mData, cmd.mDataLen, cmd.mRange );
 | 
						|
		mCursorPos = cmd.mPostPos;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( cmd.mType == TCMD_DELETE )
 | 
						|
	{
 | 
						|
		DoDeleteRange( cmd.mRange.mFrom, cmd.mRange.mTill, cmd.mRange );
 | 
						|
		mCursorPos = cmd.mPostPos;
 | 
						|
	}
 | 
						|
 | 
						|
	NotifyTextChanged( mCursorPos.mRow, 1, CT_MODIFIED ); // indicate update of current cursor position
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::DoUnexecuteCommand( TCommand& cmd )
 | 
						|
{
 | 
						|
	NotifyTextChanged( mCursorPos.mRow, 1, CT_MODIFIED ); // indicate update of current cursor position
 | 
						|
	
 | 
						|
	if ( cmd.mType == TCMD_INSERT )
 | 
						|
	{
 | 
						|
		DoDeleteRange( cmd.mRange.mFrom, cmd.mRange.mTill, cmd.mRange );
 | 
						|
		mCursorPos = cmd.mPrePos;
 | 
						|
	}
 | 
						|
	else					
 | 
						|
	if ( cmd.mType == TCMD_DELETE )
 | 
						|
	{
 | 
						|
		DoInsertText( cmd.mRange.mFrom, cmd.mData, cmd.mDataLen, cmd.mRange );
 | 
						|
		mCursorPos = cmd.mPrePos;
 | 
						|
	}
 | 
						|
 | 
						|
	NotifyTextChanged( mCursorPos.mRow, 1, CT_MODIFIED ); // indicate update of current cursor position
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::UndoImpl()
 | 
						|
{
 | 
						|
	--mCurCommand;
 | 
						|
 | 
						|
	DoUnexecuteCommand( *mCommands[mCurCommand] );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::RedoImpl()
 | 
						|
{
 | 
						|
	DoReexecuteCommand( *mCommands[mCurCommand] );
 | 
						|
 | 
						|
	++mCurCommand;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::ExecuteCommand( TCommand* pCmd )
 | 
						|
{
 | 
						|
	if ( mCurCommand < mCheckPointCmdNo )
 | 
						|
 | 
						|
		// new command is executed before the checkpoint,
 | 
						|
		// and every thing is sliced - invalidate it
 | 
						|
 | 
						|
		mCheckPointDestroyed = TRUE;
 | 
						|
 | 
						|
	// slice undo-able commands ahead in the queue,
 | 
						|
	// they wont ever be reexecuted
 | 
						|
 | 
						|
	while( mCommands.size() > mCurCommand )
 | 
						|
	{
 | 
						|
		delete mCommands.back();
 | 
						|
 | 
						|
		mCommands.pop_back();
 | 
						|
	}
 | 
						|
 | 
						|
	mCommands.push_back( pCmd );
 | 
						|
 | 
						|
	DoExecuteNewCommand( *pCmd );
 | 
						|
	++mCurCommand;
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::CanPrependCommand( TCommand* pCmd )
 | 
						|
{
 | 
						|
	if ( mCommands.size() != mCurCommand ||
 | 
						|
		 mCommands.size() == 0 ) 
 | 
						|
		 
 | 
						|
		 return FALSE;
 | 
						|
 | 
						|
	TCommand& prevCmd = *mCommands.back();
 | 
						|
 | 
						|
	if ( !(prevCmd.mRange.mTill == pCmd->mRange.mFrom) ) 
 | 
						|
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	char prevCh = prevCmd.mData[ prevCmd.mDataLen - 1];
 | 
						|
	char curCh  = pCmd->mData[0];
 | 
						|
 | 
						|
	if ( prevCh == curCh ) return TRUE;
 | 
						|
 | 
						|
	if ( prevCh == ' ' || curCh == ' ') return FALSE;
 | 
						|
 | 
						|
	if ( TTextIterator::IsSeparator(prevCh) !=
 | 
						|
		 TTextIterator::IsSeparator(curCh) )
 | 
						|
 | 
						|
		 return FALSE;
 | 
						|
	
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::PrependCommand( TCommand* pCmd )
 | 
						|
{
 | 
						|
	if ( mCheckPointCmdNo == mCurCommand )
 | 
						|
 | 
						|
		mCheckPointDestroyed = TRUE;
 | 
						|
 | 
						|
	TCommand& prevCmd = *mCommands.back();
 | 
						|
 | 
						|
	DoExecuteNewCommand( *pCmd );
 | 
						|
 | 
						|
	TCommand* pComb = new TCommand();
 | 
						|
 | 
						|
	pComb->mType    = TCMD_INSERT;
 | 
						|
	pComb->mDataLen = prevCmd.mDataLen + pCmd->mDataLen;
 | 
						|
 | 
						|
	pComb->mData        = AllocCharacters( pComb->mDataLen );
 | 
						|
	pComb->mRange.mFrom = prevCmd.mRange.mFrom;
 | 
						|
	pComb->mRange.mTill = pCmd->mRange.mTill;
 | 
						|
	pComb->mPrePos      = prevCmd.mPrePos;
 | 
						|
	pComb->mPostPos     = pCmd->mPostPos;
 | 
						|
 | 
						|
	memcpy( pComb->mData, prevCmd.mData, prevCmd.mDataLen );
 | 
						|
	memcpy( pComb->mData + prevCmd.mDataLen, pCmd->mData, pCmd->mDataLen );
 | 
						|
 | 
						|
	FreeCharacters( prevCmd.mData );
 | 
						|
	FreeCharacters( pCmd->mData );
 | 
						|
 | 
						|
	delete &prevCmd;
 | 
						|
	delete pCmd;
 | 
						|
 | 
						|
	mCommands[ mCommands.size() - 1 ] = pComb;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::SetPostPos( const TPosition& pos )
 | 
						|
{
 | 
						|
	mCommands[mCurCommand-1]->mPostPos = pos;
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::SelectionIsEmpty()
 | 
						|
{
 | 
						|
	return mSelectionStart == mSelectionEnd;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::StartBatch()
 | 
						|
{
 | 
						|
	// TBD::
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::FinishBatch()
 | 
						|
{
 | 
						|
	// TBD::
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::DeleteRange( const TPosition& from, const TPosition& till )
 | 
						|
{
 | 
						|
	TCommand* pCmd = new TCommand();
 | 
						|
 | 
						|
	pCmd->mType     = TCMD_DELETE;
 | 
						|
 | 
						|
	pCmd->mRange.mFrom = from;
 | 
						|
	pCmd->mRange.mTill = till;
 | 
						|
	pCmd->mPrePos      = mCursorPos;
 | 
						|
 | 
						|
	GetTextFromRange( from, till, &pCmd->mData, pCmd->mDataLen );
 | 
						|
 | 
						|
	ExecuteCommand( pCmd );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::InsertText( const TPosition& pos, const char* text, size_t len )
 | 
						|
{
 | 
						|
	TCommand* pCmd = new TCommand();
 | 
						|
 | 
						|
	pCmd->mType     = TCMD_INSERT;
 | 
						|
 | 
						|
	pCmd->mRange.mFrom = pos;
 | 
						|
 | 
						|
	pCmd->mData     = AllocCharacters( len, text ), 
 | 
						|
	pCmd->mDataLen  = len;
 | 
						|
	pCmd->mPrePos   = mCursorPos;
 | 
						|
 | 
						|
	ExecuteCommand( pCmd );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::DeleteSelection()
 | 
						|
{
 | 
						|
	DeleteRange( mSelectionStart, mSelectionEnd );
 | 
						|
 | 
						|
	ResetSelection();	
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::IsLastLine( const TPosition& pos )
 | 
						|
{
 | 
						|
	return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
TTextIterator wxTextEditorModel::CreateIterator( const TPosition& pos )
 | 
						|
{
 | 
						|
	size_t curRow = 0;
 | 
						|
 | 
						|
	TBlockIteratorT bIter = mBlocks.begin();
 | 
						|
 | 
						|
	TTextIterator tIter;
 | 
						|
 | 
						|
	while( bIter != mBlocks.end() )
 | 
						|
	{
 | 
						|
		TBlockIteratorT nextBlk = bIter;
 | 
						|
		++nextBlk;
 | 
						|
 | 
						|
		if ( nextBlk == mBlocks.end() ||
 | 
						|
			 ( pos.mRow >= curRow && 
 | 
						|
			   pos.mRow <= curRow + (*bIter).mRowCount )
 | 
						|
		   )
 | 
						|
		{
 | 
						|
			tIter.mFirstRowInBlock = curRow;
 | 
						|
 | 
						|
			char* cur = (*bIter).mBuf;
 | 
						|
			char* end = cur + (*bIter).mTextLen;
 | 
						|
 | 
						|
			// slightly optimized
 | 
						|
 | 
						|
			if ( curRow < pos.mRow )
 | 
						|
			{
 | 
						|
				while( cur < end )
 | 
						|
				{
 | 
						|
					if ( is_eol_char( *cur ) ) 
 | 
						|
					{
 | 
						|
						++curRow;
 | 
						|
 | 
						|
						if ( !(curRow < pos.mRow) ) 
 | 
						|
						{
 | 
						|
							++cur;
 | 
						|
							break;
 | 
						|
						}
 | 
						|
					}
 | 
						|
 | 
						|
					++cur;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			tIter.mActualRow    = curRow;
 | 
						|
			tIter.mpCurRowStart = cur;
 | 
						|
			tIter.mPos          = pos;
 | 
						|
 | 
						|
			// FOR NOW:: positioning past the end of file is not supported
 | 
						|
			tIter.mPos.mRow     = curRow;
 | 
						|
 | 
						|
			tIter.mBlockIter     = bIter;
 | 
						|
			tIter.mEndOfListIter = mBlocks.end();
 | 
						|
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			curRow += (*bIter).mRowCount;
 | 
						|
			++bIter;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return tIter;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::ArrangePositions( TPosition& upper, TPosition& lower )
 | 
						|
{
 | 
						|
	if ( upper > lower )
 | 
						|
	{
 | 
						|
		TPosition tmp( lower );
 | 
						|
		lower = upper;
 | 
						|
		upper = tmp;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::ArrangePositions( size_t& upper, size_t& lower )
 | 
						|
{
 | 
						|
	if ( upper > lower )
 | 
						|
	{
 | 
						|
		size_t tmp = lower;
 | 
						|
		lower = upper;
 | 
						|
		upper = tmp;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::MergeChange( size_t fromRow, size_t nRows )
 | 
						|
{
 | 
						|
	if ( mTextChanged == FALSE )
 | 
						|
	{
 | 
						|
		mChangedFromRow = fromRow;
 | 
						|
		mChangedTillRow = fromRow + nRows;
 | 
						|
		mTextChanged    = TRUE;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		if ( mChangedFromRow > fromRow )
 | 
						|
 | 
						|
			mChangedFromRow = fromRow;
 | 
						|
 | 
						|
		if ( mChangedTillRow < fromRow + nRows )
 | 
						|
 | 
						|
			mChangedTillRow = fromRow + nRows;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::TrackSelection()
 | 
						|
{
 | 
						|
	if ( !mIsSelectionEditMode ) return;
 | 
						|
 | 
						|
	if ( mPrevCursorPos == mSelectionStart )
 | 
						|
 | 
						|
		mSelectionStart = mCursorPos;
 | 
						|
	else
 | 
						|
		mSelectionEnd   = mCursorPos;
 | 
						|
		
 | 
						|
	ArrangePositions( mSelectionStart, mSelectionEnd );
 | 
						|
 | 
						|
	NotifyTextChanged( mSelectionStart, mPrevSelectionStart, CT_MODIFIED );
 | 
						|
	NotifyTextChanged( mSelectionEnd,   mPrevSelectionEnd,   CT_MODIFIED );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::CheckSelection()
 | 
						|
{
 | 
						|
	ArrangePositions( mSelectionStart, mSelectionEnd );
 | 
						|
 | 
						|
	if ( mIsSelectionEditMode && SelectionIsEmpty() )
 | 
						|
	{
 | 
						|
		mSelectionStart = mCursorPos;
 | 
						|
		mSelectionEnd   = mCursorPos;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( !mIsSelectionEditMode && !SelectionIsEmpty() )
 | 
						|
	{
 | 
						|
		ResetSelection();
 | 
						|
	}
 | 
						|
 | 
						|
	mPrevSelectionStart = mSelectionStart;
 | 
						|
	mPrevSelectionEnd   = mSelectionEnd;
 | 
						|
	mPrevCursorPos      = mCursorPos;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::ResetSelection()
 | 
						|
{
 | 
						|
	if ( SelectionIsEmpty() ) return;
 | 
						|
 | 
						|
	MergeChange( mSelectionStart.mRow, 
 | 
						|
				 mSelectionEnd.mRow - mSelectionStart.mRow + 1 );
 | 
						|
 | 
						|
	NotifyTextChanged( mSelectionStart, mSelectionEnd, CT_MODIFIED );
 | 
						|
 | 
						|
	mSelectionStart = TPosition(0,0);
 | 
						|
	mSelectionEnd   = TPosition(0,0);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::ClearUndoBuffer()
 | 
						|
{
 | 
						|
	for( size_t i = 0; i != mCommands.size(); ++i )
 | 
						|
	{
 | 
						|
		TCommand& cmd = *mCommands[i];
 | 
						|
 | 
						|
		if ( cmd.mData ) delete [] cmd.mData;
 | 
						|
 | 
						|
		delete &cmd;
 | 
						|
	}
 | 
						|
 | 
						|
	mCommands.erase( mCommands.begin(), mCommands.end() );
 | 
						|
 | 
						|
	mCurCommand = 0;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::GetAllText( char** text, size_t& textLen )
 | 
						|
{
 | 
						|
	GetTextFromRange( TPosition(0,0), TPosition( GetTotalRowCount()+1, 0 ),
 | 
						|
		              text, textLen
 | 
						|
		            );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::DeleteAllText()
 | 
						|
{
 | 
						|
	ResetSelection();
 | 
						|
 | 
						|
	DeleteRange( TPosition(0,0), TPosition( GetTotalRowCount()+1, 0 ) );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::SetSelectionEditMode( bool editIsOn )
 | 
						|
{
 | 
						|
	mIsSelectionEditMode = editIsOn;
 | 
						|
}
 | 
						|
 | 
						|
size_t wxTextEditorModel::GetTotalRowCount()
 | 
						|
{
 | 
						|
	size_t nRows = 0;
 | 
						|
 | 
						|
	for( TBlockIteratorT i = mBlocks.begin(); i != mBlocks.end(); ++i )
 | 
						|
 | 
						|
		nRows += (*i).mRowCount;
 | 
						|
 | 
						|
	return nRows;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::GetSelection( char** text, size_t& textLen )
 | 
						|
{
 | 
						|
	GetTextFromRange( GetStartOfSelection(), GetEndOfSelection(), text, textLen );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::NotifyView()
 | 
						|
{
 | 
						|
	mpActiveView->OnModelChanged();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::NotifyAllViews()
 | 
						|
{
 | 
						|
	for( size_t i = 0; i != mViews.size(); ++i )
 | 
						|
 | 
						|
		mViews[i]->OnModelChanged();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::PrepreForCommand()
 | 
						|
{
 | 
						|
	mTextChanged    = 0;
 | 
						|
	mChangedFromRow = 0;
 | 
						|
	mChangedTillRow = 0;
 | 
						|
}
 | 
						|
 | 
						|
size_t wxTextEditorModel::TextToScrColumn( const TPosition& pos )
 | 
						|
{
 | 
						|
	TPosition spos;
 | 
						|
 | 
						|
	mpActiveView->TextPosToScreenPos( pos, spos );
 | 
						|
	
 | 
						|
	return spos.mCol + mpActiveView->GetPagePos().mCol;
 | 
						|
}
 | 
						|
 | 
						|
size_t wxTextEditorModel::ScrToTextColumn( TPosition pos )
 | 
						|
{
 | 
						|
	TPosition tpos;
 | 
						|
 | 
						|
	pos.mCol -= mpActiveView->GetPagePos().mCol;
 | 
						|
	pos.mRow -= mpActiveView->GetPagePos().mRow;
 | 
						|
 | 
						|
	mpActiveView->ScreenPosToTextPos( pos, tpos );
 | 
						|
 | 
						|
	return tpos.mCol;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::DoMoveCursor( int rows, int cols )
 | 
						|
{
 | 
						|
	mCursorPos.mCol = TextToScrColumn( mCursorPos );
 | 
						|
 | 
						|
	mCursorPos.mRow += rows;
 | 
						|
	mCursorPos.mCol += cols;
 | 
						|
 | 
						|
	mCursorPos.mCol = ScrToTextColumn( mCursorPos );
 | 
						|
}
 | 
						|
 | 
						|
/*** public interface ***/
 | 
						|
 | 
						|
wxTextEditorModel::wxTextEditorModel()
 | 
						|
 | 
						|
	: 
 | 
						|
	  mpActiveView( NULL ),
 | 
						|
	  mTabSize( 4 ),
 | 
						|
	  mIsSelectionEditMode( FALSE ),
 | 
						|
	  mRowsPerPage( 0 ),
 | 
						|
	  mTextChanged( FALSE ),
 | 
						|
	  mCurCommand( 0 ),
 | 
						|
 | 
						|
	  mInsertMode     ( TRUE  ),
 | 
						|
	  mAutoIndentMode ( TRUE  ),
 | 
						|
	  mSmartIndentMode( TRUE  ),
 | 
						|
	  mWasChanged     ( FALSE ),
 | 
						|
	  mIsReadOnly     ( FALSE ),
 | 
						|
	  mIsUnixText     ( IS_UNIX_TEXT_BY_DEFAULT )
 | 
						|
{
 | 
						|
	// at least one block should be present
 | 
						|
	// (otherwise text-iterators wont work)
 | 
						|
 | 
						|
	mBlocks.push_back( TBlock() );
 | 
						|
}
 | 
						|
 | 
						|
wxTextEditorModel::~wxTextEditorModel()
 | 
						|
{
 | 
						|
	ClearUndoBuffer();
 | 
						|
}
 | 
						|
 | 
						|
char* wxTextEditorModel::AllocCharacters( size_t n )
 | 
						|
{
 | 
						|
	return new char[n];
 | 
						|
}
 | 
						|
 | 
						|
char* wxTextEditorModel::AllocCharacters( size_t n, const char* srcBuf )
 | 
						|
{
 | 
						|
	char* destBuf = AllocCharacters( n );
 | 
						|
 | 
						|
	memcpy( destBuf, srcBuf, n );
 | 
						|
 | 
						|
	return destBuf;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::FreeCharacters( char* buf )
 | 
						|
{
 | 
						|
	delete [] buf;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnInsertChar( char ch )
 | 
						|
{
 | 
						|
	if ( ch == 27 ) return; // hack
 | 
						|
 | 
						|
	if ( is_DOS_eol_char( ch ) ) ch = '\n';
 | 
						|
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	TCommand* pCmd = new TCommand();
 | 
						|
 | 
						|
	pCmd->mType    = TCMD_INSERT;
 | 
						|
 | 
						|
	if ( ch == '\n' && !mIsUnixText ) 
 | 
						|
	{
 | 
						|
		// DOS text with CR-LF pair
 | 
						|
		pCmd->mData    = AllocCharacters( 2 );
 | 
						|
		pCmd->mDataLen = 2;
 | 
						|
		pCmd->mData[0] = (char)13;
 | 
						|
		pCmd->mData[1] = (char)10;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		pCmd->mData    = AllocCharacters( 1 );
 | 
						|
		pCmd->mDataLen = 1;
 | 
						|
		pCmd->mData[0] = ch;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	if ( !SelectionIsEmpty() )
 | 
						|
	{
 | 
						|
		mCursorPos = mSelectionStart;
 | 
						|
		DeleteSelection();
 | 
						|
	}
 | 
						|
 | 
						|
	pCmd->mRange.mFrom = mCursorPos;
 | 
						|
 | 
						|
	if ( mInsertMode == FALSE )
 | 
						|
	{
 | 
						|
		TPosition nextPos( mCursorPos.mRow, mCursorPos.mCol + 1 );
 | 
						|
		DeleteRange( mCursorPos, nextPos );
 | 
						|
 | 
						|
		SetPostPos( mCursorPos );
 | 
						|
	}
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
 | 
						|
	size_t lineLen = iter.GetLineLen();
 | 
						|
 | 
						|
	bool indentAdded = FALSE;
 | 
						|
 | 
						|
	if ( mCursorPos.mCol > lineLen )
 | 
						|
	{
 | 
						|
 | 
						|
		wxString s( ' ', mCursorPos.mCol - lineLen );
 | 
						|
		InsertText( TPosition( mCursorPos.mRow, lineLen ), s.c_str(), s.length() );
 | 
						|
 | 
						|
		SetPostPos( mCursorPos );
 | 
						|
 | 
						|
		indentAdded = TRUE;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( CanPrependCommand( pCmd ) || indentAdded )
 | 
						|
 | 
						|
		PrependCommand( pCmd );
 | 
						|
	else
 | 
						|
		ExecuteCommand( pCmd );
 | 
						|
 | 
						|
	++mCursorPos.mCol;
 | 
						|
 | 
						|
	if ( is_eol_char( ch ) )
 | 
						|
	{
 | 
						|
		mCursorPos.mCol = 0;
 | 
						|
		++mCursorPos.mRow;
 | 
						|
 | 
						|
		SetPostPos( mCursorPos );
 | 
						|
 | 
						|
		if ( mAutoIndentMode )
 | 
						|
		{
 | 
						|
			iter.ToStartOfLine();
 | 
						|
			wxString indent;
 | 
						|
 | 
						|
			while( !iter.IsEol() )
 | 
						|
			{
 | 
						|
				char ch = iter.GetChar();
 | 
						|
 | 
						|
				if ( ch == '\t' || ch == ' ' )
 | 
						|
 | 
						|
					indent += ch;
 | 
						|
				else
 | 
						|
					break;
 | 
						|
 | 
						|
				iter.NextChar();
 | 
						|
			}
 | 
						|
 | 
						|
			if ( indent.length() )
 | 
						|
			{
 | 
						|
				// auto-indent is always prepended to the command which
 | 
						|
				// caused it
 | 
						|
 | 
						|
				mCursorPos = TPosition( mCursorPos.mRow, 0 );
 | 
						|
 | 
						|
 | 
						|
				TCommand* pICmd = new TCommand();
 | 
						|
				pICmd->mType    = TCMD_INSERT;
 | 
						|
				pICmd->mData    = AllocCharacters( indent.length() );
 | 
						|
				pICmd->mDataLen = indent.length();
 | 
						|
				memcpy( pICmd->mData, indent, indent.length() );
 | 
						|
 | 
						|
				pICmd->mRange.mFrom = TPosition( mCursorPos.mRow, 0 );
 | 
						|
 | 
						|
				PrependCommand( pICmd );
 | 
						|
 | 
						|
				SetPostPos( mCursorPos );
 | 
						|
 | 
						|
				mCursorPos.mCol = indent.length();
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else
 | 
						|
		SetPostPos( mCursorPos );
 | 
						|
 | 
						|
	FinishBatch();
 | 
						|
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnDelete()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	if ( !SelectionIsEmpty() )
 | 
						|
	{
 | 
						|
		TPosition startPos = mSelectionStart;
 | 
						|
		DeleteSelection();
 | 
						|
		mCursorPos = startPos;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
		
 | 
						|
		if ( iter.GetLineLen() == mCursorPos.mCol && !iter.IsLastLine() )
 | 
						|
		{
 | 
						|
			TPosition nextPos( mCursorPos.mRow+1, 0 );
 | 
						|
			DeleteRange( mCursorPos, nextPos );
 | 
						|
			NotifyTextChanged( mCursorPos.mRow, 2, CT_DELETED );
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			TPosition nextPos( mCursorPos.mRow, mCursorPos.mCol + 1 );
 | 
						|
			DeleteRange( mCursorPos, nextPos );
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	SetPostPos( mCursorPos );
 | 
						|
 | 
						|
	FinishBatch();
 | 
						|
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnDeleteBack()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	if ( !SelectionIsEmpty() )
 | 
						|
	{
 | 
						|
		mCursorPos = mSelectionStart;
 | 
						|
		DeleteSelection();
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( !(mCursorPos == TPosition(0,0)) )
 | 
						|
	{
 | 
						|
		TPosition prevPos;
 | 
						|
 | 
						|
		if ( mCursorPos.mCol == 0 )
 | 
						|
		{
 | 
						|
			TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
			iter.PreviousChar();
 | 
						|
 | 
						|
			prevPos = iter.GetPosition();
 | 
						|
		}
 | 
						|
		else
 | 
						|
			prevPos = TPosition( mCursorPos.mRow, mCursorPos.mCol - 1 );
 | 
						|
 | 
						|
		DeleteRange( prevPos, mCursorPos );
 | 
						|
 | 
						|
		mCursorPos = prevPos;
 | 
						|
	}
 | 
						|
 | 
						|
	SetPostPos( mCursorPos );
 | 
						|
 | 
						|
	FinishBatch();
 | 
						|
 | 
						|
	NotifyAllViews();
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnDeleteLine()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	DeleteSelection();
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
 | 
						|
	iter.ToStartOfLine();
 | 
						|
 | 
						|
	TPosition from = iter.GetPosition();
 | 
						|
 | 
						|
	iter.ToEndOfLine();
 | 
						|
 | 
						|
	if ( iter.IsLastLine() == FALSE )
 | 
						|
 | 
						|
		iter.NextChar(); // delete eol-char also, if it's not the last line
 | 
						|
 | 
						|
	TPosition till = iter.GetPosition();
 | 
						|
 | 
						|
	DeleteRange( from, till );
 | 
						|
	SetPostPos( mCursorPos );
 | 
						|
 | 
						|
	FinishBatch();
 | 
						|
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnShiftSelectionIndent( bool left )
 | 
						|
{
 | 
						|
	if ( SelectionIsEmpty() ) return;
 | 
						|
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	for( size_t row = mSelectionStart.mRow; row != mSelectionEnd.mRow; ++row )
 | 
						|
	{
 | 
						|
		TTextIterator iter = CreateIterator( TPosition( row, 0 ) );
 | 
						|
 | 
						|
		if ( left )
 | 
						|
		{
 | 
						|
			int n = 0, pos = 0;
 | 
						|
 | 
						|
			while( !iter.IsEol() && !iter.IsEof() )
 | 
						|
			{
 | 
						|
				char ch = iter.GetChar();
 | 
						|
 | 
						|
				if ( pos == mTabSize ) break;
 | 
						|
 | 
						|
				if ( ch != ' ' && ch != '\t' ) break;
 | 
						|
 | 
						|
				++n;
 | 
						|
 | 
						|
				if ( ch == '\t' ) break;
 | 
						|
 | 
						|
				++pos;
 | 
						|
 | 
						|
				iter.NextChar();
 | 
						|
			}
 | 
						|
 | 
						|
			if ( n ) DeleteRange( TPosition( row,0 ), TPosition( row, n ) );
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			char txt = '\t';
 | 
						|
 | 
						|
			InsertText( TPosition( row, 0 ), &txt, sizeof(char) );
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	FinishBatch();
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnPaste()
 | 
						|
{
 | 
						|
	// FIXME:: "wxLogQueryInterface(..)" linking problems with MSDev4.0
 | 
						|
	
 | 
						|
#ifdef __HACK_MY_MSDEV40__
 | 
						|
 | 
						|
	bool alreadyOpen=wxClipboardOpen();
 | 
						|
	if (!alreadyOpen)
 | 
						|
	{
 | 
						|
		wxOpenClipboard();
 | 
						|
	}
 | 
						|
 | 
						|
	char* data = (char*)::wxGetClipboardData( wxDF_TEXT );
 | 
						|
 | 
						|
	wxCloseClipboard();
 | 
						|
 | 
						|
	if ( data == NULL ) return;
 | 
						|
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	if ( !SelectionIsEmpty() )
 | 
						|
	{
 | 
						|
		mCursorPos = GetStartOfSelection();
 | 
						|
		DeleteSelection();
 | 
						|
	}
 | 
						|
 | 
						|
	InsertText( mCursorPos, data, strlen( data ) );
 | 
						|
 | 
						|
	delete [] data;
 | 
						|
#else
 | 
						|
 | 
						|
	if ( !wxTheClipboard->Open() ) return;
 | 
						|
 | 
						|
	wxTextDataObject data;
 | 
						|
	if ( !wxTheClipboard->IsSupported(wxDF_TEXT) ) 
 | 
						|
	{
 | 
						|
		wxTheClipboard->Close();
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	wxTheClipboard->GetData(&data);
 | 
						|
 | 
						|
	string txt = data.GetText();
 | 
						|
 | 
						|
	wxTheClipboard->Close();
 | 
						|
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	DeleteSelection();
 | 
						|
 | 
						|
	InsertText( mCursorPos, txt.c_str(), txt.length() );
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
	mCursorPos = mCommands.back()->mRange.mTill;
 | 
						|
	SetPostPos( mCursorPos );
 | 
						|
 | 
						|
	FinishBatch();
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnCut()
 | 
						|
{
 | 
						|
	OnCopy();
 | 
						|
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	DeleteSelection();
 | 
						|
	SetPostPos( mCursorPos );
 | 
						|
 | 
						|
 | 
						|
	FinishBatch();
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnCopy()
 | 
						|
{
 | 
						|
	if ( !SelectionIsEmpty() )
 | 
						|
	{
 | 
						|
		size_t len  = 0;
 | 
						|
		char*  text = NULL;
 | 
						|
 | 
						|
#ifndef __HACK_MY_MSDEV40__
 | 
						|
 | 
						|
		if ( !wxTheClipboard->Open() ) return;
 | 
						|
 | 
						|
		GetTextFromRange( mSelectionStart, mSelectionEnd, &text, len );
 | 
						|
 | 
						|
		wxString s( text, len );
 | 
						|
 | 
						|
	    wxTheClipboard->AddData( new wxTextDataObject(s) );
 | 
						|
		wxTheClipboard->Close();
 | 
						|
 | 
						|
		FreeCharacters( text );
 | 
						|
#else
 | 
						|
		bool alreadyOpen=wxClipboardOpen();
 | 
						|
		if (!alreadyOpen)
 | 
						|
		{
 | 
						|
			wxOpenClipboard();
 | 
						|
			if (!wxEmptyClipboard()) 
 | 
						|
			{
 | 
						|
				wxCloseClipboard();
 | 
						|
				return;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		GetTextFromRange( mSelectionStart, mSelectionEnd, &text, len );
 | 
						|
 | 
						|
		wxString s( text, len );
 | 
						|
 | 
						|
		bool success = ::wxEmptyClipboard();
 | 
						|
 | 
						|
		success = wxSetClipboardData( wxDF_TEXT, (wxObject*)s.c_str(), 0,0 );
 | 
						|
 | 
						|
		FreeCharacters( text );
 | 
						|
 | 
						|
		wxCloseClipboard();
 | 
						|
 | 
						|
#endif
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::CanCopy()
 | 
						|
{
 | 
						|
	return !SelectionIsEmpty();
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::CanPaste()
 | 
						|
{
 | 
						|
	if ( mIsReadOnly ) return FALSE;
 | 
						|
 | 
						|
#ifndef __HACK_MY_MSDEV40__
 | 
						|
 | 
						|
	if ( !wxTheClipboard->Open() ) return FALSE;
 | 
						|
 | 
						|
	if ( !wxTheClipboard->IsSupported(wxDF_TEXT) )
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	wxTheClipboard->Close();
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
	bool success = ::wxClipboardOpen();
 | 
						|
 | 
						|
	bool alreadyOpen=wxClipboardOpen();
 | 
						|
	if (!alreadyOpen)
 | 
						|
	{
 | 
						|
		wxOpenClipboard();
 | 
						|
	}
 | 
						|
 | 
						|
	char* data = (char*)::wxGetClipboardData( wxDF_TEXT );
 | 
						|
 | 
						|
	wxCloseClipboard();
 | 
						|
 | 
						|
	if ( data != NULL && strlen(data) != 0 )
 | 
						|
	{
 | 
						|
		delete [] data;
 | 
						|
		return TRUE;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		delete [] data;
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::CanUndo()
 | 
						|
{
 | 
						|
	return !( mCommands.size() == 0 ||
 | 
						|
			  mCurCommand == 0 );
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::CanRedo()
 | 
						|
{
 | 
						|
	return mCurCommand != mCommands.size();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnUndo()
 | 
						|
{
 | 
						|
	if ( !CanUndo() ) return;
 | 
						|
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	ResetSelection();
 | 
						|
 | 
						|
	UndoImpl();
 | 
						|
 | 
						|
	FinishBatch();
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnRedo()
 | 
						|
{
 | 
						|
	if ( !CanRedo() ) return;
 | 
						|
 | 
						|
	PrepreForCommand();
 | 
						|
	StartBatch();
 | 
						|
 | 
						|
	ResetSelection();
 | 
						|
 | 
						|
	RedoImpl();
 | 
						|
 | 
						|
	FinishBatch();
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnMoveLeft()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	if ( mCursorPos.mCol == 0 )
 | 
						|
	{
 | 
						|
		if ( mCursorPos.mRow != 0 )
 | 
						|
		{
 | 
						|
			--mCursorPos.mRow;
 | 
						|
 | 
						|
			TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
 | 
						|
			iter.ToEndOfLine();
 | 
						|
 | 
						|
			mCursorPos.mCol = iter.GetPosition().mCol;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else
 | 
						|
		--mCursorPos.mCol;
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnMoveRight()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	++mCursorPos.mCol;
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnMoveUp()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	if ( mCursorPos.mRow != 0 )
 | 
						|
	
 | 
						|
		DoMoveCursor( -1,0 );
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnMoveDown()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	if ( mCursorPos.mRow + 1 < GetTotalRowCount() )
 | 
						|
 | 
						|
		DoMoveCursor( 1,0 );
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnWordRight()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
 | 
						|
	iter.NextWord();
 | 
						|
 | 
						|
	mCursorPos = iter.GetPosition();
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnWordLeft()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
 | 
						|
	iter.PreviousWord();
 | 
						|
 | 
						|
	mCursorPos = iter.GetPosition();
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnMoveToPosition( const TPosition& pos )
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	mCursorPos = pos;
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnEndOfLine()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
	iter.ToEndOfLine();
 | 
						|
 | 
						|
	mCursorPos = iter.GetPosition();
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnStartOfLine()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	int prevCol = mCursorPos.mCol;
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
	iter.ToStartOfLine();
 | 
						|
 | 
						|
	// bypass leading white-space at the begining of the line
 | 
						|
 | 
						|
	while( !iter.IsEol() )
 | 
						|
	{
 | 
						|
		char ch = iter.GetChar();
 | 
						|
 | 
						|
		if ( ch != ' ' && ch != '\t' ) break;
 | 
						|
 | 
						|
		++mCursorPos.mCol;
 | 
						|
 | 
						|
		iter.NextChar();
 | 
						|
	}
 | 
						|
 | 
						|
	mCursorPos = iter.GetPosition();
 | 
						|
 | 
						|
	if ( mCursorPos.mCol == prevCol )
 | 
						|
 | 
						|
		mCursorPos.mCol = 0;
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnPageUp()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	if ( mCursorPos.mRow < mRowsPerPage )
 | 
						|
 | 
						|
		mCursorPos.mRow = 0;
 | 
						|
	else
 | 
						|
		DoMoveCursor( -mRowsPerPage,0 );
 | 
						|
 | 
						|
	mpActiveView->ScrollView( -(int)mRowsPerPage, 0 );
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnPageDown()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	if ( mCursorPos.mRow + mRowsPerPage >= GetTotalRowCount() )
 | 
						|
	{
 | 
						|
		if ( GetTotalRowCount() != 0 )
 | 
						|
 | 
						|
			mCursorPos.mRow = GetTotalRowCount() - 1;
 | 
						|
		else
 | 
						|
			mCursorPos.mRow = 0;
 | 
						|
	}
 | 
						|
	else
 | 
						|
		DoMoveCursor( mRowsPerPage,0 );
 | 
						|
 | 
						|
	mpActiveView->ScrollView( mRowsPerPage, 0 );
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnSlideUp()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	
 | 
						|
	if ( mpActiveView->GetPagePos().mRow + mRowsPerPage - 1 == mCursorPos.mRow  )
 | 
						|
	{
 | 
						|
		if ( mCursorPos.mRow == 0 )
 | 
						|
 | 
						|
			return;
 | 
						|
 | 
						|
		DoMoveCursor( -1,0 );
 | 
						|
	}
 | 
						|
 | 
						|
	mpActiveView->ScrollView( -1, 0 );
 | 
						|
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnSlideDown()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	
 | 
						|
	if ( mCursorPos.mRow == mpActiveView->GetPagePos().mRow )
 | 
						|
	{
 | 
						|
		if ( mCursorPos.mRow + 1 >= GetTotalRowCount() )
 | 
						|
 | 
						|
			return;
 | 
						|
 | 
						|
		DoMoveCursor( 1,0 );
 | 
						|
	}
 | 
						|
 | 
						|
	mpActiveView->ScrollView( 1, 0 );
 | 
						|
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnStartOfText()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	mCursorPos.mRow = mCursorPos.mCol = 0;
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnEndOfText()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
	CheckSelection();
 | 
						|
 | 
						|
	mCursorPos.mRow = GetTotalRowCount() - 1;
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
 | 
						|
	iter.ToEndOfLine();
 | 
						|
 | 
						|
	mCursorPos = iter.GetPosition();
 | 
						|
 | 
						|
	TrackSelection();
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnSelectWord()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
 | 
						|
	TTextIterator iter1 = CreateIterator( mCursorPos );
 | 
						|
	iter1.GotoClosestPos();
 | 
						|
 | 
						|
	if ( mCursorPos == iter1.GetPosition() )
 | 
						|
	{
 | 
						|
		TTextIterator iter2 = iter1;
 | 
						|
 | 
						|
		// find the left-edge of the word
 | 
						|
 | 
						|
		bool wasSeparator = TTextIterator::IsSeparator( iter1.GetChar() );
 | 
						|
 | 
						|
		while( !iter1.IsEol() )
 | 
						|
		{
 | 
						|
			char ch = iter1.GetChar();
 | 
						|
 | 
						|
			if ( ch == '\t' || 
 | 
						|
				 ch == ' '  ||
 | 
						|
				 wasSeparator != TTextIterator::IsSeparator( iter1.GetChar() )
 | 
						|
			  ) 
 | 
						|
			{
 | 
						|
				iter1.NextChar();
 | 
						|
				break;
 | 
						|
			}
 | 
						|
 | 
						|
			iter1.PreviousChar();
 | 
						|
		}
 | 
						|
 | 
						|
		// find the left-edge of the word
 | 
						|
 | 
						|
		while( !iter2.IsEol() )
 | 
						|
		{
 | 
						|
			char ch = iter2.GetChar();
 | 
						|
 | 
						|
			if ( ch == '\t' || 
 | 
						|
				 ch == ' '  ||
 | 
						|
				 wasSeparator != TTextIterator::IsSeparator( iter2.GetChar() ) 
 | 
						|
			)
 | 
						|
				break;
 | 
						|
 | 
						|
			iter2.NextChar();
 | 
						|
		}
 | 
						|
 | 
						|
		if ( !(iter1.GetPosition() == iter2.GetPosition()) )
 | 
						|
		{
 | 
						|
			mSelectionStart = iter1.GetPosition();
 | 
						|
			mSelectionEnd   = iter2.GetPosition();
 | 
						|
			mCursorPos      = iter2.GetPosition();
 | 
						|
 | 
						|
			NotifyTextChanged( mSelectionStart.mRow, 1, CT_MODIFIED );
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnSelectAll()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
 | 
						|
	ResetSelection();
 | 
						|
 | 
						|
	mSelectionStart = TPosition(0,0);
 | 
						|
	mSelectionEnd   = TPosition( GetTotalRowCount(), 1024 ); // FOR NOW:: hack
 | 
						|
 | 
						|
	mCursorPos = mSelectionStart;
 | 
						|
 | 
						|
	NotifyTextChanged( mSelectionStart.mRow, mSelectionEnd.mRow, CT_MODIFIED );
 | 
						|
 | 
						|
	NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnToggleBookmark()
 | 
						|
{
 | 
						|
	size_t curRow = GetCursor().mRow;
 | 
						|
 | 
						|
	if ( GetPinAt( curRow, TBookmarkPin::GetPinTypeCode() ) != NULL )
 | 
						|
 | 
						|
		RemovePinAt( curRow, TBookmarkPin::GetPinTypeCode() );
 | 
						|
	else
 | 
						|
		AddPin( new TBookmarkPin( curRow ) );
 | 
						|
 | 
						|
	MergeChange( curRow, 1 );
 | 
						|
 | 
						|
	NotifyAllViews();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnNextBookmark()
 | 
						|
{
 | 
						|
	size_t pinNo = FindNextPinFrom( mCursorPos.mRow + 1 );
 | 
						|
 | 
						|
	while( pinNo != NPOS )
 | 
						|
	{
 | 
						|
		TPinBase& pin = *mPins[pinNo];
 | 
						|
 | 
						|
		if ( pin.mTypeCode == BOOKMARK_PIN_TC )
 | 
						|
		{
 | 
						|
			OnGotoLine( pin.mRow, 0 );
 | 
						|
			break;
 | 
						|
		}
 | 
						|
 | 
						|
		if ( pinNo == mPins.size() ) break;
 | 
						|
 | 
						|
		++pinNo;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnPreviousBookmark()
 | 
						|
{
 | 
						|
	if ( mCursorPos.mRow == 0 ) return;
 | 
						|
 | 
						|
	size_t pinNo = FindPreviousPinFrom( mCursorPos.mRow - 1 );
 | 
						|
 | 
						|
	while( pinNo != NPOS )
 | 
						|
	{
 | 
						|
		TPinBase& pin = *mPins[pinNo];
 | 
						|
 | 
						|
		if ( pin.mTypeCode == BOOKMARK_PIN_TC )
 | 
						|
		{
 | 
						|
			OnGotoLine( pin.mRow, 0 );
 | 
						|
			break;
 | 
						|
		}
 | 
						|
 | 
						|
		if ( pinNo == 0 ) break;
 | 
						|
 | 
						|
		--pinNo;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::OnFind()
 | 
						|
{
 | 
						|
	if ( !SelectionIsEmpty() )
 | 
						|
	{
 | 
						|
		if ( GetStartOfSelection().mRow == GetEndOfSelection().mRow )
 | 
						|
		{
 | 
						|
			char* buf = NULL; size_t len = 0;
 | 
						|
 | 
						|
			GetSelection( &buf, len );
 | 
						|
 | 
						|
			mLastFindExpr = string( buf, 0, len );
 | 
						|
 | 
						|
			delete [] buf;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	wxFindTextDialog dlg( GetActiveView(), mLastFindExpr );
 | 
						|
	//dlg.SetExpr( mLastFindExpr );
 | 
						|
 | 
						|
	if( dlg.ShowModal() == wxID_OK )
 | 
						|
	{
 | 
						|
		mLastFindExpr = dlg.GetExpr();
 | 
						|
 | 
						|
		GetActiveView()->SetFocus();
 | 
						|
 | 
						|
		return OnFindNext();
 | 
						|
	}
 | 
						|
 | 
						|
	GetActiveView()->SetFocus();
 | 
						|
 | 
						|
	return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::OnFindNext()
 | 
						|
{
 | 
						|
	PrepreForCommand();
 | 
						|
 | 
						|
	string& val = mLastFindExpr;
 | 
						|
	size_t  len = val.length();
 | 
						|
 | 
						|
	if ( len == 0 ) 
 | 
						|
	{
 | 
						|
		NotifyView();
 | 
						|
		wxMessageBox( "Secarch string not found!" );
 | 
						|
 | 
						|
		GetActiveView()->SetFocus();
 | 
						|
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	char ch1 = val[0];
 | 
						|
 | 
						|
	TTextIterator iter = CreateIterator( mCursorPos );
 | 
						|
 | 
						|
	while( !iter.IsEof() )
 | 
						|
	{
 | 
						|
		char ch = iter.GetChar();
 | 
						|
 | 
						|
		if ( ch == ch1 )
 | 
						|
		{
 | 
						|
			size_t startCol = iter.mPos.mCol;
 | 
						|
			iter.NextChar();
 | 
						|
			ch = iter.GetChar();
 | 
						|
 | 
						|
			size_t i = 1;
 | 
						|
			while( i < len && !iter.IsEof() && ch == val[i] )
 | 
						|
			{
 | 
						|
				++i;
 | 
						|
				iter.NextChar();
 | 
						|
				ch = iter.GetChar();
 | 
						|
			}
 | 
						|
 | 
						|
			if ( i == len )
 | 
						|
			{
 | 
						|
				if ( !SelectionIsEmpty() )
 | 
						|
 | 
						|
					ResetSelection();
 | 
						|
 | 
						|
				SetStartOfSelection( TPosition( iter.mPos.mRow, startCol ) );
 | 
						|
				SetEndOfSelection( iter.mPos );
 | 
						|
 | 
						|
				MergeChange( iter.mPos.mRow, 1 );
 | 
						|
 | 
						|
				mCursorPos = iter.mPos;
 | 
						|
 | 
						|
				OnGotoLine( iter.mPos.mRow, iter.mPos.mCol );
 | 
						|
				return TRUE;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else
 | 
						|
			iter.NextChar();
 | 
						|
	}
 | 
						|
 | 
						|
	NotifyView();
 | 
						|
	MergeChange( mCursorPos.mRow, 2 );
 | 
						|
	wxMessageBox( "Secarch string not found!" );
 | 
						|
 | 
						|
	GetActiveView()->SetFocus();
 | 
						|
 | 
						|
	return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::OnFindPrevious()
 | 
						|
{
 | 
						|
	// TBD::
 | 
						|
	return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnGotoLine( int line, int col )
 | 
						|
{
 | 
						|
	if ( mpActiveView == NULL ) return;
 | 
						|
 | 
						|
	TPosition pagePos = mpActiveView->GetPagePos();
 | 
						|
 | 
						|
	if ( line >= pagePos.mRow &&
 | 
						|
		 line <  pagePos.mRow + mRowsPerPage )
 | 
						|
	{
 | 
						|
		mCursorPos.mRow = (size_t)line;
 | 
						|
		mCursorPos.mCol = (size_t)col;
 | 
						|
 | 
						|
		if ( col == - 1)
 | 
						|
		{
 | 
						|
			mCursorPos.mCol = 0;
 | 
						|
			OnStartOfLine();
 | 
						|
		}
 | 
						|
		else
 | 
						|
			NotifyView();
 | 
						|
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	size_t third = mRowsPerPage / 3;
 | 
						|
	size_t newTop = 0;
 | 
						|
 | 
						|
	if ( line < third )
 | 
						|
 | 
						|
		newTop = 0;
 | 
						|
	else
 | 
						|
		newTop = line - third;
 | 
						|
 | 
						|
 | 
						|
	mpActiveView->ScrollView( (int)newTop - (int)pagePos.mRow, -(int)pagePos.mCol );
 | 
						|
 | 
						|
	mCursorPos.mRow = line;
 | 
						|
	mCursorPos.mCol = col;
 | 
						|
 | 
						|
	if ( col == - 1)
 | 
						|
	{
 | 
						|
		mCursorPos.mCol = 0;
 | 
						|
		OnStartOfLine();
 | 
						|
	}
 | 
						|
	else
 | 
						|
		NotifyView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::OnGotoLine()
 | 
						|
{
 | 
						|
	wxTextEntryDialog* dlg = 
 | 
						|
		new wxTextEntryDialog( mpActiveView, "Line number:", "Goto line", "" );
 | 
						|
 | 
						|
	int nTries = 3;
 | 
						|
 | 
						|
	while( dlg->ShowModal() == wxID_OK && nTries )
 | 
						|
	{
 | 
						|
		ResetSelection();
 | 
						|
 | 
						|
		int i = -1;
 | 
						|
		sscanf( dlg->GetValue(), "%d", &i );
 | 
						|
 | 
						|
		if ( i == -1  )
 | 
						|
		{
 | 
						|
			wxMessageBox( "Please enter a number" );
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		if ( i == 0 ) ++i;
 | 
						|
 | 
						|
		OnGotoLine( (size_t)(i-1), 0 );
 | 
						|
		break;
 | 
						|
 | 
						|
		--nTries;
 | 
						|
	}
 | 
						|
 | 
						|
	GetActiveView()->SetFocus();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool wxTextEditorModel::IsReadOnly()
 | 
						|
{
 | 
						|
	return mIsReadOnly;
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::IsModified()
 | 
						|
{
 | 
						|
	return mCurCommand != 0;
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::IsInsertMode()
 | 
						|
{
 | 
						|
	return mInsertMode;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::SetCheckpoint()
 | 
						|
{
 | 
						|
	mCheckPointDestroyed = FALSE;
 | 
						|
	mCheckPointCmdNo     = mCurCommand;
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorModel::CheckpointModified()
 | 
						|
{
 | 
						|
	if ( mCheckPointDestroyed ) return TRUE;
 | 
						|
 | 
						|
	return mCheckPointCmdNo != mCurCommand;
 | 
						|
}
 | 
						|
 | 
						|
TPosition wxTextEditorModel::GetStartOfSelection()
 | 
						|
{
 | 
						|
	ArrangePositions( mSelectionStart, mSelectionEnd );
 | 
						|
 | 
						|
	return mSelectionStart;
 | 
						|
}
 | 
						|
 | 
						|
TPosition wxTextEditorModel::GetEndOfSelection()
 | 
						|
{
 | 
						|
	ArrangePositions( mSelectionStart, mSelectionEnd );
 | 
						|
 | 
						|
	return mSelectionEnd;
 | 
						|
}
 | 
						|
 | 
						|
TPosition wxTextEditorModel::GetCursor()
 | 
						|
{
 | 
						|
	return mCursorPos;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::SetStartOfSelection( const TPosition& pos )
 | 
						|
{
 | 
						|
	mSelectionStart = pos;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::SetEndOfSelection( const TPosition& pos )
 | 
						|
{
 | 
						|
	mSelectionEnd = pos;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::SetCursor( const TPosition& pos )
 | 
						|
{
 | 
						|
	mCursorPos = pos;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::AddView( wxTextEditorView* pView )
 | 
						|
{
 | 
						|
	mViews.push_back( pView );
 | 
						|
	pView->SetModel( this );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::RemoveView( wxTextEditorView* pView )
 | 
						|
{
 | 
						|
	for( size_t i = 0; i != mViews.size(); ++i )
 | 
						|
 | 
						|
		if ( mViews[i] == pView )
 | 
						|
		{
 | 
						|
			mViews.erase( & mViews[i] );
 | 
						|
			return;
 | 
						|
		}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::SetActiveView( wxTextEditorView* pView )
 | 
						|
{
 | 
						|
	mpActiveView = pView;
 | 
						|
}
 | 
						|
 | 
						|
wxTextEditorView* wxTextEditorModel::GetActiveView()
 | 
						|
{
 | 
						|
	return mpActiveView;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::SetRowsPerPage( size_t n )
 | 
						|
{
 | 
						|
	mRowsPerPage = n;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::AddPin( TPinBase* pPin )
 | 
						|
{
 | 
						|
	// FIXME:: binary search should be used
 | 
						|
 | 
						|
	size_t beforePin = FindNextPinFrom( pPin->mRow );
 | 
						|
 | 
						|
	if ( beforePin != NPOS )
 | 
						|
	{
 | 
						|
		// pins in the same row are ordered in the
 | 
						|
		// descending order of their type-codes
 | 
						|
 | 
						|
		while( beforePin < mPins.size() &&
 | 
						|
			   mPins[beforePin]->mRow == pPin->mRow &&
 | 
						|
			   mPins[beforePin]->mTypeCode < pPin->mTypeCode )
 | 
						|
 | 
						|
			   ++beforePin;
 | 
						|
 | 
						|
		if ( beforePin < mPins.size() )
 | 
						|
			
 | 
						|
			mPins.insert( &mPins[beforePin], pPin );
 | 
						|
		else
 | 
						|
			mPins.push_back( pPin );
 | 
						|
	}
 | 
						|
	else
 | 
						|
		mPins.push_back( pPin );
 | 
						|
}
 | 
						|
 | 
						|
PinListT& wxTextEditorModel::GetPins()
 | 
						|
{
 | 
						|
	return mPins;
 | 
						|
}
 | 
						|
 | 
						|
size_t wxTextEditorModel::FindFirstPinInRange( size_t fromRow, size_t tillRow )
 | 
						|
{
 | 
						|
	// FIXME:: pefrom binary search instead
 | 
						|
 | 
						|
	for( size_t i = 0; i != mPins.size(); ++i )
 | 
						|
	{
 | 
						|
		TPinBase& pin = *mPins[i];
 | 
						|
 | 
						|
		if ( pin.mRow >= tillRow ) return NPOS;
 | 
						|
 | 
						|
		if ( pin.mRow >= fromRow )
 | 
						|
 | 
						|
			return i;
 | 
						|
	}
 | 
						|
 | 
						|
	return NPOS;
 | 
						|
}
 | 
						|
 | 
						|
size_t wxTextEditorModel::FindNextPinFrom( size_t fromRow )
 | 
						|
{
 | 
						|
	// FIXME:: pefrom binary search instead
 | 
						|
 | 
						|
	for( size_t i = 0; i != mPins.size(); ++i )
 | 
						|
	{
 | 
						|
		TPinBase& pin = *mPins[i];
 | 
						|
 | 
						|
		if ( pin.mRow >= fromRow )
 | 
						|
 | 
						|
			return i;
 | 
						|
	}
 | 
						|
 | 
						|
	return NPOS;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
size_t wxTextEditorModel::FindPreviousPinFrom( size_t fromRow )
 | 
						|
{
 | 
						|
	// FIXME:: pefrom binary search instead
 | 
						|
 | 
						|
	if ( mPins.size() == 0 ) return NPOS;
 | 
						|
 | 
						|
	size_t i = mPins.size() - 1;
 | 
						|
 | 
						|
	for(;;)
 | 
						|
	{
 | 
						|
		TPinBase& pin = *mPins[i];
 | 
						|
 | 
						|
		if ( pin.mRow <= fromRow )
 | 
						|
 | 
						|
			return i;
 | 
						|
 | 
						|
		if ( i == 0 ) break;
 | 
						|
 | 
						|
		--i;
 | 
						|
	}
 | 
						|
 | 
						|
	return NPOS;
 | 
						|
}
 | 
						|
 | 
						|
size_t wxTextEditorModel::GetPinNoAt( size_t row, int pinTypeCode )
 | 
						|
{
 | 
						|
	size_t curPin = FindNextPinFrom( row );
 | 
						|
 | 
						|
	while( curPin != NPOS )
 | 
						|
	{
 | 
						|
		TPinBase& pin = *mPins[curPin];
 | 
						|
 | 
						|
		if ( pin.mRow > row ) return NPOS;
 | 
						|
 | 
						|
		if ( pin.mTypeCode == pinTypeCode ) return curPin;
 | 
						|
 | 
						|
		++curPin;
 | 
						|
 | 
						|
		if ( curPin == mPins.size() ) return NPOS;
 | 
						|
	}
 | 
						|
 | 
						|
	return NPOS;
 | 
						|
}
 | 
						|
 | 
						|
TPinBase* wxTextEditorModel::GetPinAt( size_t row, int pinTypeCode )
 | 
						|
{
 | 
						|
	size_t pinNo = GetPinNoAt( row, pinTypeCode );
 | 
						|
 | 
						|
	return ( pinNo == NPOS ) ? NULL : mPins[pinNo];
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::RemovePinAt( size_t row, int pinTypeCode )
 | 
						|
{
 | 
						|
	size_t pinNo = GetPinNoAt( row, pinTypeCode );
 | 
						|
 | 
						|
	if ( pinNo != NPOS )
 | 
						|
 | 
						|
		mPins.erase( &mPins[pinNo] );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorModel::AddChangeListener( TTextChangeListenerBase* pListener )
 | 
						|
{
 | 
						|
	mChangeListeners.push_back( pListener );
 | 
						|
}
 | 
						|
 | 
						|
/***** Implementation for class wxTextEditorView *****/
 | 
						|
 | 
						|
BEGIN_EVENT_TABLE( wxTextEditorView, wxScrolledWindow )
 | 
						|
 | 
						|
	EVT_SIZE  ( wxTextEditorView::OnSize   )
 | 
						|
#if (( wxVERSION_NUMBER < 2100 ) || (( wxVERSION_NUMBER == 2100 ) && (wxBETA_NUMBER <= 4)))
 | 
						|
	EVT_SCROLL( wxTextEditorView::OnScroll )
 | 
						|
#else
 | 
						|
	EVT_SCROLLWIN( wxTextEditorView::OnScroll )
 | 
						|
#endif 
 | 
						|
	EVT_PAINT ( wxTextEditorView::OnPaint  )
 | 
						|
 | 
						|
	EVT_LEFT_DOWN  ( wxTextEditorView::OnLButtonDown )
 | 
						|
	EVT_LEFT_UP    ( wxTextEditorView::OnLButtonUp   )
 | 
						|
	EVT_MOTION     ( wxTextEditorView::OnMotion      )
 | 
						|
	EVT_LEFT_DCLICK( wxTextEditorView::OnDblClick    )
 | 
						|
 | 
						|
	EVT_SET_FOCUS  ( wxTextEditorView::OnSetFocus  )
 | 
						|
	EVT_KILL_FOCUS ( wxTextEditorView::OnKillFocus )
 | 
						|
 | 
						|
	EVT_CHAR( wxTextEditorView::OnChar )
 | 
						|
	EVT_KEY_DOWN( wxTextEditorView::OnKeyDown )
 | 
						|
 | 
						|
	EVT_ERASE_BACKGROUND( wxTextEditorView::OnEraseBackground )
 | 
						|
 | 
						|
 | 
						|
END_EVENT_TABLE()
 | 
						|
 | 
						|
TCursorTimer* wxTextEditorView::mpTimer = new TCursorTimer();
 | 
						|
 | 
						|
wxTextEditorView::wxTextEditorView( wxWindow* parent, 
 | 
						|
									wxWindowID id, 
 | 
						|
									wxTextEditorModel* pModel,
 | 
						|
									int wndStyle,
 | 
						|
									bool ownsModel )
 | 
						|
 | 
						|
	: wxScrolledWindow( parent, id, wxPoint(32768,32768), wxSize(0,0),
 | 
						|
						wxHSCROLL | wxVSCROLL | wndStyle
 | 
						|
	                  ),
 | 
						|
	  mPagePos( 0,0 ),
 | 
						|
	  mDragStarted( FALSE ),
 | 
						|
	  mpDraggedText( NULL ),
 | 
						|
	  mAdjustScrollPending( FALSE ),
 | 
						|
	  mLTMode( FALSE ),
 | 
						|
	  mMaxColumns( 500 ),
 | 
						|
 | 
						|
	  mScrollingOn( TRUE ),
 | 
						|
	  mCursorOn  ( TRUE ),
 | 
						|
	  mOwnsModel ( ownsModel ),
 | 
						|
 | 
						|
	  mLastRowsTotal( (size_t)(-1) )
 | 
						|
{
 | 
						|
	SetModel( pModel );
 | 
						|
 | 
						|
	SetTextDefaults();
 | 
						|
 | 
						|
	SetSourcePainter( new SourcePainter() );
 | 
						|
 | 
						|
	mCashedIter.mPos = TPosition( (size_t)(-1), 0 );
 | 
						|
 | 
						|
	// default
 | 
						|
	AddPinPainter( new TBookmarkPainter() );
 | 
						|
}
 | 
						|
 | 
						|
wxTextEditorView::~wxTextEditorView()
 | 
						|
{
 | 
						|
	if ( mpTimer->GetView() == this && 
 | 
						|
		 mCursorOn && !mLTMode )
 | 
						|
	{
 | 
						|
		mpTimer->SetView( NULL );
 | 
						|
		mpTimer->HideCursor( TRUE );
 | 
						|
	}
 | 
						|
 | 
						|
	if ( mOwnsModel && mpModel )
 | 
						|
 | 
						|
		delete mpModel;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetTextDefaults()
 | 
						|
{
 | 
						|
	mLeftMargin   = 22;
 | 
						|
	mRightMargin  = 0;
 | 
						|
	mTopMargin    = 0;
 | 
						|
	mBottomMargin = 0;
 | 
						|
 | 
						|
	mCharDim.x = -1; // not detected yet
 | 
						|
	mCharDim.y = -1;
 | 
						|
 | 
						|
	mNormalTextCol       = *wxBLACK;
 | 
						|
	mIndentifierTextCol  = *wxBLUE;
 | 
						|
	mReservedWordTextCol = *wxRED;
 | 
						|
	mCommentTextCol      = wxColour( 0,128,128 );
 | 
						|
 | 
						|
	mNormalBkCol    = wxColour(255,255,255);//*wxWHITE;//wxColour( 128,220,128 );
 | 
						|
	mSelectionFgCol = wxColour(255,255,255);//*wxWHITE;
 | 
						|
	mSelectionBkCol = wxColour( 0,0,128 );
 | 
						|
 | 
						|
	mNormalBkBrush   = wxBrush( mNormalBkCol,    wxSOLID );
 | 
						|
	mSelectedBkBrush = wxBrush( mSelectionBkCol, wxSOLID );
 | 
						|
 | 
						|
#if defined(__WXMSW__) || defined(__WINDOWS__)
 | 
						|
    mFont.SetFaceName("Fixedsys");
 | 
						|
    mFont.SetStyle(40);
 | 
						|
    mFont.SetWeight(40);
 | 
						|
    mFont.SetPointSize( 11);
 | 
						|
#else
 | 
						|
    //mFont.SetFamily( wxSWISS );
 | 
						|
	mFont = wxSystemSettings::GetSystemFont(wxSYS_OEM_FIXED_FONT);
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
#if defined(__WXMSW__) || defined(__WINDOWS__)
 | 
						|
    mFont.RealizeResource();
 | 
						|
#endif
 | 
						|
 | 
						|
	// reduce flicker un wxGtk
 | 
						|
	SetBackgroundColour( mNormalBkCol );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetColours( const wxColour& normalBkCol,
 | 
						|
								   const wxColour& selectedBkCol,
 | 
						|
								   const wxColour& selectedTextCol )
 | 
						|
{
 | 
						|
	mNormalBkCol    = normalBkCol;
 | 
						|
	mSelectionFgCol = selectedTextCol;
 | 
						|
	mSelectionBkCol = selectedBkCol;
 | 
						|
 | 
						|
	mNormalBkBrush   = wxBrush( mNormalBkCol,    wxSOLID );
 | 
						|
	mSelectedBkBrush = wxBrush( mSelectionBkCol, wxSOLID );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetHeighlightingColours( const wxColour& normalTextCol,
 | 
						|
											    const wxColour& identifierTextCol,
 | 
						|
											    const wxColour& reservedWordTextCol,
 | 
						|
											    const wxColour& commentTextCol )
 | 
						|
{
 | 
						|
	mNormalTextCol       = normalTextCol;
 | 
						|
	mIndentifierTextCol  = identifierTextCol;
 | 
						|
	mReservedWordTextCol = reservedWordTextCol;
 | 
						|
	mCommentTextCol      = commentTextCol;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetMargins( int top, int left, int bottom, int right )
 | 
						|
{
 | 
						|
	mLeftMargin   = left;
 | 
						|
	mRightMargin  = right;
 | 
						|
	mTopMargin    = top;
 | 
						|
	mBottomMargin = bottom;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::RecalcPagingInfo()
 | 
						|
{
 | 
						|
	bool firstRefresh = mCharDim.x == -1;
 | 
						|
 | 
						|
	if ( firstRefresh )
 | 
						|
 | 
						|
		ObtainFontProperties();
 | 
						|
 | 
						|
	int w = 0, h = 0;
 | 
						|
	GetClientSize( &w, &h );
 | 
						|
 | 
						|
	w -= mLeftMargin + mRightMargin;
 | 
						|
	h -= mTopMargin  + mBottomMargin;
 | 
						|
 | 
						|
	mColsPerPage = ( ( w / mCharDim.x ) +
 | 
						|
				   ( ( w % mCharDim.x ) ? 0 : 0 ) );
 | 
						|
 | 
						|
 | 
						|
	mRowsPerPage = ( ( h / mCharDim.y ) +
 | 
						|
				   ( ( h % mCharDim.y ) ? 0 : 0 ) );
 | 
						|
 | 
						|
	if ( mpModel->GetActiveView() == this )
 | 
						|
 | 
						|
		mpModel->SetRowsPerPage( mRowsPerPage );
 | 
						|
 | 
						|
	if ( firstRefresh ) 
 | 
						|
	{
 | 
						|
		// scrolling should not happen at DC-level
 | 
						|
		EnableScrolling( FALSE, FALSE );
 | 
						|
 | 
						|
		if ( mScrollingOn )
 | 
						|
 | 
						|
			SetScrollbars( mCharDim.x, mCharDim.y,
 | 
						|
						   mMaxColumns,
 | 
						|
						   mpModel->GetTotalRowCount(),
 | 
						|
						   mPagePos.mCol,
 | 
						|
						   mPagePos.mRow,
 | 
						|
						   TRUE
 | 
						|
						 );
 | 
						|
	}
 | 
						|
 | 
						|
	PositionCursor();
 | 
						|
}
 | 
						|
 | 
						|
#if (( wxVERSION_NUMBER < 2100 ) || (( wxVERSION_NUMBER == 2100 ) && (wxBETA_NUMBER <= 4)))
 | 
						|
 // this changed in ver 2.1
 | 
						|
void wxTextEditorView::OnScroll( wxScrollEvent& event )
 | 
						|
#else
 | 
						|
void wxTextEditorView::OnScroll( wxScrollWinEvent& event )
 | 
						|
#endif
 | 
						|
{
 | 
						|
	if ( !mScrollingOn ) return;
 | 
						|
 | 
						|
	// overriden implementation of wxScrolledWindow::OnScroll,
 | 
						|
	// to reduce flicker on wxGtk, by using wxClientDC 
 | 
						|
	// instead of Refresh()
 | 
						|
 | 
						|
	int orient = event.GetOrientation();
 | 
						|
 | 
						|
	int nScrollInc = CalcScrollInc(event);
 | 
						|
	if (nScrollInc == 0) return;
 | 
						|
 | 
						|
	if (orient == wxHORIZONTAL)
 | 
						|
	{
 | 
						|
		int newPos = m_xScrollPosition + nScrollInc;
 | 
						|
		SetScrollPos(wxHORIZONTAL, newPos, TRUE );
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		int newPos = m_yScrollPosition + nScrollInc;
 | 
						|
		SetScrollPos(wxVERTICAL, newPos, TRUE );
 | 
						|
	}
 | 
						|
 | 
						|
	if (orient == wxHORIZONTAL)
 | 
						|
	{
 | 
						|
		m_xScrollPosition += nScrollInc;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		m_yScrollPosition += nScrollInc;
 | 
						|
	}
 | 
						|
 | 
						|
	int x,y;
 | 
						|
	ViewStart( &x, &y );
 | 
						|
 | 
						|
	mPagePos.mRow = y;
 | 
						|
	mPagePos.mCol = x;
 | 
						|
 | 
						|
	PositionCursor();
 | 
						|
 | 
						|
	if ( mAdjustScrollPending )
 | 
						|
	{
 | 
						|
		mLastRowsTotal = mpModel->GetTotalRowCount();
 | 
						|
		SetScrollbars( mCharDim.x, mCharDim.y,
 | 
						|
					   mMaxColumns,   // FOR NOW:: maximal line-length not calculated
 | 
						|
					   mLastRowsTotal,
 | 
						|
					   mPagePos.mCol,
 | 
						|
					   mPagePos.mRow,
 | 
						|
					   TRUE
 | 
						|
					 );
 | 
						|
 | 
						|
		mLastViewStart = mPagePos;
 | 
						|
 | 
						|
		mAdjustScrollPending = FALSE;
 | 
						|
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	wxClientDC dc( this );
 | 
						|
 | 
						|
	mFullRefreshPending = TRUE;
 | 
						|
 | 
						|
	PaintRows( mPagePos.mRow, mPagePos.mRow + mRowsPerPage, dc );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnPaint( wxPaintEvent& event )
 | 
						|
{
 | 
						|
	//wxScrolledWindow::OnPaint( event );
 | 
						|
	if ( mCharDim.x == -1 ) ObtainFontProperties();
 | 
						|
 | 
						|
	wxPaintDC dc( this );
 | 
						|
 | 
						|
	mFullRefreshPending = TRUE;
 | 
						|
 | 
						|
	PaintRows( mPagePos.mRow, mPagePos.mRow + mRowsPerPage, dc );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnSize( wxSizeEvent& event )
 | 
						|
{
 | 
						|
	RecalcPagingInfo();
 | 
						|
 | 
						|
	SyncScrollbars();
 | 
						|
 | 
						|
	event.Skip();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnEraseBackground( wxEraseEvent& event )
 | 
						|
{
 | 
						|
#if 0
 | 
						|
	int w = 0, h = 0;
 | 
						|
 | 
						|
	GetClientSize( &w, &h );
 | 
						|
	
 | 
						|
	wxPaintDC dc( this );
 | 
						|
 | 
						|
	dc.SetPen( *wxTRANSPARENT_PEN );
 | 
						|
	dc.SetBrush( *wxWHITE_BRUSH );
 | 
						|
	dc.DrawRectangle( 0,0, w,h );
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnLButtonDown( wxMouseEvent& event )
 | 
						|
{
 | 
						|
	if ( mDragStarted ) return;
 | 
						|
 | 
						|
	mDragStarted = TRUE;
 | 
						|
 | 
						|
	TPosition textPos;
 | 
						|
	PixelsToTextPos( event.m_x, event.m_y, textPos );
 | 
						|
 | 
						|
	mpModel->SetSelectionEditMode( FALSE );
 | 
						|
 | 
						|
	mpModel->OnMoveToPosition( textPos );
 | 
						|
 | 
						|
	mpModel->SetSelectionEditMode( TRUE );
 | 
						|
 | 
						|
	SetFocus();
 | 
						|
 | 
						|
	CaptureMouse();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnLButtonUp( wxMouseEvent& event )
 | 
						|
{
 | 
						|
	if ( mDragStarted )
 | 
						|
	{
 | 
						|
		OnMotion( event ); // simulate last motion event
 | 
						|
 | 
						|
		mpModel->SetSelectionEditMode( FALSE );
 | 
						|
 | 
						|
		ReleaseMouse();
 | 
						|
		mDragStarted = FALSE;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnMotion( wxMouseEvent& event )
 | 
						|
{
 | 
						|
	if ( mDragStarted )
 | 
						|
	{
 | 
						|
		TPosition textPos;
 | 
						|
 | 
						|
		if ( event.m_y < 0 && mpModel->GetCursor().mRow == 0 )
 | 
						|
		
 | 
						|
			event.m_y = 0;
 | 
						|
 | 
						|
		PixelsToTextPos( event.m_x, event.m_y, textPos );
 | 
						|
 | 
						|
		mpModel->OnMoveToPosition( textPos );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnDblClick( wxMouseEvent& event )
 | 
						|
{
 | 
						|
	event.Skip();
 | 
						|
	mpModel->OnSelectWord();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnSetFocus( wxFocusEvent& event )
 | 
						|
{
 | 
						|
	if ( !mLTMode && mCursorOn )
 | 
						|
	{
 | 
						|
		mpTimer->SetView( this );
 | 
						|
		mpTimer->ShowCursor( TRUE );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnKillFocus( wxFocusEvent& event )
 | 
						|
{
 | 
						|
	if ( !mLTMode && mCursorOn )
 | 
						|
	{
 | 
						|
		mpTimer->HideCursor( TRUE );
 | 
						|
		mpTimer->SetView( NULL );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::HoldCursor( bool hold )
 | 
						|
{
 | 
						|
	if ( mLTMode || !mCursorOn ) return;
 | 
						|
 | 
						|
	if ( !hold )
 | 
						|
	{
 | 
						|
		if ( wxWindow::FindFocus() != this )
 | 
						|
		{	
 | 
						|
			mpTimer->HideCursor();
 | 
						|
			mpTimer->SetView( NULL );
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		mpTimer->SetView( this );
 | 
						|
		mpTimer->ShowCursor();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnKeyDown( wxKeyEvent& event )
 | 
						|
{
 | 
						|
	// FOR NOW:: hard-coded key-bindings
 | 
						|
 | 
						|
	mpModel->SetSelectionEditMode( event.ShiftDown() );
 | 
						|
 | 
						|
	if ( event.ControlDown() )
 | 
						|
	{
 | 
						|
		if ( event.m_keyCode == WXK_LEFT ) 
 | 
						|
		
 | 
						|
			mpModel->OnWordLeft();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_RIGHT ) 
 | 
						|
		
 | 
						|
			mpModel->OnWordRight();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_UP ) 
 | 
						|
		
 | 
						|
			mpModel->OnSlideUp();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_DOWN ) 
 | 
						|
		
 | 
						|
			mpModel->OnSlideDown();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_HOME ) 
 | 
						|
		
 | 
						|
			mpModel->OnStartOfText();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_END ) 
 | 
						|
		
 | 
						|
			mpModel->OnEndOfText();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_INSERT )
 | 
						|
 | 
						|
			mpModel->OnCopy();
 | 
						|
		else
 | 
						|
			event.Skip();
 | 
						|
 | 
						|
		/*
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_NEXT ) 
 | 
						|
		
 | 
						|
			mpModel->();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_PRIOR ) 
 | 
						|
		
 | 
						|
			mpModel->();
 | 
						|
		*/
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		if ( event.m_keyCode == WXK_LEFT ) 
 | 
						|
		
 | 
						|
			mpModel->OnMoveLeft();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_RIGHT ) 
 | 
						|
		
 | 
						|
			mpModel->OnMoveRight();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_UP ) 
 | 
						|
		
 | 
						|
			mpModel->OnMoveUp();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_DOWN ) 
 | 
						|
		
 | 
						|
			mpModel->OnMoveDown();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_HOME ) 
 | 
						|
		
 | 
						|
			mpModel->OnStartOfLine();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_END ) 
 | 
						|
		
 | 
						|
			mpModel->OnEndOfLine();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_NEXT ) 
 | 
						|
		
 | 
						|
			mpModel->OnPageDown();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_PRIOR ) 
 | 
						|
		
 | 
						|
			mpModel->OnPageUp();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == WXK_DELETE )
 | 
						|
 | 
						|
			mpModel->OnDelete();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode ==  WXK_INSERT && event.ShiftDown() )
 | 
						|
		
 | 
						|
			mpModel->OnPaste();
 | 
						|
		else
 | 
						|
			event.Skip();
 | 
						|
	}	
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnChar( wxKeyEvent& event )
 | 
						|
{
 | 
						|
	if ( event.ControlDown() )
 | 
						|
	{
 | 
						|
		if ( event.m_keyCode == 'y' )
 | 
						|
 | 
						|
			mpModel->OnDeleteLine();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == 'v' )
 | 
						|
 | 
						|
			mpModel->OnPaste();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == 'c' )
 | 
						|
 | 
						|
			mpModel->OnCopy();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == 'z' )
 | 
						|
 | 
						|
			mpModel->OnUndo();
 | 
						|
		else
 | 
						|
		if ( event.m_keyCode == 'a' )
 | 
						|
 | 
						|
			mpModel->OnRedo();
 | 
						|
		else
 | 
						|
			event.Skip();
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( event.AltDown() )
 | 
						|
	{
 | 
						|
		if ( event.m_keyCode == WXK_BACK ) 
 | 
						|
 | 
						|
			mpModel->OnUndo();
 | 
						|
		else
 | 
						|
			event.Skip();
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( event.m_keyCode ==  WXK_BACK )
 | 
						|
	
 | 
						|
		mpModel->OnDeleteBack();
 | 
						|
	else
 | 
						|
	if ( event.m_keyCode == WXK_TAB && event.ShiftDown() )
 | 
						|
 | 
						|
		mpModel->OnShiftSelectionIndent( TRUE );
 | 
						|
	else
 | 
						|
	{
 | 
						|
		if ( !mpModel->SelectionIsEmpty() && event.m_keyCode == WXK_TAB )
 | 
						|
 | 
						|
			mpModel->OnShiftSelectionIndent( FALSE );
 | 
						|
		else
 | 
						|
			mpModel->OnInsertChar( event.m_keyCode );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetModel( wxTextEditorModel* pModel )
 | 
						|
{
 | 
						|
	mpModel = pModel;
 | 
						|
	mSelectionStart = pModel->GetStartOfSelection();
 | 
						|
	mSelectionEnd   = pModel->GetEndOfSelection();
 | 
						|
	mCursorPos      = pModel->GetCursor();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetSourcePainter( SourcePainter* pPainter )
 | 
						|
{
 | 
						|
	mpPainter = pPainter;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::AddPinPainter( TPinPainterBase* pPainter )
 | 
						|
{
 | 
						|
	mPinPainters.push_back( pPainter );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetDefaultFont( const wxFont& font )
 | 
						|
{
 | 
						|
	mFont = font;
 | 
						|
 | 
						|
#if defined(__WXMSW__) || defined(__WINDOWS__)
 | 
						|
    mFont.RealizeResource();
 | 
						|
#endif
 | 
						|
 | 
						|
	mCharDim.x = -1;
 | 
						|
	mCharDim.y = -1;
 | 
						|
 | 
						|
	RecalcPagingInfo();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetRowsPerPage( size_t n )
 | 
						|
{
 | 
						|
	mpModel->SetRowsPerPage( n );
 | 
						|
 | 
						|
	mRowsPerPage = n;
 | 
						|
	SyncScrollbars();
 | 
						|
	PositionCursor();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetMaxColumns( size_t n )
 | 
						|
{
 | 
						|
	mMaxColumns = n;
 | 
						|
 | 
						|
	SyncScrollbars();
 | 
						|
	PositionCursor();
 | 
						|
}
 | 
						|
 | 
						|
wxFont& wxTextEditorView::GetDefaultFont()
 | 
						|
{
 | 
						|
	return mFont;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SetLineTrackingMode( bool on, const wxColour& col )
 | 
						|
{
 | 
						|
	mLTColour = col;
 | 
						|
	mLTMode   = on;
 | 
						|
 | 
						|
	if ( mpTimer->GetView() == this )
 | 
						|
 | 
						|
		mpTimer->HideCursor();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::EnableCursor( bool enable )
 | 
						|
{
 | 
						|
	mCursorOn = enable;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::EnableScrollbars( bool enable )
 | 
						|
{
 | 
						|
	mScrollingOn = enable;
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorView::IsActiveView()
 | 
						|
{
 | 
						|
	return this == mpModel->GetActiveView();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::PositionCursor()
 | 
						|
{
 | 
						|
	if ( !IsActiveView() || 
 | 
						|
		 mLTMode || !mCursorOn ) return;
 | 
						|
 | 
						|
	mpTimer->HideCursor();
 | 
						|
 | 
						|
	TextPosToScreenPos( mpModel->GetCursor(), mCursorScrPos );
 | 
						|
 | 
						|
	mpTimer->ShowCursor();
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::PixelsToScrPos( int x, int y, int& scrRow, int& scrCol )
 | 
						|
{
 | 
						|
	x -= mLeftMargin;
 | 
						|
	y -= mTopMargin;
 | 
						|
 | 
						|
	//if ( x < 0 ) x = 0; // FOR NOW:: horizontal auto-scroll disabled
 | 
						|
 | 
						|
	scrCol = x / mCharDim.x;
 | 
						|
	scrRow = y / mCharDim.y;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::PixelsToTextPos( int x, int y, TPosition& textPos )
 | 
						|
{
 | 
						|
	int scrRow = 0, scrCol = 0;
 | 
						|
	PixelsToScrPos( x, y, scrRow, scrCol );
 | 
						|
 | 
						|
	if ( scrRow + (int)mPagePos.mRow < 0 )
 | 
						|
 | 
						|
		scrRow = -(int)mPagePos.mRow;
 | 
						|
 | 
						|
	if ( scrCol + (int)mPagePos.mCol < 0 )
 | 
						|
 | 
						|
		scrCol = -(int)mPagePos.mCol;
 | 
						|
 | 
						|
	ScreenPosToTextPos( TPosition( scrRow, scrCol ), textPos );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::ScreenPosToPixels( const TPosition& scrPos, int& x, int& y )
 | 
						|
{
 | 
						|
	x = mLeftMargin + scrPos.mCol * mCharDim.x;
 | 
						|
	y = mTopMargin  + scrPos.mRow * mCharDim.y;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::TextPosToScreenPos( const TPosition& txtPos, TPosition& scrPos )
 | 
						|
{
 | 
						|
	TTextIterator iter;
 | 
						|
 | 
						|
	if ( txtPos.mRow != mCashedIter.mPos.mRow )
 | 
						|
	{
 | 
						|
		iter = mpModel->CreateIterator( txtPos );
 | 
						|
		mCashedIter = iter;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		iter = mCashedIter;
 | 
						|
		iter.mPos.mCol = txtPos.mCol;
 | 
						|
	}
 | 
						|
 | 
						|
	iter.ToStartOfLine();
 | 
						|
 | 
						|
	size_t scrCol = 0;
 | 
						|
	size_t txtCol = 0;
 | 
						|
 | 
						|
	while( !iter.IsEol() && txtCol < txtPos.mCol )
 | 
						|
	{
 | 
						|
		if ( iter.GetChar() == '\t' )
 | 
						|
		{
 | 
						|
			size_t spacing = ( (scrCol / mpModel->mTabSize) + 1 ) * mpModel->mTabSize - scrCol;
 | 
						|
 | 
						|
			scrCol += spacing;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			++scrCol;
 | 
						|
 | 
						|
		++txtCol;
 | 
						|
		iter.NextChar();
 | 
						|
	}
 | 
						|
 | 
						|
	TPosition actualPos = iter.GetPosition();
 | 
						|
 | 
						|
	scrCol += txtPos.mCol - txtCol;
 | 
						|
 | 
						|
	scrPos.mRow = actualPos.mRow - mPagePos.mRow;
 | 
						|
	scrPos.mCol = scrCol - mPagePos.mCol;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::ScreenPosToTextPos( const TPosition& scrPos, TPosition& txtPos )
 | 
						|
{
 | 
						|
	TPosition absScrPos( scrPos.mRow + mPagePos.mRow, scrPos.mCol + mPagePos.mCol );
 | 
						|
 | 
						|
	TTextIterator iter = mpModel->CreateIterator( TPosition( absScrPos.mRow, 0 ) );
 | 
						|
 | 
						|
	size_t scrCol = 0;
 | 
						|
	size_t txtCol = 0;
 | 
						|
 | 
						|
	// iterate over all possible on-screen positions, and find one which matches "absScrPos"
 | 
						|
 | 
						|
	while( !iter.IsEol() && scrCol < absScrPos.mCol )
 | 
						|
	{
 | 
						|
		if ( iter.GetChar() == '\t' )
 | 
						|
		{
 | 
						|
			size_t spacing = ( (scrCol / mpModel->mTabSize) + 1 ) * mpModel->mTabSize - scrCol;
 | 
						|
 | 
						|
			scrCol += spacing;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			++scrCol;
 | 
						|
 | 
						|
		++txtCol;
 | 
						|
		iter.NextChar();
 | 
						|
	}
 | 
						|
 | 
						|
	TPosition actualPos = iter.GetPosition();
 | 
						|
 | 
						|
	if ( scrCol == absScrPos.mCol )
 | 
						|
	{
 | 
						|
		txtPos = actualPos;
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( scrCol < absScrPos.mCol )
 | 
						|
	{
 | 
						|
		// the absScrPos points past the eol
 | 
						|
 | 
						|
		txtPos = actualPos;
 | 
						|
		txtPos.mCol += absScrPos.mCol - scrCol;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( scrCol > absScrPos.mCol )
 | 
						|
	{
 | 
						|
		// there should have been a '\t' char, which made us jump too far forward
 | 
						|
 | 
						|
		txtPos = actualPos;
 | 
						|
		--txtPos.mCol;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
bool wxTextEditorView::IsClipboardCmd( wxKeyEvent& key )
 | 
						|
{
 | 
						|
	if ( key.ControlDown() && key.m_keyCode == WXK_CONTROL )
 | 
						|
 | 
						|
		return TRUE;
 | 
						|
 | 
						|
	if ( key.ShiftDown() && key.m_keyCode == WXK_SHIFT )
 | 
						|
 | 
						|
		return TRUE;
 | 
						|
 | 
						|
	if ( key.ControlDown() )
 | 
						|
	{
 | 
						|
		return ( key.m_keyCode == 'C' ||
 | 
						|
				 key.m_keyCode == 'c' ||
 | 
						|
				 key.m_keyCode == WXK_INSERT );
 | 
						|
	}
 | 
						|
 | 
						|
	return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::ObtainFontProperties()
 | 
						|
{
 | 
						|
	wxClientDC dc(this);
 | 
						|
	dc.SetFont( mFont );
 | 
						|
 | 
						|
	long w,h;
 | 
						|
 | 
						|
	dc.GetTextExtent( "X", &w, &h );
 | 
						|
 | 
						|
	mCharDim.x = w;
 | 
						|
	mCharDim.y = h;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SyncViewPortPosition()
 | 
						|
{
 | 
						|
 | 
						|
	TPosition pos = mpModel->GetCursor();
 | 
						|
 | 
						|
	TextPosToScreenPos( pos, pos );
 | 
						|
	pos.mRow += mPagePos.mRow;
 | 
						|
	pos.mCol += mPagePos.mCol;
 | 
						|
 | 
						|
	if ( pos.mRow < mPagePos.mRow )
 | 
						|
	{
 | 
						|
		mPagePos.mRow = pos.mRow;
 | 
						|
		mFullRefreshPending = TRUE;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( pos.mRow >= mPagePos.mRow + mRowsPerPage && mRowsPerPage != 0 )
 | 
						|
	{
 | 
						|
		mPagePos.mRow = pos.mRow - mRowsPerPage + 1;
 | 
						|
		mFullRefreshPending = TRUE;
 | 
						|
	}
 | 
						|
 | 
						|
	if ( pos.mCol < mPagePos.mCol )
 | 
						|
	{
 | 
						|
		mPagePos.mCol = pos.mCol;
 | 
						|
		mFullRefreshPending = TRUE;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( pos.mCol >= mPagePos.mCol + mColsPerPage )
 | 
						|
	{
 | 
						|
		mPagePos.mCol = pos.mCol - mColsPerPage + 1;
 | 
						|
		mFullRefreshPending = TRUE;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::SyncScrollbars()
 | 
						|
{
 | 
						|
	if ( !mScrollingOn ) return;
 | 
						|
 | 
						|
	size_t nRows = mpModel->GetTotalRowCount();
 | 
						|
 | 
						|
#if !defined(__WINDOWS__)
 | 
						|
 | 
						|
	if ( mLastViewStart == mPagePos )
 | 
						|
	{
 | 
						|
		if ( mLastRowsTotal != nRows )
 | 
						|
 | 
						|
			mAdjustScrollPending = TRUE;
 | 
						|
 | 
						|
		 return;
 | 
						|
	}
 | 
						|
#else
 | 
						|
	if ( mLastViewStart == mPagePos &&
 | 
						|
		 mLastRowsTotal == nRows )
 | 
						|
 | 
						|
		 return;
 | 
						|
#endif
 | 
						|
	SetScrollbars( mCharDim.x, mCharDim.y,
 | 
						|
				   mMaxColumns,
 | 
						|
				   nRows,
 | 
						|
				   mPagePos.mCol,
 | 
						|
				   mPagePos.mRow,
 | 
						|
				   TRUE
 | 
						|
				 );
 | 
						|
 | 
						|
	mLastViewStart = mPagePos;
 | 
						|
	mLastRowsTotal = nRows;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::ScrollView( int rows, int cols )
 | 
						|
{
 | 
						|
	int pageRow = (int)mPagePos.mRow; 
 | 
						|
	int pageCol = (int)mPagePos.mCol;
 | 
						|
 | 
						|
	if ( pageRow + rows < 0 ) 
 | 
						|
		pageRow = 0;
 | 
						|
	else
 | 
						|
	if ( pageRow + rows > (int)mpModel->GetTotalRowCount() )
 | 
						|
 | 
						|
		pageRow = mpModel->GetTotalRowCount();
 | 
						|
	else
 | 
						|
		pageRow = pageRow + rows;
 | 
						|
 | 
						|
	mPagePos.mRow = (size_t)pageRow;
 | 
						|
 | 
						|
	if ( pageCol + cols < 0 )
 | 
						|
 | 
						|
		pageCol = 0;
 | 
						|
	else
 | 
						|
		pageCol = pageCol + cols;
 | 
						|
 | 
						|
	mPagePos.mCol = pageCol;
 | 
						|
 | 
						|
	mFullRefreshPending = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::OnModelChanged()
 | 
						|
{
 | 
						|
	// invalidate pre-cached iterator
 | 
						|
	mCashedIter.mPos = TPosition( (size_t)(-1), 0 );
 | 
						|
 | 
						|
	SyncViewPortPosition();
 | 
						|
 | 
						|
	if ( mLTMode ) mFullRefreshPending = TRUE;
 | 
						|
 | 
						|
	if ( mpModel->mTextChanged && !mFullRefreshPending )
 | 
						|
	{
 | 
						|
		wxClientDC dc( this );
 | 
						|
		PaintRows( mpModel->mChangedFromRow, mpModel->mChangedTillRow, dc );
 | 
						|
	}
 | 
						|
	else
 | 
						|
	if ( mFullRefreshPending )
 | 
						|
	{
 | 
						|
		wxClientDC dc( this );
 | 
						|
		PaintRows( mPagePos.mRow, mPagePos.mRow + mRowsPerPage, dc );
 | 
						|
	}
 | 
						|
 | 
						|
	if ( IsActiveView() )
 | 
						|
	{	
 | 
						|
		PositionCursor();
 | 
						|
		SyncScrollbars();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::Activate()
 | 
						|
{
 | 
						|
	mpModel->SetStartOfSelection( mSelectionStart );
 | 
						|
	mpModel->SetEndOfSelection( mSelectionEnd );
 | 
						|
	mpModel->SetCursor( mCursorPos );
 | 
						|
 | 
						|
	mpModel->SetRowsPerPage( mRowsPerPage );
 | 
						|
 | 
						|
	if ( !mLTMode && mCursorOn )
 | 
						|
	{
 | 
						|
		mpTimer->SetView( this );
 | 
						|
		mpTimer->ShowCursor();
 | 
						|
	}
 | 
						|
 | 
						|
	mpModel->SetActiveView( this );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::Deactivate()
 | 
						|
{
 | 
						|
	mSelectionStart = mpModel->GetStartOfSelection();
 | 
						|
	mSelectionEnd   = mpModel->GetEndOfSelection();
 | 
						|
	mCursorPos      = mpModel->GetCursor();
 | 
						|
 | 
						|
	if ( mpTimer->GetView() == this && 
 | 
						|
		 !mLTMode && mCursorOn )
 | 
						|
		
 | 
						|
		mpTimer->HideCursor( TRUE );
 | 
						|
}
 | 
						|
 | 
						|
/*** protected methods ***/
 | 
						|
 | 
						|
char*  wxTextEditorView::mpLineBuffer    = NULL;
 | 
						|
size_t wxTextEditorView::mpLineBufferLen = 0;
 | 
						|
 | 
						|
char* wxTextEditorView::GetLineBuffer( size_t len )
 | 
						|
{
 | 
						|
	if ( mpLineBuffer == NULL || mpLineBufferLen < len )
 | 
						|
	{
 | 
						|
		if ( !mpLineBuffer ) mpModel->FreeCharacters( mpLineBuffer );
 | 
						|
 | 
						|
		mpLineBuffer = mpModel->AllocCharacters( len );
 | 
						|
 | 
						|
		mpLineBufferLen = len;
 | 
						|
	}
 | 
						|
 | 
						|
	return mpLineBuffer;
 | 
						|
}
 | 
						|
 | 
						|
TPinPainterBase* wxTextEditorView::FindPainterForPin( TPinBase& pin )
 | 
						|
{
 | 
						|
	int pinTc = pin.mTypeCode;
 | 
						|
 | 
						|
	for( size_t i = 0; i != mPinPainters.size(); ++i )
 | 
						|
 | 
						|
		if ( mPinPainters[i]->mPinTypeCode == pinTc )
 | 
						|
 | 
						|
			return mPinPainters[i];
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::PaintDecorations( size_t fromRow, 
 | 
						|
										 size_t tillRow, 
 | 
						|
										 wxDC& dc, TTextIterator& iter )
 | 
						|
{
 | 
						|
	int dcY = ( fromRow - mPagePos.mRow ) * mCharDim.y + mTopMargin;
 | 
						|
		
 | 
						|
	size_t curPin = mpModel->FindFirstPinInRange( fromRow, tillRow );
 | 
						|
 | 
						|
	PinListT& pins = mpModel->GetPins();
 | 
						|
	TPinPainterBase* pPainter = NULL;
 | 
						|
 | 
						|
	size_t prevRow = fromRow;
 | 
						|
	int    prevY   = dcY;
 | 
						|
 | 
						|
	wxPoint pos;
 | 
						|
	wxSize  dim( mLeftMargin, mCharDim.y );
 | 
						|
 | 
						|
	while( curPin != NPOS )
 | 
						|
	{
 | 
						|
		TPinBase& pin = *pins[curPin];
 | 
						|
 | 
						|
		if ( pPainter == NULL ||
 | 
						|
			 pPainter->mPinTypeCode != pin.mTypeCode )
 | 
						|
 | 
						|
			 pPainter = FindPainterForPin( pin );
 | 
						|
	
 | 
						|
 | 
						|
		// only pins which have their painters can be "visualized"
 | 
						|
 | 
						|
		if ( pPainter )
 | 
						|
		{
 | 
						|
			pos.x = 0;
 | 
						|
			pos.y = ( pin.mRow - mPagePos.mRow )* mCharDim.y + mTopMargin;
 | 
						|
 | 
						|
			if ( prevRow < pin.mRow )
 | 
						|
			{
 | 
						|
				// fill upper gap
 | 
						|
 | 
						|
				dc.SetBrush( mNormalBkBrush );
 | 
						|
				dc.SetPen( *wxTRANSPARENT_PEN );
 | 
						|
				dc.DrawRectangle( 0, prevY, 
 | 
						|
								  mLeftMargin + 1, 
 | 
						|
								  mCharDim.y * ( pin.mRow - prevRow ) + 1 );
 | 
						|
			}
 | 
						|
 | 
						|
			pPainter->DrawPin( &pin, *this, dc, pos, dim );
 | 
						|
 | 
						|
			prevRow = pin.mRow + 1;
 | 
						|
			prevY = pos.y + mCharDim.y;
 | 
						|
		}
 | 
						|
 | 
						|
		++curPin;
 | 
						|
 | 
						|
		if ( curPin >= pins.size() ||
 | 
						|
			 pins[curPin]->mRow >= tillRow )
 | 
						|
 | 
						|
			 break;
 | 
						|
	}
 | 
						|
 | 
						|
	// fill the reminder 
 | 
						|
 | 
						|
	if ( prevRow < tillRow )
 | 
						|
	{
 | 
						|
		dc.SetBrush( mNormalBkBrush );
 | 
						|
		dc.SetPen( *wxTRANSPARENT_PEN );
 | 
						|
		dc.DrawRectangle( 0, prevY, 
 | 
						|
						  mLeftMargin + 1, 
 | 
						|
						  mCharDim.y * ( tillRow - prevRow ) + 1 );
 | 
						|
	}
 | 
						|
 | 
						|
	dc.SetPen( *wxTRANSPARENT_PEN );
 | 
						|
}
 | 
						|
 | 
						|
void wxTextEditorView::PaintRows( size_t fromRow, size_t tillRow, wxDC& dc )
 | 
						|
{
 | 
						|
	// NOTE:: raws are painted from "fromRow" but not including "tillRow" - [fromRow,tillRow)
 | 
						|
 | 
						|
	dc.SetPen( *wxTRANSPARENT_PEN );
 | 
						|
 | 
						|
	// how much on-screen columns are visable?
 | 
						|
 | 
						|
	size_t fromScrCol = mPagePos.mCol;
 | 
						|
	size_t tillScrCol = fromScrCol + mColsPerPage;
 | 
						|
 | 
						|
	TPosition selStart = mpModel->GetStartOfSelection();
 | 
						|
	TPosition selEnd   = mpModel->GetEndOfSelection();
 | 
						|
 | 
						|
	bool selectionIsEmpty = ( selStart == selEnd );
 | 
						|
 | 
						|
	wxColour curFgCol;
 | 
						|
	wxColour curBkCol;
 | 
						|
 | 
						|
	wxBrush mLTBrush( mLTColour, wxSOLID );
 | 
						|
 | 
						|
	// clip given row-region to the current page
 | 
						|
 | 
						|
	if ( ( fromRow >= mPagePos.mRow + mRowsPerPage) || 
 | 
						|
		 ( tillRow <= mPagePos.mRow )
 | 
						|
	   )
 | 
						|
 | 
						|
		return;
 | 
						|
 | 
						|
	if ( fromRow < mPagePos.mRow ) fromRow = mPagePos.mRow;
 | 
						|
	if ( tillRow > mPagePos.mRow + mRowsPerPage ) tillRow = mPagePos.mRow + mRowsPerPage;
 | 
						|
 | 
						|
	if ( fromRow >= tillRow ) return;
 | 
						|
 | 
						|
	// now start the renderng
 | 
						|
 | 
						|
	if ( mpTimer->GetView() == this && mCursorOn && !mLTMode ) 
 | 
						|
	{
 | 
						|
		mpTimer->Lock();
 | 
						|
		mpTimer->SetIsShown( FALSE );
 | 
						|
	}
 | 
						|
 | 
						|
	dc.SetFont( mFont );
 | 
						|
	dc.SetBackgroundMode( wxSOLID );
 | 
						|
 | 
						|
	TTextIterator iter = mpModel->CreateIterator( TPosition( fromRow, 0 ) );
 | 
						|
 | 
						|
	PaintDecorations( fromRow, tillRow, dc, iter );
 | 
						|
 | 
						|
	size_t cursorRow = mpModel->GetCursor().mRow;
 | 
						|
 | 
						|
	size_t curRow = fromRow;
 | 
						|
	for( ; curRow != tillRow; ++curRow )
 | 
						|
	{
 | 
						|
		// place text into line-buffer
 | 
						|
 | 
						|
		iter.ToStartOfLine();
 | 
						|
		size_t lineLen = iter.GetLineLen();
 | 
						|
 | 
						|
		char* lineBuf = GetLineBuffer( lineLen + 1 );
 | 
						|
 | 
						|
		size_t i = 0;
 | 
						|
 | 
						|
  		while( !iter.IsEof() && !iter.IsEol() )
 | 
						|
  		{
 | 
						|
  			lineBuf[i++] = iter.GetChar();
 | 
						|
  			iter.NextChar();
 | 
						|
		}
 | 
						|
 | 
						|
		iter.NextChar(); // skip eol
 | 
						|
 | 
						|
		// obtain "highlights"
 | 
						|
  		
 | 
						|
		mpPainter->SetState( FALSE, FALSE );
 | 
						|
		mpPainter->Init( FALSE );
 | 
						|
		mpPainter->ProcessSource( lineBuf, lineLen );
 | 
						|
		IntListT& blocks = mpPainter->GetBlocks();
 | 
						|
 | 
						|
		// setup state vars
 | 
						|
 | 
						|
		int dcY = ( curRow - mPagePos.mRow ) * mCharDim.y + mTopMargin;
 | 
						|
		
 | 
						|
		size_t scrCol = 0;
 | 
						|
		size_t txtCol = 0;
 | 
						|
 | 
						|
		size_t curBlk = 0;
 | 
						|
		size_t curBlkCol = 0;
 | 
						|
 | 
						|
		int    chunkLen      = -1;
 | 
						|
		size_t chunkTxtStart = 0;
 | 
						|
		size_t chunkScrStart = 0;
 | 
						|
 | 
						|
		// pre-detect occurance of selection
 | 
						|
 | 
						|
		bool lineHasSelection = ( selStart.mRow == curRow ) ||
 | 
						|
			                    ( selEnd.mRow == curRow   );
 | 
						|
 | 
						|
		bool isInSelection    = ( selStart.mRow <= curRow ) &&
 | 
						|
			                    ( selEnd.mRow >= curRow   );
 | 
						|
 | 
						|
		if ( isInSelection && selStart.mRow == curRow &&
 | 
						|
			 selStart.mCol != 0 )
 | 
						|
 | 
						|
			 isInSelection = FALSE;
 | 
						|
 | 
						|
		if ( selStart == selEnd ) 
 | 
						|
		{
 | 
						|
			lineHasSelection = FALSE;
 | 
						|
			isInSelection = FALSE;
 | 
						|
		}
 | 
						|
		
 | 
						|
		char ch = '\0';
 | 
						|
 | 
						|
		// loop though the text in this row
 | 
						|
 | 
						|
		do
 | 
						|
		{
 | 
						|
			TPosition curPos( curRow, txtCol );
 | 
						|
 | 
						|
			// first check if we can finish the current chunk
 | 
						|
 | 
						|
			bool finishChunk = FALSE;
 | 
						|
 | 
						|
			if ( curBlk < blocks.size() &&
 | 
						|
				 curBlkCol + get_src_block_len( blocks[curBlk] ) == txtCol )
 | 
						|
			{
 | 
						|
				curBlkCol += get_src_block_len( blocks[curBlk] );
 | 
						|
				++curBlk;
 | 
						|
				finishChunk = TRUE;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			if ( ( !selectionIsEmpty && ( curPos == selStart || curPos == selEnd ) )
 | 
						|
				 || lineBuf[txtCol] == '\t' 
 | 
						|
				 || txtCol == lineLen )
 | 
						|
 | 
						|
				 finishChunk = TRUE;
 | 
						|
			
 | 
						|
			if ( finishChunk && chunkLen != -1 )
 | 
						|
			{
 | 
						|
				// is any part of the chunk visable?
 | 
						|
 | 
						|
				size_t chunkScrEnd = chunkScrStart + chunkLen;
 | 
						|
 | 
						|
				if ( ( // if hits from one side or is inside
 | 
						|
					   ( chunkScrStart >= fromScrCol &&
 | 
						|
					     chunkScrStart <  tillScrCol    ) ||
 | 
						|
					   ( chunkScrEnd   >= fromScrCol &&
 | 
						|
					     chunkScrEnd   <  tillScrCol    ) ) ||
 | 
						|
 | 
						|
					   // if overlaps the whole range
 | 
						|
					 (	chunkScrStart <   fromScrCol &&
 | 
						|
					    chunkScrEnd   >=  tillScrCol      )
 | 
						|
 | 
						|
				   )
 | 
						|
				{
 | 
						|
					// render chunk data to the given DC
 | 
						|
 | 
						|
					dc.SetTextForeground( curFgCol );
 | 
						|
					dc.SetTextBackground( curBkCol );
 | 
						|
 | 
						|
					// clip left edge
 | 
						|
 | 
						|
					if ( chunkScrStart < fromScrCol )
 | 
						|
					{
 | 
						|
						size_t diff = fromScrCol - chunkScrStart;
 | 
						|
						chunkLen      -= diff;
 | 
						|
						chunkTxtStart += diff;
 | 
						|
						chunkScrStart += diff;
 | 
						|
					}
 | 
						|
 | 
						|
					// clip right edge
 | 
						|
 | 
						|
					if ( chunkScrEnd > tillScrCol )
 | 
						|
					{
 | 
						|
						size_t diff  = chunkScrEnd - tillScrCol;
 | 
						|
						chunkLen    -= diff;
 | 
						|
						chunkScrEnd -= diff;
 | 
						|
					}
 | 
						|
 | 
						|
					// create string
 | 
						|
 | 
						|
					char tmp = lineBuf[chunkTxtStart + chunkLen];
 | 
						|
					
 | 
						|
					lineBuf[chunkTxtStart + chunkLen] = '\0';
 | 
						|
 | 
						|
					// use member-variable, reuse heap-buffer between outputs
 | 
						|
					mFragment = lineBuf + chunkTxtStart;
 | 
						|
 | 
						|
					lineBuf[chunkTxtStart + chunkLen] = tmp;
 | 
						|
 | 
						|
					// draw it
 | 
						|
 | 
						|
					int dcX = (chunkScrStart - fromScrCol) * mCharDim.x + mLeftMargin;
 | 
						|
 | 
						|
					dc.DrawText( mFragment, dcX, dcY );
 | 
						|
				}
 | 
						|
 | 
						|
				chunkLen = -1;
 | 
						|
 | 
						|
			} // end of "if ( finishChunk )"
 | 
						|
 | 
						|
			if ( txtCol == lineLen ) 
 | 
						|
				break;
 | 
						|
 | 
						|
			if ( chunkLen == -1 )
 | 
						|
			{
 | 
						|
				// prepare the new chunk
 | 
						|
 | 
						|
				if ( curBlk < blocks.size() )
 | 
						|
				{
 | 
						|
						switch( get_src_block_rank( blocks[curBlk] ) )
 | 
						|
						{
 | 
						|
							case RANK_BLACK : curFgCol = mNormalTextCol; break;
 | 
						|
							case RANK_BLUE  : curFgCol = mIndentifierTextCol; break;
 | 
						|
							case RANK_RED   : curFgCol = mReservedWordTextCol; break;
 | 
						|
							case RANK_GREEN : curFgCol = mCommentTextCol; break;
 | 
						|
							default : break;
 | 
						|
						}
 | 
						|
				}
 | 
						|
 | 
						|
				// track occurence of selection
 | 
						|
 | 
						|
				if ( lineHasSelection )
 | 
						|
				{
 | 
						|
					isInSelection = TRUE;
 | 
						|
 | 
						|
					if ( selEnd.mRow == curRow &&
 | 
						|
						 selEnd.mCol <= txtCol )
 | 
						|
 | 
						|
						 isInSelection = FALSE;
 | 
						|
 | 
						|
					if ( selStart.mRow == curRow &&
 | 
						|
						 selStart.mCol > txtCol )
 | 
						|
 | 
						|
						 isInSelection = FALSE;
 | 
						|
				}
 | 
						|
 | 
						|
				if ( isInSelection )
 | 
						|
				{
 | 
						|
					curFgCol = mSelectionFgCol;
 | 
						|
					curBkCol = mSelectionBkCol;
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					if ( mLTMode && curRow == cursorRow ) 
 | 
						|
 | 
						|
						curBkCol = mLTColour;
 | 
						|
					else
 | 
						|
						curBkCol = mNormalBkCol ;
 | 
						|
				}
 | 
						|
 | 
						|
				chunkScrStart = scrCol;
 | 
						|
				chunkTxtStart = txtCol;
 | 
						|
				chunkLen      = 0;
 | 
						|
			}
 | 
						|
 | 
						|
			
 | 
						|
			ch = lineBuf[txtCol];
 | 
						|
 | 
						|
			if ( ch == '\t' )
 | 
						|
			{
 | 
						|
				// tab's are treated specially (for simplicity and speed)
 | 
						|
 | 
						|
				int dcX = (chunkScrStart - fromScrCol) * mCharDim.x + mLeftMargin;
 | 
						|
 | 
						|
				if ( !isInSelection ) 
 | 
						|
				{
 | 
						|
					if ( mLTMode && curRow == cursorRow ) 
 | 
						|
						
 | 
						|
						dc.SetBrush( mLTBrush );
 | 
						|
					else 
 | 
						|
						dc.SetBrush( mNormalBkBrush );
 | 
						|
				}
 | 
						|
				else dc.SetBrush( mSelectedBkBrush );
 | 
						|
 | 
						|
				// *** "the rule of TAB..." ***
 | 
						|
 | 
						|
				size_t spacing = ( (scrCol / mpModel->mTabSize) + 1 ) * mpModel->mTabSize - scrCol;
 | 
						|
 | 
						|
				int width = spacing * mCharDim.x + 1;
 | 
						|
 | 
						|
				if ( dcX < mLeftMargin )
 | 
						|
				{
 | 
						|
					width -= mLeftMargin - dcX;
 | 
						|
 | 
						|
					dcX = mLeftMargin;
 | 
						|
				}
 | 
						|
 | 
						|
				if ( width > 0 )
 | 
						|
 | 
						|
					dc.DrawRectangle( dcX, dcY, width, mCharDim.y + 1 );
 | 
						|
 | 
						|
				scrCol += spacing;
 | 
						|
				txtCol += 1;
 | 
						|
				
 | 
						|
				// move chunk-start forward, after the occurance of '\t'
 | 
						|
 | 
						|
				chunkLen = -1;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				// increase on-screen/in-text positions
 | 
						|
 | 
						|
				++scrCol;
 | 
						|
				++txtCol;
 | 
						|
				++chunkLen;
 | 
						|
			}
 | 
						|
		
 | 
						|
		} while( TRUE );
 | 
						|
 | 
						|
		// fill the reminding white-space after eol
 | 
						|
 | 
						|
		if ( scrCol < tillScrCol && 
 | 
						|
			 ( !isInSelection ||
 | 
						|
			   ( isInSelection && curRow == selEnd.mRow ) )
 | 
						|
		   )
 | 
						|
		{
 | 
						|
			if ( scrCol < fromScrCol ) scrCol = fromScrCol;
 | 
						|
 | 
						|
			int dcX = ( scrCol - fromScrCol ) * mCharDim.x + mLeftMargin;
 | 
						|
 | 
						|
			if ( mLTMode && curRow == cursorRow )
 | 
						|
 | 
						|
				dc.SetBrush ( mLTBrush );
 | 
						|
			else
 | 
						|
				dc.SetBrush( mNormalBkBrush );
 | 
						|
 | 
						|
			dc.DrawRectangle( dcX, dcY, 
 | 
						|
							  mCharDim.x * ( tillScrCol - scrCol ) + 1, 
 | 
						|
							  mCharDim.y + 1 );
 | 
						|
		}
 | 
						|
 | 
						|
		// render selection which is located past the eol
 | 
						|
 | 
						|
		if ( ( lineHasSelection || isInSelection ) && 
 | 
						|
			 !( selEnd.mRow == curRow && selEnd.mCol <= txtCol )
 | 
						|
		   )
 | 
						|
		{
 | 
						|
			// determine start of selection on-screen
 | 
						|
 | 
						|
			size_t scrSelStart = scrCol + ( selStart.mCol - txtCol );
 | 
						|
 | 
						|
			if ( isInSelection )
 | 
						|
 | 
						|
				scrSelStart = scrCol;
 | 
						|
 | 
						|
			size_t scrSelEnd = tillScrCol;
 | 
						|
 | 
						|
			if ( selEnd.mRow == curRow )
 | 
						|
 | 
						|
				scrSelEnd = scrCol + ( selEnd.mCol - txtCol );
 | 
						|
 | 
						|
			// clipping 
 | 
						|
 | 
						|
			if ( scrSelStart < fromScrCol ) scrSelStart = fromScrCol;
 | 
						|
			if ( scrSelEnd   > tillScrCol ) scrSelEnd = tillScrCol;
 | 
						|
 | 
						|
			// drawing 
 | 
						|
 | 
						|
			if ( scrSelEnd > scrSelStart )
 | 
						|
			{
 | 
						|
				int dcX = ( scrSelStart - fromScrCol ) * mCharDim.x + mLeftMargin;
 | 
						|
 | 
						|
				dc.SetBrush( mSelectedBkBrush );
 | 
						|
				dc.DrawRectangle( dcX, dcY, 
 | 
						|
								  mCharDim.x * ( scrSelEnd - scrSelStart ) + 1, 
 | 
						|
								  mCharDim.y + 1 );
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if ( iter.IsEof() ) 
 | 
						|
		{
 | 
						|
			++curRow;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
 | 
						|
	} // end of "for(...)"
 | 
						|
 | 
						|
	if ( curRow < tillRow )
 | 
						|
	{
 | 
						|
		dc.SetBrush( mNormalBkBrush );
 | 
						|
 | 
						|
		int dcY = mTopMargin + (curRow - mPagePos.mRow)*mCharDim.y;
 | 
						|
		int dcX = mLeftMargin;
 | 
						|
 | 
						|
		dc.DrawRectangle( dcX, dcY, mColsPerPage*mCharDim.x + 1, 
 | 
						|
						  ( tillRow - curRow ) * mCharDim.y + 1
 | 
						|
				        );
 | 
						|
	}
 | 
						|
 | 
						|
	if ( mFullRefreshPending )
 | 
						|
	{
 | 
						|
		dc.SetBrush( mNormalBkBrush );
 | 
						|
 | 
						|
		// fill in "corners" which are never reached by characters
 | 
						|
		
 | 
						|
		int w,h;
 | 
						|
		GetClientSize( &w, &h );
 | 
						|
 | 
						|
		dc.SetBrush( mNormalBkBrush );
 | 
						|
 | 
						|
		int dcX = tillScrCol*mCharDim.x + mLeftMargin;
 | 
						|
 | 
						|
		dc.DrawRectangle( dcX, mTopMargin, w - dcX + 1, h );
 | 
						|
 | 
						|
		int dcY = mTopMargin + mRowsPerPage*mCharDim.y;
 | 
						|
 | 
						|
		dc.DrawRectangle( 0, dcY, w, h - dcY + 2 );
 | 
						|
 | 
						|
		++curRow;
 | 
						|
 | 
						|
		// any past-the-eof lines left at the bottom?
 | 
						|
	}
 | 
						|
 | 
						|
	mFullRefreshPending = FALSE;
 | 
						|
 | 
						|
	if ( mpTimer->GetView() == this && mCursorOn && !mLTMode ) 
 | 
						|
 | 
						|
		mpTimer->Unlock();
 | 
						|
 | 
						|
} // end of PaintRows(..)
 | 
						|
 | 
						|
/***** Implementation for class TBookmarkPainter *****/
 | 
						|
 | 
						|
TBookmarkPainter::TBookmarkPainter() 
 | 
						|
 | 
						|
	: TPinPainterBase( BOOKMARK_PIN_TC ),
 | 
						|
	  mBkBrush( wxColour( 0,255,255 ), wxSOLID )
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void TBookmarkPainter::DrawPin( TPinBase* pPin, wxTextEditorView& view, wxDC& dc, 
 | 
						|
							    const wxPoint& pos, const wxSize& dim )
 | 
						|
{
 | 
						|
	dc.SetPen( *wxBLACK_PEN );
 | 
						|
	dc.SetBrush( mBkBrush );
 | 
						|
	dc.DrawRoundedRectangle( pos.x+2, pos.y, dim.x-4, dim.y, 4 );
 | 
						|
}
 | 
						|
 | 
						|
/***** Implementation for class TBreakpointPainter *****/
 | 
						|
 | 
						|
TBreakpointPainter::TBreakpointPainter() 
 | 
						|
 | 
						|
	: TPinPainterBase( BRKPOINT_PIN_TC ),
 | 
						|
	  mBkBrush( wxColour( 196,0,0 ), wxSOLID )
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void TBreakpointPainter::DrawPin( TPinBase* pPin, wxTextEditorView& view, wxDC& dc, 
 | 
						|
								  const wxPoint& pos, const wxSize& dim )
 | 
						|
{
 | 
						|
	dc.SetPen( *wxBLACK_PEN );
 | 
						|
	dc.SetBrush( mBkBrush );
 | 
						|
	dc.DrawRoundedRectangle( pos.x+6, pos.y+2, dim.x-12, dim.y-4, 30 );
 | 
						|
}
 | 
						|
 | 
						|
/***** Implementation for class TCursorTimer *****/
 | 
						|
 | 
						|
TCursorTimer::TCursorTimer()
 | 
						|
 | 
						|
	: mIsLocked( FALSE ),
 | 
						|
	  mIsShown ( FALSE ),
 | 
						|
	  mBlinkInterval( 500 ),
 | 
						|
	  mBrush( wxColour(0,0,0), wxSOLID ),
 | 
						|
	  mMissOneTick( FALSE )
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void TCursorTimer::Notify()
 | 
						|
{
 | 
						|
	if ( mIsLocked ) return;
 | 
						|
 | 
						|
	if ( mMissOneTick )
 | 
						|
	{
 | 
						|
		// this trick is used because it's not
 | 
						|
		// possible to restart the timer under wxGtk
 | 
						|
 | 
						|
		mMissOneTick = FALSE;
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	mIsLocked = TRUE;
 | 
						|
 | 
						|
	DrawCursor();
 | 
						|
 | 
						|
	mIsShown = !mIsShown;
 | 
						|
 | 
						|
	mIsLocked = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
void TCursorTimer::SetView( wxTextEditorView* pView )
 | 
						|
{
 | 
						|
	mpView = pView;
 | 
						|
}
 | 
						|
 | 
						|
wxTextEditorView* TCursorTimer::GetView()
 | 
						|
{
 | 
						|
	return mpView;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void TCursorTimer::HideCursor( bool forceHide )
 | 
						|
{
 | 
						|
	Lock();
 | 
						|
 | 
						|
	if ( mIsShown  ) 
 | 
						|
	{
 | 
						|
		DrawCursor();
 | 
						|
		mIsShown = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	Unlock();
 | 
						|
}
 | 
						|
 | 
						|
void TCursorTimer::ShowCursor( bool forceShow )
 | 
						|
{
 | 
						|
	Lock();
 | 
						|
 | 
						|
	if ( !forceShow ) 
 | 
						|
	{
 | 
						|
		DrawCursor();
 | 
						|
		mIsShown = TRUE;
 | 
						|
 | 
						|
		if ( mStarted )
 | 
						|
			mMissOneTick = TRUE;
 | 
						|
	}
 | 
						|
 | 
						|
	Unlock();
 | 
						|
 | 
						|
	if ( !mStarted )
 | 
						|
	{
 | 
						|
		Start( mBlinkInterval );
 | 
						|
		mStarted = TRUE;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TCursorTimer::Lock()
 | 
						|
{
 | 
						|
//	while( mIsLocked );
 | 
						|
 | 
						|
	mIsLocked = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void TCursorTimer::Unlock()
 | 
						|
{
 | 
						|
	mIsLocked = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
void TCursorTimer::SetIsShown( bool isShown )
 | 
						|
{
 | 
						|
	mIsShown = isShown;
 | 
						|
}
 | 
						|
 | 
						|
/*** protected methods ***/
 | 
						|
 | 
						|
void TCursorTimer::DrawCursor()
 | 
						|
{
 | 
						|
	if ( mpView == NULL ) return;
 | 
						|
 | 
						|
	wxClientDC dc( mpView );
 | 
						|
 | 
						|
	int x = 0, y = 0;
 | 
						|
 | 
						|
	mpView->ScreenPosToPixels( mpView->mCursorScrPos, x, y );
 | 
						|
 | 
						|
	dc.SetLogicalFunction( wxINVERT );
 | 
						|
	dc.SetBrush( mBrush );
 | 
						|
 | 
						|
	dc.SetPen( *wxTRANSPARENT_PEN );
 | 
						|
	dc.DrawRectangle( x,y, 3, mpView->mCharDim.y + 1 );
 | 
						|
	dc.SetBackgroundMode( wxSOLID );
 | 
						|
}
 |