/**************************************************************
 * 
 * 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 <stdlib.h>
#include <hintids.hxx>
#include <svl/intitem.hxx>
#include <svl/stritem.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/docfilt.hxx>
#include <editeng/protitem.hxx>
#include <sfx2/linkmgr.hxx>
#include <tools/urlobj.hxx>
#include <sfx2/sfxsids.hrc>
#include <sfx2/fcontnr.hxx>
#include <docary.hxx>
#include <fmtcntnt.hxx>
#include <fmtpdsc.hxx>
#include <errhdl.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <node.hxx>
#include <pam.hxx>
#include <frmtool.hxx>
#include <editsh.hxx>
#include <hints.hxx>
#include <docsh.hxx>
#include <ndtxt.hxx>
#include <section.hxx>
#include <swserv.hxx>
#include <shellio.hxx>
#include <poolfmt.hxx>
#include <expfld.hxx>
#include <swbaslnk.hxx>
#include <mvsave.hxx>
#include <sectfrm.hxx>
#include <fmtftntx.hxx>
#include <ftnidx.hxx>
#include <doctxm.hxx>
#include <fmteiro.hxx>
#include <swerror.h>
#include <unosection.hxx>
#include <switerator.hxx>
#include <svl/smplhint.hxx>

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


SV_IMPL_REF( SwServerObject )

//static const char __FAR_DATA sSectionFmtNm[] = "Section";
#define sSectionFmtNm aEmptyStr

class SwIntrnlSectRefLink : public SwBaseLink
{
	SwSectionFmt& rSectFmt;
public:
	SwIntrnlSectRefLink( SwSectionFmt& rFmt, sal_uInt16 nUpdateType, sal_uInt16 nFmt )
		: SwBaseLink( nUpdateType, nFmt ),
		rSectFmt( rFmt )
	{}

	virtual void Closed();
	virtual void DataChanged( const String& rMimeType,
                                const uno::Any & rValue );

	virtual const SwNode* GetAnchor() const;
	virtual sal_Bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, xub_StrLen nStt = 0,
							xub_StrLen nEnd = STRING_NOTFOUND ) const;

    // --> OD 2007-02-14 #b6521322#
    inline SwSectionNode* GetSectNode()
    {
        const SwNode* pSectNd( const_cast<SwIntrnlSectRefLink*>(this)->GetAnchor() );
        return const_cast<SwSectionNode*>( dynamic_cast<const SwSectionNode*>( pSectNd ) );
    }
    // <--
};


TYPEINIT1(SwSectionFmt,SwFrmFmt );
TYPEINIT1(SwSection,SwClient );

typedef SwSection* SwSectionPtr;

SV_IMPL_PTRARR( SwSections, SwSection*)
SV_IMPL_PTRARR(SwSectionFmts,SwSectionFmt*)


SwSectionData::SwSectionData(SectionType const eType, String const& rName)
    : m_eType(eType)
    , m_sSectionName(rName)
    , m_bHiddenFlag(false)
    , m_bProtectFlag(false)
    // --> FME 2004-06-22 #114856# edit in readonly sections
    , m_bEditInReadonlyFlag(false)
    // <--
    , m_bHidden(false)
    , m_bCondHiddenFlag(true)
    , m_bConnectFlag(true)
{
}

// this must have the same semantics as operator=()
SwSectionData::SwSectionData(SwSection const& rSection)
    : m_eType(rSection.GetType())
    , m_sSectionName(rSection.GetSectionName())
    , m_sCondition(rSection.GetCondition())
    , m_sLinkFileName(rSection.GetLinkFileName())
    , m_sLinkFilePassword(rSection.GetLinkFilePassword())
    , m_Password(rSection.GetPassword())
    , m_bHiddenFlag(rSection.IsHiddenFlag())
    , m_bProtectFlag(rSection.IsProtect())
    // --> FME 2004-06-22 #114856# edit in readonly sections
    , m_bEditInReadonlyFlag(rSection.IsEditInReadonly())
    // <--
    , m_bHidden(rSection.IsHidden())
    , m_bCondHiddenFlag(true)
    , m_bConnectFlag(rSection.IsConnectFlag())
{
}

// this must have the same semantics as operator=()
SwSectionData::SwSectionData(SwSectionData const& rOther)
    : m_eType(rOther.m_eType)
    , m_sSectionName(rOther.m_sSectionName)
    , m_sCondition(rOther.m_sCondition)
    , m_sLinkFileName(rOther.m_sLinkFileName)
    , m_sLinkFilePassword(rOther.m_sLinkFilePassword)
    , m_Password(rOther.m_Password)
    , m_bHiddenFlag(rOther.m_bHiddenFlag)
    , m_bProtectFlag(rOther.m_bProtectFlag)
    // --> FME 2004-06-22 #114856# edit in readonly sections
    , m_bEditInReadonlyFlag(rOther.m_bEditInReadonlyFlag)
    // <--
    , m_bHidden(rOther.m_bHidden)
    , m_bCondHiddenFlag(true)
    , m_bConnectFlag(rOther.m_bConnectFlag)
{
}

// the semantics here are weird for reasons of backward compatibility
SwSectionData & SwSectionData::operator= (SwSectionData const& rOther)
{
    m_eType = rOther.m_eType;
    m_sSectionName = rOther.m_sSectionName;
    m_sCondition = rOther.m_sCondition;
    m_sLinkFileName = rOther.m_sLinkFileName;
    m_sLinkFilePassword = rOther.m_sLinkFilePassword;
    m_bConnectFlag = rOther.m_bConnectFlag;
    m_Password = rOther.m_Password;

    m_bEditInReadonlyFlag = rOther.m_bEditInReadonlyFlag;
    m_bProtectFlag = rOther.m_bProtectFlag;

    m_bHidden = rOther.m_bHidden;
    // FIXME: old code did not assign m_bHiddenFlag ?
    // FIXME: why should m_bCondHiddenFlag always default to true?
    m_bCondHiddenFlag = true;

    return *this;
}

// the semantics here are weird for reasons of backward compatibility
bool SwSectionData::operator==(SwSectionData const& rOther) const
{
    return (m_eType == rOther.m_eType)
        && (m_sSectionName == rOther.m_sSectionName)
        && (m_sCondition == rOther.m_sCondition)
        && (m_bHidden == rOther.m_bHidden)
        && (m_bProtectFlag == rOther.m_bProtectFlag)
        && (m_bEditInReadonlyFlag == rOther.m_bEditInReadonlyFlag)
        && (m_sLinkFileName == rOther.m_sLinkFileName)
        && (m_sLinkFilePassword == rOther.m_sLinkFilePassword)
        && (m_Password == rOther.m_Password);
    // FIXME: old code ignored m_bCondHiddenFlag m_bHiddenFlag m_bConnectFlag
}

// SwSection ===========================================================

SwSection::SwSection(
        SectionType const eType, String const& rName, SwSectionFmt & rFormat)
    : SwClient(& rFormat)
    , m_Data(eType, rName)
{
    SwSection *const pParentSect = GetParent();
	if( pParentSect )
	{
		if( pParentSect->IsHiddenFlag() )
        {
            SetHidden( true );
        }

        m_Data.SetProtectFlag( pParentSect->IsProtectFlag() );
        // --> FME 2004-06-22 #114856# edit in readonly sections
        m_Data.SetEditInReadonlyFlag( pParentSect->IsEditInReadonlyFlag() );
        // <--
    }

    if (!m_Data.IsProtectFlag())
    {
        m_Data.SetProtectFlag( rFormat.GetProtect().IsCntntProtected() );
    }

    // --> FME 2004-06-22 #114856# edit in readonly sections
    if (!m_Data.IsEditInReadonlyFlag())
    {
        m_Data.SetEditInReadonlyFlag( rFormat.GetEditInReadonly().GetValue() );
    }
    // <--
}


SwSection::~SwSection()
{
	SwSectionFmt* pFmt = GetFmt();
	if( !pFmt )
		return;

	SwDoc* pDoc = pFmt->GetDoc();
	if( pDoc->IsInDtor() )
	{
		// dann melden wir noch schnell unser Format um ans dflt FrameFmt,
		// damit es keine Abhaengigkeiten gibt
		if( pFmt->DerivedFrom() != pDoc->GetDfltFrmFmt() )
            pFmt->RegisterToFormat( *pDoc->GetDfltFrmFmt() );
	}
	else
	{
		pFmt->Remove( this );				// austragen,

        if (CONTENT_SECTION != m_Data.GetType())
        {
            pDoc->GetLinkManager().Remove( m_RefLink );
        }

        if (m_RefObj.Is())
        {
            pDoc->GetLinkManager().RemoveServer( &m_RefObj );
        }

		// ist die Section der letzte Client im Format, kann dieses
		// geloescht werden
		SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt );
		pFmt->ModifyNotification( &aMsgHint, &aMsgHint );
		if( !pFmt->GetDepends() )
		{
			// Bug: 28191 - nicht ins Undo aufnehmen, sollte schon vorher
			//			geschehen sein!!
            ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
			pDoc->DelSectionFmt( pFmt );	// und loeschen
        }
    }
    if (m_RefObj.Is())
    {
        m_RefObj->Closed();
    }
}

void SwSection::SetSectionData(SwSectionData const& rData)
{
    bool const bOldHidden( m_Data.IsHidden() );
    m_Data = rData;
    // now update format and reflink with new data
//    SetLinkFileName(m_Data.GetLinkFileName()); // old code did not do this?
    // next 2 may actually overwrite m_Data.m_b{Protect,EditInReadonly}Flag
    // in Modify, which should result in same flag value as the old code!
    SetProtect(m_Data.IsProtectFlag());
    SetEditInReadonly(m_Data.IsEditInReadonlyFlag());
    if (bOldHidden != m_Data.IsHidden()) // check if changed...
    {
        ImplSetHiddenFlag(m_Data.IsHidden(), m_Data.IsCondHidden());
    }
}

bool SwSection::DataEquals(SwSectionData const& rCmp) const
{
    // note that the old code compared the flags of the parameter with the
    // format attributes of this; the following mess should do the same...
    (void) GetLinkFileName(); // updates m_sLinkFileName
    bool const bProtect(m_Data.IsProtectFlag());
    bool const bEditInReadonly(m_Data.IsEditInReadonlyFlag());
    const_cast<SwSection*>(this)->m_Data.SetProtectFlag(IsProtect());
    const_cast<SwSection*>(this)->m_Data
        .SetEditInReadonlyFlag(IsEditInReadonly());
    bool const bResult( m_Data == rCmp );
    const_cast<SwSection*>(this)->m_Data.SetProtectFlag(bProtect);
    const_cast<SwSection*>(this)->m_Data.SetEditInReadonlyFlag(bEditInReadonly);
    return bResult;
}


void SwSection::ImplSetHiddenFlag(bool const bTmpHidden, bool const bCondition)
{
	SwSectionFmt* pFmt = GetFmt();
    ASSERT(pFmt, "ImplSetHiddenFlag: no format?");
	if( pFmt )
	{
        const bool bHide = bTmpHidden && bCondition;

        if (bHide) // should be hidden
        {
            if (!m_Data.IsHiddenFlag()) // is not hidden
            {
				// wie sieht es mit dem Parent aus, ist der versteckt ?
				// (eigentlich muesste das vom bHiddenFlag angezeigt werden!)

				// erstmal allen Childs sagen, das sie versteckt sind
				SwMsgPoolItem aMsgItem( RES_SECTION_HIDDEN );
				pFmt->ModifyNotification( &aMsgItem, &aMsgItem );

				// alle Frames loeschen
				pFmt->DelFrms();
			}
        }
        else if (m_Data.IsHiddenFlag()) // show Nodes again
        {
			// alle Frames sichtbar machen ( Childs Sections werden vom
			// MakeFrms beruecksichtigt). Aber nur wenn die ParentSection
			// nichts dagegen hat !
			SwSection* pParentSect = pFmt->GetParentSection();
			if( !pParentSect || !pParentSect->IsHiddenFlag() )
			{
				// erstmal allen Childs sagen, das der Parent nicht mehr
				// versteckt ist
				SwMsgPoolItem aMsgItem( RES_SECTION_NOT_HIDDEN );
				pFmt->ModifyNotification( &aMsgItem, &aMsgItem );

				pFmt->MakeFrms();
			}
		}
	}
}

sal_Bool SwSection::CalcHiddenFlag() const
{
	const SwSection* pSect = this;
	do {
		if( pSect->IsHidden() && pSect->IsCondHidden() )
			return sal_True;
	} while( 0 != ( pSect = pSect->GetParent()) );

	return sal_False;
}

bool SwSection::IsProtect() const
{
    SwSectionFmt *const pFmt( GetFmt() );
    ASSERT(pFmt, "SwSection::IsProtect: no format?");
    return (pFmt)
        ?   pFmt->GetProtect().IsCntntProtected()
        :   IsProtectFlag();
}

// --> FME 2004-06-22 #114856# edit in readonly sections
bool SwSection::IsEditInReadonly() const
{
    SwSectionFmt *const pFmt( GetFmt() );
    ASSERT(pFmt, "SwSection::IsEditInReadonly: no format?");
    return (pFmt)
        ?   pFmt->GetEditInReadonly().GetValue()
        :   IsEditInReadonlyFlag();
}
// <--

void SwSection::SetHidden(bool const bFlag)
{
    if (!m_Data.IsHidden() == !bFlag)
		return;

    m_Data.SetHidden(bFlag);
    ImplSetHiddenFlag(bFlag, m_Data.IsCondHidden());
}


void SwSection::SetProtect(bool const bFlag)
{
    SwSectionFmt *const pFormat( GetFmt() );
    ASSERT(pFormat, "SwSection::SetProtect: no format?");
    if (pFormat)
    {
        SvxProtectItem aItem( RES_PROTECT );
		aItem.SetCntntProtect( (sal_Bool)bFlag );
        pFormat->SetFmtAttr( aItem );
        // note: this will call m_Data.SetProtectFlag via Modify!
    }
    else
    {
        m_Data.SetProtectFlag(bFlag);
    }
}

// --> FME 2004-06-22 #114856# edit in readonly sections
void SwSection::SetEditInReadonly(bool const bFlag)
{
    SwSectionFmt *const pFormat( GetFmt() );
    ASSERT(pFormat, "SwSection::SetEditInReadonly: no format?");
    if (pFormat)
    {
        SwFmtEditInReadonly aItem;
        aItem.SetValue( (sal_Bool)bFlag );
        pFormat->SetFmtAttr( aItem );
        // note: this will call m_Data.SetEditInReadonlyFlag via Modify!
    }
    else
    {
        m_Data.SetEditInReadonlyFlag(bFlag);
    }
}
// <--

void SwSection::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
{
    bool bRemake = false;
    bool bUpdateFtn = false;
	switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
	{
	case RES_ATTRSET_CHG:
		{
			SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet();
			SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet();
			const SfxPoolItem* pItem;

			if( SFX_ITEM_SET == pNewSet->GetItemState(
						RES_PROTECT, sal_False, &pItem ) )
			{
                m_Data.SetProtectFlag( static_cast<SvxProtectItem const*>(pItem)
                        ->IsCntntProtected() );
				pNewSet->ClearItem( RES_PROTECT );
				pOldSet->ClearItem( RES_PROTECT );
			}

            // --> FME 2004-06-22 #114856# edit in readonly sections
            if( SFX_ITEM_SET == pNewSet->GetItemState(
                        RES_EDIT_IN_READONLY, sal_False, &pItem ) )
            {
                m_Data.SetEditInReadonlyFlag(
                    static_cast<SwFmtEditInReadonly const*>(pItem)->GetValue());
                pNewSet->ClearItem( RES_EDIT_IN_READONLY );
                pOldSet->ClearItem( RES_EDIT_IN_READONLY );
            }
            // <--

			if( SFX_ITEM_SET == pNewSet->GetItemState(
						RES_FTN_AT_TXTEND, sal_False, &pItem ) ||
				SFX_ITEM_SET == pNewSet->GetItemState(
						RES_END_AT_TXTEND, sal_False, &pItem ))
            {
                    bUpdateFtn = true;
            }

			if( !pNewSet->Count() )
				return;
		}
		break;

	case RES_PROTECT:
		if( pNew )
		{
            bool bNewFlag =
                static_cast<const SvxProtectItem*>(pNew)->IsCntntProtected();
			if( !bNewFlag )
			{
				// Abschalten: teste ob nicht vielleich ueber die Parents
				// 				doch ein Schutzt besteht!
				const SwSection* pSect = this;
				do {
					if( pSect->IsProtect() )
					{
                        bNewFlag = true;
						break;
					}
                    pSect = pSect->GetParent();
                } while (pSect);
            }

            m_Data.SetProtectFlag( bNewFlag );
        }
		return;
    // --> FME 2004-06-22 #114856# edit in readonly sections
    case RES_EDIT_IN_READONLY:
        if( pNew )
        {
            const bool bNewFlag =
                static_cast<const SwFmtEditInReadonly*>(pNew)->GetValue();
            m_Data.SetEditInReadonlyFlag( bNewFlag );
        }
        return;
    // <--

	case RES_SECTION_HIDDEN:
        m_Data.SetHiddenFlag(true);
		return;

	case RES_SECTION_NOT_HIDDEN:
	case RES_SECTION_RESETHIDDENFLAG:
        m_Data.SetHiddenFlag( m_Data.IsHidden() && m_Data.IsCondHidden() );
		return;

	case RES_COL:
		/* wird ggf. vom Layout erledigt */
		break;

	case RES_FTN_AT_TXTEND:
		if( pNew && pOld )
        {
            bUpdateFtn = true;
        }
		break;

	case RES_END_AT_TXTEND:
		if( pNew && pOld )
        {
            bUpdateFtn = true;
        }
		break;

    default:
		CheckRegistration( pOld, pNew );
        break;
	}

	if( bRemake )
	{
		GetFmt()->DelFrms();
		GetFmt()->MakeFrms();
	}

	if( bUpdateFtn )
	{
		SwSectionNode* pSectNd = GetFmt()->GetSectionNode( sal_False );
		if( pSectNd )
			pSectNd->GetDoc()->GetFtnIdxs().UpdateFtn(SwNodeIndex( *pSectNd ));
	}
}

