/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include <vos/ref.hxx>
#include <cppuhelper/weakref.hxx>
#include <vcl/window.hxx>
#include <svx/svdmodel.hxx>
#include <svx/unomod.hxx>
#include <tools/debug.hxx>
#include <map>
#include <list>
#include <vector>
#include <accmap.hxx>
#include <acccontext.hxx>
#include <accdoc.hxx>
#include <accpreview.hxx>
#include <accpage.hxx>
#include <accpara.hxx>
#include <accheaderfooter.hxx>
#include <accfootnote.hxx>
#include <acctextframe.hxx>
#include <accgraphic.hxx>
#include <accembedded.hxx>
#include <acccell.hxx>
#include <acctable.hxx>
#include <fesh.hxx>
#include <rootfrm.hxx>
#include <txtfrm.hxx>
#include <hffrm.hxx>
#include <ftnfrm.hxx>
#include <cellfrm.hxx>
#include <tabfrm.hxx>
#include <pagefrm.hxx>
#include <flyfrm.hxx>
#include <ndtyp.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <svx/ShapeTypeHandler.hxx>
#include <vcl/svapp.hxx>
#include <svx/ShapeTypeHandler.hxx>
#include <svx/SvxShapeTypes.hxx>
#include <svx/svdpage.hxx>
#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <cppuhelper/implbase1.hxx>
#include <pagepreviewlayout.hxx>
#include <dcontact.hxx>
#include <svx/unoapi.hxx>
#include <svx/svdmark.hxx>
#include <doc.hxx>
#include <pam.hxx>
#include <ndtxt.hxx>
#include <dflyobj.hxx>
#include <prevwpage.hxx>
#include <switerator.hxx>
#include <drawdoc.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::accessibility;
using ::rtl::OUString;
using namespace ::sw::access;

struct SwFrmFunc
{
	sal_Bool operator()( const SwFrm * p1,
				    	 const SwFrm * p2) const
	{
		return p1 < p2;
	}
};

typedef ::std::map < const SwFrm *, uno::WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl;

class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl
{
public:

#ifdef DBG_UTIL
	sal_Bool mbLocked;
#endif

	SwAccessibleContextMap_Impl()
#ifdef DBG_UTIL
		: mbLocked( sal_False )
#endif
	{}

};

//------------------------------------------------------------------------------
class SwDrawModellListener_Impl : public SfxListener,
	public ::cppu::WeakImplHelper1< document::XEventBroadcaster >
{
	mutable ::osl::Mutex maListenerMutex;
	::cppu::OInterfaceContainerHelper maEventListeners;
	SdrModel *mpDrawModel;
protected:
	virtual ~SwDrawModellListener_Impl();
public:

	SwDrawModellListener_Impl( SdrModel *pDrawModel );


    virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
    virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);

	virtual void		Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
	void Dispose();
};

SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) :
	maEventListeners( maListenerMutex ),
	mpDrawModel( pDrawModel )
{
	StartListening( *mpDrawModel );
}

SwDrawModellListener_Impl::~SwDrawModellListener_Impl()
{
	EndListening( *mpDrawModel );
}

void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
{
	maEventListeners.addInterface( xListener );
}

void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
{
	maEventListeners.removeInterface( xListener );
}

void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
		const SfxHint& rHint )
{
	// do not broadcast notifications for writer fly frames, because there
	// are no shapes that need to know about them.
    // OD 01.07.2003 #110554# - correct condition in order not to broadcast
    // notifications for writer fly frames.
    // OD 01.07.2003 #110554# - do not broadcast notifications for plane
    // <SdrObject>objects
	const SdrHint *pSdrHint = PTR_CAST( SdrHint, &rHint );
    if ( !pSdrHint ||
         ( pSdrHint->GetObject() &&
           ( pSdrHint->GetObject()->ISA(SwFlyDrawObj) ||
             pSdrHint->GetObject()->ISA(SwVirtFlyDrawObj) ||
             IS_TYPE(SdrObject,pSdrHint->GetObject()) ) ) )
    {
        return;
    }

	ASSERT( mpDrawModel, "draw model listener is disposed" );
	if( !mpDrawModel )
		return;

	document::EventObject aEvent;
	if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) )
		return;

	::cppu::OInterfaceIteratorHelper aIter( maEventListeners );
	while( aIter.hasMoreElements() )
	{
		uno::Reference < document::XEventListener > xListener( aIter.next(),
												uno::UNO_QUERY );
		try
		{
			xListener->notifyEvent( aEvent );
		}
		catch( uno::RuntimeException const & r )
		{
            (void)r;
#if OSL_DEBUG_LEVEL > 1
			ByteString aError( "Runtime exception caught while notifying shape.:\n" );
			aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US );
			DBG_ERROR( aError.GetBuffer() );
#endif
		}
	}
}

void SwDrawModellListener_Impl::Dispose()
{
	mpDrawModel = 0;
}

//------------------------------------------------------------------------------
struct SwShapeFunc
{
	sal_Bool operator()( const SdrObject * p1,
				    	 const SdrObject * p2) const
	{
		return p1 < p2;
	}
};
typedef ::std::map < const SdrObject *, uno::WeakReference < XAccessible >, SwShapeFunc > _SwAccessibleShapeMap_Impl;
typedef ::std::pair < const SdrObject *, ::vos::ORef < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl;

class SwAccessibleShapeMap_Impl: public _SwAccessibleShapeMap_Impl

{
	::accessibility::AccessibleShapeTreeInfo maInfo;

public:

#ifdef DBG_UTIL
	sal_Bool mbLocked;
#endif
	SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap )
#ifdef DBG_UTIL
		: mbLocked( sal_False )
#endif
	{
		maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
		maInfo.SetWindow( pMap->GetShell()->GetWin() );
		maInfo.SetViewForwarder( pMap );
        // --> OD 2005-08-08 #i52858# - method name changed
		uno::Reference < document::XEventBroadcaster > xModelBroadcaster =
			new SwDrawModellListener_Impl(
                    pMap->GetShell()->getIDocumentDrawModelAccess()->GetOrCreateDrawModel() );
        // <--
		maInfo.SetControllerBroadcaster( xModelBroadcaster );
	}

	~SwAccessibleShapeMap_Impl();

	const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; }

	SwAccessibleObjShape_Impl *Copy( size_t& rSize,
		const SwFEShell *pFESh = 0,
		SwAccessibleObjShape_Impl  **pSelShape = 0 ) const;
};

SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl()
{
	uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetControllerBroadcaster() );
	if( xBrd.is() )
		static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose();
}

SwAccessibleObjShape_Impl
	*SwAccessibleShapeMap_Impl::Copy(
			size_t& rSize, const SwFEShell *pFESh,
			SwAccessibleObjShape_Impl **pSelStart ) const
{
	SwAccessibleObjShape_Impl *pShapes = 0;
	SwAccessibleObjShape_Impl *pSelShape = 0;

	sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
	rSize = size();

	if( rSize > 0 )
	{
		pShapes =
			new SwAccessibleObjShape_Impl[rSize];

		const_iterator aIter = begin();
		const_iterator aEndIter = end();

		SwAccessibleObjShape_Impl *pShape = pShapes;
		pSelShape = &(pShapes[rSize]);
		while( aIter != aEndIter )
		{
			const SdrObject *pObj = (*aIter).first;
			uno::Reference < XAccessible > xAcc( (*aIter).second );
			if( nSelShapes && pFESh &&pFESh->IsObjSelected( *pObj ) )
			{
				// selected objects are inserted from the back
				--pSelShape;
				pSelShape->first = pObj;
				pSelShape->second =
					static_cast < ::accessibility::AccessibleShape* >(
													xAcc.get() );
				--nSelShapes;
			}
			else
			{
				pShape->first = pObj;
				pShape->second =
					static_cast < ::accessibility::AccessibleShape* >(
													xAcc.get() );
				++pShape;
			}
			++aIter;
		}
		ASSERT( pSelShape == pShape, "copying shapes went wrong!" );
	}

	if( pSelStart )
		*pSelStart = pSelShape;

	return pShapes;
}

//------------------------------------------------------------------------------
struct SwAccessibleEvent_Impl
{
public:
    enum EventType { CARET_OR_STATES,
                     INVALID_CONTENT,
                     POS_CHANGED,
                     CHILD_POS_CHANGED,
                     SHAPE_SELECTION,
                     DISPOSE,
                     INVALID_ATTR };

private:
	SwRect		maOldBox;				// the old bounds for CHILD_POS_CHANGED
										// and POS_CHANGED
	uno::WeakReference < XAccessible > mxAcc;	// The object that fires the event
    SwAccessibleChild   maFrmOrObj;             // the child for CHILD_POS_CHANGED and
										// the same as xAcc for any other
										// event type
	EventType 	meType;					// The event type
    // --> OD 2005-12-12 #i27301# - use new type definition for <mnStates>
    tAccessibleStates mnStates;         // check states or update caret pos
    // <--

	SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& );

public:
	const SwFrm* mpParentFrm;	// The object that fires the event
	sal_Bool IsNoXaccParentFrm() const 
	{
		return CHILD_POS_CHANGED == meType && mpParentFrm != 0;
	}
	uno::WeakReference < XAccessible > GetxAcc() const { return mxAcc;}
public:
    SwAccessibleEvent_Impl( EventType eT,
                            SwAccessibleContext *pA,
                            const SwAccessibleChild& rFrmOrObj )
        : mxAcc( pA ),
          maFrmOrObj( rFrmOrObj ),
          meType( eT ),
          mnStates( 0 ),
          mpParentFrm( 0 )
	{}

    SwAccessibleEvent_Impl( EventType eT,
                            const SwAccessibleChild& rFrmOrObj )
        : maFrmOrObj( rFrmOrObj ),
          meType( eT ),
          mnStates( 0 ),
          mpParentFrm( 0 )
	{
		ASSERT( SwAccessibleEvent_Impl::DISPOSE == meType,
				"wrong event constructor, DISPOSE only" );
	}

    SwAccessibleEvent_Impl( EventType eT )
        : meType( eT ),
          mnStates( 0 ),
          mpParentFrm( 0 )
	{
        ASSERT( SwAccessibleEvent_Impl::SHAPE_SELECTION == meType,
				"wrong event constructor, SHAPE_SELECTION only" );
	}

    SwAccessibleEvent_Impl( EventType eT,
                            SwAccessibleContext *pA,
                            const SwAccessibleChild& rFrmOrObj,
                            const SwRect& rR )
        : maOldBox( rR ),
          mxAcc( pA ),
          maFrmOrObj( rFrmOrObj ),
          meType( eT ),
          mnStates( 0 ),
          mpParentFrm( 0 )
	{
		ASSERT( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType ||
				SwAccessibleEvent_Impl::POS_CHANGED == meType,
				"wrong event constructor, (CHILD_)POS_CHANGED only" );
	}

    // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates>
    SwAccessibleEvent_Impl( EventType eT,
                            SwAccessibleContext *pA,
                            const SwAccessibleChild& rFrmOrObj,
                            const tAccessibleStates _nStates )
        : mxAcc( pA ),
          maFrmOrObj( rFrmOrObj ),
          meType( eT ),
          mnStates( _nStates ),
          mpParentFrm( 0 )
	{
		ASSERT( SwAccessibleEvent_Impl::CARET_OR_STATES == meType,
				"wrong event constructor, CARET_OR_STATES only" );
	}

	SwAccessibleEvent_Impl( EventType eT, 
                                const SwFrm *pParentFrm,
				const SwAccessibleChild& rFrmOrObj, 
                                const SwRect& rR ) :
		maOldBox( rR ),
                maFrmOrObj( rFrmOrObj ),
                meType( eT ),
		mnStates( 0 ),
                mpParentFrm( pParentFrm )
	{
		OSL_ENSURE( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType,
			"wrong event constructor, CHILD_POS_CHANGED only" );
	}
    // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
    inline void SetType( EventType eT )
    {
        meType = eT;
    }
    inline EventType GetType() const
    {
        return meType;
    }

    inline ::vos::ORef < SwAccessibleContext > GetContext() const
    {
        uno::Reference < XAccessible > xTmp( mxAcc );
        ::vos::ORef < SwAccessibleContext > xAccImpl(
                            static_cast<SwAccessibleContext*>( xTmp.get() ) );

        return xAccImpl;
    }

    inline const SwRect& GetOldBox() const
    {
        return maOldBox;
    }
    // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
    inline void SetOldBox( const SwRect& rOldBox )
    {
        maOldBox = rOldBox;
    }

    inline const SwAccessibleChild& GetFrmOrObj() const
    {
        return maFrmOrObj;
    }

    // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
    // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates>
    inline void SetStates( tAccessibleStates _nStates )
    {
        mnStates |= _nStates;
    }
    // <--

    inline sal_Bool IsUpdateCursorPos() const
    {
        return (mnStates & ACC_STATE_CARET) != 0;
    }
    inline sal_Bool IsInvalidateStates() const
    {
        return (mnStates & ACC_STATE_MASK) != 0;
    }
    inline sal_Bool IsInvalidateRelation() const
    {
        return (mnStates & ACC_STATE_RELATION_MASK) != 0;
    }
    // --> OD 2005-12-12 #i27301# - new event TEXT_SELECTION_CHANGED
    inline sal_Bool IsInvalidateTextSelection() const
    {
        return ( mnStates & ACC_STATE_TEXT_SELECTION_CHANGED ) != 0;
    }
    // <--
    // --> OD 2009-01-07 #i88069# - new event TEXT_ATTRIBUTE_CHANGED
    inline sal_Bool IsInvalidateTextAttrs() const
    {
        return ( mnStates & ACC_STATE_TEXT_ATTRIBUTE_CHANGED ) != 0;
    }
    // <--
    // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates>
    // for return value
    inline tAccessibleStates GetStates() const
    {
        return mnStates & ACC_STATE_MASK;
    }
    // <--
    // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates>
    // for return value
    inline tAccessibleStates GetAllStates() const
    {
        return mnStates;
    }
    // <--
};

//------------------------------------------------------------------------------
typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl;

class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl
{
	sal_Bool mbFiring;

public:

    SwAccessibleEventList_Impl()
        : mbFiring( sal_False )
    {}

    inline void SetFiring()
    {
        mbFiring = sal_True;
    }
    inline sal_Bool IsFiring() const
    {
        return mbFiring;
    }
	struct XAccisNULL
	{
		bool operator()(const SwAccessibleEvent_Impl& e)
		{
			return e.IsNoXaccParentFrm();
		}
	};
	void MoveInvalidXAccToEnd();
};

