/**************************************************************
 *
 * 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_sc.hxx"

#include <tools/debug.hxx>
#include <comphelper/uno3.hxx>
#include <comphelper/stl_types.hxx>
#include <svtools/unoevent.hxx>
#include <svtools/unoimap.hxx>
#include <svx/svdobj.hxx>
#include <svx/unoshape.hxx>
#include <editeng/unofield.hxx>
#include <svx/shapepropertynotifier.hxx>
#include <toolkit/helper/convert.hxx>
#include <cppuhelper/implbase2.hxx>

#include <com/sun/star/drawing/XShape.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>

#include "shapeuno.hxx"
#include "miscuno.hxx"
#include "cellsuno.hxx"
#include "textuno.hxx"
#include "fielduno.hxx"
#include "docsh.hxx"
#include "drwlayer.hxx"
#include "userdat.hxx"
#include "unonames.hxx"
#include "unoguard.hxx"

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

//------------------------------------------------------------------------

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

static ScShapeImplementationIdMap aImplementationIdMap;

const SfxItemPropertyMapEntry* lcl_GetShapeMap()
{
    static SfxItemPropertyMapEntry aShapeMap_Impl[] =
	{
        {MAP_CHAR_LEN(SC_UNONAME_ANCHOR), 0, &getCppuType((uno::Reference<uno::XInterface>*)0), 0, 0 },
        {MAP_CHAR_LEN(SC_UNONAME_HORIPOS), 0, &getCppuType((sal_Int32*)0), 0, 0 },
		{MAP_CHAR_LEN(SC_UNONAME_IMAGEMAP),	0, &getCppuType((uno::Reference<container::XIndexContainer>*)0), 0, 0 },
		{MAP_CHAR_LEN(SC_UNONAME_VERTPOS), 0, &getCppuType((sal_Int32*)0), 0, 0 },
        {0,0,0,0,0,0}
	};
	return aShapeMap_Impl;
}

// static
const SvEventDescription* ScShapeObj::GetSupportedMacroItems()
{
	static const SvEventDescription aMacroDescriptionsImpl[] =
	{
		{ 0, NULL }
	};
	return aMacroDescriptionsImpl;
}

//------------------------------------------------------------------------

namespace
{
    void lcl_initializeNotifier( SdrObject& _rSdrObj, ::cppu::OWeakObject& _rShape )
    {
        ::svx::PPropertyValueProvider pProvider( new ::svx::PropertyValueProvider( _rShape, "Anchor" ) );
        _rSdrObj.getShapePropertyChangeNotifier().registerProvider( ::svx::eSpreadsheetAnchor, pProvider );
    }
}

//------------------------------------------------------------------------

ScShapeObj::ScShapeObj( uno::Reference<drawing::XShape>& xShape ) :
      pShapePropertySet(NULL),
      pShapePropertyState(NULL),
      pImplementationId(NULL),
      bIsTextShape(false),
      bIsNoteCaption(false),
      bInitializedNotifier(false)
{
	comphelper::increment( m_refCount );

	{
		mxShapeAgg = uno::Reference<uno::XAggregation>( xShape, uno::UNO_QUERY );
		// extra block to force deletion of the temporary before setDelegator
	}

	if (mxShapeAgg.is())
	{
		xShape = NULL;		// during setDelegator, mxShapeAgg must be the only ref

		mxShapeAgg->setDelegator( (cppu::OWeakObject*)this );

		xShape.set(uno::Reference<drawing::XShape>( mxShapeAgg, uno::UNO_QUERY ));

		bIsTextShape = ( SvxUnoTextBase::getImplementation( mxShapeAgg ) != NULL );
	}

    {
        SdrObject* pObj = GetSdrObject();
        if ( pObj )
        {
            bIsNoteCaption = ScDrawLayer::IsNoteCaption( pObj );
            lcl_initializeNotifier( *pObj, *this );
            bInitializedNotifier = true;
        }
    }

	comphelper::decrement( m_refCount );
}

ScShapeObj::~ScShapeObj()
{
//	if (mxShapeAgg.is())
//		mxShapeAgg->setDelegator(uno::Reference<uno::XInterface>());
}

// XInterface

uno::Any SAL_CALL ScShapeObj::queryInterface( const uno::Type& rType )
												throw(uno::RuntimeException)
{
    uno::Any aRet = ScShapeObj_Base::queryInterface( rType );

    if ( !aRet.hasValue() && bIsTextShape )
        aRet = ScShapeObj_TextBase::queryInterface( rType );

    if ( !aRet.hasValue() && bIsNoteCaption )
        aRet = ScShapeObj_ChildBase::queryInterface( rType );

	if ( !aRet.hasValue() && mxShapeAgg.is() )
		aRet = mxShapeAgg->queryAggregation( rType );

	return aRet;
}

void SAL_CALL ScShapeObj::acquire() throw()
{
        OWeakObject::acquire();
}

void SAL_CALL ScShapeObj::release() throw()
{
        OWeakObject::release();
}

void ScShapeObj::GetShapePropertySet()
{
    // #i61908# Store the result of queryAggregation in a member.
    // The reference in mxShapeAgg is kept for this object's lifetime, so the pointer is always valid.

    if (!pShapePropertySet)
    {
        uno::Reference<beans::XPropertySet> xProp;
        if ( mxShapeAgg.is() )
            mxShapeAgg->queryAggregation( getCppuType((uno::Reference<beans::XPropertySet>*) 0) ) >>= xProp;
        pShapePropertySet = xProp.get();
    }
}

void ScShapeObj::GetShapePropertyState()
{
    // #i61908# Store the result of queryAggregation in a member.
    // The reference in mxShapeAgg is kept for this object's lifetime, so the pointer is always valid.

    if (!pShapePropertyState)
    {
        uno::Reference<beans::XPropertyState> xState;
        if ( mxShapeAgg.is() )
            mxShapeAgg->queryAggregation( getCppuType((uno::Reference<beans::XPropertyState>*) 0) ) >>= xState;
        pShapePropertyState = xState.get();
    }
}

uno::Reference<lang::XComponent> lcl_GetComponent( const uno::Reference<uno::XAggregation>& xAgg )
{
	uno::Reference<lang::XComponent> xRet;
	if ( xAgg.is() )
		xAgg->queryAggregation( getCppuType((uno::Reference<lang::XComponent>*) 0) ) >>= xRet;
	return xRet;
}

uno::Reference<text::XText> lcl_GetText( const uno::Reference<uno::XAggregation>& xAgg )
{
	uno::Reference<text::XText> xRet;
	if ( xAgg.is() )
		xAgg->queryAggregation( getCppuType((uno::Reference<text::XText>*) 0) ) >>= xRet;
	return xRet;
}

uno::Reference<text::XSimpleText> lcl_GetSimpleText( const uno::Reference<uno::XAggregation>& xAgg )
{
	uno::Reference<text::XSimpleText> xRet;
	if ( xAgg.is() )
		xAgg->queryAggregation( getCppuType((uno::Reference<text::XSimpleText>*) 0) ) >>= xRet;
	return xRet;
}

uno::Reference<text::XTextRange> lcl_GetTextRange( const uno::Reference<uno::XAggregation>& xAgg )
{
	uno::Reference<text::XTextRange> xRet;
	if ( xAgg.is() )
		xAgg->queryAggregation( getCppuType((uno::Reference<text::XTextRange>*) 0) ) >>= xRet;
	return xRet;
}

//	XPropertySet

uno::Reference<beans::XPropertySetInfo> SAL_CALL ScShapeObj::getPropertySetInfo()
														throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

    // #i61527# cache property set info for this object
    if ( !mxPropSetInfo.is() )
    {
        //	mix own and aggregated properties:
        GetShapePropertySet();
        if (pShapePropertySet)
        {
            uno::Reference<beans::XPropertySetInfo> xAggInfo(pShapePropertySet->getPropertySetInfo());
            const uno::Sequence<beans::Property> aPropSeq(xAggInfo->getProperties());
            mxPropSetInfo.set(new SfxExtItemPropertySetInfo( lcl_GetShapeMap(), aPropSeq ));
        }
    }
	return mxPropSetInfo;
}

sal_Bool lcl_GetPageNum( SdrPage* pPage, SdrModel& rModel, SCTAB& rNum )
{
	sal_uInt16 nCount = rModel.GetPageCount();
	for (sal_uInt16 i=0; i<nCount; i++)
		if ( rModel.GetPage(i) == pPage )
		{
			rNum = static_cast<SCTAB>(i);
			return sal_True;
		}

	return sal_False;
}

sal_Bool lcl_GetCaptionPoint( uno::Reference< drawing::XShape >& xShape, awt::Point& rCaptionPoint )
{
    sal_Bool bReturn = sal_False;
    rtl::OUString sType(xShape->getShapeType());
    sal_Bool bCaptionShape(sType.equalsAscii("com.sun.star.drawing.CaptionShape"));
    if (bCaptionShape)
    {
        uno::Reference < beans::XPropertySet > xShapeProp (xShape, uno::UNO_QUERY);
        if (xShapeProp.is())
        {
            xShapeProp->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" )) ) >>= rCaptionPoint;
            bReturn = sal_True;
        }
    }
    return bReturn;
}

ScRange lcl_GetAnchorCell( uno::Reference< drawing::XShape >& xShape, ScDocument* pDoc, SCTAB nTab,
                          awt::Point& rUnoPoint, awt::Size& rUnoSize, awt::Point& rCaptionPoint )
{
    ScRange aReturn;
    rUnoPoint = xShape->getPosition();
    rtl::OUString sType(xShape->getShapeType());
    sal_Bool bCaptionShape(lcl_GetCaptionPoint(xShape, rCaptionPoint));
    if (pDoc->IsNegativePage(nTab))
    {
        rUnoSize = xShape->getSize();
        rUnoPoint.X += rUnoSize.Width; // the right top point is base
        if (bCaptionShape)
        {
            if (rCaptionPoint.X > 0 && rCaptionPoint.X > rUnoSize.Width)
                rUnoPoint.X += rCaptionPoint.X - rUnoSize.Width;
            if (rCaptionPoint.Y < 0)
                rUnoPoint.Y += rCaptionPoint.Y;
        }
        aReturn = pDoc->GetRange( nTab, Rectangle( VCLPoint(rUnoPoint), VCLPoint(rUnoPoint) ));
    }
    else
    {
        if (bCaptionShape)
        {
            if (rCaptionPoint.X < 0)
                rUnoPoint.X += rCaptionPoint.X;
            if (rCaptionPoint.Y < 0)
                rUnoPoint.Y += rCaptionPoint.Y;
        }
        aReturn = pDoc->GetRange( nTab, Rectangle( VCLPoint(rUnoPoint), VCLPoint(rUnoPoint) ));
    }

    return aReturn;
}

awt::Point lcl_GetRelativePos( uno::Reference< drawing::XShape >& xShape, ScDocument* pDoc, SCTAB nTab, ScRange& rRange,
                              awt::Size& rUnoSize, awt::Point& rCaptionPoint)
{
    awt::Point aUnoPoint;
    rRange = lcl_GetAnchorCell(xShape, pDoc, nTab, aUnoPoint, rUnoSize, rCaptionPoint);
    if (pDoc->IsNegativePage(nTab))
    {
        Rectangle aRect(pDoc->GetMMRect( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab() ));
        Point aPoint(aRect.TopRight());
        aUnoPoint.X -= aPoint.X();
        aUnoPoint.Y -= aPoint.Y();
    }
    else
    {
        ScRange aRange = pDoc->GetRange( nTab, Rectangle( VCLPoint(aUnoPoint), VCLPoint(aUnoPoint) ));
        Rectangle aRect(pDoc->GetMMRect( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab() ));
        Point aPoint(aRect.TopLeft());
        aUnoPoint.X -= aPoint.X();
        aUnoPoint.Y -= aPoint.Y();
    }

    return aUnoPoint;
}

void SAL_CALL ScShapeObj::setPropertyValue(
						const rtl::OUString& aPropertyName, const uno::Any& aValue )
				throw(beans::UnknownPropertyException, beans::PropertyVetoException,
						lang::IllegalArgumentException, lang::WrappedTargetException,
						uno::RuntimeException)
{
	ScUnoGuard aGuard;
	String aNameString(aPropertyName);

	if ( aNameString.EqualsAscii( SC_UNONAME_ANCHOR ) )
    {
        uno::Reference<sheet::XCellRangeAddressable> xRangeAdd(aValue, uno::UNO_QUERY);
        if (xRangeAdd.is())
        {
            SdrObject *pObj = GetSdrObject();
		    if (pObj)
		    {
		        ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
		        SdrPage* pPage = pObj->GetPage();
		        if ( pModel && pPage )
		        {
			        ScDocument* pDoc = pModel->GetDocument();
			        if ( pDoc )
			        {
				        SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
				        if ( pObjSh && pObjSh->ISA(ScDocShell) )
				        {
					        ScDocShell* pDocSh = (ScDocShell*)pObjSh;

					        SCTAB nTab = 0;
					        if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
					        {
                                table::CellRangeAddress aAddress = xRangeAdd->getRangeAddress();
                                if (nTab == aAddress.Sheet)
                                {
                                    if (aAddress.StartRow != aAddress.EndRow) //should be a Spreadsheet
                                    {
                                        DBG_ASSERT(aAddress.StartRow == 0 && aAddress.EndRow == MAXROW &&
                                            aAddress.StartColumn == 0 && aAddress.EndColumn == MAXCOL, "here should be a XSpreadsheet");
			                            ScDrawLayer::SetAnchor(pObj, SCA_PAGE);
                                    }
                                    else
                                    {
                                        DBG_ASSERT(aAddress.StartRow == aAddress.EndRow &&
                                            aAddress.StartColumn == aAddress.EndColumn, "here should be a XCell");
			                            ScDrawLayer::SetAnchor(pObj, SCA_CELL);
                                    }
                                    Rectangle aRect(pDoc->GetMMRect( static_cast<SCCOL>(aAddress.StartColumn), static_cast<SCROW>(aAddress.StartRow),
                                        static_cast<SCCOL>(aAddress.EndColumn), static_cast<SCROW>(aAddress.EndRow), aAddress.Sheet ));
                                    uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
                                    if (xShape.is())
                                    {
                                        Point aPoint;
                                        Point aEndPoint;
                                        if (pDoc->IsNegativePage(nTab))
                                        {
                                            aPoint = aRect.TopRight();
                                            aEndPoint = aRect.BottomLeft();
                                        }
                                        else
                                        {
                                            aPoint = aRect.TopLeft();
                                            aEndPoint = aRect.BottomRight();
                                        }
                                        awt::Size aUnoSize;
                                        awt::Point aCaptionPoint;
                                        ScRange aRange;
                                        awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));

                                        aUnoPoint.X += aPoint.X();
                                        aUnoPoint.Y += aPoint.Y();

                                        if ( aUnoPoint.Y > aEndPoint.Y() )
                                            aUnoPoint.Y = aEndPoint.Y() - 2;
                                        if (pDoc->IsNegativePage(nTab))
                                        {
                                            if ( aUnoPoint.X < aEndPoint.X() )
                                                aUnoPoint.X = aEndPoint.X() + 2;
                                            aUnoPoint.X -= aUnoSize.Width;
                                            // remove difference to caption point
                                            if (aCaptionPoint.X > 0 && aCaptionPoint.X > aUnoSize.Width)
                                                aUnoPoint.X -= aCaptionPoint.X - aUnoSize.Width;
                                        }
                                        else
                                        {
                                            if ( aUnoPoint.X > aEndPoint.X() )
                                                aUnoPoint.X = aEndPoint.X() - 2;
                                            if (aCaptionPoint.X < 0)
                                                aUnoPoint.X -= aCaptionPoint.X;
                                        }
                                        if (aCaptionPoint.Y < 0)
                                            aUnoPoint.Y -= aCaptionPoint.Y;

                                        xShape->setPosition(aUnoPoint);
                                        pDocSh->SetModified();
                                    }
                                }
					        }
				        }
                    }
                }
            }
        }
        else
            throw lang::IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("only XCell or XSpreadsheet objects allowed")), static_cast<cppu::OWeakObject*>(this), 0);
    }
    else if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
	{
		SdrObject* pObj = GetSdrObject();
		if ( pObj )
		{
			ImageMap aImageMap;
            uno::Reference< uno::XInterface > xImageMapInt(aValue, uno::UNO_QUERY);

			if( !xImageMapInt.is() || !SvUnoImageMap_fillImageMap( xImageMapInt, aImageMap ) )
				throw lang::IllegalArgumentException();

			ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo(pObj);
			if( pIMapInfo )
			{
				// replace existing image map
				pIMapInfo->SetImageMap( aImageMap );
			}
			else
			{
				// insert new user data with image map
				pObj->InsertUserData(new ScIMapInfo(aImageMap) );
			}
		}
	}
    else if ( aNameString.EqualsAscii( SC_UNONAME_HORIPOS ) )
    {
        sal_Int32 nPos = 0;
        if (aValue >>= nPos)
        {
            SdrObject *pObj = GetSdrObject();
		    if (pObj)
		    {
		        ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
		        SdrPage* pPage = pObj->GetPage();
		        if ( pModel && pPage )
		        {
					SCTAB nTab = 0;
					if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
					{
			            ScDocument* pDoc = pModel->GetDocument();
			            if ( pDoc )
			            {
				            SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
				            if ( pObjSh && pObjSh->ISA(ScDocShell) )
				            {
					            ScDocShell* pDocSh = (ScDocShell*)pObjSh;
                                uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
                                if (xShape.is())
                                {
                                    if (ScDrawLayer::GetAnchor(pObj) == SCA_PAGE)
                                    {
                                        awt::Point aPoint(xShape->getPosition());
                                        awt::Size aSize(xShape->getSize());
                                        awt::Point aCaptionPoint;
                                        if (pDoc->IsNegativePage(nTab))
                                        {
                                            nPos *= -1;
                                            nPos -= aSize.Width;
                                        }
                                        if (lcl_GetCaptionPoint(xShape, aCaptionPoint))
                                        {
                                            if (pDoc->IsNegativePage(nTab))
                                            {
                                                if (aCaptionPoint.X > 0 && aCaptionPoint.X > aSize.Width)
                                                    nPos -= aCaptionPoint.X - aSize.Width;
                                            }
                                            else
                                            {
                                                if (aCaptionPoint.X < 0)
                                                    nPos -= aCaptionPoint.X;
                                            }
                                        }
                                        aPoint.X = nPos;
                                        xShape->setPosition(aPoint);
                                        pDocSh->SetModified();
                                    }
                                    else if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
                                    {
                                        awt::Size aUnoSize;
                                        awt::Point aCaptionPoint;
                                        ScRange aRange;
                                        awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));
                                        Rectangle aRect(pDoc->GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ));
                                        if (pDoc->IsNegativePage(nTab))
                                        {
                                            aUnoPoint.X = -nPos;
                                            Point aPoint(aRect.TopRight());
                                            Point aEndPoint(aRect.BottomLeft());
                                            aUnoPoint.X += aPoint.X();
                                            if (aUnoPoint.X < aEndPoint.X())
                                                aUnoPoint.X = aEndPoint.X() + 2;
                                            aUnoPoint.X -= aUnoSize.Width;
                                            if (aCaptionPoint.X > 0 && aCaptionPoint.X > aUnoSize.Width)
                                                aUnoPoint.X -= aCaptionPoint.X - aUnoSize.Width;
                                        }
                                        else
                                        {
                                            aUnoPoint.X = nPos;
                                            Point aPoint(aRect.TopLeft());
                                            Point aEndPoint(aRect.BottomRight());
                                            aUnoPoint.X += aPoint.X();
                                            if (aUnoPoint.X > aEndPoint.X())
                                                aUnoPoint.X = aEndPoint.X() - 2;
                                            if (aCaptionPoint.X < 0)
                                                aUnoPoint.X -= aCaptionPoint.X;
                                        }
                                        aUnoPoint.Y = xShape->getPosition().Y;
                                        xShape->setPosition(aUnoPoint);
                                        pDocSh->SetModified();
                                    }
                                    else
                                    {
                                        DBG_ERROR("unknown anchor type");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    else if ( aNameString.EqualsAscii( SC_UNONAME_VERTPOS ) )
    {
        sal_Int32 nPos = 0;
        if (aValue >>= nPos)
        {
            SdrObject *pObj = GetSdrObject();
		    if (pObj)
		    {
		        ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
		        SdrPage* pPage = pObj->GetPage();
		        if ( pModel && pPage )
		        {
					SCTAB nTab = 0;
					if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
					{
			            ScDocument* pDoc = pModel->GetDocument();
			            if ( pDoc )
			            {
				            SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
				            if ( pObjSh && pObjSh->ISA(ScDocShell) )
				            {
					            ScDocShell* pDocSh = (ScDocShell*)pObjSh;
                                uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
                                if (xShape.is())
                                {
                                    if (ScDrawLayer::GetAnchor(pObj) == SCA_PAGE)
                                    {
                                        awt::Point aPoint = xShape->getPosition();
                                        awt::Point aCaptionPoint;
                                        if (lcl_GetCaptionPoint(xShape, aCaptionPoint))
                                        {
                                            if (aCaptionPoint.Y < 0)
                                                nPos -= aCaptionPoint.Y;
                                        }
                                        aPoint.Y = nPos;
                                        xShape->setPosition(aPoint);
                                        pDocSh->SetModified();
                                    }
                                    else if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
                                    {
                                        awt::Size aUnoSize;
                                        awt::Point aCaptionPoint;
                                        ScRange aRange;
                                        awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));
                                        Rectangle aRect(pDoc->GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ));
                                        Point aPoint(aRect.TopRight());
                                        Point aEndPoint(aRect.BottomLeft());
                                        aUnoPoint.Y = nPos;
                                        aUnoPoint.Y += aPoint.Y();
                                        if (aUnoPoint.Y > aEndPoint.Y())
                                            aUnoPoint.Y = aEndPoint.Y() - 2;
                                        if (aCaptionPoint.Y < 0)
                                            aUnoPoint.Y -= aCaptionPoint.Y;
                                        aUnoPoint.X = xShape->getPosition().X;
                                        xShape->setPosition(aUnoPoint);
                                        pDocSh->SetModified();
                                    }
                                    else
                                    {
                                        DBG_ERROR("unknown anchor type");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
	else
	{
        GetShapePropertySet();
        if (pShapePropertySet)
            pShapePropertySet->setPropertyValue( aPropertyName, aValue );
	}
}

uno::Any SAL_CALL ScShapeObj::getPropertyValue( const rtl::OUString& aPropertyName )
				throw(beans::UnknownPropertyException, lang::WrappedTargetException,
						uno::RuntimeException)
{
	ScUnoGuard aGuard;
	String aNameString = aPropertyName;

	uno::Any aAny;
	if ( aNameString.EqualsAscii( SC_UNONAME_ANCHOR ) )
    {
		SdrObject *pObj = GetSdrObject();
		if (pObj)
		{
		    ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
		    SdrPage* pPage = pObj->GetPage();
		    if ( pModel && pPage )
		    {
			    ScDocument* pDoc = pModel->GetDocument();
			    if ( pDoc )
			    {
					SCTAB nTab = 0;
					if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
					{
				        SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
				        if ( pObjSh && pObjSh->ISA(ScDocShell) )
				        {
					        ScDocShell* pDocSh = (ScDocShell*)pObjSh;
                		    uno::Reference< uno::XInterface > xAnchor;
			                if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
                            {
                                uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
                                if (xShape.is())
                                {
                                    awt::Size aUnoSize;
                                    awt::Point aCaptionPoint;
                                    ScRange aRange;
                                    awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));

    						        xAnchor.set(static_cast<cppu::OWeakObject*>(new ScCellObj( pDocSh, aRange.aStart )));
                                }
                            }
                            else
                            {
    						    xAnchor.set(static_cast<cppu::OWeakObject*>(new ScTableSheetObj( pDocSh, nTab )));
                            }
                            aAny <<= xAnchor;
                        }
					}
                }
            }
        }
    }
    else if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
	{
		uno::Reference< uno::XInterface > xImageMap;
		SdrObject* pObj = GetSdrObject();
		if ( pObj )
		{
			ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo(GetSdrObject());
			if( pIMapInfo )
			{
				const ImageMap& rIMap = pIMapInfo->GetImageMap();
				xImageMap.set(SvUnoImageMap_createInstance( rIMap, GetSupportedMacroItems() ));
			}
			else
				xImageMap = SvUnoImageMap_createInstance( GetSupportedMacroItems() );
		}
		aAny <<= uno::Reference< container::XIndexContainer >::query( xImageMap );
	}
    else if ( aNameString.EqualsAscii( SC_UNONAME_HORIPOS ) )
    {
		SdrObject *pObj = GetSdrObject();
		if (pObj)
		{
		    ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
		    SdrPage* pPage = pObj->GetPage();
		    if ( pModel && pPage )
		    {
			    ScDocument* pDoc = pModel->GetDocument();
			    if ( pDoc )
			    {
					SCTAB nTab = 0;
					if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
					{
                        uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
                        if (xShape.is())
                        {
			                if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
                            {
                                awt::Size aUnoSize;
                                awt::Point aCaptionPoint;
                                ScRange aRange;
                                awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));
                                if (pDoc->IsNegativePage(nTab))
                                    aUnoPoint.X *= -1;
                                aAny <<= aUnoPoint.X;
                            }
                            else
                            {
                                awt::Point aCaptionPoint;
                                awt::Point aUnoPoint(xShape->getPosition());
                                awt::Size aUnoSize(xShape->getSize());
                                if (pDoc->IsNegativePage(nTab))
                                {
                                    aUnoPoint.X *= -1;
                                    aUnoPoint.X -= aUnoSize.Width;
                                }
                                if (lcl_GetCaptionPoint(xShape, aCaptionPoint))
                                {
                                    if (pDoc->IsNegativePage(nTab))
                                    {
                                        if (aCaptionPoint.X > 0 && aCaptionPoint.X > aUnoSize.Width)
                                            aUnoPoint.X -= aCaptionPoint.X - aUnoSize.Width;
                                    }
                                    else
                                    {
                                        if (aCaptionPoint.X < 0)
                                            aUnoPoint.X += aCaptionPoint.X;
                                    }
                                }
                                aAny <<= aUnoPoint.X;
                            }
                        }
					}
                }
            }
        }
    }
    else if ( aNameString.EqualsAscii( SC_UNONAME_VERTPOS ) )
    {
		SdrObject *pObj = GetSdrObject();
		if (pObj)
		{
		    ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
		    SdrPage* pPage = pObj->GetPage();
		    if ( pModel && pPage )
		    {
			    ScDocument* pDoc = pModel->GetDocument();
			    if ( pDoc )
			    {
					SCTAB nTab = 0;
					if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
					{
                        uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY );
                        if (xShape.is())
                        {
                		    uno::Reference< uno::XInterface > xAnchor;
			                if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL)
                            {
                                awt::Size aUnoSize;
                                awt::Point aCaptionPoint;
                                ScRange aRange;
                                awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint ));

                                aAny <<= aUnoPoint.Y;
                            }
                            else
                            {
                                awt::Point aUnoPoint(xShape->getPosition());
                                awt::Point aCaptionPoint;
                                if (lcl_GetCaptionPoint(xShape, aCaptionPoint))
                                {
                                    if (aCaptionPoint.Y < 0)
                                        aUnoPoint.Y += aCaptionPoint.Y;
                                }
                                aAny <<= aUnoPoint.Y;
                            }
                        }
					}
                }
            }
        }
    }
	else
	{
        if(!pShapePropertySet)	GetShapePropertySet(); //performance consideration
        if (pShapePropertySet)
            aAny = pShapePropertySet->getPropertyValue( aPropertyName );
	}

	return aAny;
}

void SAL_CALL ScShapeObj::addPropertyChangeListener( const rtl::OUString& aPropertyName,
							const uno::Reference<beans::XPropertyChangeListener>& aListener)
							throw(beans::UnknownPropertyException,
									lang::WrappedTargetException, uno::RuntimeException)
{
	ScUnoGuard aGuard;

    GetShapePropertySet();
    if (pShapePropertySet)
        pShapePropertySet->addPropertyChangeListener( aPropertyName, aListener );

    if ( !bInitializedNotifier )
    {
        // here's the latest chance to initialize the property notification at the SdrObject
        // (in the ctor, where we also attempt to do this, we do not necessarily have
        // and SdrObject, yet)
        SdrObject* pObj = GetSdrObject();
        OSL_ENSURE( pObj, "ScShapeObj::addPropertyChangeListener: no SdrObject -> no property change notification!" );
        if ( pObj )
            lcl_initializeNotifier( *pObj, *this );
        bInitializedNotifier = true;
    }
}

void SAL_CALL ScShapeObj::removePropertyChangeListener( const rtl::OUString& aPropertyName,
							const uno::Reference<beans::XPropertyChangeListener>& aListener)
							throw(beans::UnknownPropertyException,
									lang::WrappedTargetException, uno::RuntimeException)
{
	ScUnoGuard aGuard;

    GetShapePropertySet();
    if (pShapePropertySet)
        pShapePropertySet->removePropertyChangeListener( aPropertyName, aListener );
}

void SAL_CALL ScShapeObj::addVetoableChangeListener( const rtl::OUString& aPropertyName,
							const uno::Reference<beans::XVetoableChangeListener>& aListener)
							throw(beans::UnknownPropertyException,
								lang::WrappedTargetException, uno::RuntimeException)
{
	ScUnoGuard aGuard;

    GetShapePropertySet();
    if (pShapePropertySet)
        pShapePropertySet->addVetoableChangeListener( aPropertyName, aListener );
}

void SAL_CALL ScShapeObj::removeVetoableChangeListener( const rtl::OUString& aPropertyName,
							const uno::Reference<beans::XVetoableChangeListener>& aListener)
							throw(beans::UnknownPropertyException,
								lang::WrappedTargetException, uno::RuntimeException)
{
	ScUnoGuard aGuard;

    GetShapePropertySet();
    if (pShapePropertySet)
        pShapePropertySet->removeVetoableChangeListener( aPropertyName, aListener );
}

//	XPropertyState

beans::PropertyState SAL_CALL ScShapeObj::getPropertyState( const rtl::OUString& aPropertyName )
								throw(beans::UnknownPropertyException, uno::RuntimeException)
{
	ScUnoGuard aGuard;
	String aNameString(aPropertyName);

	beans::PropertyState eRet = beans::PropertyState_DIRECT_VALUE;
	if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
	{
		// ImageMap is always "direct"
	}
    else if ( aNameString.EqualsAscii( SC_UNONAME_ANCHOR ) )
	{
		// Anchor is always "direct"
	}
    else if ( aNameString.EqualsAscii( SC_UNONAME_HORIPOS ) )
	{
		// HoriPos is always "direct"
	}
    else if ( aNameString.EqualsAscii( SC_UNONAME_VERTPOS ) )
	{
		// VertPos is always "direct"
	}
	else
	{
        GetShapePropertyState();
        if (pShapePropertyState)
            eRet = pShapePropertyState->getPropertyState( aPropertyName );
	}

	return eRet;
}

uno::Sequence<beans::PropertyState> SAL_CALL ScShapeObj::getPropertyStates(
								const uno::Sequence<rtl::OUString>& aPropertyNames )
							throw(beans::UnknownPropertyException, uno::RuntimeException)
{
	ScUnoGuard aGuard;

	//	simple loop to get own and aggregated states

	const rtl::OUString* pNames = aPropertyNames.getConstArray();
	uno::Sequence<beans::PropertyState> aRet(aPropertyNames.getLength());
	beans::PropertyState* pStates = aRet.getArray();
	for(sal_Int32 i = 0; i < aPropertyNames.getLength(); i++)
		pStates[i] = getPropertyState(pNames[i]);
	return aRet;
}

void SAL_CALL ScShapeObj::setPropertyToDefault( const rtl::OUString& aPropertyName )
							throw(beans::UnknownPropertyException, uno::RuntimeException)
{
	ScUnoGuard aGuard;
	String aNameString(aPropertyName);

	if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
	{
		SdrObject* pObj = GetSdrObject();
		if ( pObj )
		{
			ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo(pObj);
			if( pIMapInfo )
			{
				ImageMap aEmpty;
				pIMapInfo->SetImageMap( aEmpty );	// replace with empty image map
			}
			else
			{
				// nothing to do (no need to insert user data for an empty map)
			}
		}
	}
	else
	{
        GetShapePropertyState();
        if (pShapePropertyState)
            pShapePropertyState->setPropertyToDefault( aPropertyName );
	}
}

uno::Any SAL_CALL ScShapeObj::getPropertyDefault( const rtl::OUString& aPropertyName )
								throw(beans::UnknownPropertyException, lang::WrappedTargetException,
										uno::RuntimeException)
{
	ScUnoGuard aGuard;
	String aNameString = aPropertyName;

	uno::Any aAny;
	if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) )
	{
		//	default: empty ImageMap
		uno::Reference< uno::XInterface > xImageMap(SvUnoImageMap_createInstance( GetSupportedMacroItems() ));
		aAny <<= uno::Reference< container::XIndexContainer >::query( xImageMap );
	}
	else
	{
        GetShapePropertyState();
        if (pShapePropertyState)
            aAny = pShapePropertyState->getPropertyDefault( aPropertyName );
	}

	return aAny;
}

// XTextContent

void SAL_CALL ScShapeObj::attach( const uno::Reference<text::XTextRange>& /* xTextRange */ )
								throw(lang::IllegalArgumentException, uno::RuntimeException)
{
	ScUnoGuard aGuard;

	throw lang::IllegalArgumentException();		// anchor cannot be changed
}

