/**************************************************************
 * 
 * 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_sw.hxx"
#include <hintids.hxx>
#include <hints.hxx>

#include <editeng/fontitem.hxx>
#include <editeng/brkitem.hxx>
#include <editeng/escpitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/tstpitem.hxx>
#include <svl/urihelper.hxx>
#ifndef _SVSTDARR_HXX
#define _SVSTDARR_ULONGS
#include <svl/svstdarr.hxx>
#endif
#include <svl/ctloptions.hxx>
#include <swmodule.hxx>
#include <txtfld.hxx>
#include <txtinet.hxx>
#include <fmtinfmt.hxx>
#include <fmtpdsc.hxx>
#include <txtatr.hxx>
#include <fmtrfmrk.hxx>
#include <txttxmrk.hxx>
#include <fchrfmt.hxx>
#include <txtftn.hxx>
#include <fmtflcnt.hxx>
#include <fmtfld.hxx>
#include <frmatr.hxx>
#include <charatr.hxx>
#include <ftnidx.hxx>
#include <ftninfo.hxx>
#include <fmtftn.hxx>
#include <fmtmeta.hxx>
#include <charfmt.hxx>
#include <ndtxt.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <docary.hxx>
#include <pam.hxx>					// fuer SwPosition
#include <fldbas.hxx>
#include <errhdl.hxx>
#include <paratr.hxx>
#include <txtfrm.hxx>
#include <ftnfrm.hxx>
#include <ftnboss.hxx>
#include <rootfrm.hxx>
#include <pagedesc.hxx>				// fuer SwPageDesc
#include <expfld.hxx>				// fuer SwTblField
#include <section.hxx>				// fuer SwSection
#include <mvsave.hxx>
#include <swcache.hxx>
#include <SwGrammarMarkUp.hxx>
#include <dcontact.hxx>
#include <redline.hxx>
#include <doctxm.hxx>
#include <IMark.hxx>
#include <scriptinfo.hxx>
#include <istyleaccess.hxx>
#include <SwStyleNameMapper.hxx>
#include <numrule.hxx>
#include <svl/intitem.hxx>
#include <swtable.hxx>
#include <docsh.hxx>
#include <SwNodeNum.hxx>
#include <svl/intitem.hxx>
#include <list.hxx>
#include <switerator.hxx>
#include <attrhint.hxx>

//UUUU
#include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
#include <svl/itemiter.hxx>

using namespace ::com::sun::star;


SV_DECL_PTRARR( TmpHints, SwTxtAttr*, 0, 4 )
SV_DECL_PTRARR(SwpHts,SwTxtAttr*,1,1)

// Leider ist das SwpHints nicht ganz wasserdicht:
// Jeder darf an den Hints rumfummeln, ohne die Sortierreihenfolge
// und Verkettung sicherstellen zu muessen.
#ifdef DBG_UTIL
#define CHECK_SWPHINTS(pNd)  { if( pNd->GetpSwpHints() && \
                                   !pNd->GetDoc()->IsInReading() ) \
								  pNd->GetpSwpHints()->Check(); }
#else
#define CHECK_SWPHINTS(pNd)
#endif

SwTxtNode *SwNodes::MakeTxtNode( const SwNodeIndex & rWhere,
								 SwTxtFmtColl *pColl,
								 SwAttrSet* pAutoAttr )
{
	ASSERT( pColl, "Collectionpointer ist 0." );

	SwTxtNode *pNode = new SwTxtNode( rWhere, pColl, pAutoAttr );

	SwNodeIndex aIdx( *pNode );

    // --> OD 2005-11-03 #125329#
    // call method <UpdateOutlineNode(..)> only for the document nodes array
    if ( IsDocNodes() )
        UpdateOutlineNode(*pNode);

	//Wenn es noch kein Layout gibt oder in einer versteckten Section
	// stehen, brauchen wir uns um das MakeFrms nicht bemuehen.
	const SwSectionNode* pSectNd;
	if( !GetDoc()->GetCurrentViewShell() ||	//swmod 071108//swmod 071225
		( 0 != (pSectNd = pNode->FindSectionNode()) &&
			pSectNd->GetSection().IsHiddenFlag() ))
		return pNode;

	SwNodeIndex aTmp( rWhere );
	do {
		// max. 2 Durchlaeufe:
		// 1. den Nachfolger nehmen
		// 2. den Vorgaenger

        SwNode * pNd = & aTmp.GetNode();
        switch (pNd->GetNodeType())
		{
		case ND_TABLENODE:
			((SwTableNode*)pNd)->MakeFrms( aIdx );
			return pNode;

		case ND_SECTIONNODE:
			if( ((SwSectionNode*)pNd)->GetSection().IsHidden() ||
				((SwSectionNode*)pNd)->IsCntntHidden() )
			{
				SwNodeIndex aTmpIdx( *pNode );
				pNd = FindPrvNxtFrmNode( aTmpIdx, pNode );
				if( !pNd )
					return pNode;
				aTmp = *pNd;
				break;
			}
			((SwSectionNode*)pNd)->MakeFrms( aIdx );
			return pNode;

		case ND_TEXTNODE:
		case ND_GRFNODE:
		case ND_OLENODE:
			((SwCntntNode*)pNd)->MakeFrms( *pNode );
			return pNode;

		case ND_ENDNODE:
            if( pNd->StartOfSectionNode()->IsSectionNode() &&
				aTmp.GetIndex() < rWhere.GetIndex() )
			{
                if( pNd->StartOfSectionNode()->GetSectionNode()->GetSection().IsHiddenFlag())
				{
					if( !GoPrevSection( &aTmp, sal_True, sal_False ) ||
						aTmp.GetNode().FindTableNode() !=
							pNode->FindTableNode() )
						return pNode;		// schade, das wars
				}
				else
                    aTmp = *pNd->StartOfSectionNode();
				break;
			}
            else if( pNd->StartOfSectionNode()->IsTableNode() &&
					aTmp.GetIndex() < rWhere.GetIndex() )
			{
				// wir stehen hinter einem TabellenNode
                aTmp = *pNd->StartOfSectionNode();
				break;
			}
			// kein break !!!
		default:
			if( rWhere == aTmp )
				aTmp -= 2;
			else
				return pNode;
			break;
		}
	} while( sal_True );
}

// --------------------
// SwTxtNode
// --------------------

SwTxtNode::SwTxtNode( const SwNodeIndex &rWhere, SwTxtFmtColl *pTxtColl, const SfxItemSet* pAutoAttr )
:   SwCntntNode( rWhere, ND_TEXTNODE, pTxtColl ),
    m_pSwpHints( 0 ),
    mpNodeNum( 0 ),
    m_Text(),
    m_pParaIdleData_Impl(0),
    m_bContainsHiddenChars(false),
    m_bHiddenCharsHidePara(false),
    m_bRecalcHiddenCharFlags(false),
    m_bLastOutlineState( false ),
    m_bNotifiable( false ),
    mbEmptyListStyleSetDueToSetOutlineLevelAttr( false ),
    mbInSetOrResetAttr( false ),
    mpList( 0 ),
    m_pNumStringCache(),
    m_wXParagraph(),
    maFillAttributes()
{
    InitSwParaStatistics( true );

	// soll eine Harte-Attributierung gesetzt werden?
    if( pAutoAttr )
        SetAttr( *pAutoAttr );

    // --> OD 2008-03-13 #refactorlists# - no longed needed
//    SyncNumberAndNumRule();
    if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
    {
        // --> OD 2009-08-27 #i101516#
        // apply paragraph style's assigned outline style list level as
        // list level of the paragraph, if it has none set already.
        if ( !HasAttrListLevel() &&
             pTxtColl && pTxtColl->IsAssignedToListLevelOfOutlineStyle() )
        {
            SetAttrListLevel( pTxtColl->GetAssignedOutlineStyleLevel() );
        }
        // <--
        AddToList();
    }
    // <--
    GetNodes().UpdateOutlineNode(*this);

    m_bNotifiable = true;

    m_bContainsHiddenChars = m_bHiddenCharsHidePara = false;
    m_bRecalcHiddenCharFlags = true;
}

SwTxtNode::~SwTxtNode()
{
    // delete loescht nur die Pointer, nicht die Arrayelemente!
    if ( m_pSwpHints )
    {
        // damit Attribute die ihren Inhalt entfernen nicht doppelt
        // geloescht werden.
        SwpHints* pTmpHints = m_pSwpHints;
        m_pSwpHints = 0;

        for( sal_uInt16 j = pTmpHints->Count(); j; )
        {
            // erst muss das Attribut aus dem Array entfernt werden,
            // denn sonst wuerde es sich selbst loeschen (Felder) !!!!
            DestroyAttr( pTmpHints->GetTextHint( --j ) );
        }

        delete pTmpHints;
    }

    RemoveFromList();

    InitSwParaStatistics( false );
}

SwCntntFrm *SwTxtNode::MakeFrm( SwFrm* pSib )
{
    SwCntntFrm *pFrm = new SwTxtFrm( this, pSib );
    return pFrm;
}

xub_StrLen SwTxtNode::Len() const
{
    return m_Text.Len();
}

/*---------------------------------------------------------------------------
 * lcl_ChangeFtnRef
 * 	After a split node, it's necessary to actualize the ref-pointer of the
 *  ftnfrms.
 * --------------------------------------------------------------------------*/

void lcl_ChangeFtnRef( SwTxtNode &rNode )
{
	SwpHints *pSwpHints = rNode.GetpSwpHints();
	if( pSwpHints && rNode.GetDoc()->GetCurrentViewShell() )	//swmod 071108//swmod 071225
	{
		SwTxtAttr* pHt;
		SwCntntFrm* pFrm = NULL;
        // OD 07.11.2002 #104840# - local variable to remember first footnote
        // of node <rNode> in order to invalidate position of its first content.
        // Thus, in its <MakeAll()> it will checked its position relative to its reference.
        SwFtnFrm* pFirstFtnOfNode = 0;
		for( sal_uInt16 j = pSwpHints->Count(); j; )
        {
            pHt = pSwpHints->GetTextHint(--j);
            if (RES_TXTATR_FTN == pHt->Which())
            {
				if( !pFrm )
				{
					pFrm = SwIterator<SwCntntFrm,SwTxtNode>::FirstElement( rNode );
					if( !pFrm )
						return;
				}
				SwTxtFtn *pAttr = (SwTxtFtn*)pHt;
				ASSERT( pAttr->GetStartNode(), "FtnAtr ohne StartNode." );
				SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
				SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
				if ( !pNd )
					pNd = pFrm->GetAttrSet()->GetDoc()->
			  			  GetNodes().GoNextSection( &aIdx, sal_True, sal_False );
				if ( !pNd )
					continue;

            	SwIterator<SwCntntFrm,SwCntntNode> aIter( *pNd );
				SwCntntFrm* pCntnt = aIter.First();
				if( pCntnt )
				{
					ASSERT( pCntnt->getRootFrm() == pFrm->getRootFrm(),
							"lcl_ChangeFtnRef: Layout double?" );
					SwFtnFrm *pFtn = pCntnt->FindFtnFrm();
					if( pFtn && pFtn->GetAttr() == pAttr )
					{
						while( pFtn->GetMaster() )
							pFtn = pFtn->GetMaster();
                        // OD 07.11.2002 #104840# - remember footnote frame
                        pFirstFtnOfNode = pFtn;
                        while ( pFtn )
						{
							pFtn->SetRef( pFrm );
							pFtn = pFtn->GetFollow();
							((SwTxtFrm*)pFrm)->SetFtn( sal_True );
						}
					}
#ifdef DBG_UTIL
					while( 0 != (pCntnt = aIter.Next()) )
					{
						SwFtnFrm *pDbgFtn = pCntnt->FindFtnFrm();
						ASSERT( !pDbgFtn || pDbgFtn->GetRef() == pFrm,
								"lcl_ChangeFtnRef: Who's that guy?" );
					}
#endif
				}
			}
        } // end of for-loop on <SwpHints>
        // OD 08.11.2002 #104840# - invalidate
        if ( pFirstFtnOfNode )
        {
            SwCntntFrm* pCntnt = pFirstFtnOfNode->ContainsCntnt();
            if ( pCntnt )
            {
                pCntnt->_InvalidatePos();
            }
        }
	}
}

