/**************************************************************
 * 
 * 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 agregated 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 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 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;
}
