]> git.saurik.com Git - wxWidgets.git/blobdiff - utils/wxPython/modules/lseditor/tdefs.cpp
lots'o' wxpython modules files
[wxWidgets.git] / utils / wxPython / modules / lseditor / tdefs.cpp
diff --git a/utils/wxPython/modules/lseditor/tdefs.cpp b/utils/wxPython/modules/lseditor/tdefs.cpp
new file mode 100644 (file)
index 0000000..e65b2fe
--- /dev/null
@@ -0,0 +1,4233 @@
+/////////////////////////////////////////////////////////////////////////////
+// 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 );
+}