/**************************************************************
 * 
 * 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 <editeng/frmdiritem.hxx>
#include <editeng/protitem.hxx>
#include <com/sun/star/i18n/CharacterIteratorMode.hdl>
#include <fmtcntnt.hxx>
#include <fmtanchr.hxx>
#include <frmfmt.hxx>
#include <txtftn.hxx>
#include <ftnfrm.hxx>
#include <doc.hxx>
#include <docary.hxx>
#include <node.hxx>
#include <ndindex.hxx>
#include <numrule.hxx>
#include <swtable.hxx>
#include <ndtxt.hxx>
#include <pam.hxx>
#include <swcache.hxx>
#include <section.hxx>
#include <cntfrm.hxx>
#include <flyfrm.hxx>
#include <txtfrm.hxx>
#include <tabfrm.hxx>  // SwTabFrm
#include <viewsh.hxx>
#include <paratr.hxx>
#include <ftnidx.hxx>
#include <fmtftn.hxx>
#include <fmthdft.hxx>
#include <frmatr.hxx>
#include <fmtautofmt.hxx>
#include <frmtool.hxx>
#include <pagefrm.hxx>
#include <node2lay.hxx>
#include <pagedesc.hxx>
#include <fmtpdsc.hxx>
#include <breakit.hxx>
#include <crsskip.hxx>
#include <SwStyleNameMapper.hxx>
#include <scriptinfo.hxx>
#include <rootfrm.hxx>
#include <istyleaccess.hxx>
#include <IDocumentListItems.hxx>
#include <switerator.hxx>
#include "ndole.hxx"

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

TYPEINIT2( SwCntntNode, SwModify, SwIndexReg )

/*
 * Some local helper functions for the attribute set handle of a content node.
 * Since the attribute set of a content node may not be modified directly,
 * we always have to create a new SwAttrSet, do the modifications, and get
 * a new handle from the style access
 */

namespace AttrSetHandleHelper
{

void GetNewAutoStyle( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
                      const SwCntntNode& rNode,
                      SwAttrSet& rNewAttrSet )
{
    const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(mrpAttrSet.get());
	if( rNode.GetModifyAtAttr() )
        const_cast<SwAttrSet*>(pAttrSet)->SetModifyAtAttr( 0 );
    IStyleAccess& rSA = pAttrSet->GetPool()->GetDoc()->GetIStyleAccess();
    mrpAttrSet = rSA.getAutomaticStyle( rNewAttrSet, rNode.IsTxtNode() ?
                                                     IStyleAccess::AUTO_STYLE_PARA :
                                                     IStyleAccess::AUTO_STYLE_NOTXT );
    const bool bSetModifyAtAttr = ((SwAttrSet*)mrpAttrSet.get())->SetModifyAtAttr( &rNode );
    rNode.SetModifyAtAttr( bSetModifyAtAttr );
}


void SetParent( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
                const SwCntntNode& rNode,
                const SwFmt* pParentFmt,
                const SwFmt* pConditionalFmt )
{
    const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(mrpAttrSet.get());
    ASSERT( pAttrSet, "no SwAttrSet" )
    ASSERT( pParentFmt || !pConditionalFmt, "ConditionalFmt without ParentFmt?" )

    const SwAttrSet* pParentSet = pParentFmt ? &pParentFmt->GetAttrSet() : 0;

    if ( pParentSet != pAttrSet->GetParent() )
    {
        SwAttrSet aNewSet( *pAttrSet );
        aNewSet.SetParent( pParentSet );
        aNewSet.ClearItem( RES_FRMATR_STYLE_NAME );
        aNewSet.ClearItem( RES_FRMATR_CONDITIONAL_STYLE_NAME );
        String sVal;

        if ( pParentFmt )
        {
            SwStyleNameMapper::FillProgName( pParentFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
            const SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal );
            aNewSet.Put( aAnyFmtColl );

            if ( pConditionalFmt != pParentFmt )
                SwStyleNameMapper::FillProgName( pConditionalFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );

            const SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal );
            aNewSet.Put( aFmtColl );
        }

        GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
    }
}

const SfxPoolItem* Put( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
                        const SwCntntNode& rNode,
                        const SfxPoolItem& rAttr )
{
    SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
    const SfxPoolItem* pRet = aNewSet.Put( rAttr );
    if ( pRet )
        GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
    return pRet;
}

int Put( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, const SwCntntNode& rNode,
         const SfxItemSet& rSet )
{
    SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );

    // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
    SfxItemSet* pStyleNames = 0;
    if ( SFX_ITEM_SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, sal_False ) )
    {
        pStyleNames = new SfxItemSet( *aNewSet.GetPool(), RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME );
        pStyleNames->Put( aNewSet );
    }
    // <--

    const int nRet = aNewSet.Put( rSet );

    // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
    if ( pStyleNames )
    {
        aNewSet.Put( *pStyleNames );
        delete pStyleNames;
    }
    // <--

    if ( nRet )
        GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );

    return nRet;
}

int Put_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
            const SwCntntNode& rNode, const SfxPoolItem& rAttr,
            SwAttrSet* pOld, SwAttrSet* pNew )
{
    SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );

    // for a correct broadcast, we need to do a SetModifyAtAttr with the items
    // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
    if( rNode.GetModifyAtAttr() )
        aNewSet.SetModifyAtAttr( &rNode );

    const int nRet = aNewSet.Put_BC( rAttr, pOld, pNew );

    if ( nRet )
        GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );

    return nRet;
}

int Put_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
            const SwCntntNode& rNode, const SfxItemSet& rSet,
            SwAttrSet* pOld, SwAttrSet* pNew )
{
    SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );

    // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
    SfxItemSet* pStyleNames = 0;
    if ( SFX_ITEM_SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, sal_False ) )
    {
        pStyleNames = new SfxItemSet( *aNewSet.GetPool(), RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME );
        pStyleNames->Put( aNewSet );
    }
    // <--

    // for a correct broadcast, we need to do a SetModifyAtAttr with the items
    // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
	if( rNode.GetModifyAtAttr() )
        aNewSet.SetModifyAtAttr( &rNode );

    const int nRet = aNewSet.Put_BC( rSet, pOld, pNew );

    // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
    if ( pStyleNames )
    {
        aNewSet.Put( *pStyleNames );
        delete pStyleNames;
    }
    // <--

    if ( nRet )
        GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );

    return nRet;
}

sal_uInt16 ClearItem_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
                     const SwCntntNode& rNode, sal_uInt16 nWhich,
                     SwAttrSet* pOld, SwAttrSet* pNew )
{
    SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
	if( rNode.GetModifyAtAttr() )
        aNewSet.SetModifyAtAttr( &rNode );
    const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich, pOld, pNew );
    if ( nRet )
        GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
    return nRet;
}

sal_uInt16 ClearItem_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
                     const SwCntntNode& rNode,
                     sal_uInt16 nWhich1, sal_uInt16 nWhich2,
                     SwAttrSet* pOld, SwAttrSet* pNew )
{
    SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
	if( rNode.GetModifyAtAttr() )
        aNewSet.SetModifyAtAttr( &rNode );
    const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich1, nWhich2, pOld, pNew );
    if ( nRet )
        GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
    return nRet;
}

}

/*******************************************************************
|*
|*	SwNode::GetSectionLevel
|*
|*	Beschreibung
|*		Die Funktion liefert den Sectionlevel an der durch
|*		aIndex bezeichneten Position.
|*
|*		Die Logik ist wie folgt:   ( S -> Start, E -> End, C -> CntntNode)
|*			Level 	0		E
|*					1 	S  E
|*					2  	 SC
|*
|*		alle EndNodes der GrundSection haben den Level 0
|*		alle StartNodes der GrundSection haben den Level 1
|*
|*	Ersterstellung
|*		VER0100 vb 901214
|*
|*	Aenderung:	JP	11.08.93
|*		keine Rekursion mehr !!
|*
*******************************************************************/


sal_uInt16 SwNode::GetSectionLevel() const
{
	// EndNode einer Grund-Section ?? diese sind immer 0 !!
	if( IsEndNode() && 0 == pStartOfSection->StartOfSectionIndex() )
		return 0;

	sal_uInt16 nLevel;
	const SwNode* pNode = IsStartNode() ? this : pStartOfSection;
	for( nLevel = 1; 0 != pNode->StartOfSectionIndex(); ++nLevel )
		pNode = pNode->pStartOfSection;
	return IsEndNode() ? nLevel-1 : nLevel;
}

