/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"


#include <memory>

#include "unoiface.hxx"

#include <tools/rc.h>

#include <vcl/decoview.hxx>
#include <vcl/svapp.hxx>

#include <svtools/svmedit.hxx>
#include <svtools/xtextedt.hxx>
#include <svl/brdcst.hxx>
#include <svl/undo.hxx>
#include <svtools/textwindowpeer.hxx>
#include <svl/lstner.hxx>
#include <svl/smplhint.hxx>


// IDs erstmal aus VCL geklaut, muss mal richtig delivert werden...
#define SV_MENU_EDIT_UNDO			1
#define SV_MENU_EDIT_CUT			2
#define SV_MENU_EDIT_COPY			3
#define SV_MENU_EDIT_PASTE			4
#define SV_MENU_EDIT_DELETE 		5
#define SV_MENU_EDIT_SELECTALL		6
#define SV_MENU_EDIT_INSERTSYMBOL	7
#include <vcl/scrbar.hxx>

namespace css = ::com::sun::star;

class TextWindow : public Window
{
private:
	ExtTextEngine*	mpExtTextEngine;
	ExtTextView*	mpExtTextView;

	sal_Bool			mbInMBDown;
	sal_Bool			mbFocusSelectionHide;
	sal_Bool			mbIgnoreTab;
	sal_Bool			mbActivePopup;
    sal_Bool            mbSelectOnTab;

public:
					TextWindow( Window* pParent );
					~TextWindow();

	ExtTextEngine* 	GetTextEngine() const { return mpExtTextEngine; }
	ExtTextView*	GetTextView() const { return mpExtTextView; }

	virtual void	MouseMove( const MouseEvent& rMEvt );
	virtual void	MouseButtonDown( const MouseEvent& rMEvt );
	virtual void	MouseButtonUp( const MouseEvent& rMEvt );
	virtual void	KeyInput( const KeyEvent& rKEvent );

	virtual void	Command( const CommandEvent& rCEvt );

	virtual void	Paint( const Rectangle& rRect );
	virtual void	Resize();

	virtual void	GetFocus();
	virtual void	LoseFocus();

	sal_Bool			IsAutoFocusHide() const { return mbFocusSelectionHide; }
	void			SetAutoFocusHide( sal_Bool bAutoHide ) { mbFocusSelectionHide = bAutoHide; }

	sal_Bool			IsIgnoreTab() const { return mbIgnoreTab; }
	void			SetIgnoreTab( sal_Bool bIgnore ) { mbIgnoreTab = bIgnore; }

    void            DisableSelectionOnFocus() {mbSelectOnTab = sal_False;}

    virtual
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >
    GetComponentInterface(sal_Bool bCreate = sal_True);
};


class ImpSvMEdit : public SfxListener
{
private:
	MultiLineEdit*		pSvMultiLineEdit;

	TextWindow* 		mpTextWindow;
	ScrollBar*			mpHScrollBar;
	ScrollBar*			mpVScrollBar;
	ScrollBarBox*		mpScrollBox;

	Point				maTextWindowOffset;
	xub_StrLen			mnTextWidth;
    mutable Selection   maSelection;

protected:
	virtual void		Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
	void				ImpUpdateSrollBarVis( WinBits nWinStyle );
	void				ImpInitScrollBars();
	void				ImpSetScrollBarRanges();
    void                ImpSetHScrollBarThumbPos();
	DECL_LINK(			ScrollHdl, ScrollBar* );

public:
				ImpSvMEdit( MultiLineEdit* pSvMultiLineEdit, WinBits nWinStyle );
				~ImpSvMEdit();

	void		SetModified( sal_Bool bMod );
	sal_Bool		IsModified() const;

	void		SetReadOnly( sal_Bool bRdOnly );
	sal_Bool		IsReadOnly() const;

	void		SetMaxTextLen( xub_StrLen nLen );
	xub_StrLen	GetMaxTextLen() const;

	void		SetInsertMode( sal_Bool bInsert );
	sal_Bool		IsInsertMode() const;

	void		InsertText( const String& rStr );
	String		GetSelected() const;
	String		GetSelected( LineEnd aSeparator ) const;

	void		SetSelection( const Selection& rSelection );
	const Selection& GetSelection() const;

	void		Cut();
	void		Copy();
	void		Paste();

	void		SetText( const String& rStr );
	String		GetText() const;
	String		GetText( LineEnd aSeparator ) const;
	String		GetTextLines() const;
	String		GetTextLines( LineEnd aSeparator ) const;

	void		Resize();
	void		GetFocus();

	sal_Bool		HandleCommand( const CommandEvent& rCEvt );

	void		Enable( sal_Bool bEnable );

	Size		CalcMinimumSize() const;
	Size		CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const;
	void		GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const;

	void		SetAlign( WinBits nWinStyle );

	void		InitFromStyle( WinBits nWinStyle );

	TextWindow* GetTextWindow() { return mpTextWindow; }
	ScrollBar*  GetHScrollBar() { return mpHScrollBar; }
	ScrollBar*  GetVScrollBar() { return mpVScrollBar; }

	void 		SetTextWindowOffset( const Point& rOffset );
};

ImpSvMEdit::ImpSvMEdit( MultiLineEdit* pEdt, WinBits nWinStyle )
	:mpHScrollBar(NULL)
	,mpVScrollBar(NULL)
	,mpScrollBox(NULL)
{
	pSvMultiLineEdit = pEdt;
	mnTextWidth = 0;
	mpTextWindow = new TextWindow( pEdt );
	mpTextWindow->Show();
	InitFromStyle( nWinStyle );
	StartListening( *mpTextWindow->GetTextEngine() );
}