void SwAccessibleEventList_Impl::MoveInvalidXAccToEnd()
{
	int nSize = size();
	if (nSize < 2 )
	{
		return;
	}
	SwAccessibleEventList_Impl lstEvent;
	iterator li = begin();
	for ( ;li != end();)
	{
		SwAccessibleEvent_Impl e = *li;
		if (e.IsNoXaccParentFrm())
		{
			iterator liNext = li;
			++liNext;
			erase(li);
			li = liNext;
			lstEvent.insert(lstEvent.end(),e);
		}
		else
			++li;
	}
	OSL_ENSURE(size() + lstEvent.size() == nSize ,"");
	insert(end(),lstEvent.begin(),lstEvent.end());
	OSL_ENSURE(size() == nSize ,"");
}
//------------------------------------------------------------------------------
// The shape list is filled if an accessible shape is destroyed. It
// simply keeps a reference to the accessible shape's XShape. These
// references are destroyed within the EndAction when firing events,
// There are twp reason for this. First of all, a new accessible shape
// for the XShape might be created soon. It's then cheaper if the XShape
// still exists. The other reason are situations where an accessible shape
// is destroyed within an SwFrmFmt::Modify. In this case, destryoing
// the XShape at the same time (indirectly by destroying the accessible
// shape) leads to an assert, because a client of the Modify is destroyed
// within a Modify call.

typedef ::std::list < uno::Reference < drawing::XShape > > _SwShapeList_Impl;

class SwShapeList_Impl: public _SwShapeList_Impl
{
public:

	SwShapeList_Impl() {}
};


//------------------------------------------------------------------------------
struct SwAccessibleChildFunc
{
    sal_Bool operator()( const SwAccessibleChild& r1,
                         const SwAccessibleChild& r2 ) const
	{
		const void *p1 = r1.GetSwFrm()
                         ? static_cast < const void * >( r1.GetSwFrm())
                         : ( r1.GetDrawObject()
                             ? static_cast < const void * >( r1.GetDrawObject() )
                             : static_cast < const void * >( r1.GetWindow() ) );
		const void *p2 = r2.GetSwFrm()
                         ? static_cast < const void * >( r2.GetSwFrm())
                         : ( r2.GetDrawObject()
                             ? static_cast < const void * >( r2.GetDrawObject() )
                             : static_cast < const void * >( r2.GetWindow() ) );
		return p1 < p2;
	}
};
typedef ::std::map < SwAccessibleChild, SwAccessibleEventList_Impl::iterator,
                     SwAccessibleChildFunc > _SwAccessibleEventMap_Impl;

class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl
{
};

//------------------------------------------------------------------------------
// --> OD 2005-12-13 #i27301# - map containing the accessible paragraph, which
// have a selection. Needed to keep this information to submit corresponding
// TEXT_SELECTION_CHANGED events.
struct SwAccessibleParaSelection
{
    xub_StrLen nStartOfSelection;
    xub_StrLen nEndOfSelection;

    SwAccessibleParaSelection( const xub_StrLen _nStartOfSelection,
                               const xub_StrLen _nEndOfSelection )
        : nStartOfSelection( _nStartOfSelection ),
          nEndOfSelection( _nEndOfSelection )
    {}
};

struct SwXAccWeakRefComp
{
    sal_Bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1,
                         const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const
    {
        return _rXAccWeakRef1.get() < _rXAccWeakRef2.get();
    }
};

typedef ::std::map< uno::WeakReference < XAccessible >,
                    SwAccessibleParaSelection,
                    SwXAccWeakRefComp > _SwAccessibleSelectedParas_Impl;

class SwAccessibleSelectedParas_Impl: public _SwAccessibleSelectedParas_Impl
{};
// <--

// helper class that stores preview data
class SwAccPreviewData
{
    typedef std::vector<Rectangle> Rectangles;
    Rectangles maPreviewRects;
    Rectangles maLogicRects;

    SwRect maVisArea;
    Fraction maScale;

    const SwPageFrm *mpSelPage;

    /** adjust logic page retangle to its visible part

        OD 17.01.2003 #103492#

        @author OD

        @param _iorLogicPgSwRect
        input/output parameter - reference to the logic page rectangle, which
        has to be adjusted.

        @param _rPrevwPgSwRect
        input parameter - constant reference to the corresponding preview page
        rectangle; needed to determine the visible part of the logic page rectangle.

        @param _rPrevwWinSize
        input parameter - constant reference to the preview window size in TWIP;
        needed to determine the visible part of the logic page rectangle
    */
    void AdjustLogicPgRectToVisibleArea( SwRect&         _iorLogicPgSwRect,
                                         const SwRect&   _rPrevwPgSwRect,
                                         const Size&     _rPrevwWinSize );

public:
    SwAccPreviewData();
    ~SwAccPreviewData();

    // OD 14.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    void Update( const SwAccessibleMap& rAccMap,
                 const std::vector<PrevwPage*>& _rPrevwPages,
                 const Fraction&  _rScale,
                 const SwPageFrm* _pSelectedPageFrm,
                 const Size&      _rPrevwWinSize );

    // OD 14.01.2003 #103492# - complete re-factoring of method due to new
    // page/print preview functionality.
    void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm );

    const SwRect& GetVisArea() const;

    MapMode GetMapModeForPreview( ) const;

    /** Adjust the MapMode so that the preview page appears at the
     * proper position. rPoint identifies the page for which the
     * MapMode should be adjusted. If bFromPreview is true, rPoint is
     * a preview coordinate; else it's a document coordinate. */
    // OD 17.01.2003 #103492# - delete unused 3rd parameter.
    void AdjustMapMode( MapMode& rMapMode,
                        const Point& rPoint ) const;

    inline const SwPageFrm *GetSelPage() const { return mpSelPage; }

    void DisposePage(const SwPageFrm *pPageFrm );
};

SwAccPreviewData::SwAccPreviewData() :
    mpSelPage( 0 )
{
}

SwAccPreviewData::~SwAccPreviewData()
{
}

// OD 13.01.2003 #103492# - complete re-factoring of method due to new page/print
// preview functionality.
void SwAccPreviewData::Update( const SwAccessibleMap& rAccMap,
                               const std::vector<PrevwPage*>& _rPrevwPages,
                               const Fraction&  _rScale,
                               const SwPageFrm* _pSelectedPageFrm,
                               const Size&      _rPrevwWinSize )
{
    // store preview scaling, maximal preview page size and selected page
    maScale = _rScale;
    mpSelPage = _pSelectedPageFrm;

    // prepare loop on preview pages
    maPreviewRects.clear();
    maLogicRects.clear();
    SwAccessibleChild aPage;
    maVisArea.Clear();

    // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and
    // <maVisArea>
    for ( std::vector<PrevwPage*>::const_iterator aPageIter = _rPrevwPages.begin();
          aPageIter != _rPrevwPages.end();
          ++aPageIter )
    {
        aPage = (*aPageIter)->pPage;

        // add preview page rectangle to <maPreviewRects>
        Rectangle aPrevwPgRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize );
        maPreviewRects.push_back( aPrevwPgRect );

        // add logic page rectangle to <maLogicRects>
        SwRect aLogicPgSwRect( aPage.GetBox( rAccMap ) );
        Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() );
        maLogicRects.push_back( aLogicPgRect );
        // union visible area with visible part of logic page rectangle
        if ( (*aPageIter)->bVisible )
        {
            if ( !(*aPageIter)->pPage->IsEmptyPage() )
            {
                AdjustLogicPgRectToVisibleArea( aLogicPgSwRect,
                                                SwRect( aPrevwPgRect ),
                                                _rPrevwWinSize );
            }
            if ( maVisArea.IsEmpty() )
                maVisArea = aLogicPgSwRect;
            else
                maVisArea.Union( aLogicPgSwRect );
        }
    }
}

// OD 16.01.2003 #103492# - complete re-factoring of method due to new page/print
// preview functionality.
void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm )
{
    mpSelPage = _pSelectedPageFrm;
    ASSERT( mpSelPage, "selected page not found" );
}

struct ContainsPredicate
{
    const Point& mrPoint;
    ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {}
    bool operator() ( const Rectangle& rRect ) const
    {
        return rRect.IsInside( mrPoint ) ? true : false;
    }
};

const SwRect& SwAccPreviewData::GetVisArea() const
{
    return maVisArea;
}

void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode,
                                      const Point& rPoint ) const
{
    // adjust scale
    rMapMode.SetScaleX( maScale );
    rMapMode.SetScaleY( maScale );

    // find proper rectangle
    Rectangles::const_iterator aBegin = maLogicRects.begin();
    Rectangles::const_iterator aEnd = maLogicRects.end();
    Rectangles::const_iterator aFound = ::std::find_if( aBegin, aEnd,
                                                 ContainsPredicate( rPoint ) );

    if( aFound != aEnd )
    {
        // found! set new origin
        Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft();
        aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft();
        rMapMode.SetOrigin( aPoint );
    }
    // else: don't adjust MapMode
}

void SwAccPreviewData::DisposePage(const SwPageFrm *pPageFrm )
{
    if( mpSelPage == pPageFrm )
        mpSelPage = 0;
}

/** adjust logic page retangle to its visible part

    OD 17.01.2003 #103492#

    @author OD
*/
void SwAccPreviewData::AdjustLogicPgRectToVisibleArea(
                            SwRect&         _iorLogicPgSwRect,
                            const SwRect&   _rPrevwPgSwRect,
                            const Size&     _rPrevwWinSize )
{
    // determine preview window rectangle
    const SwRect aPrevwWinSwRect( Point( 0, 0 ), _rPrevwWinSize );
    // calculate visible preview page rectangle
    SwRect aVisPrevwPgSwRect( _rPrevwPgSwRect );
    aVisPrevwPgSwRect.Intersection( aPrevwWinSwRect );
    // adjust logic page rectangle
    SwTwips nTmpDiff;
    // left
    nTmpDiff = aVisPrevwPgSwRect.Left() - _rPrevwPgSwRect.Left();
    if ( nTmpDiff > 0 )
        _iorLogicPgSwRect.Left( _iorLogicPgSwRect.Left() + nTmpDiff );
    // top
    nTmpDiff = aVisPrevwPgSwRect.Top() - _rPrevwPgSwRect.Top();
    if ( nTmpDiff > 0 )
        _iorLogicPgSwRect.Top( _iorLogicPgSwRect.Top() + nTmpDiff );
    // right
    nTmpDiff = _rPrevwPgSwRect.Right() - aVisPrevwPgSwRect.Right();
    if ( nTmpDiff > 0 )
        _iorLogicPgSwRect.Right( _iorLogicPgSwRect.Right() - nTmpDiff );
    // bottom
    nTmpDiff = _rPrevwPgSwRect.Bottom() - aVisPrevwPgSwRect.Bottom();
    if ( nTmpDiff > 0 )
        _iorLogicPgSwRect.Bottom( _iorLogicPgSwRect.Bottom() - nTmpDiff );
}

//------------------------------------------------------------------------------
static sal_Bool AreInSameTable( const uno::Reference< XAccessible >& rAcc,
					  		    const SwFrm *pFrm )
{
	sal_Bool bRet = sal_False;

	if( pFrm && pFrm->IsCellFrm() && rAcc.is() )
	{
		// Is it in the same table? We check that
		// by comparing the last table frame in the
		// follow chain, because that's cheaper than
		// searching the first one.
		SwAccessibleContext *pAccImpl =
			static_cast< SwAccessibleContext *>( rAcc.get() );
		if( pAccImpl->GetFrm()->IsCellFrm() )
		{
			const SwTabFrm *pTabFrm1 = pAccImpl->GetFrm()->FindTabFrm();
			while( pTabFrm1->GetFollow() )
				   pTabFrm1 = pTabFrm1->GetFollow();

			const SwTabFrm *pTabFrm2 = pFrm->FindTabFrm();
			while( pTabFrm2->GetFollow() )
				   pTabFrm2 = pTabFrm2->GetFollow();

			bRet = (pTabFrm1 == pTabFrm2);
		}
	}

	return bRet;
}

void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent )
{
	::vos::ORef < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
	if (!xAccImpl.isValid() && rEvent.mpParentFrm != 0 )
	{
		SwAccessibleContextMap_Impl::iterator aIter =
			mpFrmMap->find( rEvent.mpParentFrm );
		if( aIter != mpFrmMap->end() )
		{
			uno::Reference < XAccessible > xAcc( (*aIter).second );
			if (xAcc.is())
			{
				uno::Reference < XAccessibleContext >  xContext(xAcc,uno::UNO_QUERY);
				if (xContext.is() && xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
				{
					xAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
				}
			}			
		}
	}
	if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() )
	{
		DoInvalidateShapeSelection();
	}
	else if( xAccImpl.isValid() && xAccImpl->GetFrm() )
	{
        // --> OD 2009-01-07 #i88069#
        if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE &&
             rEvent.IsInvalidateTextAttrs() )
        {
            xAccImpl->InvalidateAttr();
        }
        // <--
		switch( rEvent.GetType() )
		{
		case SwAccessibleEvent_Impl::INVALID_CONTENT:
			xAccImpl->InvalidateContent();
			break;
		case SwAccessibleEvent_Impl::POS_CHANGED:
			xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() );
			break;
		case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
			xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrmOrObj(),
									   rEvent.GetOldBox() );
			break;
		case SwAccessibleEvent_Impl::DISPOSE:
			ASSERT( xAccImpl.isValid(),
					"dispose event has been stored" );
			break;
        // --> OD 2009-01-06 #i88069#
        case SwAccessibleEvent_Impl::INVALID_ATTR:
            // nothing to do here - handled above
            break;
        // <--
		default:
			break;
		}
		if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
		{
			if( rEvent.IsUpdateCursorPos() )
				xAccImpl->InvalidateCursorPos();
			if( rEvent.IsInvalidateStates() )
				xAccImpl->InvalidateStates( rEvent.GetStates() );
            if( rEvent.IsInvalidateRelation() )
            {
                // --> OD 2005-12-01 #i27138#
                // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and
                // CONTENT_FLOWS_TO_RELATION_CHANGED are possible
                if ( rEvent.GetAllStates() & ACC_STATE_RELATION_FROM )
                {
                    xAccImpl->InvalidateRelation(
                        AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED );
                }
                if ( rEvent.GetAllStates() & ACC_STATE_RELATION_TO )
                {
                    xAccImpl->InvalidateRelation(
                        AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
                }
                // <--
            }
            // --> OD 2005-12-12 #i27301# - submit event TEXT_SELECTION_CHANGED
            if ( rEvent.IsInvalidateTextSelection() )
            {
                xAccImpl->InvalidateTextSelection();
            }
            // <--
		}
	}
}