void SwSection::SetRefObject( SwServerObject* pObj )
{
    m_RefObj = pObj;
}


void SwSection::SetCondHidden(bool const bFlag)
{
    if (!m_Data.IsCondHidden() == !bFlag)
		return;

    m_Data.SetCondHidden(bFlag);
    ImplSetHiddenFlag(m_Data.IsHidden(), bFlag);
}


// setze/erfrage den gelinkten FileNamen
const String& SwSection::GetLinkFileName() const
{
    if (m_RefLink.Is())
    {
		String sTmp;
        switch (m_Data.GetType())
		{
		case DDE_LINK_SECTION:
            sTmp = m_RefLink->GetLinkSourceName();
			break;

		case FILE_LINK_SECTION:
			{
				String sRange, sFilter;
                if (m_RefLink->GetLinkManager() &&
                    m_RefLink->GetLinkManager()->GetDisplayNames(
                        m_RefLink, 0, &sTmp, &sRange, &sFilter ))
                {
                    ( sTmp += sfx2::cTokenSeperator ) += sFilter;
                    ( sTmp += sfx2::cTokenSeperator ) += sRange;
				}
				else if( GetFmt() && !GetFmt()->GetSectionNode() )
				{
					// ist die Section im UndoNodesArray, dann steht
					// der Link nicht im LinkManager, kann also auch nicht
					// erfragt werden. Dann returne den akt. Namen
                    return m_Data.GetLinkFileName();
				}
			}
			break;
        default: break;
		}
        const_cast<SwSection*>(this)->m_Data.SetLinkFileName(sTmp);
    }
    return m_Data.GetLinkFileName();
}


void SwSection::SetLinkFileName(const String& rNew, String const*const pPassWd)
{
    if (m_RefLink.Is())
    {
        m_RefLink->SetLinkSourceName( rNew );
    }
    m_Data.SetLinkFileName(rNew);
	if( pPassWd )
    {
        SetLinkFilePassword( *pPassWd );
    }
}

// falls es ein gelinkter Bereich war, dann muessen alle
// Child-Verknuepfungen sichtbar bemacht werden.
void SwSection::MakeChildLinksVisible( const SwSectionNode& rSectNd )
{
	const SwNode* pNd;
    const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks();
	for( sal_uInt16 n = rLnks.Count(); n; )
	{
        ::sfx2::SvBaseLink* pBLnk = &(*rLnks[ --n ]);
		if( pBLnk && !pBLnk->IsVisible() &&
			pBLnk->ISA( SwBaseLink ) &&
			0 != ( pNd = ((SwBaseLink*)pBLnk)->GetAnchor() ) )
		{
            pNd = pNd->StartOfSectionNode();    // falls SectionNode ist!
			const SwSectionNode* pParent;
			while( 0 != ( pParent = pNd->FindSectionNode() ) &&
					( CONTENT_SECTION == pParent->GetSection().GetType()
						|| pNd == &rSectNd ))
                    pNd = pParent->StartOfSectionNode();

			// steht nur noch in einer normalen Section, also
			// wieder anzeigen
			if( !pParent )
				pBLnk->SetVisible( sal_True );
		}
	}
}

const SwTOXBase* SwSection::GetTOXBase() const
{
	const SwTOXBase* pRet = 0;
	if( TOX_CONTENT_SECTION == GetType() )
		pRet = PTR_CAST( SwTOXBaseSection, this );
	return pRet;
}

// SwSectionFmt ========================================================

SwSectionFmt::SwSectionFmt( SwSectionFmt* pDrvdFrm, SwDoc *pDoc )
	: SwFrmFmt( pDoc->GetAttrPool(), sSectionFmtNm, pDrvdFrm )
{
	LockModify();
    SetFmtAttr( *GetDfltAttr( RES_COL ) );
	UnlockModify();
}

SwSectionFmt::~SwSectionFmt()
{
	if( !GetDoc()->IsInDtor() )
	{
		SwSectionNode* pSectNd;
		const SwNodeIndex* pIdx = GetCntnt( sal_False ).GetCntntIdx();
		if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
			0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
		{
			SwSection& rSect = pSectNd->GetSection();
			// falls es ein gelinkter Bereich war, dann muessen alle
			// Child-Verknuepfungen sichtbar bemacht werden.
			if( rSect.IsConnected() )
				rSect.MakeChildLinksVisible( *pSectNd );

			// vorm loeschen der Nodes pruefe, ob wir uns nicht
			// noch anzeigen muessen!
			if( rSect.IsHiddenFlag() )
			{
				SwSectionPtr pParentSect = rSect.GetParent();
				if( !pParentSect || !pParentSect->IsHiddenFlag() )
				{
					// Nodes wieder anzeigen
                    rSect.SetHidden(false);
				}
			}
            // mba: test iteration; objects are removed while iterating
            // --> OD #i117863#
            // use hint which allows to specify, if the content shall be saved or not
            CallSwClientNotify( SwSectionFrmMoveAndDeleteHint( sal_True ) );
            // <--

			// hebe die Section doch mal auf
			SwNodeRange aRg( *pSectNd, 0, *pSectNd->EndOfSectionNode() );
			GetDoc()->GetNodes().SectionUp( &aRg );
		}
		LockModify();
        ResetFmtAttr( RES_CNTNT );
		UnlockModify();
	}
}