void ImpSvMEdit::ImpUpdateSrollBarVis( WinBits nWinStyle )
{
	const sal_Bool bHaveVScroll = (NULL != mpVScrollBar);
    const sal_Bool bHaveHScroll = (NULL != mpHScrollBar);
    const sal_Bool bHaveScrollBox = (NULL != mpScrollBox);

          sal_Bool bNeedVScroll = ( nWinStyle & WB_VSCROLL ) == WB_VSCROLL;
    const sal_Bool bNeedHScroll = ( nWinStyle & WB_HSCROLL ) == WB_HSCROLL;

    const sal_Bool bAutoVScroll = ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL;
    if ( !bNeedVScroll && bAutoVScroll )
    {
        TextEngine& rEngine( *mpTextWindow->GetTextEngine() );
        sal_uLong nOverallTextHeight(0);
        for ( sal_uLong i=0; i<rEngine.GetParagraphCount(); ++i )
            nOverallTextHeight += rEngine.GetTextHeight( i );
        if ( nOverallTextHeight > (sal_uLong)mpTextWindow->GetOutputSizePixel().Height() )
            bNeedVScroll = true;
    }

    const sal_Bool bNeedScrollBox = bNeedVScroll && bNeedHScroll;

    sal_Bool bScrollbarsChanged = false;
	if ( bHaveVScroll != bNeedVScroll )
	{
		delete mpVScrollBar;
		mpVScrollBar = bNeedVScroll ? new ScrollBar( pSvMultiLineEdit, WB_VSCROLL|WB_DRAG ) : NULL;

		if ( bNeedVScroll )
		{
			mpVScrollBar->Show();
			mpVScrollBar->SetScrollHdl( LINK( this, ImpSvMEdit, ScrollHdl ) );
		}

		bScrollbarsChanged = sal_True;
	}

	if ( bHaveHScroll != bNeedHScroll )
	{
		delete mpHScrollBar;
		mpHScrollBar = bNeedHScroll ? new ScrollBar( pSvMultiLineEdit, WB_HSCROLL|WB_DRAG ) : NULL;

		if ( bNeedHScroll )
		{
			mpHScrollBar->Show();
			mpHScrollBar->SetScrollHdl( LINK( this, ImpSvMEdit, ScrollHdl ) );
		}

		bScrollbarsChanged = sal_True;
	}

	if ( bHaveScrollBox != bNeedScrollBox )
	{
		delete mpScrollBox;
		mpScrollBox = bNeedScrollBox ? new ScrollBarBox( pSvMultiLineEdit, WB_SIZEABLE ) : NULL;

		if ( bNeedScrollBox )
			mpScrollBox->Show();
	}

	if ( bScrollbarsChanged )
	{
		ImpInitScrollBars();
		Resize();
	}
}

void ImpSvMEdit::InitFromStyle( WinBits nWinStyle )
{
    ImpUpdateSrollBarVis( nWinStyle );
	SetAlign( nWinStyle );

	if ( nWinStyle & WB_NOHIDESELECTION )
		mpTextWindow->SetAutoFocusHide( sal_False );
	else
		mpTextWindow->SetAutoFocusHide( sal_True );

	if ( nWinStyle & WB_READONLY )
		mpTextWindow->GetTextView()->SetReadOnly( sal_True );
	else
		mpTextWindow->GetTextView()->SetReadOnly( sal_False );

	if ( nWinStyle & WB_IGNORETAB )
    {
		mpTextWindow->SetIgnoreTab( sal_True );
    }
	else
    {
		mpTextWindow->SetIgnoreTab( sal_False );
        // #103667# MultiLineEdit has the flag, but focusable window also needs this flag
        WinBits nStyle = mpTextWindow->GetStyle();
        nStyle |= WINDOW_DLGCTRL_MOD1TAB;
        mpTextWindow->SetStyle( nStyle );
    }
}

ImpSvMEdit::~ImpSvMEdit()
{
	EndListening( *mpTextWindow->GetTextEngine() );
	delete mpTextWindow;
	delete mpHScrollBar;
	delete mpVScrollBar;
	delete mpScrollBox;
}

void ImpSvMEdit::ImpSetScrollBarRanges()
{
	if ( mpVScrollBar )
	{
		sal_uLong nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
		mpVScrollBar->SetRange( Range( 0, (long)nTextHeight-1 ) );
	}
	if ( mpHScrollBar )
	{
//		sal_uLong nTextWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
		// Es gibt kein Notify bei Breiten-Aenderung...
//		sal_uLong nW = Max( (sal_uLong)mpTextWindow->GetOutputSizePixel().Width()*5, (sal_uLong)nTextWidth );
//		mpHScrollBar->SetRange( Range( 0, (long)nW ) );
		mpHScrollBar->SetRange( Range( 0, (long)mnTextWidth-1 ) );
	}
}

void ImpSvMEdit::ImpInitScrollBars()
{
	static const sal_Unicode sampleText[] = { 'x', '\0' };
	if ( mpHScrollBar || mpVScrollBar )
	{
		ImpSetScrollBarRanges();
		Size aCharBox;
		aCharBox.Width() = mpTextWindow->GetTextWidth( sampleText );
		aCharBox.Height() = mpTextWindow->GetTextHeight();
		Size aOutSz = mpTextWindow->GetOutputSizePixel();
		if ( mpHScrollBar )
		{
			mpHScrollBar->SetVisibleSize( aOutSz.Width() );
			mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 );
			mpHScrollBar->SetLineSize( aCharBox.Width()*10 );
            ImpSetHScrollBarThumbPos();
        }
		if ( mpVScrollBar )
		{
			mpVScrollBar->SetVisibleSize( aOutSz.Height() );
			mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 );
			mpVScrollBar->SetLineSize( aCharBox.Height() );
			mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
		}
	}
}

void ImpSvMEdit::ImpSetHScrollBarThumbPos()
{
    long nX = mpTextWindow->GetTextView()->GetStartDocPos().X();
    if ( !mpTextWindow->GetTextEngine()->IsRightToLeft() )
        mpHScrollBar->SetThumbPos( nX );
    else
        mpHScrollBar->SetThumbPos( mnTextWidth - mpHScrollBar->GetVisibleSize() - nX );

}

IMPL_LINK( ImpSvMEdit, ScrollHdl, ScrollBar*, pCurScrollBar )
{
	long nDiffX = 0, nDiffY = 0;

	if ( pCurScrollBar == mpVScrollBar )
		nDiffY = mpTextWindow->GetTextView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
	else if ( pCurScrollBar == mpHScrollBar )
		nDiffX = mpTextWindow->GetTextView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();

	mpTextWindow->GetTextView()->Scroll( nDiffX, nDiffY );
	// mpTextWindow->GetTextView()->ShowCursor( sal_False, sal_True );

	return 0;
}


// void ImpSvMEdit::ImpModified()
// {
//	// Wann wird das gerufen ?????????????????????
//	pSvMultiLineEdit->Modify();
// }

void ImpSvMEdit::SetAlign( WinBits nWinStyle )
{
    sal_Bool bRTL = Application::GetSettings().GetLayoutRTL();
    mpTextWindow->GetTextEngine()->SetRightToLeft( bRTL );

    if ( nWinStyle & WB_CENTER )
		mpTextWindow->GetTextEngine()->SetTextAlign( TXTALIGN_CENTER );
	else if ( nWinStyle & WB_RIGHT )
        mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_RIGHT : TXTALIGN_LEFT );
	else if ( nWinStyle & WB_LEFT )
        mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_LEFT : TXTALIGN_RIGHT );
}

void ImpSvMEdit::SetTextWindowOffset( const Point& rOffset )
{
	maTextWindowOffset = rOffset;
	Resize();
}

