/**************************************************************
 * 
 * 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 <tools/stream.hxx>

#include <svtools/texteng.hxx>
#include <svtools/textview.hxx>
#include <textdoc.hxx>
#include <textdat2.hxx>
#include <textundo.hxx>
#include <textund2.hxx>
#include <svl/ctloptions.hxx>
#include <vcl/window.hxx>

#include <vcl/edit.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/PropertyValues.hpp>

#ifndef _COM_SUN_STAR_TEXT_XBREAKITERATOR_HPP_
#include <com/sun/star/i18n/XBreakIterator.hpp>
#endif

#ifndef _COM_SUN_STAR_TEXT_CHARACTERITERATORMODE_HPP_
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
#endif

#ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
#include <com/sun/star/i18n/WordType.hpp>
#endif

#ifndef _COM_SUN_STAR_I18N_XEXTENDEDINPUTSEQUENCECHECKER_HDL_
#include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp>
#endif
#include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
#include <com/sun/star/i18n/ScriptType.hpp>

#include <comphelper/processfactory.hxx>

#include <unotools/localedatawrapper.hxx>
#include <vcl/unohelp.hxx>

#include <vcl/svapp.hxx>
#include <vcl/unohelp.hxx>
#include <vcl/metric.hxx>

#include <unicode/ubidi.h>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::rtl;

typedef TextView* TextViewPtr;
SV_DECL_PTRARR( TextViews, TextViewPtr, 0, 1 )
// SV_IMPL_PTRARR( TextViews, TextViewPtr );

SV_DECL_VARARR_SORT( TESortedPositions, sal_uLong, 16, 8 )
SV_IMPL_VARARR_SORT( TESortedPositions, sal_uLong )

#define RESDIFF		10
#define SCRLRANGE	20		// 1/20 der Breite/Hoehe scrollen, wenn im QueryDrop


// -------------------------------------------------------------------------
// (-) class TextEngine
// -------------------------------------------------------------------------
TextEngine::TextEngine()
{
	mpDoc = 0;
	mpTEParaPortions = 0;

	mpViews = new TextViews;
	mpActiveView = NULL;

	mbIsFormatting		= sal_False;
	mbFormatted			= sal_False;
	mbUpdate 			= sal_True;
	mbModified			= sal_False;
	mbUndoEnabled 		= sal_False;
	mbIsInUndo			= sal_False;
	mbDowning			= sal_False;
    mbRightToLeft		= sal_False;
	mbHasMultiLineParas = sal_False;

	meAlign			= TXTALIGN_LEFT;

	mnMaxTextWidth	= 0;
	mnMaxTextLen 	= 0;
	mnCurTextWidth	= 0xFFFFFFFF;
	mnCurTextHeight	= 0;

	mpUndoManager 	= NULL;
   	mpIMEInfos		= NULL;
    mpLocaleDataWrapper = NULL;

    mpIdleFormatter = new IdleFormatter;
	mpIdleFormatter->SetTimeoutHdl( LINK( this, TextEngine, IdleFormatHdl ) );

	mpRefDev = new VirtualDevice;

    ImpInitLayoutMode( mpRefDev );

	ImpInitDoc();

    maTextColor = COL_BLACK;
	Font aFont;
	aFont.SetTransparent( sal_False );
	Color aFillColor( aFont.GetFillColor() );
	aFillColor.SetTransparency( 0 );
	aFont.SetFillColor( aFillColor );
	SetFont( aFont );
}

TextEngine::~TextEngine()
{
	mbDowning = sal_True;

	delete mpIdleFormatter;
	delete mpDoc;
	delete mpTEParaPortions;
	delete mpViews;	// nur die Liste, nicht die Vies
	delete mpRefDev;
	delete mpUndoManager;
	delete mpIMEInfos;
    delete mpLocaleDataWrapper;
}

void TextEngine::InsertView( TextView* pTextView )
{
	mpViews->Insert( pTextView, mpViews->Count() );
	pTextView->SetSelection( TextSelection() );

	if ( !GetActiveView() )
		SetActiveView( pTextView );
}

void TextEngine::RemoveView( TextView* pTextView )
{
	sal_uInt16 nPos = mpViews->GetPos( pTextView );
	if( nPos != USHRT_MAX )
	{
		pTextView->HideCursor();
		mpViews->Remove( nPos, 1 );
		if ( pTextView == GetActiveView() )
			SetActiveView( 0 );
	}
}

sal_uInt16 TextEngine::GetViewCount() const
{
	return mpViews->Count();
}

TextView* TextEngine::GetView( sal_uInt16 nView ) const
{
	return mpViews->GetObject( nView );
}

TextView* TextEngine::GetActiveView() const
{
	return mpActiveView;
}

void TextEngine::SetActiveView( TextView* pTextView )
{
	if ( pTextView != mpActiveView )
	{
		if ( mpActiveView )
			mpActiveView->HideSelection();

		mpActiveView = pTextView;

		if ( mpActiveView )
			mpActiveView->ShowSelection();
	}
}

void TextEngine::SetFont( const Font& rFont )
{
	if ( rFont != maFont )
	{
		maFont = rFont;
        // #i40221# As the font's color now defaults to transparent (since i35764)
        //  we have to choose a useful textcolor in this case.
        // Otherwise maTextColor and maFont.GetColor() are both transparent....
		if( rFont.GetColor() == COL_TRANSPARENT )
		    maTextColor = COL_BLACK;
        else
            maTextColor = rFont.GetColor();

		// Wegen Selektion keinen Transparenten Font zulassen...
		// (Sonst spaeter in ImplPaint den Hintergrund anders loeschen...)
		maFont.SetTransparent( sal_False );
		// Tell VCL not to use the font color, use text color from OutputDevice
		maFont.SetColor( COL_TRANSPARENT );
		Color aFillColor( maFont.GetFillColor() );
		aFillColor.SetTransparency( 0 );
		maFont.SetFillColor( aFillColor );

		maFont.SetAlign( ALIGN_TOP );
		mpRefDev->SetFont( maFont);
		Size aTextSize;
		aTextSize.Width() = mpRefDev->GetTextWidth( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "    " ) ) );
		aTextSize.Height() = mpRefDev->GetTextHeight();
		if ( !aTextSize.Width() )
			aTextSize.Width() = mpRefDev->GetTextWidth( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "XXXX" ) ) );

		mnDefTab = (sal_uInt16)aTextSize.Width();
		if ( !mnDefTab )
			mnDefTab = 1;
		mnCharHeight = (sal_uInt16)aTextSize.Height();
/*
        // #93746# Doesn't work with CJK HalfWidth/FullWidth
        FontMetric aRealFont( mpRefDev->GetFontMetric() );
		if ( aRealFont.GetPitch() == PITCH_FIXED )
		{
			String aX100;
			aX100.Fill( 100, 'X' );
			mnFixCharWidth100 = (sal_uInt16)mpRefDev->GetTextWidth( aX100 );
		}
		else
*/
		mnFixCharWidth100 = 0;

		FormatFullDoc();
		UpdateViews();

		for ( sal_uInt16 nView = mpViews->Count(); nView; )
		{
			TextView* pView = mpViews->GetObject( --nView );
            pView->GetWindow()->SetInputContext( InputContext( GetFont(), !pView->IsReadOnly() ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) );
        }
	}
}

void TextEngine::SetDefTab( sal_uInt16 nDefTab )
{
	mnDefTab = nDefTab;
	// evtl neu setzen?
}

void TextEngine::SetMaxTextLen( sal_uLong nLen )
{
	mnMaxTextLen = nLen;
}

void TextEngine::SetMaxTextWidth( sal_uLong nMaxWidth )
{
	if ( nMaxWidth != mnMaxTextWidth )
	{
		mnMaxTextWidth = Min( nMaxWidth, (sal_uLong)0x7FFFFFFF );
		FormatFullDoc();
		UpdateViews();
	}
}

static sal_Unicode static_aLFText[] = { '\n', 0 };
static sal_Unicode static_aCRText[] = { '\r', 0 };
static sal_Unicode static_aCRLFText[] = { '\r', '\n', 0 };

static inline const sal_Unicode* static_getLineEndText( LineEnd aLineEnd )
{
	const sal_Unicode* pRet = NULL;

	switch( aLineEnd )
	{
	case LINEEND_LF: pRet = static_aLFText;break;
	case LINEEND_CR: pRet = static_aCRText;break;
	case LINEEND_CRLF: pRet = static_aCRLFText;break;
	}
	return pRet;
}

void  TextEngine::ReplaceText(const TextSelection& rSel, const String& rText)
{        
    ImpInsertText( rSel, rText );
}

String TextEngine::GetText( LineEnd aSeparator ) const
{
	return mpDoc->GetText( static_getLineEndText( aSeparator ) );
}

String TextEngine::GetTextLines( LineEnd aSeparator ) const
{
	String aText;
	sal_uLong nParas = mpTEParaPortions->Count();
	const sal_Unicode* pSep = static_getLineEndText( aSeparator );
	for ( sal_uLong nP = 0; nP < nParas; nP++ )
	{
		TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nP );

		sal_uInt16 nLines = pTEParaPortion->GetLines().Count();
		for ( sal_uInt16 nL = 0; nL < nLines; nL++ )
		{
			TextLine* pLine = pTEParaPortion->GetLines()[nL];
			aText += pTEParaPortion->GetNode()->GetText().Copy( pLine->GetStart(), pLine->GetEnd() - pLine->GetStart() );
			if ( pSep && ( ( (nP+1) < nParas ) || ( (nL+1) < nLines ) ) )
				aText += pSep;
		}
	}
	return aText;
}

String TextEngine::GetText( sal_uLong nPara ) const
{
	return mpDoc->GetText( nPara );
}

sal_uLong TextEngine::GetTextLen( LineEnd aSeparator ) const
{
	return mpDoc->GetTextLen( static_getLineEndText( aSeparator ) );
}

sal_uLong TextEngine::GetTextLen( const TextSelection& rSel, LineEnd aSeparator ) const
{
	TextSelection aSel( rSel );
	aSel.Justify();
	ValidateSelection( aSel );
	return mpDoc->GetTextLen( static_getLineEndText( aSeparator ), &aSel );
}

sal_uInt16 TextEngine::GetTextLen( sal_uLong nPara ) const
{
	return mpDoc->GetNodes().GetObject( nPara )->GetText().Len();
}

void TextEngine::SetUpdateMode( sal_Bool bUpdate )
{
	if ( bUpdate != mbUpdate )
	{
		mbUpdate = bUpdate;
		if ( mbUpdate )
		{
			FormatAndUpdate( GetActiveView() );
			if ( GetActiveView() )
				GetActiveView()->ShowCursor();
		}
	}
}

sal_Bool TextEngine::DoesKeyMoveCursor( const KeyEvent& rKeyEvent )
{
	sal_Bool bDoesMove = sal_False;

	switch ( rKeyEvent.GetKeyCode().GetCode() )
	{
		case KEY_UP:
		case KEY_DOWN:
		case KEY_LEFT:
		case KEY_RIGHT:
		case KEY_HOME:
		case KEY_END:
		case KEY_PAGEUP:
		case KEY_PAGEDOWN:
		{
			if ( !rKeyEvent.GetKeyCode().IsMod2() )
				bDoesMove = sal_True;
		}
		break;
	}
	return bDoesMove;
}

sal_Bool TextEngine::DoesKeyChangeText( const KeyEvent& rKeyEvent )
{
	sal_Bool bDoesChange = sal_False;

	KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
	if ( eFunc != KEYFUNC_DONTKNOW )
	{
		switch ( eFunc )
		{
			case KEYFUNC_UNDO:
			case KEYFUNC_REDO:
			case KEYFUNC_CUT:
			case KEYFUNC_PASTE:	bDoesChange = sal_True;
			break;
			default:	// wird dann evtl. unten bearbeitet.
						eFunc = KEYFUNC_DONTKNOW;
		}
	}
	if ( eFunc == KEYFUNC_DONTKNOW )
	{
		switch ( rKeyEvent.GetKeyCode().GetCode() )
		{
			case KEY_DELETE:
			case KEY_BACKSPACE:
			{
				if ( !rKeyEvent.GetKeyCode().IsMod2() )
					bDoesChange = sal_True;
			}
			break;
			case KEY_RETURN:
			case KEY_TAB:
			{
				if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() )
					bDoesChange = sal_True;
			}
			break;
			default:
			{
				bDoesChange = TextEngine::IsSimpleCharInput( rKeyEvent );
			}
		}
	}
	return bDoesChange;
}

sal_Bool TextEngine::IsSimpleCharInput( const KeyEvent& rKeyEvent )
{
	if( rKeyEvent.GetCharCode() >= 32 && rKeyEvent.GetCharCode() != 127 &&
        KEY_MOD1 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT) && // (ssa) #i45714#:
        KEY_MOD2 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT) )  // check for Ctrl and Alt separately
	{
		return sal_True;
	}
	return sal_False;
}

void TextEngine::ImpInitDoc()
{
	if ( mpDoc )
		mpDoc->Clear();
	else
		mpDoc = new TextDoc;

	delete mpTEParaPortions;
	mpTEParaPortions = new TEParaPortions;

	TextNode* pNode = new TextNode( String() );
	mpDoc->GetNodes().Insert( pNode, 0 );

	TEParaPortion* pIniPortion = new TEParaPortion( pNode );
	mpTEParaPortions->Insert( pIniPortion, (sal_uLong)0 );

	mbFormatted = sal_False;

	ImpParagraphRemoved( TEXT_PARA_ALL );
	ImpParagraphInserted( 0 );
}

String TextEngine::GetText( const TextSelection& rSel, LineEnd aSeparator ) const
{
	String aText;

	if ( !rSel.HasRange() )
		return aText;

	TextSelection aSel( rSel );
	aSel.Justify();

	sal_uLong nStartPara = aSel.GetStart().GetPara();
	sal_uLong nEndPara = aSel.GetEnd().GetPara();
	const sal_Unicode* pSep = static_getLineEndText( aSeparator );
	for ( sal_uLong nNode = aSel.GetStart().GetPara(); nNode <= nEndPara; nNode++ )
	{
		TextNode* pNode = mpDoc->GetNodes().GetObject( nNode );

		sal_uInt16 nStartPos = 0;
		sal_uInt16 nEndPos = pNode->GetText().Len();
		if ( nNode == nStartPara )
			nStartPos = aSel.GetStart().GetIndex();
		if ( nNode == nEndPara ) // kann auch == nStart sein!
			nEndPos = aSel.GetEnd().GetIndex();

		aText += pNode->GetText().Copy( nStartPos, nEndPos-nStartPos );
		if ( nNode < nEndPara )
			aText += pSep;
	}
	return aText;
}

void TextEngine::ImpRemoveText()
{
	ImpInitDoc();

	TextPaM aStartPaM( 0, 0 );
	TextSelection aEmptySel( aStartPaM, aStartPaM );
	for ( sal_uInt16 nView = 0; nView < mpViews->Count(); nView++ )
	{
		TextView* pView = mpViews->GetObject( nView );
		pView->ImpSetSelection( aEmptySel );
	}
	ResetUndo();
}

void TextEngine::SetText( const XubString& rText )
{
	ImpRemoveText();

	sal_Bool bUndoCurrentlyEnabled = IsUndoEnabled();
	// Der von Hand reingesteckte Text kann nicht vom Anwender rueckgaengig gemacht werden.
	EnableUndo( sal_False );

	TextPaM aStartPaM( 0, 0 );
	TextSelection aEmptySel( aStartPaM, aStartPaM );

	TextPaM aPaM = aStartPaM;
	if ( rText.Len() )
		aPaM = ImpInsertText( aEmptySel, rText );

	for ( sal_uInt16 nView = 0; nView < mpViews->Count(); nView++ )
	{
		TextView* pView = mpViews->GetObject( nView );
		pView->ImpSetSelection( aEmptySel );

		// Wenn kein Text, dann auch Kein Format&Update
		// => Der Text bleibt stehen.
		if ( !rText.Len() && GetUpdateMode() )
			pView->Invalidate();
	}

	if( !rText.Len() )	// sonst muss spaeter noch invalidiert werden, !bFormatted reicht.
		mnCurTextHeight = 0;

	FormatAndUpdate();

	EnableUndo( bUndoCurrentlyEnabled );
	DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Undo nach SetText?" );
}


void TextEngine::CursorMoved( sal_uLong nNode )
{
	// Leere Attribute loeschen, aber nur, wenn Absatz nicht leer!
	TextNode* pNode = mpDoc->GetNodes().GetObject( nNode );
	if ( pNode && pNode->GetCharAttribs().HasEmptyAttribs() && pNode->GetText().Len() )
		pNode->GetCharAttribs().DeleteEmptyAttribs();
}

void TextEngine::ImpRemoveChars( const TextPaM& rPaM, sal_uInt16 nChars, SfxUndoAction* )
{
	DBG_ASSERT( nChars, "ImpRemoveChars - 0 Chars?!" );
	if ( IsUndoEnabled() && !IsInUndo() )
	{
		// Attribute muessen hier vorm RemoveChars fuer UNDO gesichert werden!
		TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() );
		XubString aStr( pNode->GetText().Copy( rPaM.GetIndex(), nChars ) );

		// Pruefen, ob Attribute geloescht oder geaendert werden:
		sal_uInt16 nStart = rPaM.GetIndex();
		sal_uInt16 nEnd = nStart + nChars;
		for ( sal_uInt16 nAttr = pNode->GetCharAttribs().Count(); nAttr; )
		{
			TextCharAttrib* pAttr = pNode->GetCharAttribs().GetAttrib( --nAttr );
			if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetStart() < nEnd ) )
			{
//				TextSelection aSel( rPaM );
//				aSel.GetEnd().GetIndex() += nChars;
//				TextUndoSetAttribs* pAttrUndo = CreateAttribUndo( aSel );
//				InsertUndo( pAttrUndo );
				break;	// for
			}
		}
//		if ( pCurUndo && ( CreateTextPaM( pCurUndo->GetEPaM() ) == rPaM ) )
//			pCurUndo->GetStr() += aStr;
//		else
			InsertUndo( new TextUndoRemoveChars( this, rPaM, aStr ) );
	}

	mpDoc->RemoveChars( rPaM, nChars );
	ImpCharsRemoved( rPaM.GetPara(), rPaM.GetIndex(), nChars );
}

TextPaM TextEngine::ImpConnectParagraphs( sal_uLong nLeft, sal_uLong nRight )
{
	DBG_ASSERT( nLeft != nRight, "Den gleichen Absatz zusammenfuegen ?" );

	TextNode* pLeft = mpDoc->GetNodes().GetObject( nLeft );
	TextNode* pRight = mpDoc->GetNodes().GetObject( nRight );

	if ( IsUndoEnabled() && !IsInUndo() )
		InsertUndo( new TextUndoConnectParas( this, nLeft, pLeft->GetText().Len() ) );

	// Erstmal Portions suchen, da pRight nach ConnectParagraphs weg.
	TEParaPortion* pLeftPortion = mpTEParaPortions->GetObject( nLeft );
	TEParaPortion* pRightPortion = mpTEParaPortions->GetObject( nRight );
	DBG_ASSERT( pLeft && pLeftPortion, "Blinde Portion in ImpConnectParagraphs(1)" );
	DBG_ASSERT( pRight && pRightPortion, "Blinde Portion in ImpConnectParagraphs(2)" );

	TextPaM aPaM = mpDoc->ConnectParagraphs( pLeft, pRight );
	ImpParagraphRemoved( nRight );

	pLeftPortion->MarkSelectionInvalid( aPaM.GetIndex(), pLeft->GetText().Len() );

	mpTEParaPortions->Remove( nRight );
	delete pRightPortion;
	// der rechte Node wird von EditDoc::ConnectParagraphs() geloescht.

	return aPaM;
}

TextPaM TextEngine::ImpDeleteText( const TextSelection& rSel )
{
	if ( !rSel.HasRange() )
		return rSel.GetStart();

	TextSelection aSel( rSel );
	aSel.Justify();
	TextPaM aStartPaM( aSel.GetStart() );
	TextPaM aEndPaM( aSel.GetEnd() );

	CursorMoved( aStartPaM.GetPara() ); // nur damit neu eingestellte Attribute verschwinden...
	CursorMoved( aEndPaM.GetPara() );	// nur damit neu eingestellte Attribute verschwinden...

	DBG_ASSERT( mpDoc->IsValidPaM( aStartPaM ), "Index im Wald in ImpDeleteText" );
	DBG_ASSERT( mpDoc->IsValidPaM( aEndPaM ), "Index im Wald in ImpDeleteText" );

	sal_uLong nStartNode = aStartPaM.GetPara();
	sal_uLong nEndNode = aEndPaM.GetPara();

	// Alle Nodes dazwischen entfernen....
	for ( sal_uLong z = nStartNode+1; z < nEndNode; z++ )
	{
		// Immer nStartNode+1, wegen Remove()!
		ImpRemoveParagraph( nStartNode+1 );
	}

	if ( nStartNode != nEndNode )
	{
		// Den Rest des StartNodes...
		TextNode* pLeft = mpDoc->GetNodes().GetObject( nStartNode );
		sal_uInt16 nChars = pLeft->GetText().Len() - aStartPaM.GetIndex();
		if ( nChars )
		{
			ImpRemoveChars( aStartPaM, nChars );
			TEParaPortion* pPortion = mpTEParaPortions->GetObject( nStartNode );
			DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteText(3)" );
			pPortion->MarkSelectionInvalid( aStartPaM.GetIndex(), pLeft->GetText().Len() );
		}

		// Den Anfang des EndNodes....
		nEndNode = nStartNode+1;	// Die anderen Absaetze wurden geloescht
		nChars = aEndPaM.GetIndex();
		if ( nChars )
		{
			aEndPaM.GetPara() = nEndNode;
			aEndPaM.GetIndex() = 0;
			ImpRemoveChars( aEndPaM, nChars );
			TEParaPortion* pPortion = mpTEParaPortions->GetObject( nEndNode );
			DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteText(4)" );
			pPortion->MarkSelectionInvalid( 0, pPortion->GetNode()->GetText().Len() );
		}

		// Zusammenfuegen....
		aStartPaM = ImpConnectParagraphs( nStartNode, nEndNode );
	}
	else
	{
		sal_uInt16 nChars;
		nChars = aEndPaM.GetIndex() - aStartPaM.GetIndex();
		ImpRemoveChars( aStartPaM, nChars );
		TEParaPortion* pPortion = mpTEParaPortions->GetObject( nStartNode );
		DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteText(5)" );
		pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() );
	}

//	UpdateSelections();
	TextModified();
	return aStartPaM;
}

void TextEngine::ImpRemoveParagraph( sal_uLong nPara )
{
	TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
	TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara );

	// Der Node wird vom Undo verwaltet und ggf. zerstoert!
	/* delete */ mpDoc->GetNodes().Remove( nPara );
	if ( IsUndoEnabled() && !IsInUndo() )
		InsertUndo( new TextUndoDelPara( this, pNode, nPara ) );
	else
		delete pNode;

	mpTEParaPortions->Remove( nPara );
	delete pPortion;

	ImpParagraphRemoved( nPara );
}

uno::Reference < i18n::XExtendedInputSequenceChecker > TextEngine::GetInputSequenceChecker() const
{
    uno::Reference < i18n::XExtendedInputSequenceChecker > xISC;
//    if ( !xISC.is() )
    {
        uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
        uno::Reference< uno::XInterface > xI = xMSF->createInstance( OUString::createFromAscii( "com.sun.star.i18n.InputSequenceChecker" ) );
        if ( xI.is() )
        {
            Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XExtendedInputSequenceChecker >*)0) );
            x >>= xISC;
        }
    }
    return xISC;
}

sal_Bool TextEngine::IsInputSequenceCheckingRequired( sal_Unicode c, const TextSelection& rCurSel ) const
{
    uno::Reference< i18n::XBreakIterator > xBI = ((TextEngine *) this)->GetBreakIterator();
    SvtCTLOptions aCTLOptions;

    // get the index that really is first
    sal_uInt16 nFirstPos = rCurSel.GetStart().GetIndex();
    sal_uInt16 nMaxPos   = rCurSel.GetEnd().GetIndex();
    if (nMaxPos < nFirstPos)
        nFirstPos = nMaxPos;
    
    sal_Bool bIsSequenceChecking =  
        aCTLOptions.IsCTLFontEnabled() &&
        aCTLOptions.IsCTLSequenceChecking() && 
        nFirstPos != 0 && /* first char needs not to be checked */
        xBI.is() && i18n::ScriptType::COMPLEX == xBI->getScriptType( rtl::OUString( c ), 0 );
    
    return bIsSequenceChecking;
}

TextPaM TextEngine::ImpInsertText( const TextSelection& rCurSel, sal_Unicode c, sal_Bool bOverwrite )
{
    return ImpInsertText( c, rCurSel, bOverwrite, sal_False );
}

TextPaM TextEngine::ImpInsertText( sal_Unicode c, const TextSelection& rCurSel, sal_Bool bOverwrite, sal_Bool bIsUserInput )
{
    DBG_ASSERT( c != '\n', "Zeilenumbruch bei InsertText ?" );
    DBG_ASSERT( c != '\r', "Zeilenumbruch bei InsertText ?" );

    TextPaM aPaM( rCurSel.GetStart() );
    TextNode* pNode = mpDoc->GetNodes().GetObject( aPaM.GetPara() );

    if ( pNode->GetText().Len() < STRING_MAXLEN )
    {
        sal_Bool bDoOverwrite = ( bOverwrite &&
                ( aPaM.GetIndex() < pNode->GetText().Len() ) ) ? sal_True : sal_False;

        sal_Bool bUndoAction = ( rCurSel.HasRange() || bDoOverwrite );

        if ( bUndoAction )
            UndoActionStart();

        if ( rCurSel.HasRange() )
        {
            aPaM = ImpDeleteText( rCurSel );
        }
        else if ( bDoOverwrite )
        {
            // Wenn Selektion, dann kein Zeichen ueberschreiben
            TextSelection aTmpSel( aPaM );
            aTmpSel.GetEnd().GetIndex()++;
            ImpDeleteText( aTmpSel );
        }

        if (bIsUserInput && IsInputSequenceCheckingRequired( c, rCurSel ))
        {
            uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = GetInputSequenceChecker();
            SvtCTLOptions aCTLOptions;

            if (xISC.is())
            {
                xub_StrLen nTmpPos = aPaM.GetIndex();
                sal_Int16 nCheckMode = aCTLOptions.IsCTLSequenceCheckingRestricted() ? 
                        i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;

                // the text that needs to be checked is only the one 
                // before the current cursor position
                rtl::OUString aOldText( mpDoc->GetText( aPaM.GetPara() ).Copy(0, nTmpPos) );
                rtl::OUString aNewText( aOldText );
                if (aCTLOptions.IsCTLSequenceCheckingTypeAndReplace())
                {
                    xISC->correctInputSequence( aNewText, nTmpPos - 1, c, nCheckMode );

                    // find position of first character that has changed
                    sal_Int32 nOldLen = aOldText.getLength();
                    sal_Int32 nNewLen = aNewText.getLength();
                    const sal_Unicode *pOldTxt = aOldText.getStr();
                    const sal_Unicode *pNewTxt = aNewText.getStr();
                    sal_Int32 nChgPos = 0;
                    while ( nChgPos < nOldLen && nChgPos < nNewLen &&
                            pOldTxt[nChgPos] == pNewTxt[nChgPos] )
                        ++nChgPos;

                    xub_StrLen nChgLen = static_cast< xub_StrLen >(nNewLen - nChgPos);
                    String aChgText( aNewText.copy( nChgPos ).getStr(), nChgLen );

                    // select text from first pos to be changed to current pos
                    TextSelection aSel( TextPaM( aPaM.GetPara(), (sal_uInt16) nChgPos ), aPaM );

                    if (aChgText.Len())
                        // ImpInsertText implicitly handles undo...
                        return ImpInsertText( aSel, aChgText );
                    else
                        return aPaM;
                }
                else
                {
                    // should the character be ignored (i.e. not get inserted) ?
                    if (!xISC->checkInputSequence( aOldText, nTmpPos - 1, c, nCheckMode ))
                        return aPaM;    // nothing to be done -> no need for undo
                }
            }

            // at this point now we will insert the character 'normally' some lines below...
        }


        if ( IsUndoEnabled() && !IsInUndo() )
        {
            TextUndoInsertChars* pNewUndo = new TextUndoInsertChars( this, aPaM, c );
            sal_Bool bTryMerge = ( !bDoOverwrite && ( c != ' ' ) ) ? sal_True : sal_False;
            InsertUndo( pNewUndo, bTryMerge );
        }

        TEParaPortion* pPortion = mpTEParaPortions->GetObject( aPaM.GetPara() );
        pPortion->MarkInvalid( aPaM.GetIndex(), 1 );
        if ( c == '\t' )
            pPortion->SetNotSimpleInvalid();
        aPaM = mpDoc->InsertText( aPaM, c );
        ImpCharsInserted( aPaM.GetPara(), aPaM.GetIndex()-1, 1 );

        TextModified();

        if ( bUndoAction )
            UndoActionEnd();
    }

    return aPaM;
}


TextPaM TextEngine::ImpInsertText( const TextSelection& rCurSel, const XubString& rStr )
{
    UndoActionStart();

	TextPaM aPaM;

	if ( rCurSel.HasRange() )
		aPaM = ImpDeleteText( rCurSel );
	else
		aPaM = rCurSel.GetEnd();

	XubString aText( rStr );
	aText.ConvertLineEnd( LINEEND_LF );

	sal_uInt16 nStart = 0;
	while ( nStart < aText.Len() )
	{
		sal_uInt16 nEnd = aText.Search( LINE_SEP, nStart );
		if ( nEnd == STRING_NOTFOUND )
			nEnd = aText.Len();	// nicht dereferenzieren!

		// Start == End => Leerzeile
		if ( nEnd > nStart )
		{
			sal_uLong nL = aPaM.GetIndex();
			nL += ( nEnd-nStart );
			if ( nL > STRING_MAXLEN )
			{
				sal_uInt16 nDiff = (sal_uInt16) (nL-STRING_MAXLEN);
				nEnd = nEnd - nDiff;
			}

			XubString aLine( aText, nStart, nEnd-nStart );
			if ( IsUndoEnabled() && !IsInUndo() )
				InsertUndo( new TextUndoInsertChars( this, aPaM, aLine ) );

			TEParaPortion* pPortion = mpTEParaPortions->GetObject( aPaM.GetPara() );
			pPortion->MarkInvalid( aPaM.GetIndex(), aLine.Len() );
			if ( aLine.Search( '\t' ) != STRING_NOTFOUND )
				pPortion->SetNotSimpleInvalid();

			aPaM = mpDoc->InsertText( aPaM, aLine );
			ImpCharsInserted( aPaM.GetPara(), aPaM.GetIndex()-aLine.Len(), aLine.Len() );

		}
		if ( nEnd < aText.Len() )
			aPaM = ImpInsertParaBreak( aPaM );

		nStart = nEnd+1;
		
        if ( nStart < nEnd )    // #108611# overflow 
            break;
	}

    UndoActionEnd();

    TextModified();
	return aPaM;
}