SwCntntNode *SwTxtNode::SplitCntntNode( const SwPosition &rPos )
{
	// lege den Node "vor" mir an
    const xub_StrLen nSplitPos = rPos.nContent.GetIndex();
    const xub_StrLen nTxtLen = m_Text.Len();
    SwTxtNode* const pNode =
        _MakeNewTxtNode( rPos.nNode, sal_False, nSplitPos==nTxtLen );

    // the first paragraph gets the XmlId,
    // _except_ if it is empty and the second is not empty
    if (nSplitPos != 0) {
        pNode->RegisterAsCopyOf(*this, true);
        if (nSplitPos == nTxtLen)
        {
            this->RemoveMetadataReference();
            // NB: SwUndoSplitNode will call pNode->JoinNext,
            // which is sufficient even in this case!
        }
    }

    // --> OD 2008-03-27 #refactorlists#
//    // --> OD 2007-07-09 #i77372#
//    // reset numbering attribute at current node, only if it is numbered.
//    if ( GetNumRule() != NULL )
//    {
//        SetRestart(false);
//        SetStart(1);
//        SetCounted(true);
//    }
    ResetAttr( RES_PARATR_LIST_ISRESTART );
    ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
    ResetAttr( RES_PARATR_LIST_ISCOUNTED );
    if ( GetNumRule() == 0 )
    {
        ResetAttr( RES_PARATR_LIST_ID );
        ResetAttr( RES_PARATR_LIST_LEVEL );
    }
    // <--

    if ( GetDepends() && m_Text.Len() && (nTxtLen / 2) < nSplitPos )
    {
// JP 25.04.95: Optimierung fuer SplitNode:
//				Wird am Ende vom Node gesplittet, dann verschiebe die
//				Frames vom akt. auf den neuen und erzeuge fuer den akt.
//				neue. Dadurch entfaellt das neu aufbauen vom Layout.

		LockModify();	// Benachrichtigungen abschalten

		// werden FlyFrames mit verschoben, so muessen diese nicht ihre
		// Frames zerstoeren. Im SwTxtFly::SetAnchor wird es abgefragt!
        if ( HasHints() )
        {
            pNode->GetOrCreateSwpHints().SetInSplitNode(true);
        }

		//Ersten Teil des Inhalts in den neuen Node uebertragen und
		//im alten Node loeschen.
		SwIndex aIdx( this );
        CutText( pNode, aIdx, nSplitPos );

		if( GetWrong() )
        {
            pNode->SetWrong( GetWrong()->SplitList( nSplitPos ) );
        }
        SetWrongDirty( true );

        if( GetGrammarCheck() )
        {
            pNode->SetGrammarCheck( GetGrammarCheck()->SplitGrammarList( nSplitPos ) );
        }
        SetGrammarCheckDirty( true );

        SetWordCountDirty( true );

        // SMARTTAGS
        if( GetSmartTags() )
        {
            pNode->SetSmartTags( GetSmartTags()->SplitList( nSplitPos ) );
        }
        SetSmartTagDirty( true );

        if ( pNode->HasHints() )
        {
            if ( pNode->m_pSwpHints->CanBeDeleted() )
            {
                delete pNode->m_pSwpHints;
                pNode->m_pSwpHints = 0;
            }
            else
            {
                pNode->m_pSwpHints->SetInSplitNode(false);
            }

			// alle zeichengebundenen Rahmen, die im neuen Absatz laden
			// muessen aus den alten Frame entfernt werden:
			// JP 01.10.96: alle leeren und nicht zu expandierenden
			//				Attribute loeschen
            if ( HasHints() )
			{
                for ( sal_uInt16 j = m_pSwpHints->Count(); j; )
                {
                    SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
                    if ( RES_TXTATR_FLYCNT == pHt ->Which() )
                    {
                        pHt->GetFlyCnt().GetFrmFmt()->DelFrms();
                    }
                    else if ( pHt->DontExpand() )
                    {
                        const xub_StrLen* const pEnd = pHt->GetEnd();
                        if (pEnd && *pHt->GetStart() == *pEnd )
                        {
                            // delete it!
                            m_pSwpHints->DeleteAtPos( j );
                            DestroyAttr( pHt );
                        }
                    }
                }
			}

		}

		SwIterator<SwCntntFrm,SwTxtNode> aIter( *this );
        for( SwCntntFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
		{
            pFrm->RegisterToNode( *pNode );
	        if( pFrm->IsTxtFrm() && !pFrm->IsFollow() && ((SwTxtFrm*)pFrm)->GetOfst() )
				((SwTxtFrm*)pFrm)->SetOfst( 0 );
        }

		if ( IsInCache() )
		{
			SwFrm::GetCache().Delete( this );
			SetInCache( sal_False );
		}

		UnlockModify();	// Benachrichtigungen wieder freischalten

		// If there is an accessible layout we must call modify even
		// with length zero, because we have to notify about the changed
		// text node.
		const SwRootFrm *pRootFrm;
        if ( (nTxtLen != nSplitPos) ||
			( (pRootFrm = pNode->GetDoc()->GetCurrentLayout()) != 0 &&
              pRootFrm->IsAnyShellAccessible() ) )	//swmod 080218
		{
			// dann sage den Frames noch, das am Ende etwas "geloescht" wurde
			if( 1 == nTxtLen - nSplitPos )
			{
				SwDelChr aHint( nSplitPos );
				pNode->NotifyClients( 0, &aHint );
			}
			else
			{
				SwDelTxt aHint( nSplitPos, nTxtLen - nSplitPos );
				pNode->NotifyClients( 0, &aHint );
			}
		}
        if ( HasHints() )
        {
			MoveTxtAttr_To_AttrSet();
        }
		pNode->MakeFrms( *this );		// neue Frames anlegen.
		lcl_ChangeFtnRef( *this );
	}
	else
	{
        SwWrongList *pList = GetWrong();
        SetWrong( 0, false );
        SetWrongDirty( true );

        SwGrammarMarkUp *pList3 = GetGrammarCheck();
        SetGrammarCheck( 0, false );
        SetGrammarCheckDirty( true );

        SetWordCountDirty( true );

        // SMARTTAGS
        SwWrongList *pList2 = GetSmartTags();
        SetSmartTags( 0, false );
        SetSmartTagDirty( true );

		SwIndex aIdx( this );
        CutText( pNode, aIdx, nSplitPos );

		// JP 01.10.96: alle leeren und nicht zu expandierenden
		//				Attribute loeschen
        if ( HasHints() )
		{
            for ( sal_uInt16 j = m_pSwpHints->Count(); j; )
            {
                SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
                const xub_StrLen* const pEnd = pHt->GetEnd();
                if ( pHt->DontExpand() && pEnd && (*pHt->GetStart() == *pEnd) )
                {
                    // delete it!
                    m_pSwpHints->DeleteAtPos( j );
					DestroyAttr( pHt );
				}
            }
			MoveTxtAttr_To_AttrSet();
		}

        if( pList )
        {
            pNode->SetWrong( pList->SplitList( nSplitPos ) );
            SetWrong( pList, false );
        }

        if( pList3 )
        {
            pNode->SetGrammarCheck( pList3->SplitGrammarList( nSplitPos ) );
            SetGrammarCheck( pList3, false );
        }

        // SMARTTAGS
        if( pList2 )
        {
            pNode->SetSmartTags( pList2->SplitList( nSplitPos ) );
            SetSmartTags( pList2, false );
        }

		if ( GetDepends() )
        {
			MakeFrms( *pNode );		// neue Frames anlegen.
        }
		lcl_ChangeFtnRef( *pNode );
	}

	{
		//Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im
		//Paste der Frames selbst erledigen, aber das fuehrt dann wiederum
		//zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden
		//muesten. #56977# #55001# #56135#
		const SfxPoolItem *pItem;
		if( GetDepends() && SFX_ITEM_SET == pNode->GetSwAttrSet().
			GetItemState( RES_PAGEDESC, sal_True, &pItem ) )
        {
			pNode->ModifyNotification( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
        }
	}
	return pNode;
}

void SwTxtNode::MoveTxtAttr_To_AttrSet()
{
    ASSERT( m_pSwpHints, "MoveTxtAttr_To_AttrSet without SwpHints?" );
    for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
    {
        SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);

		if( *pHt->GetStart() )
			break;

		const xub_StrLen* pHtEndIdx = pHt->GetEnd();

		if( !pHtEndIdx )
			continue;

        if ( *pHtEndIdx < m_Text.Len() || pHt->IsCharFmtAttr() )
			break;

		if( !pHt->IsDontMoveAttr() &&
            SetAttr( pHt->GetAttr() ) )
		{
            m_pSwpHints->DeleteAtPos(i);
			DestroyAttr( pHt );
			--i;
		}
	}

}

SwCntntNode *SwTxtNode::JoinNext()
{
	SwNodes& rNds = GetNodes();
	SwNodeIndex aIdx( *this );
	if( SwCntntNode::CanJoinNext( &aIdx ) )
	{
		SwDoc* pDoc = rNds.GetDoc();
		SvULongs aBkmkArr( 15, 15 );
		_SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
		SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
        xub_StrLen nOldLen = m_Text.Len();

        // METADATA: merge
        this->JoinMetadatable(*pTxtNode, !this->Len(), !pTxtNode->Len());

        SwWrongList *pList = GetWrong();
        if( pList )
        {
            pList->JoinList( pTxtNode->GetWrong(), nOldLen );
            SetWrongDirty( true );
            SetWrong( 0, false );
        }
        else
        {
            pList = pTxtNode->GetWrong();
            if( pList )
            {
                pList->Move( 0, nOldLen );
                SetWrongDirty( true );
                pTxtNode->SetWrong( 0, false );
            }
        }

        SwGrammarMarkUp *pList3 = GetGrammarCheck();
        if( pList3 )
        {
            pList3->JoinGrammarList( pTxtNode->GetGrammarCheck(), nOldLen );
            SetGrammarCheckDirty( true );
            SetGrammarCheck( 0, false );
        }
        else
        {
            pList3 = pTxtNode->GetGrammarCheck();
            if( pList3 )
            {
                pList3->MoveGrammar( 0, nOldLen );
                SetGrammarCheckDirty( true );
                pTxtNode->SetGrammarCheck( 0, false );
            }
        }

        // SMARTTAGS
        SwWrongList *pList2 = GetSmartTags();
        if( pList2 )
        {
            pList2->JoinList( pTxtNode->GetSmartTags(), nOldLen );
            SetSmartTagDirty( true );
            SetSmartTags( 0, false );
        }
        else
        {
            pList2 = pTxtNode->GetSmartTags();
            if( pList2 )
            {
                pList2->Move( 0, nOldLen );
                SetSmartTagDirty( true );
                pTxtNode->SetSmartTags( 0, false );
            }
        }

        { // wg. SwIndex
            pTxtNode->CutText( this, SwIndex(pTxtNode), pTxtNode->Len() );
        }
		// verschiebe noch alle Bookmarks/TOXMarks
		if( aBkmkArr.Count() )
			_RestoreCntntIdx( pDoc, aBkmkArr, GetIndex(), nOldLen );

		if( pTxtNode->HasAnyIndex() )
		{
			// alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
			pDoc->CorrAbs( aIdx, SwPosition( *this ), nOldLen, sal_True );
		}
		rNds.Delete(aIdx);
        SetWrong( pList, false );
        SetGrammarCheck( pList3, false );
        SetSmartTags( pList2, false ); // SMARTTAGS
		InvalidateNumRule();
	}
	else {
		ASSERT( sal_False, "kein TxtNode." );
    }

	return this;
}

SwCntntNode *SwTxtNode::JoinPrev()
{
	SwNodes& rNds = GetNodes();
	SwNodeIndex aIdx( *this );
	if( SwCntntNode::CanJoinPrev( &aIdx ) )
	{
		SwDoc* pDoc = rNds.GetDoc();
		SvULongs aBkmkArr( 15, 15 );
		_SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
		SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
		xub_StrLen nLen = pTxtNode->Len();

        SwWrongList *pList = pTxtNode->GetWrong();
        if( pList )
        {
            pList->JoinList( GetWrong(), Len() );
            SetWrongDirty( true );
            pTxtNode->SetWrong( 0, false );
            SetWrong( NULL );
        }
        else
        {
            pList = GetWrong();
            if( pList )
            {
                pList->Move( 0, nLen );
                SetWrongDirty( true );
                SetWrong( 0, false );
            }
        }

        SwGrammarMarkUp *pList3 = pTxtNode->GetGrammarCheck();
        if( pList3 )
        {
            pList3->JoinGrammarList( GetGrammarCheck(), Len() );
            SetGrammarCheckDirty( true );
            pTxtNode->SetGrammarCheck( 0, false );
            SetGrammarCheck( NULL );
        }
        else
        {
            pList3 = GetGrammarCheck();
            if( pList3 )
            {
                pList3->MoveGrammar( 0, nLen );
                SetGrammarCheckDirty( true );
                SetGrammarCheck( 0, false );
            }
        }

        // SMARTTAGS
        SwWrongList *pList2 = pTxtNode->GetSmartTags();
        if( pList2 )
        {
            pList2->JoinList( GetSmartTags(), Len() );
            SetSmartTagDirty( true );
            pTxtNode->SetSmartTags( 0, false );
            SetSmartTags( NULL );
        }
        else
        {
            pList2 = GetSmartTags();
            if( pList2 )
            {
                pList2->Move( 0, nLen );
                SetSmartTagDirty( true );
                SetSmartTags( 0, false );
            }
        }

		{ // wg. SwIndex
            pTxtNode->CutText( this, SwIndex(this), SwIndex(pTxtNode), nLen );
        }
		// verschiebe noch alle Bookmarks/TOXMarks
		if( aBkmkArr.Count() )
			_RestoreCntntIdx( pDoc, aBkmkArr, GetIndex() );

		if( pTxtNode->HasAnyIndex() )
		{
			// alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
			pDoc->CorrAbs( aIdx, SwPosition( *this ), nLen, sal_True );
		}
		rNds.Delete(aIdx);
        SetWrong( pList, false );
        SetGrammarCheck( pList3, false );
        SetSmartTags( pList2, false );
		InvalidateNumRule();
	}
	else {
		ASSERT( sal_False, "kein TxtNode." );
    }

	return this;
}

// erzeugt einen AttrSet mit Bereichen fuer Frame-/Para/Char-Attributen
void SwTxtNode::NewAttrSet( SwAttrPool& rPool )
{
    ASSERT( !mpAttrSet.get(), "AttrSet ist doch gesetzt" );
    SwAttrSet aNewAttrSet( rPool, aTxtNodeSetRange );

    // put names of parent style and conditional style:
    const SwFmtColl* pAnyFmtColl = &GetAnyFmtColl();
    const SwFmtColl* pFmtColl = GetFmtColl();
    String sVal;
	SwStyleNameMapper::FillProgName( pAnyFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
    SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal );
    if ( pFmtColl != pAnyFmtColl )
    	SwStyleNameMapper::FillProgName( pFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
    SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal );
    aNewAttrSet.Put( aAnyFmtColl );
    aNewAttrSet.Put( aFmtColl );

    aNewAttrSet.SetParent( &pAnyFmtColl->GetAttrSet() );
    mpAttrSet = GetDoc()->GetIStyleAccess().getAutomaticStyle( aNewAttrSet, IStyleAccess::AUTO_STYLE_PARA );
}


// override SwIndexReg::Update => text hints do not need SwIndex for start/end!
void SwTxtNode::Update(
    SwIndex const & rPos,
    const xub_StrLen nChangeLen,
    const bool bNegative,
    const bool bDelete )
{
    SetAutoCompleteWordDirty( sal_True );

    ::std::auto_ptr<TmpHints> pCollector;
    const xub_StrLen nChangePos = rPos.GetIndex();

    if ( HasHints() )
    {
        if ( bNegative )
        {
            const xub_StrLen nChangeEnd = nChangePos + nChangeLen;
            for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
            {
                bool bTxtAttrChanged = false;
                bool bStartOfTxtAttrChanged = false;
                SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
                xub_StrLen * const pStart = pHint->GetStart();
                if ( *pStart > nChangePos )
                {
                    if ( *pStart > nChangeEnd )
                    {
                         *pStart = *pStart - nChangeLen;
                    }
                    else
                    {
                         *pStart = nChangePos;
                    }
                    bStartOfTxtAttrChanged = true;
                }

                xub_StrLen * const pEnd = pHint->GetEnd();
                if (pEnd)
                {
                    if ( *pEnd > nChangePos )
                    {
                        if( *pEnd > nChangeEnd )
                        {
                            *pEnd = *pEnd - nChangeLen;
                        }
                        else
                        {
                            *pEnd = nChangePos;
                        }
                        bTxtAttrChanged = !bStartOfTxtAttrChanged;
                    }
                }

                if ( bTxtAttrChanged
                     && pHint->Which() == RES_TXTATR_INPUTFIELD )
                {
                    SwTxtInputFld* pTxtInputFld = dynamic_cast<SwTxtInputFld*>(pHint);
                    if ( pTxtInputFld )
                    {
                        pTxtInputFld->UpdateFieldContent();
                    }
                }
            }

            m_pSwpHints->MergePortions( *this );
        }
        else
        {
            bool bNoExp = false;
            bool bResort = false;
            const sal_uInt16 coArrSz =
                static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) - static_cast<sal_uInt16>(RES_CHRATR_BEGIN);

            sal_Bool aDontExp[ coArrSz ];
            memset( &aDontExp, 0, coArrSz * sizeof(sal_Bool) );

            for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
            {
                bool bTxtAttrChanged = false;
                SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
                xub_StrLen * const pStart = pHint->GetStart();
                xub_StrLen * const pEnd = pHint->GetEnd();
                if ( *pStart >= nChangePos )
                {
                    *pStart = *pStart + nChangeLen;
                    if ( pEnd )
                    {
                        *pEnd = *pEnd + nChangeLen;
                    }
                }
                else if ( pEnd && (*pEnd >= nChangePos) )
                {
                    if ( (*pEnd > nChangePos) || IsIgnoreDontExpand() )
                    {
                        *pEnd = *pEnd + nChangeLen;
                        bTxtAttrChanged = true;
                    }
                    else // *pEnd == nChangePos
                    {
                        sal_uInt16 nWhPos;
                        const sal_uInt16 nWhich = pHint->Which();

                        ASSERT(!isCHRATR(nWhich), "Update: char attr hint?");
                        if (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich))
                        {
                            nWhPos = static_cast<sal_uInt16>(nWhich -
                                        RES_CHRATR_BEGIN);
                        }
                        else
                            continue;

                        if( aDontExp[ nWhPos ] )
                            continue;

                        if ( pHint->DontExpand() )
                        {
                            pHint->SetDontExpand( false );
                            bResort = true;
                            if ( pHint->IsCharFmtAttr() )
                            {
                                bNoExp = true;
                                aDontExp[ static_cast<sal_uInt16>(RES_TXTATR_CHARFMT) - static_cast<sal_uInt16>(RES_CHRATR_BEGIN) ]
                                    = sal_True;
                                aDontExp[ static_cast<sal_uInt16>(RES_TXTATR_INETFMT) - static_cast<sal_uInt16>(RES_CHRATR_BEGIN) ]
                                    = sal_True;
                            }
                            else
                                aDontExp[ nWhPos ] = sal_True;
                        }
                        else if( bNoExp )
                        {
                             if ( !pCollector.get() )
                             {
                                pCollector.reset( new TmpHints );
                             }
                             sal_uInt16 nCollCnt = pCollector->Count();
                             for( sal_uInt16 i = 0; i < nCollCnt; ++i )
                             {
                                 SwTxtAttr *pTmp = (*pCollector)[ i ];
                                 if( nWhich == pTmp->Which() )
                                 {
                                     pCollector->Remove( i );
                                     SwTxtAttr::Destroy( pTmp, GetDoc()->GetAttrPool() );
                                     break;
                                 }
                             }
                             SwTxtAttr * const pTmp =
                                 MakeTxtAttr( *GetDoc(), pHint->GetAttr(), nChangePos, nChangePos + nChangeLen);
                             pCollector->C40_INSERT( SwTxtAttr, pTmp, pCollector->Count() );
                        }
                        else
                        {
                            *pEnd = *pEnd + nChangeLen;
                            bTxtAttrChanged = true;
                        }
                    }
                }

                if ( bTxtAttrChanged
                     && pHint->Which() == RES_TXTATR_INPUTFIELD )
                {
                    SwTxtInputFld* pTxtInputFld = dynamic_cast<SwTxtInputFld*>(pHint);
                    if ( pTxtInputFld )
                    {
                        pTxtInputFld->UpdateFieldContent();
                    }
                }
            }
            if ( bResort )
            {
                m_pSwpHints->Resort();
            }
        }
    }

    bool bSortMarks = false;
    SwIndexReg aTmpIdxReg;
    if ( !bNegative && !bDelete )
    {
        const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
        for ( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
        {
            SwRedline *const pRedl = rTbl[ i ];
            if ( pRedl->HasMark() )
            {
                SwPosition* const pEnd = pRedl->End();
                if ( this == &pEnd->nNode.GetNode() &&
                     *pRedl->GetPoint() != *pRedl->GetMark() )
                {
                    SwIndex & rIdx = pEnd->nContent;
                    if (nChangePos == rIdx.GetIndex())
                    {
                        rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
                    }
                }
            }
            else if ( this == &pRedl->GetPoint()->nNode.GetNode() )
            {
                SwIndex & rIdx = pRedl->GetPoint()->nContent;
                if (nChangePos == rIdx.GetIndex())
                {
                    rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
                    // mst: FIXME: why does this adjust the unused position???
                    SwIndex * pIdx;
                    if ( &pRedl->GetBound( true ) == pRedl->GetPoint() )
                    {
                        pRedl->GetBound( false ) = pRedl->GetBound( true );
                        pIdx = &pRedl->GetBound( false ).nContent;
                    }
                    else
                    {
                        pRedl->GetBound( true ) = pRedl->GetBound( false );
                        pIdx = &pRedl->GetBound( true ).nContent;
                    }
                    pIdx->Assign( &aTmpIdxReg, pIdx->GetIndex() );
                }
            }
        }

        // Bookmarks must never grow to either side, when editing (directly) to the left or right (#i29942#)!
        // And a bookmark with same start and end must remain to the left of the inserted text (used in XML import).
        {
            bool bAtLeastOneBookmarkMoved = false;
            bool bAtLeastOneExpandedBookmarkAtInsertionPosition = false;
            const IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
            for ( IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin();
                ppMark != pMarkAccess->getAllMarksEnd();
                ppMark++ )
            {
                const ::sw::mark::IMark* const pMark = ppMark->get();
                const SwPosition* pEnd = &pMark->GetMarkEnd();
                SwIndex & rEndIdx = const_cast<SwIndex&>(pEnd->nContent);
                if( this == &pEnd->nNode.GetNode() &&
                    rPos.GetIndex() == rEndIdx.GetIndex() )
                {
                    rEndIdx.Assign( &aTmpIdxReg, rEndIdx.GetIndex() );
                    bAtLeastOneBookmarkMoved = true;
                }
                else if ( !bAtLeastOneExpandedBookmarkAtInsertionPosition )
                {
                    if ( pMark->IsExpanded() )
                    {
                        const SwPosition* pStart = &pMark->GetMarkStart();
                        if ( this == &pStart->nNode.GetNode()
                             && rPos.GetIndex() == pStart->nContent.GetIndex() )
                        {
                            bAtLeastOneExpandedBookmarkAtInsertionPosition = true;
                        }
                    }
                }
            }

            bSortMarks = bAtLeastOneBookmarkMoved && bAtLeastOneExpandedBookmarkAtInsertionPosition;
        }
    }

    // base class
    SwIndexReg::Update( rPos, nChangeLen, bNegative, bDelete );

    if ( pCollector.get() )
    {
        const sal_uInt16 nCount = pCollector->Count();
        for ( sal_uInt16 i = 0; i < nCount; ++i )
        {
            m_pSwpHints->TryInsertHint( (*pCollector)[ i ], *this );
        }
    }

    aTmpIdxReg.MoveTo( *this );
    if ( bSortMarks )
    {
        getIDocumentMarkAccess()->assureSortedMarkContainers();
    }
}

void SwTxtNode::_ChgTxtCollUpdateNum( const SwTxtFmtColl *pOldColl,
										const SwTxtFmtColl *pNewColl)
{
	SwDoc* pDoc = GetDoc();
	ASSERT( pDoc, "Kein Doc?" );
	// erfrage die OutlineLevel und update gegebenenfalls das Nodes-Array,
	// falls sich die Level geaendert haben !
	//const sal_uInt8 nOldLevel = pOldColl ? pOldColl->GetOutlineLevel():NO_NUMBERING;//#outline level,removed by zhaojianwei
	//const sal_uInt8 nNewLevel = pNewColl ? pNewColl->GetOutlineLevel():NO_NUMBERING;//<-end,zhaojianwei
	const int nOldLevel = pOldColl && pOldColl->IsAssignedToListLevelOfOutlineStyle() ?
	                 pOldColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
    const int nNewLevel = pNewColl && pNewColl->IsAssignedToListLevelOfOutlineStyle() ?
					 pNewColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;

//	if ( NO_NUMBERING != nNewLevel )	//#outline level,zhaojianwei
	if ( MAXLEVEL != nNewLevel )	//<-end,zhaojianwei
    {
        SetAttrListLevel(nNewLevel);
    }

	{
        if (pDoc)
            pDoc->GetNodes().UpdateOutlineNode(*this);
    }


	SwNodes& rNds = GetNodes();
	// Update beim Level 0 noch die Fussnoten !!
	if( ( !nNewLevel || !nOldLevel) && pDoc->GetFtnIdxs().Count() &&
		FTNNUM_CHAPTER == pDoc->GetFtnInfo().eNum &&
		rNds.IsDocNodes() )
	{
		SwNodeIndex aTmpIndex( rNds, GetIndex());

		pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
	}

//FEATURE::CONDCOLL
	if( /*pOldColl != pNewColl && pNewColl && */
		RES_CONDTXTFMTCOLL == pNewColl->Which() )
	{
		// Erfrage die akt. Condition des TextNodes:
		ChkCondColl();
	}
//FEATURE::CONDCOLL
}

// Wenn man sich genau am Ende einer Text- bzw. INetvorlage befindet,
// bekommt diese das DontExpand-Flag verpasst

sal_Bool SwTxtNode::DontExpandFmt( const SwIndex& rIdx, bool bFlag,
								sal_Bool bFmtToTxtAttributes )
{
	const xub_StrLen nIdx = rIdx.GetIndex();
    if ( bFmtToTxtAttributes && nIdx == m_Text.Len() )
    {
        FmtToTxtAttr( this );
    }

	sal_Bool bRet = sal_False;
    if ( HasHints() )
    {
        const sal_uInt16 nEndCnt = m_pSwpHints->GetEndCount();
		sal_uInt16 nPos = nEndCnt;
		while( nPos )
        {
            SwTxtAttr *pTmp = m_pSwpHints->GetEnd( --nPos );
			xub_StrLen *pEnd = pTmp->GetEnd();
			if( !pEnd || *pEnd > nIdx )
				continue;
			if( nIdx != *pEnd )
				nPos = 0;
			else if( bFlag != pTmp->DontExpand() && !pTmp->IsLockExpandFlag()
					 && *pEnd > *pTmp->GetStart())
			{
				bRet = sal_True;
                m_pSwpHints->NoteInHistory( pTmp );
				pTmp->SetDontExpand( bFlag );
			}
		}
	}
	return bRet;
}

static bool lcl_GetTxtAttrDefault(xub_StrLen const nIndex,
    xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
{
    return ((nHintStart <= nIndex) && (nIndex <  nHintEnd));
}
static bool lcl_GetTxtAttrExpand(xub_StrLen const nIndex,
    xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
{
    return ((nHintStart <  nIndex) && (nIndex <= nHintEnd));
}
static bool lcl_GetTxtAttrParent(xub_StrLen const nIndex,
    xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
{
    return ((nHintStart <  nIndex) && (nIndex <  nHintEnd));
}

static void
lcl_GetTxtAttrs(
    ::std::vector<SwTxtAttr *> *const pVector,
    SwTxtAttr **const ppTxtAttr,
    SwpHints *const pSwpHints,
    xub_StrLen const nIndex,
    RES_TXTATR const nWhich,
    enum SwTxtNode::GetTxtAttrMode const eMode)
{
    sal_uInt16 const nSize = (pSwpHints) ? pSwpHints->Count() : 0;
    xub_StrLen nPreviousIndex(0); // index of last hint with nWhich
    bool (*pMatchFunc)(xub_StrLen const, xub_StrLen const, xub_StrLen const)=0;
    switch (eMode)
    {
        case SwTxtNode::DEFAULT:   pMatchFunc = &lcl_GetTxtAttrDefault; break;
        case SwTxtNode::EXPAND:    pMatchFunc = &lcl_GetTxtAttrExpand;  break;
        case SwTxtNode::PARENT:    pMatchFunc = &lcl_GetTxtAttrParent;  break;
        default: OSL_ASSERT(false);
    }

    for( sal_uInt16 i = 0; i < nSize; ++i )
    {
        SwTxtAttr *const pHint = pSwpHints->GetTextHint(i);
        xub_StrLen const nHintStart( *(pHint->GetStart()) );
        if (nIndex < nHintStart)
        {
            return; // hints are sorted by start, so we are done...
        }

        if (pHint->Which() != nWhich)
        {
            continue;
        }

        xub_StrLen const*const pEndIdx = pHint->GetEnd();
        ASSERT(pEndIdx || pHint->HasDummyChar(), "hint with no end and no dummy char?");
        // Wenn bExpand gesetzt ist, wird das Verhalten bei Eingabe
        // simuliert, d.h. der Start wuede verschoben, das Ende expandiert,
        bool const bContained( (pEndIdx)
            ? (*pMatchFunc)(nIndex, nHintStart, *pEndIdx)
            : (nHintStart == nIndex) );
        if (bContained)
        {
            if (pVector)
            {
                if (nPreviousIndex < nHintStart)
                {
                    pVector->clear(); // clear hints that are outside pHint
                    nPreviousIndex = nHintStart;
                }
                pVector->push_back(pHint);
            }
            else
            {
                *ppTxtAttr = pHint; // and possibly overwrite outer hint
            }
            if (!pEndIdx)
            {
                break;
            }
        }
    }
}

::std::vector<SwTxtAttr *>
SwTxtNode::GetTxtAttrsAt(xub_StrLen const nIndex, RES_TXTATR const nWhich,
                        enum GetTxtAttrMode const eMode) const
{
    ::std::vector<SwTxtAttr *> ret;
    lcl_GetTxtAttrs(& ret, 0, m_pSwpHints, nIndex, nWhich, eMode);
    return ret;
}

SwTxtAttr *
SwTxtNode::GetTxtAttrAt(xub_StrLen const nIndex, RES_TXTATR const nWhich,
                        enum GetTxtAttrMode const eMode) const
{
    ASSERT(    (nWhich == RES_TXTATR_META)
            || (nWhich == RES_TXTATR_METAFIELD)
            || (nWhich == RES_TXTATR_AUTOFMT)
            || (nWhich == RES_TXTATR_INETFMT)
            || (nWhich == RES_TXTATR_CJK_RUBY)
            || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER)
            || (nWhich == RES_TXTATR_INPUTFIELD ),
        "GetTxtAttrAt() will give wrong result for this hint!");

    SwTxtAttr * pRet(0);
    lcl_GetTxtAttrs(0, & pRet, m_pSwpHints, nIndex, nWhich, eMode);
    return pRet;
}

const SwTxtInputFld* SwTxtNode::GetOverlappingInputFld( const SwTxtAttr& rTxtAttr ) const
{
    const SwTxtInputFld* pTxtInputFld = NULL;

    pTxtInputFld = dynamic_cast<const SwTxtInputFld*>(GetTxtAttrAt( *(rTxtAttr.GetStart()), RES_TXTATR_INPUTFIELD, PARENT ));

    if ( pTxtInputFld == NULL && rTxtAttr.End() != NULL )
    {
        pTxtInputFld = dynamic_cast<const SwTxtInputFld*>(GetTxtAttrAt( *(rTxtAttr.End()), RES_TXTATR_INPUTFIELD, PARENT ));
    }

    return pTxtInputFld;
}

SwTxtFld* SwTxtNode::GetFldTxtAttrAt(
    const xub_StrLen nIndex,
    const bool bIncludeInputFldAtStart ) const
{
    SwTxtFld* pTxtFld = NULL;

    pTxtFld = dynamic_cast<SwTxtFld*>(GetTxtAttrForCharAt( nIndex, RES_TXTATR_FIELD ));
    if ( pTxtFld == NULL )
    {
        pTxtFld = dynamic_cast<SwTxtFld*>(GetTxtAttrForCharAt( nIndex, RES_TXTATR_ANNOTATION ));
    }
    if ( pTxtFld == NULL )
    {
        pTxtFld =
            dynamic_cast<SwTxtFld*>( GetTxtAttrAt(
                nIndex,
                RES_TXTATR_INPUTFIELD,
                bIncludeInputFldAtStart ? DEFAULT : PARENT ));
    }

    return pTxtFld;
}


/*************************************************************************
 *							CopyHint()
 *************************************************************************/

SwCharFmt* lcl_FindCharFmt( const SwCharFmts* pCharFmts, const XubString& rName )
{
	if( rName.Len() )
	{
		SwCharFmt* pFmt;
		sal_uInt16 nArrLen = pCharFmts->Count();
		for( sal_uInt16 i = 1; i < nArrLen; i++ )
		{
			pFmt = (*pCharFmts)[ i ];
			if( pFmt->GetName().CompareTo( rName ) == COMPARE_EQUAL )
				return pFmt;
		}
	}
	return NULL;
}

void lcl_CopyHint(
    const sal_uInt16 nWhich,
    const SwTxtAttr * const pHt,
    SwTxtAttr *const pNewHt,
    SwDoc *const pOtherDoc,
    SwTxtNode *const pDest )
{
    ASSERT( nWhich == pHt->Which(), "Falsche Hint-Id" );
    switch( nWhich )
    {
    // copy nodesarray section with footnote content
    case RES_TXTATR_FTN :
            ASSERT(pDest, "lcl_CopyHint: no destination text node?");
            static_cast<const SwTxtFtn*>(pHt)->CopyFtn( *static_cast<SwTxtFtn*>(pNewHt), *pDest);
            break;

    // Beim Kopieren von Feldern in andere Dokumente
    // muessen die Felder bei ihren neuen Feldtypen angemeldet werden.

    // TabellenFormel muessen relativ kopiert werden.
    case RES_TXTATR_FIELD :
        {
            if( pOtherDoc != NULL )
            {
                static_cast<const SwTxtFld*>(pHt)->CopyTxtFld( static_cast<SwTxtFld*>(pNewHt) );
            }

            // Tabellenformel ??
            const SwFmtFld& rFld = pHt->GetFmtFld();
            if( RES_TABLEFLD == rFld.GetField()->GetTyp()->Which()
                && static_cast<const SwTblField*>(rFld.GetField())->IsIntrnlName())
            {
                // wandel die interne in eine externe Formel um
                const SwTableNode* const pDstTblNd =
                    static_cast<const SwTxtFld*>(pHt)->GetTxtNode().FindTableNode();
                if( pDstTblNd )
                {
                    SwTblField* const pTblFld =
                        const_cast<SwTblField*>(static_cast<const SwTblField*>(
                            pNewHt->GetFmtFld().GetField()));
                    pTblFld->PtrToBoxNm( &pDstTblNd->GetTable() );
                }
            }
        }
        break;

    case RES_TXTATR_INPUTFIELD :
    case RES_TXTATR_ANNOTATION :
        if( pOtherDoc != NULL )
        {
            static_cast<const SwTxtFld*>(pHt)->CopyTxtFld( static_cast<SwTxtFld*>(pNewHt) );
        }
        break;

    case RES_TXTATR_TOXMARK :
        if( pOtherDoc && pDest && pDest->GetpSwpHints()
            && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
        {
            // Beim Kopieren von TOXMarks(Client) in andere Dokumente
            // muss der Verzeichnis (Modify) ausgetauscht werden
            static_cast<SwTxtTOXMark*>(pNewHt)->CopyTOXMark( pOtherDoc );
        }
        break;

    case RES_TXTATR_CHARFMT :
        // Wenn wir es mit einer Zeichenvorlage zu tun haben,
        // muessen wir natuerlich auch die Formate kopieren.
        if( pDest && pDest->GetpSwpHints()
            && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
        {
            SwCharFmt* pFmt =
                static_cast<SwCharFmt*>(pHt->GetCharFmt().GetCharFmt());

            if( pFmt && pOtherDoc )
            {
                pFmt = pOtherDoc->CopyCharFmt( *pFmt );
            }
            const_cast<SwFmtCharFmt&>( static_cast<const SwFmtCharFmt&>(
                pNewHt->GetCharFmt() ) ).SetCharFmt( pFmt );
        }
        break;
    case RES_TXTATR_INETFMT :
        {
            // Wenn wir es mit benutzerdefinierten INet-Zeichenvorlagen
            // zu tun haben, muessen wir natuerlich auch die Formate kopieren.
            if( pOtherDoc && pDest && pDest->GetpSwpHints()
                && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
            {
                const SwDoc* const pDoc = static_cast<const SwTxtINetFmt*>(pHt)
                    ->GetTxtNode().GetDoc();
                if ( pDoc )
                {
                    const SwCharFmts* pCharFmts = pDoc->GetCharFmts();
                    const SwFmtINetFmt& rFmt = pHt->GetINetFmt();
                    SwCharFmt* pFmt;
                    pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetINetFmt() );
                    if( pFmt )
                        pOtherDoc->CopyCharFmt( *pFmt );
                    pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetVisitedFmt() );
                    if( pFmt )
                        pOtherDoc->CopyCharFmt( *pFmt );
                }
            }
            //JP 24.04.98: Bug 49753 - ein TextNode muss am Attribut
            //				gesetzt sein, damit die Vorlagen erzeugt
            //				werden koenne
            SwTxtINetFmt* const pINetHt = static_cast<SwTxtINetFmt*>(pNewHt);
            if ( !pINetHt->GetpTxtNode() )
            {
                pINetHt->ChgTxtNode( pDest );
            }

            //JP 22.10.97: Bug 44875 - Verbindung zum Format herstellen
            pINetHt->GetCharFmt();
            break;
        }
    case RES_TXTATR_META:
    case RES_TXTATR_METAFIELD:
        OSL_ENSURE( pNewHt, "copying Meta should not fail!" );
        OSL_ENSURE( pDest
                    && (CH_TXTATR_INWORD == pDest->GetTxt().GetChar(*pNewHt->GetStart())),
            "missing CH_TXTATR?");
        break;
    }
}

/*************************************************************************
|*	SwTxtNode::CopyAttr()
|*	Beschreibung	kopiert Attribute an der Position nStart in pDest.
|*	BP 7.6.93:		Es werden mit Absicht nur die Attribute _mit_ EndIdx
|*					kopiert! CopyAttr wird vornehmlich dann gerufen,
|*					wenn Attribute fuer einen Node mit leerem String
|*					gesetzt werden sollen.
*************************************************************************/

void SwTxtNode::CopyAttr( SwTxtNode *pDest, const xub_StrLen nTxtStartIdx,
                          const xub_StrLen nOldPos )
{
    if ( HasHints() )    // keine Attribute, keine Kekse
    {
        SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
                pDest->GetDoc() : 0;

        for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ )
        {
            SwTxtAttr *const pHt = m_pSwpHints->GetTextHint(i);
            xub_StrLen const nAttrStartIdx = *pHt->GetStart();
            if ( nTxtStartIdx < nAttrStartIdx )
                break; // ueber das Textende, da nLen == 0

            const xub_StrLen *const pEndIdx = pHt->GetEnd();
            if ( pEndIdx && !pHt->HasDummyChar() )
            {
                if ( ( *pEndIdx > nTxtStartIdx
                       || ( *pEndIdx == nTxtStartIdx
                            && nAttrStartIdx == nTxtStartIdx ) ) )
                {
                    sal_uInt16 const nWhich = pHt->Which();
                    if ( RES_TXTATR_REFMARK != nWhich )
                    {
                        // attribute in the area => copy
                        SwTxtAttr *const pNewHt =
                            pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos, nsSetAttrMode::SETATTR_IS_COPY);
                        if ( pNewHt )
                        {
                            lcl_CopyHint( nWhich, pHt, pNewHt,
                                pOtherDoc, pDest );
                        }
                    }
                    else if( !pOtherDoc
                             ? GetDoc()->IsCopyIsMove()
                             : 0 == pOtherDoc->GetRefMark( pHt->GetRefMark().GetRefName() ) )
                    {
                        pDest->InsertItem(
                            pHt->GetAttr(), nOldPos, nOldPos, nsSetAttrMode::SETATTR_IS_COPY);
                    }
                }
            }
        }
    }

    if( this != pDest )
    {
        // Frames benachrichtigen, sonst verschwinden die Ftn-Nummern
        SwUpdateAttr aHint( 
            nOldPos, 
            nOldPos, 
            0);

        pDest->ModifyNotification( 0, &aHint );
    }
}

/*************************************************************************
|*	SwTxtNode::Copy()
|*	Beschreibung		kopiert Zeichen und Attibute in pDest,
|*						wird angehaengt
*************************************************************************/

// introduction of new optional parameter to control, if all attributes have to be copied.
void SwTxtNode::CopyText( SwTxtNode *const pDest,
                      const SwIndex &rStart,
                      const xub_StrLen nLen,
                      const bool bForceCopyOfAllAttrs )
{
    SwIndex aIdx( pDest, pDest->m_Text.Len() );
    CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs );
}

// introduction of new optional parameter to control, if all attributes have to be copied.
void SwTxtNode::CopyText( SwTxtNode *const pDest,
                      const SwIndex &rDestStart,
                      const SwIndex &rStart,
                      xub_StrLen nLen,
                      const bool bForceCopyOfAllAttrs )
{
    xub_StrLen nTxtStartIdx = rStart.GetIndex();
    xub_StrLen nDestStart = rDestStart.GetIndex();		// alte Pos merken

    if (pDest->GetDoc()->IsClipBoard() && this->GetNum())
    {
        // #i111677# cache expansion of source (for clipboard)
        pDest->m_pNumStringCache.reset(
            new ::rtl::OUString(this->GetNumString()));
    }

	if( !nLen )
	{
		// wurde keine Laenge angegeben, dann Kopiere die Attribute
		// an der Position rStart.
		CopyAttr( pDest, nTxtStartIdx, nDestStart );

		// harte Absatz umspannende Attribute kopieren
        if( HasSwAttrSet() )
		{
			// alle, oder nur die CharAttribute ?
            // --> OD 2008-11-18 #i96213#
            if ( !bForceCopyOfAllAttrs &&
                 ( nDestStart ||
                   pDest->HasSwAttrSet() ||
                   nLen != pDest->GetTxt().Len() ) )
            // <--
			{
				SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
									RES_CHRATR_BEGIN, RES_CHRATR_END-1,
                                    RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
                                    RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
									RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
									0 );
				aCharSet.Put( *GetpSwAttrSet() );
				if( aCharSet.Count() )
                {
                    pDest->SetAttr( aCharSet, nDestStart, nDestStart );
                }
			}
			else
            {
				GetpSwAttrSet()->CopyToModify( *pDest );
            }
		}
		return;
	}

	// 1. Text kopieren
    const xub_StrLen oldLen = pDest->m_Text.Len();
	//JP 15.02.96: Bug 25537 - Attributbehandlung am Ende fehlt! Darum
	//				ueber die InsertMethode den Text einfuegen und nicht
	//				selbst direkt
    pDest->InsertText( m_Text.Copy( nTxtStartIdx, nLen ), rDestStart,
                   IDocumentContentOperations::INS_EMPTYEXPAND );

    // um reale Groesse Updaten !
    nLen = pDest->m_Text.Len() - oldLen;
    if ( !nLen ) // string not longer?
        return;

    SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ? pDest->GetDoc() : 0;

    // harte Absatz umspannende Attribute kopieren
    if( HasSwAttrSet() )
    {
        // alle, oder nur die CharAttribute ?
        if ( !bForceCopyOfAllAttrs
             && ( nDestStart
                  || pDest->HasSwAttrSet()
                  || nLen != pDest->GetTxt().Len() ) )
        {
            SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
                RES_CHRATR_BEGIN, RES_CHRATR_END-1,
                RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
                RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
                RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
                0 );
            aCharSet.Put( *GetpSwAttrSet() );
            if( aCharSet.Count() )
            {
                pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
            }
        }
        else
        {
            GetpSwAttrSet()->CopyToModify( *pDest );
        }
    }

    bool const bUndoNodes = !pOtherDoc
                            && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());

    // Ende erst jetzt holen, weil beim Kopieren in sich selbst der
    // Start-Index und alle Attribute vorher aktualisiert werden.
    nTxtStartIdx = rStart.GetIndex();
    const xub_StrLen nEnd = nTxtStartIdx + nLen;

    // 2. Attribute kopieren
    // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
    // des Attributs hinter dem zu kopierenden Bereich liegt
    const sal_uInt16 nSize = m_pSwpHints ? m_pSwpHints->Count() : 0;

    // wird in sich selbst kopiert, dann kann beim Einfuegen ein
    // Attribut geloescht werden. Darum erst ins Tmp-Array kopieren und
    // dann erst ins eigene uebertragen.
    SwpHts aArr( 5 );

    // Del-Array fuer alle RefMarks ohne Ausdehnung
    SwpHts aRefMrkArr;

    sal_uInt16 nDeletedDummyChars(0);
    //Achtung: kann ungueltig sein!!
    for (sal_uInt16 n = 0; ( n < nSize ); ++n)
    {
        const xub_StrLen nAttrStartIdx = *(*m_pSwpHints)[n]->GetStart();
        if ( !( nAttrStartIdx < nEnd) )
            break;

        SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
        const xub_StrLen * const pEndIdx = pHt->GetEnd();
        const sal_uInt16 nWhich = pHt->Which();

        // JP 26.04.94: REFMARK's werden nie kopiert. Hat das Refmark aber
        //				keinen Bereich umspannt, so steht im Text ein 255
        //				dieses muss entfernt werden. Trick: erst kopieren,
        //				erkennen und sammeln, nach dem kopieren Loeschen.
        //				Nimmt sein Zeichen mit ins Grab !!
        // JP 14.08.95:	Duerfen RefMarks gemovt werden?
        const bool bCopyRefMark = RES_TXTATR_REFMARK == nWhich
                                  && ( bUndoNodes
                                       || ( !pOtherDoc
                                            ? GetDoc()->IsCopyIsMove()
                                            : 0 == pOtherDoc->GetRefMark( pHt->GetRefMark().GetRefName() ) ) );

        if ( pEndIdx
             && RES_TXTATR_REFMARK == nWhich
             && !bCopyRefMark )
        {
            continue;
        }

        // Input Fields are only copied, if completely covered by copied text
        if ( nWhich == RES_TXTATR_INPUTFIELD )
        {
            ASSERT( pEndIdx != NULL,
                    "<SwTxtNode::CopyText(..)> - RES_TXTATR_INPUTFIELD without EndIndex!" );
            if ( nAttrStartIdx < nTxtStartIdx
                 || ( pEndIdx != NULL
                      && *(pEndIdx) > nEnd ) )
            {
                continue;
            }
        }

        xub_StrLen nAttrStt;
        xub_StrLen nAttrEnd;

        if( nAttrStartIdx < nTxtStartIdx )
        {
            // start is before selection
            // copy hints with end and CH_TXTATR only if dummy char is copied
            if ( pEndIdx && (*pEndIdx > nTxtStartIdx) && !pHt->HasDummyChar() )
            {
                // attribute with extent and the end is in the selection
                nAttrStt = nDestStart;
                nAttrEnd = (*pEndIdx > nEnd)
                    ? rDestStart.GetIndex()
                    : nDestStart + (*pEndIdx) - nTxtStartIdx;
            }
            else
            {
                continue;
            }
        }
        else
        {
            // start is in the selection
            nAttrStt = nDestStart + ( nAttrStartIdx - nTxtStartIdx );
            if( pEndIdx )
            {
                nAttrEnd = *pEndIdx > nEnd
                    ? rDestStart.GetIndex()
                    : nDestStart + ( *pEndIdx - nTxtStartIdx );
            }
            else
            {
                nAttrEnd = nAttrStt;
            }
        }

        SwTxtAttr * pNewHt = 0;

        if( pDest == this )
        {
            // copy the hint here, but insert it later
            pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
                    nAttrStt, nAttrEnd, COPY, pDest );

            lcl_CopyHint(nWhich, pHt, pNewHt, 0, pDest);
            aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
        }
        else
        {
            pNewHt = pDest->InsertItem(
                pHt->GetAttr(),
                nAttrStt - nDeletedDummyChars,
                nAttrEnd - nDeletedDummyChars,
                nsSetAttrMode::SETATTR_NOTXTATRCHR | nsSetAttrMode::SETATTR_IS_COPY);
            if (pNewHt)
            {
                lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
            }
            else if (pHt->HasDummyChar())
            {
                // The attribute that has failed to be copied would insert
                // dummy char, so positions of the following attributes have
                // to be shifted by one to compensate for that missing char.
                ++nDeletedDummyChars;
            }
        }

        if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark )
        {
            aRefMrkArr.C40_INSERT( SwTxtAttr, pNewHt, aRefMrkArr.Count() );
        }
    }

    // nur falls im Array Attribute stehen (kann nur beim Kopieren
    // sich selbst passieren!!)
    for ( sal_uInt16 i = 0; i < aArr.Count(); ++i )
    {
        InsertHint( aArr[ i ], nsSetAttrMode::SETATTR_NOTXTATRCHR );
    }

    if( pDest->GetpSwpHints() )
    {
        for ( sal_uInt16 i = 0; i < aRefMrkArr.Count(); ++i )
        {
            SwTxtAttr * const pNewHt = aRefMrkArr[i];
            if( pNewHt->GetEnd() )
            {
                pDest->GetpSwpHints()->Delete( pNewHt );
                pDest->DestroyAttr( pNewHt );
            }
            else
            {
                const SwIndex aIdx( pDest, *pNewHt->GetStart() );
                pDest->EraseText( aIdx, 1 );
            }
        }
    }

    CHECK_SWPHINTS(this);
}


