/**************************************************************
 * 
 * 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_starmath.hxx"
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleTextType.hpp>
#include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
#include <com/sun/star/accessibility/AccessibleEventObject.hpp>
#include <com/sun/star/awt/FocusEvent.hpp>
#include <com/sun/star/awt/XFocusListener.hpp>
#include <unotools/accessiblerelationsethelper.hxx>


#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
#include <com/sun/star/i18n/WordType.hpp>
#include <unotools/accessiblestatesethelper.hxx>
#include <comphelper/accessibleeventnotifier.hxx>
#include <tools/debug.hxx>
#include <vcl/svapp.hxx>
#include <vcl/window.hxx>
#include <vcl/unohelp2.hxx>
#include <tools/gen.hxx>
#include <vos/mutex.hxx>
#include <svl/itemset.hxx>

#include <editeng/editobj.hxx>
#include <editeng/editdata.hxx>
#include <editeng/editview.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/outliner.hxx>
#include <editeng/unoedhlp.hxx>


#include "accessibility.hxx"
#include <applicat.hxx>
#include <document.hxx>
#include <view.hxx>

using namespace rtl;
using namespace com::sun::star;
using namespace com::sun::star::lang;
using namespace com::sun::star::uno;
using namespace com::sun::star::accessibility;

#define A2OU(cChar)  rtl::OUString::createFromAscii(cChar)

//////////////////////////////////////////////////////////////////////

static awt::Rectangle lcl_GetBounds( Window *pWin )
{
    // !! see VCLXAccessibleComponent::implGetBounds()

    //! the coordinates returned are relativ to the parent window !
    //! Thus the top-left point may be different from (0, 0) !

    awt::Rectangle aBounds;
    if (pWin)
    {
        Rectangle aRect = pWin->GetWindowExtentsRelative( NULL );
        aBounds.X       = aRect.Left();
        aBounds.Y       = aRect.Top();
        aBounds.Width   = aRect.GetWidth();
        aBounds.Height  = aRect.GetHeight();
        Window* pParent = pWin->GetAccessibleParentWindow();
        if (pParent)
        {
            Rectangle aParentRect = pParent->GetWindowExtentsRelative( NULL );
            awt::Point aParentScreenLoc( aParentRect.Left(), aParentRect.Top() );
            aBounds.X -= aParentScreenLoc.X;
            aBounds.Y -= aParentScreenLoc.Y;
        }
    }
    return aBounds;
}

static awt::Point lcl_GetLocationOnScreen( Window *pWin )
{
    // !! see VCLXAccessibleComponent::getLocationOnScreen()

    awt::Point aPos;
    if (pWin)
    {
        Rectangle aRect = pWin->GetWindowExtentsRelative( NULL );
        aPos.X = aRect.Left();
        aPos.Y = aRect.Top();
    }
    return aPos;
}

//////////////////////////////////////////////////////////////////////

SmGraphicAccessible::SmGraphicAccessible( SmGraphicWindow *pGraphicWin ) :
    aAccName            ( String(SmResId(RID_DOCUMENTSTR)) ),
    nClientId           (0),
    pWin                (pGraphicWin)
{
    DBG_ASSERT( pWin, "SmGraphicAccessible: window missing" );
    //++aRefCount;
}


SmGraphicAccessible::SmGraphicAccessible( const SmGraphicAccessible &rSmAcc ) :
    SmGraphicAccessibleBaseClass(),
    aAccName            ( String(SmResId(RID_DOCUMENTSTR)) ),
    nClientId           (0)
{
    //vos::OGuard aGuard(Application::GetSolarMutex());
    pWin = rSmAcc.pWin;
    DBG_ASSERT( pWin, "SmGraphicAccessible: window missing" );
    //++aRefCount;
}


SmGraphicAccessible::~SmGraphicAccessible()
{
/*
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (--aRefCount == 0)
    {
    }
*/
}


SmDocShell * SmGraphicAccessible::GetDoc_Impl()
{
    SmViewShell *pView = pWin ? pWin->GetView() : 0;
    return pView ? pView->GetDoc() : 0;
}

String SmGraphicAccessible::GetAccessibleText_Impl()
{
    String aTxt;
    SmDocShell *pDoc = GetDoc_Impl();
    if (pDoc)
        aTxt = pDoc->GetAccessibleText();
    return aTxt;
}

void SmGraphicAccessible::ClearWin()
{
    pWin = 0;   // implicitly results in AccessibleStateType::DEFUNC set

	if ( nClientId )
	{
        comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this );
		nClientId =  0;
	}
}

void SmGraphicAccessible::LaunchEvent(
        const sal_Int16 nAccesibleEventId,
        const uno::Any &rOldVal,
        const uno::Any &rNewVal)
{
    AccessibleEventObject aEvt;
    aEvt.Source     = (XAccessible *) this;
    aEvt.EventId    = nAccesibleEventId;
    aEvt.OldValue   = rOldVal;
    aEvt.NewValue   = rNewVal ;

    // pass event on to event-listener's
	if (nClientId)
		comphelper::AccessibleEventNotifier::addEvent( nClientId, aEvt );
}

uno::Reference< XAccessibleContext > SAL_CALL SmGraphicAccessible::getAccessibleContext()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return this;
}

sal_Bool SAL_CALL SmGraphicAccessible::containsPoint( const awt::Point& aPoint )
    throw (RuntimeException)
{
    //! the arguments coordinates are relativ to the current window !
    //! Thus the top-left point is (0, 0)

	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();

    Size aSz( pWin->GetSizePixel() );
    return  aPoint.X >= 0  &&  aPoint.Y >= 0  &&
            aPoint.X < aSz.Width()  &&  aPoint.Y < aSz.Height();
}

uno::Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleAtPoint(
        const awt::Point& aPoint )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    XAccessible *pRes = 0;
    if (containsPoint( aPoint ))
        pRes = this;
    return pRes;
}

awt::Rectangle SAL_CALL SmGraphicAccessible::getBounds()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();
    DBG_ASSERT(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
            "mismatch of window parent and accessible parent" );
    return lcl_GetBounds( pWin );
}

awt::Point SAL_CALL SmGraphicAccessible::getLocation()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();
    DBG_ASSERT(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
            "mismatch of window parent and accessible parent" );
    awt::Rectangle aRect( lcl_GetBounds( pWin ) );
    return awt::Point( aRect.X, aRect.Y );
}

awt::Point SAL_CALL SmGraphicAccessible::getLocationOnScreen()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();
    DBG_ASSERT(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
            "mismatch of window parent and accessible parent" );
    return lcl_GetLocationOnScreen( pWin );
}

awt::Size SAL_CALL SmGraphicAccessible::getSize()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();
    DBG_ASSERT(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
            "mismatch of window parent and accessible parent" );

    Size aSz( pWin->GetSizePixel() );
#if OSL_DEBUG_LEVEL > 1
    awt::Rectangle aRect( lcl_GetBounds( pWin ) );
    Size aSz2( aRect.Width, aRect.Height );
    DBG_ASSERT( aSz == aSz2, "mismatch in width" );
#endif
    return awt::Size( aSz.Width(), aSz.Height() );
}

void SAL_CALL SmGraphicAccessible::grabFocus()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();

    pWin->GrabFocus();
}

sal_Int32 SAL_CALL SmGraphicAccessible::getForeground()
    throw (RuntimeException)
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    if (!pWin)
        throw RuntimeException();
    return (sal_Int32) pWin->GetTextColor().GetColor();
}

sal_Int32 SAL_CALL SmGraphicAccessible::getBackground()
    throw (RuntimeException)
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    if (!pWin)
        throw RuntimeException();
    Wallpaper aWall( pWin->GetDisplayBackground() );
    ColorData nCol;
    if (aWall.IsBitmap() || aWall.IsGradient())
        nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor().GetColor();
    else
        nCol = aWall.GetColor().GetColor();
    return (sal_Int32) nCol;
}

sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleChildCount()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return 0;
}

Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleChild(
        sal_Int32 /*i*/ )
    throw (IndexOutOfBoundsException, RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    throw IndexOutOfBoundsException();  // there is no child...
    /*return 0;*/
}

Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleParent()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();

    Window *pAccParent = pWin->GetAccessibleParentWindow();
    DBG_ASSERT( pAccParent, "accessible parent missing" );
    return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >();
}

sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleIndexInParent()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    sal_Int32 nIdx = -1;
    Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : 0;
    if (pAccParent)
    {
        sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount();
        for (sal_uInt16 i = 0;  i < nCnt  &&  nIdx == -1;  ++i)
            if (pAccParent->GetAccessibleChildWindow( i ) == pWin)
                nIdx = i;
    }
    return nIdx;
}

sal_Int16 SAL_CALL SmGraphicAccessible::getAccessibleRole()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return AccessibleRole::DOCUMENT;
}

OUString SAL_CALL SmGraphicAccessible::getAccessibleDescription()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    SmDocShell *pDoc = GetDoc_Impl();
    return pDoc ? OUString(pDoc->GetText()) : OUString();
}

OUString SAL_CALL SmGraphicAccessible::getAccessibleName()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return aAccName;
}

Reference< XAccessibleRelationSet > SAL_CALL SmGraphicAccessible::getAccessibleRelationSet()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper();
    return xRelSet;   // empty relation set
}

Reference< XAccessibleStateSet > SAL_CALL SmGraphicAccessible::getAccessibleStateSet()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
	::utl::AccessibleStateSetHelper *pStateSet =
            new ::utl::AccessibleStateSetHelper;

	Reference<XAccessibleStateSet> xStateSet( pStateSet );

    if (!pWin)
        pStateSet->AddState( AccessibleStateType::DEFUNC );
    else
    {
        //pStateSet->AddState( AccessibleStateType::EDITABLE );
        //pStateSet->AddState( AccessibleStateType::HORIZONTAL );
        //pStateSet->AddState( AccessibleStateType::TRANSIENT );
        pStateSet->AddState( AccessibleStateType::ENABLED );
        pStateSet->AddState( AccessibleStateType::FOCUSABLE );
        if (pWin->HasFocus())
            pStateSet->AddState( AccessibleStateType::FOCUSED );
        if (pWin->IsActive())
            pStateSet->AddState( AccessibleStateType::ACTIVE );
        if (pWin->IsVisible())
            pStateSet->AddState( AccessibleStateType::SHOWING );
        if (pWin->IsReallyVisible())
            pStateSet->AddState( AccessibleStateType::VISIBLE );
        if (COL_TRANSPARENT != pWin->GetBackground().GetColor().GetColor())
            pStateSet->AddState( AccessibleStateType::OPAQUE );
    }

	return xStateSet;
}

Locale SAL_CALL SmGraphicAccessible::getLocale()
    throw (IllegalAccessibleComponentStateException, RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    // should be the document language...
    // We use the language of the localized symbol names here.
    return Application::GetSettings().GetUILocale();
}


void SAL_CALL SmGraphicAccessible::addEventListener(
        const Reference< XAccessibleEventListener >& xListener )
    throw (RuntimeException)
{
	if (xListener.is())
    {
		vos::OGuard aGuard(Application::GetSolarMutex());
		if (pWin)
		{
			if (!nClientId)
                nClientId = comphelper::AccessibleEventNotifier::registerClient( );
			comphelper::AccessibleEventNotifier::addEventListener( nClientId, xListener );
		}
    }
}

void SAL_CALL SmGraphicAccessible::removeEventListener(
        const Reference< XAccessibleEventListener >& xListener )
    throw (RuntimeException)
{
	if (xListener.is())
	{
		vos::OGuard aGuard(Application::GetSolarMutex());
		sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( nClientId, xListener );
		if ( !nListenerCount )
		{
			// no listeners anymore
			// -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
			// and at least to us not firing any events anymore, in case somebody calls
			// NotifyAccessibleEvent, again
			comphelper::AccessibleEventNotifier::revokeClient( nClientId );
			nClientId = 0;
		}
	}
}

sal_Int32 SAL_CALL SmGraphicAccessible::getCaretPosition()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return 0;
}

sal_Bool SAL_CALL SmGraphicAccessible::setCaretPosition( sal_Int32 nIndex )
    throw (IndexOutOfBoundsException, RuntimeException)
{
    xub_StrLen nIdx = (xub_StrLen) nIndex;
    String aTxt( GetAccessibleText_Impl() );
    if (!(/*0 <= nIdx  &&*/  nIdx < aTxt.Len()))
        throw IndexOutOfBoundsException();
	return sal_False;
}

sal_Unicode SAL_CALL SmGraphicAccessible::getCharacter( sal_Int32 nIndex )
    throw (IndexOutOfBoundsException, RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());

    xub_StrLen nIdx = (xub_StrLen) nIndex;
    String aTxt( GetAccessibleText_Impl() );
    if (!(/*0 <= nIdx  &&*/  nIdx < aTxt.Len()))
        throw IndexOutOfBoundsException();
    return aTxt.GetChar( nIdx );
}

Sequence< beans::PropertyValue > SAL_CALL SmGraphicAccessible::getCharacterAttributes(
        sal_Int32 nIndex, 
        const uno::Sequence< ::rtl::OUString > & /*rRequestedAttributes*/ )
    throw (IndexOutOfBoundsException, RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    sal_Int32 nLen = GetAccessibleText_Impl().Len();
    if (!(0 <= nIndex  &&  nIndex < nLen))
        throw IndexOutOfBoundsException();
    return Sequence< beans::PropertyValue >();
}

awt::Rectangle SAL_CALL SmGraphicAccessible::getCharacterBounds( sal_Int32 nIndex )
    throw (IndexOutOfBoundsException, RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());

    awt::Rectangle aRes;

    if (!pWin)
        throw RuntimeException();
    else
    {
        // get accessible text
        SmViewShell *pView = pWin->GetView();
        SmDocShell  *pDoc  = pView ? pView->GetDoc() : 0;
        if (!pDoc)
            throw RuntimeException();
        String aTxt( GetAccessibleText_Impl() );
        if (!(0 <= nIndex  &&  nIndex <= aTxt.Len()))   // #108812# aTxt.Len() is valid
            throw IndexOutOfBoundsException();

        // #108812# find a reasonable rectangle for position aTxt.Len().
        bool bWasBehindText = (nIndex == aTxt.Len());
        if (bWasBehindText && nIndex)
            --nIndex;

        const SmNode *pTree = pDoc->GetFormulaTree();
        const SmNode *pNode = pTree->FindNodeWithAccessibleIndex( (xub_StrLen) nIndex );
        //! pNode may be 0 if the index belongs to a char that was inserted
        //! only for the accessible text!
        if (pNode)
        {
            sal_Int32 nAccIndex = pNode->GetAccessibleIndex();
            DBG_ASSERT( nAccIndex >= 0, "invalid accessible index" );
            DBG_ASSERT( nIndex >= nAccIndex, "index out of range" );

            String    aNodeText;
            pNode->GetAccessibleText( aNodeText );
            sal_Int32 nNodeIndex = nIndex - nAccIndex;
            if (0 <= nNodeIndex  &&  nNodeIndex < aNodeText.Len())
            {
                // get appropriate rectangle
                Point aOffset(pNode->GetTopLeft() - pTree->GetTopLeft());
                Point aTLPos (pWin->GetFormulaDrawPos() + aOffset);
//                aTLPos.X() -= pNode->GetItalicLeftSpace();
//                Size  aSize (pNode->GetItalicSize());
                aTLPos.X() -= 0;
                Size  aSize (pNode->GetSize());

                sal_Int32 *pXAry = new sal_Int32[ aNodeText.Len() ];
                pWin->SetFont( pNode->GetFont() );
                pWin->GetTextArray( aNodeText, pXAry, 0, aNodeText.Len() );
                aTLPos.X()    += nNodeIndex > 0 ? pXAry[nNodeIndex - 1] : 0;
                aSize.Width()  = nNodeIndex > 0 ? pXAry[nNodeIndex] - pXAry[nNodeIndex - 1] : pXAry[nNodeIndex];
                delete[] pXAry;

#if OSL_DEBUG_LEVEL > 1
    Point aLP00( pWin->LogicToPixel( Point(0,0)) );
    Point aPL00( pWin->PixelToLogic( Point(0,0)) );
#endif
                aTLPos = pWin->LogicToPixel( aTLPos );
                aSize  = pWin->LogicToPixel( aSize );
                aRes.X = aTLPos.X();
                aRes.Y = aTLPos.Y();
                aRes.Width  = aSize.Width();
                aRes.Height = aSize.Height();
            }
        }

        // #108812# take rectangle from last character and move it to the right
        if (bWasBehindText)
            aRes.X += aRes.Width;
    }

    return aRes;
}

sal_Int32 SAL_CALL SmGraphicAccessible::getCharacterCount()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return GetAccessibleText_Impl().Len();
}

sal_Int32 SAL_CALL SmGraphicAccessible::getIndexAtPoint( const awt::Point& aPoint )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());

    sal_Int32 nRes = -1;
    if (pWin)
    {
        const SmNode *pTree = pWin->GetView()->GetDoc()->GetFormulaTree();
		//! kann NULL sein! ZB wenn bereits beim laden des Dokuments (bevor der
		//! Parser angeworfen wurde) ins Fenster geklickt wird.
		if (!pTree)
            return nRes;

        // get position relativ to formula draw position
        Point  aPos( aPoint.X, aPoint.Y );
        aPos = pWin->PixelToLogic( aPos );
        aPos -= pWin->GetFormulaDrawPos();

        // if it was inside the formula then get the appropriate node
		const SmNode *pNode = 0;
		if (pTree->OrientedDist(aPos) <= 0)
			pNode = pTree->FindRectClosestTo(aPos);

        if (pNode)
        {
            // get appropriate rectangle
            Point   aOffset( pNode->GetTopLeft() - pTree->GetTopLeft() );
            Point   aTLPos ( /*pWin->GetFormulaDrawPos() +*/ aOffset );
//            aTLPos.X() -= pNode->GetItalicLeftSpace();
//            Size  aSize( pNode->GetItalicSize() );
            aTLPos.X() -= 0;
            Size  aSize( pNode->GetSize() );
#if OSL_DEBUG_LEVEL > 1
    Point aLP00( pWin->LogicToPixel( Point(0,0)) );
    Point aPL00( pWin->PixelToLogic( Point(0,0)) );
#endif

            Rectangle aRect( aTLPos, aSize );
            if (aRect.IsInside( aPos ))
            {
                DBG_ASSERT( pNode->IsVisible(), "node is not a leaf" );
                String aTxt;
                pNode->GetAccessibleText( aTxt );
                DBG_ASSERT( aTxt.Len(), "no accessible text available" );

                long nNodeX = pNode->GetLeft();

                sal_Int32 *pXAry = new sal_Int32[ aTxt.Len() ];
                pWin->SetFont( pNode->GetFont() );
                pWin->GetTextArray( aTxt, pXAry, 0, aTxt.Len() );
                for (sal_Int32 i = 0;  i < aTxt.Len()  &&  nRes == -1;  ++i)
                {
                    if (pXAry[i] + nNodeX > aPos.X())
                        nRes = i;
                }
                delete[] pXAry;
                DBG_ASSERT( nRes >= 0  &&  nRes < aTxt.Len(), "index out of range" );
                DBG_ASSERT( pNode->GetAccessibleIndex() >= 0,
                        "invalid accessible index" );

                nRes = pNode->GetAccessibleIndex() + nRes;
            }
		}
    }
    return nRes;
}

OUString SAL_CALL SmGraphicAccessible::getSelectedText()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return OUString();
}

sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionStart()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return -1;
}

sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionEnd()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return -1;
}

sal_Bool SAL_CALL SmGraphicAccessible::setSelection(
        sal_Int32 nStartIndex,
        sal_Int32 nEndIndex )
    throw (IndexOutOfBoundsException, RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    sal_Int32 nLen = GetAccessibleText_Impl().Len();
    if (!(0 <= nStartIndex  &&  nStartIndex < nLen) ||
        !(0 <= nEndIndex    &&  nEndIndex   < nLen))
        throw IndexOutOfBoundsException();
    return sal_False;
}

OUString SAL_CALL SmGraphicAccessible::getText()
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return GetAccessibleText_Impl();
}

OUString SAL_CALL SmGraphicAccessible::getTextRange(
        sal_Int32 nStartIndex,
        sal_Int32 nEndIndex )
    throw (IndexOutOfBoundsException, RuntimeException)
{
    //!! nEndIndex may be the string length per definition of the interface !!
    //!! text should be copied exclusive that end index though. And arguments
    //!! may be switched.

    vos::OGuard aGuard(Application::GetSolarMutex());
    String aTxt( GetAccessibleText_Impl() );
    xub_StrLen nStart = (xub_StrLen) Min(nStartIndex, nEndIndex);
    xub_StrLen nEnd   = (xub_StrLen) Max(nStartIndex, nEndIndex);
    if (!(/*0 <= nStart  &&*/  nStart <= aTxt.Len()) ||
        !(/*0 <= nEnd    &&*/  nEnd   <= aTxt.Len()))
        throw IndexOutOfBoundsException();
    return aTxt.Copy( nStart, nEnd - nStart );
}

::com::sun::star::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    String aTxt( GetAccessibleText_Impl() );
    xub_StrLen nIdx = (xub_StrLen) nIndex;
    //!! nIndex is allowed to be the string length
    if (!(/*0 <= nIdx  &&*/  nIdx <= aTxt.Len()))
        throw IndexOutOfBoundsException();

    ::com::sun::star::accessibility::TextSegment aResult;
    aResult.SegmentStart = -1;
    aResult.SegmentEnd = -1;
    if ( (AccessibleTextType::CHARACTER == aTextType)  &&  (nIdx < aTxt.Len()) )
    {
        aResult.SegmentText = aTxt.Copy(nIdx, 1);
        aResult.SegmentStart = nIdx;
        aResult.SegmentEnd = nIdx+1;
    }
    return aResult;
}

::com::sun::star::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    String aTxt( GetAccessibleText_Impl() );
    xub_StrLen nIdx = (xub_StrLen) nIndex;
    //!! nIndex is allowed to be the string length
    if (!(/*0 <= nIdx  &&*/  nIdx <= aTxt.Len()))
        throw IndexOutOfBoundsException();

    ::com::sun::star::accessibility::TextSegment aResult;
    aResult.SegmentStart = -1;
    aResult.SegmentEnd = -1;

    if ( (AccessibleTextType::CHARACTER == aTextType)  && nIdx )
    {
        aResult.SegmentText = aTxt.Copy(nIdx-1, 1);
        aResult.SegmentStart = nIdx-1;
        aResult.SegmentEnd = nIdx;
    }
    return aResult;
}