/*******************************************************************
|*
|*	SwNode::SwNode
|*
|*	Beschreibung
|*		Konstruktor; dieser fuegt einen Node in das Array rNodes
|*		an der Position rWhere ein. Dieser bekommt als
|*		theEndOfSection den EndOfSection-Index des Nodes
|*		unmittelbar vor ihm. Falls er sich an der Position 0
|*		innerhalb des variablen Arrays befindet, wird
|*		theEndOfSection 0 (der neue selbst).
|*
|*	Parameter
|*		IN
|*		rNodes bezeichnet das variable Array, in das der Node
|*		eingefuegt werden soll
|*		IN
|*		rWhere bezeichnet die Position innerhalb dieses Arrays,
|*		an der der Node eingefuegt werden soll
|*
|*	Ersterstellung
|*		VER0100 vb 901214
|*
|*	Stand
|*		VER0100 vb 901214
|*
*******************************************************************/

#ifdef DBG_UTIL
long SwNode::nSerial = 0;
#endif

SwNode::SwNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType )
	: nNodeType( nNdType ), pStartOfSection( 0 )
{
    bSetNumLSpace = bIgnoreDontExpand = sal_False;
	nAFmtNumLvl = 0;

	SwNodes& rNodes = (SwNodes&)rWhere.GetNodes();
	SwNode* pInsNd = this; 		// der MAC kann this nicht einfuegen !!
	if( rWhere.GetIndex() )
	{
		SwNode* pNd = rNodes[ rWhere.GetIndex() -1 ];
        rNodes.InsertNode( pInsNd, rWhere );
		if( 0 == ( pStartOfSection = pNd->GetStartNode()) )
		{
			pStartOfSection = pNd->pStartOfSection;
			if( pNd->GetEndNode() )		// EndNode ? Section ueberspringen!
			{
				pNd = pStartOfSection;
				pStartOfSection = pNd->pStartOfSection;
			}
		}
	}
	else
	{
        rNodes.InsertNode( pInsNd, rWhere );
		pStartOfSection = (SwStartNode*)this;
	}

#ifdef DBG_UTIL
    nMySerial = nSerial;
    nSerial++;
#endif
}

SwNode::SwNode( SwNodes& rNodes, sal_uLong nPos, const sal_uInt8 nNdType )
	: nNodeType( nNdType ), pStartOfSection( 0 )
{
    bSetNumLSpace = bIgnoreDontExpand = sal_False;
	nAFmtNumLvl = 0;

	SwNode* pInsNd = this; 		// der MAC kann this nicht einfuegen !!
	if( nPos )
	{
		SwNode* pNd = rNodes[ nPos - 1 ];
        rNodes.InsertNode( pInsNd, nPos );
		if( 0 == ( pStartOfSection = pNd->GetStartNode()) )
		{
			pStartOfSection = pNd->pStartOfSection;
			if( pNd->GetEndNode() )		// EndNode ? Section ueberspringen!
			{
				pNd = pStartOfSection;
				pStartOfSection = pNd->pStartOfSection;
			}
		}
	}
	else
	{
        rNodes.InsertNode( pInsNd, nPos );
		pStartOfSection = (SwStartNode*)this;
	}

#ifdef DBG_UTIL
    nMySerial = nSerial;
    nSerial++;
#endif
}

SwNode::~SwNode()
{
}

// suche den TabellenNode, in dem dieser steht. Wenn in keiner
// Tabelle wird 0 returnt.


SwTableNode* SwNode::FindTableNode()
{
	if( IsTableNode() )
		return GetTableNode();
	SwStartNode* pTmp = pStartOfSection;
	while( !pTmp->IsTableNode() && pTmp->GetIndex() )
#if defined( ALPHA ) && defined( UNX )
		pTmp = ((SwNode*)pTmp)->pStartOfSection;
#else
		pTmp = pTmp->pStartOfSection;
#endif
	return pTmp->GetTableNode();
}


// liegt der Node im Sichtbarenbereich der Shell ?
sal_Bool SwNode::IsInVisibleArea( ViewShell* pSh ) const
{
	sal_Bool bRet = sal_False;
	const SwCntntNode* pNd;

	if( ND_STARTNODE & nNodeType )
	{
		SwNodeIndex aIdx( *this );
		pNd = GetNodes().GoNext( &aIdx );
	}
	else if( ND_ENDNODE & nNodeType )
	{
		SwNodeIndex aIdx( *EndOfSectionNode() );
		pNd = GetNodes().GoPrevious( &aIdx );
	}
	else
		pNd = GetCntntNode();

	if( !pSh )
		// dann die Shell vom Doc besorgen:
		GetDoc()->GetEditShell( &pSh );

    if( pSh )
    {
	    const SwFrm* pFrm;
	    if( pNd && 0 != ( pFrm = pNd->getLayoutFrm( pSh->GetLayout(), 0, 0, sal_False ) ) )
	    {

			if ( pFrm->IsInTab() )
				pFrm = pFrm->FindTabFrm();

			if( !pFrm->IsValid() )
				do
				{	pFrm = pFrm->FindPrev();
				} while ( pFrm && !pFrm->IsValid() );

			if( !pFrm || pSh->VisArea().IsOver( pFrm->Frm() ) )
				bRet = sal_True;
		}
	}

	return bRet;
}

sal_Bool SwNode::IsInProtectSect() const
{
	const SwNode* pNd = ND_SECTIONNODE == nNodeType ? pStartOfSection : this;
	const SwSectionNode* pSectNd = pNd->FindSectionNode();
	return pSectNd && pSectNd->GetSection().IsProtectFlag();
}

	// befindet sich der Node in irgendetwas geschuetzten ?
	// (Bereich/Rahmen/Tabellenzellen/... incl. des Ankers bei
	//	Rahmen/Fussnoten/..)
