/**************************************************************
 * 
 * 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 <swtypes.hxx>
#include <cmdid.h>

#include <unomid.h>
#include <unodraw.hxx>
#include <unocoll.hxx>
#include <unoframe.hxx>
#include <unoparagraph.hxx>
#include <unotextrange.hxx>
#include <unoprnms.hxx>
#include <editeng/unoprnms.hxx>
#include <svx/svditer.hxx>
#include <swunohelper.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <fmtcntnt.hxx>
#include <fmtflcnt.hxx>
#include <txtatr.hxx>
#include <docsh.hxx>
#include <unomap.hxx>
#include <unoport.hxx>
#include <unocrsr.hxx>
#include <TextCursorHelper.hxx>
#include <swundo.hxx>
#include <dflyobj.hxx>
#include <ndtxt.hxx>
#include <svx/svdview.hxx>
#include <svx/unoshape.hxx>
#include <dcontact.hxx>
#include <svx/fmglob.hxx>
#include <fmtornt.hxx>
#include <fmtanchr.hxx>
#include <fmtsrnd.hxx>
#include <fmtfollowtextflow.hxx>
#include <rootfrm.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/ulspitem.hxx>
#include <svx/shapepropertynotifier.hxx>
#include <crstate.hxx>
#include <vos/mutex.hxx>
#include <comphelper/extract.hxx>
#include <comphelper/stl_types.hxx>
#include <comphelper/makesequence.hxx>
#include <svx/scene3d.hxx>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/text/HoriOrientation.hpp>
#include <com/sun/star/text/VertOrientation.hpp>
#include <basegfx/numeric/ftools.hxx>
#include <algorithm>
#include <fmtwrapinfluenceonobjpos.hxx>
#include <com/sun/star/text/TextContentAnchorType.hpp>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <vcl/svapp.hxx>
#include <slist>
#include <iterator>
#include <switerator.hxx>

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

DECLARE_STL_USTRINGACCESS_MAP( uno::Sequence< sal_Int8 > *,  SwShapeImplementationIdMap );

static SwShapeImplementationIdMap aImplementationIdMap;

class SwShapeDescriptor_Impl
{
	SwFmtHoriOrient* 	pHOrient;
	SwFmtVertOrient* 	pVOrient;
	SwFmtAnchor*		pAnchor;
	SwFmtSurround*		pSurround;
	SvxULSpaceItem*		pULSpace;
	SvxLRSpaceItem*		pLRSpace;
    sal_Bool            bOpaque;
    uno::Reference< text::XTextRange > xTextRange;
    // OD 2004-04-21 #i26791#
    SwFmtFollowTextFlow* mpFollowTextFlow;
    // OD 2004-05-05 #i28701# - add property 'WrapInfluenceOnObjPos'
    SwFmtWrapInfluenceOnObjPos* pWrapInfluenceOnObjPos;
    // --> OD 2004-08-06 #i28749#
    sal_Int16 mnPositionLayoutDir;
    // <--

public:
    bool    bInitializedPropertyNotifier;

public:
    SwShapeDescriptor_Impl() :
     // --> OD 2004-08-18 #i32349# - no defaults, in order to determine on
     // adding a shape, if positioning attributes are set or not.
     pHOrient( 0L ),
     pVOrient( 0L ),
     // <--
	 pAnchor(0),
	 pSurround(0),
	 pULSpace(0),
     pLRSpace(0),
     bOpaque(sal_False),
     // OD 2004-04-21 #i26791#
     mpFollowTextFlow( new SwFmtFollowTextFlow( sal_False ) ),
     // OD 2004-05-05 #i28701#
     // --> OD 2004-10-18 #i35017# - constant name has changed
     pWrapInfluenceOnObjPos( new SwFmtWrapInfluenceOnObjPos(
                            text::WrapInfluenceOnPosition::ONCE_CONCURRENT ) ),
     // <--
     // --> OD 2004-08-06 #i28749#
     mnPositionLayoutDir( text::PositionLayoutDir::PositionInLayoutDirOfAnchor ),
     bInitializedPropertyNotifier(false)
     {}

	~SwShapeDescriptor_Impl()
	{
		delete pHOrient;
		delete pVOrient;
		delete pAnchor;
		delete pSurround;
		delete pULSpace;
		delete pLRSpace;
        // OD 2004-04-22 #i26791#
        delete mpFollowTextFlow;
        // OD 2004-05-05 #i28701#
        delete pWrapInfluenceOnObjPos;
	}
	SwFmtAnchor* 	GetAnchor(sal_Bool bCreate = sal_False)
		{
			if(bCreate && !pAnchor)
            {
                pAnchor = new SwFmtAnchor(FLY_AS_CHAR);
            }
			return pAnchor;
		}
	SwFmtHoriOrient* GetHOrient(sal_Bool bCreate = sal_False)
		{
            if (bCreate && !pHOrient)
            {
                // OD 2004-06-03 #i26791# - change default
                pHOrient = new SwFmtHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
            }
			return pHOrient;
		}
	SwFmtVertOrient* GetVOrient(sal_Bool bCreate = sal_False)
		{
			if(bCreate && !pVOrient)
            {
                // OD 2004-04-21 #i26791# - change default
                pVOrient = new SwFmtVertOrient( 0, text::VertOrientation::NONE, text::RelOrientation::FRAME );
            }
			return pVOrient;
		}

	SwFmtSurround*	GetSurround(sal_Bool bCreate = sal_False)
		{
			if(bCreate && !pSurround)
				pSurround = new SwFmtSurround();
			return pSurround;
		}
	SvxLRSpaceItem*	GetLRSpace(sal_Bool bCreate = sal_False)
		{
			if(bCreate && !pLRSpace)
                pLRSpace = new SvxLRSpaceItem(RES_LR_SPACE);
			return pLRSpace;
		}
	SvxULSpaceItem*	GetULSpace(sal_Bool bCreate = sal_False)
		{
			if(bCreate && !pULSpace)
                pULSpace = new SvxULSpaceItem(RES_UL_SPACE);
			return pULSpace;
		}
    uno::Reference< text::XTextRange > &    GetTextRange()
	{
		return xTextRange;
	}
    sal_Bool    IsOpaque()
		{
            return bOpaque;
		}
    const sal_Bool&    GetOpaque()
		{
            return bOpaque;
		}
    void RemoveHOrient(){DELETEZ(pHOrient);}
	void RemoveVOrient(){DELETEZ(pVOrient);}
	void RemoveAnchor(){DELETEZ(pAnchor);}
	void RemoveSurround(){DELETEZ(pSurround);}
	void RemoveULSpace(){DELETEZ(pULSpace);}
	void RemoveLRSpace(){DELETEZ(pLRSpace);}
    void SetOpaque(sal_Bool bSet){bOpaque = bSet;}

    // OD 2004-04-21 #i26791#
    SwFmtFollowTextFlow* GetFollowTextFlow( sal_Bool _bCreate = sal_False )
    {
        if ( _bCreate && !mpFollowTextFlow )
            mpFollowTextFlow = new SwFmtFollowTextFlow( sal_False );
        return mpFollowTextFlow;
    }
    void RemoveFollowTextFlow()
    {
        DELETEZ(mpFollowTextFlow);
    }

    // --> OD 2004-08-06 #i28749#
    sal_Int16 GetPositionLayoutDir() const
    {
        return mnPositionLayoutDir;
    }
    void SetPositionLayoutDir( sal_Int16 _nPositionLayoutDir )
    {
        switch ( _nPositionLayoutDir )
        {
            case text::PositionLayoutDir::PositionInHoriL2R:
            case text::PositionLayoutDir::PositionInLayoutDirOfAnchor:
            {
                mnPositionLayoutDir = _nPositionLayoutDir;
            }
            break;
            default:
            {
                ASSERT( false,
                        "<SwShapeDescriptor_Impl::SetPositionLayoutDir(..)> - invalid attribute value." );
            }
        }
    }
    void RemovePositionLayoutDir()
    {
        mnPositionLayoutDir = text::PositionLayoutDir::PositionInLayoutDirOfAnchor;
    }
    // <--

    // OD 2004-05-05 #i28701#
    inline SwFmtWrapInfluenceOnObjPos* GetWrapInfluenceOnObjPos(
                                        const sal_Bool _bCreate = sal_False )
    {
        if ( _bCreate && !pWrapInfluenceOnObjPos )
        {
            pWrapInfluenceOnObjPos = new SwFmtWrapInfluenceOnObjPos(
                        // --> OD 2004-10-18 #i35017# - constant name has changed
                        text::WrapInfluenceOnPosition::ONCE_CONCURRENT );
                        // <--
        }
        return pWrapInfluenceOnObjPos;
    }
    inline void RemoveWrapInfluenceOnObjPos()
    {
        DELETEZ(pWrapInfluenceOnObjPos);
    }
};
/****************************************************************************
	class SwFmDrawPage
****************************************************************************/

SwFmDrawPage::SwFmDrawPage( SdrPage* pPage ) :
	SvxFmDrawPage( pPage ), pPageView(0)
{
}

SwFmDrawPage::~SwFmDrawPage() throw ()
{
	RemovePageView();
}

const SdrMarkList& 	SwFmDrawPage::PreGroup(const uno::Reference< drawing::XShapes > & xShapes)
{
	_SelectObjectsInView( xShapes, GetPageView() );
	const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
	return rMarkList;
}

void SwFmDrawPage::PreUnGroup(const uno::Reference< drawing::XShapeGroup >  xShapeGroup)
{
    uno::Reference< drawing::XShape >  xShape( xShapeGroup, uno::UNO_QUERY);
	_SelectObjectInView( xShape, GetPageView() );
}

SdrPageView*	SwFmDrawPage::GetPageView()
{
	if(!pPageView)
		pPageView = mpView->ShowSdrPage( mpPage );
	return pPageView;
}

void	SwFmDrawPage::RemovePageView()
{
	if(pPageView && mpView)
		mpView->HideSdrPage();
	pPageView = 0;
}

uno::Reference< uno::XInterface >  	SwFmDrawPage::GetInterface( SdrObject* pObj )
{
	uno::Reference< XInterface >  xShape;
	if( pObj )
	{
		SwFrmFmt* pFmt = ::FindFrmFmt( pObj );
		SwXShape* pxShape = SwIterator<SwXShape,SwFmt>::FirstElement( *pFmt );
		if(pxShape)
		{
			xShape =  *(cppu::OWeakObject*)pxShape;
		}
		else
			xShape = pObj->getUnoShape();
	}
	return xShape;
}

SdrObject* SwFmDrawPage::_CreateSdrObject( const uno::Reference< drawing::XShape > & xShape ) throw ()
{
	//TODO: stimmt das so - kann die Methode weg?
	return SvxFmDrawPage::_CreateSdrObject( xShape );
}

uno::Reference< drawing::XShape >  SwFmDrawPage::_CreateShape( SdrObject *pObj ) const throw ()
{
	uno::Reference< drawing::XShape >  xRet;
	if(pObj->ISA(SwVirtFlyDrawObj) || pObj->GetObjInventor() == SWGInventor)
	{
		SwFlyDrawContact* pFlyContact = (SwFlyDrawContact*)pObj->GetUserCall();
		if(pFlyContact)
		{
            FlyCntType eType = FLYCNTTYPE_ALL;
			SwFrmFmt* pFlyFmt = pFlyContact->GetFmt();
			SwDoc* pDoc = pFlyFmt->GetDoc();
			const SwNodeIndex* pIdx;
			if( RES_FLYFRMFMT == pFlyFmt->Which()
				&& 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
				&& pIdx->GetNodes().IsDocNodes()
				)
			{
				const SwNode* pNd = pDoc->GetNodes()[ pIdx->GetIndex() + 1 ];
				if(!pNd->IsNoTxtNode())
					eType = FLYCNTTYPE_FRM;
				else if( pNd->IsGrfNode() )
					eType = FLYCNTTYPE_GRF;
				else if( pNd->IsOLENode() )
					eType = FLYCNTTYPE_OLE;
			}
			else
            {
                ASSERT( false,
                        "<SwFmDrawPage::_CreateShape(..)> - could not retrieve type. Thus, no shape created." );
                return xRet;
            }
            DBG_ASSERT( eType != FLYCNTTYPE_ALL, "unexpected FlyCntType value for eType" );
			xRet = SwXFrames::GetObject( *pFlyFmt, eType );
		}
 	}
	else
	{
		// own block - temporary object has to be destroyed before
		// the delegator is set #81670#
		{
			xRet = SvxFmDrawPage::_CreateShape( pObj );
		}
		uno::Reference< XUnoTunnel > xShapeTunnel(xRet, uno::UNO_QUERY);
		//don't create an SwXShape if it already exists
		SwXShape* pShape = 0;
		if(xShapeTunnel.is())
			pShape = reinterpret_cast< SwXShape * >(
					sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SwXShape::getUnoTunnelId()) ));
		if(!pShape)
		{
			xShapeTunnel = 0;
			uno::Reference< uno::XInterface > xCreate(xRet, uno::UNO_QUERY);
			xRet = 0;
            uno::Reference< beans::XPropertySet >  xPrSet;
			if ( pObj->IsGroupObject() && (!pObj->Is3DObj() || ( PTR_CAST(E3dScene,pObj ) != NULL ) ) )
                xPrSet = new SwXGroupShape( xCreate );
            else
                xPrSet = new SwXShape( xCreate );
			xRet = uno::Reference< drawing::XShape >(xPrSet, uno::UNO_QUERY);
		}
	}
	return xRet;
}