::com::sun::star::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    String aTxt( GetAccessibleText_Impl() );
    xub_StrLen nIdx = (xub_StrLen) nIndex;
    //!! nIndex is allowed to be the string length
    if (!(/*0 <= nIdx  &&*/  nIdx <= aTxt.Len()))
        throw IndexOutOfBoundsException();

    ::com::sun::star::accessibility::TextSegment aResult;
    aResult.SegmentStart = -1;
    aResult.SegmentEnd = -1;

    nIdx++; // text *behind*
    if ( (AccessibleTextType::CHARACTER == aTextType)  &&  (nIdx < aTxt.Len()) )
    {
        aResult.SegmentText = aTxt.Copy(nIdx, 1);
        aResult.SegmentStart = nIdx;
        aResult.SegmentEnd = nIdx+1;
    }
    return aResult;
}

sal_Bool SAL_CALL SmGraphicAccessible::copyText(
        sal_Int32 nStartIndex,
        sal_Int32 nEndIndex )
    throw (IndexOutOfBoundsException, RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
	sal_Bool bReturn = sal_False;

    if (!pWin)
        throw RuntimeException();
    else
	{
        Reference< datatransfer::clipboard::XClipboard > xClipboard = pWin->GetClipboard();
		if ( xClipboard.is() )
		{
            ::rtl::OUString sText( getTextRange(nStartIndex, nEndIndex) );

			::vcl::unohelper::TextDataObject* pDataObj = new ::vcl::unohelper::TextDataObject( sText );
			const sal_uInt32 nRef = Application::ReleaseSolarMutex();
			xClipboard->setContents( pDataObj, NULL );

			Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
			if( xFlushableClipboard.is() )
				xFlushableClipboard->flushClipboard();

			Application::AcquireSolarMutex( nRef );

			bReturn = sal_True;
		}
	}

    return bReturn;
}

OUString SAL_CALL SmGraphicAccessible::getImplementationName()
    throw (RuntimeException)
{
    //vos::OGuard aGuard(Application::GetSolarMutex());
    return A2OU("SmGraphicAccessible");
}

sal_Bool SAL_CALL SmGraphicAccessible::supportsService(
        const OUString& rServiceName )
    throw (RuntimeException)
{
    //vos::OGuard aGuard(Application::GetSolarMutex());
    return  rServiceName == A2OU( "com::sun::star::accessibility::Accessible" ) ||
            rServiceName == A2OU( "com::sun::star::accessibility::AccessibleComponent" ) ||
            rServiceName == A2OU( "com::sun::star::accessibility::AccessibleContext" ) ||
            rServiceName == A2OU( "com::sun::star::accessibility::AccessibleText" );
}

Sequence< OUString > SAL_CALL SmGraphicAccessible::getSupportedServiceNames()
    throw (RuntimeException)
{
    //vos::OGuard aGuard(Application::GetSolarMutex());
    Sequence< OUString > aNames(4);
    OUString *pNames = aNames.getArray();
    pNames[0] = A2OU( "com::sun::star::accessibility::Accessible" );
    pNames[1] = A2OU( "com::sun::star::accessibility::AccessibleComponent" );
    pNames[2] = A2OU( "com::sun::star::accessibility::AccessibleContext" );
    pNames[3] = A2OU( "com::sun::star::accessibility::AccessibleText" );
    return aNames;
}

//////////////////////////////////////////////////////////////////////

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

SmEditSource::SmEditSource( SmEditWindow * /*pWin*/, SmEditAccessible &rAcc ) :
    aViewFwd    (rAcc),
    aTextFwd    (rAcc, *this),
    aEditViewFwd(rAcc),
    rEditAcc (rAcc)
{
}

SmEditSource::SmEditSource( const SmEditSource &rSrc ) :
    SvxEditSource(),
    aViewFwd    (rSrc.rEditAcc),
    aTextFwd    (rSrc.rEditAcc, *this),
    aEditViewFwd(rSrc.rEditAcc),
    rEditAcc	(rSrc.rEditAcc)
{
    //aBroadCaster;     can be completely new
}

SmEditSource::~SmEditSource()
{
}

SvxEditSource* SmEditSource::Clone() const
{
    return new SmEditSource( *this );
}

SvxTextForwarder* SmEditSource::GetTextForwarder()
{
    return &aTextFwd;
}

SvxViewForwarder* SmEditSource::GetViewForwarder()
{
    return &aViewFwd;
}

SvxEditViewForwarder* SmEditSource::GetEditViewForwarder( sal_Bool /*bCreate*/ )
{
    return &aEditViewFwd;
}

void SmEditSource::UpdateData()
{
    // would possibly only by needed if the XText inteface is implemented
    // and its text needs to be updated.
}

SfxBroadcaster & SmEditSource::GetBroadcaster() const
{
    return ((SmEditSource *) this)->aBroadCaster;
}

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

SmViewForwarder::SmViewForwarder( SmEditAccessible &rAcc ) :
    rEditAcc(rAcc)
{
}

SmViewForwarder::~SmViewForwarder()
{
}

sal_Bool SmViewForwarder::IsValid() const
{
    return rEditAcc.GetEditView() != 0;
}

Rectangle SmViewForwarder::GetVisArea() const
{
	EditView *pEditView = rEditAcc.GetEditView();
	OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;

    if( pOutDev && pEditView)
    {
        Rectangle aVisArea = pEditView->GetVisArea();

        // figure out map mode from edit engine
        EditEngine* pEditEngine = pEditView->GetEditEngine();

        if( pEditEngine )
        {
            MapMode aMapMode(pOutDev->GetMapMode());
            aVisArea = OutputDevice::LogicToLogic( aVisArea,
                                                   pEditEngine->GetRefMapMode(),
                                                   aMapMode.GetMapUnit() );
            aMapMode.SetOrigin(Point());
            return pOutDev->LogicToPixel( aVisArea, aMapMode );
        }
    }

    return Rectangle();
}

Point SmViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
{
	EditView *pEditView = rEditAcc.GetEditView();
	OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;

    if( pOutDev )
    {
        MapMode aMapMode(pOutDev->GetMapMode());
        Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
                                                  aMapMode.GetMapUnit() ) );
        aMapMode.SetOrigin(Point());
        return pOutDev->LogicToPixel( aPoint, aMapMode );
    }

    return Point();
}

Point SmViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
{
	EditView *pEditView = rEditAcc.GetEditView();
	OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;

    if( pOutDev )
    {
        MapMode aMapMode(pOutDev->GetMapMode());
        aMapMode.SetOrigin(Point());
        Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) );
        return OutputDevice::LogicToLogic( aPoint,
                                           aMapMode.GetMapUnit(),
                                           rMapMode );
    }

    return Point();
}


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

SmTextForwarder::SmTextForwarder( SmEditAccessible& rAcc, SmEditSource & rSource) :
    rEditAcc ( rAcc ),
    rEditSource (rSource)
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
		pEditEngine->SetNotifyHdl( LINK(this, SmTextForwarder, NotifyHdl) );
}

SmTextForwarder::~SmTextForwarder()
{
    EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    if (pEditEngine)
        pEditEngine->SetNotifyHdl( Link() );
}

IMPL_LINK(SmTextForwarder, NotifyHdl, EENotify*, aNotify)
{
    if (aNotify)
    {
        ::std::auto_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( aNotify );
        if (aHint.get())
            rEditSource.GetBroadcaster().Broadcast( *aHint.get() );
    }

    return 0;
}

sal_uInt16 SmTextForwarder::GetParagraphCount() const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetParagraphCount() : 0;
}

sal_uInt16 SmTextForwarder::GetTextLen( sal_uInt16 nParagraph ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetTextLen( nParagraph ) : 0;
}