uno::Reference<text::XTextRange> SAL_CALL ScShapeObj::getAnchor() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<text::XTextRange> xRet;

	SdrObject* pObj = GetSdrObject();
	if( pObj )
	{
		ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
		SdrPage* pPage = pObj->GetPage();
		if ( pModel )
		{
			ScDocument* pDoc = pModel->GetDocument();
			if ( pDoc )
			{
				SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
				if ( pObjSh && pObjSh->ISA(ScDocShell) )
				{
					ScDocShell* pDocSh = (ScDocShell*)pObjSh;

					SCTAB nTab = 0;
					if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
					{
						Point aPos(pObj->GetCurrentBoundRect().TopLeft());
						ScRange aRange(pDoc->GetRange( nTab, Rectangle( aPos, aPos ) ));

						//	anchor is always the cell

						xRet.set(new ScCellObj( pDocSh, aRange.aStart ));
					}
				}
			}
		}
	}

	return xRet;
}

// XComponent

void SAL_CALL ScShapeObj::dispose() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<lang::XComponent> xAggComp(lcl_GetComponent(mxShapeAgg));
	if ( xAggComp.is() )
		xAggComp->dispose();
}

void SAL_CALL ScShapeObj::addEventListener(
						const uno::Reference<lang::XEventListener>& xListener )
													throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<lang::XComponent> xAggComp(lcl_GetComponent(mxShapeAgg));
	if ( xAggComp.is() )
		xAggComp->addEventListener(xListener);
}