sal_Bool SwNode::IsProtect() const
{
	const SwNode* pNd = ND_SECTIONNODE == nNodeType ? pStartOfSection : this;
	const SwStartNode* pSttNd = pNd->FindSectionNode();
	if( pSttNd && ((SwSectionNode*)pSttNd)->GetSection().IsProtectFlag() )
		return sal_True;

	if( 0 != ( pSttNd = FindTableBoxStartNode() ) )
	{
		SwCntntFrm* pCFrm;
		if( IsCntntNode() && 0 != (pCFrm = ((SwCntntNode*)this)->getLayoutFrm( GetDoc()->GetCurrentLayout() ) ))
			return pCFrm->IsProtected();

		const SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
										GetTblBox( pSttNd->GetIndex() );
        //Robust #149568
		if( pBox && pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
			return sal_True;
	}

	SwFrmFmt* pFlyFmt = GetFlyFmt();
	if( pFlyFmt )
	{
		if( pFlyFmt->GetProtect().IsCntntProtected() )
			return sal_True;
		const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
		return rAnchor.GetCntntAnchor()
				? rAnchor.GetCntntAnchor()->nNode.GetNode().IsProtect()
				: sal_False;
	}

	if( 0 != ( pSttNd = FindFootnoteStartNode() ) )
	{
		const SwTxtFtn* pTFtn = GetDoc()->GetFtnIdxs().SeekEntry(
								SwNodeIndex( *pSttNd ) );
		if( pTFtn )
			return pTFtn->GetTxtNode().IsProtect();
	}

	return sal_False;
}

	// suche den PageDesc, mit dem dieser Node formatiert ist. Wenn das
	// Layout vorhanden ist wird ueber das gesucht, ansonsten gibt es nur
	// die harte Tour ueber die Nodes nach vorne suchen!!
const SwPageDesc* SwNode::FindPageDesc( sal_Bool bCalcLay,
                                        sal_uInt32* pPgDescNdIdx ) const
{
    // OD 18.03.2003 #106329#
    if ( !GetNodes().IsDocNodes() )
    {
        return 0;
    }

    const SwPageDesc* pPgDesc = 0;

    const SwCntntNode* pNode;
    if( ND_STARTNODE & nNodeType )
    {
        SwNodeIndex aIdx( *this );
        pNode = GetNodes().GoNext( &aIdx );
    }
    else if( ND_ENDNODE & nNodeType )
    {
        SwNodeIndex aIdx( *EndOfSectionNode() );
        pNode = GetNodes().GoPrevious( &aIdx );
    }
    else
    {
        pNode = GetCntntNode();
        if( pNode )
            pPgDesc = ((SwFmtPageDesc&)pNode->GetAttr( RES_PAGEDESC )).GetPageDesc();
    }

    // geht es uebers Layout?
    if( !pPgDesc )
    {
        const SwFrm* pFrm;
        const SwPageFrm* pPage;
        if( pNode && 0 != ( pFrm = pNode->getLayoutFrm( pNode->GetDoc()->GetCurrentLayout(), 0, 0, bCalcLay ) ) &&
            0 != ( pPage = pFrm->FindPageFrm() ) )
        {
            pPgDesc = pPage->GetPageDesc();
            // OD 18.03.2003 #106329#
            if ( pPgDescNdIdx )
            {
                *pPgDescNdIdx = pNode->GetIndex();
            }
        }
    }

    if( !pPgDesc )
    {
        // dann also uebers Nodes-Array
        const SwDoc* pDoc = GetDoc();
        const SwNode* pNd = this;
        const SwStartNode* pSttNd;
        if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() &&
            0 != ( pSttNd = pNd->FindFlyStartNode() ) )
        {
            // dann erstmal den richtigen Anker finden
            const SwFrmFmt* pFmt = 0;
            const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
            sal_uInt16 n;

            for( n = 0; n < rFmts.Count(); ++n )
            {
                SwFrmFmt* pFrmFmt = rFmts[ n ];
                const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
                if( rCntnt.GetCntntIdx() &&
                    &rCntnt.GetCntntIdx()->GetNode() == (SwNode*)pSttNd )
                {
                    pFmt = pFrmFmt;
                    break;
                }
            }

            if( pFmt )
            {
                const SwFmtAnchor* pAnchor = &pFmt->GetAnchor();
                if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
                    pAnchor->GetCntntAnchor() )
                {
                    pNd = &pAnchor->GetCntntAnchor()->nNode.GetNode();
                    const SwNode* pFlyNd = pNd->FindFlyStartNode();
                    while( pFlyNd )
                    {
                        // dann ueber den Anker nach oben "hangeln"
                        for( n = 0; n < rFmts.Count(); ++n )
                        {
                            const SwFrmFmt* pFrmFmt = rFmts[ n ];
                            const SwNodeIndex* pIdx = pFrmFmt->GetCntnt().
                                                        GetCntntIdx();
                            if( pIdx && pFlyNd == &pIdx->GetNode() )
                            {
                                if( pFmt == pFrmFmt )
                                {
                                    pNd = pFlyNd;
                                    pFlyNd = 0;
                                    break;
                                }
                                pAnchor = &pFrmFmt->GetAnchor();
                                if ((FLY_AT_PAGE == pAnchor->GetAnchorId()) ||
                                    !pAnchor->GetCntntAnchor() )
                                {
                                    pFlyNd = 0;
                                    break;
                                }

                                pFlyNd = pAnchor->GetCntntAnchor()->nNode.
                                        GetNode().FindFlyStartNode();
                                break;
                            }
                        }
                        if( n >= rFmts.Count() )
                        {
                            ASSERT( !this, "Fly-Section aber kein Format gefunden" );
                            return sal_False;
                        }
                    }
                }
            }
            // in pNd sollte jetzt der richtige Anker Node stehen oder
            // immer noch der this
        }

        if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
        {
            if( pNd->GetIndex() > GetNodes().GetEndOfAutotext().GetIndex() )
            {
                pPgDesc = &pDoc->GetPageDesc( 0 );
                pNd = 0;
            }
            else
            {
                // suche den Body Textnode
                if( 0 != ( pSttNd = pNd->FindHeaderStartNode() ) ||
                    0 != ( pSttNd = pNd->FindFooterStartNode() ))
                {
                    // dann in den PageDescs diesen StartNode suchen
                    sal_uInt16 nId;
                    UseOnPage eAskUse;
                    if( SwHeaderStartNode == pSttNd->GetStartNodeType())
                    {
                        nId = RES_HEADER;
                        eAskUse = nsUseOnPage::PD_HEADERSHARE;
                    }
                    else
                    {
                        nId = RES_FOOTER;
                        eAskUse = nsUseOnPage::PD_FOOTERSHARE;
                    }

                    for( sal_uInt16 n = pDoc->GetPageDescCnt(); n && !pPgDesc; )
                    {
                        const SwPageDesc& rPgDsc = pDoc->GetPageDesc( --n );
                        const SwFrmFmt* pFmt = &rPgDsc.GetMaster();
                        int nStt = 0, nLast = 1;
                        if( !( eAskUse & rPgDsc.ReadUseOn() )) ++nLast;

                        for( ; nStt < nLast; ++nStt, pFmt = &rPgDsc.GetLeft() )
                        {
                            const SwFmtHeader& rHdFt = (SwFmtHeader&)
                                                    pFmt->GetFmtAttr( nId );
                            if( rHdFt.GetHeaderFmt() )
                            {
                                const SwFmtCntnt& rCntnt =
                                    rHdFt.GetHeaderFmt()->GetCntnt();
                                if( rCntnt.GetCntntIdx() &&
                                    &rCntnt.GetCntntIdx()->GetNode() ==
                                    (SwNode*)pSttNd )
                                {
                                    pPgDesc = &rPgDsc;
                                    break;
                                }
                            }
                        }
                    }

                    if( !pPgDesc )
                        pPgDesc = &pDoc->GetPageDesc( 0 );
                    pNd = 0;
                }
                else if( 0 != ( pSttNd = pNd->FindFootnoteStartNode() ))
                {
                    // der Anker kann nur im Bodytext sein
                    const SwTxtFtn* pTxtFtn;
                    const SwFtnIdxs& rFtnArr = pDoc->GetFtnIdxs();
                    for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n )
                        if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
                            (SwNode*)pSttNd ==
                            &pTxtFtn->GetStartNode()->GetNode() )
                        {
                            pNd = &pTxtFtn->GetTxtNode();
                            break;
                        }
                }
                else
                {
                    // kann jetzt nur noch ein Seitengebundener Fly sein
                    // oder irgendetwas neueres.
                    // Hier koennen wir nur noch den Standard returnen
                    ASSERT( pNd->FindFlyStartNode(),
                            "wo befindet sich dieser Node?" );

                    pPgDesc = &pDoc->GetPageDesc( 0 );
                    pNd = 0;
                }
            }
        }

        if( pNd )
        {
            SwFindNearestNode aInfo( *pNd );
            // dann ueber alle Nodes aller PageDesc
            const SfxPoolItem* pItem;
            sal_uInt32 i, nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_PAGEDESC );
            for( i = 0; i < nMaxItems; ++i )
                if( 0 != (pItem = pDoc->GetAttrPool().GetItem2( RES_PAGEDESC, i ) ) &&
                    ((SwFmtPageDesc*)pItem)->GetDefinedIn() )
                {
                    const SwModify* pMod = ((SwFmtPageDesc*)pItem)->GetDefinedIn();
                    if( pMod->ISA( SwCntntNode ) )
                        aInfo.CheckNode( *(SwCntntNode*)pMod );
                    else if( pMod->ISA( SwFmt ))
                        ((SwFmt*)pMod)->GetInfo( aInfo );
                }

            if( 0 != ( pNd = aInfo.GetFoundNode() ))
            {
                if( pNd->IsCntntNode() )
                    pPgDesc = ((SwFmtPageDesc&)pNd->GetCntntNode()->
                                GetAttr( RES_PAGEDESC )).GetPageDesc();
                else if( pNd->IsTableNode() )
                    pPgDesc = pNd->GetTableNode()->GetTable().
                            GetFrmFmt()->GetPageDesc().GetPageDesc();
                else if( pNd->IsSectionNode() )
                    pPgDesc = pNd->GetSectionNode()->GetSection().
                            GetFmt()->GetPageDesc().GetPageDesc();
                // OD 18.03.2003 #106329#
                if ( pPgDescNdIdx )
                {
                    *pPgDescNdIdx = pNd->GetIndex();
                }
            }
            if( !pPgDesc )
                pPgDesc = &pDoc->GetPageDesc( 0 );
        }
    }
	return pPgDesc;
}


	// falls der Node in einem Fly steht, dann wird das entsprechende Format
	// returnt
SwFrmFmt* SwNode::GetFlyFmt() const
{
	SwFrmFmt* pRet = 0;
	const SwNode* pSttNd = FindFlyStartNode();
	if( pSttNd )
	{
		if( IsCntntNode() )
		{
			SwCntntFrm* pFrm = SwIterator<SwCntntFrm,SwCntntNode>::FirstElement( *(SwCntntNode*)this );
			if( pFrm )
				pRet = pFrm->FindFlyFrm()->GetFmt();
		}
		if( !pRet )
		{
			// dann gibts noch harten steinigen Weg uebers Dokument:
			const SwSpzFrmFmts& rFrmFmtTbl = *GetDoc()->GetSpzFrmFmts();
			for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n )
			{
				SwFrmFmt* pFmt = rFrmFmtTbl[n];
				const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
				if( rCntnt.GetCntntIdx() &&
					&rCntnt.GetCntntIdx()->GetNode() == pSttNd )
				{
					pRet = pFmt;
					break;
				}
			}
		}
	}
	return pRet;
}