void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
        const IDocumentContentOperations::InsertFlags nMode )
{
    ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::InsertText: invalid index." );
    ASSERT( (sal_uLong)m_Text.Len() + (sal_uLong)rStr.Len() <= STRING_LEN,
            "SwTxtNode::InsertText: node text with insertion > STRING_LEN." );

	xub_StrLen aPos = rIdx.GetIndex();
    xub_StrLen nLen = m_Text.Len() - aPos;
    m_Text.Insert( rStr, aPos );
    nLen = m_Text.Len() - aPos - nLen;

    if ( !nLen ) return;

    sal_Bool bOldExpFlg = IsIgnoreDontExpand();
    if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
    {
        SetIgnoreDontExpand( sal_True );
    }

    Update( rIdx, nLen ); // text content changed!

    if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
    {
        SetIgnoreDontExpand( bOldExpFlg );
    }

	// analog zu Insert(char) in txtedt.cxx:
	// 1) bei bHintExp leere Hints an rIdx.GetIndex suchen und aufspannen
	// 2) bei bHintExp == sal_False mitgezogene Feldattribute zuruecksetzen

    if ( HasHints() )
    {
        for ( sal_uInt16 i = 0; i < m_pSwpHints->Count() &&
                rIdx >= *(*m_pSwpHints)[i]->GetStart(); ++i )
        {
            SwTxtAttr * const pHt = m_pSwpHints->GetTextHint( i );
            xub_StrLen * const pEndIdx = pHt->GetEnd();
			if( !pEndIdx )
				continue;

			if( rIdx == *pEndIdx )
			{
                if (  (nMode & IDocumentContentOperations::INS_NOHINTEXPAND) ||
                    (!(nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
                     && pHt->DontExpand()) )
				{
					// bei leeren Attributen auch Start veraendern
					if( rIdx == *pHt->GetStart() )
						*pHt->GetStart() = *pHt->GetStart() - nLen;
					*pEndIdx = *pEndIdx - nLen;
                    m_pSwpHints->DeleteAtPos(i);
                    InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
                }
                // empty hints at insert position?
                else if ( (nMode & IDocumentContentOperations::INS_EMPTYEXPAND)
                        && (*pEndIdx == *pHt->GetStart()) )
				{
					*pHt->GetStart() = *pHt->GetStart() - nLen;
                    const sal_uInt16 nAktLen = m_pSwpHints->Count();
                    m_pSwpHints->DeleteAtPos(i);
                    InsertHint( pHt/* AUTOSTYLES:, nsSetAttrMode::SETATTR_NOHINTADJUST*/ );
                    if ( nAktLen > m_pSwpHints->Count() && i )
                    {
						--i;
                    }
					continue;
				}
				else
                {
					continue;
                }
			}
            if ( !(nMode & IDocumentContentOperations::INS_NOHINTEXPAND) &&
				 rIdx == nLen && *pHt->GetStart() == rIdx.GetIndex() &&
				 !pHt->IsDontExpandStartAttr() )
			{
				// Kein Feld, am Absatzanfang, HintExpand
                m_pSwpHints->DeleteAtPos(i);
				*pHt->GetStart() = *pHt->GetStart() - nLen;
                InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
            }
        }
        TryDeleteSwpHints();
    }

	if ( GetDepends() )
	{
		SwInsTxt aHint( aPos, nLen );
		NotifyClients( 0, &aHint );
	}

    // By inserting a character, the hidden flags
    // at the TxtNode can become invalid:
    SetCalcHiddenCharFlags();

	CHECK_SWPHINTS(this);
}

/*************************************************************************
|*
|*	SwTxtNode::Cut()
|*
|*	Beschreibung		text.doc
|*	Ersterstellung		VB 20.03.91
|*	Letzte Aenderung	JP 11.08.94
|*
*************************************************************************/

void SwTxtNode::CutText( SwTxtNode * const pDest,
            const SwIndex & rStart, const xub_StrLen nLen )
{
	if(pDest)
	{
		SwIndex aDestStt( pDest, pDest->GetTxt().Len() );
        CutImpl( pDest, aDestStt, rStart, nLen, false );
    }
    else
    {
        ASSERT(false,
            "mst: entering dead and bitrotted code; fasten your seatbelts!");
        EraseText( rStart, nLen );
    }
}


void SwTxtNode::CutImpl( SwTxtNode * const pDest, const SwIndex & rDestStart,
         const SwIndex & rStart, /*const*/ xub_StrLen nLen, const bool bUpdate )
{
	if(!pDest)
    {
        ASSERT(false,
            "mst: entering dead and bitrotted code; fasten your seatbelts!");
        EraseText( rStart, nLen );
		return;
	}

	// nicht im Dokument verschieben ?
	if( GetDoc() != pDest->GetDoc() )
	{
        ASSERT(false,
            "mst: entering dead and bitrotted code; fasten your seatbelts!");
        CopyText( pDest, rDestStart, rStart, nLen);
        EraseText(rStart, nLen);
		return;
	}

	if( !nLen )
	{
		// wurde keine Laenge angegeben, dann Kopiere die Attribute
		// an der Position rStart.
		CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() );
		return;
	}

	xub_StrLen nTxtStartIdx = rStart.GetIndex();
	xub_StrLen nDestStart = rDestStart.GetIndex();		// alte Pos merken
    const xub_StrLen nInitSize = pDest->m_Text.Len();

	// wird in sich selbst verschoben, muss es gesondert behandelt werden !!
	if( pDest == this )
	{
        ASSERT(false,
            "mst: entering dead and bitrotted code; fasten your seatbelts!");
        m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
        m_Text.Erase( nTxtStartIdx + (nDestStart<nTxtStartIdx ? nLen : 0), nLen );

        const xub_StrLen nEnd = rStart.GetIndex() + nLen;

		// dann suche mal alle Attribute zusammen, die im verschobenen
		// Bereich liegen. Diese werden in das extra Array verschoben,
		// damit sich die Indizies beim Updaten nicht veraendern !!!
		SwpHts aArr( 5 );

		// 2. Attribute verschieben
		// durch das Attribute-Array, bis der Anfang des Geltungsbereiches
		// des Attributs hinter dem zu verschiebenden Bereich liegt
        sal_uInt16 nAttrCnt = 0;
        while ( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
        {
            SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
            const xub_StrLen nAttrStartIdx = *pHt->GetStart();
            if (!( nAttrStartIdx < nEnd ))
                break;
            const xub_StrLen * const pEndIdx = pHt->GetEnd();
            const sal_uInt16 nWhich = pHt->Which();
            SwTxtAttr *pNewHt = 0;

			if(nAttrStartIdx < nTxtStartIdx)
			{
				// Anfang liegt vor dem Bereich
                if ( RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar() &&
					pEndIdx && *pEndIdx > nTxtStartIdx )
				{
					// Attribut mit einem Bereich
					// und das Ende des Attribut liegt im Bereich
                    pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 0,
										*pEndIdx > nEnd
											? nLen
											: *pEndIdx - nTxtStartIdx );
				}
			}
			else
			{
				// der Anfang liegt vollstaendig im Bereich
				if( !pEndIdx || *pEndIdx < nEnd )
				{
					// Attribut verschieben
                    m_pSwpHints->Delete( pHt );
					// die Start/End Indicies neu setzen
					*pHt->GetStart() = nAttrStartIdx - nTxtStartIdx;
					if( pEndIdx )
						*pHt->GetEnd() = *pEndIdx - nTxtStartIdx;
					aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
					continue;			// while-Schleife weiter, ohne ++ !
				}
					// das Ende liegt dahinter
                else if (RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar())
				{
                    pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
							nAttrStartIdx - nTxtStartIdx,
							!pEndIdx ? 0
									 : ( *pEndIdx > nEnd
											? nLen
											: *pEndIdx - nTxtStartIdx ));
				}
			}
			if( pNewHt )
			{
				// die Daten kopieren
				lcl_CopyHint( nWhich, pHt, pNewHt, 0, this );
				aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
			}
			++nAttrCnt;
		}

		if( bUpdate )
        {
			// Update aller Indizies
			Update( rDestStart, nLen, sal_False, sal_True );
        }
#ifdef CUTNOEXPAND
		else
			// wird am Ende eingefuegt, nur die Attribut-Indizies verschieben
            if ( 0 < nLen && 0 < nInitSize && m_pSwpHints )
            {
                // check if there was the end of an attribute at the insertion
                // position: if it is not a field, it must be expanded
                for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); n++ )
                {
                    SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
                    const xub_StrLen * const pEndIdx = pHt->GetEnd();
                    if ( pEndIdx  && (*pEndIdx == nInitSize) )
                    {
                        *pEndIdx = *pEndIdx + nLen;
                    }
                }
            }
#endif
		CHECK_SWPHINTS(this);

		Update( rStart, nLen, sal_True, sal_True );

		CHECK_SWPHINTS(this);

		// dann setze die kopierten/geloeschten Attribute in den Node
		if( nDestStart <= nTxtStartIdx )
        {
			nTxtStartIdx = nTxtStartIdx + nLen;
        }
		else
        {
			nDestStart = nDestStart - nLen;
        }

        for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
        {
            SwTxtAttr *const pNewHt = aArr[n];
			*pNewHt->GetStart() = nDestStart + *pNewHt->GetStart();
            xub_StrLen * const pEndIdx = pNewHt->GetEnd();
            if ( pEndIdx )
            {
                *pEndIdx = nDestStart + *pEndIdx;
            }
            InsertHint( pNewHt, nsSetAttrMode::SETATTR_NOTXTATRCHR );
        }
    }
    else
    {
        pDest->m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
        m_Text.Erase( nTxtStartIdx, nLen );
        nLen = pDest->m_Text.Len() - nInitSize; // update w/ current size!
		if( !nLen )					// String nicht gewachsen ??
			return;

		if( bUpdate )
        {
			// Update aller Indizies
			pDest->Update( rDestStart, nLen, sal_False, sal_True);
        }
#ifdef CUTNOEXPAND
		else
			// wird am Ende eingefuegt, nur die Attribut-Indizies verschieben
            if ( 0 < nLen && 0 < nInitSize && pDest->m_pSwpHints )
            {
                // check if there was the end of an attribute at the insertion
                // position: if it is not a field, it must be expanded
                for ( sal_uInt16 n = 0; n < pDest->m_pSwpHints->Count(); n++ )
                {
                    SwTxtAttr * const pHt = pDest->m_pSwpHints->GetTextHint(n);
                    const xub_StrLen * const pEndIdx = pHt->GetEnd();
                    if ( pEndIdx  && (*pEndIdx == nInitSize) )
                    {
                        *pEndIdx = *pEndIdx + nLen;
                    }
                }
            }
#endif
		CHECK_SWPHINTS(pDest);

        const xub_StrLen nEnd = rStart.GetIndex() + nLen;
        SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc())
            ? pDest->GetDoc() : 0;
        bool const bUndoNodes = !pOtherDoc
            && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());

        ASSERT(!pOtherDoc,
            "mst: entering dead and bitrotted code; fasten your seatbelts!");

		// harte Absatz umspannende Attribute kopieren
        if( HasSwAttrSet() )
		{
			// alle, oder nur die CharAttribute ?
            if( nInitSize || pDest->HasSwAttrSet() ||
				nLen != pDest->GetTxt().Len() )
			{
				SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
									RES_CHRATR_BEGIN, RES_CHRATR_END-1,
                                    RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
                                    RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
									RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
									0 );
				aCharSet.Put( *GetpSwAttrSet() );
				if( aCharSet.Count() )
                    pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
			}
			else
            {
				GetpSwAttrSet()->CopyToModify( *pDest );
            }
		}

		// 2. Attribute verschieben
		// durch das Attribute-Array, bis der Anfang des Geltungsbereiches
		// des Attributs hinter dem zu verschiebenden Bereich liegt
        sal_uInt16 nAttrCnt = 0;
        while ( m_pSwpHints && (nAttrCnt < m_pSwpHints->Count()) )
        {
            SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
            const xub_StrLen nAttrStartIdx = *pHt->GetStart();
            if (!( nAttrStartIdx < nEnd ))
                break;
            const xub_StrLen * const pEndIdx = pHt->GetEnd();
            const sal_uInt16 nWhich = pHt->Which();
            SwTxtAttr *pNewHt = 0;

            // if the hint has a dummy character, then it must not be split!
			if(nAttrStartIdx < nTxtStartIdx)
			{
				// Anfang liegt vor dem Bereich
                if( !pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich
					|| bUndoNodes ) && pEndIdx && *pEndIdx > nTxtStartIdx )
				{
					// Attribut mit einem Bereich
					// und das Ende des Attribut liegt im Bereich
                    pNewHt = MakeTxtAttr( *pDest->GetDoc(), pHt->GetAttr(),
                                    nDestStart,
                                    nDestStart + (
										*pEndIdx > nEnd
											? nLen
											: *pEndIdx - nTxtStartIdx ) );
				}
			}
			else
			{
				// der Anfang liegt vollstaendig im Bereich
				if( !pEndIdx || *pEndIdx < nEnd ||
					(!pOtherDoc && !bUndoNodes && RES_TXTATR_REFMARK == nWhich)
                    || pHt->HasDummyChar() )
				{
					// do not delete note and later add it -> sidebar flickering
					if ( GetDoc()->GetDocShell() )
                    {
						GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
                    }
					// Attribut verschieben
                    m_pSwpHints->Delete( pHt );
					// die Start/End Indicies neu setzen
					*pHt->GetStart() =
							nDestStart + (nAttrStartIdx - nTxtStartIdx);
					if( pEndIdx )
                    {
						*pHt->GetEnd() = nDestStart + (
										*pEndIdx > nEnd
											? nLen
											: *pEndIdx - nTxtStartIdx );
                    }
                    pDest->InsertHint( pHt,
                              nsSetAttrMode::SETATTR_NOTXTATRCHR
                            | nsSetAttrMode::SETATTR_DONTREPLACE );
					if ( GetDoc()->GetDocShell() )
                    {
						GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
                    }
					continue;			// while-Schleife weiter, ohne ++ !
				}
					// das Ende liegt dahinter
				else if( RES_TXTATR_REFMARK != nWhich || bUndoNodes )
				{
                    pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
							nDestStart + (nAttrStartIdx - nTxtStartIdx),
							!pEndIdx ? 0
									 : nDestStart + ( *pEndIdx > nEnd
											? nLen
											: *pEndIdx - nTxtStartIdx ));
				}
			}
			if ( pNewHt )
            {
                const bool bSuccess( pDest->InsertHint( pNewHt,
                              nsSetAttrMode::SETATTR_NOTXTATRCHR
                            | nsSetAttrMode::SETATTR_DONTREPLACE
                            | nsSetAttrMode::SETATTR_IS_COPY) );
                if (bSuccess)
                {
                    lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
                }
            }
			++nAttrCnt;
		}
		// sollten jetzt noch leere Attribute rumstehen, dann haben diese
		// eine hoehere Praezedenz. Also herausholen und das Array updaten.
		// Die dabei entstehenden leeren Hints werden von den gesicherten
		// "uebergeplaettet".	(Bug: 6977)
        if( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
        {
            SwpHts aArr( 5 );
            while ( nAttrCnt < m_pSwpHints->Count() )
            {
                SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
                if ( nEnd != *pHt->GetStart() )
                    break;
                const xub_StrLen * const pEndIdx = pHt->GetEnd();
                if ( pEndIdx && *pEndIdx == nEnd )
                {
					aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
                    m_pSwpHints->Delete( pHt );
                }
                else
                {
                    ++nAttrCnt;
                }
			}
			Update( rStart, nLen, sal_True, sal_True );

            for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
			{
                SwTxtAttr * const pHt = aArr[ n ];
				*pHt->GetStart() = *pHt->GetEnd() = rStart.GetIndex();
                InsertHint( pHt );
            }
        }
		else
        {
			Update( rStart, nLen, sal_True, sal_True );
        }

		CHECK_SWPHINTS(this);
	}

    TryDeleteSwpHints();

	// Frames benachrichtigen;
	SwInsTxt aInsHint( nDestStart, nLen );
    pDest->ModifyNotification( 0, &aInsHint );
	SwDelTxt aDelHint( nTxtStartIdx, nLen );
    ModifyNotification( 0, &aDelHint );
}


void SwTxtNode::EraseText(const SwIndex &rIdx, const xub_StrLen nCount,
        const IDocumentContentOperations::InsertFlags nMode )
{
    ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::EraseText: invalid index." );

    const xub_StrLen nStartIdx = rIdx.GetIndex();
    const xub_StrLen nCnt = (STRING_LEN == nCount)
                      ? m_Text.Len() - nStartIdx : nCount;
    const xub_StrLen nEndIdx = nStartIdx + nCnt;
    m_Text.Erase( nStartIdx, nCnt );

	/* GCAttr(); alle leeren weggwerfen ist zu brutal.
	 * Es duerfen nur die wegggeworfen werden,
	 * die im Bereich liegen und nicht am Ende des Bereiches liegen
	 */

    for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
    {
        SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);

        const xub_StrLen nHintStart = *pHt->GetStart();

        if ( nHintStart < nStartIdx )
            continue;

        if ( nHintStart > nEndIdx )
            break; // hints are sorted by end, so break here

        const xub_StrLen* pHtEndIdx = pHt->GetEnd();
        const sal_uInt16 nWhich = pHt->Which();

        if( !pHtEndIdx )
        {
            ASSERT(pHt->HasDummyChar(),
                    "attribute with neither end nor CH_TXTATR?");
            if (isTXTATR(nWhich) &&
                (nHintStart >= nStartIdx) && (nHintStart < nEndIdx))
            {
                m_pSwpHints->DeleteAtPos(i);
                DestroyAttr( pHt );
                --i;
            }
            continue;
        }

        ASSERT (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx)
                    && pHt->HasDummyChar() )
                // next line: deleting exactly dummy char: DeleteAttributes
                || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)),
                "ERROR: deleting left-overlapped attribute with CH_TXTATR");

        // Delete the hint if:
        // 1. The hint ends before the deletion end position or
        // 2. The hint ends at the deletion end position and
        //    we are not in empty expand mode and
        //    the hint is a [toxmark|refmark|ruby|inputfield] text attribute
        // 3. deleting exactly the dummy char of an hint with end and dummy
        //    char deletes the hint
        if (   (*pHtEndIdx < nEndIdx)
            || ( (*pHtEndIdx == nEndIdx)     &&
                 !(IDocumentContentOperations::INS_EMPTYEXPAND & nMode)  &&
                 (  (RES_TXTATR_TOXMARK == nWhich)  ||
                    (RES_TXTATR_REFMARK == nWhich)  ||
                    (RES_TXTATR_CJK_RUBY == nWhich) ||
                    (RES_TXTATR_INPUTFIELD == nWhich) ) )
            || ( (nHintStart < nEndIdx)     &&
                 pHt->HasDummyChar()        )
           )
        {
            m_pSwpHints->DeleteAtPos(i);
            DestroyAttr( pHt );
            --i;
        }
    }

    ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");

    TryDeleteSwpHints();

    Update( rIdx, nCnt, sal_True );

    if( 1 == nCnt )
    {
        SwDelChr aHint( nStartIdx );
        NotifyClients( 0, &aHint );
    }
    else
    {
        SwDelTxt aHint( nStartIdx, nCnt );
        NotifyClients( 0, &aHint );
    }

    ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");

    // By deleting a character, the hidden flags
    // at the TxtNode can become invalid:
    SetCalcHiddenCharFlags();

    CHECK_SWPHINTS(this);
}

/***********************************************************************
#*	Class		:	SwTxtNode
#*	Methode 	:	GCAttr
#*
#*	Beschreibung
#*					text.doc
#*
#*	Datum		:	MS 28.11.90
#*	Update		:	VB 24.07.91
#***********************************************************************/