void ImpSvMEdit::SetModified( sal_Bool bMod )
{
	mpTextWindow->GetTextEngine()->SetModified( bMod );
}

sal_Bool ImpSvMEdit::IsModified() const
{
	return mpTextWindow->GetTextEngine()->IsModified();
}

void ImpSvMEdit::SetInsertMode( sal_Bool bInsert )
{
	mpTextWindow->GetTextView()->SetInsertMode( bInsert );
}

void ImpSvMEdit::SetReadOnly( sal_Bool bRdOnly )
{
	mpTextWindow->GetTextView()->SetReadOnly( bRdOnly );
	// Farbe anpassen ???????????????????????????
}

sal_Bool ImpSvMEdit::IsReadOnly() const
{
	return mpTextWindow->GetTextView()->IsReadOnly();
}

void ImpSvMEdit::SetMaxTextLen( xub_StrLen nLen )
{
	mpTextWindow->GetTextEngine()->SetMaxTextLen( nLen );
}

xub_StrLen ImpSvMEdit::GetMaxTextLen() const
{
	return sal::static_int_cast< xub_StrLen >(
        mpTextWindow->GetTextEngine()->GetMaxTextLen());
}

void ImpSvMEdit::InsertText( const String& rStr )
{
	mpTextWindow->GetTextView()->InsertText( rStr );
}

String ImpSvMEdit::GetSelected() const
{
	return mpTextWindow->GetTextView()->GetSelected();
}

String ImpSvMEdit::GetSelected( LineEnd aSeparator ) const
{
	return mpTextWindow->GetTextView()->GetSelected( aSeparator );
}

void ImpSvMEdit::Resize()
{
    size_t nIteration = 1;
    do
    {
        WinBits nWinStyle( pSvMultiLineEdit->GetStyle() );
        if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
            ImpUpdateSrollBarVis( nWinStyle );

	    Size aSz = pSvMultiLineEdit->GetOutputSizePixel();
        Size aEditSize = aSz;
	    long nSBWidth = pSvMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize();
	    nSBWidth = pSvMultiLineEdit->CalcZoom( nSBWidth );

	    if ( mpHScrollBar )
		    aSz.Height() -= nSBWidth+1;
	    if ( mpVScrollBar )
		    aSz.Width() -= nSBWidth+1;

	    if ( !mpHScrollBar )
		    mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() );
        else
		    mpHScrollBar->SetPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth );

        Point aTextWindowPos( maTextWindowOffset );
	    if ( mpVScrollBar )
        {
            if( Application::GetSettings().GetLayoutRTL() )
            {
                mpVScrollBar->SetPosSizePixel( 0, 0, nSBWidth, aSz.Height() );
                aTextWindowPos.X() += nSBWidth;
            }
            else
                mpVScrollBar->SetPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() );
        }

	    if ( mpScrollBox )
		    mpScrollBox->SetPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth );

	    Size aTextWindowSize( aSz );
	    aTextWindowSize.Width() -= maTextWindowOffset.X();
	    aTextWindowSize.Height() -= maTextWindowOffset.Y();
        if ( aTextWindowSize.Width() < 0 )
            aTextWindowSize.Width() = 0;
        if ( aTextWindowSize.Height() < 0 )
            aTextWindowSize.Height() = 0;

        Size aOldTextWindowSize( mpTextWindow->GetSizePixel() );
        mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize );
        if ( aOldTextWindowSize == aTextWindowSize )
            break;

        // Changing the text window size might effectively have changed the need for
        // scrollbars, so do another iteration.
        ++nIteration;
        OSL_ENSURE( nIteration < 3, "ImpSvMEdit::Resize: isn't this expected to terminate with the second iteration?" );

    } while ( nIteration <= 3 );    // artificial break after four iterations

    ImpInitScrollBars();
}

void ImpSvMEdit::GetFocus()
{
	mpTextWindow->GrabFocus();
}

void ImpSvMEdit::Cut()
{
	if ( !mpTextWindow->GetTextView()->IsReadOnly() )
		mpTextWindow->GetTextView()->Cut();
}

void ImpSvMEdit::Copy()
{
	mpTextWindow->GetTextView()->Copy();
}

void ImpSvMEdit::Paste()
{
	if ( !mpTextWindow->GetTextView()->IsReadOnly() )
		mpTextWindow->GetTextView()->Paste();
}

void ImpSvMEdit::SetText( const String& rStr )
{
	sal_Bool bWasModified = mpTextWindow->GetTextEngine()->IsModified();
	mpTextWindow->GetTextEngine()->SetText( rStr );
	if ( !bWasModified )
		mpTextWindow->GetTextEngine()->SetModified( sal_False );

	mpTextWindow->GetTextView()->SetSelection( TextSelection() );

    WinBits nWinStyle( pSvMultiLineEdit->GetStyle() );
    if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
        ImpUpdateSrollBarVis( nWinStyle );
}

String ImpSvMEdit::GetText() const
{
	return mpTextWindow->GetTextEngine()->GetText();
}

String ImpSvMEdit::GetText( LineEnd aSeparator ) const
{
	return mpTextWindow->GetTextEngine()->GetText( aSeparator );
}

String ImpSvMEdit::GetTextLines() const
{
	return mpTextWindow->GetTextEngine()->GetTextLines();
}

String ImpSvMEdit::GetTextLines( LineEnd aSeparator ) const
{
	return mpTextWindow->GetTextEngine()->GetTextLines( aSeparator );
}

void ImpSvMEdit::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
	if ( rHint.ISA( TextHint ) )
	{
		const TextHint& rTextHint = (const TextHint&)rHint;
		if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED )
		{
			if ( mpHScrollBar )
				ImpSetHScrollBarThumbPos();
			if ( mpVScrollBar )
				mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
		}
		else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED )
		{
			if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() )
			{
				long nOutHeight = mpTextWindow->GetOutputSizePixel().Height();
				long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
				if ( nTextHeight < nOutHeight )
					mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() );
			}

			ImpSetScrollBarRanges();
		}
		else if( rTextHint.GetId() == TEXT_HINT_TEXTFORMATTED )
		{
			if ( mpHScrollBar )
			{
				sal_uLong nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
				if ( nWidth != mnTextWidth )
				{
					mnTextWidth = sal::static_int_cast< xub_StrLen >(nWidth);
					mpHScrollBar->SetRange( Range( 0, (long)mnTextWidth-1 ) );
                    ImpSetHScrollBarThumbPos();
				}
			}
		}
		else if( rTextHint.GetId() == TEXT_HINT_MODIFIED )
		{
			pSvMultiLineEdit->Modify();
		}
	}
}

void ImpSvMEdit::SetSelection( const Selection& rSelection )
{
	String aText = mpTextWindow->GetTextEngine()->GetText();

	Selection aNewSelection( rSelection );
	if ( aNewSelection.Min() < 0 )
		aNewSelection.Min() = 0;
	else if ( aNewSelection.Min() > aText.Len() )
		aNewSelection.Min() = aText.Len();
	if ( aNewSelection.Max() < 0 )
		aNewSelection.Max() = 0;
	else if ( aNewSelection.Max() > aText.Len() )
		aNewSelection.Max() = aText.Len();

	long nEnd = Max( aNewSelection.Min(), aNewSelection.Max() );
	TextSelection aTextSel;
	sal_uLong nPara = 0;
	sal_uInt16 nChar = 0;
	sal_uInt16 x = 0;
	while ( x <= nEnd )
	{
		if ( x == aNewSelection.Min() )
			aTextSel.GetStart() = TextPaM( nPara, nChar );
		if ( x == aNewSelection.Max() )
			aTextSel.GetEnd() = TextPaM( nPara, nChar );

		if ( ( x < aText.Len() ) && ( aText.GetChar( x ) == '\n' ) )
		{
			nPara++;
			nChar = 0;
		}
		else
			nChar++;
		x++;
	}
	mpTextWindow->GetTextView()->SetSelection( aTextSel );
}

const Selection& ImpSvMEdit::GetSelection() const
{
    maSelection = Selection();
	TextSelection aTextSel( mpTextWindow->GetTextView()->GetSelection() );
	aTextSel.Justify();
	// Selektion flachklopfen => jeder Umbruch ein Zeichen...

	ExtTextEngine* pExtTextEngine = mpTextWindow->GetTextEngine();
	// Absaetze davor:
	sal_uLong n;
	for ( n = 0; n < aTextSel.GetStart().GetPara(); n++ )
	{
		maSelection.Min() += pExtTextEngine->GetTextLen( n );
		maSelection.Min()++;
	}

	// Erster Absatz mit Selektion:
	maSelection.Max() = maSelection.Min();
	maSelection.Min() += aTextSel.GetStart().GetIndex();

	for ( n = aTextSel.GetStart().GetPara(); n < aTextSel.GetEnd().GetPara(); n++ )
	{
		maSelection.Max() += pExtTextEngine->GetTextLen( n );
		maSelection.Max()++;
	}

	maSelection.Max() += aTextSel.GetEnd().GetIndex();

	return maSelection;
}

Size ImpSvMEdit::CalcMinimumSize() const
{
	Size aSz(	mpTextWindow->GetTextEngine()->CalcTextWidth(),
				mpTextWindow->GetTextEngine()->GetTextHeight() );

	if ( mpHScrollBar )
		aSz.Height() += mpHScrollBar->GetSizePixel().Height();
	if ( mpVScrollBar )
		aSz.Width() += mpVScrollBar->GetSizePixel().Width();

	return aSz;
}

Size ImpSvMEdit::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
{
	static const sal_Unicode sampleText[] = { 'X', '\0' };

	Size aSz;
	Size aCharSz;
	aCharSz.Width() = mpTextWindow->GetTextWidth( sampleText );
	aCharSz.Height() = mpTextWindow->GetTextHeight();

	if ( nLines )
		aSz.Height() = nLines*aCharSz.Height();
	else
		aSz.Height() = mpTextWindow->GetTextEngine()->GetTextHeight();

	if ( nColumns )
		aSz.Width() = nColumns*aCharSz.Width();
	else
		aSz.Width() = mpTextWindow->GetTextEngine()->CalcTextWidth();

	if ( mpHScrollBar )
		aSz.Height() += mpHScrollBar->GetSizePixel().Height();
	if ( mpVScrollBar )
		aSz.Width() += mpVScrollBar->GetSizePixel().Width();

	return aSz;
}

void ImpSvMEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
{
	static const sal_Unicode sampleText[] = { 'x', '\0' };
	Size aOutSz = mpTextWindow->GetOutputSizePixel();
	Size aCharSz( mpTextWindow->GetTextWidth( sampleText ), mpTextWindow->GetTextHeight() );
	rnCols = (sal_uInt16) (aOutSz.Width()/aCharSz.Width());
	rnLines = (sal_uInt16) (aOutSz.Height()/aCharSz.Height());
}

void ImpSvMEdit::Enable( sal_Bool bEnable )
{
	mpTextWindow->Enable( bEnable );
	if ( mpHScrollBar )
		mpHScrollBar->Enable( bEnable );
	if ( mpVScrollBar )
		mpVScrollBar->Enable( bEnable );
}

sal_Bool ImpSvMEdit::HandleCommand( const CommandEvent& rCEvt )
{
	sal_Bool bDone = sal_False;
	if ( ( rCEvt.GetCommand() == COMMAND_WHEEL ) ||
		 ( rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL ) ||
		 ( rCEvt.GetCommand() == COMMAND_AUTOSCROLL ) )
	{
		mpTextWindow->HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
		bDone = sal_True;
	}
	return bDone;
}


TextWindow::TextWindow( Window* pParent ) : Window( pParent )
{
	mbInMBDown = sal_False;
    mbSelectOnTab = sal_True;
	mbFocusSelectionHide = sal_False;
	mbIgnoreTab = sal_False;
	mbActivePopup = sal_False;
    mbSelectOnTab = sal_True;

	SetPointer( Pointer( POINTER_TEXT ) );

	mpExtTextEngine = new ExtTextEngine;
	mpExtTextEngine->SetMaxTextLen( STRING_MAXLEN );
    if( pParent->GetStyle() & WB_BORDER )
		mpExtTextEngine->SetLeftMargin( 2 );
	mpExtTextEngine->SetLocale( GetSettings().GetLocale() );
    mpExtTextView = new ExtTextView( mpExtTextEngine, this );
	mpExtTextEngine->InsertView( mpExtTextView );
	mpExtTextEngine->EnableUndo( sal_True );
	mpExtTextView->ShowCursor();

	Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor();
	SetBackground( aBackgroundColor );
	pParent->SetBackground( aBackgroundColor );
}

TextWindow::~TextWindow()
{
	delete mpExtTextView;
	delete mpExtTextEngine;
}

void TextWindow::MouseMove( const MouseEvent& rMEvt )
{
	mpExtTextView->MouseMove( rMEvt );
	Window::MouseMove( rMEvt );
}

void TextWindow::MouseButtonDown( const MouseEvent& rMEvt )
{
	mbInMBDown = sal_True;	// Dann im GetFocus nicht alles selektieren wird
	mpExtTextView->MouseButtonDown( rMEvt );
	Window::MouseButtonDown( rMEvt );
	GrabFocus();
	mbInMBDown = sal_False;
}