TextPaM TextEngine::ImpInsertParaBreak( const TextSelection& rCurSel, sal_Bool bKeepEndingAttribs )
{
	TextPaM aPaM;
	if ( rCurSel.HasRange() )
		aPaM = ImpDeleteText( rCurSel );
	else
		aPaM = rCurSel.GetEnd();

	return ImpInsertParaBreak( aPaM, bKeepEndingAttribs );
}

TextPaM TextEngine::ImpInsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs )
{
	if ( IsUndoEnabled() && !IsInUndo() )
		InsertUndo( new TextUndoSplitPara( this, rPaM.GetPara(), rPaM.GetIndex() ) );

	TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() );
	sal_Bool bFirstParaContentChanged = rPaM.GetIndex() < pNode->GetText().Len();

	TextPaM aPaM( mpDoc->InsertParaBreak( rPaM, bKeepEndingAttribs ) );

	TEParaPortion* pPortion = mpTEParaPortions->GetObject( rPaM.GetPara() );
	DBG_ASSERT( pPortion, "Blinde Portion in ImpInsertParaBreak" );
	pPortion->MarkInvalid( rPaM.GetIndex(), 0 );

	TextNode* pNewNode = mpDoc->GetNodes().GetObject( aPaM.GetPara() );
	TEParaPortion* pNewPortion = new TEParaPortion( pNewNode );
	mpTEParaPortions->Insert( pNewPortion, aPaM.GetPara() );
	ImpParagraphInserted( aPaM.GetPara() );

	CursorMoved( rPaM.GetPara() );	// falls leeres Attribut entstanden.
	TextModified();

	if ( bFirstParaContentChanged )
		Broadcast( TextHint( TEXT_HINT_PARACONTENTCHANGED, rPaM.GetPara() ) );

	return aPaM;
}

Rectangle TextEngine::PaMtoEditCursor( const TextPaM& rPaM, sal_Bool bSpecial )
{
	DBG_ASSERT( GetUpdateMode(), "Darf bei Update=sal_False nicht erreicht werden: PaMtoEditCursor" );

	Rectangle aEditCursor;
	long nY = 0;

	if ( !mbHasMultiLineParas )
	{
		nY = rPaM.GetPara() * mnCharHeight;
	}
	else
	{
		for ( sal_uLong nPortion = 0; nPortion < rPaM.GetPara(); nPortion++ )
		{
			TEParaPortion* pPortion = mpTEParaPortions->GetObject(nPortion);
			nY += pPortion->GetLines().Count() * mnCharHeight;
		}
	}

	aEditCursor = GetEditCursor( rPaM, bSpecial );
	aEditCursor.Top() += nY;
	aEditCursor.Bottom() += nY;
	return aEditCursor;
}

Rectangle TextEngine::GetEditCursor( const TextPaM& rPaM, sal_Bool bSpecial, sal_Bool bPreferPortionStart )
{
    if ( !IsFormatted() && !IsFormatting() )
		FormatAndUpdate();

	TEParaPortion* pPortion = mpTEParaPortions->GetObject( rPaM.GetPara() );
	//TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() );

	/*
	 bSpecial:	Wenn hinter dem letzten Zeichen einer umgebrochenen Zeile,
	 am Ende der Zeile bleiben, nicht am Anfang der naechsten.
	 Zweck: 	- END => wirklich hinter das letzte Zeichen
				- Selektion....
	  bSpecial: If behind the last character of a made up line, stay at the
	  			end of the line, not at the start of the next line.
	  Purpose:  - really END = > behind the last character
	  			- to selection...

	*/

	long nY = 0;
	sal_uInt16 nCurIndex = 0;
	TextLine* pLine = 0;
	for ( sal_uInt16 nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
	{
		TextLine* pTmpLine = pPortion->GetLines().GetObject( nLine );
		if ( ( pTmpLine->GetStart() == rPaM.GetIndex() ) || ( pTmpLine->IsIn( rPaM.GetIndex(), bSpecial ) ) )
		{
			pLine = pTmpLine;
			break;
		}

		nCurIndex = nCurIndex + pTmpLine->GetLen();
		nY += mnCharHeight;
	}
	if ( !pLine )
	{
		// Cursor am Ende des Absatzes.
		DBG_ASSERT( rPaM.GetIndex() == nCurIndex, "Index voll daneben in GetEditCursor!" );

		pLine = pPortion->GetLines().GetObject( pPortion->GetLines().Count()-1 );
		nY -= mnCharHeight;
		nCurIndex = nCurIndex - pLine->GetLen();
	}

	Rectangle aEditCursor;

	aEditCursor.Top() = nY;
	nY += mnCharHeight;
	aEditCursor.Bottom() = nY-1;

	// innerhalb der Zeile suchen....
	long nX = ImpGetXPos( rPaM.GetPara(), pLine, rPaM.GetIndex(), bPreferPortionStart );
	aEditCursor.Left() = aEditCursor.Right() = nX;
	return aEditCursor;
}

long TextEngine::ImpGetXPos( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_Bool bPreferPortionStart )
{
	DBG_ASSERT( ( nIndex >= pLine->GetStart() ) && ( nIndex <= pLine->GetEnd() ) , "ImpGetXPos muss richtig gerufen werden!" );

    sal_Bool bDoPreferPortionStart = bPreferPortionStart;
    // Assure that the portion belongs to this line:
    if ( nIndex == pLine->GetStart() )
        bDoPreferPortionStart = sal_True;
    else if ( nIndex == pLine->GetEnd() )
        bDoPreferPortionStart = sal_False;

	TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara );

    sal_uInt16 nTextPortionStart = 0;
    sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart );

    DBG_ASSERT( ( nTextPortion >= pLine->GetStartPortion() ) && ( nTextPortion <= pLine->GetEndPortion() ), "GetXPos: Portion not in current line! " );

    TETextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );

    long nX = ImpGetPortionXOffset( nPara, pLine, nTextPortion );

    long nPortionTextWidth = pPortion->GetWidth();

    if ( nTextPortionStart != nIndex )
    {
        // Search within portion...
        if ( nIndex == ( nTextPortionStart + pPortion->GetLen() ) )
        {
            // End of Portion
            if ( ( pPortion->GetKind() == PORTIONKIND_TAB ) || 
                 ( !IsRightToLeft() && !pPortion->IsRightToLeft() ) ||
                 ( IsRightToLeft() && pPortion->IsRightToLeft() ) )
            {
				nX += nPortionTextWidth;
                if ( ( pPortion->GetKind() == PORTIONKIND_TAB ) && ( (nTextPortion+1) < pParaPortion->GetTextPortions().Count() ) )
                {
                    TETextPortion* pNextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion+1 );
                    if ( ( pNextPortion->GetKind() != PORTIONKIND_TAB ) && ( 
                              ( !IsRightToLeft() && pNextPortion->IsRightToLeft() ) ||
                              ( IsRightToLeft() && !pNextPortion->IsRightToLeft() ) ) )
                    {
//                        nX += pNextPortion->GetWidth();
                        // End of the tab portion, use start of next for cursor pos
                        DBG_ASSERT( !bPreferPortionStart, "ImpGetXPos - How can we this tab portion here???" );
                        nX = ImpGetXPos( nPara, pLine, nIndex, sal_True );
                    }

                }
            }
        }
        else if ( pPortion->GetKind() == PORTIONKIND_TEXT )
        {
			DBG_ASSERT( nIndex != pLine->GetStart(), "Strange behavior in new ImpGetXPos()" );

            long nPosInPortion = (long)CalcTextWidth( nPara, nTextPortionStart, nIndex-nTextPortionStart );

            if ( ( !IsRightToLeft() && !pPortion->IsRightToLeft() ) ||
                 ( IsRightToLeft() && pPortion->IsRightToLeft() ) )
            {
				nX += nPosInPortion;
            }
            else
            {
				nX += nPortionTextWidth - nPosInPortion;
            }
		}
    }
    else // if ( nIndex == pLine->GetStart() )
    {
        if ( ( pPortion->GetKind() != PORTIONKIND_TAB ) &&
                ( ( !IsRightToLeft() && pPortion->IsRightToLeft() ) ||
                ( IsRightToLeft() && !pPortion->IsRightToLeft() ) ) )
        {
		    nX += nPortionTextWidth;
        }
    }

	return nX;
}

const TextAttrib* TextEngine::FindAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const
{
	const TextAttrib* pAttr = NULL;
	const TextCharAttrib* pCharAttr = FindCharAttrib( rPaM, nWhich );
	if ( pCharAttr )
		pAttr = &pCharAttr->GetAttr();
	return pAttr;
}

const TextCharAttrib* TextEngine::FindCharAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const
{
	const TextCharAttrib* pAttr = NULL;
	TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() );
	if ( pNode && ( rPaM.GetIndex() < pNode->GetText().Len() ) )
		pAttr = pNode->GetCharAttribs().FindAttrib( nWhich, rPaM.GetIndex() );
	return pAttr;
}

sal_Bool TextEngine::HasAttrib( sal_uInt16 nWhich ) const
{
	sal_Bool bAttr = sal_False;
	for ( sal_uLong n = mpDoc->GetNodes().Count(); --n && !bAttr; )
	{
		TextNode* pNode = mpDoc->GetNodes().GetObject( n );
		bAttr = pNode->GetCharAttribs().HasAttrib( nWhich );
	}
	return bAttr;
}

TextPaM TextEngine::GetPaM( const Point& rDocPos, sal_Bool bSmart )
{
	DBG_ASSERT( GetUpdateMode(), "Darf bei Update=sal_False nicht erreicht werden: GetPaM" );

	long nY = 0;
	for ( sal_uLong nPortion = 0; nPortion < mpTEParaPortions->Count(); nPortion++ )
	{
		TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPortion );
		long nTmpHeight = pPortion->GetLines().Count() * mnCharHeight;
		nY += nTmpHeight;
		if ( nY > rDocPos.Y() )
		{
			nY -= nTmpHeight;
			Point aPosInPara( rDocPos );
			aPosInPara.Y() -= nY;

			TextPaM aPaM( nPortion, 0 );
			aPaM.GetIndex() = ImpFindIndex( nPortion, aPosInPara, bSmart );
			return aPaM;
		}
	}

	// Nicht gefunden - Dann den letzten sichtbare...
	sal_uLong nLastNode = mpDoc->GetNodes().Count() - 1;
	TextNode* pLast = mpDoc->GetNodes().GetObject( nLastNode );
	return TextPaM( nLastNode, pLast->GetText().Len() );
}

sal_uInt16 TextEngine::ImpFindIndex( sal_uLong nPortion, const Point& rPosInPara, sal_Bool bSmart )
{
	DBG_ASSERT( IsFormatted(), "GetPaM: Nicht formatiert" );
	TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPortion );

	sal_uInt16 nCurIndex = 0;

	long nY = 0;
	TextLine* pLine = 0;
	sal_uInt16 nLine;
	for ( nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
	{
		TextLine* pTmpLine = pPortion->GetLines().GetObject( nLine );
		nY += mnCharHeight;
		if ( nY > rPosInPara.Y() ) 	// das war 'se
		{
			pLine = pTmpLine;
			break;					// richtige Y-Position intressiert nicht
		}
	}
	DBG_ASSERT( pLine, "ImpFindIndex: pLine ?" );

	nCurIndex = GetCharPos( nPortion, nLine, rPosInPara.X(), bSmart );

	if ( nCurIndex && ( nCurIndex == pLine->GetEnd() ) &&
		 ( pLine != pPortion->GetLines().GetObject( pPortion->GetLines().Count()-1) ) )
	{
		uno::Reference < i18n::XBreakIterator > xBI = GetBreakIterator();
		sal_Int32 nCount = 1;
		nCurIndex = (sal_uInt16)xBI->previousCharacters( pPortion->GetNode()->GetText(), nCurIndex, GetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
	}
	return nCurIndex;
}

sal_uInt16 TextEngine::GetCharPos( sal_uLong nPortion, sal_uInt16 nLine, long nXPos, sal_Bool )
{

	TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPortion );
	TextLine* pLine = pPortion->GetLines().GetObject( nLine );

	sal_uInt16 nCurIndex = pLine->GetStart();

	long nTmpX = pLine->GetStartX();
	if ( nXPos <= nTmpX )
		return nCurIndex;

	for ( sal_uInt16 i = pLine->GetStartPortion(); i <= pLine->GetEndPortion(); i++ )
	{
		TETextPortion* pTextPortion = pPortion->GetTextPortions().GetObject( i );
		nTmpX += pTextPortion->GetWidth();

		if ( nTmpX > nXPos )
		{
			if( pTextPortion->GetLen() > 1 )
			{
				nTmpX -= pTextPortion->GetWidth();	// vor die Portion stellen
				// Optimieren: Kein GetTextBreak, wenn feste Fontbreite...
				Font aFont;
				SeekCursor( nPortion, nCurIndex+1, aFont, NULL );
				mpRefDev->SetFont( aFont);
                long nPosInPortion = nXPos-nTmpX;
                if ( IsRightToLeft() != pTextPortion->IsRightToLeft() )
                    nPosInPortion = pTextPortion->GetWidth() - nPosInPortion;
				nCurIndex = mpRefDev->GetTextBreak( pPortion->GetNode()->GetText(), nPosInPortion, nCurIndex );
                // MT: GetTextBreak should assure that we are not withing a CTL cell...
			}
			return nCurIndex;
		}
		nCurIndex = nCurIndex + pTextPortion->GetLen();
	}
	return nCurIndex;
}


sal_uLong TextEngine::GetTextHeight() const
{
	DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: GetTextHeight" );

    if ( !IsFormatted() && !IsFormatting() )
		((TextEngine*)this)->FormatAndUpdate();

	return mnCurTextHeight;
}

sal_uLong TextEngine::GetTextHeight( sal_uLong nParagraph ) const
{
	DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: GetTextHeight" );

  	if ( !IsFormatted() && !IsFormatting() )
		((TextEngine*)this)->FormatAndUpdate();

	return CalcParaHeight( nParagraph );
}

sal_uLong TextEngine::CalcTextWidth( sal_uLong nPara )
{
	sal_uLong nParaWidth = 0;
	TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara );
	for ( sal_uInt16 nLine = pPortion->GetLines().Count(); nLine; )
	{
		sal_uLong nLineWidth = 0;
		TextLine* pLine = pPortion->GetLines().GetObject( --nLine );
		for ( sal_uInt16 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ )
		{
			TETextPortion* pTextPortion = pPortion->GetTextPortions().GetObject( nTP );
			nLineWidth += pTextPortion->GetWidth();
		}
		if ( nLineWidth > nParaWidth )
			nParaWidth = nLineWidth;
	}
	return nParaWidth;
}

sal_uLong TextEngine::CalcTextWidth()
{
	if ( !IsFormatted() && !IsFormatting() )
		FormatAndUpdate();

	if ( mnCurTextWidth == 0xFFFFFFFF )
	{
		mnCurTextWidth = 0;
		for ( sal_uLong nPara = mpTEParaPortions->Count(); nPara; )
		{
			sal_uLong nParaWidth = CalcTextWidth( --nPara );
			if ( nParaWidth > mnCurTextWidth )
				mnCurTextWidth = nParaWidth; 
		}
	}
	return mnCurTextWidth+1;// Ein breiter, da in CreateLines bei >= umgebrochen wird.
}