SwTableBox* SwNode::GetTblBox() const
{
	SwTableBox* pBox = 0;
	const SwNode* pSttNd = FindTableBoxStartNode();
	if( pSttNd )
		pBox = (SwTableBox*)pSttNd->FindTableNode()->GetTable().GetTblBox(
													pSttNd->GetIndex() );
	return pBox;
}

SwStartNode* SwNode::FindSttNodeByType( SwStartNodeType eTyp )
{
	SwStartNode* pTmp = IsStartNode() ? (SwStartNode*)this : pStartOfSection;

	while( eTyp != pTmp->GetStartNodeType() && pTmp->GetIndex() )
#if defined( ALPHA ) && defined( UNX )
		pTmp = ((SwNode*)pTmp)->pStartOfSection;
#else
		pTmp = pTmp->pStartOfSection;
#endif
	return eTyp == pTmp->GetStartNodeType() ? pTmp : 0;
}

const SwTxtNode* SwNode::FindOutlineNodeOfLevel( sal_uInt8 nLvl ) const
{
	const SwTxtNode* pRet = 0;
	const SwOutlineNodes& rONds = GetNodes().GetOutLineNds();
	if( MAXLEVEL > nLvl && rONds.Count() )
	{
		sal_uInt16 nPos;
		SwNode* pNd = (SwNode*)this;
		sal_Bool bCheckFirst = sal_False;
		if( !rONds.Seek_Entry( pNd, &nPos ))
		{
			if( nPos )
				nPos = nPos-1;
			else
				bCheckFirst = sal_True;
		}

		if( bCheckFirst )
		{
			// der 1.GliederungsNode liegt hinter dem Fragenden. Dann
			// teste mal, ob dieser auf der gleichen Seite steht. Wenn
			// nicht, ist das ein ungueltiger. Bug 61865
			pRet = rONds[0]->GetTxtNode();

			const SwCntntNode* pCNd = GetCntntNode();

			Point aPt( 0, 0 );
			const SwFrm* pFrm = pRet->getLayoutFrm( pRet->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ),
					   * pMyFrm = pCNd ? pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ) : 0;
			const SwPageFrm* pPgFrm = pFrm ? pFrm->FindPageFrm() : 0;
			if( pPgFrm && pMyFrm &&
				pPgFrm->Frm().Top() > pMyFrm->Frm().Top() )
			{
				// der Fragende liegt vor der Seite, also ist er ungueltig
				pRet = 0;
			}
		}
		else
		{
			// oder ans Feld und von dort holen !!
            while( nPos &&
                   nLvl < ( pRet = rONds[nPos]->GetTxtNode() )
					//->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
                    ->GetAttrOutlineLevel() - 1 )  //<-end,zhaojianwei
				--nPos;

			if( !nPos )		// bei 0 gesondert holen !!
				pRet = rONds[0]->GetTxtNode();
		}
	}
	return pRet;
}

inline sal_Bool IsValidNextPrevNd( const SwNode& rNd )
{
	return ND_TABLENODE == rNd.GetNodeType() ||
           ( ND_CONTENTNODE & rNd.GetNodeType() ) ||
			( ND_ENDNODE == rNd.GetNodeType() && rNd.StartOfSectionNode() &&
            ND_TABLENODE == rNd.StartOfSectionNode()->GetNodeType() );
}

sal_uInt8 SwNode::HasPrevNextLayNode() const
{
    // assumption: <this> node is a node inside the document nodes array section.

	sal_uInt8 nRet = 0;
	if( IsValidNextPrevNd( *this ))
	{
		SwNodeIndex aIdx( *this, -1 );
        // --> OD 2007-06-04 #i77805#
        // skip section start and end nodes
        while ( aIdx.GetNode().IsSectionNode() ||
                ( aIdx.GetNode().IsEndNode() &&
                  aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) )
        {
            --aIdx;
        }
        // <--
		if( IsValidNextPrevNd( aIdx.GetNode() ))
			nRet |= ND_HAS_PREV_LAYNODE;
        // --> OD 2007-06-04 #i77805#
        // skip section start and end nodes
//        aIdx += 2;
        aIdx = SwNodeIndex( *this, +1 );
        while ( aIdx.GetNode().IsSectionNode() ||
                ( aIdx.GetNode().IsEndNode() &&
                  aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) )
        {
            ++aIdx;
        }
        // <--
        if( IsValidNextPrevNd( aIdx.GetNode() ))
			nRet |= ND_HAS_NEXT_LAYNODE;
	}
	return nRet;
}

/*******************************************************************
|*
|*	SwNode::StartOfSection
|*
|*	Beschreibung
|*		Die Funktion liefert die StartOfSection des Nodes.
|*
|*	Parameter
|*		IN
|*		rNodes bezeichnet das variable Array, in dem sich der Node
|*		befindet
|*	Ersterstellung
|*		VER0100 vb 901214
|*
|*	Stand
|*		VER0100 vb 901214
|*
*******************************************************************/


SwStartNode::SwStartNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType,
							SwStartNodeType eSttNd )
	: SwNode( rWhere, nNdType ), eSttNdTyp( eSttNd )
{
	// erstmal temporaer, bis der EndNode eingefuegt wird.
	pEndOfSection = (SwEndNode*)this;
}

SwStartNode::SwStartNode( SwNodes& rNodes, sal_uLong nPos )
	: SwNode( rNodes, nPos, ND_STARTNODE ), eSttNdTyp( SwNormalStartNode )
{
	// erstmal temporaer, bis der EndNode eingefuegt wird.
	pEndOfSection = (SwEndNode*)this;
}


void SwStartNode::CheckSectionCondColl() const
{
//FEATURE::CONDCOLL
	SwNodeIndex aIdx( *this );
	sal_uLong nEndIdx = EndOfSectionIndex();
	const SwNodes& rNds = GetNodes();
	SwCntntNode* pCNd;
	while( 0 != ( pCNd = rNds.GoNext( &aIdx )) && pCNd->GetIndex() < nEndIdx )
		pCNd->ChkCondColl();
//FEATURE::CONDCOLL
}

/*******************************************************************
|*
|*	SwEndNode::SwEndNode
|*
|*	Beschreibung
|*		Konstruktor; dieser fuegt einen Node in das Array rNodes
|*		an der Position aWhere ein. Der
|*		theStartOfSection-Pointer wird entsprechend gesetzt,
|*		und der EndOfSection-Pointer des zugehoerigen
|*		Startnodes -- durch rStartOfSection bezeichnet --
|*		wird auf diesen Node gesetzt.
|*
|*	Parameter
|*		IN
|*		rNodes bezeichnet das variable Array, in das der Node
|*		eingefuegt werden soll
|*		IN
|*		aWhere bezeichnet die Position innerhalb dieses Arrays,
|*		an der der Node eingefuegt werden soll
|*		!!!!!!!!!!!!
|*		Es wird eine Kopie uebergeben!
|*
|*	Ersterstellung
|*		VER0100 vb 901214
|*
|*	Stand
|*		VER0100 vb 901214
|*
*******************************************************************/


SwEndNode::SwEndNode( const SwNodeIndex &rWhere, SwStartNode& rSttNd )
	: SwNode( rWhere, ND_ENDNODE )
{
	pStartOfSection = &rSttNd;
	pStartOfSection->pEndOfSection = this;
}

SwEndNode::SwEndNode( SwNodes& rNds, sal_uLong nPos, SwStartNode& rSttNd )
	: SwNode( rNds, nPos, ND_ENDNODE )
{
	pStartOfSection = &rSttNd;
	pStartOfSection->pEndOfSection = this;
}



// --------------------
// SwCntntNode
// --------------------


SwCntntNode::SwCntntNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType,
							SwFmtColl *pColl )
	: SwModify( pColl ),	 // CrsrsShell, FrameFmt,
    SwNode( rWhere, nNdType ),
    pCondColl( 0 ),
    mbSetModifyAtAttr( false )
#ifdef OLD_INDEX
	,SwIndexReg(2)
#endif
{
}


SwCntntNode::~SwCntntNode()
{
	// Die Basisklasse SwClient vom SwFrm nimmt sich aus
	// der Abhaengikeitsliste raus!
	// Daher muessen alle Frames in der Abhaengigkeitsliste geloescht werden.
	if( GetDepends() )
		DelFrms();

    if( pCondColl )
		delete pCondColl;

    if ( mpAttrSet.get() && mbSetModifyAtAttr )
        ((SwAttrSet*)mpAttrSet.get())->SetModifyAtAttr( 0 );
}

void SwCntntNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
{
	sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
					pNewValue ? pNewValue->Which() : 0 ;

	switch( nWhich )
	{
	case RES_OBJECTDYING :
		{
			SwFmt * pFmt = (SwFmt *) ((SwPtrMsgPoolItem *)pNewValue)->pObject;

			// nicht umhaengen wenn dieses das oberste Format ist !!
			if( GetRegisteredIn() == pFmt )
			{
				if( pFmt->GetRegisteredIn() )
				{
					// wenn Parent, dann im neuen Parent wieder anmelden
					((SwModify*)pFmt->GetRegisteredIn())->Add( this );
                    if ( GetpSwAttrSet() )
                        AttrSetHandleHelper::SetParent( mpAttrSet, *this, GetFmtColl(), GetFmtColl() );
				}
				else
				{
					// sonst auf jeden Fall beim sterbenden abmelden
					((SwModify*)GetRegisteredIn())->Remove( this );
                    if ( GetpSwAttrSet() )
                        AttrSetHandleHelper::SetParent( mpAttrSet, *this, 0, 0 );
				}
			}
		}
		break;


	case RES_FMT_CHG:
		// falls mein Format Parent umgesetzt wird, dann melde ich
		// meinen Attrset beim Neuen an.

		// sein eigenes Modify ueberspringen !!
        if( GetpSwAttrSet() &&
			((SwFmtChg*)pNewValue)->pChangedFmt == GetRegisteredIn() )
		{
			// den Set an den neuen Parent haengen
            AttrSetHandleHelper::SetParent( mpAttrSet, *this, GetFmtColl(), GetFmtColl() );
		}
		break;
//FEATURE::CONDCOLL
	case RES_CONDCOLL_CONDCHG:
		if( ((SwCondCollCondChg*)pNewValue)->pChangedFmt == GetRegisteredIn() &&
			&GetNodes() == &GetDoc()->GetNodes() )
		{
			ChkCondColl();
		}
		return ;	// nicht an die Basisklasse / Frames weitergeben
//FEATURE::CONDCOLL

	case RES_ATTRSET_CHG:
		if( GetNodes().IsDocNodes() && IsTxtNode() )
		{
            if( SFX_ITEM_SET == ((SwAttrSetChg*)pOldValue)->GetChgSet()->GetItemState(
                RES_CHRATR_HIDDEN, sal_False ) )
            {
                ((SwTxtNode*)this)->SetCalcHiddenCharFlags();
            }
		}
		break;

    case RES_UPDATE_ATTR:
		if( GetNodes().IsDocNodes() && IsTxtNode() )
        {
            const sal_uInt16 nTmp = ((SwUpdateAttr*)pNewValue)->nWhichAttr;
            if ( RES_ATTRSET_CHG == nTmp )
            {
                // anybody wants to do some optimization here?
                ((SwTxtNode*)this)->SetCalcHiddenCharFlags();
            }
        }
        break;
	}

	NotifyClients( pOldValue, pNewValue );
}

sal_Bool SwCntntNode::InvalidateNumRule()
{
	SwNumRule* pRule = 0;
	const SfxPoolItem* pItem;
	if( GetNodes().IsDocNodes() &&
		0 != ( pItem = GetNoCondAttr( RES_PARATR_NUMRULE, sal_True )) &&
		((SwNumRuleItem*)pItem)->GetValue().Len() &&
		0 != (pRule = GetDoc()->FindNumRulePtr(
								((SwNumRuleItem*)pItem)->GetValue() ) ) )
	{
		pRule->SetInvalidRule( sal_True );
	}
	return 0 != pRule;
}

SwCntntFrm *SwCntntNode::getLayoutFrm( const SwRootFrm* _pRoot,
    const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm ) const
{
	return (SwCntntFrm*) ::GetFrmOfModify( _pRoot, *(SwModify*)this, FRM_CNTNT,
											pPoint, pPos, bCalcFrm );
}

SwRect SwCntntNode::FindLayoutRect( const sal_Bool bPrtArea, const Point* pPoint,
									const sal_Bool bCalcFrm ) const
{
	SwRect aRet;
	SwCntntFrm* pFrm = (SwCntntFrm*)::GetFrmOfModify( 0, *(SwModify*)this,
											FRM_CNTNT, pPoint, 0, bCalcFrm );
	if( pFrm )
		aRet = bPrtArea ? pFrm->Prt() : pFrm->Frm();
	return aRet;
}

SwRect SwCntntNode::FindPageFrmRect( const sal_Bool bPrtArea, const Point* pPoint,
									const sal_Bool bCalcFrm ) const
{
	SwRect aRet;
	SwFrm* pFrm = ::GetFrmOfModify( 0, *(SwModify*)this,
											FRM_CNTNT, pPoint, 0, bCalcFrm );
	if( pFrm && 0 != ( pFrm = pFrm->FindPageFrm() ))
		aRet = bPrtArea ? pFrm->Prt() : pFrm->Frm();
	return aRet;
}

xub_StrLen SwCntntNode::Len() const { return 0; }



SwFmtColl *SwCntntNode::ChgFmtColl( SwFmtColl *pNewColl )
{
	ASSERT( pNewColl, "Collectionpointer ist 0." );
	SwFmtColl *pOldColl = GetFmtColl();

	if( pNewColl != pOldColl )
	{
		pNewColl->Add( this );

		// setze den Parent von unseren Auto-Attributen auf die neue
		// Collection:
        if( GetpSwAttrSet() )
            AttrSetHandleHelper::SetParent( mpAttrSet, *this, pNewColl, pNewColl );

//FEATURE::CONDCOLL
		// HACK: hier muss die entsprechend der neuen Vorlage die Bedingungen
		//		neu ueberprueft werden!
		if( sal_True /*pNewColl */ )
		{
			SetCondFmtColl( 0 );
		}
//FEATURE::CONDCOLL

		if( !IsModifyLocked() )
		{
			SwFmtChg aTmp1( pOldColl );
			SwFmtChg aTmp2( pNewColl );
            SwCntntNode::Modify( &aTmp1, &aTmp2 );
		}
	}
	if ( IsInCache() )
	{
		SwFrm::GetCache().Delete( this );
		SetInCache( sal_False );
	}
	return pOldColl;
}


sal_Bool SwCntntNode::GoNext(SwIndex * pIdx, sal_uInt16 nMode ) const
{
	sal_Bool bRet = sal_True;
	if( pIdx->GetIndex() < Len() )
	{
		if( !IsTxtNode() )
			(*pIdx)++;
		else
		{
			const SwTxtNode& rTNd = *GetTxtNode();
			xub_StrLen nPos = pIdx->GetIndex();
			if( pBreakIt->GetBreakIter().is() )
			{
				sal_Int32 nDone = 0;
				sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ?
                                        CharacterIteratorMode::SKIPCELL :
                                        CharacterIteratorMode::SKIPCONTROLCHARACTER;
                nPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharacters( rTNd.GetTxt(), nPos,
                                   pBreakIt->GetLocale( rTNd.GetLang( nPos ) ),
                                   nItrMode, 1, nDone );

                // Check if nPos is inside hidden text range:
                if ( CRSR_SKIP_HIDDEN & nMode )
                {
                    xub_StrLen nHiddenStart;
                    xub_StrLen nHiddenEnd;
                    SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd );
                    if ( nHiddenStart != STRING_LEN && nHiddenStart != nPos )
                         nPos = nHiddenEnd;
                }

				if( 1 == nDone )
					*pIdx = nPos;
				else
					bRet = sal_False;
			}
			else if( nPos < rTNd.GetTxt().Len() )
				(*pIdx)++;
			else
				bRet = sal_False;
		}
	}
	else
		bRet = sal_False;
	return bRet;
}