SwSection * SwSectionFmt::GetSection() const
{
	return SwIterator<SwSection,SwSectionFmt>::FirstElement( *this );
}

extern void lcl_DeleteFtn( SwSectionNode *pNd, sal_uLong nStt, sal_uLong nEnd );

//Vernichtet alle Frms in aDepend (Frms werden per PTR_CAST erkannt).
void SwSectionFmt::DelFrms()
{
	SwSectionNode* pSectNd;
	const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
	if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
		0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
	{
        // #147431# : First delete the <SwSectionFrm> of the <SwSectionFmt> instance
        // mba: test iteration as objects are removed in iteration
        // --> OD #i117863#
        // use hint which allows to specify, if the content shall be saved or not
        CallSwClientNotify( SwSectionFrmMoveAndDeleteHint( sal_False ) );
        // <--
 
        // Then delete frames of the nested <SwSectionFmt> instances
        SwIterator<SwSectionFmt,SwSectionFmt> aIter( *this );
        SwSectionFmt *pLast = aIter.First();
        while ( pLast )
        {
            pLast->DelFrms();
            pLast = aIter.Next();
        }

		sal_uLong nEnde = pSectNd->EndOfSectionIndex();
		sal_uLong nStart = pSectNd->GetIndex()+1;
		lcl_DeleteFtn( pSectNd, nStart, nEnde );
	}
	if( pIdx )
	{
		//JP 22.09.98:
		//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#
		SwNodeIndex aNextNd( *pIdx );
		SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection( &aNextNd, sal_True, sal_False );
		if( pCNd )
		{
			const SfxPoolItem& rItem = pCNd->GetSwAttrSet().Get( RES_PAGEDESC );
			pCNd->ModifyNotification( (SfxPoolItem*)&rItem, (SfxPoolItem*)&rItem );
		}
	}
}


//Erzeugt die Ansichten
void SwSectionFmt::MakeFrms()
{
	SwSectionNode* pSectNd;
	const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();

	if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
		0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
	{
		SwNodeIndex aIdx( *pIdx );
		pSectNd->MakeFrms( &aIdx );
	}
}

void SwSectionFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
{
	sal_Bool bClients = sal_False;
	sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
	switch( nWhich )
	{
	case RES_ATTRSET_CHG:
		if( GetDepends() )
		{
			SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet();
			SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet();
			const SfxPoolItem *pItem;
			if( SFX_ITEM_SET == pNewSet->GetItemState(
										RES_PROTECT, sal_False, &pItem ))
			{
				ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
				pNewSet->ClearItem( RES_PROTECT );
				pOldSet->ClearItem( RES_PROTECT );
			}

            // --> FME 2004-06-22 #114856# edit in readonly sections
            if( SFX_ITEM_SET == pNewSet->GetItemState(
                        RES_EDIT_IN_READONLY, sal_False, &pItem ) )
            {
				ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
                pNewSet->ClearItem( RES_EDIT_IN_READONLY );
                pOldSet->ClearItem( RES_EDIT_IN_READONLY );
            }
            // <--

			if( SFX_ITEM_SET == pNewSet->GetItemState(
									RES_FTN_AT_TXTEND, sal_False, &pItem ))
			{
				ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_FTN_AT_TXTEND ), (SfxPoolItem*)pItem );
				pNewSet->ClearItem( RES_FTN_AT_TXTEND );
				pOldSet->ClearItem( RES_FTN_AT_TXTEND );
			}
			if( SFX_ITEM_SET == pNewSet->GetItemState(
									RES_END_AT_TXTEND, sal_False, &pItem ))
			{
				ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_END_AT_TXTEND ), (SfxPoolItem*)pItem );
				pNewSet->ClearItem( RES_END_AT_TXTEND );
				pOldSet->ClearItem( RES_END_AT_TXTEND );
			}
			if( !((SwAttrSetChg*)pOld)->GetChgSet()->Count() )
				return;
		}
		break;

	case RES_SECTION_RESETHIDDENFLAG:
	case RES_FTN_AT_TXTEND:
	case RES_END_AT_TXTEND : bClients = sal_True;
							// no break !!
	case RES_SECTION_HIDDEN:
	case RES_SECTION_NOT_HIDDEN:
		{
			SwSection* pSect = GetSection();
			if( pSect && ( bClients || ( RES_SECTION_HIDDEN == nWhich ?
							!pSect->IsHiddenFlag() : pSect->IsHiddenFlag() ) ) )
			{
                ModifyBroadcast( pOld, pNew );
			}
		}
		return ;


	case RES_PROTECT:
    // --> FME 2004-06-22 #114856# edit in readonly sections
    case RES_EDIT_IN_READONLY:
    // <--
        // diese Messages bis zum Ende des Baums durchreichen !
		if( GetDepends() )
		{
            ModifyBroadcast( pOld, pNew );
		}
		return; 	// das wars

    case RES_OBJECTDYING:
		if( !GetDoc()->IsInDtor() &&
			((SwPtrMsgPoolItem *)pOld)->pObject == (void*)GetRegisteredIn() )
		{
			// mein Parent wird vernichtet, dann an den Parent vom Parent
			// umhaengen und wieder aktualisieren
			SwFrmFmt::Modify( pOld, pNew ); 	//	erst umhaengen !!!
			UpdateParent();
			return;
		}
		break;

	case RES_FMT_CHG:
		if( !GetDoc()->IsInDtor() &&
			((SwFmtChg*)pNew)->pChangedFmt == (void*)GetRegisteredIn() &&
			((SwFmtChg*)pNew)->pChangedFmt->IsA( TYPE( SwSectionFmt )) )
		{
			// mein Parent wird veraendert, muss mich aktualisieren
			SwFrmFmt::Modify( pOld, pNew ); 	//	erst umhaengen !!!
			UpdateParent();
			return;
		}
		break;
	}
	SwFrmFmt::Modify( pOld, pNew );

    if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
    {   // invalidate cached uno object
        SetXTextSection(uno::Reference<text::XTextSection>(0));
    }
}

		// erfrage vom Format Informationen
sal_Bool SwSectionFmt::GetInfo( SfxPoolItem& rInfo ) const
{
	switch( rInfo.Which() )
	{
	case RES_FINDNEARESTNODE:
        if( ((SwFmtPageDesc&)GetFmtAttr( RES_PAGEDESC )).GetPageDesc() )
		{
			const SwSectionNode* pNd = GetSectionNode();
			if( pNd )
				((SwFindNearestNode&)rInfo).CheckNode( *pNd );
		}
		return sal_True;

	case RES_CONTENT_VISIBLE:
		{
			SwFrm* pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*this);
			// if the current section has no own frame search for the children
			if(!pFrm)
			{
                SwIterator<SwSectionFmt,SwSectionFmt> aFormatIter(*this);
				SwSectionFmt* pChild = aFormatIter.First();
				while(pChild && !pFrm)
				{
        			pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*pChild);
					pChild = aFormatIter.Next();
				}
			}
			((SwPtrMsgPoolItem&)rInfo).pObject = pFrm;
		}
		return sal_False;
	}
	return SwModify::GetInfo( rInfo );
}