sal_uLong TextEngine::CalcTextHeight()
{
	DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: CalcTextHeight" );

	sal_uLong nY = 0;
	for ( sal_uLong nPortion = mpTEParaPortions->Count(); nPortion; )
		nY += CalcParaHeight( --nPortion );
	return nY;
}

sal_uLong TextEngine::CalcTextWidth( sal_uLong nPara, sal_uInt16 nPortionStart, sal_uInt16 nLen, const Font* pFont )
{
	// Innerhalb des Textes darf es keinen Portionwechsel (Attribut/Tab) geben!
	DBG_ASSERT( mpDoc->GetNodes().GetObject( nPara )->GetText().Search( '\t', nPortionStart ) >= (nPortionStart+nLen), "CalcTextWidth: Tab!" );

	sal_uLong nWidth;
	if ( mnFixCharWidth100 )
    {
		nWidth = (sal_uLong)nLen*mnFixCharWidth100/100;
    }
	else
	{
		if ( pFont )
		{
			if ( !mpRefDev->GetFont().IsSameInstance( *pFont ) )
				mpRefDev->SetFont( *pFont );
		}
		else
		{
			Font aFont;
			SeekCursor( nPara, nPortionStart+1, aFont, NULL );
			mpRefDev->SetFont( aFont );
		}
		TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
		nWidth = (sal_uLong)mpRefDev->GetTextWidth( pNode->GetText(), nPortionStart, nLen );

	}
	return nWidth;
}


sal_uInt16 TextEngine::GetLineCount( sal_uLong nParagraph ) const
{
	DBG_ASSERT( nParagraph < mpTEParaPortions->Count(), "GetLineCount: Out of range" );

	TEParaPortion* pPPortion = mpTEParaPortions->GetObject( nParagraph );
	if ( pPPortion )
		return pPPortion->GetLines().Count();

	return 0xFFFF;
}

sal_uInt16 TextEngine::GetLineLen( sal_uLong nParagraph, sal_uInt16 nLine ) const
{
	DBG_ASSERT( nParagraph < mpTEParaPortions->Count(), "GetLineCount: Out of range" );

	TEParaPortion* pPPortion = mpTEParaPortions->GetObject( nParagraph );
	if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
	{
		TextLine* pLine = pPPortion->GetLines().GetObject( nLine );
		return pLine->GetLen();
	}

	return 0xFFFF;
}

sal_uLong TextEngine::CalcParaHeight( sal_uLong nParagraph ) const
{
	sal_uLong nHeight = 0;

	TEParaPortion* pPPortion = mpTEParaPortions->GetObject( nParagraph );
	DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetParaHeight" );
	if ( pPPortion )
		nHeight = pPPortion->GetLines().Count() * mnCharHeight;

	return nHeight;
}

void TextEngine::UpdateSelections()
{
}

Range TextEngine::GetInvalidYOffsets( sal_uLong nPortion )
{
	TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPortion );
	sal_uInt16 nLines = pTEParaPortion->GetLines().Count();
	sal_uInt16 nLastInvalid, nFirstInvalid = 0;
	sal_uInt16 nLine;
	for ( nLine = 0; nLine < nLines; nLine++ )
	{
		TextLine* pL = pTEParaPortion->GetLines().GetObject( nLine );
		if ( pL->IsInvalid() )
		{
			nFirstInvalid = nLine;
			break;
		}
	}

	for ( nLastInvalid = nFirstInvalid; nLastInvalid < nLines; nLastInvalid++ )
	{
		TextLine* pL = pTEParaPortion->GetLines().GetObject( nLine );
		if ( pL->IsValid() )
			break;
	}

	if ( nLastInvalid >= nLines )
		nLastInvalid = nLines-1;

	return Range( nFirstInvalid*mnCharHeight, ((nLastInvalid+1)*mnCharHeight)-1 );
}

sal_uLong TextEngine::GetParagraphCount() const
{
	return mpDoc->GetNodes().Count();
}

void TextEngine::EnableUndo( sal_Bool bEnable )
{
	// Beim Umschalten des Modus Liste loeschen:
	if ( bEnable != IsUndoEnabled() )
		ResetUndo();

	mbUndoEnabled = bEnable;
}

::svl::IUndoManager& TextEngine::GetUndoManager()
{
	if ( !mpUndoManager )
		mpUndoManager = new TextUndoManager( this );
	return *mpUndoManager;
}

void TextEngine::UndoActionStart( sal_uInt16 nId )
{
	if ( IsUndoEnabled() && !IsInUndo() )
	{
		String aComment;
		// ...
		GetUndoManager().EnterListAction( aComment, XubString(), nId );
	}
}

void TextEngine::UndoActionEnd()
{
	if ( IsUndoEnabled() && !IsInUndo() )
		GetUndoManager().LeaveListAction();
}

void TextEngine::InsertUndo( TextUndo* pUndo, sal_Bool bTryMerge )
{
	DBG_ASSERT( !IsInUndo(), "InsertUndo im Undomodus!" );
	GetUndoManager().AddUndoAction( pUndo, bTryMerge );
}

void TextEngine::ResetUndo()
{
	if ( mpUndoManager )
		mpUndoManager->Clear();
}

void TextEngine::InsertContent( TextNode* pNode, sal_uLong nPara )
{
	DBG_ASSERT( pNode, "NULL-Pointer in InsertContent! " );
	DBG_ASSERT( IsInUndo(), "InsertContent nur fuer Undo()!" );
	TEParaPortion* pNew = new TEParaPortion( pNode );
	mpTEParaPortions->Insert( pNew, nPara );
	mpDoc->GetNodes().Insert( pNode, nPara );
	ImpParagraphInserted( nPara );
}

TextPaM TextEngine::SplitContent( sal_uLong nNode, sal_uInt16 nSepPos )
{
    #ifdef DBG_UTIL
	TextNode* pNode = mpDoc->GetNodes().GetObject( nNode );
	DBG_ASSERT( pNode, "Ungueltiger Node in SplitContent" );
	DBG_ASSERT( IsInUndo(), "SplitContent nur fuer Undo()!" );
	DBG_ASSERT( nSepPos <= pNode->GetText().Len(), "Index im Wald: SplitContent" );
    #endif
	TextPaM aPaM( nNode, nSepPos );
	return ImpInsertParaBreak( aPaM );
}

TextPaM TextEngine::ConnectContents( sal_uLong nLeftNode )
{
	DBG_ASSERT( IsInUndo(), "ConnectContent nur fuer Undo()!" );
	return ImpConnectParagraphs( nLeftNode, nLeftNode+1 );
}

void TextEngine::SeekCursor( sal_uLong nPara, sal_uInt16 nPos, Font& rFont, OutputDevice* pOutDev )
{
	rFont = maFont;
	if ( pOutDev )
		pOutDev->SetTextColor( maTextColor );

	TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
	sal_uInt16 nAttribs = pNode->GetCharAttribs().Count();
	for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
	{
		TextCharAttrib* pAttrib = pNode->GetCharAttribs().GetAttrib( nAttr );
		if ( pAttrib->GetStart() > nPos )
			break;

		// Beim Seeken nicht die Attr beruecksichtigen, die dort beginnen!
		// Leere Attribute werden beruecksichtigt( verwendet), da diese
		// gerade eingestellt wurden.
		// 12.4.95: Doch keine Leeren Attribute verwenden:
		// - Wenn gerade eingestellt und leer => keine Auswirkung auf Font
		// In einem leeren Absatz eingestellte Zeichen werden sofort wirksam.
		if ( ( ( pAttrib->GetStart() < nPos ) && ( pAttrib->GetEnd() >= nPos ) )
					|| !pNode->GetText().Len() )
		{
			if ( pAttrib->Which() != TEXTATTR_FONTCOLOR )
			{
				pAttrib->GetAttr().SetFont( rFont );
			}
			else
			{
				if ( pOutDev )
					pOutDev->SetTextColor( ((TextAttribFontColor&)pAttrib->GetAttr()).GetColor() );
			}
		}
	}

	if ( mpIMEInfos && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetPara() == nPara ) &&
		( nPos > mpIMEInfos->aPos.GetIndex() ) && ( nPos <= ( mpIMEInfos->aPos.GetIndex() + mpIMEInfos->nLen ) ) )
	{
		sal_uInt16 nAttr = mpIMEInfos->pAttribs[ nPos - mpIMEInfos->aPos.GetIndex() - 1 ];
		if ( nAttr & EXTTEXTINPUT_ATTR_UNDERLINE )
			rFont.SetUnderline( UNDERLINE_SINGLE );
		else if ( nAttr & EXTTEXTINPUT_ATTR_BOLDUNDERLINE )
			rFont.SetUnderline( UNDERLINE_BOLD );
		else if ( nAttr & EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE )
			rFont.SetUnderline( UNDERLINE_DOTTED );
		else if ( nAttr & EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE )
			rFont.SetUnderline( UNDERLINE_DOTTED );
		if ( nAttr & EXTTEXTINPUT_ATTR_REDTEXT )
			rFont.SetColor( Color( COL_RED ) );
		else if ( nAttr & EXTTEXTINPUT_ATTR_HALFTONETEXT )
			rFont.SetColor( Color( COL_LIGHTGRAY ) );
		if ( nAttr & EXTTEXTINPUT_ATTR_HIGHLIGHT )
		{
			const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
			rFont.SetColor( rStyleSettings.GetHighlightTextColor() );
			rFont.SetFillColor( rStyleSettings.GetHighlightColor() );
			rFont.SetTransparent( sal_False );
		}
		else if ( nAttr & EXTTEXTINPUT_ATTR_GRAYWAVELINE )
		{
			rFont.SetUnderline( UNDERLINE_WAVE );
//			if( pOut )
//				pOut->SetTextLineColor( Color( COL_LIGHTGRAY ) );
		}
	}
}

void TextEngine::SetUpdateMode( sal_Bool bUp, TextView* pCurView, sal_Bool bForceUpdate )
{
	sal_Bool bChanged = ( GetUpdateMode() != bUp );

	mbUpdate = bUp;
	if ( mbUpdate && ( bChanged || bForceUpdate ) )
		FormatAndUpdate( pCurView );
}

void TextEngine::FormatAndUpdate( TextView* pCurView )
{
	if ( mbDowning )
		return ;

	if ( IsInUndo() )
		IdleFormatAndUpdate( pCurView );
	else
	{
		FormatDoc();
		UpdateViews( pCurView );
	}
}


void TextEngine::IdleFormatAndUpdate( TextView* pCurView, sal_uInt16 nMaxTimerRestarts )
{
	mpIdleFormatter->DoIdleFormat( pCurView, nMaxTimerRestarts );
}

void TextEngine::TextModified()
{
	mbFormatted = sal_False;
	mbModified = sal_True;
}

void TextEngine::UpdateViews( TextView* pCurView )
{
	if ( !GetUpdateMode() || IsFormatting() || maInvalidRec.IsEmpty() )
		return;

	DBG_ASSERT( IsFormatted(), "UpdateViews: Doc nicht formatiert!" );

	for ( sal_uInt16 nView = 0; nView < mpViews->Count(); nView++ )
	{
		TextView* pView = mpViews->GetObject( nView );
		pView->HideCursor();

		Rectangle aClipRec( maInvalidRec );
        Size aOutSz = pView->GetWindow()->GetOutputSizePixel();
		Rectangle aVisArea( pView->GetStartDocPos(), aOutSz );
		aClipRec.Intersection( aVisArea );
		if ( !aClipRec.IsEmpty() )
		{
			// in Fensterkoordinaten umwandeln....
            Point aNewPos = pView->GetWindowPos( aClipRec.TopLeft() );
            if ( IsRightToLeft() )
                aNewPos.X() -= aOutSz.Width() - 1;
			aClipRec.SetPos( aNewPos );

			if ( pView == pCurView )
				pView->ImpPaint( aClipRec, !pView->GetWindow()->IsPaintTransparent() );
			else
				pView->GetWindow()->Invalidate( aClipRec );
		}
	}

	if ( pCurView )
	{
        pCurView->ShowCursor( pCurView->IsAutoScroll() );
	}

	maInvalidRec = Rectangle();
}

IMPL_LINK( TextEngine, IdleFormatHdl, Timer *, EMPTYARG )
{
	FormatAndUpdate( mpIdleFormatter->GetView() );
	return 0;
}

void TextEngine::CheckIdleFormatter()
{
	mpIdleFormatter->ForceTimeout();
}

void TextEngine::FormatFullDoc()
{
	for ( sal_uLong nPortion = 0; nPortion < mpTEParaPortions->Count(); nPortion++ )
	{
		TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPortion );		sal_uInt16 nLen = pTEParaPortion->GetNode()->GetText().Len();
		pTEParaPortion->MarkSelectionInvalid( 0, nLen );
	}
	mbFormatted = sal_False;
	FormatDoc();
}

void TextEngine::FormatDoc()
{
	if ( IsFormatted() || !GetUpdateMode() || IsFormatting() )
		return;

	mbIsFormatting = sal_True;
	mbHasMultiLineParas = sal_False;

	long nY = 0;
	sal_Bool bGrow = sal_False;

	maInvalidRec = Rectangle();	// leermachen
	for ( sal_uLong nPara = 0; nPara < mpTEParaPortions->Count(); nPara++ )
	{
		TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );
		if ( pTEParaPortion->IsInvalid() )
		{
			sal_uLong nOldParaWidth = 0xFFFFFFFF;
			if ( mnCurTextWidth != 0xFFFFFFFF )
				nOldParaWidth = CalcTextWidth( nPara );

			ImpFormattingParagraph( nPara );

			if ( CreateLines( nPara ) )
				bGrow = sal_True;

			// InvalidRec nur einmal setzen...
			if ( maInvalidRec.IsEmpty() )
			{
				// Bei Paperwidth 0 (AutoPageSize) bleibt es sonst Empty()...
				long nWidth = (long)mnMaxTextWidth;
				if ( !nWidth )
					nWidth = 0x7FFFFFFF;
				Range aInvRange( GetInvalidYOffsets( nPara ) );
				maInvalidRec = Rectangle( Point( 0, nY+aInvRange.Min() ),
					Size( nWidth, aInvRange.Len() ) );
			}
			else
			{
				maInvalidRec.Bottom() = nY + CalcParaHeight( nPara );
			}

			if ( mnCurTextWidth != 0xFFFFFFFF )
			{
				sal_uLong nNewParaWidth = CalcTextWidth( nPara );
				if ( nNewParaWidth >= mnCurTextWidth )
					mnCurTextWidth = nNewParaWidth; 
				else if ( ( nOldParaWidth != 0xFFFFFFFF ) && ( nOldParaWidth >= mnCurTextWidth ) )
					mnCurTextWidth = 0xFFFFFFFF;
			}
		}
		else if ( bGrow )
		{
			maInvalidRec.Bottom() = nY + CalcParaHeight( nPara );
		}
		nY += CalcParaHeight( nPara );
		if ( !mbHasMultiLineParas && pTEParaPortion->GetLines().Count() > 1 )
			mbHasMultiLineParas = sal_True;
	}

	if ( !maInvalidRec.IsEmpty() )
	{
		sal_uLong nNewHeight = CalcTextHeight();
		long nDiff = nNewHeight - mnCurTextHeight;
		if ( nNewHeight < mnCurTextHeight )
		{
			maInvalidRec.Bottom() = (long)Max( nNewHeight, mnCurTextHeight );
			if ( maInvalidRec.IsEmpty() )
			{
				maInvalidRec.Top() = 0;
				// Left und Right werden nicht ausgewertet, aber wegen IsEmpty gesetzt.
				maInvalidRec.Left() = 0;
				maInvalidRec.Right() = mnMaxTextWidth;
			}
		}

		mnCurTextHeight = nNewHeight;
		if ( nDiff )
		{
			mbFormatted = sal_True;
			ImpTextHeightChanged();
		}
	}

	mbIsFormatting = sal_False;
	mbFormatted = sal_True;

	ImpTextFormatted();
}