sal_Bool SwCntntNode::GoPrevious(SwIndex * pIdx, sal_uInt16 nMode ) const
{
	sal_Bool bRet = sal_True;
	if( pIdx->GetIndex() > 0 )
	{
		if( !IsTxtNode() )
			(*pIdx)--;
		else
		{
			const SwTxtNode& rTNd = *GetTxtNode();
			xub_StrLen nPos = pIdx->GetIndex();
			if( pBreakIt->GetBreakIter().is() )
			{
				sal_Int32 nDone = 0;
				sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ?
                                        CharacterIteratorMode::SKIPCELL :
                                        CharacterIteratorMode::SKIPCONTROLCHARACTER;
                nPos = (xub_StrLen)pBreakIt->GetBreakIter()->previousCharacters( rTNd.GetTxt(), nPos,
                                   pBreakIt->GetLocale( rTNd.GetLang( nPos ) ),
                                   nItrMode, 1, nDone );

                // Check if nPos is inside hidden text range:
                if ( CRSR_SKIP_HIDDEN & nMode )
                {
                    xub_StrLen nHiddenStart;
                    xub_StrLen nHiddenEnd;
                    SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd );
                    if ( nHiddenStart != STRING_LEN  )
                         nPos = nHiddenStart;
                }

				if( 1 == nDone )
					*pIdx = nPos;
				else
					bRet = sal_False;
			}
			else if( nPos )
				(*pIdx)--;
			else
				bRet = sal_False;
		}
	}
	else
		bRet = sal_False;
	return bRet;
}


/*
 * Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom
 * Dokument. Die erzeugten Contentframes werden in das entsprechende
 * Layout gehaengt.
 */


void SwCntntNode::MakeFrms( SwCntntNode& rNode )
{
	ASSERT( &rNode != this,
			"Kein Contentnode oder Copy-Node und neuer Node identisch." );

	if( !GetDepends() || &rNode == this )	// gibt es ueberhaupt Frames ??
		return;

	SwFrm *pFrm, *pNew;
	SwLayoutFrm *pUpper;
	// Frames anlegen fuer Nodes, die vor oder hinter der Tabelle stehen ??
	ASSERT( FindTableNode() == rNode.FindTableNode(), "Table confusion" )

	SwNode2Layout aNode2Layout( *this, rNode.GetIndex() );

	while( 0 != (pUpper = aNode2Layout.UpperFrm( pFrm, rNode )) )
	{
		pNew = rNode.MakeFrm( pUpper );
		pNew->Paste( pUpper, pFrm );
        // --> OD 2005-12-01 #i27138#
        // notify accessibility paragraphs objects about changed
        // CONTENT_FLOWS_FROM/_TO relation.
        // Relation CONTENT_FLOWS_FROM for next paragraph will change
        // and relation CONTENT_FLOWS_TO for previous paragraph will change.
        if ( pNew->IsTxtFrm() )
        {
            ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
            if ( pViewShell && pViewShell->GetLayout() &&
                 pViewShell->GetLayout()->IsAnyShellAccessible() )
            {
                pViewShell->InvalidateAccessibleParaFlowRelation(
                            dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
                            dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) );
            }
        }
        // <--
    }
}

/*
 * Methode loescht fuer den Node alle Ansichten vom
 * Dokument. Die Contentframes werden aus dem entsprechenden
 * Layout ausgehaengt.
 */


void SwCntntNode::DelFrms()
{
	if( !GetDepends() )
		return;

    SwCntntFrm::DelFrms(*this);
	if( IsTxtNode() )
	{
        ((SwTxtNode*)this)->SetWrong( NULL );
        ((SwTxtNode*)this)->SetWrongDirty( true );

        ((SwTxtNode*)this)->SetGrammarCheck( NULL );
        ((SwTxtNode*)this)->SetGrammarCheckDirty( true );
        // SMARTTAGS
        ((SwTxtNode*)this)->SetSmartTags( NULL );
        ((SwTxtNode*)this)->SetSmartTagDirty( true );

        ((SwTxtNode*)this)->SetWordCountDirty( true );
        ((SwTxtNode*)this)->SetAutoCompleteWordDirty( true );
	}
}


SwCntntNode *SwCntntNode::JoinNext()
{
	return this;
}


SwCntntNode *SwCntntNode::JoinPrev()
{
	return this;
}



	// erfrage vom Modify Informationen
sal_Bool SwCntntNode::GetInfo( SfxPoolItem& rInfo ) const
{
	switch( rInfo.Which() )
	{
	case RES_AUTOFMT_DOCNODE:
		if( &GetNodes() == ((SwAutoFmtGetDocNode&)rInfo).pNodes )
		{
			((SwAutoFmtGetDocNode&)rInfo).pCntntNode = this;
			return sal_False;
		}
		break;
    // --> OD 2008-02-19 #refactorlists#
//    case RES_GETNUMNODES:
//        // #111955# only numbered nodes in rInfo
//        if( IsTxtNode())
//        {
//            SwTxtNode * pTxtNode = (SwTxtNode*)this;
//            pItem = (SwNumRuleItem*)GetNoCondAttr(RES_PARATR_NUMRULE, sal_True );

//            if (0 != pItem  &&
//                pItem->GetValue().Len() &&
//                pItem->GetValue() == ((SwNumRuleInfo&)rInfo).GetName() &&
//                GetNodes().IsDocNodes())
//            {
//                ((SwNumRuleInfo&)rInfo).AddNode( *pTxtNode );
//            }
//        }

//        return sal_True;
    // <--

	case RES_FINDNEARESTNODE:
        if( ((SwFmtPageDesc&)GetAttr( RES_PAGEDESC )).GetPageDesc() )
			((SwFindNearestNode&)rInfo).CheckNode( *this );
		return sal_True;

	case RES_CONTENT_VISIBLE:
		{
			((SwPtrMsgPoolItem&)rInfo).pObject =
				SwIterator<SwFrm,SwCntntNode>::FirstElement(*this);
		}
		return sal_False;
	}

	return SwModify::GetInfo( rInfo );
}


	// setze ein Attribut
sal_Bool SwCntntNode::SetAttr(const SfxPoolItem& rAttr )
{
    if( !GetpSwAttrSet() )            // lasse von den entsprechenden Nodes die
		NewAttrSet( GetDoc()->GetAttrPool() );		// AttrSets anlegen

    ASSERT( GetpSwAttrSet(), "warum wurde kein AttrSet angelegt?" );

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

	sal_Bool bRet = sal_False;
	// wenn Modify gelockt ist, werden keine Modifies verschickt
	if( IsModifyLocked() ||
		( !GetDepends() &&  RES_PARATR_NUMRULE != rAttr.Which() ))
	{
        bRet = 0 != AttrSetHandleHelper::Put( mpAttrSet, *this, rAttr );
	}
	else
	{
        SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
                  aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
        if( 0 != ( bRet = 0 != AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rAttr, &aOld, &aNew ) ))
		{
            SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
            SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
			ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt
		}
	}
	return bRet;
}
#include <svl/itemiter.hxx>

sal_Bool SwCntntNode::SetAttr( const SfxItemSet& rSet )
{
    if ( IsInCache() )
	{
		SwFrm::GetCache().Delete( this );
		SetInCache( sal_False );
	}

    const SfxPoolItem* pFnd = 0;
    if( SFX_ITEM_SET == rSet.GetItemState( RES_AUTO_STYLE, sal_False, &pFnd ) )
    {
        ASSERT( rSet.Count() == 1, "SetAutoStyle mixed with other attributes?!" );
        const SwFmtAutoFmt* pTmp = static_cast<const SwFmtAutoFmt*>(pFnd);

        // If there already is an attribute set (usually containing a numbering
        // item), we have to merge the attribute of the new set into the old set:
        bool bSetParent = true;
        if ( GetpSwAttrSet() )
        {
            bSetParent = false;
            AttrSetHandleHelper::Put( mpAttrSet, *this, *pTmp->GetStyleHandle() );
        }
        else
        {
            mpAttrSet = pTmp->GetStyleHandle();
        }

        if ( bSetParent )
        {
            // If the content node has a conditional style, we have to set the
            // string item containing the correct conditional style name (the
            // style name property has already been set during the import!)
            // In case we do not have a conditional style, we make use of the
            // fact that nobody else uses the attribute set behind the handle.
            // FME 2007-07-10 #i78124# If autostyle does not have a parent,
            // the string is empty.
            const SfxPoolItem* pNameItem = 0;
            if ( 0 != GetCondFmtColl() ||
                 SFX_ITEM_SET != mpAttrSet->GetItemState( RES_FRMATR_STYLE_NAME, sal_False, &pNameItem ) ||
                 0 == static_cast<const SfxStringItem*>(pNameItem)->GetValue().Len() )
                AttrSetHandleHelper::SetParent( mpAttrSet, *this, &GetAnyFmtColl(), GetFmtColl() );
            else
                const_cast<SfxItemSet*>(mpAttrSet.get())->SetParent( &GetFmtColl()->GetAttrSet() );
        }

        return sal_True;
    }

    if( !GetpSwAttrSet() )            // lasse von den entsprechenden Nodes die
		NewAttrSet( GetDoc()->GetAttrPool() );		// AttrSets anlegen

    sal_Bool bRet = sal_False;
	// wenn Modify gelockt ist, werden keine Modifies verschickt
    if ( IsModifyLocked() ||
         ( !GetDepends() &&
           SFX_ITEM_SET != rSet.GetItemState( RES_PARATR_NUMRULE, sal_False ) ) )
	{
		// einige Sonderbehandlungen fuer Attribute
        bRet = 0 != AttrSetHandleHelper::Put( mpAttrSet, *this, rSet );
	}
	else
	{
        SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
                  aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
        if( 0 != (bRet = 0 != AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rSet, &aOld, &aNew )) )
		{
			// einige Sonderbehandlungen fuer Attribute
            SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
            SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
			ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt
		}
	}
	return bRet;
}