void SAL_CALL ScShapeObj::removeEventListener(
						const uno::Reference<lang::XEventListener>& xListener )
													throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<lang::XComponent> xAggComp(lcl_GetComponent(mxShapeAgg));
	if ( xAggComp.is() )
		xAggComp->removeEventListener(xListener);
}

// XText
// (special handling for ScCellFieldObj)

void lcl_CopyOneProperty( beans::XPropertySet& rDest, beans::XPropertySet& rSource, const sal_Char* pName )
{
	rtl::OUString aNameStr(rtl::OUString::createFromAscii(pName));
	try
	{
		rDest.setPropertyValue( aNameStr, rSource.getPropertyValue( aNameStr ) );
	}
	catch (uno::Exception&)
	{
		DBG_ERROR("Exception in text field");
	}
}

void SAL_CALL ScShapeObj::insertTextContent( const uno::Reference<text::XTextRange>& xRange,
												const uno::Reference<text::XTextContent>& xContent,
												sal_Bool bAbsorb )
									throw(lang::IllegalArgumentException, uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<text::XTextContent> xEffContent;

	ScCellFieldObj* pCellField = ScCellFieldObj::getImplementation( xContent );
	if ( pCellField )
	{
		//	#105585# createInstance("TextField.URL") from the document creates a ScCellFieldObj.
		//	To insert it into drawing text, a SvxUnoTextField is needed instead.
		//	The ScCellFieldObj object is left in non-inserted state.

		SvxUnoTextField* pDrawField = new SvxUnoTextField( ID_URLFIELD );
		xEffContent.set(pDrawField);
		lcl_CopyOneProperty( *pDrawField, *pCellField, SC_UNONAME_URL );
		lcl_CopyOneProperty( *pDrawField, *pCellField, SC_UNONAME_REPR );
		lcl_CopyOneProperty( *pDrawField, *pCellField, SC_UNONAME_TARGET );
	}
	else
		xEffContent.set(xContent);

	uno::Reference<text::XText> xAggText(lcl_GetText(mxShapeAgg));
	if ( xAggText.is() )
		xAggText->insertTextContent( xRange, xEffContent, bAbsorb );
}