void TextWindow::MouseButtonUp( const MouseEvent& rMEvt )
{
	mpExtTextView->MouseButtonUp( rMEvt );
	Window::MouseButtonUp( rMEvt );
}

void TextWindow::KeyInput( const KeyEvent& rKEvent )
{
	sal_Bool bDone = sal_False;
	sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
	if ( nCode == com::sun::star::awt::Key::SELECT_ALL || 
         ( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() )
       )
	{
		mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) );
		bDone = sal_True;
	}
	else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() )
	{
		if ( Edit::GetGetSpecialCharsFunction() )
		{
			// Damit die Selektion erhalten bleibt
			mbActivePopup = sal_True;
			XubString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() );
			if ( aChars.Len() )
			{
				mpExtTextView->InsertText( aChars );
				mpExtTextView->GetTextEngine()->SetModified( sal_True );
			}
			mbActivePopup = sal_False;
			bDone = sal_True;
		}
	}
	else if ( nCode == KEY_TAB )
	{
		if ( !mbIgnoreTab || rKEvent.GetKeyCode().IsMod1() )
			bDone = mpExtTextView->KeyInput( rKEvent  );
	}
	else
	{
		bDone = mpExtTextView->KeyInput( rKEvent  );
	}

	if ( !bDone )
		Window::KeyInput( rKEvent );
}

void TextWindow::Paint( const Rectangle& rRect )
{
	mpExtTextView->Paint( rRect );
}

void TextWindow::Resize()
{
}

void TextWindow::Command( const CommandEvent& rCEvt )
{
	if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
	{
		PopupMenu* pPopup = Edit::CreatePopupMenu();
		const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
		if ( rStyleSettings.GetOptions() & STYLE_OPTION_HIDEDISABLED )
			pPopup->SetMenuFlags( MENU_FLAG_HIDEDISABLEDENTRIES );
		if ( !mpExtTextView->HasSelection() )
		{
			pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False );
			pPopup->EnableItem( SV_MENU_EDIT_COPY, sal_False );
			pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False );
		}
		if ( mpExtTextView->IsReadOnly() )
		{
			pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False );
			pPopup->EnableItem( SV_MENU_EDIT_PASTE, sal_False );
			pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False );
			pPopup->EnableItem( SV_MENU_EDIT_INSERTSYMBOL, sal_False );
		}
		if ( !mpExtTextView->GetTextEngine()->HasUndoManager() || !mpExtTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() )
		{
			pPopup->EnableItem( SV_MENU_EDIT_UNDO, sal_False );
		}
//		if ( ( maSelection.Min() == 0 ) && ( maSelection.Max() == maText.Len() ) )
//		{
//			pPopup->EnableItem( SV_MENU_EDIT_SELECTALL, sal_False );
//		}
		if ( !Edit::GetGetSpecialCharsFunction() )
		{
			sal_uInt16 nPos = pPopup->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL );
			pPopup->RemoveItem( nPos );
			pPopup->RemoveItem( nPos-1 );
		}

		mbActivePopup = sal_True;
		Point aPos = rCEvt.GetMousePosPixel();
		if ( !rCEvt.IsMouseEvent() )
		{
			// !!! Irgendwann einmal Menu zentriert in der Selektion anzeigen !!!
			Size aSize = GetOutputSizePixel();
			aPos = Point( aSize.Width()/2, aSize.Height()/2 );
		}
//		pPopup->RemoveDisabledEntries();
		sal_uInt16 n = pPopup->Execute( this, aPos );
		Edit::DeletePopupMenu( pPopup );
		switch ( n )
		{
			case SV_MENU_EDIT_UNDO: 	mpExtTextView->Undo();
										mpExtTextEngine->SetModified( sal_True );
										mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
										break;
			case SV_MENU_EDIT_CUT:		mpExtTextView->Cut();
										mpExtTextEngine->SetModified( sal_True );
										mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
										break;
			case SV_MENU_EDIT_COPY: 	mpExtTextView->Copy();
										break;
			case SV_MENU_EDIT_PASTE:	mpExtTextView->Paste();
										mpExtTextEngine->SetModified( sal_True );
										mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
										break;
			case SV_MENU_EDIT_DELETE:	mpExtTextView->DeleteSelected();
										mpExtTextEngine->SetModified( sal_True );
										mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
										break;
			case SV_MENU_EDIT_SELECTALL:	mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFFFFFF, 0xFFFF ) ) );
											break;
			case SV_MENU_EDIT_INSERTSYMBOL:
				{
					XubString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() );
					if ( aChars.Len() )
					{
						mpExtTextView->InsertText( aChars );
						mpExtTextEngine->SetModified( sal_True );
						mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
					}
				}
				break;
		}
		mbActivePopup = sal_False;
	}
	else
	{
		mpExtTextView->Command( rCEvt );
	}
	Window::Command( rCEvt );
}

void TextWindow::GetFocus()
{
    Window::GetFocus();

    if ( !mbActivePopup )
    {
        sal_Bool bGotoCursor = !mpExtTextView->IsReadOnly();
        if ( mbFocusSelectionHide
             && IsReallyVisible()
             && !mpExtTextView->IsReadOnly()
             && ( mbSelectOnTab
                  && ( !mbInMBDown
                       || ( GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_FOCUS ) ) ) )
        {
            // Alles selektieren, aber nicht scrollen
            sal_Bool bAutoScroll = mpExtTextView->IsAutoScroll();
            mpExtTextView->SetAutoScroll( sal_False );
            mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) );
            mpExtTextView->SetAutoScroll( bAutoScroll );
            bGotoCursor = sal_False;
        }
        mpExtTextView->SetPaintSelection( sal_True );
        mpExtTextView->ShowCursor( bGotoCursor );
    }
}


void TextWindow::LoseFocus()
{
    Window::LoseFocus();

    if ( mbFocusSelectionHide && !mbActivePopup )
        mpExtTextView->SetPaintSelection( sal_False );
}


// virtual
::css::uno::Reference< ::css::awt::XWindowPeer >
TextWindow::GetComponentInterface(sal_Bool bCreate)
{
    ::css::uno::Reference< ::css::awt::XWindowPeer > xPeer(
        Window::GetComponentInterface(false));
    if (!xPeer.is() && bCreate)
    {
        xPeer = new ::svt::TextWindowPeer(*GetTextView(), true);
        SetComponentInterface(xPeer);
    }
    return xPeer;
}