void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
{
	vos::OGuard aGuard( maEventMutex );

	if( !mpEvents )
		mpEvents = new SwAccessibleEventList_Impl;
	if( !mpEventMap )
		mpEventMap = new SwAccessibleEventMap_Impl;

	if( mpEvents->IsFiring() )
	{
		// While events are fired new ones are generated. They have to be fired
		// now. This does not work for DISPOSE events!
		ASSERT( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
				"dispose event while firing events" );
		FireEvent( rEvent );
	}
	else
	{

		SwAccessibleEventMap_Impl::iterator aIter =
                                        mpEventMap->find( rEvent.GetFrmOrObj() );
		if( aIter != mpEventMap->end() )
		{
			SwAccessibleEvent_Impl aEvent( *(*aIter).second );
			ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
					"dispose events should not be stored" );
			sal_Bool bAppendEvent = sal_True;
			switch( rEvent.GetType() )
			{
			case SwAccessibleEvent_Impl::CARET_OR_STATES:
				// A CARET_OR_STATES event is added to any other
				// event only. It is broadcasted after any other event, so the
				// event should be put to the back.
                ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
						"invalid event combination" );
				aEvent.SetStates( rEvent.GetAllStates() );
				break;
			case SwAccessibleEvent_Impl::INVALID_CONTENT:
				// An INVALID_CONTENT event overwrites a CARET_OR_STATES
				// event (but keeps its flags) and it is contained in a
				// POS_CHANGED event.
				// Therefor, the event's type has to be adapted and the event
				// has to be put at the end.
                ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
						"invalid event combination" );
                if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES )
					aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
				break;
			case SwAccessibleEvent_Impl::POS_CHANGED:
				// A pos changed event overwrites CARET_STATES (keeping its
				// flags) as well as INVALID_CONTENT. The old box position
				// has to be stored however if the old event is not a
				// POS_CHANGED itself.
                ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
						"invalid event combination" );
				if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED )
					aEvent.SetOldBox( rEvent.GetOldBox() );
				aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED );
				break;
			case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
				// CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED
				// events. The only action that needs to be done again is
				// to put the old event to the back. The new one cannot be used,
				// because we are interested in the old frame bounds.
                ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
						"invalid event combination" );
				break;
			case SwAccessibleEvent_Impl::SHAPE_SELECTION:
                ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION,
						"invalid event combination" );
				break;
			case SwAccessibleEvent_Impl::DISPOSE:
				// DISPOSE events overwrite all others. They are not stored
				// but executed immediately to avoid broadcasting of
				// defunctional objects. So what needs to be done here is to
				// remove all events for the frame in question.
				bAppendEvent = sal_False;
				break;
            // --> OD 2009-01-06 #i88069#
            case SwAccessibleEvent_Impl::INVALID_ATTR:
                ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR,
                        "invalid event combination" );
                break;
            // <--
			}
			if( bAppendEvent )
			{
				mpEvents->erase( (*aIter).second );
				(*aIter).second = mpEvents->insert( mpEvents->end(), aEvent );
			}
			else
			{
				mpEvents->erase( (*aIter).second );
				mpEventMap->erase( aIter );
			}
		}
		else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
		{
			SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrmOrObj(),
					mpEvents->insert( mpEvents->end(), rEvent ) );
			mpEventMap->insert( aEntry );
		}
	}
}

void SwAccessibleMap::InvalidateCursorPosition(
		const uno::Reference< XAccessible >& rAcc )
{
	SwAccessibleContext *pAccImpl =
		static_cast< SwAccessibleContext *>( rAcc.get() );
	ASSERT( pAccImpl, "no caret context" );
	ASSERT( pAccImpl->GetFrm(), "caret context is disposed" );
	if( GetShell()->ActionPend() )
	{
        SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
                                       pAccImpl,
                                       SwAccessibleChild(pAccImpl->GetFrm()),
                                       ACC_STATE_CARET );
		AppendEvent( aEvent );
	}
	else
	{
		FireEvents();
		// While firing events the current frame might have
		// been disposed because it moved out of the vis area.
		// Setting the cursor for such frames is useless and even
		// causes asserts.
		if( pAccImpl->GetFrm() )
			pAccImpl->InvalidateCursorPos();
	}
}

void SwAccessibleMap::InvalidateShapeSelection()
{
	if( GetShell()->ActionPend() )
	{
		SwAccessibleEvent_Impl aEvent(
			SwAccessibleEvent_Impl::SHAPE_SELECTION );
		AppendEvent( aEvent );
	}
	else
	{
		FireEvents();
		DoInvalidateShapeSelection();
	}
}
//This method should implement the following functions:
//1.find the shape objects and set the selected state.
//2.find the Swframe objects and set the selected state.
//3.find the paragraph objects and set the selected state.
void SwAccessibleMap::InvalidateShapeInParaSelection()
{
	SwAccessibleObjShape_Impl *pShapes = 0;
	SwAccessibleObjShape_Impl *pSelShape = 0;
	size_t nShapes = 0;

	const ViewShell *pVSh = GetShell();
	const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
							static_cast< const SwFEShell * >( pVSh ) : 0;
	SwPaM* pCrsr = pFESh ? pFESh->GetCrsr( sal_False /* ??? */ ) : NULL;
	//sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;

	{
		vos::OGuard aGuard( maMutex );
		if( mpShapeMap )
			pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
	}
	
	sal_Bool bIsSelAll =IsDocumentSelAll();
	
	if( mpShapeMap )
	{
		//Checked for shapes.
		_SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
		_SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
		::vos::ORef< SwAccessibleContext > xParentAccImpl;

		if( bIsSelAll)
		{
			while( aIter != aEndIter )
			{
				uno::Reference < XAccessible > xAcc( (*aIter).second );
				if( xAcc.is() )
					(static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED );
				
				++aIter;
			}	
		}
		else
		{
			while( aIter != aEndIter )
			{
				sal_Bool bChanged = sal_False;
				sal_Bool bMarked = sal_False;
				SwAccessibleChild pFrm( (*aIter).first );
				
				const SwFrmFmt *pFrmFmt = (*aIter).first ? ::FindFrmFmt( (*aIter).first ) : 0;
				if( !pFrmFmt ) { ++aIter; continue; }
				const SwFmtAnchor& pAnchor = pFrmFmt->GetAnchor();
				const SwPosition *pPos = pAnchor.GetCntntAnchor();
				
				if(pAnchor.GetAnchorId() == FLY_AT_PAGE)
				{
					uno::Reference < XAccessible > xAcc( (*aIter).second );
					if(xAcc.is())
						(static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
					
					++aIter; continue;
				}
				
				if( !pPos ) { ++aIter; continue; } 
				if( pPos->nNode.GetNode().GetTxtNode() )
				{
					int pIndex = pPos->nContent.GetIndex();
					SwPaM* pTmpCrsr = pCrsr;
					if( pTmpCrsr != NULL )
					{
						const SwTxtNode* pNode = pPos->nNode.GetNode().GetTxtNode();
						sal_uLong nHere = pNode->GetIndex();
						
						do
						{
							// ignore, if no mark
							if( pTmpCrsr->HasMark() )
							{
								bMarked = sal_True;
								// check whether nHere is 'inside' pCrsr
								SwPosition* pStart = pTmpCrsr->Start();
								sal_uLong nStartIndex = pStart->nNode.GetIndex();
								SwPosition* pEnd = pTmpCrsr->End();
								sal_uLong nEndIndex = pEnd->nNode.GetIndex();
								if( ( nHere >= nStartIndex ) && (nHere <= nEndIndex)  )
								{
									if( pAnchor.GetAnchorId() == FLY_AS_CHAR )
									{
										if( ( (nHere == nStartIndex) && (pIndex >= pStart->nContent.GetIndex()) || (nHere > nStartIndex) )
											&&( (nHere == nEndIndex) && (pIndex < pEnd->nContent.GetIndex()) || (nHere < nEndIndex) ) )
										{
											uno::Reference < XAccessible > xAcc( (*aIter).second );
											if( xAcc.is() )
												bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED );
										}
										else
										{
											uno::Reference < XAccessible > xAcc( (*aIter).second );
											if( xAcc.is() )
												bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
										}
									}
									else if( pAnchor.GetAnchorId() == FLY_AT_PARA )
									{
										if( ((nHere > nStartIndex) || pStart->nContent.GetIndex() ==0 )
											&& (nHere < nEndIndex ) )
										{
											uno::Reference < XAccessible > xAcc( (*aIter).second );
											if( xAcc.is() )
												bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED );
										}
										else
										{
											uno::Reference < XAccessible > xAcc( (*aIter).second );
											if(xAcc.is()) 
												bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
										}
									}
								}
							}
							// next PaM in ring
							pTmpCrsr = static_cast<SwPaM*>( pTmpCrsr->GetNext() );
						}
						while( pTmpCrsr != pCrsr );
					}
					if( !bMarked )
					{
						SwAccessibleObjShape_Impl  *pShape = pShapes;
						size_t nNumShapes = nShapes;
						while( nNumShapes )
						{
							if( pShape < pSelShape && (pShape->first==(*aIter).first) )
							{
								uno::Reference < XAccessible > xAcc( (*aIter).second );
								if(xAcc.is())
									bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
							}
							--nNumShapes;
							++pShape;
						}
					}
				}
				++aIter;
			}//while( aIter != aEndIter )
		}//else
	}
	
	//Checked for FlyFrm
	SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
	while( aIter != mpFrmMap->end() )
	{
		const SwFrm *pFrm = (*aIter).first;
		if(pFrm->IsFlyFrm())
		{
			sal_Bool bFrmChanged = sal_False;
			uno::Reference < XAccessible > xAcc = (*aIter).second;
			
			if(xAcc.is())
			{
				SwAccessibleFrameBase *pAccFrame = (static_cast< SwAccessibleFrameBase * >(xAcc.get()));
				bFrmChanged = pAccFrame->SetSelectedState( sal_True );
				if (bFrmChanged)
				{
					const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( pFrm );
					const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
					if (pFrmFmt)
					{
						const SwFmtAnchor& pAnchor = pFrmFmt->GetAnchor();
						if( pAnchor.GetAnchorId() == FLY_AS_CHAR )
						{
							uno::Reference< XAccessible > xAccParent = pAccFrame->getAccessibleParent();
							if (xAccParent.is())
							{
								uno::Reference< XAccessibleContext > xAccContext = xAccParent->getAccessibleContext();
								if(xAccContext.is() && xAccContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
								{
									SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xAccContext.get());
									if(pAccFrame->IsSeletedInDoc())
									{
										m_setParaAdd.insert(pAccPara);
									}
									else if(m_setParaAdd.count(pAccPara) == 0)
									{
										m_setParaRemove.insert(pAccPara);
									}
								}
							}
						}
					}
                }
			}
		}
		++aIter;
	}
	typedef std::vector< SwAccessibleContext* > VEC_PARA;
	VEC_PARA vecAdd;
	VEC_PARA vecRemove;
	//Checked for Paras.
	SwPaM* pTmpCrsr = pCrsr;
	sal_Bool bMarkChanged = sal_False;
	SwAccessibleContextMap_Impl mapTemp;
	if( pTmpCrsr != NULL )
	{
		do
		{
			if( pTmpCrsr->HasMark() )
			{
				SwNodeIndex nStartIndex( pTmpCrsr->Start()->nNode );
				SwNodeIndex nEndIndex( pTmpCrsr->End()->nNode );
				while(nStartIndex <= nEndIndex)
				{
					SwFrm *pFrm = NULL;
					if(nStartIndex.GetNode().IsCntntNode())
					{	
						SwCntntNode* pCNd = (SwCntntNode*)&(nStartIndex.GetNode());
						SwClientIter aClientIter( *pCNd );
						pFrm = (SwFrm*)aClientIter.First( TYPE(SwFrm));
					}
					else if( nStartIndex.GetNode().IsTableNode() )
					{
						SwTableNode * pTable= (SwTableNode *)&(nStartIndex.GetNode());
						SwFrmFmt* pFmt = const_cast<SwFrmFmt*>(pTable->GetTable().GetFrmFmt());
						SwClientIter aClientIter( *pFmt );
						pFrm = (SwFrm*)aClientIter.First( TYPE(SwFrm));
					}
					
                    if( pFrm && mpFrmMap)
					{
						aIter = mpFrmMap->find( pFrm );
						if( aIter != mpFrmMap->end() )
						{
							uno::Reference < XAccessible > xAcc = (*aIter).second;
							sal_Bool isChanged = sal_False;
							if( xAcc.is() )
							{
								isChanged = (static_cast< SwAccessibleContext * >(xAcc.get()))->SetSelectedState( sal_True );
							}
							if(!isChanged)
							{
								SwAccessibleContextMap_Impl::iterator aEraseIter = mpSeletedFrmMap->find( pFrm );
								if(aEraseIter != mpSeletedFrmMap->end())
									mpSeletedFrmMap->erase(aEraseIter);
							}
							else
							{
								bMarkChanged = sal_True;
								vecAdd.push_back(static_cast< SwAccessibleContext * >(xAcc.get()));
							}
							
							mapTemp.insert( SwAccessibleContextMap_Impl::value_type( pFrm, xAcc ) );
						}
					}
					nStartIndex++;
				}
			}
			pTmpCrsr = static_cast<SwPaM*>( pTmpCrsr->GetNext() );
		}
		while( pTmpCrsr != pCrsr );
	}
	if( !mpSeletedFrmMap )
		mpSeletedFrmMap = new SwAccessibleContextMap_Impl;
	if( !mpSeletedFrmMap->empty() )
	{
		aIter = mpSeletedFrmMap->begin();
		while( aIter != mpSeletedFrmMap->end() )
		{
			uno::Reference < XAccessible > xAcc = (*aIter).second;
			if(xAcc.is())
				(static_cast< SwAccessibleContext * >(xAcc.get()))->SetSelectedState( sal_False );
			++aIter;
			vecRemove.push_back(static_cast< SwAccessibleContext * >(xAcc.get()));
		}
		bMarkChanged = sal_True;
		mpSeletedFrmMap->clear();
	}
	
	if( !mapTemp.empty() )
	{
		aIter = mapTemp.begin();
		while( aIter != mapTemp.end() )
		{
			mpSeletedFrmMap->insert( SwAccessibleContextMap_Impl::value_type( (*aIter).first, (*aIter).second ) );
			++aIter;
		}
		mapTemp.clear();
	}
	if( bMarkChanged && mpFrmMap)
	{
		VEC_PARA::iterator vi = vecAdd.begin();
		for (; vi != vecAdd.end() ; ++vi)
		{
			AccessibleEventObject aEvent;
			aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
			SwAccessibleContext* pAccPara = *vi;
			if (pAccPara)
			{
				pAccPara->FireAccessibleEvent( aEvent );
			}			
		}
		vi = vecRemove.begin();
		for (; vi != vecRemove.end() ; ++vi)
		{
			AccessibleEventObject aEvent;
			aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
			SwAccessibleContext* pAccPara = *vi;
			if (pAccPara)
			{
				pAccPara->FireAccessibleEvent( aEvent );
			}			
		}
	}
}

//Marge with DoInvalidateShapeFocus
void SwAccessibleMap::DoInvalidateShapeSelection(sal_Bool bInvalidateFocusMode /*=sal_False*/)
{
	SwAccessibleObjShape_Impl *pShapes = 0;
	SwAccessibleObjShape_Impl *pSelShape = 0;
	size_t nShapes = 0;

	const ViewShell *pVSh = GetShell();
	const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
							static_cast< const SwFEShell * >( pVSh ) : 0;
	sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
	

	//when InvalidateFocus Call this function ,and the current selected shape count is not 1 ,
	//return 
	if (bInvalidateFocusMode && nSelShapes != 1)
	{
		return;
	}
	{
		vos::OGuard aGuard( maMutex );
		if( mpShapeMap )
			pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
	}

	if( pShapes )
	{
		typedef std::vector< ::vos::ORef < ::accessibility::AccessibleShape >  >  VEC_SHAPE;
		VEC_SHAPE vecxShapeAdd;
		VEC_SHAPE vecxShapeRemove;
		int nCountSelectedShape=0;

		Window *pWin = GetShell()->GetWin();
		sal_Bool bFocused = pWin && pWin->HasFocus();
		SwAccessibleObjShape_Impl *pShape = pShapes;
		int nShapeCount = nShapes;
		while( nShapeCount )
		{
			//if( pShape->second.isValid() )
			if (pShape->second.isValid() && IsInSameLevel(pShape->first, pFESh))
				{
				if( pShape < pSelShape )
				{
					if(pShape->second->ResetState( AccessibleStateType::SELECTED ))
					{
						vecxShapeRemove.push_back(pShape->second);
					}
					pShape->second->ResetState( AccessibleStateType::FOCUSED );
				}
			}
			--nShapeCount;
			++pShape;
		}

		VEC_SHAPE::iterator vi =vecxShapeRemove.begin();
		for (; vi != vecxShapeRemove.end(); ++vi)
		{
			::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr());
			if (pAccShape)
			{
				pAccShape->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE, uno::Any(), uno::Any());
			}
		}

		pShape = pShapes;
		while( nShapes )
		{
			//if( pShape->second.isValid() )
			if (pShape->second.isValid() && IsInSameLevel(pShape->first, pFESh))
			{
				// IA2 - why?
				// sal_Bool bChanged;
				if( pShape >= pSelShape )
				{
					// IA2: first fire focus event
					// bChanged = pShape->second->SetState( AccessibleStateType::SELECTED );					

					//first fire focus event
					if( bFocused && 1 == nSelShapes )
						pShape->second->SetState( AccessibleStateType::FOCUSED );
					else
						pShape->second->ResetState( AccessibleStateType::FOCUSED );

					if(pShape->second->SetState( AccessibleStateType::SELECTED ))
					{
						vecxShapeAdd.push_back(pShape->second);
					}
					++nCountSelectedShape;
				}
				/* MT: This still was in DEV300m80, but was removed in IA2 CWS.
				   Someone needs to check what should happen here, see original diff CWS oo31ia2 vs. OOO310M11
				else
				{
					bChanged =
						pShape->second->ResetState( AccessibleStateType::SELECTED );
					pShape->second->ResetState( AccessibleStateType::FOCUSED );
				}
				if( bChanged )
				{
                    const SwFrm* pParent = SwAccessibleFrame::GetParent(
                                                    SwAccessibleChild( pShape->first ),
                                                    GetShell()->IsPreView() );
                    aParents.push_back( pParent );
				}
				*/
			}

			--nShapes;
			++pShape;
		}

		const unsigned int SELECTION_WITH_NUM = 10;
		if (vecxShapeAdd.size() > SELECTION_WITH_NUM )
		{
			uno::Reference< XAccessible > xDoc = GetDocumentView( );
			 SwAccessibleContext * pCont = static_cast<SwAccessibleContext *>(xDoc.get());
			 if (pCont)
			 {
				 AccessibleEventObject aEvent;
				 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
				 pCont->FireAccessibleEvent(aEvent);
			 }
		}
		else
		{
			short nEventID = AccessibleEventId::SELECTION_CHANGED_ADD;
			if (nCountSelectedShape <= 1 && vecxShapeAdd.size() == 1 )
			{
				nEventID = AccessibleEventId::SELECTION_CHANGED;
			}
			vi = vecxShapeAdd.begin();
			for (; vi != vecxShapeAdd.end(); ++vi)
			{
				::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr());
				if (pAccShape)
				{
					pAccShape->CommitChange(nEventID, uno::Any(), uno::Any());
				}				
			}
		}

		vi = vecxShapeAdd.begin();
		for (; vi != vecxShapeAdd.end(); ++vi)
		{
			::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr());
			if (pAccShape)
			{
				SdrObject *pObj = GetSdrObjectFromXShape(pAccShape->GetXShape());
				SwFrmFmt *pFrmFmt = pObj ? FindFrmFmt( pObj ) : NULL;
				if (pFrmFmt)
				{
					const SwFmtAnchor& pAnchor = pFrmFmt->GetAnchor();
					if( pAnchor.GetAnchorId() == FLY_AS_CHAR )
					{
						uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent();
						if (xPara.is())
						{
							uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext();
							if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
							{
								SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get());
								if (pAccPara)
								{
									m_setParaAdd.insert(pAccPara);
								}
							}
						}
					}
				}
			}
		}
		vi = vecxShapeRemove.begin();
		for (; vi != vecxShapeRemove.end(); ++vi)
		{
			::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr());
			if (pAccShape)
			{
				uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent();
				uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext();
				if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
				{
					SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get());
					if (m_setParaAdd.count(pAccPara) == 0 )
					{
						m_setParaRemove.insert(pAccPara);
					}
				}
			}
		}		
		delete[] pShapes;
	}
}

//Marge with DoInvalidateShapeSelection
/*
void SwAccessibleMap::DoInvalidateShapeFocus()
{
	const ViewShell *pVSh = GetShell();
	const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
							static_cast< const SwFEShell * >( pVSh ) : 0;
	sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;

	if( nSelShapes != 1 )
		return;

	SwAccessibleObjShape_Impl *pShapes = 0;
	SwAccessibleObjShape_Impl *pSelShape = 0;
	size_t nShapes = 0;


	{
		vos::OGuard aGuard( maMutex );
		if( mpShapeMap )
			pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
	}

	if( pShapes )
	{
		Window *pWin = GetShell()->GetWin();
		sal_Bool bFocused = pWin && pWin->HasFocus();
		SwAccessibleObjShape_Impl  *pShape = pShapes;
		while( nShapes )
		{
			if( pShape->second.isValid() )
			{
				if( bFocused && pShape >= pSelShape )
					pShape->second->SetState( AccessibleStateType::FOCUSED );
				else
					pShape->second->ResetState( AccessibleStateType::FOCUSED );
			}

			--nShapes;
			++pShape;
		}

		delete[] pShapes;
	}
}
*/

SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) :
	mpFrmMap( 0  ),
	mpShapeMap( 0  ),
	mpShapes( 0  ),
	mpEvents( 0  ),
	mpEventMap( 0  ),
    // --> OD 2005-12-13 #i27301#
    mpSelectedParas( 0 ),
    // <--
	mpVSh( pSh ),
    	mpPreview( 0 ),
	mnPara( 1 ),
	mnFootnote( 1 ),
	mnEndnote( 1 ),
	mbShapeSelected( sal_False ),
	mpSeletedFrmMap(NULL)
{
	pSh->GetLayout()->AddAccessibleShell();
}

SwAccessibleMap::~SwAccessibleMap()
{
	uno::Reference < XAccessible > xAcc;
	{
		vos::OGuard aGuard( maMutex );
		if( mpFrmMap )
		{
			const SwRootFrm *pRootFrm = GetShell()->GetLayout();
			SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
			if( aIter != mpFrmMap->end() )
				xAcc = (*aIter).second;
			if( !xAcc.is() )
				xAcc = new SwAccessibleDocument( this );
		}
	}

	if(xAcc.is())
	{
	SwAccessibleDocument *pAcc =
		static_cast< SwAccessibleDocument * >( xAcc.get() );
	pAcc->Dispose( sal_True );
	}
	if( mpFrmMap )
	{
		SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
		while( aIter != mpFrmMap->end() )
		{
			uno::Reference < XAccessible > xTmp = (*aIter).second;
			if( xTmp.is() )
			{
				SwAccessibleContext *pTmp = static_cast< SwAccessibleContext * >( xTmp.get() );
				pTmp->SetMap(NULL);
			}
			++aIter;
		}
	}
	{
		vos::OGuard aGuard( maMutex );
#ifdef DBG_UTIL
		ASSERT( !mpFrmMap || mpFrmMap->empty(),
				"Frame map should be empty after disposing the root frame" );
		if( mpFrmMap )
		{
			SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
			while( aIter != mpFrmMap->end() )
			{
				uno::Reference < XAccessible > xTmp = (*aIter).second;
				if( xTmp.is() )
				{
					SwAccessibleContext *pTmp =
						static_cast< SwAccessibleContext * >( xTmp.get() );
					(void) pTmp;
				}
				++aIter;
			}
		}
		ASSERT( !mpShapeMap || mpShapeMap->empty(),
				"Object map should be empty after disposing the root frame" );
		if( mpShapeMap )
		{
			SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->begin();
			while( aIter != mpShapeMap->end() )
			{
				uno::Reference < XAccessible > xTmp = (*aIter).second;
				if( xTmp.is() )
				{
					::accessibility::AccessibleShape *pTmp =
						static_cast< ::accessibility::AccessibleShape* >( xTmp.get() );
					(void) pTmp;
				}
				++aIter;
			}
		}
#endif
		delete mpFrmMap;
		mpFrmMap = 0;
		delete mpShapeMap;
		mpShapeMap = 0;
		delete mpShapes;
		mpShapes = 0;
        // --> OD 2005-12-13 #i27301#
        delete mpSelectedParas;
        mpSelectedParas = 0;
        // <--
	}

	delete mpPreview;
	mpPreview = NULL;

    {
		vos::OGuard aGuard( maEventMutex );
#ifdef DBG_UTIL
		ASSERT( !(mpEvents || mpEventMap), "pending events" );
		if( mpEvents )
		{
			SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
			while( aIter != mpEvents->end() )
			{
				++aIter;
			}
		}
		if( mpEventMap )
		{
			SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->begin();
			while( aIter != mpEventMap->end() )
			{
				++aIter;
			}
		}
#endif
		delete mpEventMap;
		mpEventMap = 0;
		delete mpEvents;
		mpEvents = 0;
	}
	mpVSh->GetLayout()->RemoveAccessibleShell();
	delete mpSeletedFrmMap;
}

uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView(
    sal_Bool bPagePreview )
{
	uno::Reference < XAccessible > xAcc;
	sal_Bool bSetVisArea = sal_False;

	{
		vos::OGuard aGuard( maMutex );

		if( !mpFrmMap )
		{
			mpFrmMap = new SwAccessibleContextMap_Impl;
#ifdef DBG_UTIL
			mpFrmMap->mbLocked = sal_False;
#endif
		}

#ifdef DBG_UTIL
		ASSERT( !mpFrmMap->mbLocked, "Map is locked" );
		mpFrmMap->mbLocked = sal_True;
#endif

		const SwRootFrm *pRootFrm = GetShell()->GetLayout();
		SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
		if( aIter != mpFrmMap->end() )
			xAcc = (*aIter).second;
		if( xAcc.is() )
		{
			bSetVisArea = sal_True; // Set VisArea when map mutex is not
									// locked
		}
		else
		{
            if( bPagePreview )
                xAcc = new SwAccessiblePreview( this );
            else
                xAcc = new SwAccessibleDocument( this );

			if( aIter != mpFrmMap->end() )
			{
				(*aIter).second = xAcc;
			}
			else
			{
				SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc );
				mpFrmMap->insert( aEntry );
			}
		}

#ifdef DBG_UTIL
		mpFrmMap->mbLocked = sal_False;
#endif
	}

	if( bSetVisArea )
	{
		SwAccessibleDocumentBase *pAcc =
			static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
		pAcc->SetVisArea();
	}

	return xAcc;
}

uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( )
{
    return _GetDocumentView( sal_False );
}

// OD 14.01.2003 #103492# - complete re-factoring of method due to new page/print
// preview functionality.
uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview(
                                    const std::vector<PrevwPage*>& _rPrevwPages,
                                    const Fraction&  _rScale,
                                    const SwPageFrm* _pSelectedPageFrm,
                                    const Size&      _rPrevwWinSize )
{
    // create & update preview data object
    if( mpPreview == NULL )
        mpPreview = new SwAccPreviewData();
    mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );

    uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True );
    return xAcc;
}

uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm,
												     sal_Bool bCreate )
{
	uno::Reference < XAccessible > xAcc;
	uno::Reference < XAccessible > xOldCursorAcc;
	sal_Bool bOldShapeSelected = sal_False;

	{
		vos::OGuard aGuard( maMutex );

		if( !mpFrmMap && bCreate )
			mpFrmMap = new SwAccessibleContextMap_Impl;
		if( mpFrmMap )
		{
			SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm );
			if( aIter != mpFrmMap->end() )
				xAcc = (*aIter).second;

			if( !xAcc.is() && bCreate )
			{
				SwAccessibleContext *pAcc = 0;
				switch( pFrm->GetType() )
				{
				case FRM_TXT:
                    mnPara++;
                    pAcc = new SwAccessibleParagraph( *this,
                                    static_cast< const SwTxtFrm& >( *pFrm ) );
					break;
				case FRM_HEADER:
					pAcc = new SwAccessibleHeaderFooter( this,
									static_cast< const SwHeaderFrm *>( pFrm ) );
					break;
				case FRM_FOOTER:
					pAcc = new SwAccessibleHeaderFooter( this,
									static_cast< const SwFooterFrm *>( pFrm ) );
					break;
				case FRM_FTN:
					{
						const SwFtnFrm *pFtnFrm =
							static_cast < const SwFtnFrm * >( pFrm );
						sal_Bool bIsEndnote =
							SwAccessibleFootnote::IsEndnote( pFtnFrm );
						pAcc = new SwAccessibleFootnote( this, bIsEndnote,
									/*(bIsEndnote ? mnEndnote++ : mnFootnote++),*/
									pFtnFrm );
					}
					break;
				case FRM_FLY:
					{
						const SwFlyFrm *pFlyFrm =
							static_cast < const SwFlyFrm * >( pFrm );
						switch( SwAccessibleFrameBase::GetNodeType( pFlyFrm ) )
						{
						case ND_GRFNODE:
							pAcc = new SwAccessibleGraphic( this, pFlyFrm );
							break;
						case ND_OLENODE:
							pAcc = new SwAccessibleEmbeddedObject( this, pFlyFrm );
							break;
						default:
							pAcc = new SwAccessibleTextFrame( this, pFlyFrm );
							break;
						}
					}
					break;
				case FRM_CELL:
					pAcc = new SwAccessibleCell( this,
									static_cast< const SwCellFrm *>( pFrm ) );
					break;
				case FRM_TAB:
                    pAcc = new SwAccessibleTable( this,
									static_cast< const SwTabFrm *>( pFrm ) );
					break;
                case FRM_PAGE:
                    DBG_ASSERT( GetShell()->IsPreView(),
                                "accessible page frames only in PagePreview" );
                    pAcc = new SwAccessiblePage( this, pFrm );
                    break;
				}
				xAcc = pAcc;

				ASSERT( xAcc.is(), "unknown frame type" );
				if( xAcc.is() )
				{
					if( aIter != mpFrmMap->end() )
					{
						(*aIter).second = xAcc;
					}
					else
					{
						SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc );
						mpFrmMap->insert( aEntry );
					}

					if( pAcc->HasCursor() &&
						!AreInSameTable( mxCursorContext, pFrm ) )
					{
						// If the new context has the focus, and if we know
						// another context that had the focus, then the focus
						// just moves from the old context to the new one. We
						// have to send a focus event and a caret event for
						// the old context then. We have to to that know,
						// because after we have left this method, anyone might
						// call getStates for the new context and will get a
						// focused state then. Sending the focus changes event
						// after that seems to be strange. However, we cannot
						// send a focus event fo the new context now, because
					    // no one except us knows it. In any case, we remember
						// the new context as the one that has the focus
						// currently.

						xOldCursorAcc = mxCursorContext;
						mxCursorContext = xAcc;

						bOldShapeSelected = mbShapeSelected;
						mbShapeSelected = sal_False;
					}
				}
			}
		}
	}

	// Invalidate focus for old object when map is not locked
	if( xOldCursorAcc.is() )
		InvalidateCursorPosition( xOldCursorAcc );
	if( bOldShapeSelected )
		InvalidateShapeSelection();

	return xAcc;
}

::vos::ORef < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
			const SwFrm *pFrm,
			sal_Bool bCreate )
{
	uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) );

	::vos::ORef < SwAccessibleContext > xAccImpl(
		 static_cast< SwAccessibleContext * >( xAcc.get() ) );

	return xAccImpl;
}

uno::Reference< XAccessible> SwAccessibleMap::GetContext(
		const SdrObject *pObj,
		SwAccessibleContext *pParentImpl,
		sal_Bool bCreate )
{
	uno::Reference < XAccessible > xAcc;
	uno::Reference < XAccessible > xOldCursorAcc;

	{
		vos::OGuard aGuard( maMutex );

		if( !mpShapeMap && bCreate )
			mpShapeMap = new SwAccessibleShapeMap_Impl( this );
		if( mpShapeMap )
		{
			SwAccessibleShapeMap_Impl::iterator aIter =
			   	mpShapeMap->find( pObj );
			if( aIter != mpShapeMap->end() )
				xAcc = (*aIter).second;

			if( !xAcc.is() && bCreate )
			{
				::accessibility::AccessibleShape *pAcc = 0;
				uno::Reference < drawing::XShape > xShape(
					const_cast< SdrObject * >( pObj )->getUnoShape(),
					uno::UNO_QUERY );
				if( xShape.is() )
				{
					::accessibility::ShapeTypeHandler& rShapeTypeHandler =
								::accessibility::ShapeTypeHandler::Instance();
					uno::Reference < XAccessible > xParent( pParentImpl );
					::accessibility::AccessibleShapeInfo aShapeInfo(
							xShape, xParent, this );

					pAcc = rShapeTypeHandler.CreateAccessibleObject(
								aShapeInfo, mpShapeMap->GetInfo() );
				}
				xAcc = pAcc;

				ASSERT( xAcc.is(), "unknown shape type" );
				if( xAcc.is() )
				{
					pAcc->Init();
					if( aIter != mpShapeMap->end() )
					{
						(*aIter).second = xAcc;
					}
					else
					{
						SwAccessibleShapeMap_Impl::value_type aEntry( pObj,
																	  xAcc );
						mpShapeMap->insert( aEntry );
					}
					// TODO: focus!!!
				}
				if (xAcc.is())
					AddGroupContext(pObj, xAcc);
			}
		}
	}

	// Invalidate focus for old object when map is not locked
	if( xOldCursorAcc.is() )
		InvalidateCursorPosition( xOldCursorAcc );

	return xAcc;
}
sal_Bool SwAccessibleMap::IsInSameLevel(const SdrObject* pObj, const SwFEShell* pFESh)
{
	if (pFESh)
		return pFESh->IsObjSameLevelWithMarked(pObj);
	return sal_False;
}
void SwAccessibleMap::AddShapeContext(const SdrObject *pObj, uno::Reference < XAccessible > xAccShape)
{
	vos::OGuard aGuard( maMutex );

	if( mpShapeMap )
	{
		SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAccShape );
		mpShapeMap->insert( aEntry );
	}

}

//Added by yanjun for sym2_6407
void SwAccessibleMap::RemoveGroupContext(const SdrObject *pParentObj, ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible > xAccParent)
{
	vos::OGuard aGuard( maMutex );
	if (mpShapeMap && pParentObj && pParentObj->IsGroupObject() && xAccParent.is())
	{
		uno::Reference < XAccessibleContext > xContext = xAccParent->getAccessibleContext();
		if (xContext.is())
		{
			for (sal_Int32 i = 0; i < xContext->getAccessibleChildCount(); ++i)
			{
				uno::Reference < XAccessible > xChild = xContext->getAccessibleChild(i);
				if (xChild.is())
				{
					uno::Reference < XAccessibleContext > xChildContext = xChild->getAccessibleContext();
					if (xChildContext.is())
					{
						if (xChildContext->getAccessibleRole() == AccessibleRole::SHAPE)
						{
							::accessibility::AccessibleShape* pAccShape = static_cast < ::accessibility::AccessibleShape* >( xChild.get());
							uno::Reference < drawing::XShape > xShape = pAccShape->GetXShape();
							if (xShape.is())
							{
								SdrObject* pObj = GetSdrObjectFromXShape(xShape);
								if (pObj)
									RemoveContext(pObj);
							}
						}
					}
				}
			}
		}
	}
}
//End


void SwAccessibleMap::AddGroupContext(const SdrObject *pParentObj, uno::Reference < XAccessible > xAccParent)
{
	vos::OGuard aGuard( maMutex );
	if( mpShapeMap )
	{
		//here get all the sub list.
		if (pParentObj->IsGroupObject())
		{
			if (xAccParent.is())
			{
				uno::Reference < XAccessibleContext > xContext = xAccParent->getAccessibleContext();
				if (xContext.is())
				{
					sal_Int32 nChildren = xContext->getAccessibleChildCount();
					for(sal_Int32 i = 0; i<nChildren; i++)
					{
						uno::Reference < XAccessible > xChild = xContext->getAccessibleChild(i);
						if (xChild.is())
						{
							uno::Reference < XAccessibleContext > xChildContext = xChild->getAccessibleContext();
							if (xChildContext.is())
							{
								short nRole = xChildContext->getAccessibleRole();
								if (nRole == AccessibleRole::SHAPE)
								{
									::accessibility::AccessibleShape* pAccShape = static_cast < ::accessibility::AccessibleShape* >( xChild.get());
									uno::Reference < drawing::XShape > xShape = pAccShape->GetXShape();
									if (xShape.is())
									{
										SdrObject* pObj = GetSdrObjectFromXShape(xShape);
										AddShapeContext(pObj, xChild);
										AddGroupContext(pObj,xChild);
									}
								}
							}
						}	
					}
				}
			}
		}
	}				
}

::vos::ORef < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl(
			const SdrObject *pObj,
			SwAccessibleContext *pParentImpl,
			sal_Bool bCreate )
{
	uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) );

	::vos::ORef < ::accessibility::AccessibleShape > xAccImpl(
		 static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) );

	return xAccImpl;
}


void SwAccessibleMap::RemoveContext( const SwFrm *pFrm )
{
	vos::OGuard aGuard( maMutex );

	if( mpFrmMap )
	{
		SwAccessibleContextMap_Impl::iterator aIter =
			mpFrmMap->find( pFrm );
		if( aIter != mpFrmMap->end() )
		{
			mpFrmMap->erase( aIter );

			// Remove reference to old caret object. Though mxCursorContext
			// is a weak reference and cleared automatically, clearing it
			// directly makes sure to not keep a defunctional object.
			uno::Reference < XAccessible > xOldAcc( mxCursorContext );
			if( xOldAcc.is() )
			{
				SwAccessibleContext *pOldAccImpl =
					static_cast< SwAccessibleContext *>( xOldAcc.get() );
				ASSERT( pOldAccImpl->GetFrm(), "old caret context is disposed" );
				if( pOldAccImpl->GetFrm() == pFrm )
				{
					xOldAcc.clear();	// get an empty ref
					mxCursorContext = xOldAcc;
				}
			}

			if( mpFrmMap->empty() )
			{
				delete mpFrmMap;
				mpFrmMap = 0;
			}
		}
	}
}

void SwAccessibleMap::RemoveContext( const SdrObject *pObj )
{
	vos::OGuard aGuard( maMutex );

	if( mpShapeMap )
	{
		SwAccessibleShapeMap_Impl::iterator aIter =
			mpShapeMap->find( pObj );
		if( aIter != mpShapeMap->end() )
		{
			uno::Reference < XAccessible > xAcc( (*aIter).second );
			mpShapeMap->erase( aIter );
			RemoveGroupContext(pObj, xAcc);
			// The shape selection flag is not cleared, but one might do
			// so but has to make sure that the removed context is the one
			// that is selected.
			
			if( mpShapeMap && mpShapeMap->empty() )
			{
				delete mpShapeMap;
				mpShapeMap = 0;
			}
		}
	}
}


void SwAccessibleMap::Dispose( const SwFrm *pFrm,
                               const SdrObject *pObj,
                               Window* pWindow,
							   sal_Bool bRecursive )
{
    SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );

	// Indeed, the following assert checks the frame's accessible flag,
	// because that's the one that is evaluated in the layout. The frame
	// might not be accessible anyway. That's the case for cell frames that
	// contain further cells.
	ASSERT( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(),
			"non accessible frame should be disposed" );

	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
	{
        ::vos::ORef< SwAccessibleContext > xAccImpl;
        ::vos::ORef< SwAccessibleContext > xParentAccImpl;
        ::vos::ORef< ::accessibility::AccessibleShape > xShapeAccImpl;
		// get accessible context for frame
		{
			vos::OGuard aGuard( maMutex );

			// First of all look for an accessible context for a frame
			if( aFrmOrObj.GetSwFrm() && mpFrmMap )
			{
				SwAccessibleContextMap_Impl::iterator aIter =
					mpFrmMap->find( aFrmOrObj.GetSwFrm() );
				if( aIter != mpFrmMap->end() )
				{
					uno::Reference < XAccessible > xAcc( (*aIter).second );
					xAccImpl =
						static_cast< SwAccessibleContext *>( xAcc.get() );
				}
			}
			if( !xAccImpl.isValid() && mpFrmMap )
			{
				// If there is none, look if the parent is accessible.
				const SwFrm *pParent =
						SwAccessibleFrame::GetParent( aFrmOrObj,
                                                      GetShell()->IsPreView());

				if( pParent )
				{
					SwAccessibleContextMap_Impl::iterator aIter =
						mpFrmMap->find( pParent );
					if( aIter != mpFrmMap->end() )
					{
						uno::Reference < XAccessible > xAcc( (*aIter).second );
						xParentAccImpl =
							static_cast< SwAccessibleContext *>( xAcc.get() );
					}
				}
			}
			if( !xParentAccImpl.isValid() && !aFrmOrObj.GetSwFrm() &&
				mpShapeMap )
			{
				SwAccessibleShapeMap_Impl::iterator aIter =
                    mpShapeMap->find( aFrmOrObj.GetDrawObject() );
				if( aIter != mpShapeMap->end() )
				{
					uno::Reference < XAccessible > xAcc( (*aIter).second );
					xShapeAccImpl =
						static_cast< ::accessibility::AccessibleShape *>( xAcc.get() );
				}
			}
			if( pObj && GetShell()->ActionPend() &&
				(xParentAccImpl.isValid() || xShapeAccImpl.isValid()) )
			{
				// Keep a reference to the XShape to avoid that it
				// is deleted with a SwFrmFmt::Modify.
				uno::Reference < drawing::XShape > xShape(
					const_cast< SdrObject * >( pObj )->getUnoShape(),
					uno::UNO_QUERY );
				if( xShape.is() )
				{
					if( !mpShapes )
						mpShapes = new SwShapeList_Impl;
					mpShapes->push_back( xShape );
				}
			}
		}

		// remove events stored for the frame
		{
			vos::OGuard aGuard( maEventMutex );
			if( mpEvents )
			{
				SwAccessibleEventMap_Impl::iterator aIter =
					mpEventMap->find( aFrmOrObj );
				if( aIter != mpEventMap->end() )
				{
					SwAccessibleEvent_Impl aEvent(
							SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj );
					AppendEvent( aEvent );
				}
			}
		}

		// If the frame is accessible and there is a context for it, dispose
		// the frame. If the frame is no context for it but disposing should
		// take place recursive, the frame's children have to be disposed
		// anyway, so we have to create the context then.
		if( xAccImpl.isValid() )
		{
			xAccImpl->Dispose( bRecursive );
		}
		else if( xParentAccImpl.isValid() )
		{
			// If the frame is a cell frame, the table must be notified.
			// If we are in an action, a table model change event will
			// be broadcasted at the end of the action to give the table
			// a chance to generate a single table change event.

			xParentAccImpl->DisposeChild( aFrmOrObj, bRecursive );
		}
		else if( xShapeAccImpl.isValid() )
		{
            RemoveContext( aFrmOrObj.GetDrawObject() );
			xShapeAccImpl->dispose();
		}

		if( mpPreview && pFrm && pFrm->IsPageFrm() )
			mpPreview->DisposePage( static_cast< const SwPageFrm *>( pFrm ) );
	}
}