String SmTextForwarder::GetText( const ESelection& rSel ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	String aRet;
	if (pEditEngine)
		aRet = pEditEngine->GetText( rSel, LINEEND_LF );
	aRet.ConvertLineEnd();
	return aRet;
}

SfxItemSet SmTextForwarder::GetAttribs( const ESelection& rSel, sal_Bool bOnlyHardAttrib ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	DBG_ASSERT( pEditEngine, "EditEngine missing" );
	if( rSel.nStartPara == rSel.nEndPara )
	{
		sal_uInt8 nFlags = 0;
		switch( bOnlyHardAttrib )
		{
		case EditEngineAttribs_All:
			nFlags = GETATTRIBS_ALL;
			break;
		case EditEngineAttribs_HardAndPara:
			nFlags = GETATTRIBS_PARAATTRIBS|GETATTRIBS_CHARATTRIBS;
			break;
		case EditEngineAttribs_OnlyHard:
			nFlags = GETATTRIBS_CHARATTRIBS;
			break;
		default:
            DBG_ERROR("unknown flags for SmTextForwarder::GetAttribs");
		}

		return pEditEngine->GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags );
	}
	else
	{
		return pEditEngine->GetAttribs( rSel, bOnlyHardAttrib );
	}
}

SfxItemSet SmTextForwarder::GetParaAttribs( sal_uInt16 nPara ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	DBG_ASSERT( pEditEngine, "EditEngine missing" );

	SfxItemSet aSet( pEditEngine->GetParaAttribs( nPara ) );

	sal_uInt16 nWhich = EE_PARA_START;
	while( nWhich <= EE_PARA_END )
	{
		if( aSet.GetItemState( nWhich, sal_True ) != SFX_ITEM_ON )
		{
			if( pEditEngine->HasParaAttrib( nPara, nWhich ) )
				aSet.Put( pEditEngine->GetParaAttrib( nPara, nWhich ) );
		}
		nWhich++;
	}

	return aSet;
}

void SmTextForwarder::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet )
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
		pEditEngine->SetParaAttribs( nPara, rSet );
}

SfxItemPool* SmTextForwarder::GetPool() const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetEmptyItemSet().GetPool() : 0;
}

void SmTextForwarder::RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich )
{
    EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    if (pEditEngine)
        pEditEngine->RemoveAttribs( rSelection, bRemoveParaAttribs, nWhich );
}    

void SmTextForwarder::GetPortions( sal_uInt16 nPara, SvUShorts& rList ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
		pEditEngine->GetPortions( nPara, rList );
}

void SmTextForwarder::QuickInsertText( const String& rText, const ESelection& rSel )
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
		pEditEngine->QuickInsertText( rText, rSel );
}

void SmTextForwarder::QuickInsertLineBreak( const ESelection& rSel )
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
		pEditEngine->QuickInsertLineBreak( rSel );
}

void SmTextForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
		pEditEngine->QuickInsertField( rFld, rSel );
}

void SmTextForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
		pEditEngine->QuickSetAttribs( rSet, rSel );
}

sal_Bool SmTextForwarder::IsValid() const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    // cannot reliably query EditEngine state
    // while in the middle of an update
	return pEditEngine ? pEditEngine->GetUpdateMode() : sal_False;
}

XubString SmTextForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_uInt16 nPara, sal_uInt16 nPos, Color*& rpTxtColor, Color*& rpFldColor )
{
	XubString aTxt;
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
		aTxt = pEditEngine->CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor );
	return aTxt;
}

void SmTextForwarder::FieldClicked(const SvxFieldItem&, sal_uInt16, sal_uInt16)
{
}

sal_uInt16 GetSvxEditEngineItemState( EditEngine& rEditEngine, const ESelection& rSel, sal_uInt16 nWhich )
{
	EECharAttribArray aAttribs;

	const SfxPoolItem*	pLastItem = NULL;

	SfxItemState eState = SFX_ITEM_DEFAULT;

	// check all paragraphs inside the selection
	for( sal_uInt16 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ )
	{
		SfxItemState eParaState = SFX_ITEM_DEFAULT;

		// calculate start and endpos for this paragraph
		sal_uInt16 nPos = 0;
		if( rSel.nStartPara == nPara )
			nPos = rSel.nStartPos;

		sal_uInt16 nEndPos = rSel.nEndPos;
		if( rSel.nEndPara != nPara )
			nEndPos = rEditEngine.GetTextLen( nPara );


		// get list of char attribs
		rEditEngine.GetCharAttribs( nPara, aAttribs );

		sal_Bool bEmpty = sal_True;		// we found no item inside the selektion of this paragraph
		sal_Bool bGaps  = sal_False;	// we found items but theire gaps between them
		sal_uInt16 nLastEnd = nPos;

		const SfxPoolItem* pParaItem = NULL;

		for( sal_uInt16 nAttrib = 0; nAttrib < aAttribs.Count(); nAttrib++ )
		{
			struct EECharAttrib aAttrib = aAttribs.GetObject( nAttrib );
			DBG_ASSERT( aAttrib.pAttr, "GetCharAttribs gives corrupt data" );

			const sal_Bool bEmptyPortion = aAttrib.nStart == aAttrib.nEnd;
			if( (!bEmptyPortion && (aAttrib.nStart >= nEndPos)) || (bEmptyPortion && (aAttrib.nStart > nEndPos)) )
				break;	// break if we are already behind our selektion

			if( (!bEmptyPortion && (aAttrib.nEnd <= nPos)) || (bEmptyPortion && (aAttrib.nEnd < nPos)) )
				continue;	// or if the attribute ends before our selektion

			if( aAttrib.pAttr->Which() != nWhich )
				continue; // skip if is not the searched item

			// if we already found an item
			if( pParaItem )
			{
				// ... and its different to this one than the state is dont care
				if( *pParaItem != *aAttrib.pAttr )
					return SFX_ITEM_DONTCARE;
			}
			else
			{
				pParaItem = aAttrib.pAttr;
			}

			if( bEmpty )
				bEmpty = sal_False;

			if( !bGaps && aAttrib.nStart > nLastEnd )
				bGaps = sal_True;

			nLastEnd = aAttrib.nEnd;
		}

		if( !bEmpty && !bGaps && nLastEnd < ( nEndPos - 1 ) )
			bGaps = sal_True;
/*
		// since we have no portion with our item or if there were gaps
		if( bEmpty || bGaps )
		{
			// we need to check the paragraph item
			const SfxItemSet& rParaSet = rEditEngine.GetParaAttribs( nPara );
			if( rParaSet.GetItemState( nWhich ) == SFX_ITEM_SET )
			{
				eState = SFX_ITEM_SET;
				// get item from the paragraph
				const SfxPoolItem* pTempItem = rParaSet.GetItem( nWhich );
				if( pParaItem )
				{
					if( *pParaItem != *pTempItem )
						return SFX_ITEM_DONTCARE;
				}
				else
				{
					pParaItem = pTempItem;
				}

				// set if theres no last item or if its the same
				eParaState = SFX_ITEM_SET;
			}
			else if( bEmpty )
			{
				eParaState = SFX_ITEM_DEFAULT;
			}
			else if( bGaps )
			{
				// gaps and item not set in paragraph, thats a dont care
				return SFX_ITEM_DONTCARE;
			}
		}
		else
		{
			eParaState = SFX_ITEM_SET;
		}
*/
		if( bEmpty )
			eParaState = SFX_ITEM_DEFAULT;
		else if( bGaps )
			eParaState = SFX_ITEM_DONTCARE;
		else
			eParaState = SFX_ITEM_SET;

		// if we already found an item check if we found the same
		if( pLastItem )
		{
			if( (pParaItem == NULL) || (*pLastItem != *pParaItem) )
				return SFX_ITEM_DONTCARE;
		}
		else
		{
			pLastItem = pParaItem;
			eState = eParaState;
		}
	}

	return eState;
}