void SwTxtNode::GCAttr()
{
    if ( !HasHints() )
        return;

    bool   bChanged = false;
    sal_uInt16 nMin = m_Text.Len();
    sal_uInt16 nMax = 0;
    const bool bAll = nMin != 0; // Bei leeren Absaetzen werden nur die INet-Formate entfernt.

    for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
    {
        SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(i);

        // wenn Ende und Start gleich sind --> loeschen
        const xub_StrLen * const pEndIdx = pHt->GetEnd();
        if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == *pHt->GetStart())
            && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) )
        {
            bChanged = true;
            nMin = Min( nMin, *pHt->GetStart() );
            nMax = Max( nMax, *pHt->GetEnd() );
            DestroyAttr( m_pSwpHints->Cut(i) );
            --i;
        }
        else
        {
            pHt->SetDontExpand( false );
        }
    }
    TryDeleteSwpHints();

    if(bChanged)
    {
        //TxtFrm's reagieren auf aHint, andere auf aNew
        SwUpdateAttr aHint( 
            nMin, 
            nMax, 
            0);

        NotifyClients( 0, &aHint );
        SwFmtChg aNew( GetTxtColl() );
        NotifyClients( 0, &aNew );
    }
}

// #i23726#
SwNumRule* SwTxtNode::_GetNumRule(sal_Bool bInParent) const
{
    SwNumRule* pRet = 0;

    const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent );
    bool bNoNumRule = false;
    if ( pItem )
    {
        String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue();
        if (sNumRuleName.Len() > 0)
        {
            pRet = GetDoc()->FindNumRulePtr( sNumRuleName );
        }
        else // numbering is turned off
            bNoNumRule = true;
    }

    if ( !bNoNumRule )
    {
        if ( pRet && pRet == GetDoc()->GetOutlineNumRule() &&
             ( !HasSwAttrSet() ||
               SFX_ITEM_SET !=
                GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) ) )
        {
            SwTxtFmtColl* pColl = GetTxtColl();
            if ( pColl )
            {
                const SwNumRuleItem& rDirectItem = pColl->GetNumRule( sal_False );
                if ( rDirectItem.GetValue().Len() == 0 )
                {
                    pRet = 0L;
                }
            }
        }
    }

    return pRet;
}

SwNumRule* SwTxtNode::GetNumRule(sal_Bool bInParent) const
{
    SwNumRule * pRet = _GetNumRule(bInParent);

    return pRet;
}

void SwTxtNode::NumRuleChgd()
{
    // --> OD 2008-04-04 #refactorlists#
    if ( IsInList() )
    {
        SwNumRule* pNumRule = GetNumRule();
        if ( pNumRule && pNumRule != GetNum()->GetNumRule() )
        {
            mpNodeNum->ChangeNumRule( *pNumRule );
        }
    }
    // <--

    if( IsInCache() )
	{
		SwFrm::GetCache().Delete( this );
		SetInCache( sal_False );
	}
	SetInSwFntCache( sal_False );

    // Sending "noop" modify in order to cause invalidations of registered
    // <SwTxtFrm> instances to get the list style change respectively the change 
    // in the list tree reflected in the layout.
    // Important note: 
    {
        SvxLRSpaceItem& rLR = (SvxLRSpaceItem&)GetSwAttrSet().GetLRSpace();
        NotifyClients( &rLR, &rLR );
    }
}

// -> #i27615#
sal_Bool SwTxtNode::IsNumbered() const
{
    sal_Bool bResult = sal_False;

    SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
    if ( pRule && IsCountedInList() )
        bResult = sal_True;

    return bResult;
}

// --> OD 2008-04-02 #refactorlists#
bool SwTxtNode::HasMarkedLabel() const
{
    bool bResult = false;

    if ( IsInList() )
    {
        bResult =
            GetDoc()->getListByName( GetListId() )->IsListLevelMarked( GetActualListLevel() );
    }

    return bResult;
}
// <--
// <- #i27615#

SwTxtNode* SwTxtNode::_MakeNewTxtNode( const SwNodeIndex& rPos, sal_Bool bNext,
										sal_Bool bChgFollow )
{
	/* hartes PageBreak/PageDesc/ColumnBreak aus AUTO-Set ignorieren */
	SwAttrSet* pNewAttrSet = 0;
    // --> OD 2007-07-10 #i75353#
    bool bClearHardSetNumRuleWhenFmtCollChanges( false );
    // <--
    if( HasSwAttrSet() )
	{
		pNewAttrSet = new SwAttrSet( *GetpSwAttrSet() );
        const SfxItemSet* pTmpSet = GetpSwAttrSet();

		if( bNext )		// der naechste erbt keine Breaks!
			pTmpSet = pNewAttrSet;

		// PageBreaks/PageDesc/ColBreak rausschmeissen.
        sal_Bool bRemoveFromCache = sal_False;
        std::vector<sal_uInt16> aClearWhichIds;
        if ( bNext )
            bRemoveFromCache = ( 0 != pNewAttrSet->ClearItem( RES_PAGEDESC ) );
        else
            aClearWhichIds.push_back( RES_PAGEDESC );

		if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_BREAK, sal_False ) )
		{
            if ( bNext )
                pNewAttrSet->ClearItem( RES_BREAK );
            else
                aClearWhichIds.push_back( RES_BREAK );
            bRemoveFromCache = sal_True;
		}
		if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_KEEP, sal_False ) )
		{
            if ( bNext )
                pNewAttrSet->ClearItem( RES_KEEP );
            else
                aClearWhichIds.push_back( RES_KEEP );
            bRemoveFromCache = sal_True;
		}
		if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, sal_False ) )
		{
            if ( bNext )
                pNewAttrSet->ClearItem( RES_PARATR_SPLIT );
            else
                aClearWhichIds.push_back( RES_PARATR_SPLIT );
            bRemoveFromCache = sal_True;
		}
		if(SFX_ITEM_SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, sal_False))
        {
            SwNumRule * pRule = GetNumRule();

            if (pRule && IsOutline())
            {
                if ( bNext )
                    pNewAttrSet->ClearItem(RES_PARATR_NUMRULE);
                else
                {
                    // --> OD 2007-07-10 #i75353#
                    // No clear of hard set numbering rule at an outline paragraph at this point.
                    // Only if the paragraph style changes - see below.
//                    aClearWhichIds.push_back( RES_PARATR_NUMRULE );
                    bClearHardSetNumRuleWhenFmtCollChanges = true;
                    // <--
                }
                bRemoveFromCache = sal_True;
            }
        }

        if ( 0 != aClearWhichIds.size() )
            bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds );

		if( !bNext && bRemoveFromCache && IsInCache() )
		{
			SwFrm::GetCache().Delete( this );
			SetInCache( sal_False );
		}
	}
	SwNodes& rNds = GetNodes();

	SwTxtFmtColl* pColl = GetTxtColl();

	SwTxtNode *pNode = new SwTxtNode( rPos, pColl, pNewAttrSet );

	if( pNewAttrSet )
		delete pNewAttrSet;

	const SwNumRule* pRule = GetNumRule();
	if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() ) // #115901#
	{
        // --> OD 2005-10-18 #i55459#
        // - correction: parameter <bNext> has to be checked, as it was in the
        //   previous implementation.
        if ( !bNext && !IsCountedInList() )
            SetCountedInList(true);
        // <--
	}

	// jetzt kann es sein, das durch die Nummerierung dem neuen Node eine
	// Vorlage aus dem Pool zugewiesen wurde. Dann darf diese nicht
	// nochmal uebergeplaettet werden !!
	if( pColl != pNode->GetTxtColl() ||
		( bChgFollow && pColl != GetTxtColl() ))
		return pNode;		// mehr duerfte nicht gemacht werden oder ????

	pNode->_ChgTxtCollUpdateNum( 0, pColl ); // fuer Nummerierung/Gliederung
	if( bNext || !bChgFollow )
		return pNode;

	SwTxtFmtColl *pNextColl = &pColl->GetNextTxtFmtColl();
    // --> OD 2009-08-12 #i101870#
    // perform action on different paragraph styles before applying the new paragraph style
    if (pNextColl != pColl)
    {
        // --> OD 2007-07-10 #i75353#
        if ( bClearHardSetNumRuleWhenFmtCollChanges )
        {
            std::vector<sal_uInt16> aClearWhichIds;
            aClearWhichIds.push_back( RES_PARATR_NUMRULE );
            if ( ClearItemsFromAttrSet( aClearWhichIds ) != 0 && IsInCache() )
            {
                SwFrm::GetCache().Delete( this );
                SetInCache( sal_False );
            }
        }
        // <--
    }
    // <--
	ChgFmtColl( pNextColl );

	return pNode;
}

SwCntntNode* SwTxtNode::AppendNode( const SwPosition & rPos )
{
    // Position hinter dem eingefuegt wird
    SwNodeIndex aIdx( rPos.nNode, 1 );
    SwTxtNode* pNew = _MakeNewTxtNode( aIdx, sal_True );

    // reset list attributes at appended text node
    pNew->ResetAttr( RES_PARATR_LIST_ISRESTART );
    pNew->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
    pNew->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
    if ( pNew->GetNumRule() == 0 )
    {
        pNew->ResetAttr( RES_PARATR_LIST_ID );
        pNew->ResetAttr( RES_PARATR_LIST_LEVEL );
    }

    if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
    {
        AddToList();
    }

    if( GetDepends() )
        MakeFrms( *pNew );
    return pNew;
}

/*************************************************************************
 *						SwTxtNode::GetTxtAttr
 *************************************************************************/

SwTxtAttr * SwTxtNode::GetTxtAttrForCharAt(
    const xub_StrLen nIndex,
    const RES_TXTATR nWhich ) const
{
    if ( HasHints() )
    {
        for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); ++i )
        {
            SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(i);
            const xub_StrLen nStartPos = *pHint->GetStart();
            if ( nIndex < nStartPos )
            {
                return 0;
            }
            if ( (nIndex == nStartPos) && pHint->HasDummyChar() )
            {
                return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() )
                       ? pHint : 0;
            }
        }
    }
    return 0;
}

// -> #i29560#
sal_Bool SwTxtNode::HasNumber() const
{
    sal_Bool bResult = sal_False;

    const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
    if ( pRule )
    {
        SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel())));

        // #i40041#
        bResult = aFmt.IsEnumeration() &&
            SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType();
    }

    return bResult;
}

sal_Bool SwTxtNode::HasBullet() const
{
    sal_Bool bResult = sal_False;

    const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
    if ( pRule )
    {
        SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel())));

        bResult = aFmt.IsItemize();
    }

    return bResult;
}
// <- #i29560#

// --> OD 2005-11-17 #128041# - introduce parameter <_bInclPrefixAndSuffixStrings>
//i53420 added max outline parameter
XubString SwTxtNode::GetNumString( const bool _bInclPrefixAndSuffixStrings, const unsigned int _nRestrictToThisLevel ) const
{
    if (GetDoc()->IsClipBoard() && m_pNumStringCache.get())
    {
        // #i111677# do not expand number strings in clipboard documents
        return *m_pNumStringCache;
    }
    const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
    if ( pRule &&
         IsCountedInList() )
    {
        SvxNumberType const& rNumberType(
                pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ) );
        if (rNumberType.IsTxtFmt() ||
        // #b6432095#
            (style::NumberingType::NUMBER_NONE == rNumberType.GetNumberingType()))
        {
            return pRule->MakeNumString( GetNum()->GetNumberVector(),
                                     _bInclPrefixAndSuffixStrings ? sal_True : sal_False,
                                     sal_False,
                                     _nRestrictToThisLevel );
        }
    }

    return aEmptyStr;
}

long SwTxtNode::GetLeftMarginWithNum( sal_Bool bTxtLeft ) const
{
    long nRet = 0;
    const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
	if( pRule )
	{
        const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
        // --> OD 2008-01-16 #newlistlevelattrs#
        if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
        {
            nRet = rFmt.GetAbsLSpace();

            if( !bTxtLeft )
            {
                if( 0 > rFmt.GetFirstLineOffset() &&
                    nRet > -rFmt.GetFirstLineOffset() )
                    nRet = nRet + rFmt.GetFirstLineOffset();
                else
                    nRet = 0;
            }

            if( pRule->IsAbsSpaces() )
                nRet = nRet - GetSwAttrSet().GetLRSpace().GetLeft();
        }
        else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
        {
            if ( AreListLevelIndentsApplicable() )
            {
                nRet = rFmt.GetIndentAt();
                // --> OD 2008-06-06 #i90401#
                // Only negative first line indents have consider for the left margin
                if ( !bTxtLeft &&
                     rFmt.GetFirstLineIndent() < 0 )
                {
                    nRet = nRet + rFmt.GetFirstLineIndent();
                }
                // <--
            }
        }
        // <--
	}

    return nRet;
}

sal_Bool SwTxtNode::GetFirstLineOfsWithNum( short& rFLOffset ) const
{
    sal_Bool bRet( sal_False );
    // --> OD 2009-09-08 #i95907#, #b6879723#
    rFLOffset = 0;
    // <--

    // --> OD 2005-11-02 #i51089 - TUNING#
    const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
    if ( pRule )
	{
        if ( IsCountedInList() )
        {
            // --> OD 2008-01-16 #newlistlevelattrs#
            const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
            if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
            {
                rFLOffset = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() )).GetFirstLineOffset();

                if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
                {
                    SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
                    rFLOffset = rFLOffset + aItem.GetTxtFirstLineOfst();
                }
            }
            else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
            {
                if ( AreListLevelIndentsApplicable() )
                {
                    rFLOffset = static_cast<sal_uInt16>(rFmt.GetFirstLineIndent());
                }
                else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
                {
                    SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
                    rFLOffset = aItem.GetTxtFirstLineOfst();
                }
            }
            // <--
        }

        bRet = sal_True;
	}
    else
    {
        rFLOffset = GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
    }

    return bRet;
}

// --> OD 2010-01-05 #b6884103#
SwTwips SwTxtNode::GetAdditionalIndentForStartingNewList() const
{
    SwTwips nAdditionalIndent = 0;

    const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
    if ( pRule )
    {
        const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
        if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
        {
            nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();

            if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
            {
                nAdditionalIndent = nAdditionalIndent -
                                    GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
            }
        }
        else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
        {
            if ( AreListLevelIndentsApplicable() )
            {
                nAdditionalIndent = rFmt.GetIndentAt() + rFmt.GetFirstLineIndent();
            }
            else
            {
                nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
                if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
                {
                    nAdditionalIndent = nAdditionalIndent -
                                        GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
                }
            }
        }
    }
    else
    {
        nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
    }

    return nAdditionalIndent;
}
// <--

// --> OD 2008-12-02 #i96772#
void SwTxtNode::ClearLRSpaceItemDueToListLevelIndents( SvxLRSpaceItem& o_rLRSpaceItem ) const
{
    if ( AreListLevelIndentsApplicable() )
    {
        const SwNumRule* pRule = GetNumRule();
        if ( pRule && GetActualListLevel() >= 0 )
        {
            const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
            if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
            {
                SvxLRSpaceItem aLR( RES_LR_SPACE );
                o_rLRSpaceItem = aLR;
            }
        }
    }
}
// <--

// --> OD 2008-07-01 #i91133#
long SwTxtNode::GetLeftMarginForTabCalculation() const
{
    long nLeftMarginForTabCalc = 0;

    bool bLeftMarginForTabCalcSetToListLevelIndent( false );
    const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0;
    if( pRule )
    {
        const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
        if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
        {
            if ( AreListLevelIndentsApplicable() )
            {
                nLeftMarginForTabCalc = rFmt.GetIndentAt();
                bLeftMarginForTabCalcSetToListLevelIndent = true;
            }
        }
    }
    if ( !bLeftMarginForTabCalcSetToListLevelIndent )
    {
        nLeftMarginForTabCalc = GetSwAttrSet().GetLRSpace().GetTxtLeft();
    }

    return nLeftMarginForTabCalc;
}
// <--

void SwTxtNode::Replace0xFF(
    XubString& rTxt,
    xub_StrLen& rTxtStt,
    xub_StrLen nEndPos,
    sal_Bool bExpandFlds ) const
{
    if( GetpSwpHints() )
    {
        sal_Unicode cSrchChr = CH_TXTATR_BREAKWORD;
        for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter, cSrchChr = CH_TXTATR_INWORD )
        {
            xub_StrLen nPos = rTxt.Search( cSrchChr );
            while( STRING_NOTFOUND != nPos && nPos < nEndPos )
            {
                const SwTxtAttr* const pAttr =
                    GetTxtAttrForCharAt( rTxtStt + nPos );
                if( pAttr )
                {
                    switch( pAttr->Which() )
                    {
                    case RES_TXTATR_FIELD:
                    case RES_TXTATR_ANNOTATION:
                        rTxt.Erase( nPos, 1 );
                        if( bExpandFlds )
                        {
                            const XubString aExpand(
                                static_cast<SwTxtFld const*>(pAttr)->GetFmtFld().GetField()->ExpandField(true));
                            rTxt.Insert( aExpand, nPos );
                            nPos = nPos + aExpand.Len();
                            nEndPos = nEndPos + aExpand.Len();
                            rTxtStt = rTxtStt - aExpand.Len();
                        }
                        ++rTxtStt;
                        break;

                    case RES_TXTATR_FTN:
                        rTxt.Erase( nPos, 1 );
                        if( bExpandFlds )
                        {
                            const SwFmtFtn& rFtn = pAttr->GetFtn();
                            XubString sExpand;
                            if( rFtn.GetNumStr().Len() )
                                sExpand = rFtn.GetNumStr();
                            else if( rFtn.IsEndNote() )
                                sExpand = GetDoc()->GetEndNoteInfo().aFmt.
                                GetNumStr( rFtn.GetNumber() );
                            else
                                sExpand = GetDoc()->GetFtnInfo().aFmt.
                                GetNumStr( rFtn.GetNumber() );
                            rTxt.Insert( sExpand, nPos );
                            nPos = nPos + sExpand.Len();
                            nEndPos = nEndPos + sExpand.Len();
                            rTxtStt = rTxtStt - sExpand.Len();
                        }
                        ++rTxtStt;
                        break;

                    default:
                        rTxt.Erase( nPos, 1 );
                        ++rTxtStt;
                    }
                }
                else
                    ++nPos, ++nEndPos;
                nPos = rTxt.Search( cSrchChr, nPos );
            }
        }
    }
}

/*************************************************************************
 *                      SwTxtNode::GetExpandTxt
 * Expand fields
 *************************************************************************/
// --> OD 2007-11-15 #i83479# - handling of new parameters
XubString SwTxtNode::GetExpandTxt( const xub_StrLen nIdx,
                                   const xub_StrLen nLen,
                                   const bool bWithNum,
                                   const bool bAddSpaceAfterListLabelStr,
                                   const bool bWithSpacesForLevel ) const
{
    XubString aTxt( GetTxt().Copy( nIdx, nLen ) );
    xub_StrLen nTxtStt = nIdx;
    Replace0xFF( aTxt, nTxtStt, aTxt.Len(), sal_True );

    // remove dummy characters of Input Fields
    aTxt.EraseAllChars( CH_TXT_ATR_INPUTFIELDSTART );
    aTxt.EraseAllChars( CH_TXT_ATR_INPUTFIELDEND );

    if( bWithNum )
    {
        XubString aListLabelStr = GetNumString();
        if ( aListLabelStr.Len() > 0 )
        {
            if ( bAddSpaceAfterListLabelStr )
            {
                const sal_Unicode aSpace = ' ';
                aTxt.Insert( aSpace, 0 );
            }
            aTxt.Insert( GetNumString(), 0 );
        }
    }

    if ( bWithSpacesForLevel && GetActualListLevel() > 0 )
    {
        int nLevel( GetActualListLevel() );
        while ( nLevel > 0 )
        {
            const sal_Unicode aSpace = ' ';
            aTxt.Insert( aSpace , 0 );
            aTxt.Insert( aSpace , 0 );
            --nLevel;
        }
    }

	return aTxt;
}
// <--

sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx,
                        xub_StrLen nIdx, xub_StrLen nLen, sal_Bool bWithNum,
                        sal_Bool bWithFtn, sal_Bool bReplaceTabsWithSpaces ) const
{
	if( &rDestNd == this )
		return sal_False;

	SwIndex aDestIdx( &rDestNd, rDestNd.GetTxt().Len() );
	if( pDestIdx )
		aDestIdx = *pDestIdx;
	xub_StrLen nDestStt = aDestIdx.GetIndex();

	// Text einfuegen
    String sTmpText = GetTxt();
    if( bReplaceTabsWithSpaces )
        sTmpText.SearchAndReplaceAll('\t', ' ');

    // mask hidden characters
    const xub_Unicode cChar = CH_TXTATR_BREAKWORD;
    sal_uInt16 nHiddenChrs =
        SwScriptInfo::MaskHiddenRanges( *this, sTmpText, 0, sTmpText.Len(), cChar );

    sTmpText = sTmpText.Copy( nIdx, nLen );
    // remove dummy characters of Input Fields
    {
        sTmpText.EraseAllChars( CH_TXT_ATR_INPUTFIELDSTART );
        sTmpText.EraseAllChars( CH_TXT_ATR_INPUTFIELDEND );
    }
    rDestNd.InsertText( sTmpText, aDestIdx );
    nLen = aDestIdx.GetIndex() - nDestStt;

	// alle FontAttribute mit CHARSET Symbol in dem Bereich setzen
    if ( HasHints() )
    {
		xub_StrLen nInsPos = nDestStt - nIdx;
        for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ )
        {
            const SwTxtAttr* pHt = (*m_pSwpHints)[i];
            const xub_StrLen nAttrStartIdx = *pHt->GetStart();
            const sal_uInt16 nWhich = pHt->Which();
            if (nIdx + nLen <= nAttrStartIdx)
				break;		// ueber das Textende

			const xub_StrLen *pEndIdx = pHt->End();
			if( pEndIdx && *pEndIdx > nIdx &&
				( RES_CHRATR_FONT == nWhich ||
                  RES_TXTATR_CHARFMT == nWhich ||
                  RES_TXTATR_AUTOFMT == nWhich ))
            {
                const SvxFontItem* const pFont =
                    static_cast<const SvxFontItem*>(
                        CharFmt::GetItem( *pHt, RES_CHRATR_FONT ));
                if ( pFont && RTL_TEXTENCODING_SYMBOL == pFont->GetCharSet() )
                {
                    // attribute in area => copy
                    rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont),
                            nInsPos + nAttrStartIdx, nInsPos + *pEndIdx );
                }
            }
            else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) )
            {
                aDestIdx = nInsPos + nAttrStartIdx;
                switch( nWhich )
                {
                case RES_TXTATR_FIELD:
                case RES_TXTATR_ANNOTATION:
                    {
                        XubString const aExpand(
                            static_cast<SwTxtFld const*>(pHt)->GetFmtFld().GetField()->ExpandField(true) );
                        if( aExpand.Len() )
                        {
                            aDestIdx++;		// dahinter einfuegen;
                            rDestNd.InsertText( aExpand, aDestIdx );
                            aDestIdx = nInsPos + nAttrStartIdx;
                            nInsPos = nInsPos + aExpand.Len();
                        }
                        rDestNd.EraseText( aDestIdx, 1 );
                        --nInsPos;
                    }
                    break;

                case RES_TXTATR_FTN:
                    {
                        if ( bWithFtn )
                        {
                            const SwFmtFtn& rFtn = pHt->GetFtn();
                            XubString sExpand;
                            if( rFtn.GetNumStr().Len() )
                                sExpand = rFtn.GetNumStr();
                            else if( rFtn.IsEndNote() )
                                sExpand = GetDoc()->GetEndNoteInfo().aFmt.
                                GetNumStr( rFtn.GetNumber() );
                            else
                                sExpand = GetDoc()->GetFtnInfo().aFmt.
                                GetNumStr( rFtn.GetNumber() );
                            if( sExpand.Len() )
                            {
                                aDestIdx++;     // insert behind
                                SvxEscapementItem aItem(
                                    SVX_ESCAPEMENT_SUPERSCRIPT );
                                rDestNd.InsertItem(
                                    aItem,
                                    aDestIdx.GetIndex(),
                                    aDestIdx.GetIndex() );
                                rDestNd.InsertText( sExpand, aDestIdx, IDocumentContentOperations::INS_EMPTYEXPAND);
                                aDestIdx = nInsPos + nAttrStartIdx;
                                nInsPos = nInsPos + sExpand.Len();
                            }
                        }
                        rDestNd.EraseText( aDestIdx, 1 );
                        --nInsPos;
                    }
                    break;

                default:
                    rDestNd.EraseText( aDestIdx, 1 );
                    --nInsPos;
                }
            }
        }
    }

    if( bWithNum )
    {
        aDestIdx = nDestStt;
        rDestNd.InsertText( GetNumString(), aDestIdx );
    }

    if ( nHiddenChrs > 0 )
    {
        aDestIdx = 0;
        while ( aDestIdx < rDestNd.GetTxt().Len() )
        {
            if ( cChar == rDestNd.GetTxt().GetChar( aDestIdx.GetIndex() ) )
            {
                xub_StrLen nIndex = aDestIdx.GetIndex();
                while ( nIndex < rDestNd.GetTxt().Len() &&
                        cChar == rDestNd.GetTxt().GetChar( ++nIndex ) )
                    ;
                rDestNd.EraseText( aDestIdx, nIndex - aDestIdx.GetIndex() );
            }
            else
                ++aDestIdx;
        }
    }

	return sal_True;
}

const ModelToViewHelper::ConversionMap*
        SwTxtNode::BuildConversionMap( rtl::OUString& rRetText ) const
{
    const rtl::OUString& rNodeText = GetTxt();
    rRetText = rNodeText;
    ModelToViewHelper::ConversionMap* pConversionMap = 0;

    const SwpHints* pSwpHints2 = GetpSwpHints();
    xub_StrLen nPos = 0;

    for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i )
    {
        const SwTxtAttr* pAttr = (*pSwpHints2)[i];
        if ( pAttr->Which() == RES_TXTATR_FIELD
             || pAttr->Which() == RES_TXTATR_ANNOTATION )
        {
            const XubString aExpand(
                static_cast<SwTxtFld const*>(pAttr)->GetFmtFld().GetField()->ExpandField(true));
            if ( aExpand.Len() > 0 )
            {
                const xub_StrLen nFieldPos = *pAttr->GetStart();
                rRetText = rRetText.replaceAt( nPos + nFieldPos, 1, aExpand );
                if ( !pConversionMap )
                    pConversionMap = new ModelToViewHelper::ConversionMap;
                pConversionMap->push_back(
                        ModelToViewHelper::ConversionMapEntry(
                            nFieldPos, nPos + nFieldPos ) );
                nPos += ( aExpand.Len() - 1 );
            }
        }
    }

    if ( pConversionMap && pConversionMap->size() )
        pConversionMap->push_back(
            ModelToViewHelper::ConversionMapEntry(
                rNodeText.getLength()+1, rRetText.getLength()+1 ) );

    return pConversionMap;
}

XubString SwTxtNode::GetRedlineTxt( xub_StrLen nIdx, xub_StrLen nLen,
								sal_Bool bExpandFlds, sal_Bool bWithNum ) const
{
	SvUShorts aRedlArr;
	const SwDoc* pDoc = GetDoc();
	sal_uInt16 nRedlPos = pDoc->GetRedlinePos( *this, nsRedlineType_t::REDLINE_DELETE );
	if( USHRT_MAX != nRedlPos )
	{
		// es existiert fuer den Node irgendein Redline-Delete-Object
		const sal_uLong nNdIdx = GetIndex();
		for( ; nRedlPos < pDoc->GetRedlineTbl().Count() ; ++nRedlPos )
		{
			const SwRedline* pTmp = pDoc->GetRedlineTbl()[ nRedlPos ];
			if( nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
			{
				const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
				if( pRStt->nNode < nNdIdx )
				{
					if( pREnd->nNode > nNdIdx )
						// Absatz ist komplett geloescht
						return aEmptyStr;
					else if( pREnd->nNode == nNdIdx )
					{
						// von 0 bis nContent ist alles geloescht
						aRedlArr.Insert( xub_StrLen(0), aRedlArr.Count() );
						aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
					}
				}
				else if( pRStt->nNode == nNdIdx )
				{
					aRedlArr.Insert( pRStt->nContent.GetIndex(), aRedlArr.Count() );
					if( pREnd->nNode == nNdIdx )
						aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
					else
					{
						aRedlArr.Insert( GetTxt().Len(), aRedlArr.Count() );
						break; 		// mehr kann nicht kommen
					}
				}
				else
					break; 		// mehr kann nicht kommen
			}
		}
	}

	XubString aTxt( GetTxt().Copy( nIdx, nLen ) );

	xub_StrLen nTxtStt = nIdx, nIdxEnd = nIdx + aTxt.Len();
	for( sal_uInt16 n = 0; n < aRedlArr.Count(); n += 2 )
	{
		xub_StrLen nStt = aRedlArr[ n ], nEnd = aRedlArr[ n+1 ];
		if( ( nIdx <= nStt && nStt <= nIdxEnd ) ||
			( nIdx <= nEnd && nEnd <= nIdxEnd ))
		{
			if( nStt < nIdx ) nStt = nIdx;
			if( nIdxEnd < nEnd ) nEnd = nIdxEnd;
			xub_StrLen nDelCnt = nEnd - nStt;
			aTxt.Erase( nStt - nTxtStt, nDelCnt );
			Replace0xFF( aTxt, nTxtStt, nStt - nTxtStt, bExpandFlds );
			nTxtStt = nTxtStt + nDelCnt;
		}
		else if( nStt >= nIdxEnd )
			break;
	}
	Replace0xFF( aTxt, nTxtStt, aTxt.Len(), bExpandFlds );

	if( bWithNum )
		aTxt.Insert( GetNumString(), 0 );
	return aTxt;
}

/*************************************************************************
 *                        SwTxtNode::ReplaceText
 *************************************************************************/

void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
                             const XubString& rText )
{
    ASSERT( rStart.GetIndex() < m_Text.Len() &&
            rStart.GetIndex() + nDelLen <= m_Text.Len(),
            "SwTxtNode::ReplaceText: index out of bounds" );
    const xub_StrLen nStartPos = rStart.GetIndex();
    xub_StrLen nEndPos = nStartPos + nDelLen;
    xub_StrLen nLen = nDelLen;
    for ( xub_StrLen nPos = nStartPos; nPos < nEndPos; ++nPos )
    {
        if ( ( CH_TXTATR_BREAKWORD == m_Text.GetChar( nPos ) ) ||
             ( CH_TXTATR_INWORD    == m_Text.GetChar( nPos ) ) )
        {
            SwTxtAttr *const pHint = GetTxtAttrForCharAt( nPos );
            if (pHint)
            {
                ASSERT (!( pHint->GetEnd() && pHint->HasDummyChar()
                            && (*pHint->GetStart() < nEndPos)
                            && (*pHint->GetEnd()   > nEndPos) ),
                    "ReplaceText: ERROR: "
                    "deleting left-overlapped attribute with CH_TXTATR");
                DeleteAttribute( pHint );
                --nEndPos;
                --nLen;
            }
        }
    }

	sal_Bool bOldExpFlg = IsIgnoreDontExpand();
	SetIgnoreDontExpand( sal_True );

	if( nLen && rText.Len() )
	{
		// dann das 1. Zeichen ersetzen den Rest loschen und einfuegen
		// Dadurch wird die Attributierung des 1. Zeichen expandiert!
        m_Text.SetChar( nStartPos, rText.GetChar( 0 ) );

		((SwIndex&)rStart)++;
        m_Text.Erase( rStart.GetIndex(), nLen - 1 );
        Update( rStart, nLen - 1, true );

		XubString aTmpTxt( rText ); aTmpTxt.Erase( 0, 1 );
        m_Text.Insert( aTmpTxt, rStart.GetIndex() );
        Update( rStart, aTmpTxt.Len(), false );
    }
    else
    {
        m_Text.Erase( nStartPos, nLen );
        Update( rStart, nLen, true );

        m_Text.Insert( rText, nStartPos );
        Update( rStart, rText.Len(), false );
    }

	SetIgnoreDontExpand( bOldExpFlg );
    SwDelTxt aDelHint( nStartPos, nDelLen );
	NotifyClients( 0, &aDelHint );

    SwInsTxt aHint( nStartPos, rText.Len() );
	NotifyClients( 0, &aHint );
}

// --> OD 2008-03-27 #refactorlists#
namespace {
    // Helper method for special handling of modified attributes at text node.
    // The following is handled:
    // (1) on changing the paragraph style - RES_FMT_CHG:
    // Check, if list style of the text node is changed. If yes, add respectively
    // remove the text node to the corresponding list.
    // (2) on changing the attributes - RES_ATTRSET_CHG:
    // Same as (1).
    // (3) on changing the list style - RES_PARATR_NUMRULE:
    // Same as (1).
    void HandleModifyAtTxtNode( SwTxtNode& rTxtNode,
                                const SfxPoolItem* pOldValue,
                                const SfxPoolItem* pNewValue )
    {
        const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
                              pNewValue ? pNewValue->Which() : 0 ;
        bool bNumRuleSet = false;
        bool bParagraphStyleChanged = false;
        String sNumRule;
        String sOldNumRule;
        switch ( nWhich )
        {
            case RES_FMT_CHG:
            {
                bParagraphStyleChanged = true;
                if( rTxtNode.GetNodes().IsDocNodes() )
                {
                    const SwNumRule* pFormerNumRuleAtTxtNode =
                        rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
                    if ( pFormerNumRuleAtTxtNode )
                    {
                        sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
                    }
                    if ( rTxtNode.IsEmptyListStyleDueToSetOutlineLevelAttr() )
                    {
                        const SwNumRuleItem& rNumRuleItem = rTxtNode.GetTxtColl()->GetNumRule();
                        if ( rNumRuleItem.GetValue().Len() > 0 )
                        {
                            rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
                        }
                    }
                    const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
                    if ( pNumRuleAtTxtNode )
                    {
                        bNumRuleSet = true;
                        sNumRule = pNumRuleAtTxtNode->GetName();
                    }
                }
                break;
            }
            case RES_ATTRSET_CHG:
            {
                const SfxPoolItem* pItem = 0;
                const SwNumRule* pFormerNumRuleAtTxtNode =
                    rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
                if ( pFormerNumRuleAtTxtNode )
                {
                    sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
                }
                if ( dynamic_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) ==
                        SFX_ITEM_SET )
                {
                    rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
                    bNumRuleSet = true;
                }
                const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
                if ( pNumRuleAtTxtNode )
                {
                    sNumRule = pNumRuleAtTxtNode->GetName();
                }
                break;
            }
            case RES_PARATR_NUMRULE:
            {
                if ( rTxtNode.GetNodes().IsDocNodes() )
                {
                    const SwNumRule* pFormerNumRuleAtTxtNode =
                        rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
                    if ( pFormerNumRuleAtTxtNode )
                    {
                        sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
                    }
                    if ( pNewValue )
                    {
                        rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
                        bNumRuleSet = true;
                    }
                    const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
                    if ( pNumRuleAtTxtNode )
                    {
                        sNumRule = pNumRuleAtTxtNode->GetName();
                    }
                }
                break;
            }
        }
        if ( sNumRule != sOldNumRule )
        {
            if ( bNumRuleSet )
            {
                if ( sNumRule.Len() == 0 )
                {
                    rTxtNode.RemoveFromList();
                    if ( bParagraphStyleChanged )
                    {
                        SvUShortsSort aResetAttrsArray;
                        aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
                        aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
                        aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
                        aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
                        aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
                        SwPaM aPam( rTxtNode );
                        // suppress side effect "send data changed events"
                        rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
                                                       &aResetAttrsArray,
                                                       false );
                    }
                }
                else
                {
                    rTxtNode.RemoveFromList();
                    // If new list style is the outline style, apply outline
                    // level as the list level.
                    if ( sNumRule ==
                            String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) )
                    {
                        ASSERT( rTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle(),
                                "<HandleModifyAtTxtNode()> - text node with outline style, but its paragraph style is not assigned to outline style." );
                        const int nNewListLevel = rTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
                        if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
                        {
                            rTxtNode.SetAttrListLevel( nNewListLevel );
                        }
                    }
                    rTxtNode.AddToList();
                }
            }
            else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0>
            {
                rTxtNode.RemoveFromList();
                if ( bParagraphStyleChanged )
                {
                    SvUShortsSort aResetAttrsArray;
                    aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
                    aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
                    aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
                    aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
                    aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
                    SwPaM aPam( rTxtNode );
                    rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
                                                   &aResetAttrsArray,
                                                   false );
                    if ( dynamic_cast<const SfxUInt16Item &>(rTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 )
                    {
                        rTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
                    }
                }
            }
        }
        else if ( sNumRule.Len() > 0 && !rTxtNode.IsInList() )
        {
            rTxtNode.AddToList();
        }
    }
    // End of method <HandleModifyAtTxtNode>
}
// <--

void SwTxtNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
{
    bool bWasNotifiable = m_bNotifiable;
    m_bNotifiable = false;

	// Bug 24616/24617:
	// 		Modify ueberladen, damit beim Loeschen von Vorlagen diese
	// 		wieder richtig verwaltet werden (Outline-Numerierung!!)
	// 	Bug25481:
	//		bei Nodes im Undo nie _ChgTxtCollUpdateNum rufen.
	if( pOldValue && pNewValue && RES_FMT_CHG == pOldValue->Which() &&
		GetRegisteredIn() == ((SwFmtChg*)pNewValue)->pChangedFmt &&
		GetNodes().IsDocNodes() )
    {
		_ChgTxtCollUpdateNum(
						(SwTxtFmtColl*)((SwFmtChg*)pOldValue)->pChangedFmt,
						(SwTxtFmtColl*)((SwFmtChg*)pNewValue)->pChangedFmt );
    }

    //UUUU reset fill information
    if(maFillAttributes.get())
    {
        sal_uInt16 nWhich = pNewValue ? pNewValue->Which() : 0;
        bool bReset(RES_FMT_CHG == nWhich); // ..on format change (e.g. style changed)

        if(!bReset && RES_ATTRSET_CHG == nWhich) // ..on ItemChange from DrawingLayer FillAttributes
        {
            SfxItemIter aIter(*((SwAttrSetChg*)pNewValue)->GetChgSet());

            for(const SfxPoolItem* pItem = aIter.FirstItem(); pItem && !bReset; pItem = aIter.NextItem())
            {
                bReset = !IsInvalidItem(pItem) && pItem->Which() >= XATTR_FILL_FIRST && pItem->Which() <= XATTR_FILL_LAST;
            }
        }

        if(bReset)
        {
            maFillAttributes.reset();
        }
    }

    // --> OD 2008-03-27 #refactorlists#
    if ( !mbInSetOrResetAttr )
    {
        HandleModifyAtTxtNode( *this, pOldValue, pNewValue );
    }
    // <--

	SwCntntNode::Modify( pOldValue, pNewValue );

    SwDoc * pDoc = GetDoc();
    // --> OD 2005-11-02 #125329# - assure that text node is in document nodes array
    if ( pDoc && !pDoc->IsInDtor() && &pDoc->GetNodes() == &GetNodes() )
    // <--
    {
        pDoc->GetNodes().UpdateOutlineNode(*this);
    }

    m_bNotifiable = bWasNotifiable;

    if (pOldValue && (RES_REMOVE_UNO_OBJECT == pOldValue->Which()))
    {   // invalidate cached uno object
        SetXParagraph(::com::sun::star::uno::Reference<
                ::com::sun::star::text::XTextContent>(0));
    }
}

SwFmtColl* SwTxtNode::ChgFmtColl( SwFmtColl *pNewColl )
{
    ASSERT( pNewColl,"ChgFmtColl: Collectionpointer ist 0." );
    ASSERT( dynamic_cast< SwTxtFmtColl* >( pNewColl ), "ChgFmtColl: ist kein Text-Collectionpointer." );

    SwTxtFmtColl *pOldColl = GetTxtColl();
    if( pNewColl != pOldColl )
    {
        SetCalcHiddenCharFlags();
        SwCntntNode::ChgFmtColl( pNewColl );
        // --> OD 2008-03-27 #refactorlists#
//        NumRuleChgd();
#if OSL_DEBUG_LEVEL > 1
        ASSERT( !mbInSetOrResetAttr,
                "DEBUG ASSERTION - <SwTxtNode::ChgFmtColl(..)> called during <Set/ResetAttr(..)>" )
#endif
        if ( !mbInSetOrResetAttr )
        {
            SwFmtChg aTmp1( pOldColl );
            SwFmtChg aTmp2( pNewColl );
            HandleModifyAtTxtNode( *this, &aTmp1, &aTmp2  );
        }
        // <--

        //UUUU reset fill information on parent style change
        if(maFillAttributes.get())
        {
            maFillAttributes.reset();
        }
    }

    // nur wenn im normalen Nodes-Array
    if( GetNodes().IsDocNodes() )
    {
        _ChgTxtCollUpdateNum( pOldColl, static_cast<SwTxtFmtColl *>(pNewColl) );
    }

    GetNodes().UpdateOutlineNode(*this);

    return pOldColl;
}