// Nimmt den Hint mit nWhich aus dem Delta-Array


sal_Bool SwCntntNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
{
    if( !GetpSwAttrSet() )
		return sal_False;

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

	// wenn Modify gelockt ist, werden keine Modifies verschickt
	if( IsModifyLocked() )
	{
        sal_uInt16 nDel = 0;
        if ( !nWhich2 || nWhich2 < nWhich1 )
        {
            std::vector<sal_uInt16> aClearWhichIds;
            aClearWhichIds.push_back( nWhich1 );
            nDel = ClearItemsFromAttrSet( aClearWhichIds );
        }
        else
            nDel = AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, 0, 0 );

        if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
            mpAttrSet.reset();//DELETEZ( mpAttrSet );
		return 0 != nDel;
	}

	// sollte kein gueltiger Bereich definiert sein ?
	if( !nWhich2 || nWhich2 < nWhich1 )
		nWhich2 = nWhich1;		// dann setze auf 1. Id, nur dieses Item

    SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
              aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
    sal_Bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, &aOld, &aNew );

	if( bRet )
	{
        SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
        SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
		ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt

        if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
            mpAttrSet.reset();//DELETEZ( mpAttrSet );
	}
	return bRet;
}
sal_Bool SwCntntNode::ResetAttr( const SvUShorts& rWhichArr )
{
    if( !GetpSwAttrSet() )
		return sal_False;

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

	// wenn Modify gelockt ist, werden keine Modifies verschickt
	sal_uInt16 nDel = 0;
	if( IsModifyLocked() )
	{
        std::vector<sal_uInt16> aClearWhichIds;
		for( sal_uInt16 n = 0, nEnd = rWhichArr.Count(); n < nEnd; ++n )
            aClearWhichIds.push_back( rWhichArr[ n ] );

        nDel = ClearItemsFromAttrSet( aClearWhichIds );
    }
	else
	{
        SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
                  aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );

		for( sal_uInt16 n = 0, nEnd = rWhichArr.Count(); n < nEnd; ++n )
            if( AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, rWhichArr[ n ], &aOld, &aNew ))
				++nDel;

		if( nDel )
		{
            SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
            SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
			ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt
		}
	}
    if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
        mpAttrSet.reset();//DELETEZ( mpAttrSet );
	return 0 != nDel ;
}


sal_uInt16 SwCntntNode::ResetAllAttr()
{
    if( !GetpSwAttrSet() )
		return 0;

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

	// wenn Modify gelockt ist, werden keine Modifies verschickt
	if( IsModifyLocked() )
	{
        std::vector<sal_uInt16> aClearWhichIds;
        aClearWhichIds.push_back(0);
        sal_uInt16 nDel = ClearItemsFromAttrSet( aClearWhichIds );
        if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
            mpAttrSet.reset();            // DELETEZ( mpAttrSet );
		return nDel;
	}

    SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
              aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
    sal_Bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, 0, &aOld, &aNew );

	if( bRet )
	{
        SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
        SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
		ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt

        if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
            mpAttrSet.reset();//DELETEZ( mpAttrSet );
	}
	return aNew.Count();
}


sal_Bool SwCntntNode::GetAttr( SfxItemSet& rSet, sal_Bool bInParent ) const
{
	if( rSet.Count() )
		rSet.ClearItem();

	const SwAttrSet& rAttrSet = GetSwAttrSet();
	if( bInParent )
		return rSet.Set( rAttrSet, sal_True ) ? sal_True : sal_False;

	rSet.Put( rAttrSet );
	return rSet.Count() ? sal_True : sal_False;
}

sal_uInt16 SwCntntNode::ClearItemsFromAttrSet( const std::vector<sal_uInt16>& rWhichIds )
{
    sal_uInt16 nRet = 0;
    if ( 0 == rWhichIds.size() )
        return nRet;

    ASSERT( GetpSwAttrSet(), "no item set" )
    SwAttrSet aNewAttrSet( *GetpSwAttrSet() );
    for ( std::vector<sal_uInt16>::const_iterator aIter = rWhichIds.begin();
          aIter != rWhichIds.end();
          ++aIter )
    {
        nRet = nRet + aNewAttrSet.ClearItem( *aIter );
    }
    if ( nRet )
        AttrSetHandleHelper::GetNewAutoStyle( mpAttrSet, *this, aNewAttrSet );

    return nRet;
}

const SfxPoolItem* SwCntntNode::GetNoCondAttr( sal_uInt16 nWhich,
												sal_Bool bInParents ) const
{
	const SfxPoolItem* pFnd = 0;
	if( pCondColl && pCondColl->GetRegisteredIn() )
	{
        if( !GetpSwAttrSet() || ( SFX_ITEM_SET != GetpSwAttrSet()->GetItemState(
					nWhich, sal_False, &pFnd ) && bInParents ))
			((SwFmt*)GetRegisteredIn())->GetItemState( nWhich, bInParents, &pFnd );
	}
    // --> OD 2005-10-25 #126347# - undo change of issue #i51029#
    // Note: <GetSwAttrSet()> returns <mpAttrSet>, if set, otherwise it returns
    //       the attribute set of the paragraph style, which is valid for the
    //       content node - see file <node.hxx>
    else
    // <--
    {
		GetSwAttrSet().GetItemState( nWhich, bInParents, &pFnd );
    }
	return pFnd;
}

	// koennen 2 Nodes zusammengefasst werden ?
	// in pIdx kann die 2. Position returnt werden.