void SAL_CALL ScShapeObj::removeTextContent( const uno::Reference<text::XTextContent>& xContent )
								throw(container::NoSuchElementException, uno::RuntimeException)
{
	ScUnoGuard aGuard;

	//	ScCellFieldObj can't be used here.

	uno::Reference<text::XText> xAggText(lcl_GetText(mxShapeAgg));
	if ( xAggText.is() )
		xAggText->removeTextContent( xContent );
}

// XSimpleText (parent of XText)
// Use own SvxUnoTextCursor subclass - everything is just passed to aggregated object

uno::Reference<text::XTextCursor> SAL_CALL ScShapeObj::createTextCursor()
													throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	if ( mxShapeAgg.is() )
	{
		//	ScDrawTextCursor must be used to ensure the ScShapeObj is returned by getText

		SvxUnoTextBase* pText = SvxUnoTextBase::getImplementation( mxShapeAgg );
		if (pText)
			return new ScDrawTextCursor( this, *pText );
	}

	return uno::Reference<text::XTextCursor>();
}

uno::Reference<text::XTextCursor> SAL_CALL ScShapeObj::createTextCursorByRange(
									const uno::Reference<text::XTextRange>& aTextPosition )
													throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	if ( mxShapeAgg.is() && aTextPosition.is() )
	{
		//	ScDrawTextCursor must be used to ensure the ScShapeObj is returned by getText

		SvxUnoTextBase* pText = SvxUnoTextBase::getImplementation( mxShapeAgg );
		SvxUnoTextRangeBase* pRange = SvxUnoTextRangeBase::getImplementation( aTextPosition );
		if ( pText && pRange )
		{
			SvxUnoTextCursor* pCursor = new ScDrawTextCursor( this, *pText );
			uno::Reference<text::XTextCursor> xCursor( pCursor );
			pCursor->SetSelection( pRange->GetSelection() );
			return xCursor;
		}
	}

	return uno::Reference<text::XTextCursor>();
}