SwNodeNum* SwTxtNode::CreateNum() const
{
    if ( !mpNodeNum )
    {
        // --> OD 2008-02-19 #refactorlists#
        mpNodeNum = new SwNodeNum( const_cast<SwTxtNode*>(this) );
        // <--
    }
    return mpNodeNum;
}

SwNumberTree::tNumberVector SwTxtNode::GetNumberVector() const
{
    if ( GetNum() )
    {
        return GetNum()->GetNumberVector();
    }
    else
    {
        SwNumberTree::tNumberVector aResult;
        return aResult;
    }
}

bool SwTxtNode::IsOutline() const
{
    bool bResult = false;

    //if ( GetOutlineLevel() != NO_NUMBERING )//#outline level,removed by zhaojianwei
    if ( GetAttrOutlineLevel() > 0 )            //<-end,zhaojianwei
    {
        bResult = !IsInRedlines();
    }
    else
    {
        const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : 0L );
        if ( pRule && pRule->IsOutlineRule() )
        {
            bResult = !IsInRedlines();
        }
    }

    return bResult;
}

bool SwTxtNode::IsOutlineStateChanged() const
{
    return IsOutline() != m_bLastOutlineState;
}

void SwTxtNode::UpdateOutlineState()
{
    m_bLastOutlineState = IsOutline();
}

//#outline level, zhaojianwei
int SwTxtNode::GetAttrOutlineLevel() const
{
	return ((const SfxUInt16Item &)GetAttr(RES_PARATR_OUTLINELEVEL)).GetValue();
}
void SwTxtNode::SetAttrOutlineLevel(int nLevel)
{
    ASSERT( 0 <= nLevel && nLevel <= MAXLEVEL ,"SwTxtNode: Level Out Of Range" );//#outline level,zhaojianwei
    if ( 0 <= nLevel && nLevel <= MAXLEVEL )
    {
        SetAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL,
                                static_cast<sal_uInt16>(nLevel) ) );
    }
}
//<-end

// --> OD 2008-11-19 #i70748#
bool SwTxtNode::IsEmptyListStyleDueToSetOutlineLevelAttr()
{
    return mbEmptyListStyleSetDueToSetOutlineLevelAttr;
}

void SwTxtNode::SetEmptyListStyleDueToSetOutlineLevelAttr()
{
    if ( !mbEmptyListStyleSetDueToSetOutlineLevelAttr )
    {
        SetAttr( SwNumRuleItem() );
        mbEmptyListStyleSetDueToSetOutlineLevelAttr = true;
    }
}

void SwTxtNode::ResetEmptyListStyleDueToResetOutlineLevelAttr()
{
    if ( mbEmptyListStyleSetDueToSetOutlineLevelAttr )
    {
        ResetAttr( RES_PARATR_NUMRULE );
        mbEmptyListStyleSetDueToSetOutlineLevelAttr = false;
    }
}
// <--


// --> OD 2008-02-27 #refactorlists#
void SwTxtNode::SetAttrListLevel( int nLevel )
{
    if ( nLevel < 0 || nLevel >= MAXLEVEL )
    {
        ASSERT( false,
                "<SwTxtNode::SetAttrListLevel()> - value of parameter <nLevel> is out of valid range" );
        return;
    }

    SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL,
                                    static_cast<sal_Int16>(nLevel) );
    SetAttr( aNewListLevelItem );
}
// <--
// --> OD 2008-02-27 #refactorlists#
bool SwTxtNode::HasAttrListLevel() const
{
    return GetpSwAttrSet() &&
           GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, sal_False ) == SFX_ITEM_SET;
}
// <--
// --> OD 2008-02-27 #refactorlists#
int SwTxtNode::GetAttrListLevel() const
{
    int nAttrListLevel = 0;

    const SfxInt16Item& aListLevelItem =
        dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_LEVEL ));
    nAttrListLevel = static_cast<int>(aListLevelItem.GetValue());

    return nAttrListLevel;
}
// <--

int SwTxtNode::GetActualListLevel() const
{
    return GetNum() ? GetNum()->GetLevelInListTree() : -1;
}

// --> OD 2008-02-25 #refactorlists#
void SwTxtNode::SetListRestart( bool bRestart )
{
//    CreateNum()->SetRestart(bRestart);
    if ( !bRestart )
    {
        // attribute not contained in paragraph style's attribute set. Thus,
        // it can be reset to the attribute pool default by resetting the attribute.
        ResetAttr( RES_PARATR_LIST_ISRESTART );
    }
    else
    {
        SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART,
                                       sal_True );
        SetAttr( aNewIsRestartItem );
    }
}

// --> OD 2008-02-25 #refactorlists#
bool SwTxtNode::IsListRestart() const
{
//    return GetNum() ? GetNum()->IsRestart() : false;
    const SfxBoolItem& aIsRestartItem =
        dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISRESTART ));

    return aIsRestartItem.GetValue() ? true : false;
}
// <--

/** Returns if the paragraph has a visible numbering or bullet.
    This includes all kinds of numbering/bullet/outlines.
    OD 2008-02-28 #newlistlevelattrs#
    The concrete list label string has to be checked, too.
 */
bool SwTxtNode::HasVisibleNumberingOrBullet() const
{
    bool bRet = false;

    const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
    if ( pRule && IsCountedInList())
    {
        // --> OD 2008-03-19 #i87154#
        // Correction of #newlistlevelattrs#:
        // The numbering type has to be checked for bullet lists.
        const SwNumFmt& rFmt = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() ));
        if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() ||
             pRule->MakeNumString( *(GetNum()) ).Len() > 0 )
        {
            bRet = true;
        }
        // <--
    }

    return bRet;
}

// --> OD 2008-02-25 #refactorlists#
void SwTxtNode::SetAttrListRestartValue( SwNumberTree::tSwNumTreeNumber nNumber )
{
//    CreateNum()->SetStart(nNumber);
    const bool bChanged( HasAttrListRestartValue()
                         ? GetAttrListRestartValue() != nNumber
                         : nNumber != USHRT_MAX );

    if ( bChanged || !HasAttrListRestartValue() )
    {
        if ( nNumber == USHRT_MAX )
        {
            ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
        }
        else
        {
            SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE,
                                                   static_cast<sal_Int16>(nNumber) );
            SetAttr( aNewListRestartValueItem );
        }
    }
}
// <--

// --> OD 2008-02-27 #refactorlists#
bool SwTxtNode::HasAttrListRestartValue() const
{
    return GetpSwAttrSet() &&
           GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False ) == SFX_ITEM_SET;
}
// <--
SwNumberTree::tSwNumTreeNumber SwTxtNode::GetAttrListRestartValue() const
{
    ASSERT( HasAttrListRestartValue(),
            "<SwTxtNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." );

    const SfxInt16Item& aListRestartValueItem =
        dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_RESTARTVALUE ));
    return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue());
}

// --> OD 2008-02-25 #refactorlists#
SwNumberTree::tSwNumTreeNumber SwTxtNode::GetActualListStartValue() const
{
//    return GetNum() ? GetNum()->GetStart() : 1;
    SwNumberTree::tSwNumTreeNumber nListRestartValue = 1;

    if ( IsListRestart() && HasAttrListRestartValue() )
    {
        nListRestartValue = GetAttrListRestartValue();
    }
    else
    {
        SwNumRule* pRule = GetNumRule();
        if ( pRule )
        {
            const SwNumFmt* pFmt =
                    pRule->GetNumFmt( static_cast<sal_uInt16>(GetAttrListLevel()) );
            if ( pFmt )
            {
                nListRestartValue = pFmt->GetStart();
            }
        }
    }

    return nListRestartValue;
}
// <--

bool SwTxtNode::IsNotifiable() const
{
    return m_bNotifiable && IsNotificationEnabled();
}

bool SwTxtNode::IsNotificationEnabled() const
{
    bool bResult = false;
    const SwDoc * pDoc = GetDoc();
    if( pDoc )
    {
        bResult = pDoc->IsInReading() || pDoc->IsInDtor() ? false : true;
    }
    return bResult;
}

// --> OD 2008-02-27 #refactorlists#
void SwTxtNode::SetCountedInList( bool bCounted )
{
    if ( bCounted )
    {
        // attribute not contained in paragraph style's attribute set. Thus,
        // it can be reset to the attribute pool default by resetting the attribute.
        ResetAttr( RES_PARATR_LIST_ISCOUNTED );
    }
    else
    {
        SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, sal_False );
        SetAttr( aIsCountedInListItem );
    }
}
// <--

bool SwTxtNode::IsCountedInList() const
{
    const SfxBoolItem& aIsCountedInListItem =
        dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISCOUNTED ));

    return aIsCountedInListItem.GetValue() ? true : false;
}

// --> OD 2008-03-13 #refactorlists#
void SwTxtNode::AddToList()
{
    if ( IsInList() )
    {
        ASSERT( false,
                "<SwTxtNode::AddToList()> - the text node is already added to a list. Serious defect -> please inform OD" );
        return;
    }

    const String sListId = GetListId();
    if ( sListId.Len() > 0 )
    {
        SwList* pList = GetDoc()->getListByName( sListId );
        if ( pList == 0 )
        {
            // Create corresponding list.
            SwNumRule* pNumRule = GetNumRule();
            if ( pNumRule )
            {
                pList = GetDoc()->createList( sListId, GetNumRule()->GetName() );
            }
        }
        ASSERT( pList != 0,
                "<SwTxtNode::AddToList()> - no list for given list id. Serious defect -> please inform OD" );
        if ( pList )
        {
            pList->InsertListItem( *CreateNum(), GetAttrListLevel() );
            mpList = pList;
        }
    }
}

void SwTxtNode::RemoveFromList()
{
    if ( IsInList() )
    {
        mpList->RemoveListItem( *mpNodeNum );
        mpList = 0;
        delete mpNodeNum;
        mpNodeNum = 0L;
    }
}

bool SwTxtNode::IsInList() const
{
    return GetNum() != 0 && GetNum()->GetParent() != 0;
}
// <--

bool SwTxtNode::IsFirstOfNumRule() const
{
    bool bResult = false;

    if ( GetNum() && GetNum()->GetNumRule())
        bResult = GetNum()->IsFirst();

    return bResult;
}

// --> OD 2008-02-20 #refactorlists#
void SwTxtNode::SetListId( const String sListId )
{
    const SfxStringItem& rListIdItem =
            dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
    if ( rListIdItem.GetValue() != sListId )
    {
        if ( sListId.Len() == 0 )
        {
            ResetAttr( RES_PARATR_LIST_ID );
        }
        else
        {
            SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
            SetAttr( aNewListIdItem );
        }
    }
}

String SwTxtNode::GetListId() const
{
    String sListId;

    const SfxStringItem& rListIdItem =
                dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
    sListId = rListIdItem.GetValue();

    // As long as no explicit list id attribute is set, use the list id of
    // the list, which has been created for the applied list style.
    if ( sListId.Len() == 0 )
    {
        SwNumRule* pRule = GetNumRule();
        if ( pRule )
        {
            sListId = pRule->GetDefaultListId();
//#if OSL_DEBUG_LEVEL > 1
//            ASSERT( false,
//                    "DEBUG ASSERTION: default list id of list style is applied." );
//#endif
//            // setting list id directly using <SwCntntNode::SetAttr(..)>,
//            // because no handling of this attribute set is needed and to avoid
//            // recursive calls of <SwTxtNode::SetAttr(..)>
//            SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
//            const_cast<SwTxtNode*>(this)->SwCntntNode::SetAttr( aNewListIdItem );
        }
    }

    return sListId;
}
// <--

/** Determines, if the list level indent attributes can be applied to the
    paragraph.

    OD 2008-01-17 #newlistlevelattrs#
    The list level indents can be applied to the paragraph under the one
    of following conditions:
    - the list style is directly applied to the paragraph and the paragraph
      has no own indent attributes.
    - the list style is applied to the paragraph through one of its paragraph
      styles, the paragraph has no own indent attributes and on the paragraph
      style hierarchy from the paragraph to the paragraph style with the
      list style no indent attributes are found.

    @author OD

    @return boolean
*/
bool SwTxtNode::AreListLevelIndentsApplicable() const
{
    bool bAreListLevelIndentsApplicable( true );

    if ( !GetNum() || !GetNum()->GetNumRule() )
    {
        // no list style applied to paragraph
        bAreListLevelIndentsApplicable = false;
    }
    else if ( HasSwAttrSet() &&
              GetpSwAttrSet()->GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
    {
        // paragraph has hard-set indent attributes
        bAreListLevelIndentsApplicable = false;
    }
    else if ( HasSwAttrSet() &&
              GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
    {
        // list style is directly applied to paragraph and paragraph has no
        // hard-set indent attributes
        bAreListLevelIndentsApplicable = true;
    }
    else
    {
        // list style is applied through one of the paragraph styles and
        // paragraph has no hard-set indent attributes

        // check, paragraph's
        const SwTxtFmtColl* pColl = GetTxtColl();
        while ( pColl )
        {
            if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
            {
                // indent attributes found in the paragraph style hierarchy.
                bAreListLevelIndentsApplicable = false;
                break;
            }

            if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
            {
                // paragraph style with the list style found and until now no
                // indent attributes are found in the paragraph style hierarchy.
                bAreListLevelIndentsApplicable = true;
                break;
            }

            pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom());
            ASSERT( pColl,
                    "<SwTxtNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." );
        }
    }

    return bAreListLevelIndentsApplicable;
}

/** Retrieves the list tab stop position, if the paragraph's list level defines
    one and this list tab stop has to merged into the tap stops of the paragraph

    OD 2008-01-17 #newlistlevelattrs#

    @author OD

    @param nListTabStopPosition
    output parameter - containing the list tab stop position

    @return boolean - indicating, if a list tab stop position is provided
*/
bool SwTxtNode::GetListTabStopPosition( long& nListTabStopPosition ) const
{
    bool bListTanStopPositionProvided( false );

    const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
    if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
    {
        const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) );
        if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT &&
             rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
        {
            bListTanStopPositionProvided = true;
            nListTabStopPosition = rFmt.GetListtabPos();

            if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
            {
                // tab stop position are treated to be relative to the "before text"
                // indent value of the paragraph. Thus, adjust <nListTabStopPos>.
                if ( AreListLevelIndentsApplicable() )
                {
                    nListTabStopPosition -= rFmt.GetIndentAt();
                }
                else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
                {
                    SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
                    nListTabStopPosition -= aItem.GetTxtLeft();
                }
            }
        }
    }

    return bListTanStopPositionProvided;
}

/** Retrieves the character following the list label, if the paragraph's
    list level defines one.

    OD 2008-01-17 #newlistlevelattrs#

    @author OD

    @return XubString - the list tab stop position
*/
XubString SwTxtNode::GetLabelFollowedBy() const
{
    XubString aLabelFollowedBy;

    const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
    if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
    {
        const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) );
        if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
        {
            switch ( rFmt.GetLabelFollowedBy() )
            {
                case SvxNumberFormat::LISTTAB:
                {
                    const sal_Unicode aTab = '\t';
                    aLabelFollowedBy.Insert( aTab, 0 );
                }
                break;
                case SvxNumberFormat::SPACE:
                {
                    const sal_Unicode aSpace = ' ';
                    aLabelFollowedBy.Insert( aSpace, 0 );
                }
                break;
                case SvxNumberFormat::NOTHING:
                {
                    // intentionally left blank.
                }
                break;
                default:
                {
                    ASSERT( false,
                            "<SwTxtNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" );
                }
            }
        }
    }

    return aLabelFollowedBy;
}

void SwTxtNode::CalcHiddenCharFlags() const
{
    xub_StrLen nStartPos;
    xub_StrLen nEndPos;
    // Update of the flags is done inside GetBoundsOfHiddenRange()
    SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos );
}