void TextEngine::CreateAndInsertEmptyLine( sal_uLong nPara )
{
	TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
	TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );

	TextLine* pTmpLine = new TextLine;
	pTmpLine->SetStart( pNode->GetText().Len() );
	pTmpLine->SetEnd( pTmpLine->GetStart() );
	pTEParaPortion->GetLines().Insert( pTmpLine, pTEParaPortion->GetLines().Count() );

	if ( ImpGetAlign() == TXTALIGN_CENTER )
		pTmpLine->SetStartX( (short)(mnMaxTextWidth / 2) );
	else if ( ImpGetAlign() == TXTALIGN_RIGHT )
		pTmpLine->SetStartX( (short)mnMaxTextWidth );
	else
		pTmpLine->SetStartX( mpDoc->GetLeftMargin() );

	sal_Bool bLineBreak = pNode->GetText().Len() ? sal_True : sal_False;

	TETextPortion* pDummyPortion = new TETextPortion( 0 );
	pDummyPortion->GetWidth() = 0;
	pTEParaPortion->GetTextPortions().Insert( pDummyPortion, pTEParaPortion->GetTextPortions().Count() );

	if ( bLineBreak == sal_True )
	{
		// -2: Die neue ist bereits eingefuegt.
        #ifdef DBG_UTIL
		TextLine* pLastLine = pTEParaPortion->GetLines().GetObject( pTEParaPortion->GetLines().Count()-2 );
		DBG_ASSERT( pLastLine, "Weicher Umbruch, keine Zeile ?!" );
        #endif
		sal_uInt16 nPos = (sal_uInt16) pTEParaPortion->GetTextPortions().Count() - 1 ;
		pTmpLine->SetStartPortion( nPos );
		pTmpLine->SetEndPortion( nPos );
	}
}

void TextEngine::ImpBreakLine( sal_uLong nPara, TextLine* pLine, TETextPortion*, sal_uInt16 nPortionStart, long nRemainingWidth )
{
	TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );

	// Font sollte noch eingestellt sein.
	sal_uInt16 nMaxBreakPos = mpRefDev->GetTextBreak( pNode->GetText(), nRemainingWidth, nPortionStart );

	DBG_ASSERT( nMaxBreakPos < pNode->GetText().Len(), "Break?!" );

	if ( nMaxBreakPos == STRING_LEN )	// GetTextBreak() ist anderer Auffassung als GetTextSize()
		nMaxBreakPos = pNode->GetText().Len() - 1;

	uno::Reference < i18n::XBreakIterator > xBI = GetBreakIterator();
	i18n::LineBreakHyphenationOptions aHyphOptions( NULL, uno::Sequence< beans::PropertyValue >(), 1 );

    i18n::LineBreakUserOptions aUserOptions;
	aUserOptions.forbiddenBeginCharacters = ImpGetLocaleDataWrapper()->getForbiddenCharacters().beginLine;
	aUserOptions.forbiddenEndCharacters = ImpGetLocaleDataWrapper()->getForbiddenCharacters().endLine;
	aUserOptions.applyForbiddenRules = sal_True;
	aUserOptions.allowPunctuationOutsideMargin = sal_False;
	aUserOptions.allowHyphenateEnglish = sal_False;

    static const com::sun::star::lang::Locale aDefLocale;
	i18n::LineBreakResults aLBR = xBI->getLineBreak( pNode->GetText(), nMaxBreakPos, aDefLocale, pLine->GetStart(), aHyphOptions, aUserOptions );
	sal_uInt16 nBreakPos = (sal_uInt16)aLBR.breakIndex;
	if ( nBreakPos <= pLine->GetStart() )
    {
		nBreakPos = nMaxBreakPos;
		if ( nBreakPos <= pLine->GetStart() )
			nBreakPos = pLine->GetStart() + 1; 	// Sonst Endlosschleife!
    }


	// die angeknackste Portion ist die End-Portion
	pLine->SetEnd( nBreakPos );
	sal_uInt16 nEndPortion = SplitTextPortion( nPara, nBreakPos );

	sal_Bool bBlankSeparator = ( ( nBreakPos >= pLine->GetStart() ) &&
								 ( pNode->GetText().GetChar( nBreakPos ) == ' ' ) ) ? sal_True : sal_False;
	if ( bBlankSeparator )
	{
		// Blanks am Zeilenende generell unterdruecken...
		TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );
		TETextPortion* pTP = pTEParaPortion->GetTextPortions().GetObject( nEndPortion );
		DBG_ASSERT( nBreakPos > pLine->GetStart(), "SplitTextPortion am Anfang der Zeile?" );
		pTP->GetWidth() = (long)CalcTextWidth( nPara, nBreakPos-pTP->GetLen(), pTP->GetLen()-1 );
	}
	pLine->SetEndPortion( nEndPortion );
}

sal_uInt16 TextEngine::SplitTextPortion( sal_uLong nPara, sal_uInt16 nPos )
{

	// Die Portion bei nPos wird geplittet, wenn bei nPos nicht
	// sowieso ein Wechsel ist
	if ( nPos == 0 )
		return 0;

	sal_uInt16 nSplitPortion;
	sal_uInt16 nTmpPos = 0;
	TETextPortion* pTextPortion = 0;
	TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );
	sal_uInt16 nPortions = pTEParaPortion->GetTextPortions().Count();
	for ( nSplitPortion = 0; nSplitPortion < nPortions; nSplitPortion++ )
	{
		TETextPortion* pTP = pTEParaPortion->GetTextPortions().GetObject(nSplitPortion);
		nTmpPos = nTmpPos + pTP->GetLen();
		if ( nTmpPos >= nPos )
		{
			if ( nTmpPos == nPos )	// dann braucht nichts geteilt werden
				return nSplitPortion;
			pTextPortion = pTP;
			break;
		}
	}

	DBG_ASSERT( pTextPortion, "Position ausserhalb des Bereichs!" );

	sal_uInt16 nOverlapp = nTmpPos - nPos;
	pTextPortion->GetLen() = pTextPortion->GetLen() - nOverlapp;
	TETextPortion* pNewPortion = new TETextPortion( nOverlapp );
	pTEParaPortion->GetTextPortions().Insert( pNewPortion, nSplitPortion+1 );
	pTextPortion->GetWidth() = (long)CalcTextWidth( nPara, nPos-pTextPortion->GetLen(), pTextPortion->GetLen() );

	return nSplitPortion;
}

void TextEngine::CreateTextPortions( sal_uLong nPara, sal_uInt16 nStartPos )
{
	TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );
	TextNode* pNode = pTEParaPortion->GetNode();
	DBG_ASSERT( pNode->GetText().Len(), "CreateTextPortions sollte nicht fuer leere Absaetze verwendet werden!" );

	TESortedPositions aPositions;
	sal_uLong nZero = 0;
	aPositions.Insert( nZero );

	sal_uInt16 nAttribs = pNode->GetCharAttribs().Count();
	for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
	{
		TextCharAttrib* pAttrib = pNode->GetCharAttribs().GetAttrib( nAttr );

		// Start und Ende in das Array eintragen...
		// Die InsertMethode laesst keine doppelten Werte zu....
		aPositions.Insert( pAttrib->GetStart() );
		aPositions.Insert( pAttrib->GetEnd() );
	}
	aPositions.Insert( pNode->GetText().Len() );

    const TEWritingDirectionInfos& rWritingDirections = pTEParaPortion->GetWritingDirectionInfos();
	for ( sal_uInt16 nD = 0; nD < rWritingDirections.Count(); nD++ )
		aPositions.Insert( rWritingDirections[nD].nStartPos );

	if ( mpIMEInfos && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetPara() == nPara ) )
	{
		sal_uInt16 nLastAttr = 0xFFFF;
		for( sal_uInt16 n = 0; n < mpIMEInfos->nLen; n++ )
		{
			if ( mpIMEInfos->pAttribs[n] != nLastAttr )
			{
				aPositions.Insert( mpIMEInfos->aPos.GetIndex() + n );
				nLastAttr = mpIMEInfos->pAttribs[n];
			}
		}
	}

	sal_uInt16 nTabPos = pNode->GetText().Search( '\t', 0 );
	while ( nTabPos != STRING_NOTFOUND )
	{
		aPositions.Insert( nTabPos );
		aPositions.Insert( nTabPos + 1 );
		nTabPos = pNode->GetText().Search( '\t', nTabPos+1 );
	}

	// Ab ... loeschen:
	// Leider muss die Anzahl der TextPortions mit aPositions.Count()
	// nicht uebereinstimmen, da evtl. Zeilenumbrueche...
	sal_uInt16 nPortionStart = 0;
	sal_uInt16 nInvPortion = 0;
    sal_uInt16 nP;
	for ( nP = 0; nP < pTEParaPortion->GetTextPortions().Count(); nP++ )
	{
		TETextPortion* pTmpPortion = pTEParaPortion->GetTextPortions().GetObject(nP);
		nPortionStart = nPortionStart + pTmpPortion->GetLen();
		if ( nPortionStart >= nStartPos )
		{
			nPortionStart = nPortionStart - pTmpPortion->GetLen();
			nInvPortion = nP;
			break;
		}
	}
	DBG_ASSERT( nP < pTEParaPortion->GetTextPortions().Count() || !pTEParaPortion->GetTextPortions().Count(), "Nichts zum loeschen: CreateTextPortions" );
	if ( nInvPortion && ( nPortionStart+pTEParaPortion->GetTextPortions().GetObject(nInvPortion)->GetLen() > nStartPos ) )
	{
		// lieber eine davor...
		// Aber nur wenn es mitten in der Portion war, sonst ist es evtl.
		// die einzige in der Zeile davor !
		nInvPortion--;
		nPortionStart = nPortionStart - pTEParaPortion->GetTextPortions().GetObject(nInvPortion)->GetLen();
	}
	pTEParaPortion->GetTextPortions().DeleteFromPortion( nInvPortion );

	// Eine Portion kann auch durch einen Zeilenumbruch entstanden sein:
	aPositions.Insert( nPortionStart );

	sal_uInt16 nInvPos;
    #ifdef DBG_UTIL
	sal_Bool bFound = 
    #endif
        aPositions.Seek_Entry( nPortionStart, &nInvPos );
	DBG_ASSERT( bFound && ( nInvPos < (aPositions.Count()-1) ), "InvPos ?!" );
	for ( sal_uInt16 i = nInvPos+1; i < aPositions.Count(); i++ )
	{
		TETextPortion* pNew = new TETextPortion( (sal_uInt16)aPositions[i] - (sal_uInt16)aPositions[i-1] );
		pTEParaPortion->GetTextPortions().Insert( pNew, pTEParaPortion->GetTextPortions().Count());
	}

	DBG_ASSERT( pTEParaPortion->GetTextPortions().Count(), "Keine Portions?!" );
#ifdef EDITDEBUG
	DBG_ASSERT( pTEParaPortion->DbgCheckTextPortions(), "Portions kaputt?" );
#endif
}

void TextEngine::RecalcTextPortion( sal_uLong nPara, sal_uInt16 nStartPos, short nNewChars )
{
	TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );
	DBG_ASSERT( pTEParaPortion->GetTextPortions().Count(), "Keine Portions!" );
	DBG_ASSERT( nNewChars, "RecalcTextPortion mit Diff == 0" );

	TextNode* const pNode = pTEParaPortion->GetNode();
	if ( nNewChars > 0 )
	{
		// Wenn an nStartPos ein Attribut beginnt/endet, oder vor nStartPos
		// ein Tab steht, faengt eine neue Portion an,
		// ansonsten wird die Portion an nStartPos erweitert.
		// Oder wenn ganz vorne ( StartPos 0 ) und dann ein Tab

		if ( ( pNode->GetCharAttribs().HasBoundingAttrib( nStartPos ) ) ||
			 ( nStartPos && ( pNode->GetText().GetChar( nStartPos - 1 ) == '\t' ) ) ||
			 ( ( !nStartPos && ( nNewChars < pNode->GetText().Len() ) && pNode->GetText().GetChar( nNewChars ) == '\t' ) ) )
		{
			sal_uInt16 nNewPortionPos = 0;
			if ( nStartPos )
				nNewPortionPos = SplitTextPortion( nPara, nStartPos ) + 1;
//			else if ( ( pTEParaPortion->GetTextPortions().Count() == 1 ) &&
//						!pTEParaPortion->GetTextPortions()[0]->GetLen() )
//				pTEParaPortion->GetTextPortions().Reset();	// DummyPortion

			// Eine leere Portion kann hier stehen, wenn der Absatz leer war,
			// oder eine Zeile durch einen harten Zeilenumbruch entstanden ist.
			if ( ( nNewPortionPos < pTEParaPortion->GetTextPortions().Count() ) &&
					!pTEParaPortion->GetTextPortions()[nNewPortionPos]->GetLen() )
			{
				// Dann die leere Portion verwenden.
                sal_uInt16 & r =
                    pTEParaPortion->GetTextPortions()[nNewPortionPos]->GetLen();
                r = r + nNewChars;
			}
			else
			{
				TETextPortion* pNewPortion = new TETextPortion( nNewChars );
				pTEParaPortion->GetTextPortions().Insert( pNewPortion, nNewPortionPos );
			}
		}
		else
		{
			sal_uInt16 nPortionStart;
			const sal_uInt16 nTP = pTEParaPortion->GetTextPortions().
				FindPortion( nStartPos, nPortionStart );
			TETextPortion* const pTP = pTEParaPortion->GetTextPortions()[ nTP ];
			DBG_ASSERT( pTP, "RecalcTextPortion: Portion nicht gefunden"  );
			pTP->GetLen() = pTP->GetLen() + nNewChars;
			pTP->GetWidth() = (-1);
		}
	}
	else
	{
		// Portion schrumpfen oder ggf. entfernen.
		// Vor Aufruf dieser Methode muss sichergestellt sein, dass
		// keine Portions in dem geloeschten Bereich lagen!

		// Es darf keine reinragende oder im Bereich startende Portion geben,
		// also muss nStartPos <= nPos <= nStartPos - nNewChars(neg.) sein
		sal_uInt16 nPortion = 0;
		sal_uInt16 nPos = 0;
		sal_uInt16 nEnd = nStartPos-nNewChars;
		sal_uInt16 nPortions = pTEParaPortion->GetTextPortions().Count();
		TETextPortion* pTP = 0;
		for ( nPortion = 0; nPortion < nPortions; nPortion++ )
		{
			pTP = pTEParaPortion->GetTextPortions()[ nPortion ];
			if ( ( nPos+pTP->GetLen() ) > nStartPos )
			{
				DBG_ASSERT( nPos <= nStartPos, "Start falsch!" );
				DBG_ASSERT( nPos+pTP->GetLen() >= nEnd, "End falsch!" );
				break;
			}
			nPos = nPos + pTP->GetLen();
		}
		DBG_ASSERT( pTP, "RecalcTextPortion: Portion nicht gefunden" );
		if ( ( nPos == nStartPos ) && ( (nPos+pTP->GetLen()) == nEnd ) )
		{
			// Portion entfernen;
			pTEParaPortion->GetTextPortions().Remove( nPortion );
			delete pTP;
		}
		else
		{
			DBG_ASSERT( pTP->GetLen() > (-nNewChars), "Portion zu klein zum schrumpfen!" );
			pTP->GetLen() = pTP->GetLen() + nNewChars;
		}
		DBG_ASSERT( pTEParaPortion->GetTextPortions().Count(), "RecalcTextPortions: Keine mehr da!" );
	}