int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const
{
	const SwNodes& rNds = GetNodes();
	sal_uInt8 nNdType = GetNodeType();
	SwNodeIndex aIdx( *this, 1 );

	const SwNode* pNd = this;
	while( aIdx < rNds.Count()-1 &&
		(( pNd = &aIdx.GetNode())->IsSectionNode() ||
            ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
		aIdx++;

	if( pNd->GetNodeType() != nNdType || rNds.Count()-1 == aIdx.GetIndex() )
		return sal_False;
    if( IsTxtNode() )
    {   // Do not merge strings if the result exceeds the allowed string length
        const SwTxtNode* pTxtNd = static_cast<const SwTxtNode*>(this);
        sal_uInt64 nSum = pTxtNd->GetTxt().Len();
        pTxtNd = static_cast<const SwTxtNode*>(pNd);
        nSum += pTxtNd->GetTxt().Len();
        if( nSum > STRING_LEN )
            return sal_False;
    }
	if( pIdx )
		*pIdx = aIdx;
	return sal_True;
}


	// koennen 2 Nodes zusammengefasst werden ?
	// in pIdx kann die 2. Position returnt werden.
int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const
{
    sal_uInt8 nNdType = GetNodeType();
	SwNodeIndex aIdx( *this, -1 );

	const SwNode* pNd = this;
	while( aIdx.GetIndex() &&
		(( pNd = &aIdx.GetNode())->IsSectionNode() ||
            ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
		aIdx--;

	if( pNd->GetNodeType() != nNdType || 0 == aIdx.GetIndex() )
		return sal_False;
	if( pIdx )
		*pIdx = aIdx;
	return sal_True;
}


//FEATURE::CONDCOLL


void SwCntntNode::SetCondFmtColl( SwFmtColl* pColl )
{
	if( (!pColl && pCondColl) || ( pColl && !pCondColl ) ||
		( pColl && pColl != pCondColl->GetRegisteredIn() ) )
	{
		SwFmtColl* pOldColl = GetCondFmtColl();
		delete pCondColl;
		if( pColl )
			pCondColl = new SwDepend( this, pColl );
		else
			pCondColl = 0;

        if( GetpSwAttrSet() )
		{
            AttrSetHandleHelper::SetParent( mpAttrSet, *this, &GetAnyFmtColl(), GetFmtColl() );
		}

		if( !IsModifyLocked() )
		{
			SwFmtChg aTmp1( pOldColl ? pOldColl : GetFmtColl() );
			SwFmtChg aTmp2( pColl ? pColl : GetFmtColl() );
			NotifyClients( &aTmp1, &aTmp2 );
		}
		if( IsInCache() )
		{
			SwFrm::GetCache().Delete( this );
			SetInCache( sal_False );
		}
	}
}


sal_Bool SwCntntNode::IsAnyCondition( SwCollCondition& rTmp ) const
{
	const SwNodes& rNds = GetNodes();
	{
		int nCond = 0;
        const SwStartNode* pSttNd = StartOfSectionNode();
		while( pSttNd )
		{
			switch( pSttNd->GetNodeType() )
			{
			case ND_TABLENODE:		nCond = PARA_IN_TABLEBODY; break;
			case ND_SECTIONNODE: 	nCond = PARA_IN_SECTION; break;

			default:
				switch( pSttNd->GetStartNodeType() )
				{
				case SwTableBoxStartNode:
					{
						nCond = PARA_IN_TABLEBODY;
						const SwTableNode* pTblNd = pSttNd->FindTableNode();
						const SwTableBox* pBox;
						if( pTblNd && 0 != ( pBox = pTblNd->GetTable().
							GetTblBox( pSttNd->GetIndex() ) ) && pBox &&
							pBox->IsInHeadline( &pTblNd->GetTable() ) )
							nCond = PARA_IN_TABLEHEAD;
					}
					break;
				case SwFlyStartNode:		nCond = PARA_IN_FRAME; break;
				case SwFootnoteStartNode:
					{
						nCond = PARA_IN_FOOTENOTE;
						const SwFtnIdxs& rFtnArr = rNds.GetDoc()->GetFtnIdxs();
						const SwTxtFtn* pTxtFtn;
						const SwNode* pSrchNd = pSttNd;

						for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n )
							if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
								pSrchNd == &pTxtFtn->GetStartNode()->GetNode() )
							{
								if( pTxtFtn->GetFtn().IsEndNote() )
									nCond = PARA_IN_ENDNOTE;
								break;
							}
					}
					break;
				case SwHeaderStartNode:     nCond = PARA_IN_HEADER; break;
				case SwFooterStartNode:     nCond = PARA_IN_FOOTER; break;
				case SwNormalStartNode:     break;
				}
			}

			if( nCond )
			{
				rTmp.SetCondition( (Master_CollConditions)nCond, 0 );
				return sal_True;
			}
			pSttNd = pSttNd->GetIndex()
                        ? pSttNd->StartOfSectionNode()
						: 0;
		}
	}

	{
		sal_uInt16 nPos;
		const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
		if( rOutlNds.Count() )
		{
			if( !rOutlNds.Seek_Entry( (SwCntntNode*)this, &nPos ) && nPos )
				--nPos;
			if( nPos < rOutlNds.Count() &&
				rOutlNds[ nPos ]->GetIndex() < GetIndex() )
			{
				SwTxtNode* pOutlNd = rOutlNds[ nPos ]->GetTxtNode();

				if( pOutlNd->IsOutline())
				{
                    rTmp.SetCondition( PARA_IN_OUTLINE, pOutlNd->GetAttrOutlineLevel() - 1 );
					return sal_True;
				}
			}
		}
	}

	return sal_False;
}


void SwCntntNode::ChkCondColl()
{
	// zur Sicherheit abfragen
	if( RES_CONDTXTFMTCOLL == GetFmtColl()->Which() )
	{
		SwCollCondition aTmp( 0, 0, 0 );
		const SwCollCondition* pCColl;

        bool bDone = false;

		if( IsAnyCondition( aTmp ))
        {
            pCColl = static_cast<SwConditionTxtFmtColl*>(GetFmtColl())
                ->HasCondition( aTmp );

            if (pCColl)
            {
                SetCondFmtColl( pCColl->GetTxtFmtColl() );
                bDone = true;
            }
        }

		if (!bDone)
		{
            if( IsTxtNode() && ((SwTxtNode*)this)->GetNumRule())
			{
				// steht in einer Numerierung
				// welcher Level?
				aTmp.SetCondition( PARA_IN_LIST,
                                ((SwTxtNode*)this)->GetActualListLevel() );
				pCColl = ((SwConditionTxtFmtColl*)GetFmtColl())->
								HasCondition( aTmp );
			}
			else
				pCColl = 0;

			if( pCColl )
				SetCondFmtColl( pCColl->GetTxtFmtColl() );
			else if( pCondColl )
				SetCondFmtColl( 0 );
		}
	}
}

// --> OD 2005-02-21 #i42921#
short SwCntntNode::GetTextDirection( const SwPosition& rPos,
                                     const Point* pPt ) const
{
    short nRet = -1;

    Point aPt;
    if( pPt )
        aPt = *pPt;

    // --> OD 2007-01-10 #i72024#
    // No format of the frame, because this can cause recursive layout actions
    SwFrm* pFrm = getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, &rPos, sal_False );
    // <--

    if ( pFrm )
    {
        if ( pFrm->IsVertical() )
        {
            if ( pFrm->IsRightToLeft() )
                nRet = FRMDIR_VERT_TOP_LEFT;
            else
                nRet = FRMDIR_VERT_TOP_RIGHT;
        }
        else
        {
            if ( pFrm->IsRightToLeft() )
                nRet = FRMDIR_HORI_RIGHT_TOP;
            else
                nRet = FRMDIR_HORI_LEFT_TOP;
        }
    }


    return nRet;
}
// <--

SwOLENodes* SwCntntNode::CreateOLENodesArray( const SwFmtColl& rColl, bool bOnlyWithInvalidSize )
{
    SwOLENodes *pNodes = 0;
    SwIterator<SwCntntNode,SwFmtColl> aIter( rColl );
    for( SwCntntNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
    {
        SwOLENode *pONd = pNd->GetOLENode();
        if ( pONd && (!bOnlyWithInvalidSize || pONd->IsOLESizeInvalid()) )
        {
            if ( !pNodes  )
                pNodes = new SwOLENodes;
            pNodes->Insert( pONd, pNodes->Count() );
        }
    }

    return pNodes;
}

//FEATURE::CONDCOLL
// Metoden aus Node.hxx - erst hier ist der TxtNode bekannt !!
// os: nur fuer ICC, da der zum optimieren zu dumm ist
#ifdef ICC
SwTxtNode   *SwNode::GetTxtNode()
{
	 return ND_TEXTNODE == nNodeType ? (SwTxtNode*)this : 0;
}
const SwTxtNode   *SwNode::GetTxtNode() const
{
	 return ND_TEXTNODE == nNodeType ? (const SwTxtNode*)this : 0;
}
#endif

/*
 * Document Interface Access
 */
const IDocumentSettingAccess* SwNode::getIDocumentSettingAccess() const { return GetDoc(); }
const IDocumentDeviceAccess* SwNode::getIDocumentDeviceAccess() const { return GetDoc(); }
const IDocumentMarkAccess* SwNode::getIDocumentMarkAccess() const { return GetDoc()->getIDocumentMarkAccess(); }
const IDocumentRedlineAccess* SwNode::getIDocumentRedlineAccess() const { return GetDoc(); }
const IDocumentStylePoolAccess* SwNode::getIDocumentStylePoolAccess() const { return GetDoc(); }
const IDocumentLineNumberAccess* SwNode::getIDocumentLineNumberAccess() const { return GetDoc(); }
const IDocumentDrawModelAccess* SwNode::getIDocumentDrawModelAccess() const { return GetDoc(); }
const IDocumentLayoutAccess* SwNode::getIDocumentLayoutAccess() const { return GetDoc(); }
IDocumentLayoutAccess* SwNode::getIDocumentLayoutAccess() { return GetDoc(); }
const IDocumentLinksAdministration* SwNode::getIDocumentLinksAdministration() const { return GetDoc(); }
IDocumentLinksAdministration* SwNode::getIDocumentLinksAdministration() { return GetDoc(); }
const IDocumentFieldsAccess* SwNode::getIDocumentFieldsAccess() const { return GetDoc(); }
IDocumentFieldsAccess* SwNode::getIDocumentFieldsAccess() { return GetDoc(); }
IDocumentContentOperations* SwNode::getIDocumentContentOperations() { return GetDoc(); }
IStyleAccess& SwNode::getIDocumentStyleAccess() { return GetDoc()->GetIStyleAccess(); }
// --> OD 2007-10-31 #i83479#
IDocumentListItems& SwNode::getIDocumentListItems()
{
    return *GetDoc();
}
// <--

sal_Bool SwNode::IsInRedlines() const
{
    const SwDoc * pDoc = GetDoc();
    sal_Bool bResult = sal_False;

    if (pDoc != NULL)
        bResult = pDoc->IsInRedlines(*this);

    return bResult;
}