sal_uInt16 SmTextForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
{
	sal_uInt16 nState = SFX_ITEM_DISABLED;
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
		nState = GetSvxEditEngineItemState( *pEditEngine, rSel, nWhich );
	return nState;
}

sal_uInt16 SmTextForwarder::GetItemState( sal_uInt16 nPara, sal_uInt16 nWhich ) const
{
	sal_uInt16 nState = SFX_ITEM_DISABLED;
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
	{
		const SfxItemSet& rSet = pEditEngine->GetParaAttribs( nPara );
		nState = rSet.GetItemState( nWhich );
	}
	return nState;
}

LanguageType SmTextForwarder::GetLanguage( sal_uInt16 nPara, sal_uInt16 nIndex ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetLanguage(nPara, nIndex) : LANGUAGE_NONE;
}

sal_uInt16 SmTextForwarder::GetFieldCount( sal_uInt16 nPara ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetFieldCount(nPara) : 0;
}

EFieldInfo SmTextForwarder::GetFieldInfo( sal_uInt16 nPara, sal_uInt16 nField ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetFieldInfo( nPara, nField ) : EFieldInfo();
}

EBulletInfo SmTextForwarder::GetBulletInfo( sal_uInt16 /*nPara*/ ) const
{
    return EBulletInfo();
}

Rectangle SmTextForwarder::GetCharBounds( sal_uInt16 nPara, sal_uInt16 nIndex ) const
{
	Rectangle aRect(0,0,0,0);
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    
	if (pEditEngine)
	{
		// #108900# Handle virtual position one-past-the end of the string
		if( nIndex >= pEditEngine->GetTextLen(nPara) )
		{
			if( nIndex )
				aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex-1) );

			aRect.Move( aRect.Right() - aRect.Left(), 0 );
			aRect.SetSize( Size(1, pEditEngine->GetTextHeight()) );
		}
		else
		{
			aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex) );
	    }
	}
	return aRect;
}

Rectangle SmTextForwarder::GetParaBounds( sal_uInt16 nPara ) const
{
	Rectangle aRect(0,0,0,0);
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	
	if (pEditEngine)
	{
		const Point aPnt = pEditEngine->GetDocPosTopLeft( nPara );
		const sal_uLong nWidth = pEditEngine->CalcTextWidth();
		const sal_uLong nHeight = pEditEngine->GetTextHeight( nPara );
		aRect = Rectangle( aPnt.X(), aPnt.Y(), aPnt.X() + nWidth, aPnt.Y() + nHeight );
	}

    return aRect;
}

MapMode SmTextForwarder::GetMapMode() const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetRefMapMode() : MapMode( MAP_100TH_MM );
}

OutputDevice* SmTextForwarder::GetRefDevice() const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetRefDevice() : 0;
}

sal_Bool SmTextForwarder::GetIndexAtPoint( const Point& rPos, sal_uInt16& nPara, sal_uInt16& nIndex ) const
{
	sal_Bool bRes = sal_False;
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
	{
		EPosition aDocPos = pEditEngine->FindDocPosition( rPos );
		nPara	= aDocPos.nPara;
		nIndex	= aDocPos.nIndex;
		bRes = sal_True;
	}
	return bRes;
}

sal_Bool SmTextForwarder::GetWordIndices( sal_uInt16 nPara, sal_uInt16 nIndex, sal_uInt16& nStart, sal_uInt16& nEnd ) const
{
	sal_Bool bRes = sal_False;
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
	{
		ESelection aRes = pEditEngine->GetWord( ESelection(nPara, nIndex, nPara, nIndex), com::sun::star::i18n::WordType::DICTIONARY_WORD );

		if( aRes.nStartPara == nPara &&
			aRes.nStartPara == aRes.nEndPara )
		{
			nStart = aRes.nStartPos;
			nEnd = aRes.nEndPos;

			bRes = sal_True;
	    }
	}

    return bRes;
}

sal_Bool SmTextForwarder::GetAttributeRun( sal_uInt16& nStartIndex, sal_uInt16& nEndIndex, sal_uInt16 nPara, sal_uInt16 nIndex, sal_Bool bInCell ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    return pEditEngine ? 
		SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, *pEditEngine, nPara, nIndex, bInCell )
		: sal_False;
}

sal_uInt16 SmTextForwarder::GetLineCount( sal_uInt16 nPara ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetLineCount(nPara) : 0;
}

sal_uInt16 SmTextForwarder::GetLineLen( sal_uInt16 nPara, sal_uInt16 nLine ) const
{
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	return pEditEngine ? pEditEngine->GetLineLen(nPara, nLine) : 0;
}
    
void SmTextForwarder::GetLineBoundaries( /*out*/sal_uInt16 &rStart, /*out*/sal_uInt16 &rEnd, sal_uInt16 nPara, sal_uInt16 nLine ) const
{
    EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    pEditEngine->GetLineBoundaries(rStart, rEnd, nPara, nLine);
}    

sal_uInt16 SmTextForwarder::GetLineNumberAtIndex( sal_uInt16 nPara, sal_uInt16 nIndex ) const
{
    EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    return pEditEngine ? pEditEngine->GetLineNumberAtIndex(nPara, nIndex) : 0;
}    

sal_Bool SmTextForwarder::QuickFormatDoc( sal_Bool /*bFull*/ )
{
	sal_Bool bRes = sal_False;
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
	{
		pEditEngine->QuickFormatDoc();
		bRes = sal_True;
	}
    return bRes;
}

sal_Int16 SmTextForwarder::GetDepth( sal_uInt16 /*nPara*/ ) const
{
    // math has no outliner...
    return -1;
}

sal_Bool SmTextForwarder::SetDepth( sal_uInt16 /*nPara*/, sal_Int16 nNewDepth )
{
    // math has no outliner...
    return -1 == nNewDepth;  // is it the value from 'GetDepth' ?
}

sal_Bool SmTextForwarder::Delete( const ESelection& rSelection )
{
	sal_Bool bRes = sal_False;
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
	{
		pEditEngine->QuickDelete( rSelection );
		pEditEngine->QuickFormatDoc();
		bRes = sal_True;
	}
	return bRes;
}

sal_Bool SmTextForwarder::InsertText( const String& rStr, const ESelection& rSelection )
{
	sal_Bool bRes = sal_False;
	EditEngine *pEditEngine = rEditAcc.GetEditEngine();
	if (pEditEngine)
	{
		pEditEngine->QuickInsertText( rStr, rSelection );
		pEditEngine->QuickFormatDoc();
		bRes = sal_True;
	}
	return bRes;
}

const SfxItemSet*   SmTextForwarder::GetEmptyItemSetPtr()
{
    const SfxItemSet *pItemSet = 0;
    EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    if (pEditEngine)
    {
        pItemSet = &pEditEngine->GetEmptyItemSet();
    }
    return pItemSet;
}

void SmTextForwarder::AppendParagraph()
{
    // append an empty paragraph
    EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    if (pEditEngine)
    {
        sal_uInt16 nParaCount = pEditEngine->GetParagraphCount();
        pEditEngine->InsertParagraph( nParaCount, String() );
    }
}