extern "C" {

	int
#if defined( WNT )
 	__cdecl
#endif
#if defined( ICC )
 	_Optlink
#endif
		lcl_SectionCmpPos( const void *pFirst, const void *pSecond)
	{
		const SwSectionFmt* pFSectFmt = (*(SwSectionPtr*)pFirst)->GetFmt();
		const SwSectionFmt* pSSectFmt = (*(SwSectionPtr*)pSecond)->GetFmt();
		ASSERT( pFSectFmt && pSSectFmt &&
				pFSectFmt->GetCntnt(sal_False).GetCntntIdx() &&
				pSSectFmt->GetCntnt(sal_False).GetCntntIdx(),
					"ungueltige Sections" );
		return (int)((long)pFSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex()) -
				  	pSSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex();
	}

	int
#if defined( WNT )
 	__cdecl
#endif
#if defined( ICC )
 	_Optlink
#endif
		lcl_SectionCmpNm( const void *pFirst, const void *pSecond)
	{
		const SwSectionPtr pFSect = *(SwSectionPtr*)pFirst;
		const SwSectionPtr pSSect = *(SwSectionPtr*)pSecond;
		ASSERT( pFSect && pSSect, "ungueltige Sections" );
        StringCompare const eCmp =
            pFSect->GetSectionName().CompareTo( pSSect->GetSectionName() );
		return eCmp == COMPARE_EQUAL ? 0
							: eCmp == COMPARE_LESS ? 1 : -1;
	}
}

	// alle Sections, die von dieser abgeleitet sind