/****************************************************************************
	class SwXShapesEnumeration
****************************************************************************/
namespace
{
    class SwXShapesEnumeration
        : public SwSimpleEnumeration_Base
    {
        private:
            typedef ::std::slist< ::com::sun::star::uno::Any > shapescontainer_t;
            shapescontainer_t m_aShapes;
        protected:
            virtual ~SwXShapesEnumeration() {};
        public:
            SwXShapesEnumeration(SwXDrawPage* const pDrawPage);

            //XEnumeration
            virtual sal_Bool SAL_CALL hasMoreElements(void) throw(uno::RuntimeException);
            virtual uno::Any SAL_CALL nextElement(void) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException);

            //XServiceInfo
            virtual OUString SAL_CALL getImplementationName(void) throw(uno::RuntimeException);
            virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(uno::RuntimeException);
            virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames(void) throw(uno::RuntimeException);
    };
}

SwXShapesEnumeration::SwXShapesEnumeration(SwXDrawPage* const pDrawPage)
    : m_aShapes()
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    ::std::insert_iterator<shapescontainer_t> pInserter = ::std::insert_iterator<shapescontainer_t>(m_aShapes, m_aShapes.begin());
    sal_Int32 nCount = pDrawPage->getCount();
    for(sal_Int32 nIdx = 0; nIdx < nCount; nIdx++)
    {
        uno::Reference<drawing::XShape> xShape = uno::Reference<drawing::XShape>(pDrawPage->getByIndex(nIdx), uno::UNO_QUERY);
        *pInserter++ = uno::makeAny(xShape);
    }
}

sal_Bool SwXShapesEnumeration::hasMoreElements(void) throw(uno::RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return !m_aShapes.empty();
}

uno::Any SwXShapesEnumeration::nextElement(void) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if(m_aShapes.empty())
        throw container::NoSuchElementException();
    uno::Any aResult = *m_aShapes.begin();
    m_aShapes.pop_front();
    return aResult;
}

OUString SwXShapesEnumeration::getImplementationName(void) throw(uno::RuntimeException)
{
    return C2U("SwXShapeEnumeration");
}

sal_Bool SwXShapesEnumeration::supportsService(const OUString& ServiceName) throw(uno::RuntimeException)
{
    return C2U("com.sun.star.container.XEnumeration") == ServiceName;
}

uno::Sequence< OUString > SwXShapesEnumeration::getSupportedServiceNames(void) throw(uno::RuntimeException)
{
    return ::comphelper::makeSequence(C2U("com.sun.star.container.XEnumeration"));
}
/****************************************************************************
	class SwXDrawPage
****************************************************************************/
uno::Reference< container::XEnumeration > SwXDrawPage::createEnumeration(void) throw( uno::RuntimeException )
{
    vos::OGuard aGuard(Application::GetSolarMutex());
    return uno::Reference< container::XEnumeration >(
        new SwXShapesEnumeration(this));
}

rtl::OUString SwXDrawPage::getImplementationName(void) throw( uno::RuntimeException )
{
	return C2U("SwXDrawPage");
}

sal_Bool SwXDrawPage::supportsService(const rtl::OUString& rServiceName) throw( uno::RuntimeException )
{
    return C2U("com.sun.star.drawing.GenericDrawPage") == rServiceName;
}

uno::Sequence< rtl::OUString > SwXDrawPage::getSupportedServiceNames(void) throw( uno::RuntimeException )
{
    uno::Sequence< rtl::OUString > aRet(1);
    rtl::OUString* pArray = aRet.getArray();
    pArray[0] = C2U("com.sun.star.drawing.GenericDrawPage");
	return aRet;
}

SwXDrawPage::SwXDrawPage(SwDoc* pDc) :
	pDoc(pDc),
	pDrawPage(0)
{
}

SwXDrawPage::~SwXDrawPage()
{
	if(xPageAgg.is())
	{
		uno::Reference< uno::XInterface >  xInt;
		xPageAgg->setDelegator(xInt);
	}
}

uno::Any SwXDrawPage::queryInterface( const uno::Type& aType )
                                                throw( uno::RuntimeException )
{
    uno::Any aRet = SwXDrawPageBaseClass::queryInterface(aType);
	if(!aRet.hasValue())
	{
        // secure with checking if page exists. This may not be the case
        // either for new SW docs with no yet graphics usage or when
        // the doc is closed and someone else still holds a UNO reference
        // to the XDrawPage (in that case, pDoc is set to 0)
        SwFmDrawPage* pPage = GetSvxPage();

        if(pPage)
        {
    		aRet = pPage->queryAggregation(aType);
        }
	}
	return aRet;
}

uno::Sequence< uno::Type > SwXDrawPage::getTypes() throw( uno::RuntimeException )
{
    uno::Sequence< uno::Type > aPageTypes = SwXDrawPageBaseClass::getTypes();
    uno::Sequence< uno::Type > aSvxTypes = GetSvxPage()->getTypes();

	long nIndex = aPageTypes.getLength();
    aPageTypes.realloc(aPageTypes.getLength() + aSvxTypes.getLength() + 1);

	uno::Type* pPageTypes = aPageTypes.getArray();
	const uno::Type* pSvxTypes = aSvxTypes.getConstArray();
	long nPos;
	for(nPos = 0; nPos < aSvxTypes.getLength(); nPos++)
	{
		pPageTypes[nIndex++] = pSvxTypes[nPos];
	}
    pPageTypes[nIndex] = ::getCppuType((uno::Reference<form::XFormsSupplier2>*)0);
    return aPageTypes;
}

sal_Int32 SwXDrawPage::getCount(void) throw( uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	if(!pDoc)
		throw uno::RuntimeException();
	if(!pDoc->GetDrawModel())
		return 0;
	else
	{
		((SwXDrawPage*)this)->GetSvxPage();
		return pDrawPage->getCount();
	}
}

uno::Any SwXDrawPage::getByIndex(sal_Int32 nIndex)
        throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException,
               uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	if(!pDoc)
		throw uno::RuntimeException();
	if(!pDoc->GetDrawModel())
        throw lang::IndexOutOfBoundsException();

	((SwXDrawPage*)this)->GetSvxPage();
	return pDrawPage->getByIndex( nIndex );
}

uno::Type  SwXDrawPage::getElementType(void) throw( uno::RuntimeException )
{
	return ::getCppuType((const uno::Reference<drawing::XShape>*)0);
}

sal_Bool SwXDrawPage::hasElements(void) throw( uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	if(!pDoc)
		throw uno::RuntimeException();
	if(!pDoc->GetDrawModel())
		return sal_False;
	else
		return ((SwXDrawPage*)this)->GetSvxPage()->hasElements();
}

void SwXDrawPage::add(const uno::Reference< drawing::XShape > & xShape)
	throw( uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	if(!pDoc)
		throw uno::RuntimeException();
    uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShape, uno::UNO_QUERY);
	SwXShape* pShape = 0;
	SvxShape* pSvxShape = 0;
	if(xShapeTunnel.is())
	{
		pShape 		= reinterpret_cast< SwXShape * >(
				sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SwXShape::getUnoTunnelId()) ));
		pSvxShape 	= reinterpret_cast< SvxShape * >(
				sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SvxShape::getUnoTunnelId()) ));
	}

    if(!pShape || pShape->GetRegisteredIn() || !pShape->m_bDescriptor )
    {
        uno::RuntimeException aExcept;
        if(pShape)
            aExcept.Message = C2U("object already inserted");
        else
            aExcept.Message = C2U("illegal object");
        throw aExcept;
    }

    // --> OD, HB
    if ( pSvxShape->GetSdrObject() )
    {
        if ( pSvxShape->GetSdrObject()->IsInserted() )
        {
            return;
        }
    }
    // <--
	GetSvxPage()->add(xShape);

	uno::Reference< uno::XAggregation > 	xAgg = pShape->GetAggregationInterface();

	DBG_ASSERT(pSvxShape, "warum gibt es hier kein SvxShape?");
	//diese Position ist auf jeden Fall in 1/100 mm
	awt::Point aMM100Pos(pSvxShape->getPosition());

	//jetzt noch die Properties aus dem SwShapeDescriptor_Impl auswerten
	SwShapeDescriptor_Impl* pDesc = pShape->GetDescImpl();

	SfxItemSet aSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN,
										RES_FRMATR_END-1 );
    SwFmtAnchor aAnchor( FLY_AS_CHAR );
    sal_Bool bOpaque = sal_False;
    if( pDesc )
	{
		if(pDesc->GetSurround())
			aSet.Put( *pDesc->GetSurround());
		//die Items sind schon in Twip gesetzt
		if(pDesc->GetLRSpace())
		{
			aSet.Put(*pDesc->GetLRSpace());
		}
		if(pDesc->GetULSpace())
		{
			aSet.Put(*pDesc->GetULSpace());
		}
		if(pDesc->GetAnchor())
			aAnchor = *pDesc->GetAnchor();

        // --> OD 2004-08-18 #i32349# - if no horizontal position exists, create one
        if ( !pDesc->GetHOrient() )
        {
            SwFmtHoriOrient* pHori = pDesc->GetHOrient( sal_True );
            SwTwips nHoriPos = MM100_TO_TWIP(aMM100Pos.X);
            pHori->SetPos( nHoriPos );
        }
        // <--
		{
            if(pDesc->GetHOrient()->GetHoriOrient() == text::HoriOrientation::NONE)
				aMM100Pos.X = TWIP_TO_MM100(pDesc->GetHOrient()->GetPos());
			aSet.Put( *pDesc->GetHOrient() );
		}
        // --> OD 2004-08-18 #i32349# - if no vertical position exists, create one
        if ( !pDesc->GetVOrient() )
        {
            SwFmtVertOrient* pVert = pDesc->GetVOrient( sal_True );
            SwTwips nVertPos = MM100_TO_TWIP(aMM100Pos.Y);
            pVert->SetPos( nVertPos );
        }
        // <--
		{
            if(pDesc->GetVOrient()->GetVertOrient() == text::VertOrientation::NONE)
				aMM100Pos.Y = TWIP_TO_MM100(pDesc->GetVOrient()->GetPos());
			aSet.Put( *pDesc->GetVOrient() );
		}

		if(pDesc->GetSurround())
			aSet.Put( *pDesc->GetSurround());
        bOpaque = pDesc->IsOpaque();

        // OD 2004-04-22 #i26791#
        if ( pDesc->GetFollowTextFlow() )
        {
            aSet.Put( *pDesc->GetFollowTextFlow() );
        }

        // OD 2004-05-05 #i28701#
        if ( pDesc->GetWrapInfluenceOnObjPos() )
        {
            aSet.Put( *pDesc->GetWrapInfluenceOnObjPos() );
        }
    }

	pSvxShape->setPosition(aMM100Pos);
    SdrObject* pObj = pSvxShape->GetSdrObject();
    // OD 25.06.2003 #108784# - set layer of new drawing object to corresponding
    // invisible layer.
    if(FmFormInventor != pObj->GetObjInventor())
        pObj->SetLayer( bOpaque ? pDoc->GetInvisibleHeavenId() : pDoc->GetInvisibleHellId() );
    else
        pObj->SetLayer(pDoc->GetInvisibleControlsId());

	SwPaM* pPam = new SwPaM(pDoc->GetNodes().GetEndOfContent());
	SwUnoInternalPaM* pInternalPam = 0;
    uno::Reference< text::XTextRange >  xRg;
	if( pDesc && (xRg = pDesc->GetTextRange()).is() )
	{
		pInternalPam = new SwUnoInternalPaM(*pDoc);
        if (::sw::XTextRangeToSwPaM(*pInternalPam, xRg))
		{
			if(FLY_AT_FLY == aAnchor.GetAnchorId() &&
								!pInternalPam->GetNode()->FindFlyStartNode())
            {
                        aAnchor.SetType(FLY_AS_CHAR);
            }
            else if (FLY_AT_PAGE == aAnchor.GetAnchorId())
            {
				aAnchor.SetAnchor(pInternalPam->Start());
            }
		}
		else
			throw uno::RuntimeException();
    }
    else if ((aAnchor.GetAnchorId() != FLY_AT_PAGE) && pDoc->GetCurrentLayout())
    {
		SwCrsrMoveState aState( MV_SETONLYTEXT );
		Point aTmp(MM100_TO_TWIP(aMM100Pos.X), MM100_TO_TWIP(aMM100Pos.Y));
		pDoc->GetCurrentLayout()->GetCrsrOfst( pPam->GetPoint(), aTmp, &aState );	//swmod 080218
		aAnchor.SetAnchor( pPam->GetPoint() );

        // --> OD 2004-08-18 #i32349# - adjustment of vertical positioning
        // attributes no longer needed, because its already got a default.
	}
	else
    {
        aAnchor.SetType(FLY_AT_PAGE);

        // --> OD 2004-08-18 #i32349# - adjustment of vertical positioning
        // attributes no longer needed, because its already got a default.
	}
	aSet.Put(aAnchor);
	SwPaM* pTemp = pInternalPam;
	if ( !pTemp )
		pTemp = pPam;
	UnoActionContext aAction(pDoc);
	pDoc->Insert( *pTemp, *pObj, &aSet, NULL );
	SwFrmFmt* pFmt = ::FindFrmFmt( pObj );
	if(pFmt)
		pFmt->Add(pShape);
    pShape->m_bDescriptor = sal_False;

	delete pPam;
	delete pInternalPam;
}

void SwXDrawPage::remove(const uno::Reference< drawing::XShape > & xShape) throw( uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	if(!pDoc)
		throw uno::RuntimeException();
    uno::Reference<lang::XComponent> xComp(xShape, uno::UNO_QUERY);
    xComp->dispose();
}

uno::Reference< drawing::XShapeGroup >  SwXDrawPage::group(const uno::Reference< drawing::XShapes > & xShapes) throw( uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	if(!pDoc || !xShapes.is())
		throw uno::RuntimeException();
	uno::Reference< drawing::XShapeGroup >  xRet;
	if(xPageAgg.is())
	{

		SwFmDrawPage* pPage = GetSvxPage();
		if(pPage)//kann das auch Null sein?
		{
			//markieren und MarkList zurueckgeben
			const SdrMarkList& rMarkList = pPage->PreGroup(xShapes);
			if ( rMarkList.GetMarkCount() > 1 )
			{
				sal_Bool bFlyInCnt = sal_False;
				for ( sal_uInt16 i = 0; !bFlyInCnt && i < rMarkList.GetMarkCount(); ++i )
				{
					const SdrObject *pObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
                    if (FLY_AS_CHAR == ::FindFrmFmt(const_cast<SdrObject*>(
                                            pObj))->GetAnchor().GetAnchorId())
                    {
						bFlyInCnt = sal_True;
                    }
				}
				if( bFlyInCnt )
					throw uno::RuntimeException();
				if( !bFlyInCnt )
				{
					UnoActionContext aContext(pDoc);
                    pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );

					SwDrawContact* pContact = pDoc->GroupSelection( *pPage->GetDrawView() );
                    pDoc->ChgAnchor(
                        pPage->GetDrawView()->GetMarkedObjectList(),
                        FLY_AT_PARA/*int eAnchorId*/,
						sal_True, sal_False );

					pPage->GetDrawView()->UnmarkAll();
					if(pContact)
					{
						uno::Reference< uno::XInterface >  xInt = pPage->GetInterface( pContact->GetMaster() );
                        xRet = uno::Reference< drawing::XShapeGroup >(xInt, uno::UNO_QUERY);
                    }
                    pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
                }
            }
			pPage->RemovePageView();
		}
	}
	return xRet;
}

void SwXDrawPage::ungroup(const uno::Reference< drawing::XShapeGroup > & xShapeGroup) throw( uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	if(!pDoc)
		throw uno::RuntimeException();
	if(xPageAgg.is())
	{
		SwFmDrawPage* pPage = GetSvxPage();
		if(pPage)//kann das auch Null sein?
		{
			pPage->PreUnGroup(xShapeGroup);
			UnoActionContext aContext(pDoc);
            pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );

			pDoc->UnGroupSelection( *pPage->GetDrawView() );
            pDoc->ChgAnchor( pPage->GetDrawView()->GetMarkedObjectList(),
                        FLY_AT_PARA/*int eAnchorId*/,
						sal_True, sal_False );
            pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
        }
		pPage->RemovePageView();
	}
}

SwFmDrawPage* 	SwXDrawPage::GetSvxPage()
{
	if(!xPageAgg.is() && pDoc)
	{
		vos::OGuard  aGuard(Application::GetSolarMutex());
        // --> OD 2005-08-08 #i52858# - method name changed
        SdrModel* pModel = pDoc->GetOrCreateDrawModel();
        // <--
		SdrPage* pPage = pModel->GetPage( 0 );

		{
			// waehrend des queryInterface braucht man ein Ref auf das
			// Objekt, sonst wird es geloescht.
			pDrawPage = new SwFmDrawPage(pPage);
			uno::Reference< drawing::XDrawPage >  xPage = pDrawPage;
			uno::Any aAgg = xPage->queryInterface(::getCppuType((uno::Reference< uno::XAggregation >*)0));
			if(aAgg.getValueType() == ::getCppuType((uno::Reference< uno::XAggregation >*)0))
				xPageAgg = *(uno::Reference< uno::XAggregation >*)aAgg.getValue();
		}
		if( xPageAgg.is() )
			xPageAgg->setDelegator( (cppu::OWeakObject*)this );
	}
	return pDrawPage;
}

// renamed and outlined to detect where it's called
void SwXDrawPage::InvalidateSwDoc()
{
    pDoc = 0;
}

/****************************************************************************

****************************************************************************/
TYPEINIT1(SwXShape, SwClient);

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

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

	if( xShapeAgg.is() )
	{
        const uno::Type& rTunnelType = ::getCppuType((uno::Reference<lang::XUnoTunnel>*)0 );
		uno::Any aAgg = xShapeAgg->queryAggregation( rTunnelType );
		if(aAgg.getValueType() == rTunnelType)
		{
            uno::Reference<lang::XUnoTunnel> xAggTunnel =
                    *(uno::Reference<lang::XUnoTunnel>*)aAgg.getValue();
			if(xAggTunnel.is())
				return xAggTunnel->getSomething(rId);
		}
	}
	return 0;
}
namespace
{
    static void lcl_addShapePropertyEventFactories( SdrObject& _rObj, SwXShape& _rShape )
    {
        ::svx::PPropertyValueProvider pProvider( new ::svx::PropertyValueProvider( _rShape, "AnchorType" ) );
        _rObj.getShapePropertyChangeNotifier().registerProvider( ::svx::eTextShapeAnchorType, pProvider );
    }
}


SwXShape::SwXShape(uno::Reference< uno::XInterface > & xShape) :
    m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_SHAPE)),
    m_pPropertyMapEntries(aSwMapProvider.GetPropertyMapEntries(PROPERTY_MAP_TEXT_SHAPE)),
    pImplementationId(0),
	pImpl(new SwShapeDescriptor_Impl()),
	m_bDescriptor(sal_True)
{
	if(xShape.is())  // default Ctor
	{
		const uno::Type& rAggType = ::getCppuType((const uno::Reference< uno::XAggregation >*)0);
		//aAgg contains a reference of the SvxShape!
		{
			uno::Any aAgg = xShape->queryInterface(rAggType);
			if(aAgg.getValueType() == rAggType)
				xShapeAgg = *(uno::Reference< uno::XAggregation >*)aAgg.getValue();
            // --> OD 2004-07-23 #i31698#
            if ( xShapeAgg.is() )
            {
                xShapeAgg->queryAggregation( ::getCppuType((uno::Reference< drawing::XShape >*)0) ) >>= mxShape;
                ASSERT( mxShape.is(),
                        "<SwXShape::SwXShape(..)> - no XShape found at <xShapeAgg>" );
            }
            // <--
		}
		xShape = 0;
		m_refCount++;
		if( xShapeAgg.is() )
			xShapeAgg->setDelegator( (cppu::OWeakObject*)this );
		m_refCount--;

        uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
		SvxShape* pShape = 0;
		if(xShapeTunnel.is())
			pShape = reinterpret_cast< SvxShape * >(
					sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SvxShape::getUnoTunnelId()) ));

		SdrObject* pObj = pShape ? pShape->GetSdrObject() : 0;
		if(pObj)
		{
			SwFrmFmt* pFmt = ::FindFrmFmt( pObj );
			if(pFmt)
				pFmt->Add(this);

            lcl_addShapePropertyEventFactories( *pObj, *this );
            pImpl->bInitializedPropertyNotifier = true;
		}
	}
}

void SwXShape::AddExistingShapeToFmt( SdrObject& _rObj )
{
    SdrObjListIter aIter( _rObj, IM_DEEPNOGROUPS );
    while ( aIter.IsMore() )
    {
        SdrObject* pCurrent = aIter.Next();
        OSL_ENSURE( pCurrent, "SwXShape::AddExistingShapeToFmt: invalid object list element!" );
        if ( !pCurrent )
            continue;

        SwXShape* pSwShape = NULL;
        uno::Reference< lang::XUnoTunnel > xShapeTunnel( pCurrent->getWeakUnoShape(), uno::UNO_QUERY );
        if ( xShapeTunnel.is() )
            pSwShape = reinterpret_cast< SwXShape * >(
				    sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething( SwXShape::getUnoTunnelId() ) ) );
        if ( pSwShape )
        {
            if ( pSwShape->m_bDescriptor )
            {
		        SwFrmFmt* pFmt = ::FindFrmFmt( const_cast< SdrObject* >( pCurrent ) );
		        if ( pFmt )
			        pFmt->Add( pSwShape );
                pSwShape->m_bDescriptor = sal_False;
            }

            if ( !pSwShape->pImpl->bInitializedPropertyNotifier )
            {
                lcl_addShapePropertyEventFactories( *pCurrent, *pSwShape );
                pSwShape->pImpl->bInitializedPropertyNotifier = true;
            }
        }
    }
}


SwXShape::~SwXShape()
{
	if (xShapeAgg.is())
	{
		uno::Reference< uno::XInterface >  xRef;
		xShapeAgg->setDelegator(xRef);
	}
	delete pImpl;
}

uno::Any SwXShape::queryInterface( const uno::Type& aType ) throw( uno::RuntimeException )
{
    uno::Any aRet = SwXShapeBaseClass::queryInterface(aType);
    // --> OD 2005-08-15 #i53320# - follow-up of #i31698#
    // interface drawing::XShape is overloaded. Thus, provide
    // correct object instance.
    if(!aRet.hasValue() && xShapeAgg.is())
    {
        if(aType == ::getCppuType((uno::Reference<XShape>*)0))
            aRet <<= uno::Reference<XShape>(this);
        else
            aRet = xShapeAgg->queryAggregation(aType);
    }
    // <--
	return aRet;
}

uno::Sequence< uno::Type > SwXShape::getTypes(  ) throw(uno::RuntimeException)
{
    uno::Sequence< uno::Type > aRet = SwXShapeBaseClass::getTypes();
	if(xShapeAgg.is())
	{
        uno::Any aProv = xShapeAgg->queryAggregation(::getCppuType((uno::Reference< XTypeProvider >*)0));
		if(aProv.hasValue())
		{
            uno::Reference< XTypeProvider > xAggProv;
			aProv >>= xAggProv;
            uno::Sequence< uno::Type > aAggTypes = xAggProv->getTypes();
			const uno::Type* pAggTypes = aAggTypes.getConstArray();
			long nIndex = aRet.getLength();

			aRet.realloc(nIndex + aAggTypes.getLength());
			uno::Type* pBaseTypes = aRet.getArray();

			for(long i = 0; i < aAggTypes.getLength(); i++)
				pBaseTypes[nIndex++] = pAggTypes[i];
		}
	}
	return aRet;
}

uno::Sequence< sal_Int8 > SwXShape::getImplementationId(  ) throw(uno::RuntimeException)
{
    vos::OGuard aGuard( Application::GetSolarMutex() );
	// do we need to compute the implementation id for this instance?
    if( !pImplementationId && xShapeAgg.is())
	{
        uno::Reference< XShape > xAggShape;
        xShapeAgg->queryAggregation( ::getCppuType((uno::Reference< XShape >*)0) ) >>= xAggShape;

        if( xAggShape.is() )
		{
            const rtl::OUString aShapeType( xAggShape->getShapeType() );
            // did we already compute an implementation id for the agregated shape type?
            SwShapeImplementationIdMap::iterator aIter( aImplementationIdMap.find(aShapeType ) );
			if( aIter == aImplementationIdMap.end() )
			{
				// we need to create a new implementation id for this
				// note: this memory is not free'd until application exists
				//		 but since we have a fixed set of shapetypes and the
				//		 memory will be reused this is ok.
                pImplementationId = new uno::Sequence< sal_Int8 >( 16 );
                rtl_createUuid( (sal_uInt8 *) pImplementationId->getArray(), 0, sal_True );
                aImplementationIdMap[ aShapeType ] = pImplementationId;
			}
			else
			{
				// use the already computed implementation id
                pImplementationId = (*aIter).second;
			}
		}
	}
    if( NULL == pImplementationId )
	{
        DBG_ERROR( "Could not create an implementation id for a SwXShape!" );
        return uno::Sequence< sal_Int8 > ();
	}
	else
	{
        return *pImplementationId;
	}
}

uno::Reference< beans::XPropertySetInfo >  SwXShape::getPropertySetInfo(void) throw( uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
    uno::Reference< beans::XPropertySetInfo >  aRet;
	if(xShapeAgg.is())
	{
        const uno::Type& rPropSetType = ::getCppuType((const uno::Reference< beans::XPropertySet >*)0);
		uno::Any aPSet = xShapeAgg->queryAggregation( rPropSetType );
		if(aPSet.getValueType() == rPropSetType && aPSet.getValue())
		{
            uno::Reference< beans::XPropertySet >  xPrSet =
                    *(uno::Reference< beans::XPropertySet >*)aPSet.getValue();
            uno::Reference< beans::XPropertySetInfo >  xInfo = xPrSet->getPropertySetInfo();
			// PropertySetInfo verlaengern!
            const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
            aRet = new SfxExtItemPropertySetInfo( m_pPropertyMapEntries, aPropSeq );
		}
	}
	if(!aRet.is())
        aRet = m_pPropSet->getPropertySetInfo();
	return aRet;
}