// --> FME 2004-06-08 #i12836# enhanced pdf export
bool SwTxtNode::IsHidden() const
{
    if ( HasHiddenParaField() || HasHiddenCharAttribute( true ) )
        return true;

    const SwSectionNode* pSectNd = FindSectionNode();
    if ( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
        return true;

    return false;
}
// <--

// --> OD 2008-03-13 #refactorlists#
namespace {
    // Helper class for special handling of setting attributes at text node:
    // In constructor an instance of the helper class recognize whose attributes
    // are set and perform corresponding actions before the intrinsic set of
    // attributes has been taken place.
    // In the destructor - after the attributes have been set at the text
    // node - corresponding actions are performed.
    // The following is handled:
    // (1) When the list style attribute - RES_PARATR_NUMRULE - is set,
    //     (A) list style attribute is empty -> the text node is removed from
    //         its list.
    //     (B) list style attribute is not empty
    //         (a) text node has no list style -> add text node to its list after
    //             the attributes have been set.
    //         (b) text node has list style -> change of list style is notified
    //             after the attributes have been set.
    // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed,
    //     the text node is removed from its current list before the attributes
    //     are set and added to its new list after the attributes have been set.
    // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set
    //     and changed after the attributes have been set
    // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set
    //     and changed after the attributes have been set
    // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE -
    //     is set and changed after the attributes have been set
    // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set
    //     and changed after the attributes have been set
    // (7) Set or Reset emtpy list style due to changed outline level - RES_PARATR_OUTLINELEVEL.
    class HandleSetAttrAtTxtNode
    {
        public:
            HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
                                    const SfxPoolItem& pItem );
            HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
                                    const SfxItemSet& rItemSet );
            ~HandleSetAttrAtTxtNode();

        private:
            SwTxtNode& mrTxtNode;
            bool mbAddTxtNodeToList;
            bool mbUpdateListLevel;
            bool mbUpdateListRestart;
            bool mbUpdateListCount;
            // --> OD 2008-11-19 #i70748#
            bool mbOutlineLevelSet;
            // <--
    };

    HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
                                                    const SfxPoolItem& pItem )
        : mrTxtNode( rTxtNode ),
          mbAddTxtNodeToList( false ),
          mbUpdateListLevel( false ),
          mbUpdateListRestart( false ),
          mbUpdateListCount( false ),
          // --> OD 2008-11-19 #i70748#
          mbOutlineLevelSet( false )
          // <--
    {
        switch ( pItem.Which() )
        {
            // handle RES_PARATR_NUMRULE
            case RES_PARATR_NUMRULE:
            {
                mrTxtNode.RemoveFromList();

                const SwNumRuleItem& pNumRuleItem =
                                dynamic_cast<const SwNumRuleItem&>(pItem);
                if ( pNumRuleItem.GetValue().Len() > 0 )
                {
                    mbAddTxtNodeToList = true;
                    // --> OD 2010-05-12 #i105562#
                    // 
                    mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
                    // <--
                }
            }
            break;

            // handle RES_PARATR_LIST_ID
            case RES_PARATR_LIST_ID:
            {
                const SfxStringItem& pListIdItem =
                                        dynamic_cast<const SfxStringItem&>(pItem);
                ASSERT( pListIdItem.GetValue().Len() > 0,
                        "<HandleSetAttrAtTxtNode(..)> - empty list id attribute not excepted. Serious defect -> please inform OD." );
                const String sListIdOfTxtNode = rTxtNode.GetListId();
                if ( pListIdItem.GetValue() != sListIdOfTxtNode )
                {
                    mbAddTxtNodeToList = true;
                    if ( mrTxtNode.IsInList() )
                    {
                        mrTxtNode.RemoveFromList();
                    }
                }
            }
            break;

            // handle RES_PARATR_LIST_LEVEL
            case RES_PARATR_LIST_LEVEL:
            {
                const SfxInt16Item& aListLevelItem =
                                    dynamic_cast<const SfxInt16Item&>(pItem);
                if ( aListLevelItem.GetValue() != mrTxtNode.GetAttrListLevel() )
                {
                    mbUpdateListLevel = true;
                }
            }
            break;

            // handle RES_PARATR_LIST_ISRESTART
            case RES_PARATR_LIST_ISRESTART:
            {
                const SfxBoolItem& aListIsRestartItem =
                                    dynamic_cast<const SfxBoolItem&>(pItem);
                if ( aListIsRestartItem.GetValue() !=
                                    (mrTxtNode.IsListRestart() ? sal_True : sal_False) )
                {
                    mbUpdateListRestart = true;
                }
            }
            break;

            // handle RES_PARATR_LIST_RESTARTVALUE
            case RES_PARATR_LIST_RESTARTVALUE:
            {
                const SfxInt16Item& aListRestartValueItem =
                                    dynamic_cast<const SfxInt16Item&>(pItem);
                if ( !mrTxtNode.HasAttrListRestartValue() ||
                     aListRestartValueItem.GetValue() != mrTxtNode.GetAttrListRestartValue() )
                {
                    mbUpdateListRestart = true;
                }
            }
            break;

            // handle RES_PARATR_LIST_ISCOUNTED
            case RES_PARATR_LIST_ISCOUNTED:
            {
                const SfxBoolItem& aIsCountedInListItem =
                                    dynamic_cast<const SfxBoolItem&>(pItem);
                if ( aIsCountedInListItem.GetValue() !=
                                    (mrTxtNode.IsCountedInList() ? sal_True : sal_False) )
                {
                    mbUpdateListCount = true;
                }
            }
            break;

            // --> OD 2008-11-19 #i70748#
            // handle RES_PARATR_OUTLINELEVEL
            case RES_PARATR_OUTLINELEVEL:
            {
                const SfxUInt16Item& aOutlineLevelItem =
                                    dynamic_cast<const SfxUInt16Item&>(pItem);
                if ( aOutlineLevelItem.GetValue() != mrTxtNode.GetAttrOutlineLevel() )
                {
                    mbOutlineLevelSet = true;
                }
            }
            break;
            // <--
        }

    }

    HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
                                                    const SfxItemSet& rItemSet )
        : mrTxtNode( rTxtNode ),
          mbAddTxtNodeToList( false ),
          mbUpdateListLevel( false ),
          mbUpdateListRestart( false ),
          mbUpdateListCount( false ),
          // --> OD 2008-11-19 #i70748#
          mbOutlineLevelSet( false )
          // <--
    {
        const SfxPoolItem* pItem = 0;
        // handle RES_PARATR_NUMRULE
        if ( rItemSet.GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == SFX_ITEM_SET )
        {
            mrTxtNode.RemoveFromList();

            const SwNumRuleItem* pNumRuleItem =
                            dynamic_cast<const SwNumRuleItem*>(pItem);
            if ( pNumRuleItem->GetValue().Len() > 0 )
            {
                mbAddTxtNodeToList = true;
                // --> OD 2008-11-19 #i70748#
                mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
                // <--
            }
        }

        // handle RES_PARATR_LIST_ID
        if ( rItemSet.GetItemState( RES_PARATR_LIST_ID, sal_False, &pItem ) == SFX_ITEM_SET )
        {
            const SfxStringItem* pListIdItem =
                                    dynamic_cast<const SfxStringItem*>(pItem);
            const String sListIdOfTxtNode = mrTxtNode.GetListId();
            if ( pListIdItem &&
                 pListIdItem->GetValue() != sListIdOfTxtNode )
            {
                mbAddTxtNodeToList = true;
                if ( mrTxtNode.IsInList() )
                {
                    mrTxtNode.RemoveFromList();
                }
            }
        }

        // handle RES_PARATR_LIST_LEVEL
        if ( rItemSet.GetItemState( RES_PARATR_LIST_LEVEL, sal_False, &pItem ) == SFX_ITEM_SET )
        {
            const SfxInt16Item* pListLevelItem =
                                dynamic_cast<const SfxInt16Item*>(pItem);
            if ( pListLevelItem->GetValue() != mrTxtNode.GetAttrListLevel() )
            {
                mbUpdateListLevel = true;
            }
        }

        // handle RES_PARATR_LIST_ISRESTART
        if ( rItemSet.GetItemState( RES_PARATR_LIST_ISRESTART, sal_False, &pItem ) == SFX_ITEM_SET )
        {
            const SfxBoolItem* pListIsRestartItem =
                                dynamic_cast<const SfxBoolItem*>(pItem);
            if ( pListIsRestartItem->GetValue() !=
                                    (mrTxtNode.IsListRestart() ? sal_True : sal_False) )
            {
                mbUpdateListRestart = true;
            }
        }

        // handle RES_PARATR_LIST_RESTARTVALUE
        if ( rItemSet.GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False, &pItem ) == SFX_ITEM_SET )
        {
            const SfxInt16Item* pListRestartValueItem =
                                dynamic_cast<const SfxInt16Item*>(pItem);
            if ( !mrTxtNode.HasAttrListRestartValue() ||
                 pListRestartValueItem->GetValue() != mrTxtNode.GetAttrListRestartValue() )
            {
                mbUpdateListRestart = true;
            }
        }

        // handle RES_PARATR_LIST_ISCOUNTED
        if ( rItemSet.GetItemState( RES_PARATR_LIST_ISCOUNTED, sal_False, &pItem ) == SFX_ITEM_SET )
        {
            const SfxBoolItem* pIsCountedInListItem =
                                dynamic_cast<const SfxBoolItem*>(pItem);
            if ( pIsCountedInListItem->GetValue() !=
                                (mrTxtNode.IsCountedInList() ? sal_True : sal_False) )
            {
                mbUpdateListCount = true;
            }
        }

        // --> OD 2008-11-19 #i70748#
        // handle RES_PARATR_OUTLINELEVEL
        if ( rItemSet.GetItemState( RES_PARATR_OUTLINELEVEL, sal_False, &pItem ) == SFX_ITEM_SET )
        {
            const SfxUInt16Item* pOutlineLevelItem =
                                dynamic_cast<const SfxUInt16Item*>(pItem);
            if ( pOutlineLevelItem->GetValue() != mrTxtNode.GetAttrOutlineLevel() )
            {
                mbOutlineLevelSet = true;
            }
        }
        // <--
    }

    HandleSetAttrAtTxtNode::~HandleSetAttrAtTxtNode()
    {
        if ( mbAddTxtNodeToList )
        {
            SwNumRule* pNumRuleAtTxtNode = mrTxtNode.GetNumRule();
            if ( pNumRuleAtTxtNode )
            {
                mrTxtNode.AddToList();
            }
        }
        else
        {
            if ( mbUpdateListLevel && mrTxtNode.IsInList() )
            {
                const_cast<SwNodeNum*>(mrTxtNode.GetNum())->SetLevelInListTree(
                                                    mrTxtNode.GetAttrListLevel() );
            }

            if ( mbUpdateListRestart && mrTxtNode.IsInList() )
            {
                SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
                pNodeNum->InvalidateMe();
                pNodeNum->NotifyInvalidSiblings();
            }

            if ( mbUpdateListCount && mrTxtNode.IsInList() )
            {
                const_cast<SwNodeNum*>(mrTxtNode.GetNum())->InvalidateAndNotifyTree();
            }
        }

        // --> OD 2008-11-19 #i70748#
        if ( mbOutlineLevelSet )
        {
            mrTxtNode.GetNodes().UpdateOutlineNode( mrTxtNode );
            if ( mrTxtNode.GetAttrOutlineLevel() == 0 )
            {
                mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
            }
            else
            {
                const SfxPoolItem* pItem = 0;
                if ( mrTxtNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE,
                                                            sal_True, &pItem )
                                                                != SFX_ITEM_SET )
                {
                    mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
                }
            }
        }
        // <--
    }
    // End of class <HandleSetAttrAtTxtNode>
}

sal_Bool SwTxtNode::SetAttr( const SfxPoolItem& pItem )
{
    const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
    mbInSetOrResetAttr = true;

    HandleSetAttrAtTxtNode aHandleSetAttr( *this, pItem );

    sal_Bool bRet = SwCntntNode::SetAttr( pItem );

    mbInSetOrResetAttr = bOldIsSetOrResetAttr;

    return bRet;
}

sal_Bool SwTxtNode::SetAttr( const SfxItemSet& rSet )
{
    const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
    mbInSetOrResetAttr = true;

    HandleSetAttrAtTxtNode aHandleSetAttr( *this, rSet );

    sal_Bool bRet = SwCntntNode::SetAttr( rSet );

    mbInSetOrResetAttr = bOldIsSetOrResetAttr;

    return bRet;
}

namespace {
    // Helper class for special handling of resetting attributes at text node:
    // In constructor an instance of the helper class recognize whose attributes
    // are reset and perform corresponding actions before the intrinsic reset of
    // attributes has been taken place.
    // In the destructor - after the attributes have been reset at the text
    // node - corresponding actions are performed.
    // The following is handled:
    // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset,
    //     the text is removed from its list before the attributes have been reset.
    // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset,
    //     the text is removed from its list before the attributes have been reset.
    // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset.
    // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset.
    // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset.
    // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset.
    // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset.
    class HandleResetAttrAtTxtNode
    {
        public:
            HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
                                      const sal_uInt16 nWhich1,
                                      const sal_uInt16 nWhich2 );
            HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
                                      const SvUShorts& rWhichArr );
            HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode );

            ~HandleResetAttrAtTxtNode();

        private:
            SwTxtNode& mrTxtNode;
            bool mbListStyleOrIdReset;
            bool mbUpdateListLevel;
            bool mbUpdateListRestart;
            bool mbUpdateListCount;
    };

    HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
                                                        const sal_uInt16 nWhich1,
                                                        const sal_uInt16 nWhich2 )
        : mrTxtNode( rTxtNode ),
          mbListStyleOrIdReset( false ),
          mbUpdateListLevel( false ),
          mbUpdateListRestart( false ),
          mbUpdateListCount( false )
    {
        bool bRemoveFromList( false );
        if ( nWhich2 != 0 && nWhich2 > nWhich1 )
        {
            // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
            if ( nWhich1 <= RES_PARATR_NUMRULE && RES_PARATR_NUMRULE <= nWhich2 )
            {
                bRemoveFromList = mrTxtNode.GetNumRule() != 0;
                mbListStyleOrIdReset = true;
            }
            else if ( nWhich1 <= RES_PARATR_LIST_ID && RES_PARATR_LIST_ID <= nWhich2 )
            {
                bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
                    mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET;
                // --> OD 2008-10-20 #i92898#
                mbListStyleOrIdReset = true;
                // <--
            }

            if ( !bRemoveFromList )
            {
                // RES_PARATR_LIST_LEVEL
                mbUpdateListLevel = ( nWhich1 <= RES_PARATR_LIST_LEVEL &&
                                      RES_PARATR_LIST_LEVEL <= nWhich2 &&
                                      mrTxtNode.HasAttrListLevel() );

                // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
                mbUpdateListRestart =
                    ( nWhich1 <= RES_PARATR_LIST_ISRESTART && RES_PARATR_LIST_ISRESTART <= nWhich2 &&
                      mrTxtNode.IsListRestart() ) ||
                    ( nWhich1 <= RES_PARATR_LIST_RESTARTVALUE && RES_PARATR_LIST_RESTARTVALUE <= nWhich2 &&
                      mrTxtNode.HasAttrListRestartValue() );

                // RES_PARATR_LIST_ISCOUNTED
                mbUpdateListCount =
                    ( nWhich1 <= RES_PARATR_LIST_ISCOUNTED && RES_PARATR_LIST_ISCOUNTED <= nWhich2 &&
                      !mrTxtNode.IsCountedInList() );
            }

            // --> OD 2008-11-19 #i70748#
            // RES_PARATR_OUTLINELEVEL
            if ( nWhich1 <= RES_PARATR_OUTLINELEVEL && RES_PARATR_OUTLINELEVEL <= nWhich2 )
            {
                mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
            }
            // <--
        }
        else
        {
            // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
            if ( nWhich1 == RES_PARATR_NUMRULE )
            {
                bRemoveFromList = mrTxtNode.GetNumRule() != 0;
                mbListStyleOrIdReset = true;
            }
            else if ( nWhich1 == RES_PARATR_LIST_ID )
            {
                bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
                    mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET;
                // --> OD 2008-10-20 #i92898#
                mbListStyleOrIdReset = true;
                // <--
            }
            // --> OD 2008-11-19 #i70748#
            // RES_PARATR_OUTLINELEVEL
            else if ( nWhich1 == RES_PARATR_OUTLINELEVEL )
            {
                mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
            }
            // <--

            if ( !bRemoveFromList )
            {
                // RES_PARATR_LIST_LEVEL
                mbUpdateListLevel = nWhich1 == RES_PARATR_LIST_LEVEL &&
                                    mrTxtNode.HasAttrListLevel();

                // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
                mbUpdateListRestart = ( nWhich1 == RES_PARATR_LIST_ISRESTART &&
                                        mrTxtNode.IsListRestart() ) ||
                                      ( nWhich1 == RES_PARATR_LIST_RESTARTVALUE &&
                                        mrTxtNode.HasAttrListRestartValue() );

                // RES_PARATR_LIST_ISCOUNTED
                mbUpdateListCount = nWhich1 == RES_PARATR_LIST_ISCOUNTED &&
                                    !mrTxtNode.IsCountedInList();
            }
        }

        if ( bRemoveFromList && mrTxtNode.IsInList() )
        {
            mrTxtNode.RemoveFromList();
        }
    }

    HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
                                                        const SvUShorts& rWhichArr )
        : mrTxtNode( rTxtNode ),
          mbListStyleOrIdReset( false ),
          mbUpdateListLevel( false ),
          mbUpdateListRestart( false ),
          mbUpdateListCount( false )
    {
        bool bRemoveFromList( false );
        {
            const sal_uInt16 nEnd = rWhichArr.Count();
            for ( sal_uInt16 n = 0; n < nEnd; ++n )
            {
                // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
                if ( rWhichArr[ n ] == RES_PARATR_NUMRULE )
                {
                    bRemoveFromList = bRemoveFromList ||
                                      mrTxtNode.GetNumRule() != 0;
                    mbListStyleOrIdReset = true;
                }
                else if ( rWhichArr[ n ] == RES_PARATR_LIST_ID )
                {
                    bRemoveFromList = bRemoveFromList ||
                        ( mrTxtNode.GetpSwAttrSet() &&
                          mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET );
                    // --> OD 2008-10-20 #i92898#
                    mbListStyleOrIdReset = true;
                    // <--
                }
                // --> OD 2008-11-19 #i70748#
                // RES_PARATR_OUTLINELEVEL
                else if ( rWhichArr[ n ] == RES_PARATR_OUTLINELEVEL )
                {
                    mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
                }
                // <--

                if ( !bRemoveFromList )
                {
                    // RES_PARATR_LIST_LEVEL
                    mbUpdateListLevel = mbUpdateListLevel ||
                                        ( rWhichArr[ n ] == RES_PARATR_LIST_LEVEL &&
                                          mrTxtNode.HasAttrListLevel() );

                    // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
                    mbUpdateListRestart = mbUpdateListRestart ||
                                          ( rWhichArr[ n ] == RES_PARATR_LIST_ISRESTART &&
                                            mrTxtNode.IsListRestart() ) ||
                                          ( rWhichArr[ n ] == RES_PARATR_LIST_RESTARTVALUE &&
                                            mrTxtNode.HasAttrListRestartValue() );

                    // RES_PARATR_LIST_ISCOUNTED
                    mbUpdateListCount = mbUpdateListCount ||
                                        ( rWhichArr[ n ] == RES_PARATR_LIST_ISCOUNTED &&
                                          !mrTxtNode.IsCountedInList() );
                }
            }
        }

        if ( bRemoveFromList && mrTxtNode.IsInList() )
        {
            mrTxtNode.RemoveFromList();
        }
    }

    HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode )
        : mrTxtNode( rTxtNode ),
          mbListStyleOrIdReset( false ),
          mbUpdateListLevel( false ),
          mbUpdateListRestart( false ),
          mbUpdateListCount( false )
    {
        mbListStyleOrIdReset = true;
        if ( rTxtNode.IsInList() )
        {
            rTxtNode.RemoveFromList();
        }
        // --> OD 2008-11-19 #i70748#
        mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
        // <--
    }

    HandleResetAttrAtTxtNode::~HandleResetAttrAtTxtNode()
    {
        if ( mbListStyleOrIdReset && !mrTxtNode.IsInList() )
        {
            // check, if in spite of the reset of the list style or the list id
            // the paragraph still has to be added to a list.
            if ( mrTxtNode.GetNumRule() &&
                 mrTxtNode.GetListId().Len() > 0 )
            {
                // --> OD 2009-01-14 #i96062#
                // If paragraph has no list level attribute set and list style
                // is the outline style, apply outline level as the list level.
                if ( !mrTxtNode.HasAttrListLevel() &&
                     mrTxtNode.GetNumRule()->GetName() ==
                        String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) &&
                     mrTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() )
                {
                    int nNewListLevel = mrTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
                    if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
                    {
                        mrTxtNode.SetAttrListLevel( nNewListLevel );
                    }
                }
                // <--
                mrTxtNode.AddToList();
            }
            // --> OD 2008-11-19 #i70748#
            // --> OD 2010-05-12 #i105562#
            else if ( mrTxtNode.GetpSwAttrSet() &&
                      dynamic_cast<const SfxUInt16Item &>(mrTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 )
            {
                mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
            }
            // <--
        }

        if ( mrTxtNode.IsInList() )
        {
            if ( mbUpdateListLevel )
            {
                SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
                pNodeNum->SetLevelInListTree( mrTxtNode.GetAttrListLevel() );
            }

            if ( mbUpdateListRestart )
            {
                SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
                pNodeNum->InvalidateMe();
                pNodeNum->NotifyInvalidSiblings();
            }

            if ( mbUpdateListCount )
            {
                SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
                pNodeNum->InvalidateAndNotifyTree();
            }
        }
    }
    // End of class <HandleResetAttrAtTxtNode>
}

sal_Bool SwTxtNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
{
    const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
    mbInSetOrResetAttr = true;

    HandleResetAttrAtTxtNode aHandleResetAttr( *this, nWhich1, nWhich2 );

    sal_Bool bRet = SwCntntNode::ResetAttr( nWhich1, nWhich2 );

    mbInSetOrResetAttr = bOldIsSetOrResetAttr;

    return bRet;
}

sal_Bool SwTxtNode::ResetAttr( const SvUShorts& rWhichArr )
{
    const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
    mbInSetOrResetAttr = true;

    HandleResetAttrAtTxtNode aHandleResetAttr( *this, rWhichArr );

    sal_Bool bRet = SwCntntNode::ResetAttr( rWhichArr );

    mbInSetOrResetAttr = bOldIsSetOrResetAttr;

    return bRet;
}

sal_uInt16 SwTxtNode::ResetAllAttr()
{
    const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
    mbInSetOrResetAttr = true;

    HandleResetAttrAtTxtNode aHandleResetAttr( *this );

    sal_uInt16 nRet = SwCntntNode::ResetAllAttr();

    mbInSetOrResetAttr = bOldIsSetOrResetAttr;

    return nRet;
}
// <--

// sw::Metadatable
::sfx2::IXmlIdRegistry& SwTxtNode::GetRegistry()
{
    return GetDoc()->GetXmlIdRegistry();
}

bool SwTxtNode::IsInClipboard() const
{
    return GetDoc()->IsClipBoard();
}

bool SwTxtNode::IsInUndo() const
{
    return GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
}

bool SwTxtNode::IsInContent() const
{
    return !GetDoc()->IsInHeaderFooter( SwNodeIndex(*this) );
}

void SwTxtNode::SwClientNotify( const SwModify& rModify, const SfxHint& rHint )
{   
    const SwAttrHint* pHint = dynamic_cast<const SwAttrHint*>(&rHint);
    if ( pHint && pHint->GetId() == RES_CONDTXTFMTCOLL && &rModify == GetRegisteredIn() )
        ChkCondColl();
}

#include <unoparagraph.hxx>

uno::Reference< rdf::XMetadatable >
SwTxtNode::MakeUnoObject()
{
    const uno::Reference<rdf::XMetadatable> xMeta(
            SwXParagraph::CreateXParagraph(*GetDoc(), *this), uno::UNO_QUERY);
    return xMeta;
}

//Bug 120881:Modify here for Directly Page Numbering
bool SwTxtNode::HasPageNumberField()
{
    const xub_StrLen nEnd = Len();
    for( xub_StrLen nStart = 0; nStart < nEnd; ++nStart )
    {
        const SwTxtAttr* pTxtAttr = GetTxtAttrAt( nStart, RES_TXTATR_FIELD );
        if ( pTxtAttr == NULL )
        {
            continue;
        }
        const SwField* pSwField = pTxtAttr->GetFmtFld().GetField();
        const SwFieldType* pType = pSwField
            ? pSwField->GetTyp()
            : NULL;
        if ( pType && pType->Which() == RES_PAGENUMBERFLD )
        {
            return true;
        }
    }
    return false;

}
//Bug 120881(End)

//UUUU
drawinglayer::attribute::SdrAllFillAttributesHelperPtr SwTxtNode::getSdrAllFillAttributesHelper() const
{
    // create SdrAllFillAttributesHelper on demand
    if(!maFillAttributes.get())
    {
        const_cast< SwTxtNode* >(this)->maFillAttributes.reset(new drawinglayer::attribute::SdrAllFillAttributesHelper(GetSwAttrSet()));
    }

    return maFillAttributes;
}

// eof