#ifdef EDITDEBUG
	DBG_ASSERT( pTEParaPortion->DbgCheckTextPortions(), "Portions kaputt?" );
#endif
}

void TextEngine::ImpPaint( OutputDevice* pOutDev, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange, TextSelection const* pSelection )
{
	if ( !GetUpdateMode() )
		return;

	if ( !IsFormatted() )
		FormatDoc();
    
    bool bTransparent = false;
    Window* pOutWin = dynamic_cast<Window*>(pOutDev);
    bTransparent = (pOutWin && pOutWin->IsPaintTransparent());

	long nY = rStartPos.Y();

	TextPaM const* pSelStart = 0;
	TextPaM const* pSelEnd = 0;
	if ( pSelection && pSelection->HasRange() )
	{
		sal_Bool bInvers = pSelection->GetEnd() < pSelection->GetStart();
		pSelStart = !bInvers ? &pSelection->GetStart() : &pSelection->GetEnd();
		pSelEnd = bInvers ? &pSelection->GetStart() : &pSelection->GetEnd();
	}
	DBG_ASSERT( !pPaintRange || ( pPaintRange->GetStart() < pPaintRange->GetEnd() ), "ImpPaint: Paint-Range?!" );

	const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();

	// --------------------------------------------------
	// Ueber alle Absaetze...
	// --------------------------------------------------
	for ( sal_uLong nPara = 0; nPara < mpTEParaPortions->Count(); nPara++ )
	{
		TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara );
		// falls beim Tippen Idle-Formatierung, asynchrones Paint.
		if ( pPortion->IsInvalid() )
			return;

		sal_uLong nParaHeight = CalcParaHeight( nPara );
		sal_uInt16 nIndex = 0;
		if ( ( !pPaintArea || ( ( nY + (long)nParaHeight ) > pPaintArea->Top() ) )
				&& ( !pPaintRange || ( ( nPara >= pPaintRange->GetStart().GetPara() ) && ( nPara <= pPaintRange->GetEnd().GetPara() ) ) ) )
		{
			// --------------------------------------------------
			// Ueber die Zeilen des Absatzes...
			// --------------------------------------------------
			sal_uInt16 nLines = pPortion->GetLines().Count();
			for ( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
			{
				TextLine* pLine = pPortion->GetLines().GetObject(nLine);
				Point aTmpPos( rStartPos.X() + pLine->GetStartX(), nY );

				if ( ( !pPaintArea || ( ( nY + mnCharHeight ) > pPaintArea->Top() ) )
					&& ( !pPaintRange || (
						( TextPaM( nPara, pLine->GetStart() ) < pPaintRange->GetEnd() ) &&
						( TextPaM( nPara, pLine->GetEnd() ) > pPaintRange->GetStart() ) ) ) )
				{
					// --------------------------------------------------
					// Ueber die Portions der Zeile...
					// --------------------------------------------------
					nIndex = pLine->GetStart();
					for ( sal_uInt16 y = pLine->GetStartPortion(); y <= pLine->GetEndPortion(); y++ )
					{
						DBG_ASSERT( pPortion->GetTextPortions().Count(), "Zeile ohne Textportion im Paint!" );
						TETextPortion* pTextPortion = pPortion->GetTextPortions().GetObject( y );
						DBG_ASSERT( pTextPortion, "NULL-Pointer im Portioniterator in UpdateViews" );

                        ImpInitLayoutMode( pOutDev /*, pTextPortion->IsRightToLeft() */);

						long nTxtWidth = pTextPortion->GetWidth();
                        aTmpPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nIndex, nIndex );

						// nur ausgeben, was im sichtbaren Bereich beginnt:
						if ( ( ( aTmpPos.X() + nTxtWidth ) >= 0 )
							&& ( !pPaintRange || (
								( TextPaM( nPara, nIndex ) < pPaintRange->GetEnd() ) &&
									( TextPaM( nPara, nIndex + pTextPortion->GetLen() ) > pPaintRange->GetStart() ) ) ) )
						{
							switch ( pTextPortion->GetKind() )
							{
								case PORTIONKIND_TEXT:
								{
									{
										Font aFont;
										SeekCursor( nPara, nIndex+1, aFont, pOutDev );
                                        if( bTransparent )
                                            aFont.SetTransparent( sal_True );
										else if ( pSelection )
											aFont.SetTransparent( sal_False );
										pOutDev->SetFont( aFont );

										sal_uInt16 nTmpIndex = nIndex;
										sal_uInt16 nEnd = nTmpIndex + pTextPortion->GetLen();
										Point aPos = aTmpPos;
										if ( pPaintRange )
										{
											// evtl soll nicht alles ausgegeben werden...
											if ( ( pPaintRange->GetStart().GetPara() == nPara )
													&& ( nTmpIndex < pPaintRange->GetStart().GetIndex() ) )
											{
												nTmpIndex = pPaintRange->GetStart().GetIndex();
											}
											if ( ( pPaintRange->GetEnd().GetPara() == nPara )
													&& ( nEnd > pPaintRange->GetEnd().GetIndex() ) )
											{
												nEnd = pPaintRange->GetEnd().GetIndex();
											}
										}

										sal_Bool bDone = sal_False;
										if ( pSelStart )
										{
											// liegt ein Teil in der Selektion???
											TextPaM aTextStart( nPara, nTmpIndex );
											TextPaM aTextEnd( nPara, nEnd );
											if ( ( aTextStart < *pSelEnd ) && ( aTextEnd > *pSelStart ) )
											{
												sal_uInt16 nL;

												// 1) Bereich vor Selektion
												if ( aTextStart < *pSelStart )
												{
													nL = pSelStart->GetIndex() - nTmpIndex;
													pOutDev->SetFont( aFont);
                                                    aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nTmpIndex+nL );
													pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nL );
													nTmpIndex = nTmpIndex + nL;

												}
												// 2) Bereich mit Selektion
												nL = nEnd-nTmpIndex;
												if ( aTextEnd > *pSelEnd )
													nL = pSelEnd->GetIndex() - nTmpIndex;
												if ( nL )
												{
													Color aOldTextColor = pOutDev->GetTextColor();
													pOutDev->SetTextColor( rStyleSettings.GetHighlightTextColor() );
													pOutDev->SetTextFillColor( rStyleSettings.GetHighlightColor() );
													aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nTmpIndex+nL );
													pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nL );
													pOutDev->SetTextColor( aOldTextColor );
													pOutDev->SetTextFillColor();
													nTmpIndex = nTmpIndex + nL;
												}

												// 3) Bereich nach Selektion
												if ( nTmpIndex < nEnd )
												{
												    nL = nEnd-nTmpIndex;
                                                    aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nTmpIndex+nL );
													pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nEnd-nTmpIndex );
												}
												bDone = sal_True;
											}
										}
										if ( !bDone )
                                        {
                                            aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nEnd );
											pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nEnd-nTmpIndex );
                                        }
									}

								}
								break;
								case PORTIONKIND_TAB:
								{
									// Bei HideSelection() nur Range, pSelection = 0.
									if ( pSelStart || pPaintRange )
									{
										Rectangle aTabArea( aTmpPos, Point( aTmpPos.X()+nTxtWidth, aTmpPos.Y()+mnCharHeight-1 ) );
										sal_Bool bDone = sal_False;
										if ( pSelStart )
										{
											// liegt der Tab in der Selektion???
											TextPaM aTextStart( nPara, nIndex );
											TextPaM aTextEnd( nPara, nIndex+1 );
											if ( ( aTextStart < *pSelEnd ) && ( aTextEnd > *pSelStart ) )
											{
												Color aOldColor = pOutDev->GetFillColor();
												pOutDev->SetFillColor( rStyleSettings.GetHighlightColor() );
												pOutDev->DrawRect( aTabArea );
												pOutDev->SetFillColor( aOldColor );
												bDone = sal_True;
											}
										}
										if ( !bDone )
										{
											pOutDev->Erase( aTabArea );
										}
									}
#ifdef EDITDEBUG
									Rectangle aTabArea( aTmpPos, Point( aTmpPos.X()+nTxtWidth, aTmpPos.Y()+mnCharHeight-1 ) );
									Color aOldColor = pOutDev->GetFillColor();
                                    pOutDev->SetFillColor( (y%2) ? COL_RED : COL_GREEN );
									pOutDev->DrawRect( aTabArea );
									pOutDev->SetFillColor( aOldColor );
#endif
								}
								break;
								default:	DBG_ERROR( "ImpPaint: Unknown Portion-Type !" );
							}
						}

						nIndex = nIndex + pTextPortion->GetLen();
					}
				}

				nY += mnCharHeight;

				if ( pPaintArea && ( nY >= pPaintArea->Bottom() ) )
					break;	// keine sichtbaren Aktionen mehr...
			}
		}
		else
		{
			nY += nParaHeight;
		}

		if ( pPaintArea && ( nY > pPaintArea->Bottom() ) )
			break;	// keine sichtbaren Aktionen mehr...
	}
}