sal_uInt16 SwSectionFmt::GetChildSections( SwSections& rArr,
										SectionSort eSort,
										sal_Bool bAllSections ) const
{
	rArr.Remove( 0, rArr.Count() );

	if( GetDepends() )
	{
        SwIterator<SwSectionFmt,SwSectionFmt> aIter(*this);
		const SwNodeIndex* pIdx;
		for( SwSectionFmt* pLast = aIter.First(); pLast; pLast = aIter.Next() )
			if( bAllSections ||
				( 0 != ( pIdx = pLast->GetCntnt(sal_False).
				GetCntntIdx()) && &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
			{
				const SwSection* Dummy = pLast->GetSection();
				rArr.C40_INSERT( SwSection,
					Dummy,
					rArr.Count() );
			}

		// noch eine Sortierung erwuenscht ?
		if( 1 < rArr.Count() )
			switch( eSort )
			{
			case SORTSECT_NAME:
				qsort( (void*)rArr.GetData(),
						rArr.Count(),
						sizeof( SwSectionPtr ),
						lcl_SectionCmpNm );
				break;

			case SORTSECT_POS:
				qsort( (void*)rArr.GetData(),
						rArr.Count(),
						sizeof( SwSectionPtr ),
						lcl_SectionCmpPos );
				break;
            case SORTSECT_NOT: break;
			}
	}
	return rArr.Count();
}

	// erfrage, ob sich die Section im Nodes-Array oder UndoNodes-Array
	// befindet.
sal_Bool SwSectionFmt::IsInNodesArr() const
{
	const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
	return pIdx && &pIdx->GetNodes() == &GetDoc()->GetNodes();
}


void SwSectionFmt::UpdateParent()		// Parent wurde veraendert
{
	if( !GetDepends() )
		return;

	SwSectionPtr pSection = 0;
	const SvxProtectItem* pProtect(0);
    // --> FME 2004-06-22 #114856# edit in readonly sections
    const SwFmtEditInReadonly* pEditInReadonly = 0;
    // <--
    bool bIsHidden = false;

	SwClientIter aIter( *this );    // TODO
	::SwClient * pLast = aIter.GoStart();
	if( pLast ) 	// konnte zum Anfang gesprungen werden ??
		do {
			if( pLast->IsA( TYPE(SwSectionFmt) ) )
			{
				if( !pSection )
				{
					pSection = GetSection();
					if( GetRegisteredIn() )
					{
						const SwSectionPtr pPS = GetParentSection();
						pProtect = &pPS->GetFmt()->GetProtect();
                        // --> FME 2004-06-22 #114856# edit in readonly sections
                        pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly();
                        // <--
						bIsHidden = pPS->IsHiddenFlag();
					}
					else
					{
						pProtect = &GetProtect();
                        // --> FME 2004-06-22 #114856# edit in readonly sections
                        pEditInReadonly = &GetEditInReadonly();
                        // <--
                        bIsHidden = pSection->IsHidden();
					}
				}
                if (!pProtect->IsCntntProtected() !=
                    !pSection->IsProtectFlag())
                {
					pLast->ModifyNotification( (SfxPoolItem*)pProtect,
									(SfxPoolItem*)pProtect );
                }

                // --> FME 2004-06-22 #114856# edit in readonly sections
                if (!pEditInReadonly->GetValue() !=
                    !pSection->IsEditInReadonlyFlag())
                {
                    pLast->ModifyNotification( (SfxPoolItem*)pEditInReadonly,
                                    (SfxPoolItem*)pEditInReadonly );
                }
                // <--

				if( bIsHidden == pSection->IsHiddenFlag() )
				{
					SwMsgPoolItem aMsgItem( static_cast<sal_uInt16>(bIsHidden
								? RES_SECTION_HIDDEN
								: RES_SECTION_NOT_HIDDEN ) );
					pLast->ModifyNotification( &aMsgItem, &aMsgItem );
				}
			}
			else if( !pSection &&
					pLast->IsA( TYPE(SwSection) ) )
			{
				pSection = (SwSectionPtr)pLast;
				if( GetRegisteredIn() )
				{
					const SwSectionPtr pPS = GetParentSection();
					pProtect = &pPS->GetFmt()->GetProtect();
                    // --> FME 2004-06-22 #114856# edit in readonly sections
                    pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly();
                    // <--
					bIsHidden = pPS->IsHiddenFlag();
				}
				else
				{
					pProtect = &GetProtect();
                    // --> FME 2004-06-22 #114856# edit in readonly sections
                    pEditInReadonly = &GetEditInReadonly();
                    // <--
                    bIsHidden = pSection->IsHidden();
				}
			}
		} while( 0 != ( pLast = ++aIter ));
}


SwSectionNode* SwSectionFmt::GetSectionNode(bool const bAlways)
{
	const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
	if( pIdx && ( bAlways || &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
		return pIdx->GetNode().GetSectionNode();
	return 0;
}

	// ist die Section eine gueltige fuers GlobalDocument?
const SwSection* SwSectionFmt::GetGlobalDocSection() const
{
	const SwSectionNode* pNd = GetSectionNode();
	if( pNd &&
		( FILE_LINK_SECTION == pNd->GetSection().GetType() ||
		  TOX_CONTENT_SECTION == pNd->GetSection().GetType() ) &&
		pNd->GetIndex() > pNd->GetNodes().GetEndOfExtras().GetIndex() &&
        !pNd->StartOfSectionNode()->IsSectionNode() &&
        !pNd->StartOfSectionNode()->FindSectionNode() )
		return &pNd->GetSection();
	return 0;
}

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

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

bool SwSectionFmt::IsInUndo() const
{
    return !IsInNodesArr();
}

bool SwSectionFmt::IsInContent() const
{
    SwNodeIndex const*const pIdx = GetCntnt(sal_False).GetCntntIdx();
    OSL_ENSURE(pIdx, "SwSectionFmt::IsInContent: no index?");
    return (pIdx) ? !GetDoc()->IsInHeaderFooter(*pIdx) : true;
}

// n.b.: if the section format represents an index, then there is both a
// SwXDocumentIndex and a SwXTextSection instance for this single core object.
// these two can both implement XMetadatable and forward to the same core
// section format.  but here only one UNO object can be returned,
// so always return the text section.
uno::Reference< rdf::XMetadatable >
SwSectionFmt::MakeUnoObject()
{
    uno::Reference<rdf::XMetadatable> xMeta;
    SwSection *const pSection( GetSection() );
    if (pSection)
    {
        xMeta.set(  SwXTextSection::CreateXTextSection(this,
                        TOX_HEADER_SECTION == pSection->GetType()),
                    uno::UNO_QUERY );
    }
    return xMeta;
}


// --> OD 2007-02-14 #b6521322#
// Method to break section links inside a linked section
void lcl_BreakSectionLinksInSect( const SwSectionNode& rSectNd )
{
    if ( !rSectNd.GetDoc() )
    {
        ASSERT( false,
                "method <lcl_RemoveSectionLinksInSect(..)> - no Doc at SectionNode" );
        return;
    }

    if ( !rSectNd.GetSection().IsConnected() )
    {
        ASSERT( false,
                "method <lcl_RemoveSectionLinksInSect(..)> - no Link at Section of SectionNode" );
        return;
    }
    const ::sfx2::SvBaseLink* pOwnLink( &(rSectNd.GetSection().GetBaseLink() ) );
    const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks();
    for ( sal_uInt16 n = rLnks.Count(); n > 0; )
    {
        SwIntrnlSectRefLink* pSectLnk = dynamic_cast<SwIntrnlSectRefLink*>(&(*rLnks[ --n ]));
        if ( pSectLnk && pSectLnk != pOwnLink &&
             pSectLnk->IsInRange( rSectNd.GetIndex(), rSectNd.EndOfSectionIndex() ) )
        {
            // break the link of the corresponding section.
            // the link is also removed from the link manager
            pSectLnk->GetSectNode()->GetSection().BreakLink();

            // for robustness, because link is removed from the link manager
            if ( n > rLnks.Count() )
            {
                n = rLnks.Count();
            }
        }
    }
}
// <--

void lcl_UpdateLinksInSect( SwBaseLink& rUpdLnk, SwSectionNode& rSectNd )
{
	SwDoc* pDoc = rSectNd.GetDoc();
	SwDocShell* pDShell = pDoc->GetDocShell();
	if( !pDShell || !pDShell->GetMedium() )
		return ;

	String sName( pDShell->GetMedium()->GetName() );
	SwBaseLink* pBLink;
	String sMimeType( SotExchange::GetFormatMimeType( FORMAT_FILE ));
    uno::Any aValue;
	aValue <<= ::rtl::OUString( sName );						// beliebiger Name

    const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks();
	for( sal_uInt16 n = rLnks.Count(); n; )
	{
        ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
		if( pLnk && pLnk != &rUpdLnk &&
			OBJECT_CLIENT_FILE == pLnk->GetObjType() &&
			pLnk->ISA( SwBaseLink ) &&
			( pBLink = (SwBaseLink*)pLnk )->IsInRange( rSectNd.GetIndex(),
												rSectNd.EndOfSectionIndex() ) )
		{
			// liegt in dem Bereich: also updaten. Aber nur wenns nicht
			// im gleichen File liegt
			String sFName;
			pDoc->GetLinkManager().GetDisplayNames( pBLink, 0, &sFName, 0, 0 );
			if( sFName != sName )
			{
				pBLink->DataChanged( sMimeType, aValue );

				// ggfs. neu den Link-Pointer wieder suchen, damit nicht einer
				// ausgelassen oder doppelt gerufen wird.
				if( n >= rLnks.Count() && 0 != ( n = rLnks.Count() ))
					--n;

				if( n && pLnk != &(*rLnks[ n ]) )
				{
					// suchen - kann nur davor liegen!!
					while( n )
						if( pLnk == &(*rLnks[ --n ] ) )
							break;
				}
			}
		}
	}
}


// sucht sich die richtige DocShell raus oder erzeugt eine neue:
// Der Return-Wert gibt an, was mit der Shell zu geschehen hat:
//	0 - Fehler, konnte DocShell nicht finden
//	1 - DocShell ist ein existieren Document
//	2 - DocShell wurde neu angelegt, muss also wieder geschlossen werden ( will be assigned to xLockRef additionaly )

int lcl_FindDocShell( SfxObjectShellRef& xDocSh,
                        SfxObjectShellLock& xLockRef,
						const String& rFileName,
						const String& rPasswd,
						String& rFilter,
						sal_Int16 nVersion,
						SwDocShell* pDestSh )
{
	if( !rFileName.Len() )
		return 0;

	// 1. existiert die Datei schon in der Liste aller Dokumente?
	INetURLObject aTmpObj( rFileName );
	aTmpObj.SetMark( aEmptyStr );

	// erstmal nur ueber die DocumentShells laufen und die mit dem
	// Namen heraussuchen:
	TypeId aType( TYPE(SwDocShell) );

	SfxObjectShell* pShell = pDestSh;
	sal_Bool bFirst = 0 != pShell;

	if( !bFirst )
		// keine DocShell uebergeben, also beginne mit der ersten aus der
		// DocShell Liste
		pShell = SfxObjectShell::GetFirst( &aType );

	while( pShell )
	{
		// die wollen wir haben
		SfxMedium* pMed = pShell->GetMedium();
		if( pMed && pMed->GetURLObject() == aTmpObj )
		{
			const SfxPoolItem* pItem;
			if( ( SFX_ITEM_SET == pMed->GetItemSet()->GetItemState(
											SID_VERSION, sal_False, &pItem ) )
					? (nVersion == ((SfxInt16Item*)pItem)->GetValue())
					: !nVersion )
			{
				// gefunden also returnen
				xDocSh = pShell;
				return 1;
			}
		}

		if( bFirst )
		{
			bFirst = sal_False;
			pShell = SfxObjectShell::GetFirst( &aType );
		}
		else
			pShell = SfxObjectShell::GetNext( *pShell, &aType );
	}

	// 2. selbst die Date oeffnen
	SfxMedium* pMed = new SfxMedium( aTmpObj.GetMainURL(
							 INetURLObject::NO_DECODE ), STREAM_READ, sal_True );
	if( INET_PROT_FILE == aTmpObj.GetProtocol() )
		pMed->DownLoad(); 	  // nur mal das Medium anfassen (DownLoaden)

	const SfxFilter* pSfxFlt = 0;
	if( !pMed->GetError() )
	{
        String sFactory(String::CreateFromAscii(SwDocShell::Factory().GetShortName()));
        SfxFilterMatcher aMatcher( sFactory );

        // kein Filter, dann suche ihn. Ansonsten teste, ob der angegebene
		// ein gueltiger ist
		if( rFilter.Len() )
		{
            pSfxFlt = aMatcher.GetFilter4FilterName( rFilter );
		}

		if( nVersion )
			pMed->GetItemSet()->Put( SfxInt16Item( SID_VERSION, nVersion ));

		if( rPasswd.Len() )
			pMed->GetItemSet()->Put( SfxStringItem( SID_PASSWORD, rPasswd ));

		if( !pSfxFlt )
            aMatcher.DetectFilter( *pMed, &pSfxFlt, sal_False, sal_False );

		if( pSfxFlt )
		{
			// ohne Filter geht gar nichts
			pMed->SetFilter( pSfxFlt );

            // if the new shell is created, SfxObjectShellLock should be used to let it be closed later for sure
			xLockRef = new SwDocShell( SFX_CREATE_MODE_INTERNAL );
            xDocSh = (SfxObjectShell*)xLockRef;
			if( xDocSh->DoLoad( pMed ) )
				return 2;
		}
	}

	if( !xDocSh.Is() )		// Medium muss noch geloescht werden
		delete pMed;

	return 0;	// das war wohl nichts
}


void SwIntrnlSectRefLink::DataChanged( const String& rMimeType,
                                const uno::Any & rValue )
{
	SwSectionNode* pSectNd = rSectFmt.GetSectionNode( sal_False );
	SwDoc* pDoc = rSectFmt.GetDoc();

	sal_uLong nDataFormat = SotExchange::GetFormatIdFromMimeType( rMimeType );

	if( !pSectNd || !pDoc || pDoc->IsInDtor() || ChkNoDataFlag() ||
		sfx2::LinkManager::RegisterStatusInfoId() == nDataFormat )
	{
		// sollten wir schon wieder im Undo stehen?
		return ;
	}

    // --> OD 2005-02-11 #i38810# - Due to possible existing signatures, the
    // document has to be modified after updating a link.
    pDoc->SetModified();
    // set additional flag that links have been updated, in order to check this
    // during load.
    pDoc->SetLinksUpdated( sal_True );
    // <--

	// Undo immer abschalten
    bool const bWasUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
    pDoc->GetIDocumentUndoRedo().DoUndo(false);
	sal_Bool bWasVisibleLinks = pDoc->IsVisibleLinks();
	pDoc->SetVisibleLinks( sal_False );

	SwPaM* pPam;
	ViewShell* pVSh = 0;
	SwEditShell* pESh = pDoc->GetEditShell( &pVSh );
	pDoc->LockExpFlds();
	{
		// am Anfang des Bereichs einen leeren TextNode einfuegen
		SwNodeIndex aIdx( *pSectNd, +1 );
		SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
		SwTxtNode* pNewNd = pDoc->GetNodes().MakeTxtNode( aIdx,
						pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );

		if( pESh )
			pESh->StartAllAction();
		else if( pVSh )
			pVSh->StartAction();

		SwPosition aPos( aIdx, SwIndex( pNewNd, 0 ));
		aPos.nNode--;
		pDoc->CorrAbs( aIdx, aEndIdx, aPos, sal_True );

		pPam = new SwPaM( aPos );

		//und alles dahinter liegende loeschen
		aIdx--;
		DelFlyInRange( aIdx, aEndIdx );
		_DelBookmarks(aIdx, aEndIdx);
		aIdx++;

		pDoc->GetNodes().Delete( aIdx, aEndIdx.GetIndex() - aIdx.GetIndex() );
	}

	SwSection& rSection = pSectNd->GetSection();
    rSection.SetConnectFlag(false);

	::rtl::OUString sNewFileName;
	Reader* pRead = 0;
	switch( nDataFormat )
	{
	case FORMAT_STRING:
		pRead = ReadAscii;
		break;

	case FORMAT_RTF:
		pRead = SwReaderWriter::GetReader( READER_WRITER_RTF );
		break;

	case FORMAT_FILE:
		if( rValue.hasValue() && ( rValue >>= sNewFileName ) )
		{
			String sFilter, sRange, sFileName( sNewFileName );
			pDoc->GetLinkManager().GetDisplayNames( this, 0, &sFileName,
													&sRange, &sFilter );

            RedlineMode_t eOldRedlineMode = nsRedlineMode_t::REDLINE_NONE;
			SfxObjectShellRef xDocSh;
            SfxObjectShellLock xLockRef;
			int nRet;
			if( !sFileName.Len() )
			{
				xDocSh = pDoc->GetDocShell();
				nRet = 1;
			}
			else
			{
				nRet = lcl_FindDocShell( xDocSh, xLockRef, sFileName,
                                    rSection.GetLinkFilePassword(),
									sFilter, 0, pDoc->GetDocShell() );
				if( nRet )
				{
					SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc();
					eOldRedlineMode = pSrcDoc->GetRedlineMode();
					pSrcDoc->SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_INSERT );
				}
			}

			if( nRet )
			{
                rSection.SetConnectFlag(true);

				SwNodeIndex aSave( pPam->GetPoint()->nNode, -1 );
				SwNodeRange* pCpyRg = 0;

				if( xDocSh->GetMedium() &&
                    !rSection.GetLinkFilePassword().Len() )
				{
					const SfxPoolItem* pItem;
					if( SFX_ITEM_SET == xDocSh->GetMedium()->GetItemSet()->
						GetItemState( SID_PASSWORD, sal_False, &pItem ) )
                        rSection.SetLinkFilePassword(
								((SfxStringItem*)pItem)->GetValue() );
				}

				SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc();

				if( sRange.Len() )
				{
					// Rekursionen abfangen
					sal_Bool bRecursion = sal_False;
					if( pSrcDoc == pDoc )
					{
						SwServerObjectRef refObj( (SwServerObject*)
										pDoc->CreateLinkSource( sRange ));
						if( refObj.Is() )
						{
							bRecursion = refObj->IsLinkInServer( this ) ||
										ChkNoDataFlag();
						}
					}

					SwNodeIndex& rInsPos = pPam->GetPoint()->nNode;

					SwPaM* pCpyPam = 0;
					if( !bRecursion &&
						pSrcDoc->SelectServerObj( sRange, pCpyPam, pCpyRg )
						&& pCpyPam )
					{
						if( pSrcDoc != pDoc ||
							pCpyPam->Start()->nNode > rInsPos ||
							rInsPos >= pCpyPam->End()->nNode )
                        {
                            pSrcDoc->CopyRange( *pCpyPam, *pPam->GetPoint(),
                                    false );
                        }
						delete pCpyPam;
					}
					if( pCpyRg && pSrcDoc == pDoc &&
						pCpyRg->aStart < rInsPos && rInsPos < pCpyRg->aEnd )
						delete pCpyRg, pCpyRg = 0;
				}
				else if( pSrcDoc != pDoc )
					pCpyRg = new SwNodeRange( pSrcDoc->GetNodes().GetEndOfExtras(), 2,
										  pSrcDoc->GetNodes().GetEndOfContent() );

                // --> OD 2007-11-30 #i81653#
                // Update links of extern linked document or extern linked
                // document section, if section is protected.
                if ( pSrcDoc != pDoc &&
                     rSection.IsProtectFlag() )
                {
                    pSrcDoc->GetLinkManager().UpdateAllLinks( sal_False, sal_True, sal_False, 0 );
                }
                // <--
				if( pCpyRg )
				{
					SwNodeIndex& rInsPos = pPam->GetPoint()->nNode;
					sal_Bool bCreateFrm = rInsPos.GetIndex() <=
								pDoc->GetNodes().GetEndOfExtras().GetIndex() ||
								rInsPos.GetNode().FindTableNode();

					SwTblNumFmtMerge aTNFM( *pSrcDoc, *pDoc );

                    pSrcDoc->CopyWithFlyInFly( *pCpyRg, 0, rInsPos, NULL, bCreateFrm );
					aSave++;

					if( !bCreateFrm )
						::MakeFrms( pDoc, aSave, rInsPos );

					// den letzten Node noch loeschen, aber nur wenn
					// erfolgreich kopiert werden konnte, also der Bereich
					// mehr als 1 Node enthaelt
					if( 2 < pSectNd->EndOfSectionIndex() - pSectNd->GetIndex() )
					{
						aSave = rInsPos;
						pPam->Move( fnMoveBackward, fnGoNode );
						pPam->SetMark();	// beide SwPositions ummelden!

						pDoc->CorrAbs( aSave, *pPam->GetPoint(), 0, sal_True );
						pDoc->GetNodes().Delete( aSave, 1 );
					}
					delete pCpyRg;
				}

                // --> OD 2007-02-14 #b6521322#
                lcl_BreakSectionLinksInSect( *pSectNd );
                // <--

                // update alle Links in diesem Bereich
				lcl_UpdateLinksInSect( *this, *pSectNd );
			}
			if( xDocSh.Is() )
			{
				if( 2 == nRet )
					xDocSh->DoClose();
                else if( ((SwDocShell*)&xDocSh)->GetDoc() )
					((SwDocShell*)&xDocSh)->GetDoc()->SetRedlineMode(
								eOldRedlineMode );
			}
		}
		break;
	}

	// !!!! DDE nur updaten wenn Shell vorhanden ist??
    uno::Sequence< sal_Int8 > aSeq;
	if( pRead && rValue.hasValue() && ( rValue >>= aSeq ) )
	{
		if( pESh )
		{
			pESh->Push();
			SwPaM* pCrsr = pESh->GetCrsr();
			*pCrsr->GetPoint() = *pPam->GetPoint();
			delete pPam;
			pPam = pCrsr;
		}

		SvMemoryStream aStrm( (void*)aSeq.getConstArray(), aSeq.getLength(),
								STREAM_READ );
		aStrm.Seek( 0 );

#if OSL_DEBUG_LEVEL > 1
		{
			SvFileStream aDeb( String::CreateFromAscii(
					"file:///d|/temp/update.txt" ), STREAM_WRITE );
			aDeb << aStrm;
		}
		aStrm.Seek( 0 );
#endif

        // TODO/MBA: it's impossible to set a BaseURL here!
        SwReader aTmpReader( aStrm, aEmptyStr, pDoc->GetDocShell()->GetMedium()->GetBaseURL(), *pPam );

		if( !IsError( aTmpReader.Read( *pRead ) ))
        {
            rSection.SetConnectFlag(true);
        }

		if( pESh )
		{
			pESh->Pop( sal_False );
			pPam = 0;			        // pam is deleted before
		}
	}


    // remove all undo actions and turn undo on again
    pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
    pDoc->GetIDocumentUndoRedo().DoUndo(bWasUndo);
	pDoc->SetVisibleLinks( bWasVisibleLinks );

	pDoc->UnlockExpFlds();
	if( !pDoc->IsExpFldsLocked() )
		pDoc->UpdateExpFlds(NULL, true);

	if( pESh )
		pESh->EndAllAction();
	else if( pVSh )
		pVSh->EndAction();
	delete pPam;			// wurde am Anfang angelegt
}


void SwIntrnlSectRefLink::Closed()
{
	SwDoc* pDoc = rSectFmt.GetDoc();
	if( pDoc && !pDoc->IsInDtor() )
	{
		// Advise verabschiedet sich, den Bereich als nicht geschuetzt
		// kennzeichnen und das Flag umsetzen

		const SwSectionFmts& rFmts = pDoc->GetSections();
		for( sal_uInt16 n = rFmts.Count(); n; )
			if( rFmts[ --n ] == &rSectFmt )
			{
				ViewShell* pSh;
				SwEditShell* pESh = pDoc->GetEditShell( &pSh );

				if( pESh )
					pESh->StartAllAction();
				else
					pSh->StartAction();

                SwSectionData aSectionData(*rSectFmt.GetSection());
                aSectionData.SetType( CONTENT_SECTION );
                aSectionData.SetLinkFileName( aEmptyStr );
                aSectionData.SetHidden( false );
                aSectionData.SetProtectFlag( false );
                // --> FME 2004-06-22 #114856# edit in readonly sections
                aSectionData.SetEditInReadonlyFlag( false );
                // <--

                aSectionData.SetConnectFlag( false );

                pDoc->UpdateSection( n, aSectionData );

				// alle in der Section liegenden Links werden sichtbar
				SwSectionNode* pSectNd = rSectFmt.GetSectionNode( sal_False );
				if( pSectNd )
					pSectNd->GetSection().MakeChildLinksVisible( *pSectNd );

				if( pESh )
					pESh->EndAllAction();
				else
					pSh->EndAction();
				break;
			}
	}
	SvBaseLink::Closed();
}


void SwSection::CreateLink( LinkCreateType eCreateType )
{
	SwSectionFmt* pFmt = GetFmt();
    ASSERT(pFmt, "SwSection::CreateLink: no format?");
    if (!pFmt || (CONTENT_SECTION == m_Data.GetType()))
		return ;

    sal_uInt16 nUpdateType = sfx2::LINKUPDATE_ALWAYS;

    if (!m_RefLink.Is())
    {
        // create BaseLink
        m_RefLink = new SwIntrnlSectRefLink( *pFmt, nUpdateType, FORMAT_RTF );
    }
    else
    {
        pFmt->GetDoc()->GetLinkManager().Remove( m_RefLink );
    }

    SwIntrnlSectRefLink *const pLnk =
        static_cast<SwIntrnlSectRefLink*>(& m_RefLink);

    String sCmd( m_Data.GetLinkFileName() );
	xub_StrLen nPos;
	while( STRING_NOTFOUND != (nPos = sCmd.SearchAscii( "  " )) )
		sCmd.Erase( nPos, 1 );

	pLnk->SetUpdateMode( nUpdateType );
	pLnk->SetVisible( pFmt->GetDoc()->IsVisibleLinks() );

    switch (m_Data.GetType())
	{
	case DDE_LINK_SECTION:
		pLnk->SetLinkSourceName( sCmd );
		pFmt->GetDoc()->GetLinkManager().InsertDDELink( pLnk );
		break;
	case FILE_LINK_SECTION:
		{
			pLnk->SetContentType( FORMAT_FILE );
            String sFltr( sCmd.GetToken( 1, sfx2::cTokenSeperator ) );
            String sRange( sCmd.GetToken( 2, sfx2::cTokenSeperator ) );
			pFmt->GetDoc()->GetLinkManager().InsertFileLink( *pLnk,
                                static_cast<sal_uInt16>(m_Data.GetType()),
                                sCmd.GetToken( 0, sfx2::cTokenSeperator ),
								( sFltr.Len() ? &sFltr : 0 ),
								( sRange.Len() ? &sRange : 0 ) );
		}
		break;
	default:
		ASSERT( !this, "Was ist das fuer ein Link?" )
	}

	switch( eCreateType )
	{
	case CREATE_CONNECT:			// Link gleich connecten
		pLnk->Connect();
		break;

	case CREATE_UPDATE: 		// Link connecten und updaten
		pLnk->Update();
		break;
    case CREATE_NONE: break;
	}
}

// --> OD 2007-02-14 #b6521322#
void SwSection::BreakLink()
{
    const SectionType eCurrentType( GetType() );
    if ( eCurrentType == CONTENT_SECTION ||
         eCurrentType == TOX_HEADER_SECTION ||
         eCurrentType == TOX_CONTENT_SECTION )
    {
        // nothing to do
        return;
    }

    // release link, if it exists
    if (m_RefLink.Is())
    {
        SwSectionFmt *const pFormat( GetFmt() );
        ASSERT(pFormat, "SwSection::BreakLink: no format?");
        if (pFormat)
        {
            pFormat->GetDoc()->GetLinkManager().Remove( m_RefLink );
        }
        m_RefLink.Clear();
    }
    // change type
    SetType( CONTENT_SECTION );
    // reset linked file data
    SetLinkFileName( aEmptyStr );
    SetLinkFilePassword( aEmptyStr );
}
// <--

const SwNode* SwIntrnlSectRefLink::GetAnchor() const
{
	return rSectFmt.GetSectionNode( sal_False );
}


sal_Bool SwIntrnlSectRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd,
									 xub_StrLen , xub_StrLen ) const
{
	SwStartNode* pSttNd = rSectFmt.GetSectionNode( sal_False );
	return pSttNd &&
			nSttNd < pSttNd->GetIndex() &&
			pSttNd->EndOfSectionIndex() < nEndNd;
}