void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm,
										   const SdrObject *pObj,
                                           Window* pWindow,
										   const SwRect& rOldBox )
{
    SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
	{
		::vos::ORef< SwAccessibleContext > xAccImpl;
		::vos::ORef< SwAccessibleContext > xParentAccImpl;
		const SwFrm *pParent =NULL;
		{
			vos::OGuard aGuard( maMutex );

			if( mpFrmMap )
			{
				if( aFrmOrObj.GetSwFrm() )
				{
					SwAccessibleContextMap_Impl::iterator aIter =
						mpFrmMap->find( aFrmOrObj.GetSwFrm() );
					if( aIter != mpFrmMap->end() )
					{
						// If there is an accesible object already it is
						// notified directly.
						uno::Reference < XAccessible > xAcc( (*aIter).second );
						xAccImpl =
							static_cast< SwAccessibleContext *>( xAcc.get() );
					}
				}
				if( !xAccImpl.isValid() )
				{
					// Otherwise we look if the parent is accessible.
					// If not, there is nothing to do.
					pParent = SwAccessibleFrame::GetParent( aFrmOrObj,
                                                      GetShell()->IsPreView());

					if( pParent )
					{
						SwAccessibleContextMap_Impl::iterator aIter =
							mpFrmMap->find( pParent );
						if( aIter != mpFrmMap->end() )
						{
							uno::Reference < XAccessible > xAcc( (*aIter).second );
							xParentAccImpl =
								static_cast< SwAccessibleContext *>( xAcc.get() );
						}
					}
				}
			}
		}

		if( xAccImpl.isValid() )
		{
			if( GetShell()->ActionPend() )
			{
				SwAccessibleEvent_Impl aEvent(
					SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.getBodyPtr(),
					aFrmOrObj, rOldBox );
				AppendEvent( aEvent );
			}
			else
			{
				FireEvents();
				xAccImpl->InvalidatePosOrSize( rOldBox );
			}
		}
		else if( xParentAccImpl.isValid() )
		{
			if( GetShell()->ActionPend() )
			{
				SwAccessibleEvent_Impl aEvent(
					SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
					xParentAccImpl.getBodyPtr(), aFrmOrObj, rOldBox );
				AppendEvent( aEvent );
			}
			else
			{
				FireEvents();
				xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj,
														  rOldBox );
			}
		}
		else if(pParent)
		{
/*
For child graphic and it's parent paragraph,if split 2 graphic to 2 paragraph,
will delete one graphic swfrm and new create 1 graphic swfrm ,
then the new paragraph and the new graphic SwFrm will add .
but when add graphic SwFrm ,the accessible of the new Paragraph is not created yet.
so the new graphic accessible 'parent is NULL,
so run here: save the parent's SwFrm not the accessible object parent,
*/		
			sal_Bool bIsValidFrm = sal_False;
			sal_Bool bIsTxtParent = sal_False;
			if (aFrmOrObj.GetSwFrm())
			{
				int nType = pFrm->GetType();
				if ( FRM_FLY == nType )
				{
					bIsValidFrm =sal_True;
				}
			}
			else if(pObj)
			{
				int nType = pParent->GetType();
				if (FRM_TXT == nType)
				{
					bIsTxtParent =sal_True;
				}
			}
//			sal_Bool bIsVisibleChildrenOnly =aFrmOrObj.IsVisibleChildrenOnly() ;
//			sal_Bool bIsBoundAsChar =aFrmOrObj.IsBoundAsChar() ;//bIsVisibleChildrenOnly && bIsBoundAsChar && 
			if((bIsValidFrm || bIsTxtParent) )
			{
				if( GetShell()->ActionPend() )
				{
					SwAccessibleEvent_Impl aEvent(
						SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
						pParent, aFrmOrObj, rOldBox );
					AppendEvent( aEvent );
				}
				else
				{
					OSL_ENSURE(false,"");
				}
			}
		}
	}
}

void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm )
{
    SwAccessibleChild aFrmOrObj( pFrm );
	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
	{
		uno::Reference < XAccessible > xAcc;
		{
			vos::OGuard aGuard( maMutex );

			if( mpFrmMap )
			{
				SwAccessibleContextMap_Impl::iterator aIter =
					mpFrmMap->find( aFrmOrObj.GetSwFrm() );
				if( aIter != mpFrmMap->end() )
					xAcc = (*aIter).second;
			}
		}

		if( xAcc.is() )
		{
			SwAccessibleContext *pAccImpl =
				static_cast< SwAccessibleContext *>( xAcc.get() );
			if( GetShell()->ActionPend() )
			{
				SwAccessibleEvent_Impl aEvent(
					SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl,
					aFrmOrObj );
				AppendEvent( aEvent );
			}
			else
			{
				FireEvents();
				pAccImpl->InvalidateContent();
			}
		}
	}
}

// --> OD 2009-01-06 #i88069#
void SwAccessibleMap::InvalidateAttr( const SwTxtFrm& rTxtFrm )
{
    SwAccessibleChild aFrmOrObj( &rTxtFrm );
    if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
    {
        uno::Reference < XAccessible > xAcc;
        {
            vos::OGuard aGuard( maMutex );

            if( mpFrmMap )
            {
                SwAccessibleContextMap_Impl::iterator aIter =
                    mpFrmMap->find( aFrmOrObj.GetSwFrm() );
                if( aIter != mpFrmMap->end() )
                    xAcc = (*aIter).second;
            }
        }

        if( xAcc.is() )
        {
            SwAccessibleContext *pAccImpl =
                static_cast< SwAccessibleContext *>( xAcc.get() );
            if( GetShell()->ActionPend() )
            {
                SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR,
                                               pAccImpl, aFrmOrObj );
                aEvent.SetStates( ACC_STATE_TEXT_ATTRIBUTE_CHANGED );
                AppendEvent( aEvent );
            }
            else
            {
                FireEvents();
                pAccImpl->InvalidateAttr();
            }
        }
    }
}
// <--

void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm )
{
    SwAccessibleChild aFrmOrObj( pFrm );
	sal_Bool bShapeSelected = sal_False;
	const ViewShell *pVSh = GetShell();
	if( pVSh->ISA( SwCrsrShell ) )
	{
		const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
		if( pCSh->IsTableMode() )
		{
			while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() )
				aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
		}
		else if( pVSh->ISA( SwFEShell ) )
		{
			sal_uInt16 nObjCount;
			const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
			const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
			if( pFlyFrm )
			{
				ASSERT( !pFrm || pFrm->FindFlyFrm() == pFlyFrm,
						"cursor is not contained in fly frame" );
				aFrmOrObj = pFlyFrm;
			}
			else if( (nObjCount = pFESh->IsObjSelected()) > 0 )
			{
				bShapeSelected = sal_True;
				aFrmOrObj = static_cast<const SwFrm *>( 0 );
			}
		}
	}

	ASSERT( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreView()),
			"frame is not accessible" );

	uno::Reference < XAccessible > xOldAcc;
	uno::Reference < XAccessible > xAcc;
	sal_Bool bOldShapeSelected = sal_False;

	{
		vos::OGuard aGuard( maMutex );

		xOldAcc = mxCursorContext;
		mxCursorContext = xAcc;	// clear reference

		bOldShapeSelected = mbShapeSelected;
		mbShapeSelected = bShapeSelected;

		if( aFrmOrObj.GetSwFrm() && mpFrmMap )
		{
			SwAccessibleContextMap_Impl::iterator aIter =
				mpFrmMap->find( aFrmOrObj.GetSwFrm() );
			if( aIter != mpFrmMap->end() )
				xAcc = (*aIter).second;
			else
			{
				SwRect rcEmpty;
				const SwTabFrm* pTabFrm = aFrmOrObj.GetSwFrm()->FindTabFrm();
				if (pTabFrm)
				{
					InvalidatePosOrSize(pTabFrm,0,0,rcEmpty);
				}
				else
				{
					InvalidatePosOrSize(aFrmOrObj.GetSwFrm(),0,0,rcEmpty);
				}


				aIter =
					mpFrmMap->find( aFrmOrObj.GetSwFrm() );
				if( aIter != mpFrmMap->end() )
				{
					xAcc = (*aIter).second;
				}
			}

			// For cells, some extra thoughts are necessary,
			// because invalidating the cursor for one cell
			// invalidates the cursor for all cells of the same
			// table. For this reason, we don't want to
			// invalidate the cursor for the old cursor object
			// and the new one if they are within the same table,
			// because this would result in doing the work twice.
			// Moreover, we have to make sure to invalidate the
			// cursor even if the current cell has no accessible object.
			// If the old cursor objects exists and is in the same
			// table, its the best choice, because using it avoids
			// an unnessarary cursor invalidation cycle when creating
			// a new object for the current cell.
			if( aFrmOrObj.GetSwFrm()->IsCellFrm() )
			{
				if( xOldAcc.is() &&
					AreInSameTable( xOldAcc, aFrmOrObj.GetSwFrm() ) )
				{
					if( xAcc.is() )
						xOldAcc = xAcc;	// avoid extra invalidation
					else
						xAcc = xOldAcc;	// make sure ate least one
				}
				if( !xAcc.is() )
					xAcc = GetContext( aFrmOrObj.GetSwFrm(), sal_True );
			}
		}
        else if (bShapeSelected)
        {
            const SwFEShell *pFESh = pVSh ? static_cast< const SwFEShell * >( pVSh ) : NULL ;
            if(pFESh)
            {
                const SdrMarkList *pMarkList = pFESh->GetMarkList();
                if (pMarkList != NULL && pMarkList->GetMarkCount() == 1)
                {
                    SdrObject *pObj = pMarkList->GetMark( 0 )->GetMarkedSdrObj();
					::vos::ORef < ::accessibility::AccessibleShape > pAccShapeImpl = GetContextImpl(pObj,NULL,sal_False);
                    if (!pAccShapeImpl.isValid())
                    {
                        while (pObj && pObj->GetUpGroup())
                        {
                            pObj = pObj->GetUpGroup();
                        }
                        if (pObj != NULL)
                        {
                            const SwFrm *pParent = SwAccessibleFrame::GetParent( SwAccessibleChild(pObj), GetShell()->IsPreView() );
                            if( pParent )
                            {
                                ::vos::ORef< SwAccessibleContext > xParentAccImpl = GetContextImpl(pParent,sal_False);
                                if (!xParentAccImpl.isValid())
                                {
                                    const SwTabFrm* pTabFrm = pParent->FindTabFrm();
                                    if (pTabFrm)
                                    {   
                                        //The Table should not add in acc.because the "pParent" is not add to acc .
                                        uno::Reference< XAccessible>  xAccParentTab = GetContext(pTabFrm,sal_True);//Should Create.

                                        const SwFrm *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pTabFrm), GetShell()->IsPreView() );
                                        if (pParentRoot)
                                        {
                                            ::vos::ORef< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,sal_False);
                                            if(xParentAccImplRoot.isValid())
                                            {
                                                AccessibleEventObject aEvent;
                                                aEvent.EventId = AccessibleEventId::CHILD;
                                                aEvent.NewValue <<= xAccParentTab;
                                                xParentAccImplRoot->FireAccessibleEvent( aEvent );
                                            }
                                        }

                                        //Get "pParent" acc again.
                                        xParentAccImpl = GetContextImpl(pParent,sal_False);
                                    }
                                    else
                                    {   
                                        //directly create this acc para .
                                        xParentAccImpl = GetContextImpl(pParent,sal_True);//Should Create.

                                        const SwFrm *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pParent), GetShell()->IsPreView() );

                                        ::vos::ORef< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,sal_False);
                                        if(xParentAccImplRoot.isValid())
                                        {
                                            AccessibleEventObject aEvent;
                                            aEvent.EventId = AccessibleEventId::CHILD;
                                            aEvent.NewValue <<= uno::Reference< XAccessible>(xParentAccImpl.getBodyPtr());
                                            xParentAccImplRoot->FireAccessibleEvent( aEvent );
                                        }
                                    }
                                }
                                if (xParentAccImpl.isValid())
                                {
                                    uno::Reference< XAccessible>  xAccShape = 
                                        GetContext(pObj,xParentAccImpl.getBodyPtr(),sal_True);

                                    AccessibleEventObject aEvent;
                                    aEvent.EventId = AccessibleEventId::CHILD;
                                    aEvent.NewValue <<= xAccShape;
                                    xParentAccImpl->FireAccessibleEvent( aEvent );
                                }
                            }
                        }
                    }
                }
            }
        }
	}

	m_setParaAdd.clear();
	m_setParaRemove.clear();
	if( xOldAcc.is() && xOldAcc != xAcc )
		InvalidateCursorPosition( xOldAcc );
	if( bOldShapeSelected || bShapeSelected )
		InvalidateShapeSelection();
	if( xAcc.is() )
		InvalidateCursorPosition( xAcc );

	InvalidateShapeInParaSelection();

	SET_PARA::iterator si = m_setParaRemove.begin();
	for (; si != m_setParaRemove.end() ; ++si)
	{
		SwAccessibleParagraph* pAccPara = *si;
		if(pAccPara && pAccPara->getSelectedAccessibleChildCount() == 0 && pAccPara->getSelectedText().getLength() == 0)
		{
			if(pAccPara->SetSelectedState(sal_False))
			{
				AccessibleEventObject aEvent;
				aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
				pAccPara->FireAccessibleEvent( aEvent );
			}
		}			
	}
	si = m_setParaAdd.begin();
	for (; si != m_setParaAdd.end() ; ++si)
	{
		SwAccessibleParagraph* pAccPara = *si;
		if(pAccPara && pAccPara->SetSelectedState(sal_True))
		{
			AccessibleEventObject aEvent;
			aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
			pAccPara->FireAccessibleEvent( aEvent );
		}
	}
}

//Notify the page change event to bridge. 
void SwAccessibleMap::FirePageChangeEvent(sal_uInt16 nOldPage, sal_uInt16 nNewPage)
{
	uno::Reference<XAccessible> xAcc = GetDocumentView( );
    	if ( xAcc.is() )
    	{
    		SwAccessibleDocumentBase *pAcc =
			static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
			if (pAcc)
			{
				AccessibleEventObject aEvent;
				aEvent.EventId = AccessibleEventId::PAGE_CHANGED;
				aEvent.OldValue <<= nOldPage;
				aEvent.NewValue <<= nNewPage;
				pAcc->FireAccessibleEvent( aEvent );
			}
    	}
}
 