MultiLineEdit::MultiLineEdit( Window* pParent, WinBits nWinStyle )
	: Edit( pParent, nWinStyle )
{
	SetType( WINDOW_MULTILINEEDIT );
	pImpSvMEdit = new ImpSvMEdit( this, nWinStyle );
	ImplInitSettings( sal_True, sal_True, sal_True );
	pUpdateDataTimer = 0;

	SetCompoundControl( sal_True );
	SetStyle( ImplInitStyle( nWinStyle ) );
}

MultiLineEdit::MultiLineEdit( Window* pParent, const ResId& rResId )
	: Edit( pParent, rResId.SetRT( RSC_MULTILINEEDIT ) )
{
	SetType( WINDOW_MULTILINEEDIT );
    WinBits nWinStyle = rResId.GetWinBits();
	pImpSvMEdit = new ImpSvMEdit( this, nWinStyle );
	ImplInitSettings( sal_True, sal_True, sal_True );
	pUpdateDataTimer = 0;

	sal_uInt16 nMaxLen = Edit::GetMaxTextLen();
	if ( nMaxLen )
		SetMaxTextLen( nMaxLen );

	SetText( Edit::GetText() );

	if ( IsVisible() )
		pImpSvMEdit->Resize();

	SetCompoundControl( sal_True );
	SetStyle( ImplInitStyle( nWinStyle ) );

    // Base Edit ctor could call Show already, but that would cause problems
    // with accessibility, as Show might (indirectly) trigger a call to virtual
    // GetComponentInterface, which is the Edit's base version instead of the
    // MultiLineEdit's version while in the base Edit ctor:
    if ((GetStyle() & WB_HIDE) == 0)
        Show();
}

MultiLineEdit::~MultiLineEdit()
{
    {
        ::std::auto_ptr< ImpSvMEdit > pDelete( pImpSvMEdit );
        pImpSvMEdit = NULL;
    }
	delete pUpdateDataTimer;
}

WinBits MultiLineEdit::ImplInitStyle( WinBits nStyle )
{
	if ( !(nStyle & WB_NOTABSTOP) )
		nStyle |= WB_TABSTOP;

	if ( !(nStyle & WB_NOGROUP) )
		nStyle |= WB_GROUP;

	if ( !(nStyle & WB_IGNORETAB ))
		nStyle |= WINDOW_DLGCTRL_MOD1TAB;

	return nStyle;
}


void MultiLineEdit::ImplInitSettings( sal_Bool /*bFont*/, sal_Bool /*bForeground*/, sal_Bool bBackground )
{
	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();

	// Der Font muss immer mit manipuliert werden, weil die TextEngine
	// sich nicht um TextColor/Background kuemmert

	Color aTextColor = rStyleSettings.GetFieldTextColor();
	if ( IsControlForeground() )
		aTextColor = GetControlForeground();
    if ( !IsEnabled() )
        aTextColor = rStyleSettings.GetDisableColor();

	Font aFont = rStyleSettings.GetFieldFont();
	if ( IsControlFont() )
		aFont.Merge( GetControlFont() );
	aFont.SetTransparent( IsPaintTransparent() );
	SetZoomedPointFont( aFont );
	Font TheFont = GetFont();
	TheFont.SetColor( aTextColor );
    if( IsPaintTransparent() )
        TheFont.SetFillColor( Color( COL_TRANSPARENT ) );
    else
        TheFont.SetFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() );
	pImpSvMEdit->GetTextWindow()->SetFont( TheFont );
	pImpSvMEdit->GetTextWindow()->GetTextEngine()->SetFont( TheFont );
	pImpSvMEdit->GetTextWindow()->SetTextColor( aTextColor );

	if ( bBackground )
	{
        if( IsPaintTransparent() )
        {
            pImpSvMEdit->GetTextWindow()->SetPaintTransparent( sal_True );
            pImpSvMEdit->GetTextWindow()->SetBackground();
            pImpSvMEdit->GetTextWindow()->SetControlBackground();
            SetBackground();
            SetControlBackground();
        }
        else
        {
            if( IsControlBackground() )
                pImpSvMEdit->GetTextWindow()->SetBackground( GetControlBackground() );
            else
                pImpSvMEdit->GetTextWindow()->SetBackground( rStyleSettings.GetFieldColor() );
            // Auch am MultiLineEdit einstellen, weil die TextComponent
            // ggf. die Scrollbars hidet.
            SetBackground( pImpSvMEdit->GetTextWindow()->GetBackground() );
        }
	}
}

void MultiLineEdit::Modify()
{
	aModifyHdlLink.Call( this );

    CallEventListeners( VCLEVENT_EDIT_MODIFY );

    if ( pUpdateDataTimer )
		pUpdateDataTimer->Start();
}

IMPL_LINK( MultiLineEdit, ImpUpdateDataHdl, Timer*, EMPTYARG )
{
	UpdateData();
	return 0;
}

void MultiLineEdit::UpdateData()
{
	aUpdateDataHdlLink.Call( this );
}

void MultiLineEdit::SetModifyFlag()
{
	pImpSvMEdit->SetModified( sal_True );
}

void MultiLineEdit::ClearModifyFlag()
{
	pImpSvMEdit->SetModified( sal_False );
}

sal_Bool MultiLineEdit::IsModified() const
{
	return pImpSvMEdit->IsModified();
}

void MultiLineEdit::EnableUpdateData( sal_uLong nTimeout )
{
	if ( !nTimeout )
		DisableUpdateData();
	else
	{
		if ( !pUpdateDataTimer )
		{
			pUpdateDataTimer = new Timer;
			pUpdateDataTimer->SetTimeoutHdl( LINK( this, MultiLineEdit, ImpUpdateDataHdl ) );
		}
		pUpdateDataTimer->SetTimeout( nTimeout );
	}
}

void MultiLineEdit::SetReadOnly( sal_Bool bReadOnly )
{
	pImpSvMEdit->SetReadOnly( bReadOnly );
	Edit::SetReadOnly( bReadOnly );

    // #94921# ReadOnly can be overwritten in InitFromStyle() when WB not set.
    WinBits nStyle = GetStyle();
    if ( bReadOnly )
        nStyle |= WB_READONLY;
    else
        nStyle &= ~WB_READONLY;
    SetStyle( nStyle );
}

sal_Bool MultiLineEdit::IsReadOnly() const
{
	return pImpSvMEdit->IsReadOnly();
}

void MultiLineEdit::SetMaxTextLen( xub_StrLen nMaxLen )
{
	pImpSvMEdit->SetMaxTextLen( nMaxLen );
}

xub_StrLen MultiLineEdit::GetMaxTextLen() const
{
	return pImpSvMEdit->GetMaxTextLen();
}

void MultiLineEdit::ReplaceSelected( const String& rStr )
{
	pImpSvMEdit->InsertText( rStr );
}