void SwXShape::setPropertyValue(const rtl::OUString& rPropertyName, const uno::Any& aValue)
     throw( beans::UnknownPropertyException, beans::PropertyVetoException,
            lang::IllegalArgumentException, lang::WrappedTargetException,
            uno::RuntimeException)
{
    vos::OGuard  aGuard(Application::GetSolarMutex());
	SwFrmFmt* 	pFmt = GetFrmFmt();
    const SfxItemPropertySimpleEntry*  pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
	if(xShapeAgg.is())
	{
        if(pEntry)
		{
            if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
                throw beans::PropertyVetoException ( rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
			//mit Layout kann der Anker umgesetzt werden, ohne dass sich die Position aendert
			if(pFmt)
			{
				SwAttrSet aSet(pFmt->GetAttrSet());
                SwDoc* pDoc = pFmt->GetDoc();
                if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORFRAME == pEntry->nMemberId)
                {
                    sal_Bool bDone = sal_True;
                    uno::Reference<text::XTextFrame> xFrame;
                    if(aValue >>= xFrame)
                    {
                        uno::Reference<lang::XUnoTunnel> xTunnel(xFrame, uno::UNO_QUERY);
                        SwXFrame* pFrame = xTunnel.is() ?
                                reinterpret_cast< SwXFrame * >(
									sal::static_int_cast< sal_IntPtr >( xTunnel->getSomething(SwXFrame::getUnoTunnelId()) ))
								: 0;
                        if(pFrame && pFrame->GetFrmFmt() &&
                            pFrame->GetFrmFmt()->GetDoc() == pDoc)
                        {
                            UnoActionContext aCtx(pDoc);
                            SfxItemSet aItemSet( pDoc->GetAttrPool(),
                                        RES_FRMATR_BEGIN, RES_FRMATR_END - 1 );
                            aItemSet.SetParent(&pFmt->GetAttrSet());
                            SwFmtAnchor aAnchor = (const SwFmtAnchor&)aItemSet.Get(pEntry->nWID);
                            SwPosition aPos(*pFrame->GetFrmFmt()->GetCntnt().GetCntntIdx());
                            aAnchor.SetAnchor(&aPos);
                            aAnchor.SetType(FLY_AT_FLY);
                            aItemSet.Put(aAnchor);
                            pFmt->SetFmtAttr(aItemSet);
                            bDone = sal_True;
                        }
                    }
                    if(!bDone)
                        throw lang::IllegalArgumentException();
                }
                else if(RES_OPAQUE == pEntry->nWID)
                {
                    SvxShape* pSvxShape = GetSvxShape();
                    DBG_ASSERT(pSvxShape, "No SvxShape found!");
                    if(pSvxShape)
                    {
                        SdrObject* pObj = pSvxShape->GetSdrObject();
                        // OD 25.06.2003 #108784# - set layer of new drawing
                        // object to corresponding invisible layer.
                        bool bIsVisible = pDoc->IsVisibleLayerId( pObj->GetLayer() );
                        if(FmFormInventor != pObj->GetObjInventor())
                        {
                            pObj->SetLayer( *(sal_Bool*)aValue.getValue()
                                            ? ( bIsVisible ? pDoc->GetHeavenId() : pDoc->GetInvisibleHeavenId() )
                                            : ( bIsVisible ? pDoc->GetHellId() : pDoc->GetInvisibleHellId() ));
                        }
                        else
                        {
                            pObj->SetLayer( bIsVisible ? pDoc->GetControlsId() : pDoc->GetInvisibleControlsId());
                        }

                    }

                }
                // OD 2004-04-22 #i26791# - special handling for property FN_TEXT_RANGE
                else if ( FN_TEXT_RANGE == pEntry->nWID )
                {
                    SwFmtAnchor aAnchor( static_cast<const SwFmtAnchor&>(aSet.Get( RES_ANCHOR )) );
                    if (aAnchor.GetAnchorId() == FLY_AT_PAGE)
                    {
                        // set property <TextRange> not valid for to-page anchored shapes
                        throw lang::IllegalArgumentException();
                    }
                    else
                    {
                        SwUnoInternalPaM* pInternalPam =
                                        new SwUnoInternalPaM( *(pFmt->GetDoc()) );
                        uno::Reference< text::XTextRange > xRg;
                        aValue >>= xRg;
                        if (::sw::XTextRangeToSwPaM(*pInternalPam, xRg) )
                        {
                            if (aAnchor.GetAnchorId() == FLY_AS_CHAR)
                            {
                                //delete old SwFmtFlyCnt
                                //With AnchorAsCharacter the current TxtAttribute has to be deleted.
                                //Tbis removes the frame format too.
                                //To prevent this the connection between format and attribute has to be broken before.
                                const SwPosition *pPos = aAnchor.GetCntntAnchor();
                                SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
                                ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
                                const xub_StrLen nIdx = pPos->nContent.GetIndex();
                                SwTxtAttr * const pHnt =
                                    pTxtNode->GetTxtAttrForCharAt(
                                        nIdx, RES_TXTATR_FLYCNT );
                                DBG_ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
                                            "Missing FlyInCnt-Hint." );
                                DBG_ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFmt,
                                            "Wrong TxtFlyCnt-Hint." );
                                const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt())
                                    .SetFlyFmt();

                                //The connection is removed now the attribute can be deleted.
                                pTxtNode->DeleteAttributes(
                                    RES_TXTATR_FLYCNT, nIdx );
                                //create a new one
                                SwTxtNode *pNd = pInternalPam->GetNode()->GetTxtNode();
                                DBG_ASSERT( pNd, "Cursor not at TxtNode." );
                                SwFmtFlyCnt aFmt( pFmt );
                                pNd->InsertItem(aFmt, pInternalPam->GetPoint()
                                        ->nContent.GetIndex(), 0 );
                            }
                            else
                            {
                                aAnchor.SetAnchor( pInternalPam->GetPoint() );
                                aSet.Put(aAnchor);
                                pFmt->SetFmtAttr(aSet);
                            }
                        }
                        else
                        {
                            throw uno::RuntimeException();
                        }
                        delete pInternalPam;
                    }
                }
                // --> OD 2004-08-06 #i28749#
                else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
                {
                    sal_Int16 nPositionLayoutDir = 0;
                    aValue >>= nPositionLayoutDir;
                    pFmt->SetPositionLayoutDir( nPositionLayoutDir );
                }
                // <--
                else if( pDoc->GetCurrentLayout())	//swmod 080218
				{
                    UnoActionContext aCtx(pDoc);
                    if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
                    {
                        SdrObject* pObj = pFmt->FindSdrObject();
                        SdrMarkList aList;
                        SdrMark aMark(pObj);
                        aList.InsertEntry(aMark);
                        sal_Int32 nAnchor = 0;
                        cppu::enum2int( nAnchor, aValue );
                        pDoc->ChgAnchor( aList, (RndStdIds)nAnchor,
                                                sal_False, sal_True );
                    }
                    else
					{
                        m_pPropSet->setPropertyValue(*pEntry, aValue, aSet);
                        pFmt->SetFmtAttr(aSet);
					}
				}
                else
				{
                    m_pPropSet->setPropertyValue( *pEntry, aValue, aSet );

                    if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
                    {
                        bool bSetAttr = true;
                        sal_Int32 eNewAnchor = SWUnoHelper::GetEnumAsInt32( aValue );

                        //if old anchor was in_cntnt the related text attribute has to be removed
                        const SwFmtAnchor& rOldAnchor = pFmt->GetAnchor();
                        RndStdIds eOldAnchorId = rOldAnchor.GetAnchorId();
                        SdrObject* pObj = pFmt->FindSdrObject();
                        SwFrmFmt *pFlyFmt = FindFrmFmt( pObj );
                        pFlyFmt->DelFrms();
                        if( text::TextContentAnchorType_AS_CHARACTER != eNewAnchor &&
                            (FLY_AS_CHAR == eOldAnchorId))
                        {
                            //With AnchorAsCharacter the current TxtAttribute has to be deleted.
                            //Tbis removes the frame format too.
                            //To prevent this the connection between format and attribute has to be broken before.
                            const SwPosition *pPos = rOldAnchor.GetCntntAnchor();
                            SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
                            ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
                            const xub_StrLen nIdx = pPos->nContent.GetIndex();
                            SwTxtAttr * const pHnt =
                                pTxtNode->GetTxtAttrForCharAt(
                                    nIdx, RES_TXTATR_FLYCNT );
                            DBG_ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
                                        "Missing FlyInCnt-Hint." );
                            DBG_ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFlyFmt,
                                        "Wrong TxtFlyCnt-Hint." );
                            const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt())
                                .SetFlyFmt();

                            //The connection is removed now the attribute can be deleted.
                            pTxtNode->DeleteAttributes(RES_TXTATR_FLYCNT, nIdx);
                        }
                        else if( text::TextContentAnchorType_AT_PAGE != eNewAnchor &&
                                (FLY_AT_PAGE == eOldAnchorId))
                        {
                            SwFmtAnchor aNewAnchor( dynamic_cast< const SwFmtAnchor& >( aSet.Get( RES_ANCHOR ) ) );
                            //if the fly has been anchored at page then it needs to be connected
                            //to the content position
                            SwPaM aPam(pDoc->GetNodes().GetEndOfContent());
                            if( pDoc->GetCurrentLayout() )
                            {
                                SwCrsrMoveState aState( MV_SETONLYTEXT );
                                Point aTmp( pObj->GetSnapRect().TopLeft() );
                                pDoc->GetCurrentLayout()->GetCrsrOfst( aPam.GetPoint(), aTmp, &aState );
                            }
                            else
                            {
                                //without access to the layout the last node of the body will be used as anchor position
                                aPam.Move( fnMoveBackward, fnGoDoc );
                            }
                            //anchor position has to be inserted after the text attribute has been inserted
                            aNewAnchor.SetAnchor( aPam.GetPoint() );
                            aSet.Put( aNewAnchor );
                            pFmt->SetFmtAttr(aSet);
                            bSetAttr = false;
                            if( text::TextContentAnchorType_AS_CHARACTER == eNewAnchor &&
                                (FLY_AS_CHAR != eOldAnchorId))
                            {
                                //the RES_TXTATR_FLYCNT needs to be added now
                                SwTxtNode *pNd = aPam.GetNode()->GetTxtNode();
                                DBG_ASSERT( pNd, "Crsr is not in a TxtNode." );
                                SwFmtFlyCnt aFmt( pFlyFmt );
                                pNd->InsertItem(aFmt,
                                    aPam.GetPoint()->nContent.GetIndex(), 0 );
                                //aPam.GetPoint()->nContent--;

                            }
                        }
                        if( bSetAttr )
                            pFmt->SetFmtAttr(aSet);
                    }
                    else
                        pFmt->SetFmtAttr(aSet);
				}
			}
			else
			{
				SfxPoolItem* pItem = 0;
                switch(pEntry->nWID)
				{
					case RES_ANCHOR:
						pItem = pImpl->GetAnchor(sal_True);
					break;
					case RES_HORI_ORIENT:
						pItem = pImpl->GetHOrient(sal_True);
					break;
					case RES_VERT_ORIENT:
						pItem = pImpl->GetVOrient(sal_True);
					break;
					case  RES_LR_SPACE:
						pItem = pImpl->GetLRSpace(sal_True);
					break;
					case  RES_UL_SPACE:
						pItem = pImpl->GetULSpace(sal_True);
					break;
					case  RES_SURROUND:
						pItem = pImpl->GetSurround(sal_True);
					break;
					case  FN_TEXT_RANGE:
					{
                        const uno::Type rTextRangeType =
                            ::getCppuType((uno::Reference< text::XTextRange>*)0);
						if(aValue.getValueType() == rTextRangeType)
						{
                            uno::Reference< text::XTextRange > & rRange = pImpl->GetTextRange();
                            rRange = *(uno::Reference< text::XTextRange > *)aValue.getValue();
						}
					}
					break;
                    case RES_OPAQUE :
                        pImpl->SetOpaque(*(sal_Bool*)aValue.getValue());
                    break;
                    // OD 2004-04-22 #i26791#
                    case RES_FOLLOW_TEXT_FLOW:
                    {
                        pItem = pImpl->GetFollowTextFlow( sal_True );
                    }
                    break;
                    // OD 2004-05-05 #i28701#
                    case RES_WRAP_INFLUENCE_ON_OBJPOS:
                    {
                        pItem = pImpl->GetWrapInfluenceOnObjPos( sal_True );
                    }
                    break;
                    // --> OD 2004-08-06 #i28749#
                    case FN_SHAPE_POSITION_LAYOUT_DIR :
                    {
                        sal_Int16 nPositionLayoutDir = 0;
                        aValue >>= nPositionLayoutDir;
                        pImpl->SetPositionLayoutDir( nPositionLayoutDir );
                    }
                    break;
                    // <--
                }
                if(pItem)
                    ((SfxPoolItem*)pItem)->PutValue(aValue, pEntry->nMemberId);
            }
        }
        else
        {
            uno::Reference< beans::XPropertySet >  xPrSet;
            const uno::Type& rPSetType =
                ::getCppuType((const uno::Reference< beans::XPropertySet >*)0);
			uno::Any aPSet = xShapeAgg->queryAggregation(rPSetType);
			if(aPSet.getValueType() != rPSetType || !aPSet.getValue())
				throw uno::RuntimeException();
            xPrSet = *(uno::Reference< beans::XPropertySet >*)aPSet.getValue();
            // --> OD 2004-08-05 #i31698# - setting the caption point of a
            // caption object doesn't have to change the object position.
            // Thus, keep the position, before the caption point is set and
            // restore it afterwards.
            awt::Point aKeepedPosition( 0, 0 );
            if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CaptionPoint"))) &&
                 getShapeType().equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CaptionShape"))) )
            {
                    aKeepedPosition = getPosition();
            }
            // <--
            if( pFmt && pFmt->GetDoc()->GetCurrentViewShell() )	//swmod 071108//swmod 071225
			{
				UnoActionContext aCtx(pFmt->GetDoc());
                xPrSet->setPropertyValue(rPropertyName, aValue);
			}
			else
                xPrSet->setPropertyValue(rPropertyName, aValue);
            // --> OD 2004-11-11 #i35007# - adjustment of the position
            // attributes, if the transformation is set, causes wrong alignments
            // and is no longer needed.
            // The position attributes are set, if the drawing object is added
            // to the draw page - see <SwXDrawPage::add(..)> -  and on its first
            // positioning - see <SwAnchoredDrawObject::MakeObjPos().
//            // --> OD 2004-07-28 #i31698# - additionally adjust the position
//            // properties of the shape, if the transformation is set and
//            // the shape isn't a group member.
//            if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation"))) &&
//                 !_GetTopGroupObj() )
//            {
//                drawing::HomogenMatrix3 aMatrix;
//                aValue >>= aMatrix;
//                awt::Point aNewPos( basegfx::fround( aMatrix.Line1.Column3 ),
//                                    basegfx::fround( aMatrix.Line2.Column3 ) );
//                _AdjustPositionProperties( aNewPos );
//            }
            // --> OD 2004-08-05 #i31698# - restore object position, if caption
            // point is set.
            if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CaptionPoint"))) &&
                 getShapeType().equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CaptionShape"))) )
            {
                setPosition( aKeepedPosition );
            }
		}
	}
}

uno::Any SwXShape::getPropertyValue(const rtl::OUString& rPropertyName)
    throw( beans::UnknownPropertyException, lang::WrappedTargetException,
           uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	uno::Any aRet;
	SwFrmFmt* 	pFmt = GetFrmFmt();
	if(xShapeAgg.is())
	{
        const SfxItemPropertySimpleEntry*  pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
        if(pEntry)
		{
			if(pFmt)
			{
                if(RES_OPAQUE == pEntry->nWID)
                {
                    SvxShape* pSvxShape = GetSvxShape();
                    DBG_ASSERT(pSvxShape, "No SvxShape found!");
                    if(pSvxShape)
                    {
                        SdrObject* pObj = pSvxShape->GetSdrObject();
                        // OD 02.07.2003 #108784# - consider invisible layers
                        sal_Bool bOpaque =
                            ( pObj->GetLayer() != pFmt->GetDoc()->GetHellId() &&
                              pObj->GetLayer() != pFmt->GetDoc()->GetInvisibleHellId() );
                        aRet.setValue(&bOpaque, ::getBooleanCppuType());
                    }
                }
                else if(FN_ANCHOR_POSITION == pEntry->nWID)
                {
                    SvxShape* pSvxShape = GetSvxShape();
                    DBG_ASSERT(pSvxShape, "No SvxShape found!");
                    if(pSvxShape)
                    {
                        SdrObject* pObj = pSvxShape->GetSdrObject();
                        Point aPt = pObj->GetAnchorPos();
                        awt::Point aPoint( TWIP_TO_MM100( aPt.X() ),
                                           TWIP_TO_MM100( aPt.Y() ) );
                        aRet.setValue(&aPoint, ::getCppuType( (awt::Point*)0 ));
                    }
                }
                // OD 2004-04-22 #i26791# - special handling for FN_TEXT_RANGE
                else if ( FN_TEXT_RANGE == pEntry->nWID )
                {
                    const SwFmtAnchor aAnchor = pFmt->GetAnchor();
                    if (aAnchor.GetAnchorId() == FLY_AT_PAGE)
                    {
                        // return nothing, because property <TextRange> isn't
                        // valid for to-page anchored shapes
                        uno::Any aAny;
                        aRet = aAny;
                    }
                    else
                    {
                        if ( aAnchor.GetCntntAnchor() )
                        {
                            const uno::Reference< text::XTextRange > xTextRange
                                = SwXTextRange::CreateXTextRange(
                                                    *pFmt->GetDoc(),
                                                    *aAnchor.GetCntntAnchor(),
                                                    0L );
                            aRet.setValue(&xTextRange, ::getCppuType((uno::Reference<text::XTextRange>*)0));
                        }
                        else
                        {
                            // return nothing
                            uno::Any aAny;
                            aRet = aAny;
                        }
                    }
                }
                // --> OD 2004-08-06 #i28749#
                else if ( FN_SHAPE_TRANSFORMATION_IN_HORI_L2R == pEntry->nWID )
                {
                    // get property <::drawing::Shape::Transformation>
                    // without conversion to layout direction as below
                    aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")) );
                }
                else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
                {
                    aRet <<= pFmt->GetPositionLayoutDir();
                }
                // <--
                // --> OD 2004-10-28 #i36248#
                else if ( FN_SHAPE_STARTPOSITION_IN_HORI_L2R == pEntry->nWID )
                {
                    // get property <::drawing::Shape::StartPosition>
                    // without conversion to layout direction as below
                    aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartPosition")) );
                }
                else if ( FN_SHAPE_ENDPOSITION_IN_HORI_L2R == pEntry->nWID )
                {
                    // get property <::drawing::Shape::EndPosition>
                    // without conversion to layout direction as below
                    aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EndPosition")) );
                }
                // <--
                else
                {
                    const SwAttrSet& rSet = pFmt->GetAttrSet();
                    m_pPropSet->getPropertyValue(*pEntry, rSet, aRet);
                }
			}
			else
			{
				SfxPoolItem* pItem = 0;
                switch(pEntry->nWID)
				{
					case RES_ANCHOR:
						pItem = pImpl->GetAnchor();
					break;
					case RES_HORI_ORIENT:
						pItem = pImpl->GetHOrient();
					break;
					case RES_VERT_ORIENT:
						pItem = pImpl->GetVOrient();
					break;
					case  RES_LR_SPACE:
						pItem = pImpl->GetLRSpace();
					break;
					case  RES_UL_SPACE:
						pItem = pImpl->GetULSpace();
					break;
					case  RES_SURROUND:
						pItem = pImpl->GetSurround();
					break;
					case FN_TEXT_RANGE :
                        aRet.setValue(&pImpl->GetTextRange(), ::getCppuType((uno::Reference<text::XTextRange>*)0));
					break;
                    case RES_OPAQUE :
                        aRet.setValue(&pImpl->GetOpaque(), ::getBooleanCppuType());
                    break;
                    case FN_ANCHOR_POSITION :
                    {
                        awt::Point aPoint;
                        aRet.setValue(&aPoint, ::getCppuType( (awt::Point*)0 ));
                    }
                    break;
                    // OD 2004-04-22 #i26791#
                    case RES_FOLLOW_TEXT_FLOW :
                    {
                        pItem = pImpl->GetFollowTextFlow();
                    }
                    break;
                    // OD 2004-05-05 #i28701#
                    case RES_WRAP_INFLUENCE_ON_OBJPOS:
                    {
                        pItem = pImpl->GetWrapInfluenceOnObjPos();
                    }
                    break;
                    // --> OD 2004-08-06 #i28749#
                    case FN_SHAPE_TRANSFORMATION_IN_HORI_L2R:
                    {
                        // get property <::drawing::Shape::Transformation>
                        // without conversion to layout direction as below
                        aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")) );
                    }
                    break;
                    case FN_SHAPE_POSITION_LAYOUT_DIR:
                    {
                        aRet <<= pImpl->GetPositionLayoutDir();
                    }
                    break;
                    // <--
                    // --> OD 2004-08-06 #i36248#
                    case FN_SHAPE_STARTPOSITION_IN_HORI_L2R:
                    {
                        // get property <::drawing::Shape::StartPosition>
                        // without conversion to layout direction as below
                        aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartPosition")) );
                    }
                    break;
                    case FN_SHAPE_ENDPOSITION_IN_HORI_L2R:
                    {
                        // get property <::drawing::Shape::StartPosition>
                        // without conversion to layout direction as below
                        aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EndPosition")) );
                    }
                    break;
                    // <--
                }
                if(pItem)
                    pItem->QueryValue(aRet, pEntry->nMemberId);
            }
        }
        else
        {
            aRet = _getPropAtAggrObj( rPropertyName );

            // --> OD 2004-07-28 #i31698# - convert the position (translation)
            // of the drawing object in the transformation
            if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation"))) )
            {
                drawing::HomogenMatrix3 aMatrix;
                aRet >>= aMatrix;
                aRet <<= _ConvertTransformationToLayoutDir( aMatrix );
            }
            // <--
            // --> OD 2004-10-28 #i36248#
            else if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartPosition"))) )
            {
                awt::Point aStartPos;
                aRet >>= aStartPos;
                // --> OD 2009-01-12 #i59051#
                aRet <<= _ConvertStartOrEndPosToLayoutDir( aStartPos );
                // <--
            }
            else if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EndPosition"))) )
            {
                awt::Point aEndPos;
                aRet >>= aEndPos;
                // --> OD 2009-01-12 #i59051#
                aRet <<= _ConvertStartOrEndPosToLayoutDir( aEndPos );
                // <--
            }
            // --> OD 2009-01-16 #i59051#
            else if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PolyPolygonBezier"))) )
            {
                drawing::PolyPolygonBezierCoords aPath;
                aRet >>= aPath;
                aRet <<= _ConvertPolyPolygonBezierToLayoutDir( aPath );
                // <--
            }
            // <--
        }
	}
	return aRet;
}

uno::Any SwXShape::_getPropAtAggrObj( const ::rtl::OUString& _rPropertyName )
    throw( beans::UnknownPropertyException, lang::WrappedTargetException,
           uno::RuntimeException )
{
    uno::Any aRet;

    uno::Reference< beans::XPropertySet >  xPrSet;
    const uno::Type& rPSetType =
                ::getCppuType((const uno::Reference< beans::XPropertySet >*)0);
    uno::Any aPSet = xShapeAgg->queryAggregation(rPSetType);
    if ( aPSet.getValueType() != rPSetType || !aPSet.getValue() )
    {
        throw uno::RuntimeException();
    }
    xPrSet = *(uno::Reference< beans::XPropertySet >*)aPSet.getValue();
    aRet = xPrSet->getPropertyValue( _rPropertyName );

    return aRet;
}


beans::PropertyState SwXShape::getPropertyState( const rtl::OUString& rPropertyName )
    throw(beans::UnknownPropertyException, uno::RuntimeException)
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
    uno::Sequence< rtl::OUString > aNames(1);
    rtl::OUString* pStrings = aNames.getArray();
	pStrings[0] = rPropertyName;
    uno::Sequence< beans::PropertyState > aStates = getPropertyStates(aNames);
	return aStates.getConstArray()[0];
}

uno::Sequence< beans::PropertyState > SwXShape::getPropertyStates(
    const uno::Sequence< rtl::OUString >& aPropertyNames )
        throw(beans::UnknownPropertyException, uno::RuntimeException)
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	SwFrmFmt* 	pFmt = GetFrmFmt();
    uno::Sequence< beans::PropertyState > aRet(aPropertyNames.getLength());
	if(xShapeAgg.is())
	{
        SvxShape* pSvxShape = GetSvxShape();
        sal_Bool bGroupMember = sal_False;
        sal_Bool bFormControl = sal_False;
        SdrObject* pObject = pSvxShape->GetSdrObject();
        if(pObject)
        {
            bGroupMember = pObject->GetUpGroup() != 0;
            bFormControl = pObject->GetObjInventor() == FmFormInventor;
        }
        const rtl::OUString* pNames = aPropertyNames.getConstArray();
        beans::PropertyState* pRet = aRet.getArray();
        uno::Reference< XPropertyState >  xShapePrState;
		for(sal_Int32 nProperty = 0; nProperty < aPropertyNames.getLength(); nProperty++)
		{
            const SfxItemPropertySimpleEntry*  pEntry = m_pPropSet->getPropertyMap()->getByName( pNames[nProperty] );
            if(pEntry)
			{
                if(RES_OPAQUE == pEntry->nWID)
                    pRet[nProperty] = bFormControl ?
                        beans::PropertyState_DEFAULT_VALUE : beans::PropertyState_DIRECT_VALUE;
                else if(FN_ANCHOR_POSITION == pEntry->nWID)
                    pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
                else if(FN_TEXT_RANGE == pEntry->nWID)
                    pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
                else if(bGroupMember)
                    pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
                else if(pFmt)
				{
                    const SwAttrSet& rSet = pFmt->GetAttrSet();
                    SfxItemState eItemState = rSet.GetItemState(pEntry->nWID, sal_False);

                    if(SFX_ITEM_SET == eItemState)
                        pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
                    else if(SFX_ITEM_DEFAULT == eItemState)
                        pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
                    else
                        pRet[nProperty] = beans::PropertyState_AMBIGUOUS_VALUE;
				}
				else
				{
					SfxPoolItem* pItem = 0;
                    switch(pEntry->nWID)
					{
						case RES_ANCHOR:
							pItem = pImpl->GetAnchor();
						break;
						case RES_HORI_ORIENT:
							pItem = pImpl->GetHOrient();
						break;
						case RES_VERT_ORIENT:
							pItem = pImpl->GetVOrient();
						break;
						case  RES_LR_SPACE:
							pItem = pImpl->GetLRSpace();
						break;
						case  RES_UL_SPACE:
							pItem = pImpl->GetULSpace();
						break;
						case  RES_SURROUND:
							pItem = pImpl->GetSurround();
						break;
                        // OD 2004-05-05 #i28701#
                        case RES_WRAP_INFLUENCE_ON_OBJPOS:
                        {
                            pItem = pImpl->GetWrapInfluenceOnObjPos();
                        }
                        break;
                    }
					if(pItem)
                        pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
					else
                        pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
				}
			}
			else
			{
				if(!xShapePrState.is())
				{
                    const uno::Type& rPStateType = ::getCppuType((uno::Reference< XPropertyState >*)0);
					uno::Any aPState = xShapeAgg->queryAggregation(rPStateType);
					if(aPState.getValueType() != rPStateType || !aPState.getValue())
						throw uno::RuntimeException();
                    xShapePrState = *(uno::Reference< XPropertyState >*)aPState.getValue();
				}
				pRet[nProperty] = xShapePrState->getPropertyState(pNames[nProperty]);
			}
		}
	}
	else
        throw uno::RuntimeException();
	return aRet;
}

void SwXShape::setPropertyToDefault( const rtl::OUString& rPropertyName )
    throw(beans::UnknownPropertyException, uno::RuntimeException)
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	SwFrmFmt* 	pFmt = GetFrmFmt();
	if(xShapeAgg.is())
	{
        const SfxItemPropertySimpleEntry*  pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
        if(pEntry)
		{
            if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
                throw uno::RuntimeException( rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
			if(pFmt)
			{
				const SfxItemSet& rSet = pFmt->GetAttrSet();
                SfxItemSet aSet(pFmt->GetDoc()->GetAttrPool(), pEntry->nWID, pEntry->nWID);
				aSet.SetParent(&rSet);
                aSet.ClearItem(pEntry->nWID);
				pFmt->GetDoc()->SetAttr(aSet, *pFmt);
			}
			else
			{
                switch(pEntry->nWID)
				{
					case RES_ANCHOR:		pImpl->RemoveAnchor(); 	break;
					case RES_HORI_ORIENT: 	pImpl->RemoveHOrient(); break;
					case RES_VERT_ORIENT:	pImpl->RemoveVOrient();	break;
					case  RES_LR_SPACE:		pImpl->RemoveLRSpace();	break;
					case  RES_UL_SPACE:		pImpl->RemoveULSpace();	break;
					case  RES_SURROUND:		pImpl->RemoveSurround();break;
                    case RES_OPAQUE :       pImpl->SetOpaque(sal_False);  break;
                    case FN_TEXT_RANGE :
					break;
                    // OD 2004-04-22 #i26791#
                    case RES_FOLLOW_TEXT_FLOW:
                    {
                        pImpl->RemoveFollowTextFlow();
                    }
                    break;
                    // OD 2004-05-05 #i28701#
                    case RES_WRAP_INFLUENCE_ON_OBJPOS:
                    {
                        pImpl->RemoveWrapInfluenceOnObjPos();
                    }
                    break;
				}
			}
		}
		else
		{
            const uno::Type& rPStateType = ::getCppuType((uno::Reference< XPropertyState >*)0);
			uno::Any aPState = xShapeAgg->queryAggregation(rPStateType);
			if(aPState.getValueType() != rPStateType || !aPState.getValue())
				throw uno::RuntimeException();
            uno::Reference< XPropertyState > xShapePrState = *(uno::Reference< XPropertyState >*)aPState.getValue();
			xShapePrState->setPropertyToDefault( rPropertyName );
		}
	}
	else
        throw uno::RuntimeException();
}

uno::Any SwXShape::getPropertyDefault( const rtl::OUString& rPropertyName )
    throw( beans::UnknownPropertyException, lang::WrappedTargetException,
           uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	SwFrmFmt* 	pFmt = GetFrmFmt();
    uno::Any aRet;
	if(xShapeAgg.is())
	{
        const SfxItemPropertySimpleEntry*  pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
        if(pEntry)
		{
            if(pEntry->nWID < RES_FRMATR_END && pFmt)
			{
				const SfxPoolItem& rDefItem =
                    pFmt->GetDoc()->GetAttrPool().GetDefaultItem(pEntry->nWID);
                rDefItem.QueryValue(aRet, pEntry->nMemberId);
			}
			else
                throw uno::RuntimeException();
		}
		else
		{
            const uno::Type& rPStateType = ::getCppuType((uno::Reference< XPropertyState >*)0);
			uno::Any aPState = xShapeAgg->queryAggregation(rPStateType);
			if(aPState.getValueType() != rPStateType || !aPState.getValue())
				throw uno::RuntimeException();
            uno::Reference< XPropertyState > xShapePrState = *(uno::Reference< XPropertyState >*)aPState.getValue();
			xShapePrState->getPropertyDefault( rPropertyName );
		}
	}
	else
        throw uno::RuntimeException();
	return aRet;
}

void SwXShape::addPropertyChangeListener(
    const rtl::OUString& _propertyName,
    const uno::Reference< beans::XPropertyChangeListener > & _listener )
    throw( beans::UnknownPropertyException, lang::WrappedTargetException,
           uno::RuntimeException )
{
    if ( !xShapeAgg.is() )
        throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no shape aggregate" ) ), *this );

    // must be handled by the aggregate
    uno::Reference< beans::XPropertySet > xShapeProps;
    if ( xShapeAgg->queryAggregation( beans::XPropertySet::static_type() ) >>= xShapeProps )
        xShapeProps->addPropertyChangeListener( _propertyName, _listener );
}

void SwXShape::removePropertyChangeListener(
    const rtl::OUString& _propertyName,
    const uno::Reference< beans::XPropertyChangeListener > & _listener)
    throw( beans::UnknownPropertyException, lang::WrappedTargetException,
           uno::RuntimeException )
{
    if ( !xShapeAgg.is() )
        throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no shape aggregate" ) ), *this );

    // must be handled by the aggregate
    uno::Reference< beans::XPropertySet > xShapeProps;
    if ( xShapeAgg->queryAggregation( beans::XPropertySet::static_type() ) >>= xShapeProps )
        xShapeProps->removePropertyChangeListener( _propertyName, _listener );
}

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

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

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

void SwXShape::attach(const uno::Reference< text::XTextRange > & xTextRange)
    throw( lang::IllegalArgumentException, uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());

    // get access to SwDoc
    // (see also SwXTextRange::XTextRangeToSwPaM)
    SwDoc*      pDoc = 0;
    uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
    if(xRangeTunnel.is())
	{
        SwXTextRange* pRange = 0;
        OTextCursorHelper* pCursor = 0;
        SwXTextPortion* pPortion = 0;
        SwXText* pText = 0;
        SwXParagraph* pParagraph = 0;

		pRange 	= reinterpret_cast< SwXTextRange * >(
				sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXTextRange::getUnoTunnelId()) ));
        pText 	= reinterpret_cast< SwXText * >(
				sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXText::getUnoTunnelId()) ));
        pCursor = reinterpret_cast< OTextCursorHelper * >(
				sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( OTextCursorHelper::getUnoTunnelId()) ));
        pPortion = reinterpret_cast< SwXTextPortion * >(
				sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXTextPortion::getUnoTunnelId()) ));
        pParagraph = reinterpret_cast< SwXParagraph * >(
                sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXParagraph::getUnoTunnelId( ) ) ) );

        if (pRange)
            pDoc = pRange->GetDoc();
        else if (!pDoc && pText)
            pDoc = pText->GetDoc();
        else if (!pDoc && pCursor)
            pDoc = pCursor->GetDoc();
        else if ( !pDoc && pPortion && pPortion->GetCursor() )
        {
            pDoc = pPortion->GetCursor()->GetDoc();
        }
        else if ( !pDoc && pParagraph && pParagraph->GetTxtNode( ) )
        {
            pDoc = const_cast<SwDoc*>(pParagraph->GetTxtNode()->GetDoc());
        }

    }

    if(!pDoc)
		throw uno::RuntimeException();
    SwDocShell *pDocSh = pDoc->GetDocShell();
    if (pDocSh)
    {
        uno::Reference< frame::XModel > xModel;
        xModel = pDocSh->GetModel();
        uno::Reference< drawing::XDrawPageSupplier > xDPS(xModel, uno::UNO_QUERY);
        if (xDPS.is())
        {
            uno::Reference< drawing::XDrawPage > xDP( xDPS->getDrawPage() );
            if (xDP.is())
            {
                uno::Any aPos;
                aPos <<= xTextRange;
                setPropertyValue(S2U("TextRange"), aPos);
                uno::Reference< drawing::XShape > xTemp( (cppu::OWeakObject*) this, uno::UNO_QUERY );
                xDP->add( xTemp );
            }
        }
    }
}

uno::Reference< text::XTextRange >  SwXShape::getAnchor(void) throw( uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
    uno::Reference< text::XTextRange >  aRef;
	SwFrmFmt* pFmt = GetFrmFmt();
	if(pFmt)
	{
        const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
        // return an anchor for non-page bound frames
        // and for page bound frames that have a page no == NULL and a content position
        if ((rAnchor.GetAnchorId() != FLY_AT_PAGE) ||
            (rAnchor.GetCntntAnchor() && !rAnchor.GetPageNum()))
		{
			const SwPosition &rPos = *(pFmt->GetAnchor().GetCntntAnchor());
            aRef = SwXTextRange::CreateXTextRange(*pFmt->GetDoc(), rPos, 0);
		}
	}
	else
		aRef = pImpl->GetTextRange();
	return aRef;
}

void SwXShape::dispose(void) throw( uno::RuntimeException )
{
	vos::OGuard  aGuard(Application::GetSolarMutex());
	SwFrmFmt* pFmt = GetFrmFmt();
	if(pFmt)
	{
        // OD 10.07.2003 #110742# - determine correct <SdrObject>
        //SdrObject* pObj = pFmt->FindSdrObject();
        SdrObject* pObj = GetSvxShape()->GetSdrObject();
        // OD 10.07.2003 #110742# - safety assertion:
        // <pObj> must be the same as <pFmt->FindSdrObject()>, if <pObj> isn't
        // a 'virtual' drawing object.
        // OD 25.08.2003 #111713# - refine assertion for safety reason.
        // --> OD 2005-02-02 #119236# - correct assertion and refine it.
        ASSERT( !pObj ||
                pObj->ISA(SwDrawVirtObj) ||
                pObj->GetUpGroup() ||
                pObj == pFmt->FindSdrObject(),
                "<SwXShape::dispose(..) - different 'master' drawing objects!!" );
        // <--
        // OD 10.07.2003 #110742# - perform delete of draw frame format *not*
        // for 'virtual' drawing objects.
        // --> OD 2005-02-02 #119236# - no delete of draw format for members
        // of a group
        if ( pObj &&
             !pObj->ISA(SwDrawVirtObj) &&
             !pObj->GetUpGroup() &&
             pObj->IsInserted() )
        // <--
        {
            if (pFmt->GetAnchor().GetAnchorId() == FLY_AS_CHAR)
            {
                const SwPosition &rPos = *(pFmt->GetAnchor().GetCntntAnchor());
                SwTxtNode *pTxtNode = rPos.nNode.GetNode().GetTxtNode();
                const xub_StrLen nIdx = rPos.nContent.GetIndex();
                pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
            }
            else
                pFmt->GetDoc()->DelLayoutFmt( pFmt );
        }
    }
    if(xShapeAgg.is())
    {
        uno::Any aAgg(xShapeAgg->queryAggregation( ::getCppuType((uno::Reference<XComponent>*)0)));
        uno::Reference<XComponent> xComp;
        aAgg >>= xComp;
        if(xComp.is())
            xComp->dispose();
    }
}

void SwXShape::addEventListener(
                    const uno::Reference< lang::XEventListener > & aListener)
                    throw( uno::RuntimeException )
{
    uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
	SvxShape* pSvxShape = GetSvxShape();
	if(pSvxShape)
 		pSvxShape->addEventListener(aListener);
}

void SwXShape::removeEventListener(
                    const uno::Reference< lang::XEventListener > & aListener)
                    throw( uno::RuntimeException )
{
	SvxShape* pSvxShape = GetSvxShape();
	if(pSvxShape)
		pSvxShape->removeEventListener(aListener);
}

rtl::OUString SwXShape::getImplementationName(void) throw( uno::RuntimeException )
{
	return C2U("SwXShape");
}

sal_Bool SwXShape::supportsService(const rtl::OUString& rServiceName) throw( uno::RuntimeException )
{
	sal_Bool bRet = sal_False;
	if(COMPARE_EQUAL == rServiceName.compareToAscii("com.sun.star.drawing.Shape"))
		bRet = sal_True;
	else if(xShapeAgg.is())
	{
        uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
		SvxShape* pSvxShape = GetSvxShape();
		bRet = pSvxShape->supportsService(rServiceName);
	}
	return bRet;
}

uno::Sequence< rtl::OUString > SwXShape::getSupportedServiceNames(void) throw( uno::RuntimeException )
{
    uno::Sequence< rtl::OUString > aSeq;
	if(xShapeAgg.is())
	{
        uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
		SvxShape* pSvxShape = GetSvxShape();
		if(pSvxShape)
			aSeq = pSvxShape->getSupportedServiceNames();
	}
	else
	{
		aSeq.realloc(1);
		aSeq.getArray()[0] = C2U("com.sun.star.drawing.Shape");
	}
	return aSeq;
}

SvxShape*	SwXShape::GetSvxShape()
{
	SvxShape* pSvxShape = 0;
	if(xShapeAgg.is())
	{
        uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
		if(xShapeTunnel.is())
			pSvxShape = reinterpret_cast< SvxShape * >(
					sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SvxShape::getUnoTunnelId()) ));
	}
	return pSvxShape;
}