void SwAccessibleMap::FireSectionChangeEvent(sal_uInt16 nOldSection, sal_uInt16 nNewSection)
{
	uno::Reference<XAccessible> xAcc = GetDocumentView( );
    	if ( xAcc.is() )
    	{
    		SwAccessibleDocumentBase *pAcc =
			static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
			if (pAcc)
			{
				AccessibleEventObject aEvent;
				aEvent.EventId = AccessibleEventId::SECTION_CHANGED;
				aEvent.OldValue <<= nOldSection;
				aEvent.NewValue <<= nNewSection;
				pAcc->FireAccessibleEvent( aEvent );

			}
    	}
}
void SwAccessibleMap::FireColumnChangeEvent(sal_uInt16 nOldColumn, sal_uInt16 nNewColumn)
{
	uno::Reference<XAccessible> xAcc = GetDocumentView( );
    	if ( xAcc.is() )
    	{
    		SwAccessibleDocumentBase *pAcc =
			static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
		if (pAcc)
		{
				AccessibleEventObject aEvent;
				aEvent.EventId = AccessibleEventId::COLUMN_CHANGED;
				aEvent.OldValue <<= nOldColumn;
				aEvent.NewValue <<= nNewColumn;
				pAcc->FireAccessibleEvent( aEvent );
			
		}
    	}
}

void SwAccessibleMap::InvalidateFocus()
{
	if(GetShell()->IsPreView())
	{
		uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True );
		if (xAcc.get())
		{
			SwAccessiblePreview *pAccPreview = static_cast<SwAccessiblePreview *>(xAcc.get());
			if (pAccPreview)
			{
				pAccPreview->InvalidateFocus();
				return ;
			}			
		}
	}
	uno::Reference < XAccessible > xAcc;
	sal_Bool bShapeSelected;
	{
		vos::OGuard aGuard( maMutex );

		xAcc = mxCursorContext;
		bShapeSelected = mbShapeSelected;
	}

	if( xAcc.is() )
	{
		SwAccessibleContext *pAccImpl =
			static_cast< SwAccessibleContext *>( xAcc.get() );
		pAccImpl->InvalidateFocus();
	}
	else
	{
		DoInvalidateShapeSelection(sal_True);
	}
}

void SwAccessibleMap::SetCursorContext(
		const ::vos::ORef < SwAccessibleContext >& rCursorContext )
{
	vos::OGuard aGuard( maMutex );
	uno::Reference < XAccessible > xAcc( rCursorContext.getBodyPtr() );
	mxCursorContext = xAcc;
}

// --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
void SwAccessibleMap::InvalidateStates( tAccessibleStates _nStates,
                                        const SwFrm* _pFrm )
{
	// Start with the frame or the first upper that is accessible
    SwAccessibleChild aFrmOrObj( _pFrm );
	while( aFrmOrObj.GetSwFrm() &&
			!aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
		aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
	if( !aFrmOrObj.GetSwFrm() )
		aFrmOrObj = GetShell()->GetLayout();

	uno::Reference< XAccessible > xAcc( GetContext( aFrmOrObj.GetSwFrm(), sal_True ) );
	SwAccessibleContext *pAccImpl =
		static_cast< SwAccessibleContext *>( xAcc.get() );
	if( GetShell()->ActionPend() )
	{
        SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
                                       pAccImpl,
                                       SwAccessibleChild(pAccImpl->GetFrm()),
                                       _nStates );
		AppendEvent( aEvent );
	}
	else
	{
		FireEvents();
        pAccImpl->InvalidateStates( _nStates );
	}
}
// <--

void SwAccessibleMap::_InvalidateRelationSet( const SwFrm* pFrm,
                                              sal_Bool bFrom )
{
    // first, see if this frame is accessible, and if so, get the respective
    SwAccessibleChild aFrmOrObj( pFrm );
	if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
	{
		uno::Reference < XAccessible > xAcc;
		{
			vos::OGuard aGuard( maMutex );

			if( mpFrmMap )
			{
				SwAccessibleContextMap_Impl::iterator aIter =
                                        mpFrmMap->find( aFrmOrObj.GetSwFrm() );
				if( aIter != mpFrmMap->end() )
				{
					xAcc = (*aIter).second;
				}
			}
		}

        // deliver event directly, or queue event
		if( xAcc.is() )
		{
			SwAccessibleContext *pAccImpl =
                            static_cast< SwAccessibleContext *>( xAcc.get() );
            if( GetShell()->ActionPend() )
            {
                SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
                                               pAccImpl, SwAccessibleChild(pFrm),
                                               ( bFrom
                                                 ? ACC_STATE_RELATION_FROM
                                                 : ACC_STATE_RELATION_TO ) );
                AppendEvent( aEvent );
            }
            else
            {
				FireEvents();
                pAccImpl->InvalidateRelation( bFrom
                        ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED
                        : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
            }
        }
    }
}

void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster,
                                             const SwFrm* pFollow )
{
    _InvalidateRelationSet( pMaster, sal_False );
    _InvalidateRelationSet( pFollow, sal_True );
}

/** invalidation CONTENT_FLOW_FROM/_TO relation of a paragraph

    OD 2005-12-01 #i27138#

    @author OD
*/
void SwAccessibleMap::InvalidateParaFlowRelation( const SwTxtFrm& _rTxtFrm,
                                                  const bool _bFrom )
{
    _InvalidateRelationSet( &_rTxtFrm, _bFrom );
}

/** invalidation of text selection of a paragraph

    OD 2005-12-12 #i27301#

    @author OD
*/
void SwAccessibleMap::InvalidateParaTextSelection( const SwTxtFrm& _rTxtFrm )
{
    // first, see if this frame is accessible, and if so, get the respective
    SwAccessibleChild aFrmOrObj( &_rTxtFrm );
    if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
    {
        uno::Reference < XAccessible > xAcc;
        {
            vos::OGuard aGuard( maMutex );

            if( mpFrmMap )
            {
                SwAccessibleContextMap_Impl::iterator aIter =
                                        mpFrmMap->find( aFrmOrObj.GetSwFrm() );
                if( aIter != mpFrmMap->end() )
                {
                    xAcc = (*aIter).second;
                }
            }
        }

        // deliver event directly, or queue event
        if( xAcc.is() )
        {
            SwAccessibleContext *pAccImpl =
                            static_cast< SwAccessibleContext *>( xAcc.get() );
            if( GetShell()->ActionPend() )
            {
                SwAccessibleEvent_Impl aEvent(
                    SwAccessibleEvent_Impl::CARET_OR_STATES,
                    pAccImpl,
                    SwAccessibleChild( &_rTxtFrm ),
                    ACC_STATE_TEXT_SELECTION_CHANGED );
                AppendEvent( aEvent );
            }
            else
            {
                FireEvents();
                pAccImpl->InvalidateTextSelection();
            }
        }
    }
}

sal_Int32 SwAccessibleMap::GetChildIndex( const SwFrm& rParentFrm,
                                          Window& rChild ) const
{
    sal_Int32 nIndex( -1 );

    SwAccessibleChild aFrmOrObj( &rParentFrm );
    if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
    {
        uno::Reference < XAccessible > xAcc;
        {
            vos::OGuard aGuard( maMutex );

            if( mpFrmMap )
            {
                SwAccessibleContextMap_Impl::iterator aIter =
                                        mpFrmMap->find( aFrmOrObj.GetSwFrm() );
                if( aIter != mpFrmMap->end() )
                {
                    xAcc = (*aIter).second;
                }
            }
        }

        if( xAcc.is() )
        {
            SwAccessibleContext *pAccImpl =
                            static_cast< SwAccessibleContext *>( xAcc.get() );

            nIndex = pAccImpl->GetChildIndex( const_cast<SwAccessibleMap&>(*this),
                                              SwAccessibleChild( &rChild ) );
        }
    }

    return nIndex;
}


// OD 15.01.2003 #103492# - complete re-factoring of method due to new page/print
// preview functionality.
void SwAccessibleMap::UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages,
                                     const Fraction&  _rScale,
                                     const SwPageFrm* _pSelectedPageFrm,
                                     const Size&      _rPrevwWinSize )
{
    DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
    DBG_ASSERT( mpPreview != NULL, "no preview data?" );

    // OD 15.01.2003 #103492# - adjustments for changed method signature
    mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );

    // propagate change of VisArea through the document's
    // accessibility tree; this will also send appropriate scroll
    // events
    SwAccessibleContext* pDoc =
        GetContextImpl( GetShell()->GetLayout() ).getBodyPtr();
    static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea();

	uno::Reference < XAccessible > xOldAcc;
	uno::Reference < XAccessible > xAcc;
	{
		vos::OGuard aGuard( maMutex );

		xOldAcc = mxCursorContext;

		const SwPageFrm *pSelPage = mpPreview->GetSelPage();
		if( pSelPage && mpFrmMap )
		{
			SwAccessibleContextMap_Impl::iterator aIter =
				mpFrmMap->find( pSelPage );
			if( aIter != mpFrmMap->end() )
				xAcc = (*aIter).second;
		}
	}

	if( xOldAcc.is() && xOldAcc != xAcc )
		InvalidateCursorPosition( xOldAcc );
	if( xAcc.is() )
		InvalidateCursorPosition( xAcc );
}

void SwAccessibleMap::InvalidatePreViewSelection( sal_uInt16 nSelPage )
{
    DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
    DBG_ASSERT( mpPreview != NULL, "no preview data?" );

    // OD 16.01.2003 #103492# - changed metthod call due to method signature change.
    mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) );

	uno::Reference < XAccessible > xOldAcc;
	uno::Reference < XAccessible > xAcc;
	{
		vos::OGuard aGuard( maMutex );

		xOldAcc = mxCursorContext;

		const SwPageFrm *pSelPage = mpPreview->GetSelPage();
		if( pSelPage && mpFrmMap )
		{
			SwAccessibleContextMap_Impl::iterator aIter =
				mpFrmMap->find( pSelPage );
			if( aIter != mpFrmMap->end() )
				xAcc = (*aIter).second;
		}
	}

	if( xOldAcc.is() && xOldAcc != xAcc )
		InvalidateCursorPosition( xOldAcc );
	if( xAcc.is() )
		InvalidateCursorPosition( xAcc );
}


sal_Bool SwAccessibleMap::IsPageSelected( const SwPageFrm *pPageFrm ) const
{
	return mpPreview && mpPreview->GetSelPage() == pPageFrm;
}


void SwAccessibleMap::FireEvents()
{
	{
		vos::OGuard aGuard( maEventMutex );
		if( mpEvents )
		{
			mpEvents->SetFiring();
			mpEvents->MoveInvalidXAccToEnd();
			SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
			while( aIter != mpEvents->end() )
			{
				FireEvent( *aIter );
				++aIter;
			}

			delete mpEventMap;
			mpEventMap = 0;

			delete mpEvents;
			mpEvents = 0;
		}
	}
	{
		vos::OGuard aGuard( maMutex );
		if( mpShapes )
		{
			delete mpShapes;
			mpShapes = 0;
		}
	}

}

sal_Bool SwAccessibleMap::IsValid() const
{
	return sal_True;
}

Rectangle SwAccessibleMap::GetVisibleArea() const
{
    MapMode aSrc( MAP_TWIP );
	MapMode aDest( MAP_100TH_MM );
	return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest );
}

// Convert a MM100 value realtive to the document root into a pixel value
// realtive to the screen!
Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const
{
	MapMode aSrc( MAP_100TH_MM );
	MapMode aDest( MAP_TWIP );

    Point aPoint = rPoint;

	aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
	Window *pWin = GetShell()->GetWin();
	if( pWin )
    {
        // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion
        MapMode aMapMode;
        GetMapMode( aPoint, aMapMode );
        aPoint = pWin->LogicToPixel( aPoint, aMapMode );
		aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint );
    }

	return aPoint;
}

Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const
{
	MapMode aSrc( MAP_100TH_MM );
	MapMode aDest( MAP_TWIP );
	Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) );
	if( GetShell()->GetWin() )
    {
        // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion
        MapMode aMapMode;
        GetMapMode( Point(0,0), aMapMode );
        aSize = GetShell()->GetWin()->LogicToPixel( aSize, aMapMode );
    }

	return aSize;
}

Point SwAccessibleMap::PixelToLogic( const Point& rPoint ) const
{
	Point aPoint;
	Window *pWin = GetShell()->GetWin();
	if( pWin )
	{
		aPoint = pWin->ScreenToOutputPixel( rPoint );
        // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion
        MapMode aMapMode;
        GetMapMode( aPoint, aMapMode );
        aPoint = pWin->PixelToLogic( aPoint, aMapMode );
		MapMode aSrc( MAP_TWIP );
		MapMode aDest( MAP_100TH_MM );
		aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
	}

	return aPoint;
}

Size SwAccessibleMap::PixelToLogic( const Size& rSize ) const
{
	Size aSize;
	if( GetShell()->GetWin() )
	{
        // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion
        MapMode aMapMode;
        GetMapMode( Point(0,0), aMapMode );
        aSize = GetShell()->GetWin()->PixelToLogic( rSize, aMapMode );
		MapMode aSrc( MAP_TWIP );
		MapMode aDest( MAP_100TH_MM );
		aSize = OutputDevice::LogicToLogic( aSize, aSrc, aDest );
	}

	return aSize;
}

sal_Bool SwAccessibleMap::ReplaceChild (
        ::accessibility::AccessibleShape* pCurrentChild,
		const uno::Reference< drawing::XShape >& _rxShape,
        const long /*_nIndex*/,
        const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/
	)	throw (uno::RuntimeException)
{
	const SdrObject *pObj = 0;
	{
		vos::OGuard aGuard( maMutex );
		if( mpShapeMap )
		{
			SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
			SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
			while( aIter != aEndIter && !pObj )
			{
				uno::Reference < XAccessible > xAcc( (*aIter).second );
				::accessibility::AccessibleShape *pAccShape =
					static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
				if( pAccShape == pCurrentChild )
				{
					pObj = (*aIter).first;
				}
				++aIter;
			}
		}
	}
	if( !pObj )
		return sal_False;

	uno::Reference < drawing::XShape > xShape( _rxShape ); //keep reference to shape, because
											 // we might be the only one that
											 // hold it.
	// Also get keep parent.
	uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() );
	pCurrentChild = 0;	// well be realease by dispose
    Dispose( 0, pObj, 0 );

	{
		vos::OGuard aGuard( maMutex );

		if( !mpShapeMap )
			mpShapeMap = new SwAccessibleShapeMap_Impl( this );

		// create the new child
		::accessibility::ShapeTypeHandler& rShapeTypeHandler =
						::accessibility::ShapeTypeHandler::Instance();
		::accessibility::AccessibleShapeInfo aShapeInfo(
											xShape, xParent, this );
		::accessibility::AccessibleShape* pReplacement =
			rShapeTypeHandler.CreateAccessibleObject (
				aShapeInfo, mpShapeMap->GetInfo() );

		uno::Reference < XAccessible > xAcc( pReplacement );
		if( xAcc.is() )
		{
			pReplacement->Init();

			SwAccessibleShapeMap_Impl::iterator aIter =
				mpShapeMap->find( pObj );
			if( aIter != mpShapeMap->end() )
			{
				(*aIter).second = xAcc;
			}
			else
			{
				SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc );
				mpShapeMap->insert( aEntry );
			}
		}
	}

	SwRect aEmptyRect;
    InvalidatePosOrSize( 0, pObj, 0, aEmptyRect );

	return sal_True;
}

//Get the accessible control shape from the model object, here model object is with XPropertySet type
::accessibility::AccessibleControlShape * SwAccessibleMap::GetAccControlShapeFromModel(::com::sun::star::beans::XPropertySet* pSet) throw (::com::sun::star::uno::RuntimeException)
{
	if( mpShapeMap )
	{
		SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
		SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
		while( aIter != aEndIter)
		{
			uno::Reference < XAccessible > xAcc( (*aIter).second );
			::accessibility::AccessibleShape *pAccShape =
				static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
			if(pAccShape && ::accessibility::ShapeTypeHandler::Instance().GetTypeId (pAccShape->GetXShape()) == ::accessibility::DRAWING_CONTROL)
			{
				::accessibility::AccessibleControlShape *pCtlAccShape = static_cast < ::accessibility::AccessibleControlShape* >(pAccShape);
				if (pCtlAccShape && pCtlAccShape->GetControlModel() == pSet)
					return pCtlAccShape;
			}
			++aIter;
		}
	}
	return NULL;
}

::com::sun::star::uno::Reference< XAccessible >
    SwAccessibleMap::GetAccessibleCaption (const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape)
    throw (::com::sun::star::uno::RuntimeException)
{
		SdrObject* captionedObject = GetSdrObjectFromXShape(xShape);

		SwDrawContact *pContact = (SwDrawContact*)GetUserCall( captionedObject );
		ASSERT( RES_DRAWFRMFMT == pContact->GetFmt()->Which(),
				"fail" );
		if( !pContact )
			return 0;

		SwDrawFrmFmt *pCaptionedFmt = (SwDrawFrmFmt *)pContact->GetFmt();
		if( !pCaptionedFmt )
			return 0;

		SwFlyFrm* pFrm = NULL;
		if (pCaptionedFmt->HasCaption())
		{
			const SwFrmFmt *pCaptionFrmFmt = pCaptionedFmt->GetCaptionFmt();
			SwClientIter aIter (*(SwModify*)pCaptionFrmFmt);
			pFrm = (SwFlyFrm*)aIter.First( TYPE ( SwFlyFrm ));
		}
		if (!pFrm)
			return 0;
		//SwFrmFmt* pFrm = pCaptionedFmt->GetCaptionFmt();
		uno::Reference < XAccessible > xAcc( GetContext((SwFrm*)pFrm,sal_True) );
		//Reference < XAccessibleShape > xAccShape( xAcc, UNO_QUERY );
		
		uno::Reference< XAccessibleContext > xAccContext = xAcc->getAccessibleContext();
		if( xAccContext.is() )
		{	//get the parent of caption frame, which is paragaph
			uno::Reference< XAccessible > xAccParent = xAccContext->getAccessibleParent();
			if(xAccParent.is())
			{
				//get the great parent of caption frame which is text frame.
				uno::Reference< XAccessibleContext > xAccParentContext = xAccParent->getAccessibleContext();
				uno::Reference< XAccessible > xAccGreatParent = xAccParentContext->getAccessibleParent();
				if(xAccGreatParent.is())
				{
					AccessibleEventObject aEvent;
					aEvent.EventId = AccessibleEventId::CHILD;
					aEvent.NewValue <<= xAccParent;
					( static_cast< SwAccessibleContext * >(xAccGreatParent.get()) )->FireAccessibleEvent( aEvent );

				}

				AccessibleEventObject aEvent;
				aEvent.EventId = AccessibleEventId::CHILD;
				aEvent.NewValue <<= xAcc;
				( static_cast< SwAccessibleContext * >(xAccParent.get()) )->FireAccessibleEvent( aEvent );
			}
		}
		
		if(xAcc.get())
			return xAcc;
		else
			return NULL;

}
Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const
{
	Point aPoint;
	if( GetShell()->GetWin() )
	{
        // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)>
        MapMode aMapMode;
        GetMapMode( rPoint, aMapMode );
        aPoint = GetShell()->GetWin()->PixelToLogic( rPoint, aMapMode );
	}
	return aPoint;
}

static inline long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue,
                                          long aRefValue, bool bToLower)
{
    long aResult = aCoarseValue;

    if (bToLower)
    {
        if (aFineValue < aRefValue)
            aResult -= 1;
    }
    else
    {
        if (aFineValue > aRefValue)
            aResult += 1;
    }

    return aResult;
}

static inline void lcl_CorrectRectangle(Rectangle & rRect,
                                        const Rectangle & rSource,
                                        const Rectangle & rInGrid)
{
    rRect.nLeft = lcl_CorrectCoarseValue(rRect.nLeft, rSource.nLeft,
                                         rInGrid.nLeft, false);
    rRect.nTop = lcl_CorrectCoarseValue(rRect.nTop, rSource.nTop,
                                        rInGrid.nTop, false);
    rRect.nRight = lcl_CorrectCoarseValue(rRect.nRight, rSource.nRight,
                                          rInGrid.nRight, true);
    rRect.nBottom = lcl_CorrectCoarseValue(rRect.nBottom, rSource.nBottom,
                                           rInGrid.nBottom, true);
}

Rectangle SwAccessibleMap::CoreToPixel( const Rectangle& rRect ) const
{
    Rectangle aRect;
	if( GetShell()->GetWin() )
    {
        // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)>
        MapMode aMapMode;
        GetMapMode( rRect.TopLeft(), aMapMode );
        aRect = GetShell()->GetWin()->LogicToPixel( rRect, aMapMode );

        Rectangle aTmpRect = GetShell()->GetWin()->PixelToLogic( aRect, aMapMode );
        lcl_CorrectRectangle(aRect, rRect, aTmpRect);
    }

	return aRect;
}

/** get mapping mode for LogicToPixel and PixelToLogic conversions

    OD 15.01.2003 #103492#
    Replacement method <PreviewAdjust(..)> by new method <GetMapMode>.
    Method returns mapping mode of current output device and adjusts it,
    if the shell is in page/print preview.
    Necessary, because <PreviewAdjust(..)> changes mapping mode at current
    output device for mapping logic document positions to page preview window
    positions and vice versa and doesn't take care to recover its changes.

    @author OD
*/
void SwAccessibleMap::GetMapMode( const Point& _rPoint,
                                  MapMode&     _orMapMode ) const
{
    MapMode aMapMode = GetShell()->GetWin()->GetMapMode();
    if( GetShell()->IsPreView() )
    {
        DBG_ASSERT( mpPreview != NULL, "need preview data" );

        mpPreview->AdjustMapMode( aMapMode, _rPoint );
    }
    _orMapMode = aMapMode;
}

/** get size of a dedicated preview page

    OD 15.01.2003 #103492#

    @author OD
*/
Size SwAccessibleMap::GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const
{
    DBG_ASSERT( mpVSh->IsPreView(), "no page preview accessible." );
    DBG_ASSERT( mpVSh->IsPreView() && ( mpPreview != NULL ),
                "missing accessible preview data at page preview" );
    if ( mpVSh->IsPreView() && ( mpPreview != NULL ) )
    {
        return mpVSh->PagePreviewLayout()->GetPrevwPageSizeByPageNum( _nPrevwPageNum );
    }
    else
    {
        return Size( 0, 0 );
    }
}

/** method to build up a new data structure of the accessible pararaphs,
    which have a selection

    OD 2005-12-13 #i27301#
    Important note: method has to used inside a mutual exclusive section

    @author OD
*/
SwAccessibleSelectedParas_Impl* SwAccessibleMap::_BuildSelectedParas()
{
    // no accessible contexts, no selection
    if ( !mpFrmMap )
    {
        return 0L;
    }

    // get cursor as an instance of its base class <SwPaM>
    SwPaM* pCrsr( 0L );
    {
        SwCrsrShell* pCrsrShell = dynamic_cast<SwCrsrShell*>(GetShell());
        if ( pCrsrShell )
        {
            SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCrsrShell);
            if ( !pFEShell ||
                 ( !pFEShell->IsFrmSelected() &&
                   pFEShell->IsObjSelected() == 0 ) )
            {
                // get cursor without updating an existing table cursor.
                pCrsr = pCrsrShell->GetCrsr( sal_False );
            }
        }
    }
    // no cursor, no selection
    if ( !pCrsr )
    {
        return 0L;
    }

    SwAccessibleSelectedParas_Impl* pRetSelectedParas( 0L );

    // loop on all cursors
    SwPaM* pRingStart = pCrsr;
    do {

        // for a selection the cursor has to have a mark.
        // for savety reasons assure that point and mark are in text nodes
        if ( pCrsr->HasMark() &&
             pCrsr->GetPoint()->nNode.GetNode().IsTxtNode() &&
             pCrsr->GetMark()->nNode.GetNode().IsTxtNode() )
        {
            SwPosition* pStartPos = pCrsr->Start();
            SwPosition* pEndPos = pCrsr->End();
            // loop on all text nodes inside the selection
            SwNodeIndex aIdx( pStartPos->nNode );
            for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx )
            {
                SwTxtNode* pTxtNode( aIdx.GetNode().GetTxtNode() );
                if ( pTxtNode )
                {
                    // loop on all text frames registered at the text node.
                    SwIterator<SwTxtFrm,SwTxtNode> aIter( *pTxtNode );
                    for( SwTxtFrm* pTxtFrm = aIter.First(); pTxtFrm; pTxtFrm = aIter.Next() )
                        {
                            uno::WeakReference < XAccessible > xWeakAcc;
                            SwAccessibleContextMap_Impl::iterator aMapIter =
                                                    mpFrmMap->find( pTxtFrm );
                            if( aMapIter != mpFrmMap->end() )
                            {
                                xWeakAcc = (*aMapIter).second;
                                SwAccessibleParaSelection aDataEntry(
                                    pTxtNode == &(pStartPos->nNode.GetNode())
                                                ? pStartPos->nContent.GetIndex()
                                                : 0,
                                    pTxtNode == &(pEndPos->nNode.GetNode())
                                                ? pEndPos->nContent.GetIndex()
                                                : STRING_LEN );
                                SwAccessibleSelectedParas_Impl::value_type
                                                aEntry( xWeakAcc, aDataEntry );
                                if ( !pRetSelectedParas )
                                {
                                    pRetSelectedParas =
                                            new SwAccessibleSelectedParas_Impl;
                                }
                                pRetSelectedParas->insert( aEntry );
                            }
                        }
                    }
                }
            }

        // prepare next turn: get next cursor in ring
        pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
    } while ( pCrsr != pRingStart );

    return pRetSelectedParas;
}

/** invalidation of text selection of all paragraphs

    OD 2005-12-13 #i27301#

    @author OD
*/
void SwAccessibleMap::InvalidateTextSelectionOfAllParas()
{
    vos::OGuard aGuard( maMutex );

    // keep previously known selected paragraphs
    SwAccessibleSelectedParas_Impl* pPrevSelectedParas( mpSelectedParas );

    // determine currently selected paragraphs
    mpSelectedParas = _BuildSelectedParas();

    // compare currently selected paragraphs with the previously selected
    // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events.
    // first, search for new and changed selections.
    // on the run remove selections from previously known ones, if they are
    // also in the current ones.
    if ( mpSelectedParas )
    {
        SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin();
        for ( ; aIter != mpSelectedParas->end(); ++aIter )
        {
            bool bSubmitEvent( false );
            if ( !pPrevSelectedParas )
            {
                // new selection
                bSubmitEvent = true;
            }
            else
            {
                SwAccessibleSelectedParas_Impl::iterator aPrevSelected =
                                        pPrevSelectedParas->find( (*aIter).first );
                if ( aPrevSelected != pPrevSelectedParas->end() )
                {
                    // check, if selection has changed
                    if ( (*aIter).second.nStartOfSelection !=
                                    (*aPrevSelected).second.nStartOfSelection ||
                         (*aIter).second.nEndOfSelection !=
                                    (*aPrevSelected).second.nEndOfSelection )
                    {
                        // changed selection
                        bSubmitEvent = true;
                    }
                    pPrevSelectedParas->erase( aPrevSelected );
                }
                else
                {
                    // new selection
                    bSubmitEvent = true;
                }
            }

            if ( bSubmitEvent )
            {
                uno::Reference < XAccessible > xAcc( (*aIter).first );
                if ( xAcc.is() )
                {
                    ::vos::ORef < SwAccessibleContext > xAccImpl(
                                static_cast<SwAccessibleContext*>( xAcc.get() ) );
                    if ( xAccImpl.isValid() && xAccImpl->GetFrm() )
                    {
                        const SwTxtFrm* pTxtFrm(
                            dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
                        ASSERT( pTxtFrm,
                                "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
                        if ( pTxtFrm )
                        {
                            InvalidateParaTextSelection( *pTxtFrm );
                        }
                    }
                }
            }
        }
    }

    // second, handle previous selections - after the first step the data
    // structure of the previously known only contains the 'old' selections
    if ( pPrevSelectedParas )
    {
        SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin();
        for ( ; aIter != pPrevSelectedParas->end(); ++aIter )
        {
            uno::Reference < XAccessible > xAcc( (*aIter).first );
            if ( xAcc.is() )
            {
                ::vos::ORef < SwAccessibleContext > xAccImpl(
                            static_cast<SwAccessibleContext*>( xAcc.get() ) );
                if ( xAccImpl.isValid() && xAccImpl->GetFrm() )
                {
                    const SwTxtFrm* pTxtFrm(
                            dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
                    ASSERT( pTxtFrm,
                            "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
                    if ( pTxtFrm )
                    {
                        InvalidateParaTextSelection( *pTxtFrm );
                    }
                }
            }
        }

        delete pPrevSelectedParas;
    }
}

const SwRect& SwAccessibleMap::GetVisArea() const
{
    DBG_ASSERT( !GetShell()->IsPreView() || (mpPreview != NULL),
                "preview without preview data?" );

    return GetShell()->IsPreView()
           ? mpPreview->GetVisArea()
           : GetShell()->VisArea();
}

sal_Bool SwAccessibleMap::IsDocumentSelAll()
{
	return GetShell()->GetDoc()->IsPrepareSelAll();
}