sal_Bool TextEngine::CreateLines( sal_uLong nPara )
{
	// sal_Bool: Aenderung der Hoehe des Absatzes Ja/Nein - sal_True/sal_False

	TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
	TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );
	DBG_ASSERT( pTEParaPortion->IsInvalid(), "CreateLines: Portion nicht invalid!" );

	sal_uInt16 nOldLineCount = pTEParaPortion->GetLines().Count();

	// ---------------------------------------------------------------
	// Schnelle Sonderbehandlung fuer leere Absaetze...
	// ---------------------------------------------------------------
	if ( pTEParaPortion->GetNode()->GetText().Len() == 0 )
	{
		// schnelle Sonderbehandlung...
		if ( pTEParaPortion->GetTextPortions().Count() )
			pTEParaPortion->GetTextPortions().Reset();
		if ( pTEParaPortion->GetLines().Count() )
			pTEParaPortion->GetLines().DeleteAndDestroy( 0, pTEParaPortion->GetLines().Count() );
		CreateAndInsertEmptyLine( nPara );
		pTEParaPortion->SetValid();
		return nOldLineCount != pTEParaPortion->GetLines().Count();
	}

	// ---------------------------------------------------------------
	// Initialisierung......
	// ---------------------------------------------------------------

	if ( pTEParaPortion->GetLines().Count() == 0 )
	{
		TextLine* pL = new TextLine;
		pTEParaPortion->GetLines().Insert( pL, 0 );
	}

	const short nInvalidDiff = pTEParaPortion->GetInvalidDiff();
	const sal_uInt16 nInvalidStart = pTEParaPortion->GetInvalidPosStart();
	const sal_uInt16 nInvalidEnd =  nInvalidStart + Abs( nInvalidDiff );
	sal_Bool bQuickFormat = sal_False;

	if ( !pTEParaPortion->GetWritingDirectionInfos().Count() )
		ImpInitWritingDirections( nPara );

    if ( pTEParaPortion->GetWritingDirectionInfos().Count() == 1 )
    {
	    if ( pTEParaPortion->IsSimpleInvalid() && ( nInvalidDiff > 0 ) )
	    {
		    bQuickFormat = sal_True;
	    }
	    else if ( ( pTEParaPortion->IsSimpleInvalid() ) && ( nInvalidDiff < 0 ) )
	    {
		    // pruefen, ob loeschen ueber Portiongrenzen erfolgte...
		    sal_uInt16 nStart = nInvalidStart;	// DOPPELT !!!!!!!!!!!!!!!
		    sal_uInt16 nEnd = nStart - nInvalidDiff;  // neg.
		    bQuickFormat = sal_True;
		    sal_uInt16 nPos = 0;
		    sal_uInt16 nPortions = pTEParaPortion->GetTextPortions().Count();
		    for ( sal_uInt16 nTP = 0; nTP < nPortions; nTP++ )
		    {
			    // Es darf kein Start/Ende im geloeschten Bereich liegen.
			    TETextPortion* const pTP = pTEParaPortion->GetTextPortions().GetObject( nTP );
			    nPos = nPos + pTP->GetLen();
			    if ( ( nPos > nStart ) && ( nPos < nEnd ) )
			    {
				    bQuickFormat = sal_False;
				    break;
			    }
		    }
	    }
    }

	if ( bQuickFormat )
		RecalcTextPortion( nPara, nInvalidStart, nInvalidDiff );
	else
		CreateTextPortions( nPara, nInvalidStart );

	// ---------------------------------------------------------------
	// Zeile mit InvalidPos suchen, eine Zeile davor beginnen...
	// Zeilen flaggen => nicht removen !
	// ---------------------------------------------------------------

	sal_uInt16 nLine = pTEParaPortion->GetLines().Count()-1;
	for ( sal_uInt16 nL = 0; nL <= nLine; nL++ )
	{
		TextLine* pLine = pTEParaPortion->GetLines().GetObject( nL );
		if ( pLine->GetEnd() > nInvalidStart )
		{
			nLine = nL;
			break;
		}
		pLine->SetValid();
	}
	// Eine Zeile davor beginnen...
	// Wenn ganz hinten getippt wird, kann sich die Zeile davor nicht aendern.
	if ( nLine && ( !pTEParaPortion->IsSimpleInvalid() || ( nInvalidEnd < pNode->GetText().Len() ) || ( nInvalidDiff <= 0 ) ) )
		nLine--;

	TextLine* pLine = pTEParaPortion->GetLines().GetObject( nLine );

	// ---------------------------------------------------------------
	// Ab hier alle Zeilen durchformatieren...
	// ---------------------------------------------------------------
	sal_uInt16 nDelFromLine = 0xFFFF;
	sal_Bool bLineBreak = sal_False;

	sal_uInt16 nIndex = pLine->GetStart();
	TextLine aSaveLine( *pLine );

	Font aFont;

	sal_Bool bCalcPortion = sal_True;

	while ( nIndex < pNode->GetText().Len() )
	{
		sal_Bool bEOL = sal_False;
		sal_Bool bEOC = sal_False;
		sal_uInt16 nPortionStart = 0;
		sal_uInt16 nPortionEnd = 0;

		sal_uInt16 nTmpPos = nIndex;
		sal_uInt16 nTmpPortion = pLine->GetStartPortion();
		long nTmpWidth = mpDoc->GetLeftMargin();
//		long nXWidth = mnMaxTextWidth ? ( mnMaxTextWidth - mpDoc->GetLeftMargin() ) : 0x7FFFFFFF;
		// Margin nicht abziehen, ist schon in TmpWidth enthalten.
		long nXWidth = mnMaxTextWidth ? mnMaxTextWidth : 0x7FFFFFFF;
		if ( nXWidth < nTmpWidth )
			nXWidth = nTmpWidth;

		// Portion suchen, die nicht mehr in Zeile passt....
		TETextPortion* pPortion = 0;
		sal_Bool bBrokenLine = sal_False;
		bLineBreak = sal_False;

		while ( ( nTmpWidth <= nXWidth ) && !bEOL && ( nTmpPortion < pTEParaPortion->GetTextPortions().Count() ) )
		{
			nPortionStart = nTmpPos;
			pPortion = pTEParaPortion->GetTextPortions().GetObject( nTmpPortion );
			DBG_ASSERT( pPortion->GetLen(), "Leere Portion in CreateLines ?!" );
			if ( pNode->GetText().GetChar( nTmpPos ) == '\t' )
			{
				long nCurPos = nTmpWidth-mpDoc->GetLeftMargin();
				nTmpWidth = ((nCurPos/mnDefTab)+1)*mnDefTab+mpDoc->GetLeftMargin();
				pPortion->GetWidth() = nTmpWidth - nCurPos - mpDoc->GetLeftMargin();
				// Wenn dies das erste Token in der Zeile ist, und
				// nTmpWidth > aPaperSize.Width, habe ich eine Endlos-Schleife!
				if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->GetStartPortion() ) )
				{
					// Aber was jetzt ? Tab passend machen!
					pPortion->GetWidth() = nXWidth-1;
					nTmpWidth = pPortion->GetWidth();
					bEOL = sal_True;
					bBrokenLine = sal_True;
				}
				pPortion->GetKind() = PORTIONKIND_TAB;
			}
			else
			{

				if ( bCalcPortion || !pPortion->HasValidSize() )
					pPortion->GetWidth() = (long)CalcTextWidth( nPara, nTmpPos, pPortion->GetLen() );
				nTmpWidth += pPortion->GetWidth();

                pPortion->GetRightToLeft() = ImpGetRightToLeft( nPara, nTmpPos+1 );
				pPortion->GetKind() = PORTIONKIND_TEXT;
			}

			nTmpPos = nTmpPos + pPortion->GetLen();
			nPortionEnd = nTmpPos;
			nTmpPortion++;
		}

		// das war evtl. eine Portion zu weit:
		sal_Bool bFixedEnd = sal_False;
		if ( nTmpWidth > nXWidth )
		{
			nPortionEnd = nTmpPos;
			nTmpPos = nTmpPos - pPortion->GetLen();
			nPortionStart = nTmpPos;
			nTmpPortion--;
			bEOL = sal_False;
			bEOC = sal_False;

			nTmpWidth -= pPortion->GetWidth();
			if ( pPortion->GetKind() == PORTIONKIND_TAB )
			{
				bEOL = sal_True;
				bFixedEnd = sal_True;
			}
		}
		else
		{
			bEOL = sal_True;
			bEOC = sal_True;
			pLine->SetEnd( nPortionEnd );
			DBG_ASSERT( pTEParaPortion->GetTextPortions().Count(), "Keine TextPortions?" );
			pLine->SetEndPortion( (sal_uInt16)pTEParaPortion->GetTextPortions().Count() - 1 );
		}

		if ( bFixedEnd )
		{
			pLine->SetEnd( nPortionStart );
			pLine->SetEndPortion( nTmpPortion-1 );
		}
		else if ( bLineBreak || bBrokenLine )
		{
			pLine->SetEnd( nPortionStart+1 );
			pLine->SetEndPortion( nTmpPortion-1 );
			bEOC = sal_False; // wurde oben gesetzt, vielleich mal die if's umstellen?
		}
		else if ( !bEOL )
		{
			DBG_ASSERT( (nPortionEnd-nPortionStart) == pPortion->GetLen(), "Doch eine andere Portion?!" );
			long nRemainingWidth = mnMaxTextWidth - nTmpWidth;
			ImpBreakLine( nPara, pLine, pPortion, nPortionStart, nRemainingWidth );
		}

		if ( ( ImpGetAlign() == TXTALIGN_CENTER ) || ( ImpGetAlign() == TXTALIGN_RIGHT ) )
		{
			// Ausrichten...
			long nTextWidth = 0;
			for ( sal_uInt16 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ )
			{
				TETextPortion* pTextPortion = pTEParaPortion->GetTextPortions().GetObject( nTP );
				nTextWidth += pTextPortion->GetWidth();
			}
			long nSpace = mnMaxTextWidth - nTextWidth;
			if ( nSpace > 0 )
			{
				if ( ImpGetAlign() == TXTALIGN_CENTER )
					pLine->SetStartX( (sal_uInt16)(nSpace / 2) );
				else	// TXTALIGN_RIGHT
					pLine->SetStartX( (sal_uInt16)nSpace );
			}
		}
		else
		{
			pLine->SetStartX( mpDoc->GetLeftMargin() );
		}

		// -----------------------------------------------------------------
		// pruefen, ob die Zeile neu ausgegeben werden muss...
		// -----------------------------------------------------------------
		pLine->SetInvalid();

		if ( pTEParaPortion->IsSimpleInvalid() )
		{
			// Aenderung durch einfache Textaenderung...
			// Formatierung nicht abbrechen, da Portions evtl. wieder
			// gesplittet werden muessen!
			// Wenn irgendwann mal abbrechbar, dann fogende Zeilen Validieren!
			// Aber ggf. als Valid markieren, damit weniger Ausgabe...
			if ( pLine->GetEnd() < nInvalidStart )
			{
				if ( *pLine == aSaveLine )
				{
					pLine->SetValid();
				}
			}
			else
			{
				sal_uInt16 nStart = pLine->GetStart();
				sal_uInt16 nEnd = pLine->GetEnd();

				if ( nStart > nInvalidEnd )
				{
					if ( ( ( nStart-nInvalidDiff ) == aSaveLine.GetStart() ) &&
							( ( nEnd-nInvalidDiff ) == aSaveLine.GetEnd() ) )
					{
						pLine->SetValid();
						if ( bCalcPortion && bQuickFormat )
						{
							bCalcPortion = sal_False;
							pTEParaPortion->CorrectValuesBehindLastFormattedLine( nLine );
							break;
						}
					}
				}
				else if ( bQuickFormat && ( nEnd > nInvalidEnd) )
				{
					// Wenn die ungueltige Zeile so endet, dass die naechste an
					// der 'gleichen' Textstelle wie vorher beginnt, also nicht
					// anders umgebrochen wird, brauche ich dort auch nicht die
					// textbreiten neu bestimmen:
					if ( nEnd == ( aSaveLine.GetEnd() + nInvalidDiff ) )
					{
						bCalcPortion = sal_False;
						pTEParaPortion->CorrectValuesBehindLastFormattedLine( nLine );
						break;
					}
				}
			}
		}

		nIndex = pLine->GetEnd();	// naechste Zeile Start = letzte Zeile Ende
									// weil nEnd hinter das letzte Zeichen zeigt!

		sal_uInt16 nEndPortion = pLine->GetEndPortion();

		// Naechste Zeile oder ggf. neue Zeile....
		pLine = 0;
		if ( nLine < pTEParaPortion->GetLines().Count()-1 )
			pLine = pTEParaPortion->GetLines().GetObject( ++nLine );
		if ( pLine && ( nIndex >= pNode->GetText().Len() ) )
		{
			nDelFromLine = nLine;
			break;
		}
		if ( !pLine && ( nIndex < pNode->GetText().Len() )  )
		{
			pLine = new TextLine;
			pTEParaPortion->GetLines().Insert( pLine, ++nLine );
		}
		if ( pLine )
		{
			aSaveLine = *pLine;
			pLine->SetStart( nIndex );
			pLine->SetEnd( nIndex );
			pLine->SetStartPortion( nEndPortion+1 );
			pLine->SetEndPortion( nEndPortion+1 );
		}
	}	// while ( Index < Len )

	if ( nDelFromLine != 0xFFFF )
		pTEParaPortion->GetLines().DeleteAndDestroy( nDelFromLine, pTEParaPortion->GetLines().Count() - nDelFromLine );

	DBG_ASSERT( pTEParaPortion->GetLines().Count(), "Keine Zeile nach CreateLines!" );

	if ( bLineBreak == sal_True )
		CreateAndInsertEmptyLine( nPara );

	pTEParaPortion->SetValid();

	return nOldLineCount != pTEParaPortion->GetLines().Count();
}

String TextEngine::GetWord( const TextPaM& rCursorPos, TextPaM* pStartOfWord )
{
	String aWord;
	if ( rCursorPos.GetPara() < mpDoc->GetNodes().Count() )
	{
		TextSelection aSel( rCursorPos );
		TextNode* pNode = mpDoc->GetNodes().GetObject(  rCursorPos.GetPara() );
		uno::Reference < i18n::XBreakIterator > xBI = GetBreakIterator();
		i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rCursorPos.GetIndex(), GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
		aSel.GetStart().GetIndex() = (sal_uInt16)aBoundary.startPos;
		aSel.GetEnd().GetIndex() = (sal_uInt16)aBoundary.endPos;
		aWord = pNode->GetText().Copy( aSel.GetStart().GetIndex(), aSel.GetEnd().GetIndex() - aSel.GetStart().GetIndex() );
		if ( pStartOfWord )
			*pStartOfWord = aSel.GetStart();
	}
	return aWord;
}

sal_Bool TextEngine::Read( SvStream& rInput, const TextSelection* pSel )
{
	sal_Bool bUpdate = GetUpdateMode();
	SetUpdateMode( sal_False );

	UndoActionStart();
	TextSelection aSel;
	if ( pSel )
		aSel = *pSel;
	else
	{
		sal_uLong nParas = mpDoc->GetNodes().Count();
		TextNode* pNode = mpDoc->GetNodes().GetObject( nParas - 1 );
		aSel = TextPaM( nParas-1 , pNode->GetText().Len() );
	}

	if ( aSel.HasRange() )
		aSel = ImpDeleteText( aSel );

	ByteString aLine;
	sal_Bool bDone = rInput.ReadLine( aLine );
	String aTmpStr( aLine, rInput.GetStreamCharSet() ), aStr;
	while ( bDone )
	{
		aSel = ImpInsertText( aSel, aTmpStr );
		bDone = rInput.ReadLine( aLine );
		aTmpStr = String( aLine, rInput.GetStreamCharSet() );
		if ( bDone )
			aSel = ImpInsertParaBreak( aSel.GetEnd() );
	}

	UndoActionEnd();

	TextSelection aNewSel( aSel.GetEnd(), aSel.GetEnd() );

	// Damit bei FormatAndUpdate nicht auf die ungueltige Selektion zugegriffen wird.
	if ( GetActiveView() )
		GetActiveView()->ImpSetSelection( aNewSel );

	SetUpdateMode( bUpdate );
	FormatAndUpdate( GetActiveView() );

	return rInput.GetError() ? sal_False : sal_True;
}

sal_Bool TextEngine::Write( SvStream& rOutput, const TextSelection* pSel, sal_Bool bHTML )
{
	TextSelection aSel;
	if ( pSel )
		aSel = *pSel;
	else
	{
		sal_uLong nParas = mpDoc->GetNodes().Count();
		TextNode* pNode = mpDoc->GetNodes().GetObject( nParas - 1 );
		aSel.GetStart() = TextPaM( 0, 0 );
		aSel.GetEnd() = TextPaM( nParas-1, pNode->GetText().Len() );
	}

	if ( bHTML )
	{
		rOutput.WriteLine( "<HTML>" );
		rOutput.WriteLine( "<BODY>" );
	}

	for ( sal_uLong nPara = aSel.GetStart().GetPara(); nPara <= aSel.GetEnd().GetPara(); nPara++  )
	{
		TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );

		sal_uInt16 nStartPos = 0;
		sal_uInt16 nEndPos = pNode->GetText().Len();
		if ( nPara == aSel.GetStart().GetPara() )
			nStartPos = aSel.GetStart().GetIndex();
		if ( nPara == aSel.GetEnd().GetPara() )
			nEndPos = aSel.GetEnd().GetIndex();

		String aText;
		if ( !bHTML )
		{
			aText = pNode->GetText().Copy( nStartPos, nEndPos-nStartPos );
		}
		else
		{
			aText.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "<P STYLE=\"margin-bottom: 0cm\">" ) );

			if ( nStartPos == nEndPos )
			{
				// Leerzeilen werden von Writer wegoptimiert
				aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "<BR>" ) );
			}
			else
			{
				sal_uInt16 nTmpStart = nStartPos;
				sal_uInt16 nTmpEnd = nEndPos;
				do
				{
					TextCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( TEXTATTR_HYPERLINK, nTmpStart, nEndPos );
					nTmpEnd = pAttr ? pAttr->GetStart() : nEndPos;

					// Text vor dem Attribut
					aText += pNode->GetText().Copy( nTmpStart, nTmpEnd-nTmpStart );

					if ( pAttr )
					{
						nTmpEnd = Min( pAttr->GetEnd(), nEndPos );

						// z.B. <A HREF="http://www.mopo.de/">Morgenpost</A>
						aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "<A HREF=\"" ) );
						aText += ((const TextAttribHyperLink&) pAttr->GetAttr() ).GetURL();
						aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "\">" ) );
						nTmpStart = pAttr->GetStart();
						aText += pNode->GetText().Copy( nTmpStart, nTmpEnd-nTmpStart );
						aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "</A>" ) );

						nTmpStart = pAttr->GetEnd();
					}
				} while ( nTmpEnd < nEndPos );
			}

			aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "</P>" ) );
		}
		rOutput.WriteLine( ByteString( aText, rOutput.GetStreamCharSet() ) );
	}

	if ( bHTML )
	{
		rOutput.WriteLine( "</BODY>" );
		rOutput.WriteLine( "</HTML>" );
	}

	return rOutput.GetError() ? sal_False : sal_True;
}

void TextEngine::RemoveAttribs( sal_uLong nPara, sal_Bool bIdleFormatAndUpdate )
{
	if ( nPara < mpDoc->GetNodes().Count() )
	{
		TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
		if ( pNode->GetCharAttribs().Count() )
		{
			pNode->GetCharAttribs().Clear( sal_True );

			TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );
			pTEParaPortion->MarkSelectionInvalid( 0, pNode->GetText().Len() );

			mbFormatted = sal_False;

    		if ( bIdleFormatAndUpdate )
    			IdleFormatAndUpdate( NULL, 0xFFFF );
    		else
    			FormatAndUpdate( NULL );
		}
	}
}
void TextEngine::RemoveAttribs( sal_uLong nPara, sal_uInt16 nWhich, sal_Bool bIdleFormatAndUpdate )
{
    if ( nPara < mpDoc->GetNodes().Count() )
    {
        TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
        if ( pNode->GetCharAttribs().Count() )
        {
            TextCharAttribList& rAttribs = pNode->GetCharAttribs();
            sal_uInt16 nAttrCount = rAttribs.Count();
            for(sal_uInt16 nAttr = nAttrCount; nAttr; --nAttr)
            {
                if(rAttribs.GetAttrib( nAttr - 1 )->Which() == nWhich)
                    rAttribs.RemoveAttrib( nAttr -1 );
            }
            TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );
            pTEParaPortion->MarkSelectionInvalid( 0, pNode->GetText().Len() );
            mbFormatted = sal_False;
            if(bIdleFormatAndUpdate)
                IdleFormatAndUpdate( NULL, 0xFFFF );
            else
                FormatAndUpdate( NULL );
        }
    }
}        
void TextEngine::RemoveAttrib( sal_uLong nPara, const TextCharAttrib& rAttrib )
{
    if ( nPara < mpDoc->GetNodes().Count() )
    {
        TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
        if ( pNode->GetCharAttribs().Count() )
        {
            TextCharAttribList& rAttribs = pNode->GetCharAttribs();
            sal_uInt16 nAttrCount = rAttribs.Count();
            for(sal_uInt16 nAttr = nAttrCount; nAttr; --nAttr)
            {
                if(rAttribs.GetAttrib( nAttr - 1 ) == &rAttrib)
                {        
                    rAttribs.RemoveAttrib( nAttr -1 );
                    break;
                }
            }
            TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );
            pTEParaPortion->MarkSelectionInvalid( 0, pNode->GetText().Len() );
            mbFormatted = sal_False;
            FormatAndUpdate( NULL );
        }
    }
}        