void SAL_CALL ScShapeObj::insertString( const uno::Reference<text::XTextRange>& xRange,
										const rtl::OUString& aString, sal_Bool bAbsorb )
									throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<text::XSimpleText> xAggSimpleText(lcl_GetSimpleText(mxShapeAgg));
	if ( xAggSimpleText.is() )
		xAggSimpleText->insertString( xRange, aString, bAbsorb );
	else
		throw uno::RuntimeException();
}

void SAL_CALL ScShapeObj::insertControlCharacter( const uno::Reference<text::XTextRange>& xRange,
												sal_Int16 nControlCharacter, sal_Bool bAbsorb )
									throw(lang::IllegalArgumentException, uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<text::XSimpleText> xAggSimpleText(lcl_GetSimpleText(mxShapeAgg));
	if ( xAggSimpleText.is() )
		xAggSimpleText->insertControlCharacter( xRange, nControlCharacter, bAbsorb );
	else
		throw uno::RuntimeException();
}

// XTextRange
// (parent of XSimpleText)

uno::Reference<text::XText> SAL_CALL ScShapeObj::getText() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	return this;
}

uno::Reference<text::XTextRange> SAL_CALL ScShapeObj::getStart() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg));
	if ( xAggTextRange.is() )
		return xAggTextRange->getStart();
	else
		throw uno::RuntimeException();