// --> OD 2004-07-22 #i31698# -
// implementation of virtual methods from drawing::XShape
awt::Point SAL_CALL SwXShape::getPosition() throw ( uno::RuntimeException )
{
    awt::Point aPos( _GetAttrPosition() );

    // handle group members
    SvxShape* pSvxShape = GetSvxShape();
    if ( pSvxShape )
    {
        SdrObject* pTopGroupObj = _GetTopGroupObj( pSvxShape );
        if ( pTopGroupObj )
        {
            // --> OD 2004-10-01 #i34750# - get attribute position of top group
            // shape and add offset between top group object and group member
            uno::Reference< drawing::XShape > xGroupShape =
                    uno::Reference< drawing::XShape >( pTopGroupObj->getUnoShape(),
                                                       uno::UNO_QUERY );
            aPos = xGroupShape->getPosition();
            // add offset between top group object and group member
            // to the determined attribute position
            // --> OD 2004-10-01 #i34750# - correction:
            // consider the layout direction
            const Rectangle aMemberObjRect = GetSvxShape()->GetSdrObject()->GetSnapRect();
            const Rectangle aGroupObjRect = pTopGroupObj->GetSnapRect();
            // --> OD 2005-08-16 #i53320# - relative position of group member and
            // top group object is always given in horizontal left-to-right layout.
//            const SwFrmFmt::tLayoutDir eLayoutDir = GetFrmFmt()
//                                                    ? GetFrmFmt()->GetLayoutDir()
//                                                    : SwFrmFmt::HORI_L2R;
            awt::Point aOffset( 0, 0 );
//            switch ( eLayoutDir )
//            {
//                case SwFrmFmt::HORI_L2R:
                {
                    aOffset.X = ( aMemberObjRect.Left() - aGroupObjRect.Left() );
                    aOffset.Y = ( aMemberObjRect.Top() - aGroupObjRect.Top() );
                }
//                break;
//                case SwFrmFmt::HORI_R2L:
//                {
//                    aOffset.X = ( aGroupObjRect.Right() - aMemberObjRect.Right() );
//                    aOffset.Y = ( aMemberObjRect.Top() - aGroupObjRect.Top() );
//                }
//                break;
//                case SwFrmFmt::VERT_R2L:
//                {
//                    aOffset.X = ( aMemberObjRect.Top() - aGroupObjRect.Top() );
//                    aOffset.Y = ( aGroupObjRect.Right() - aMemberObjRect.Right() );
//                }
//                break;
//                default:
//                {
//                    ASSERT( false,
//                            "<SwXShape::getPosition()> - unsupported layout direction" );
//                }
//            }
            // <--
            aOffset.X = TWIP_TO_MM100(aOffset.X);
            aOffset.Y = TWIP_TO_MM100(aOffset.Y);
            aPos.X += aOffset.X;
            aPos.Y += aOffset.Y;
            // <--
        }
    }

    return aPos;
}
void SAL_CALL SwXShape::setPosition( const awt::Point& aPosition )
                                                throw ( uno::RuntimeException )
{
    SdrObject* pTopGroupObj = _GetTopGroupObj();
    if ( !pTopGroupObj )
    {
        // --> OD 2005-02-10 #i37877# - no adjustment of position attributes,
        // if the position also has to be applied at the drawing object and
        // a contact object is already registered at the drawing object.
        bool bApplyPosAtDrawObj(false);
        bool bNoAdjustOfPosProp(false);
        // --> OD 2004-10-19 #i35798# - apply position also to drawing object,
        // if drawing object has no anchor position set.
        if ( mxShape.is() )
        {
            SvxShape* pSvxShape = GetSvxShape();
            if ( pSvxShape )
            {
                const SdrObject* pObj = pSvxShape->GetSdrObject();
                if ( pObj &&
                     pObj->GetAnchorPos().X() == 0 &&
                     pObj->GetAnchorPos().Y() == 0 )
                {
                    bApplyPosAtDrawObj = true;
                    if ( pObj->GetUserCall() &&
                         pObj->GetUserCall()->ISA(SwDrawContact) )
                    {
                        bNoAdjustOfPosProp = true;
                    }
                }
            }
        }
        // <--
        // shape isn't a group member. Thus, set positioning attributes
        if ( !bNoAdjustOfPosProp )
        {
            _AdjustPositionProperties( aPosition );
        }
        if ( bApplyPosAtDrawObj )
        {
            mxShape->setPosition( aPosition );
        }
        // <--
    }
    else if ( mxShape.is() )
    {
        // shape is a member of a group. Thus, set its position.
        awt::Point aNewPos( aPosition );
        // The given position is given in the according layout direction. Thus,
        // it has to be converted to a position in horizontal left-to-right
        // layout.
        // convert given absolute attribute position in layout direction into
        // position in horizontal left-to-right layout.
        {
            aNewPos = _ConvertPositionToHoriL2R( aNewPos, getSize() );
        }
        // Convert given absolute position in horizontal left-to-right
        // layout into relative position in horizontal left-to-right layout.
        uno::Reference< drawing::XShape > xGroupShape =
                uno::Reference< drawing::XShape >( pTopGroupObj->getUnoShape(),
                                                   uno::UNO_QUERY );
        {
            // --> OD 2004-09-29 #i34750# - correction:
            // use method <xGroupShape->getPosition()> to get the correct
            // position of the top group object.
            awt::Point aAttrPosInHoriL2R(
                    _ConvertPositionToHoriL2R( xGroupShape->getPosition(),
                                               xGroupShape->getSize() ) );
            // <--
            aNewPos.X -= aAttrPosInHoriL2R.X;
            aNewPos.Y -= aAttrPosInHoriL2R.Y;
        }
        // convert relative position in horizontal left-to-right layout into
        // absolute position in horizontal left-to-right layout
        {
            // --> OD 2004-10-01 #i34750# - correction:
            // use method <SvxShape->getPosition()> to get the correct
            // 'Drawing layer' position of the top group shape.
            uno::Reference< lang::XUnoTunnel > xGrpShapeTunnel(
                                                    pTopGroupObj->getUnoShape(),
                                                    uno::UNO_QUERY );
            SvxShape* pSvxGroupShape = reinterpret_cast< SvxShape * >(
					sal::static_int_cast< sal_IntPtr >( xGrpShapeTunnel->getSomething(SvxShape::getUnoTunnelId()) ));
            const awt::Point aGroupPos = pSvxGroupShape->getPosition();
            aNewPos.X += aGroupPos.X;
            aNewPos.Y += aGroupPos.Y;
            // <--
        }
        // set position
        mxShape->setPosition( aNewPos );
    }
}
awt::Size SAL_CALL SwXShape::getSize() throw ( uno::RuntimeException )
{
    awt::Size aSize;
    if ( mxShape.is() )
    {
        aSize = mxShape->getSize();
    }
    return aSize;
}
void SAL_CALL SwXShape::setSize( const awt::Size& aSize )
                                        throw ( beans::PropertyVetoException,
                                                uno::RuntimeException )
{
    if ( mxShape.is() )
    {
        mxShape->setSize( aSize );
    }
}
// <--
// --> OD 2004-07-22 #i31698# -
// implementation of virtual methods from drawing::XShapeDescriptor
::rtl::OUString SAL_CALL SwXShape::getShapeType() throw ( uno::RuntimeException )
{
    ::rtl::OUString aType;
    if ( mxShape.is() )
    {
        aType = mxShape->getShapeType();
    }
    return aType;
}
// <--
/** method to determine top group object

    OD 2004-08-03 #i31698#

    @author OD
*/
SdrObject* SwXShape::_GetTopGroupObj( SvxShape* _pSvxShape )
{
    SdrObject* pTopGroupObj( 0L );

    SvxShape* pSvxShape = _pSvxShape ? _pSvxShape : GetSvxShape();
    if ( pSvxShape )
    {
        SdrObject* pSdrObj = pSvxShape->GetSdrObject();
        if ( pSdrObj && pSdrObj->GetUpGroup() )
        {
            pTopGroupObj = pSdrObj->GetUpGroup();
            while ( pTopGroupObj->GetUpGroup() )
            {
                pTopGroupObj = pTopGroupObj->GetUpGroup();
            }
        }
    }

    return pTopGroupObj;
}

/** method to determine position according to the positioning attributes

    OD 2004-08-03 #i31698#

    @author OD
*/
awt::Point SwXShape::_GetAttrPosition()
{
    awt::Point aAttrPos;

    uno::Any aHoriPos( getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HoriOrientPosition")) ) );
    aHoriPos >>= aAttrPos.X;
    uno::Any aVertPos( getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VertOrientPosition")) ) );
    aVertPos >>= aAttrPos.Y;
    // --> OD 2004-10-19 #i35798# - fallback, if attribute position is (0,0)
    // and no anchor position is applied to the drawing object
    SvxShape* pSvxShape = GetSvxShape();
    if ( pSvxShape )
    {
        const SdrObject* pObj = pSvxShape->GetSdrObject();
        if ( pObj &&
             pObj->GetAnchorPos().X() == 0 &&
             pObj->GetAnchorPos().Y() == 0 &&
             aAttrPos.X == 0 && aAttrPos.Y == 0 )
        {
            const Rectangle aObjRect = pObj->GetSnapRect();
            aAttrPos.X = TWIP_TO_MM100(aObjRect.Left());
            aAttrPos.Y = TWIP_TO_MM100(aObjRect.Top());
        }
    }
    // <--
    // --> OD 2004-11-10 #i35007# - If drawing object is anchored as-character,
    // it's x-position isn't sensible. Thus, return the x-position as zero in this case.
    text::TextContentAnchorType eTextAnchorType =
                            text::TextContentAnchorType_AT_PARAGRAPH;
    {
        rtl::OUString sAnchorType( RTL_CONSTASCII_USTRINGPARAM( "AnchorType" ) );
        uno::Any aAny = getPropertyValue( sAnchorType );
        aAny >>= eTextAnchorType;
    }
    if ( eTextAnchorType == text::TextContentAnchorType_AS_CHARACTER )
    {
        aAttrPos.X = 0;
    }
    // <--

    return aAttrPos;
}

/** method to convert the position (translation) of the drawing object to
    the layout direction horizontal left-to-right.

    OD 2004-07-27 #i31698#

    @author OD
*/
awt::Point SwXShape::_ConvertPositionToHoriL2R( const awt::Point _aObjPos,
                                                const awt::Size _aObjSize )
{
    awt::Point aObjPosInHoriL2R( _aObjPos );

    SwFrmFmt* pFrmFmt = GetFrmFmt();
    if ( pFrmFmt )
    {
        SwFrmFmt::tLayoutDir eLayoutDir = pFrmFmt->GetLayoutDir();
        switch ( eLayoutDir )
        {
            case SwFrmFmt::HORI_L2R:
            {
                // nothing to do
            }
            break;
            case SwFrmFmt::HORI_R2L:
            {
                aObjPosInHoriL2R.X = -_aObjPos.X - _aObjSize.Width;
            }
            break;
            case SwFrmFmt::VERT_R2L:
            {
                aObjPosInHoriL2R.X = -_aObjPos.Y - _aObjSize.Width;
                aObjPosInHoriL2R.Y = _aObjPos.X;
            }
            break;
            default:
            {
                ASSERT( false,
                        "<SwXShape::_ConvertPositionToHoriL2R(..)> - unsupported layout direction" );
            }
        }
    }

    return aObjPosInHoriL2R;
}
/** method to convert the transformation of the drawing object to the layout
    direction, the drawing object is in

    OD 2004-07-27 #i31698#

    @author OD
*/
drawing::HomogenMatrix3 SwXShape::_ConvertTransformationToLayoutDir(
                                    drawing::HomogenMatrix3 _aMatrixInHoriL2R )
{
    drawing::HomogenMatrix3 aMatrix( _aMatrixInHoriL2R );

    // --> OD 2005-03-10 #i44334#, #i44681# - direct manipulation of the
    // tranformation structure isn't valid, if it contains rotation.
    SvxShape* pSvxShape = GetSvxShape();
    ASSERT( pSvxShape,
            "<SwXShape::_ConvertTransformationToLayoutDir(..)> - no SvxShape found!")
    if ( pSvxShape )
    {
        const SdrObject* pObj = pSvxShape->GetSdrObject();
        ASSERT( pObj,
                "<SwXShape::_ConvertTransformationToLayoutDir(..)> - no SdrObject found!")
        if ( pObj )
        {
            // get position of object in Writer coordinate system.
            awt::Point aPos( getPosition() );
            // get position of object in Drawing layer coordinate system
            const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
            const awt::Point aObjPos(
                    TWIP_TO_MM100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
                    TWIP_TO_MM100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
            // determine difference between these positions according to the
            // Writer coordinate system
            const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
                                             aPos.Y - aObjPos.Y );
            // apply translation difference to transformation matrix.
            if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
            {
                // --> OD 2007-01-03 #i73079# - use correct matrix type
                ::basegfx::B2DHomMatrix aTempMatrix;
                // <--

				aTempMatrix.set(0, 0, aMatrix.Line1.Column1 );
                aTempMatrix.set(0, 1, aMatrix.Line1.Column2 );
                aTempMatrix.set(0, 2, aMatrix.Line1.Column3 );
                aTempMatrix.set(1, 0, aMatrix.Line2.Column1 );
                aTempMatrix.set(1, 1, aMatrix.Line2.Column2 );
                aTempMatrix.set(1, 2, aMatrix.Line2.Column3 );
                aTempMatrix.set(2, 0, aMatrix.Line3.Column1 );
                aTempMatrix.set(2, 1, aMatrix.Line3.Column2 );
                aTempMatrix.set(2, 2, aMatrix.Line3.Column3 );

                // --> OD 2007-01-03 #i73079#
                aTempMatrix.translate( aTranslateDiff.X, aTranslateDiff.Y );
                // <--

                aMatrix.Line1.Column1 = aTempMatrix.get(0, 0);
                aMatrix.Line1.Column2 = aTempMatrix.get(0, 1);
                aMatrix.Line1.Column3 = aTempMatrix.get(0, 2);
                aMatrix.Line2.Column1 = aTempMatrix.get(1, 0);
                aMatrix.Line2.Column2 = aTempMatrix.get(1, 1);
                aMatrix.Line2.Column3 = aTempMatrix.get(1, 2);
                aMatrix.Line3.Column1 = aTempMatrix.get(2, 0);
                aMatrix.Line3.Column2 = aTempMatrix.get(2, 1);
                aMatrix.Line3.Column3 = aTempMatrix.get(2, 2);
            }
        }
    }
    // <--

    return aMatrix;
}

/** method to adjust the positioning properties

    OD 2004-08-02 #i31698#

    @author OD
*/
void SwXShape::_AdjustPositionProperties( const awt::Point _aPosition )
{
    // handle x-position
    // --> OD 2004-11-10 #i35007# - no handling of x-position, if drawing
    // object is anchored as-character, because it doesn't make sense.
    text::TextContentAnchorType eTextAnchorType =
                            text::TextContentAnchorType_AT_PARAGRAPH;
    {
        rtl::OUString sAnchorType( RTL_CONSTASCII_USTRINGPARAM( "AnchorType" ) );
        uno::Any aAny = getPropertyValue( sAnchorType );
        aAny >>= eTextAnchorType;
    }
    if ( eTextAnchorType != text::TextContentAnchorType_AS_CHARACTER )
    // <--
    {
        // determine current x-postion
        rtl::OUString aHoriPosPropStr( RTL_CONSTASCII_USTRINGPARAM("HoriOrientPosition") );
        uno::Any aHoriPos( getPropertyValue( aHoriPosPropStr ) );
        sal_Int32 dCurrX = 0;
        aHoriPos >>= dCurrX;
        // change x-position attribute, if needed
        if ( dCurrX != _aPosition.X )
        {
            // adjust x-position orientation to text::HoriOrientation::NONE, if needed
            // Note: has to be done before setting x-position attribute
            rtl::OUString aHoriOrientPropStr( RTL_CONSTASCII_USTRINGPARAM("HoriOrient") );
            uno::Any aHoriOrient( getPropertyValue( aHoriOrientPropStr ) );
            sal_Int16 eHoriOrient;
            if (aHoriOrient >>= eHoriOrient) // may be void
            {
                if ( eHoriOrient != text::HoriOrientation::NONE )
                {
                    eHoriOrient = text::HoriOrientation::NONE;
                    aHoriOrient <<= eHoriOrient;
                    setPropertyValue( aHoriOrientPropStr, aHoriOrient );
                }
            }
            // set x-position attribute
            aHoriPos <<= _aPosition.X;
            setPropertyValue( aHoriPosPropStr, aHoriPos );
        }
    }

    // handle y-position
    {
        // determine current y-postion
        rtl::OUString aVertPosPropStr( RTL_CONSTASCII_USTRINGPARAM("VertOrientPosition") );
        uno::Any aVertPos( getPropertyValue( aVertPosPropStr ) );
        sal_Int32 dCurrY = 0;
        aVertPos >>= dCurrY;
        // change y-position attribute, if needed
        if ( dCurrY != _aPosition.Y )
        {
            // adjust y-position orientation to text::VertOrientation::NONE, if needed
            // Note: has to be done before setting y-position attribute
            rtl::OUString aVertOrientPropStr( RTL_CONSTASCII_USTRINGPARAM("VertOrient") );
            uno::Any aVertOrient( getPropertyValue( aVertOrientPropStr ) );
            sal_Int16 eVertOrient;
            if (aVertOrient >>= eVertOrient) // may be void
            {
                if ( eVertOrient != text::VertOrientation::NONE )
                {
                    eVertOrient = text::VertOrientation::NONE;
                    aVertOrient <<= eVertOrient;
                    setPropertyValue( aVertOrientPropStr, aVertOrient );
                }
            }
            // set y-position attribute
            aVertPos <<= _aPosition.Y;
            setPropertyValue( aVertPosPropStr, aVertPos );
        }
    }
}

/** method to convert start or end position of the drawing object to the
    Writer specific position, which is the attribute position in layout direction

    OD 2009-01-12 #i59051#

    @author OD
*/
::com::sun::star::awt::Point SwXShape::_ConvertStartOrEndPosToLayoutDir(
                            const ::com::sun::star::awt::Point& aStartOrEndPos )
{
    awt::Point aConvertedPos( aStartOrEndPos );

    SvxShape* pSvxShape = GetSvxShape();
    ASSERT( pSvxShape,
            "<SwXShape::_ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!")
    if ( pSvxShape )
    {
        const SdrObject* pObj = pSvxShape->GetSdrObject();
        ASSERT( pObj,
                "<SwXShape::_ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!")
        if ( pObj )
        {
            // get position of object in Writer coordinate system.
            awt::Point aPos( getPosition() );
            // get position of object in Drawing layer coordinate system
            const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
            const awt::Point aObjPos(
                    TWIP_TO_MM100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
                    TWIP_TO_MM100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
            // determine difference between these positions according to the
            // Writer coordinate system
            const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
                                             aPos.Y - aObjPos.Y );
            // apply translation difference to transformation matrix.
            if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
            {
                aConvertedPos.X = aConvertedPos.X + aTranslateDiff.X;
                aConvertedPos.Y = aConvertedPos.Y + aTranslateDiff.Y;
            }
        }
    }

    return aConvertedPos;
}

::com::sun::star::drawing::PolyPolygonBezierCoords SwXShape::_ConvertPolyPolygonBezierToLayoutDir(
                    const ::com::sun::star::drawing::PolyPolygonBezierCoords& aPath )
{
    drawing::PolyPolygonBezierCoords aConvertedPath( aPath );

    SvxShape* pSvxShape = GetSvxShape();
    ASSERT( pSvxShape,
            "<SwXShape::_ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!")
    if ( pSvxShape )
    {
        const SdrObject* pObj = pSvxShape->GetSdrObject();
        ASSERT( pObj,
                "<SwXShape::_ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!")
        if ( pObj )
        {
            // get position of object in Writer coordinate system.
            awt::Point aPos( getPosition() );
            // get position of object in Drawing layer coordinate system
            const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
            const awt::Point aObjPos(
                    TWIP_TO_MM100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
                    TWIP_TO_MM100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
            // determine difference between these positions according to the
            // Writer coordinate system
            const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
                                             aPos.Y - aObjPos.Y );
            // apply translation difference to PolyPolygonBezier.
            if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
            {
                const basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
                    aTranslateDiff.X, aTranslateDiff.Y));

                const sal_Int32 nOuterSequenceCount(aConvertedPath.Coordinates.getLength());
                drawing::PointSequence* pInnerSequence = aConvertedPath.Coordinates.getArray();
                for(sal_Int32 a(0); a < nOuterSequenceCount; a++)
                {
                    const sal_Int32 nInnerSequenceCount(pInnerSequence->getLength());
                    awt::Point* pArray = pInnerSequence->getArray();

                    for(sal_Int32 b(0); b < nInnerSequenceCount; b++)
                    {
                        basegfx::B2DPoint aNewCoordinatePair(pArray->X, pArray->Y);
                        aNewCoordinatePair *= aMatrix;
                        pArray->X = basegfx::fround(aNewCoordinatePair.getX());
                        pArray->Y = basegfx::fround(aNewCoordinatePair.getY());
                        pArray++;
                    }
                }
            }
        }
    }

    return aConvertedPath;
}


SwXGroupShape::SwXGroupShape(uno::Reference< XInterface > & xShape) :
        SwXShape(xShape)
{
#ifdef DBG_UTIL
    uno::Reference<XShapes> xShapes(xShapeAgg, uno::UNO_QUERY);
    DBG_ASSERT(xShapes.is(), "no SvxShape found or shape is not a group shape");
#endif
}


SwXGroupShape::~SwXGroupShape()
{
}

uno::Any SwXGroupShape::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException)
{
    uno::Any aRet;
    if(rType == ::getCppuType((uno::Reference<XShapes>*)0))
        aRet <<= uno::Reference<XShapes>(this);
    else
        aRet = SwXShape::queryInterface(rType);
    return aRet;
}

void SwXGroupShape::acquire(  ) throw()
{
    SwXShape::acquire();
}

void SwXGroupShape::release(  ) throw()
{
    SwXShape::release();
}

void SwXGroupShape::add( const uno::Reference< XShape >& xShape ) throw (uno::RuntimeException)
{
    vos::OGuard  aGuard(Application::GetSolarMutex());
    SvxShape* pSvxShape = GetSvxShape();
    SwFrmFmt* pFmt = GetFrmFmt();
    if(pSvxShape && pFmt)
    {
        uno::Reference<XShapes> xShapes;
        if( xShapeAgg.is() )
        {
            const uno::Type& rType = ::getCppuType((uno::Reference<XShapes>*)0 );
            uno::Any aAgg = xShapeAgg->queryAggregation( rType );
            aAgg >>= xShapes;
        }
        if(xShapes.is())
            xShapes->add(xShape);
        else
            throw uno::RuntimeException();

        uno::Reference<lang::XUnoTunnel> xTunnel(xShape, uno::UNO_QUERY);
        SwXShape* pSwShape = 0;
        if(xShape.is())
            pSwShape = reinterpret_cast< SwXShape * >(
					sal::static_int_cast< sal_IntPtr >( xTunnel->getSomething(SwXShape::getUnoTunnelId()) ));
        if(pSwShape && pSwShape->m_bDescriptor)
        {
            SvxShape* pAddShape = reinterpret_cast< SvxShape * >(
					sal::static_int_cast< sal_IntPtr >( xTunnel->getSomething(SvxShape::getUnoTunnelId()) ));
            if(pAddShape)
            {
                SdrObject* pObj = pAddShape->GetSdrObject();
                if(pObj)
                {
                    SwDoc* pDoc = pFmt->GetDoc();
                    // OD 25.06.2003 #108784# - set layer of new drawing
                    // object to corresponding invisible layer.
                    if( FmFormInventor != pObj->GetObjInventor())
                    {
                        pObj->SetLayer( pSwShape->pImpl->GetOpaque()
                                        ? pDoc->GetInvisibleHeavenId()
                                        : pDoc->GetInvisibleHellId() );
                    }
                    else
                    {
                        pObj->SetLayer(pDoc->GetInvisibleControlsId());
                    }
                }
            }
            pSwShape->m_bDescriptor = sal_False;
            //add the group member to the format of the group
            SwFrmFmt* pShapeFmt = ::FindFrmFmt( pSvxShape->GetSdrObject() );
            if(pShapeFmt)
                pFmt->Add(pSwShape);
        }
    }
    else
        throw uno::RuntimeException();
}

void SwXGroupShape::remove( const uno::Reference< XShape >& xShape ) throw (uno::RuntimeException)
{
    vos::OGuard  aGuard(Application::GetSolarMutex());
    uno::Reference<XShapes> xShapes;
    if( xShapeAgg.is() )
	{
        const uno::Type& rType = ::getCppuType((uno::Reference<XShapes>*)0 );
        uno::Any aAgg = xShapeAgg->queryAggregation( rType );
        aAgg >>= xShapes;
    }
    if(!xShapes.is())
        throw uno::RuntimeException();
    xShapes->remove(xShape);
}

sal_Int32 SwXGroupShape::getCount(void) throw( uno::RuntimeException )
{
    vos::OGuard  aGuard(Application::GetSolarMutex());
    uno::Reference<XIndexAccess> xAcc;
    if( xShapeAgg.is() )
	{
        const uno::Type& rType = ::getCppuType((uno::Reference<XIndexAccess>*)0 );
        uno::Any aAgg = xShapeAgg->queryAggregation( rType );
        aAgg >>= xAcc;
    }
    if(!xAcc.is())
        throw uno::RuntimeException();
    return xAcc->getCount();
}

uno::Any SwXGroupShape::getByIndex(sal_Int32 nIndex)
        throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException,
               uno::RuntimeException )
{
    vos::OGuard  aGuard(Application::GetSolarMutex());
    uno::Reference<XIndexAccess> xAcc;
    if( xShapeAgg.is() )
	{
        const uno::Type& rType = ::getCppuType((uno::Reference<XIndexAccess>*)0 );
        uno::Any aAgg = xShapeAgg->queryAggregation( rType );
        aAgg >>= xAcc;
    }
    if(!xAcc.is())
        throw uno::RuntimeException();
    return xAcc->getByIndex(nIndex);
}

uno::Type SwXGroupShape::getElementType(  ) throw(uno::RuntimeException)
{
    vos::OGuard  aGuard(Application::GetSolarMutex());
    uno::Reference<XIndexAccess> xAcc;
    if( xShapeAgg.is() )
	{
        const uno::Type& rType = ::getCppuType((uno::Reference<XIndexAccess>*)0 );
        uno::Any aAgg = xShapeAgg->queryAggregation( rType );
        aAgg >>= xAcc;
    }
    if(!xAcc.is())
        throw uno::RuntimeException();
    return xAcc->getElementType();
}

sal_Bool SwXGroupShape::hasElements(  ) throw(uno::RuntimeException)
{
    vos::OGuard  aGuard(Application::GetSolarMutex());
    uno::Reference<XIndexAccess> xAcc;
    if( xShapeAgg.is() )
	{
        const uno::Type& rType = ::getCppuType((uno::Reference<XIndexAccess>*)0 );
        uno::Any aAgg = xShapeAgg->queryAggregation( rType );
        aAgg >>= xAcc;
    }
    if(!xAcc.is())
        throw uno::RuntimeException();
    return xAcc->hasElements();
}