void MultiLineEdit::DeleteSelected()
{
	pImpSvMEdit->InsertText( String() );
}

String MultiLineEdit::GetSelected() const
{
	return pImpSvMEdit->GetSelected();
}

String MultiLineEdit::GetSelected( LineEnd aSeparator ) const
{
	return pImpSvMEdit->GetSelected( aSeparator );
}

void MultiLineEdit::Cut()
{
	pImpSvMEdit->Cut();
}

void MultiLineEdit::Copy()
{
	pImpSvMEdit->Copy();
}

void MultiLineEdit::Paste()
{
	pImpSvMEdit->Paste();
}

void MultiLineEdit::SetText( const String& rStr )
{
	pImpSvMEdit->SetText( rStr );
}

String MultiLineEdit::GetText() const
{
	return pImpSvMEdit->GetText();
}

String MultiLineEdit::GetText( LineEnd aSeparator ) const
{
	return pImpSvMEdit->GetText( aSeparator );
}

String MultiLineEdit::GetTextLines() const
{
	return pImpSvMEdit->GetTextLines();
}

String MultiLineEdit::GetTextLines(  LineEnd aSeparator ) const
{
	return pImpSvMEdit->GetTextLines( aSeparator );
}

void MultiLineEdit::Resize()
{
	pImpSvMEdit->Resize();
}

void MultiLineEdit::GetFocus()
{
    if ( pImpSvMEdit == NULL )  // might be called from within the dtor, when pImpSvMEdit == NULL is a valid state
        return;

    Edit::GetFocus();

    pImpSvMEdit->GetFocus();
}


void MultiLineEdit::SetSelection( const Selection& rSelection )
{
	pImpSvMEdit->SetSelection( rSelection );
}

const Selection& MultiLineEdit::GetSelection() const
{
	return pImpSvMEdit->GetSelection();
}

Size MultiLineEdit::CalcMinimumSize() const
{
	Size aSz = pImpSvMEdit->CalcMinimumSize();

	sal_Int32 nLeft, nTop, nRight, nBottom;
	((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
	aSz.Width() += nLeft+nRight;
	aSz.Height() += nTop+nBottom;

	return aSz;
}

Size MultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const
{
	Size aSz = rPrefSize;
	sal_Int32 nLeft, nTop, nRight, nBottom;
	((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );

	// In der Hoehe auf ganze Zeilen justieren

	long nHeight = aSz.Height() - nTop - nBottom;
	long nLineHeight = pImpSvMEdit->CalcSize( 1, 1 ).Height();
	long nLines = nHeight / nLineHeight;
	if ( nLines < 1 )
		nLines = 1;

	aSz.Height() = nLines * nLineHeight;
	aSz.Height() += nTop+nBottom;

	return aSz;
}

Size MultiLineEdit::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
{
	Size aSz = pImpSvMEdit->CalcSize( nColumns, nLines );

	sal_Int32 nLeft, nTop, nRight, nBottom;
	((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
	aSz.Width() += nLeft+nRight;
	aSz.Height() += nTop+nBottom;
	return aSz;
}

void MultiLineEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
{
	pImpSvMEdit->GetMaxVisColumnsAndLines( rnCols, rnLines );
}

void MultiLineEdit::StateChanged( StateChangedType nType )
{
	if( nType == STATE_CHANGE_ENABLE )
	{
		pImpSvMEdit->Enable( IsEnabled() );
		ImplInitSettings( sal_True, sal_False, sal_False );
	}
	else if( nType == STATE_CHANGE_READONLY )
	{
		pImpSvMEdit->SetReadOnly( IsReadOnly() );
	}
	else if ( nType == STATE_CHANGE_ZOOM )
	{
		pImpSvMEdit->GetTextWindow()->SetZoom( GetZoom() );
		ImplInitSettings( sal_True, sal_False, sal_False );
		Resize();
	}
	else if ( nType == STATE_CHANGE_CONTROLFONT )
	{
		ImplInitSettings( sal_True, sal_False, sal_False );
		Resize();
		Invalidate();
	}
	else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
	{
		ImplInitSettings( sal_False, sal_True, sal_False );
		Invalidate();
	}
	else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
	{
		ImplInitSettings( sal_False, sal_False, sal_True );
		Invalidate();
	}
	else if ( nType == STATE_CHANGE_STYLE )
	{
		pImpSvMEdit->InitFromStyle( GetStyle() );
		SetStyle( ImplInitStyle( GetStyle() ) );
	}
    else if ( nType == STATE_CHANGE_INITSHOW )
    {
        if( IsPaintTransparent() )
        {
            pImpSvMEdit->GetTextWindow()->SetPaintTransparent( sal_True );
            pImpSvMEdit->GetTextWindow()->SetBackground();
            pImpSvMEdit->GetTextWindow()->SetControlBackground();
            SetBackground();
            SetControlBackground();
        }
    }

	Control::StateChanged( nType );
}

void MultiLineEdit::DataChanged( const DataChangedEvent& rDCEvt )
{
	if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
		 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
	{
		ImplInitSettings( sal_True, sal_True, sal_True );
		Resize();
		Invalidate();
	}
	else
		Control::DataChanged( rDCEvt );
}

void MultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
{
	ImplInitSettings( sal_True, sal_True, sal_True );

	Point aPos = pDev->LogicToPixel( rPos );
	Size aSize = pDev->LogicToPixel( rSize );
	Font aFont = pImpSvMEdit->GetTextWindow()->GetDrawPixelFont( pDev );
	aFont.SetTransparent( sal_True );
	OutDevType eOutDevType = pDev->GetOutDevType();

	pDev->Push();
	pDev->SetMapMode();
	pDev->SetFont( aFont );
	pDev->SetTextFillColor();

	// Border/Background
	pDev->SetLineColor();
	pDev->SetFillColor();
	sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
	sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
	if ( bBorder || bBackground )
	{
		Rectangle aRect( aPos, aSize );
		if ( bBorder )
		{
			DecorationView aDecoView( pDev );
			aRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN );
		}
		if ( bBackground )
		{
			pDev->SetFillColor( GetControlBackground() );
			pDev->DrawRect( aRect );
		}
	}

	// Inhalt
	if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
		pDev->SetTextColor( Color( COL_BLACK ) );
	else
	{
		if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
		{
			const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
			pDev->SetTextColor( rStyleSettings.GetDisableColor() );
		}
		else
		{
			pDev->SetTextColor( GetTextColor() );
		}
	}

	XubString aText = GetText();
	Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() );
	sal_uLong nLines = (sal_uLong) (aSize.Height() / aTextSz.Height());
	if ( !nLines )
		nLines = 1;
	aTextSz.Height() = nLines*aTextSz.Height();
	long nOnePixel = GetDrawPixel( pDev, 1 );
	long nOffX = 3*nOnePixel;
	long nOffY = 2*nOnePixel;

	// Clipping?
	if ( ( nOffY < 0  ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) )
	{
		Rectangle aClip( aPos, aSize );
		if ( aTextSz.Height() > aSize.Height() )
			aClip.Bottom() += aTextSz.Height() - aSize.Height() + 1;  // Damit HP-Drucker nicht 'weg-optimieren'
		pDev->IntersectClipRegion( aClip );
	}

	TextEngine aTE;
	aTE.SetText( GetText() );
	aTE.SetMaxTextWidth( aSize.Width() );
	aTE.SetFont( aFont );
	aTE.SetTextAlign( pImpSvMEdit->GetTextWindow()->GetTextEngine()->GetTextAlign() );
	aTE.Draw( pDev, Point( aPos.X() + nOffX, aPos.Y() + nOffY ) );

	pDev->Pop();
}

long MultiLineEdit::Notify( NotifyEvent& rNEvt )
{
	long nDone = 0;
	if( rNEvt.GetType() == EVENT_COMMAND )
	{
		nDone = pImpSvMEdit->HandleCommand( *rNEvt.GetCommandEvent() );
	}
	return nDone ? nDone : Edit::Notify( rNEvt );
}

long MultiLineEdit::PreNotify( NotifyEvent& rNEvt )
{
	long nDone = 0;

#if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL)
	if( rNEvt.GetType() == EVENT_KEYINPUT )
	{
		const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
        if ( ( rKEvent.GetKeyCode().GetCode() == KEY_W ) && rKEvent.GetKeyCode().IsMod1() && rKEvent.GetKeyCode().IsMod2() )
        {
            SetRightToLeft( !IsRightToLeft() );
        }
    }
#endif

	if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) )
	{
		const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
		if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) )
		{
			nDone = 1;
			TextSelection aSel = pImpSvMEdit->GetTextWindow()->GetTextView()->GetSelection();
			if ( aSel.HasRange() )
			{
				aSel.GetStart() = aSel.GetEnd();
				pImpSvMEdit->GetTextWindow()->GetTextView()->SetSelection( aSel );
			}
			else
			{
				switch ( rKEvent.GetKeyCode().GetCode() )
				{
					case KEY_UP:
					{
						if ( pImpSvMEdit->GetVScrollBar() )
							pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEUP );
					}
					break;
					case KEY_DOWN:
					{
						if ( pImpSvMEdit->GetVScrollBar() )
							pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEDOWN );
					}
					break;
					case KEY_PAGEUP	:
					{
						if ( pImpSvMEdit->GetVScrollBar() )
							pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEUP );
					}
					break;
					case KEY_PAGEDOWN:
					{
						if ( pImpSvMEdit->GetVScrollBar() )
							pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEDOWN );
					}
					break;
					case KEY_LEFT:
					{
						if ( pImpSvMEdit->GetHScrollBar() )
							pImpSvMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEUP );
					}
					break;
					case KEY_RIGHT:
					{
						if ( pImpSvMEdit->GetHScrollBar() )
							pImpSvMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEDOWN );
					}
					break;
					case KEY_HOME:
					{
						if ( rKEvent.GetKeyCode().IsMod1() )
							pImpSvMEdit->GetTextWindow()->GetTextView()->
								SetSelection( TextSelection( TextPaM( 0, 0 ) ) );
					}
					break;
					case KEY_END:
					{
						if ( rKEvent.GetKeyCode().IsMod1() )
							pImpSvMEdit->GetTextWindow()->GetTextView()->
								SetSelection( TextSelection( TextPaM( 0xFFFF, 0xFFFF ) ) );
					}
					break;
					default:
					{
						nDone = 0;
					}
				}
			}
		}
	}

	return nDone ? nDone : Edit::PreNotify( rNEvt );
}

