summaryrefslogtreecommitdiff
path: root/sw/source/core/access
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/access')
-rw-r--r--sw/source/core/access/acccell.cxx378
-rw-r--r--sw/source/core/access/acccell.hxx139
-rw-r--r--sw/source/core/access/acccontext.cxx1607
-rw-r--r--sw/source/core/access/acccontext.hxx461
-rw-r--r--sw/source/core/access/accdoc.cxx516
-rw-r--r--sw/source/core/access/accdoc.hxx213
-rw-r--r--sw/source/core/access/accembedded.cxx100
-rw-r--r--sw/source/core/access/accembedded.hxx72
-rw-r--r--sw/source/core/access/accfootnote.cxx158
-rw-r--r--sw/source/core/access/accfootnote.hxx90
-rw-r--r--sw/source/core/access/accframe.cxx499
-rw-r--r--sw/source/core/access/accframe.hxx177
-rw-r--r--sw/source/core/access/accframebase.cxx280
-rw-r--r--sw/source/core/access/accframebase.hxx75
-rw-r--r--sw/source/core/access/accfrmobj.cxx430
-rw-r--r--sw/source/core/access/accfrmobj.hxx98
-rw-r--r--sw/source/core/access/accfrmobjmap.cxx171
-rw-r--r--sw/source/core/access/accfrmobjmap.hxx98
-rw-r--r--sw/source/core/access/accfrmobjslist.cxx175
-rw-r--r--sw/source/core/access/accfrmobjslist.hxx148
-rw-r--r--sw/source/core/access/accgraphic.cxx100
-rw-r--r--sw/source/core/access/accgraphic.hxx72
-rw-r--r--sw/source/core/access/accheaderfooter.cxx146
-rw-r--r--sw/source/core/access/accheaderfooter.hxx85
-rw-r--r--sw/source/core/access/acchyperlink.cxx192
-rw-r--r--sw/source/core/access/acchyperlink.hxx93
-rw-r--r--sw/source/core/access/acchypertextdata.cxx58
-rw-r--r--sw/source/core/access/acchypertextdata.hxx53
-rw-r--r--sw/source/core/access/accmap.cxx2789
-rw-r--r--sw/source/core/access/accnotextframe.cxx278
-rw-r--r--sw/source/core/access/accnotextframe.hxx113
-rw-r--r--sw/source/core/access/accpage.cxx201
-rw-r--r--sw/source/core/access/accpage.hxx99
-rw-r--r--sw/source/core/access/accpara.cxx2680
-rw-r--r--sw/source/core/access/accpara.hxx451
-rw-r--r--sw/source/core/access/accportions.cxx754
-rw-r--r--sw/source/core/access/accportions.hxx177
-rw-r--r--sw/source/core/access/accpreview.cxx105
-rw-r--r--sw/source/core/access/accpreview.hxx78
-rw-r--r--sw/source/core/access/accselectionhelper.cxx337
-rw-r--r--sw/source/core/access/accselectionhelper.hxx83
-rw-r--r--sw/source/core/access/acctable.cxx1806
-rw-r--r--sw/source/core/access/acctable.hxx335
-rw-r--r--sw/source/core/access/acctextframe.cxx281
-rw-r--r--sw/source/core/access/acctextframe.hxx118
-rw-r--r--sw/source/core/access/makefile.mk100
-rw-r--r--sw/source/core/access/parachangetrackinginfo.cxx234
-rw-r--r--sw/source/core/access/parachangetrackinginfo.hxx61
-rw-r--r--sw/source/core/access/textmarkuphelper.cxx234
-rw-r--r--sw/source/core/access/textmarkuphelper.hxx89
50 files changed, 18087 insertions, 0 deletions
diff --git a/sw/source/core/access/acccell.cxx b/sw/source/core/access/acccell.cxx
new file mode 100644
index 000000000000..dbd1b5196593
--- /dev/null
+++ b/sw/source/core/access/acccell.cxx
@@ -0,0 +1,378 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <osl/mutex.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <rtl/uuid.h>
+#include <vcl/svapp.hxx>
+#include <cellfrm.hxx>
+#include <tabfrm.hxx>
+#include <swtable.hxx>
+#include "crsrsh.hxx"
+#include "viscrs.hxx"
+#include <accfrmobj.hxx>
+#include <accfrmobjslist.hxx>
+#include "frmfmt.hxx"
+#include "cellatr.hxx"
+#include "accmap.hxx"
+#include <acccell.hxx>
+
+#ifndef _STLP_CFLOAT
+#include <cfloat>
+#endif
+
+#include <limits.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+using namespace sw::access;
+
+const sal_Char sServiceName[] = "com.sun.star.table.AccessibleCellView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleCellView";
+
+sal_Bool SwAccessibleCell::IsSelected()
+{
+ sal_Bool bRet = sal_False;
+
+ DBG_ASSERT( GetMap(), "no map?" );
+ const ViewShell *pVSh = GetMap()->GetShell();
+ DBG_ASSERT( pVSh, "no shell?" );
+ if( pVSh->ISA( SwCrsrShell ) )
+ {
+ const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
+ if( pCSh->IsTableMode() )
+ {
+ const SwCellFrm *pCFrm =
+ static_cast< const SwCellFrm * >( GetFrm() );
+ SwTableBox *pBox =
+ const_cast< SwTableBox *>( pCFrm->GetTabBox() ); //SVPtrArr!
+ bRet = pCSh->GetTableCrsr()->GetBoxes().Seek_Entry( pBox );
+ }
+ }
+
+ return bRet;
+}
+
+void SwAccessibleCell::GetStates( ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // SELECTABLE
+ const ViewShell *pVSh = GetMap()->GetShell();
+ DBG_ASSERT( pVSh, "no shell?" );
+ if( pVSh->ISA( SwCrsrShell ) )
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+
+ // SELECTED
+ if( IsSelected() )
+ {
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+ OSL_ENSURE( bIsSelected, "bSelected out of sync" );
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+}
+
+SwAccessibleCell::SwAccessibleCell( SwAccessibleMap *pInitMap,
+ const SwCellFrm *pCellFrm )
+ : SwAccessibleContext( pInitMap, AccessibleRole::TABLE_CELL, pCellFrm )
+ , bIsSelected( sal_False )
+{
+ SolarMutexGuard aGuard;
+ OUString sBoxName( pCellFrm->GetTabBox()->GetName() );
+ SetName( sBoxName );
+
+ bIsSelected = IsSelected();
+}
+
+sal_Bool SwAccessibleCell::_InvalidateMyCursorPos()
+{
+ sal_Bool bNew = IsSelected();
+ sal_Bool bOld;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bOld = bIsSelected;
+ bIsSelected = bNew;
+ }
+ if( bNew )
+ {
+ // remember that object as the one that has the caret. This is
+ // neccessary to notify that object if the cursor leaves it.
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ sal_Bool bChanged = bOld != bNew;
+ if( bChanged )
+ FireStateChangedEvent( AccessibleStateType::SELECTED, bNew );
+
+ return bChanged;
+}
+
+sal_Bool SwAccessibleCell::_InvalidateChildrenCursorPos( const SwFrm *pFrm )
+{
+ sal_Bool bChanged = sal_False;
+
+ const SwAccessibleChildSList aVisList( GetVisArea(), *pFrm, *GetMap() );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ if( rLower.IsAccessible( GetMap()->GetShell()->IsPreView() ) )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pLower, sal_False ) );
+ if( xAccImpl.is() )
+ {
+ OSL_ENSURE( xAccImpl->GetFrm()->IsCellFrm(),
+ "table child is not a cell frame" );
+ bChanged |= static_cast< SwAccessibleCell *>(
+ xAccImpl.get() )->_InvalidateMyCursorPos();
+ }
+ else
+ bChanged = sal_True; // If the context is not know we
+ // don't know whether the selection
+ // changed or not.
+ }
+ else
+ {
+ // This is a box with sub rows.
+ bChanged |= _InvalidateChildrenCursorPos( pLower );
+ }
+ }
+ ++aIter;
+ }
+
+ return bChanged;
+}
+
+void SwAccessibleCell::_InvalidateCursorPos()
+{
+
+ const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
+ OSL_ENSURE( pParent->IsTabFrm(), "parent is not a tab frame" );
+ const SwTabFrm *pTabFrm = static_cast< const SwTabFrm * >( pParent );
+ if( pTabFrm->IsFollow() )
+ pTabFrm = pTabFrm->FindMaster();
+
+ while( pTabFrm )
+ {
+ sal_Bool bChanged = _InvalidateChildrenCursorPos( pTabFrm );
+ if( bChanged )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pTabFrm, sal_False ) );
+ if( xAccImpl.is() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
+ xAccImpl->FireAccessibleEvent( aEvent );
+ }
+ }
+
+ pTabFrm = pTabFrm->GetFollow();
+ }
+}
+
+sal_Bool SwAccessibleCell::HasCursor()
+{
+ osl::MutexGuard aGuard( aMutex );
+ return bIsSelected;
+}
+
+SwAccessibleCell::~SwAccessibleCell()
+{
+}
+
+OUString SAL_CALL SwAccessibleCell::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ return GetName();
+}
+
+OUString SAL_CALL SwAccessibleCell::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleCell::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleCell::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+void SwAccessibleCell::Dispose( sal_Bool bRecursive )
+{
+ const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
+ ::rtl::Reference< SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pParent, sal_False ) );
+ if( xAccImpl.is() )
+ xAccImpl->DisposeChild( SwAccessibleChild(GetFrm()), bRecursive );
+ SwAccessibleContext::Dispose( bRecursive );
+}
+
+void SwAccessibleCell::InvalidatePosOrSize( const SwRect& rOldBox )
+{
+ const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
+ ::rtl::Reference< SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pParent, sal_False ) );
+ if( xAccImpl.is() )
+ xAccImpl->InvalidateChildPosOrSize( SwAccessibleChild(GetFrm()), rOldBox );
+ SwAccessibleContext::InvalidatePosOrSize( rOldBox );
+}
+
+
+// ===== XAccessibleInterface ===========================================
+
+uno::Any SwAccessibleCell::queryInterface( const uno::Type& rType )
+ throw( uno::RuntimeException )
+{
+ if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) ) )
+ {
+ uno::Reference<XAccessibleValue> xValue = this;
+ uno::Any aRet;
+ aRet <<= xValue;
+ return aRet;
+ }
+ else
+ {
+ return SwAccessibleContext::queryInterface( rType );
+ }
+}
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleCell::getTypes()
+ throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ aTypes.realloc( nIndex + 1 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) );
+
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleCell::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+// ===== XAccessibleValue ===============================================
+
+SwFrmFmt* SwAccessibleCell::GetTblBoxFormat() const
+{
+ DBG_ASSERT( GetFrm() != NULL, "no frame?" );
+ DBG_ASSERT( GetFrm()->IsCellFrm(), "no cell frame?" );
+
+ const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>( GetFrm() );
+ return pCellFrm->GetTabBox()->GetFrmFmt();
+}
+
+
+uno::Any SwAccessibleCell::getCurrentValue( )
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleValue );
+
+ uno::Any aAny;
+ aAny <<= GetTblBoxFormat()->GetTblBoxValue().GetValue();
+ return aAny;
+}
+
+sal_Bool SwAccessibleCell::setCurrentValue( const uno::Any& aNumber )
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleValue );
+
+ double fValue = 0;
+ sal_Bool bValid = (aNumber >>= fValue);
+ if( bValid )
+ {
+ SwTblBoxValue aValue( fValue );
+ GetTblBoxFormat()->SetFmtAttr( aValue );
+ }
+ return bValid;
+}
+
+uno::Any SwAccessibleCell::getMaximumValue( )
+ throw( uno::RuntimeException )
+{
+ uno::Any aAny;
+ aAny <<= DBL_MAX;
+ return aAny;
+}
+
+uno::Any SwAccessibleCell::getMinimumValue( )
+ throw( uno::RuntimeException )
+{
+ uno::Any aAny;
+ aAny <<= -DBL_MAX;
+ return aAny;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acccell.hxx b/sw/source/core/access/acccell.hxx
new file mode 100644
index 000000000000..05385a40dbac
--- /dev/null
+++ b/sw/source/core/access/acccell.hxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCCELL_HXX
+#define _ACCCELL_HXX
+
+#include "acccontext.hxx"
+#include <com/sun/star/accessibility/XAccessibleValue.hpp>
+
+class SwCellFrm;
+class SwFrmFmt;
+
+class SwAccessibleCell : public SwAccessibleContext,
+ ::com::sun::star::accessibility::XAccessibleValue
+
+{
+ sal_Bool bIsSelected; // protected by base class mutex
+
+ sal_Bool IsSelected();
+
+ sal_Bool _InvalidateMyCursorPos();
+ sal_Bool _InvalidateChildrenCursorPos( const SwFrm *pFrm );
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additionaly sets SELECTABLE(1) and SELECTED(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual void _InvalidateCursorPos();
+
+ virtual ~SwAccessibleCell();
+
+public:
+
+ SwAccessibleCell( SwAccessibleMap* pInitMap, const SwCellFrm *pCellFrm );
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+
+ virtual void InvalidatePosOrSize( const SwRect& rFrm );
+
+ //===== XInterface ======================================================
+
+ // (XInterface methods need to be implemented to disambiguate
+ // between those inherited through SwAcessibleContext and
+ // XAccessibleValue).
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleValue ================================================
+
+private:
+ SwFrmFmt* GetTblBoxFormat() const;
+
+public:
+ virtual ::com::sun::star::uno::Any SAL_CALL getCurrentValue( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL setCurrentValue(
+ const ::com::sun::star::uno::Any& aNumber )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Any SAL_CALL getMaximumValue( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Any SAL_CALL getMinimumValue( )
+ throw (::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acccontext.cxx b/sw/source/core/access/acccontext.cxx
new file mode 100644
index 000000000000..127820fe1ffa
--- /dev/null
+++ b/sw/source/core/access/acccontext.cxx
@@ -0,0 +1,1607 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
+ #ifndef _STRING_HXX
+ #include <tools/string.hxx>
+ #endif
+
+ #ifndef _STREAM_HXX
+ #include <tools/stream.hxx>
+ #endif
+#endif // #if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
+#include <tools/debug.hxx>
+#include <vcl/window.hxx>
+#include <errhdl.hxx>
+#include <swtypes.hxx>
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <viewsh.hxx>
+#include <crsrsh.hxx>
+#include <fesh.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <pagefrm.hxx>
+#include <flyfrm.hxx>
+#include <dflyobj.hxx>
+#include <pam.hxx>
+#include <viewimp.hxx>
+#include <accmap.hxx>
+#include <accfrmobjslist.hxx>
+#include <acccontext.hxx>
+#include <svx/AccessibleShape.hxx>
+#include <comphelper/accessibleeventnotifier.hxx>
+#include <PostItMgr.hxx>
+
+using namespace sw::access;
+
+#if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
+#define DBG_MSG( _msg ) \
+ lcl_SwAccessibleContext_DbgMsg( this, _msg, 0, sal_False );
+#define DBG_MSG_CD( _msg ) \
+ lcl_SwAccessibleContext_DbgMsg( this, _msg, 0, sal_True );
+#define DBG_MSG_PARAM( _msg, _param ) \
+ lcl_SwAccessibleContext_DbgMsg( this, _msg, _param, sal_False );
+#define DBG_MSG_THIS_PARAM( _msg, _this, _param ) \
+ lcl_SwAccessibleContext_DbgMsg( _this, _msg, _param, sal_False );
+
+void lcl_SwAccessibleContext_DbgMsg( SwAccessibleContext *pThisAcc,
+ const char *pMsg,
+ SwAccessibleContext *pChildAcc,
+ sal_Bool bConstrDestr );
+#else
+#define DBG_MSG( _msg )
+#define DBG_MSG_PARAM( _msg, _param )
+#define DBG_MSG_THIS_PARAM( _msg, _this, _param )
+#define DBG_MSG_CD( _msg )
+#endif
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+void SwAccessibleContext::InitStates()
+{
+ bIsShowingState = GetMap() ? IsShowing( *(GetMap()) ) : sal_False;
+
+ ViewShell *pVSh = GetMap()->GetShell();
+ bIsEditableState = pVSh && IsEditable( pVSh );
+ bIsOpaqueState = pVSh && IsOpaque( pVSh );
+ bIsDefuncState = sal_False;
+}
+
+void SwAccessibleContext::SetParent( SwAccessibleContext *pParent )
+{
+ osl::MutexGuard aGuard( aMutex );
+
+ uno::Reference < XAccessible > xParent( pParent );
+ xWeakParent = xParent;
+}
+
+uno::Reference< XAccessible > SwAccessibleContext::GetWeakParent() const
+{
+ osl::MutexGuard aGuard( aMutex );
+
+ uno::Reference< XAccessible > xParent( xWeakParent );
+ return xParent;
+}
+
+Window *SwAccessibleContext::GetWindow()
+{
+ Window *pWin = 0;
+
+ if( GetMap() )
+ {
+ const ViewShell *pVSh = GetMap()->GetShell();
+ OSL_ENSURE( pVSh, "no view shell" );
+ if( pVSh )
+ pWin = pVSh->GetWin();
+
+ OSL_ENSURE( pWin, "no window" );
+ }
+
+ return pWin;
+}
+
+// get ViewShell from accessibility map, and cast to cursor shell
+SwCrsrShell* SwAccessibleContext::GetCrsrShell()
+{
+ SwCrsrShell* pCrsrShell;
+ ViewShell* pViewShell = GetMap() ? GetMap()->GetShell() : 0;
+ OSL_ENSURE( pViewShell, "no view shell" );
+ if( pViewShell && pViewShell->ISA( SwCrsrShell ) )
+ pCrsrShell = static_cast<SwCrsrShell*>( pViewShell );
+ else
+ pCrsrShell = NULL;
+
+ return pCrsrShell;
+}
+
+const SwCrsrShell* SwAccessibleContext::GetCrsrShell() const
+{
+ // just like non-const GetCrsrShell
+ const SwCrsrShell* pCrsrShell;
+ const ViewShell* pViewShell = GetMap() ? GetMap()->GetShell() : 0;
+ OSL_ENSURE( pViewShell, "no view shell" );
+ if( pViewShell && pViewShell->ISA( SwCrsrShell ) )
+ pCrsrShell = static_cast<const SwCrsrShell*>( pViewShell );
+ else
+ pCrsrShell = NULL;
+
+ return pCrsrShell;
+}
+
+
+enum Action { NONE, SCROLLED, SCROLLED_WITHIN,
+ SCROLLED_IN, SCROLLED_OUT };
+
+void SwAccessibleContext::ChildrenScrolled( const SwFrm *pFrm,
+ const SwRect& rOldVisArea )
+{
+ const SwRect& rNewVisArea = GetVisArea();
+ const bool bVisibleChildrenOnly = SwAccessibleChild( pFrm ).IsVisibleChildrenOnly();
+
+ const SwAccessibleChildSList aList( *pFrm, *(GetMap()) );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ while( aIter != aList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwRect aBox( rLower.GetBox( *(GetMap()) ) );
+ if( rLower.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ Action eAction = NONE;
+ if( aBox.IsOver( rNewVisArea ) )
+ {
+ if( aBox.IsOver( rOldVisArea ) )
+ {
+ eAction = SCROLLED_WITHIN;
+ }
+ else
+ {
+ if ( bVisibleChildrenOnly &&
+ !rLower.AlwaysIncludeAsChild() )
+ {
+ eAction = SCROLLED_IN;
+ }
+ else
+ {
+ eAction = SCROLLED;
+ }
+ }
+ }
+ else if( aBox.IsOver( rOldVisArea ) )
+ {
+ if ( bVisibleChildrenOnly &&
+ !rLower.AlwaysIncludeAsChild() )
+ {
+ eAction = SCROLLED_OUT;
+ }
+ else
+ {
+ eAction = SCROLLED;
+ }
+ }
+ else if( !bVisibleChildrenOnly ||
+ rLower.AlwaysIncludeAsChild() )
+ {
+ // This wouldn't be required if the SwAccessibleFrame,
+ // wouldn't know about the vis area.
+ eAction = SCROLLED;
+ }
+ if( NONE != eAction )
+ {
+ if ( rLower.GetSwFrm() )
+ {
+ OSL_ENSURE( !rLower.AlwaysIncludeAsChild(),
+ "<SwAccessibleContext::ChildrenScrolled(..)> - always included child not considered!" );
+ const SwFrm* pLower( rLower.GetSwFrm() );
+ ::rtl::Reference< SwAccessibleContext > xAccImpl =
+ GetMap()->GetContextImpl( pLower, SCROLLED_OUT == eAction ||
+ SCROLLED_IN == eAction );
+ if( xAccImpl.is() )
+ {
+ switch( eAction )
+ {
+ case SCROLLED:
+ xAccImpl->Scrolled( rOldVisArea );
+ break;
+ case SCROLLED_WITHIN:
+ xAccImpl->ScrolledWithin( rOldVisArea );
+ break;
+ case SCROLLED_IN:
+ xAccImpl->ScrolledIn();
+ break;
+ case SCROLLED_OUT:
+ xAccImpl->ScrolledOut( rOldVisArea );
+ break;
+ case NONE:
+ break;
+ }
+ }
+ else
+ {
+ ChildrenScrolled( pLower, rOldVisArea );
+ }
+ }
+ else if ( rLower.GetDrawObject() )
+ {
+ OSL_ENSURE( !rLower.AlwaysIncludeAsChild(),
+ "<SwAccessibleContext::ChildrenScrolled(..)> - always included child not considered!" );
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
+ GetMap()->GetContextImpl( rLower.GetDrawObject(),
+ this,
+ SCROLLED_OUT == eAction ||
+ SCROLLED_IN == eAction );
+ if( xAccImpl.is() )
+ {
+ switch( eAction )
+ {
+ case SCROLLED:
+ case SCROLLED_WITHIN:
+ xAccImpl->ViewForwarderChanged(
+ ::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA,
+ GetMap() );
+ break;
+ case SCROLLED_IN:
+ ScrolledInShape( rLower.GetDrawObject(),
+ xAccImpl.get() );
+ break;
+ case SCROLLED_OUT:
+ {
+ xAccImpl->ViewForwarderChanged(
+ ::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA,
+ GetMap() );
+ DisposeShape( rLower.GetDrawObject(),
+ xAccImpl.get() );
+ }
+ break;
+ case NONE:
+ break;
+ }
+ }
+ }
+ else if ( rLower.GetWindow() )
+ {
+ // nothing to do - as such children are always included as children.
+ OSL_ENSURE( rLower.AlwaysIncludeAsChild(),
+ "<SwAccessibleContext::ChildrenScrolled(..)> - not always included child not considered!" );
+ }
+ }
+ }
+ else if ( rLower.GetSwFrm() &&
+ ( !bVisibleChildrenOnly ||
+ aBox.IsOver( rOldVisArea ) ||
+ aBox.IsOver( rNewVisArea ) ) )
+ {
+ // There are no unaccessible SdrObjects that need to be notified
+ ChildrenScrolled( rLower.GetSwFrm(), rOldVisArea );
+ }
+ ++aIter;
+ }
+}
+
+void SwAccessibleContext::Scrolled( const SwRect& rOldVisArea )
+{
+ SetVisArea( GetMap()->GetVisArea() );
+
+ ChildrenScrolled( GetFrm(), rOldVisArea );
+
+ sal_Bool bIsOldShowingState;
+ sal_Bool bIsNewShowingState = IsShowing( *(GetMap()) );
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bIsOldShowingState = bIsShowingState;
+ bIsShowingState = bIsNewShowingState;
+ }
+
+ if( bIsOldShowingState != bIsNewShowingState )
+ FireStateChangedEvent( AccessibleStateType::SHOWING,
+ bIsNewShowingState );
+}
+
+void SwAccessibleContext::ScrolledWithin( const SwRect& rOldVisArea )
+{
+ SetVisArea( GetMap()->GetVisArea() );
+
+ ChildrenScrolled( GetFrm(), rOldVisArea );
+
+ FireVisibleDataEvent();
+}
+
+void SwAccessibleContext::ScrolledIn()
+{
+ // This accessible should be freshly created, because it
+ // was not visisble before. Therefor, its vis area must already
+ // reflect the scrolling.
+ OSL_ENSURE( GetVisArea() == GetMap()->GetVisArea(),
+ "Vis area of child is wrong. Did it exist already?" );
+
+ // Send child event at parent. That's all we have to do here.
+ const SwFrm* pParent = GetParent();
+ ::rtl::Reference< SwAccessibleContext > xParentImpl(
+ GetMap()->GetContextImpl( pParent, sal_False ) );
+ uno::Reference < XAccessibleContext > xThis( this );
+ if( xParentImpl.is() )
+ {
+ SetParent( xParentImpl.get() );
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.NewValue <<= xThis;
+
+ xParentImpl->FireAccessibleEvent( aEvent );
+ DBG_MSG_PARAM( "AccessibleChild (added)", xChildImpl.get() );
+
+ if( HasCursor() )
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ {
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_True );
+ }
+ }
+
+ }
+}
+
+void SwAccessibleContext::ScrolledOut( const SwRect& rOldVisArea )
+{
+ SetVisArea( GetMap()->GetVisArea() );
+
+ // First of all, update the children. That's required to dispose
+ // all children that are existing only if they are visible. They
+ // are not disposed by the recusive Dispose call that follows later on,
+ // because this call will only dispose children that are in the
+ // new vis area. The children we want to dispode however are in the
+ // old vis area all.
+ ChildrenScrolled( GetFrm(), rOldVisArea );
+
+ // Broadcast a state changed event for the showing state.
+ // It might be that the child is freshly created just to send
+ // the child event. In this case no listener will exist.
+ FireStateChangedEvent( AccessibleStateType::SHOWING, sal_False );
+
+ // We now dispose the frame
+ Dispose( sal_True );
+}
+
+// --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
+void SwAccessibleContext::InvalidateChildrenStates( const SwFrm* _pFrm,
+ tAccessibleStates _nStates )
+{
+ const SwAccessibleChildSList aVisList( GetVisArea(), *_pFrm, *(GetMap()) );
+
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm* pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl;
+ if( rLower.IsAccessible( GetShell()->IsPreView() ) )
+ xAccImpl = GetMap()->GetContextImpl( pLower, sal_False );
+ if( xAccImpl.is() )
+ xAccImpl->InvalidateStates( _nStates );
+ else
+ InvalidateChildrenStates( pLower, _nStates );
+ }
+ else if ( rLower.GetDrawObject() )
+ {
+ // TODO: SdrObjects
+ }
+ else if ( rLower.GetWindow() )
+ {
+ // nothing to do ?
+ }
+
+ ++aIter;
+ }
+}
+// <--
+
+void SwAccessibleContext::DisposeChildren( const SwFrm *pFrm,
+ sal_Bool bRecursive )
+{
+ const SwAccessibleChildSList aVisList( GetVisArea(), *pFrm, *(GetMap()) );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm* pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl;
+ if( rLower.IsAccessible( GetShell()->IsPreView() ) )
+ xAccImpl = GetMap()->GetContextImpl( pLower, sal_False );
+ if( xAccImpl.is() )
+ xAccImpl->Dispose( bRecursive );
+ else if( bRecursive )
+ DisposeChildren( pLower, bRecursive );
+ }
+ else if ( rLower.GetDrawObject() )
+ {
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl(
+ GetMap()->GetContextImpl( rLower.GetDrawObject(),
+ this, sal_False ) );
+ if( xAccImpl.is() )
+ DisposeShape( rLower.GetDrawObject(), xAccImpl.get() );
+ }
+ else if ( rLower.GetWindow() )
+ {
+ DisposeChild( rLower, sal_False );
+ }
+ ++aIter;
+ }
+}
+
+void SwAccessibleContext::_InvalidateContent( sal_Bool )
+{
+}
+
+void SwAccessibleContext::_InvalidateCursorPos()
+{
+}
+
+void SwAccessibleContext::_InvalidateFocus()
+{
+}
+
+void SwAccessibleContext::FireAccessibleEvent( AccessibleEventObject& rEvent )
+{
+ OSL_ENSURE( GetFrm(), "fire event for diposed frame?" );
+ if( !GetFrm() )
+ return;
+
+ if( !rEvent.Source.is() )
+ {
+ uno::Reference < XAccessibleContext > xThis( this );
+ rEvent.Source = xThis;
+ }
+
+ if (nClientId)
+ comphelper::AccessibleEventNotifier::addEvent( nClientId, rEvent );
+}
+
+void SwAccessibleContext::FireVisibleDataEvent()
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
+
+ FireAccessibleEvent( aEvent );
+ DBG_MSG( "AccessibleVisibleData" )
+}
+
+void SwAccessibleContext::FireStateChangedEvent( sal_Int16 nState,
+ sal_Bool bNewState )
+{
+ AccessibleEventObject aEvent;
+
+ aEvent.EventId = AccessibleEventId::STATE_CHANGED;
+ if( bNewState )
+ aEvent.NewValue <<= nState;
+ else
+ aEvent.OldValue <<= nState;
+
+ FireAccessibleEvent( aEvent );
+ DBG_MSG( "StateChanged" )
+}
+
+void SwAccessibleContext::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SolarMutexGuard aGuard;
+
+ // SHOWING
+ if( bIsShowingState )
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+
+ // EDITABLE
+ if( bIsEditableState )
+ rStateSet.AddState( AccessibleStateType::EDITABLE );
+
+ // ENABLED
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+
+ // OPAQUE
+ if( bIsOpaqueState )
+ rStateSet.AddState( AccessibleStateType::OPAQUE );
+
+ // VISIBLE
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+
+ if( bIsDefuncState )
+ rStateSet.AddState( AccessibleStateType::DEFUNC );
+}
+
+sal_Bool SwAccessibleContext::IsEditableState()
+{
+ sal_Bool bRet;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bRet = bIsEditableState;
+ }
+
+ return bRet;
+}
+
+SwAccessibleContext::SwAccessibleContext( SwAccessibleMap *pM,
+ sal_Int16 nR,
+ const SwFrm *pF )
+ : SwAccessibleFrame( pM->GetVisArea().SVRect(), pF,
+ pM->GetShell()->IsPreView() )
+ , pMap( pM )
+ , nClientId(0)
+ , nRole( nR )
+ , bDisposing( sal_False )
+ , bRegisteredAtAccessibleMap( true )
+{
+ InitStates();
+ DBG_MSG_CD( "constructed" )
+}
+
+SwAccessibleContext::~SwAccessibleContext()
+{
+ SolarMutexGuard aGuard;
+
+ DBG_MSG_CD( "destructed" )
+ RemoveFrmFromAccessibleMap();
+}
+
+uno::Reference< XAccessibleContext > SAL_CALL
+ SwAccessibleContext::getAccessibleContext( void )
+ throw (uno::RuntimeException)
+{
+ uno::Reference < XAccessibleContext > xRet( this );
+ return xRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleContext::getAccessibleChildCount( void )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ return bDisposing ? 0 : GetChildCount( *(GetMap()) );
+}
+
+uno::Reference< XAccessible> SAL_CALL
+ SwAccessibleContext::getAccessibleChild( sal_Int32 nIndex )
+ throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ const SwAccessibleChild aChild( GetChild( *(GetMap()), nIndex ) );
+ if( !aChild.IsValid() )
+ {
+ uno::Reference < XAccessibleContext > xThis( this );
+ lang::IndexOutOfBoundsException aExcept(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("index out of bounds") ),
+ xThis );
+ throw aExcept;
+ }
+
+ uno::Reference< XAccessible > xChild;
+ if( aChild.GetSwFrm() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xChildImpl(
+ GetMap()->GetContextImpl( aChild.GetSwFrm(), !bDisposing ) );
+ if( xChildImpl.is() )
+ {
+ xChildImpl->SetParent( this );
+ xChild = xChildImpl.get();
+ }
+ }
+ else if ( aChild.GetDrawObject() )
+ {
+ ::rtl::Reference < ::accessibility::AccessibleShape > xChildImpl(
+ GetMap()->GetContextImpl( aChild.GetDrawObject(),
+ this, !bDisposing ) );
+ if( xChildImpl.is() )
+ xChild = xChildImpl.get();
+ }
+ else if ( aChild.GetWindow() )
+ {
+ xChild = aChild.GetWindow()->GetAccessible();
+ }
+
+ return xChild;
+}
+
+uno::Reference< XAccessible> SAL_CALL SwAccessibleContext::getAccessibleParent (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ const SwFrm *pUpper = GetParent();
+ OSL_ENSURE( pUpper != 0 || bDisposing, "no upper found" );
+
+ uno::Reference< XAccessible > xAcc;
+ if( pUpper )
+ xAcc = GetMap()->GetContext( pUpper, !bDisposing );
+
+ OSL_ENSURE( xAcc.is() || bDisposing, "no parent found" );
+
+ // Remember the parent as weak ref.
+ {
+ osl::MutexGuard aWeakParentGuard( aMutex );
+ xWeakParent = xAcc;
+ }
+
+ return xAcc;
+}
+
+sal_Int32 SAL_CALL SwAccessibleContext::getAccessibleIndexInParent (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ const SwFrm *pUpper = GetParent();
+ OSL_ENSURE( pUpper != 0 || bDisposing, "no upper found" );
+
+ sal_Int32 nIndex = -1;
+ if( pUpper )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pUpper, !bDisposing ) );
+ OSL_ENSURE( xAccImpl.is() || bDisposing, "no parent found" );
+ if( xAccImpl.is() )
+ nIndex = xAccImpl->GetChildIndex( *(GetMap()), SwAccessibleChild(GetFrm()) );
+ }
+
+ return nIndex;
+}
+
+sal_Int16 SAL_CALL SwAccessibleContext::getAccessibleRole (void)
+ throw (uno::RuntimeException)
+{
+ return nRole;
+}
+
+OUString SAL_CALL SwAccessibleContext::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ OSL_ENSURE( !this, "description needs to be overloaded" );
+ THROW_RUNTIME_EXCEPTION( XAccessibleContext, "internal error (method must be overloaded)" );
+}
+
+OUString SAL_CALL SwAccessibleContext::getAccessibleName (void)
+ throw (uno::RuntimeException)
+{
+ return sName;
+}
+
+uno::Reference< XAccessibleRelationSet> SAL_CALL
+ SwAccessibleContext::getAccessibleRelationSet (void)
+ throw (uno::RuntimeException)
+{
+ // by default there are no relations
+ uno::Reference< XAccessibleRelationSet> xRet( new utl::AccessibleRelationSetHelper() );
+ return xRet;
+}
+
+uno::Reference<XAccessibleStateSet> SAL_CALL
+ SwAccessibleContext::getAccessibleStateSet (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ ::utl::AccessibleStateSetHelper *pStateSet =
+ new ::utl::AccessibleStateSetHelper;
+
+ uno::Reference<XAccessibleStateSet> xStateSet( pStateSet );
+ GetStates( *pStateSet );
+
+ return xStateSet;
+}
+
+lang::Locale SAL_CALL SwAccessibleContext::getLocale (void)
+ throw (IllegalAccessibleComponentStateException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ lang::Locale aLoc( Application::GetSettings().GetLocale() );
+ return aLoc;
+}
+
+void SAL_CALL SwAccessibleContext::addEventListener(
+ const uno::Reference< XAccessibleEventListener >& xListener )
+ throw (uno::RuntimeException)
+{
+ DBG_MSG( "accessible event listener added" )
+
+ if (xListener.is())
+ {
+ SolarMutexGuard aGuard;
+ if (!nClientId)
+ nClientId = comphelper::AccessibleEventNotifier::registerClient( );
+ comphelper::AccessibleEventNotifier::addEventListener( nClientId, xListener );
+ }
+}
+
+void SAL_CALL SwAccessibleContext::removeEventListener(
+ const uno::Reference< XAccessibleEventListener >& xListener )
+ throw (uno::RuntimeException)
+{
+ DBG_MSG( "accessible event listener removed" )
+
+ if (xListener.is())
+ {
+ SolarMutexGuard aGuard;
+ 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;
+ }
+ }
+}
+
+static sal_Bool lcl_PointInRectangle(const awt::Point & aPoint,
+ const awt::Rectangle & aRect)
+{
+ long nDiffX = aPoint.X - aRect.X;
+ long nDiffY = aPoint.Y - aRect.Y;
+
+ return
+ nDiffX >= 0 && nDiffX < aRect.Width && nDiffY >= 0 &&
+ nDiffY < aRect.Height;
+
+}
+
+sal_Bool SAL_CALL SwAccessibleContext::containsPoint(
+ const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ awt::Rectangle aPixBounds = getBoundsImpl(sal_True);
+ aPixBounds.X = 0;
+ aPixBounds.Y = 0;
+
+ return lcl_PointInRectangle(aPoint, aPixBounds);
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleContext::getAccessibleAtPoint(
+ const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleComponent )
+
+ uno::Reference< XAccessible > xAcc;
+
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Point aPixPoint( aPoint.X, aPoint.Y ); // px rel to parent
+ if( !GetFrm()->IsRootFrm() )
+ {
+ SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root
+ Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() );
+ aPixPoint.X() += aPixPos.X();
+ aPixPoint.Y() += aPixPos.Y();
+ }
+
+ const SwAccessibleChild aChild( GetChildAtPixel( aPixPoint, *(GetMap()) ) );
+ if( aChild.GetSwFrm() )
+ {
+ xAcc = GetMap()->GetContext( aChild.GetSwFrm() );
+ }
+ else if( aChild.GetDrawObject() )
+ {
+ xAcc = GetMap()->GetContext( aChild.GetDrawObject(), this );
+ }
+ else if ( aChild.GetWindow() )
+ {
+ xAcc = aChild.GetWindow()->GetAccessible();
+ }
+
+ return xAcc;
+}
+
+
+/**
+ Get bounding box.
+
+ There are two modes.
+
+ - realative
+
+ Return bounding box relative to parent if parent is no root
+ frame. Otherwise return the absolute bounding box.
+
+ - absolute
+
+ Return the absolute bounding box.
+
+ @param bRelative
+ true: Use relative mode.
+ false: Use absolute mode.
+*/
+awt::Rectangle SAL_CALL SwAccessibleContext::getBoundsImpl(sal_Bool bRelative)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleComponent )
+
+ const SwFrm *pParent = GetParent();
+ OSL_ENSURE( pParent, "no Parent found" );
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin && pParent )
+
+ SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root
+ Rectangle aPixBounds( 0, 0, 0, 0 );
+ if( GetFrm()->IsPageFrm() &&
+ static_cast < const SwPageFrm * >( GetFrm() )->IsEmptyPage() )
+ {
+ OSL_ENSURE( GetShell()->IsPreView(), "empty page accessible?" );
+ if( GetShell()->IsPreView() )
+ {
+ // OD 15.01.2003 #103492# - adjust method call <GetMap()->GetPreViewPageSize()>
+ sal_uInt16 nPageNum =
+ static_cast < const SwPageFrm * >( GetFrm() )->GetPhyPageNum();
+ aLogBounds.SSize( GetMap()->GetPreViewPageSize( nPageNum ) );
+ }
+ }
+ if( !aLogBounds.IsEmpty() )
+ {
+ aPixBounds = GetMap()->CoreToPixel( aLogBounds.SVRect() );
+ if( !pParent->IsRootFrm() && bRelative)
+ {
+ SwRect aParentLogBounds( GetBounds( *(GetMap()), pParent ) ); // twip rel to doc root
+ Point aParentPixPos( GetMap()->CoreToPixel( aParentLogBounds.SVRect() ).TopLeft() );
+ aPixBounds.Move( -aParentPixPos.X(), -aParentPixPos.Y() );
+ }
+ }
+
+ awt::Rectangle aBox( aPixBounds.Left(), aPixBounds.Top(),
+ aPixBounds.GetWidth(), aPixBounds.GetHeight() );
+
+ return aBox;
+}
+
+
+awt::Rectangle SAL_CALL SwAccessibleContext::getBounds()
+ throw (uno::RuntimeException)
+{
+ return getBoundsImpl(sal_True);
+}
+
+awt::Point SAL_CALL SwAccessibleContext::getLocation()
+ throw (uno::RuntimeException)
+{
+ awt::Rectangle aRect = getBoundsImpl(sal_True);
+ awt::Point aPoint(aRect.X, aRect.Y);
+
+ return aPoint;
+}
+
+
+
+awt::Point SAL_CALL SwAccessibleContext::getLocationOnScreen()
+ throw (uno::RuntimeException)
+{
+ awt::Rectangle aRect = getBoundsImpl(sal_False);
+
+ Point aPixPos(aRect.X, aRect.Y);
+
+ /* getBoundsImpl already checked that GetWindow returns valid pointer. */
+ aPixPos = GetWindow()->OutputToAbsoluteScreenPixel(aPixPos);
+ awt::Point aPoint(aPixPos.X(), aPixPos.Y());
+
+ return aPoint;
+}
+
+
+awt::Size SAL_CALL SwAccessibleContext::getSize()
+ throw (uno::RuntimeException)
+{
+ awt::Rectangle aRect = getBoundsImpl(sal_False);
+ awt::Size aSize( aRect.Width, aRect.Height );
+
+ return aSize;
+}
+
+void SAL_CALL SwAccessibleContext::grabFocus()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ if( GetFrm()->IsFlyFrm() )
+ {
+ const SdrObject *pObj =
+ static_cast < const SwFlyFrm * >( GetFrm() )->GetVirtDrawObj();
+ if( pObj )
+ Select( const_cast < SdrObject * >( pObj ), sal_False );
+ }
+ else
+ {
+ const SwCntntFrm *pCFrm = 0;
+ if( GetFrm()->IsCntntFrm() )
+ pCFrm = static_cast< const SwCntntFrm * >( GetFrm() );
+ else if( GetFrm()->IsLayoutFrm() )
+ pCFrm = static_cast< const SwLayoutFrm * >( GetFrm() )->ContainsCntnt();
+
+ if( pCFrm && pCFrm->IsTxtFrm() )
+ {
+ const SwTxtFrm *pTxtFrm = static_cast< const SwTxtFrm * >( pCFrm );
+ const SwTxtNode *pTxtNd = pTxtFrm->GetTxtNode();
+ if( pTxtNd )
+ {
+ // create pam for selection
+ SwIndex aIndex( const_cast< SwTxtNode * >( pTxtNd ),
+ pTxtFrm->GetOfst() );
+ SwPosition aStartPos( *pTxtNd, aIndex );
+ SwPaM aPaM( aStartPos );
+
+ // set PaM at cursor shell
+ Select( aPaM );
+ }
+ }
+ }
+}
+
+
+uno::Any SAL_CALL SwAccessibleContext::getAccessibleKeyBinding()
+ throw (uno::RuntimeException)
+{
+ // There are no key bindings
+ return uno::Any();
+}
+
+sal_Int32 SAL_CALL SwAccessibleContext::getForeground()
+ throw (uno::RuntimeException)
+{
+ return 0;
+}
+
+sal_Int32 SAL_CALL SwAccessibleContext::getBackground()
+ throw (uno::RuntimeException)
+{
+ return 0xffffff;
+}
+
+
+OUString SAL_CALL SwAccessibleContext::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ OSL_ENSURE( !this, "implementation name needs to be overloaded" );
+
+ THROW_RUNTIME_EXCEPTION( lang::XServiceInfo, "implementation name needs to be overloaded" )
+}
+
+sal_Bool SAL_CALL
+ SwAccessibleContext::supportsService (const ::rtl::OUString& )
+ throw (uno::RuntimeException)
+{
+ OSL_ENSURE( !this, "supports service needs to be overloaded" );
+ THROW_RUNTIME_EXCEPTION( lang::XServiceInfo, "supports service needs to be overloaded" )
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleContext::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ OSL_ENSURE( !this, "supported services names needs to be overloaded" );
+ THROW_RUNTIME_EXCEPTION( lang::XServiceInfo, "supported services needs to be overloaded" )
+}
+
+void SwAccessibleContext::DisposeShape( const SdrObject *pObj,
+ ::accessibility::AccessibleShape *pAccImpl )
+{
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl( pAccImpl );
+ if( !xAccImpl.is() )
+ xAccImpl = GetMap()->GetContextImpl( pObj, this, sal_True );
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ uno::Reference< XAccessible > xAcc( xAccImpl.get() );
+ aEvent.OldValue <<= xAcc;
+ FireAccessibleEvent( aEvent );
+
+ GetMap()->RemoveContext( pObj );
+ xAccImpl->dispose();
+}
+
+void SwAccessibleContext::ScrolledInShape( const SdrObject* ,
+ ::accessibility::AccessibleShape *pAccImpl )
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ uno::Reference< XAccessible > xAcc( pAccImpl );
+ aEvent.NewValue <<= xAcc;
+ FireAccessibleEvent( aEvent );
+
+ if( pAccImpl->GetState( AccessibleStateType::FOCUSED ) )
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ {
+ AccessibleEventObject aStateChangedEvent;
+ aStateChangedEvent.EventId = AccessibleEventId::STATE_CHANGED;
+ aStateChangedEvent.NewValue <<= AccessibleStateType::FOCUSED;
+ aStateChangedEvent.Source = xAcc;
+
+ FireAccessibleEvent( aStateChangedEvent );
+ }
+ }
+}
+
+void SwAccessibleContext::Dispose( sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( GetFrm() && GetMap(), "already disposed" );
+ OSL_ENSURE( GetMap()->GetVisArea() == GetVisArea(),
+ "invalid vis area for dispose" );
+
+ bDisposing = sal_True;
+
+ // dispose children
+ if( bRecursive )
+ DisposeChildren( GetFrm(), bRecursive );
+
+ // get parent
+ uno::Reference< XAccessible > xParent( GetWeakParent() );
+ uno::Reference < XAccessibleContext > xThis( this );
+
+ // send child event at parent
+ if( xParent.is() )
+ {
+ SwAccessibleContext *pAcc = (SwAccessibleContext *)xParent.get();
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.OldValue <<= xThis;
+ pAcc->FireAccessibleEvent( aEvent );
+ DBG_MSG_THIS_PARAM( "AccessibleChild (removed)", pAcc, this )
+ }
+
+ // set defunc state (its not required to broadcast a state changed
+ // event if the object is diposed afterwards)
+ {
+ osl::MutexGuard aDefuncStateGuard( aMutex );
+ bIsDefuncState = sal_True;
+ }
+
+ // broadcast dispose event
+ if ( nClientId )
+ {
+ comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this );
+ nClientId = 0;
+ DBG_MSG_CD( "dispose" )
+ }
+
+ RemoveFrmFromAccessibleMap();
+ ClearFrm();
+ pMap = 0;
+
+ bDisposing = sal_False;
+}
+
+void SwAccessibleContext::DisposeChild( const SwAccessibleChild& rChildFrmOrObj,
+ sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ if ( IsShowing( *(GetMap()), rChildFrmOrObj ) ||
+ rChildFrmOrObj.AlwaysIncludeAsChild() ||
+ !SwAccessibleChild( GetFrm() ).IsVisibleChildrenOnly() )
+ {
+ // If the object could have existed before, than there is nothing to do,
+ // because no wrapper exists now and therefor no one is interested to
+ // get notified of the movement.
+ if( rChildFrmOrObj.GetSwFrm() )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetSwFrm(),
+ sal_True );
+ xAccImpl->Dispose( bRecursive );
+ }
+ else if ( rChildFrmOrObj.GetDrawObject() )
+ {
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetDrawObject(),
+ this, sal_True );
+ DisposeShape( rChildFrmOrObj.GetDrawObject(),
+ xAccImpl.get() );
+ }
+ else if ( rChildFrmOrObj.GetWindow() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ uno::Reference< XAccessible > xAcc =
+ rChildFrmOrObj.GetWindow()->GetAccessible();
+ aEvent.OldValue <<= xAcc;
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ else if( bRecursive && rChildFrmOrObj.GetSwFrm() )
+ DisposeChildren( rChildFrmOrObj.GetSwFrm(), bRecursive );
+}
+
+void SwAccessibleContext::InvalidatePosOrSize( const SwRect& )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( GetFrm() && !GetFrm()->Frm().IsEmpty(), "context should have a size" );
+
+ sal_Bool bIsOldShowingState;
+ sal_Bool bIsNewShowingState = IsShowing( *(GetMap()) );
+ {
+ osl::MutexGuard aShowingStateGuard( aMutex );
+ bIsOldShowingState = bIsShowingState;
+ bIsShowingState = bIsNewShowingState;
+ }
+
+ if( bIsOldShowingState != bIsNewShowingState )
+ {
+ FireStateChangedEvent( AccessibleStateType::SHOWING,
+ bIsNewShowingState );
+ }
+ else if( bIsNewShowingState )
+ {
+ // The frame stays visible -> broadcast event
+ FireVisibleDataEvent();
+ }
+
+ if( !bIsNewShowingState &&
+ SwAccessibleChild( GetParent() ).IsVisibleChildrenOnly() )
+ {
+ // The frame is now invisible -> dispose it
+ Dispose( sal_True );
+ }
+ else
+ {
+ _InvalidateContent( sal_True );
+ }
+}
+
+void SwAccessibleContext::InvalidateChildPosOrSize(
+ const SwAccessibleChild& rChildFrmOrObj,
+ const SwRect& rOldFrm )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( !rChildFrmOrObj.GetSwFrm() ||
+ !rChildFrmOrObj.GetSwFrm()->Frm().IsEmpty(),
+ "child context should have a size" );
+
+ if ( rChildFrmOrObj.AlwaysIncludeAsChild() )
+ {
+ // nothing to do;
+ return;
+ }
+
+ const bool bVisibleChildrenOnly = SwAccessibleChild( GetFrm() ).IsVisibleChildrenOnly();
+ const bool bNew = rOldFrm.IsEmpty() ||
+ ( rOldFrm.Left() == 0 && rOldFrm.Top() == 0 );
+ if( IsShowing( *(GetMap()), rChildFrmOrObj ) )
+ {
+ // If the object could have existed before, than there is nothing to do,
+ // because no wrapper exists now and therefor no one is interested to
+ // get notified of the movement.
+ if( bNew || (bVisibleChildrenOnly && !IsShowing( rOldFrm )) )
+ {
+ if( rChildFrmOrObj.GetSwFrm() )
+ {
+ // The frame becomes visible. A child event must be send.
+ ::rtl::Reference< SwAccessibleContext > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetSwFrm(),
+ sal_True );
+ xAccImpl->ScrolledIn();
+ }
+ else if ( rChildFrmOrObj.GetDrawObject() )
+ {
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetDrawObject(),
+ this, sal_True );
+ // --> OD 2004-11-29 #i37790#
+ if ( xAccImpl.is() )
+ {
+ ScrolledInShape( rChildFrmOrObj.GetDrawObject(),
+ xAccImpl.get() );
+ }
+ else
+ {
+ OSL_ENSURE( false ,
+ "<SwAccessibleContext::InvalidateChildPosOrSize(..)> - no accessible shape found." );
+ }
+ // <--
+ }
+ else if ( rChildFrmOrObj.GetWindow() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.NewValue <<= (rChildFrmOrObj.GetWindow()->GetAccessible());
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ }
+ else
+ {
+ // If the frame was visible before, than a child event for the parent
+ // needs to be send. However, there is no wrapper existing, and so
+ // no notifications for grandchildren are required. If the are
+ // grandgrandchildren, they would be notified by the layout.
+ if( bVisibleChildrenOnly &&
+ !bNew && IsShowing( rOldFrm ) )
+ {
+ if( rChildFrmOrObj.GetSwFrm() )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetSwFrm(),
+ sal_True );
+ xAccImpl->SetParent( this );
+ xAccImpl->Dispose( sal_True );
+ }
+ else if ( rChildFrmOrObj.GetDrawObject() )
+ {
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetDrawObject(),
+ this, sal_True );
+ DisposeShape( rChildFrmOrObj.GetDrawObject(),
+ xAccImpl.get() );
+ }
+ else if ( rChildFrmOrObj.GetWindow() )
+ {
+ OSL_ENSURE( false,
+ "<SwAccessibleContext::InvalidateChildPosOrSize(..)> - not expected to handle dispose of child of type <Window>." );
+ }
+ }
+ }
+}
+
+void SwAccessibleContext::InvalidateContent()
+{
+ SolarMutexGuard aGuard;
+
+ _InvalidateContent( sal_False );
+}
+
+void SwAccessibleContext::InvalidateCursorPos()
+{
+ SolarMutexGuard aGuard;
+
+ _InvalidateCursorPos();
+}
+
+void SwAccessibleContext::InvalidateFocus()
+{
+ SolarMutexGuard aGuard;
+
+ _InvalidateFocus();
+}
+
+// --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
+void SwAccessibleContext::InvalidateStates( tAccessibleStates _nStates )
+{
+ if( GetMap() )
+ {
+ ViewShell *pVSh = GetMap()->GetShell();
+ if( pVSh )
+ {
+ if( (_nStates & ACC_STATE_EDITABLE) != 0 )
+ {
+ sal_Bool bIsOldEditableState;
+ sal_Bool bIsNewEditableState = IsEditable( pVSh );
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bIsOldEditableState = bIsEditableState;
+ bIsEditableState = bIsNewEditableState;
+ }
+
+ if( bIsOldEditableState != bIsNewEditableState )
+ FireStateChangedEvent( AccessibleStateType::EDITABLE,
+ bIsNewEditableState );
+ }
+ if( (_nStates & ACC_STATE_OPAQUE) != 0 )
+ {
+ sal_Bool bIsOldOpaqueState;
+ sal_Bool bIsNewOpaqueState = IsOpaque( pVSh );
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bIsOldOpaqueState = bIsOpaqueState;
+ bIsOpaqueState = bIsNewOpaqueState;
+ }
+
+ if( bIsOldOpaqueState != bIsNewOpaqueState )
+ FireStateChangedEvent( AccessibleStateType::OPAQUE,
+ bIsNewOpaqueState );
+ }
+ }
+
+ InvalidateChildrenStates( GetFrm(), _nStates );
+ }
+}
+// <--
+
+void SwAccessibleContext::InvalidateRelation( sal_uInt16 nType )
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = nType;
+
+ FireAccessibleEvent( aEvent );
+}
+
+/** text selection has changed
+
+ OD 2005-12-14 #i27301#
+
+ @author OD
+*/
+void SwAccessibleContext::InvalidateTextSelection()
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::TEXT_SELECTION_CHANGED;
+
+ FireAccessibleEvent( aEvent );
+}
+
+/** attributes has changed
+
+ OD 2009-01-06 #i88069#
+
+ @author OD
+*/
+void SwAccessibleContext::InvalidateAttr()
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::TEXT_ATTRIBUTE_CHANGED;
+
+ FireAccessibleEvent( aEvent );
+}
+
+sal_Bool SwAccessibleContext::HasCursor()
+{
+ return sal_False;
+}
+
+sal_Bool SwAccessibleContext::Select( SwPaM *pPaM, SdrObject *pObj,
+ sal_Bool bAdd )
+{
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( !pCrsrShell )
+ return sal_False;
+
+ SwFEShell* pFEShell = pCrsrShell->ISA( SwFEShell )
+ ? static_cast<SwFEShell*>( pCrsrShell )
+ : 0;
+ // Get rid of activated OLE object
+ if( pFEShell )
+ pFEShell->FinishOLEObj();
+
+ sal_Bool bRet = sal_False;
+ if( pObj )
+ {
+ if( pFEShell )
+ {
+ Point aDummy;
+ sal_uInt8 nFlags = bAdd ? SW_ADD_SELECT : 0;
+ pFEShell->SelectObj( aDummy, nFlags, pObj );
+ bRet = sal_True;
+ }
+ }
+ else if( pPaM )
+ {
+ // Get rid of frame selection. If there is one, make text cursor
+ // visible again.
+ sal_Bool bCallShowCrsr = sal_False;
+ if( pFEShell && (pFEShell->IsFrmSelected() ||
+ pFEShell->IsObjSelected()) )
+ {
+ Point aPt( LONG_MIN, LONG_MIN );
+ pFEShell->SelectObj( aPt, 0 );
+ bCallShowCrsr = sal_True;
+ }
+ pCrsrShell->KillPams();
+ pCrsrShell->SetSelection( *pPaM );
+ if( bCallShowCrsr )
+ pCrsrShell->ShowCrsr();
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+OUString SwAccessibleContext::GetResource( sal_uInt16 nResId,
+ const OUString *pArg1,
+ const OUString *pArg2 )
+{
+ String sStr;
+ {
+ SolarMutexGuard aGuard;
+
+ sStr = SW_RES( nResId );
+ }
+
+ if( pArg1 )
+ {
+ sStr.SearchAndReplace( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "$(ARG1)" )),
+ String( *pArg1 ) );
+ }
+ if( pArg2 )
+ {
+ sStr.SearchAndReplace( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "$(ARG2)" )),
+ String( *pArg2 ) );
+ }
+
+ return OUString( sStr );
+}
+
+void SwAccessibleContext::RemoveFrmFromAccessibleMap()
+{
+ if( bRegisteredAtAccessibleMap && GetFrm() && GetMap() )
+ GetMap()->RemoveContext( GetFrm() );
+}
+
+bool SwAccessibleContext::HasAdditionalAccessibleChildren()
+{
+ bool bRet( false );
+
+ if ( GetFrm()->IsTxtFrm() )
+ {
+ SwPostItMgr* pPostItMgr = GetMap()->GetShell()->GetPostItMgr();
+ if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
+ {
+ bRet = pPostItMgr->HasFrmConnectedSidebarWins( *(GetFrm()) );
+ }
+ }
+
+ return bRet;
+}
+/** get additional accessible child by index
+
+ OD 2010-01-27 #i88070#
+
+ @author OD
+*/
+Window* SwAccessibleContext::GetAdditionalAccessibleChild( const sal_Int32 nIndex )
+{
+ Window* pAdditionalAccessibleChild( 0 );
+
+ if ( GetFrm()->IsTxtFrm() )
+ {
+ SwPostItMgr* pPostItMgr = GetMap()->GetShell()->GetPostItMgr();
+ if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
+ {
+ pAdditionalAccessibleChild =
+ pPostItMgr->GetSidebarWinForFrmByIndex( *(GetFrm()), nIndex );
+ }
+ }
+
+ return pAdditionalAccessibleChild;
+}
+
+/** get all additional accessible children
+
+ OD 2010-01-27 #i88070#
+
+ @author OD
+*/
+void SwAccessibleContext::GetAdditionalAccessibleChildren( std::vector< Window* >* pChildren )
+{
+ if ( GetFrm()->IsTxtFrm() )
+ {
+ SwPostItMgr* pPostItMgr = GetMap()->GetShell()->GetPostItMgr();
+ if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
+ {
+ pPostItMgr->GetAllSidebarWinForFrm( *(GetFrm()), pChildren );
+ }
+ }
+}
+
+#if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
+void lcl_SwAccessibleContext_DbgMsg( SwAccessibleContext *pThisAcc,
+ const char *pMsg,
+ SwAccessibleContext *pChildAcc,
+ sal_Bool bConstrDestr )
+{
+ static SvFileStream aStrm( String::CreateFromAscii("j:\\acc.log"),
+ STREAM_WRITE|STREAM_TRUNC|STREAM_SHARE_DENYNONE );
+ ByteString aName( String(pThisAcc->GetName()),
+ RTL_TEXTENCODING_ISO_8859_1 );
+ if( aName.Len() )
+ {
+ aStrm << aName.GetBuffer()
+ << ": ";
+ }
+ aStrm << pMsg;
+ if( pChildAcc )
+ {
+ ByteString aChild( String(pChildAcc->GetName()),
+ RTL_TEXTENCODING_ISO_8859_1 );
+ aStrm << ": "
+ << aChild.GetBuffer();
+ }
+ aStrm << "\r\n (";
+
+ if( !bConstrDestr )
+ {
+ ByteString aDesc( String(pThisAcc->getAccessibleDescription()),
+ RTL_TEXTENCODING_ISO_8859_1 );
+ aStrm << aDesc.GetBuffer()
+ << ", ";
+ }
+
+ Rectangle aVisArea( pThisAcc->GetVisArea() );
+ aStrm << "VA: "
+ << ByteString::CreateFromInt32( aVisArea.Left() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aVisArea.Top() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aVisArea.GetWidth() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aVisArea.GetHeight() ).GetBuffer();
+
+ if( pThisAcc->GetFrm() )
+ {
+ Rectangle aBounds( pThisAcc->GetBounds( pThisAcc->GetFrm() ) );
+ aStrm << ", BB: "
+ << ByteString::CreateFromInt32( aBounds.Left() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aBounds.Top() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aBounds.GetWidth() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aBounds.GetHeight() ).GetBuffer()
+ << ")\r\n";
+ }
+
+ aStrm.Flush();
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acccontext.hxx b/sw/source/core/access/acccontext.hxx
new file mode 100644
index 000000000000..43612ebaed2d
--- /dev/null
+++ b/sw/source/core/access/acccontext.hxx
@@ -0,0 +1,461 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCBASE_HXX
+#define _ACCBASE_HXX
+#include <accframe.hxx>
+#include <accmap.hxx>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase5.hxx>
+#include <cppuhelper/interfacecontainer.hxx>
+
+class Window;
+class SwAccessibleMap;
+class SwCrsrShell;
+class SdrObject;
+class SwPaM;
+namespace utl {
+ class AccessibleStateSetHelper;
+}
+namespace accessibility {
+ class AccessibleShape;
+}
+class SwFmtFld;
+class SwAccessibleChildContainer;
+
+const sal_Char sAccessibleServiceName[] = "com.sun.star.accessibility.Accessible";
+
+class SwAccessibleContext :
+ public ::cppu::WeakImplHelper5<
+ ::com::sun::star::accessibility::XAccessible,
+ ::com::sun::star::accessibility::XAccessibleContext,
+ ::com::sun::star::accessibility::XAccessibleComponent,
+ ::com::sun::star::accessibility::XAccessibleEventBroadcaster,
+ ::com::sun::star::lang::XServiceInfo
+ >,
+ public SwAccessibleFrame
+{
+ // The implements for the XAccessibleSelection interface has been
+ // 'externalized' and wants access to the protected members like
+ // GetMap, GetChild, GetParent, and GetFrm.
+ friend class SwAccessibleSelectionHelper;
+
+
+protected:
+
+ mutable ::osl::Mutex aListenerMutex;
+ mutable ::osl::Mutex aMutex;
+
+private:
+
+ ::rtl::OUString sName; // immutable outside constructor
+
+ // The parent if it has been retrieved. This is always an
+ // SwAccessibleContext. (protected by Mutex)
+ ::com::sun::star::uno::WeakReference <
+ ::com::sun::star::accessibility::XAccessible > xWeakParent;
+
+ SwAccessibleMap *pMap; // must be protected by solar mutex
+
+ sal_uInt32 nClientId; // client id in the AccessibleEventNotifier queue
+ sal_Int16 nRole; // immutable outside constructor
+
+ // The current states (protected by mutex)
+ sal_Bool bIsShowingState : 1;
+ sal_Bool bIsEditableState : 1;
+ sal_Bool bIsOpaqueState : 1;
+ sal_Bool bIsDefuncState : 1;
+
+ // Are we currently disposing that object (protected by solar mutex)?
+ sal_Bool bDisposing : 1;
+
+ // --> OD 2008-03-10 #i85634#
+ // boolean, indicating if the accessible context is in general registered at
+ // the accessible map.
+ bool bRegisteredAtAccessibleMap;
+ // <--
+
+ void InitStates();
+
+protected:
+ void SetName( const ::rtl::OUString& rName ) { sName = rName; }
+ inline sal_Int16 GetRole() const
+ {
+ return nRole;
+ }
+
+ void SetParent( SwAccessibleContext *pParent );
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> GetWeakParent() const;
+
+ sal_Bool IsDisposing() const { return bDisposing; }
+
+ Window *GetWindow();
+ SwAccessibleMap *GetMap() { return pMap; }
+ const SwAccessibleMap *GetMap() const { return pMap; }
+
+ /** convenience method to get the SwViewShell through accessibility map */
+ inline ViewShell* GetShell()
+ {
+ return GetMap()->GetShell();
+ }
+ inline const ViewShell* GetShell() const
+ {
+ return GetMap()->GetShell();
+ }
+
+ /** convenience method to get SwCrsrShell through accessibility map
+ * @returns SwCrsrShell, or NULL if none is found */
+ SwCrsrShell* GetCrsrShell();
+ const SwCrsrShell* GetCrsrShell() const;
+
+ // Notify all children that the vis araea has changed.
+ // The SwFrm might belong to the current object or to any other child or
+ // grandchild.
+ void ChildrenScrolled( const SwFrm *pFrm, const SwRect& rOldVisArea );
+
+ // The context's showing state changed. May only be called for context that
+ // exist even if they aren't visible.
+ void Scrolled( const SwRect& rOldVisArea );
+
+ // A child has been moved while setting the vis area
+ void ScrolledWithin( const SwRect& rOldVisArea );
+
+ // The has been added while setting the vis area
+ void ScrolledIn();
+
+ // The context has to be removed while setting the vis area
+ void ScrolledOut( const SwRect& rOldVisArea );
+
+ // Invalidate the states of all children of the specified SwFrm. The
+ // SwFrm might belong the the current object or to any child or grandchild!
+ // --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
+ void InvalidateChildrenStates( const SwFrm* _pFrm,
+ tAccessibleStates _nStates );
+ // <--
+
+ // Dispose children of the specified SwFrm. The SwFrm might belong to
+ // the current object or to any other child or grandchild.
+ void DisposeChildren( const SwFrm *pFrm,
+ sal_Bool bRecursive );
+
+ void DisposeShape( const SdrObject *pObj,
+ ::accessibility::AccessibleShape *pAccImpl );
+ void ScrolledInShape( const SdrObject *pObj,
+ ::accessibility::AccessibleShape *pAccImpl );
+
+ virtual void _InvalidateContent( sal_Bool bVisibleDataFired );
+
+ virtual void _InvalidateCursorPos();
+ virtual void _InvalidateFocus();
+
+public:
+
+ void FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventObject& rEvent );
+
+protected:
+
+ // broadcast visual data event
+ void FireVisibleDataEvent();
+
+ // broadcast state change event
+ void FireStateChangedEvent( sal_Int16 nState, sal_Bool bNewState );
+
+ // Set states for getAccessibleStateSet.
+ // This base class sets DEFUNC(0/1), EDITABLE(0/1), ENABLED(1),
+ // SHOWING(0/1), OPAQUE(0/1) and VISIBLE(1).
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ sal_Bool IsEditableState();
+
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL
+ getBoundsImpl(sal_Bool bRelative)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // --> OD 2008-03-10 #i85634#
+ inline void NotRegisteredAtAccessibleMap()
+ {
+ bRegisteredAtAccessibleMap = false;
+ }
+ void RemoveFrmFromAccessibleMap();
+ // <--
+
+ virtual ~SwAccessibleContext();
+
+public:
+
+ SwAccessibleContext( SwAccessibleMap *pMap, sal_Int16 nRole,
+ const SwFrm *pFrm );
+
+ //===== XAccessible =====================================================
+
+ /// Return the XAccessibleContext.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext> SAL_CALL
+ getAccessibleContext (void) throw (com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return the number of currently visible children.
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the specified child or NULL if index is invalid.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleChild (sal_Int32 nIndex)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IndexOutOfBoundsException);
+
+ /// Return a reference to the parent.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleParent (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this objects index among the parents children.
+ virtual sal_Int32 SAL_CALL
+ getAccessibleIndexInParent (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this object's role.
+ virtual sal_Int16 SAL_CALL
+ getAccessibleRole (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the object's current name.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return NULL to indicate that an empty relation set.
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleRelationSet> SAL_CALL
+ getAccessibleRelationSet (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the set of current states.
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleStateSet> SAL_CALL
+ getAccessibleStateSet (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return the parents locale or throw exception if this object has no
+ parent yet/anymore.
+ */
+ virtual ::com::sun::star::lang::Locale SAL_CALL
+ getLocale (void)
+ throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleEventBroadcaster =====================================
+
+ virtual void SAL_CALL addEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleEventListener >& xListener )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleEventListener >& xListener )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleComponent ============================================
+ virtual sal_Bool SAL_CALL containsPoint(
+ const ::com::sun::star::awt::Point& aPoint )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(
+ const ::com::sun::star::awt::Point& aPoint )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocation()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Size SAL_CALL getSize()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL grabFocus()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getForeground()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getBackground()
+ throw (::com::sun::star::uno::RuntimeException);
+
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //====== thread safe C++ interface ========================================
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+
+ // The child object is not visible an longer and should be destroyed
+ virtual void DisposeChild( const sw::access::SwAccessibleChild& rFrmOrObj, sal_Bool bRecursive );
+
+ // The object has been moved by the layout
+ virtual void InvalidatePosOrSize( const SwRect& rFrm );
+
+ // The vhild object has been moved by the layout
+ virtual void InvalidateChildPosOrSize( const sw::access::SwAccessibleChild& rFrmOrObj,
+ const SwRect& rFrm );
+
+ // The content may have changed (but it hasn't tohave changed)
+ void InvalidateContent();
+
+ // The caretPos has changed
+ void InvalidateCursorPos();
+
+ // The Focus state has changed
+ void InvalidateFocus();
+
+ // Check states
+ // --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
+ void InvalidateStates( tAccessibleStates _nStates );
+ // <--
+
+ // the XAccessibleRelationSet may have changed
+ void InvalidateRelation( sal_uInt16 nType );
+
+ /** text selection has changed
+
+ OD 2005-12-14 #i27301#
+
+ @author OD
+ */
+ void InvalidateTextSelection();
+
+ /** attributes has changed
+
+ OD 2009-01-06 #i88069#
+
+ @author OD
+ */
+ void InvalidateAttr();
+
+ bool HasAdditionalAccessibleChildren();
+
+ /** get additional child by index
+
+ OD 2010-01-27 #i88070#
+
+ @author OD
+ */
+ Window* GetAdditionalAccessibleChild( const sal_Int32 nIndex );
+
+ /** get all additional accessible children
+
+ OD 2010-01-27 #i88070#
+
+ @author OD
+ */
+ void GetAdditionalAccessibleChildren( std::vector< Window* >* pChildren );
+
+
+ const ::rtl::OUString& GetName() const { return sName; }
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+
+ sal_Bool Select( SwPaM *pPaM, SdrObject *pObj, sal_Bool bAdd );
+ inline sal_Bool Select( SwPaM& rPaM )
+ {
+ return Select( &rPaM, 0, sal_False );
+ }
+ inline sal_Bool Select( SdrObject *pObj, sal_Bool bAdd )
+ {
+ return Select( 0, pObj, bAdd );
+ }
+
+ static ::rtl::OUString GetResource( sal_uInt16 nResId,
+ const ::rtl::OUString *pArg1 = 0,
+ const ::rtl::OUString *pArg2 = 0 );
+
+
+};
+
+// some heaviliy used exception support
+const sal_Char sDefunc[] = "object is defunctional";
+const sal_Char sMissingWindow[] = "window is missing";
+
+#define THROW_RUNTIME_EXCEPTION( ifc, msg ) \
+ ::com::sun::star::uno::Reference < ifc > xThis( this ); \
+ ::com::sun::star::uno::RuntimeException aExcept( \
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(msg) ), xThis ); \
+ throw aExcept;
+
+#define CHECK_FOR_DEFUNC_THIS( ifc, ths ) \
+ if( !(GetFrm() && GetMap()) ) \
+ { \
+ ::com::sun::star::uno::Reference < ifc > xThis( ths ); \
+ ::com::sun::star::lang::DisposedException aExcept( \
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sDefunc) ), \
+ xThis ); \
+ throw aExcept; \
+ }
+
+#define CHECK_FOR_DEFUNC( ifc ) \
+ CHECK_FOR_DEFUNC_THIS( ifc, this )
+
+#define CHECK_FOR_WINDOW( i, w ) \
+ if( !(w) ) \
+ { \
+ THROW_RUNTIME_EXCEPTION( i, sMissingWindow ); \
+ }
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accdoc.cxx b/sw/source/core/access/accdoc.cxx
new file mode 100644
index 000000000000..e7b8e8b43141
--- /dev/null
+++ b/sw/source/core/access/accdoc.cxx
@@ -0,0 +1,516 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <vcl/window.hxx>
+#include <rootfrm.hxx>
+
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <tools/link.hxx>
+#include <sfx2/viewsh.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <viewsh.hxx>
+#include <doc.hxx>
+#include <accmap.hxx>
+#include <accdoc.hxx>
+#include "access.hrc"
+#include <pagefrm.hxx>
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextDocumentView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleDocumentView";
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+using lang::IndexOutOfBoundsException;
+
+
+
+//
+// SwAccessibleDocumentBase: base class for SwAccessibleDocument and
+// SwAccessiblePreview
+//
+
+SwAccessibleDocumentBase::SwAccessibleDocumentBase ( SwAccessibleMap* pInitMap ) :
+ SwAccessibleContext( pInitMap, AccessibleRole::DOCUMENT,
+ pInitMap->GetShell()->getIDocumentLayoutAccess()->GetRootFrm() ),
+ mxParent( pInitMap->GetShell()->GetWin()->GetAccessibleParentWindow()->GetAccessible() ),
+ mpChildWin( 0 )
+{
+}
+
+SwAccessibleDocumentBase::~SwAccessibleDocumentBase()
+{
+}
+
+void SwAccessibleDocumentBase::SetVisArea()
+{
+ SolarMutexGuard aGuard;
+
+ SwRect aOldVisArea( GetVisArea() );
+ const SwRect& rNewVisArea = GetMap()->GetVisArea();
+ if( aOldVisArea != rNewVisArea )
+ {
+ SwAccessibleFrame::SetVisArea( GetMap()->GetVisArea() );
+ // --> OD 2007-12-07 #i58139#
+ // showing state of document view needs also be updated.
+ // Thus, call method <Scrolled(..)> instead of <ChildrenScrolled(..)>
+// ChildrenScrolled( GetFrm(), aOldVisArea );
+ Scrolled( aOldVisArea );
+ // <--
+ }
+}
+
+void SwAccessibleDocumentBase::AddChild( Window *pWin, sal_Bool bFireEvent )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( !mpChildWin, "only one child window is supported" );
+ if( !mpChildWin )
+ {
+ mpChildWin = pWin;
+
+ if( bFireEvent )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.NewValue <<= mpChildWin->GetAccessible();
+ FireAccessibleEvent( aEvent );
+ }
+ }
+}
+
+void SwAccessibleDocumentBase::RemoveChild( Window *pWin )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( !mpChildWin || pWin == mpChildWin, "invalid child window to remove" );
+ if( mpChildWin && pWin == mpChildWin )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.OldValue <<= mpChildWin->GetAccessible();
+ FireAccessibleEvent( aEvent );
+
+ mpChildWin = 0;
+ }
+}
+
+sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleChildCount( void )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // CHECK_FOR_DEFUNC is called by parent
+
+ sal_Int32 nChildren = SwAccessibleContext::getAccessibleChildCount();
+ if( !IsDisposing() && mpChildWin )
+ nChildren++;
+
+ return nChildren;
+}
+
+uno::Reference< XAccessible> SAL_CALL
+ SwAccessibleDocumentBase::getAccessibleChild( sal_Int32 nIndex )
+ throw (uno::RuntimeException,
+ lang::IndexOutOfBoundsException)
+{
+ SolarMutexGuard aGuard;
+
+ if( mpChildWin )
+ {
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+ if ( nIndex == GetChildCount( *(GetMap()) ) )
+ {
+ return mpChildWin->GetAccessible();
+ }
+ }
+
+ return SwAccessibleContext::getAccessibleChild( nIndex );
+}
+
+
+uno::Reference< XAccessible> SAL_CALL SwAccessibleDocumentBase::getAccessibleParent (void)
+ throw (uno::RuntimeException)
+{
+ return mxParent;
+}
+
+sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleIndexInParent (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference < XAccessibleContext > xAcc( mxParent->getAccessibleContext() );
+ uno::Reference < XAccessible > xThis( this );
+ sal_Int32 nCount = xAcc->getAccessibleChildCount();
+
+ for( sal_Int32 i=0; i < nCount; i++ )
+ {
+ if( xAcc->getAccessibleChild( i ) == xThis )
+ return i;
+ }
+ return -1L;
+}
+
+OUString SAL_CALL SwAccessibleDocumentBase::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ return GetResource( STR_ACCESS_DOC_DESC );
+}
+
+awt::Rectangle SAL_CALL SwAccessibleDocumentBase::getBounds()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Rectangle aPixBounds( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ) );
+ awt::Rectangle aBox( aPixBounds.Left(), aPixBounds.Top(),
+ aPixBounds.GetWidth(), aPixBounds.GetHeight() );
+
+ return aBox;
+}
+
+
+awt::Point SAL_CALL SwAccessibleDocumentBase::getLocation()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Point aPixPos( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ).TopLeft() );
+ awt::Point aLoc( aPixPos.X(), aPixPos.Y() );
+
+ return aLoc;
+}
+
+
+::com::sun::star::awt::Point SAL_CALL SwAccessibleDocumentBase::getLocationOnScreen()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Point aPixPos( pWin->GetWindowExtentsRelative( 0 ).TopLeft() );
+ awt::Point aLoc( aPixPos.X(), aPixPos.Y() );
+
+ return aLoc;
+}
+
+
+::com::sun::star::awt::Size SAL_CALL SwAccessibleDocumentBase::getSize()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Size aPixSize( pWin->GetWindowExtentsRelative( 0 ).GetSize() );
+ awt::Size aSize( aPixSize.Width(), aPixSize.Height() );
+
+ return aSize;
+}
+
+sal_Bool SAL_CALL SwAccessibleDocumentBase::containsPoint(
+ const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Rectangle aPixBounds( pWin->GetWindowExtentsRelative( 0 ) );
+ aPixBounds.Move(-aPixBounds.Left(), -aPixBounds.Top());
+
+ Point aPixPoint( aPoint.X, aPoint.Y );
+ return aPixBounds.IsInside( aPixPoint );
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleDocumentBase::getAccessibleAtPoint(
+ const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if( mpChildWin )
+ {
+ CHECK_FOR_DEFUNC( XAccessibleComponent )
+
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Point aPixPoint( aPoint.X, aPoint.Y ); // px rel to window
+ if( mpChildWin->GetWindowExtentsRelative( pWin ).IsInside( aPixPoint ) )
+ return mpChildWin->GetAccessible();
+ }
+
+ return SwAccessibleContext::getAccessibleAtPoint( aPoint );
+}
+
+//
+// SwAccessibeDocument
+//
+
+void SwAccessibleDocument::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // MULTISELECTABLE
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
+}
+
+
+SwAccessibleDocument::SwAccessibleDocument ( SwAccessibleMap* pInitMap ) :
+ SwAccessibleDocumentBase( pInitMap ),
+ maSelectionHelper( *this )
+{
+ SetName( GetResource( STR_ACCESS_DOC_NAME ) );
+ Window *pWin = pInitMap->GetShell()->GetWin();
+ if( pWin )
+ {
+ pWin->AddChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
+ USHORT nCount = pWin->GetChildCount();
+ for( sal_uInt16 i=0; i < nCount; i++ )
+ {
+ Window* pChildWin = pWin->GetChild( i );
+ if( pChildWin &&
+ AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
+ AddChild( pChildWin, sal_False );
+ }
+ }
+}
+
+SwAccessibleDocument::~SwAccessibleDocument()
+{
+ Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : 0;
+ if( pWin )
+ pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
+}
+
+void SwAccessibleDocument::Dispose( sal_Bool bRecursive )
+{
+ OSL_ENSURE( GetFrm() && GetMap(), "already disposed" );
+
+ Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : 0;
+ if( pWin )
+ pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
+ SwAccessibleContext::Dispose( bRecursive );
+}
+
+IMPL_LINK( SwAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent )
+{
+ DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
+ if ( pEvent && pEvent->ISA( VclWindowEvent ) )
+ {
+ VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent );
+ DBG_ASSERT( pVclEvent->GetWindow(), "Window???" );
+ switch ( pVclEvent->GetId() )
+ {
+ case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
+ {
+ Window* pChildWin = static_cast< Window* >( pVclEvent->GetData() );
+ if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
+ {
+ AddChild( pChildWin );
+ }
+ }
+ break;
+ case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children
+ {
+ Window* pChildWin = static_cast< Window* >( pVclEvent->GetData() );
+ if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
+ {
+ RemoveChild( pChildWin );
+ }
+ }
+ break;
+ case VCLEVENT_OBJECT_DYING: // send destroy on hide for direct accessible children
+ {
+ Window* pChildWin = pVclEvent->GetWindow();
+ if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
+ {
+ RemoveChild( pChildWin );
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+
+OUString SAL_CALL SwAccessibleDocument::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleDocument::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleDocument::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+//===== XInterface ======================================================
+
+uno::Any SwAccessibleDocument::queryInterface(
+ const uno::Type& rType )
+ throw ( uno::RuntimeException )
+{
+ uno::Any aRet;
+ if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ) )
+ {
+ uno::Reference<XAccessibleSelection> aSelect = this;
+ aRet <<= aSelect;
+ }
+ else
+ aRet = SwAccessibleContext::queryInterface( rType );
+ return aRet;
+}
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleDocument::getTypes()
+ throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleDocumentBase::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ aTypes.realloc( nIndex + 1 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) );
+
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleDocument::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+//===== XAccessibleSelection ============================================
+
+void SwAccessibleDocument::selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ maSelectionHelper.selectAccessibleChild(nChildIndex);
+}
+
+sal_Bool SwAccessibleDocument::isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ return maSelectionHelper.isAccessibleChildSelected(nChildIndex);
+}
+
+void SwAccessibleDocument::clearAccessibleSelection( )
+ throw ( uno::RuntimeException )
+{
+ maSelectionHelper.clearAccessibleSelection();
+}
+
+void SwAccessibleDocument::selectAllAccessibleChildren( )
+ throw ( uno::RuntimeException )
+{
+ maSelectionHelper.selectAllAccessibleChildren();
+}
+
+sal_Int32 SwAccessibleDocument::getSelectedAccessibleChildCount( )
+ throw ( uno::RuntimeException )
+{
+ return maSelectionHelper.getSelectedAccessibleChildCount();
+}
+
+uno::Reference<XAccessible> SwAccessibleDocument::getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ return maSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
+}
+
+// --> OD 2004-11-16 #111714# - index has to be treated as global child index.
+void SwAccessibleDocument::deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ maSelectionHelper.deselectAccessibleChild( nChildIndex );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accdoc.hxx b/sw/source/core/access/accdoc.hxx
new file mode 100644
index 000000000000..05f061358f1f
--- /dev/null
+++ b/sw/source/core/access/accdoc.hxx
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCDOC_HXX
+#define _ACCDOC_HXX
+#include "acccontext.hxx"
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <accselectionhelper.hxx>
+
+class VclSimpleEvent;
+
+/**
+ * base class for SwAccessibleDocument (in this same header file) and
+ * SwAccessiblePreview
+ */
+class SwAccessibleDocumentBase : public SwAccessibleContext
+{
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible> mxParent;
+
+ Window* mpChildWin; // protected by solar mutext
+
+ using SwAccessibleFrame::SetVisArea;
+
+protected:
+
+ virtual ~SwAccessibleDocumentBase();
+
+public:
+
+ SwAccessibleDocumentBase( SwAccessibleMap* pInitMap );
+
+ void SetVisArea();
+
+ virtual void AddChild( Window *pWin, sal_Bool bFireEvent = sal_True );
+ virtual void RemoveChild( Window *pWin );
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return the number of currently visible children.
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the specified child or NULL if index is invalid.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleChild (sal_Int32 nIndex)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IndexOutOfBoundsException);
+
+ /// Return a reference to the parent.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleParent (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this objects index among the parents children.
+ virtual sal_Int32 SAL_CALL
+ getAccessibleIndexInParent (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void) throw (com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleComponent ==============================================
+ virtual sal_Bool SAL_CALL containsPoint(
+ const ::com::sun::star::awt::Point& aPoint )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(
+ const ::com::sun::star::awt::Point& aPoint )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocation()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Size SAL_CALL getSize()
+ throw (::com::sun::star::uno::RuntimeException);
+};
+
+
+
+/**
+ * access to an accessible Writer document
+ */
+class SwAccessibleDocument : public SwAccessibleDocumentBase,
+ public com::sun::star::accessibility::XAccessibleSelection
+{
+ // Implementation for XAccessibleSelection interface
+ SwAccessibleSelectionHelper maSelectionHelper;
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additinaly sets MULTISELECTABLE(1)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual ~SwAccessibleDocument();
+
+public:
+
+ SwAccessibleDocument( SwAccessibleMap* pInitMap );
+
+ DECL_LINK( WindowChildEventListener, VclSimpleEvent* );
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XInterface ======================================================
+
+ // XInterface is inherited through SwAcessibleContext and
+ // XAccessibleSelection. These methods are needed to avoid
+ // ambigiouties.
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleSelection ============================================
+
+ virtual void SAL_CALL selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Bool SAL_CALL isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL clearAccessibleSelection( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL selectAllAccessibleChildren( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // --> OD 2004-11-16 #111714# - index has to be treated as global child index.
+ virtual void SAL_CALL deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ //====== thread safe C++ interface ========================================
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accembedded.cxx b/sw/source/core/access/accembedded.cxx
new file mode 100644
index 000000000000..18808e2e80a4
--- /dev/null
+++ b/sw/source/core/access/accembedded.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <rtl/uuid.h>
+#include <flyfrm.hxx>
+#include "accembedded.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextEmbeddedObject";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleEmbeddedObject";
+
+SwAccessibleEmbeddedObject::SwAccessibleEmbeddedObject(
+ SwAccessibleMap* pInitMap,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleNoTextFrame( pInitMap, AccessibleRole::EMBEDDED_OBJECT, pFlyFrm )
+{
+}
+
+SwAccessibleEmbeddedObject::~SwAccessibleEmbeddedObject()
+{
+}
+
+OUString SAL_CALL SwAccessibleEmbeddedObject::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleEmbeddedObject::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleEmbeddedObject::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleEmbeddedObject::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accembedded.hxx b/sw/source/core/access/accembedded.hxx
new file mode 100644
index 000000000000..c1376afa909f
--- /dev/null
+++ b/sw/source/core/access/accembedded.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCEMBEDDED_HXX
+#define _ACCEMBEDDED_HXX
+#include "accnotextframe.hxx"
+
+class SwAccessibleEmbeddedObject : public SwAccessibleNoTextFrame
+{
+
+protected:
+
+ virtual ~SwAccessibleEmbeddedObject();
+
+public:
+
+ SwAccessibleEmbeddedObject( SwAccessibleMap* pInitMap,
+ const SwFlyFrm* pFlyFrm );
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfootnote.cxx b/sw/source/core/access/accfootnote.cxx
new file mode 100644
index 000000000000..6cfea848696c
--- /dev/null
+++ b/sw/source/core/access/accfootnote.cxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <osl/mutex.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <rtl/uuid.h>
+#include <vcl/svapp.hxx>
+#include <ftnfrm.hxx>
+#include <fmtftn.hxx>
+#include <txtftn.hxx>
+#include <viewsh.hxx>
+#include <accmap.hxx>
+#include "accfootnote.hxx"
+#include "access.hrc"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const sal_Char sServiceNameFootnote[] = "com.sun.star.text.AccessibleFootnoteView";
+const sal_Char sServiceNameEndnote[] = "com.sun.star.text.AccessibleEndnoteView";
+const sal_Char sImplementationNameFootnote[] = "com.sun.star.comp.Writer.SwAccessibleFootnoteView";
+const sal_Char sImplementationNameEndnote[] = "com.sun.star.comp.Writer.SwAccessibleEndnoteView";
+
+SwAccessibleFootnote::SwAccessibleFootnote(
+ SwAccessibleMap* pInitMap,
+ sal_Bool bIsEndnote,
+ sal_Int32 nFootEndNote,
+ const SwFtnFrm *pFtnFrm ) :
+ SwAccessibleContext( pInitMap,
+ bIsEndnote ? AccessibleRole::END_NOTE : AccessibleRole::FOOTNOTE,
+ pFtnFrm )
+{
+ SolarMutexGuard aGuard;
+
+ sal_uInt16 nResId = bIsEndnote ? STR_ACCESS_ENDNOTE_NAME
+ : STR_ACCESS_FOOTNOTE_NAME;
+ OUString sArg( OUString::valueOf( nFootEndNote ) );
+ SetName( GetResource( nResId, &sArg ) );
+}
+
+SwAccessibleFootnote::~SwAccessibleFootnote()
+{
+}
+
+OUString SAL_CALL SwAccessibleFootnote::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ sal_uInt16 nResId = AccessibleRole::END_NOTE == GetRole()
+ ? STR_ACCESS_ENDNOTE_DESC
+ : STR_ACCESS_FOOTNOTE_DESC ;
+
+ OUString sArg;
+ const SwTxtFtn *pTxtFtn =
+ static_cast< const SwFtnFrm *>( GetFrm() )->GetAttr();
+ if( pTxtFtn )
+ {
+ const SwDoc *pDoc = GetMap()->GetShell()->GetDoc();
+ sArg = pTxtFtn->GetFtn().GetViewNumStr( *pDoc );
+ }
+
+ return GetResource( nResId, &sArg );
+}
+
+OUString SAL_CALL SwAccessibleFootnote::getImplementationName()
+ throw( RuntimeException )
+{
+ if( AccessibleRole::END_NOTE == GetRole() )
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationNameEndnote));
+ else
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationNameFootnote));
+}
+
+sal_Bool SAL_CALL SwAccessibleFootnote::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ if( sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 ) )
+ return sal_True;
+ else if( AccessibleRole::END_NOTE == GetRole() )
+ return sTestServiceName.equalsAsciiL( sServiceNameEndnote, sizeof(sServiceNameEndnote)-1 );
+ else
+ return sTestServiceName.equalsAsciiL( sServiceNameFootnote, sizeof(sServiceNameFootnote)-1 );
+
+}
+
+Sequence< OUString > SAL_CALL SwAccessibleFootnote::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ if( AccessibleRole::END_NOTE == GetRole() )
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceNameEndnote) );
+ else
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceNameFootnote) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessibleFootnote::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+sal_Bool SwAccessibleFootnote::IsEndnote( const SwFtnFrm *pFtnFrm )
+{
+ const SwTxtFtn *pTxtFtn = pFtnFrm ->GetAttr();
+ return pTxtFtn && pTxtFtn->GetFtn().IsEndNote() ;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfootnote.hxx b/sw/source/core/access/accfootnote.hxx
new file mode 100644
index 000000000000..eae0820dcbd2
--- /dev/null
+++ b/sw/source/core/access/accfootnote.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFOOTNOTE_HXX
+#define _ACCFOOTNOTE_HXX
+
+#include <sal/types.h>
+
+#include <acccontext.hxx>
+
+class SwAccessibleMap;
+class SwFtnFrm;
+
+class SwAccessibleFootnote : public SwAccessibleContext
+{
+
+protected:
+
+ virtual ~SwAccessibleFootnote();
+
+public:
+
+ SwAccessibleFootnote( SwAccessibleMap* pInitMap,
+ sal_Bool bIsEndnote,
+ sal_Int32 nFootEndNote,
+ const SwFtnFrm *pFtnFrm );
+
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ static sal_Bool IsEndnote( const SwFtnFrm *pFrm );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accframe.cxx b/sw/source/core/access/accframe.cxx
new file mode 100644
index 000000000000..4bb48d0b826d
--- /dev/null
+++ b/sw/source/core/access/accframe.cxx
@@ -0,0 +1,499 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include <hintids.hxx>
+#include <editeng/brshitem.hxx>
+#include <flyfrm.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+#include <sectfrm.hxx>
+#include <pagefrm.hxx>
+#include <section.hxx>
+#include <viewsh.hxx>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <frmatr.hxx>
+#include <pagefrm.hxx>
+#include <pagedesc.hxx>
+#include <fmtanchr.hxx>
+#include <fldbas.hxx>
+#include <dcontact.hxx>
+#include <accmap.hxx>
+#include <accfrmobjslist.hxx>
+#include <accfrmobjmap.hxx>
+#include <accframe.hxx>
+
+using namespace sw::access;
+
+// Regarding visibilily (or in terms of accessibility: regarding the showing
+// state): A frame is visible and therfor contained in the tree if its frame
+// size overlaps with the visible area. The bounding box however is the
+// frame's paint area.
+/* static */ sal_Int32 SwAccessibleFrame::GetChildCount( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm *pFrm,
+ sal_Bool bInPagePreview )
+{
+ sal_Int32 nCount = 0;
+
+ const SwAccessibleChildSList aVisList( rVisArea, *pFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ nCount++;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ nCount += GetChildCount( rAccMap,
+ rVisArea, rLower.GetSwFrm(),
+ bInPagePreview );
+ }
+ ++aIter;
+ }
+
+ return nCount;
+}
+
+/* static */ SwAccessibleChild SwAccessibleFrame::GetChild(
+ SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ sal_Int32& rPos,
+ sal_Bool bInPagePreview )
+{
+ SwAccessibleChild aRet;
+
+ if( rPos >= 0 )
+ {
+ if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
+ {
+ // We need a sorted list here
+ const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildMap::const_iterator aIter( aVisMap.begin() );
+ while( aIter != aVisMap.end() && !aRet.IsValid() )
+ {
+ const SwAccessibleChild& rLower = (*aIter).second;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ if( 0 == rPos )
+ aRet = rLower;
+ else
+ rPos--;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ aRet = GetChild( rAccMap,
+ rVisArea, *(rLower.GetSwFrm()), rPos,
+ bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+ else
+ {
+ // The unsorted list is sorted enough, because it return lower
+ // frames in the correct order.
+ const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() && !aRet.IsValid() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ if( 0 == rPos )
+ aRet = rLower;
+ else
+ rPos--;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ aRet = GetChild( rAccMap,
+ rVisArea, *(rLower.GetSwFrm()), rPos,
+ bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+ }
+
+ return aRet;
+}
+
+/* static */ sal_Bool SwAccessibleFrame::GetChildIndex(
+ SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ const SwAccessibleChild& rChild,
+ sal_Int32& rPos,
+ sal_Bool bInPagePreview )
+{
+ sal_Bool bFound = sal_False;
+
+ if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
+ {
+ // We need a sorted list here
+ const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildMap::const_iterator aIter( aVisMap.begin() );
+ while( aIter != aVisMap.end() && !bFound )
+ {
+ const SwAccessibleChild& rLower = (*aIter).second;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ if( rChild == rLower )
+ bFound = sal_True;
+ else
+ rPos++;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ bFound = GetChildIndex( rAccMap,
+ rVisArea, *(rLower.GetSwFrm()), rChild,
+ rPos, bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+ else
+ {
+ // The unsorted list is sorted enough, because it return lower
+ // frames in the correct order.
+ const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() && !bFound )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ if( rChild == rLower )
+ bFound = sal_True;
+ else
+ rPos++;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ bFound = GetChildIndex( rAccMap,
+ rVisArea, *(rLower.GetSwFrm()), rChild,
+ rPos, bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+
+ return bFound;
+}
+
+SwAccessibleChild SwAccessibleFrame::GetChildAtPixel( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ const Point& rPixPos,
+ sal_Bool bInPagePreview,
+ SwAccessibleMap& rAccMap )
+{
+ SwAccessibleChild aRet;
+
+ if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
+ {
+ // We need a sorted list here, and we have to reverse iterate,
+ // because objects in front should be returned.
+ const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildMap::const_reverse_iterator aRIter( aVisMap.rbegin() );
+ while( aRIter != aVisMap.rend() && !aRet.IsValid() )
+ {
+ const SwAccessibleChild& rLower = (*aRIter).second;
+ // A frame is returned if it's frame size is inside the visarea
+ // and the positiion is inside the frame's paint area.
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ SwRect aLogBounds( rLower.GetBounds( rAccMap ) );
+ if( !aLogBounds.IsEmpty() )
+ {
+ Rectangle aPixBounds( rAccMap.CoreToPixel( aLogBounds.SVRect() ) );
+ if( aPixBounds.IsInside( rPixPos ) )
+ aRet = rLower;
+ }
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ aRet = GetChildAtPixel( rVisArea, *(rLower.GetSwFrm()), rPixPos,
+ bInPagePreview, rAccMap );
+ }
+ aRIter++;
+ }
+ }
+ else
+ {
+ // The unsorted list is sorted enough, because it returns lower
+ // frames in the correct order. Morover, we can iterate forward,
+ // because the lowers don't overlap!
+ const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() && !aRet.IsValid() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ // A frame is returned if it's frame size is inside the visarea
+ // and the positiion is inside the frame's paint area.
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ SwRect aLogBounds( rLower.GetBounds( rAccMap ) );
+ if( !aLogBounds.IsEmpty() )
+ {
+ Rectangle aPixBounds( rAccMap.CoreToPixel( aLogBounds.SVRect() ) );
+ if( aPixBounds.IsInside( rPixPos ) )
+ aRet = rLower;
+ }
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ aRet = GetChildAtPixel( rVisArea, *(rLower.GetSwFrm()), rPixPos,
+ bInPagePreview, rAccMap );
+ }
+ ++aIter;
+ }
+ }
+
+ return aRet;
+}
+
+/* static */ void SwAccessibleFrame::GetChildren( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ ::std::list< SwAccessibleChild >& rChildren,
+ sal_Bool bInPagePreview )
+{
+ if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
+ {
+ // We need a sorted list here
+ const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildMap::const_iterator aIter( aVisMap.begin() );
+ while( aIter != aVisMap.end() )
+ {
+ const SwAccessibleChild& rLower = (*aIter).second;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ rChildren.push_back( rLower );
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ GetChildren( rAccMap, rVisArea, *(rLower.GetSwFrm()),
+ rChildren, bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+ else
+ {
+ // The unsorted list is sorted enough, because it return lower
+ // frames in the correct order.
+ const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ rChildren.push_back( rLower );
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ GetChildren( rAccMap, rVisArea, *(rLower.GetSwFrm()),
+ rChildren, bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+}
+
+SwRect SwAccessibleFrame::GetBounds( const SwAccessibleMap& rAccMap,
+ const SwFrm *pFrm )
+{
+ if( !pFrm )
+ pFrm = GetFrm();
+
+ SwAccessibleChild aFrm( pFrm );
+ SwRect aBounds( aFrm.GetBounds( rAccMap ).Intersection( maVisArea ) );
+ return aBounds;
+}
+
+sal_Bool SwAccessibleFrame::IsEditable( ViewShell *pVSh ) const
+{
+ const SwFrm *pFrm = GetFrm();
+ if( !pFrm )
+ return sal_False;
+
+ OSL_ENSURE( pVSh, "no view shell" );
+ if( pVSh && (pVSh->GetViewOptions()->IsReadonly() ||
+ pVSh->IsPreView()) )
+ return sal_False;
+
+ if( !pFrm->IsRootFrm() && pFrm->IsProtected() )
+ return sal_False;
+
+ return sal_True;
+}
+
+sal_Bool SwAccessibleFrame::IsOpaque( ViewShell *pVSh ) const
+{
+ SwAccessibleChild aFrm( GetFrm() );
+ if( !aFrm.GetSwFrm() )
+ return sal_False;
+
+ OSL_ENSURE( pVSh, "no view shell" );
+ if( !pVSh )
+ return sal_False;
+
+ const SwViewOption *pVOpt = pVSh->GetViewOptions();
+ do
+ {
+ const SwFrm *pFrm = aFrm.GetSwFrm();
+ if( pFrm->IsRootFrm() )
+ return sal_True;
+
+ if( pFrm->IsPageFrm() && !pVOpt->IsPageBack() )
+ return sal_False;
+
+ const SvxBrushItem &rBack = pFrm->GetAttrSet()->GetBackground();
+ if( !rBack.GetColor().GetTransparency() ||
+ rBack.GetGraphicPos() != GPOS_NONE )
+ return sal_True;
+
+ /// OD 20.08.2002 #99657#
+ /// If a fly frame has a transparent background color, we have
+ /// to consider the background.
+ /// But a background color "no fill"/"auto fill" has *not* to be considered.
+ if( pFrm->IsFlyFrm() &&
+ (rBack.GetColor().GetTransparency() != 0) &&
+ (rBack.GetColor() != COL_TRANSPARENT)
+ )
+ return sal_True;
+
+ if( pFrm->IsSctFrm() )
+ {
+ const SwSection* pSection = ((SwSectionFrm*)pFrm)->GetSection();
+ if( pSection && ( TOX_HEADER_SECTION == pSection->GetType() ||
+ TOX_CONTENT_SECTION == pSection->GetType() ) &&
+ !pVOpt->IsReadonly() &&
+ SwViewOption::IsIndexShadings() )
+ return sal_True;
+ }
+ if( pFrm->IsFlyFrm() )
+ aFrm = static_cast<const SwFlyFrm*>(pFrm)->GetAnchorFrm();
+ else
+ aFrm = pFrm->GetUpper();
+ } while( aFrm.GetSwFrm() && !aFrm.IsAccessible( IsInPagePreview() ) );
+
+ return sal_False;
+}
+
+SwAccessibleFrame::SwAccessibleFrame( const SwRect& rVisArea,
+ const SwFrm *pF,
+ sal_Bool bIsPagePreview ) :
+ maVisArea( rVisArea ),
+ mpFrm( pF ),
+ mbIsInPagePreview( bIsPagePreview )
+{
+}
+
+SwAccessibleFrame::~SwAccessibleFrame()
+{
+}
+
+/* static */ const SwFrm* SwAccessibleFrame::GetParent( const SwAccessibleChild& rFrmOrObj,
+ sal_Bool bInPagePreview )
+{
+ return rFrmOrObj.GetParent( bInPagePreview );
+}
+
+String SwAccessibleFrame::GetFormattedPageNumber() const
+{
+ sal_uInt16 nPageNum = GetFrm()->GetVirtPageNum();
+ sal_uInt32 nFmt = GetFrm()->FindPageFrm()->GetPageDesc()
+ ->GetNumType().GetNumberingType();
+ if( SVX_NUM_NUMBER_NONE == nFmt )
+ nFmt = SVX_NUM_ARABIC;
+
+ String sRet( FormatNumber( nPageNum, nFmt ) );
+ return sRet;
+}
+
+sal_Int32 SwAccessibleFrame::GetChildCount( SwAccessibleMap& rAccMap ) const
+{
+ return GetChildCount( rAccMap, maVisArea, mpFrm, IsInPagePreview() );
+}
+
+sw::access::SwAccessibleChild SwAccessibleFrame::GetChild(
+ SwAccessibleMap& rAccMap,
+ sal_Int32 nPos ) const
+{
+ return SwAccessibleFrame::GetChild( rAccMap, maVisArea, *mpFrm, nPos, IsInPagePreview() );
+}
+
+sal_Int32 SwAccessibleFrame::GetChildIndex( SwAccessibleMap& rAccMap,
+ const sw::access::SwAccessibleChild& rChild ) const
+{
+ sal_Int32 nPos = 0;
+ return GetChildIndex( rAccMap, maVisArea, *mpFrm, rChild, nPos, IsInPagePreview() )
+ ? nPos
+ : -1L;
+}
+
+sw::access::SwAccessibleChild SwAccessibleFrame::GetChildAtPixel(
+ const Point& rPos,
+ SwAccessibleMap& rAccMap ) const
+{
+ return GetChildAtPixel( maVisArea, *mpFrm, rPos, IsInPagePreview(), rAccMap );
+}
+
+void SwAccessibleFrame::GetChildren( SwAccessibleMap& rAccMap,
+ ::std::list< sw::access::SwAccessibleChild >& rChildren ) const
+{
+ GetChildren( rAccMap, maVisArea, *mpFrm, rChildren, IsInPagePreview() );
+}
+
+sal_Bool SwAccessibleFrame::IsShowing( const SwAccessibleMap& rAccMap,
+ const sw::access::SwAccessibleChild& rFrmOrObj ) const
+{
+ return IsShowing( rFrmOrObj.GetBox( rAccMap ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accframe.hxx b/sw/source/core/access/accframe.hxx
new file mode 100644
index 000000000000..f92d58fcf9ee
--- /dev/null
+++ b/sw/source/core/access/accframe.hxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRAME_HXX
+#define _ACCFRAME_HXX
+
+#include <swrect.hxx>
+
+#include <sal/types.h>
+#include <tools/string.hxx>
+
+#include <list>
+#include <accfrmobj.hxx>
+
+class SwAccessibleMap;
+class SwFrm;
+class ViewShell;
+namespace sw { namespace access {
+ class SwAccessibleChild;
+}}
+
+// Any method of this class must be called with an acquired solar mutex!
+
+class SwAccessibleFrame
+{
+ SwRect maVisArea;
+ const SwFrm* mpFrm;
+ const sal_Bool mbIsInPagePreview;
+
+protected:
+ // --> OD 2007-06-29 #i77106#
+ // method needs to be called by new class <SwAccessibleTableColHeaders>
+ static sal_Int32 GetChildCount( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm *pFrm,
+ sal_Bool bInPagePreview );
+private:
+ static sw::access::SwAccessibleChild GetChild( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ sal_Int32& rPos,
+ sal_Bool bInPagePreview);
+
+ static sal_Bool GetChildIndex( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ const sw::access::SwAccessibleChild& rChild,
+ sal_Int32& rPos,
+ sal_Bool bInPagePreview );
+
+ static sw::access::SwAccessibleChild GetChildAtPixel( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ const Point& rPos,
+ sal_Bool bInPagePreview,
+ SwAccessibleMap& rAccMap );
+
+ static void GetChildren( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ ::std::list< sw::access::SwAccessibleChild >& rChildren,
+ sal_Bool bInPagePreview );
+
+protected:
+
+ sal_Bool IsEditable( ViewShell *pVSh ) const;
+
+ sal_Bool IsOpaque( ViewShell *pVSh ) const;
+
+ sal_Bool IsShowing( const SwAccessibleMap& rAccMap,
+ const sw::access::SwAccessibleChild& rFrmOrObj ) const;
+ inline sal_Bool IsShowing( const SwRect& rFrm ) const;
+ inline sal_Bool IsShowing( const SwAccessibleMap& rAccMap ) const;
+
+ inline sal_Bool IsInPagePreview() const
+ {
+ return mbIsInPagePreview;
+ }
+
+ inline void ClearFrm()
+ {
+ mpFrm = 0;
+ }
+
+ SwAccessibleFrame( const SwRect& rVisArea,
+ const SwFrm *pFrm,
+ sal_Bool bIsPagePreview );
+ virtual ~SwAccessibleFrame();
+
+public:
+ // Return the SwFrm this context is attached to.
+ const SwFrm* GetFrm() const { return mpFrm; };
+
+ static const SwFrm* GetParent( const sw::access::SwAccessibleChild& rFrmOrObj,
+ sal_Bool bInPagePreview );
+
+ sal_Int32 GetChildIndex( SwAccessibleMap& rAccMap,
+ const sw::access::SwAccessibleChild& rChild ) const;
+
+protected:
+
+ // Return the bounding box of the frame clipped to the vis area. If
+ // no frame is specified, use this' frame.
+ SwRect GetBounds( const SwAccessibleMap& rAccMap,
+ const SwFrm *pFrm = 0 );
+
+ // Return the upper that has a context attached. This might be
+ // another one than the immediate upper.
+ inline const SwFrm *GetParent() const;
+
+ // Return the lower count or the nth lower, there the lowers have a
+ // not be same one as the SwFrm's lowers
+ sal_Int32 GetChildCount( SwAccessibleMap& rAccMap ) const;
+ sw::access::SwAccessibleChild GetChild( SwAccessibleMap& rAccMap,
+ sal_Int32 nPos ) const;
+ sw::access::SwAccessibleChild GetChildAtPixel( const Point& rPos,
+ SwAccessibleMap& rAccMap ) const;
+ void GetChildren( SwAccessibleMap& rAccMap,
+ ::std::list< sw::access::SwAccessibleChild >& rChildren ) const;
+
+ inline void SetVisArea( const SwRect& rNewVisArea )
+ {
+ maVisArea = rNewVisArea;
+ }
+
+ inline const SwRect& GetVisArea() const
+ {
+ return maVisArea;
+ }
+
+
+ String GetFormattedPageNumber() const;
+};
+
+inline sal_Bool SwAccessibleFrame::IsShowing( const SwRect& rFrm ) const
+{
+ return rFrm.IsOver( maVisArea );
+}
+
+inline sal_Bool SwAccessibleFrame::IsShowing( const SwAccessibleMap& rAccMap ) const
+{
+ sw::access::SwAccessibleChild aFrmOrObj( GetFrm() );
+ return IsShowing( rAccMap, aFrmOrObj );
+}
+
+inline const SwFrm *SwAccessibleFrame::GetParent() const
+{
+ sw::access::SwAccessibleChild aFrmOrObj( GetFrm() );
+ return GetParent( aFrmOrObj, IsInPagePreview() );
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accframebase.cxx b/sw/source/core/access/accframebase.cxx
new file mode 100644
index 000000000000..f9c77e2a0e26
--- /dev/null
+++ b/sw/source/core/access/accframebase.cxx
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <frmfmt.hxx>
+#include <ndnotxt.hxx>
+#include <flyfrm.hxx>
+#include <cntfrm.hxx>
+#include <fmtcntnt.hxx>
+#include <ndindex.hxx>
+#include "fesh.hxx"
+#include <hints.hxx>
+#include "accmap.hxx"
+#include "accframebase.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+sal_Bool SwAccessibleFrameBase::IsSelected()
+{
+ sal_Bool bRet = sal_False;
+
+ DBG_ASSERT( GetMap(), "no map?" );
+ const ViewShell *pVSh = GetMap()->GetShell();
+ DBG_ASSERT( pVSh, "no shell?" );
+ if( pVSh->ISA( SwFEShell ) )
+ {
+ const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
+ const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
+ if( pFlyFrm == GetFrm() )
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+void SwAccessibleFrameBase::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ const ViewShell *pVSh = GetMap()->GetShell();
+ DBG_ASSERT( pVSh, "no shell?" );
+ sal_Bool bSelectable = pVSh->ISA( SwFEShell );
+
+ // SELECTABLE
+ if( bSelectable )
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+
+ // FOCUSABLE
+ if( bSelectable )
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ // SELECTED and FOCUSED
+ if( IsSelected() )
+ {
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+ OSL_ENSURE( bIsSelected, "bSelected out of sync" );
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+ }
+}
+
+
+sal_uInt8 SwAccessibleFrameBase::GetNodeType( const SwFlyFrm *pFlyFrm )
+{
+ sal_uInt8 nType = ND_TEXTNODE;
+ if( pFlyFrm->Lower() )
+ {
+ if( pFlyFrm->Lower()->IsNoTxtFrm() )
+ {
+ const SwCntntFrm *pCntFrm =
+ static_cast<const SwCntntFrm *>( pFlyFrm->Lower() );
+ nType = pCntFrm->GetNode()->GetNodeType();
+ }
+ }
+ else
+ {
+ const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ const SwNodeIndex *pNdIdx = rCntnt.GetCntntIdx();
+ if( pNdIdx )
+ {
+ const SwCntntNode *pCNd =
+ (pNdIdx->GetNodes())[pNdIdx->GetIndex()+1]->GetCntntNode();
+ if( pCNd )
+ nType = pCNd->GetNodeType();
+ }
+ }
+
+ return nType;
+}
+
+SwAccessibleFrameBase::SwAccessibleFrameBase(
+ SwAccessibleMap* pInitMap,
+ sal_Int16 nInitRole,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleContext( pInitMap, nInitRole, pFlyFrm ),
+ bIsSelected( sal_False )
+{
+ SolarMutexGuard aGuard;
+
+ const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
+ const_cast< SwFrmFmt * >( pFrmFmt )->Add( this );
+
+ SetName( pFrmFmt->GetName() );
+
+ bIsSelected = IsSelected();
+}
+
+void SwAccessibleFrameBase::_InvalidateCursorPos()
+{
+ sal_Bool bNewSelected = IsSelected();
+ sal_Bool bOldSelected;
+
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bOldSelected = bIsSelected;
+ bIsSelected = bNewSelected;
+ }
+
+ if( bNewSelected )
+ {
+ // remember that object as the one that has the caret. This is
+ // neccessary to notify that object if the cursor leaves it.
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ if( bOldSelected != bNewSelected )
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() && bNewSelected )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
+ FireStateChangedEvent( AccessibleStateType::SELECTED, bNewSelected );
+ if( pWin && pWin->HasFocus() && !bNewSelected )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
+
+ uno::Reference< XAccessible > xParent( GetWeakParent() );
+ if( xParent.is() )
+ {
+ SwAccessibleContext *pAcc =
+ static_cast <SwAccessibleContext *>( xParent.get() );
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
+ pAcc->FireAccessibleEvent( aEvent );
+ }
+ }
+}
+
+void SwAccessibleFrameBase::_InvalidateFocus()
+{
+ Window *pWin = GetWindow();
+ if( pWin )
+ {
+ sal_Bool bSelected;
+
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bSelected = bIsSelected;
+ }
+ OSL_ENSURE( bSelected, "focus object should be selected" );
+
+ FireStateChangedEvent( AccessibleStateType::FOCUSED,
+ pWin->HasFocus() && bSelected );
+ }
+}
+
+sal_Bool SwAccessibleFrameBase::HasCursor()
+{
+ osl::MutexGuard aGuard( aMutex );
+ return bIsSelected;
+}
+
+
+SwAccessibleFrameBase::~SwAccessibleFrameBase()
+{
+}
+
+void SwAccessibleFrameBase::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew)
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+ const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( GetFrm() );
+ switch( nWhich )
+ {
+ case RES_NAME_CHANGED:
+ if( pFlyFrm )
+ {
+ const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
+ OSL_ENSURE( pFrmFmt == GetRegisteredIn(), "invalid frame" );
+
+ OUString sOldName( GetName() );
+ OSL_ENSURE( !pOld ||
+ static_cast < SwStringMsgPoolItem * >( pOld )->GetString() == String( sOldName ),
+ "invalid old name" );
+
+ const String& rNewName = pFrmFmt->GetName();
+ SetName( rNewName );
+ OSL_ENSURE( !pNew ||
+ static_cast < SwStringMsgPoolItem * >( pNew )->GetString() == rNewName,
+ "invalid new name" );
+
+ if( sOldName != GetName() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::NAME_CHANGED;
+ aEvent.OldValue <<= sOldName;
+ aEvent.NewValue <<= GetName();
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ break;
+ case RES_OBJECTDYING:
+ if( GetRegisteredIn() ==
+ static_cast< SwModify *>( static_cast< SwPtrMsgPoolItem * >( pOld )->pObject ) )
+ pRegisteredIn->Remove( this );
+ break;
+
+ case RES_FMT_CHG:
+ if( static_cast< SwFmtChg * >(pNew)->pChangedFmt == GetRegisteredIn() &&
+ static_cast< SwFmtChg * >(pOld)->pChangedFmt->IsFmtInDTOR() )
+ pRegisteredIn->Remove( this );
+ break;
+ default:
+ SwClient::Modify( pOld, pNew );
+ break;
+ }
+}
+
+void SwAccessibleFrameBase::Dispose( sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ if( GetRegisteredIn() )
+ pRegisteredIn->Remove( this );
+
+ SwAccessibleContext::Dispose( bRecursive );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accframebase.hxx b/sw/source/core/access/accframebase.hxx
new file mode 100644
index 000000000000..780249f72b9e
--- /dev/null
+++ b/sw/source/core/access/accframebase.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRAMEBASE_HXX
+#define _ACCFRAMEBASE_HXX
+
+#include <acccontext.hxx>
+
+#include <calbck.hxx>
+
+class SwFlyFrm;
+
+class SwAccessibleFrameBase : public SwAccessibleContext,
+ public SwClient
+{
+ sal_Bool bIsSelected; // protected by base class mutex
+
+ sal_Bool IsSelected();
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additionaly sets SELECTABLE(1), SELECTED(+),
+ // FOCUSABLE(1) and FOCUSED(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual void _InvalidateCursorPos();
+ virtual void _InvalidateFocus();
+
+ virtual ~SwAccessibleFrameBase();
+
+public:
+
+ SwAccessibleFrameBase( SwAccessibleMap* pInitMap,
+ sal_Int16 nInitRole,
+ const SwFlyFrm *pFlyFrm );
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+
+ virtual void Modify( SfxPoolItem *pOld, SfxPoolItem *pNew);
+
+ static sal_uInt8 GetNodeType( const SwFlyFrm *pFlyFrm );
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobj.cxx b/sw/source/core/access/accfrmobj.cxx
new file mode 100644
index 000000000000..1e72847fbe3f
--- /dev/null
+++ b/sw/source/core/access/accfrmobj.cxx
@@ -0,0 +1,430 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <accfrmobj.hxx>
+
+#include <accmap.hxx>
+#include <acccontext.hxx>
+
+#include <viewsh.hxx>
+#include <rootfrm.hxx>
+#include <flyfrm.hxx>
+#include <pagefrm.hxx>
+#include <cellfrm.hxx>
+#include <swtable.hxx>
+#include <dflyobj.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <dcontact.hxx>
+
+#include <vcl/window.hxx>
+
+namespace css = ::com::sun::star;
+
+namespace sw { namespace access {
+
+SwAccessibleChild::SwAccessibleChild()
+ : mpFrm( 0 )
+ , mpDrawObj( 0 )
+ , mpWindow( 0 )
+{}
+
+SwAccessibleChild::SwAccessibleChild( const SdrObject* pDrawObj )
+ : mpFrm( 0 )
+ , mpDrawObj( 0 )
+ , mpWindow( 0 )
+{
+ Init( pDrawObj );
+}
+
+SwAccessibleChild::SwAccessibleChild( const SwFrm* pFrm )
+ : mpFrm( 0 )
+ , mpDrawObj( 0 )
+ , mpWindow( 0 )
+{
+ Init( pFrm );
+}
+
+SwAccessibleChild::SwAccessibleChild( Window* pWindow )
+ : mpFrm( 0 )
+ , mpDrawObj( 0 )
+ , mpWindow( 0 )
+{
+ Init( pWindow );
+}
+
+
+SwAccessibleChild::SwAccessibleChild( const SwFrm* pFrm,
+ const SdrObject* pDrawObj,
+ Window* pWindow )
+{
+ if ( pFrm )
+ {
+ Init( pFrm );
+ }
+ else if ( pDrawObj )
+ {
+ Init( pDrawObj );
+ }
+ else if ( pWindow )
+ {
+ Init( pWindow );
+ }
+ OSL_ENSURE( (!pFrm || pFrm == mpFrm) &&
+ (!pDrawObj || pDrawObj == mpDrawObj) &&
+ (!pWindow || pWindow == mpWindow),
+ "invalid frame/object/window combination" );
+
+}
+
+void SwAccessibleChild::Init( const SdrObject* pDrawObj )
+{
+ mpDrawObj = pDrawObj;
+ mpFrm = mpDrawObj && mpDrawObj->ISA(SwVirtFlyDrawObj)
+ ? static_cast < const SwVirtFlyDrawObj * >( mpDrawObj )->GetFlyFrm()
+ : 0;
+ mpWindow = 0;
+}
+
+void SwAccessibleChild::Init( const SwFrm* pFrm )
+{
+ mpFrm = pFrm;
+ mpDrawObj = mpFrm && mpFrm->IsFlyFrm()
+ ? static_cast < const SwFlyFrm * >( mpFrm )->GetVirtDrawObj()
+ : 0;
+ mpWindow = 0;
+}
+
+void SwAccessibleChild::Init( Window* pWindow )
+{
+ mpWindow = pWindow;
+ mpFrm = 0;
+ mpDrawObj = 0;
+}
+
+bool SwAccessibleChild::IsAccessible( sal_Bool bPagePreview ) const
+{
+ bool bRet( false );
+
+ if ( mpFrm )
+ {
+ bRet = mpFrm->IsAccessibleFrm() &&
+ ( !mpFrm->IsCellFrm() ||
+ static_cast<const SwCellFrm *>( mpFrm )->GetTabBox()->GetSttNd() != 0 ) &&
+ !mpFrm->IsInCoveredCell() &&
+ ( bPagePreview ||
+ !mpFrm->IsPageFrm() );
+ }
+ else if ( mpDrawObj )
+ {
+ bRet = true;
+ }
+ else if ( mpWindow )
+ {
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool SwAccessibleChild::IsBoundAsChar() const
+{
+ bool bRet( false );
+
+ if ( mpFrm )
+ {
+ bRet = mpFrm->IsFlyFrm() &&
+ static_cast< const SwFlyFrm *>(mpFrm)->IsFlyInCntFrm();
+ }
+ else if ( mpDrawObj )
+ {
+ const SwFrmFmt* mpFrmFmt = ::FindFrmFmt( mpDrawObj );
+ bRet = mpFrmFmt
+ ? (FLY_AS_CHAR == mpFrmFmt->GetAnchor().GetAnchorId())
+ : false;
+ }
+ else if ( mpWindow )
+ {
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+SwAccessibleChild::SwAccessibleChild( const SwAccessibleChild& r )
+ : mpFrm( r.mpFrm )
+ , mpDrawObj( r.mpDrawObj )
+ , mpWindow( r.mpWindow )
+{}
+
+SwAccessibleChild& SwAccessibleChild::operator=( const SwAccessibleChild& r )
+{
+ mpDrawObj = r.mpDrawObj;
+ mpFrm = r.mpFrm;
+ mpWindow = r.mpWindow;
+
+ return *this;
+}
+
+SwAccessibleChild& SwAccessibleChild::operator=( const SdrObject* pDrawObj )
+{
+ Init( pDrawObj );
+ return *this;
+}
+
+SwAccessibleChild& SwAccessibleChild::operator=( const SwFrm* pFrm )
+{
+ Init( pFrm );
+ return *this;
+}
+
+SwAccessibleChild& SwAccessibleChild::operator=( Window* pWindow )
+{
+ Init( pWindow );
+ return *this;
+}
+
+bool SwAccessibleChild::operator==( const SwAccessibleChild& r ) const
+{
+ return mpFrm == r.mpFrm &&
+ mpDrawObj == r.mpDrawObj &&
+ mpWindow == r.mpWindow;
+}
+
+bool SwAccessibleChild::IsValid() const
+{
+ return mpFrm != 0 ||
+ mpDrawObj != 0 ||
+ mpWindow != 0;
+}
+
+const SdrObject* SwAccessibleChild::GetDrawObject() const
+{
+ return mpDrawObj;
+}
+
+const SwFrm *SwAccessibleChild::GetSwFrm() const
+{
+ return mpFrm;
+}
+
+Window* SwAccessibleChild::GetWindow() const
+{
+ return mpWindow;
+}
+
+bool SwAccessibleChild::IsVisibleChildrenOnly() const
+{
+ bool bRet( false );
+
+ if ( !mpFrm )
+ {
+ bRet = true;
+ }
+ else
+ {
+ bRet = mpFrm->IsRootFrm() ||
+ !( mpFrm->IsTabFrm() ||
+ mpFrm->IsInTab() ||
+ ( IsBoundAsChar() &&
+ static_cast<const SwFlyFrm*>(mpFrm)->GetAnchorFrm()->IsInTab() ) );
+ }
+
+ return bRet;
+}
+
+SwRect SwAccessibleChild::GetBox( const SwAccessibleMap& rAccMap ) const
+{
+ SwRect aBox;
+
+ if ( mpFrm )
+ {
+ if ( mpFrm->IsPageFrm() &&
+ static_cast< const SwPageFrm * >( mpFrm )->IsEmptyPage() )
+ {
+ aBox = SwRect( mpFrm->Frm().Left(), mpFrm->Frm().Top()-1, 1, 1 );
+ }
+ else if ( mpFrm->IsTabFrm() )
+ {
+ aBox = SwRect( mpFrm->Frm() );
+ aBox.Intersection( mpFrm->GetUpper()->Frm() );
+ }
+ else
+ {
+ aBox = mpFrm->Frm();
+ }
+ }
+ else if( mpDrawObj )
+ {
+ aBox = SwRect( mpDrawObj->GetCurrentBoundRect() );
+ }
+ else if ( mpWindow )
+ {
+ aBox = SwRect( rAccMap.GetShell()->GetWin()->PixelToLogic(
+ Rectangle( mpWindow->GetPosPixel(),
+ mpWindow->GetSizePixel() ) ) );
+}
+
+ return aBox;
+}
+
+SwRect SwAccessibleChild::GetBounds( const SwAccessibleMap& rAccMap ) const
+{
+ SwRect aBound;
+
+ if( mpFrm )
+ {
+ if( mpFrm->IsPageFrm() &&
+ static_cast< const SwPageFrm * >( mpFrm )->IsEmptyPage() )
+ {
+ aBound = SwRect( mpFrm->Frm().Left(), mpFrm->Frm().Top()-1, 0, 0 );
+ }
+ else
+ aBound = mpFrm->PaintArea();
+ }
+ else if( mpDrawObj )
+ {
+ aBound = GetBox( rAccMap );
+ }
+ else if ( mpWindow )
+ {
+ aBound = GetBox( rAccMap );
+ }
+
+ return aBound;
+}
+
+bool SwAccessibleChild::AlwaysIncludeAsChild() const
+{
+ bool bAlwaysIncludedAsChild( false );
+
+ if ( mpWindow )
+ {
+ bAlwaysIncludedAsChild = true;
+ }
+
+ return bAlwaysIncludedAsChild;
+}
+
+const SwFrm* SwAccessibleChild::GetParent( const sal_Bool bInPagePreview ) const
+{
+ const SwFrm* pParent( 0 );
+
+ if ( mpFrm )
+ {
+ if( mpFrm->IsFlyFrm() )
+ {
+ const SwFlyFrm* pFly = static_cast< const SwFlyFrm *>( mpFrm );
+ if( pFly->IsFlyInCntFrm() )
+ {
+ // For FLY_AS_CHAR the parent is the anchor
+ pParent = pFly->GetAnchorFrm();
+ OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ),
+ "parent is not accessible" );
+ }
+ else
+ {
+ // In any other case the parent is the root frm
+ // (in page preview, the page frame)
+ if( bInPagePreview )
+ pParent = pFly->FindPageFrm();
+ else
+ pParent = pFly->FindRootFrm();
+ }
+ }
+ else
+ {
+ SwAccessibleChild aUpper( mpFrm->GetUpper() );
+ while( aUpper.GetSwFrm() && !aUpper.IsAccessible(bInPagePreview) )
+ {
+ aUpper = aUpper.GetSwFrm()->GetUpper();
+ }
+ pParent = aUpper.GetSwFrm();
+ }
+ }
+ else if( mpDrawObj )
+ {
+ const SwDrawContact *pContact =
+ static_cast< const SwDrawContact* >( GetUserCall( mpDrawObj ) );
+ OSL_ENSURE( pContact, "sdr contact is missing" );
+ if( pContact )
+ {
+ const SwFrmFmt *pFrmFmt = pContact->GetFmt();
+ OSL_ENSURE( pFrmFmt, "frame format is missing" );
+ if( pFrmFmt && FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
+ {
+ // For FLY_AS_CHAR the parent is the anchor
+ pParent = pContact->GetAnchorFrm();
+ OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ),
+ "parent is not accessible" );
+
+ }
+ else
+ {
+ // In any other case the parent is the root frm
+ if( bInPagePreview )
+ pParent = pContact->GetAnchorFrm()->FindPageFrm();
+ else
+ pParent = pContact->GetAnchorFrm()->FindRootFrm();
+ }
+ }
+ }
+ else if ( mpWindow )
+ {
+ css::uno::Reference < css::accessibility::XAccessible > xAcc =
+ mpWindow->GetAccessible();
+ if ( xAcc.is() )
+ {
+ css::uno::Reference < css::accessibility::XAccessibleContext > xAccContext =
+ xAcc->getAccessibleContext();
+ if ( xAccContext.is() )
+ {
+ css::uno::Reference < css::accessibility::XAccessible > xAccParent =
+ xAccContext->getAccessibleParent();
+ if ( xAccParent.is() )
+ {
+ SwAccessibleContext* pAccParentImpl =
+ dynamic_cast< SwAccessibleContext *>( xAccParent.get() );
+ if ( pAccParentImpl )
+ {
+ pParent = pAccParentImpl->GetFrm();
+ }
+ }
+ }
+ }
+ }
+
+ return pParent;
+}
+
+} } // eof of namespace sw::access
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobj.hxx b/sw/source/core/access/accfrmobj.hxx
new file mode 100644
index 000000000000..5bb470d2a4f8
--- /dev/null
+++ b/sw/source/core/access/accfrmobj.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRMOBJ_HXX
+#define _ACCFRMOBJ_HXX
+
+#include <sal/types.h>
+
+class SwAccessibleMap;
+class SwFrm;
+class SdrObject;
+class Window;
+class SwRect;
+
+namespace sw { namespace access {
+
+class SwAccessibleChild
+{
+ public:
+ SwAccessibleChild();
+ explicit SwAccessibleChild( const SdrObject* pDrawObj );
+ explicit SwAccessibleChild( const SwFrm* pFrm );
+ explicit SwAccessibleChild( Window* pWindow );
+ SwAccessibleChild( const SwFrm* pFrm,
+ const SdrObject* pDrawObj,
+ Window* pWindow );
+
+ SwAccessibleChild( const SwAccessibleChild& r );
+ SwAccessibleChild& operator=( const SwAccessibleChild& r );
+
+ SwAccessibleChild& operator=( const SdrObject* pDrawObj );
+ SwAccessibleChild& operator=( const SwFrm* pFrm );
+ SwAccessibleChild& operator=( Window* pWindow );
+
+ bool operator==( const SwAccessibleChild& r ) const;
+
+ bool IsValid() const;
+
+ const SwFrm* GetSwFrm() const;
+ const SdrObject* GetDrawObject() const;
+ Window* GetWindow() const;
+
+ const SwFrm* GetParent( const sal_Bool bInPagePreview ) const;
+
+ bool IsAccessible( sal_Bool bPagePreview ) const;
+ bool IsBoundAsChar() const;
+
+ bool IsVisibleChildrenOnly() const;
+ SwRect GetBox( const SwAccessibleMap& rAccMap ) const;
+ SwRect GetBounds( const SwAccessibleMap& rAccMap ) const;
+
+ /** indicating, if accessible child is included even, if the corresponding
+ object is not visible.
+
+ @author OD
+ */
+ bool AlwaysIncludeAsChild() const;
+
+ private:
+ const SwFrm* mpFrm;
+ const SdrObject* mpDrawObj;
+ Window* mpWindow;
+
+ void Init( const SdrObject* pDrawObj );
+ void Init( const SwFrm* pFrm );
+ void Init( Window* pWindow );
+};
+
+
+} } // eof of namespace sw::access
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobjmap.cxx b/sw/source/core/access/accfrmobjmap.cxx
new file mode 100644
index 000000000000..e7fd8644da77
--- /dev/null
+++ b/sw/source/core/access/accfrmobjmap.cxx
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <accfrmobjmap.hxx>
+#include <accframe.hxx>
+#include <accmap.hxx>
+#include <acccontext.hxx>
+
+#include <viewsh.hxx>
+#include <doc.hxx>
+#include <frmfmt.hxx>
+#include <pagefrm.hxx>
+#include <txtfrm.hxx>
+#include <node.hxx>
+#include <sortedobjs.hxx>
+#include <anchoredobject.hxx>
+
+#include <svx/svdobj.hxx>
+
+using namespace sw::access;
+
+SwAccessibleChildMap::SwAccessibleChildMap( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ SwAccessibleMap& rAccMap )
+ : nHellId( rAccMap.GetShell()->GetDoc()->GetHellId() )
+ , nControlsId( rAccMap.GetShell()->GetDoc()->GetControlsId() )
+{
+ const bool bVisibleChildrenOnly = SwAccessibleChild( &rFrm ).IsVisibleChildrenOnly();
+
+ sal_uInt32 nPos = 0;
+ SwAccessibleChild aLower( rFrm.GetLower() );
+ while( aLower.GetSwFrm() )
+ {
+ if ( !bVisibleChildrenOnly ||
+ aLower.AlwaysIncludeAsChild() ||
+ aLower.GetBox( rAccMap ).IsOver( rVisArea ) )
+ {
+ insert( nPos++, SwAccessibleChildMapKey::TEXT, aLower );
+ }
+
+ aLower = aLower.GetSwFrm()->GetNext();
+ }
+
+ if ( rFrm.IsPageFrm() )
+ {
+ OSL_ENSURE( bVisibleChildrenOnly, "page frame within tab frame???" );
+ const SwPageFrm *pPgFrm =
+ static_cast< const SwPageFrm * >( &rFrm );
+ const SwSortedObjs *pObjs = pPgFrm->GetSortedObjs();
+ if ( pObjs )
+ {
+ for( sal_uInt16 i=0; i<pObjs->Count(); i++ )
+ {
+ aLower = (*pObjs)[i]->GetDrawObj();
+ if ( aLower.GetBox( rAccMap ).IsOver( rVisArea ) )
+ {
+ insert( aLower.GetDrawObject(), aLower );
+ }
+ }
+ }
+ }
+ else if( rFrm.IsTxtFrm() )
+ {
+ const SwSortedObjs *pObjs = rFrm.GetDrawObjs();
+ if ( pObjs )
+ {
+ for( sal_uInt16 i=0; i<pObjs->Count(); i++ )
+ {
+ aLower = (*pObjs)[i]->GetDrawObj();
+ if ( aLower.IsBoundAsChar() &&
+ ( !bVisibleChildrenOnly ||
+ aLower.AlwaysIncludeAsChild() ||
+ aLower.GetBox( rAccMap ).IsOver( rVisArea ) ) )
+ {
+ insert( aLower.GetDrawObject(), aLower );
+ }
+ }
+ }
+
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl =
+ rAccMap.GetContextImpl( &rFrm, sal_False );
+ if( xAccImpl.is() )
+ {
+ SwAccessibleContext* pAccImpl = xAccImpl.get();
+ if ( pAccImpl &&
+ pAccImpl->HasAdditionalAccessibleChildren() )
+ {
+ std::vector< Window* >* pAdditionalChildren =
+ new std::vector< Window* >();
+ pAccImpl->GetAdditionalAccessibleChildren( pAdditionalChildren );
+
+ sal_Int32 nCounter( 0 );
+ for ( std::vector< Window* >::iterator aIter = pAdditionalChildren->begin();
+ aIter != pAdditionalChildren->end();
+ ++aIter )
+ {
+ aLower = (*aIter);
+ insert( ++nCounter, SwAccessibleChildMapKey::XWINDOW, aLower );
+ }
+
+ delete pAdditionalChildren;
+ }
+ }
+ }
+ }
+}
+
+::std::pair< SwAccessibleChildMap::iterator, bool > SwAccessibleChildMap::insert(
+ const sal_uInt32 nPos,
+ const SwAccessibleChildMapKey::LayerId eLayerId,
+ const SwAccessibleChild& rLower )
+{
+ SwAccessibleChildMapKey aKey( eLayerId, nPos );
+ value_type aEntry( aKey, rLower );
+ return _SwAccessibleChildMap::insert( aEntry );
+}
+
+::std::pair< SwAccessibleChildMap::iterator, bool > SwAccessibleChildMap::insert(
+ const SdrObject *pObj,
+ const SwAccessibleChild& rLower )
+{
+ const SdrLayerID nLayer = pObj->GetLayer();
+ SwAccessibleChildMapKey::LayerId eLayerId =
+ (nHellId == nLayer)
+ ? SwAccessibleChildMapKey::HELL
+ : ( (nControlsId == nLayer)
+ ? SwAccessibleChildMapKey::CONTROLS
+ : SwAccessibleChildMapKey::HEAVEN );
+ SwAccessibleChildMapKey aKey( eLayerId, pObj->GetOrdNum() );
+ value_type aEntry( aKey, rLower );
+ return _SwAccessibleChildMap::insert( aEntry );
+}
+
+/* static */ sal_Bool SwAccessibleChildMap::IsSortingRequired( const SwFrm& rFrm )
+{
+ return ( rFrm.IsPageFrm() &&
+ static_cast< const SwPageFrm& >( rFrm ).GetSortedObjs() ) ||
+ ( rFrm.IsTxtFrm() &&
+ rFrm.GetDrawObjs() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobjmap.hxx b/sw/source/core/access/accfrmobjmap.hxx
new file mode 100644
index 000000000000..441202e6acb9
--- /dev/null
+++ b/sw/source/core/access/accfrmobjmap.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRMOBJMAP_HXX
+#define _ACCFRMOBJMAP_HXX
+
+#include <accfrmobj.hxx>
+
+#include <svx/svdtypes.hxx>
+
+#include <map>
+
+class SwAccessibleMap;
+class SwDoc;
+class SwRect;
+class SwFrm;
+class SdrObject;
+
+class SwAccessibleChildMapKey
+{
+public:
+ enum LayerId { INVALID, HELL, TEXT, HEAVEN, CONTROLS, XWINDOW };
+
+ inline SwAccessibleChildMapKey()
+ : eLayerId( INVALID )
+ , nOrdNum( 0 )
+ {}
+
+ inline SwAccessibleChildMapKey( LayerId eId, sal_uInt32 nOrd )
+ : eLayerId( eId )
+ , nOrdNum( nOrd )
+ {}
+
+ inline bool operator()( const SwAccessibleChildMapKey& r1,
+ const SwAccessibleChildMapKey& r2 ) const
+ {
+ return (r1.eLayerId == r2.eLayerId)
+ ? (r1.nOrdNum < r2.nOrdNum)
+ : (r1.eLayerId < r2.eLayerId);
+ }
+
+private:
+
+ LayerId eLayerId;
+ sal_uInt32 nOrdNum;
+
+};
+
+typedef ::std::map < SwAccessibleChildMapKey, sw::access::SwAccessibleChild, SwAccessibleChildMapKey >
+ _SwAccessibleChildMap;
+
+class SwAccessibleChildMap : public _SwAccessibleChildMap
+{
+ const SdrLayerID nHellId;
+ const SdrLayerID nControlsId;
+
+ ::std::pair< iterator, bool > insert( const sal_uInt32 nPos,
+ const SwAccessibleChildMapKey::LayerId eLayerId,
+ const sw::access::SwAccessibleChild& rLower );
+ ::std::pair< iterator, bool > insert( const SdrObject* pObj,
+ const sw::access::SwAccessibleChild& rLower );
+
+public:
+
+ SwAccessibleChildMap( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ SwAccessibleMap& rAccMap );
+
+ static sal_Bool IsSortingRequired( const SwFrm& rFrm );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobjslist.cxx b/sw/source/core/access/accfrmobjslist.cxx
new file mode 100644
index 000000000000..846e06a0435c
--- /dev/null
+++ b/sw/source/core/access/accfrmobjslist.cxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <accfrmobjslist.hxx>
+#include <accmap.hxx>
+#include <acccontext.hxx>
+
+#include <pagefrm.hxx>
+#include <sortedobjs.hxx>
+#include <anchoredobject.hxx>
+
+using namespace ::sw::access;
+
+SwAccessibleChildSList_const_iterator::SwAccessibleChildSList_const_iterator(
+ const SwAccessibleChildSList& rLst,
+ SwAccessibleMap& rAccMap )
+ : rList( rLst ),
+ aCurr( rList.GetFrm().GetLower() ),
+ nNextObj( 0 )
+{
+ if( !aCurr.GetSwFrm() )
+ {
+ const SwFrm& rFrm = rList.GetFrm();
+ if( rFrm.IsPageFrm() )
+ {
+ const SwPageFrm& rPgFrm = static_cast< const SwPageFrm& >( rFrm );
+ const SwSortedObjs *pObjs = rPgFrm.GetSortedObjs();
+ if( pObjs && pObjs->Count() )
+ {
+ aCurr = (*pObjs)[nNextObj++]->GetDrawObj();
+ }
+ }
+ else if( rFrm.IsTxtFrm() )
+ {
+ const SwSortedObjs *pObjs = rFrm.GetDrawObjs();
+ if ( pObjs && pObjs->Count() )
+ {
+ aCurr = (*pObjs)[nNextObj++]->GetDrawObj();
+ while( aCurr.IsValid() && !aCurr.IsBoundAsChar() )
+ {
+ aCurr = (nNextObj < pObjs->Count())
+ ? (*pObjs)[nNextObj++]->GetDrawObj()
+ : static_cast< const SdrObject *>( 0 );
+ }
+ }
+ if ( !aCurr.IsValid() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl =
+ rAccMap.GetContextImpl( &rFrm, sal_False );
+ if( xAccImpl.is() )
+ {
+ SwAccessibleContext* pAccImpl = xAccImpl.get();
+ aCurr = SwAccessibleChild( pAccImpl->GetAdditionalAccessibleChild( 0 ) );
+ ++nNextObj;
+ }
+ }
+ }
+ }
+
+ if( rList.IsVisibleChildrenOnly() )
+ {
+ // Find the first visible
+ while( aCurr.IsValid() &&
+ !aCurr.AlwaysIncludeAsChild() &&
+ !aCurr.GetBox( rAccMap ).IsOver( rList.GetVisArea() ) )
+ {
+ next();
+ }
+ }
+}
+
+SwAccessibleChildSList_const_iterator& SwAccessibleChildSList_const_iterator::next()
+{
+ bool bNextTaken( true );
+ if( aCurr.GetDrawObject() || aCurr.GetWindow() )
+ {
+ bNextTaken = false;
+ }
+ else if( aCurr.GetSwFrm() )
+ {
+ aCurr = aCurr.GetSwFrm()->GetNext();
+ if( !aCurr.GetSwFrm() )
+ {
+ bNextTaken = false;
+ }
+ }
+
+ if( !bNextTaken )
+ {
+ const SwFrm& rFrm = rList.GetFrm();
+ if( rFrm.IsPageFrm() )
+ {
+ const SwPageFrm& rPgFrm = static_cast< const SwPageFrm& >( rFrm );
+ const SwSortedObjs *pObjs = rPgFrm.GetSortedObjs();
+ aCurr = ( pObjs && nNextObj < pObjs->Count() )
+ ? (*pObjs)[nNextObj++]->GetDrawObj()
+ : static_cast< const SdrObject *>( 0 );
+ }
+ else if( rFrm.IsTxtFrm() )
+ {
+ const SwSortedObjs* pObjs = rFrm.GetDrawObjs();
+ const sal_uInt32 nObjsCount = pObjs ? pObjs->Count() : 0;
+ aCurr = ( pObjs && nNextObj < nObjsCount )
+ ? (*pObjs)[nNextObj++]->GetDrawObj()
+ : static_cast< const SdrObject *>( 0 );
+ while( aCurr.IsValid() && !aCurr.IsBoundAsChar() )
+ {
+ aCurr = ( nNextObj < nObjsCount )
+ ? (*pObjs)[nNextObj++]->GetDrawObj()
+ : static_cast< const SdrObject *>( 0 );
+ }
+ if ( !aCurr.IsValid() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl =
+ rList.GetAccMap().GetContextImpl( &rFrm, sal_False );
+ if( xAccImpl.is() )
+ {
+ SwAccessibleContext* pAccImpl = xAccImpl.get();
+ aCurr = SwAccessibleChild( pAccImpl->GetAdditionalAccessibleChild( nNextObj - nObjsCount ) );
+ ++nNextObj;
+ }
+ }
+ }
+ }
+
+ return *this;
+}
+
+SwAccessibleChildSList_const_iterator& SwAccessibleChildSList_const_iterator::next_visible()
+{
+ next();
+ while( aCurr.IsValid() &&
+ !aCurr.AlwaysIncludeAsChild() &&
+ !aCurr.GetBox( rList.GetAccMap() ).IsOver( rList.GetVisArea() ) )
+ {
+ next();
+ }
+
+ return *this;
+}
+
+SwAccessibleChildSList_const_iterator& SwAccessibleChildSList_const_iterator::operator++()
+{
+ return rList.IsVisibleChildrenOnly() ? next_visible() : next();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobjslist.hxx b/sw/source/core/access/accfrmobjslist.hxx
new file mode 100644
index 000000000000..78052177fbac
--- /dev/null
+++ b/sw/source/core/access/accfrmobjslist.hxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRMOBJSLIST_HXX
+#define _ACCFRMOBJSLIST_HXX
+
+#include <accfrmobj.hxx>
+#include <swrect.hxx>
+
+class SwAccessibleMap;
+
+class SwAccessibleChildSList;
+
+class SwAccessibleChildSList_const_iterator
+{
+private:
+ friend class SwAccessibleChildSList;
+
+ const SwAccessibleChildSList& rList; // The frame we are iterating over
+ sw::access::SwAccessibleChild aCurr; // The current object
+ sal_uInt16 nNextObj; // The index of the current sdr object
+
+ inline SwAccessibleChildSList_const_iterator( const SwAccessibleChildSList& rLst )
+ : rList( rLst )
+ , nNextObj( 0 )
+ {}
+
+ SwAccessibleChildSList_const_iterator( const SwAccessibleChildSList& rLst,
+ SwAccessibleMap& rAccMap );
+
+ SwAccessibleChildSList_const_iterator& next();
+ SwAccessibleChildSList_const_iterator& next_visible();
+
+public:
+
+ inline SwAccessibleChildSList_const_iterator( const SwAccessibleChildSList_const_iterator& rIter )
+ : rList( rIter.rList )
+ , aCurr( rIter.aCurr )
+ , nNextObj( rIter.nNextObj )
+ {}
+
+ inline sal_Bool operator==( const SwAccessibleChildSList_const_iterator& r ) const
+ {
+ return aCurr == r.aCurr;
+ }
+
+ inline sal_Bool operator!=(
+ const SwAccessibleChildSList_const_iterator& r ) const
+ {
+ return !(*this == r);
+ }
+
+ SwAccessibleChildSList_const_iterator& operator++();
+
+ inline const sw::access::SwAccessibleChild& operator*() const
+ {
+ return aCurr;
+ }
+};
+
+// An iterator to iterate over a frame's child in any order
+class SwAccessibleChildSList
+{
+ const SwRect maVisArea;
+ const SwFrm& mrFrm;
+ const sal_Bool mbVisibleChildrenOnly;
+ SwAccessibleMap& mrAccMap;
+
+public:
+
+ typedef SwAccessibleChildSList_const_iterator const_iterator;
+
+ inline SwAccessibleChildSList( const SwFrm& rFrm,
+ SwAccessibleMap& rAccMap )
+ : maVisArea()
+ , mrFrm( rFrm )
+ , mbVisibleChildrenOnly( sal_False )
+ , mrAccMap( rAccMap )
+ {}
+
+ inline SwAccessibleChildSList( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ SwAccessibleMap& rAccMap )
+ : maVisArea( rVisArea )
+ , mrFrm( rFrm )
+ , mbVisibleChildrenOnly( sw::access::SwAccessibleChild( &rFrm ).IsVisibleChildrenOnly() )
+ , mrAccMap( rAccMap )
+ {
+ }
+
+ inline const_iterator begin() const
+ {
+ return SwAccessibleChildSList_const_iterator( *this, mrAccMap );
+ }
+
+ inline const_iterator end() const
+ {
+ return SwAccessibleChildSList_const_iterator( *this );
+ }
+
+ inline const SwFrm& GetFrm() const
+ {
+ return mrFrm;
+ }
+
+ inline sal_Bool IsVisibleChildrenOnly() const
+ {
+ return mbVisibleChildrenOnly;
+ }
+
+ inline const SwRect& GetVisArea() const
+ {
+ return maVisArea;
+ }
+
+ inline SwAccessibleMap& GetAccMap() const
+ {
+ return mrAccMap;
+ }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accgraphic.cxx b/sw/source/core/access/accgraphic.cxx
new file mode 100644
index 000000000000..d6ba4ee9ff6d
--- /dev/null
+++ b/sw/source/core/access/accgraphic.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <rtl/uuid.h>
+#include <flyfrm.hxx>
+#include "accgraphic.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextGraphicObject";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleGraphic";
+
+SwAccessibleGraphic::SwAccessibleGraphic(
+ SwAccessibleMap* pInitMap,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleNoTextFrame( pInitMap, AccessibleRole::GRAPHIC, pFlyFrm )
+{
+}
+
+SwAccessibleGraphic::~SwAccessibleGraphic()
+{
+}
+
+OUString SAL_CALL SwAccessibleGraphic::getImplementationName()
+ throw( RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleGraphic::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+Sequence< OUString > SAL_CALL SwAccessibleGraphic::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessibleGraphic::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accgraphic.hxx b/sw/source/core/access/accgraphic.hxx
new file mode 100644
index 000000000000..e9c9ef0c7a6c
--- /dev/null
+++ b/sw/source/core/access/accgraphic.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCGRAPHIC_HXX
+#define _ACCGRAPHIC_HXX
+#include "accnotextframe.hxx"
+
+class SwAccessibleGraphic : public SwAccessibleNoTextFrame
+{
+
+protected:
+
+ virtual ~SwAccessibleGraphic();
+
+public:
+
+ SwAccessibleGraphic( SwAccessibleMap* pInitMap,
+ const SwFlyFrm *pFlyFrm );
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accheaderfooter.cxx b/sw/source/core/access/accheaderfooter.cxx
new file mode 100644
index 000000000000..c1e2697116b7
--- /dev/null
+++ b/sw/source/core/access/accheaderfooter.cxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <osl/mutex.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <rtl/uuid.h>
+#include <vcl/svapp.hxx>
+#include <hffrm.hxx>
+#include "accheaderfooter.hxx"
+#include "access.hrc"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const sal_Char sServiceNameHeader[] = "com.sun.star.text.AccessibleHeaderView";
+const sal_Char sServiceNameFooter[] = "com.sun.star.text.AccessibleFooterView";
+const sal_Char sImplementationNameHeader[] = "com.sun.star.comp.Writer.SwAccessibleHeaderView";
+const sal_Char sImplementationNameFooter[] = "com.sun.star.comp.Writer.SwAccessibleFooterView";
+
+SwAccessibleHeaderFooter::SwAccessibleHeaderFooter(
+ SwAccessibleMap* pInitMap,
+ const SwHeaderFrm* pHdFrm ) :
+ SwAccessibleContext( pInitMap, AccessibleRole::HEADER, pHdFrm )
+{
+ SolarMutexGuard aGuard;
+
+ OUString sArg( OUString::valueOf( (sal_Int32)pHdFrm->GetPhyPageNum() ) );
+ SetName( GetResource( STR_ACCESS_HEADER_NAME, &sArg ) );
+}
+
+SwAccessibleHeaderFooter::SwAccessibleHeaderFooter(
+ SwAccessibleMap* pInitMap,
+ const SwFooterFrm* pFtFrm ) :
+ SwAccessibleContext( pInitMap, AccessibleRole::FOOTER, pFtFrm )
+{
+ SolarMutexGuard aGuard;
+
+ OUString sArg( OUString::valueOf( (sal_Int32)pFtFrm->GetPhyPageNum() ) );
+ SetName( GetResource( STR_ACCESS_FOOTER_NAME, &sArg ) );
+}
+
+SwAccessibleHeaderFooter::~SwAccessibleHeaderFooter()
+{
+}
+
+OUString SAL_CALL SwAccessibleHeaderFooter::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ sal_uInt16 nResId = AccessibleRole::HEADER == GetRole()
+ ? STR_ACCESS_HEADER_DESC
+ : STR_ACCESS_FOOTER_DESC ;
+
+ OUString sArg( GetFormattedPageNumber() );
+
+ return GetResource( nResId, &sArg );
+}
+
+OUString SAL_CALL SwAccessibleHeaderFooter::getImplementationName()
+ throw( RuntimeException )
+{
+ if( AccessibleRole::HEADER == GetRole() )
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationNameHeader));
+ else
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationNameFooter));
+}
+
+sal_Bool SAL_CALL SwAccessibleHeaderFooter::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ if( sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 ) )
+ return sal_True;
+ else if( AccessibleRole::HEADER == GetRole() )
+ return sTestServiceName.equalsAsciiL( sServiceNameHeader, sizeof(sServiceNameHeader)-1 );
+ else
+ return sTestServiceName.equalsAsciiL( sServiceNameFooter, sizeof(sServiceNameFooter)-1 );
+
+}
+
+Sequence< OUString > SAL_CALL SwAccessibleHeaderFooter::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ if( AccessibleRole::HEADER == GetRole() )
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceNameHeader) );
+ else
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceNameFooter) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessibleHeaderFooter::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accheaderfooter.hxx b/sw/source/core/access/accheaderfooter.hxx
new file mode 100644
index 000000000000..4d72923c752d
--- /dev/null
+++ b/sw/source/core/access/accheaderfooter.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCHEADERFOOTER_HXX
+#define _ACCHEADERFOOTER_HXX
+#include "acccontext.hxx"
+
+class SwHeaderFrm;
+class SwFooterFrm;
+
+class SwAccessibleHeaderFooter : public SwAccessibleContext
+{
+
+protected:
+
+ virtual ~SwAccessibleHeaderFooter();
+
+public:
+
+ SwAccessibleHeaderFooter( SwAccessibleMap* pInitMap,
+ const SwHeaderFrm* pHdFrm );
+ SwAccessibleHeaderFooter( SwAccessibleMap* pInitMap,
+ const SwFooterFrm* pFtFrm );
+
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acchyperlink.cxx b/sw/source/core/access/acchyperlink.cxx
new file mode 100644
index 000000000000..96fd0c70bf57
--- /dev/null
+++ b/sw/source/core/access/acchyperlink.cxx
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <swurl.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <ndtxt.hxx>
+#include <txtinet.hxx>
+#include <accpara.hxx>
+#include <acchyperlink.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+SwAccessibleHyperlink::SwAccessibleHyperlink( sal_uInt16 nHPos,
+ SwAccessibleParagraph *p, sal_Int32 nStt, sal_Int32 nEnd ) :
+ nHintPos( nHPos ),
+ xPara( p ),
+ nStartIdx( nStt ),
+ nEndIdx( nEnd )
+{
+}
+
+const SwTxtAttr *SwAccessibleHyperlink::GetTxtAttr() const
+{
+ const SwTxtAttr *pTxtAttr = 0;
+ if( xPara.is() && xPara->GetMap() )
+ {
+ const SwTxtNode *pTxtNd = xPara->GetTxtNode();
+ const SwpHints *pHints = pTxtNd->GetpSwpHints();
+ if( pHints && nHintPos < pHints->Count() )
+ {
+ const SwTxtAttr *pHt = (*pHints)[nHintPos];
+ if( RES_TXTATR_INETFMT == pHt->Which() )
+ pTxtAttr = pHt;
+ }
+ }
+
+ return pTxtAttr;
+}
+
+
+// XAccessibleAction
+sal_Int32 SAL_CALL SwAccessibleHyperlink::getAccessibleActionCount()
+ throw (uno::RuntimeException)
+{
+ return isValid() ? 1 : 0;
+}
+
+sal_Bool SAL_CALL SwAccessibleHyperlink::doAccessibleAction( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ sal_Bool bRet = sal_False;
+
+ const SwTxtAttr *pTxtAttr = GetTxtAttr();
+ if( pTxtAttr && 0 == nIndex )
+ {
+ const SwFmtINetFmt& rINetFmt = pTxtAttr->GetINetFmt();
+ if( rINetFmt.GetValue().Len() )
+ {
+ ViewShell *pVSh = xPara->GetShell();
+ if( pVSh )
+ {
+ LoadURL( rINetFmt.GetValue(), pVSh, URLLOAD_NOFILTER,
+ &rINetFmt.GetTargetFrame() );
+ OSL_ENSURE( pTxtAttr == rINetFmt.GetTxtINetFmt(),
+ "lost my txt attr" );
+ const SwTxtINetFmt* pTxtAttr2 = rINetFmt.GetTxtINetFmt();
+ if( pTxtAttr2 )
+ {
+ const_cast<SwTxtINetFmt*>(pTxtAttr2)->SetVisited(true);
+ const_cast<SwTxtINetFmt*>(pTxtAttr2)->SetVisitedValid(true);
+ }
+ bRet = sal_True;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+OUString SAL_CALL SwAccessibleHyperlink::getAccessibleActionDescription(
+ sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ OUString sDesc;
+
+ const SwTxtAttr *pTxtAttr = GetTxtAttr();
+ if( pTxtAttr && 0 == nIndex )
+ {
+ const SwFmtINetFmt& rINetFmt = pTxtAttr->GetINetFmt();
+ sDesc = OUString( rINetFmt.GetValue() );
+ }
+
+ return sDesc;
+}
+
+uno::Reference< XAccessibleKeyBinding > SAL_CALL
+ SwAccessibleHyperlink::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< XAccessibleKeyBinding > xKeyBinding;
+
+ if( isValid() && 0==nIndex )
+ {
+ ::comphelper::OAccessibleKeyBindingHelper* pKeyBindingHelper =
+ new ::comphelper::OAccessibleKeyBindingHelper();
+ xKeyBinding = pKeyBindingHelper;
+
+ awt::KeyStroke aKeyStroke;
+ aKeyStroke.Modifiers = 0;
+ aKeyStroke.KeyCode = KEY_RETURN;
+ aKeyStroke.KeyChar = 0;
+ aKeyStroke.KeyFunc = 0;
+ pKeyBindingHelper->AddKeyBinding( aKeyStroke );
+ }
+
+ return xKeyBinding;
+}
+
+// XAccessibleHyperlink
+uno::Any SAL_CALL SwAccessibleHyperlink::getAccessibleActionAnchor(
+ sal_Int32 /*nIndex*/ )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ return uno::Any();
+}
+
+uno::Any SAL_CALL SwAccessibleHyperlink::getAccessibleActionObject(
+ sal_Int32 /*nIndex*/ )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ return uno::Any();
+}
+
+sal_Int32 SAL_CALL SwAccessibleHyperlink::getStartIndex()
+ throw (uno::RuntimeException)
+{
+ return nStartIdx;
+}
+
+sal_Int32 SAL_CALL SwAccessibleHyperlink::getEndIndex()
+ throw (uno::RuntimeException)
+{
+ return nEndIdx;
+}
+
+sal_Bool SAL_CALL SwAccessibleHyperlink::isValid( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return xPara.is();
+}
+
+void SwAccessibleHyperlink::Invalidate()
+{
+ SolarMutexGuard aGuard;
+ xPara = 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acchyperlink.hxx b/sw/source/core/access/acchyperlink.hxx
new file mode 100644
index 000000000000..2907f20c8f03
--- /dev/null
+++ b/sw/source/core/access/acchyperlink.hxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCHYPERLINK_HXX
+#define _ACCHYPERLINK_HXX
+#include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
+#include <rtl/ref.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <fmtinfmt.hxx>
+
+class SwAccessibleParagraph;
+class SwTxtAttr;
+
+class SwAccessibleHyperlink :
+ public ::cppu::WeakImplHelper1<
+ ::com::sun::star::accessibility::XAccessibleHyperlink >
+{
+ friend class SwAccessibleParagraph;
+ friend class SwAccessibleHyperTextData;
+ sal_uInt16 nHintPos;
+ ::rtl::Reference< SwAccessibleParagraph > xPara;
+ sal_Int32 nStartIdx;
+ sal_Int32 nEndIdx;
+
+ SwAccessibleHyperlink( sal_uInt16 nHintPos,
+ SwAccessibleParagraph *p,
+ sal_Int32 nStt, sal_Int32 nEnd );
+
+ const SwTxtAttr *GetTxtAttr() const;
+ void Invalidate();
+
+public:
+
+ // XAccessibleAction
+ virtual sal_Int32 SAL_CALL getAccessibleActionCount()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL doAccessibleAction( sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleActionDescription(
+ sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleKeyBinding > SAL_CALL
+ getAccessibleActionKeyBinding( sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleHyperlink
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionAnchor(
+ sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionObject(
+ sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getStartIndex()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getEndIndex()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isValid( )
+ throw (::com::sun::star::uno::RuntimeException);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acchypertextdata.cxx b/sw/source/core/access/acchypertextdata.cxx
new file mode 100644
index 000000000000..39ac794174e9
--- /dev/null
+++ b/sw/source/core/access/acchypertextdata.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <acchyperlink.hxx>
+#include <acchypertextdata.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+
+SwAccessibleHyperTextData::SwAccessibleHyperTextData() :
+ _SwAccessibleHyperlinkMap_Impl()
+{
+}
+
+SwAccessibleHyperTextData::~SwAccessibleHyperTextData()
+{
+ iterator aIter = begin();
+ while( aIter != end() )
+ {
+ Reference < XAccessibleHyperlink > xTmp = (*aIter).second;
+ if( xTmp.is() )
+ {
+ SwAccessibleHyperlink *pTmp =
+ static_cast< SwAccessibleHyperlink * >( xTmp.get() );
+ pTmp->Invalidate();
+ }
+ ++aIter;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acchypertextdata.hxx b/sw/source/core/access/acchypertextdata.hxx
new file mode 100644
index 000000000000..91ce303275ab
--- /dev/null
+++ b/sw/source/core/access/acchypertextdata.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCHYPERTEXTDATA_HXX
+#define _ACCHYPERTEXTDATA_HXX
+
+#include <cppuhelper/weakref.hxx>
+
+#include <map>
+
+class SwTxtAttr;
+
+namespace com { namespace sun { namespace star {
+ namespace accessibility { class XAccessibleHyperlink; }
+} } }
+
+typedef ::std::less< const SwTxtAttr * > SwTxtAttrPtrLess;
+typedef ::std::map < const SwTxtAttr *, ::com::sun::star::uno::WeakReference < com::sun::star::accessibility::XAccessibleHyperlink >, SwTxtAttrPtrLess > _SwAccessibleHyperlinkMap_Impl;
+
+class SwAccessibleHyperTextData : public _SwAccessibleHyperlinkMap_Impl
+{
+public:
+ SwAccessibleHyperTextData();
+ ~SwAccessibleHyperTextData();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accmap.cxx b/sw/source/core/access/accmap.cxx
new file mode 100644
index 000000000000..3c9a7d6794d9
--- /dev/null
+++ b/sw/source/core/access/accmap.cxx
@@ -0,0 +1,2789 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <rtl/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 <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 <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <pagepreviewlayout.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <dflyobj.hxx>
+#include <prevwpage.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:
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool mbLocked;
+#endif
+
+ SwAccessibleContextMap_Impl()
+#if OSL_DEBUG_LEVEL > 1
+ : 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.
+ 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;
+ }
+
+ OSL_ENSURE( 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 *, ::rtl::Reference < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl;
+
+class SwAccessibleShapeMap_Impl: public _SwAccessibleShapeMap_Impl
+
+{
+ ::accessibility::AccessibleShapeTreeInfo maInfo;
+
+public:
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool mbLocked;
+#endif
+ SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap )
+#if OSL_DEBUG_LEVEL > 1
+ : mbLocked( sal_False )
+#endif
+ {
+ maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
+ maInfo.SetWindow( pMap->GetShell()->GetWin() );
+ maInfo.SetViewForwarder( pMap );
+ 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->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;
+ }
+ OSL_ENSURE( 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
+ tAccessibleStates mnStates; // check states or update caret pos
+
+ SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& );
+
+public:
+ SwAccessibleEvent_Impl( EventType eT,
+ SwAccessibleContext *pA,
+ const SwAccessibleChild& rFrmOrObj )
+ : mxAcc( pA ),
+ maFrmOrObj( rFrmOrObj ),
+ meType( eT ),
+ mnStates( 0 )
+ {}
+
+ SwAccessibleEvent_Impl( EventType eT,
+ const SwAccessibleChild& rFrmOrObj )
+ : maFrmOrObj( rFrmOrObj ),
+ meType( eT ),
+ mnStates( 0 )
+ {
+ OSL_ENSURE( SwAccessibleEvent_Impl::DISPOSE == meType,
+ "wrong event constructor, DISPOSE only" );
+ }
+
+ SwAccessibleEvent_Impl( EventType eT )
+ : meType( eT ),
+ mnStates( 0 )
+ {
+ OSL_ENSURE( 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 )
+ {
+ OSL_ENSURE( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType ||
+ SwAccessibleEvent_Impl::POS_CHANGED == meType,
+ "wrong event constructor, (CHILD_)POS_CHANGED only" );
+ }
+
+ SwAccessibleEvent_Impl( EventType eT,
+ SwAccessibleContext *pA,
+ const SwAccessibleChild& rFrmOrObj,
+ const tAccessibleStates _nStates )
+ : mxAcc( pA ),
+ maFrmOrObj( rFrmOrObj ),
+ meType( eT ),
+ mnStates( _nStates )
+ {
+ OSL_ENSURE( SwAccessibleEvent_Impl::CARET_OR_STATES == meType,
+ "wrong event constructor, CARET_OR_STATES only" );
+ }
+
+ // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
+ inline void SetType( EventType eT )
+ {
+ meType = eT;
+ }
+ inline EventType GetType() const
+ {
+ return meType;
+ }
+
+ inline ::rtl::Reference < SwAccessibleContext > GetContext() const
+ {
+ uno::Reference < XAccessible > xTmp( mxAcc );
+ ::rtl::Reference < 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(..)>
+ 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;
+ }
+ inline sal_Bool IsInvalidateTextSelection() const
+ {
+ return ( mnStates & ACC_STATE_TEXT_SELECTION_CHANGED ) != 0;
+ }
+
+ inline sal_Bool IsInvalidateTextAttrs() const
+ {
+ return ( mnStates & ACC_STATE_TEXT_ATTRIBUTE_CHANGED ) != 0;
+ }
+
+ inline tAccessibleStates GetStates() const
+ {
+ return mnStates & ACC_STATE_MASK;
+ }
+
+ 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;
+ }
+};
+
+//------------------------------------------------------------------------------
+// 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
+{
+};
+
+//------------------------------------------------------------------------------
+
+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
+
+ @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 paramter - 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();
+
+ void Update( const SwAccessibleMap& rAccMap,
+ const std::vector<PrevwPage*>& _rPrevwPages,
+ const Fraction& _rScale,
+ const SwPageFrm* _pSelectedPageFrm,
+ const Size& _rPrevwWinSize );
+
+ 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. */
+ 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()
+{
+}
+
+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 );
+ }
+ }
+}
+
+void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm )
+{
+ mpSelPage = _pSelectedPageFrm;
+ OSL_ENSURE( 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
+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 )
+{
+ ::rtl::Reference < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
+ if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() )
+ {
+ DoInvalidateShapeSelection();
+ }
+ else if( xAccImpl.is() && xAccImpl->GetFrm() )
+ {
+ 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:
+ OSL_ENSURE( xAccImpl.is(),
+ "dispose event has been stored" );
+ break;
+ 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() )
+ {
+ // 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 );
+ }
+ }
+
+ if ( rEvent.IsInvalidateTextSelection() )
+ {
+ xAccImpl->InvalidateTextSelection();
+ }
+ }
+ }
+}
+
+void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
+{
+ osl::MutexGuard 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!
+ OSL_ENSURE( 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 );
+ OSL_ENSURE( 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.
+ OSL_ENSURE( 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.
+ OSL_ENSURE( 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.
+ OSL_ENSURE( 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.
+ OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
+ "invalid event combination" );
+ break;
+ case SwAccessibleEvent_Impl::SHAPE_SELECTION:
+ OSL_ENSURE( 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 immediatly 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;
+ case SwAccessibleEvent_Impl::INVALID_ATTR:
+ OSL_ENSURE( 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() );
+ OSL_ENSURE( pAccImpl, "no caret context" );
+ OSL_ENSURE( 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();
+ }
+}
+
+void SwAccessibleMap::DoInvalidateShapeSelection()
+{
+ 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;
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+ if( mpShapeMap )
+ pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
+ }
+
+ if( pShapes )
+ {
+ ::std::list< const SwFrm * > aParents;
+ Window *pWin = GetShell()->GetWin();
+ sal_Bool bFocused = pWin && pWin->HasFocus();
+ SwAccessibleObjShape_Impl *pShape = pShapes;
+ while( nShapes )
+ {
+ if( pShape->second.is() )
+ {
+ sal_Bool bChanged;
+ if( pShape >= pSelShape )
+ {
+ bChanged =
+ pShape->second->SetState( AccessibleStateType::SELECTED );
+ if( bFocused && 1 == nSelShapes )
+ pShape->second->SetState( AccessibleStateType::FOCUSED );
+ else
+ pShape->second->ResetState( AccessibleStateType::FOCUSED );
+ }
+ 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;
+ }
+ if( aParents.size() > 0 )
+ {
+ ::std::list< const SwFrm * >::const_iterator aIter = aParents.begin();
+ ::std::list< const SwFrm * >::const_iterator aEndIter = aParents.end();
+ while( aIter != aEndIter )
+ {
+ ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
+ {
+ osl::MutexGuard aGuard( maMutex );
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::const_iterator aMapIter =
+ mpFrmMap->find( *aIter );
+ if( aMapIter != mpFrmMap->end() )
+ {
+ uno::Reference < XAccessible > xAcc( (*aMapIter).second );
+ xParentAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ }
+ }
+ }
+ if( xParentAccImpl.is() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
+ xParentAccImpl->FireAccessibleEvent( aEvent );
+ }
+
+ ++aIter;
+ }
+ }
+
+ delete[] pShapes;
+ }
+}
+
+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;
+
+
+ {
+ osl::MutexGuard 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.is() )
+ {
+ 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 ),
+ mpSelectedParas( 0 ),
+ mpVSh( pSh ),
+ mpPreview( 0 ),
+ mnPara( 1 ),
+ mnFootnote( 1 ),
+ mnEndnote( 1 ),
+ mbShapeSelected( sal_False )
+{
+ pSh->GetLayout()->AddAccessibleShell();
+}
+
+SwAccessibleMap::~SwAccessibleMap()
+{
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard 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 );
+ }
+ }
+
+ SwAccessibleDocument *pAcc =
+ static_cast< SwAccessibleDocument * >( xAcc.get() );
+ pAcc->Dispose( sal_True );
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !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;
+ }
+ }
+ OSL_ENSURE( !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;
+ delete mpSelectedParas;
+ mpSelectedParas = 0;
+ }
+
+ delete mpPreview;
+ mpPreview = NULL;
+
+ {
+ osl::MutexGuard aGuard( maEventMutex );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !(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();
+}
+
+uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView(
+ sal_Bool bPagePreview )
+{
+ uno::Reference < XAccessible > xAcc;
+ sal_Bool bSetVisArea = sal_False;
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( !mpFrmMap )
+ {
+ mpFrmMap = new SwAccessibleContextMap_Impl;
+#if OSL_DEBUG_LEVEL > 1
+ mpFrmMap->mbLocked = sal_False;
+#endif
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !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 );
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ 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 );
+}
+
+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;
+
+ {
+ osl::MutexGuard 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;
+
+ OSL_ENSURE( 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
+ // noone except us knows it. In any case, we remeber
+ // 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;
+}
+
+::rtl::Reference < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
+ const SwFrm *pFrm,
+ sal_Bool bCreate )
+{
+ uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) );
+
+ ::rtl::Reference < 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;
+
+ {
+ osl::MutexGuard 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;
+
+ OSL_ENSURE( 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!!!
+ }
+ }
+ }
+ }
+
+ // Invalidate focus for old object when map is not locked
+ if( xOldCursorAcc.is() )
+ InvalidateCursorPosition( xOldCursorAcc );
+
+ return xAcc;
+}
+
+::rtl::Reference < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl(
+ const SdrObject *pObj,
+ SwAccessibleContext *pParentImpl,
+ sal_Bool bCreate )
+{
+ uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) );
+
+ ::rtl::Reference < ::accessibility::AccessibleShape > xAccImpl(
+ static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) );
+
+ return xAccImpl;
+}
+
+
+void SwAccessibleMap::RemoveContext( const SwFrm *pFrm )
+{
+ osl::MutexGuard 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() );
+ OSL_ENSURE( 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 )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ if( mpShapeMap )
+ {
+ SwAccessibleShapeMap_Impl::iterator aIter =
+ mpShapeMap->find( pObj );
+ if( aIter != mpShapeMap->end() )
+ {
+ mpShapeMap->erase( aIter );
+
+ // 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->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.
+ OSL_ENSURE( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(),
+ "non accessible frame should be disposed" );
+
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl;
+ ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
+ ::rtl::Reference< ::accessibility::AccessibleShape > xShapeAccImpl;
+ // get accessible context for frame
+ {
+ osl::MutexGuard 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.is() && 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.is() && !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.is() || xShapeAccImpl.is()) )
+ {
+ // 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
+ {
+ osl::MutexGuard 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.is() )
+ {
+ xAccImpl->Dispose( bRecursive );
+ }
+ else if( xParentAccImpl.is() )
+ {
+ // 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.is() )
+ {
+ 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() ) )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl;
+ ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
+ {
+ osl::MutexGuard 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.is() )
+ {
+ // Otherwise we look if the parent is accessible.
+ // If not, there is nothing to do.
+ 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( xAccImpl.is() )
+ {
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent(
+ SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.get(),
+ aFrmOrObj, rOldBox );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ xAccImpl->InvalidatePosOrSize( rOldBox );
+ }
+ }
+ else if( xParentAccImpl.is() )
+ {
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent(
+ SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
+ xParentAccImpl.get(), aFrmOrObj, rOldBox );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj,
+ rOldBox );
+ }
+ }
+ }
+}
+
+void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm )
+{
+ SwAccessibleChild aFrmOrObj( pFrm );
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard 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();
+ }
+ }
+ }
+}
+
+void SwAccessibleMap::InvalidateAttr( const SwTxtFrm& rTxtFrm )
+{
+ SwAccessibleChild aFrmOrObj( &rTxtFrm );
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard 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 )
+ {
+ OSL_ENSURE( !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 );
+ }
+ }
+ }
+
+ OSL_ENSURE( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreView()),
+ "frame is not accessible" );
+
+ uno::Reference < XAccessible > xOldAcc;
+ uno::Reference < XAccessible > xAcc;
+ sal_Bool bOldShapeSelected = sal_False;
+
+ {
+ osl::MutexGuard 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;
+
+ // 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 );
+ }
+ }
+ }
+
+ if( xOldAcc.is() && xOldAcc != xAcc )
+ InvalidateCursorPosition( xOldAcc );
+ if( bOldShapeSelected || bShapeSelected )
+ InvalidateShapeSelection();
+ if( xAcc.is() )
+ InvalidateCursorPosition( xAcc );
+}
+
+void SwAccessibleMap::InvalidateFocus()
+{
+ uno::Reference < XAccessible > xAcc;
+ sal_Bool bShapeSelected;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ xAcc = mxCursorContext;
+ bShapeSelected = mbShapeSelected;
+ }
+
+ if( xAcc.is() )
+ {
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ pAccImpl->InvalidateFocus();
+ }
+ else if( bShapeSelected )
+ {
+ DoInvalidateShapeFocus();
+ }
+}
+
+void SwAccessibleMap::SetCursorContext(
+ const ::rtl::Reference < SwAccessibleContext >& rCursorContext )
+{
+ osl::MutexGuard aGuard( maMutex );
+ uno::Reference < XAccessible > xAcc( rCursorContext.get() );
+ mxCursorContext = xAcc;
+}
+
+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;
+ {
+ osl::MutexGuard 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 of CONTENT_FLOW_FROM/_TO relation of a paragraph
+void SwAccessibleMap::InvalidateParaFlowRelation( const SwTxtFrm& _rTxtFrm,
+ const bool _bFrom )
+{
+ _InvalidateRelationSet( &_rTxtFrm, _bFrom );
+}
+
+// invalidation of text selection of a paragraph
+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;
+ {
+ osl::MutexGuard 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;
+ {
+ osl::MutexGuard 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;
+}
+
+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?" );
+
+ 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() ).get();
+ static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea();
+
+ uno::Reference < XAccessible > xOldAcc;
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard 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?" );
+
+ mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) );
+
+ uno::Reference < XAccessible > xOldAcc;
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard 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()
+{
+ {
+ osl::MutexGuard aGuard( maEventMutex );
+ if( mpEvents )
+ {
+ mpEvents->SetFiring();
+ SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
+ while( aIter != mpEvents->end() )
+ {
+ FireEvent( *aIter );
+ ++aIter;
+ }
+
+ delete mpEventMap;
+ mpEventMap = 0;
+
+ delete mpEvents;
+ mpEvents = 0;
+ }
+ }
+ {
+ osl::MutexGuard 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 )
+ {
+ 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() )
+ {
+ 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 );
+ 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() )
+ {
+ 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;
+ {
+ osl::MutexGuard 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 );
+
+ {
+ osl::MutexGuard 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;
+}
+
+Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const
+{
+ Point aPoint;
+ if( GetShell()->GetWin() )
+ {
+ 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() )
+ {
+ 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
+
+ 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.
+*/
+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;
+}
+
+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
+ Important note: method has to used inside a mutual exclusive section
+*/
+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( 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.
+ SwClientIter aIter( *pTxtNode );
+ for( SwFrm* pFrm = (SwFrm*)aIter.First( TYPE(SwFrm) );
+ pFrm;
+ pFrm = (SwFrm*)aIter.Next() )
+ {
+ OSL_ENSURE( dynamic_cast<SwTxtFrm*>(pFrm),
+ "<SwAccessibleMap::_BuildSelectedParas()> - unexpected frame type" );
+ SwTxtFrm* pTxtFrm( dynamic_cast<SwTxtFrm*>(pFrm) );
+ if ( pTxtFrm )
+ {
+ 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;
+}
+
+void SwAccessibleMap::InvalidateTextSelectionOfAllParas()
+{
+ osl::MutexGuard 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() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl(
+ static_cast<SwAccessibleContext*>( xAcc.get() ) );
+ if ( xAccImpl.is() && xAccImpl->GetFrm() )
+ {
+ const SwTxtFrm* pTxtFrm(
+ dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
+ OSL_ENSURE( 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() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl(
+ static_cast<SwAccessibleContext*>( xAcc.get() ) );
+ if ( xAccImpl.is() && xAccImpl->GetFrm() )
+ {
+ const SwTxtFrm* pTxtFrm(
+ dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
+ OSL_ENSURE( 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();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accnotextframe.cxx b/sw/source/core/access/accnotextframe.cxx
new file mode 100644
index 000000000000..7b6e5864d892
--- /dev/null
+++ b/sw/source/core/access/accnotextframe.cxx
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <frmfmt.hxx>
+#include <ndnotxt.hxx>
+#include <flyfrm.hxx>
+#include <cntfrm.hxx>
+// --> OD 2009-07-14 #i73249#
+#include <hints.hxx>
+// <--
+#include "accnotextframe.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const SwNoTxtNode *SwAccessibleNoTextFrame::GetNoTxtNode() const
+{
+ const SwNoTxtNode *pNd = 0;
+ const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm *>( GetFrm() );
+ if( pFlyFrm->Lower() && pFlyFrm->Lower()->IsNoTxtFrm() )
+ {
+ const SwCntntFrm *pCntFrm =
+ static_cast<const SwCntntFrm *>( pFlyFrm->Lower() );
+ pNd = pCntFrm->GetNode()->GetNoTxtNode();
+ }
+
+ return pNd;
+}
+
+SwAccessibleNoTextFrame::SwAccessibleNoTextFrame(
+ SwAccessibleMap* pInitMap,
+ sal_Int16 nInitRole,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleFrameBase( pInitMap, nInitRole, pFlyFrm ),
+ aDepend( this, const_cast < SwNoTxtNode * >( GetNoTxtNode() ) ),
+ msTitle(),
+ msDesc()
+{
+ const SwNoTxtNode* pNd = GetNoTxtNode();
+ // --> OD 2009-07-14 #i73249#
+ // consider new attributes Title and Description
+ if( pNd )
+ {
+ msTitle = pNd->GetTitle();
+
+ msDesc = pNd->GetDescription();
+ if ( msDesc.getLength() == 0 &&
+ msTitle != GetName() )
+ {
+ msDesc = msTitle;
+ }
+ }
+ // <--
+}
+
+SwAccessibleNoTextFrame::~SwAccessibleNoTextFrame()
+{
+}
+
+void SwAccessibleNoTextFrame::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew)
+{
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+ // --> OD 2009-07-14 #i73249#
+ // suppress handling of RES_NAME_CHANGED in case that attribute Title is
+ // used as the accessible name.
+ if ( nWhich != RES_NAME_CHANGED ||
+ msTitle.getLength() == 0 )
+ {
+ SwAccessibleFrameBase::Modify( pOld, pNew );
+ }
+
+ const SwNoTxtNode *pNd = GetNoTxtNode();
+ OSL_ENSURE( pNd == aDepend.GetRegisteredIn(), "invalid frame" );
+ switch( nWhich )
+ {
+ // --> OD 2009-07-14 #i73249#
+ case RES_TITLE_CHANGED:
+ {
+ const String& sOldTitle(
+ dynamic_cast<SwStringMsgPoolItem*>(pOld)->GetString() );
+ const String& sNewTitle(
+ dynamic_cast<SwStringMsgPoolItem*>(pNew)->GetString() );
+ if ( sOldTitle == sNewTitle )
+ {
+ break;
+ }
+ msTitle = sNewTitle;
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::NAME_CHANGED;
+ aEvent.OldValue <<= OUString( sOldTitle );
+ aEvent.NewValue <<= msTitle;
+ FireAccessibleEvent( aEvent );
+
+ if ( pNd->GetDescription().Len() != 0 )
+ {
+ break;
+ }
+ }
+ // intentional no break here
+ case RES_DESCRIPTION_CHANGED:
+ {
+ if ( pNd && GetFrm() )
+ {
+ const OUString sOldDesc( msDesc );
+
+ const String& rDesc = pNd->GetDescription();
+ msDesc = rDesc;
+ if ( msDesc.getLength() == 0 &&
+ msTitle != GetName() )
+ {
+ msDesc = msTitle;
+ }
+
+ if ( msDesc != sOldDesc )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
+ aEvent.OldValue <<= sOldDesc;
+ aEvent.NewValue <<= msDesc;
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ }
+ break;
+ // <--
+ /*
+ case RES_OBJECTDYING:
+ if( aDepend.GetRegisteredIn() ==
+ static_cast< SwModify *>( static_cast< SwPtrMsgPoolItem * >( pOld )->pObject ) )
+ const_cast < SwModify *>( aDepend.GetRegisteredIn()->Remove( aDepend );
+ break;
+
+ case RES_FMT_CHG:
+ if( static_cast< SwFmtChg * >(pNew)->pChangedFmt == GetRegisteredIn() &&
+ static_cast< SwFmtChg * >(pOld)->pChangedFmt->IsFmtInDTOR() )
+ pRegisteredIn->Remove( this );
+ break;
+ */
+ }
+}
+
+void SwAccessibleNoTextFrame::Dispose( sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ if( aDepend.GetRegisteredIn() )
+ const_cast < SwModify *>( aDepend.GetRegisteredIn() )->Remove( &aDepend );
+
+ SwAccessibleFrameBase::Dispose( bRecursive );
+}
+
+// --> OD 2009-07-14 #i73249#
+OUString SAL_CALL SwAccessibleNoTextFrame::getAccessibleName (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ if ( msTitle.getLength() != 0 )
+ {
+ return msTitle;
+ }
+
+ return SwAccessibleFrameBase::getAccessibleName();
+}
+// <--
+
+OUString SAL_CALL SwAccessibleNoTextFrame::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ return msDesc;
+}
+
+
+
+//
+// XInterface
+//
+
+uno::Any SAL_CALL SwAccessibleNoTextFrame::queryInterface( const uno::Type& aType )
+ throw (uno::RuntimeException)
+{
+ if( aType ==
+ ::getCppuType( static_cast<uno::Reference<XAccessibleImage>*>( NULL ) ) )
+ {
+ uno::Reference<XAccessibleImage> xImage = this;
+ uno::Any aAny;
+ aAny <<= xImage;
+ return aAny;
+ }
+ else
+ return SwAccessibleContext::queryInterface( aType );
+}
+
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleNoTextFrame::getTypes() throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleFrameBase::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ aTypes.realloc( nIndex + 1 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleImage > * >( 0 ) );
+
+ return aTypes;
+}
+
+
+//
+// XAccessibleImage
+//
+
+// implementation of the XAccessibleImage methods is a no-brainer, as
+// all releveant information is already accessible through other
+// methods. So we just delegate to those.
+
+OUString SAL_CALL SwAccessibleNoTextFrame::getAccessibleImageDescription()
+ throw ( uno::RuntimeException )
+{
+ return getAccessibleDescription();
+}
+
+sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getAccessibleImageHeight( )
+ throw ( uno::RuntimeException )
+{
+ return getSize().Height;
+}
+
+sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getAccessibleImageWidth( )
+ throw ( uno::RuntimeException )
+{
+ return getSize().Width;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accnotextframe.hxx b/sw/source/core/access/accnotextframe.hxx
new file mode 100644
index 000000000000..1ee13d61ce56
--- /dev/null
+++ b/sw/source/core/access/accnotextframe.hxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCNOTEXTFRAME_HXX
+#define _ACCNOTEXTFRAME_HXX
+#include "accframebase.hxx"
+#include <com/sun/star/accessibility/XAccessibleImage.hpp>
+
+class SwFlyFrm;
+class SwNoTxtNode;
+
+class SwAccessibleNoTextFrame : public SwAccessibleFrameBase,
+ public ::com::sun::star::accessibility::XAccessibleImage
+{
+ SwDepend aDepend;
+ // --> OD 2009-07-14 #i73249#
+ ::rtl::OUString msTitle;
+ // <--
+ ::rtl::OUString msDesc;
+
+protected:
+
+ virtual ~SwAccessibleNoTextFrame();
+
+ const SwNoTxtNode *GetNoTxtNode() const;
+
+public:
+
+ SwAccessibleNoTextFrame( SwAccessibleMap* pInitMap,
+ sal_Int16 nInitRole,
+ const SwFlyFrm *pFlyFrm );
+
+ virtual void Modify( SfxPoolItem *pOld, SfxPoolItem *pNew);
+
+ //===== XAccessibleContext ==============================================
+
+ // --> OD 2009-07-14 #i73249#
+ /// Return the object's current name.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+ // <--
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XInterface ======================================================
+
+ // XInterface methods need to be implemented to disambiguate
+ // between those inherited through SwAcessibleContext and
+ // XAccessibleImage.
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleImage ================================================
+
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleImageDescription( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int32 SAL_CALL
+ getAccessibleImageHeight( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int32 SAL_CALL
+ getAccessibleImageWidth( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpage.cxx b/sw/source/core/access/accpage.cxx
new file mode 100644
index 000000000000..cd1dc8a02ac4
--- /dev/null
+++ b/sw/source/core/access/accpage.cxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <rtl/uuid.h>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include "accpage.hxx"
+
+#include "access.hrc"
+#include <pagefrm.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+using uno::Reference;
+using uno::RuntimeException;
+using uno::Sequence;
+using ::rtl::OUString;
+
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessiblePageView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessiblePageView";
+
+sal_Bool SwAccessiblePage::IsSelected()
+{
+ return GetMap()->IsPageSelected( static_cast < const SwPageFrm * >( GetFrm() ) );
+}
+
+void SwAccessiblePage::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // FOCUSABLE
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ // FOCUSED
+ if( IsSelected() )
+ {
+ OSL_ENSURE( bIsSelected, "bSelected out of sync" );
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+ }
+}
+
+void SwAccessiblePage::_InvalidateCursorPos()
+{
+ sal_Bool bNewSelected = IsSelected();
+ sal_Bool bOldSelected;
+
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bOldSelected = bIsSelected;
+ bIsSelected = bNewSelected;
+ }
+
+ if( bNewSelected )
+ {
+ // remember that object as the one that has the caret. This is
+ // neccessary to notify that object if the cursor leaves it.
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ if( bOldSelected != bNewSelected )
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
+ }
+}
+
+void SwAccessiblePage::_InvalidateFocus()
+{
+ Window *pWin = GetWindow();
+ if( pWin )
+ {
+ sal_Bool bSelected;
+
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bSelected = bIsSelected;
+ }
+ OSL_ENSURE( bSelected, "focus object should be selected" );
+
+ FireStateChangedEvent( AccessibleStateType::FOCUSED,
+ pWin->HasFocus() && bSelected );
+ }
+}
+
+SwAccessiblePage::SwAccessiblePage( SwAccessibleMap* pInitMap,
+ const SwFrm* pFrame )
+ : SwAccessibleContext( pInitMap, AccessibleRole::PANEL, pFrame )
+ , bIsSelected( sal_False )
+{
+ DBG_ASSERT( pFrame != NULL, "need frame" );
+ DBG_ASSERT( pInitMap != NULL, "need map" );
+ DBG_ASSERT( pFrame->IsPageFrm(), "need page frame" );
+
+ SolarMutexGuard aGuard;
+
+ OUString sPage = OUString::valueOf(
+ static_cast<sal_Int32>(
+ static_cast<const SwPageFrm*>( GetFrm() )->GetPhyPageNum() ) );
+ SetName( GetResource( STR_ACCESS_PAGE_NAME, &sPage ) );
+}
+
+SwAccessiblePage::~SwAccessiblePage()
+{
+}
+
+sal_Bool SwAccessiblePage::HasCursor()
+{
+ osl::MutexGuard aGuard( aMutex );
+ return bIsSelected;
+}
+
+OUString SwAccessiblePage::getImplementationName( )
+ throw( RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SwAccessiblePage::supportsService( const OUString& rServiceName)
+ throw( RuntimeException )
+{
+ return rServiceName.equalsAsciiL( sServiceName, sizeof(sServiceName)-1 ) ||
+ rServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+Sequence<OUString> SwAccessiblePage::getSupportedServiceNames( )
+ throw( RuntimeException )
+{
+ Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessiblePage::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+OUString SwAccessiblePage::getAccessibleDescription( )
+ throw( RuntimeException )
+{
+ CHECK_FOR_DEFUNC( ::com::sun::star::accessibility::XAccessibleContext );
+
+ OUString sArg( GetFormattedPageNumber() );
+ return GetResource( STR_ACCESS_PAGE_DESC, &sArg );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpage.hxx b/sw/source/core/access/accpage.hxx
new file mode 100644
index 000000000000..690bf12acfe2
--- /dev/null
+++ b/sw/source/core/access/accpage.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCPAGE_HXX
+#define _ACCPAGE_HXX
+
+#include "acccontext.hxx"
+
+
+/**
+ * accessibility implementation for the page (SwPageFrm)
+ * The page is _only_ visible in the page preview. For the regular
+ * document view, it doesn't make sense to add this additional element
+ * into the hierarchy. For the page preview, however, the page is the
+ * important.
+ */
+class SwAccessiblePage : public SwAccessibleContext
+{
+ sal_Bool bIsSelected; // protected by base class mutex
+
+ sal_Bool IsSelected();
+
+ using SwAccessibleFrame::GetBounds;
+
+protected:
+
+ // return the bounding box for the page in page preview mode
+ SwRect GetBounds( /* const SwFrm *pFrm =0 */ );
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additionaly sets
+ // FOCUSABLE(1) and FOCUSED(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual void _InvalidateCursorPos();
+ virtual void _InvalidateFocus();
+
+ virtual ~SwAccessiblePage();
+
+public:
+ // convenience constructor to avoid typecast;
+ // may only be called with SwPageFrm argument
+ SwAccessiblePage( SwAccessibleMap* pInitMap, const SwFrm* pFrame );
+
+
+
+ //
+ // XAccessibleContext methods that need to be overridden
+ //
+
+ virtual ::rtl::OUString SAL_CALL getAccessibleDescription (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //
+ // XServiceInfo
+ //
+
+ virtual ::rtl::OUString SAL_CALL getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService (
+ const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
new file mode 100644
index 000000000000..5774d78dc19a
--- /dev/null
+++ b/sw/source/core/access/accpara.cxx
@@ -0,0 +1,2680 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <txtfrm.hxx>
+#include <flyfrm.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <unotextrange.hxx>
+#include <unocrsrhelper.hxx>
+#include <crstate.hxx>
+#include <accmap.hxx>
+#include <fesh.hxx>
+#include <viewopt.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <rtl/ustrbuf.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/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <breakit.hxx>
+#include <accpara.hxx>
+#include <access.hrc>
+#include <accportions.hxx>
+#include <sfx2/viewsh.hxx> // for ExecuteAtViewShell(...)
+#include <sfx2/viewfrm.hxx> // for ExecuteAtViewShell(...)
+#include <sfx2/dispatch.hxx> // for ExecuteAtViewShell(...)
+#include <unotools/charclass.hxx> // for GetWordBoundary
+// for get/setCharacterAttribute(...)
+#include <unocrsr.hxx>
+#include <unoport.hxx>
+#include <doc.hxx>
+#include <crsskip.hxx>
+#include <txtatr.hxx>
+#include <acchyperlink.hxx>
+#include <acchypertextdata.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <comphelper/accessibletexthelper.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <editeng/brshitem.hxx>
+#include <viewimp.hxx>
+#include <boost/scoped_ptr.hpp>
+#include <textmarkuphelper.hxx>
+// --> OD 2010-02-22 #i10825#
+#include <parachangetrackinginfo.hxx>
+#include <com/sun/star/text/TextMarkupType.hpp>
+// <--
+// --> OD 2010-03-08 #i92233#
+#include <comphelper/stlunosequence.hxx>
+// <--
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+using beans::PropertyValue;
+using beans::XMultiPropertySet;
+using beans::UnknownPropertyException;
+using beans::PropertyState_DIRECT_VALUE;
+
+using std::max;
+using std::min;
+using std::sort;
+
+namespace com { namespace sun { namespace star {
+ namespace text {
+ class XText;
+ }
+} } }
+
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView";
+const xub_StrLen MAX_DESC_TEXT_LEN = 40;
+const SwTxtNode* SwAccessibleParagraph::GetTxtNode() const
+{
+ const SwFrm* pFrm = GetFrm();
+ DBG_ASSERT( pFrm->IsTxtFrm(), "The text frame has mutated!" );
+
+ const SwTxtNode* pNode = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode();
+ DBG_ASSERT( pNode != NULL, "A text frame without a text node." );
+
+ return pNode;
+}
+
+::rtl::OUString SwAccessibleParagraph::GetString()
+{
+ return GetPortionData().GetAccessibleString();
+}
+
+::rtl::OUString SwAccessibleParagraph::GetDescription()
+{
+ // --> OD 2004-09-29 #117933# - provide empty description for paragraphs
+ return ::rtl::OUString();
+ // <--
+}
+
+sal_Int32 SwAccessibleParagraph::GetCaretPos()
+{
+ sal_Int32 nRet = -1;
+
+ // get the selection's point, and test whether it's in our node
+ // --> OD 2005-12-20 #i27301# - consider adjusted method signature
+ SwPaM* pCaret = GetCursor( false ); // caret is first PaM in PaM-ring
+ // <--
+ if( pCaret != NULL )
+ {
+ const SwTxtNode* pNode = GetTxtNode();
+
+ // check whether the point points into 'our' node
+ SwPosition* pPoint = pCaret->GetPoint();
+ if( pNode->GetIndex() == pPoint->nNode.GetIndex() )
+ {
+ // same node? Then check whether it's also within 'our' part
+ // of the paragraph
+ USHORT nIndex = pPoint->nContent.GetIndex();
+ if( GetPortionData().IsValidCorePosition( nIndex ) )
+ {
+ // Yes, it's us!
+ // --> OD 2006-10-19 #70538#
+ // consider that cursor/caret is in front of the list label
+ if ( pCaret->IsInFrontOfLabel() )
+ {
+ nRet = 0;
+ }
+ else
+ {
+ nRet = GetPortionData().GetAccessiblePosition( nIndex );
+ }
+ // <--
+
+ DBG_ASSERT( nRet >= 0, "invalid cursor?" );
+ DBG_ASSERT( nRet <= GetPortionData().GetAccessibleString().
+ getLength(), "invalid cursor?" );
+ }
+ // else: in this paragraph, but in different frame
+ }
+ // else: not in this paragraph
+ }
+ // else: no cursor -> no caret
+
+ return nRet;
+}
+
+sal_Bool SwAccessibleParagraph::GetSelection(
+ sal_Int32& nStart, sal_Int32& nEnd)
+{
+ sal_Bool bRet = sal_False;
+ nStart = -1;
+ nEnd = -1;
+
+ // get the selection, and test whether it affects our text node
+ // --> OD 2005-12-20 #i27301# - consider adjusted method signature
+ SwPaM* pCrsr = GetCursor( true );
+ // <--
+ if( pCrsr != NULL )
+ {
+ // get SwPosition for my node
+ const SwTxtNode* pNode = GetTxtNode();
+ ULONG nHere = pNode->GetIndex();
+
+ // iterate over ring
+ SwPaM* pRingStart = pCrsr;
+ do
+ {
+ // ignore, if no mark
+ if( pCrsr->HasMark() )
+ {
+ // check whether nHere is 'inside' pCrsr
+ SwPosition* pStart = pCrsr->Start();
+ ULONG nStartIndex = pStart->nNode.GetIndex();
+ SwPosition* pEnd = pCrsr->End();
+ ULONG nEndIndex = pEnd->nNode.GetIndex();
+ if( ( nHere >= nStartIndex ) &&
+ ( nHere <= nEndIndex ) )
+ {
+ // translate start and end positions
+
+ // start position
+ sal_Int32 nLocalStart = -1;
+ if( nHere > nStartIndex )
+ {
+ // selection starts in previous node:
+ // then our local selection starts with the paragraph
+ nLocalStart = 0;
+ }
+ else
+ {
+ DBG_ASSERT( nHere == nStartIndex,
+ "miscalculated index" );
+
+ // selection starts in this node:
+ // then check whether it's before or inside our part of
+ // the paragraph, and if so, get the proper position
+ USHORT nCoreStart = pStart->nContent.GetIndex();
+ if( nCoreStart <
+ GetPortionData().GetFirstValidCorePosition() )
+ {
+ nLocalStart = 0;
+ }
+ else if( nCoreStart <=
+ GetPortionData().GetLastValidCorePosition() )
+ {
+ DBG_ASSERT(
+ GetPortionData().IsValidCorePosition(
+ nCoreStart ),
+ "problem determining valid core position" );
+
+ nLocalStart =
+ GetPortionData().GetAccessiblePosition(
+ nCoreStart );
+ }
+ }
+
+ // end position
+ sal_Int32 nLocalEnd = -1;
+ if( nHere < nEndIndex )
+ {
+ // selection ends in following node:
+ // then our local selection extends to the end
+ nLocalEnd = GetPortionData().GetAccessibleString().
+ getLength();
+ }
+ else
+ {
+ DBG_ASSERT( nHere == nEndIndex,
+ "miscalculated index" );
+
+ // selection ends in this node: then select everything
+ // before our part of the node
+ USHORT nCoreEnd = pEnd->nContent.GetIndex();
+ if( nCoreEnd >
+ GetPortionData().GetLastValidCorePosition() )
+ {
+ // selection extends beyond out part of this para
+ nLocalEnd = GetPortionData().GetAccessibleString().
+ getLength();
+ }
+ else if( nCoreEnd >=
+ GetPortionData().GetFirstValidCorePosition() )
+ {
+ // selection is inside our part of this para
+ DBG_ASSERT(
+ GetPortionData().IsValidCorePosition(
+ nCoreEnd ),
+ "problem determining valid core position" );
+
+ nLocalEnd = GetPortionData().GetAccessiblePosition(
+ nCoreEnd );
+ }
+ }
+
+ if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) )
+ {
+ nStart = nLocalStart;
+ nEnd = nLocalEnd;
+ bRet = sal_True;
+ }
+ }
+ // else: this PaM doesn't point to this paragraph
+ }
+ // else: this PaM is collapsed and doesn't select anything
+
+ // next PaM in ring
+ pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
+ }
+ while( !bRet && (pCrsr != pRingStart) );
+ }
+ // else: nocursor -> no selection
+
+ return bRet;
+}
+
+// --> OD 2005-12-20 #i27301# - new parameter <_bForSelection>
+SwPaM* SwAccessibleParagraph::GetCursor( const bool _bForSelection )
+{
+ // get the cursor shell; if we don't have any, we don't have a
+ // cursor/selection either
+ SwPaM* pCrsr = NULL;
+ SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
+ // --> OD 2005-12-20 #i27301#
+ // - if cursor is retrieved for selection, the cursors for a table selection
+ // has to be returned.
+ if ( pCrsrShell != NULL &&
+ ( _bForSelection || !pCrsrShell->IsTableMode() ) )
+ // <--
+ {
+ SwFEShell *pFESh = pCrsrShell->ISA( SwFEShell )
+ ? static_cast< SwFEShell * >( pCrsrShell ) : 0;
+ if( !pFESh ||
+ !(pFESh->IsFrmSelected() || pFESh->IsObjSelected() > 0) )
+ {
+ // get the selection, and test whether it affects our text node
+ pCrsr = pCrsrShell->GetCrsr( FALSE /* ??? */ );
+ }
+ }
+
+ return pCrsr;
+}
+
+sal_Bool SwAccessibleParagraph::IsHeading() const
+{
+ const SwTxtNode *pTxtNd = GetTxtNode();
+ return pTxtNd->IsOutline();
+}
+
+void SwAccessibleParagraph::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // MULTILINE
+ rStateSet.AddState( AccessibleStateType::MULTI_LINE );
+
+ // MULTISELECTABLE
+ SwCrsrShell *pCrsrSh = GetCrsrShell();
+ if( pCrsrSh )
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
+
+ // FOCUSABLE
+ if( pCrsrSh )
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ // FOCUSED (simulates node index of cursor)
+ // --> OD 2005-12-20 #i27301# - consider adjusted method signature
+ SwPaM* pCaret = GetCursor( false );
+ // <--
+ const SwTxtNode* pTxtNd = GetTxtNode();
+ if( pCaret != 0 && pTxtNd != 0 &&
+ pTxtNd->GetIndex() == pCaret->GetPoint()->nNode.GetIndex() &&
+ nOldCaretPos != -1)
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+}
+
+void SwAccessibleParagraph::_InvalidateContent( sal_Bool bVisibleDataFired )
+{
+ ::rtl::OUString sOldText( GetString() );
+
+ ClearPortionData();
+
+ const ::rtl::OUString& rText = GetString();
+
+ if( rText != sOldText )
+ {
+ // The text is changed
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::TEXT_CHANGED;
+
+ // determine exact changes between sOldText and rText
+ comphelper::OCommonAccessibleText::implInitTextChangedEvent(
+ sOldText, rText,
+ aEvent.OldValue, aEvent.NewValue );
+
+ FireAccessibleEvent( aEvent );
+ }
+ else if( !bVisibleDataFired )
+ {
+ FireVisibleDataEvent();
+ }
+
+ sal_Bool bNewIsHeading = IsHeading();
+ sal_Bool bOldIsHeading;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bOldIsHeading = bIsHeading;
+ if( bIsHeading != bNewIsHeading )
+ bIsHeading = bNewIsHeading;
+ }
+
+
+ if( bNewIsHeading != bOldIsHeading || rText != sOldText )
+ {
+ ::rtl::OUString sNewDesc( GetDescription() );
+ ::rtl::OUString sOldDesc;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ sOldDesc = sDesc;
+ if( sDesc != sNewDesc )
+ sDesc = sNewDesc;
+ }
+
+ if( sNewDesc != sOldDesc )
+ {
+ // The text is changed
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
+ aEvent.OldValue <<= sOldDesc;
+ aEvent.NewValue <<= sNewDesc;
+
+ FireAccessibleEvent( aEvent );
+ }
+ }
+}
+
+void SwAccessibleParagraph::_InvalidateCursorPos()
+{
+ // The text is changed
+ sal_Int32 nNew = GetCaretPos();
+ sal_Int32 nOld;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ nOld = nOldCaretPos;
+ nOldCaretPos = nNew;
+ }
+ if( -1 != nNew )
+ {
+ // remember that object as the one that has the caret. This is
+ // neccessary to notify that object if the cursor leaves it.
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ Window *pWin = GetWindow();
+ if( nOld != nNew )
+ {
+ // The cursor's node position is sumilated by the focus!
+ if( pWin && pWin->HasFocus() && -1 == nOld )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_True );
+
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CARET_CHANGED;
+ aEvent.OldValue <<= nOld;
+ aEvent.NewValue <<= nNew;
+
+ FireAccessibleEvent( aEvent );
+
+ if( pWin && pWin->HasFocus() && -1 == nNew )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_False );
+ }
+}
+
+void SwAccessibleParagraph::_InvalidateFocus()
+{
+ Window *pWin = GetWindow();
+ if( pWin )
+ {
+ sal_Int32 nPos;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ nPos = nOldCaretPos;
+ }
+ OSL_ENSURE( nPos != -1, "focus object should be selected" );
+
+ FireStateChangedEvent( AccessibleStateType::FOCUSED,
+ pWin->HasFocus() && nPos != -1 );
+ }
+}
+
+SwAccessibleParagraph::SwAccessibleParagraph(
+ SwAccessibleMap& rInitMap,
+ const SwTxtFrm& rTxtFrm )
+ // --> OD 2010-02-24 #i108125#
+ : SwClient( const_cast<SwTxtNode*>(rTxtFrm.GetTxtNode()) )
+ // <--
+ , SwAccessibleContext( &rInitMap, AccessibleRole::PARAGRAPH, &rTxtFrm )
+ , sDesc()
+ , pPortionData( NULL )
+ , pHyperTextData( NULL )
+ , nOldCaretPos( -1 )
+ , bIsHeading( sal_False )
+ , aSelectionHelper( *this )
+ // --> OD 2010-02-19 #i108125#
+ , mpParaChangeTrackInfo( new SwParaChangeTrackingInfo( rTxtFrm ) )
+ // <--
+{
+ SolarMutexGuard aGuard;
+
+ bIsHeading = IsHeading();
+ // --> OD 2004-09-27 #117970# - set an empty accessibility name for paragraphs
+ SetName( ::rtl::OUString() );
+ // <--
+
+ // If this object has the focus, then it is remembered by the map itself.
+ nOldCaretPos = GetCaretPos();
+}
+
+SwAccessibleParagraph::~SwAccessibleParagraph()
+{
+ SolarMutexGuard aGuard;
+
+ delete pPortionData;
+ delete pHyperTextData;
+ // --> OD 2010-02-22 #i108125#
+ delete mpParaChangeTrackInfo;
+ // <--
+}
+
+sal_Bool SwAccessibleParagraph::HasCursor()
+{
+ osl::MutexGuard aGuard( aMutex );
+ return nOldCaretPos != -1;
+}
+
+void SwAccessibleParagraph::UpdatePortionData()
+ throw( uno::RuntimeException )
+{
+ // obtain the text frame
+ DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" );
+ DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
+ const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+
+ // build new portion data
+ delete pPortionData;
+ pPortionData = new SwAccessiblePortionData(
+ pFrm->GetTxtNode(), GetMap()->GetShell()->GetViewOptions() );
+ pFrm->VisitPortions( *pPortionData );
+
+ DBG_ASSERT( pPortionData != NULL, "UpdatePortionData() failed" );
+}
+
+void SwAccessibleParagraph::ClearPortionData()
+{
+ delete pPortionData;
+ pPortionData = NULL;
+
+ delete pHyperTextData;
+ pHyperTextData = 0;
+}
+
+
+void SwAccessibleParagraph::ExecuteAtViewShell( UINT16 nSlot )
+{
+ DBG_ASSERT( GetMap() != NULL, "no map?" );
+ ViewShell* pViewShell = GetMap()->GetShell();
+
+ DBG_ASSERT( pViewShell != NULL, "View shell exptected!" );
+ SfxViewShell* pSfxShell = pViewShell->GetSfxViewShell();
+
+ DBG_ASSERT( pSfxShell != NULL, "SfxViewShell shell exptected!" );
+ if( !pSfxShell )
+ return;
+
+ SfxViewFrame *pFrame = pSfxShell->GetViewFrame();
+ DBG_ASSERT( pFrame != NULL, "View frame exptected!" );
+ if( !pFrame )
+ return;
+
+ SfxDispatcher *pDispatcher = pFrame->GetDispatcher();
+ DBG_ASSERT( pDispatcher != NULL, "Dispatcher exptected!" );
+ if( !pDispatcher )
+ return;
+
+ pDispatcher->Execute( nSlot );
+}
+
+SwXTextPortion* SwAccessibleParagraph::CreateUnoPortion(
+ sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex )
+{
+ DBG_ASSERT( (IsValidChar(nStartIndex, GetString().getLength()) &&
+ (nEndIndex == -1)) ||
+ IsValidRange(nStartIndex, nEndIndex, GetString().getLength()),
+ "please check parameters before calling this method" );
+
+ USHORT nStart = GetPortionData().GetModelPosition( nStartIndex );
+ USHORT nEnd = (nEndIndex == -1) ? (nStart + 1) :
+ GetPortionData().GetModelPosition( nEndIndex );
+
+ // create UNO cursor
+ SwTxtNode* pTxtNode = const_cast<SwTxtNode*>( GetTxtNode() );
+ SwIndex aIndex( pTxtNode, nStart );
+ SwPosition aStartPos( *pTxtNode, aIndex );
+ SwUnoCrsr* pUnoCursor = pTxtNode->GetDoc()->CreateUnoCrsr( aStartPos );
+ pUnoCursor->SetMark();
+ pUnoCursor->GetMark()->nContent = nEnd;
+
+ // create a (dummy) text portion to be returned
+ uno::Reference<text::XText> aEmpty;
+ SwXTextPortion* pPortion =
+ new SwXTextPortion ( pUnoCursor, aEmpty, PORTION_TEXT);
+ delete pUnoCursor;
+
+ return pPortion;
+}
+
+
+//
+// range checking for parameter
+//
+
+sal_Bool SwAccessibleParagraph::IsValidChar(
+ sal_Int32 nPos, sal_Int32 nLength)
+{
+ return (nPos >= 0) && (nPos < nLength);
+}
+
+sal_Bool SwAccessibleParagraph::IsValidPosition(
+ sal_Int32 nPos, sal_Int32 nLength)
+{
+ return (nPos >= 0) && (nPos <= nLength);
+}
+
+sal_Bool SwAccessibleParagraph::IsValidRange(
+ sal_Int32 nBegin, sal_Int32 nEnd, sal_Int32 nLength)
+{
+ return IsValidPosition(nBegin, nLength) && IsValidPosition(nEnd, nLength);
+}
+
+
+//
+// text boundaries
+//
+
+
+sal_Bool SwAccessibleParagraph::GetCharBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString&,
+ sal_Int32 nPos )
+{
+ rBound.startPos = nPos;
+ rBound.endPos = nPos+1;
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetWordBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 nPos )
+{
+ sal_Bool bRet = sal_False;
+
+ // now ask the Break-Iterator for the word
+ DBG_ASSERT( pBreakIt != NULL, "We always need a break." );
+ DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." );
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ // get locale for this position
+ USHORT nModelPos = GetPortionData().GetModelPosition( nPos );
+ lang::Locale aLocale = pBreakIt->GetLocale(
+ GetTxtNode()->GetLang( nModelPos ) );
+
+ // which type of word are we interested in?
+ // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.)
+ const USHORT nWordType = i18n::WordType::ANY_WORD;
+
+ // get word boundary, as the Break-Iterator sees fit.
+ rBound = pBreakIt->GetBreakIter()->getWordBoundary(
+ rText, nPos, aLocale, nWordType, sal_True );
+
+ // It's a word if the first character is an alpha-numeric character.
+ bRet = GetAppCharClass().isLetterNumeric(
+ rText.getStr()[ rBound.startPos ] );
+ }
+ else
+ {
+ // no break Iterator -> no word
+ rBound.startPos = nPos;
+ rBound.endPos = nPos;
+ }
+
+ return bRet;
+}
+
+sal_Bool SwAccessibleParagraph::GetSentenceBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString&,
+ sal_Int32 nPos )
+{
+ GetPortionData().GetSentenceBoundary( rBound, nPos );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetLineBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 nPos )
+{
+ if( rText.getLength() == nPos )
+ GetPortionData().GetLastLineBoundary( rBound );
+ else
+ GetPortionData().GetLineBoundary( rBound, nPos );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetParagraphBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 )
+{
+ rBound.startPos = 0;
+ rBound.endPos = rText.getLength();
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetAttributeBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString&,
+ sal_Int32 nPos )
+{
+ GetPortionData().GetAttributeBoundary( rBound, nPos );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetGlyphBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 nPos )
+{
+ sal_Bool bRet = sal_False;
+
+ // ask the Break-Iterator for the glyph by moving one cell
+ // forward, and then one cell back
+ DBG_ASSERT( pBreakIt != NULL, "We always need a break." );
+ DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." );
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ // get locale for this position
+ USHORT nModelPos = GetPortionData().GetModelPosition( nPos );
+ lang::Locale aLocale = pBreakIt->GetLocale(
+ GetTxtNode()->GetLang( nModelPos ) );
+
+ // get word boundary, as the Break-Iterator sees fit.
+ const USHORT nIterMode = i18n::CharacterIteratorMode::SKIPCELL;
+ sal_Int32 nDone = 0;
+ rBound.endPos = pBreakIt->GetBreakIter()->nextCharacters(
+ rText, nPos, aLocale, nIterMode, 1, nDone );
+ rBound.startPos = pBreakIt->GetBreakIter()->previousCharacters(
+ rText, rBound.endPos, aLocale, nIterMode, 1, nDone );
+
+ DBG_ASSERT( rBound.startPos <= nPos, "start pos too high" );
+ DBG_ASSERT( rBound.endPos >= nPos, "end pos too low" );
+ }
+ else
+ {
+ // no break Iterator -> no glyph
+ rBound.startPos = nPos;
+ rBound.endPos = nPos;
+ }
+
+ return bRet;
+}
+
+
+sal_Bool SwAccessibleParagraph::GetTextBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 nPos,
+ sal_Int16 nTextType )
+ throw (
+ lang::IndexOutOfBoundsException,
+ lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ // error checking
+ if( !( AccessibleTextType::LINE == nTextType
+ ? IsValidPosition( nPos, rText.getLength() )
+ : IsValidChar( nPos, rText.getLength() ) ) )
+ throw lang::IndexOutOfBoundsException();
+
+ sal_Bool bRet;
+
+ switch( nTextType )
+ {
+ case AccessibleTextType::WORD:
+ bRet = GetWordBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::SENTENCE:
+ bRet = GetSentenceBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::PARAGRAPH:
+ bRet = GetParagraphBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::CHARACTER:
+ bRet = GetCharBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::LINE:
+ bRet = GetLineBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::ATTRIBUTE_RUN:
+ bRet = GetAttributeBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::GLYPH:
+ bRet = GetGlyphBoundary( rBound, rText, nPos );
+ break;
+
+ default:
+ throw lang::IllegalArgumentException( );
+ }
+
+ return bRet;
+}
+
+::rtl::OUString SAL_CALL SwAccessibleParagraph::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ osl::MutexGuard aGuard2( aMutex );
+ if( !sDesc.getLength() )
+ sDesc = GetDescription();
+
+ return sDesc;
+}
+
+lang::Locale SAL_CALL SwAccessibleParagraph::getLocale (void)
+ throw (IllegalAccessibleComponentStateException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtFrm *pTxtFrm = PTR_CAST( SwTxtFrm, GetFrm() );
+ if( !pTxtFrm )
+ {
+ THROW_RUNTIME_EXCEPTION( XAccessibleContext, "internal error (no text frame)" );
+ }
+
+ const SwTxtNode *pTxtNd = pTxtFrm->GetTxtNode();
+ lang::Locale aLoc( pBreakIt->GetLocale( pTxtNd->GetLang( 0 ) ) );
+
+ return aLoc;
+}
+
+/** paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO
+
+ OD 2005-12-02 #i27138#
+
+ @author OD
+*/
+uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleParagraph::getAccessibleRelationSet()
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ utl::AccessibleRelationSetHelper* pHelper = new utl::AccessibleRelationSetHelper();
+
+ const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(GetFrm());
+ OSL_ENSURE( pTxtFrm,
+ "<SwAccessibleParagraph::getAccessibleRelationSet()> - missing text frame");
+ if ( pTxtFrm )
+ {
+ const SwCntntFrm* pPrevCntFrm( pTxtFrm->FindPrevCnt( true ) );
+ if ( pPrevCntFrm )
+ {
+ uno::Sequence< uno::Reference<XInterface> > aSequence(1);
+ aSequence[0] = GetMap()->GetContext( pPrevCntFrm );
+ AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM,
+ aSequence );
+ pHelper->AddRelation( aAccRel );
+ }
+
+ const SwCntntFrm* pNextCntFrm( pTxtFrm->FindNextCnt( true ) );
+ if ( pNextCntFrm )
+ {
+ uno::Sequence< uno::Reference<XInterface> > aSequence(1);
+ aSequence[0] = GetMap()->GetContext( pNextCntFrm );
+ AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO,
+ aSequence );
+ pHelper->AddRelation( aAccRel );
+ }
+ }
+
+ return pHelper;
+}
+
+void SAL_CALL SwAccessibleParagraph::grabFocus()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ // get cursor shell
+ SwCrsrShell *pCrsrSh = GetCrsrShell();
+ // --> OD 2005-12-20 #i27301# - consider new method signature
+ SwPaM *pCrsr = GetCursor( false );
+ // <--
+ const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ const SwTxtNode* pTxtNd = pTxtFrm->GetTxtNode();
+
+ if( pCrsrSh != 0 && pTxtNd != 0 &&
+ ( pCrsr == 0 ||
+ pCrsr->GetPoint()->nNode.GetIndex() != pTxtNd->GetIndex() ||
+ !pTxtFrm->IsInside( pCrsr->GetPoint()->nContent.GetIndex()) ) )
+ {
+ // create pam for selection
+ SwIndex aIndex( const_cast< SwTxtNode * >( pTxtNd ),
+ pTxtFrm->GetOfst() );
+ SwPosition aStartPos( *pTxtNd, aIndex );
+ SwPaM aPaM( aStartPos );
+
+ // set PaM at cursor shell
+ Select( aPaM );
+
+
+ }
+
+ /* ->#i13955# */
+ Window * pWindow = GetWindow();
+
+ if (pWindow != NULL)
+ pWindow->GrabFocus();
+ /* <-#i13955# */
+}
+
+// --> OD 2007-01-17 #i71385#
+bool lcl_GetBackgroundColor( Color & rColor,
+ const SwFrm* pFrm,
+ SwCrsrShell* pCrsrSh )
+{
+ const SvxBrushItem* pBackgrdBrush = 0;
+ const Color* pSectionTOXColor = 0;
+ SwRect aDummyRect;
+ if ( pFrm &&
+ pFrm->GetBackgroundBrush( pBackgrdBrush, pSectionTOXColor, aDummyRect, false ) )
+ {
+ if ( pSectionTOXColor )
+ {
+ rColor = *pSectionTOXColor;
+ return true;
+ }
+ else
+ {
+ rColor = pBackgrdBrush->GetColor();
+ return true;
+ }
+ }
+ else if ( pCrsrSh )
+ {
+ rColor = pCrsrSh->Imp()->GetRetoucheColor();
+ return true;
+ }
+
+ return false;
+}
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getForeground()
+ throw (uno::RuntimeException)
+{
+ Color aBackgroundCol;
+
+ if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
+ {
+ if ( aBackgroundCol.IsDark() )
+ {
+ return COL_WHITE;
+ }
+ else
+ {
+ return COL_BLACK;
+ }
+ }
+
+ return SwAccessibleContext::getForeground();
+}
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground()
+ throw (uno::RuntimeException)
+{
+ Color aBackgroundCol;
+
+ if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
+ {
+ return aBackgroundCol.GetColor();
+ }
+
+ return SwAccessibleContext::getBackground();
+}
+// <--
+
+::rtl::OUString SAL_CALL SwAccessibleParagraph::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleParagraph::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< ::rtl::OUString > SAL_CALL SwAccessibleParagraph::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< ::rtl::OUString > aRet(2);
+ ::rtl::OUString* pArray = aRet.getArray();
+ pArray[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+//
+//===== XInterface =======================================================
+//
+
+uno::Any SwAccessibleParagraph::queryInterface( const uno::Type& rType )
+ throw (uno::RuntimeException)
+{
+ uno::Any aRet;
+ if ( rType == ::getCppuType((uno::Reference<XAccessibleText> *)0) )
+ {
+ uno::Reference<XAccessibleText> aAccText = (XAccessibleText *) *this; // resolve ambiguity
+ aRet <<= aAccText;
+ }
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleEditableText> *)0) )
+ {
+ uno::Reference<XAccessibleEditableText> aAccEditText = this;
+ aRet <<= aAccEditText;
+ }
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleSelection> *)0) )
+ {
+ uno::Reference<XAccessibleSelection> aAccSel = this;
+ aRet <<= aAccSel;
+ }
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleHypertext> *)0) )
+ {
+ uno::Reference<XAccessibleHypertext> aAccHyp = this;
+ aRet <<= aAccHyp;
+ }
+ // --> OD 2006-07-13 #i63870#
+ // add interface com::sun:star:accessibility::XAccessibleTextAttributes
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextAttributes> *)0) )
+ {
+ uno::Reference<XAccessibleTextAttributes> aAccTextAttr = this;
+ aRet <<= aAccTextAttr;
+ }
+ // <--
+ // --> OD 2008-06-10 #i89175#
+ // add interface com::sun:star:accessibility::XAccessibleTextMarkup
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextMarkup> *)0) )
+ {
+ uno::Reference<XAccessibleTextMarkup> aAccTextMarkup = this;
+ aRet <<= aAccTextMarkup;
+ }
+ // add interface com::sun:star:accessibility::XAccessibleMultiLineText
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleMultiLineText> *)0) )
+ {
+ uno::Reference<XAccessibleMultiLineText> aAccMultiLineText = this;
+ aRet <<= aAccMultiLineText;
+ }
+ // <--
+ else
+ {
+ aRet = SwAccessibleContext::queryInterface(rType);
+ }
+
+ return aRet;
+}
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleParagraph::getTypes() throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ // --> OD 2006-07-13 #i63870#
+ // add type accessibility::XAccessibleTextAttributes
+ // --> OD 2008-06-10 #i89175#
+ // add type accessibility::XAccessibleTextMarkup and accessibility::XAccessibleMultiLineText
+ aTypes.realloc( nIndex + 6 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleEditableText > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextAttributes > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextMarkup > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleMultiLineText > * >( 0 ) );
+ pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleHypertext > * >( 0 ) );
+ // <--
+
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleParagraph::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+
+//
+//===== XAccesibleText ===================================================
+//
+
+sal_Int32 SwAccessibleParagraph::getCaretPosition()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ sal_Int32 nRet = GetCaretPos();
+ {
+ osl::MutexGuard aOldCaretPosGuard( aMutex );
+ OSL_ENSURE( nRet == nOldCaretPos, "caret pos out of sync" );
+ nOldCaretPos = nRet;
+ }
+ if( -1 != nRet )
+ {
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ return nRet;
+}
+
+sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ // parameter checking
+ sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidPosition( nIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ sal_Bool bRet = sal_False;
+
+ // get cursor shell
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell != NULL )
+ {
+ // create pam for selection
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+ SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nIndex));
+ SwPosition aStartPos( *pNode, aIndex );
+ SwPaM aPaM( aStartPos );
+
+ // set PaM at cursor shell
+ bRet = Select( aPaM );
+ }
+
+ return bRet;
+}
+
+sal_Unicode SwAccessibleParagraph::getCharacter( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ ::rtl::OUString sText( GetString() );
+
+ // return character (if valid)
+ if( IsValidChar(nIndex, sText.getLength() ) )
+ {
+ return sText.getStr()[nIndex];
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+}
+
+// --> OD 2006-07-20 #i63870#
+// re-implement method on behalf of methods <_getDefaultAttributesImpl(..)> and
+// <_getRunAttributesImpl(..)>
+uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes(
+ sal_Int32 nIndex,
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ const ::rtl::OUString& rText = GetString();
+
+ if( ! IsValidChar( nIndex, rText.getLength() ) )
+ throw lang::IndexOutOfBoundsException();
+
+ // retrieve default character attributes
+ tAccParaPropValMap aDefAttrSeq;
+ _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq, true );
+
+ // retrieved run character attributes
+ tAccParaPropValMap aRunAttrSeq;
+ _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq );
+
+ // merge default and run attributes
+ uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 i = 0;
+ for ( tAccParaPropValMap::const_iterator aDefIter = aDefAttrSeq.begin();
+ aDefIter != aDefAttrSeq.end();
+ ++aDefIter )
+ {
+ tAccParaPropValMap::const_iterator aRunIter =
+ aRunAttrSeq.find( aDefIter->first );
+ if ( aRunIter != aRunAttrSeq.end() )
+ {
+ pValues[i] = aRunIter->second;
+ }
+ else
+ {
+ pValues[i] = aDefIter->second;
+ }
+ ++i;
+ }
+
+// // create a (dummy) text portion for the sole purpose of calling
+// // getPropertyValues on it
+// Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nIndex, nIndex + 1 );
+
+// // get values
+// Sequence<OUString> aNames = getAttributeNames();
+// sal_Int32 nLength = aNames.getLength();
+// Sequence<Any> aAnys( nLength );
+// aAnys = xPortion->getPropertyValues( aNames );
+
+// // copy names + anys into return sequence
+// Sequence<PropertyValue> aValues( aNames.getLength() );
+// const OUString* pNames = aNames.getConstArray();
+// const Any* pAnys = aAnys.getConstArray();
+// PropertyValue* pValues = aValues.getArray();
+// for( sal_Int32 i = 0; i < nLength; i++ )
+// {
+// PropertyValue& rValue = pValues[i];
+// rValue.Name = pNames[i];
+// rValue.Value = pAnys[i];
+// rValue.Handle = -1; // handle not supported
+// rValue.State = PropertyState_DIRECT_VALUE; // states not supported
+// }
+
+// // adjust background color if we're in a gray portion
+// DBG_ASSERT( pValues[CHAR_BACK_COLOR_POS].Name.
+// equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CharBackColor")),
+// "Please adjust CHAR_BACK_COLOR_POS constant." );
+// if( GetPortionData().IsInGrayPortion( nIndex ) )
+// pValues[CHAR_BACK_COLOR_POS].Value <<= SwViewOption::GetFieldShadingsColor().GetColor();
+
+ return aValues;
+}
+
+// --> OD 2006-07-11 #i63870#
+void SwAccessibleParagraph::_getDefaultAttributesImpl(
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
+ tAccParaPropValMap& rDefAttrSeq,
+ const bool bOnlyCharAttrs )
+{
+ // retrieve default attributes
+ const SwTxtNode* pTxtNode( GetTxtNode() );
+ ::boost::scoped_ptr<SfxItemSet> pSet;
+ if ( !bOnlyCharAttrs )
+ {
+ pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ RES_PARATR_BEGIN, RES_PARATR_END - 1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
+ 0 ) );
+ }
+ else
+ {
+ pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ 0 ) );
+ }
+ // --> OD 2007-11-12 #i82637#
+ // From the perspective of the a11y API the default character attributes
+ // are the character attributes, which are set at the paragraph style
+ // of the paragraph. The character attributes set at the automatic paragraph
+ // style of the paragraph are treated as run attributes.
+// pTxtNode->SwCntntNode::GetAttr( *pSet );
+ // get default paragraph attributes, if needed, and merge these into <pSet>
+ if ( !bOnlyCharAttrs )
+ {
+ SfxItemSet aParaSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
+ RES_PARATR_BEGIN, RES_PARATR_END - 1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
+ 0 );
+ pTxtNode->SwCntntNode::GetAttr( aParaSet );
+ pSet->Put( aParaSet );
+ }
+ // get default character attributes and merge these into <pSet>
+ OSL_ENSURE( pTxtNode->GetTxtColl(),
+ "<SwAccessibleParagraph::_getDefaultAttributesImpl(..)> - missing paragraph style. Serious defect, please inform OD!" );
+ if ( pTxtNode->GetTxtColl() )
+ {
+ SfxItemSet aCharSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ 0 );
+ aCharSet.Put( pTxtNode->GetTxtColl()->GetAttrSet() );
+ pSet->Put( aCharSet );
+ }
+ // <--
+
+ // build-up sequence containing the run attributes <rDefAttrSeq>
+ tAccParaPropValMap aDefAttrSeq;
+ {
+ const SfxItemPropertyMap* pPropMap =
+ aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
+ PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries();
+ PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
+ while ( aPropIt != aPropertyEntries.end() )
+ {
+ const SfxPoolItem* pItem = pSet->GetItem( aPropIt->nWID );
+ if ( pItem )
+ {
+ uno::Any aVal;
+ pItem->QueryValue( aVal, aPropIt->nMemberId );
+
+ PropertyValue rPropVal;
+ rPropVal.Name = aPropIt->sName;
+ rPropVal.Value = aVal;
+ rPropVal.Handle = -1;
+ rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
+
+ aDefAttrSeq[rPropVal.Name] = rPropVal;
+ }
+ ++aPropIt;
+ }
+
+ // --> OD 2007-01-15 #i72800#
+ // add property value entry for the paragraph style
+ if ( !bOnlyCharAttrs && pTxtNode->GetTxtColl() )
+ {
+ const ::rtl::OUString sParaStyleName =
+ ::rtl::OUString::createFromAscii(
+ GetPropName( UNO_NAME_PARA_STYLE_NAME ).pName );
+ if ( aDefAttrSeq.find( sParaStyleName ) == aDefAttrSeq.end() )
+ {
+ PropertyValue rPropVal;
+ rPropVal.Name = sParaStyleName;
+ uno::Any aVal( uno::makeAny( ::rtl::OUString( pTxtNode->GetTxtColl()->GetName() ) ) );
+ rPropVal.Value = aVal;
+ rPropVal.Handle = -1;
+ rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
+
+ aDefAttrSeq[rPropVal.Name] = rPropVal;
+ }
+ }
+ // <--
+
+ // --> OD 2007-01-15 #i73371#
+ // resolve value text::WritingMode2::PAGE of property value entry WritingMode
+ if ( !bOnlyCharAttrs && GetFrm() )
+ {
+ const ::rtl::OUString sWritingMode =
+ ::rtl::OUString::createFromAscii(
+ GetPropName( UNO_NAME_WRITING_MODE ).pName );
+ tAccParaPropValMap::iterator aIter = aDefAttrSeq.find( sWritingMode );
+ if ( aIter != aDefAttrSeq.end() )
+ {
+ PropertyValue rPropVal( aIter->second );
+ sal_Int16 nVal = rPropVal.Value.get<sal_Int16>();
+ if ( nVal == text::WritingMode2::PAGE )
+ {
+ const SwFrm* pUpperFrm( GetFrm()->GetUpper() );
+ while ( pUpperFrm )
+ {
+ if ( pUpperFrm->GetType() &
+ ( FRM_PAGE | FRM_FLY | FRM_SECTION | FRM_TAB | FRM_CELL ) )
+ {
+ if ( pUpperFrm->IsVertical() )
+ {
+ nVal = text::WritingMode2::TB_RL;
+ }
+ else if ( pUpperFrm->IsRightToLeft() )
+ {
+ nVal = text::WritingMode2::RL_TB;
+ }
+ else
+ {
+ nVal = text::WritingMode2::LR_TB;
+ }
+ rPropVal.Value <<= nVal;
+ aDefAttrSeq[rPropVal.Name] = rPropVal;
+ break;
+ }
+
+ if ( dynamic_cast<const SwFlyFrm*>(pUpperFrm) )
+ {
+ pUpperFrm = dynamic_cast<const SwFlyFrm*>(pUpperFrm)->GetAnchorFrm();
+ }
+ else
+ {
+ pUpperFrm = pUpperFrm->GetUpper();
+ }
+ }
+ }
+ }
+ }
+ // <--
+ }
+
+ if ( aRequestedAttributes.getLength() == 0 )
+ {
+ rDefAttrSeq = aDefAttrSeq;
+ }
+ else
+ {
+ const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray();
+ const sal_Int32 nLength = aRequestedAttributes.getLength();
+ for( sal_Int32 i = 0; i < nLength; ++i )
+ {
+ tAccParaPropValMap::const_iterator const aIter = aDefAttrSeq.find( pReqAttrs[i] );
+ if ( aIter != aDefAttrSeq.end() )
+ {
+ rDefAttrSeq[ aIter->first ] = aIter->second;
+ }
+ }
+ }
+}
+
+uno::Sequence< PropertyValue > SwAccessibleParagraph::getDefaultAttributes(
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ tAccParaPropValMap aDefAttrSeq;
+ _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq );
+
+ // --> OD 2010-03-08 #i92233#
+ static rtl::OUString sMMToPixelRatio(RTL_CONSTASCII_USTRINGPARAM("MMToPixelRatio"));
+ bool bProvideMMToPixelRatio( false );
+ {
+ if ( aRequestedAttributes.getLength() == 0 )
+ {
+ bProvideMMToPixelRatio = true;
+ }
+ else
+ {
+ const rtl::OUString* aRequestedAttrIter =
+ ::std::find( ::comphelper::stl_begin( aRequestedAttributes ),
+ ::comphelper::stl_end( aRequestedAttributes ),
+ sMMToPixelRatio );
+ if ( aRequestedAttrIter != ::comphelper::stl_end( aRequestedAttributes ) )
+ {
+ bProvideMMToPixelRatio = true;
+ }
+ }
+ }
+ // <--
+
+ uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() +
+ ( bProvideMMToPixelRatio ? 1 : 0 ) );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 i = 0;
+ for ( tAccParaPropValMap::const_iterator aIter = aDefAttrSeq.begin();
+ aIter != aDefAttrSeq.end();
+ ++aIter )
+ {
+ pValues[i] = aIter->second;
+ ++i;
+ }
+
+ // --> OD 2010-03-08 #i92233#
+ if ( bProvideMMToPixelRatio )
+ {
+ PropertyValue rPropVal;
+ rPropVal.Name = sMMToPixelRatio;
+ const Size a100thMMSize( 1000, 1000 );
+ const Size aPixelSize = GetMap()->LogicToPixel( a100thMMSize );
+ const float fRatio = ((float)a100thMMSize.Width()/100)/aPixelSize.Width();
+ rPropVal.Value = uno::makeAny( fRatio );
+ rPropVal.Handle = -1;
+ rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
+ pValues[ aValues.getLength() - 1 ] = rPropVal;
+ }
+ // <--
+
+ return aValues;
+}
+
+void SwAccessibleParagraph::_getRunAttributesImpl(
+ const sal_Int32 nIndex,
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
+ tAccParaPropValMap& rRunAttrSeq )
+{
+ // create PaM for character at position <nIndex>
+ SwPaM* pPaM( 0 );
+ {
+ const SwTxtNode* pTxtNode( GetTxtNode() );
+ SwPosition* pStartPos = new SwPosition( *pTxtNode );
+ pStartPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<USHORT>(nIndex) );
+ SwPosition* pEndPos = new SwPosition( *pTxtNode );
+ pEndPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<USHORT>(nIndex+1) );
+
+ pPaM = new SwPaM( *pStartPos, *pEndPos );
+
+ delete pStartPos;
+ delete pEndPos;
+ }
+
+ // retrieve character attributes for the created PaM <pPaM>
+ SfxItemSet aSet( pPaM->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END -1,
+ 0 );
+ // --> OD 2007-11-12 #i82637#
+ // From the perspective of the a11y API the character attributes, which
+ // are set at the automatic paragraph style of the paragraph are treated
+ // as run attributes.
+// SwXTextCursor::GetCrsrAttr( *pPaM, aSet, TRUE, TRUE );
+ // get character attributes from automatic paragraph style and merge these into <aSet>
+ {
+ const SwTxtNode* pTxtNode( GetTxtNode() );
+ if ( pTxtNode->HasSwAttrSet() )
+ {
+ SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END -1,
+ 0 );
+ aAutomaticParaStyleCharAttrs.Put( *(pTxtNode->GetpSwAttrSet()), FALSE );
+ aSet.Put( aAutomaticParaStyleCharAttrs );
+ }
+ }
+ // get character attributes at <pPaM> and merge these into <aSet>
+ {
+ SfxItemSet aCharAttrsAtPaM( pPaM->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END -1,
+ 0 );
+ SwUnoCursorHelper::GetCrsrAttr(*pPaM, aCharAttrsAtPaM, TRUE, TRUE);
+ aSet.Put( aCharAttrsAtPaM );
+ }
+ // <--
+
+ // build-up sequence containing the run attributes <rRunAttrSeq>
+ {
+ tAccParaPropValMap aRunAttrSeq;
+ {
+ // --> OD 2007-11-12 #i82637#
+ tAccParaPropValMap aDefAttrSeq;
+ uno::Sequence< ::rtl::OUString > aDummy;
+ _getDefaultAttributesImpl( aDummy, aDefAttrSeq, true );
+ // <--
+
+ const SfxItemPropertyMap* pPropMap =
+ aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
+ PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries();
+ PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
+ while ( aPropIt != aPropertyEntries.end() )
+ {
+ const SfxPoolItem* pItem( 0 );
+ // --> OD 2007-11-12 #i82637#
+ // Found character attributes, whose value equals the value of
+ // the corresponding default character attributes, are excluded.
+ if ( aSet.GetItemState( aPropIt->nWID, TRUE, &pItem ) == SFX_ITEM_SET )
+ {
+ uno::Any aVal;
+ pItem->QueryValue( aVal, aPropIt->nMemberId );
+
+ PropertyValue rPropVal;
+ rPropVal.Name = aPropIt->sName;
+ rPropVal.Value = aVal;
+ rPropVal.Handle = -1;
+ rPropVal.State = PropertyState_DIRECT_VALUE;
+
+ tAccParaPropValMap::const_iterator aDefIter =
+ aDefAttrSeq.find( rPropVal.Name );
+ if ( aDefIter == aDefAttrSeq.end() ||
+ rPropVal.Value != aDefIter->second.Value )
+ {
+ aRunAttrSeq[rPropVal.Name] = rPropVal;
+ }
+ }
+
+ ++aPropIt;
+ }
+ }
+
+ if ( aRequestedAttributes.getLength() == 0 )
+ {
+ rRunAttrSeq = aRunAttrSeq;
+ }
+ else
+ {
+ const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray();
+ const sal_Int32 nLength = aRequestedAttributes.getLength();
+ for( sal_Int32 i = 0; i < nLength; ++i )
+ {
+ tAccParaPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] );
+ if ( aIter != aRunAttrSeq.end() )
+ {
+ rRunAttrSeq[ (*aIter).first ] = (*aIter).second;
+ }
+ }
+ }
+ }
+
+ delete pPaM;
+}
+
+uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes(
+ sal_Int32 nIndex,
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ {
+ const ::rtl::OUString& rText = GetString();
+ if ( !IsValidChar( nIndex, rText.getLength() ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+ }
+
+ tAccParaPropValMap aRunAttrSeq;
+ _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq );
+
+ uno::Sequence< PropertyValue > aValues( aRunAttrSeq.size() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 i = 0;
+ for ( tAccParaPropValMap::const_iterator aIter = aRunAttrSeq.begin();
+ aIter != aRunAttrSeq.end();
+ ++aIter )
+ {
+ pValues[i] = aIter->second;
+ ++i;
+ }
+
+ return aValues;
+}
+// <--
+
+awt::Rectangle SwAccessibleParagraph::getCharacterBounds(
+ sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+
+ /* #i12332# The position after the string needs special treatment.
+ IsValidChar -> IsValidPosition
+ */
+ if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) )
+ throw lang::IndexOutOfBoundsException();
+
+ /* #i12332# */
+ sal_Bool bBehindText = sal_False;
+ if ( nIndex == GetString().getLength() )
+ bBehindText = sal_True;
+
+ // get model position & prepare GetCharRect() arguments
+ SwCrsrMoveState aMoveState;
+ aMoveState.bRealHeight = TRUE;
+ aMoveState.bRealWidth = TRUE;
+ SwSpecialPos aSpecialPos;
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+
+ USHORT nPos = 0;
+
+ /* #i12332# FillSpecialPos does not accept nIndex ==
+ GetString().getLength(). In that case nPos is set to the
+ length of the string in the core. This way GetCharRect
+ returns the rectangle for a cursor at the end of the
+ paragraph. */
+ if (bBehindText)
+ {
+ nPos = pNode->GetTxt().Len();
+ }
+ else
+ nPos = GetPortionData().FillSpecialPos
+ (nIndex, aSpecialPos, aMoveState.pSpecialPos );
+
+ // call GetCharRect
+ SwRect aCoreRect;
+ SwIndex aIndex( pNode, nPos );
+ SwPosition aPosition( *pNode, aIndex );
+ GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState );
+
+ // translate core coordinates into accessibility coordinates
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
+
+ Rectangle aScreenRect( GetMap()->CoreToPixel( aCoreRect.SVRect() ));
+ SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
+
+ Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
+ aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
+
+ // convert into AWT Rectangle
+ return awt::Rectangle(
+ aScreenRect.Left(), aScreenRect.Top(),
+ aScreenRect.GetWidth(), aScreenRect.GetHeight() );
+}
+
+sal_Int32 SwAccessibleParagraph::getCharacterCount()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ return GetString().getLength();
+}
+
+sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ // construct SwPosition (where GetCrsrOfst() will put the result into)
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+ SwIndex aIndex( pNode, 0);
+ SwPosition aPos( *pNode, aIndex );
+
+ // construct Point (translate into layout coordinates)
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
+ Point aPoint( rPoint.X, rPoint.Y );
+ SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root
+ Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() );
+ aPoint.X() += aPixPos.X();
+ aPoint.Y() += aPixPos.Y();
+ MapMode aMapMode = pWin->GetMapMode();
+ Point aCorePoint( GetMap()->PixelToCore( aPoint ) );
+ if( !aLogBounds.IsInside( aCorePoint ) )
+ {
+ /* #i12332# rPoint is may also be in rectangle returned by
+ getCharacterBounds(getCharacterCount() */
+
+ awt::Rectangle aRectEndPos =
+ getCharacterBounds(getCharacterCount());
+
+ if (rPoint.X - aRectEndPos.X >= 0 &&
+ rPoint.X - aRectEndPos.X < aRectEndPos.Width &&
+ rPoint.Y - aRectEndPos.Y >= 0 &&
+ rPoint.Y - aRectEndPos.Y < aRectEndPos.Height)
+ return getCharacterCount();
+
+ return -1;
+ }
+
+ // ask core for position
+ DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" );
+ DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
+ const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ SwCrsrMoveState aMoveState;
+ aMoveState.bPosMatchesBounds = TRUE;
+ sal_Bool bSuccess = pFrm->GetCrsrOfst( &aPos, aCorePoint, &aMoveState );
+
+ SwIndex aCntntIdx = aPos.nContent;
+ const xub_StrLen nIndex = aCntntIdx.GetIndex();
+ if ( nIndex > 0 )
+ {
+ SwRect aResultRect;
+ pFrm->GetCharRect( aResultRect, aPos );
+ bool bVert = pFrm->IsVertical();
+ bool bR2L = pFrm->IsRightToLeft();
+
+ if ( (!bVert && aResultRect.Pos().X() > aCorePoint.X()) ||
+ ( bVert && aResultRect.Pos().Y() > aCorePoint.Y()) ||
+ ( bR2L && aResultRect.Right() < aCorePoint.X()) )
+ {
+ SwIndex aIdxPrev( pNode, nIndex - 1);
+ SwPosition aPosPrev( *pNode, aIdxPrev );
+ SwRect aResultRectPrev;
+ pFrm->GetCharRect( aResultRectPrev, aPosPrev );
+ if ( (!bVert && aResultRectPrev.Pos().X() < aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) ||
+ ( bVert && aResultRectPrev.Pos().Y() < aCorePoint.Y() && aResultRect.Pos().X() == aResultRectPrev.Pos().X()) ||
+ ( bR2L && aResultRectPrev.Right() > aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) )
+ aPos = aPosPrev;
+ }
+ }
+
+ return bSuccess ?
+ GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() )
+ : -1L;
+}
+
+::rtl::OUString SwAccessibleParagraph::getSelectedText()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ sal_Int32 nStart, nEnd;
+ sal_Bool bSelected = GetSelection( nStart, nEnd );
+ return bSelected
+ ? GetString().copy( nStart, nEnd - nStart )
+ : ::rtl::OUString();
+}
+
+sal_Int32 SwAccessibleParagraph::getSelectionStart()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ sal_Int32 nStart, nEnd;
+ GetSelection( nStart, nEnd );
+ return nStart;
+}
+
+sal_Int32 SwAccessibleParagraph::getSelectionEnd()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ sal_Int32 nStart, nEnd;
+ GetSelection( nStart, nEnd );
+ return nEnd;
+}
+
+sal_Bool SwAccessibleParagraph::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ // parameter checking
+ sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidRange( nStartIndex, nEndIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ sal_Bool bRet = sal_False;
+
+ // get cursor shell
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell != NULL )
+ {
+ // create pam for selection
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+ SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nStartIndex));
+ SwPosition aStartPos( *pNode, aIndex );
+ SwPaM aPaM( aStartPos );
+ aPaM.SetMark();
+ aPaM.GetPoint()->nContent =
+ GetPortionData().GetModelPosition(nEndIndex);
+
+ // set PaM at cursor shell
+ bRet = Select( aPaM );
+ }
+
+ return bRet;
+}
+
+::rtl::OUString SwAccessibleParagraph::getText()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ return GetString();
+}
+
+::rtl::OUString SwAccessibleParagraph::getTextRange(
+ sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ ::rtl::OUString sText( GetString() );
+
+ if ( IsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
+ {
+ OrderRange( nStartIndex, nEndIndex );
+ return sText.copy(nStartIndex, nEndIndex-nStartIndex );
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+}
+
+/*accessibility::*/TextSegment SwAccessibleParagraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ /*accessibility::*/TextSegment aResult;
+ aResult.SegmentStart = -1;
+ aResult.SegmentEnd = -1;
+
+ const ::rtl::OUString rText = GetString();
+ // implement the silly specification that first position after
+ // text must return an empty string, rather than throwing an
+ // IndexOutOfBoundsException, except for LINE, where the last
+ // line is returned
+ if( nIndex == rText.getLength() && AccessibleTextType::LINE != nTextType )
+ return aResult;
+
+ // with error checking
+ i18n::Boundary aBound;
+ sal_Bool bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
+
+ DBG_ASSERT( aBound.startPos >= 0, "illegal boundary" );
+ DBG_ASSERT( aBound.startPos <= aBound.endPos, "illegal boundary" );
+
+ // return word (if present)
+ if ( bWord )
+ {
+ aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
+ aResult.SegmentStart = aBound.startPos;
+ aResult.SegmentEnd = aBound.endPos;
+ }
+
+ return aResult;
+}
+
+/*accessibility::*/TextSegment SwAccessibleParagraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ const ::rtl::OUString rText = GetString();
+
+ /*accessibility::*/TextSegment aResult;
+ aResult.SegmentStart = -1;
+ aResult.SegmentEnd = -1;
+
+ // get starting pos
+ i18n::Boundary aBound;
+ if (nIndex == rText.getLength())
+ aBound.startPos = aBound.endPos = nIndex;
+ else
+ {
+ sal_Bool bTmp = GetTextBoundary( aBound, rText, nIndex, nTextType );
+
+ if ( ! bTmp )
+ aBound.startPos = aBound.endPos = nIndex;
+ }
+
+ // now skip to previous word
+ sal_Bool bWord = sal_False;
+ while( !bWord )
+ {
+ nIndex = min( nIndex, aBound.startPos ) - 1;
+ if( nIndex >= 0 )
+ bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
+ else
+ break; // exit if beginning of string is reached
+ }
+
+ if ( bWord )
+ {
+ aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
+ aResult.SegmentStart = aBound.startPos;
+ aResult.SegmentEnd = aBound.endPos;
+ };
+ return aResult;
+}
+
+/*accessibility::*/TextSegment SwAccessibleParagraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ /*accessibility::*/TextSegment aResult;
+ aResult.SegmentStart = -1;
+ aResult.SegmentEnd = -1;
+ const ::rtl::OUString rText = GetString();
+
+ // implement the silly specification that first position after
+ // text must return an empty string, rather than throwing an
+ // IndexOutOfBoundsException
+ if( nIndex == rText.getLength() )
+ return aResult;
+
+
+ // get first word, then skip to next word
+ i18n::Boundary aBound;
+ GetTextBoundary( aBound, rText, nIndex, nTextType );
+ sal_Bool bWord = sal_False;
+ while( !bWord )
+ {
+ nIndex = max( sal_Int32(nIndex+1), aBound.endPos );
+ if( nIndex < rText.getLength() )
+ bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
+ else
+ break; // exit if end of string is reached
+ }
+
+ if ( bWord )
+ {
+ aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
+ aResult.SegmentStart = aBound.startPos;
+ aResult.SegmentEnd = aBound.endPos;
+ }
+ return aResult;
+}
+
+sal_Bool SwAccessibleParagraph::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+ SolarMutexGuard aGuard;
+
+ // select and copy (through dispatch mechanism)
+ setSelection( nStartIndex, nEndIndex );
+ ExecuteAtViewShell( SID_COPY );
+ return sal_True;
+}
+
+
+//
+//===== XAccesibleEditableText ==========================================
+//
+
+sal_Bool SwAccessibleParagraph::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ CHECK_FOR_DEFUNC( XAccessibleEditableText );
+ SolarMutexGuard aGuard;
+
+ if( !IsEditableState() )
+ return sal_False;
+
+ // select and cut (through dispatch mechanism)
+ setSelection( nStartIndex, nEndIndex );
+ ExecuteAtViewShell( SID_CUT );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::pasteText( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ CHECK_FOR_DEFUNC( XAccessibleEditableText );
+ SolarMutexGuard aGuard;
+
+ if( !IsEditableState() )
+ return sal_False;
+
+ // select and paste (through dispatch mechanism)
+ setSelection( nIndex, nIndex );
+ ExecuteAtViewShell( SID_PASTE );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ return replaceText( nStartIndex, nEndIndex, ::rtl::OUString() );
+}
+
+sal_Bool SwAccessibleParagraph::insertText( const ::rtl::OUString& sText, sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ return replaceText( nIndex, nIndex, sText );
+}
+
+sal_Bool SwAccessibleParagraph::replaceText(
+ sal_Int32 nStartIndex, sal_Int32 nEndIndex,
+ const ::rtl::OUString& sReplacement )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleEditableText );
+
+ const ::rtl::OUString& rText = GetString();
+
+ if( IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
+ {
+ if( !IsEditableState() )
+ return sal_False;
+
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+
+ // translate positions
+ USHORT nStart, nEnd;
+ sal_Bool bSuccess = GetPortionData().GetEditableRange(
+ nStartIndex, nEndIndex, nStart, nEnd );
+
+ // edit only if the range is editable
+ if( bSuccess )
+ {
+ // create SwPosition for nStartIndex
+ SwIndex aIndex( pNode, nStart );
+ SwPosition aStartPos( *pNode, aIndex );
+
+ // create SwPosition for nEndIndex
+ SwPosition aEndPos( aStartPos );
+ aEndPos.nContent = nEnd;
+
+ // now create XTextRange as helper and set string
+ const uno::Reference<text::XTextRange> xRange(
+ SwXTextRange::CreateXTextRange(
+ *pNode->GetDoc(), aStartPos, &aEndPos));
+ xRange->setString(sReplacement);
+
+ // delete portion data
+ ClearPortionData();
+ }
+
+ return bSuccess;
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+}
+
+struct IndexCompare
+{
+ const PropertyValue* pValues;
+ IndexCompare( const PropertyValue* pVals ) : pValues(pVals) {}
+ bool operator() ( const sal_Int32& a, const sal_Int32& b ) const
+ {
+ return (pValues[a].Name < pValues[b].Name) ? true : false;
+ }
+};
+
+
+sal_Bool SwAccessibleParagraph::setAttributes(
+ sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex,
+ const uno::Sequence<PropertyValue>& rAttributeSet )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleEditableText );
+
+ const ::rtl::OUString& rText = GetString();
+
+ if( ! IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
+ throw lang::IndexOutOfBoundsException();
+
+ if( !IsEditableState() )
+ return sal_False;
+
+
+ // create a (dummy) text portion for the sole purpose of calling
+ // setPropertyValue on it
+ uno::Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nStartIndex,
+ nEndIndex );
+
+ // build sorted index array
+ sal_Int32 nLength = rAttributeSet.getLength();
+ const PropertyValue* pPairs = rAttributeSet.getConstArray();
+ sal_Int32* pIndices = new sal_Int32[nLength];
+ sal_Int32 i;
+ for( i = 0; i < nLength; i++ )
+ pIndices[i] = i;
+ sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
+
+ // create sorted sequences accoring to index array
+ uno::Sequence< ::rtl::OUString > aNames( nLength );
+ ::rtl::OUString* pNames = aNames.getArray();
+ uno::Sequence< uno::Any > aValues( nLength );
+ uno::Any* pValues = aValues.getArray();
+ for( i = 0; i < nLength; i++ )
+ {
+ const PropertyValue& rVal = pPairs[pIndices[i]];
+ pNames[i] = rVal.Name;
+ pValues[i] = rVal.Value;
+ }
+ delete[] pIndices;
+
+ // now set the values
+ sal_Bool bRet = sal_True;
+ try
+ {
+ xPortion->setPropertyValues( aNames, aValues );
+ }
+ catch( UnknownPropertyException e )
+ {
+ // error handling through return code!
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+sal_Bool SwAccessibleParagraph::setText( const ::rtl::OUString& sText )
+ throw (uno::RuntimeException)
+{
+ return replaceText(0, GetString().getLength(), sText);
+}
+
+//===== XAccessibleSelection ============================================
+
+void SwAccessibleParagraph::selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ aSelectionHelper.selectAccessibleChild(nChildIndex);
+}
+
+sal_Bool SwAccessibleParagraph::isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ return aSelectionHelper.isAccessibleChildSelected(nChildIndex);
+}
+
+void SwAccessibleParagraph::clearAccessibleSelection( )
+ throw ( uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ aSelectionHelper.clearAccessibleSelection();
+}
+
+void SwAccessibleParagraph::selectAllAccessibleChildren( )
+ throw ( uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ aSelectionHelper.selectAllAccessibleChildren();
+}
+
+sal_Int32 SwAccessibleParagraph::getSelectedAccessibleChildCount( )
+ throw ( uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ return aSelectionHelper.getSelectedAccessibleChildCount();
+}
+
+uno::Reference<XAccessible> SwAccessibleParagraph::getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
+}
+
+// --> OD 2004-11-16 #111714# - index has to be treated as global child index.
+void SwAccessibleParagraph::deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ aSelectionHelper.deselectAccessibleChild( nChildIndex );
+}
+
+//===== XAccessibleHypertext ============================================
+
+class SwHyperlinkIter_Impl
+{
+ const SwpHints *pHints;
+ xub_StrLen nStt;
+ xub_StrLen nEnd;
+ sal_uInt16 nPos;
+
+public:
+ SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm );
+ const SwTxtAttr *next();
+ sal_uInt16 getCurrHintPos() const { return nPos-1; }
+
+ xub_StrLen startIdx() const { return nStt; }
+ xub_StrLen endIdx() const { return nEnd; }
+};
+
+SwHyperlinkIter_Impl::SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ) :
+ pHints( pTxtFrm->GetTxtNode()->GetpSwpHints() ),
+ nStt( pTxtFrm->GetOfst() ),
+ nPos( 0 )
+{
+ const SwTxtFrm *pFollFrm = pTxtFrm->GetFollow();
+ nEnd = pFollFrm ? pFollFrm->GetOfst() : pTxtFrm->GetTxtNode()->Len();
+}
+
+const SwTxtAttr *SwHyperlinkIter_Impl::next()
+{
+ const SwTxtAttr *pAttr = 0;
+ if( pHints )
+ {
+ while( !pAttr && nPos < pHints->Count() )
+ {
+ const SwTxtAttr *pHt = (*pHints)[nPos];
+ if( RES_TXTATR_INETFMT == pHt->Which() )
+ {
+ xub_StrLen nHtStt = *pHt->GetStart();
+ xub_StrLen nHtEnd = *pHt->GetAnyEnd();
+ if( nHtEnd > nHtStt &&
+ ( (nHtStt >= nStt && nHtStt < nEnd) ||
+ (nHtEnd > nStt && nHtEnd <= nEnd) ) )
+ {
+ pAttr = pHt;
+ }
+ }
+ ++nPos;
+ }
+ }
+
+ return pAttr;
+};
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkCount()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleHypertext );
+
+ sal_Int32 nCount = 0;
+ // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
+// if( !IsEditableState() )
+ // <--
+ {
+ const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ SwHyperlinkIter_Impl aIter( pTxtFrm );
+ while( aIter.next() )
+ nCount++;
+ }
+
+ return nCount;
+}
+
+uno::Reference< XAccessibleHyperlink > SAL_CALL
+ SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleHypertext );
+
+ uno::Reference< XAccessibleHyperlink > xRet;
+
+ // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
+// if( !IsEditableState() )
+ // <--
+ {
+ const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ SwHyperlinkIter_Impl aHIter( pTxtFrm );
+ while( nLinkIndex-- )
+ aHIter.next();
+
+ const SwTxtAttr *pHt = aHIter.next();
+ if( pHt )
+ {
+ if( !pHyperTextData )
+ pHyperTextData = new SwAccessibleHyperTextData;
+ SwAccessibleHyperTextData::iterator aIter =
+ pHyperTextData ->find( pHt );
+ if( aIter != pHyperTextData->end() )
+ {
+ xRet = (*aIter).second;
+ }
+ if( !xRet.is() )
+ {
+ sal_Int32 nHStt= GetPortionData().GetAccessiblePosition(
+ max( aHIter.startIdx(), *pHt->GetStart() ) );
+ sal_Int32 nHEnd= GetPortionData().GetAccessiblePosition(
+ min( aHIter.endIdx(), *pHt->GetAnyEnd() ) );
+ xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(),
+ this, nHStt, nHEnd );
+ if( aIter != pHyperTextData->end() )
+ {
+ (*aIter).second = xRet;
+ }
+ else
+ {
+ SwAccessibleHyperTextData::value_type aEntry( pHt, xRet );
+ pHyperTextData->insert( aEntry );
+ }
+ }
+ }
+ }
+
+ if( !xRet.is() )
+ throw lang::IndexOutOfBoundsException();
+
+ return xRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleHypertext );
+
+ // parameter checking
+ sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidPosition( nCharIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ sal_Int32 nRet = -1;
+ // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
+// if( !IsEditableState() )
+ // <--
+ {
+ const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ SwHyperlinkIter_Impl aHIter( pTxtFrm );
+
+ xub_StrLen nIdx = GetPortionData().GetModelPosition( nCharIndex );
+ sal_Int32 nPos = 0;
+ const SwTxtAttr *pHt = aHIter.next();
+ while( pHt && !(nIdx >= *pHt->GetStart() && nIdx < *pHt->GetAnyEnd()) )
+ {
+ pHt = aHIter.next();
+ nPos++;
+ }
+
+ if( pHt )
+ nRet = nPos;
+
+ }
+
+ return nRet;
+}
+
+// --> OD 2008-05-26 #i71360#
+// --> OD 2010-02-22 #i108125# - adjustments for change tracking text markup
+sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType )
+ throw (lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
+ switch ( nTextMarkupType )
+ {
+ case text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ case text::TextMarkupType::TRACK_CHANGE_DELETION:
+ case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper(
+ GetPortionData(),
+ *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
+ }
+ break;
+ default:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
+ }
+ }
+
+ return pTextMarkupHelper->getTextMarkupCount( nTextMarkupType );
+}
+
+/*accessibility::*/TextSegment SAL_CALL
+ SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex,
+ sal_Int32 nTextMarkupType )
+ throw (lang::IndexOutOfBoundsException,
+ lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
+ switch ( nTextMarkupType )
+ {
+ case text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ case text::TextMarkupType::TRACK_CHANGE_DELETION:
+ case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper(
+ GetPortionData(),
+ *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
+ }
+ break;
+ default:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
+ }
+ }
+
+ return pTextMarkupHelper->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
+}
+
+uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL
+ SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex,
+ sal_Int32 nTextMarkupType )
+ throw (lang::IndexOutOfBoundsException,
+ lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ // parameter checking
+ const sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidPosition( nCharIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
+ switch ( nTextMarkupType )
+ {
+ case text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ case text::TextMarkupType::TRACK_CHANGE_DELETION:
+ case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper(
+ GetPortionData(),
+ *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
+ }
+ break;
+ default:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
+ }
+ }
+
+ return pTextMarkupHelper->getTextMarkupAtIndex( nCharIndex, nTextMarkupType );
+}
+// <--
+
+// --> OD 2008-05-29 #i89175#
+sal_Int32 SAL_CALL SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ // parameter checking
+ const sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidPosition( nIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ const sal_Int32 nLineNo = GetPortionData().GetLineNo( nIndex );
+ return nLineNo;
+}
+
+/*accessibility::*/TextSegment SAL_CALL
+ SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo )
+ throw (lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ // parameter checking
+ if ( nLineNo < 0 ||
+ nLineNo >= GetPortionData().GetLineCount() )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ i18n::Boundary aLineBound;
+ GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
+
+ /*accessibility::*/TextSegment aTextAtLine;
+ const ::rtl::OUString rText = GetString();
+ aTextAtLine.SegmentText = rText.copy( aLineBound.startPos,
+ aLineBound.endPos - aLineBound.startPos );
+ aTextAtLine.SegmentStart = aLineBound.startPos;
+ aTextAtLine.SegmentEnd = aLineBound.endPos;
+
+ return aTextAtLine;
+}
+
+/*accessibility::*/TextSegment SAL_CALL SwAccessibleParagraph::getTextAtLineWithCaret()
+ throw (uno::RuntimeException)
+{
+ const sal_Int32 nLineNoOfCaret = getNumberOfLineWithCaret();
+
+ if ( nLineNoOfCaret >= 0 &&
+ nLineNoOfCaret < GetPortionData().GetLineCount() )
+ {
+ return getTextAtLineNumber( nLineNoOfCaret );
+ }
+
+ return /*accessibility::*/TextSegment();
+}
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getNumberOfLineWithCaret()
+ throw (uno::RuntimeException)
+{
+ const sal_Int32 nCaretPos = getCaretPosition();
+ const sal_Int32 nLength = GetString().getLength();
+ if ( !IsValidPosition( nCaretPos, nLength ) )
+ {
+ return -1;
+ }
+
+ sal_Int32 nLineNo = GetPortionData().GetLineNo( nCaretPos );
+
+ // special handling for cursor positioned at end of text line via End key
+ if ( nCaretPos != 0 )
+ {
+ i18n::Boundary aLineBound;
+ GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
+ if ( nCaretPos == aLineBound.startPos )
+ {
+ SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
+ if ( pCrsrShell != 0 )
+ {
+ const awt::Rectangle aCharRect = getCharacterBounds( nCaretPos );
+
+ const SwRect& aCursorCoreRect = pCrsrShell->GetCharRect();
+ // translate core coordinates into accessibility coordinates
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
+
+ Rectangle aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect.SVRect() ));
+
+ SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
+ Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
+ aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
+
+ // convert into AWT Rectangle
+ const awt::Rectangle aCursorRect( aScreenRect.Left(),
+ aScreenRect.Top(),
+ aScreenRect.GetWidth(),
+ aScreenRect.GetHeight() );
+
+ if ( aCharRect.X != aCursorRect.X ||
+ aCharRect.Y != aCursorRect.Y )
+ {
+ --nLineNo;
+ }
+ }
+ }
+ }
+
+ return nLineNo;
+}
+
+// --> OD 2010-02-19 #i108125#
+void SwAccessibleParagraph::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
+{
+ mpParaChangeTrackInfo->reset();
+
+ SwClient::Modify( pOld, pNew );
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpara.hxx b/sw/source/core/access/accpara.hxx
new file mode 100644
index 000000000000..9b1038acc26f
--- /dev/null
+++ b/sw/source/core/access/accpara.hxx
@@ -0,0 +1,451 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCPARA_HXX
+#define _ACCPARA_HXX
+
+#include <acccontext.hxx>
+#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
+#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
+#include <hash_map>
+#include <accselectionhelper.hxx>
+// --> OD 2010-02-19 #i108125#
+#include <calbck.hxx>
+// <--
+
+class SwTxtFrm;
+class SwTxtNode;
+class SwPaM;
+class SwAccessiblePortionData;
+class SwAccessibleHyperTextData;
+class SwXTextPortion;
+// --> OD 2010-02-19 #i108125#
+class SwParaChangeTrackingInfo;
+// <--
+
+namespace rtl { class OUString; }
+namespace com { namespace sun { namespace star {
+ namespace i18n { struct Boundary; }
+ namespace accessibility { class XAccessibleHyperlink; }
+} } }
+
+typedef ::std::hash_map< ::rtl::OUString,
+ ::com::sun::star::beans::PropertyValue,
+ ::rtl::OUStringHash,
+ ::std::equal_to< ::rtl::OUString > > tAccParaPropValMap;
+
+class SwAccessibleParagraph :
+ // --> OD 2010-02-19 #i108125#
+ public SwClient,
+ // <--
+ public SwAccessibleContext,
+ public ::com::sun::star::accessibility::XAccessibleEditableText,
+ public com::sun::star::accessibility::XAccessibleSelection,
+ public com::sun::star::accessibility::XAccessibleHypertext,
+ public com::sun::star::accessibility::XAccessibleTextMarkup,
+ public com::sun::star::accessibility::XAccessibleMultiLineText,
+ public ::com::sun::star::accessibility::XAccessibleTextAttributes
+{
+ friend class SwAccessibleHyperlink;
+
+ ::rtl::OUString sDesc; // protected by base classes mutex
+
+ /// data for this paragraph's text portions; this contains the
+ /// mapping from the core 'model string' to the accessible text
+ /// string.
+ /// pPortionData may be NULL; it should only be accessed through the
+ /// Get/Clear/Has/UpdatePortionData() methods
+ SwAccessiblePortionData* pPortionData;
+ SwAccessibleHyperTextData *pHyperTextData;
+
+ sal_Int32 nOldCaretPos; // The 'old' caret pos. It's only valid as long
+ // as the cursor is inside this object (protected by
+ // mutex)
+
+ sal_Bool bIsHeading; // protected by base classes mutex
+
+ // implementation for XAccessibleSelection
+ SwAccessibleSelectionHelper aSelectionHelper;
+
+ // --> OD 2010-02-19 #i108125#
+ SwParaChangeTrackingInfo* mpParaChangeTrackInfo;
+ // <--
+
+ /// get the SwTxtNode (requires frame; check before)
+ const SwTxtNode* GetTxtNode() const;
+
+ /// get the (accessible) text string (requires frame; check before)
+ ::rtl::OUString GetString();
+
+ ::rtl::OUString GetDescription();
+
+ // get the current care position
+ sal_Int32 GetCaretPos();
+
+ /// determine the current selection. Fill the values with
+ /// -1 if there is no selection in the this paragraph
+ sal_Bool GetSelection(sal_Int32& nStart, sal_Int32& nEnd);
+
+ // helper for GetSelection and getCaretPosition
+ // --> OD 2005-12-20 #i27301#
+ // - add parameter <_bForSelection>, which indicates, if the cursor is
+ // retrieved for selection or for caret position.
+ SwPaM* GetCursor( const bool _bForSelection );
+
+ /// for cut/copy/paste: execute a particular slot at the view shell
+ void ExecuteAtViewShell( UINT16 nSlot );
+
+ /// helper method for get/setAttributes
+ /// (for the special case of (nEndIndex==-1) a single character will
+ /// be selected)
+ SwXTextPortion* CreateUnoPortion( sal_Int32 nStart, sal_Int32 nEnd );
+
+
+ // methods for checking the parameter range:
+
+ /// does nPos point to a char?
+ sal_Bool IsValidChar(sal_Int32 nPos, sal_Int32 nLength);
+
+ /// does nPos point to a position? (may be behind the last character)
+ sal_Bool IsValidPosition(sal_Int32 nPos, sal_Int32 nLength);
+
+ /// is nBegin...nEnd a valid range? (nEnd points past the last character)
+ sal_Bool IsValidRange(sal_Int32 nBegin, sal_Int32 nEnd, sal_Int32 nLength);
+
+ /// Ensure ordered range (i.e. nBegin is smaller then nEnd)
+ inline void OrderRange(sal_Int32& nBegin, sal_Int32& nEnd)
+ {
+ if( nBegin > nEnd )
+ {
+ sal_Int32 nTmp = nBegin; nBegin = nEnd; nEnd = nTmp;
+ }
+ }
+
+ // --> OD 2006-07-13 #i63870#
+ void _getDefaultAttributesImpl(
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
+ tAccParaPropValMap& rDefAttrSeq,
+ const bool bOnlyCharAttrs = false );
+ void _getRunAttributesImpl(
+ const sal_Int32 nIndex,
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
+ tAccParaPropValMap& rRunAttrSeq );
+ // <--
+
+public:
+
+ sal_Bool IsHeading() const;
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additinaly sets MULTILINE(1), MULTISELECTABLE(+),
+ // FOCUSABLE(+) and FOCUSED(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual void _InvalidateContent( sal_Bool bVisibleDataFired );
+
+ virtual void _InvalidateCursorPos();
+ virtual void _InvalidateFocus();
+
+ virtual ~SwAccessibleParagraph();
+
+ //===== handling of data for the text portions ===========================
+
+ /// force update of new portion data
+ void UpdatePortionData()
+ throw( com::sun::star::uno::RuntimeException );
+
+ /// remove the current portion data
+ void ClearPortionData();
+
+ /// get portion data; update if necesary
+ SwAccessiblePortionData& GetPortionData()
+ throw( com::sun::star::uno::RuntimeException )
+ {
+ if( pPortionData == NULL )
+ UpdatePortionData();
+ return *pPortionData;
+ }
+
+ /// determine if portion data is currently available
+ sal_Bool HasPortionData() { return (pPortionData != NULL); }
+
+
+ //===== helpers for word boundaries ====================================
+
+ sal_Bool GetCharBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetWordBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetSentenceBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetLineBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetParagraphBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetAttributeBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetGlyphBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+
+ /// get boundaries of word/sentence/etc. for specified text type
+ /// Does all argument checking, and then delegates to helper methods above.
+ sal_Bool GetTextBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos,
+ sal_Int16 aTextType )
+ throw (
+ ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+public:
+
+ SwAccessibleParagraph( SwAccessibleMap& rInitMap,
+ const SwTxtFrm& rTxtFrm );
+
+ inline operator ::com::sun::star::accessibility::XAccessibleText *();
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+
+ // --> OD 2010-02-19 #i108125#
+ virtual void Modify( SfxPoolItem* pOld, SfxPoolItem* pNew);
+ // <--
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ /** Return the parents locale or throw exception if this object has no
+ parent yet/anymore.
+ */
+ virtual ::com::sun::star::lang::Locale SAL_CALL
+ getLocale (void)
+ throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
+
+ /** paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO
+
+ OD 2005-12-02 #i27138#
+
+ @author OD
+ */
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleRelationSet> SAL_CALL
+ getAccessibleRelationSet (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleComponent ============================================
+
+ virtual void SAL_CALL grabFocus()
+ throw (::com::sun::star::uno::RuntimeException);
+ // --> OD 2007-01-17 #i71385#
+ virtual sal_Int32 SAL_CALL getForeground()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getBackground()
+ throw (::com::sun::star::uno::RuntimeException);
+ // <--
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+
+ //===== XInterface ======================================================
+
+ // (XInterface methods need to be implemented to disambiguate
+ // between those inherited through SwAcessibleContext and
+ // XAccessibleEditableText).
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccesibleText ==================================================
+ virtual sal_Int32 SAL_CALL getCaretPosition( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL setCaretPosition( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Unicode SAL_CALL getCharacter( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getCharacterBounds( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getCharacterCount( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getIndexAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getSelectedText( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getSelectionStart( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getSelectionEnd( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getText( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+
+ //===== XAccesibleEditableText ==========================================
+ virtual sal_Bool SAL_CALL cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL pasteText( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL insertText( const ::rtl::OUString& sText, sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::rtl::OUString& sReplacement ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aAttributeSet ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL setText( const ::rtl::OUString& sText ) throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleSelection ============================================
+ virtual void SAL_CALL selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Bool SAL_CALL isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL clearAccessibleSelection( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL selectAllAccessibleChildren( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // --> OD 2004-11-16 #111714# - index has to be treated as global child index.
+ virtual void SAL_CALL deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ //===== XAccessibleHypertext ============================================
+ virtual sal_Int32 SAL_CALL getHyperLinkCount()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleHyperlink >
+ SAL_CALL getHyperLink( sal_Int32 nLinkIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getHyperLinkIndex( sal_Int32 nCharIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // --> OD 2008-05-19 #i71360#
+ //===== XAccesibleTextMarkup ============================================
+ virtual sal_Int32 SAL_CALL getTextMarkupCount( sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL
+ getTextMarkup( sal_Int32 nTextMarkupIndex,
+ sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::accessibility::TextSegment > SAL_CALL
+ getTextMarkupAtIndex( sal_Int32 nCharIndex,
+ sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ // <--
+
+ // --> OD 2008-05-29 #i89175#
+ //===== XAccessibleMultiLineText ========================================
+ virtual sal_Int32 SAL_CALL getLineNumberAtIndex( sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL
+ getTextAtLineNumber( sal_Int32 nLineNo )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL
+ getTextAtLineWithCaret()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual sal_Int32 SAL_CALL getNumberOfLineWithCaret()
+ throw (::com::sun::star::uno::RuntimeException);
+ // <--
+
+ // --> OD 2006-07-11 #i63870#
+ //===== XAccesibleTextAttributes ========================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getDefaultAttributes( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getRunAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ // <--
+};
+
+inline SwAccessibleParagraph::operator ::com::sun::star::accessibility::XAccessibleText *()
+{
+ return static_cast<
+ ::com::sun::star::accessibility::XAccessibleEditableText * >( this );
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accportions.cxx b/sw/source/core/access/accportions.cxx
new file mode 100644
index 000000000000..bf1d21407296
--- /dev/null
+++ b/sw/source/core/access/accportions.cxx
@@ -0,0 +1,754 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "accportions.hxx"
+#include <tools/debug.hxx>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/i18n/Boundary.hpp>
+#include <txttypes.hxx>
+
+// for portion replacement in Special()
+#include "access.hrc"
+#include <tools/resid.hxx>
+#include "viewopt.hxx"
+
+// for GetWordBoundary(...), GetSentenceBoundary(...):
+#include <breakit.hxx>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <ndtxt.hxx>
+
+// for FillSpecialPos(...)
+#include "crstate.hxx"
+
+// for SwAccessibleContext::GetResource()
+#include "acccontext.hxx"
+
+// for Post-It replacement text:
+#include "txatbase.hxx"
+#include "fmtfld.hxx"
+#include "fldbas.hxx"
+#include "docufld.hxx"
+
+// for in-line graphics replacement:
+#include "ndindex.hxx"
+#include "ndnotxt.hxx"
+#include "fmtflcnt.hxx"
+#include "frmfmt.hxx"
+#include "fmtcntnt.hxx"
+
+
+using namespace ::com::sun::star;
+
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using i18n::Boundary;
+
+
+// 'portion type' for terminating portions
+#define POR_TERMINATE 0
+
+
+// portion attributes
+#define PORATTR_SPECIAL 1
+#define PORATTR_READONLY 2
+#define PORATTR_GRAY 4
+#define PORATTR_TERM 128
+
+SwAccessiblePortionData::SwAccessiblePortionData(
+ const SwTxtNode* pTxtNd,
+ const SwViewOption* pViewOpt ) :
+ SwPortionHandler(),
+ pTxtNode( pTxtNd ),
+ aBuffer(),
+ nModelPosition( 0 ),
+ bFinished( sal_False ),
+ pViewOptions( pViewOpt ),
+ sAccessibleString(),
+ aLineBreaks(),
+ aModelPositions(),
+ aAccessiblePositions(),
+ pSentences( 0 ),
+ nBeforePortions( 0 ),
+ bLastIsSpecial( sal_False )
+{
+ DBG_ASSERT( pTxtNode != NULL, "Text node is needed!" );
+
+ // reserve some space to reduce memory allocations
+ aLineBreaks.reserve( 5 );
+ aModelPositions.reserve( 10 );
+ aAccessiblePositions.reserve( 10 );
+
+ // always include 'first' line-break position
+ aLineBreaks.push_back( 0 );
+}
+
+SwAccessiblePortionData::~SwAccessiblePortionData()
+{
+ delete pSentences;
+}
+
+void SwAccessiblePortionData::Text(USHORT nLength, USHORT nType)
+{
+ DBG_ASSERT( (nModelPosition + nLength) <= pTxtNode->GetTxt().Len(),
+ "portion exceeds model string!" );
+
+ DBG_ASSERT( !bFinished, "We are already done!" );
+
+ // ignore zero-length portions
+ if( nLength == 0 )
+ return;
+
+ // store 'old' positions
+ aModelPositions.push_back( nModelPosition );
+ aAccessiblePositions.push_back( aBuffer.getLength() );
+
+ // store portion attributes
+ sal_uInt8 nAttr = IsGrayPortionType(nType) ? PORATTR_GRAY : 0;
+ aPortionAttrs.push_back( nAttr );
+
+ // update buffer + nModelPosition
+ aBuffer.append( OUString(
+ pTxtNode->GetTxt().Copy(
+ static_cast<USHORT>( nModelPosition ),
+ nLength ) ) );
+ nModelPosition += nLength;
+
+ bLastIsSpecial = sal_False;
+}
+
+void SwAccessiblePortionData::Special(
+ USHORT nLength, const String& rText, USHORT nType)
+{
+ DBG_ASSERT( nModelPosition >= 0, "illegal position" );
+ DBG_ASSERT( (nModelPosition + nLength) <= pTxtNode->GetTxt().Len(),
+ "portion exceeds model string!" );
+
+ DBG_ASSERT( !bFinished, "We are already done!" );
+
+ // construct string with representation; either directly from
+ // rText, or use resources for special case portions
+ String sDisplay;
+ switch( nType )
+ {
+ case POR_POSTITS:
+ case POR_FLYCNT:
+ case POR_GRFNUM:
+ sDisplay = String(sal_Unicode(0xfffc));
+
+ break;
+ case POR_NUMBER:
+ {
+ OUStringBuffer aTmpBuffer( rText.Len() + 1 );
+ aTmpBuffer.append( rText );
+ aTmpBuffer.append( sal_Unicode(' ') );
+ sDisplay = aTmpBuffer.makeStringAndClear();
+ break;
+ }
+ // --> OD 2010-06-04 #i111768# - apply patch from kstribley:
+ // Include the control characters.
+ case POR_CONTROLCHAR:
+ {
+ OUStringBuffer aTmpBuffer( rText.Len() + 1 );
+ aTmpBuffer.append( rText );
+ aTmpBuffer.append( pTxtNode->GetTxt().GetChar(nModelPosition) );
+ sDisplay = aTmpBuffer.makeStringAndClear();
+ break;
+ }
+ // <--
+ default:
+ sDisplay = rText;
+ break;
+ }
+
+ // ignore zero/zero portions (except for terminators)
+ if( (nLength == 0) && (sDisplay.Len() == 0) && (nType != POR_TERMINATE) )
+ return;
+
+ // special treatment for zero length portion at the beginning:
+ // count as 'before' portion
+ if( ( nLength == 0 ) && ( nModelPosition == 0 ) )
+ nBeforePortions++;
+
+ // store the 'old' positions
+ aModelPositions.push_back( nModelPosition );
+ aAccessiblePositions.push_back( aBuffer.getLength() );
+
+ // store portion attributes
+ sal_uInt8 nAttr = PORATTR_SPECIAL;
+ if( IsGrayPortionType(nType) ) nAttr |= PORATTR_GRAY;
+ if( nLength == 0 ) nAttr |= PORATTR_READONLY;
+ if( nType == POR_TERMINATE ) nAttr |= PORATTR_TERM;
+ aPortionAttrs.push_back( nAttr );
+
+ // update buffer + nModelPosition
+ aBuffer.append( OUString(sDisplay) );
+ nModelPosition += nLength;
+
+ // remember 'last' special portion (unless it's our own 'closing'
+ // portions from 'Finish()'
+ if( nType != POR_TERMINATE )
+ bLastIsSpecial = sal_True;
+}
+
+void SwAccessiblePortionData::LineBreak()
+{
+ DBG_ASSERT( !bFinished, "We are already done!" );
+
+ aLineBreaks.push_back( aBuffer.getLength() );
+}
+
+void SwAccessiblePortionData::Skip(USHORT nLength)
+{
+ DBG_ASSERT( !bFinished, "We are already done!" );
+ DBG_ASSERT( aModelPositions.size() == 0, "Never Skip() after portions" );
+ DBG_ASSERT( nLength <= pTxtNode->GetTxt().Len(), "skip exceeds model string!" );
+
+ nModelPosition += nLength;
+}
+
+void SwAccessiblePortionData::Finish()
+{
+ DBG_ASSERT( !bFinished, "We are already done!" );
+
+ // include terminator values: always include two 'last character'
+ // markers in the position arrays to make sure we always find one
+ // position before the end
+ Special( 0, String(), POR_TERMINATE );
+ Special( 0, String(), POR_TERMINATE );
+ LineBreak();
+ LineBreak();
+
+ sAccessibleString = aBuffer.makeStringAndClear();
+ bFinished = sal_True;
+}
+
+
+sal_Bool SwAccessiblePortionData::IsPortionAttrSet(
+ size_t nPortionNo, sal_uInt8 nAttr ) const
+{
+ DBG_ASSERT( nPortionNo < aPortionAttrs.size(),
+ "Illegal portion number" );
+ return (aPortionAttrs[nPortionNo] & nAttr) != 0;
+}
+
+sal_Bool SwAccessiblePortionData::IsSpecialPortion( size_t nPortionNo ) const
+{
+ return IsPortionAttrSet(nPortionNo, PORATTR_SPECIAL);
+}
+
+sal_Bool SwAccessiblePortionData::IsReadOnlyPortion( size_t nPortionNo ) const
+{
+ return IsPortionAttrSet(nPortionNo, PORATTR_READONLY);
+}
+
+sal_Bool SwAccessiblePortionData::IsGrayPortionType( USHORT nType ) const
+{
+ // gray portions?
+ // Compare with: inftxt.cxx, SwTxtPaintInfo::DrawViewOpt(...)
+ sal_Bool bGray = sal_False;
+ switch( nType )
+ {
+ case POR_FTN:
+ case POR_ISOREF:
+ case POR_REF:
+ case POR_QUOVADIS:
+ case POR_NUMBER:
+ case POR_FLD:
+ case POR_URL:
+ case POR_ISOTOX:
+ case POR_TOX:
+ case POR_HIDDEN:
+ bGray = !pViewOptions->IsPagePreview() &&
+ !pViewOptions->IsReadonly() && SwViewOption::IsFieldShadings();
+ break;
+ case POR_TAB: bGray = pViewOptions->IsTab(); break;
+ case POR_SOFTHYPH: bGray = pViewOptions->IsSoftHyph(); break;
+ case POR_BLANK: bGray = pViewOptions->IsHardBlank(); break;
+ default:
+ break; // bGray is false
+ }
+ return bGray;
+}
+
+
+const OUString& SwAccessiblePortionData::GetAccessibleString() const
+{
+ DBG_ASSERT( bFinished, "Shouldn't call this before we are done!" );
+
+ return sAccessibleString;
+}
+
+
+void SwAccessiblePortionData::GetLineBoundary(
+ Boundary& rBound,
+ sal_Int32 nPos ) const
+{
+ FillBoundary( rBound, aLineBreaks,
+ FindBreak( aLineBreaks, nPos ) );
+}
+
+// --> OD 2008-05-30 #i89175#
+sal_Int32 SwAccessiblePortionData::GetLineCount() const
+{
+ size_t nBreaks = aLineBreaks.size();
+ // A non-empty paragraph has at least 4 breaks: one for each line3 and
+ // 3 additional ones.
+ // An empty paragraph has 3 breaks.
+ // Less than 3 breaks is an error case.
+ sal_Int32 nLineCount = ( nBreaks > 3 )
+ ? nBreaks - 3
+ : ( ( nBreaks == 3 ) ? 1 : 0 );
+ return nLineCount;
+}
+
+sal_Int32 SwAccessiblePortionData::GetLineNo( const sal_Int32 nPos ) const
+{
+ sal_Int32 nLineNo = FindBreak( aLineBreaks, nPos );
+
+ // handling of position after last character
+ const sal_Int32 nLineCount( GetLineCount() );
+ if ( nLineNo >= nLineCount )
+ {
+ nLineNo = nLineCount - 1;
+ }
+
+ return nLineNo;
+}
+
+void SwAccessiblePortionData::GetBoundaryOfLine( const sal_Int32 nLineNo,
+ i18n::Boundary& rLineBound )
+{
+ FillBoundary( rLineBound, aLineBreaks, nLineNo );
+}
+// <--
+
+void SwAccessiblePortionData::GetLastLineBoundary(
+ Boundary& rBound ) const
+{
+ DBG_ASSERT( aLineBreaks.size() >= 2, "need min + max value" );
+
+ // The last two positions except the two deleimiters are the ones
+ // we are looking for, except for empty paragraphs (nBreaks==3)
+ size_t nBreaks = aLineBreaks.size();
+ FillBoundary( rBound, aLineBreaks, nBreaks <= 3 ? 0 : nBreaks-4 );
+}
+
+USHORT SwAccessiblePortionData::GetModelPosition( sal_Int32 nPos ) const
+{
+ DBG_ASSERT( nPos >= 0, "illegal position" );
+ DBG_ASSERT( nPos <= sAccessibleString.getLength(), "illegal position" );
+
+ // find the portion number
+ size_t nPortionNo = FindBreak( aAccessiblePositions, nPos );
+
+ // get model portion size
+ sal_Int32 nStartPos = aModelPositions[nPortionNo];
+
+ // if it's a non-special portion, move into the portion, else
+ // return the portion start
+ if( ! IsSpecialPortion( nPortionNo ) )
+ {
+ // 'wide' portions have to be of the same width
+ DBG_ASSERT( ( aModelPositions[nPortionNo+1] - nStartPos ) ==
+ ( aAccessiblePositions[nPortionNo+1] -
+ aAccessiblePositions[nPortionNo] ),
+ "accesability portion disagrees with text model" );
+
+ sal_Int32 nWithinPortion = nPos - aAccessiblePositions[nPortionNo];
+ nStartPos += nWithinPortion;
+ }
+ // else: return nStartPos unmodified
+
+ DBG_ASSERT( (nStartPos >= 0) && (nStartPos < USHRT_MAX),
+ "How can the SwTxtNode have so many characters?" );
+ return static_cast<USHORT>(nStartPos);
+}
+
+void SwAccessiblePortionData::FillBoundary(
+ Boundary& rBound,
+ const Positions_t& rPositions,
+ size_t nPos ) const
+{
+ rBound.startPos = rPositions[nPos];
+ rBound.endPos = rPositions[nPos+1];
+}
+
+
+size_t SwAccessiblePortionData::FindBreak(
+ const Positions_t& rPositions,
+ sal_Int32 nValue ) const
+{
+ DBG_ASSERT( rPositions.size() >= 2, "need min + max value" );
+ DBG_ASSERT( rPositions[0] <= nValue, "need min value" );
+ DBG_ASSERT( rPositions[rPositions.size()-1] >= nValue,
+ "need first terminator value" );
+ DBG_ASSERT( rPositions[rPositions.size()-2] >= nValue,
+ "need second terminator value" );
+
+ size_t nMin = 0;
+ size_t nMax = rPositions.size()-2;
+
+ // loop until no more than two candidates are left
+ while( nMin+1 < nMax )
+ {
+ // check loop invariants
+ DBG_ASSERT( ( (nMin == 0) && (rPositions[nMin] <= nValue) ) ||
+ ( (nMin != 0) && (rPositions[nMin] < nValue) ),
+ "minvalue not minimal" );
+ DBG_ASSERT( nValue <= rPositions[nMax], "max value not maximal" );
+
+ // get middle (and ensure progress)
+ size_t nMiddle = (nMin + nMax)/2;
+ DBG_ASSERT( nMin < nMiddle, "progress?" );
+ DBG_ASSERT( nMiddle < nMax, "progress?" );
+
+ // check array
+ DBG_ASSERT( rPositions[nMin] <= rPositions[nMiddle],
+ "garbled positions array" );
+ DBG_ASSERT( rPositions[nMiddle] <= rPositions[nMax],
+ "garbled positions array" );
+
+ if( nValue > rPositions[nMiddle] )
+ nMin = nMiddle;
+ else
+ nMax = nMiddle;
+ }
+
+ // only two are left; we only need to check which one is the winner
+ DBG_ASSERT( (nMax == nMin) || (nMax == nMin+1), "only two left" );
+ if( (rPositions[nMin] < nValue) && (rPositions[nMin+1] <= nValue) )
+ nMin = nMin+1;
+
+ // finally, check to see whether the returned value is the 'right' position
+ DBG_ASSERT( rPositions[nMin] <= nValue, "not smaller or equal" );
+ DBG_ASSERT( nValue <= rPositions[nMin+1], "not equal or larger" );
+ DBG_ASSERT( (nMin == 0) || (rPositions[nMin-1] <= nValue),
+ "earlier value should have been returned" );
+
+ DBG_ASSERT( nMin < rPositions.size()-1,
+ "shouldn't return last position (due to termintator values)" );
+
+ return nMin;
+}
+
+size_t SwAccessiblePortionData::FindLastBreak(
+ const Positions_t& rPositions,
+ sal_Int32 nValue ) const
+{
+ size_t nResult = FindBreak( rPositions, nValue );
+
+ // skip 'zero-length' portions
+ // --> OD 2006-10-19 #i70538#
+ // consider size of <rPosition> and ignore last entry
+// while( rPositions[nResult+1] <= nValue )
+ while ( nResult < rPositions.size() - 2 &&
+ rPositions[nResult+1] <= nValue )
+ {
+ nResult++;
+ }
+ // <--
+
+ return nResult;
+}
+
+
+void SwAccessiblePortionData::GetSentenceBoundary(
+ Boundary& rBound,
+ sal_Int32 nPos )
+{
+ DBG_ASSERT( nPos >= 0, "illegal position; check before" );
+ DBG_ASSERT( nPos < sAccessibleString.getLength(), "illegal position" );
+
+ if( pSentences == NULL )
+ {
+ DBG_ASSERT( pBreakIt != NULL, "We always need a break." );
+ DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." );
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ pSentences = new Positions_t();
+ pSentences->reserve(10);
+
+ // use xBreak->endOfSentence to iterate over all words; store
+ // positions in pSentences
+ sal_Int32 nCurrent = 0;
+ sal_Int32 nLength = sAccessibleString.getLength();
+ do
+ {
+ pSentences->push_back( nCurrent );
+
+ USHORT nModelPos = GetModelPosition( nCurrent );
+
+ sal_Int32 nNew = pBreakIt->GetBreakIter()->endOfSentence(
+ sAccessibleString, nCurrent,
+ pBreakIt->GetLocale(pTxtNode->GetLang(nModelPos)) ) + 1;
+
+ if( (nNew < 0) && (nNew > nLength) )
+ nNew = nLength;
+ else if (nNew <= nCurrent)
+ nNew = nCurrent + 1; // ensure forward progress
+
+ nCurrent = nNew;
+ }
+ while (nCurrent < nLength);
+
+ // finish with two terminators
+ pSentences->push_back( nLength );
+ pSentences->push_back( nLength );
+ }
+ else
+ {
+ // no break iterator -> empty word
+ rBound.startPos = 0;
+ rBound.endPos = 0;
+ return;
+ }
+ }
+
+ FillBoundary( rBound, *pSentences, FindBreak( *pSentences, nPos ) );
+}
+
+void SwAccessiblePortionData::GetAttributeBoundary(
+ Boundary& rBound,
+ sal_Int32 nPos) const
+{
+ DBG_ASSERT( pTxtNode != NULL, "Need SwTxtNode!" );
+
+ // attribute boundaries can only occur on portion boundaries
+ FillBoundary( rBound, aAccessiblePositions,
+ FindBreak( aAccessiblePositions, nPos ) );
+}
+
+
+sal_Int32 SwAccessiblePortionData::GetAccessiblePosition( USHORT nPos ) const
+{
+ DBG_ASSERT( nPos <= pTxtNode->GetTxt().Len(), "illegal position" );
+
+ // find the portion number
+ // --> OD 2006-10-19 #i70538#
+ // consider "empty" model portions - e.g. number portion
+ size_t nPortionNo = FindLastBreak( aModelPositions,
+ static_cast<sal_Int32>(nPos) );
+ // <--
+
+ sal_Int32 nRet = aAccessiblePositions[nPortionNo];
+
+ // if the model portion has more than one position, go into it;
+ // else return that position
+ sal_Int32 nStartPos = aModelPositions[nPortionNo];
+ sal_Int32 nEndPos = aModelPositions[nPortionNo+1];
+ if( (nEndPos - nStartPos) > 1 )
+ {
+ // 'wide' portions have to be of the same width
+ DBG_ASSERT( ( nEndPos - nStartPos ) ==
+ ( aAccessiblePositions[nPortionNo+1] -
+ aAccessiblePositions[nPortionNo] ),
+ "accesability portion disagrees with text model" );
+
+ sal_Int32 nWithinPortion = nPos - aModelPositions[nPortionNo];
+ nRet += nWithinPortion;
+ }
+ // else: return nRet unmodified
+
+ DBG_ASSERT( (nRet >= 0) && (nRet <= sAccessibleString.getLength()),
+ "too long!" );
+ return nRet;
+}
+
+USHORT SwAccessiblePortionData::FillSpecialPos(
+ sal_Int32 nPos,
+ SwSpecialPos& rPos,
+ SwSpecialPos*& rpPos ) const
+{
+ size_t nPortionNo = FindLastBreak( aAccessiblePositions, nPos );
+
+ BYTE nExtend(SP_EXTEND_RANGE_NONE);
+ sal_Int32 nRefPos(0);
+ sal_Int32 nModelPos(0);
+
+ if( nPortionNo < nBeforePortions )
+ {
+ nExtend = SP_EXTEND_RANGE_BEFORE;
+ rpPos = &rPos;
+ }
+ else
+ {
+ sal_Int32 nModelEndPos = aModelPositions[nPortionNo+1];
+ nModelPos = aModelPositions[nPortionNo];
+
+ // skip backwards over zero-length portions, since GetCharRect()
+ // counts all model-zero-length portions as belonging to the
+ // previus portion
+ size_t nCorePortionNo = nPortionNo;
+ while( nModelPos == nModelEndPos )
+ {
+ nCorePortionNo--;
+ nModelEndPos = nModelPos;
+ nModelPos = aModelPositions[nCorePortionNo];
+
+ DBG_ASSERT( nModelPos >= 0, "Can't happen." );
+ DBG_ASSERT( nCorePortionNo >= nBeforePortions, "Can't happen." );
+ }
+ DBG_ASSERT( nModelPos != nModelEndPos,
+ "portion with core-representation expected" );
+
+ // if we have anything except plain text, compute nExtend + nRefPos
+ if( (nModelEndPos - nModelPos == 1) &&
+ (pTxtNode->GetTxt().GetChar(static_cast<USHORT>(nModelPos)) !=
+ sAccessibleString.getStr()[nPos]) )
+ {
+ // case 1: a one-character, non-text portion
+ // reference position is the first accessibilty for our
+ // core portion
+ nRefPos = aAccessiblePositions[ nCorePortionNo ];
+ nExtend = SP_EXTEND_RANGE_NONE;
+ rpPos = &rPos;
+ }
+ else if(nPortionNo != nCorePortionNo)
+ {
+ // case 2: a multi-character (text!) portion, followed by
+ // zero-length portions
+ // reference position is the first character of the next
+ // portion, and we are 'behind'
+ nRefPos = aAccessiblePositions[ nCorePortionNo+1 ];
+ nExtend = SP_EXTEND_RANGE_BEHIND;
+ rpPos = &rPos;
+ }
+ else
+ {
+ // case 3: regular text portion
+ DBG_ASSERT( ( nModelEndPos - nModelPos ) ==
+ ( aAccessiblePositions[nPortionNo+1] -
+ aAccessiblePositions[nPortionNo] ),
+ "text portion expected" );
+
+ nModelPos += nPos - aAccessiblePositions[ nPortionNo ];
+ rpPos = NULL;
+ }
+ }
+ if( rpPos != NULL )
+ {
+ DBG_ASSERT( rpPos == &rPos, "Yes!" );
+ DBG_ASSERT( nRefPos <= nPos, "wrong reference" );
+ DBG_ASSERT( (nExtend == SP_EXTEND_RANGE_NONE) ||
+ (nExtend == SP_EXTEND_RANGE_BEFORE) ||
+ (nExtend == SP_EXTEND_RANGE_BEHIND), "need extend" );
+
+ // get the line number, and adjust nRefPos for the line
+ // (if necessary)
+ size_t nRefLine = FindBreak( aLineBreaks, nRefPos );
+ size_t nMyLine = FindBreak( aLineBreaks, nPos );
+ USHORT nLineOffset = static_cast<USHORT>( nMyLine - nRefLine );
+ if( nLineOffset != 0 )
+ nRefPos = aLineBreaks[ nMyLine ];
+
+ // fill char offset and 'special position'
+ rPos.nCharOfst = static_cast<USHORT>( nPos - nRefPos );
+ rPos.nExtendRange = nExtend;
+ rPos.nLineOfst = nLineOffset;
+ }
+
+ return static_cast<USHORT>( nModelPos );
+}
+
+void SwAccessiblePortionData::AdjustAndCheck(
+ sal_Int32 nPos,
+ size_t& nPortionNo,
+ USHORT& nCorePos,
+ sal_Bool& bEdit) const
+{
+ // find portion and get mode position
+ nPortionNo = FindBreak( aAccessiblePositions, nPos );
+ nCorePos = static_cast<USHORT>( aModelPositions[ nPortionNo ] );
+
+ // for special portions, make sure we're on a portion boundary
+ // for text portions, add the in-portion offset
+ if( IsSpecialPortion( nPortionNo ) )
+ bEdit &= nPos == aAccessiblePositions[nPortionNo];
+ else
+ nCorePos = static_cast<USHORT>( nCorePos +
+ nPos - aAccessiblePositions[nPortionNo] );
+}
+
+sal_Bool SwAccessiblePortionData::GetEditableRange(
+ sal_Int32 nStart, sal_Int32 nEnd,
+ USHORT& nCoreStart, USHORT& nCoreEnd ) const
+{
+ sal_Bool bIsEditable = sal_True;
+
+ // get start and end portions
+ size_t nStartPortion, nEndPortion;
+ AdjustAndCheck( nStart, nStartPortion, nCoreStart, bIsEditable );
+ AdjustAndCheck( nEnd, nEndPortion, nCoreEnd, bIsEditable );
+
+ // iterate over portions, and make sure there is no read-only portion
+ // in-between
+ size_t nLastPortion = nEndPortion;
+
+ // don't count last portion if we're in front of a special portion
+ if( IsSpecialPortion(nLastPortion) )
+ {
+ if (nLastPortion > 0)
+ nLastPortion--;
+ else
+ // special case: because size_t is usually unsigned, we can't just
+ // decrease nLastPortion to -1 (which would normally do the job, so
+ // this whole if wouldn't be needed). Instead, we'll do this
+ // special case and just increae the start portion beyond the last
+ // portion to make sure the loop below will have zero iteration.
+ nStartPortion = nLastPortion + 1;
+ }
+
+ for( size_t nPor = nStartPortion; nPor <= nLastPortion; nPor ++ )
+ {
+ bIsEditable &= ! IsReadOnlyPortion( nPor );
+ }
+
+ return bIsEditable;
+}
+
+sal_Bool SwAccessiblePortionData::IsValidCorePosition( USHORT nPos ) const
+{
+ // a position is valid its within the model positions that we know
+ return ( aModelPositions[0] <= nPos ) &&
+ ( nPos <= aModelPositions[ aModelPositions.size()-1 ] );
+}
+
+USHORT SwAccessiblePortionData::GetFirstValidCorePosition() const
+{
+ return static_cast<USHORT>( aModelPositions[0] );
+}
+
+USHORT SwAccessiblePortionData::GetLastValidCorePosition() const
+{
+ return static_cast<USHORT>( aModelPositions[ aModelPositions.size()-1 ] );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accportions.hxx b/sw/source/core/access/accportions.hxx
new file mode 100644
index 000000000000..1a58ae123e4b
--- /dev/null
+++ b/sw/source/core/access/accportions.hxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCPORTIONS_HXX
+#define _ACCPORTIONS_HXX
+#include <SwPortionHandler.hxx>
+#include <sal/types.h>
+#include <rtl/ustrbuf.hxx>
+#include <vector>
+
+class String;
+class SwTxtNode;
+struct SwSpecialPos;
+class SwViewOption;
+namespace com { namespace sun { namespace star {
+ namespace i18n { struct Boundary; }
+} } }
+
+/**
+ * collect text portion data from the layout through SwPortionHandler interface
+ */
+class SwAccessiblePortionData : public SwPortionHandler
+{
+ // the node this portion is referring to
+ const SwTxtNode* pTxtNode;
+
+ // variables used while collecting the data
+ rtl::OUStringBuffer aBuffer;
+ sal_Int32 nModelPosition;
+ sal_Bool bFinished;
+ const SwViewOption* pViewOptions;
+
+ // the accessible string
+ rtl::OUString sAccessibleString;
+
+ // positions array
+ // instances of Position_t must always include the minimum and
+ // maximum positions as first/last elements (to simplify the
+ // algorithms)
+ typedef std::vector<sal_Int32> Positions_t;
+
+ Positions_t aLineBreaks; /// position of line breaks
+ Positions_t aModelPositions; /// position of portion breaks in the model
+ Positions_t aAccessiblePositions; /// portion breaks in sAccessibleString
+
+ typedef std::vector<sal_uInt8> PortionAttrs_t;
+ PortionAttrs_t aPortionAttrs; /// additional portion attributes
+
+ Positions_t* pSentences; /// positions of sentence breaks
+
+ size_t nBeforePortions; /// # of portions before first model character
+ sal_Bool bLastIsSpecial; /// set if last portion was 'Special()'
+
+ /// returns the index of the first position whose value is smaller
+ /// or equal, and whose following value is equal or larger
+ size_t FindBreak( const Positions_t& rPositions, sal_Int32 nValue ) const;
+
+ /// like FindBreak, but finds the last equal or larger position
+ size_t FindLastBreak( const Positions_t& rPositions, sal_Int32 nValue ) const;
+
+ /// fill the boundary with the values from rPositions[nPos]
+ void FillBoundary(com::sun::star::i18n::Boundary& rBound,
+ const Positions_t& rPositions,
+ size_t nPos ) const;
+
+ /// Access to portion attributes
+ sal_Bool IsPortionAttrSet( size_t nPortionNo, sal_uInt8 nAttr ) const;
+ sal_Bool IsSpecialPortion( size_t nPortionNo ) const;
+ sal_Bool IsReadOnlyPortion( size_t nPortionNo ) const;
+ sal_Bool IsGrayPortionType( USHORT nType ) const;
+
+ // helper method for GetEditableRange(...):
+ void AdjustAndCheck( sal_Int32 nPos, size_t& nPortionNo,
+ USHORT& nCorePos, sal_Bool& bEdit ) const;
+
+public:
+ SwAccessiblePortionData( const SwTxtNode* pTxtNd,
+ const SwViewOption* pViewOpt = NULL );
+ virtual ~SwAccessiblePortionData();
+
+ // SwPortionHandler methods
+ virtual void Text(USHORT nLength, USHORT nType);
+ virtual void Special(USHORT nLength, const String& rText, USHORT nType);
+ virtual void LineBreak();
+ virtual void Skip(USHORT nLength);
+ virtual void Finish();
+
+
+ // access to the portion data
+
+ /// get the text string, as presented by the layout
+ const rtl::OUString& GetAccessibleString() const;
+
+ /// get the start & end positions of the sentence
+ void GetLineBoundary( com::sun::star::i18n::Boundary& rBound,
+ sal_Int32 nPos ) const;
+
+ // get start and end position of the last line
+ void GetLastLineBoundary( com::sun::star::i18n::Boundary& rBound ) const;
+
+ // --> OD 2008-05-30 #i89175#
+ sal_Int32 GetLineCount() const;
+ sal_Int32 GetLineNo( const sal_Int32 nPos ) const;
+ void GetBoundaryOfLine( const sal_Int32 nLineNo,
+ com::sun::star::i18n::Boundary& rLineBound );
+ // <--
+
+ /// get the position in the model string for a given
+ /// (accessibility) position
+ USHORT GetModelPosition( sal_Int32 nPos ) const;
+
+ /// get the position in the accessibility string for a given model position
+ sal_Int32 GetAccessiblePosition( USHORT nPos ) const;
+
+ /// fill a SwSpecialPos structure, suitable for calling
+ /// SwTxtFrm->GetCharRect
+ /// Returns the core position, and fills thr rpPos either with NULL or
+ /// with the &rPos, after putting the appropriate data into it.
+ USHORT FillSpecialPos( sal_Int32 nPos,
+ SwSpecialPos& rPos,
+ SwSpecialPos*& rpPos ) const;
+
+
+ // get boundaries of words/sentences. The data structures are
+ // created on-demand.
+ void GetSentenceBoundary( com::sun::star::i18n::Boundary& rBound,
+ sal_Int32 nPos );
+
+ // get (a) boundary for attribut change
+ void GetAttributeBoundary( com::sun::star::i18n::Boundary& rBound,
+ sal_Int32 nPos ) const;
+
+ /// Convert start and end positions into core positions.
+ /// @returns true if 'special' portions are included either completely
+ /// or not at all. This can be used to test whether editing
+ /// that range would be legal
+ sal_Bool GetEditableRange( sal_Int32 nStart, sal_Int32 nEnd,
+ USHORT& nCoreStart, USHORT& nCoreEnd ) const;
+
+ /// Determine whether this core position is valid for these portions.
+ /// (A paragraph may be split into several frames, e.g. at page
+ /// boundaries. In this case, only part of a paragraph is represented
+ /// through this object. This method determines whether one particular
+ /// position is valid for this object or not.)
+ sal_Bool IsValidCorePosition( USHORT nPos ) const;
+ USHORT GetFirstValidCorePosition() const;
+ USHORT GetLastValidCorePosition() const;
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpreview.cxx b/sw/source/core/access/accpreview.cxx
new file mode 100644
index 000000000000..dd0ef1aab786
--- /dev/null
+++ b/sw/source/core/access/accpreview.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <vcl/svapp.hxx>
+#include <rtl/uuid.h>
+#include "access.hrc"
+#include <accpreview.hxx>
+
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextDocumentPageView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleDocumentPageView";
+
+
+// using namespace accessibility;
+
+using ::com::sun::star::lang::IndexOutOfBoundsException;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::uno::Sequence;
+using ::rtl::OUString;
+
+
+
+
+//
+// SwAccessiblePreview
+//
+
+SwAccessiblePreview::SwAccessiblePreview( SwAccessibleMap *pMp ) :
+ SwAccessibleDocumentBase( pMp )
+{
+ SetName( GetResource( STR_ACCESS_DOC_NAME ) );
+}
+
+SwAccessiblePreview::~SwAccessiblePreview()
+{
+}
+
+OUString SwAccessiblePreview::getImplementationName( )
+ throw( RuntimeException )
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM( sImplementationName ) );
+}
+
+sal_Bool SwAccessiblePreview::supportsService( const OUString& rServiceName )
+ throw( RuntimeException )
+{
+ return rServiceName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( sServiceName) ) ||
+ rServiceName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( sAccessibleServiceName ) );
+}
+
+Sequence<OUString> SwAccessiblePreview::getSupportedServiceNames( )
+ throw( RuntimeException )
+{
+ Sequence<OUString> aSeq( 2 );
+ aSeq[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( sServiceName ) );
+ aSeq[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( sAccessibleServiceName ) );
+ return aSeq;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessiblePreview::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpreview.hxx b/sw/source/core/access/accpreview.hxx
new file mode 100644
index 000000000000..d976efefa114
--- /dev/null
+++ b/sw/source/core/access/accpreview.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCPREVIEW_HXX
+#define _ACCPREVIEW_HXX
+
+#include "accdoc.hxx"
+
+/**
+ * accessibility implementation for the page preview.
+ * The children of the page preview are the pages that are visible in the
+ * preview.
+ *
+ * The vast majority of the implemention logic is inherited from
+ * SwAccessibleDocumentBase.
+ */
+class SwAccessiblePreview : public SwAccessibleDocumentBase
+{
+ virtual ~SwAccessiblePreview();
+
+public:
+
+ SwAccessiblePreview( SwAccessibleMap *pMap );
+
+
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accselectionhelper.cxx b/sw/source/core/access/accselectionhelper.cxx
new file mode 100644
index 000000000000..acb2bcd8427d
--- /dev/null
+++ b/sw/source/core/access/accselectionhelper.cxx
@@ -0,0 +1,337 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <accselectionhelper.hxx>
+
+#include <acccontext.hxx>
+#include <accmap.hxx>
+#include <svx/AccessibleShape.hxx>
+#include <viewsh.hxx>
+#include <fesh.hxx>
+#include <vcl/svapp.hxx> // for SolarMutex
+#include <tools/debug.hxx>
+#include <flyfrm.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+using ::com::sun::star::accessibility::XAccessible;
+using ::com::sun::star::accessibility::XAccessibleContext;
+using ::com::sun::star::accessibility::XAccessibleSelection;
+
+using namespace ::sw::access;
+
+SwAccessibleSelectionHelper::SwAccessibleSelectionHelper(
+ SwAccessibleContext& rCtxt ) :
+ rContext( rCtxt )
+{
+}
+
+SwAccessibleSelectionHelper::~SwAccessibleSelectionHelper()
+{
+}
+
+SwFEShell* SwAccessibleSelectionHelper::GetFEShell()
+{
+ DBG_ASSERT( rContext.GetMap() != NULL, "no map?" );
+ ViewShell* pViewShell = rContext.GetMap()->GetShell();
+ DBG_ASSERT( pViewShell != NULL,
+ "No view shell? Then what are you looking at?" );
+
+ SwFEShell* pFEShell = NULL;
+ if( pViewShell->ISA( SwFEShell ) )
+ {
+ pFEShell = static_cast<SwFEShell*>( pViewShell );
+ }
+
+ return pFEShell;
+}
+
+void SwAccessibleSelectionHelper::throwIndexOutOfBoundsException()
+ throw ( lang::IndexOutOfBoundsException )
+{
+ Reference < XAccessibleContext > xThis( &rContext );
+ Reference < XAccessibleSelection >xSelThis( xThis, UNO_QUERY );
+ lang::IndexOutOfBoundsException aExcept(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("index out of bounds") ),
+ xSelThis ); \
+ throw aExcept;
+}
+
+
+//===== XAccessibleSelection ============================================
+
+void SwAccessibleSelectionHelper::selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ // Get the respective child as SwFrm (also do index checking), ...
+ const SwAccessibleChild aChild = rContext.GetChild( *(rContext.GetMap()),
+ nChildIndex );
+ if( !aChild.IsValid() )
+ throwIndexOutOfBoundsException();
+
+ // we can only select fly frames, so we ignore (should: return
+ // false) all other attempts at child selection
+ sal_Bool bRet = sal_False;
+ SwFEShell* pFEShell = GetFEShell();
+ if( pFEShell != NULL )
+ {
+ const SdrObject *pObj = aChild.GetDrawObject();
+ if( pObj )
+ {
+ bRet = rContext.Select( const_cast< SdrObject *>( pObj ), 0==aChild.GetSwFrm());
+ }
+ }
+ // no frame shell, or no frame, or no fly frame -> can't select
+
+ // return bRet;
+}
+
+sal_Bool SwAccessibleSelectionHelper::isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ // Get the respective child as SwFrm (also do index checking), ...
+ const SwAccessibleChild aChild = rContext.GetChild( *(rContext.GetMap()),
+ nChildIndex );
+ if( !aChild.IsValid() )
+ throwIndexOutOfBoundsException();
+
+ // ... and compare to the currently selected frame
+ sal_Bool bRet = sal_False;
+ SwFEShell* pFEShell = GetFEShell();
+ if( pFEShell )
+ {
+ if ( aChild.GetSwFrm() != 0 )
+ {
+ bRet = (pFEShell->GetCurrFlyFrm() == aChild.GetSwFrm());
+ }
+ else if ( aChild.GetDrawObject() )
+ {
+ bRet = pFEShell->IsObjSelected( *aChild.GetDrawObject() );
+ }
+ }
+
+ return bRet;
+}
+
+void SwAccessibleSelectionHelper::clearAccessibleSelection( )
+ throw ( RuntimeException )
+{
+ // return sal_False // we can't deselect
+}
+
+void SwAccessibleSelectionHelper::selectAllAccessibleChildren( )
+ throw ( RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ // We can select only one. So iterate over the children to find
+ // the first we can select, and select it.
+
+ SwFEShell* pFEShell = GetFEShell();
+ if( pFEShell )
+ {
+ ::std::list< SwAccessibleChild > aChildren;
+ rContext.GetChildren( *(rContext.GetMap()), aChildren );
+
+ ::std::list< SwAccessibleChild >::const_iterator aIter = aChildren.begin();
+ ::std::list< SwAccessibleChild >::const_iterator aEndIter = aChildren.end();
+ while( aIter != aEndIter )
+ {
+ const SwAccessibleChild& rChild = *aIter;
+ const SdrObject* pObj = rChild.GetDrawObject();
+ const SwFrm* pFrm = rChild.GetSwFrm();
+ if( pObj && !(pFrm != 0 && pFEShell->IsObjSelected()) )
+ {
+ rContext.Select( const_cast< SdrObject *>( pObj ), 0==pFrm );
+ if( pFrm )
+ break;
+ }
+ ++aIter;
+ }
+ }
+}
+
+sal_Int32 SwAccessibleSelectionHelper::getSelectedAccessibleChildCount( )
+ throw ( RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nCount = 0;
+ // Only one frame can be selected at a time, and we only frames
+ // for selectable children.
+ SwFEShell* pFEShell = GetFEShell();
+ if( pFEShell != 0 )
+ {
+ const SwFlyFrm* pFlyFrm = pFEShell->GetCurrFlyFrm();
+ if( pFlyFrm )
+ {
+ if( rContext.GetParent( SwAccessibleChild(pFlyFrm), rContext.IsInPagePreview()) ==
+ rContext.GetFrm() )
+ {
+ nCount = 1;
+ }
+ }
+ else
+ {
+ sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
+ if( nSelObjs > 0 )
+ {
+ ::std::list< SwAccessibleChild > aChildren;
+ rContext.GetChildren( *(rContext.GetMap()), aChildren );
+
+ ::std::list< SwAccessibleChild >::const_iterator aIter =
+ aChildren.begin();
+ ::std::list< SwAccessibleChild >::const_iterator aEndIter =
+ aChildren.end();
+ while( aIter != aEndIter && nCount < nSelObjs )
+ {
+ const SwAccessibleChild& rChild = *aIter;
+ if( rChild.GetDrawObject() && !rChild.GetSwFrm() &&
+ rContext.GetParent(rChild, rContext.IsInPagePreview())
+ == rContext.GetFrm() &&
+ pFEShell->IsObjSelected( *rChild.GetDrawObject() ) )
+ {
+ nCount++;
+ }
+ ++aIter;
+ }
+ }
+ }
+ }
+ return nCount;
+}
+
+Reference<XAccessible> SwAccessibleSelectionHelper::getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // Since the index is relative to the selected children, and since
+ // there can be at most one selected frame child, the index must
+ // be 0, and a selection must exist, otherwise we have to throw an
+ // lang::IndexOutOfBoundsException
+ SwFEShell* pFEShell = GetFEShell();
+ if( 0 == pFEShell )
+ throwIndexOutOfBoundsException();
+
+ SwAccessibleChild aChild;
+ const SwFlyFrm *pFlyFrm = pFEShell->GetCurrFlyFrm();
+ if( pFlyFrm )
+ {
+ if( 0 == nSelectedChildIndex &&
+ rContext.GetParent( SwAccessibleChild(pFlyFrm), rContext.IsInPagePreview()) ==
+ rContext.GetFrm() )
+ {
+ aChild = pFlyFrm;
+ }
+ }
+ else
+ {
+ sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
+ if( 0 == nSelObjs || nSelectedChildIndex >= nSelObjs )
+ throwIndexOutOfBoundsException();
+
+ ::std::list< SwAccessibleChild > aChildren;
+ rContext.GetChildren( *(rContext.GetMap()), aChildren );
+
+ ::std::list< SwAccessibleChild >::const_iterator aIter = aChildren.begin();
+ ::std::list< SwAccessibleChild >::const_iterator aEndIter = aChildren.end();
+ while( aIter != aEndIter && !aChild.IsValid() )
+ {
+ const SwAccessibleChild& rChild = *aIter;
+ if( rChild.GetDrawObject() && !rChild.GetSwFrm() &&
+ rContext.GetParent(rChild, rContext.IsInPagePreview()) ==
+ rContext.GetFrm() &&
+ pFEShell->IsObjSelected( *rChild.GetDrawObject() ) )
+ {
+ if( 0 == nSelectedChildIndex )
+ aChild = rChild;
+ else
+ --nSelectedChildIndex;
+ }
+ ++aIter;
+ }
+ }
+
+ if( !aChild.IsValid() )
+ throwIndexOutOfBoundsException();
+
+ DBG_ASSERT( rContext.GetMap() != NULL, "We need the map." );
+ Reference< XAccessible > xChild;
+ if( aChild.GetSwFrm() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xChildImpl(
+ rContext.GetMap()->GetContextImpl( aChild.GetSwFrm(),
+ sal_True ) );
+ if( xChildImpl.is() )
+ {
+ xChildImpl->SetParent( &rContext );
+ xChild = xChildImpl.get();
+ }
+ }
+ else if ( aChild.GetDrawObject() )
+ {
+ ::rtl::Reference < ::accessibility::AccessibleShape > xChildImpl(
+ rContext.GetMap()->GetContextImpl( aChild.GetDrawObject(),
+ &rContext, sal_True ) );
+ if( xChildImpl.is() )
+ xChild = xChildImpl.get();
+ }
+ return xChild;
+}
+
+// --> OD 2004-11-16 #111714# - index has to be treated as global child index.
+void SwAccessibleSelectionHelper::deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ RuntimeException )
+{
+ // return sal_False // we can't deselect
+ if( nChildIndex < 0 ||
+ nChildIndex >= rContext.GetChildCount( *(rContext.GetMap()) ) )
+ throwIndexOutOfBoundsException();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accselectionhelper.hxx b/sw/source/core/access/accselectionhelper.hxx
new file mode 100644
index 000000000000..502ec819e860
--- /dev/null
+++ b/sw/source/core/access/accselectionhelper.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCSELECTIONHELPER_HXX_
+#define _ACCSELECTIONHELPER_HXX_
+class SwAccessibleContext;
+class SwFEShell;
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+
+class SwAccessibleSelectionHelper
+{
+ /// the context on which this helper works
+ SwAccessibleContext& rContext;
+
+
+ /// get FE-Shell
+ SwFEShell* GetFEShell();
+
+ void throwIndexOutOfBoundsException()
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException );
+
+public:
+
+ SwAccessibleSelectionHelper( SwAccessibleContext& rContext );
+ ~SwAccessibleSelectionHelper();
+
+
+ //===== XAccessibleSelection ============================================
+
+ void selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ sal_Bool isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+ void clearAccessibleSelection( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ void selectAllAccessibleChildren( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ sal_Int32 getSelectedAccessibleChildCount( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ // --> OD 2004-11-16 #111714# - index has to be treated as global child index.
+ void deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acctable.cxx b/sw/source/core/access/acctable.cxx
new file mode 100644
index 000000000000..28e01cd65777
--- /dev/null
+++ b/sw/source/core/access/acctable.cxx
@@ -0,0 +1,1806 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <osl/mutex.hxx>
+#include <rtl/uuid.h>
+#include <rtl/ustrbuf.hxx>
+
+#include <list>
+#include <set>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <frmfmt.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <swtable.hxx>
+#include <crsrsh.hxx>
+#include <viscrs.hxx>
+#include <hints.hxx>
+#include <fesh.hxx>
+#include <accfrmobjslist.hxx>
+#include <accmap.hxx>
+#include <access.hrc>
+#include <acctable.hxx>
+
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using namespace ::sw::access;
+
+const sal_Char sServiceName[] = "com.sun.star.table.AccessibleTableView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleTableView";
+
+typedef ::std::less < sal_Int32 > Int32Less_Impl;
+typedef ::std::set < sal_Int32, Int32Less_Impl > Int32Set_Impl;
+
+typedef ::std::pair < sal_Int32, sal_Int32 > Int32Pair_Impl;
+typedef ::std::list < Int32Pair_Impl > Int32PairList_Impl;
+
+class SwAccTableSelHander_Impl
+{
+public:
+ virtual void Unselect( sal_Int32 nRowOrCol, sal_Int32 nExt ) = 0;
+};
+
+
+//------------------------------------------------------------------------------
+
+class SwAccessibleTableData_Impl
+{
+ SwAccessibleMap& mrAccMap;
+ Int32Set_Impl maRows;
+ Int32Set_Impl maColumns;
+ Int32PairList_Impl maExtents; // cell extends for event processing only
+ Point maTabFrmPos;
+ const SwTabFrm *mpTabFrm;
+ sal_Bool mbIsInPagePreview;
+ bool mbOnlyTableColumnHeader;
+
+ void CollectData( const SwFrm *pFrm );
+ void CollectExtents( const SwFrm *pFrm );
+
+ sal_Bool FindCell( const Point& rPos, const SwFrm *pFrm ,
+ sal_Bool bExact, const SwFrm *& rFrm ) const;
+
+ void GetSelection( const Point& rTabPos, const SwRect& rArea,
+ const SwSelBoxes& rSelBoxes, const SwFrm *pFrm,
+ SwAccTableSelHander_Impl& rSelHdl,
+ sal_Bool bColumns ) const;
+
+ // --> OD 2007-06-27 #i77106#
+ inline bool IncludeRow( const SwFrm& rFrm ) const
+ {
+ return !mbOnlyTableColumnHeader ||
+ mpTabFrm->IsInHeadline( rFrm );
+ }
+ // <--
+public:
+ // --> OD 2007-06-27 #i77106#
+ // add third optional parameter <bOnlyTableColumnHeader>, default value <false>
+ SwAccessibleTableData_Impl( SwAccessibleMap& rAccMap,
+ const SwTabFrm *pTabFrm,
+ sal_Bool bIsInPagePreview,
+ bool bOnlyTableColumnHeader = false );
+ // <--
+
+ const Int32Set_Impl& GetRows() const { return maRows; }
+ const Int32Set_Impl& GetColumns() const { return maColumns; }
+
+ inline Int32Set_Impl::const_iterator GetRowIter( sal_Int32 nRow ) const;
+ inline Int32Set_Impl::const_iterator GetColumnIter( sal_Int32 nCol ) const;
+
+ const SwFrm *GetCell( sal_Int32 nRow, sal_Int32 nColumn, sal_Bool bExact,
+ SwAccessibleTable *pThis ) const
+ throw(lang::IndexOutOfBoundsException );
+ const SwFrm *GetCellAtPos( sal_Int32 nLeft, sal_Int32 nTop,
+ sal_Bool bExact ) const;
+ inline sal_Int32 GetRowCount() const;
+ inline sal_Int32 GetColumnCount() const;
+ sal_Bool CompareExtents( const SwAccessibleTableData_Impl& r ) const;
+
+ void GetSelection( sal_Int32 nStart, sal_Int32 nEnd,
+ const SwSelBoxes& rSelBoxes,
+ SwAccTableSelHander_Impl& rSelHdl,
+ sal_Bool bColumns ) const;
+
+ void CheckRowAndCol( sal_Int32 nRow, sal_Int32 nCol,
+ SwAccessibleTable *pThis ) const
+ throw(lang::IndexOutOfBoundsException );
+
+ void GetRowColumnAndExtent( const SwRect& rBox,
+ sal_Int32& rRow, sal_Int32& rColumn,
+ sal_Int32& rRowExtent,
+ sal_Int32& rColumnExtent ) const;
+
+ const Point& GetTablePos() const { return maTabFrmPos; }
+ void SetTablePos( const Point& rPos ) { maTabFrmPos = rPos; }
+};
+
+void SwAccessibleTableData_Impl::CollectData( const SwFrm *pFrm )
+{
+ const SwAccessibleChildSList aList( *pFrm, mrAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ SwAccessibleChildSList::const_iterator aEndIter( aList.end() );
+ while( aIter != aEndIter )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ if( pLower->IsRowFrm() )
+ {
+ // --> OD 2007-06-27 #i77106#
+ if ( IncludeRow( *pLower ) )
+ {
+ maRows.insert( pLower->Frm().Top() - maTabFrmPos.Y() );
+ CollectData( pLower );
+ }
+ // <--
+ }
+ else if( pLower->IsCellFrm() &&
+ rLower.IsAccessible( mbIsInPagePreview ) )
+ {
+ maColumns.insert( pLower->Frm().Left() - maTabFrmPos.X() );
+ }
+ else
+ {
+ CollectData( pLower );
+ }
+ }
+ ++aIter;
+ }
+}
+
+void SwAccessibleTableData_Impl::CollectExtents( const SwFrm *pFrm )
+{
+ const SwAccessibleChildSList aList( *pFrm, mrAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ SwAccessibleChildSList::const_iterator aEndIter( aList.end() );
+ while( aIter != aEndIter )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ if( pLower->IsCellFrm() &&
+ rLower.IsAccessible( mbIsInPagePreview ) )
+ {
+ sal_Int32 nRow, nCol;
+ Int32Pair_Impl aCellExtents;
+ GetRowColumnAndExtent( pLower->Frm(), nRow, nCol,
+ aCellExtents.first,
+ aCellExtents.second );
+
+ maExtents.push_back( aCellExtents );
+ }
+ else
+ {
+ // --> OD 2007-06-27 #i77106#
+ if ( !pLower->IsRowFrm() ||
+ IncludeRow( *pLower ) )
+ {
+ CollectExtents( pLower );
+ }
+ // <--
+ }
+ }
+ ++aIter;
+ }
+}
+
+sal_Bool SwAccessibleTableData_Impl::FindCell(
+ const Point& rPos, const SwFrm *pFrm, sal_Bool bExact,
+ const SwFrm *& rRet ) const
+{
+ sal_Bool bFound = sal_False;
+
+ const SwAccessibleChildSList aList( *pFrm, mrAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ SwAccessibleChildSList::const_iterator aEndIter( aList.end() );
+ while( !bFound && aIter != aEndIter )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ OSL_ENSURE( pLower, "child should be a frame" );
+ if( pLower )
+ {
+ if( rLower.IsAccessible( mbIsInPagePreview ) )
+ {
+ OSL_ENSURE( pLower->IsCellFrm(), "lower is not a cell frame" );
+ const SwRect& rFrm = pLower->Frm();
+ if( rFrm.Right() >= rPos.X() && rFrm.Bottom() >= rPos.Y() )
+ {
+ // We have found the cell
+ OSL_ENSURE( rFrm.Left() <= rPos.X() && rFrm.Top() <= rPos.Y(),
+ "find frame moved to far!" );
+ bFound = sal_True;
+ if( !bExact ||
+ (rFrm.Top() == rPos.Y() && rFrm.Left() == rPos.Y() ) )
+ {
+ rRet = pLower;
+ }
+ }
+ }
+ else
+ {
+ // --> OD 2007-06-27 #i77106#
+ if ( !pLower->IsRowFrm() ||
+ IncludeRow( *pLower ) )
+ {
+ bFound = FindCell( rPos, pLower, bExact, rRet );
+ }
+ // <--
+ }
+ }
+ ++aIter;
+ }
+
+ return bFound;
+}
+
+void SwAccessibleTableData_Impl::GetSelection(
+ const Point& rTabPos,
+ const SwRect& rArea,
+ const SwSelBoxes& rSelBoxes,
+ const SwFrm *pFrm,
+ SwAccTableSelHander_Impl& rSelHdl,
+ sal_Bool bColumns ) const
+{
+ const SwAccessibleChildSList aList( *pFrm, mrAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ SwAccessibleChildSList::const_iterator aEndIter( aList.end() );
+ while( aIter != aEndIter )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ OSL_ENSURE( pLower, "child should be a frame" );
+ const SwRect& rBox = rLower.GetBox( mrAccMap );
+ if( pLower && rBox.IsOver( rArea ) )
+ {
+ if( rLower.IsAccessible( mbIsInPagePreview ) )
+ {
+ OSL_ENSURE( pLower->IsCellFrm(), "lower is not a cell frame" );
+ const SwCellFrm *pCFrm =
+ static_cast < const SwCellFrm * >( pLower );
+ SwTableBox *pBox =
+ const_cast< SwTableBox *>( pCFrm->GetTabBox() ); //SVPtrArr!
+ if( !rSelBoxes.Seek_Entry( pBox ) )
+ {
+ const Int32Set_Impl rRowsOrCols =
+ bColumns ? maColumns : maRows;
+
+ sal_Int32 nPos = bColumns ? (rBox.Left() - rTabPos.X())
+ : (rBox.Top() - rTabPos.Y());
+ Int32Set_Impl::const_iterator aSttRowOrCol(
+ rRowsOrCols.lower_bound( nPos ) );
+ sal_Int32 nRowOrCol =
+ static_cast< sal_Int32 >( ::std::distance(
+ rRowsOrCols.begin(), aSttRowOrCol ) );
+
+ nPos = bColumns ? (rBox.Right() - rTabPos.X())
+ : (rBox.Bottom() - rTabPos.Y());
+ Int32Set_Impl::const_iterator aEndRowOrCol(
+ rRowsOrCols.upper_bound( nPos ) );
+ sal_Int32 nExt =
+ static_cast< sal_Int32 >( ::std::distance(
+ aSttRowOrCol, aEndRowOrCol ) );
+
+ rSelHdl.Unselect( nRowOrCol, nExt );
+ }
+ }
+ else
+ {
+ // --> OD 2007-06-27 #i77106#
+ if ( !pLower->IsRowFrm() ||
+ IncludeRow( *pLower ) )
+ {
+ GetSelection( rTabPos, rArea, rSelBoxes, pLower, rSelHdl,
+ bColumns );
+ }
+ // <--
+ }
+ }
+ ++aIter;
+ }
+}
+
+const SwFrm *SwAccessibleTableData_Impl::GetCell(
+ sal_Int32 nRow, sal_Int32 nColumn, sal_Bool,
+ SwAccessibleTable *pThis ) const
+ throw(lang::IndexOutOfBoundsException )
+{
+ CheckRowAndCol( nRow, nColumn, pThis );
+
+ Int32Set_Impl::const_iterator aSttCol( GetColumnIter( nColumn ) );
+ Int32Set_Impl::const_iterator aSttRow( GetRowIter( nRow ) );
+ const SwFrm *pCellFrm = GetCellAtPos( *aSttCol, *aSttRow, sal_False );
+
+ return pCellFrm;
+}
+
+void SwAccessibleTableData_Impl::GetSelection(
+ sal_Int32 nStart, sal_Int32 nEnd,
+ const SwSelBoxes& rSelBoxes,
+ SwAccTableSelHander_Impl& rSelHdl,
+ sal_Bool bColumns ) const
+{
+ SwRect aArea( mpTabFrm->Frm() );
+ Point aPos( aArea.Pos() );
+
+ const Int32Set_Impl& rRowsOrColumns = bColumns ? maColumns : maRows;
+ if( nStart > 0 )
+ {
+ Int32Set_Impl::const_iterator aStt( rRowsOrColumns.begin() );
+ ::std::advance( aStt,
+ static_cast< Int32Set_Impl::difference_type >( nStart ) );
+ if( bColumns )
+ aArea.Left( *aStt + aPos.X() );
+ else
+ aArea.Top( *aStt + aPos.Y() );
+ }
+ if( nEnd < static_cast< sal_Int32 >( rRowsOrColumns.size() ) )
+ {
+ Int32Set_Impl::const_iterator aEnd( rRowsOrColumns.begin() );
+ ::std::advance( aEnd,
+ static_cast< Int32Set_Impl::difference_type >( nEnd ) );
+ if( bColumns )
+ aArea.Right( *aEnd + aPos.X() - 1 );
+ else
+ aArea.Bottom( *aEnd + aPos.Y() - 1 );
+ }
+
+ GetSelection( aPos, aArea, rSelBoxes, mpTabFrm, rSelHdl, bColumns );
+}
+
+const SwFrm *SwAccessibleTableData_Impl::GetCellAtPos(
+ sal_Int32 nLeft, sal_Int32 nTop, sal_Bool bExact ) const
+{
+ Point aPos( mpTabFrm->Frm().Pos() );
+ aPos.Move( nLeft, nTop );
+ const SwFrm *pRet = 0;
+ FindCell( aPos, mpTabFrm, bExact, pRet );
+
+ return pRet;
+}
+
+inline sal_Int32 SwAccessibleTableData_Impl::GetRowCount() const
+{
+ return static_cast< sal_Int32 >( maRows.size() );
+}
+
+inline sal_Int32 SwAccessibleTableData_Impl::GetColumnCount() const
+{
+ return static_cast< sal_Int32 >( maColumns.size() );
+}
+
+sal_Bool SwAccessibleTableData_Impl::CompareExtents(
+ const SwAccessibleTableData_Impl& rCmp ) const
+{
+ if( maExtents.size() != rCmp.maExtents.size() )
+ return sal_False;
+
+ Int32PairList_Impl::const_iterator aIter( maExtents.begin() );
+ Int32PairList_Impl::const_iterator aEndIter( maExtents.end() );
+ Int32PairList_Impl::const_iterator aCmpIter( rCmp.maExtents.begin() );
+ while( aIter != aEndIter )
+ {
+ if( *aIter != *aCmpIter )
+ return sal_False;
+
+ ++aIter;
+ ++aCmpIter;
+ }
+
+ return sal_True;
+}
+
+SwAccessibleTableData_Impl::SwAccessibleTableData_Impl( SwAccessibleMap& rAccMap,
+ const SwTabFrm *pTabFrm,
+ sal_Bool bIsInPagePreview,
+ bool bOnlyTableColumnHeader )
+ : mrAccMap( rAccMap )
+ , maTabFrmPos( pTabFrm->Frm().Pos() )
+ , mpTabFrm( pTabFrm )
+ , mbIsInPagePreview( bIsInPagePreview )
+ , mbOnlyTableColumnHeader( bOnlyTableColumnHeader )
+{
+ CollectData( mpTabFrm );
+ CollectExtents( mpTabFrm );
+}
+
+inline Int32Set_Impl::const_iterator SwAccessibleTableData_Impl::GetRowIter(
+ sal_Int32 nRow ) const
+{
+ Int32Set_Impl::const_iterator aCol( GetRows().begin() );
+ if( nRow > 0 )
+ {
+ ::std::advance( aCol,
+ static_cast< Int32Set_Impl::difference_type >( nRow ) );
+ }
+ return aCol;
+}
+
+inline Int32Set_Impl::const_iterator SwAccessibleTableData_Impl::GetColumnIter(
+ sal_Int32 nColumn ) const
+{
+ Int32Set_Impl::const_iterator aCol = GetColumns().begin();
+ if( nColumn > 0 )
+ {
+ ::std::advance( aCol,
+ static_cast< Int32Set_Impl::difference_type >( nColumn ) );
+ }
+ return aCol;
+}
+
+void SwAccessibleTableData_Impl::CheckRowAndCol(
+ sal_Int32 nRow, sal_Int32 nCol, SwAccessibleTable *pThis ) const
+ throw(lang::IndexOutOfBoundsException )
+{
+ if( ( nRow < 0 || nRow >= static_cast< sal_Int32 >( maRows.size() ) ) ||
+ ( nCol < 0 || nCol >= static_cast< sal_Int32 >( maColumns.size() ) ) )
+ {
+ uno::Reference < XAccessibleTable > xThis( pThis );
+ lang::IndexOutOfBoundsException aExcept(
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "row or column index out of range") ),
+ xThis );
+ throw aExcept;
+ }
+}
+
+void SwAccessibleTableData_Impl::GetRowColumnAndExtent(
+ const SwRect& rBox,
+ sal_Int32& rRow, sal_Int32& rColumn,
+ sal_Int32& rRowExtent, sal_Int32& rColumnExtent ) const
+{
+ Int32Set_Impl::const_iterator aStt(
+ maRows.lower_bound( rBox.Top() - maTabFrmPos.Y() ) );
+ Int32Set_Impl::const_iterator aEnd(
+ maRows.upper_bound( rBox.Bottom() - maTabFrmPos.Y() ) );
+ rRow =
+ static_cast< sal_Int32 >( ::std::distance( maRows.begin(), aStt ) );
+ rRowExtent =
+ static_cast< sal_Int32 >( ::std::distance( aStt, aEnd ) );
+
+ aStt = maColumns.lower_bound( rBox.Left() - maTabFrmPos.X() );
+ aEnd = maColumns.upper_bound( rBox.Right() - maTabFrmPos.X() );
+ rColumn =
+ static_cast< sal_Int32 >( ::std::distance( maColumns.begin(), aStt ) );
+ rColumnExtent =
+ static_cast< sal_Int32 >( ::std::distance( aStt, aEnd ) );
+}
+
+//------------------------------------------------------------------------------
+
+class SwAccSingleTableSelHander_Impl : public SwAccTableSelHander_Impl
+{
+ sal_Bool bSelected;
+
+public:
+
+ inline SwAccSingleTableSelHander_Impl();
+
+ inline sal_Bool IsSelected() const { return bSelected; }
+
+ virtual void Unselect( sal_Int32, sal_Int32 );
+};
+
+inline SwAccSingleTableSelHander_Impl::SwAccSingleTableSelHander_Impl() :
+ bSelected( sal_True )
+{
+}
+
+void SwAccSingleTableSelHander_Impl::Unselect( sal_Int32, sal_Int32 )
+{
+ bSelected = sal_False;
+}
+
+//------------------------------------------------------------------------------
+
+class SwAccAllTableSelHander_Impl : public SwAccTableSelHander_Impl
+
+{
+ ::std::vector< sal_Bool > aSelected;
+ sal_Int32 nCount;
+
+public:
+
+ inline SwAccAllTableSelHander_Impl( sal_Int32 nSize );
+
+ uno::Sequence < sal_Int32 > GetSelSequence();
+
+ virtual void Unselect( sal_Int32 nRowOrCol, sal_Int32 nExt );
+ virtual ~SwAccAllTableSelHander_Impl();
+};
+
+SwAccAllTableSelHander_Impl::~SwAccAllTableSelHander_Impl()
+{
+}
+
+inline SwAccAllTableSelHander_Impl::SwAccAllTableSelHander_Impl( sal_Int32 nSize ) :
+ aSelected( nSize, sal_True ),
+ nCount( nSize )
+{
+}
+
+uno::Sequence < sal_Int32 > SwAccAllTableSelHander_Impl::GetSelSequence()
+{
+ OSL_ENSURE( nCount >= 0, "underflow" );
+ uno::Sequence < sal_Int32 > aRet( nCount );
+ sal_Int32 *pRet = aRet.getArray();
+ sal_Int32 nPos = 0;
+ size_t nSize = aSelected.size();
+ for( size_t i=0; i < nSize && nPos < nCount; i++ )
+ {
+ if( aSelected[i] )
+ {
+ *pRet++ = i;
+ nPos++;
+ }
+ }
+
+ OSL_ENSURE( nPos == nCount, "count is wrong" );
+
+ return aRet;
+}
+
+void SwAccAllTableSelHander_Impl::Unselect( sal_Int32 nRowOrCol,
+ sal_Int32 nExt )
+{
+ OSL_ENSURE( static_cast< size_t >( nRowOrCol ) < aSelected.size(),
+ "index to large" );
+ OSL_ENSURE( static_cast< size_t >( nRowOrCol+nExt ) <= aSelected.size(),
+ "extent to large" );
+ while( nExt )
+ {
+ if( aSelected[static_cast< size_t >( nRowOrCol )] )
+ {
+ aSelected[static_cast< size_t >( nRowOrCol )] = sal_False;
+ nCount--;
+ }
+ nExt--;
+ nRowOrCol++;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+const SwSelBoxes *SwAccessibleTable::GetSelBoxes() const
+{
+ const SwSelBoxes *pSelBoxes = 0;
+ const SwCrsrShell *pCSh = GetCrsrShell();
+ if( (pCSh != NULL) && pCSh->IsTableMode() )
+ {
+ pSelBoxes = &pCSh->GetTableCrsr()->GetBoxes();
+ }
+
+ return pSelBoxes;
+}
+
+void SwAccessibleTable::FireTableChangeEvent(
+ const SwAccessibleTableData_Impl& rTableData )
+{
+ AccessibleTableModelChange aModelChange;
+ aModelChange.Type = AccessibleTableModelChangeType::UPDATE;
+ aModelChange.FirstRow = 0;
+ aModelChange.LastRow = rTableData.GetRowCount() - 1;
+ aModelChange.FirstColumn = 0;
+ aModelChange.LastColumn = rTableData.GetColumnCount() - 1;
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED;
+ aEvent.NewValue <<= aModelChange;
+
+ FireAccessibleEvent( aEvent );
+}
+
+
+const SwTableBox* SwAccessibleTable::GetTableBox( sal_Int32 nChildIndex ) const
+{
+ DBG_ASSERT( nChildIndex >= 0, "Illegal child index." );
+ // --> OD 2007-06-27 #i77106#
+ DBG_ASSERT( nChildIndex < const_cast<SwAccessibleTable*>(this)->getAccessibleChildCount(), "Illegal child index." );
+ // <--
+
+ const SwTableBox* pBox = NULL;
+
+ // get table box for 'our' table cell
+ SwAccessibleChild aCell( GetChild( *(const_cast<SwAccessibleMap*>(GetMap())), nChildIndex ) );
+ if( aCell.GetSwFrm() )
+ {
+ const SwFrm* pChildFrm = aCell.GetSwFrm();
+ if( (pChildFrm != NULL) && pChildFrm->IsCellFrm() )
+ {
+ const SwCellFrm* pCellFrm =
+ static_cast<const SwCellFrm*>( pChildFrm );
+ pBox = pCellFrm->GetTabBox();
+ }
+ }
+
+ DBG_ASSERT( pBox != NULL, "We need the table box." );
+ return pBox;
+}
+
+sal_Bool SwAccessibleTable::IsChildSelected( sal_Int32 nChildIndex ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwSelBoxes* pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ const SwTableBox* pBox = GetTableBox( nChildIndex );
+ DBG_ASSERT( pBox != NULL, "We need the table box." );
+ bRet = pSelBoxes->Seek_Entry( const_cast<SwTableBox*>( pBox ) );
+ }
+
+ return bRet;
+}
+
+sal_Int32 SwAccessibleTable::GetIndexOfSelectedChild(
+ sal_Int32 nSelectedChildIndex ) const
+{
+ // iterate over all children to n-th isAccessibleChildSelected()
+ // --> OD 2007-06-27 #i77106#
+ sal_Int32 nChildren = const_cast<SwAccessibleTable*>(this)->getAccessibleChildCount();
+ // <--
+ if( nSelectedChildIndex >= nChildren )
+ return -1L;
+
+ sal_Int32 n = 0;
+ while( n < nChildren )
+ {
+ if( IsChildSelected( n ) )
+ {
+ if( 0 == nSelectedChildIndex )
+ break;
+ else
+ --nSelectedChildIndex;
+ }
+ ++n;
+ }
+
+ return n < nChildren ? n : -1L;
+}
+
+void SwAccessibleTable::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // MULTISELECTABLE
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell )
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
+}
+
+SwAccessibleTable::SwAccessibleTable(
+ SwAccessibleMap* pInitMap,
+ const SwTabFrm* pTabFrm ) :
+ SwAccessibleContext( pInitMap, AccessibleRole::TABLE, pTabFrm ),
+ mpTableData( 0 )
+{
+ SolarMutexGuard aGuard;
+
+ const SwFrmFmt *pFrmFmt = pTabFrm->GetFmt();
+ const_cast< SwFrmFmt * >( pFrmFmt )->Add( this );
+ const String& rName = pFrmFmt->GetName();
+
+ OUStringBuffer aBuffer( rName.Len() + 4 );
+ aBuffer.append( OUString(rName) );
+ aBuffer.append( static_cast<sal_Unicode>( '-' ) );
+ aBuffer.append( static_cast<sal_Int32>( pTabFrm->GetPhyPageNum() ) );
+
+ SetName( aBuffer.makeStringAndClear() );
+
+ OUString sArg1( static_cast< const SwTabFrm * >( GetFrm() )
+ ->GetFmt()->GetName() );
+ OUString sArg2( GetFormattedPageNumber() );
+
+ sDesc = GetResource( STR_ACCESS_TABLE_DESC, &sArg1, &sArg2 );
+}
+
+SwAccessibleTable::~SwAccessibleTable()
+{
+ SolarMutexGuard aGuard;
+
+ delete mpTableData;
+}
+
+void SwAccessibleTable::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew)
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+ const SwTabFrm *pTabFrm = static_cast< const SwTabFrm * >( GetFrm() );
+ switch( nWhich )
+ {
+ case RES_NAME_CHANGED:
+ if( pTabFrm )
+ {
+ const SwFrmFmt *pFrmFmt = pTabFrm->GetFmt();
+ OSL_ENSURE( pFrmFmt == GetRegisteredIn(), "invalid frame" );
+
+ OUString sOldName( GetName() );
+
+ const String& rNewTabName = pFrmFmt->GetName();
+ OUStringBuffer aBuffer( rNewTabName.Len() + 4 );
+ aBuffer.append( OUString(rNewTabName) );
+ aBuffer.append( static_cast<sal_Unicode>( '-' ) );
+ aBuffer.append( static_cast<sal_Int32>( pTabFrm->GetPhyPageNum() ) );
+
+ SetName( aBuffer.makeStringAndClear() );
+ if( sOldName != GetName() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::NAME_CHANGED;
+ aEvent.OldValue <<= sOldName;
+ aEvent.NewValue <<= GetName();
+ FireAccessibleEvent( aEvent );
+ }
+
+ OUString sOldDesc( sDesc );
+ OUString sArg1( rNewTabName );
+ OUString sArg2( GetFormattedPageNumber() );
+
+ sDesc = GetResource( STR_ACCESS_TABLE_DESC, &sArg1, &sArg2 );
+ if( sDesc != sOldDesc )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
+ aEvent.OldValue <<= sOldDesc;
+ aEvent.NewValue <<= sDesc;
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ break;
+
+ case RES_OBJECTDYING:
+ if( GetRegisteredIn() ==
+ static_cast< SwModify *>( static_cast< SwPtrMsgPoolItem * >( pOld )->pObject ) )
+ pRegisteredIn->Remove( this );
+ break;
+
+ default:
+ SwClient::Modify( pOld, pNew );
+ break;
+ }
+}
+
+uno::Any SwAccessibleTable::queryInterface( const uno::Type& rType )
+ throw (uno::RuntimeException)
+{
+ uno::Any aRet;
+ if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleTable > * >( 0 ) ) )
+ {
+ uno::Reference<XAccessibleTable> xThis( this );
+ aRet <<= xThis;
+ }
+ else if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ) )
+ {
+ uno::Reference<XAccessibleSelection> xSelection( this );
+ aRet <<= xSelection;
+ }
+ else
+ {
+ aRet = SwAccessibleContext::queryInterface(rType);
+ }
+
+ return aRet;
+}
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleTable::getTypes()
+ throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ aTypes.realloc( nIndex + 2 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTable > * >( 0 ) );
+
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleTable::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+// --> OD 2007-06-28 #i77106#
+SwAccessibleTableData_Impl* SwAccessibleTable::CreateNewTableData()
+{
+ const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( GetFrm() );
+ return new SwAccessibleTableData_Impl( *GetMap(), pTabFrm, IsInPagePreview() );
+}
+// <--
+
+void SwAccessibleTable::UpdateTableData()
+{
+ // --> OD 2007-06-28 #i77106# - usage of new method <CreateNewTableData()>
+ delete mpTableData;
+ mpTableData = CreateNewTableData();
+ // <--
+}
+
+void SwAccessibleTable::ClearTableData()
+{
+ delete mpTableData;
+ mpTableData = 0;
+}
+
+OUString SAL_CALL SwAccessibleTable::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ return sDesc;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleRowCount()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ return GetTableData().GetRowCount();
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleColumnCount( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ return GetTableData().GetColumnCount();
+}
+
+OUString SAL_CALL SwAccessibleTable::getAccessibleRowDescription(
+ sal_Int32 nRow )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ // --> OD 2010-03-10 #i87532#
+ // determine table cell in <nRow>th row and in first column of row header table
+ // and return its text content.
+ OUString sRowDesc;
+
+ GetTableData().CheckRowAndCol(nRow, 0, this);
+
+ uno::Reference< XAccessibleTable > xTableRowHeader = getAccessibleRowHeaders();
+ if ( xTableRowHeader.is() )
+ {
+ uno::Reference< XAccessible > xRowHeaderCell =
+ xTableRowHeader->getAccessibleCellAt( nRow, 0 );
+ OSL_ENSURE( xRowHeaderCell.is(),
+ "<SwAccessibleTable::getAccessibleRowDescription(..)> - missing row header cell -> serious issue." );
+ uno::Reference< XAccessibleContext > xRowHeaderCellContext =
+ xRowHeaderCell->getAccessibleContext();
+ const sal_Int32 nCellChildCount( xRowHeaderCellContext->getAccessibleChildCount() );
+ for ( sal_Int32 nChildIndex = 0; nChildIndex < nCellChildCount; ++nChildIndex )
+ {
+ uno::Reference< XAccessible > xChild = xRowHeaderCellContext->getAccessibleChild( nChildIndex );
+ uno::Reference< XAccessibleText > xChildText( xChild, uno::UNO_QUERY );
+ if ( xChildText.is() )
+ {
+ sRowDesc = sRowDesc + xChildText->getText();
+ }
+ }
+ }
+
+ return sRowDesc;
+ // <--
+}
+
+OUString SAL_CALL SwAccessibleTable::getAccessibleColumnDescription(
+ sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ // --> OD 2010-03-10 #i87532#
+ // determine table cell in first row and in <nColumn>th column of column header table
+ // and return its text content.
+ OUString sColumnDesc;
+
+ GetTableData().CheckRowAndCol(0, nColumn, this);
+
+ uno::Reference< XAccessibleTable > xTableColumnHeader = getAccessibleColumnHeaders();
+ if ( xTableColumnHeader.is() )
+ {
+ uno::Reference< XAccessible > xColumnHeaderCell =
+ xTableColumnHeader->getAccessibleCellAt( 0, nColumn );
+ OSL_ENSURE( xColumnHeaderCell.is(),
+ "<SwAccessibleTable::getAccessibleColumnDescription(..)> - missing column header cell -> serious issue." );
+ uno::Reference< XAccessibleContext > xColumnHeaderCellContext =
+ xColumnHeaderCell->getAccessibleContext();
+ const sal_Int32 nCellChildCount( xColumnHeaderCellContext->getAccessibleChildCount() );
+ for ( sal_Int32 nChildIndex = 0; nChildIndex < nCellChildCount; ++nChildIndex )
+ {
+ uno::Reference< XAccessible > xChild = xColumnHeaderCellContext->getAccessibleChild( nChildIndex );
+ uno::Reference< XAccessibleText > xChildText( xChild, uno::UNO_QUERY );
+ if ( xChildText.is() )
+ {
+ sColumnDesc = sColumnDesc + xChildText->getText();
+ }
+ }
+ }
+
+ return sColumnDesc;
+ // <--
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleRowExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nExtend = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ GetTableData().CheckRowAndCol( nRow, nColumn, this );
+
+ Int32Set_Impl::const_iterator aSttCol(
+ GetTableData().GetColumnIter( nColumn ) );
+ Int32Set_Impl::const_iterator aSttRow(
+ GetTableData().GetRowIter( nRow ) );
+ const SwFrm *pCellFrm = GetTableData().GetCellAtPos( *aSttCol, *aSttRow,
+ sal_False );
+ if( pCellFrm )
+ {
+ sal_Int32 nBottom = pCellFrm->Frm().Bottom();
+ nBottom -= GetFrm()->Frm().Top();
+ Int32Set_Impl::const_iterator aEndRow(
+ GetTableData().GetRows().upper_bound( nBottom ) );
+ nExtend =
+ static_cast< sal_Int32 >( ::std::distance( aSttRow, aEndRow ) );
+ }
+
+ return nExtend;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleColumnExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nExtend = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ GetTableData().CheckRowAndCol( nRow, nColumn, this );
+
+ Int32Set_Impl::const_iterator aSttCol(
+ GetTableData().GetColumnIter( nColumn ) );
+ Int32Set_Impl::const_iterator aSttRow(
+ GetTableData().GetRowIter( nRow ) );
+ const SwFrm *pCellFrm = GetTableData().GetCellAtPos( *aSttCol, *aSttRow,
+ sal_False );
+ if( pCellFrm )
+ {
+ sal_Int32 nRight = pCellFrm->Frm().Right();
+ nRight -= GetFrm()->Frm().Left();
+ Int32Set_Impl::const_iterator aEndCol(
+ GetTableData().GetColumns().upper_bound( nRight ) );
+ nExtend =
+ static_cast< sal_Int32 >( ::std::distance( aSttCol, aEndCol ) );
+ }
+
+ return nExtend;
+}
+
+uno::Reference< XAccessibleTable > SAL_CALL
+ SwAccessibleTable::getAccessibleRowHeaders( )
+ throw (uno::RuntimeException)
+{
+ // Row headers aren't supported
+ return uno::Reference< XAccessibleTable >();
+}
+
+uno::Reference< XAccessibleTable > SAL_CALL
+ SwAccessibleTable::getAccessibleColumnHeaders( )
+ throw (uno::RuntimeException)
+{
+ // --> OD 2010-03-10 #i87532#
+ // assure that return accesible object is empty, if no column header exists.
+ SwAccessibleTableColHeaders* pTableColHeaders =
+ new SwAccessibleTableColHeaders( GetMap(), static_cast< const SwTabFrm *>( GetFrm() ) );
+ uno::Reference< XAccessibleTable > xTableColumnHeaders( pTableColHeaders );
+ if ( pTableColHeaders->getAccessibleChildCount() <= 0 )
+ {
+ return uno::Reference< XAccessibleTable >();
+ }
+
+ return xTableColumnHeaders;
+ // <--
+}
+
+uno::Sequence< sal_Int32 > SAL_CALL SwAccessibleTable::getSelectedAccessibleRows()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ sal_Int32 nRows = GetTableData().GetRowCount();
+ SwAccAllTableSelHander_Impl aSelRows( nRows );
+
+ GetTableData().GetSelection( 0, nRows, *pSelBoxes, aSelRows,
+ sal_False );
+
+ return aSelRows.GetSelSequence();
+ }
+ else
+ {
+ return uno::Sequence< sal_Int32 >( 0 );
+ }
+}
+
+uno::Sequence< sal_Int32 > SAL_CALL SwAccessibleTable::getSelectedAccessibleColumns()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ sal_Int32 nCols = GetTableData().GetColumnCount();
+ SwAccAllTableSelHander_Impl aSelCols( nCols );
+
+ GetTableData().GetSelection( 0, nCols, *pSelBoxes, aSelCols, sal_True );
+
+ return aSelCols.GetSelSequence();
+ }
+ else
+ {
+ return uno::Sequence< sal_Int32 >( 0 );
+ }
+}
+
+sal_Bool SAL_CALL SwAccessibleTable::isAccessibleRowSelected( sal_Int32 nRow )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ GetTableData().CheckRowAndCol( nRow, 0, this );
+
+ sal_Bool bRet;
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ SwAccSingleTableSelHander_Impl aSelRow;
+ GetTableData().GetSelection( nRow, nRow+1, *pSelBoxes, aSelRow,
+ sal_False );
+ bRet = aSelRow.IsSelected();
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+sal_Bool SAL_CALL SwAccessibleTable::isAccessibleColumnSelected(
+ sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ GetTableData().CheckRowAndCol( 0, nColumn, this );
+
+ sal_Bool bRet;
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ SwAccSingleTableSelHander_Impl aSelCol;
+
+ GetTableData().GetSelection( nColumn, nColumn+1, *pSelBoxes, aSelCol,
+ sal_True );
+ bRet = aSelCol.IsSelected();
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleTable::getAccessibleCellAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< XAccessible > xRet;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ const SwFrm *pCellFrm =
+ GetTableData().GetCell( nRow, nColumn, sal_False, this );
+ if( pCellFrm )
+ xRet = GetMap()->GetContext( pCellFrm, sal_True );
+
+ return xRet;
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleTable::getAccessibleCaption()
+ throw (uno::RuntimeException)
+{
+ // captions aren't supported
+ return uno::Reference< XAccessible >();
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleTable::getAccessibleSummary()
+ throw (uno::RuntimeException)
+{
+ // summaries aren't supported
+ return uno::Reference< XAccessible >();
+}
+
+sal_Bool SAL_CALL SwAccessibleTable::isAccessibleSelected(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Bool bRet = sal_False;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ const SwFrm *pFrm =
+ GetTableData().GetCell( nRow, nColumn, sal_False, this );
+ if( pFrm && pFrm->IsCellFrm() )
+ {
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ const SwCellFrm *pCFrm = static_cast < const SwCellFrm * >( pFrm );
+ SwTableBox *pBox =
+ const_cast< SwTableBox *>( pCFrm->GetTabBox() ); //SVPtrArr!
+ bRet = pSelBoxes->Seek_Entry( pBox );
+ }
+ }
+
+ return bRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleIndex(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nRet = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ SwAccessibleChild aCell( GetTableData().GetCell( nRow, nColumn, sal_False, this ));
+ if ( aCell.IsValid() )
+ {
+ nRet = GetChildIndex( *(GetMap()), aCell );
+ }
+
+ return nRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleRow( sal_Int32 nChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nRet = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ // --> OD 2007-06-27 #i77106#
+ if ( ( nChildIndex < 0 ) ||
+ ( nChildIndex >= getAccessibleChildCount() ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+ // <--
+
+ SwAccessibleChild aCell( GetChild( *(GetMap()), nChildIndex ) );
+ if ( aCell.GetSwFrm() )
+ {
+ sal_Int32 nTop = aCell.GetSwFrm()->Frm().Top();
+ nTop -= GetFrm()->Frm().Top();
+ Int32Set_Impl::const_iterator aRow(
+ GetTableData().GetRows().lower_bound( nTop ) );
+ nRet = static_cast< sal_Int32 >( ::std::distance(
+ GetTableData().GetRows().begin(), aRow ) );
+ }
+ else
+ {
+ OSL_ENSURE( !aCell.IsValid(), "SwAccessibleTable::getAccessibleColumn:"
+ "aCell not expected to be valid.");
+
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ return nRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleColumn(
+ sal_Int32 nChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nRet = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ // --> OD 2007-06-27 #i77106#
+ if ( ( nChildIndex < 0 ) ||
+ ( nChildIndex >= getAccessibleChildCount() ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+ // <--
+
+ SwAccessibleChild aCell( GetChild( *(GetMap()), nChildIndex ) );
+ if ( aCell.GetSwFrm() )
+ {
+ sal_Int32 nLeft = aCell.GetSwFrm()->Frm().Left();
+ nLeft -= GetFrm()->Frm().Left();
+ Int32Set_Impl::const_iterator aCol(
+ GetTableData().GetColumns().lower_bound( nLeft ) );
+ nRet = static_cast< sal_Int32 >( ::std::distance(
+ GetTableData().GetColumns().begin(), aCol ) );
+ }
+ else
+ {
+ OSL_ENSURE( !aCell.IsValid(), "SwAccessibleTable::getAccessibleColumn:"
+ "aCell not expected to be valid.");
+
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ return nRet;
+}
+
+
+OUString SAL_CALL SwAccessibleTable::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleTable::supportsService(
+ const OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleTable::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+void SwAccessibleTable::InvalidatePosOrSize( const SwRect& rOldBox )
+{
+ SolarMutexGuard aGuard;
+
+ if( HasTableData() )
+ GetTableData().SetTablePos( GetFrm()->Frm().Pos() );
+
+ SwAccessibleContext::InvalidatePosOrSize( rOldBox );
+}
+
+void SwAccessibleTable::Dispose( sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ if( GetRegisteredIn() )
+ pRegisteredIn->Remove( this );
+
+ SwAccessibleContext::Dispose( bRecursive );
+}
+
+void SwAccessibleTable::DisposeChild( const SwAccessibleChild& rChildFrmOrObj,
+ sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ const SwFrm *pFrm = rChildFrmOrObj.GetSwFrm();
+ OSL_ENSURE( pFrm, "frame expected" );
+ if( HasTableData() )
+ {
+ FireTableChangeEvent( GetTableData() );
+ ClearTableData();
+ }
+
+ // There are two reason why this method has been called. The first one
+ // is there is no context for pFrm. The method is them called by
+ // the map, and we have to call our superclass.
+ // The other situation is that we have been call by a call to get notified
+ // about its change. We then must not call the superclass
+ uno::Reference< XAccessible > xAcc( GetMap()->GetContext( pFrm, sal_False ) );
+ if( !xAcc.is() )
+ SwAccessibleContext::DisposeChild( rChildFrmOrObj, bRecursive );
+}
+
+void SwAccessibleTable::InvalidateChildPosOrSize( const SwAccessibleChild& rChildFrmOrObj,
+ const SwRect& rOldBox )
+{
+ SolarMutexGuard aGuard;
+
+ if( HasTableData() )
+ {
+ OSL_ENSURE( !HasTableData() ||
+ GetFrm()->Frm().Pos() == GetTableData().GetTablePos(),
+ "table has invalid position" );
+ if( HasTableData() )
+ {
+ // --> OD 2007-06-28 #i77106#
+ SwAccessibleTableData_Impl *pNewTableData = CreateNewTableData();
+ // <--
+ if( !pNewTableData->CompareExtents( GetTableData() ) )
+ {
+ FireTableChangeEvent( GetTableData() );
+ ClearTableData();
+ mpTableData = pNewTableData;
+ }
+ else
+ {
+ delete pNewTableData;
+ }
+ }
+ }
+
+ // --> OD 2010-02-18 #i013961# - always call super class method
+ SwAccessibleContext::InvalidateChildPosOrSize( rChildFrmOrObj, rOldBox );
+ // <--
+}
+
+
+//
+// XAccessibleSelection
+//
+
+void SAL_CALL SwAccessibleTable::selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ // --> OD 2007-06-27 #i77106#
+ if( (nChildIndex < 0) || (nChildIndex >= getAccessibleChildCount()) )
+ // <--
+ throw lang::IndexOutOfBoundsException();
+
+ // preliminaries: get 'our' table box, and get the cursor shell
+ const SwTableBox* pBox = GetTableBox( nChildIndex );
+ DBG_ASSERT( pBox != NULL, "We need the table box." );
+
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell == NULL )
+ return;
+
+ // --> OD 2004-11-16 #111714# - assure, that child, indentified by the given
+ // index, isn't already selected.
+ if ( IsChildSelected( nChildIndex ) )
+ {
+ return;
+ }
+ // <--
+
+ // now we can start to do the work: check whether we already have
+ // a table selection (in 'our' table). If so, extend the
+ // selection, else select the current cell.
+
+ // if we have a selection in a table, check if it's in the
+ // same table that we're trying to select in
+ const SwTableNode* pSelectedTable = pCrsrShell->IsCrsrInTbl();
+ if( pSelectedTable != NULL )
+ {
+ // get top-most table line
+ const SwTableLine* pUpper = pBox->GetUpper();
+ while( pUpper->GetUpper() != NULL )
+ pUpper = pUpper->GetUpper()->GetUpper();
+ USHORT nPos =
+ pSelectedTable->GetTable().GetTabLines().GetPos( pUpper );
+ if( nPos == USHRT_MAX )
+ pSelectedTable = NULL;
+ }
+
+ // create the new selection
+ const SwStartNode* pStartNode = pBox->GetSttNd();
+ if( pSelectedTable == NULL || !pCrsrShell->GetTblCrs() )
+ {
+ // if we're in the wrong table, or there's no table selection
+ // at all, then select the current table cell.
+// SwPaM* pPaM = pCrsrShell->GetCrsr();
+// pPaM->DeleteMark();
+// *(pPaM->GetPoint()) = SwPosition( *pStartNode );
+// pPaM->Move( fnMoveForward, fnGoNode );
+// // pCrsrShell->SelTblBox();
+
+ pCrsrShell->StartAction();
+ // Set cursor into current cell. This deletes any table cursor.
+ SwPaM aPaM( *pStartNode );
+ aPaM.Move( fnMoveForward, fnGoNode );
+ Select( aPaM );
+ // Move cursor to the end of the table creating a selection and a table
+ // cursor.
+ pCrsrShell->SetMark();
+ pCrsrShell->MoveTable( fnTableCurr, fnTableEnd );
+ // now set the cursor into the cell again.
+ SwPaM *pPaM = pCrsrShell->GetTblCrs() ? pCrsrShell->GetTblCrs()
+ : pCrsrShell->GetCrsr();
+ *pPaM->GetPoint() = *pPaM->GetMark();
+ pCrsrShell->EndAction();
+ // we now have one cell selected!
+ }
+ else
+ {
+ // if the cursor is already in this table,
+ // expand the current selection (i.e., set
+ // point to new position; keep mark)
+ SwPaM aPaM( *pStartNode );
+ aPaM.Move( fnMoveForward, fnGoNode );
+ aPaM.SetMark();
+ const SwPaM *pPaM = pCrsrShell->GetTblCrs() ? pCrsrShell->GetTblCrs()
+ : pCrsrShell->GetCrsr();
+ *(aPaM.GetMark()) = *pPaM->GetMark();
+ Select( aPaM );
+
+ // if only one box is selected, we select this one in
+ // order to maintain our table selection
+// if( aPaM.GetPoint()->nNode.GetNode().FindTableBoxStartNode() ==
+// aPaM.GetMark()->nNode.GetNode().FindTableBoxStartNode() )
+// {
+// // pCrsrShell->SelTblBox();
+// }
+// else
+// {
+ // finally; set the selection. This will call UpdateCursor
+ // on the cursor shell, too.
+// pCrsrShell->KillPams();
+ // pCrsrShell->SetSelection( aPaM );
+// }
+ }
+}
+
+
+sal_Bool SAL_CALL SwAccessibleTable::isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ // --> OD 2007-06-27 #i77106#
+ if( (nChildIndex < 0) || (nChildIndex >= getAccessibleChildCount()) )
+ // <--
+ throw lang::IndexOutOfBoundsException();
+
+ return IsChildSelected( nChildIndex );
+}
+
+void SAL_CALL SwAccessibleTable::clearAccessibleSelection( )
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell != NULL )
+ {
+ pCrsrShell->StartAction();
+ pCrsrShell->ClearMark();
+ pCrsrShell->EndAction();
+ }
+}
+
+void SAL_CALL SwAccessibleTable::selectAllAccessibleChildren( )
+ throw ( uno::RuntimeException )
+{
+ // first clear selection, then select first and last child
+ clearAccessibleSelection();
+ selectAccessibleChild( 0 );
+ // --> OD 2007-06-27 #i77106#
+ selectAccessibleChild( getAccessibleChildCount()-1 );
+ // <--
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getSelectedAccessibleChildCount( )
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ // iterate over all children and count isAccessibleChildSelected()
+ sal_Int32 nCount = 0;
+
+ // --> OD 2007-06-27 #i71106#
+ sal_Int32 nChildren = getAccessibleChildCount();
+ // <--
+ for( sal_Int32 n = 0; n < nChildren; n++ )
+ if( IsChildSelected( n ) )
+ nCount++;
+
+ return nCount;
+}
+
+uno::Reference<XAccessible> SAL_CALL SwAccessibleTable::getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ // paremter checking (part 1): index lower 0
+ if( nSelectedChildIndex < 0 )
+ throw lang::IndexOutOfBoundsException();
+
+ sal_Int32 nChildIndex = GetIndexOfSelectedChild( nSelectedChildIndex );
+
+ // parameter checking (part 2): index higher than selected children?
+ if( nChildIndex < 0 )
+ throw lang::IndexOutOfBoundsException();
+
+ // --> OD 2007-06-28 #i77106#
+ if ( nChildIndex >= getAccessibleChildCount() )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+ // <--
+
+ return getAccessibleChild( nChildIndex );
+}
+
+// --> OD 2004-11-16 #111714# - index has to be treated as global child index.
+void SAL_CALL SwAccessibleTable::deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+
+ // --> OD 2004-11-16 #111714# - index has to be treated as global child index
+ if ( !pCrsrShell )
+ throw lang::IndexOutOfBoundsException();
+
+ // assure, that given child index is in bounds.
+ // --> OD 2007-06-27 #i77106#
+ if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
+ // <--
+ throw lang::IndexOutOfBoundsException();
+
+ // assure, that child, identified by the given index, is selected.
+ if ( !IsChildSelected( nChildIndex ) )
+ return;
+ // <--
+
+ const SwTableBox* pBox = GetTableBox( nChildIndex );
+ DBG_ASSERT( pBox != NULL, "We need the table box." );
+
+ // If we unselect point, then set cursor to mark. If we clear another
+ // selected box, then set cursor to point.
+ // reduce selection to mark.
+ SwPaM *pPaM = pCrsrShell->GetTblCrs() ? pCrsrShell->GetTblCrs()
+ : pCrsrShell->GetCrsr();
+ sal_Bool bDeselectPoint =
+ pBox->GetSttNd() ==
+ pPaM->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+
+ SwPaM aPaM( bDeselectPoint ? *pPaM->GetMark() : *pPaM->GetPoint() );
+
+ pCrsrShell->StartAction();
+
+ // Set cursor into either point or mark
+ Select( aPaM );
+ // Move cursor to the end of the table creating a selection and a table
+ // cursor.
+ pCrsrShell->SetMark();
+ pCrsrShell->MoveTable( fnTableCurr, fnTableEnd );
+ // now set the cursor into the cell again.
+ pPaM = pCrsrShell->GetTblCrs() ? pCrsrShell->GetTblCrs()
+ : pCrsrShell->GetCrsr();
+ *pPaM->GetPoint() = *pPaM->GetMark();
+ pCrsrShell->EndAction();
+}
+
+// --> OD 2007-06-28 #i77106#
+// implementation of class <SwAccessibleTableColHeaders>
+SwAccessibleTableColHeaders::SwAccessibleTableColHeaders( SwAccessibleMap *pMap2,
+ const SwTabFrm *pTabFrm )
+ : SwAccessibleTable( pMap2, pTabFrm )
+{
+ SolarMutexGuard aGuard;
+
+ const SwFrmFmt *pFrmFmt = pTabFrm->GetFmt();
+ const_cast< SwFrmFmt * >( pFrmFmt )->Add( this );
+ const String& rName = pFrmFmt->GetName();
+
+ OUStringBuffer aBuffer( rName.Len() + 15 + 6 );
+ aBuffer.append( OUString(rName) );
+ aBuffer.append( String::CreateFromAscii("-ColumnHeaders-") );
+ aBuffer.append( static_cast<sal_Int32>( pTabFrm->GetPhyPageNum() ) );
+
+ SetName( aBuffer.makeStringAndClear() );
+
+ OUStringBuffer aBuffer2( rName.Len() + 14 );
+ aBuffer2.append( OUString(rName) );
+ aBuffer2.append( String::CreateFromAscii("-ColumnHeaders") );
+ OUString sArg1( aBuffer2.makeStringAndClear() );
+ OUString sArg2( GetFormattedPageNumber() );
+
+ OUString sDesc2 = GetResource( STR_ACCESS_TABLE_DESC, &sArg1, &sArg2 );
+ SetDesc( sDesc2 );
+
+ // --> OD 2008-03-10 #i85634#
+ NotRegisteredAtAccessibleMap();
+ // <--
+}
+
+SwAccessibleTableData_Impl* SwAccessibleTableColHeaders::CreateNewTableData()
+{
+ const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( GetFrm() );
+ return new SwAccessibleTableData_Impl( *(GetMap()), pTabFrm, IsInPagePreview(), true );
+}
+
+
+void SwAccessibleTableColHeaders::Modify( SfxPoolItem * /*pOld*/, SfxPoolItem * /*pNew*/ )
+{
+}
+
+//===== XInterface ======================================================
+uno::Any SAL_CALL SwAccessibleTableColHeaders::queryInterface( const uno::Type& aType )
+ throw (uno::RuntimeException)
+{
+ return SwAccessibleTable::queryInterface( aType );
+}
+
+//===== XAccessibleContext ==============================================
+sal_Int32 SAL_CALL SwAccessibleTableColHeaders::getAccessibleChildCount(void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ sal_Int32 nCount = 0;
+
+ const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( GetFrm() );
+ const SwAccessibleChildSList aVisList( GetVisArea(), *pTabFrm, *(GetMap()) );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( IsInPagePreview() ) )
+ {
+ nCount++;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ if ( !rLower.GetSwFrm()->IsRowFrm() ||
+ pTabFrm->IsInHeadline( *(rLower.GetSwFrm()) ) )
+ {
+ nCount += SwAccessibleFrame::GetChildCount( *(GetMap()),
+ GetVisArea(),
+ rLower.GetSwFrm(),
+ IsInPagePreview() );
+ }
+ }
+ ++aIter;
+ }
+
+ return nCount;
+}
+
+uno::Reference< XAccessible> SAL_CALL
+ SwAccessibleTableColHeaders::getAccessibleChild (sal_Int32 nIndex)
+ throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ if ( nIndex < 0 || nIndex >= getAccessibleChildCount() )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ return SwAccessibleTable::getAccessibleChild( nIndex );
+}
+
+//===== XAccessibleTable ================================================
+uno::Reference< XAccessibleTable >
+ SAL_CALL SwAccessibleTableColHeaders::getAccessibleRowHeaders()
+ throw (uno::RuntimeException)
+{
+ return uno::Reference< XAccessibleTable >();
+}
+
+uno::Reference< XAccessibleTable >
+ SAL_CALL SwAccessibleTableColHeaders::getAccessibleColumnHeaders()
+ throw (uno::RuntimeException)
+{
+ return uno::Reference< XAccessibleTable >();
+}
+
+//===== XServiceInfo ====================================================
+
+::rtl::OUString SAL_CALL SwAccessibleTableColHeaders::getImplementationName (void)
+ throw (uno::RuntimeException)
+{
+ static const sal_Char sImplName[] = "com.sun.star.comp.Writer.SwAccessibleTableColumnHeadersView";
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplName));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acctable.hxx b/sw/source/core/access/acctable.hxx
new file mode 100644
index 000000000000..7bff387b6092
--- /dev/null
+++ b/sw/source/core/access/acctable.hxx
@@ -0,0 +1,335 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCTABLE_HXX
+#define _ACCTABLE_HXX
+#include <com/sun/star/accessibility/XAccessibleTable.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+
+#include <acccontext.hxx>
+
+class SwTabFrm;
+class SwAccessibleTableData_Impl;
+class SwTableBox;
+class SwSelBoxes;
+
+namespace sw { namespace access {
+ class SwAccessibleChild;
+} }
+
+class SwAccessibleTable :
+ public SwAccessibleContext,
+ public ::com::sun::star::accessibility::XAccessibleTable,
+ public ::com::sun::star::accessibility::XAccessibleSelection,
+ public SwClient
+{
+ SwAccessibleTableData_Impl *mpTableData; // the table's data, prot by Sol-Mutex
+ ::rtl::OUString sDesc;
+ const SwSelBoxes *GetSelBoxes() const;
+
+ void FireTableChangeEvent( const SwAccessibleTableData_Impl& rTableData );
+
+ /** get the SwTableBox* for the given child */
+ const SwTableBox* GetTableBox( sal_Int32 ) const;
+
+ sal_Bool IsChildSelected( sal_Int32 nChildIndex ) const;
+
+ sal_Int32 GetIndexOfSelectedChild( sal_Int32 nSelectedChildIndex ) const;
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additinaly sets MULTISELECTABLE(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual ~SwAccessibleTable();
+
+ // --> OD 2007-06-27 #i77106#
+ inline void SetDesc( ::rtl::OUString sNewDesc )
+ {
+ sDesc = sNewDesc;
+ }
+
+ // --> OD 2007-06-28 #i77106#
+ virtual SwAccessibleTableData_Impl* CreateNewTableData();
+ // <--
+
+ // force update of table data
+ void UpdateTableData();
+
+ // remove the current table data
+ void ClearTableData();
+
+ // get table data, update if necessary
+ inline SwAccessibleTableData_Impl& GetTableData();
+
+ // Is table data evailable?
+ sal_Bool HasTableData() const { return (mpTableData != 0); }
+
+public:
+
+ SwAccessibleTable( SwAccessibleMap* pInitMap, const SwTabFrm* pTableFrm );
+
+ virtual void Modify( SfxPoolItem *pOld, SfxPoolItem *pNew);
+
+ //===== XInterface ======================================================
+
+ // (XInterface methods need to be implemented to disambigouate
+ // between those inherited through SwAcessibleContext and
+ // XAccessibleTable).
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleTable ================================================
+
+ virtual sal_Int32 SAL_CALL getAccessibleRowCount()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleColumnCount( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleRowDescription(
+ sal_Int32 nRow )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleColumnDescription(
+ sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleRowExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleColumnExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleTable >
+ SAL_CALL getAccessibleRowHeaders( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleTable >
+ SAL_CALL getAccessibleColumnHeaders( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL
+ getSelectedAccessibleRows( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL
+ getSelectedAccessibleColumns( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isAccessibleRowSelected( sal_Int32 nRow )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isAccessibleColumnSelected( sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL
+ getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL
+ getAccessibleCaption( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL
+ getAccessibleSummary( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isAccessibleSelected(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleIndex(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleRow( sal_Int32 nChildIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleColumn( sal_Int32 nChildIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== C++ interface ======================================================
+
+ // The object has been moved by the layout
+ virtual void InvalidatePosOrSize( const SwRect& rOldBox );
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+
+ virtual void DisposeChild( const sw::access::SwAccessibleChild& rFrmOrObj,
+ sal_Bool bRecursive );
+ virtual void InvalidateChildPosOrSize( const sw::access::SwAccessibleChild& rFrmOrObj,
+ const SwRect& rFrm );
+
+ //===== XAccessibleSelection ============================================
+
+ virtual void SAL_CALL selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Bool SAL_CALL isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual void SAL_CALL clearAccessibleSelection( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual void SAL_CALL selectAllAccessibleChildren( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // --> OD 2004-11-16 #111714# - index has to be treated as global child index.
+ virtual void SAL_CALL deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+};
+
+inline SwAccessibleTableData_Impl& SwAccessibleTable::GetTableData()
+{
+ if( !mpTableData )
+ UpdateTableData();
+ return *mpTableData;
+}
+
+// --> OD 2007-06-28 #i77106#
+// subclass to represent table column headers
+class SwAccessibleTableColHeaders : public SwAccessibleTable
+{
+protected:
+
+ virtual ~SwAccessibleTableColHeaders()
+ {}
+
+ virtual SwAccessibleTableData_Impl* CreateNewTableData();
+
+public:
+
+ SwAccessibleTableColHeaders( SwAccessibleMap *pMap, const SwTabFrm *pTabFrm );
+
+ virtual void Modify( SfxPoolItem *pOld, SfxPoolItem *pNew);
+
+ //===== XInterface ======================================================
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return the number of currently visible children.
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the specified child or NULL if index is invalid.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleChild (sal_Int32 nIndex)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IndexOutOfBoundsException);
+
+ //===== XAccessibleTable ================================================
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleTable >
+ SAL_CALL getAccessibleRowHeaders( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleTable >
+ SAL_CALL getAccessibleColumnHeaders( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+};
+// <--
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acctextframe.cxx b/sw/source/core/access/acctextframe.cxx
new file mode 100644
index 000000000000..8d520323eda2
--- /dev/null
+++ b/sw/source/core/access/acctextframe.cxx
@@ -0,0 +1,281 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <rtl/uuid.h>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleRelation.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <frmfmt.hxx>
+#include <flyfrm.hxx>
+#include <accmap.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+// --> OD 2009-07-14 #i73249#
+#include <hints.hxx>
+// <--
+#include "acctextframe.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+using utl::AccessibleRelationSetHelper;
+using ::com::sun::star::accessibility::XAccessibleContext;
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextFrameView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleTextFrameView";
+
+SwAccessibleTextFrame::SwAccessibleTextFrame(
+ SwAccessibleMap* pInitMap,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleFrameBase( pInitMap, AccessibleRole::TEXT_FRAME, pFlyFrm ),
+ msTitle(),
+ msDesc()
+{
+ if ( pFlyFrm )
+ {
+ const SwFlyFrmFmt* pFlyFrmFmt =
+ dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
+ msTitle = pFlyFrmFmt->GetObjTitle();
+
+ msDesc = pFlyFrmFmt->GetObjDescription();
+ if ( msDesc.getLength() == 0 &&
+ msTitle != GetName() )
+ {
+ msDesc = msTitle;
+ }
+ }
+}
+
+SwAccessibleTextFrame::~SwAccessibleTextFrame()
+{
+}
+
+void SwAccessibleTextFrame::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew)
+{
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+ // --> OD 2009-07-14 #i73249#
+ // suppress handling of RES_NAME_CHANGED in case that attribute Title is
+ // used as the accessible name.
+ if ( nWhich != RES_NAME_CHANGED ||
+ msTitle.getLength() == 0 )
+ {
+ SwAccessibleFrameBase::Modify( pOld, pNew );
+ }
+
+ const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( GetFrm() );
+ switch( nWhich )
+ {
+ // --> OD 2009-07-14 #i73249#
+ case RES_TITLE_CHANGED:
+ {
+ const String& sOldTitle(
+ dynamic_cast<SwStringMsgPoolItem*>(pOld)->GetString() );
+ const String& sNewTitle(
+ dynamic_cast<SwStringMsgPoolItem*>(pNew)->GetString() );
+ if ( sOldTitle == sNewTitle )
+ {
+ break;
+ }
+ msTitle = sNewTitle;
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::NAME_CHANGED;
+ aEvent.OldValue <<= OUString( sOldTitle );
+ aEvent.NewValue <<= msTitle;
+ FireAccessibleEvent( aEvent );
+
+ const SwFlyFrmFmt* pFlyFrmFmt =
+ dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
+ if ( pFlyFrmFmt->GetObjDescription().Len() != 0 )
+ {
+ break;
+ }
+ }
+ // intentional no break here
+ case RES_DESCRIPTION_CHANGED:
+ {
+ if ( pFlyFrm )
+ {
+ const OUString sOldDesc( msDesc );
+
+ const SwFlyFrmFmt* pFlyFrmFmt =
+ dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
+ const String& rDesc = pFlyFrmFmt->GetObjDescription();
+ msDesc = rDesc;
+ if ( msDesc.getLength() == 0 &&
+ msTitle != GetName() )
+ {
+ msDesc = msTitle;
+ }
+
+ if ( msDesc != sOldDesc )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
+ aEvent.OldValue <<= sOldDesc;
+ aEvent.NewValue <<= msDesc;
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ }
+ break;
+ // <--
+ }
+}
+
+// --> OD 2009-07-14 #i73249#
+OUString SAL_CALL SwAccessibleTextFrame::getAccessibleName (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ if ( msTitle.getLength() != 0 )
+ {
+ return msTitle;
+ }
+
+ return SwAccessibleFrameBase::getAccessibleName();
+}
+// <--
+OUString SAL_CALL SwAccessibleTextFrame::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ return msDesc;
+
+}
+
+OUString SAL_CALL SwAccessibleTextFrame::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleTextFrame::supportsService(
+ const OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleTextFrame::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleTextFrame::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+
+//
+// XAccessibleRelationSet
+//
+
+
+SwFlyFrm* SwAccessibleTextFrame::getFlyFrm() const
+{
+ SwFlyFrm* pFlyFrm = NULL;
+
+ const SwFrm* pFrm = GetFrm();
+ DBG_ASSERT( pFrm != NULL, "frame expected" );
+ if( pFrm->IsFlyFrm() )
+ {
+ pFlyFrm = static_cast<SwFlyFrm*>( const_cast<SwFrm*>( pFrm ) );
+ }
+
+ return pFlyFrm;
+}
+
+AccessibleRelation SwAccessibleTextFrame::makeRelation( sal_Int16 nType, const SwFlyFrm* pFrm )
+{
+ uno::Sequence<uno::Reference<XInterface> > aSequence(1);
+ aSequence[0] = GetMap()->GetContext( pFrm );
+ return AccessibleRelation( nType, aSequence );
+}
+
+
+uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleTextFrame::getAccessibleRelationSet( )
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ // get the frame, and insert prev/next relations into helper
+
+ AccessibleRelationSetHelper* pHelper = new AccessibleRelationSetHelper();
+
+ SwFlyFrm* pFlyFrm = getFlyFrm();
+ DBG_ASSERT( pFlyFrm != NULL, "fly frame expected" );
+
+ const SwFlyFrm* pPrevFrm = pFlyFrm->GetPrevLink();
+ if( pPrevFrm != NULL )
+ pHelper->AddRelation( makeRelation(
+ AccessibleRelationType::CONTENT_FLOWS_FROM, pPrevFrm ) );
+
+ const SwFlyFrm* pNextFrm = pFlyFrm->GetNextLink();
+ if( pNextFrm != NULL )
+ pHelper->AddRelation( makeRelation(
+ AccessibleRelationType::CONTENT_FLOWS_TO, pNextFrm ) );
+
+ return pHelper;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acctextframe.hxx b/sw/source/core/access/acctextframe.hxx
new file mode 100644
index 000000000000..e8d0bd47cc9e
--- /dev/null
+++ b/sw/source/core/access/acctextframe.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCTEXTFRAME_HXX
+#define _ACCTEXTFRAME_HXX
+#include "accframebase.hxx"
+
+class SwFlyFrm;
+namespace utl { class AccessibleRelationSetHelper; }
+namespace com { namespace star {
+ namespace accessibility { struct AccessibleRelation; }
+} }
+
+class SwAccessibleTextFrame : public SwAccessibleFrameBase
+{
+private:
+ // --> OD 2009-07-14 #i73249#
+ ::rtl::OUString msTitle;
+ ::rtl::OUString msDesc;
+ // <--
+
+protected:
+
+ virtual ~SwAccessibleTextFrame();
+
+public:
+
+ SwAccessibleTextFrame( SwAccessibleMap* pInitMap, const SwFlyFrm* pFlyFrm );
+
+ virtual void Modify( SfxPoolItem *pOld, SfxPoolItem *pNew);
+
+
+ //===== XAccessibleContext ==============================================
+
+ // --> OD 2009-07-14 #i73249#
+ /// Return the object's current name.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+ // <--
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+
+ //===== XAccessibleContext::getAccessibleRelationSet ====================
+
+ // text frame may have accessible relations to their
+ // predocesor/successor frames
+
+private:
+ // helper methods for getAccessibleRelationSet:
+ SwFlyFrm* getFlyFrm() const;
+
+ com::sun::star::accessibility::AccessibleRelation makeRelation(
+ sal_Int16 nType, const SwFlyFrm* pFrm );
+
+public:
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleRelationSet> SAL_CALL
+ getAccessibleRelationSet (void)
+ throw (::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/makefile.mk b/sw/source/core/access/makefile.mk
new file mode 100644
index 000000000000..72871314f722
--- /dev/null
+++ b/sw/source/core/access/makefile.mk
@@ -0,0 +1,100 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=sw
+TARGET=access
+
+# --- Settings -----------------------------------------------------
+#ENABLE_EXCEPTIONS=TRUE
+
+.INCLUDE : $(PRJ)$/inc$/swpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/inc$/sw.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/acccell.obj \
+ $(SLO)$/acccontext.obj \
+ $(SLO)$/accdoc.obj \
+ $(SLO)$/accembedded.obj \
+ $(SLO)$/accfootnote.obj \
+ $(SLO)$/accframe.obj \
+ $(SLO)$/accframebase.obj \
+ $(SLO)$/accfrmobj.obj \
+ $(SLO)$/accfrmobjmap.obj \
+ $(SLO)$/accfrmobjslist.obj \
+ $(SLO)$/accgraphic.obj \
+ $(SLO)$/accheaderfooter.obj \
+ $(SLO)$/acchyperlink.obj \
+ $(SLO)$/acchypertextdata.obj \
+ $(SLO)$/accmap.obj \
+ $(SLO)$/accnotextframe.obj \
+ $(SLO)$/accpage.obj \
+ $(SLO)$/accpara.obj \
+ $(SLO)$/accportions.obj \
+ $(SLO)$/accpreview.obj \
+ $(SLO)$/accselectionhelper.obj \
+ $(SLO)$/acctable.obj \
+ $(SLO)$/acctextframe.obj \
+ $(SLO)$/textmarkuphelper.obj \
+ $(SLO)$/parachangetrackinginfo.obj
+
+EXCEPTIONSFILES= \
+ $(SLO)$/acccell.obj \
+ $(SLO)$/acccontext.obj \
+ $(SLO)$/accdoc.obj \
+ $(SLO)$/accembedded.obj \
+ $(SLO)$/accfootnote.obj \
+ $(SLO)$/accframe.obj \
+ $(SLO)$/accframebase.obj \
+ $(SLO)$/accfrmobj.obj \
+ $(SLO)$/accfrmobjmap.obj \
+ $(SLO)$/accfrmobjslist.obj \
+ $(SLO)$/accgraphic.obj \
+ $(SLO)$/accheaderfooter.obj \
+ $(SLO)$/acchyperlink.obj \
+ $(SLO)$/acchypertextdata.obj \
+ $(SLO)$/accmap.obj \
+ $(SLO)$/accnotextframe.obj \
+ $(SLO)$/accpage.obj \
+ $(SLO)$/accpara.obj \
+ $(SLO)$/accportions.obj \
+ $(SLO)$/accpreview.obj \
+ $(SLO)$/accselectionhelper.obj \
+ $(SLO)$/acctable.obj \
+ $(SLO)$/acctextframe.obj \
+ $(SLO)$/textmarkuphelper.obj \
+ $(SLO)$/parachangetrackinginfo.obj
+
+# --- Targets -------------------------------------------------------
+
+
+.INCLUDE : target.mk
+
diff --git a/sw/source/core/access/parachangetrackinginfo.cxx b/sw/source/core/access/parachangetrackinginfo.cxx
new file mode 100644
index 000000000000..8dd2af0a0dd0
--- /dev/null
+++ b/sw/source/core/access/parachangetrackinginfo.cxx
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: $
+ * $Revision: $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sw.hxx"
+
+#include <parachangetrackinginfo.hxx>
+
+#include <errhdl.hxx>
+#include <wrong.hxx>
+#include <com/sun/star/text/TextMarkupType.hpp>
+
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <docary.hxx>
+#include <redline.hxx>
+
+namespace css = com::sun::star;
+
+namespace {
+ void initChangeTrackTextMarkupLists( const SwTxtFrm& rTxtFrm,
+ SwWrongList*& opChangeTrackInsertionTextMarkupList,
+ SwWrongList*& opChangeTrackDeletionTextMarkupList,
+ SwWrongList*& opChangeTrackFormatChangeTextMarkupList )
+ {
+ opChangeTrackInsertionTextMarkupList = new SwWrongList( WRONGLIST_CHANGETRACKING );
+ opChangeTrackDeletionTextMarkupList = new SwWrongList( WRONGLIST_CHANGETRACKING );
+ opChangeTrackFormatChangeTextMarkupList = new SwWrongList( WRONGLIST_CHANGETRACKING );
+
+ if ( !rTxtFrm.GetTxtNode() )
+ {
+ OSL_ENSURE( false,
+ "<initChangeTrackTextMarkupLists(..) - missing <SwTxtNode> instance!" );
+ return;
+ }
+ const SwTxtNode& rTxtNode( *(rTxtFrm.GetTxtNode()) );
+
+ const IDocumentRedlineAccess* pIDocChangeTrack( rTxtNode.getIDocumentRedlineAccess() );
+ if ( !pIDocChangeTrack )
+ {
+ OSL_ENSURE( false,
+ "<initChangeTrackTextMarkupLists(..) - missing <IDocumentRedlineAccess> instance!" );
+ return;
+ }
+
+ if ( !IDocumentRedlineAccess::IsShowChanges( pIDocChangeTrack->GetRedlineMode() ) ||
+ pIDocChangeTrack->GetRedlineTbl().Count() == 0 )
+ {
+ // nothing to do --> empty change track text markup lists.
+ return;
+ }
+
+ const sal_uInt16 nIdxOfFirstRedlineForTxtNode =
+ pIDocChangeTrack->GetRedlinePos( rTxtNode, USHRT_MAX );
+ if ( nIdxOfFirstRedlineForTxtNode == USHRT_MAX )
+ {
+ // nothing to do --> empty change track text markup lists.
+ return;
+ }
+
+ const xub_StrLen nTxtFrmTextStartPos = rTxtFrm.IsFollow()
+ ? rTxtFrm.GetOfst()
+ : 0;
+ const xub_StrLen nTxtFrmTextEndPos = rTxtFrm.HasFollow()
+ ? rTxtFrm.GetFollow()->GetOfst()
+ : rTxtFrm.GetTxt().Len();
+
+ // iteration over the redlines which overlap with the text node.
+ const SwRedlineTbl& rRedlineTbl = pIDocChangeTrack->GetRedlineTbl();
+ const USHORT nRedlineCount( rRedlineTbl.Count() );
+ for ( sal_uInt16 nActRedline = nIdxOfFirstRedlineForTxtNode;
+ nActRedline < nRedlineCount;
+ ++nActRedline)
+ {
+ const SwRedline* pActRedline = rRedlineTbl[ nActRedline ];
+ if ( pActRedline->Start()->nNode > rTxtNode.GetIndex() )
+ {
+ break;
+ }
+
+ xub_StrLen nTxtNodeChangeTrackStart( STRING_LEN );
+ xub_StrLen nTxtNodeChangeTrackEnd( STRING_LEN );
+ pActRedline->CalcStartEnd( rTxtNode.GetIndex(),
+ nTxtNodeChangeTrackStart,
+ nTxtNodeChangeTrackEnd );
+ if ( nTxtNodeChangeTrackStart > nTxtFrmTextEndPos ||
+ nTxtNodeChangeTrackEnd < nTxtFrmTextStartPos )
+ {
+ // Consider only redlines which overlap with the text frame's text.
+ continue;
+ }
+
+ SwWrongList* pMarkupList( 0 );
+ switch ( pActRedline->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ {
+ pMarkupList = opChangeTrackInsertionTextMarkupList;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ {
+ pMarkupList = opChangeTrackDeletionTextMarkupList;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_FORMAT:
+ {
+ pMarkupList = opChangeTrackFormatChangeTextMarkupList;
+ }
+ break;
+ default:
+ {
+ // other types are not considered
+ }
+ }
+ if ( pMarkupList )
+ {
+ const xub_StrLen nTxtFrmChangeTrackStart =
+ nTxtNodeChangeTrackStart <= nTxtFrmTextStartPos
+ ? nTxtFrmTextStartPos
+ : nTxtNodeChangeTrackStart;
+
+ const xub_StrLen nTxtFrmChangeTrackEnd =
+ nTxtNodeChangeTrackEnd >= nTxtFrmTextEndPos
+ ? nTxtFrmTextEndPos
+ : nTxtNodeChangeTrackEnd;
+
+ pMarkupList->Insert( rtl::OUString(), 0,
+ nTxtFrmChangeTrackStart,
+ nTxtFrmChangeTrackEnd - nTxtFrmChangeTrackStart,
+ pMarkupList->Count() );
+ }
+ } // eof iteration over the redlines which overlap with the text node
+ }
+} // eof anonymous namespace
+
+SwParaChangeTrackingInfo::SwParaChangeTrackingInfo( const SwTxtFrm& rTxtFrm )
+ : mrTxtFrm( rTxtFrm )
+ , mpChangeTrackInsertionTextMarkupList( 0 )
+ , mpChangeTrackDeletionTextMarkupList( 0 )
+ , mpChangeTrackFormatChangeTextMarkupList( 0 )
+{
+}
+
+
+SwParaChangeTrackingInfo::~SwParaChangeTrackingInfo()
+{
+ reset();
+}
+
+void SwParaChangeTrackingInfo::reset()
+{
+ delete mpChangeTrackInsertionTextMarkupList;
+ mpChangeTrackInsertionTextMarkupList = 0;
+
+ delete mpChangeTrackDeletionTextMarkupList;
+ mpChangeTrackDeletionTextMarkupList = 0;
+
+ delete mpChangeTrackFormatChangeTextMarkupList;
+ mpChangeTrackFormatChangeTextMarkupList = 0;
+}
+
+const SwWrongList* SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList( const sal_Int32 nTextMarkupType )
+{
+ SwWrongList* pChangeTrackingTextMarkupList = 0;
+
+ if ( mpChangeTrackInsertionTextMarkupList == 0 )
+ {
+ OSL_ENSURE( mpChangeTrackDeletionTextMarkupList == 0,
+ "<SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList(..) - <mpChangeTrackDeletionTextMarkupList> expected to be NULL." );
+ OSL_ENSURE( mpChangeTrackFormatChangeTextMarkupList == 0,
+ "<SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList(..) - <mpChangeTrackFormatChangeTextMarkupList> expected to be NULL." );
+ initChangeTrackTextMarkupLists( mrTxtFrm,
+ mpChangeTrackInsertionTextMarkupList,
+ mpChangeTrackDeletionTextMarkupList,
+ mpChangeTrackFormatChangeTextMarkupList );
+ }
+
+ switch ( nTextMarkupType )
+ {
+ case css::text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ {
+ pChangeTrackingTextMarkupList = mpChangeTrackInsertionTextMarkupList;
+ }
+ break;
+ case css::text::TextMarkupType::TRACK_CHANGE_DELETION:
+ {
+ pChangeTrackingTextMarkupList = mpChangeTrackDeletionTextMarkupList;
+ }
+ break;
+ case css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pChangeTrackingTextMarkupList = mpChangeTrackFormatChangeTextMarkupList;
+ }
+ break;
+ default:
+ {
+ OSL_ENSURE( false,
+ "<SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList(..)> - misusage - unexpected text markup type for change tracking." );
+ }
+ }
+
+ return pChangeTrackingTextMarkupList;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/parachangetrackinginfo.hxx b/sw/source/core/access/parachangetrackinginfo.hxx
new file mode 100644
index 000000000000..8949937cfbed
--- /dev/null
+++ b/sw/source/core/access/parachangetrackinginfo.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: $
+ * $Revision: $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PARACHANGETRACKINGINFO_HXX_
+#define _PARACHANGETRACKINGINFO_HXX_
+
+#include <sal/types.h>
+
+class SwTxtFrm;
+class SwWrongList;
+
+class SwParaChangeTrackingInfo
+{
+ public:
+ explicit SwParaChangeTrackingInfo( const SwTxtFrm& rTxtFrm );
+ ~SwParaChangeTrackingInfo();
+
+ void reset();
+
+ const SwWrongList* getChangeTrackingTextMarkupList( const sal_Int32 nTextMarkupType );
+
+ private:
+ SwParaChangeTrackingInfo( const SwParaChangeTrackingInfo& );
+ SwParaChangeTrackingInfo& operator=( const SwParaChangeTrackingInfo& );
+
+ const SwTxtFrm& mrTxtFrm;
+
+ SwWrongList* mpChangeTrackInsertionTextMarkupList;
+ SwWrongList* mpChangeTrackDeletionTextMarkupList;
+ SwWrongList* mpChangeTrackFormatChangeTextMarkupList;
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/textmarkuphelper.cxx b/sw/source/core/access/textmarkuphelper.cxx
new file mode 100644
index 000000000000..e49054879a4e
--- /dev/null
+++ b/sw/source/core/access/textmarkuphelper.cxx
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sw.hxx"
+
+#include <textmarkuphelper.hxx>
+#include <accportions.hxx>
+
+#include <vector>
+#include <algorithm>
+#include <comphelper/stlunosequence.hxx>
+
+#include <errhdl.hxx>
+
+#include <com/sun/star/text/TextMarkupType.hpp>
+#include <com/sun/star/accessibility/TextSegment.hpp>
+
+#include <ndtxt.hxx>
+#include <wrong.hxx>
+
+using namespace com::sun::star;
+
+// helper functions
+namespace {
+ const SwWrongList* getTextMarkupList( const SwTxtNode& rTxtNode,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ const SwWrongList* pTextMarkupList( 0 );
+ switch ( nTextMarkupType )
+ {
+ case text::TextMarkupType::SPELLCHECK:
+ {
+ pTextMarkupList = rTxtNode.GetWrong();
+ }
+ break;
+ case text::TextMarkupType::PROOFREADING:
+ {
+ // support not implemented yet
+ pTextMarkupList = 0;
+ }
+ break;
+ case text::TextMarkupType::SMARTTAG:
+ {
+ // support not implemented yet
+ pTextMarkupList = 0;
+ }
+ break;
+ default:
+ {
+ throw lang::IllegalArgumentException();
+ }
+ }
+
+ return pTextMarkupList;
+ }
+}
+
+// implementation of class <SwTextMarkupoHelper>
+SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
+ const SwTxtNode& rTxtNode )
+ : mrPortionData( rPortionData )
+ // --> OD 2010-02-19 #i108125#
+ , mpTxtNode( &rTxtNode )
+ , mpTextMarkupList( 0 )
+ // <--
+{
+}
+
+// --> OD 2010-02-19 #i108125#
+SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
+ const SwWrongList& rTextMarkupList )
+ : mrPortionData( rPortionData )
+ , mpTxtNode( 0 )
+ , mpTextMarkupList( &rTextMarkupList )
+{
+}
+// <--
+
+sal_Int32 SwTextMarkupHelper::getTextMarkupCount( const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ sal_Int32 nTextMarkupCount( 0 );
+
+ // --> OD 2010-02-19 #i108125#
+ const SwWrongList* pTextMarkupList =
+ mpTextMarkupList
+ ? mpTextMarkupList
+ : getTextMarkupList( *mpTxtNode, nTextMarkupType );
+ // <--
+ if ( pTextMarkupList )
+ {
+ nTextMarkupCount = pTextMarkupList->Count();
+ }
+
+ return nTextMarkupCount;
+}
+::com::sun::star::accessibility::TextSegment
+ SwTextMarkupHelper::getTextMarkup( const sal_Int32 nTextMarkupIndex,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ if ( nTextMarkupIndex >= getTextMarkupCount( nTextMarkupType ) ||
+ nTextMarkupIndex < 0 )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ ::com::sun::star::accessibility::TextSegment aTextMarkupSegment;
+ aTextMarkupSegment.SegmentStart = -1;
+ aTextMarkupSegment.SegmentEnd = -1;
+
+ // --> OD 2010-02-19 #i108125#
+ const SwWrongList* pTextMarkupList =
+ mpTextMarkupList
+ ? mpTextMarkupList
+ : getTextMarkupList( *mpTxtNode, nTextMarkupType );
+ // <--
+ if ( pTextMarkupList )
+ {
+ const SwWrongArea* pTextMarkup =
+ pTextMarkupList->GetElement( static_cast<USHORT>(nTextMarkupIndex) );
+ if ( pTextMarkup )
+ {
+ const ::rtl::OUString rText = mrPortionData.GetAccessibleString();
+ const sal_Int32 nStartPos =
+ mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos );
+ const sal_Int32 nEndPos =
+ mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos + pTextMarkup->mnLen );
+ aTextMarkupSegment.SegmentText = rText.copy( nStartPos, nEndPos - nStartPos );
+ aTextMarkupSegment.SegmentStart = nStartPos;
+ aTextMarkupSegment.SegmentEnd = nEndPos;
+ }
+ else
+ {
+ OSL_ENSURE( false,
+ "<SwTextMarkupHelper::getTextMarkup(..)> - missing <SwWrongArea> instance" );
+ }
+ }
+
+ return aTextMarkupSegment;
+}
+
+::com::sun::star::uno::Sequence< ::com::sun::star::accessibility::TextSegment >
+ SwTextMarkupHelper::getTextMarkupAtIndex( const sal_Int32 nCharIndex,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ // assumption:
+ // value of <nCharIndex> is in range [0..length of accessible text)
+
+ const USHORT nCoreCharIndex = mrPortionData.GetModelPosition( nCharIndex );
+ // Handling of portions with core length == 0 at the beginning of the
+ // paragraph - e.g. numbering portion.
+ if ( mrPortionData.GetAccessiblePosition( nCoreCharIndex ) > nCharIndex )
+ {
+ return uno::Sequence< ::com::sun::star::accessibility::TextSegment >();
+ }
+
+ // --> OD 2010-02-19 #i108125#
+ const SwWrongList* pTextMarkupList =
+ mpTextMarkupList
+ ? mpTextMarkupList
+ : getTextMarkupList( *mpTxtNode, nTextMarkupType );
+ // <--
+ ::std::vector< ::com::sun::star::accessibility::TextSegment > aTmpTextMarkups;
+ if ( pTextMarkupList )
+ {
+ const ::rtl::OUString rText = mrPortionData.GetAccessibleString();
+
+ const USHORT nTextMarkupCount = pTextMarkupList->Count();
+ for ( USHORT nTextMarkupIdx = 0; nTextMarkupIdx < nTextMarkupCount; ++nTextMarkupIdx )
+ {
+ const SwWrongArea* pTextMarkup =
+ pTextMarkupList->GetElement( static_cast<USHORT>(nTextMarkupIdx) );
+ OSL_ENSURE( pTextMarkup,
+ "<SwTextMarkupHelper::getTextMarkup(..)> - missing <SwWrongArea> instance" );
+ if ( pTextMarkup &&
+ pTextMarkup->mnPos <= nCoreCharIndex &&
+ nCoreCharIndex < ( pTextMarkup->mnPos + pTextMarkup->mnLen ) )
+ {
+ const sal_Int32 nStartPos =
+ mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos );
+ const sal_Int32 nEndPos =
+ mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos + pTextMarkup->mnLen );
+ ::com::sun::star::accessibility::TextSegment aTextMarkupSegment;
+ aTextMarkupSegment.SegmentText = rText.copy( nStartPos, nEndPos - nStartPos );
+ aTextMarkupSegment.SegmentStart = nStartPos;
+ aTextMarkupSegment.SegmentEnd = nEndPos;
+ aTmpTextMarkups.push_back( aTextMarkupSegment );
+ }
+ }
+ }
+
+ uno::Sequence< ::com::sun::star::accessibility::TextSegment > aTextMarkups(
+ aTmpTextMarkups.size() );
+ ::std::copy( aTmpTextMarkups.begin(), aTmpTextMarkups.end(),
+ ::comphelper::stl_begin( aTextMarkups ) );
+
+ return aTextMarkups;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/textmarkuphelper.hxx b/sw/source/core/access/textmarkuphelper.hxx
new file mode 100644
index 000000000000..447959971f5d
--- /dev/null
+++ b/sw/source/core/access/textmarkuphelper.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _TEXTMARKUPHELPER_HXX_
+#define _TEXTMARKUPHELPER_HXX_
+
+#include <sal/types.h>
+#include "com/sun/star/lang/IndexOutOfBoundsException.hdl"
+#include "com/sun/star/lang/IllegalArgumentException.hdl"
+#include "com/sun/star/uno/RuntimeException.hdl"
+#include "com/sun/star/uno/Sequence.h"
+
+namespace com { namespace sun { namespace star { namespace accessibility {
+struct TextSegment;
+} } } }
+
+class SwAccessiblePortionData;
+class SwTxtNode;
+// --> OD 2010-02-19 #i108125#
+class SwWrongList;
+// <--
+
+class SwTextMarkupHelper
+{
+ public:
+ SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
+ const SwTxtNode& rTxtNode );
+ // --> OD 2010-02-19 #i108125#
+ SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
+ const SwWrongList& rTextMarkupList );
+ // <--
+ ~SwTextMarkupHelper() {}
+
+ sal_Int32 getTextMarkupCount( const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ ::com::sun::star::accessibility::TextSegment getTextMarkup(
+ const sal_Int32 nTextMarkupIndex,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ ::com::sun::star::uno::Sequence< ::com::sun::star::accessibility::TextSegment >
+ getTextMarkupAtIndex( const sal_Int32 nCharIndex,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ private:
+ SwTextMarkupHelper( const SwTextMarkupHelper& );
+ SwTextMarkupHelper& operator=( const SwTextMarkupHelper& );
+
+ const SwAccessiblePortionData& mrPortionData;
+
+ // --> OD 2010-02-19 #i108125#
+ const SwTxtNode* mpTxtNode;
+ const SwWrongList* mpTextMarkupList;
+ // <--
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */