Files
libreoffice/sw/source/core/access/accdoc.cxx

887 lines
28 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
re-base on ALv2 code. Includes: Patches contributed by Oliver-Rainer Wittmann sw34bf06: #i117783# - Writer's implementation of XPagePrintable - apply print settings to new printing routines http://svn.apache.org/viewvc?view=revision&revision=1172115 sw34bf06: #o12311627# use <rtl_random> methods to create unique ids for list styles and list ids http://svn.apache.org/viewvc?view=revision&revision=1172112 sw34bf06 #i114725#,#i115828# - method <SwDoc::ClearDoc()> - clear list structures completely http://svn.apache.org/viewvc?view=revision&revision=1172122 i#118572 - remove ui string and help content regarding usage of Java Mail in Writer's Mail Merge as Java Mail is not used. http://svn.apache.org/viewvc?view=revision&revision=1197035 Patches contributed by Mathias Bauer cws mba34issues01: #i117718#: provide filter name in case storage of medium does not allow to detect one http://svn.apache.org/viewvc?view=revision&revision=1172350 cws mba34issues01: #i117721#: directly provide parameters retrieved from SfxMedium http://svn.apache.org/viewvc?view=revision&revision=1172353 gnumake4 work variously http://svn.apache.org/viewvc?view=revision&revision=1394707 http://svn.apache.org/viewvc?view=revision&revision=1394326 http://svn.apache.org/viewvc?view=revision&revision=1396797 http://svn.apache.org/viewvc?view=revision&revision=1397315 cws mba34issues01: #i117723#: convert assertion into trace http://svn.apache.org/viewvc?view=revision&revision=1172355 cws mba34issues01: #i117699#: keep layout alive until swdoc dies http://svn.apache.org/viewvc?view=revision&revision=1172362 cws mba34issues01: #i117943#: missing color attributes in RTF clipboard http://svn.apache.org/viewvc?view=revision&revision=1172363 Patch contributed by Henning Brinkmann imported patch i#103878 http://svn.apache.org/viewvc?view=revision&revision=1172109 Patches contributed by Michael Stahl sw34bf06: #i117955#: WW8 export: disable storing of section breaks in endnotes http://svn.apache.org/viewvc?view=revision&revision=1172119 Patch contributed by imacat Fixed the Asian language work count. http://svn.apache.org/viewvc?view=revision&revision=1241345 Patch contributed by Pedro Giffuni i#20878 - Add comment with BZ issue for reference. http://svn.apache.org/viewvc?view=revision&revision=1244517 Patch contributed by Andre Fischer Do not add targets for junit tests when junit is disabled. http://svn.apache.org/viewvc?view=revision&revision=1241508 add writerperfect dependency.
2011-03-31 10:05:04 +02:00
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
2002-02-04 13:10:18 +00:00
#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/accessibility/AccessibleEventId.hpp>
2002-02-05 14:52:06 +00:00
#include <unotools/accessiblestatesethelper.hxx>
#include <sfx2/viewsh.hxx>
2002-02-04 13:10:18 +00:00
#include <vcl/svapp.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <viewsh.hxx>
#include <doc.hxx>
#include <accmap.hxx>
#include "accdoc.hxx"
#include <strings.hrc>
2002-05-22 10:48:43 +00:00
#include <pagefrm.hxx>
#include <editeng/brushitem.hxx>
#include <swatrset.hxx>
#include <frmatr.hxx>
#include <unostyle.hxx>
#include <docsh.hxx>
#include <crsrsh.hxx>
#include <fesh.hxx>
#include <fmtclds.hxx>
#include <flyfrm.hxx>
#include <colfrm.hxx>
#include <txtfrm.hxx>
#include <sectfrm.hxx>
#include <section.hxx>
#include <svx/unoapi.hxx>
#include <swmodule.hxx>
#include <svtools/colorcfg.hxx>
#include <fmtanchr.hxx>
#include <viewimp.hxx>
#include <dview.hxx>
#include <dcontact.hxx>
#include <svx/svdmark.hxx>
const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextDocumentView";
const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleDocumentView";
2002-02-04 13:10:18 +00:00
using namespace ::com::sun::star;
using namespace ::com::sun::star::accessibility;
2002-02-04 13:10:18 +00:00
using lang::IndexOutOfBoundsException;
2002-05-22 10:48:43 +00:00
// SwAccessibleDocumentBase: base class for SwAccessibleDocument and
// SwAccessiblePreview
2002-02-05 14:52:06 +00:00
tdf#58624 sw: fix ~SwAccessibleContext() use-after-free race As seen in JunitTest_toolkit_unoapi_1: Method doAccessibleAction() finished with state OK LOG> doAccessibleAction(): COMPLETED.OK debug:27272:12: -SwAccessibleParagraph mutexwait 0x3fd9f50 debug:27272:9: SwAccessibleContext::Dispose 0x3872620 11SwRootFrame debug:27272:9: SwAccessibleContext::DisposeChildren 0x4047c80 0x386d600 11SwPageFrame debug:27272:9: SwAccessibleContext::DisposeChildren xAcc 0 debug:27272:9: SwAccessibleContext::DisposeChildren 0x4047c80 0x386cef0 11SwBodyFrame debug:27272:9: SwAccessibleContext::DisposeChildren xAcc 0 debug:27272:9: SwAccessibleContext::DisposeChildren 0x4047c80 0x3878fe0 11SwTextFrame debug:27272:9: SwAccessibleContext::DisposeChildren xAcc 0 debug:27272:9: SwAccessibleMap::RemoveContext erase 0x3872620 debug:27272:9: ~SwAccessibleMap: frame entry 0x3878fe0 debug:27272:9: ~SwAccessibleMap: mpFrameMap 0x3eb64a0 debug:27272:9: ~SwAccessibleMap: mpShapeMap 0 soffice.bin: sw/source/core/access/accmap.cxx:1726: virtual SwAccessibleMap::~SwAccessibleMap(): Assertion `(!mpFrameMap || mpFrameMap->empty()) && "Frame map should be empty after disposing the root frame"' The problem here is that thread 12 is blocked on SolarMutex in ~SwAccessibleParagraph(), while thread 9 is in ~SwAccessibleMap(). This means that in SwAccessibleContext::DisposeChildren(), the WeakReference to the SwAccessibleParagraph cannot create a uno::Reference because its reference count is 0, so SwAccessibleContext::Dispose() is not called on it and it remains in the SwAccessibleMap::mpFrameMap. This triggers the assert and later on ~SwAccessibleContext() would access the deleted SwAccessibleMap and crash. To fix this, introduce a weak reference from SwAccessibleContext to SwAccessibleMap; use a std::weak_ptr because that is not derived from OWeakObject. The weak_ptr is only used in the dtor ~SwAccessibleContext(); as long as the ref-count of SwAccessibleContext is > 0 it is guaranteed that the SwAccessibleContext::m_pMap is either null or valid as the recursive Dispose() will work fine. It is possible that additional temporary owning references could delay the destruction of SwAccessibleMap, and the order of destruction of Writer documents is very fragile, so rely on the SolarMutex lock to prevent that; the only shared_ptr that owns SwAccessibleMap while SolarMutex is not locked is the one in SwViewShellImp. (An alternative fix would be to represent the 3 lifecycle stages of SwAccessibleContext by adding a C++-pointer to the SwAccessibleMap::mpFrameMap, so that DisposeChildren() can, if the WeakReference is no longer valid due to ref-count 0, use the pointer and clear SwAccessibleContext::m_pMap - this and the corresponding call to SwAccessibleMap::RemoveContext() from ~SwAccessibleContext() under a mutex that is shared_ptr-owned by SwAccessibleMap and all SwAccessibleContext.) Change-Id: If2b44c79189e3b3d276491a5c57d5404bb2be71a
2017-03-24 13:04:32 +01:00
SwAccessibleDocumentBase::SwAccessibleDocumentBase(
std::shared_ptr<SwAccessibleMap> const& pMap)
: SwAccessibleContext(pMap, AccessibleRole::DOCUMENT_TEXT,
pMap->GetShell()->GetLayout())
, mxParent(pMap->GetShell()->GetWin()->GetAccessibleParentWindow()->GetAccessible())
, mpChildWin(nullptr)
2002-02-04 13:10:18 +00:00
{
}
2002-05-22 10:48:43 +00:00
SwAccessibleDocumentBase::~SwAccessibleDocumentBase()
2002-02-04 13:10:18 +00:00
{
}
2002-05-22 10:48:43 +00:00
void SwAccessibleDocumentBase::SetVisArea()
2002-04-11 13:04:40 +00:00
{
SolarMutexGuard aGuard;
2002-04-11 13:04:40 +00:00
SwRect aOldVisArea( GetVisArea() );
const SwRect& rNewVisArea = GetMap()->GetVisArea();
if( aOldVisArea != rNewVisArea )
{
SwAccessibleFrame::SetVisArea( GetMap()->GetVisArea() );
2011-01-30 04:19:53 +09:00
// #i58139# - showing state of document view needs also be updated.
// Thus, call method <Scrolled(..)> instead of <ChildrenScrolled(..)>
// ChildrenScrolled( GetFrame(), aOldVisArea );
Scrolled( aOldVisArea );
2002-04-11 13:04:40 +00:00
}
}
void SwAccessibleDocumentBase::AddChild( vcl::Window *pWin, 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( vcl::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 = nullptr;
}
}
sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleChildCount()
{
SolarMutexGuard aGuard;
// ThrowIfDisposed 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 )
{
SolarMutexGuard aGuard;
if( mpChildWin )
{
ThrowIfDisposed();
if ( nIndex == GetChildCount( *(GetMap()) ) )
{
return mpChildWin->GetAccessible();
}
}
return SwAccessibleContext::getAccessibleChild( nIndex );
}
uno::Reference< XAccessible> SAL_CALL SwAccessibleDocumentBase::getAccessibleParent()
2002-02-04 13:10:18 +00:00
{
return mxParent;
2002-02-04 13:10:18 +00:00
}
sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleIndexInParent()
2002-02-04 13:10:18 +00:00
{
SolarMutexGuard aGuard;
2002-02-04 13:10:18 +00:00
uno::Reference < XAccessibleContext > xAcc( mxParent->getAccessibleContext() );
uno::Reference < XAccessible > xThis( this );
2002-02-04 13:10:18 +00:00
sal_Int32 nCount = xAcc->getAccessibleChildCount();
for( sal_Int32 i=0; i < nCount; i++ )
{
try
{
if( xAcc->getAccessibleChild( i ) == xThis )
return i;
}
catch(const css::lang::IndexOutOfBoundsException &)
{
return -1;
}
2002-02-04 13:10:18 +00:00
}
return -1;
2002-02-04 13:10:18 +00:00
}
OUString SAL_CALL SwAccessibleDocumentBase::getAccessibleDescription()
2002-02-04 13:10:18 +00:00
{
return GetResource( STR_ACCESS_DOC_DESC );
}
OUString SAL_CALL SwAccessibleDocumentBase::getAccessibleName()
{
SolarMutexGuard g;
OUString sAccName = GetResource( STR_ACCESS_DOC_WORDPROCESSING );
SwDoc *pDoc = GetMap() ? GetShell()->GetDoc() : nullptr;
if ( pDoc )
{
OUString sFileName = pDoc->getDocAccTitle();
if ( sFileName.isEmpty() )
{
SwDocShell* pDocSh = pDoc->GetDocShell();
if ( pDocSh )
{
sFileName = pDocSh->GetTitle( SFX_TITLE_APINAME );
}
}
if ( !sFileName.isEmpty() )
{
sAccName = sFileName + " - " + sAccName;
}
}
return sAccName;
}
2002-05-22 10:48:43 +00:00
awt::Rectangle SAL_CALL SwAccessibleDocumentBase::getBounds()
2002-02-04 13:10:18 +00:00
{
try
{
SolarMutexGuard aGuard;
2002-02-04 13:10:18 +00:00
vcl::Window *pWin = GetWindow();
if (!pWin)
{
throw uno::RuntimeException("no Window", static_cast<cppu::OWeakObject*>(this));
}
2002-02-04 13:10:18 +00:00
tools::Rectangle aPixBounds( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ) );
awt::Rectangle aBox( aPixBounds.Left(), aPixBounds.Top(),
aPixBounds.GetWidth(), aPixBounds.GetHeight() );
2002-02-04 13:10:18 +00:00
return aBox;
}
catch(const css::lang::IndexOutOfBoundsException &)
{
return awt::Rectangle();
}
2002-02-04 13:10:18 +00:00
}
2002-05-22 10:48:43 +00:00
awt::Point SAL_CALL SwAccessibleDocumentBase::getLocation()
2002-02-04 13:10:18 +00:00
{
SolarMutexGuard aGuard;
2002-02-04 13:10:18 +00:00
vcl::Window *pWin = GetWindow();
if (!pWin)
{
throw uno::RuntimeException("no Window", static_cast<cppu::OWeakObject*>(this));
}
2002-02-04 13:10:18 +00:00
2002-04-17 13:07:39 +00:00
Point aPixPos( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ).TopLeft() );
awt::Point aLoc( aPixPos.getX(), aPixPos.getY() );
2002-02-04 13:10:18 +00:00
return aLoc;
}
css::awt::Point SAL_CALL SwAccessibleDocumentBase::getLocationOnScreen()
2002-02-04 13:10:18 +00:00
{
SolarMutexGuard aGuard;
2002-02-04 13:10:18 +00:00
vcl::Window *pWin = GetWindow();
if (!pWin)
{
throw uno::RuntimeException("no Window", static_cast<cppu::OWeakObject*>(this));
}
2002-02-04 13:10:18 +00:00
Point aPixPos( pWin->GetWindowExtentsRelative( nullptr ).TopLeft() );
awt::Point aLoc( aPixPos.getX(), aPixPos.getY() );
2002-02-04 13:10:18 +00:00
return aLoc;
}
css::awt::Size SAL_CALL SwAccessibleDocumentBase::getSize()
2002-02-04 13:10:18 +00:00
{
SolarMutexGuard aGuard;
2002-02-04 13:10:18 +00:00
vcl::Window *pWin = GetWindow();
if (!pWin)
{
throw uno::RuntimeException("no Window", static_cast<cppu::OWeakObject*>(this));
}
2002-02-04 13:10:18 +00:00
Size aPixSize( pWin->GetWindowExtentsRelative( nullptr ).GetSize() );
2002-02-04 13:10:18 +00:00
awt::Size aSize( aPixSize.Width(), aPixSize.Height() );
return aSize;
}
sal_Bool SAL_CALL SwAccessibleDocumentBase::containsPoint(
const awt::Point& aPoint )
{
SolarMutexGuard aGuard;
vcl::Window *pWin = GetWindow();
if (!pWin)
{
throw uno::RuntimeException("no Window", static_cast<cppu::OWeakObject*>(this));
}
tools::Rectangle aPixBounds( pWin->GetWindowExtentsRelative( nullptr ) );
2002-10-02 07:48:09 +00:00
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 )
{
SolarMutexGuard aGuard;
if( mpChildWin )
{
ThrowIfDisposed();
vcl::Window *pWin = GetWindow();
if (!pWin)
{
throw uno::RuntimeException("no Window", static_cast<cppu::OWeakObject*>(this));
}
2002-02-04 13:10:18 +00:00
Point aPixPoint( aPoint.X, aPoint.Y ); // px rel to window
if( mpChildWin->GetWindowExtentsRelative( pWin ).IsInside( aPixPoint ) )
return mpChildWin->GetAccessible();
}
return SwAccessibleContext::getAccessibleAtPoint( aPoint );
}
2002-05-22 10:48:43 +00:00
// SwAccessibleDocument
2002-05-22 10:48:43 +00:00
void SwAccessibleDocument::GetStates(
::utl::AccessibleStateSetHelper& rStateSet )
{
SwAccessibleContext::GetStates( rStateSet );
// MULTISELECTABLE
rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
2002-05-22 10:48:43 +00:00
}
tdf#58624 sw: fix ~SwAccessibleContext() use-after-free race As seen in JunitTest_toolkit_unoapi_1: Method doAccessibleAction() finished with state OK LOG> doAccessibleAction(): COMPLETED.OK debug:27272:12: -SwAccessibleParagraph mutexwait 0x3fd9f50 debug:27272:9: SwAccessibleContext::Dispose 0x3872620 11SwRootFrame debug:27272:9: SwAccessibleContext::DisposeChildren 0x4047c80 0x386d600 11SwPageFrame debug:27272:9: SwAccessibleContext::DisposeChildren xAcc 0 debug:27272:9: SwAccessibleContext::DisposeChildren 0x4047c80 0x386cef0 11SwBodyFrame debug:27272:9: SwAccessibleContext::DisposeChildren xAcc 0 debug:27272:9: SwAccessibleContext::DisposeChildren 0x4047c80 0x3878fe0 11SwTextFrame debug:27272:9: SwAccessibleContext::DisposeChildren xAcc 0 debug:27272:9: SwAccessibleMap::RemoveContext erase 0x3872620 debug:27272:9: ~SwAccessibleMap: frame entry 0x3878fe0 debug:27272:9: ~SwAccessibleMap: mpFrameMap 0x3eb64a0 debug:27272:9: ~SwAccessibleMap: mpShapeMap 0 soffice.bin: sw/source/core/access/accmap.cxx:1726: virtual SwAccessibleMap::~SwAccessibleMap(): Assertion `(!mpFrameMap || mpFrameMap->empty()) && "Frame map should be empty after disposing the root frame"' The problem here is that thread 12 is blocked on SolarMutex in ~SwAccessibleParagraph(), while thread 9 is in ~SwAccessibleMap(). This means that in SwAccessibleContext::DisposeChildren(), the WeakReference to the SwAccessibleParagraph cannot create a uno::Reference because its reference count is 0, so SwAccessibleContext::Dispose() is not called on it and it remains in the SwAccessibleMap::mpFrameMap. This triggers the assert and later on ~SwAccessibleContext() would access the deleted SwAccessibleMap and crash. To fix this, introduce a weak reference from SwAccessibleContext to SwAccessibleMap; use a std::weak_ptr because that is not derived from OWeakObject. The weak_ptr is only used in the dtor ~SwAccessibleContext(); as long as the ref-count of SwAccessibleContext is > 0 it is guaranteed that the SwAccessibleContext::m_pMap is either null or valid as the recursive Dispose() will work fine. It is possible that additional temporary owning references could delay the destruction of SwAccessibleMap, and the order of destruction of Writer documents is very fragile, so rely on the SolarMutex lock to prevent that; the only shared_ptr that owns SwAccessibleMap while SolarMutex is not locked is the one in SwViewShellImp. (An alternative fix would be to represent the 3 lifecycle stages of SwAccessibleContext by adding a C++-pointer to the SwAccessibleMap::mpFrameMap, so that DisposeChildren() can, if the WeakReference is no longer valid due to ref-count 0, use the pointer and clear SwAccessibleContext::m_pMap - this and the corresponding call to SwAccessibleMap::RemoveContext() from ~SwAccessibleContext() under a mutex that is shared_ptr-owned by SwAccessibleMap and all SwAccessibleContext.) Change-Id: If2b44c79189e3b3d276491a5c57d5404bb2be71a
2017-03-24 13:04:32 +01:00
SwAccessibleDocument::SwAccessibleDocument(
std::shared_ptr<SwAccessibleMap> const& pInitMap)
: SwAccessibleDocumentBase(pInitMap)
, maSelectionHelper(*this)
2002-05-22 10:48:43 +00:00
{
SetName(pInitMap->GetDocName());
vcl::Window *pWin = pInitMap->GetShell()->GetWin();
if( pWin )
{
pWin->AddChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
sal_uInt16 nCount = pWin->GetChildCount();
for( sal_uInt16 i=0; i < nCount; i++ )
{
vcl::Window* pChildWin = pWin->GetChild( i );
if( pChildWin &&
AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
AddChild( pChildWin, false );
}
}
2002-05-22 10:48:43 +00:00
}
SwAccessibleDocument::~SwAccessibleDocument()
{
vcl::Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : nullptr;
if( pWin )
pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
2002-05-22 10:48:43 +00:00
}
void SwAccessibleDocument::Dispose(bool bRecursive, bool bCanSkipInvisible)
{
OSL_ENSURE( GetFrame() && GetMap(), "already disposed" );
vcl::Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : nullptr;
if( pWin )
pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
SwAccessibleContext::Dispose(bRecursive, bCanSkipInvisible);
}
IMPL_LINK( SwAccessibleDocument, WindowChildEventListener, VclWindowEvent&, rEvent, void )
{
OSL_ENSURE( rEvent.GetWindow(), "Window???" );
switch ( rEvent.GetId() )
{
case VclEventId::WindowShow: // send create on show for direct accessible children
{
vcl::Window* pChildWin = static_cast< vcl::Window* >( rEvent.GetData() );
if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
{
AddChild( pChildWin );
}
}
break;
case VclEventId::WindowHide: // send destroy on hide for direct accessible children
{
vcl::Window* pChildWin = static_cast< vcl::Window* >( rEvent.GetData() );
if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
{
RemoveChild( pChildWin );
}
}
break;
case VclEventId::ObjectDying: // send destroy on hide for direct accessible children
{
vcl::Window* pChildWin = rEvent.GetWindow();
if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
{
RemoveChild( pChildWin );
}
}
break;
default: break;
}
}
2002-05-22 10:48:43 +00:00
2002-02-04 13:10:18 +00:00
OUString SAL_CALL SwAccessibleDocument::getImplementationName()
{
return OUString(sImplementationName);
2002-02-04 13:10:18 +00:00
}
sal_Bool SAL_CALL SwAccessibleDocument::supportsService(const OUString& sTestServiceName)
2002-02-04 13:10:18 +00:00
{
return cppu::supportsService(this, sTestServiceName);
2002-02-04 13:10:18 +00:00
}
uno::Sequence< OUString > SAL_CALL SwAccessibleDocument::getSupportedServiceNames()
2002-02-04 13:10:18 +00:00
{
uno::Sequence< OUString > aRet(2);
2002-02-04 13:10:18 +00:00
OUString* pArray = aRet.getArray();
pArray[0] = sServiceName;
pArray[1] = sAccessibleServiceName;
2002-02-04 13:10:18 +00:00
return aRet;
}
// XInterface
uno::Any SwAccessibleDocument::queryInterface(
const uno::Type& rType )
{
uno::Any aRet;
if ( rType == cppu::UnoType<XAccessibleSelection>::get() )
{
uno::Reference<XAccessibleSelection> aSelect = this;
aRet <<= aSelect;
}
else if ( rType == cppu::UnoType<XAccessibleExtendedAttributes>::get())
{
uno::Reference<XAccessibleExtendedAttributes> aAttribute = this;
aRet <<= aAttribute;
}
else if(rType == cppu::UnoType<XAccessibleGetAccFlowTo>::get())
{
uno::Reference<XAccessibleGetAccFlowTo> AccFlowTo = this;
aRet <<= AccFlowTo;
}
else
aRet = SwAccessibleContext::queryInterface( rType );
return aRet;
}
// XTypeProvider
uno::Sequence< uno::Type > SAL_CALL SwAccessibleDocument::getTypes()
{
uno::Sequence< uno::Type > aTypes( SwAccessibleDocumentBase::getTypes() );
sal_Int32 nIndex = aTypes.getLength();
//Reset types memory alloc
aTypes.realloc( nIndex + 1 );
uno::Type* pTypes = aTypes.getArray();
pTypes[nIndex] = cppu::UnoType<XAccessibleSelection>::get();
return aTypes;
}
uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleDocument::getImplementationId()
{
return css::uno::Sequence<sal_Int8>();
}
// XAccessibleSelection
void SwAccessibleDocument::selectAccessibleChild(
sal_Int32 nChildIndex )
{
maSelectionHelper.selectAccessibleChild(nChildIndex);
}
sal_Bool SwAccessibleDocument::isAccessibleChildSelected(
sal_Int32 nChildIndex )
{
return maSelectionHelper.isAccessibleChildSelected(nChildIndex);
}
void SwAccessibleDocument::clearAccessibleSelection( )
{
}
void SwAccessibleDocument::selectAllAccessibleChildren( )
{
maSelectionHelper.selectAllAccessibleChildren();
}
sal_Int32 SwAccessibleDocument::getSelectedAccessibleChildCount( )
{
return maSelectionHelper.getSelectedAccessibleChildCount();
}
uno::Reference<XAccessible> SwAccessibleDocument::getSelectedAccessibleChild(
sal_Int32 nSelectedChildIndex )
{
return maSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
}
2011-01-30 04:19:53 +09:00
// index has to be treated as global child index.
void SwAccessibleDocument::deselectAccessibleChild(
sal_Int32 nChildIndex )
{
maSelectionHelper.deselectAccessibleChild( nChildIndex );
}
uno::Any SAL_CALL SwAccessibleDocument::getExtendedAttributes()
{
SolarMutexGuard g;
uno::Any anyAtrribute;
SwDoc *pDoc = GetMap() ? GetShell()->GetDoc() : nullptr;
if (!pDoc)
return anyAtrribute;
SwCursorShell* pCursorShell = GetCursorShell();
if( !pCursorShell )
return anyAtrribute;
SwFEShell* pFEShell = dynamic_cast<const SwFEShell*>( pCursorShell) != nullptr
? static_cast<SwFEShell*>( pCursorShell )
: nullptr;
OUString sAttrName;
OUString sValue;
sal_uInt16 nPage, nLogPage;
OUString sDisplay;
if( pFEShell )
{
pFEShell->GetPageNumber(-1,true,nPage,nLogPage,sDisplay);
sAttrName = "page-name:";
sValue = sAttrName + sDisplay ;
sAttrName = ";page-number:";
sValue += sAttrName;
sValue += OUString::number( nPage ) ;
sAttrName = ";total-pages:";
sValue += sAttrName;
sValue += OUString::number( pCursorShell->GetPageCnt() ) ;
sValue += ";";
sAttrName = "line-number:";
SwContentFrame* pCurrFrame = pCursorShell->GetCurrFrame();
SwPageFrame* pCurrPage=static_cast<SwFrame*>(pCurrFrame)->FindPageFrame();
sal_uLong nLineNum = 0;
SwTextFrame* pTextFrame = nullptr;
SwTextFrame* pCurrTextFrame = nullptr;
pTextFrame = static_cast< SwTextFrame* >(pCurrPage->ContainsContent());
if (pCurrFrame->IsInFly())//such as, graphic,chart
{
SwFlyFrame *pFlyFrame = pCurrFrame->FindFlyFrame();
const SwFormatAnchor& rAnchor = pFlyFrame->GetFormat()->GetAnchor();
RndStdIds eAnchorId = rAnchor.GetAnchorId();
if(eAnchorId == RndStdIds::FLY_AS_CHAR)
{
const SwFrame *pSwFrame = pFlyFrame->GetAnchorFrame();
if(pSwFrame->IsTextFrame())
pCurrTextFrame = const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pSwFrame));
}
}
else
pCurrTextFrame = static_cast<SwTextFrame* >(pCurrFrame);
//check whether the text frame where the Graph/OLE/Frame anchored is in the Header/Footer
SwFrame* pFrame = pCurrTextFrame;
while ( pFrame && !pFrame->IsHeaderFrame() && !pFrame->IsFooterFrame() )
pFrame = pFrame->GetUpper();
if ( pFrame )
pCurrTextFrame = nullptr;
//check shape
if(pCursorShell->Imp()->GetDrawView())
{
const SdrMarkList &rMrkList = pCursorShell->Imp()->GetDrawView()->GetMarkedObjectList();
for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
{
SdrObject *pObj = rMrkList.GetMark(i)->GetMarkedSdrObj();
SwFrameFormat* pFormat = static_cast<SwDrawContact*>(pObj->GetUserCall())->GetFormat();
const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
if( RndStdIds::FLY_AS_CHAR != rAnchor.GetAnchorId() )
pCurrTextFrame = nullptr;
}
}
//calculate line number
if (pCurrTextFrame && pTextFrame)
{
if (!(pCurrTextFrame->IsInTab() || pCurrTextFrame->IsInFootnote()))
{
while( pTextFrame != pCurrTextFrame )
{
//check header/footer
pFrame = pTextFrame;
while ( pFrame && !pFrame->IsHeaderFrame() && !pFrame->IsFooterFrame() )
pFrame = pFrame->GetUpper();
if ( pFrame )
{
pTextFrame = static_cast< SwTextFrame*>(pTextFrame->GetNextContentFrame());
continue;
}
if (!(pTextFrame->IsInTab() || pTextFrame->IsInFootnote() || pTextFrame->IsInFly()))
nLineNum += pTextFrame->GetThisLines();
pTextFrame = static_cast< SwTextFrame* >(pTextFrame ->GetNextContentFrame());
}
SwPaM* pCaret = pCursorShell->GetCursor();
if (!pCurrTextFrame->IsEmpty() && pCaret)
{
if (pCurrTextFrame->IsTextFrame())
{
const SwPosition* pPoint = nullptr;
if(pCurrTextFrame->IsInFly())
{
SwFlyFrame *pFlyFrame = pCurrTextFrame->FindFlyFrame();
const SwFormatAnchor& rAnchor = pFlyFrame->GetFormat()->GetAnchor();
pPoint= rAnchor.GetContentAnchor();
}
else
pPoint = pCaret->GetPoint();
const sal_Int32 nActPos = pPoint->nContent.GetIndex();
nLineNum += pCurrTextFrame->GetLineCount( nActPos );
}
else//graphic, form, shape, etc.
{
SwPosition* pPoint = pCaret->GetPoint();
Point aPt = pCursorShell->GetCursor_()->GetPtPos();
if( pCursorShell->GetLayout()->GetCursorOfst( pPoint, aPt/*,* &eTmpState*/ ) )
{
const sal_Int32 nActPos = pPoint->nContent.GetIndex();
nLineNum += pCurrTextFrame->GetLineCount( nActPos );
}
}
}
else
++nLineNum;
}
}
sValue += sAttrName;
sValue += OUString::number( nLineNum ) ;
sValue += ";";
SwFrame* pCurrCol=static_cast<SwFrame*>(pCurrFrame)->FindColFrame();
sAttrName = "column-number:";
sValue += sAttrName;
int nCurrCol = 1;
if(pCurrCol!=nullptr)
{
//SwLayoutFrame* pParent = pCurrCol->GetUpper();
SwFrame* pCurrPageCol=static_cast<SwFrame*>(pCurrFrame)->FindColFrame();
while(pCurrPageCol && pCurrPageCol->GetUpper() && pCurrPageCol->GetUpper()->IsPageFrame())
{
pCurrPageCol = pCurrPageCol->GetUpper();
}
SwLayoutFrame* pParent = pCurrPageCol->GetUpper();
if(pParent!=nullptr)
{
SwFrame* pCol = pParent->Lower();
while(pCol&&(pCol!=pCurrPageCol))
{
pCol = pCol->GetNext();
++nCurrCol;
}
}
}
sValue += OUString::number( nCurrCol ) ;
sValue += ";";
sAttrName = "total-columns:";
const SwFormatCol &rFormatCol=pCurrPage->GetAttrSet()->GetCol();
sal_uInt16 nColCount=rFormatCol.GetNumCols();
nColCount = nColCount>0?nColCount:1;
sValue += sAttrName;
sValue += OUString::number( nColCount ) ;
sValue += ";";
SwSectionFrame* pCurrSctFrame=static_cast<SwFrame*>(pCurrFrame)->FindSctFrame();
if(pCurrSctFrame!=nullptr && pCurrSctFrame->GetSection()!=nullptr )
{
sAttrName = "section-name:";
sValue += sAttrName;
OUString sectionName = pCurrSctFrame->GetSection()->GetSectionName();
sectionName = sectionName.replaceFirst( "\\" , "\\\\" );
sectionName = sectionName.replaceFirst( "=" , "\\=" );
sectionName = sectionName.replaceFirst( ";" , "\\;" );
sectionName = sectionName.replaceFirst( "," , "\\," );
sectionName = sectionName.replaceFirst( ":" , "\\:" );
sValue += sectionName;
sValue += ";";
//section-columns-number
sAttrName = "section-columns-number:";
nCurrCol = 1;
if(pCurrCol!=nullptr)
{
SwLayoutFrame* pParent = pCurrCol->GetUpper();
if(pParent!=nullptr)
{
SwFrame* pCol = pParent->Lower();
while(pCol&&(pCol!=pCurrCol))
{
pCol = pCol->GetNext();
nCurrCol +=1;
}
}
}
sValue += sAttrName;
sValue += OUString::number( nCurrCol ) ;
sValue += ";";
//section-total-columns
sAttrName = "section-total-columns:";
const SwFormatCol &rFormatSctCol=pCurrSctFrame->GetAttrSet()->GetCol();
sal_uInt16 nSctColCount=rFormatSctCol.GetNumCols();
nSctColCount = nSctColCount>0?nSctColCount:1;
sValue += sAttrName;
sValue += OUString::number( nSctColCount ) ;
sValue += ";";
}
anyAtrribute <<= sValue;
}
return anyAtrribute;
}
sal_Int32 SAL_CALL SwAccessibleDocument::getBackground()
{
SolarMutexGuard aGuard;
return sal_Int32(SW_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor);
}
css::uno::Sequence< css::uno::Any >
SAL_CALL SwAccessibleDocument::getAccFlowTo(const css::uno::Any& rAny, sal_Int32 nType)
{
SolarMutexGuard g;
const sal_Int32 FORSPELLCHECKFLOWTO = 1;
const sal_Int32 FORFINDREPLACEFLOWTO = 2;
SwAccessibleMap* pAccMap = GetMap();
if ( !pAccMap )
{
return uno::Sequence< uno::Any >();
}
if ( nType == FORSPELLCHECKFLOWTO )
{
uno::Reference< css::drawing::XShape > xShape;
rAny >>= xShape;
if( xShape.is() )
{
SdrObject* pObj = GetSdrObjectFromXShape(xShape);
if( pObj )
{
uno::Reference<XAccessible> xAcc = pAccMap->GetContext(pObj, this, false);
uno::Reference < XAccessibleSelection > xAccSelection( xAcc, uno::UNO_QUERY );
if ( xAccSelection.is() )
{
try
{
if ( xAccSelection->getSelectedAccessibleChildCount() )
{
uno::Reference < XAccessible > xSel = xAccSelection->getSelectedAccessibleChild( 0 );
if ( xSel.is() )
{
uno::Reference < XAccessibleContext > xSelContext( xSel->getAccessibleContext() );
if ( xSelContext.is() )
{
//if in sw we find the selected paragraph here
if ( xSelContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
{
uno::Sequence<uno::Any> aRet( 1 );
aRet[0] <<= xSel;
return aRet;
}
}
}
}
}
catch ( const css::lang::IndexOutOfBoundsException& )
{
return uno::Sequence< uno::Any >();
}
//end of try...catch
}
}
}
else
{
uno::Reference< XAccessible > xAcc = pAccMap->GetCursorContext();
SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
if ( pAccImpl && pAccImpl->getAccessibleRole() == AccessibleRole::PARAGRAPH )
{
uno::Sequence< uno::Any > aRet(1);
aRet[0] <<= xAcc;
return aRet;
}
}
}
else if ( nType == FORFINDREPLACEFLOWTO )
{
SwCursorShell* pCursorShell = GetCursorShell();
if ( pCursorShell )
{
SwPaM *_pStartCursor = pCursorShell->GetCursor(), *_pStartCursor2 = _pStartCursor;
SwContentNode* pPrevNode = nullptr;
std::vector<SwFrame*> vFrameList;
do
{
if ( _pStartCursor && _pStartCursor->HasMark() )
{
SwContentNode* pContentNode = _pStartCursor->GetContentNode();
if ( pContentNode == pPrevNode )
{
continue;
}
SwFrame* pFrame = pContentNode ? pContentNode->getLayoutFrame( pCursorShell->GetLayout() ) : nullptr;
if ( pFrame )
{
vFrameList.push_back( pFrame );
}
pPrevNode = pContentNode;
}
}
while( _pStartCursor && ( (_pStartCursor = _pStartCursor->GetNext()) != _pStartCursor2) );
if ( vFrameList.size() )
{
uno::Sequence< uno::Any > aRet(vFrameList.size());
std::vector<SwFrame*>::iterator aIter = vFrameList.begin();
for ( sal_Int32 nIndex = 0; aIter != vFrameList.end(); ++aIter, nIndex++ )
{
uno::Reference< XAccessible > xAcc = pAccMap->GetContext(*aIter, false);
if ( xAcc.is() )
{
SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
if ( pAccImpl && pAccImpl->getAccessibleRole() == AccessibleRole::PARAGRAPH )
{
aRet[nIndex] <<= xAcc;
}
}
}
return aRet;
}
}
}
return uno::Sequence< uno::Any >();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */