/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/


#ifdef _MSC_VER
#pragma hdrstop
#endif

#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/text/ControlCharacter.hpp>

#include <cmdid.h>
#include <osl/mutex.hxx>
#include <vcl/svapp.hxx>
#include <rtl/uuid.h>

#include <osl/diagnose.h>

#include <unoobj.hxx>
#include <unoport.hxx>
#include <unotbl.hxx>
#include <unoidx.hxx>
#include <unoframe.hxx>
#include <unofield.hxx>
#include <unodraw.hxx>
#include <unoredline.hxx>
#include <unomap.hxx>
#include <docsh.hxx>
#include <docary.hxx>

#include <horiornt.hxx>

#include <doc.hxx>
#include <redline.hxx>
#include <section.hxx>
#include <unocrsr.hxx>
#include <bookmrk.hxx>
#include <fmthbsh.hxx>
#include <crsskip.hxx>
#include <bf_sfx2/sfxuno.hxx>
namespace binfilter {

using namespace ::com::sun::star;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::beans;

using rtl::OUString;

const sal_Char cInvalidObject[] = "this object is invalid";
/******************************************************************
 * SwXText
 ******************************************************************/


const SwStartNode *SwXText::GetStartNode() const
{
    return GetDoc()->GetNodes().GetEndOfContent().StartOfSectionNode();
}

uno::Reference< XTextCursor >   SwXText::createCursor() throw ( ::com::sun::star::uno::RuntimeException)
{
    uno::Reference< XTextCursor >  xRet;
    OUString sRet;
    if(IsValid())
    {
        SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
        SwPosition aPos(rNode);
        xRet =  (XWordCursor*)new SwXTextCursor(this, aPos, GetTextType(), GetDoc());
        xRet->gotoStart(sal_False);
    }
    return xRet;
}

SwXText::SwXText(SwDoc* pDc, CursorType eType) :
    pDoc(pDc),
    bObjectValid(0 != pDc),
    eCrsrType(eType),
    _pMap(aSwMapProvider.GetPropertyMap(PROPERTY_MAP_TEXT))
{
}

SwXText::~SwXText()
{
}

uno::Any SAL_CALL SwXText::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException)
{
    const uno::Type& rXTextType = ::getCppuType((uno::Reference< XText >*)0);
    const uno::Type& rXTextRangeCompareType = ::getCppuType((uno::Reference< XTextRangeCompare >*)0);
    const uno::Type& rXSimpleTextType = ::getCppuType((const uno::Reference< XSimpleText >*)0);
    const uno::Type& rXTextRangeType = ::getCppuType((uno::Reference< XTextRange >*)0);
    const uno::Type& rXTypeProviderType = ::getCppuType((uno::Reference< lang::XTypeProvider >*)0);
    const uno::Type& rXTextContentInsert = ::getCppuType((uno::Reference< XRelativeTextContentInsert >*)0);
    const uno::Type& rXTextContentRemove = ::getCppuType((uno::Reference< XRelativeTextContentRemove >*)0);
    const uno::Type& rXPropertySet = ::getCppuType((uno::Reference<XPropertySet>*)0);
    const uno::Type& rXUnoTunnel = ::getCppuType((uno::Reference< XUnoTunnel >*)0);

    uno::Any aRet;
    if(rType == rXTextType)
    {
        uno::Reference< XText > xRet = this;
        aRet.setValue(&xRet, rXTextType);
    }
    else if(rType == rXSimpleTextType)
    {
        uno::Reference< XSimpleText > xRet = this;
        aRet.setValue(&xRet, rXSimpleTextType);
    }
    else if(rType == rXTextRangeType)
    {
        uno::Reference< XTextRange > xRet = this;
        aRet.setValue(&xRet, rXTextRangeType);
    }
    else if(rType == rXTextRangeCompareType)
    {
        uno::Reference< XTextRangeCompare > xRet = this;
        aRet.setValue(&xRet, rXTextRangeCompareType);
    }
    else if(rType == rXTypeProviderType)
    {
        uno::Reference< lang::XTypeProvider > xRet = this;
        aRet.setValue(&xRet, rXTypeProviderType);
    }
    else if(rType == rXTextContentInsert)
    {
        uno::Reference< XRelativeTextContentInsert > xRet = this;
        aRet.setValue(&xRet, rXTextContentInsert);
    }
    else if(rType == rXTextContentRemove)
    {
        uno::Reference< XRelativeTextContentRemove > xRet = this;
        aRet.setValue(&xRet, rXTextContentRemove);
    }
    else if(rType == rXPropertySet)
    {
        uno::Reference< XPropertySet > xRet = this;
        aRet.setValue(&xRet, rXPropertySet);
    }
    else if(rType == rXUnoTunnel )
    {
        uno::Reference< XUnoTunnel > xRet = this;
        aRet.setValue(&xRet, rXUnoTunnel);
    }
    return aRet;
}

uno::Sequence< uno::Type > SAL_CALL SwXText::getTypes() throw(uno::RuntimeException)
{
    uno::Sequence< uno::Type > aRet(6);
    uno::Type* pTypes = aRet.getArray();
    pTypes[0] = ::getCppuType((uno::Reference< XText >*)0);
    pTypes[1] = ::getCppuType((uno::Reference< XTextRangeCompare >*)0);
    pTypes[2] = ::getCppuType((uno::Reference< XRelativeTextContentInsert >*)0);
    pTypes[3] = ::getCppuType((uno::Reference< XRelativeTextContentRemove >*)0);
    pTypes[4] = ::getCppuType((uno::Reference< XUnoTunnel >*)0);
    pTypes[5] = ::getCppuType((uno::Reference< XPropertySet >*)0);

    return aRet;
}

/*-----------------------------------------------------------------------
    Gehoert der Range in den Text ? - dann einfuegen
  -----------------------------------------------------------------------*/
void SwXText::insertString(const uno::Reference< XTextRange > & xTextRange,
                                const OUString& aString, sal_Bool bAbsorb)
                                throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    if(GetDoc() && xTextRange.is())
    {
        uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
        SwXTextRange* pRange = 0;
        OTextCursorHelper* pCursor = 0;
        if(xRangeTunnel.is())
        {
            pRange = (SwXTextRange*)xRangeTunnel->getSomething(
                                    SwXTextRange::getUnoTunnelId());
            pCursor = (OTextCursorHelper*)xRangeTunnel->getSomething(
                                    OTextCursorHelper::getUnoTunnelId());
        }

        if( (pRange && pRange->GetDoc() == GetDoc()) ||
            (pCursor && pCursor->GetDoc() == GetDoc()) )
        {
            const SwStartNode* pOwnStartNode = GetStartNode();
            if(pCursor)
            {
                const SwStartNode* pTmp = pCursor->GetPaM()->GetNode()->FindStartNode();
                while(pTmp && pTmp->IsSectionNode())
                {
                    pTmp = pTmp->FindStartNode();
                }
                if( !pOwnStartNode || pOwnStartNode != pTmp)
                {
                    throw uno::RuntimeException();
                }
            }
            else //dann pRange
            {
                SwBookmark* pBkm = pRange->GetBookmark();
                const SwStartNode* pTmp = pBkm->GetPos().nNode.GetNode().FindStartNode();
                while( pTmp && pTmp->IsSectionNode())
                {
                    pTmp = pTmp->FindStartNode();
                }
                if( !pOwnStartNode || pOwnStartNode != pTmp)
                {
                    throw uno::RuntimeException();
                }
            }
            if(bAbsorb)
            {
                xTextRange->setString(aString);
            }
            else
            {
                //hier wird ein PaM angelegt, der vor dem Parameter-PaM liegt, damit der
                //Text davor eingefuegt wird
                UnoActionContext aContext(GetDoc());
                const SwPosition* pPos = pCursor ? pCursor->GetPaM()->Start() : &pRange->GetBookmark()->GetPos();
                SwPaM aInsertPam(*pPos);
                if(!GetDoc()->Insert(aInsertPam, aString ))
                    OSL_FAIL("Text wurde nicht eingefuegt");
            }
        }
        else
        {
            throw uno::RuntimeException();
        }
    }
    else
    {
        throw uno::RuntimeException();
    }
}

void SwXText::insertControlCharacter(const uno::Reference< XTextRange > & xTextRange,
                sal_Int16 nControlCharacter, sal_Bool bAbsorb)
                throw( lang::IllegalArgumentException, uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    if(GetDoc() && xTextRange.is())
    {
        SwUnoInternalPaM aPam(*GetDoc());
        if(SwXTextRange::XTextRangeToSwPaM(aPam, xTextRange))
        {
            //Steuerzeichen einfuegen
            SwPaM aTmp(*aPam.Start());
            if(bAbsorb && aPam.HasMark())
                pDoc->DeleteAndJoin(aPam);

            sal_Unicode cIns = 0;
            switch( nControlCharacter )
            {
                case ControlCharacter::PARAGRAPH_BREAK :
                    // eine Tabellen Zelle wird jetzt zu einer normalen Textzelle!
                    pDoc->ClearBoxNumAttrs( aTmp.GetPoint()->nNode );
                    pDoc->SplitNode( *aTmp.GetPoint(), sal_False );
                    break;
                case ControlCharacter::APPEND_PARAGRAPH:
                {
                    pDoc->ClearBoxNumAttrs( aTmp.GetPoint()->nNode );
                    pDoc->AppendTxtNode( *aTmp.GetPoint() );

                    uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
                    SwXTextRange* pRange = 0;
                    OTextCursorHelper* pCursor = 0;
                    if(xRangeTunnel.is())
                    {
                        pRange = (SwXTextRange*)xRangeTunnel->getSomething(
                                                SwXTextRange::getUnoTunnelId());
                        pCursor = (OTextCursorHelper*)xRangeTunnel->getSomething(
                                                OTextCursorHelper::getUnoTunnelId());
                    }
                    if(pRange)
                    {
                        pRange->_CreateNewBookmark(aTmp);
                    }
                    else if(pCursor)
                    {
                        SwPaM* pCrsr = pCursor->GetPaM();
                        *pCrsr->GetPoint() = *aTmp.GetPoint();
                        pCrsr->DeleteMark();
                    }
                }
                break;
                case ControlCharacter::LINE_BREAK:  cIns = 10;      break;
                case ControlCharacter::SOFT_HYPHEN: cIns = CHAR_SOFTHYPHEN; break;
                case ControlCharacter::HARD_HYPHEN: cIns = CHAR_HARDHYPHEN; break;
                case ControlCharacter::HARD_SPACE:  cIns = CHAR_HARDBLANK;  break;
            }
            if( cIns )
                pDoc->Insert( aTmp, cIns );

            if(bAbsorb)
            {
                uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
                SwXTextRange* pRange = 0;
                OTextCursorHelper* pCursor = 0;
                if(xRangeTunnel.is())
                {
                    pRange = (SwXTextRange*)xRangeTunnel->getSomething(
                                            SwXTextRange::getUnoTunnelId());
                    pCursor = (OTextCursorHelper*)xRangeTunnel->getSomething(
                                            OTextCursorHelper::getUnoTunnelId());
                }

                SwCursor aCrsr(*aTmp.GetPoint());
                SwXTextCursor::SelectPam(aCrsr, sal_True);
                aCrsr.Left(1, CRSR_SKIP_CHARS);
                //hier muss der uebergebene PaM umgesetzt werden:
                if(pRange)
                    pRange->_CreateNewBookmark(aCrsr);
                else
                {
                    SwPaM* pUnoCrsr = pCursor->GetPaM();
                    *pUnoCrsr->GetPoint() = *aCrsr.GetPoint();
                    if(aCrsr.HasMark())
                    {
                        pUnoCrsr->SetMark();
                        *pUnoCrsr->GetMark() = *aCrsr.GetMark();
                    }
                    else
                        pUnoCrsr->DeleteMark();
                }
            }
        }
    }
    else
        throw uno::RuntimeException();
}


void SwXText::insertTextContent(const uno::Reference< XTextRange > & xRange,
                const uno::Reference< XTextContent > & xContent, sal_Bool bAbsorb)
                throw( lang::IllegalArgumentException, uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    // erstmal testen, ob der Range an der richtigen Stelle ist und dann
    // am Sw-Content attachToRange aufrufen
    if(!GetDoc())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    if(xRange.is() && xContent.is())
    {
        SwUnoInternalPaM aPam(*GetDoc());
        if(SwXTextRange::XTextRangeToSwPaM(aPam, xRange))
        {
            uno::Reference<lang::XUnoTunnel> xRangeTunnel( xRange, uno::UNO_QUERY);
            SwXTextRange* pRange = 0;
            OTextCursorHelper* pCursor = 0;
            SwXTextPortion* pPortion = 0;
            SwXText* pText = 0;
            if(xRangeTunnel.is())
            {
                pRange = (SwXTextRange*)xRangeTunnel->getSomething(
                                        SwXTextRange::getUnoTunnelId());
                pCursor = (OTextCursorHelper*)xRangeTunnel->getSomething(
                                        OTextCursorHelper::getUnoTunnelId());
                pPortion = (SwXTextPortion*)xRangeTunnel->getSomething(
                                        SwXTextPortion::getUnoTunnelId());
                pText = (SwXText*)xRangeTunnel->getSomething(
                                        SwXText::getUnoTunnelId());
            }

            const SwStartNode* pOwnStartNode = GetStartNode();
            SwStartNodeType eSearchNodeType = SwNormalStartNode;
            switch(eCrsrType)
            {
                case CURSOR_FRAME:      eSearchNodeType = SwFlyStartNode;       break;
                case CURSOR_TBLTEXT:    eSearchNodeType = SwTableBoxStartNode;  break;
                case CURSOR_FOOTNOTE:   eSearchNodeType = SwFootnoteStartNode;  break;
                case CURSOR_HEADER:     eSearchNodeType = SwHeaderStartNode;    break;
                case CURSOR_FOOTER:     eSearchNodeType = SwFooterStartNode;    break;
                default:
                    break;
            }

            const SwNode* pSrcNode = 0;
            if(pCursor && pCursor->GetPaM())
            {
                pSrcNode = pCursor->GetPaM()->GetNode();
            }
            else if (pRange && pRange->GetBookmark())
            {
                SwBookmark* pBkm = pRange->GetBookmark();
                pSrcNode = &pBkm->GetPos().nNode.GetNode();
            }
            else if (pPortion && pPortion->GetCrsr())
            {
                pSrcNode = pPortion->GetCrsr()->GetNode();
            }
            else if (pText)
            {
                Reference<XTextCursor> xTextCursor = pText->createCursor();
                xTextCursor->gotoEnd(sal_True);
                Reference<XUnoTunnel> xCrsrTunnel( xTextCursor, UNO_QUERY );
                pCursor = (OTextCursorHelper*)xCrsrTunnel->getSomething(
                        OTextCursorHelper::getUnoTunnelId() );
                pSrcNode = pCursor->GetPaM()->GetNode();
            }
            else
                throw lang::IllegalArgumentException();

            const SwStartNode* pTmp = pSrcNode->FindSttNodeByType(eSearchNodeType);

            //SectionNodes ueberspringen
            while(pTmp && pTmp->IsSectionNode())
            {
                pTmp = pTmp->FindStartNode();
            }
            //if the document starts with a section
            while(pOwnStartNode->IsSectionNode())
            {
                pOwnStartNode = pOwnStartNode->FindStartNode();
            }
            //this checks if (this) and xRange are in the same XText interface
            if(pOwnStartNode != pTmp)
            {
                RuntimeException aRunException;
                aRunException.Message = C2U("text interface and cursor not related");
                throw aRunException;
            }
            // Sonderbehandlung fuer Contents, die den Range nicht ersetzen, sonder darueber gelegt werden
            // Bookmarks, IndexEntry
            sal_Bool bAttribute = sal_False;
            uno::Reference<lang::XUnoTunnel> xContentTunnel( xContent, uno::UNO_QUERY);
            if(!xContentTunnel.is())
            {
                IllegalArgumentException aArgException;
                aArgException.Message = C2U("text content doesn't support ::com::sun::star::lang::XUnoTunnel");
                throw aArgException;
            }
            SwXDocumentIndexMark* pDocumentIndexMark =
                (SwXDocumentIndexMark*)xContentTunnel->getSomething(
                                        SwXDocumentIndexMark::getUnoTunnelId());


            SwXTextSection* pSection = (SwXTextSection*)xContentTunnel->getSomething(
                                        SwXTextSection::getUnoTunnelId());

            SwXBookmark* pBookmark = (SwXBookmark*)xContentTunnel->getSomething(
                                        SwXBookmark::getUnoTunnelId());


            SwXReferenceMark* pReferenceMark = (SwXReferenceMark*)
                        xContentTunnel->getSomething(
                                        SwXReferenceMark::getUnoTunnelId());

            bAttribute = pBookmark || pDocumentIndexMark || pSection || pReferenceMark;

            if(bAbsorb && !bAttribute)
            {
                xRange->setString(aEmptyStr);
            }
            //hier wird tatsaechlich eingefuegt
            uno::Reference< XTextRange >  xTempRange;
            if(bAttribute && bAbsorb)
                xTempRange = xRange;
            else
                xTempRange = xRange->getStart();
            SwXTextTable* pTable = (SwXTextTable*)
                        xContentTunnel->getSomething(
                                        SwXTextTable::getUnoTunnelId());

            if(pTable)
                pTable->attachToRange(xTempRange);
            else
            {
                if(pBookmark)
                    pBookmark ->attachToRange(xTempRange);
                else
                {
                    if(pSection)
                        pSection ->attachToRange(xTempRange);
                    else
                    {
                        SwXFootnote* pFootnote = (SwXFootnote*)
                                xContentTunnel->getSomething(
                                                SwXFootnote::getUnoTunnelId());

                        if(pFootnote)
                            pFootnote->attachToRange(xTempRange);
                        else
                        {
                            if(pReferenceMark)
                                pReferenceMark->attachToRange(xTempRange);
                            else
                            {
                                SwXFrame* pFrame = (SwXFrame*)
                                    xContentTunnel->getSomething(
                                                    SwXFrame::getUnoTunnelId());

                                if(pFrame)
                                    pFrame->attachToRange(xTempRange);
                                else
                                {
                                    SwXDocumentIndex* pDocumentIndex = (SwXDocumentIndex*)
                                        xContentTunnel->getSomething(
                                                        SwXDocumentIndex::getUnoTunnelId());

                                    if(pDocumentIndex)
                                        pDocumentIndex->attachToRange(xTempRange);
                                    else
                                    {
                                        if(pDocumentIndexMark)
                                            pDocumentIndexMark->attachToRange(xTempRange);
                                        else
                                        {
                                            SwXTextField* pTextField = (SwXTextField*)
                                                xContentTunnel->getSomething(
                                                                SwXTextField::getUnoTunnelId());

                                            if(pTextField)
                                                pTextField->attachToRange(xTempRange);
                                            else
                                            {
                                                uno::Reference<beans::XPropertySet> xShapeProperties(xContent, uno::UNO_QUERY);
                                                SwXShape* pShape = 0;
                                                if(xShapeProperties.is())
                                                    pShape = (SwXShape*)xContentTunnel->getSomething(
                                                                            SwXShape::getUnoTunnelId());
                                                if(pShape)
                                                {
                                                    uno::Any aPos(&xRange,
                                                        ::getCppuType((uno::Reference<XTextRange>*)0));
                                                    pShape->setPropertyValue(C2U("TextRange"), aPos);

                                                    uno::Reference<frame::XModel> xModel =
                                                                    pDoc->GetDocShell()->GetBaseModel();
                                                    uno::Reference<drawing::XDrawPageSupplier> xPageSupp(
                                                                xModel, uno::UNO_QUERY);

                                                    uno::Reference<drawing::XDrawPage> xPage = xPageSupp->getDrawPage();

                                                    uno::Reference<drawing::XShape> xShape((cppu::OWeakObject*)pShape,
                                                                                                            uno::UNO_QUERY);
                                                    //nuer die XShapes haengen an der Sw-Drawpage
                                                    uno::Reference<drawing::XShapes> xShps(xPage, uno::UNO_QUERY);
                                                    xShps->add(xShape);
                                                }
                                                else
                                                {
                                                    IllegalArgumentException aArgException;
                                                    aArgException.Message = C2U("unknown text content");
                                                    throw aArgException;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        else
        {
            IllegalArgumentException aIllegal;
            aIllegal.Message = C2U("first parameter invalid");
            throw aIllegal;
        }
    }
    else
    {
        IllegalArgumentException aIllegal;
        if(!xRange.is())
            aIllegal.Message = C2U("first parameter invalid;");
        if(!xContent.is())
            aIllegal.Message += C2U("second parameter invalid");
        throw aIllegal;
    }

}

void SwXText::insertTextContentBefore(
    const Reference< XTextContent>& xNewContent,
    const Reference< XTextContent>& xSuccessor)
        throw(IllegalArgumentException, RuntimeException)
{
    SolarMutexGuard aGuard;
    if(!GetDoc())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }

    SwXParagraph* pPara = SwXParagraph::GetImplementation(xNewContent);
    if(!pPara || !pPara->IsDescriptor() || !xSuccessor.is())
        throw IllegalArgumentException();

    sal_Bool bRet = FALSE;
    SwXTextSection* pXSection = SwXTextSection::GetImplementation( xSuccessor );
    SwXTextTable* pXTable = SwXTextTable::GetImplementation(xSuccessor );
    SwFrmFmt* pTableFmt = pXTable ? pXTable->GetFrmFmt() : 0;
    SwUnoCrsr* pUnoCrsr = 0;
    if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
    {
        SwTable* pTable = SwTable::FindTable( pTableFmt );
        SwTableNode* pTblNode = pTable->GetTableNode();

        SwNodeIndex aTblIdx(  *pTblNode, -1 );
        SwPosition aBefore(aTblIdx);
        bRet = GetDoc()->AppendTxtNode( aBefore );
        pUnoCrsr = GetDoc()->CreateUnoCrsr( aBefore, FALSE);
    }
    else if(pXSection &&
        pXSection->GetFmt() &&
            pXSection->GetFmt()->GetDoc() == GetDoc())
    {
        SwSectionFmt* pSectFmt = pXSection->GetFmt();
        SwSectionNode* pSectNode = pSectFmt->GetSectionNode();

        SwNodeIndex aSectIdx(  *pSectNode, -1 );
        SwPosition aBefore(aSectIdx);
        bRet = GetDoc()->AppendTxtNode( aBefore );
        pUnoCrsr = GetDoc()->CreateUnoCrsr( aBefore, FALSE);
    }
    if(!bRet)
        throw IllegalArgumentException();
    else
    {
        pPara->attachToText(this, pUnoCrsr);
    }

}

void SwXText::insertTextContentAfter(
    const Reference< XTextContent>& xNewContent,
    const Reference< XTextContent>& xPredecessor)
        throw(IllegalArgumentException, RuntimeException)
{
    SolarMutexGuard aGuard;
    if(!GetDoc())
        throw RuntimeException();
    SwXParagraph* pPara = SwXParagraph::GetImplementation(xNewContent);
    if(!pPara || !pPara->IsDescriptor() || !xPredecessor.is())
        throw IllegalArgumentException();

    SwUnoCrsr* pUnoCrsr = 0;
    SwXTextSection* pXSection = SwXTextSection::GetImplementation( xPredecessor );
    SwXTextTable* pXTable = SwXTextTable::GetImplementation(xPredecessor );
    SwFrmFmt* pTableFmt = pXTable ? pXTable->GetFrmFmt() : 0;
    sal_Bool bRet = FALSE;
    if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
    {
        SwTable* pTable = SwTable::FindTable( pTableFmt );
        SwTableNode* pTblNode = pTable->GetTableNode();

        SwEndNode* pTableEnd = pTblNode->EndOfSectionNode();
        SwPosition aTableEnd(*pTableEnd);
        bRet = GetDoc()->AppendTxtNode( aTableEnd );
        pUnoCrsr = GetDoc()->CreateUnoCrsr( aTableEnd, FALSE);
    }
    else if(pXSection &&
        pXSection->GetFmt() &&
            pXSection->GetFmt()->GetDoc() == GetDoc())
    {
        SwSectionFmt* pSectFmt = pXSection->GetFmt();
        SwSectionNode* pSectNode = pSectFmt->GetSectionNode();
        SwEndNode* pEnd = pSectNode->EndOfSectionNode();
        SwPosition aEnd(*pEnd);
        bRet = GetDoc()->AppendTxtNode( aEnd );
        pUnoCrsr = GetDoc()->CreateUnoCrsr( aEnd, FALSE);
    }
    if(!bRet)
        throw IllegalArgumentException();
    else
    {
        pPara->attachToText(this, pUnoCrsr);
    }
}

void SwXText::removeTextContentBefore(
    const Reference< XTextContent>& xSuccessor)
        throw(IllegalArgumentException, RuntimeException)
{
    SolarMutexGuard aGuard;
    if(!GetDoc())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }

    sal_Bool bRet = FALSE;
    SwXTextSection* pXSection = SwXTextSection::GetImplementation( xSuccessor );
    SwXTextTable* pXTable = SwXTextTable::GetImplementation( xSuccessor );
    SwFrmFmt* pTableFmt = pXTable ? pXTable->GetFrmFmt() : 0;
    if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
    {
        SwTable* pTable = SwTable::FindTable( pTableFmt );
        SwTableNode* pTblNode = pTable->GetTableNode();

        SwNodeIndex aTblIdx(  *pTblNode, -1 );
        if(aTblIdx.GetNode().IsTxtNode())
        {
            SwPaM aBefore(aTblIdx);
            bRet = GetDoc()->DelFullPara( aBefore );
        }
    }
    else if(pXSection &&
        pXSection->GetFmt() &&
            pXSection->GetFmt()->GetDoc() == GetDoc())
    {
        SwSectionFmt* pSectFmt = pXSection->GetFmt();
        SwSectionNode* pSectNode = pSectFmt->GetSectionNode();

        SwNodeIndex aSectIdx(  *pSectNode, -1 );
        if(aSectIdx.GetNode().IsTxtNode())
        {
            SwPaM aBefore(aSectIdx);
            bRet = GetDoc()->DelFullPara( aBefore );
        }
    }
    if(!bRet)
        throw IllegalArgumentException();
}

void SwXText::removeTextContentAfter(const Reference< XTextContent>& xPredecessor)
        throw(IllegalArgumentException, RuntimeException)
{
    SolarMutexGuard aGuard;
    if(!GetDoc())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }

    sal_Bool bRet = FALSE;
    SwXTextSection* pXSection = SwXTextSection::GetImplementation( xPredecessor );
    SwXTextTable* pXTable = SwXTextTable::GetImplementation(xPredecessor );
    SwFrmFmt* pTableFmt = pXTable ? pXTable->GetFrmFmt() : 0;
    if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
    {
        SwTable* pTable = SwTable::FindTable( pTableFmt );
        SwTableNode* pTblNode = pTable->GetTableNode();
        SwEndNode* pTableEnd = pTblNode->EndOfSectionNode();

        SwNodeIndex aTblIdx(  *pTableEnd, 1 );
        if(aTblIdx.GetNode().IsTxtNode())
        {
            SwPaM aPaM(aTblIdx);
            bRet = GetDoc()->DelFullPara( aPaM );
        }
    }
    else if(pXSection &&
        pXSection->GetFmt() &&
            pXSection->GetFmt()->GetDoc() == GetDoc())
    {
        SwSectionFmt* pSectFmt = pXSection->GetFmt();
        SwSectionNode* pSectNode = pSectFmt->GetSectionNode();
        SwEndNode* pEnd = pSectNode->EndOfSectionNode();
        SwNodeIndex aSectIdx(  *pEnd, 1 );
        if(aSectIdx.GetNode().IsTxtNode())
        {
            SwPaM aAfter(aSectIdx);
            bRet = GetDoc()->DelFullPara( aAfter );
        }
    }
    if(!bRet)
        throw IllegalArgumentException();
}

void SwXText::removeTextContent(const uno::Reference< XTextContent > & xContent)
    throw( container::NoSuchElementException, uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    if(!xContent.is())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U("first parameter invalid");
        throw aRuntime;
    }
    else
        xContent->dispose();
}

uno::Reference< XText >  SwXText::getText(void)
        throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< XText >  xRet = (SwXText*)this;
    return xRet;

}

uno::Reference< XTextRange >  SwXText::getStart(void) throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< XTextCursor >  xRef = createCursor();
    if(!xRef.is())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    xRef->gotoStart(sal_False);
    uno::Reference< XTextRange >  xRet(xRef, uno::UNO_QUERY);
    return xRet;
}

uno::Reference< XTextRange >  SwXText::getEnd(void) throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< XTextCursor >  xRef = createCursor();
    if(!xRef.is())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    else
        xRef->gotoEnd(sal_False);
    uno::Reference< XTextRange >  xRet(xRef, uno::UNO_QUERY);;

    return xRet;
}

OUString SwXText::getString(void) throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< XTextCursor >  xRet = createCursor();
    if(!xRet.is())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    else
    {
        xRet->gotoEnd(sal_True);
    }
    return xRet->getString();
}

void SwXText::setString(const OUString& aString) throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    const SwStartNode* pStartNode = GetStartNode();
    if(!pStartNode)
        throw uno::RuntimeException();

    //insert an empty paragraph at the start and at the end to ensure that
    //all tables and sections can be removed by the selecting XTextCursor
    {
        SwPosition aStartPos(*pStartNode);
        const SwEndNode* pEnd = pStartNode->EndOfSectionNode();
        SwNodeIndex aEndIdx(*pEnd);
        aEndIdx--;
        //the inserting of nodes should only be done if really necessary
        //to prevent #97924# (removes paragraph attributes when setting the text
        //e.g. of a table cell
        BOOL bInsertNodes = FALSE;
        SwNodeIndex aStartIdx(*pStartNode);
        do
        {
            aStartIdx++;
            SwNode& rCurrentNode = aStartIdx.GetNode();
            if(rCurrentNode.GetNodeType() == ND_SECTIONNODE
                ||rCurrentNode.GetNodeType() == ND_TABLENODE)
            {
                bInsertNodes = TRUE;
                break;
            }
        }
        while(aStartIdx < aEndIdx);
        if(bInsertNodes)
        {
            GetDoc()->AppendTxtNode( aStartPos );
            SwPosition aEndPos(aEndIdx.GetNode());
            SwPaM aPam(aEndPos);
            GetDoc()->AppendTxtNode( *aPam.Start() );
        }
    }

    uno::Reference< XTextCursor >  xRet = createCursor();
    if(!xRet.is())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    else
    {
        xRet->gotoEnd(sal_True);
    }
    xRet->setString(aString);
}
/* ---------------------------------------------------------------------------
    Description: Checks if pRange/pCursor are member of the same text interface.
                Only one of the pointers has to be set!
 ---------------------------------------------------------------------------*/
sal_Bool    SwXText::CheckForOwnMember(
    const SwXTextRange* pRange,
    const OTextCursorHelper* pCursor)
        throw(IllegalArgumentException, RuntimeException)
{
    DBG_ASSERT((!pRange || !pCursor) && (pRange || pCursor), "only one pointer will be checked" );
    Reference<XTextCursor> xOwnCursor = createCursor();

    uno::Reference<lang::XUnoTunnel> xTunnel( xOwnCursor, uno::UNO_QUERY);
    OTextCursorHelper* pOwnCursor = 0;
    if(xTunnel.is())
    {
        pOwnCursor = (OTextCursorHelper*)xTunnel->getSomething(OTextCursorHelper::getUnoTunnelId());
    }
    DBG_ASSERT(pOwnCursor, "OTextCursorHelper::getUnoTunnelId() ??? ");
    const SwStartNode* pOwnStartNode = pOwnCursor->GetPaM()->GetNode()->FindStartNode();
    SwStartNodeType eSearchNodeType = SwNormalStartNode;
    switch(eCrsrType)
    {
        case CURSOR_FRAME:      eSearchNodeType = SwFlyStartNode;       break;
        case CURSOR_TBLTEXT:    eSearchNodeType = SwTableBoxStartNode;  break;
        case CURSOR_FOOTNOTE:   eSearchNodeType = SwFootnoteStartNode;  break;
        case CURSOR_HEADER:     eSearchNodeType = SwHeaderStartNode;    break;
        case CURSOR_FOOTER:     eSearchNodeType = SwFooterStartNode;    break;
        default:
            break;
    }

    const SwNode* pSrcNode;
    if(pCursor)
    {
        pSrcNode = pCursor->GetPaM()->GetNode();
    }
    else //dann pRange
    {
        SwBookmark* pBkm = pRange->GetBookmark();
        pSrcNode = &pBkm->GetPos().nNode.GetNode();
    }
    const SwStartNode* pTmp = pSrcNode->FindSttNodeByType(eSearchNodeType);

    //SectionNodes ueberspringen
    while(pTmp && pTmp->IsSectionNode())
    {
        pTmp = pTmp->FindStartNode();
    }
    //if the document starts with a section
    while(pOwnStartNode->IsSectionNode())
    {
        pOwnStartNode = pOwnStartNode->FindStartNode();
    }
    //this checks if (this) and xRange are in the same XText interface
    return(pOwnStartNode == pTmp);
}


sal_Int16 SwXText::ComparePositions(
    const Reference<XTextRange>& xPos1,
    const Reference<XTextRange>& xPos2)
            throw(IllegalArgumentException, RuntimeException)
{
    sal_Int16 nCompare(0);
    SwUnoInternalPaM aPam1(*GetDoc());
    SwUnoInternalPaM aPam2(*GetDoc());

    BOOL bExcept = FALSE;
    if(SwXTextRange::XTextRangeToSwPaM(aPam1, xPos1) &&
            SwXTextRange::XTextRangeToSwPaM(aPam2, xPos2))
    {
        uno::Reference<lang::XUnoTunnel> xRangeTunnel1( xPos1, UNO_QUERY);
        SwXTextRange* pRange1 = 0;
        OTextCursorHelper* pCursor1 = 0;
        if(xRangeTunnel1.is())
        {
            pRange1 = (SwXTextRange*)xRangeTunnel1->getSomething(
                                    SwXTextRange::getUnoTunnelId());
            pCursor1 = (OTextCursorHelper*)xRangeTunnel1->getSomething(
                                    OTextCursorHelper::getUnoTunnelId());
        }
        uno::Reference<lang::XUnoTunnel> xRangeTunnel2( xPos2, UNO_QUERY);
        SwXTextRange* pRange2 = 0;
        OTextCursorHelper* pCursor2 = 0;
        if(xRangeTunnel2.is())
        {
            pRange2 = (SwXTextRange*)xRangeTunnel2->getSomething(
                                    SwXTextRange::getUnoTunnelId());
            pCursor2 = (OTextCursorHelper*)xRangeTunnel2->getSomething(
                                    OTextCursorHelper::getUnoTunnelId());
        }

        if((pRange1||pCursor1) && (pRange2||pCursor2))
        {
            if(CheckForOwnMember(pRange1, pCursor1)
                && CheckForOwnMember( pRange2, pCursor2))
            {
                const SwPosition *pStart1 = 0;
                const SwPosition *pStart2 = 0;

                if(pRange1)
                    pStart1 = pRange1->GetBookmark() ? &pRange1->GetBookmark()->GetPos() : 0;
                else
                    pStart1 = pCursor1->GetPaM() ? pCursor1->GetPaM()->Start() : 0;

                if(pRange2)
                    pStart2 = pRange2->GetBookmark() ? &pRange2->GetBookmark()->GetPos() : 0;
                else
                    pStart2 = pCursor2->GetPaM() ? pCursor2->GetPaM()->Start() : 0;

                if(pStart1 && pStart2)
                {
                    if(*pStart1 < *pStart2)
                        nCompare = 1;
                    else if(*pStart1 > *pStart2)
                        nCompare = -1;
                    else
                    {
                        DBG_ASSERT(*pStart1 == *pStart2, "SwPositions should be equal here");
                        nCompare = 0;
                    }
                }
                else
                    bExcept = TRUE;
            }
            else
                bExcept = TRUE;
        }
        else
            bExcept = TRUE;
    }
    else
        bExcept = TRUE;
    if(bExcept)
        throw IllegalArgumentException();

    return nCompare;
}


sal_Int16 SwXText::compareRegionStarts(
    const Reference<XTextRange>& xR1,
    const Reference<XTextRange>& xR2)
            throw(IllegalArgumentException, RuntimeException)
{
    SolarMutexGuard aGuard;
    if(!xR1.is() || !xR2.is())
        throw IllegalArgumentException();
    Reference<XTextRange> xStart1 = xR1->getStart();
    Reference<XTextRange> xStart2 = xR2->getStart();

    return ComparePositions(xStart1, xStart2);
}

sal_Int16 SwXText::compareRegionEnds(
    const Reference<XTextRange>& xR1,
    const Reference<XTextRange>& xR2)
                    throw(IllegalArgumentException, RuntimeException)
{
    SolarMutexGuard aGuard;
    if(!xR1.is() || !xR2.is())
        throw IllegalArgumentException();
    Reference<XTextRange> xEnd1 = xR1->getEnd();
    Reference<XTextRange> xEnd2 = xR2->getEnd();

    return ComparePositions(xEnd1, xEnd2);
}


uno::Reference< beans::XPropertySetInfo > SwXText::getPropertySetInfo(  )
    throw(uno::RuntimeException)
{
    static uno::Reference< beans::XPropertySetInfo > xInfo =
        new SfxItemPropertySetInfo(_pMap);
    return xInfo;
}

void SwXText::setPropertyValue( const ::rtl::OUString& /*aPropertyName*/, const uno::Any& /*aValue*/ )
    throw(beans::UnknownPropertyException, beans::PropertyVetoException,
    lang::IllegalArgumentException, lang::WrappedTargetException,
    uno::RuntimeException)
{
    throw lang::IllegalArgumentException();
}

uno::Any SwXText::getPropertyValue(
    const ::rtl::OUString& rPropertyName )
        throw(beans::UnknownPropertyException, lang::WrappedTargetException,
                uno::RuntimeException)
{
    SolarMutexGuard aGuard;
    if(!IsValid())
        throw  uno::RuntimeException();
    const SfxItemPropertyMap*   pMap = SfxItemPropertyMap::GetByName(
                                                    _pMap, rPropertyName);
    uno::Any aRet;
    if(pMap)
    {
        switch(pMap->nWID)
        {
//          no code necessary - the redline is always located at the end node
//            case FN_UNO_REDLINE_NODE_START:
//            break;
            case FN_UNO_REDLINE_NODE_END:
            {
                const SwRedlineTbl& rRedTbl = GetDoc()->GetRedlineTbl();
                USHORT nRedTblCount = rRedTbl.Count();
                if ( nRedTblCount > 0 )
                {
                    const SwStartNode* pStartNode = GetStartNode();
                    ULONG nOwnIndex = pStartNode->EndOfSectionIndex();
                    for(USHORT nRed = 0; nRed < nRedTblCount; nRed++)
                    {
                        const SwRedline* pRedline = rRedTbl[nRed];
                        const SwPosition* pRedStart = pRedline->Start();
                        const SwNodeIndex nRedNode = pRedStart->nNode;
                        if(nOwnIndex == nRedNode.GetIndex())
                        {
                            aRet <<= SwXRedlinePortion::CreateRedlineProperties(*pRedline, TRUE);
                            break;
                        }
                    }
                }
            }
            break;
        }
    }
    else
    {
        UnknownPropertyException aExcept;
        aExcept.Message = C2U("Unknown property: ");
        aExcept.Message += rPropertyName;
        throw aExcept;
    }
    return aRet;

}

void SwXText::addPropertyChangeListener(
    const ::rtl::OUString& /*aPropertyName*/,
    const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
        throw(beans::UnknownPropertyException, lang::WrappedTargetException,
        uno::RuntimeException)
{
    throw uno::RuntimeException();
}

void SwXText::removePropertyChangeListener(
    const ::rtl::OUString& /*aPropertyName*/,
    const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
        throw(beans::UnknownPropertyException, lang::WrappedTargetException,
            uno::RuntimeException)
{
    throw uno::RuntimeException();
}

void SwXText::addVetoableChangeListener(
    const ::rtl::OUString& /*PropertyName*/,
    const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
        throw(beans::UnknownPropertyException, lang::WrappedTargetException,
        uno::RuntimeException)
{
    throw uno::RuntimeException();
}

void SwXText::removeVetoableChangeListener(
    const ::rtl::OUString& /*PropertyName*/,
    const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
        throw(beans::UnknownPropertyException, lang::WrappedTargetException,
        uno::RuntimeException)
{
    throw uno::RuntimeException();
}


const uno::Sequence< sal_Int8 > & SwXText::getUnoTunnelId()
{
    static uno::Sequence< sal_Int8 > aSeq = ::binfilter::CreateUnoTunnelId();
    return aSeq;
}

sal_Int64 SwXText::getSomething( const uno::Sequence< sal_Int8 >& rId )
    throw(uno::RuntimeException)
{
    if( rId.getLength() == 16
        && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
                                        rId.getConstArray(), 16 ) )
    {
            return (sal_Int64)this;
    }
    return 0;
}

/******************************************************************
 * SwXBodyText
 ******************************************************************/
SwXBodyText::SwXBodyText(SwDoc* pDocIn) :
    SwXText(pDocIn, CURSOR_BODY)
{
}


SwXBodyText::~SwXBodyText()
{

}

OUString SwXBodyText::getImplementationName(void) throw( RuntimeException )
{
    return C2U("SwXBodyText");
}

BOOL SwXBodyText::supportsService(const OUString& rServiceName) throw( RuntimeException )
{
    return C2U("com.sun.star.text.Text") == rServiceName;
}

Sequence< OUString > SwXBodyText::getSupportedServiceNames(void) throw( RuntimeException )
{
    Sequence< OUString > aRet(1);
    OUString* pArray = aRet.getArray();
    pArray[0] = C2U("com.sun.star.text.Text");
    return aRet;
}

uno::Any SwXBodyText::queryAggregation(
    const uno::Type& rType )
        throw(::com::sun::star::uno::RuntimeException)
{
    uno::Any aRet;
    const uno::Type& rXEnumerationAccessType = ::getCppuType((uno::Reference< container::XEnumerationAccess >*)0);
    const uno::Type& rXElementAccessType = ::getCppuType((uno::Reference< container::XElementAccess >*)0);
    const uno::Type& rXServiceInfoType = ::getCppuType((uno::Reference< lang::XServiceInfo >*)0);

    if(rType == rXEnumerationAccessType)
    {
        Reference<container::XEnumerationAccess> xRet = this;
        aRet.setValue(&xRet, rXEnumerationAccessType);
    }
    else if(rType == rXElementAccessType)
    {
        Reference<container::XElementAccess> xRet = this;
        aRet.setValue(&xRet, rXElementAccessType);
    }
    else if(rType == rXServiceInfoType)
    {
        Reference<lang::XServiceInfo> xRet = this;
        aRet.setValue(&xRet, rXServiceInfoType);
    }
    else
    {
        aRet = SwXText::queryInterface( rType );
    }
    if(aRet.getValueType() == ::getCppuVoidType())
        aRet = OWeakAggObject::queryAggregation( rType );
    return aRet;
}


uno::Sequence< uno::Type > SwXBodyText::getTypes(  ) throw(uno::RuntimeException)
{
    uno::Sequence< uno::Type > aTypes = SwXBodyTextBaseClass::getTypes();
    uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
    long nIndex = aTypes.getLength();
    aTypes.realloc(aTypes.getLength() + aTextTypes.getLength());
    uno::Type* pTypes = aTypes.getArray();
    const uno::Type* pTextTypes = aTextTypes.getConstArray();
    for(int i = 0; i < aTextTypes.getLength(); i++)
        pTypes[nIndex++] = pTextTypes[i];
    return aTypes;
}

uno::Sequence< sal_Int8 > SwXBodyText::getImplementationId(  ) throw(uno::RuntimeException)
{
    SolarMutexGuard aGuard;
    static Sequence< sal_Int8 > aId( 16 );
    static sal_Bool bInit = sal_False;
    if(!bInit)
    {
        rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
        bInit = sal_True;
    }
    return aId;
}

uno::Any SAL_CALL
    SwXBodyText::queryInterface( const uno::Type& rType )
        throw(uno::RuntimeException)
{
      uno::Any aRet = SwXText::queryInterface( rType );
    if(aRet.getValueType() == ::getCppuVoidType())
        aRet = SwXBodyTextBaseClass::queryInterface( rType );
    return aRet;
}

uno::Reference< XTextCursor >  SwXBodyText::CreateTextCursor(sal_Bool bIgnoreTables)
{
    uno::Reference< XTextCursor >  xRet;
    if(IsValid())
    {
        SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
        //erstmal sicherstellen, dass wir nicht in einer Tabelle stehen
        SwPaM aPam(rNode);
        aPam.Move( fnMoveBackward, fnGoDoc );
        if(!bIgnoreTables)
        {
            SwTableNode* pTblNode = aPam.GetNode()->FindTableNode();
            SwCntntNode* pCont = 0;
            while( pTblNode )
            {
                aPam.GetPoint()->nNode = *pTblNode->EndOfSectionNode();
                pCont = GetDoc()->GetNodes().GoNext(&aPam.GetPoint()->nNode);
                pTblNode = pCont->FindTableNode();
            }
            if(pCont)
                aPam.GetPoint()->nContent.Assign(pCont, 0);
        }
        xRet =  (XWordCursor*)new SwXTextCursor(this, *aPam.GetPoint(), CURSOR_BODY, GetDoc());
    }
    return xRet;
}

uno::Reference< XTextCursor >  SwXBodyText::createTextCursor(void) throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< XTextCursor >  aRef = CreateTextCursor(sal_False);
    if(!aRef.is())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    return aRef;
}

uno::Reference< XTextCursor >  SwXBodyText::createTextCursorByRange(
            const uno::Reference< XTextRange > & aTextPosition) throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< XTextCursor >  aRef;
    if(!IsValid())
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    SwUnoInternalPaM aPam(*GetDoc());
    if(SwXTextRange::XTextRangeToSwPaM(aPam, aTextPosition))
    {
        SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();

        SwStartNode* p1 = aPam.GetNode()->FindStartNode();
        //document starts with a section?
        while(p1->IsSectionNode())
        {
            p1 = p1->FindStartNode();
        }
        SwStartNode* p2 = rNode.FindStartNode();

        if(p1 == p2)
            aRef =  (XWordCursor*)new SwXTextCursor(this , *aPam.GetPoint(), CURSOR_BODY, GetDoc(), aPam.GetMark());
    }
    if(!aRef.is())
        throw uno::RuntimeException();
    return aRef;
}

uno::Reference< container::XEnumeration >  SwXBodyText::createEnumeration(void)
                            throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< container::XEnumeration >  aRef;
    if(IsValid())
    {
        SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
        SwPosition aPos(rNode);
        SwUnoCrsr* pUnoCrsr = GetDoc()->CreateUnoCrsr(aPos, sal_False);
        pUnoCrsr->Move( fnMoveBackward, fnGoDoc );
        aRef = new SwXParagraphEnumeration(this, pUnoCrsr, CURSOR_BODY);
    }
    else
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    return aRef;

}

uno::Type SwXBodyText::getElementType(void) throw( uno::RuntimeException )
{
    return ::getCppuType((uno::Reference<XTextRange>*)0);
}

sal_Bool SwXBodyText::hasElements(void) throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    if(IsValid())
        return sal_True;
    else
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    return sal_False;
}
/******************************************************************
 *  SwXHeadFootText
 ******************************************************************/
TYPEINIT1(SwXHeadFootText, SwClient);

OUString SwXHeadFootText::getImplementationName(void) throw( RuntimeException )
{
    return C2U("SwXHeadFootText");
}

BOOL SwXHeadFootText::supportsService(const OUString& rServiceName) throw( RuntimeException )
{
    return C2U("com.sun.star.text.Text") == rServiceName;
}

Sequence< OUString > SwXHeadFootText::getSupportedServiceNames(void) throw( RuntimeException )
{
    Sequence< OUString > aRet(1);
    OUString* pArray = aRet.getArray();
    pArray[0] = C2U("com.sun.star.text.Text");
    return aRet;
}

SwXHeadFootText::SwXHeadFootText(SwFrmFmt& rHeadFootFmt, BOOL bHeader) :
    SwXText(rHeadFootFmt.GetDoc(), bHeader ? CURSOR_HEADER : CURSOR_FOOTER),
    SwClient(&rHeadFootFmt),
    bIsHeader(bHeader)
{

}

SwXHeadFootText::~SwXHeadFootText()
{

}

const SwStartNode *SwXHeadFootText::GetStartNode() const
{
    const SwStartNode *pSttNd = 0;
    SwFrmFmt* pHeadFootFmt = GetFmt();
    if(pHeadFootFmt)
    {
        const SwFmtCntnt& rFlyCntnt = pHeadFootFmt->GetCntnt();
        if( rFlyCntnt.GetCntntIdx() )
            pSttNd = rFlyCntnt.GetCntntIdx()->GetNode().GetStartNode();
    }
    return pSttNd;
}

uno::Reference< XTextCursor >   SwXHeadFootText::createCursor() throw(uno::RuntimeException)
{
    return createTextCursor();
}

uno::Sequence< ::com::sun::star::uno::Type > SwXHeadFootText::getTypes(  ) throw(uno::RuntimeException)
{
    uno::Sequence< uno::Type > aHFTypes = SwXHeadFootTextBaseClass::getTypes();
    uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();

    long nIndex = aHFTypes.getLength();
    aHFTypes.realloc(
        aHFTypes.getLength() +
        aTextTypes.getLength());

    uno::Type* pHFTypes = aHFTypes.getArray();
    const uno::Type* pTextTypes = aTextTypes.getConstArray();
    for(long nPos = 0; nPos < aTextTypes.getLength(); nPos++)
        pHFTypes[nIndex++] = pTextTypes[nPos];

    return aHFTypes;
}


uno::Sequence< sal_Int8 > SwXHeadFootText::getImplementationId(  ) throw(uno::RuntimeException)
{
    SolarMutexGuard aGuard;
    static Sequence< sal_Int8 > aId( 16 );
    static sal_Bool bInit = sal_False;
    if(!bInit)
    {
        rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
        bInit = sal_True;
    }
    return aId;
}

uno::Any SwXHeadFootText::queryInterface( const uno::Type& aType ) throw(uno::RuntimeException)
{
    uno::Any aRet = SwXHeadFootTextBaseClass::queryInterface(aType);
    if(aRet.getValueType() == ::getCppuVoidType() )
        aRet = SwXText::queryInterface(aType);
    return aRet;
}


uno::Reference< XTextCursor >  SwXHeadFootText::createTextCursor(void) throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< XTextCursor >   xRet;
    SwFrmFmt* pHeadFootFmt = GetFmt();
    if(pHeadFootFmt)
    {
        const SwFmtCntnt& rFlyCntnt = pHeadFootFmt->GetCntnt();
        const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
        SwPosition aPos(rNode);
        SwXTextCursor* pCrsr = new SwXTextCursor(this, aPos, bIsHeader ? CURSOR_HEADER : CURSOR_FOOTER, GetDoc());
        SwUnoCrsr* pUnoCrsr = pCrsr->GetCrsr();
        pUnoCrsr->Move(fnMoveForward, fnGoNode);

        //save current start node to be able to check if there is content after the table -
        //otherwise the cursor would be in the body text!

        const SwStartNode* pOwnStartNode = rNode.FindSttNodeByType(
                        bIsHeader ? SwHeaderStartNode : SwFooterStartNode);
        //steht hier eine Tabelle?
        SwTableNode* pTblNode = pUnoCrsr->GetNode()->FindTableNode();
        SwCntntNode* pCont = 0;
        while( pTblNode )
        {
            pUnoCrsr->GetPoint()->nNode = *pTblNode->EndOfSectionNode();
            pCont = GetDoc()->GetNodes().GoNext(&pUnoCrsr->GetPoint()->nNode);
            pTblNode = pCont->FindTableNode();
        }
        if(pCont)
            pUnoCrsr->GetPoint()->nContent.Assign(pCont, 0);
        const SwStartNode* pNewStartNode = pUnoCrsr->GetNode()->FindSttNodeByType(
                        bIsHeader ? SwHeaderStartNode : SwFooterStartNode);
        if(!pNewStartNode || pNewStartNode != pOwnStartNode)
        {
            pCrsr = NULL;
            uno::RuntimeException aExcept;
            aExcept.Message = S2U("no text available");
            throw aExcept;
        }
        xRet =  (XWordCursor*)pCrsr;
    }
    else
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }
    return xRet;
}

uno::Reference< XTextCursor >  SwXHeadFootText::createTextCursorByRange(
                const uno::Reference< XTextRange > & aTextPosition) throw( uno::RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< XTextCursor >  xRet;
    SwFrmFmt* pHeadFootFmt = GetFmt();
    SwUnoInternalPaM aPam(*GetDoc());
    if(pHeadFootFmt && SwXTextRange::XTextRangeToSwPaM(aPam, aTextPosition))
    {
        SwNode& rNode = pHeadFootFmt->GetCntnt().GetCntntIdx()->GetNode();
        SwPosition aPos(rNode);
        SwPaM aHFPam(aPos);
        aHFPam.Move(fnMoveForward, fnGoNode);
        SwStartNode* pOwnStartNode = aHFPam.GetNode()->FindSttNodeByType(
                        bIsHeader ? SwHeaderStartNode : SwFooterStartNode);
        SwStartNode* p1 = aPam.GetNode()->FindSttNodeByType(
            bIsHeader ? SwHeaderStartNode : SwFooterStartNode);
        if(p1 == pOwnStartNode)
            xRet =  (XWordCursor*)new SwXTextCursor(this, *aPam.GetPoint(),
                            bIsHeader ? CURSOR_HEADER : CURSOR_FOOTER, GetDoc(), aPam.GetMark());
    }
    return xRet;
}

uno::Reference< container::XEnumeration >  SwXHeadFootText::createEnumeration(void)
    throw( RuntimeException )
{
    SolarMutexGuard aGuard;
    uno::Reference< container::XEnumeration >  aRef;
    //wenn this ungueltig ist, dann kommt die uno::Exception aus createTextCursor()
    SwFrmFmt* pHeadFootFmt = GetFmt();
    if(pHeadFootFmt)
    {
        const SwFmtCntnt& rFlyCntnt = pHeadFootFmt->GetCntnt();
        const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
        SwPosition aPos(rNode);
        SwUnoCrsr* pUnoCrsr = GetDoc()->CreateUnoCrsr(aPos, sal_False);
        pUnoCrsr->Move(fnMoveForward, fnGoNode);
        aRef = new SwXParagraphEnumeration(this, pUnoCrsr, bIsHeader ? CURSOR_HEADER : CURSOR_FOOTER);
    }
    else
    {
        RuntimeException aRuntime;
        aRuntime.Message = C2U(cInvalidObject);
        throw aRuntime;
    }

    return aRef;
}

uno::Type SwXHeadFootText::getElementType(void) throw( uno::RuntimeException )
{
    return ::getCppuType((uno::Reference<XTextRange>*)0);
}

sal_Bool SwXHeadFootText::hasElements(void) throw( uno::RuntimeException )
{
    return sal_True;
}


void    SwXHeadFootText::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew)
{
    ClientModify( this, pOld, pNew);
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