//    return uno::Reference<text::XTextRange>();
}

uno::Reference<text::XTextRange> SAL_CALL ScShapeObj::getEnd() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg));
	if ( xAggTextRange.is() )
		return xAggTextRange->getEnd();
	else
		throw uno::RuntimeException();

//    return uno::Reference<text::XTextRange>();
}

rtl::OUString SAL_CALL ScShapeObj::getString() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg));
	if ( xAggTextRange.is() )
		return xAggTextRange->getString();
	else
		throw uno::RuntimeException();

//    return rtl::OUString();
}

void SAL_CALL ScShapeObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg));
	if ( xAggTextRange.is() )
		xAggTextRange->setString( aText );
	else
		throw uno::RuntimeException();
}

// XChild

uno::Reference< uno::XInterface > SAL_CALL ScShapeObj::getParent() throw (uno::RuntimeException)
{
	ScUnoGuard aGuard;

    // receive cell position from caption object (parent of a note caption is the note cell)
	SdrObject* pObj = GetSdrObject();
	if( pObj )
	{
		ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel();
		SdrPage* pPage = pObj->GetPage();
		if ( pModel )
		{
			ScDocument* pDoc = pModel->GetDocument();
			if ( pDoc )
			{
				SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
				if ( pObjSh && pObjSh->ISA(ScDocShell) )
				{
					ScDocShell* pDocSh = (ScDocShell*)pObjSh;

					SCTAB nTab = 0;
					if ( lcl_GetPageNum( pPage, *pModel, nTab ) )
					{
                        const ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObj, nTab );
                        if( pCaptData )
                            return static_cast< ::cppu::OWeakObject* >( new ScCellObj( pDocSh, pCaptData->maStart ) );
                    }
                }
            }
        }
    }

	return 0;
}