//
// Internas fuer abgeleitete Klassen, z.B. TextComponent

ExtTextEngine* MultiLineEdit::GetTextEngine() const
{
	return pImpSvMEdit->GetTextWindow()->GetTextEngine();
}

ExtTextView* MultiLineEdit::GetTextView() const
{
	return pImpSvMEdit->GetTextWindow()->GetTextView();
}

ScrollBar* MultiLineEdit::GetHScrollBar() const
{
	return pImpSvMEdit->GetHScrollBar();
}


ScrollBar* MultiLineEdit::GetVScrollBar() const
{
	return pImpSvMEdit->GetVScrollBar();
}

void MultiLineEdit::EnableFocusSelectionHide( sal_Bool bHide )
{
	pImpSvMEdit->GetTextWindow()->SetAutoFocusHide( bHide );
}

sal_Bool MultiLineEdit::IsFocusSelectionHideEnabled() const
{
	return pImpSvMEdit->GetTextWindow()->IsAutoFocusHide();
}


void MultiLineEdit::SetLeftMargin( sal_uInt16 n )
{
    if ( GetTextEngine() )
        GetTextEngine()->SetLeftMargin( n );
}

sal_uInt16 MultiLineEdit::GetLeftMargin() const
{
    if ( GetTextEngine() )
        return GetTextEngine()->GetLeftMargin();
    else
        return 0;
}

void MultiLineEdit::SetRightToLeft( sal_Bool bRightToLeft )
{
    if ( GetTextEngine() )
    {
        GetTextEngine()->SetRightToLeft( bRightToLeft );
        GetTextView()->ShowCursor();
    }
}

sal_Bool MultiLineEdit::IsRightToLeft() const
{
    sal_Bool bRightToLeft = sal_False;

    if ( GetTextEngine() )
        bRightToLeft = GetTextEngine()->IsRightToLeft();

    return bRightToLeft;
}

// virtual
::css::uno::Reference< ::css::awt::XWindowPeer >
MultiLineEdit::GetComponentInterface(sal_Bool bCreate)
{
    ::css::uno::Reference< ::css::awt::XWindowPeer > xPeer(
        Edit::GetComponentInterface(false));
    if (!xPeer.is() && bCreate)
    {
        ::std::auto_ptr< VCLXMultiLineEdit > xEdit(new VCLXMultiLineEdit());
        xEdit->SetWindow(this);
        xPeer = xEdit.release();
        SetComponentInterface(xPeer);
    }
    return xPeer;
}
/*-- 11.08.2004 11:29:23---------------------------------------------------

  -----------------------------------------------------------------------*/
void MultiLineEdit::DisableSelectionOnFocus()
{
    pImpSvMEdit->GetTextWindow()->DisableSelectionOnFocus();
}