void TextEngine::SetAttrib( const TextAttrib& rAttr, sal_uLong nPara, sal_uInt16 nStart, sal_uInt16 nEnd, sal_Bool bIdleFormatAndUpdate )
{
	// Es wird hier erstmal nicht geprueft, ob sich Attribute ueberlappen!
	// Diese Methode ist erstmal nur fuer einen Editor, der fuer eine Zeile
	// _schnell_ das Syntax-Highlight einstellen will.

	// Da die TextEngine z.Zt fuer Editoren gedacht ist gibt es auch kein
	// Undo fuer Attribute!

	if ( nPara < mpDoc->GetNodes().Count() )
	{
		TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
		TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara );

		sal_uInt16 nMax = pNode->GetText().Len();
		if ( nStart > nMax )
			nStart = nMax;
		if ( nEnd > nMax )
			nEnd = nMax;

		pNode->GetCharAttribs().InsertAttrib( new TextCharAttrib( rAttr, nStart, nEnd ) );
		pTEParaPortion->MarkSelectionInvalid( nStart, nEnd );

		mbFormatted = sal_False;
		if ( bIdleFormatAndUpdate )
			IdleFormatAndUpdate( NULL, 0xFFFF );
		else
			FormatAndUpdate( NULL );
	}
}

void TextEngine::SetTextAlign( TxtAlign eAlign )
{
	if ( eAlign != meAlign )
	{
		meAlign = eAlign;
		FormatFullDoc();
		UpdateViews();
	}
}


void TextEngine::ValidateSelection( TextSelection& rSel ) const
{
	ValidatePaM( rSel.GetStart() );
	ValidatePaM( rSel.GetEnd() );
}

void TextEngine::ValidatePaM( TextPaM& rPaM ) const
{
	sal_uLong nMaxPara = mpDoc->GetNodes().Count() - 1;
	if ( rPaM.GetPara() > nMaxPara )
	{
		rPaM.GetPara() = nMaxPara;
		rPaM.GetIndex() = 0xFFFF;
	}

	sal_uInt16 nMaxIndex = GetTextLen( rPaM.GetPara() );
	if ( rPaM.GetIndex() > nMaxIndex )
		rPaM.GetIndex() = nMaxIndex;
}


// Status & Selektionsanpassung

void TextEngine::ImpParagraphInserted( sal_uLong nPara )
{
	// Die aktive View braucht nicht angepasst werden, aber bei allen
	// passiven muss die Selektion angepasst werden:
	if ( mpViews->Count() > 1 )
	{
		for ( sal_uInt16 nView = mpViews->Count(); nView; )
		{
			TextView* pView = mpViews->GetObject( --nView );
			if ( pView != GetActiveView() )
			{
//				sal_Bool bInvers = pView->maSelection.GetEnd() < pView->maSelection.GetStart();
//				TextPaM& rMin = !bInvers ? pView->maSelection.GetStart(): pView->maSelection.GetEnd();
//				TextPaM& rMax = bInvers ? pView->maSelection.GetStart() : pView->maSelection.GetEnd();
//
//				if ( rMin.GetPara() >= nPara )
//					rMin.GetPara()++;
//				if ( rMax.GetPara() >= nPara )
//					rMax.GetPara()++;
				for ( int n = 0; n <= 1; n++ )
				{
                    TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd();
					if ( rPaM.GetPara() >= nPara )
						rPaM.GetPara()++;
				}
			}
		}
	}
	Broadcast( TextHint( TEXT_HINT_PARAINSERTED, nPara ) );
}

void TextEngine::ImpParagraphRemoved( sal_uLong nPara )
{
	if ( mpViews->Count() > 1 )
	{
		for ( sal_uInt16 nView = mpViews->Count(); nView; )
		{
			TextView* pView = mpViews->GetObject( --nView );
			if ( pView != GetActiveView() )
			{
				sal_uLong nParas = mpDoc->GetNodes().Count();
				for ( int n = 0; n <= 1; n++ )
				{
                    TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd();
					if ( rPaM.GetPara() > nPara )
						rPaM.GetPara()--;
					else if ( rPaM.GetPara() == nPara )
					{
						rPaM.GetIndex() = 0;
						if ( rPaM.GetPara() >= nParas )
							rPaM.GetPara()--;
					}
				}
			}
		}
	}
	Broadcast( TextHint( TEXT_HINT_PARAREMOVED, nPara ) );
}

void TextEngine::ImpCharsRemoved( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars )
{
	if ( mpViews->Count() > 1 )
	{
		for ( sal_uInt16 nView = mpViews->Count(); nView; )
		{
			TextView* pView = mpViews->GetObject( --nView );
			if ( pView != GetActiveView() )
			{
				sal_uInt16 nEnd = nPos+nChars;
				for ( int n = 0; n <= 1; n++ )
				{
                    TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd();
					if ( rPaM.GetPara() == nPara )
					{
						if ( rPaM.GetIndex() > nEnd )
							rPaM.GetIndex() = rPaM.GetIndex() - nChars;
						else if ( rPaM.GetIndex() > nPos )
							rPaM.GetIndex() = nPos;
					}
				}
			}
		}
	}
	Broadcast( TextHint( TEXT_HINT_PARACONTENTCHANGED, nPara ) );
}

void TextEngine::ImpCharsInserted( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars )
{
	if ( mpViews->Count() > 1 )
	{
		for ( sal_uInt16 nView = mpViews->Count(); nView; )
		{
			TextView* pView = mpViews->GetObject( --nView );
			if ( pView != GetActiveView() )
			{
				for ( int n = 0; n <= 1; n++ )
				{
                    TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd();
					if ( rPaM.GetPara() == nPara )
					{
						if ( rPaM.GetIndex() >= nPos )
							rPaM.GetIndex() = rPaM.GetIndex() + nChars;
					}
				}
			}
		}
	}
	Broadcast( TextHint( TEXT_HINT_PARACONTENTCHANGED, nPara ) );
}

void TextEngine::ImpFormattingParagraph( sal_uLong nPara )
{
	Broadcast( TextHint( TEXT_HINT_FORMATPARA, nPara ) );
}

void TextEngine::ImpTextHeightChanged()
{
	Broadcast( TextHint( TEXT_HINT_TEXTHEIGHTCHANGED ) );
}

void TextEngine::ImpTextFormatted()
{
	Broadcast( TextHint( TEXT_HINT_TEXTFORMATTED ) );
}

void TextEngine::Draw( OutputDevice* pDev, const Point& rPos )
{
	ImpPaint( pDev, rPos, NULL );
}

void TextEngine::SetLeftMargin( sal_uInt16 n )
{
	mpDoc->SetLeftMargin( n );
}

sal_uInt16 TextEngine::GetLeftMargin() const
{
	return mpDoc->GetLeftMargin();
}

uno::Reference< i18n::XBreakIterator > TextEngine::GetBreakIterator()
{
	if ( !mxBreakIterator.is() )
		mxBreakIterator = vcl::unohelper::CreateBreakIterator();
    DBG_ASSERT( mxBreakIterator.is(), "Could not create BreakIterator" );
	return mxBreakIterator;
}

void TextEngine::SetLocale( const ::com::sun::star::lang::Locale& rLocale )
{
    maLocale = rLocale;
    delete mpLocaleDataWrapper;
    mpLocaleDataWrapper = NULL;
}

::com::sun::star::lang::Locale TextEngine::GetLocale()
{
	if ( !maLocale.Language.getLength() )
	{
        maLocale = Application::GetSettings().GetUILocale();
	}
	return maLocale;
}

LocaleDataWrapper* TextEngine::ImpGetLocaleDataWrapper()
{
    if ( !mpLocaleDataWrapper )
        mpLocaleDataWrapper = new LocaleDataWrapper( vcl::unohelper::GetMultiServiceFactory(), GetLocale() );

    return mpLocaleDataWrapper;
}

void TextEngine::SetRightToLeft( sal_Bool bR2L ) 
{ 
    if ( mbRightToLeft != bR2L )
    {
        mbRightToLeft = bR2L; 
        meAlign = bR2L ? TXTALIGN_RIGHT : TXTALIGN_LEFT;
		FormatFullDoc();
		UpdateViews();
    }
}

void TextEngine::ImpInitWritingDirections( sal_uLong nPara )
{
	TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara );
	TEWritingDirectionInfos& rInfos = pParaPortion->GetWritingDirectionInfos();
	rInfos.Remove( 0, rInfos.Count() );

	if ( pParaPortion->GetNode()->GetText().Len() )
	{
        const UBiDiLevel nBidiLevel = IsRightToLeft() ? 1 /*RTL*/ : 0 /*LTR*/;
        String aText( pParaPortion->GetNode()->GetText() );

        //
        // Bidi functions from icu 2.0
        //
        UErrorCode nError = U_ZERO_ERROR;
        UBiDi* pBidi = ubidi_openSized( aText.Len(), 0, &nError );
        nError = U_ZERO_ERROR;

        ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(aText.GetBuffer()), aText.Len(), nBidiLevel, NULL, &nError );	// UChar != sal_Unicode in MinGW
        nError = U_ZERO_ERROR;

        long nCount = ubidi_countRuns( pBidi, &nError );

        int32_t nStart = 0;
        int32_t nEnd;
        UBiDiLevel nCurrDir;

        for ( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx )
        {
            ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
            rInfos.Insert( TEWritingDirectionInfo( nCurrDir, (sal_uInt16)nStart, (sal_uInt16)nEnd ), rInfos.Count() );
            nStart = nEnd;
        }

        ubidi_close( pBidi );
	}

    // No infos mean no CTL and default dir is L2R...
    if ( !rInfos.Count() )
        rInfos.Insert( TEWritingDirectionInfo( 0, 0, (sal_uInt16)pParaPortion->GetNode()->GetText().Len() ), rInfos.Count() );

}

sal_uInt8 TextEngine::ImpGetRightToLeft( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16* pStart, sal_uInt16* pEnd )
{
    sal_uInt8 nRightToLeft = 0;

    TextNode* pNode = mpDoc->GetNodes().GetObject( nPara );
    if ( pNode && pNode->GetText().Len() )
    {
		TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara );
		if ( !pParaPortion->GetWritingDirectionInfos().Count() )
			ImpInitWritingDirections( nPara );

		TEWritingDirectionInfos& rDirInfos = pParaPortion->GetWritingDirectionInfos();
		for ( sal_uInt16 n = 0; n < rDirInfos.Count(); n++ ) 
		{
			if ( ( rDirInfos[n].nStartPos <= nPos ) && ( rDirInfos[n].nEndPos >= nPos ) )
	   		{
				nRightToLeft = rDirInfos[n].nType;
                if ( pStart )
                    *pStart = rDirInfos[n].nStartPos;
                if ( pEnd )
                    *pEnd = rDirInfos[n].nEndPos;
				break;
			}
		}
    }
    return nRightToLeft;
}

long TextEngine::ImpGetPortionXOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nTextPortion )
{
	long nX = pLine->GetStartX();

	TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara );

    for ( sal_uInt16 i = pLine->GetStartPortion(); i < nTextPortion; i++ )
	{
		TETextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( i );
		nX += pPortion->GetWidth();
    }

    TETextPortion* pDestPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
    if ( pDestPortion->GetKind() != PORTIONKIND_TAB )
    {
        if ( !IsRightToLeft() && pDestPortion->GetRightToLeft() )
        {
            // Portions behind must be added, visual before this portion
            sal_uInt16 nTmpPortion = nTextPortion+1;
            while ( nTmpPortion <= pLine->GetEndPortion() )
            {
		        TETextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
                if ( pNextTextPortion->GetRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
                    nX += pNextTextPortion->GetWidth();
                else
                    break;
                nTmpPortion++;
            }
            // Portions before must be removed, visual behind this portion
            nTmpPortion = nTextPortion;
            while ( nTmpPortion > pLine->GetStartPortion() )
            {
                --nTmpPortion;
		        TETextPortion* pPrevTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
                if ( pPrevTextPortion->GetRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
                    nX -= pPrevTextPortion->GetWidth();
                else
                    break;
            }
        }
        else if ( IsRightToLeft() && !pDestPortion->IsRightToLeft() )
        {
            // Portions behind must be removed, visual behind this portion
            sal_uInt16 nTmpPortion = nTextPortion+1;
            while ( nTmpPortion <= pLine->GetEndPortion() )
            {
		        TETextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
                if ( !pNextTextPortion->IsRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
                    nX += pNextTextPortion->GetWidth();
                else
                    break;
                nTmpPortion++;
            }
            // Portions before must be added, visual before this portion
            nTmpPortion = nTextPortion;
            while ( nTmpPortion > pLine->GetStartPortion() )
            {
                --nTmpPortion;
		        TETextPortion* pPrevTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
                if ( !pPrevTextPortion->IsRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
                    nX -= pPrevTextPortion->GetWidth();
                else
                    break;
            }
        }
    }
/*
    if ( IsRightToLeft() )
    {
        // Switch X postions...
        DBG_ASSERT( GetMaxTextWidth(), "GetPortionXOffset - max text width?!" );
        DBG_ASSERT( nX <= (long)GetMaxTextWidth(), "GetPortionXOffset - position out of paper size!" );
        nX = GetMaxTextWidth() - nX;
        nX -= pDestPortion->GetWidth();
    }
*/

    return nX;
}

void TextEngine::ImpInitLayoutMode( OutputDevice* pOutDev, sal_Bool bDrawingR2LPortion )
{
    sal_uLong nLayoutMode = pOutDev->GetLayoutMode();
    
    nLayoutMode &= ~(TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_COMPLEX_DISABLED | TEXT_LAYOUT_BIDI_STRONG );
    if ( bDrawingR2LPortion )
        nLayoutMode |= TEXT_LAYOUT_BIDI_RTL;
    
    pOutDev->SetLayoutMode( nLayoutMode );
}

TxtAlign TextEngine::ImpGetAlign() const
{
    TxtAlign eAlign = meAlign;
    if ( IsRightToLeft() )
    {
        if ( eAlign == TXTALIGN_LEFT )
            eAlign = TXTALIGN_RIGHT;
        else if ( eAlign == TXTALIGN_RIGHT )
            eAlign = TXTALIGN_LEFT;
    }
    return eAlign;
}

long TextEngine::ImpGetOutputOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_uInt16 nIndex2 )
{
    TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara );

    sal_uInt16 nPortionStart;
    sal_uInt16 nPortion = pPortion->GetTextPortions().FindPortion( nIndex, nPortionStart, sal_True );

    TETextPortion* pTextPortion = pPortion->GetTextPortions().GetObject( nPortion );

    long nX;

    if ( ( nIndex == nPortionStart ) && ( nIndex == nIndex2 )  )
    {
        // Output of full portion, so we need portion x offset.
        // Use ImpGetPortionXOffset, because GetXPos may deliver left or right position from portioon, depending on R2L, L2R
        nX = ImpGetPortionXOffset( nPara, pLine, nPortion );
        if ( IsRightToLeft() )
        {
	        nX = -nX -pTextPortion->GetWidth();
        }
    }
    else
    {
        nX = ImpGetXPos( nPara, pLine, nIndex, nIndex == nPortionStart );
        if ( nIndex2 != nIndex )
        {
            long nX2 = ImpGetXPos( nPara, pLine, nIndex2, sal_False );
            if ( ( !IsRightToLeft() && ( nX2 < nX ) ) ||
                 ( IsRightToLeft() && ( nX2 > nX ) ) )
            {
                nX = nX2;
            }
        }
        if ( IsRightToLeft() )
        {
	        nX = -nX;
        }
    }

    return nX;
}