void SAL_CALL ScShapeObj::setParent( const uno::Reference< uno::XInterface >& ) throw (lang::NoSupportException, uno::RuntimeException)
{
    throw lang::NoSupportException();
}

// XTypeProvider

uno::Sequence<uno::Type> SAL_CALL ScShapeObj::getTypes() throw(uno::RuntimeException)
{
    uno::Sequence< uno::Type > aBaseTypes( ScShapeObj_Base::getTypes() );

    uno::Sequence< uno::Type > aTextTypes;
    if ( bIsTextShape )
        aTextTypes = ScShapeObj_TextBase::getTypes();

	uno::Reference<lang::XTypeProvider> xBaseProvider;
	if ( mxShapeAgg.is() )
		mxShapeAgg->queryAggregation( getCppuType((uno::Reference<lang::XTypeProvider>*) 0) ) >>= xBaseProvider;
	DBG_ASSERT( xBaseProvider.is(), "ScShapeObj: No XTypeProvider from aggregated shape!" );

    uno::Sequence< uno::Type > aAggTypes;
	if( xBaseProvider.is() )
		aAggTypes = xBaseProvider->getTypes();

    return ::comphelper::concatSequences( aBaseTypes, aTextTypes, aAggTypes );
}

uno::Sequence<sal_Int8> SAL_CALL ScShapeObj::getImplementationId()
													throw(uno::RuntimeException)
{
    ScUnoGuard aGuard;
	// do we need to compute the implementation id for this instance?
    if( !pImplementationId && mxShapeAgg.is())
	{
        uno::Reference< drawing::XShape > xAggShape;
        mxShapeAgg->queryAggregation( ::getCppuType((uno::Reference< drawing::XShape >*)0) ) >>= xAggShape;

        if( xAggShape.is() )
		{
            const rtl::OUString aShapeType( xAggShape->getShapeType() );
            // did we already compute an implementation id for the aggregated shape type?
            ScShapeImplementationIdMap::iterator aIter( aImplementationIdMap.find(aShapeType ) );
			if( aIter == aImplementationIdMap.end() )
			{
				// we need to create a new implementation id for this
				// note: this memory is not freed 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 ScXShape!" );
        return uno::Sequence< sal_Int8 > ();
	}
	else
	{
        return *pImplementationId;
	}
}

SdrObject* ScShapeObj::GetSdrObject() const throw()
{
	if(mxShapeAgg.is())
	{
		SvxShape* pShape = SvxShape::getImplementation( mxShapeAgg );
		if(pShape)
			return pShape->GetSdrObject();
	}

	return NULL;
}

#define SC_EVENTACC_ONCLICK     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnClick" ) )
#ifdef ISSUE66550_HLINK_FOR_SHAPES
#define SC_EVENTACC_ONACTION    ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnAction" ) )
#define SC_EVENTACC_URL         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) )
#define SC_EVENTACC_ACTION      ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Action" ) )
#endif
#define SC_EVENTACC_SCRIPT      ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Script" ) )
#define SC_EVENTACC_EVENTTYPE   ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EventType" ) )

typedef ::cppu::WeakImplHelper1< container::XNameReplace > ShapeUnoEventAcess_BASE;
class ShapeUnoEventAccessImpl : public ShapeUnoEventAcess_BASE
{
private:
	ScShapeObj* mpShape;

    ScMacroInfo* getInfo( sal_Bool bCreate = sal_False )
	{
        if( mpShape )
            if( SdrObject* pObj = mpShape->GetSdrObject() )
                return ScDrawLayer::GetMacroInfo( pObj, bCreate );
        return 0;
	}

public:
	ShapeUnoEventAccessImpl( ScShapeObj* pShape ): mpShape( pShape )
	{
	}

	// XNameReplace
	virtual void SAL_CALL replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) throw(lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
	{
        if ( !hasByName( aName ) )
			throw container::NoSuchElementException();
		uno::Sequence< beans::PropertyValue > aProperties;
		aElement >>= aProperties;
		const beans::PropertyValue* pProperties = aProperties.getConstArray();
		const sal_Int32 nCount = aProperties.getLength();
		sal_Int32 nIndex;
		bool isEventType = false;
		for( nIndex = 0; nIndex < nCount; nIndex++, pProperties++ )
		{
            if ( pProperties->Name.equals( SC_EVENTACC_EVENTTYPE ) )
			{
				isEventType = true;
				continue;
			}
#ifdef ISSUE66550_HLINK_FOR_SHAPES
            if ( isEventType && ((pProperties->Name == SC_EVENTACC_SCRIPT) || (pProperties->Name == SC_EVENTACC_URL)) )
#else
            if ( isEventType && (pProperties->Name == SC_EVENTACC_SCRIPT) )
#endif
			{
                rtl::OUString sValue;
                if ( pProperties->Value >>= sValue )
                {
                    ScMacroInfo* pInfo = getInfo( sal_True );
                    DBG_ASSERT( pInfo, "shape macro info could not be created!" );
                    if ( !pInfo )
                        break;
                    if ( pProperties->Name == SC_EVENTACC_SCRIPT )
                        pInfo->SetMacro( sValue );
#ifdef ISSUE66550_HLINK_FOR_SHAPES
                    else
                        pInfo->SetHlink( sValue );
#endif
                }
			}
		}
	}

	// XNameAccess
	virtual uno::Any SAL_CALL getByName( const rtl::OUString& aName ) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
	{
        uno::Sequence< beans::PropertyValue > aProperties;
        ScMacroInfo* pInfo = getInfo();

        if ( aName == SC_EVENTACC_ONCLICK )
        {
            if ( pInfo && (pInfo->GetMacro().getLength() > 0) )
            {
                aProperties.realloc( 2 );
                aProperties[ 0 ].Name = SC_EVENTACC_EVENTTYPE;
                aProperties[ 0 ].Value <<= SC_EVENTACC_SCRIPT;
                aProperties[ 1 ].Name = SC_EVENTACC_SCRIPT;
                aProperties[ 1 ].Value <<= pInfo->GetMacro();
            }
        }
#ifdef ISSUE66550_HLINK_FOR_SHAPES
        else if( aName == SC_EVENTACC_ONACTION )
        {
            if ( pInfo && (pInfo->GetHlink().getLength() > 0) )
            {
                aProperties.realloc( 2 );
                aProperties[ 0 ].Name = SC_EVENTACC_EVENTTYPE;
                aProperties[ 0 ].Value <<= SC_EVENTACC_ACTION;
                aProperties[ 1 ].Name = SC_EVENTACC_URL;
                aProperties[ 1 ].Value <<= pInfo->GetHlink();
            }
        }
#endif
        else
        {
            throw container::NoSuchElementException();
        }

        return uno::Any( aProperties );
	}

    virtual uno::Sequence< rtl::OUString > SAL_CALL getElementNames() throw(uno::RuntimeException)
	{
#ifdef ISSUE66550_HLINK_FOR_SHAPES
        uno::Sequence< rtl::OUString > aSeq( 2 );
#else
        uno::Sequence< rtl::OUString > aSeq( 1 );
#endif
        aSeq[ 0 ] = SC_EVENTACC_ONCLICK;
#ifdef ISSUE66550_HLINK_FOR_SHAPES
        aSeq[ 1 ] = SC_EVENTACC_ONACTION;
#endif
        return aSeq;
	}

	virtual sal_Bool SAL_CALL hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
	{
#ifdef ISSUE66550_HLINK_FOR_SHAPES
        return (aName == SC_EVENTACC_ONCLICK) || (aName == SC_EVENTACC_ONACTION);
#else
        return aName == SC_EVENTACC_ONCLICK;
#endif
	}

	// XElementAccess
    virtual uno::Type SAL_CALL getElementType() throw(uno::RuntimeException)
	{
		return *SEQTYPE(::getCppuType((const uno::Sequence< beans::PropertyValue >*)0));
	}

    virtual sal_Bool SAL_CALL hasElements() throw(uno::RuntimeException)
	{
        // elements are always present (but contained property sequences may be empty)
        return sal_True;
	}
};

::uno::Reference< container::XNameReplace > SAL_CALL
ScShapeObj::getEvents(  ) throw(uno::RuntimeException)
{
	return new ShapeUnoEventAccessImpl( this );
}

::rtl::OUString SAL_CALL ScShapeObj::getImplementationName(  ) throw (uno::RuntimeException)
{
    return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.sc.ScShapeObj" ) );
}

::sal_Bool SAL_CALL ScShapeObj::supportsService( const ::rtl::OUString& _ServiceName ) throw (uno::RuntimeException)
{
    uno::Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
    for ( const ::rtl::OUString* pSupported = aSupported.getConstArray();
          pSupported != aSupported.getConstArray() + aSupported.getLength();
          ++pSupported
        )
        if ( _ServiceName == *pSupported )
            return sal_True;
    return sal_False;
}

uno::Sequence< ::rtl::OUString > SAL_CALL ScShapeObj::getSupportedServiceNames(  ) throw (uno::RuntimeException)
{
    uno::Reference<lang::XServiceInfo> xSI;
    if ( mxShapeAgg.is() )
        mxShapeAgg->queryAggregation( lang::XServiceInfo::static_type() ) >>= xSI;

    uno::Sequence< ::rtl::OUString > aSupported;
    if ( xSI.is() )
        aSupported = xSI->getSupportedServiceNames();

    aSupported.realloc( aSupported.getLength() + 1 );
    aSupported[ aSupported.getLength() - 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.Shape" ) );

    if( bIsNoteCaption )
    {
        aSupported.realloc( aSupported.getLength() + 1 );
        aSupported[ aSupported.getLength() - 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.CellAnnotationShape" ) );
    }

    return aSupported;
}