xub_StrLen SmTextForwarder::AppendTextPortion( sal_uInt16 nPara, const String &rText, const SfxItemSet &rSet )
{
    xub_StrLen nRes = 0;
    EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    if (pEditEngine && nPara < pEditEngine->GetParagraphCount())
    {
        // append text
        ESelection aSel( nPara, pEditEngine->GetTextLen( nPara ) );
        pEditEngine->QuickInsertText( rText, aSel );
        
        // set attributes for new appended text
        nRes = aSel.nEndPos = pEditEngine->GetTextLen( nPara );
        pEditEngine->QuickSetAttribs( rSet, aSel );
    }
    return nRes;
}

void SmTextForwarder::CopyText(const SvxTextForwarder& rSource)
{
    
    const SmTextForwarder* pSourceForwarder = dynamic_cast< const SmTextForwarder* >( &rSource );
    if( !pSourceForwarder )
        return;
    EditEngine* pSourceEditEngine = pSourceForwarder->rEditAcc.GetEditEngine();
    EditEngine *pEditEngine = rEditAcc.GetEditEngine();
    if (pEditEngine && pSourceEditEngine )
    {
        EditTextObject* pNewTextObject = pSourceEditEngine->CreateTextObject();
        pEditEngine->SetText( *pNewTextObject );
        delete pNewTextObject;
    }
}    

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

SmEditViewForwarder::SmEditViewForwarder( SmEditAccessible& rAcc ) :
    rEditAcc( rAcc )
{
}

SmEditViewForwarder::~SmEditViewForwarder()
{
}

sal_Bool SmEditViewForwarder::IsValid() const
{
    return rEditAcc.GetEditView() != 0;
}

Rectangle SmEditViewForwarder::GetVisArea() const
{
	Rectangle aRect(0,0,0,0);

	EditView *pEditView = rEditAcc.GetEditView();
	OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;

    if( pOutDev && pEditView)
    {
        Rectangle aVisArea = pEditView->GetVisArea();

        // figure out map mode from edit engine
        EditEngine* pEditEngine = pEditView->GetEditEngine();

        if( pEditEngine )
        {
            MapMode aMapMode(pOutDev->GetMapMode());
            aVisArea = OutputDevice::LogicToLogic( aVisArea,
                                                   pEditEngine->GetRefMapMode(),
                                                   aMapMode.GetMapUnit() );
            aMapMode.SetOrigin(Point());
            aRect = pOutDev->LogicToPixel( aVisArea, aMapMode );
        }
    }

    return aRect;
}

Point SmEditViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
{
	EditView *pEditView = rEditAcc.GetEditView();
	OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;

    if( pOutDev )
    {
        MapMode aMapMode(pOutDev->GetMapMode());
        Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
                                                  aMapMode.GetMapUnit() ) );
        aMapMode.SetOrigin(Point());
        return pOutDev->LogicToPixel( aPoint, aMapMode );
    }

    return Point();
}

Point SmEditViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
{
	EditView *pEditView = rEditAcc.GetEditView();
	OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;

    if( pOutDev )
    {
        MapMode aMapMode(pOutDev->GetMapMode());
        aMapMode.SetOrigin(Point());
        Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) );
        return OutputDevice::LogicToLogic( aPoint,
                                           aMapMode.GetMapUnit(),
                                           rMapMode );
    }

    return Point();
}

sal_Bool SmEditViewForwarder::GetSelection( ESelection& rSelection ) const
{
	sal_Bool bRes = sal_False;
	EditView *pEditView = rEditAcc.GetEditView();
	if (pEditView)
	{
		rSelection = pEditView->GetSelection();
		bRes = sal_True;
	}
    return bRes;
}

sal_Bool SmEditViewForwarder::SetSelection( const ESelection& rSelection )
{
	sal_Bool bRes = sal_False;
	EditView *pEditView = rEditAcc.GetEditView();
	if (pEditView)
	{
		pEditView->SetSelection( rSelection );
		bRes = sal_True;
	}
	return bRes;
}

sal_Bool SmEditViewForwarder::Copy()
{
	sal_Bool bRes = sal_False;
	EditView *pEditView = rEditAcc.GetEditView();
	if (pEditView)
	{
		pEditView->Copy();
		bRes = sal_True;
	}
	return bRes;
}

sal_Bool SmEditViewForwarder::Cut()
{
	sal_Bool bRes = sal_False;
	EditView *pEditView = rEditAcc.GetEditView();
	if (pEditView)
	{
		pEditView->Cut();
		bRes = sal_True;
	}
	return bRes;
}

sal_Bool SmEditViewForwarder::Paste()
{
	sal_Bool bRes = sal_False;
	EditView *pEditView = rEditAcc.GetEditView();
	if (pEditView)
	{
		pEditView->Paste();
		bRes = sal_True;
	}
	return bRes;
}

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

SmEditAccessible::SmEditAccessible( SmEditWindow *pEditWin ) :
    aAccName            ( String(SmResId(STR_CMDBOXWINDOW)) ),
    pTextHelper         (0),
    pWin                (pEditWin)
{
    DBG_ASSERT( pWin, "SmEditAccessible: window missing" );
    //++aRefCount;
}


SmEditAccessible::SmEditAccessible( const SmEditAccessible &rSmAcc ) :
    SmEditAccessibleBaseClass(),
    aAccName            ( String(SmResId(STR_CMDBOXWINDOW)) )
{
    //vos::OGuard aGuard(Application::GetSolarMutex());
    pWin = rSmAcc.pWin;
    DBG_ASSERT( pWin, "SmEditAccessible: window missing" );
    //++aRefCount;
}

SmEditAccessible::~SmEditAccessible()
{
    delete pTextHelper;
/*
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (--aRefCount == 0)
    {
    }
*/
}

void SmEditAccessible::Init()
{
    DBG_ASSERT( pWin, "SmEditAccessible: window missing" );
    if (pWin)
    {
        EditEngine *pEditEngine = pWin->GetEditEngine();
        EditView   *pEditView   = pWin->GetEditView();
        if (pEditEngine && pEditView)
        {
            ::std::auto_ptr< SvxEditSource > pEditSource(
                    new SmEditSource( pWin, *this ) );
            pTextHelper = new ::accessibility::AccessibleTextHelper( pEditSource );
            pTextHelper->SetEventSource( this );
        }
    }
}

#ifdef TL_NOT_YET_USED
SmDocShell * SmEditAccessible::GetDoc_Impl()
{
    SmViewShell *pView = pWin ? pWin->GetView() : 0;
    return pView ? pView->GetDoc() : 0;
}
#endif // TL_NOT_YET_USED

void SmEditAccessible::ClearWin()
{
	// #112565# remove handler before current object gets destroyed
	// (avoid handler being called for already dead object)
	EditEngine *pEditEngine = GetEditEngine();
	if (pEditEngine)
		pEditEngine->SetNotifyHdl( Link() );

	pWin = 0;   // implicitly results in AccessibleStateType::DEFUNC set

    //! make TextHelper implicitly release C++ references to some core objects
    pTextHelper->SetEditSource( ::std::auto_ptr<SvxEditSource>(NULL) );
    //! make TextHelper release references
    //! (e.g. the one set by the 'SetEventSource' call)
    pTextHelper->Dispose();
    delete pTextHelper;     pTextHelper = 0;
}

// XAccessible
uno::Reference< XAccessibleContext > SAL_CALL SmEditAccessible::getAccessibleContext(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return this;
}

// XAccessibleComponent
sal_Bool SAL_CALL SmEditAccessible::containsPoint( const awt::Point& aPoint )
    throw (RuntimeException)
{
    //! the arguments coordinates are relativ to the current window !
    //! Thus the top left-point is (0, 0)

	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();

    Size aSz( pWin->GetSizePixel() );
    return  aPoint.X >= 0  &&  aPoint.Y >= 0  &&
            aPoint.X < aSz.Width()  &&  aPoint.Y < aSz.Height();
}

uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleAtPoint( const awt::Point& aPoint )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pTextHelper)
        throw RuntimeException();
    return pTextHelper->GetAt( aPoint );
}

awt::Rectangle SAL_CALL SmEditAccessible::getBounds(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();
    DBG_ASSERT(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
            "mismatch of window parent and accessible parent" );
    return lcl_GetBounds( pWin );
}

awt::Point SAL_CALL SmEditAccessible::getLocation(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();
    DBG_ASSERT(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
            "mismatch of window parent and accessible parent" );
    awt::Rectangle aRect( lcl_GetBounds( pWin ) );
    return awt::Point( aRect.X, aRect.Y );
}

awt::Point SAL_CALL SmEditAccessible::getLocationOnScreen(  )
    throw (RuntimeException)
{
    vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();
    DBG_ASSERT(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
            "mismatch of window parent and accessible parent" );
    return lcl_GetLocationOnScreen( pWin );
}

awt::Size SAL_CALL SmEditAccessible::getSize(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();
    DBG_ASSERT(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
            "mismatch of window parent and accessible parent" );

    Size aSz( pWin->GetSizePixel() );
#if OSL_DEBUG_LEVEL > 1
    awt::Rectangle aRect( lcl_GetBounds( pWin ) );
    Size aSz2( aRect.Width, aRect.Height );
    DBG_ASSERT( aSz == aSz2, "mismatch in width" );
#endif
    return awt::Size( aSz.Width(), aSz.Height() );
}

void SAL_CALL SmEditAccessible::grabFocus(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();

    pWin->GrabFocus();
}

sal_Int32 SAL_CALL SmEditAccessible::getForeground()
    throw (RuntimeException)
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    if (!pWin)
        throw RuntimeException();
    return (sal_Int32) pWin->GetTextColor().GetColor();
}

sal_Int32 SAL_CALL SmEditAccessible::getBackground()
    throw (RuntimeException)
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    if (!pWin)
        throw RuntimeException();
    Wallpaper aWall( pWin->GetDisplayBackground() );
    ColorData nCol;
    if (aWall.IsBitmap() || aWall.IsGradient())
        nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor().GetColor();
    else
        nCol = aWall.GetColor().GetColor();
    return (sal_Int32) nCol;
}

// XAccessibleContext
sal_Int32 SAL_CALL SmEditAccessible::getAccessibleChildCount(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pTextHelper)
        throw RuntimeException();
    return pTextHelper->GetChildCount();
}

uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleChild( sal_Int32 i )
    throw (IndexOutOfBoundsException, RuntimeException)
{
    vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pTextHelper)
        throw RuntimeException();
    return pTextHelper->GetChild( i );
}

uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleParent(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    if (!pWin)
        throw RuntimeException();

    Window *pAccParent = pWin->GetAccessibleParentWindow();
    DBG_ASSERT( pAccParent, "accessible parent missing" );
    return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >();
}

sal_Int32 SAL_CALL SmEditAccessible::getAccessibleIndexInParent(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    sal_Int32 nIdx = -1;
    Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : 0;
    if (pAccParent)
    {
        sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount();
        for (sal_uInt16 i = 0;  i < nCnt  &&  nIdx == -1;  ++i)
            if (pAccParent->GetAccessibleChildWindow( i ) == pWin)
                nIdx = i;
    }
    return nIdx;
}

sal_Int16 SAL_CALL SmEditAccessible::getAccessibleRole(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return AccessibleRole::PANEL /*TEXT ?*/;
}

rtl::OUString SAL_CALL SmEditAccessible::getAccessibleDescription(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    return OUString();  // empty as agreed with product-management
}

rtl::OUString SAL_CALL SmEditAccessible::getAccessibleName(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    // same name as displayed by the window when not docked
    return aAccName;
}

uno::Reference< XAccessibleRelationSet > SAL_CALL SmEditAccessible::getAccessibleRelationSet(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper();
    return xRelSet;   // empty relation set
}

uno::Reference< XAccessibleStateSet > SAL_CALL SmEditAccessible::getAccessibleStateSet(  )
    throw (RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
	::utl::AccessibleStateSetHelper *pStateSet =
            new ::utl::AccessibleStateSetHelper;

	Reference<XAccessibleStateSet> xStateSet( pStateSet );

    if (!pWin || !pTextHelper)
        pStateSet->AddState( AccessibleStateType::DEFUNC );
    else
    {
        //pStateSet->AddState( AccessibleStateType::EDITABLE );
        pStateSet->AddState( AccessibleStateType::MULTI_LINE );
        //pStateSet->AddState( AccessibleStateType::HORIZONTAL );
        //pStateSet->AddState( AccessibleStateType::TRANSIENT );
        pStateSet->AddState( AccessibleStateType::ENABLED );
        pStateSet->AddState( AccessibleStateType::FOCUSABLE );
        if (pWin->HasFocus())
            pStateSet->AddState( AccessibleStateType::FOCUSED );
        if (pWin->IsActive())
            pStateSet->AddState( AccessibleStateType::ACTIVE );
        if (pWin->IsVisible())
            pStateSet->AddState( AccessibleStateType::SHOWING );
        if (pWin->IsReallyVisible())
            pStateSet->AddState( AccessibleStateType::VISIBLE );
        if (COL_TRANSPARENT != pWin->GetBackground().GetColor().GetColor())
            pStateSet->AddState( AccessibleStateType::OPAQUE );
    }

	return xStateSet;
}

Locale SAL_CALL SmEditAccessible::getLocale(  )
    throw (IllegalAccessibleComponentStateException, RuntimeException)
{
	vos::OGuard aGuard(Application::GetSolarMutex());
    // should be the document language...
    // We use the language of the localized symbol names here.
    return Application::GetSettings().GetUILocale();
}


// XAccessibleEventBroadcaster
void SAL_CALL SmEditAccessible::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
    throw (RuntimeException)
{
    //vos::OGuard aGuard(Application::GetSolarMutex());   if (pTextHelper)   // not disposing (about to destroy view shell)
        pTextHelper->AddEventListener( xListener );
}

void SAL_CALL SmEditAccessible::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
    throw (RuntimeException)
{
    //vos::OGuard aGuard(Application::GetSolarMutex());
   if (pTextHelper)   // not disposing (about to destroy view shell)
        pTextHelper->RemoveEventListener( xListener );
}

OUString SAL_CALL SmEditAccessible::getImplementationName()
    throw (RuntimeException)
{
    //vos::OGuard aGuard(Application::GetSolarMutex());
    return A2OU("SmEditAccessible");
}

sal_Bool SAL_CALL SmEditAccessible::supportsService(
        const OUString& rServiceName )
    throw (RuntimeException)
{
    //vos::OGuard aGuard(Application::GetSolarMutex());
    return  rServiceName == A2OU( "com::sun::star::accessibility::Accessible" ) ||
            rServiceName == A2OU( "com::sun::star::accessibility::AccessibleComponent" ) ||
            rServiceName == A2OU( "com::sun::star::accessibility::AccessibleContext" );
}

Sequence< OUString > SAL_CALL SmEditAccessible::getSupportedServiceNames()
    throw (RuntimeException)
{
    //vos::OGuard aGuard(Application::GetSolarMutex());
    Sequence< OUString > aNames(3);
    OUString *pNames = aNames.getArray();
    pNames[0] = A2OU( "com::sun::star::accessibility::Accessible" );
    pNames[1] = A2OU( "com::sun::star::accessibility::AccessibleComponent" );
    pNames[2] = A2OU( "com::sun::star::accessibility::AccessibleContext" );
    return aNames;
}

//////////////////////////////////////////////////////////////////////

