Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx
Warning:line 2458, column 37
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name accmap.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx

/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <rtl/ref.hxx>
21#include <cppuhelper/weakref.hxx>
22#include <vcl/window.hxx>
23#include <svx/svdmodel.hxx>
24#include <svx/unomod.hxx>
25#include <algorithm>
26#include <map>
27#include <unordered_map>
28#include <list>
29#include <vector>
30#include <accmap.hxx>
31#include "acccontext.hxx"
32#include "accdoc.hxx"
33#include <strings.hrc>
34#include "accpreview.hxx"
35#include "accpage.hxx"
36#include "accpara.hxx"
37#include "accheaderfooter.hxx"
38#include "accfootnote.hxx"
39#include "acctextframe.hxx"
40#include "accgraphic.hxx"
41#include "accembedded.hxx"
42#include "acccell.hxx"
43#include "acctable.hxx"
44#include <fesh.hxx>
45#include <rootfrm.hxx>
46#include <txtfrm.hxx>
47#include <hffrm.hxx>
48#include <ftnfrm.hxx>
49#include <cellfrm.hxx>
50#include <tabfrm.hxx>
51#include <pagefrm.hxx>
52#include <flyfrm.hxx>
53#include <ndtyp.hxx>
54#include <IDocumentDrawModelAccess.hxx>
55#include <svx/AccessibleShapeInfo.hxx>
56#include <svx/ShapeTypeHandler.hxx>
57#include <svx/SvxShapeTypes.hxx>
58#include <svx/svdpage.hxx>
59#include <com/sun/star/accessibility/AccessibleEventId.hpp>
60#include <com/sun/star/accessibility/AccessibleStateType.hpp>
61#include <com/sun/star/accessibility/AccessibleRole.hpp>
62#include <com/sun/star/beans/XPropertySet.hpp>
63#include <com/sun/star/document/XShapeEventBroadcaster.hpp>
64#include <cppuhelper/implbase.hxx>
65#include <comphelper/interfacecontainer2.hxx>
66#include <pagepreviewlayout.hxx>
67#include <dcontact.hxx>
68#include <svx/unoapi.hxx>
69#include <svx/svdmark.hxx>
70#include <doc.hxx>
71#include <drawdoc.hxx>
72#include <pam.hxx>
73#include <ndtxt.hxx>
74#include <dflyobj.hxx>
75#include <prevwpage.hxx>
76#include <calbck.hxx>
77#include <undobj.hxx>
78#include <tools/diagnose_ex.h>
79#include <tools/debug.hxx>
80
81using namespace ::com::sun::star;
82using namespace ::com::sun::star::accessibility;
83using namespace ::sw::access;
84
85namespace {
86
87struct SwFrameFunc
88{
89 bool operator()( const SwFrame * p1, const SwFrame * p2) const
90 {
91 return p1 < p2;
92 }
93};
94
95}
96
97class SwAccessibleContextMap_Impl
98{
99public:
100 typedef const SwFrame * key_type;
101 typedef uno::WeakReference < XAccessible > mapped_type;
102 typedef std::pair<const key_type,mapped_type> value_type;
103 typedef SwFrameFunc key_compare;
104 typedef std::map<key_type,mapped_type,key_compare>::iterator iterator;
105 typedef std::map<key_type,mapped_type,key_compare>::const_iterator const_iterator;
106private:
107 std::map <key_type,mapped_type,key_compare> maMap;
108public:
109
110#if OSL_DEBUG_LEVEL1 > 0
111 bool mbLocked;
112#endif
113
114 SwAccessibleContextMap_Impl()
115#if OSL_DEBUG_LEVEL1 > 0
116 : mbLocked( false )
117#endif
118 {}
119
120 iterator begin() { return maMap.begin(); }
121 iterator end() { return maMap.end(); }
122 bool empty() const { return maMap.empty(); }
123 void clear() { maMap.clear(); }
124 iterator find(const key_type& key) { return maMap.find(key); }
21
Value assigned to 'pParent', which participates in a condition later
125 template<class... Args>
126 std::pair<iterator,bool> emplace(Args&&... args) { return maMap.emplace(std::forward<Args>(args)...); }
127 iterator erase(const_iterator const & pos) { return maMap.erase(pos); }
128};
129
130namespace {
131
132class SwDrawModellListener_Impl : public SfxListener,
133 public ::cppu::WeakImplHelper< document::XShapeEventBroadcaster >
134{
135 mutable ::osl::Mutex maListenerMutex;
136 ::comphelper::OInterfaceContainerHelper2 maEventListeners;
137 std::unordered_multimap<css::uno::Reference< css::drawing::XShape >, css::uno::Reference< css::document::XShapeEventListener >> maShapeListeners;
138 SdrModel *mpDrawModel;
139protected:
140 virtual ~SwDrawModellListener_Impl() override;
141
142public:
143 explicit SwDrawModellListener_Impl( SdrModel *pDrawModel );
144
145 // css::document::XEventBroadcaster
146 virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) override;
147 virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) override;
148 // css::document::XShapeEventBroadcaster
149 virtual void SAL_CALL addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const css::uno::Reference< css::document::XShapeEventListener >& xListener ) override;
150 virtual void SAL_CALL removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const css::uno::Reference< css::document::XShapeEventListener >& xListener ) override;
151
152 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
153 void Dispose();
154};
155
156}
157
158SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) :
159 maEventListeners( maListenerMutex ),
160 mpDrawModel( pDrawModel )
161{
162 StartListening( *mpDrawModel );
163}
164
165SwDrawModellListener_Impl::~SwDrawModellListener_Impl()
166{
167 Dispose();
168}
169
170void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener )
171{
172 maEventListeners.addInterface( xListener );
173}
174
175void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener )
176{
177 maEventListeners.removeInterface( xListener );
178}
179
180void SAL_CALL SwDrawModellListener_Impl::addShapeEventListener(
181 const css::uno::Reference< css::drawing::XShape >& xShape,
182 const uno::Reference< document::XShapeEventListener >& xListener )
183{
184 assert(xShape.is() && "no shape?")(static_cast <bool> (xShape.is() && "no shape?"
) ? void (0) : __assert_fail ("xShape.is() && \"no shape?\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 184, __extension__ __PRETTY_FUNCTION__))
;
185 osl::MutexGuard aGuard(maListenerMutex);
186 maShapeListeners.emplace(xShape, xListener);
187}
188
189void SAL_CALL SwDrawModellListener_Impl::removeShapeEventListener(
190 const css::uno::Reference< css::drawing::XShape >& xShape,
191 const uno::Reference< document::XShapeEventListener >& xListener )
192{
193 osl::MutexGuard aGuard(maListenerMutex);
194 auto [itBegin, itEnd] = maShapeListeners.equal_range(xShape);
195 for (auto it = itBegin; it != itEnd; ++it)
196 if (it->second == xListener)
197 {
198 maShapeListeners.erase(it);
199 return;
200 }
201}
202
203void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
204 const SfxHint& rHint )
205{
206 // do not broadcast notifications for writer fly frames, because there
207 // are no shapes that need to know about them.
208 if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
209 return;
210 const SdrHint *pSdrHint = static_cast<const SdrHint*>( &rHint );
211 if (pSdrHint->GetObject() &&
212 ( dynamic_cast< const SwFlyDrawObj* >(pSdrHint->GetObject()) != nullptr ||
213 dynamic_cast< const SwVirtFlyDrawObj* >(pSdrHint->GetObject()) != nullptr ||
214 typeid(SdrObject) == typeid(pSdrHint->GetObject()) ) )
215 {
216 return;
217 }
218
219 OSL_ENSURE( mpDrawModel, "draw model listener is disposed" )do { if (true && (!(mpDrawModel))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "219" ": "), "%s", "draw model listener is disposed"); }
} while (false)
;
220 if( !mpDrawModel )
221 return;
222
223 document::EventObject aEvent;
224 if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) )
225 return;
226
227 ::comphelper::OInterfaceIteratorHelper2 aIter( maEventListeners );
228 while( aIter.hasMoreElements() )
229 {
230 uno::Reference < document::XEventListener > xListener( aIter.next(),
231 uno::UNO_QUERY );
232 try
233 {
234 xListener->notifyEvent( aEvent );
235 }
236 catch( uno::RuntimeException const & )
237 {
238 TOOLS_WARN_EXCEPTION("sw.a11y", "Runtime exception caught while notifying shape")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.a11y")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Runtime exception caught while notifying shape"
<< " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"sw.a11y"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "238" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Runtime exception caught while notifying shape"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Runtime exception caught while notifying shape" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.a11y"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "238" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Runtime exception caught while notifying shape" <<
" " << exceptionToString(tools_warn_exception)) == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.a11y")
, ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "238" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Runtime exception caught while notifying shape"
<< " " << exceptionToString(tools_warn_exception
)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Runtime exception caught while notifying shape" <<
" " << exceptionToString(tools_warn_exception); ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.a11y"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "238" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
239 }
240 }
241
242 // right now, we're only handling the specific event necessary to fix this performance problem
243 if (pSdrHint->GetKind() == SdrHintKind::ObjectChange)
244 {
245 auto pSdrObject = const_cast<SdrObject*>(pSdrHint->GetObject());
246 uno::Reference<drawing::XShape> xShape(pSdrObject->getUnoShape(), uno::UNO_QUERY);
247 osl::MutexGuard aGuard(maListenerMutex);
248 auto [itBegin, itEnd] = maShapeListeners.equal_range(xShape);
249 for (auto it = itBegin; it != itEnd; ++it)
250 it->second->notifyShapeEvent(aEvent);
251 }
252}
253
254void SwDrawModellListener_Impl::Dispose()
255{
256 if (mpDrawModel != nullptr) {
257 EndListening( *mpDrawModel );
258 }
259 mpDrawModel = nullptr;
260}
261
262namespace {
263
264struct SwShapeFunc
265{
266 bool operator()( const SdrObject * p1, const SdrObject * p2) const
267 {
268 return p1 < p2;
269 }
270};
271
272}
273
274typedef std::pair < const SdrObject *, ::rtl::Reference < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl;
275
276class SwAccessibleShapeMap_Impl
277{
278public:
279
280 typedef const SdrObject * key_type;
281 typedef uno::WeakReference<XAccessible> mapped_type;
282 typedef std::pair<const key_type,mapped_type> value_type;
283 typedef SwShapeFunc key_compare;
284 typedef std::map<key_type,mapped_type,key_compare>::iterator iterator;
285 typedef std::map<key_type,mapped_type,key_compare>::const_iterator const_iterator;
286
287private:
288
289 ::accessibility::AccessibleShapeTreeInfo maInfo;
290 std::map<key_type,mapped_type,SwShapeFunc> maMap;
291
292public:
293
294 explicit SwAccessibleShapeMap_Impl( SwAccessibleMap const *pMap )
295 : maMap()
296 {
297 maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
298 maInfo.SetDevice( pMap->GetShell()->GetWin() );
299 maInfo.SetViewForwarder( pMap );
300 uno::Reference < document::XShapeEventBroadcaster > xModelBroadcaster =
301 new SwDrawModellListener_Impl(
302 pMap->GetShell()->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
303 maInfo.SetModelBroadcaster( xModelBroadcaster );
304 }
305
306 ~SwAccessibleShapeMap_Impl();
307
308 const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; }
309
310 std::unique_ptr<SwAccessibleObjShape_Impl[]> Copy( size_t& rSize,
311 const SwFEShell *pFESh,
312 SwAccessibleObjShape_Impl **pSelShape ) const;
313
314 iterator end() { return maMap.end(); }
315 const_iterator cbegin() const { return maMap.cbegin(); }
316 const_iterator cend() const { return maMap.cend(); }
317 bool empty() const { return maMap.empty(); }
318 iterator find(const key_type& key) { return maMap.find(key); }
319 template<class... Args>
320 std::pair<iterator,bool> emplace(Args&&... args) { return maMap.emplace(std::forward<Args>(args)...); }
321 iterator erase(const_iterator const & pos) { return maMap.erase(pos); }
322};
323
324SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl()
325{
326 uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetModelBroadcaster() );
327 if( xBrd.is() )
328 static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose();
329}
330
331std::unique_ptr<SwAccessibleObjShape_Impl[]>
332 SwAccessibleShapeMap_Impl::Copy(
333 size_t& rSize, const SwFEShell *pFESh,
334 SwAccessibleObjShape_Impl **pSelStart ) const
335{
336 std::unique_ptr<SwAccessibleObjShape_Impl[]> pShapes;
337 SwAccessibleObjShape_Impl *pSelShape = nullptr;
338
339 size_t nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
340 rSize = maMap.size();
341
342 if( rSize > 0 )
343 {
344 pShapes.reset(new SwAccessibleObjShape_Impl[rSize]);
345
346 SwAccessibleObjShape_Impl *pShape = pShapes.get();
347 pSelShape = &(pShapes[rSize]);
348 for( const auto& rEntry : maMap )
349 {
350 const SdrObject *pObj = rEntry.first;
351 uno::Reference < XAccessible > xAcc( rEntry.second );
352 if( nSelShapes && pFESh && pFESh->IsObjSelected( *pObj ) )
353 {
354 // selected objects are inserted from the back
355 --pSelShape;
356 pSelShape->first = pObj;
357 pSelShape->second =
358 static_cast < ::accessibility::AccessibleShape* >(
359 xAcc.get() );
360 --nSelShapes;
361 }
362 else
363 {
364 pShape->first = pObj;
365 pShape->second =
366 static_cast < ::accessibility::AccessibleShape* >(
367 xAcc.get() );
368 ++pShape;
369 }
370 }
371 assert(pSelShape == pShape)(static_cast <bool> (pSelShape == pShape) ? void (0) : __assert_fail
("pSelShape == pShape", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 371, __extension__ __PRETTY_FUNCTION__))
;
372 }
373
374 if( pSelStart )
375 *pSelStart = pSelShape;
376
377 return pShapes;
378}
379
380struct SwAccessibleEvent_Impl
381{
382public:
383 enum EventType { CARET_OR_STATES,
384 INVALID_CONTENT,
385 POS_CHANGED,
386 CHILD_POS_CHANGED,
387 SHAPE_SELECTION,
388 DISPOSE,
389 INVALID_ATTR };
390
391private:
392 SwRect maOldBox; // the old bounds for CHILD_POS_CHANGED
393 // and POS_CHANGED
394 uno::WeakReference < XAccessible > mxAcc; // The object that fires the event
395 SwAccessibleChild maFrameOrObj; // the child for CHILD_POS_CHANGED and
396 // the same as xAcc for any other
397 // event type
398 EventType meType; // The event type
399 AccessibleStates mnStates; // check states or update caret pos
400
401public:
402 const SwFrame* mpParentFrame; // The object that fires the event
403 bool IsNoXaccParentFrame() const
404 {
405 return CHILD_POS_CHANGED == meType && mpParentFrame != nullptr;
406 }
407
408public:
409 SwAccessibleEvent_Impl( EventType eT,
410 SwAccessibleContext *pA,
411 const SwAccessibleChild& rFrameOrObj )
412 : mxAcc( pA ),
413 maFrameOrObj( rFrameOrObj ),
414 meType( eT ),
415 mnStates( AccessibleStates::NONE ),
416 mpParentFrame( nullptr )
417 {}
418
419 SwAccessibleEvent_Impl( EventType eT,
420 const SwAccessibleChild& rFrameOrObj )
421 : maFrameOrObj( rFrameOrObj ),
422 meType( eT ),
423 mnStates( AccessibleStates::NONE ),
424 mpParentFrame( nullptr )
425 {
426 assert(SwAccessibleEvent_Impl::DISPOSE == meType &&(static_cast <bool> (SwAccessibleEvent_Impl::DISPOSE ==
meType && "wrong event constructor, DISPOSE only") ?
void (0) : __assert_fail ("SwAccessibleEvent_Impl::DISPOSE == meType && \"wrong event constructor, DISPOSE only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 427, __extension__ __PRETTY_FUNCTION__))
427 "wrong event constructor, DISPOSE only")(static_cast <bool> (SwAccessibleEvent_Impl::DISPOSE ==
meType && "wrong event constructor, DISPOSE only") ?
void (0) : __assert_fail ("SwAccessibleEvent_Impl::DISPOSE == meType && \"wrong event constructor, DISPOSE only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 427, __extension__ __PRETTY_FUNCTION__))
;
428 }
429
430 explicit SwAccessibleEvent_Impl( EventType eT )
431 : meType( eT ),
432 mnStates( AccessibleStates::NONE ),
433 mpParentFrame( nullptr )
434 {
435 assert(SwAccessibleEvent_Impl::SHAPE_SELECTION == meType &&(static_cast <bool> (SwAccessibleEvent_Impl::SHAPE_SELECTION
== meType && "wrong event constructor, SHAPE_SELECTION only"
) ? void (0) : __assert_fail ("SwAccessibleEvent_Impl::SHAPE_SELECTION == meType && \"wrong event constructor, SHAPE_SELECTION only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 436, __extension__ __PRETTY_FUNCTION__))
436 "wrong event constructor, SHAPE_SELECTION only" )(static_cast <bool> (SwAccessibleEvent_Impl::SHAPE_SELECTION
== meType && "wrong event constructor, SHAPE_SELECTION only"
) ? void (0) : __assert_fail ("SwAccessibleEvent_Impl::SHAPE_SELECTION == meType && \"wrong event constructor, SHAPE_SELECTION only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 436, __extension__ __PRETTY_FUNCTION__))
;
437 }
438
439 SwAccessibleEvent_Impl( EventType eT,
440 SwAccessibleContext *pA,
441 const SwAccessibleChild& rFrameOrObj,
442 const SwRect& rR )
443 : maOldBox( rR ),
444 mxAcc( pA ),
445 maFrameOrObj( rFrameOrObj ),
446 meType( eT ),
447 mnStates( AccessibleStates::NONE ),
448 mpParentFrame( nullptr )
449 {
450 assert((SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType ||(static_cast <bool> ((SwAccessibleEvent_Impl::CHILD_POS_CHANGED
== meType || SwAccessibleEvent_Impl::POS_CHANGED == meType) &&
"wrong event constructor, (CHILD_)POS_CHANGED only") ? void (
0) : __assert_fail ("(SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType || SwAccessibleEvent_Impl::POS_CHANGED == meType) && \"wrong event constructor, (CHILD_)POS_CHANGED only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 452, __extension__ __PRETTY_FUNCTION__))
451 SwAccessibleEvent_Impl::POS_CHANGED == meType) &&(static_cast <bool> ((SwAccessibleEvent_Impl::CHILD_POS_CHANGED
== meType || SwAccessibleEvent_Impl::POS_CHANGED == meType) &&
"wrong event constructor, (CHILD_)POS_CHANGED only") ? void (
0) : __assert_fail ("(SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType || SwAccessibleEvent_Impl::POS_CHANGED == meType) && \"wrong event constructor, (CHILD_)POS_CHANGED only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 452, __extension__ __PRETTY_FUNCTION__))
452 "wrong event constructor, (CHILD_)POS_CHANGED only" )(static_cast <bool> ((SwAccessibleEvent_Impl::CHILD_POS_CHANGED
== meType || SwAccessibleEvent_Impl::POS_CHANGED == meType) &&
"wrong event constructor, (CHILD_)POS_CHANGED only") ? void (
0) : __assert_fail ("(SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType || SwAccessibleEvent_Impl::POS_CHANGED == meType) && \"wrong event constructor, (CHILD_)POS_CHANGED only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 452, __extension__ __PRETTY_FUNCTION__))
;
453 }
454
455 SwAccessibleEvent_Impl( EventType eT,
456 SwAccessibleContext *pA,
457 const SwAccessibleChild& rFrameOrObj,
458 const AccessibleStates _nStates )
459 : mxAcc( pA ),
460 maFrameOrObj( rFrameOrObj ),
461 meType( eT ),
462 mnStates( _nStates ),
463 mpParentFrame( nullptr )
464 {
465 assert( SwAccessibleEvent_Impl::CARET_OR_STATES == meType &&(static_cast <bool> (SwAccessibleEvent_Impl::CARET_OR_STATES
== meType && "wrong event constructor, CARET_OR_STATES only"
) ? void (0) : __assert_fail ("SwAccessibleEvent_Impl::CARET_OR_STATES == meType && \"wrong event constructor, CARET_OR_STATES only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 466, __extension__ __PRETTY_FUNCTION__))
466 "wrong event constructor, CARET_OR_STATES only" )(static_cast <bool> (SwAccessibleEvent_Impl::CARET_OR_STATES
== meType && "wrong event constructor, CARET_OR_STATES only"
) ? void (0) : __assert_fail ("SwAccessibleEvent_Impl::CARET_OR_STATES == meType && \"wrong event constructor, CARET_OR_STATES only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 466, __extension__ __PRETTY_FUNCTION__))
;
467 }
468
469 SwAccessibleEvent_Impl( EventType eT, const SwFrame *pParentFrame,
470 const SwAccessibleChild& rFrameOrObj, const SwRect& rR ) :
471 maOldBox( rR ),
472 maFrameOrObj( rFrameOrObj ),
473 meType( eT ),
474 mnStates( AccessibleStates::NONE ),
475 mpParentFrame( pParentFrame )
476 {
477 assert( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType &&(static_cast <bool> (SwAccessibleEvent_Impl::CHILD_POS_CHANGED
== meType && "wrong event constructor, CHILD_POS_CHANGED only"
) ? void (0) : __assert_fail ("SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType && \"wrong event constructor, CHILD_POS_CHANGED only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 478, __extension__ __PRETTY_FUNCTION__))
478 "wrong event constructor, CHILD_POS_CHANGED only" )(static_cast <bool> (SwAccessibleEvent_Impl::CHILD_POS_CHANGED
== meType && "wrong event constructor, CHILD_POS_CHANGED only"
) ? void (0) : __assert_fail ("SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType && \"wrong event constructor, CHILD_POS_CHANGED only\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 478, __extension__ __PRETTY_FUNCTION__))
;
479 }
480
481 // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
482 void SetType( EventType eT )
483 {
484 meType = eT;
485 }
486 EventType GetType() const
487 {
488 return meType;
489 }
490
491 ::rtl::Reference < SwAccessibleContext > GetContext() const
492 {
493 uno::Reference < XAccessible > xTmp( mxAcc );
494 ::rtl::Reference < SwAccessibleContext > xAccImpl(
495 static_cast<SwAccessibleContext*>( xTmp.get() ) );
496
497 return xAccImpl;
498 }
499
500 const SwRect& GetOldBox() const
501 {
502 return maOldBox;
503 }
504 // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
505 void SetOldBox( const SwRect& rOldBox )
506 {
507 maOldBox = rOldBox;
508 }
509
510 const SwAccessibleChild& GetFrameOrObj() const
511 {
512 return maFrameOrObj;
513 }
514
515 // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
516 void SetStates( AccessibleStates _nStates )
517 {
518 mnStates |= _nStates;
519 }
520
521 bool IsUpdateCursorPos() const
522 {
523 return bool(mnStates & AccessibleStates::CARET);
524 }
525 bool IsInvalidateStates() const
526 {
527 return bool(mnStates & (AccessibleStates::EDITABLE | AccessibleStates::OPAQUE));
528 }
529 bool IsInvalidateRelation() const
530 {
531 return bool(mnStates & (AccessibleStates::RELATION_FROM | AccessibleStates::RELATION_TO));
532 }
533 bool IsInvalidateTextSelection() const
534 {
535 return bool( mnStates & AccessibleStates::TEXT_SELECTION_CHANGED );
536 }
537
538 bool IsInvalidateTextAttrs() const
539 {
540 return bool( mnStates & AccessibleStates::TEXT_ATTRIBUTE_CHANGED );
541 }
542
543 AccessibleStates GetStates() const
544 {
545 return mnStates;
546 }
547
548 AccessibleStates GetAllStates() const
549 {
550 return mnStates;
551 }
552};
553
554class SwAccessibleEventList_Impl
555{
556 std::list<SwAccessibleEvent_Impl> maEvents;
557 bool mbFiring;
558
559public:
560 SwAccessibleEventList_Impl()
561 : mbFiring( false )
562 {}
563
564 void SetFiring()
565 {
566 mbFiring = true;
567 }
568 bool IsFiring() const
569 {
570 return mbFiring;
571 }
572
573 void MoveMissingXAccToEnd();
574
575 size_t size() const { return maEvents.size(); }
576 std::list<SwAccessibleEvent_Impl>::iterator begin() { return maEvents.begin(); }
577 std::list<SwAccessibleEvent_Impl>::iterator end() { return maEvents.end(); }
578 std::list<SwAccessibleEvent_Impl>::iterator insert( const std::list<SwAccessibleEvent_Impl>::iterator& aIter,
579 const SwAccessibleEvent_Impl& rEvent )
580 {
581 return maEvents.insert( aIter, rEvent );
582 }
583 std::list<SwAccessibleEvent_Impl>::iterator erase( const std::list<SwAccessibleEvent_Impl>::iterator& aPos )
584 {
585 return maEvents.erase( aPos );
586 }
587};
588
589// see comment in SwAccessibleMap::InvalidatePosOrSize()
590// last case "else if(pParent)" for why this surprising hack exists
591void SwAccessibleEventList_Impl::MoveMissingXAccToEnd()
592{
593 size_t nSize = size();
594 if (nSize < 2 )
595 {
596 return;
597 }
598 SwAccessibleEventList_Impl lstEvent;
599 for (auto li = begin(); li != end(); )
600 {
601 if (li->IsNoXaccParentFrame())
602 {
603 lstEvent.insert(lstEvent.end(), *li);
604 li = erase(li);
605 }
606 else
607 ++li;
608 }
609 assert(size() + lstEvent.size() == nSize)(static_cast <bool> (size() + lstEvent.size() == nSize)
? void (0) : __assert_fail ("size() + lstEvent.size() == nSize"
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 609, __extension__ __PRETTY_FUNCTION__))
;
610 maEvents.insert(end(),lstEvent.begin(),lstEvent.end());
611 assert(size() == nSize)(static_cast <bool> (size() == nSize) ? void (0) : __assert_fail
("size() == nSize", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 611, __extension__ __PRETTY_FUNCTION__))
;
612}
613
614namespace {
615
616struct SwAccessibleChildFunc
617{
618 bool operator()( const SwAccessibleChild& r1,
619 const SwAccessibleChild& r2 ) const
620 {
621 const void *p1 = r1.GetSwFrame()
622 ? static_cast < const void * >( r1.GetSwFrame())
623 : ( r1.GetDrawObject()
624 ? static_cast < const void * >( r1.GetDrawObject() )
625 : static_cast < const void * >( r1.GetWindow() ) );
626 const void *p2 = r2.GetSwFrame()
627 ? static_cast < const void * >( r2.GetSwFrame())
628 : ( r2.GetDrawObject()
629 ? static_cast < const void * >( r2.GetDrawObject() )
630 : static_cast < const void * >( r2.GetWindow() ) );
631 return p1 < p2;
632 }
633};
634
635}
636
637class SwAccessibleEventMap_Impl
638{
639public:
640 typedef SwAccessibleChild key_type;
641 typedef std::list<SwAccessibleEvent_Impl>::iterator mapped_type;
642 typedef std::pair<const key_type,mapped_type> value_type;
643 typedef SwAccessibleChildFunc key_compare;
644 typedef std::map<key_type,mapped_type,key_compare>::iterator iterator;
645 typedef std::map<key_type,mapped_type,key_compare>::const_iterator const_iterator;
646private:
647 std::map <key_type,mapped_type,key_compare> maMap;
648public:
649 iterator end() { return maMap.end(); }
650 iterator find(const key_type& key) { return maMap.find(key); }
651 template<class... Args>
652 std::pair<iterator,bool> emplace(Args&&... args) { return maMap.emplace(std::forward<Args>(args)...); }
653 iterator erase(const_iterator const & pos) { return maMap.erase(pos); }
654};
655
656namespace {
657
658struct SwAccessibleParaSelection
659{
660 TextFrameIndex nStartOfSelection;
661 TextFrameIndex nEndOfSelection;
662
663 SwAccessibleParaSelection(const TextFrameIndex nStartOfSelection_,
664 const TextFrameIndex nEndOfSelection_)
665 : nStartOfSelection(nStartOfSelection_)
666 , nEndOfSelection(nEndOfSelection_)
667 {}
668};
669
670struct SwXAccWeakRefComp
671{
672 bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1,
673 const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const
674 {
675 return _rXAccWeakRef1.get() < _rXAccWeakRef2.get();
676 }
677};
678
679}
680
681class SwAccessibleSelectedParas_Impl
682{
683public:
684 typedef uno::WeakReference < XAccessible > key_type;
685 typedef SwAccessibleParaSelection mapped_type;
686 typedef std::pair<const key_type,mapped_type> value_type;
687 typedef SwXAccWeakRefComp key_compare;
688 typedef std::map<key_type,mapped_type,key_compare>::iterator iterator;
689 typedef std::map<key_type,mapped_type,key_compare>::const_iterator const_iterator;
690private:
691 std::map<key_type,mapped_type,key_compare> maMap;
692public:
693 iterator begin() { return maMap.begin(); }
694 iterator end() { return maMap.end(); }
695 iterator find(const key_type& key) { return maMap.find(key); }
696 template<class... Args>
697 std::pair<iterator,bool> emplace(Args&&... args) { return maMap.emplace(std::forward<Args>(args)...); }
698 iterator erase(const_iterator const & pos) { return maMap.erase(pos); }
699};
700
701// helper class that stores preview data
702class SwAccPreviewData
703{
704 typedef std::vector<tools::Rectangle> Rectangles;
705 Rectangles maPreviewRects;
706 Rectangles maLogicRects;
707
708 SwRect maVisArea;
709 Fraction maScale;
710
711 const SwPageFrame *mpSelPage;
712
713 /** adjust logic page rectangle to its visible part
714
715 @param _iorLogicPgSwRect
716 input/output parameter - reference to the logic page rectangle, which
717 has to be adjusted.
718
719 @param _rPreviewPgSwRect
720 input parameter - constant reference to the corresponding preview page
721 rectangle; needed to determine the visible part of the logic page rectangle.
722
723 @param _rPreviewWinSize
724 input parameter - constant reference to the preview window size in TWIP;
725 needed to determine the visible part of the logic page rectangle
726 */
727 static void AdjustLogicPgRectToVisibleArea( SwRect& _iorLogicPgSwRect,
728 const SwRect& _rPreviewPgSwRect,
729 const Size& _rPreviewWinSize );
730
731public:
732 SwAccPreviewData();
733
734 void Update( const SwAccessibleMap& rAccMap,
735 const std::vector<std::unique_ptr<PreviewPage>>& _rPreviewPages,
736 const Fraction& _rScale,
737 const SwPageFrame* _pSelectedPageFrame,
738 const Size& _rPreviewWinSize );
739
740 void InvalidateSelection( const SwPageFrame* _pSelectedPageFrame );
741
742 const SwRect& GetVisArea() const { return maVisArea;}
743
744 /** Adjust the MapMode so that the preview page appears at the
745 * proper position. rPoint identifies the page for which the
746 * MapMode should be adjusted. If bFromPreview is true, rPoint is
747 * a preview coordinate; else it's a document coordinate. */
748 void AdjustMapMode( MapMode& rMapMode,
749 const Point& rPoint ) const;
750
751 const SwPageFrame *GetSelPage() const { return mpSelPage; }
752
753 void DisposePage(const SwPageFrame *pPageFrame );
754};
755
756SwAccPreviewData::SwAccPreviewData() :
757 mpSelPage( nullptr )
758{
759}
760
761void SwAccPreviewData::Update( const SwAccessibleMap& rAccMap,
762 const std::vector<std::unique_ptr<PreviewPage>>& _rPreviewPages,
763 const Fraction& _rScale,
764 const SwPageFrame* _pSelectedPageFrame,
765 const Size& _rPreviewWinSize )
766{
767 // store preview scaling, maximal preview page size and selected page
768 maScale = _rScale;
769 mpSelPage = _pSelectedPageFrame;
770
771 // prepare loop on preview pages
772 maPreviewRects.clear();
773 maLogicRects.clear();
774 SwAccessibleChild aPage;
775 maVisArea.Clear();
776
777 // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and
778 // <maVisArea>
779 for ( auto & rpPreviewPage : _rPreviewPages )
780 {
781 aPage = rpPreviewPage->pPage;
782
783 // add preview page rectangle to <maPreviewRects>
784 tools::Rectangle aPreviewPgRect( rpPreviewPage->aPreviewWinPos, rpPreviewPage->aPageSize );
785 maPreviewRects.push_back( aPreviewPgRect );
786
787 // add logic page rectangle to <maLogicRects>
788 SwRect aLogicPgSwRect( aPage.GetBox( rAccMap ) );
789 tools::Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() );
790 maLogicRects.push_back( aLogicPgRect );
791 // union visible area with visible part of logic page rectangle
792 if ( rpPreviewPage->bVisible )
793 {
794 if ( !rpPreviewPage->pPage->IsEmptyPage() )
795 {
796 AdjustLogicPgRectToVisibleArea( aLogicPgSwRect,
797 SwRect( aPreviewPgRect ),
798 _rPreviewWinSize );
799 }
800 if ( maVisArea.IsEmpty() )
801 maVisArea = aLogicPgSwRect;
802 else
803 maVisArea.Union( aLogicPgSwRect );
804 }
805 }
806}
807
808void SwAccPreviewData::InvalidateSelection( const SwPageFrame* _pSelectedPageFrame )
809{
810 mpSelPage = _pSelectedPageFrame;
811 assert(mpSelPage)(static_cast <bool> (mpSelPage) ? void (0) : __assert_fail
("mpSelPage", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 811, __extension__ __PRETTY_FUNCTION__))
;
812}
813
814namespace {
815
816struct ContainsPredicate
817{
818 const Point& mrPoint;
819 explicit ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {}
820 bool operator() ( const tools::Rectangle& rRect ) const
821 {
822 return rRect.IsInside( mrPoint );
823 }
824};
825
826}
827
828void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode,
829 const Point& rPoint ) const
830{
831 // adjust scale
832 rMapMode.SetScaleX( maScale );
833 rMapMode.SetScaleY( maScale );
834
835 // find proper rectangle
836 Rectangles::const_iterator aBegin = maLogicRects.begin();
837 Rectangles::const_iterator aEnd = maLogicRects.end();
838 Rectangles::const_iterator aFound = std::find_if( aBegin, aEnd,
839 ContainsPredicate( rPoint ) );
840
841 if( aFound != aEnd )
842 {
843 // found! set new origin
844 Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft();
845 aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft();
846 rMapMode.SetOrigin( aPoint );
847 }
848 // else: don't adjust MapMode
849}
850
851void SwAccPreviewData::DisposePage(const SwPageFrame *pPageFrame )
852{
853 if( mpSelPage == pPageFrame )
854 mpSelPage = nullptr;
855}
856
857// adjust logic page rectangle to its visible part
858void SwAccPreviewData::AdjustLogicPgRectToVisibleArea(
859 SwRect& _iorLogicPgSwRect,
860 const SwRect& _rPreviewPgSwRect,
861 const Size& _rPreviewWinSize )
862{
863 // determine preview window rectangle
864 const SwRect aPreviewWinSwRect( Point( 0, 0 ), _rPreviewWinSize );
865 // calculate visible preview page rectangle
866 SwRect aVisPreviewPgSwRect( _rPreviewPgSwRect );
867 aVisPreviewPgSwRect.Intersection( aPreviewWinSwRect );
868 // adjust logic page rectangle
869 SwTwips nTmpDiff;
870 // left
871 nTmpDiff = aVisPreviewPgSwRect.Left() - _rPreviewPgSwRect.Left();
872 _iorLogicPgSwRect.AddLeft( nTmpDiff );
873 // top
874 nTmpDiff = aVisPreviewPgSwRect.Top() - _rPreviewPgSwRect.Top();
875 _iorLogicPgSwRect.AddTop( nTmpDiff );
876 // right
877 nTmpDiff = _rPreviewPgSwRect.Right() - aVisPreviewPgSwRect.Right();
878 _iorLogicPgSwRect.AddRight( - nTmpDiff );
879 // bottom
880 nTmpDiff = _rPreviewPgSwRect.Bottom() - aVisPreviewPgSwRect.Bottom();
881 _iorLogicPgSwRect.AddBottom( - nTmpDiff );
882}
883
884static bool AreInSameTable( const uno::Reference< XAccessible >& rAcc,
885 const SwFrame *pFrame )
886{
887 bool bRet = false;
888
889 if( pFrame && pFrame->IsCellFrame() && rAcc.is() )
890 {
891 // Is it in the same table? We check that
892 // by comparing the last table frame in the
893 // follow chain, because that's cheaper than
894 // searching the first one.
895 SwAccessibleContext *pAccImpl =
896 static_cast< SwAccessibleContext *>( rAcc.get() );
897 if( pAccImpl->GetFrame()->IsCellFrame() )
898 {
899 const SwTabFrame *pTabFrame1 = pAccImpl->GetFrame()->FindTabFrame();
900 if (pTabFrame1)
901 {
902 while (pTabFrame1->GetFollow())
903 pTabFrame1 = pTabFrame1->GetFollow();
904 }
905
906 const SwTabFrame *pTabFrame2 = pFrame->FindTabFrame();
907 if (pTabFrame2)
908 {
909 while (pTabFrame2->GetFollow())
910 pTabFrame2 = pTabFrame2->GetFollow();
911 }
912
913 bRet = (pTabFrame1 == pTabFrame2);
914 }
915 }
916
917 return bRet;
918}
919
920void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent )
921{
922 ::rtl::Reference < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
923 if (!xAccImpl.is() && rEvent.mpParentFrame != nullptr)
924 {
925 SwAccessibleContextMap_Impl::iterator aIter =
926 mpFrameMap->find( rEvent.mpParentFrame );
927 if( aIter != mpFrameMap->end() )
928 {
929 uno::Reference < XAccessible > xAcc( (*aIter).second );
930 if (xAcc.is())
931 {
932 uno::Reference < XAccessibleContext > xContext(xAcc,uno::UNO_QUERY);
933 if (xContext.is() && xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
934 {
935 xAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
936 }
937 }
938 }
939 }
940 if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() )
941 {
942 DoInvalidateShapeSelection();
943 }
944 else if( xAccImpl.is() && xAccImpl->GetFrame() )
945 {
946 if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE &&
947 rEvent.IsInvalidateTextAttrs() )
948 {
949 xAccImpl->InvalidateAttr();
950 }
951 switch( rEvent.GetType() )
952 {
953 case SwAccessibleEvent_Impl::INVALID_CONTENT:
954 xAccImpl->InvalidateContent();
955 break;
956 case SwAccessibleEvent_Impl::POS_CHANGED:
957 xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() );
958 break;
959 case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
960 xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrameOrObj(),
961 rEvent.GetOldBox() );
962 break;
963 case SwAccessibleEvent_Impl::DISPOSE:
964 assert(!"dispose event has been stored")(static_cast <bool> (!"dispose event has been stored") ?
void (0) : __assert_fail ("!\"dispose event has been stored\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 964, __extension__ __PRETTY_FUNCTION__))
;
965 break;
966 case SwAccessibleEvent_Impl::INVALID_ATTR:
967 // nothing to do here - handled above
968 break;
969 default:
970 break;
971 }
972 if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
973 {
974 if( rEvent.IsUpdateCursorPos() )
975 xAccImpl->InvalidateCursorPos();
976 if( rEvent.IsInvalidateStates() )
977 xAccImpl->InvalidateStates( rEvent.GetStates() );
978 if( rEvent.IsInvalidateRelation() )
979 {
980 // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and
981 // CONTENT_FLOWS_TO_RELATION_CHANGED are possible
982 if ( rEvent.GetAllStates() & AccessibleStates::RELATION_FROM )
983 {
984 xAccImpl->InvalidateRelation(
985 AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED );
986 }
987 if ( rEvent.GetAllStates() & AccessibleStates::RELATION_TO )
988 {
989 xAccImpl->InvalidateRelation(
990 AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
991 }
992 }
993
994 if ( rEvent.IsInvalidateTextSelection() )
995 {
996 xAccImpl->InvalidateTextSelection();
997 }
998 }
999 }
1000}
1001
1002void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
1003{
1004 osl::MutexGuard aGuard( maEventMutex );
1005
1006 if( !mpEvents )
1007 mpEvents.reset(new SwAccessibleEventList_Impl);
1008 if( !mpEventMap )
1009 mpEventMap.reset(new SwAccessibleEventMap_Impl);
1010
1011 if( mpEvents->IsFiring() )
1012 {
1013 // While events are fired new ones are generated. They have to be fired
1014 // now. This does not work for DISPOSE events!
1015 OSL_ENSURE( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,do { if (true && (!(rEvent.GetType() != SwAccessibleEvent_Impl
::DISPOSE))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1016" ": "), "%s", "dispose event while firing events")
; } } while (false)
1016 "dispose event while firing events" )do { if (true && (!(rEvent.GetType() != SwAccessibleEvent_Impl
::DISPOSE))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1016" ": "), "%s", "dispose event while firing events")
; } } while (false)
;
1017 FireEvent( rEvent );
1018 }
1019 else
1020 {
1021
1022 SwAccessibleEventMap_Impl::iterator aIter =
1023 mpEventMap->find( rEvent.GetFrameOrObj() );
1024 if( aIter != mpEventMap->end() )
1025 {
1026 SwAccessibleEvent_Impl aEvent( *(*aIter).second );
1027 assert( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE &&(static_cast <bool> (aEvent.GetType() != SwAccessibleEvent_Impl
::DISPOSE && "dispose events should not be stored") ?
void (0) : __assert_fail ("aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE && \"dispose events should not be stored\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1028, __extension__ __PRETTY_FUNCTION__))
1028 "dispose events should not be stored" )(static_cast <bool> (aEvent.GetType() != SwAccessibleEvent_Impl
::DISPOSE && "dispose events should not be stored") ?
void (0) : __assert_fail ("aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE && \"dispose events should not be stored\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1028, __extension__ __PRETTY_FUNCTION__))
;
1029 bool bAppendEvent = true;
1030 switch( rEvent.GetType() )
1031 {
1032 case SwAccessibleEvent_Impl::CARET_OR_STATES:
1033 // A CARET_OR_STATES event is added to any other
1034 // event only. It is broadcasted after any other event, so the
1035 // event should be put to the back.
1036 OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,do { if (true && (!(aEvent.GetType() != SwAccessibleEvent_Impl
::CHILD_POS_CHANGED))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1037" ": "), "%s", "invalid event combination"); } } while
(false)
1037 "invalid event combination" )do { if (true && (!(aEvent.GetType() != SwAccessibleEvent_Impl
::CHILD_POS_CHANGED))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1037" ": "), "%s", "invalid event combination"); } } while
(false)
;
1038 aEvent.SetStates( rEvent.GetAllStates() );
1039 break;
1040 case SwAccessibleEvent_Impl::INVALID_CONTENT:
1041 // An INVALID_CONTENT event overwrites a CARET_OR_STATES
1042 // event (but keeps its flags) and it is contained in a
1043 // POS_CHANGED event.
1044 // Therefore, the event's type has to be adapted and the event
1045 // has to be put at the end.
1046 //
1047 // fdo#56031 An INVALID_CONTENT event overwrites a INVALID_ATTR
1048 // event and overwrites its flags
1049 OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,do { if (true && (!(aEvent.GetType() != SwAccessibleEvent_Impl
::CHILD_POS_CHANGED))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1050" ": "), "%s", "invalid event combination"); } } while
(false)
1050 "invalid event combination" )do { if (true && (!(aEvent.GetType() != SwAccessibleEvent_Impl
::CHILD_POS_CHANGED))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1050" ": "), "%s", "invalid event combination"); } } while
(false)
;
1051 if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES )
1052 aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
1053 else if ( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR )
1054 {
1055 aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
1056 aEvent.SetStates( rEvent.GetAllStates() );
1057 }
1058
1059 break;
1060 case SwAccessibleEvent_Impl::POS_CHANGED:
1061 // A pos changed event overwrites CARET_STATES (keeping its
1062 // flags) as well as INVALID_CONTENT. The old box position
1063 // has to be stored however if the old event is not a
1064 // POS_CHANGED itself.
1065 OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,do { if (true && (!(aEvent.GetType() != SwAccessibleEvent_Impl
::CHILD_POS_CHANGED))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1066" ": "), "%s", "invalid event combination"); } } while
(false)
1066 "invalid event combination" )do { if (true && (!(aEvent.GetType() != SwAccessibleEvent_Impl
::CHILD_POS_CHANGED))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1066" ": "), "%s", "invalid event combination"); } } while
(false)
;
1067 if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED )
1068 aEvent.SetOldBox( rEvent.GetOldBox() );
1069 aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED );
1070 break;
1071 case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
1072 // CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED
1073 // events. The only action that needs to be done again is
1074 // to put the old event to the back. The new one cannot be used,
1075 // because we are interested in the old frame bounds.
1076 OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED,do { if (true && (!(aEvent.GetType() == SwAccessibleEvent_Impl
::CHILD_POS_CHANGED))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1077" ": "), "%s", "invalid event combination"); } } while
(false)
1077 "invalid event combination" )do { if (true && (!(aEvent.GetType() == SwAccessibleEvent_Impl
::CHILD_POS_CHANGED))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1077" ": "), "%s", "invalid event combination"); } } while
(false)
;
1078 break;
1079 case SwAccessibleEvent_Impl::SHAPE_SELECTION:
1080 OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION,do { if (true && (!(aEvent.GetType() == SwAccessibleEvent_Impl
::SHAPE_SELECTION))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1081" ": "), "%s", "invalid event combination"); } } while
(false)
1081 "invalid event combination" )do { if (true && (!(aEvent.GetType() == SwAccessibleEvent_Impl
::SHAPE_SELECTION))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1081" ": "), "%s", "invalid event combination"); } } while
(false)
;
1082 break;
1083 case SwAccessibleEvent_Impl::DISPOSE:
1084 // DISPOSE events overwrite all others. They are not stored
1085 // but executed immediately to avoid broadcasting of
1086 // nonfunctional objects. So what needs to be done here is to
1087 // remove all events for the frame in question.
1088 bAppendEvent = false;
1089 break;
1090 case SwAccessibleEvent_Impl::INVALID_ATTR:
1091 OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR,do { if (true && (!(aEvent.GetType() == SwAccessibleEvent_Impl
::INVALID_ATTR))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1092" ": "), "%s", "invalid event combination"); } } while
(false)
1092 "invalid event combination" )do { if (true && (!(aEvent.GetType() == SwAccessibleEvent_Impl
::INVALID_ATTR))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1092" ": "), "%s", "invalid event combination"); } } while
(false)
;
1093 break;
1094 }
1095 if( bAppendEvent )
1096 {
1097 mpEvents->erase( (*aIter).second );
1098 (*aIter).second = mpEvents->insert( mpEvents->end(), aEvent );
1099 }
1100 else
1101 {
1102 mpEvents->erase( (*aIter).second );
1103 mpEventMap->erase( aIter );
1104 }
1105 }
1106 else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
1107 {
1108 mpEventMap->emplace( rEvent.GetFrameOrObj(),
1109 mpEvents->insert( mpEvents->end(), rEvent ) );
1110 }
1111 }
1112}
1113
1114void SwAccessibleMap::InvalidateCursorPosition(
1115 const uno::Reference< XAccessible >& rAcc )
1116{
1117 SwAccessibleContext *pAccImpl =
1118 static_cast< SwAccessibleContext *>( rAcc.get() );
1119 assert(pAccImpl)(static_cast <bool> (pAccImpl) ? void (0) : __assert_fail
("pAccImpl", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1119, __extension__ __PRETTY_FUNCTION__))
;
1120 assert(pAccImpl->GetFrame())(static_cast <bool> (pAccImpl->GetFrame()) ? void (0
) : __assert_fail ("pAccImpl->GetFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1120, __extension__ __PRETTY_FUNCTION__))
;
1121 if( GetShell()->ActionPend() )
1122 {
1123 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
1124 pAccImpl,
1125 SwAccessibleChild(pAccImpl->GetFrame()),
1126 AccessibleStates::CARET );
1127 AppendEvent( aEvent );
1128 }
1129 else
1130 {
1131 FireEvents();
1132 // While firing events the current frame might have
1133 // been disposed because it moved out of the visible area.
1134 // Setting the cursor for such frames is useless and even
1135 // causes asserts.
1136 if( pAccImpl->GetFrame() )
1137 pAccImpl->InvalidateCursorPos();
1138 }
1139}
1140
1141void SwAccessibleMap::InvalidateShapeSelection()
1142{
1143 if( GetShell()->ActionPend() )
1144 {
1145 SwAccessibleEvent_Impl aEvent(
1146 SwAccessibleEvent_Impl::SHAPE_SELECTION );
1147 AppendEvent( aEvent );
1148 }
1149 else
1150 {
1151 FireEvents();
1152 DoInvalidateShapeSelection();
1153 }
1154}
1155
1156//This method should implement the following functions:
1157//1.find the shape objects and set the selected state.
1158//2.find the Swframe objects and set the selected state.
1159//3.find the paragraph objects and set the selected state.
1160void SwAccessibleMap::InvalidateShapeInParaSelection()
1161{
1162 std::unique_ptr<SwAccessibleObjShape_Impl[]> pShapes;
1163 SwAccessibleObjShape_Impl *pSelShape = nullptr;
1164 size_t nShapes = 0;
1165
1166 const SwViewShell *pVSh = GetShell();
1167 const SwFEShell *pFESh = dynamic_cast<const SwFEShell*>( pVSh) != nullptr ?
1168 static_cast< const SwFEShell * >( pVSh ) : nullptr;
1169 SwPaM* pCursor = pFESh ? pFESh->GetCursor( false /* ??? */ ) : nullptr;
1170
1171 //const size_t nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1172
1173 {
1174 osl::MutexGuard aGuard( maMutex );
1175 if( mpShapeMap )
1176 pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1177 }
1178
1179 bool bIsSelAll =IsDocumentSelAll();
1180
1181 if( mpShapeMap )
1182 {
1183 //Checked for shapes.
1184 SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->cbegin();
1185 SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->cend();
1186
1187 if( bIsSelAll)
1188 {
1189 while( aIter != aEndIter )
1190 {
1191 uno::Reference < XAccessible > xAcc( (*aIter).second );
1192 if( xAcc.is() )
1193 static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->SetState( AccessibleStateType::SELECTED );
1194
1195 ++aIter;
1196 }
1197 }
1198 else
1199 {
1200 while( aIter != aEndIter )
1201 {
1202 const SwFrameFormat *pFrameFormat = (*aIter).first ? ::FindFrameFormat( (*aIter).first ) : nullptr;
1203 if( !pFrameFormat )
1204 {
1205 ++aIter;
1206 continue;
1207 }
1208 const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
1209 const SwPosition *pPos = rAnchor.GetContentAnchor();
1210
1211 if(rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
1212 {
1213 uno::Reference < XAccessible > xAcc( (*aIter).second );
1214 if(xAcc.is())
1215 static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->ResetState( AccessibleStateType::SELECTED );
1216
1217 ++aIter;
1218 continue;
1219 }
1220
1221 if( !pPos )
1222 {
1223 ++aIter;
1224 continue;
1225 }
1226 if( pPos->nNode.GetNode().GetTextNode() )
1227 {
1228 int nIndex = pPos->nContent.GetIndex();
1229 bool bMarked = false;
1230 if( pCursor != nullptr )
1231 {
1232 const SwTextNode* pNode = pPos->nNode.GetNode().GetTextNode();
1233 SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(pNode->getLayoutFrame(pVSh->GetLayout())));
1234 sal_uLong nFirstNode(pFrame->GetTextNodeFirst()->GetIndex());
1235 sal_uLong nLastNode;
1236 if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara())
1237 {
1238 nLastNode = pMerged->pLastNode->GetIndex();
1239 }
1240 else
1241 {
1242 nLastNode = nFirstNode;
1243 }
1244
1245 sal_uLong nHere = pNode->GetIndex();
1246
1247 for(SwPaM& rTmpCursor : pCursor->GetRingContainer())
1248 {
1249 // ignore, if no mark
1250 if( rTmpCursor.HasMark() )
1251 {
1252 bMarked = true;
1253 // check whether nHere is 'inside' pCursor
1254 SwPosition* pStart = rTmpCursor.Start();
1255 sal_uLong nStartIndex = pStart->nNode.GetIndex();
1256 SwPosition* pEnd = rTmpCursor.End();
1257 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
1258 if ((nStartIndex <= nLastNode) && (nFirstNode <= nEndIndex))
1259 {
1260 if( rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR )
1261 {
1262 if( ( ((nHere == nStartIndex) && (nIndex >= pStart->nContent.GetIndex())) || (nHere > nStartIndex) )
1263 &&( ((nHere == nEndIndex) && (nIndex < pEnd->nContent.GetIndex())) || (nHere < nEndIndex) ) )
1264 {
1265 uno::Reference < XAccessible > xAcc( (*aIter).second );
1266 if( xAcc.is() )
1267 static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->SetState( AccessibleStateType::SELECTED );
1268 }
1269 else
1270 {
1271 uno::Reference < XAccessible > xAcc( (*aIter).second );
1272 if( xAcc.is() )
1273 static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->ResetState( AccessibleStateType::SELECTED );
1274 }
1275 }
1276 else if( rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA )
1277 {
1278 uno::Reference<XAccessible> const xAcc((*aIter).second);
1279 if (xAcc.is())
1280 {
1281 if (IsSelectFrameAnchoredAtPara(*pPos, *pStart, *pEnd))
1282 {
1283 static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->SetState( AccessibleStateType::SELECTED );
1284 }
1285 else
1286 {
1287 static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->ResetState( AccessibleStateType::SELECTED );
1288 }
1289 }
1290 }
1291 else if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
1292 {
1293 uno::Reference<XAccessible> const xAcc((*aIter).second);
1294 if (xAcc.is())
1295 {
1296 if (IsDestroyFrameAnchoredAtChar(*pPos, *pStart, *pEnd))
1297 {
1298 static_cast<::accessibility::AccessibleShape*>(xAcc.get())->SetState( AccessibleStateType::SELECTED );
1299 }
1300 else
1301 {
1302 static_cast<::accessibility::AccessibleShape*>(xAcc.get())->ResetState( AccessibleStateType::SELECTED );
1303 }
1304 }
1305 }
1306 }
1307 }
1308 }
1309 }
1310 if( !bMarked )
1311 {
1312 SwAccessibleObjShape_Impl *pShape = pShapes.get();
1313 size_t nNumShapes = nShapes;
1314 while( nNumShapes )
1315 {
1316 if( pShape < pSelShape && (pShape->first==(*aIter).first) )
1317 {
1318 uno::Reference < XAccessible > xAcc( (*aIter).second );
1319 if(xAcc.is())
1320 static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->ResetState( AccessibleStateType::SELECTED );
1321 }
1322 --nNumShapes;
1323 ++pShape;
1324 }
1325 }
1326 }
1327
1328 ++aIter;
1329 }//while( aIter != aEndIter )
1330 }//else
1331 }
1332
1333 pShapes.reset();
1334
1335 //Checked for FlyFrame
1336 if (mpFrameMap)
1337 {
1338 SwAccessibleContextMap_Impl::iterator aIter = mpFrameMap->begin();
1339 while( aIter != mpFrameMap->end() )
1340 {
1341 const SwFrame *pFrame = (*aIter).first;
1342 if(pFrame->IsFlyFrame())
1343 {
1344 uno::Reference < XAccessible > xAcc = (*aIter).second;
1345
1346 if(xAcc.is())
1347 {
1348 SwAccessibleFrameBase *pAccFrame = static_cast< SwAccessibleFrameBase * >(xAcc.get());
1349 bool bFrameChanged = pAccFrame->SetSelectedState( true );
1350 if (bFrameChanged)
1351 {
1352 const SwFlyFrame *pFlyFrame = static_cast< const SwFlyFrame * >( pFrame );
1353 const SwFrameFormat *pFrameFormat = pFlyFrame->GetFormat();
1354 if (pFrameFormat)
1355 {
1356 const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
1357 if( rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR )
1358 {
1359 uno::Reference< XAccessible > xAccParent = pAccFrame->getAccessibleParent();
1360 if (xAccParent.is())
1361 {
1362 uno::Reference< XAccessibleContext > xAccContext = xAccParent->getAccessibleContext();
1363 if(xAccContext.is() && xAccContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1364 {
1365 SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xAccContext.get());
1366 if(pAccFrame->IsSeletedInDoc())
1367 {
1368 m_setParaAdd.insert(pAccPara);
1369 }
1370 else if(m_setParaAdd.count(pAccPara) == 0)
1371 {
1372 m_setParaRemove.insert(pAccPara);
1373 }
1374 }
1375 }
1376 }
1377 }
1378 }
1379 }
1380 }
1381 ++aIter;
1382 }
1383 }
1384
1385 typedef std::vector< SwAccessibleContext* > VEC_PARA;
1386 VEC_PARA vecAdd;
1387 VEC_PARA vecRemove;
1388 //Checked for Paras.
1389 bool bMarkChanged = false;
1390 SwAccessibleContextMap_Impl mapTemp;
1391 if( pCursor != nullptr )
1392 {
1393 for(SwPaM& rTmpCursor : pCursor->GetRingContainer())
1394 {
1395 if( rTmpCursor.HasMark() )
1396 {
1397 SwNodeIndex nStartIndex( rTmpCursor.Start()->nNode );
1398 SwNodeIndex nEndIndex( rTmpCursor.End()->nNode );
1399 for (; nStartIndex <= nEndIndex; ++nStartIndex)
1400 {
1401 SwFrame *pFrame = nullptr;
1402 if(nStartIndex.GetNode().IsContentNode())
1403 {
1404 SwContentNode* pCNd = static_cast<SwContentNode*>(&(nStartIndex.GetNode()));
1405 pFrame = SwIterator<SwFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*pCNd).First();
1406 if (mapTemp.find(pFrame) != mapTemp.end())
1407 {
1408 continue; // sw_redlinehide: once is enough
1409 }
1410 }
1411 else if( nStartIndex.GetNode().IsTableNode() )
1412 {
1413 SwTableNode * pTable = static_cast<SwTableNode *>(&(nStartIndex.GetNode()));
1414 SwTableFormat* pFormat = pTable->GetTable().GetFrameFormat();
1415 pFrame = SwIterator<SwFrame, SwTableFormat>(*pFormat).First();
1416 }
1417
1418 if( pFrame && mpFrameMap)
1419 {
1420 SwAccessibleContextMap_Impl::iterator aIter = mpFrameMap->find( pFrame );
1421 if( aIter != mpFrameMap->end() )
1422 {
1423 uno::Reference < XAccessible > xAcc = (*aIter).second;
1424 bool isChanged = false;
1425 if( xAcc.is() )
1426 {
1427 isChanged = static_cast< SwAccessibleContext * >(xAcc.get())->SetSelectedState( true );
1428 }
1429 if(!isChanged)
1430 {
1431 SwAccessibleContextMap_Impl::iterator aEraseIter = mpSeletedFrameMap->find( pFrame );
1432 if(aEraseIter != mpSeletedFrameMap->end())
1433 mpSeletedFrameMap->erase(aEraseIter);
1434 }
1435 else
1436 {
1437 bMarkChanged = true;
1438 vecAdd.push_back(static_cast< SwAccessibleContext * >(xAcc.get()));
1439 }
1440
1441 mapTemp.emplace( pFrame, xAcc );
1442 }
1443 }
1444 }
1445 }
1446 }
1447 }
1448 if( !mpSeletedFrameMap )
1449 mpSeletedFrameMap.reset( new SwAccessibleContextMap_Impl );
1450 if( !mpSeletedFrameMap->empty() )
1451 {
1452 SwAccessibleContextMap_Impl::iterator aIter = mpSeletedFrameMap->begin();
1453 while( aIter != mpSeletedFrameMap->end() )
1454 {
1455 uno::Reference < XAccessible > xAcc = (*aIter).second;
1456 if(xAcc.is())
1457 static_cast< SwAccessibleContext * >(xAcc.get())->SetSelectedState( false );
1458 ++aIter;
1459 vecRemove.push_back(static_cast< SwAccessibleContext * >(xAcc.get()));
1460 }
1461 bMarkChanged = true;
1462 mpSeletedFrameMap->clear();
1463 }
1464
1465 SwAccessibleContextMap_Impl::iterator aIter = mapTemp.begin();
1466 while( aIter != mapTemp.end() )
1467 {
1468 mpSeletedFrameMap->emplace( (*aIter).first, (*aIter).second );
1469 ++aIter;
1470 }
1471 mapTemp.clear();
1472
1473 if( !(bMarkChanged && mpFrameMap))
1474 return;
1475
1476 for (SwAccessibleContext* pAccPara : vecAdd)
1477 {
1478 AccessibleEventObject aEvent;
1479 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1480 if (pAccPara)
1481 {
1482 pAccPara->FireAccessibleEvent( aEvent );
1483 }
1484 }
1485 for (SwAccessibleContext* pAccPara : vecRemove)
1486 {
1487 AccessibleEventObject aEvent;
1488 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
1489 if (pAccPara)
1490 {
1491 pAccPara->FireAccessibleEvent( aEvent );
1492 }
1493 }
1494}
1495
1496//Merge with DoInvalidateShapeFocus
1497void SwAccessibleMap::DoInvalidateShapeSelection(bool bInvalidateFocusMode /*=false*/)
1498{
1499 std::unique_ptr<SwAccessibleObjShape_Impl[]> pShapes;
1500 SwAccessibleObjShape_Impl *pSelShape = nullptr;
1501 size_t nShapes = 0;
1502
1503 const SwViewShell *pVSh = GetShell();
1504 const SwFEShell *pFESh = dynamic_cast<const SwFEShell*>( pVSh) != nullptr ?
1505 static_cast< const SwFEShell * >( pVSh ) : nullptr;
1506 const size_t nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1507
1508 //when InvalidateFocus Call this function ,and the current selected shape count is not 1 ,
1509 //return
1510 if (bInvalidateFocusMode && nSelShapes != 1)
1511 {
1512 return;
1513 }
1514 {
1515 osl::MutexGuard aGuard( maMutex );
1516 if( mpShapeMap )
1517 pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1518 }
1519
1520 if( !pShapes )
1521 return;
1522
1523 typedef std::vector< ::rtl::Reference < ::accessibility::AccessibleShape > > VEC_SHAPE;
1524 VEC_SHAPE vecxShapeAdd;
1525 VEC_SHAPE vecxShapeRemove;
1526 int nCountSelectedShape=0;
1527
1528 vcl::Window *pWin = GetShell()->GetWin();
1529 bool bFocused = pWin && pWin->HasFocus();
1530 SwAccessibleObjShape_Impl *pShape = pShapes.get();
1531 int nShapeCount = nShapes;
1532 while( nShapeCount )
1533 {
1534 if (pShape->second.is() && IsInSameLevel(pShape->first, pFESh))
1535 {
1536 if( pShape < pSelShape )
1537 {
1538 if(pShape->second->ResetState( AccessibleStateType::SELECTED ))
1539 {
1540 vecxShapeRemove.push_back(pShape->second);
1541 }
1542 pShape->second->ResetState( AccessibleStateType::FOCUSED );
1543 }
1544 }
1545 --nShapeCount;
1546 ++pShape;
1547 }
1548
1549 for (const auto& rpShape : vecxShapeRemove)
1550 {
1551 ::accessibility::AccessibleShape *pAccShape = rpShape.get();
1552 if (pAccShape)
1553 {
1554 pAccShape->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE, uno::Any(), uno::Any());
1555 }
1556 }
1557
1558 pShape = pShapes.get();
1559
1560 while( nShapes )
1561 {
1562 if (pShape->second.is() && IsInSameLevel(pShape->first, pFESh))
1563 {
1564 if( pShape >= pSelShape )
1565 {
1566 //first fire focus event
1567 if( bFocused && 1 == nSelShapes )
1568 pShape->second->SetState( AccessibleStateType::FOCUSED );
1569 else
1570 pShape->second->ResetState( AccessibleStateType::FOCUSED );
1571
1572 if(pShape->second->SetState( AccessibleStateType::SELECTED ))
1573 {
1574 vecxShapeAdd.push_back(pShape->second);
1575 }
1576 ++nCountSelectedShape;
1577 }
1578 }
1579
1580 --nShapes;
1581 ++pShape;
1582 }
1583
1584 const unsigned int SELECTION_WITH_NUM = 10;
1585 if (vecxShapeAdd.size() > SELECTION_WITH_NUM )
1586 {
1587 uno::Reference< XAccessible > xDoc = GetDocumentView( );
1588 SwAccessibleContext * pCont = static_cast<SwAccessibleContext *>(xDoc.get());
1589 if (pCont)
1590 {
1591 AccessibleEventObject aEvent;
1592 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
1593 pCont->FireAccessibleEvent(aEvent);
1594 }
1595 }
1596 else
1597 {
1598 short nEventID = AccessibleEventId::SELECTION_CHANGED_ADD;
1599 if (nCountSelectedShape <= 1 && vecxShapeAdd.size() == 1 )
1600 {
1601 nEventID = AccessibleEventId::SELECTION_CHANGED;
1602 }
1603 for (const auto& rpShape : vecxShapeAdd)
1604 {
1605 ::accessibility::AccessibleShape *pAccShape = rpShape.get();
1606 if (pAccShape)
1607 {
1608 pAccShape->CommitChange(nEventID, uno::Any(), uno::Any());
1609 }
1610 }
1611 }
1612
1613 for (const auto& rpShape : vecxShapeAdd)
1614 {
1615 ::accessibility::AccessibleShape *pAccShape = rpShape.get();
1616 if (pAccShape)
1617 {
1618 SdrObject *pObj = GetSdrObjectFromXShape(pAccShape->GetXShape());
1619 SwFrameFormat *pFrameFormat = pObj ? FindFrameFormat( pObj ) : nullptr;
1620 if (pFrameFormat)
1621 {
1622 const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
1623 if( rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR )
1624 {
1625 uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent();
1626 if (xPara.is())
1627 {
1628 uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext();
1629 if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1630 {
1631 SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get());
1632 if (pAccPara)
1633 {
1634 m_setParaAdd.insert(pAccPara);
1635 }
1636 }
1637 }
1638 }
1639 }
1640 }
1641 }
1642 for (const auto& rpShape : vecxShapeRemove)
1643 {
1644 ::accessibility::AccessibleShape *pAccShape = rpShape.get();
1645 if (pAccShape)
1646 {
1647 uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent();
1648 uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext();
1649 if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1650 {
1651 SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get());
1652 if (m_setParaAdd.count(pAccPara) == 0 )
1653 {
1654 m_setParaRemove.insert(pAccPara);
1655 }
1656 }
1657 }
1658 }
1659}
1660
1661//Merge with DoInvalidateShapeSelection
1662/*
1663void SwAccessibleMap::DoInvalidateShapeFocus()
1664{
1665 const SwViewShell *pVSh = GetShell();
1666 const SwFEShell *pFESh = dynamic_cast<const SwFEShell*>( pVSh) != nullptr ?
1667 static_cast< const SwFEShell * >( pVSh ) : nullptr;
1668 const size_t nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1669
1670 if( nSelShapes != 1 )
1671 return;
1672
1673 SwAccessibleObjShape_Impl *pShapes = nullptr;
1674 SwAccessibleObjShape_Impl *pSelShape = nullptr;
1675 size_t nShapes = 0;
1676
1677 {
1678 osl::MutexGuard aGuard( maMutex );
1679 if( mpShapeMap )
1680 pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1681 }
1682
1683 if( pShapes )
1684 {
1685 vcl::Window *pWin = GetShell()->GetWin();
1686 bool bFocused = pWin && pWin->HasFocus();
1687 SwAccessibleObjShape_Impl *pShape = pShapes;
1688 while( nShapes )
1689 {
1690 if( pShape->second.is() )
1691 {
1692 if( bFocused && pShape >= pSelShape )
1693 pShape->second->SetState( AccessibleStateType::FOCUSED );
1694 else
1695 pShape->second->ResetState( AccessibleStateType::FOCUSED );
1696 }
1697
1698 --nShapes;
1699 ++pShape;
1700 }
1701
1702 delete[] pShapes;
1703 }
1704}
1705
1706*/
1707
1708SwAccessibleMap::SwAccessibleMap( SwViewShell *pSh ) :
1709 mpVSh( pSh ),
1710 mbShapeSelected( false ),
1711 maDocName(SwAccessibleContext::GetResource(STR_ACCESS_DOC_NAMEreinterpret_cast<char const *>("STR_ACCESS_DOC_NAME" "\004"
u8"Document view")
))
1712{
1713 pSh->GetLayout()->AddAccessibleShell();
1714}
1715
1716SwAccessibleMap::~SwAccessibleMap()
1717{
1718 DBG_TESTSOLARMUTEX()do { DbgTestSolarMutex(); } while(false);
1719 uno::Reference < XAccessible > xAcc;
1720 {
1721 osl::MutexGuard aGuard( maMutex );
1722 if( mpFrameMap )
1723 {
1724 const SwRootFrame *pRootFrame = GetShell()->GetLayout();
1725 SwAccessibleContextMap_Impl::iterator aIter = mpFrameMap->find( pRootFrame );
1726 if( aIter != mpFrameMap->end() )
1727 xAcc = (*aIter).second;
1728 if( !xAcc.is() )
1729 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1729, __extension__ __PRETTY_FUNCTION__))
; // let's hope this can't happen? the vcl::Window apparently owns the top-level
1730 //xAcc = new SwAccessibleDocument(shared_from_this());
1731 }
1732 }
1733
1734 if(xAcc.is())
1735 {
1736 SwAccessibleDocumentBase *const pAcc =
1737 static_cast<SwAccessibleDocumentBase *>(xAcc.get());
1738 pAcc->Dispose( true );
1739 }
1740#if OSL_DEBUG_LEVEL1 > 0 && !defined NDEBUG
1741 if( mpFrameMap )
1742 {
1743 SwAccessibleContextMap_Impl::iterator aIter = mpFrameMap->begin();
1744 while( aIter != mpFrameMap->end() )
1745 {
1746 uno::Reference < XAccessible > xTmp = (*aIter).second;
1747 if( xTmp.is() )
1748 {
1749 SwAccessibleContext *pTmp = static_cast< SwAccessibleContext * >( xTmp.get() );
1750 assert(pTmp->GetMap() == nullptr)(static_cast <bool> (pTmp->GetMap() == nullptr) ? void
(0) : __assert_fail ("pTmp->GetMap() == nullptr", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1750, __extension__ __PRETTY_FUNCTION__))
; // must be disposed
1751 }
1752 ++aIter;
1753 }
1754 }
1755#endif
1756 {
1757 osl::MutexGuard aGuard( maMutex );
1758 assert((!mpFrameMap || mpFrameMap->empty()) &&(static_cast <bool> ((!mpFrameMap || mpFrameMap->empty
()) && "Frame map should be empty after disposing the root frame"
) ? void (0) : __assert_fail ("(!mpFrameMap || mpFrameMap->empty()) && \"Frame map should be empty after disposing the root frame\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1759, __extension__ __PRETTY_FUNCTION__))
1759 "Frame map should be empty after disposing the root frame")(static_cast <bool> ((!mpFrameMap || mpFrameMap->empty
()) && "Frame map should be empty after disposing the root frame"
) ? void (0) : __assert_fail ("(!mpFrameMap || mpFrameMap->empty()) && \"Frame map should be empty after disposing the root frame\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1759, __extension__ __PRETTY_FUNCTION__))
;
1760 assert((!mpShapeMap || mpShapeMap->empty()) &&(static_cast <bool> ((!mpShapeMap || mpShapeMap->empty
()) && "Object map should be empty after disposing the root frame"
) ? void (0) : __assert_fail ("(!mpShapeMap || mpShapeMap->empty()) && \"Object map should be empty after disposing the root frame\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1761, __extension__ __PRETTY_FUNCTION__))
1761 "Object map should be empty after disposing the root frame")(static_cast <bool> ((!mpShapeMap || mpShapeMap->empty
()) && "Object map should be empty after disposing the root frame"
) ? void (0) : __assert_fail ("(!mpShapeMap || mpShapeMap->empty()) && \"Object map should be empty after disposing the root frame\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1761, __extension__ __PRETTY_FUNCTION__))
;
1762 mpFrameMap.reset();
1763 mpShapeMap.reset();
1764 mvShapes.clear();
1765 mpSelectedParas.reset();
1766 }
1767
1768 mpPreview.reset();
1769
1770 {
1771 osl::MutexGuard aGuard( maEventMutex );
1772 assert(!mpEvents)(static_cast <bool> (!mpEvents) ? void (0) : __assert_fail
("!mpEvents", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1772, __extension__ __PRETTY_FUNCTION__))
;
1773 assert(!mpEventMap)(static_cast <bool> (!mpEventMap) ? void (0) : __assert_fail
("!mpEventMap", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1773, __extension__ __PRETTY_FUNCTION__))
;
1774 mpEventMap.reset();
1775 mpEvents.reset();
1776 }
1777 mpVSh->GetLayout()->RemoveAccessibleShell();
1778}
1779
1780uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView_(
1781 bool bPagePreview )
1782{
1783 uno::Reference < XAccessible > xAcc;
1784 bool bSetVisArea = false;
1785
1786 {
1787 osl::MutexGuard aGuard( maMutex );
1788
1789 if( !mpFrameMap )
1790 {
1791 mpFrameMap.reset(new SwAccessibleContextMap_Impl);
1792#if OSL_DEBUG_LEVEL1 > 0
1793 mpFrameMap->mbLocked = false;
1794#endif
1795 }
1796
1797#if OSL_DEBUG_LEVEL1 > 0
1798 assert(!mpFrameMap->mbLocked)(static_cast <bool> (!mpFrameMap->mbLocked) ? void (
0) : __assert_fail ("!mpFrameMap->mbLocked", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1798, __extension__ __PRETTY_FUNCTION__))
;
1799 mpFrameMap->mbLocked = true;
1800#endif
1801
1802 const SwRootFrame *pRootFrame = GetShell()->GetLayout();
1803 SwAccessibleContextMap_Impl::iterator aIter = mpFrameMap->find( pRootFrame );
1804 if( aIter != mpFrameMap->end() )
1805 xAcc = (*aIter).second;
1806 if( xAcc.is() )
1807 {
1808 bSetVisArea = true; // Set VisArea when map mutex is not locked
1809 }
1810 else
1811 {
1812 if( bPagePreview )
1813 xAcc = new SwAccessiblePreview(shared_from_this());
1814 else
1815 xAcc = new SwAccessibleDocument(shared_from_this());
1816
1817 if( aIter != mpFrameMap->end() )
1818 {
1819 (*aIter).second = xAcc;
1820 }
1821 else
1822 {
1823 mpFrameMap->emplace( pRootFrame, xAcc );
1824 }
1825 }
1826
1827#if OSL_DEBUG_LEVEL1 > 0
1828 mpFrameMap->mbLocked = false;
1829#endif
1830 }
1831
1832 if( bSetVisArea )
1833 {
1834 SwAccessibleDocumentBase *pAcc =
1835 static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
1836 pAcc->SetVisArea();
1837 }
1838
1839 return xAcc;
1840}
1841
1842uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( )
1843{
1844 return GetDocumentView_( false );
1845}
1846
1847uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview(
1848 const std::vector<std::unique_ptr<PreviewPage>>& _rPreviewPages,
1849 const Fraction& _rScale,
1850 const SwPageFrame* _pSelectedPageFrame,
1851 const Size& _rPreviewWinSize )
1852{
1853 // create & update preview data object
1854 if( mpPreview == nullptr )
1855 mpPreview.reset( new SwAccPreviewData() );
1856 mpPreview->Update( *this, _rPreviewPages, _rScale, _pSelectedPageFrame, _rPreviewWinSize );
1857
1858 uno::Reference<XAccessible> xAcc = GetDocumentView_( true );
1859 return xAcc;
1860}
1861
1862uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrame *pFrame,
1863 bool bCreate )
1864{
1865 DBG_TESTSOLARMUTEX()do { DbgTestSolarMutex(); } while(false);
1866 uno::Reference < XAccessible > xAcc;
1867 uno::Reference < XAccessible > xOldCursorAcc;
1868 bool bOldShapeSelected = false;
1869
1870 {
1871 osl::MutexGuard aGuard( maMutex );
1872
1873 if( !mpFrameMap && bCreate )
1874 mpFrameMap.reset(new SwAccessibleContextMap_Impl);
1875 if( mpFrameMap )
1876 {
1877 SwAccessibleContextMap_Impl::iterator aIter = mpFrameMap->find( pFrame );
1878 if( aIter != mpFrameMap->end() )
1879 xAcc = (*aIter).second;
1880
1881 if( !xAcc.is() && bCreate )
1882 {
1883 SwAccessibleContext *pAcc = nullptr;
1884 switch( pFrame->GetType() )
1885 {
1886 case SwFrameType::Txt:
1887 pAcc = new SwAccessibleParagraph(shared_from_this(),
1888 static_cast< const SwTextFrame& >( *pFrame ) );
1889 break;
1890 case SwFrameType::Header:
1891 pAcc = new SwAccessibleHeaderFooter(shared_from_this(),
1892 static_cast< const SwHeaderFrame *>( pFrame ) );
1893 break;
1894 case SwFrameType::Footer:
1895 pAcc = new SwAccessibleHeaderFooter(shared_from_this(),
1896 static_cast< const SwFooterFrame *>( pFrame ) );
1897 break;
1898 case SwFrameType::Ftn:
1899 {
1900 const SwFootnoteFrame *pFootnoteFrame =
1901 static_cast < const SwFootnoteFrame * >( pFrame );
1902 bool bIsEndnote =
1903 SwAccessibleFootnote::IsEndnote( pFootnoteFrame );
1904 pAcc = new SwAccessibleFootnote(shared_from_this(), bIsEndnote,
1905 /*(bIsEndnote ? mnEndnote++ : mnFootnote++),*/
1906 pFootnoteFrame );
1907 }
1908 break;
1909 case SwFrameType::Fly:
1910 {
1911 const SwFlyFrame *pFlyFrame =
1912 static_cast < const SwFlyFrame * >( pFrame );
1913 switch( SwAccessibleFrameBase::GetNodeType( pFlyFrame ) )
1914 {
1915 case SwNodeType::Grf:
1916 pAcc = new SwAccessibleGraphic(shared_from_this(), pFlyFrame );
1917 break;
1918 case SwNodeType::Ole:
1919 pAcc = new SwAccessibleEmbeddedObject(shared_from_this(), pFlyFrame );
1920 break;
1921 default:
1922 pAcc = new SwAccessibleTextFrame(shared_from_this(), *pFlyFrame );
1923 break;
1924 }
1925 }
1926 break;
1927 case SwFrameType::Cell:
1928 pAcc = new SwAccessibleCell(shared_from_this(),
1929 static_cast< const SwCellFrame *>( pFrame ) );
1930 break;
1931 case SwFrameType::Tab:
1932 pAcc = new SwAccessibleTable(shared_from_this(),
1933 static_cast< const SwTabFrame *>( pFrame ) );
1934 break;
1935 case SwFrameType::Page:
1936 OSL_ENSURE( GetShell()->IsPreview(),do { if (true && (!(GetShell()->IsPreview()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1937" ": "), "%s", "accessible page frames only in PagePreview"
); } } while (false)
1937 "accessible page frames only in PagePreview" )do { if (true && (!(GetShell()->IsPreview()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "1937" ": "), "%s", "accessible page frames only in PagePreview"
); } } while (false)
;
1938 pAcc = new SwAccessiblePage(shared_from_this(), pFrame);
1939 break;
1940 default: break;
1941 }
1942 xAcc = pAcc;
1943 assert(xAcc.is())(static_cast <bool> (xAcc.is()) ? void (0) : __assert_fail
("xAcc.is()", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 1943, __extension__ __PRETTY_FUNCTION__))
;
1944
1945 if( aIter != mpFrameMap->end() )
1946 {
1947 (*aIter).second = xAcc;
1948 }
1949 else
1950 {
1951 mpFrameMap->emplace( pFrame, xAcc );
1952 }
1953
1954 if( pAcc->HasCursor() &&
1955 !AreInSameTable( mxCursorContext, pFrame ) )
1956 {
1957 // If the new context has the focus, and if we know
1958 // another context that had the focus, then the focus
1959 // just moves from the old context to the new one. We
1960 // then have to send a focus event and a caret event for
1961 // the old context. We have to do that now,
1962 // because after we have left this method, anyone might
1963 // call getStates for the new context and will get a
1964 // focused state then. Sending the focus changes event
1965 // after that seems to be strange. However, we cannot
1966 // send a focus event for the new context now, because
1967 // no one except us knows it. In any case, we remember
1968 // the new context as the one that has the focus
1969 // currently.
1970
1971 xOldCursorAcc = mxCursorContext;
1972 mxCursorContext = xAcc;
1973
1974 bOldShapeSelected = mbShapeSelected;
1975 mbShapeSelected = false;
1976 }
1977 }
1978 }
1979 }
1980
1981 // Invalidate focus for old object when map is not locked
1982 if( xOldCursorAcc.is() )
1983 InvalidateCursorPosition( xOldCursorAcc );
1984 if( bOldShapeSelected )
1985 InvalidateShapeSelection();
1986
1987 return xAcc;
1988}
1989
1990::rtl::Reference < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
1991 const SwFrame *pFrame,
1992 bool bCreate )
1993{
1994 uno::Reference < XAccessible > xAcc( GetContext( pFrame, bCreate ) );
1995
1996 ::rtl::Reference < SwAccessibleContext > xAccImpl(
1997 static_cast< SwAccessibleContext * >( xAcc.get() ) );
1998
1999 return xAccImpl;
2000}
2001
2002uno::Reference< XAccessible> SwAccessibleMap::GetContext(
2003 const SdrObject *pObj,
2004 SwAccessibleContext *pParentImpl,
2005 bool bCreate )
2006{
2007 uno::Reference < XAccessible > xAcc;
2008 uno::Reference < XAccessible > xOldCursorAcc;
2009
2010 {
2011 osl::MutexGuard aGuard( maMutex );
2012
2013 if( !mpShapeMap && bCreate )
2014 mpShapeMap.reset(new SwAccessibleShapeMap_Impl( this ));
2015 if( mpShapeMap )
2016 {
2017 SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( pObj );
2018 if( aIter != mpShapeMap->end() )
2019 xAcc = (*aIter).second;
2020
2021 if( !xAcc.is() && bCreate )
2022 {
2023 rtl::Reference< ::accessibility::AccessibleShape> pAcc;
2024 uno::Reference < drawing::XShape > xShape(
2025 const_cast< SdrObject * >( pObj )->getUnoShape(),
2026 uno::UNO_QUERY );
2027 if( xShape.is() )
2028 {
2029 ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
2030 ::accessibility::ShapeTypeHandler::Instance();
2031 uno::Reference < XAccessible > xParent( pParentImpl );
2032 ::accessibility::AccessibleShapeInfo aShapeInfo(
2033 xShape, xParent, this );
2034
2035 pAcc = rShapeTypeHandler.CreateAccessibleObject(
2036 aShapeInfo, mpShapeMap->GetInfo() );
2037 }
2038 xAcc = pAcc.get();
2039 assert(xAcc.is())(static_cast <bool> (xAcc.is()) ? void (0) : __assert_fail
("xAcc.is()", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 2039, __extension__ __PRETTY_FUNCTION__))
;
2040 pAcc->Init();
2041 if( aIter != mpShapeMap->end() )
2042 {
2043 (*aIter).second = xAcc;
2044 }
2045 else
2046 {
2047 mpShapeMap->emplace( pObj, xAcc );
2048 }
2049 // TODO: focus!!!
2050 AddGroupContext(pObj, xAcc);
2051 }
2052 }
2053 }
2054
2055 // Invalidate focus for old object when map is not locked
2056 if( xOldCursorAcc.is() )
2057 InvalidateCursorPosition( xOldCursorAcc );
2058
2059 return xAcc;
2060}
2061
2062bool SwAccessibleMap::IsInSameLevel(const SdrObject* pObj, const SwFEShell* pFESh)
2063{
2064 if (pFESh)
2065 return pFESh->IsObjSameLevelWithMarked(pObj);
2066 return false;
2067}
2068
2069void SwAccessibleMap::AddShapeContext(const SdrObject *pObj, uno::Reference < XAccessible > const & xAccShape)
2070{
2071 osl::MutexGuard aGuard( maMutex );
2072
2073 if( mpShapeMap )
2074 {
2075 mpShapeMap->emplace( pObj, xAccShape );
2076 }
2077
2078}
2079
2080//Added by yanjun for sym2_6407
2081void SwAccessibleMap::RemoveGroupContext(const SdrObject *pParentObj)
2082{
2083 osl::MutexGuard aGuard( maMutex );
2084 // TODO: Why are sub-shapes of group shapes even added to our map?
2085 // Doesn't the AccessibleShape of the top-level shape create them
2086 // on demand anyway? Why does SwAccessibleMap need to know them?
2087 // We cannot rely on getAccessibleChild here to remove the sub-shapes
2088 // from mpShapes because the top-level shape may not only be disposed here
2089 // but also by visibility checks in svx, then it doesn't return children.
2090 if (mpShapeMap && pParentObj && pParentObj->IsGroupObject())
2091 {
2092 SdrObjList *const pChildren(pParentObj->GetSubList());
2093 for (size_t i = 0; pChildren && i < pChildren->GetObjCount(); ++i)
2094 {
2095 SdrObject *const pChild(pChildren->GetObj(i));
2096 assert(pChild)(static_cast <bool> (pChild) ? void (0) : __assert_fail
("pChild", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 2096, __extension__ __PRETTY_FUNCTION__))
;
2097 RemoveContext(pChild);
2098 }
2099 }
2100}
2101//End
2102
2103void SwAccessibleMap::AddGroupContext(const SdrObject *pParentObj, uno::Reference < XAccessible > const & xAccParent)
2104{
2105 osl::MutexGuard aGuard( maMutex );
2106 if( !mpShapeMap )
2107 return;
2108
2109 //here get all the sub list.
2110 if (!pParentObj->IsGroupObject())
2111 return;
2112
2113 if (!xAccParent.is())
2114 return;
2115
2116 uno::Reference < XAccessibleContext > xContext = xAccParent->getAccessibleContext();
2117 if (!xContext.is())
2118 return;
2119
2120 sal_Int32 nChildren = xContext->getAccessibleChildCount();
2121 for(sal_Int32 i = 0; i<nChildren; i++)
2122 {
2123 uno::Reference < XAccessible > xChild = xContext->getAccessibleChild(i);
2124 if (xChild.is())
2125 {
2126 uno::Reference < XAccessibleContext > xChildContext = xChild->getAccessibleContext();
2127 if (xChildContext.is())
2128 {
2129 short nRole = xChildContext->getAccessibleRole();
2130 if (nRole == AccessibleRole::SHAPE)
2131 {
2132 ::accessibility::AccessibleShape* pAccShape = static_cast < ::accessibility::AccessibleShape* >( xChild.get());
2133 uno::Reference < drawing::XShape > xShape = pAccShape->GetXShape();
2134 if (xShape.is())
2135 {
2136 SdrObject* pObj = GetSdrObjectFromXShape(xShape);
2137 AddShapeContext(pObj, xChild);
2138 AddGroupContext(pObj,xChild);
2139 }
2140 }
2141 }
2142 }
2143 }
2144}
2145
2146::rtl::Reference < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl(
2147 const SdrObject *pObj,
2148 SwAccessibleContext *pParentImpl,
2149 bool bCreate )
2150{
2151 uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) );
2152
2153 ::rtl::Reference < ::accessibility::AccessibleShape > xAccImpl(
2154 static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) );
2155
2156 return xAccImpl;
2157}
2158
2159void SwAccessibleMap::RemoveContext( const SwFrame *pFrame )
2160{
2161 osl::MutexGuard aGuard( maMutex );
2162
2163 if( !mpFrameMap )
2164 return;
2165
2166 SwAccessibleContextMap_Impl::iterator aIter =
2167 mpFrameMap->find( pFrame );
2168 if( aIter == mpFrameMap->end() )
2169 return;
2170
2171 mpFrameMap->erase( aIter );
2172
2173 // Remove reference to old caret object. Though mxCursorContext
2174 // is a weak reference and cleared automatically, clearing it
2175 // directly makes sure to not keep a non-functional object.
2176 uno::Reference < XAccessible > xOldAcc( mxCursorContext );
2177 if( xOldAcc.is() )
2178 {
2179 SwAccessibleContext *pOldAccImpl =
2180 static_cast< SwAccessibleContext *>( xOldAcc.get() );
2181 OSL_ENSURE( pOldAccImpl->GetFrame(), "old caret context is disposed" )do { if (true && (!(pOldAccImpl->GetFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "2181" ": "), "%s", "old caret context is disposed"); } }
while (false)
;
2182 if( pOldAccImpl->GetFrame() == pFrame )
2183 {
2184 xOldAcc.clear(); // get an empty ref
2185 mxCursorContext = xOldAcc;
2186 }
2187 }
2188
2189 if( mpFrameMap->empty() )
2190 {
2191 mpFrameMap.reset();
2192 }
2193}
2194
2195void SwAccessibleMap::RemoveContext( const SdrObject *pObj )
2196{
2197 osl::MutexGuard aGuard( maMutex );
2198
2199 if( !mpShapeMap )
2200 return;
2201
2202 SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( pObj );
2203 if( aIter == mpShapeMap->end() )
2204 return;
2205
2206 uno::Reference < XAccessible > xTempHold( (*aIter).second );
2207 mpShapeMap->erase( aIter );
2208 RemoveGroupContext(pObj);
2209 // The shape selection flag is not cleared, but one might do
2210 // so but has to make sure that the removed context is the one
2211 // that is selected.
2212
2213 if( mpShapeMap && mpShapeMap->empty() )
2214 {
2215 mpShapeMap.reset();
2216 }
2217}
2218
2219bool SwAccessibleMap::Contains(const SwFrame *pFrame) const
2220{
2221 return (pFrame && mpFrameMap && mpFrameMap->find(pFrame) != mpFrameMap->end());
2222}
2223
2224void SwAccessibleMap::A11yDispose( const SwFrame *pFrame,
2225 const SdrObject *pObj,
2226 vcl::Window* pWindow,
2227 bool bRecursive,
2228 bool bCanSkipInvisible )
2229{
2230 SwAccessibleChild aFrameOrObj( pFrame, pObj, pWindow );
2231
2232 // Indeed, the following assert checks the frame's accessible flag,
2233 // because that's the one that is evaluated in the layout. The frame
2234 // might not be accessible anyway. That's the case for cell frames that
2235 // contain further cells.
2236 OSL_ENSURE( !aFrameOrObj.GetSwFrame() || aFrameOrObj.GetSwFrame()->IsAccessibleFrame(),do { if (true && (!(!aFrameOrObj.GetSwFrame() || aFrameOrObj
.GetSwFrame()->IsAccessibleFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "2237" ": "), "%s", "non accessible frame should be disposed"
); } } while (false)
2237 "non accessible frame should be disposed" )do { if (true && (!(!aFrameOrObj.GetSwFrame() || aFrameOrObj
.GetSwFrame()->IsAccessibleFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "2237" ": "), "%s", "non accessible frame should be disposed"
); } } while (false)
;
2238
2239 if (!(aFrameOrObj.IsAccessible(GetShell()->IsPreview())
2240 // fdo#87199 dispose the darn thing if it ever was accessible
2241 || Contains(pFrame)))
2242 return;
2243
2244 ::rtl::Reference< SwAccessibleContext > xAccImpl;
2245 ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
2246 ::rtl::Reference< ::accessibility::AccessibleShape > xShapeAccImpl;
2247 // get accessible context for frame
2248 {
2249 osl::MutexGuard aGuard( maMutex );
2250
2251 // First of all look for an accessible context for a frame
2252 if( aFrameOrObj.GetSwFrame() && mpFrameMap )
2253 {
2254 SwAccessibleContextMap_Impl::iterator aIter =
2255 mpFrameMap->find( aFrameOrObj.GetSwFrame() );
2256 if( aIter != mpFrameMap->end() )
2257 {
2258 uno::Reference < XAccessible > xAcc( (*aIter).second );
2259 xAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
2260 }
2261 }
2262 if( !xAccImpl.is() && mpFrameMap )
2263 {
2264 // If there is none, look if the parent is accessible.
2265 const SwFrame *pParent =
2266 SwAccessibleFrame::GetParent( aFrameOrObj,
2267 GetShell()->IsPreview());
2268
2269 if( pParent )
2270 {
2271 SwAccessibleContextMap_Impl::iterator aIter =
2272 mpFrameMap->find( pParent );
2273 if( aIter != mpFrameMap->end() )
2274 {
2275 uno::Reference < XAccessible > xAcc( (*aIter).second );
2276 xParentAccImpl =
2277 static_cast< SwAccessibleContext *>( xAcc.get() );
2278 }
2279 }
2280 }
2281 if( !xParentAccImpl.is() && !aFrameOrObj.GetSwFrame() && mpShapeMap )
2282 {
2283 SwAccessibleShapeMap_Impl::iterator aIter =
2284 mpShapeMap->find( aFrameOrObj.GetDrawObject() );
2285 if( aIter != mpShapeMap->end() )
2286 {
2287 uno::Reference < XAccessible > xAcc( (*aIter).second );
2288 xShapeAccImpl =
2289 static_cast< ::accessibility::AccessibleShape *>( xAcc.get() );
2290 }
2291 }
2292 if( pObj && GetShell()->ActionPend() &&
2293 (xParentAccImpl.is() || xShapeAccImpl.is()) )
2294 {
2295 // Keep a reference to the XShape to avoid that it
2296 // is deleted with a SwFrameFormat::Modify.
2297 uno::Reference < drawing::XShape > xShape(
2298 const_cast< SdrObject * >( pObj )->getUnoShape(),
2299 uno::UNO_QUERY );
2300 if( xShape.is() )
2301 {
2302 mvShapes.push_back( xShape );
2303 }
2304 }
2305 }
2306
2307 // remove events stored for the frame
2308 {
2309 osl::MutexGuard aGuard( maEventMutex );
2310 if( mpEvents )
2311 {
2312 SwAccessibleEventMap_Impl::iterator aIter =
2313 mpEventMap->find( aFrameOrObj );
2314 if( aIter != mpEventMap->end() )
2315 {
2316 SwAccessibleEvent_Impl aEvent(
2317 SwAccessibleEvent_Impl::DISPOSE, aFrameOrObj );
2318 AppendEvent( aEvent );
2319 }
2320 }
2321 }
2322
2323 // If the frame is accessible and there is a context for it, dispose
2324 // the frame. If the frame is no context for it but disposing should
2325 // take place recursive, the frame's children have to be disposed
2326 // anyway, so we have to create the context then.
2327 if( xAccImpl.is() )
2328 {
2329 xAccImpl->Dispose( bRecursive );
2330 }
2331 else if( xParentAccImpl.is() )
2332 {
2333 // If the frame is a cell frame, the table must be notified.
2334 // If we are in an action, a table model change event will
2335 // be broadcasted at the end of the action to give the table
2336 // a chance to generate a single table change event.
2337
2338 xParentAccImpl->DisposeChild( aFrameOrObj, bRecursive, bCanSkipInvisible );
2339 }
2340 else if( xShapeAccImpl.is() )
2341 {
2342 RemoveContext( aFrameOrObj.GetDrawObject() );
2343 xShapeAccImpl->dispose();
2344 }
2345
2346 if( mpPreview && pFrame && pFrame->IsPageFrame() )
2347 mpPreview->DisposePage( static_cast< const SwPageFrame *>( pFrame ) );
2348}
2349
2350void SwAccessibleMap::InvalidatePosOrSize( const SwFrame *pFrame,
2351 const SdrObject *pObj,
2352 vcl::Window* pWindow,
2353 const SwRect& rOldBox )
2354{
2355 SwAccessibleChild aFrameOrObj( pFrame, pObj, pWindow );
2356 if( !aFrameOrObj.IsAccessible( GetShell()->IsPreview() ) )
11
Assuming the condition is false
12
Taking false branch
2357 return;
2358
2359 ::rtl::Reference< SwAccessibleContext > xAccImpl;
2360 ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
2361 const SwFrame *pParent =nullptr;
2362 {
2363 osl::MutexGuard aGuard( maMutex );
2364
2365 if( mpFrameMap )
13
Taking true branch
2366 {
2367 if( aFrameOrObj.GetSwFrame() )
14
Assuming the condition is true
15
Taking true branch
2368 {
2369 SwAccessibleContextMap_Impl::iterator aIter =
2370 mpFrameMap->find( aFrameOrObj.GetSwFrame() );
2371 if( aIter != mpFrameMap->end() )
16
Taking false branch
2372 {
2373 // If there is an accessible object already it is
2374 // notified directly.
2375 uno::Reference < XAccessible > xAcc( (*aIter).second );
2376 xAccImpl =
2377 static_cast< SwAccessibleContext *>( xAcc.get() );
2378 }
2379 }
2380 if( !xAccImpl.is() )
17
Taking true branch
2381 {
2382 // Otherwise we look if the parent is accessible.
2383 // If not, there is nothing to do.
2384 pParent =
2385 SwAccessibleFrame::GetParent( aFrameOrObj,
2386 GetShell()->IsPreview());
2387
2388 if( pParent )
18
Assuming 'pParent' is non-null
19
Taking true branch
2389 {
2390 SwAccessibleContextMap_Impl::iterator aIter =
2391 mpFrameMap->find( pParent );
20
Calling 'SwAccessibleContextMap_Impl::find'
22
Returning from 'SwAccessibleContextMap_Impl::find'
2392 if( aIter != mpFrameMap->end() )
23
Taking false branch
2393 {
2394 uno::Reference < XAccessible > xAcc( (*aIter).second );
2395 xParentAccImpl =
2396 static_cast< SwAccessibleContext *>( xAcc.get() );
2397 }
2398 }
2399 }
2400 }
2401 }
2402
2403 if( xAccImpl.is() )
24
Calling 'Reference::is'
26
Returning from 'Reference::is'
27
Taking false branch
2404 {
2405 if( GetShell()->ActionPend() )
2406 {
2407 SwAccessibleEvent_Impl aEvent(
2408 SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.get(),
2409 aFrameOrObj, rOldBox );
2410 AppendEvent( aEvent );
2411 }
2412 else
2413 {
2414 FireEvents();
2415 if (xAccImpl->GetFrame()) // not if disposed by FireEvents()
2416 {
2417 xAccImpl->InvalidatePosOrSize(rOldBox);
2418 }
2419 }
2420 }
2421 else if( xParentAccImpl.is() )
28
Calling 'Reference::is'
30
Returning from 'Reference::is'
31
Taking false branch
2422 {
2423 if( GetShell()->ActionPend() )
2424 {
2425 assert(pParent)(static_cast <bool> (pParent) ? void (0) : __assert_fail
("pParent", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 2425, __extension__ __PRETTY_FUNCTION__))
;
2426 // tdf#99722 faster not to buffer events that won't be sent
2427 if (!SwAccessibleChild(pParent).IsVisibleChildrenOnly()
2428 || xParentAccImpl->IsShowing(rOldBox)
2429 || xParentAccImpl->IsShowing(*this, aFrameOrObj))
2430 {
2431 SwAccessibleEvent_Impl aEvent(
2432 SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2433 xParentAccImpl.get(), aFrameOrObj, rOldBox );
2434 AppendEvent( aEvent );
2435 }
2436 }
2437 else
2438 {
2439 FireEvents();
2440 xParentAccImpl->InvalidateChildPosOrSize( aFrameOrObj,
2441 rOldBox );
2442 }
2443 }
2444 else if(pParent)
32
Assuming 'pParent' is non-null
33
Taking true branch
2445 {
2446/*
2447For child graphic and its parent paragraph,if split 2 graphic to 2 paragraph,
2448will delete one graphic swfrm and new create 1 graphic swfrm ,
2449then the new paragraph and the new graphic SwFrame will add .
2450but when add graphic SwFrame ,the accessible of the new Paragraph is not created yet.
2451so the new graphic accessible 'parent is NULL,
2452so run here: save the parent's SwFrame not the accessible object parent,
2453*/
2454 bool bIsValidFrame = false;
2455 bool bIsTextParent = false;
2456 if (aFrameOrObj.GetSwFrame())
34
Taking true branch
2457 {
2458 if (SwFrameType::Fly == pFrame->GetType())
35
Called C++ object pointer is null
2459 {
2460 bIsValidFrame =true;
2461 }
2462 }
2463 else if(pObj)
2464 {
2465 if (SwFrameType::Txt == pParent->GetType())
2466 {
2467 bIsTextParent =true;
2468 }
2469 }
2470 if( bIsValidFrame || bIsTextParent )
2471 {
2472 if( GetShell()->ActionPend() )
2473 {
2474 SwAccessibleEvent_Impl aEvent(
2475 SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2476 pParent, aFrameOrObj, rOldBox );
2477 AppendEvent( aEvent );
2478 }
2479 else
2480 {
2481 OSL_ENSURE(false,"")do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "2481" ": "), "%s", ""); } } while (false)
;
2482 }
2483 }
2484 }
2485}
2486
2487void SwAccessibleMap::InvalidateContent( const SwFrame *pFrame )
2488{
2489 SwAccessibleChild aFrameOrObj( pFrame );
2490 if( !aFrameOrObj.IsAccessible( GetShell()->IsPreview() ) )
2491 return;
2492
2493 uno::Reference < XAccessible > xAcc;
2494 {
2495 osl::MutexGuard aGuard( maMutex );
2496
2497 if( mpFrameMap )
2498 {
2499 SwAccessibleContextMap_Impl::iterator aIter =
2500 mpFrameMap->find( aFrameOrObj.GetSwFrame() );
2501 if( aIter != mpFrameMap->end() )
2502 xAcc = (*aIter).second;
2503 }
2504 }
2505
2506 if( !xAcc.is() )
2507 return;
2508
2509 SwAccessibleContext *pAccImpl =
2510 static_cast< SwAccessibleContext *>( xAcc.get() );
2511 if( GetShell()->ActionPend() )
2512 {
2513 SwAccessibleEvent_Impl aEvent(
2514 SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl,
2515 aFrameOrObj );
2516 AppendEvent( aEvent );
2517 }
2518 else
2519 {
2520 FireEvents();
2521 pAccImpl->InvalidateContent();
2522 }
2523}
2524
2525void SwAccessibleMap::InvalidateAttr( const SwTextFrame& rTextFrame )
2526{
2527 SwAccessibleChild aFrameOrObj( &rTextFrame );
2528 if( !aFrameOrObj.IsAccessible( GetShell()->IsPreview() ) )
2529 return;
2530
2531 uno::Reference < XAccessible > xAcc;
2532 {
2533 osl::MutexGuard aGuard( maMutex );
2534
2535 if( mpFrameMap )
2536 {
2537 SwAccessibleContextMap_Impl::iterator aIter =
2538 mpFrameMap->find( aFrameOrObj.GetSwFrame() );
2539 if( aIter != mpFrameMap->end() )
2540 xAcc = (*aIter).second;
2541 }
2542 }
2543
2544 if( !xAcc.is() )
2545 return;
2546
2547 SwAccessibleContext *pAccImpl =
2548 static_cast< SwAccessibleContext *>( xAcc.get() );
2549 if( GetShell()->ActionPend() )
2550 {
2551 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR,
2552 pAccImpl, aFrameOrObj );
2553 aEvent.SetStates( AccessibleStates::TEXT_ATTRIBUTE_CHANGED );
2554 AppendEvent( aEvent );
2555 }
2556 else
2557 {
2558 FireEvents();
2559 pAccImpl->InvalidateAttr();
2560 }
2561}
2562
2563void SwAccessibleMap::InvalidateCursorPosition( const SwFrame *pFrame )
2564{
2565 SwAccessibleChild aFrameOrObj( pFrame );
2566 bool bShapeSelected = false;
2567 const SwViewShell *pVSh = GetShell();
2568 if( auto pCSh = dynamic_cast<const SwCursorShell*>(pVSh) )
2569 {
2570 if( pCSh->IsTableMode() )
2571 {
2572 while( aFrameOrObj.GetSwFrame() && !aFrameOrObj.GetSwFrame()->IsCellFrame() )
2573 aFrameOrObj = aFrameOrObj.GetSwFrame()->GetUpper();
2574 }
2575 else if( auto pFESh = dynamic_cast<const SwFEShell*>(pVSh) )
2576 {
2577 const SwFrame *pFlyFrame = pFESh->GetSelectedFlyFrame();
2578 if( pFlyFrame )
2579 {
2580 OSL_ENSURE( !pFrame || pFrame->FindFlyFrame() == pFlyFrame,do { if (true && (!(!pFrame || pFrame->FindFlyFrame
() == pFlyFrame))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "2581" ": "), "%s", "cursor is not contained in fly frame"
); } } while (false)
2581 "cursor is not contained in fly frame" )do { if (true && (!(!pFrame || pFrame->FindFlyFrame
() == pFlyFrame))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "2581" ": "), "%s", "cursor is not contained in fly frame"
); } } while (false)
;
2582 aFrameOrObj = pFlyFrame;
2583 }
2584 else if( pFESh->IsObjSelected() > 0 )
2585 {
2586 bShapeSelected = true;
2587 aFrameOrObj = static_cast<const SwFrame *>( nullptr );
2588 }
2589 }
2590 }
2591
2592 OSL_ENSURE( bShapeSelected || aFrameOrObj.IsAccessible(GetShell()->IsPreview()),do { if (true && (!(bShapeSelected || aFrameOrObj.IsAccessible
(GetShell()->IsPreview())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "2593" ": "), "%s", "frame is not accessible"); } } while
(false)
2593 "frame is not accessible" )do { if (true && (!(bShapeSelected || aFrameOrObj.IsAccessible
(GetShell()->IsPreview())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "2593" ": "), "%s", "frame is not accessible"); } } while
(false)
;
2594
2595 uno::Reference < XAccessible > xOldAcc;
2596 uno::Reference < XAccessible > xAcc;
2597 bool bOldShapeSelected = false;
2598
2599 {
2600 osl::MutexGuard aGuard( maMutex );
2601
2602 xOldAcc = mxCursorContext;
2603 mxCursorContext = xAcc; // clear reference
2604
2605 bOldShapeSelected = mbShapeSelected;
2606 mbShapeSelected = bShapeSelected;
2607
2608 if( aFrameOrObj.GetSwFrame() && mpFrameMap )
2609 {
2610 SwAccessibleContextMap_Impl::iterator aIter =
2611 mpFrameMap->find( aFrameOrObj.GetSwFrame() );
2612 if( aIter != mpFrameMap->end() )
2613 xAcc = (*aIter).second;
2614 else
2615 {
2616 SwRect rcEmpty;
2617 const SwTabFrame* pTabFrame = aFrameOrObj.GetSwFrame()->FindTabFrame();
2618 if (pTabFrame)
2619 {
2620 InvalidatePosOrSize(pTabFrame, nullptr, nullptr, rcEmpty);
2621 }
2622 else
2623 {
2624 InvalidatePosOrSize(aFrameOrObj.GetSwFrame(), nullptr, nullptr, rcEmpty);
2625 }
2626
2627 aIter = mpFrameMap->find( aFrameOrObj.GetSwFrame() );
2628 if( aIter != mpFrameMap->end() )
2629 {
2630 xAcc = (*aIter).second;
2631 }
2632 }
2633
2634 // For cells, some extra thoughts are necessary,
2635 // because invalidating the cursor for one cell
2636 // invalidates the cursor for all cells of the same
2637 // table. For this reason, we don't want to
2638 // invalidate the cursor for the old cursor object
2639 // and the new one if they are within the same table,
2640 // because this would result in doing the work twice.
2641 // Moreover, we have to make sure to invalidate the
2642 // cursor even if the current cell has no accessible object.
2643 // If the old cursor objects exists and is in the same
2644 // table, it's the best choice, because using it avoids
2645 // an unnecessary cursor invalidation cycle when creating
2646 // a new object for the current cell.
2647 if( aFrameOrObj.GetSwFrame()->IsCellFrame() )
2648 {
2649 if( xOldAcc.is() &&
2650 AreInSameTable( xOldAcc, aFrameOrObj.GetSwFrame() ) )
2651 {
2652 if( xAcc.is() )
2653 xOldAcc = xAcc; // avoid extra invalidation
2654 else
2655 xAcc = xOldAcc; // make sure at least one
2656 }
2657 if( !xAcc.is() )
2658 xAcc = GetContext( aFrameOrObj.GetSwFrame() );
2659 }
2660 }
2661 else if (bShapeSelected)
2662 {
2663 const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
2664 const SdrMarkList *pMarkList = pFESh->GetMarkList();
2665 if (pMarkList != nullptr && pMarkList->GetMarkCount() == 1)
2666 {
2667 SdrObject *pObj = pMarkList->GetMark( 0 )->GetMarkedSdrObj();
2668 ::rtl::Reference < ::accessibility::AccessibleShape > pAccShapeImpl = GetContextImpl(pObj,nullptr,false);
2669 if (!pAccShapeImpl.is())
2670 {
2671 while (pObj && pObj->getParentSdrObjectFromSdrObject())
2672 {
2673 pObj = pObj->getParentSdrObjectFromSdrObject();
2674 }
2675 if (pObj != nullptr)
2676 {
2677 const SwFrame *pParent = SwAccessibleFrame::GetParent( SwAccessibleChild(pObj), GetShell()->IsPreview() );
2678 if( pParent )
2679 {
2680 ::rtl::Reference< SwAccessibleContext > xParentAccImpl = GetContextImpl(pParent,false);
2681 if (!xParentAccImpl.is())
2682 {
2683 const SwTabFrame* pTabFrame = pParent->FindTabFrame();
2684 if (pTabFrame)
2685 {
2686 //The Table should not add in acc.because the "pParent" is not add to acc .
2687 uno::Reference< XAccessible> xAccParentTab = GetContext(pTabFrame);//Should Create.
2688
2689 const SwFrame *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pTabFrame), GetShell()->IsPreview() );
2690 if (pParentRoot)
2691 {
2692 ::rtl::Reference< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,false);
2693 if(xParentAccImplRoot.is())
2694 {
2695 AccessibleEventObject aEvent;
2696 aEvent.EventId = AccessibleEventId::CHILD;
2697 aEvent.NewValue <<= xAccParentTab;
2698 xParentAccImplRoot->FireAccessibleEvent( aEvent );
2699 }
2700 }
2701
2702 //Get "pParent" acc again.
2703 xParentAccImpl = GetContextImpl(pParent,false);
2704 }
2705 else
2706 {
2707 //directly create this acc para .
2708 xParentAccImpl = GetContextImpl(pParent);//Should Create.
2709
2710 const SwFrame *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pParent), GetShell()->IsPreview() );
2711
2712 ::rtl::Reference< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,false);
2713 if(xParentAccImplRoot.is())
2714 {
2715 AccessibleEventObject aEvent;
2716 aEvent.EventId = AccessibleEventId::CHILD;
2717 aEvent.NewValue <<= uno::Reference< XAccessible>(xParentAccImpl.get());
2718 xParentAccImplRoot->FireAccessibleEvent( aEvent );
2719 }
2720 }
2721 }
2722 if (xParentAccImpl.is())
2723 {
2724 uno::Reference< XAccessible> xAccShape =
2725 GetContext(pObj,xParentAccImpl.get());
2726
2727 AccessibleEventObject aEvent;
2728 aEvent.EventId = AccessibleEventId::CHILD;
2729 aEvent.NewValue <<= xAccShape;
2730 xParentAccImpl->FireAccessibleEvent( aEvent );
2731 }
2732 }
2733 }
2734 }
2735 }
2736 }
2737 }
2738
2739 m_setParaAdd.clear();
2740 m_setParaRemove.clear();
2741 if( xOldAcc.is() && xOldAcc != xAcc )
2742 InvalidateCursorPosition( xOldAcc );
2743 if( bOldShapeSelected || bShapeSelected )
2744 InvalidateShapeSelection();
2745 if( xAcc.is() )
2746 InvalidateCursorPosition( xAcc );
2747
2748 InvalidateShapeInParaSelection();
2749
2750 for (SwAccessibleParagraph* pAccPara : m_setParaRemove)
2751 {
2752 if(pAccPara && pAccPara->getSelectedAccessibleChildCount() == 0 && pAccPara->getSelectedText().getLength() == 0)
2753 {
2754 if(pAccPara->SetSelectedState(false))
2755 {
2756 AccessibleEventObject aEvent;
2757 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
2758 pAccPara->FireAccessibleEvent( aEvent );
2759 }
2760 }
2761 }
2762 for (SwAccessibleParagraph* pAccPara : m_setParaAdd)
2763 {
2764 if(pAccPara && pAccPara->SetSelectedState(true))
2765 {
2766 AccessibleEventObject aEvent;
2767 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
2768 pAccPara->FireAccessibleEvent( aEvent );
2769 }
2770 }
2771}
2772
2773void SwAccessibleMap::InvalidateFocus()
2774{
2775 if(GetShell()->IsPreview())
2776 {
2777 uno::Reference<XAccessible> xAcc = GetDocumentView_( true );
2778 if (xAcc)
2779 {
2780 SwAccessiblePreview *pAccPreview = static_cast<SwAccessiblePreview *>(xAcc.get());
2781 if (pAccPreview)
2782 {
2783 pAccPreview->InvalidateFocus();
2784 return ;
2785 }
2786 }
2787 }
2788 uno::Reference < XAccessible > xAcc;
2789 {
2790 osl::MutexGuard aGuard( maMutex );
2791
2792 xAcc = mxCursorContext;
2793 }
2794
2795 if( xAcc.is() )
2796 {
2797 SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
2798 pAccImpl->InvalidateFocus();
2799 }
2800 else
2801 {
2802 DoInvalidateShapeSelection(true);
2803 }
2804}
2805
2806void SwAccessibleMap::SetCursorContext(
2807 const ::rtl::Reference < SwAccessibleContext >& rCursorContext )
2808{
2809 osl::MutexGuard aGuard( maMutex );
2810 uno::Reference < XAccessible > xAcc( rCursorContext.get() );
2811 mxCursorContext = xAcc;
2812}
2813
2814void SwAccessibleMap::InvalidateEditableStates( const SwFrame* _pFrame )
2815{
2816 // Start with the frame or the first upper that is accessible
2817 SwAccessibleChild aFrameOrObj( _pFrame );
2818 while( aFrameOrObj.GetSwFrame() &&
2819 !aFrameOrObj.IsAccessible( GetShell()->IsPreview() ) )
2820 aFrameOrObj = aFrameOrObj.GetSwFrame()->GetUpper();
2821 if( !aFrameOrObj.GetSwFrame() )
2822 aFrameOrObj = GetShell()->GetLayout();
2823
2824 uno::Reference< XAccessible > xAcc( GetContext( aFrameOrObj.GetSwFrame() ) );
2825 SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
2826 if( GetShell()->ActionPend() )
2827 {
2828 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
2829 pAccImpl,
2830 SwAccessibleChild(pAccImpl->GetFrame()),
2831 AccessibleStates::EDITABLE );
2832 AppendEvent( aEvent );
2833 }
2834 else
2835 {
2836 FireEvents();
2837 pAccImpl->InvalidateStates( AccessibleStates::EDITABLE );
2838 }
2839}
2840
2841void SwAccessibleMap::InvalidateRelationSet_( const SwFrame* pFrame,
2842 bool bFrom )
2843{
2844 // first, see if this frame is accessible, and if so, get the respective
2845 SwAccessibleChild aFrameOrObj( pFrame );
2846 if( !aFrameOrObj.IsAccessible( GetShell()->IsPreview() ) )
2847 return;
2848
2849 uno::Reference < XAccessible > xAcc;
2850 {
2851 osl::MutexGuard aGuard( maMutex );
2852
2853 if( mpFrameMap )
2854 {
2855 SwAccessibleContextMap_Impl::iterator aIter =
2856 mpFrameMap->find( aFrameOrObj.GetSwFrame() );
2857 if( aIter != mpFrameMap->end() )
2858 {
2859 xAcc = (*aIter).second;
2860 }
2861 }
2862 }
2863
2864 // deliver event directly, or queue event
2865 if( !xAcc.is() )
2866 return;
2867
2868 SwAccessibleContext *pAccImpl =
2869 static_cast< SwAccessibleContext *>( xAcc.get() );
2870 if( GetShell()->ActionPend() )
2871 {
2872 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
2873 pAccImpl, SwAccessibleChild(pFrame),
2874 ( bFrom
2875 ? AccessibleStates::RELATION_FROM
2876 : AccessibleStates::RELATION_TO ) );
2877 AppendEvent( aEvent );
2878 }
2879 else
2880 {
2881 FireEvents();
2882 pAccImpl->InvalidateRelation( bFrom
2883 ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED
2884 : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
2885 }
2886}
2887
2888void SwAccessibleMap::InvalidateRelationSet( const SwFrame* pMaster,
2889 const SwFrame* pFollow )
2890{
2891 InvalidateRelationSet_( pMaster, false );
2892 InvalidateRelationSet_( pFollow, true );
2893}
2894
2895// invalidation of CONTENT_FLOW_FROM/_TO relation of a paragraph
2896void SwAccessibleMap::InvalidateParaFlowRelation( const SwTextFrame& _rTextFrame,
2897 const bool _bFrom )
2898{
2899 InvalidateRelationSet_( &_rTextFrame, _bFrom );
2900}
2901
2902// invalidation of text selection of a paragraph
2903void SwAccessibleMap::InvalidateParaTextSelection( const SwTextFrame& _rTextFrame )
2904{
2905 // first, see if this frame is accessible, and if so, get the respective
2906 SwAccessibleChild aFrameOrObj( &_rTextFrame );
2907 if( !aFrameOrObj.IsAccessible( GetShell()->IsPreview() ) )
2908 return;
2909
2910 uno::Reference < XAccessible > xAcc;
2911 {
2912 osl::MutexGuard aGuard( maMutex );
2913
2914 if( mpFrameMap )
2915 {
2916 SwAccessibleContextMap_Impl::iterator aIter =
2917 mpFrameMap->find( aFrameOrObj.GetSwFrame() );
2918 if( aIter != mpFrameMap->end() )
2919 {
2920 xAcc = (*aIter).second;
2921 }
2922 }
2923 }
2924
2925 // deliver event directly, or queue event
2926 if( !xAcc.is() )
2927 return;
2928
2929 SwAccessibleContext *pAccImpl =
2930 static_cast< SwAccessibleContext *>( xAcc.get() );
2931 if( GetShell()->ActionPend() )
2932 {
2933 SwAccessibleEvent_Impl aEvent(
2934 SwAccessibleEvent_Impl::CARET_OR_STATES,
2935 pAccImpl,
2936 SwAccessibleChild( &_rTextFrame ),
2937 AccessibleStates::TEXT_SELECTION_CHANGED );
2938 AppendEvent( aEvent );
2939 }
2940 else
2941 {
2942 FireEvents();
2943 pAccImpl->InvalidateTextSelection();
2944 }
2945}
2946
2947sal_Int32 SwAccessibleMap::GetChildIndex( const SwFrame& rParentFrame,
2948 vcl::Window& rChild ) const
2949{
2950 sal_Int32 nIndex( -1 );
2951
2952 SwAccessibleChild aFrameOrObj( &rParentFrame );
2953 if( aFrameOrObj.IsAccessible( GetShell()->IsPreview() ) )
2954 {
2955 uno::Reference < XAccessible > xAcc;
2956 {
2957 osl::MutexGuard aGuard( maMutex );
2958
2959 if( mpFrameMap )
2960 {
2961 SwAccessibleContextMap_Impl::iterator aIter =
2962 mpFrameMap->find( aFrameOrObj.GetSwFrame() );
2963 if( aIter != mpFrameMap->end() )
2964 {
2965 xAcc = (*aIter).second;
2966 }
2967 }
2968 }
2969
2970 if( xAcc.is() )
2971 {
2972 SwAccessibleContext *pAccImpl =
2973 static_cast< SwAccessibleContext *>( xAcc.get() );
2974
2975 nIndex = pAccImpl->GetChildIndex( const_cast<SwAccessibleMap&>(*this),
2976 SwAccessibleChild( &rChild ) );
2977 }
2978 }
2979
2980 return nIndex;
2981}
2982
2983void SwAccessibleMap::UpdatePreview( const std::vector<std::unique_ptr<PreviewPage>>& _rPreviewPages,
2984 const Fraction& _rScale,
2985 const SwPageFrame* _pSelectedPageFrame,
2986 const Size& _rPreviewWinSize )
2987{
2988 assert(GetShell()->IsPreview() && "no preview?")(static_cast <bool> (GetShell()->IsPreview() &&
"no preview?") ? void (0) : __assert_fail ("GetShell()->IsPreview() && \"no preview?\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 2988, __extension__ __PRETTY_FUNCTION__))
;
2989 assert(mpPreview != nullptr && "no preview data?")(static_cast <bool> (mpPreview != nullptr && "no preview data?"
) ? void (0) : __assert_fail ("mpPreview != nullptr && \"no preview data?\""
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 2989, __extension__ __PRETTY_FUNCTION__))
;
2990
2991 mpPreview->Update( *this, _rPreviewPages, _rScale, _pSelectedPageFrame, _rPreviewWinSize );
2992
2993 // propagate change of VisArea through the document's
2994 // accessibility tree; this will also send appropriate scroll
2995 // events
2996 SwAccessibleContext* pDoc =
2997 GetContextImpl( GetShell()->GetLayout() ).get();
2998 static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea();
2999
3000 uno::Reference < XAccessible > xOldAcc;
3001 uno::Reference < XAccessible > xAcc;
3002 {
3003 osl::MutexGuard aGuard( maMutex );
3004
3005 xOldAcc = mxCursorContext;
3006
3007 const SwPageFrame *pSelPage = mpPreview->GetSelPage();
3008 if( pSelPage && mpFrameMap )
3009 {
3010 SwAccessibleContextMap_Impl::iterator aIter =
3011 mpFrameMap->find( pSelPage );
3012 if( aIter != mpFrameMap->end() )
3013 xAcc = (*aIter).second;
3014 }
3015 }
3016
3017 if( xOldAcc.is() && xOldAcc != xAcc )
3018 InvalidateCursorPosition( xOldAcc );
3019 if( xAcc.is() )
3020 InvalidateCursorPosition( xAcc );
3021}
3022
3023void SwAccessibleMap::InvalidatePreviewSelection( sal_uInt16 nSelPage )
3024{
3025 assert(GetShell()->IsPreview())(static_cast <bool> (GetShell()->IsPreview()) ? void
(0) : __assert_fail ("GetShell()->IsPreview()", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 3025, __extension__ __PRETTY_FUNCTION__))
;
3026 assert(mpPreview != nullptr)(static_cast <bool> (mpPreview != nullptr) ? void (0) :
__assert_fail ("mpPreview != nullptr", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 3026, __extension__ __PRETTY_FUNCTION__))
;
3027
3028 mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) );
3029
3030 uno::Reference < XAccessible > xOldAcc;
3031 uno::Reference < XAccessible > xAcc;
3032 {
3033 osl::MutexGuard aGuard( maMutex );
3034
3035 xOldAcc = mxCursorContext;
3036
3037 const SwPageFrame *pSelPage = mpPreview->GetSelPage();
3038 if( pSelPage && mpFrameMap )
3039 {
3040 SwAccessibleContextMap_Impl::iterator aIter = mpFrameMap->find( pSelPage );
3041 if( aIter != mpFrameMap->end() )
3042 xAcc = (*aIter).second;
3043 }
3044 }
3045
3046 if( xOldAcc.is() && xOldAcc != xAcc )
3047 InvalidateCursorPosition( xOldAcc );
3048 if( xAcc.is() )
3049 InvalidateCursorPosition( xAcc );
3050}
3051
3052bool SwAccessibleMap::IsPageSelected( const SwPageFrame *pPageFrame ) const
3053{
3054 return mpPreview && mpPreview->GetSelPage() == pPageFrame;
3055}
3056
3057void SwAccessibleMap::FireEvents()
3058{
3059 {
3060 osl::MutexGuard aGuard( maEventMutex );
3061 if( mpEvents )
3062 {
3063 if (mpEvents->IsFiring())
3064 {
3065 return; // prevent recursive FireEvents()
3066 }
3067
3068 mpEvents->SetFiring();
3069 mpEvents->MoveMissingXAccToEnd();
3070 for( auto const& aEvent : *mpEvents )
3071 FireEvent(aEvent);
3072
3073 mpEventMap.reset();
3074 mpEvents.reset();
3075 }
3076 }
3077 {
3078 osl::MutexGuard aGuard( maMutex );
3079 mvShapes.clear();
3080 }
3081
3082}
3083
3084tools::Rectangle SwAccessibleMap::GetVisibleArea() const
3085{
3086 MapMode aSrc( MapUnit::MapTwip );
3087 MapMode aDest( MapUnit::Map100thMM );
3088 return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest );
3089}
3090
3091// Convert a MM100 value relative to the document root into a pixel value
3092// relative to the screen!
3093Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const
3094{
3095 MapMode aSrc( MapUnit::Map100thMM );
3096 MapMode aDest( MapUnit::MapTwip );
3097
3098 Point aPoint = OutputDevice::LogicToLogic( rPoint, aSrc, aDest );
3099 if (const vcl::Window* pWin = GetShell()->GetWin())
3100 {
3101 MapMode aMapMode;
3102 GetMapMode( aPoint, aMapMode );
3103 aPoint = pWin->LogicToPixel( aPoint, aMapMode );
3104 aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint );
3105 }
3106
3107 return aPoint;
3108}
3109
3110Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const
3111{
3112 MapMode aSrc( MapUnit::Map100thMM );
3113 MapMode aDest( MapUnit::MapTwip );
3114 Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) );
3115 if (const OutputDevice* pWin = GetShell()->GetWin())
3116 {
3117 MapMode aMapMode;
3118 GetMapMode( Point(0,0), aMapMode );
3119 aSize = pWin->LogicToPixel( aSize, aMapMode );
3120 }
3121
3122 return aSize;
3123}
3124
3125bool SwAccessibleMap::ReplaceChild (
3126 ::accessibility::AccessibleShape* pCurrentChild,
3127 const uno::Reference< drawing::XShape >& _rxShape,
3128 const long /*_nIndex*/,
3129 const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/
3130 )
3131{
3132 const SdrObject *pObj = nullptr;
3133 {
3134 osl::MutexGuard aGuard( maMutex );
3135 if( mpShapeMap )
1
Taking true branch
3136 {
3137 SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->cbegin();
3138 SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->cend();
3139 while( aIter != aEndIter && !pObj )
2
Loop condition is true. Entering loop body
3140 {
3141 uno::Reference < XAccessible > xAcc( (*aIter).second );
3142 ::accessibility::AccessibleShape *pAccShape =
3143 static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
3144 if( pAccShape == pCurrentChild )
3
Assuming 'pAccShape' is equal to 'pCurrentChild'
4
Taking true branch
3145 {
3146 pObj = (*aIter).first;
3147 }
3148 ++aIter;
3149 }
3150 }
3151 }
3152 if( !pObj )
5
Assuming 'pObj' is non-null
6
Taking false branch
3153 return false;
3154
3155 uno::Reference < drawing::XShape > xShape( _rxShape ); // keep reference to shape, because
3156 // we might be the only one that
3157 // holds it.
3158 // Also get keep parent.
3159 uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() );
3160 pCurrentChild = nullptr; // will be released by dispose
3161 A11yDispose( nullptr, pObj, nullptr );
3162
3163 {
3164 osl::MutexGuard aGuard( maMutex );
3165
3166 if( !mpShapeMap )
7
Taking false branch
3167 mpShapeMap.reset(new SwAccessibleShapeMap_Impl( this ));
3168
3169 // create the new child
3170 ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
3171 ::accessibility::ShapeTypeHandler::Instance();
3172 ::accessibility::AccessibleShapeInfo aShapeInfo(
3173 xShape, xParent, this );
3174 rtl::Reference< ::accessibility::AccessibleShape> pReplacement(
3175 rShapeTypeHandler.CreateAccessibleObject (
3176 aShapeInfo, mpShapeMap->GetInfo() ));
3177
3178 uno::Reference < XAccessible > xAcc( pReplacement.get() );
3179 if( xAcc.is() )
8
Taking false branch
3180 {
3181 pReplacement->Init();
3182
3183 SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( pObj );
3184 if( aIter != mpShapeMap->end() )
3185 {
3186 (*aIter).second = xAcc;
3187 }
3188 else
3189 {
3190 mpShapeMap->emplace( pObj, xAcc );
3191 }
3192 }
3193 }
3194
3195 SwRect aEmptyRect;
3196 InvalidatePosOrSize( nullptr, pObj, nullptr, aEmptyRect );
9
Passing null pointer value via 1st parameter 'pFrame'
10
Calling 'SwAccessibleMap::InvalidatePosOrSize'
3197
3198 return true;
3199}
3200
3201//Get the accessible control shape from the model object, here model object is with XPropertySet type
3202::accessibility::AccessibleControlShape * SwAccessibleMap::GetAccControlShapeFromModel(css::beans::XPropertySet* pSet)
3203{
3204 if( mpShapeMap )
3205 {
3206 SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->cbegin();
3207 SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->cend();
3208 while( aIter != aEndIter)
3209 {
3210 uno::Reference < XAccessible > xAcc( (*aIter).second );
3211 ::accessibility::AccessibleShape *pAccShape =
3212 static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
3213 if(pAccShape && ::accessibility::ShapeTypeHandler::Instance().GetTypeId (pAccShape->GetXShape()) == ::accessibility::DRAWING_CONTROL)
3214 {
3215 ::accessibility::AccessibleControlShape *pCtlAccShape = static_cast < ::accessibility::AccessibleControlShape* >(pAccShape);
3216 if (pCtlAccShape->GetControlModel() == pSet)
3217 return pCtlAccShape;
3218 }
3219 ++aIter;
3220 }
3221 }
3222 return nullptr;
3223}
3224
3225css::uno::Reference< XAccessible >
3226 SwAccessibleMap::GetAccessibleCaption (const css::uno::Reference< css::drawing::XShape >&)
3227{
3228 return nullptr;
3229}
3230
3231Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const
3232{
3233 Point aPoint;
3234 if (const OutputDevice* pWin = GetShell()->GetWin())
3235 {
3236 MapMode aMapMode;
3237 GetMapMode( rPoint, aMapMode );
3238 aPoint = pWin->PixelToLogic( rPoint, aMapMode );
3239 }
3240 return aPoint;
3241}
3242
3243static long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue,
3244 long aRefValue, bool bToLower)
3245{
3246 long aResult = aCoarseValue;
3247
3248 if (bToLower)
3249 {
3250 if (aFineValue < aRefValue)
3251 aResult -= 1;
3252 }
3253 else
3254 {
3255 if (aFineValue > aRefValue)
3256 aResult += 1;
3257 }
3258
3259 return aResult;
3260}
3261
3262static void lcl_CorrectRectangle(tools::Rectangle & rRect,
3263 const tools::Rectangle & rSource,
3264 const tools::Rectangle & rInGrid)
3265{
3266 rRect.SetLeft( lcl_CorrectCoarseValue(rRect.Left(), rSource.Left(),
3267 rInGrid.Left(), false) );
3268 rRect.SetTop( lcl_CorrectCoarseValue(rRect.Top(), rSource.Top(),
3269 rInGrid.Top(), false) );
3270 rRect.SetRight( lcl_CorrectCoarseValue(rRect.Right(), rSource.Right(),
3271 rInGrid.Right(), true) );
3272 rRect.SetBottom( lcl_CorrectCoarseValue(rRect.Bottom(), rSource.Bottom(),
3273 rInGrid.Bottom(), true) );
3274}
3275
3276tools::Rectangle SwAccessibleMap::CoreToPixel( const tools::Rectangle& rRect ) const
3277{
3278 tools::Rectangle aRect;
3279 if (const OutputDevice* pWin = GetShell()->GetWin())
3280 {
3281 MapMode aMapMode;
3282 GetMapMode( rRect.TopLeft(), aMapMode );
3283 aRect = pWin->LogicToPixel( rRect, aMapMode );
3284
3285 tools::Rectangle aTmpRect = pWin->PixelToLogic( aRect, aMapMode );
3286 lcl_CorrectRectangle(aRect, rRect, aTmpRect);
3287 }
3288
3289 return aRect;
3290}
3291
3292/** get mapping mode for LogicToPixel and PixelToLogic conversions
3293
3294 Method returns mapping mode of current output device and adjusts it,
3295 if the shell is in page/print preview.
3296 Necessary, because <PreviewAdjust(..)> changes mapping mode at current
3297 output device for mapping logic document positions to page preview window
3298 positions and vice versa and doesn't take care to recover its changes.
3299*/
3300void SwAccessibleMap::GetMapMode( const Point& _rPoint,
3301 MapMode& _orMapMode ) const
3302{
3303 MapMode aMapMode = GetShell()->GetWin()->GetMapMode();
3304 if( GetShell()->IsPreview() )
3305 {
3306 assert(mpPreview != nullptr)(static_cast <bool> (mpPreview != nullptr) ? void (0) :
__assert_fail ("mpPreview != nullptr", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 3306, __extension__ __PRETTY_FUNCTION__))
;
3307 mpPreview->AdjustMapMode( aMapMode, _rPoint );
3308 }
3309 _orMapMode = aMapMode;
3310}
3311
3312Size SwAccessibleMap::GetPreviewPageSize(sal_uInt16 const nPreviewPageNum) const
3313{
3314 assert(mpVSh->IsPreview())(static_cast <bool> (mpVSh->IsPreview()) ? void (0) :
__assert_fail ("mpVSh->IsPreview()", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 3314, __extension__ __PRETTY_FUNCTION__))
;
3315 assert(mpPreview != nullptr)(static_cast <bool> (mpPreview != nullptr) ? void (0) :
__assert_fail ("mpPreview != nullptr", "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 3315, __extension__ __PRETTY_FUNCTION__))
;
3316 return mpVSh->PagePreviewLayout()->GetPreviewPageSizeByPageNum(nPreviewPageNum);
3317}
3318
3319/** method to build up a new data structure of the accessible paragraphs,
3320 which have a selection
3321 Important note: method has to be used inside a mutual exclusive section
3322*/
3323std::unique_ptr<SwAccessibleSelectedParas_Impl> SwAccessibleMap::BuildSelectedParas()
3324{
3325 // no accessible contexts, no selection
3326 if ( !mpFrameMap )
3327 {
3328 return nullptr;
3329 }
3330
3331 // get cursor as an instance of its base class <SwPaM>
3332 SwPaM* pCursor( nullptr );
3333 {
3334 SwCursorShell* pCursorShell = dynamic_cast<SwCursorShell*>(GetShell());
3335 if ( pCursorShell )
3336 {
3337 SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCursorShell);
3338 if ( !pFEShell ||
3339 ( !pFEShell->IsFrameSelected() &&
3340 pFEShell->IsObjSelected() == 0 ) )
3341 {
3342 // get cursor without updating an existing table cursor.
3343 pCursor = pCursorShell->GetCursor( false );
3344 }
3345 }
3346 }
3347 // no cursor, no selection
3348 if ( !pCursor )
3349 {
3350 return nullptr;
3351 }
3352
3353 std::unique_ptr<SwAccessibleSelectedParas_Impl> pRetSelectedParas;
3354
3355 // loop on all cursors
3356 SwPaM* pRingStart = pCursor;
3357 do {
3358
3359 // for a selection the cursor has to have a mark.
3360 // for safety reasons assure that point and mark are in text nodes
3361 if ( pCursor->HasMark() &&
3362 pCursor->GetPoint()->nNode.GetNode().IsTextNode() &&
3363 pCursor->GetMark()->nNode.GetNode().IsTextNode() )
3364 {
3365 SwPosition* pStartPos = pCursor->Start();
3366 SwPosition* pEndPos = pCursor->End();
3367 // loop on all text nodes inside the selection
3368 SwNodeIndex aIdx( pStartPos->nNode );
3369 for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx )
3370 {
3371 SwTextNode* pTextNode( aIdx.GetNode().GetTextNode() );
3372 if ( pTextNode )
3373 {
3374 // loop on all text frames registered at the text node.
3375 SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pTextNode);
3376 for( SwTextFrame* pTextFrame = aIter.First(); pTextFrame; pTextFrame = aIter.Next() )
3377 {
3378 uno::WeakReference < XAccessible > xWeakAcc;
3379 SwAccessibleContextMap_Impl::iterator aMapIter =
3380 mpFrameMap->find( pTextFrame );
3381 if( aMapIter != mpFrameMap->end() )
3382 {
3383 xWeakAcc = (*aMapIter).second;
3384 SwAccessibleParaSelection aDataEntry(
3385 sw::FrameContainsNode(*pTextFrame, pStartPos->nNode.GetIndex())
3386 ? pTextFrame->MapModelToViewPos(*pStartPos)
3387 : TextFrameIndex(0),
3388
3389 sw::FrameContainsNode(*pTextFrame, pEndPos->nNode.GetIndex())
3390 ? pTextFrame->MapModelToViewPos(*pEndPos)
3391 : TextFrameIndex(COMPLETE_STRING));
3392 if ( !pRetSelectedParas )
3393 {
3394 pRetSelectedParas.reset(
3395 new SwAccessibleSelectedParas_Impl);
3396 }
3397 // sw_redlinehide: should be idempotent for multiple nodes in a merged para
3398 pRetSelectedParas->emplace( xWeakAcc, aDataEntry );
3399 }
3400 }
3401 }
3402 }
3403 }
3404
3405 // prepare next turn: get next cursor in ring
3406 pCursor = pCursor->GetNext();
3407 } while ( pCursor != pRingStart );
3408
3409 return pRetSelectedParas;
3410}
3411
3412void SwAccessibleMap::InvalidateTextSelectionOfAllParas()
3413{
3414 osl::MutexGuard aGuard( maMutex );
3415
3416 // keep previously known selected paragraphs
3417 std::unique_ptr<SwAccessibleSelectedParas_Impl> pPrevSelectedParas( std::move(mpSelectedParas) );
3418
3419 // determine currently selected paragraphs
3420 mpSelectedParas = BuildSelectedParas();
3421
3422 // compare currently selected paragraphs with the previously selected
3423 // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events.
3424 // first, search for new and changed selections.
3425 // on the run remove selections from previously known ones, if they are
3426 // also in the current ones.
3427 if ( mpSelectedParas )
3428 {
3429 SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin();
3430 for ( ; aIter != mpSelectedParas->end(); ++aIter )
3431 {
3432 bool bSubmitEvent( false );
3433 if ( !pPrevSelectedParas )
3434 {
3435 // new selection
3436 bSubmitEvent = true;
3437 }
3438 else
3439 {
3440 SwAccessibleSelectedParas_Impl::iterator aPrevSelected =
3441 pPrevSelectedParas->find( (*aIter).first );
3442 if ( aPrevSelected != pPrevSelectedParas->end() )
3443 {
3444 // check, if selection has changed
3445 if ( (*aIter).second.nStartOfSelection !=
3446 (*aPrevSelected).second.nStartOfSelection ||
3447 (*aIter).second.nEndOfSelection !=
3448 (*aPrevSelected).second.nEndOfSelection )
3449 {
3450 // changed selection
3451 bSubmitEvent = true;
3452 }
3453 pPrevSelectedParas->erase( aPrevSelected );
3454 }
3455 else
3456 {
3457 // new selection
3458 bSubmitEvent = true;
3459 }
3460 }
3461
3462 if ( bSubmitEvent )
3463 {
3464 uno::Reference < XAccessible > xAcc( (*aIter).first );
3465 if ( xAcc.is() )
3466 {
3467 ::rtl::Reference < SwAccessibleContext > xAccImpl(
3468 static_cast<SwAccessibleContext*>( xAcc.get() ) );
3469 if ( xAccImpl.is() && xAccImpl->GetFrame() )
3470 {
3471 const SwTextFrame* pTextFrame(
3472 dynamic_cast<const SwTextFrame*>(xAccImpl->GetFrame()) );
3473 OSL_ENSURE( pTextFrame,do { if (true && (!(pTextFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "3474" ": "), "%s", "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexpected type of frame"
); } } while (false)
3474 "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexpected type of frame" )do { if (true && (!(pTextFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "3474" ": "), "%s", "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexpected type of frame"
); } } while (false)
;
3475 if ( pTextFrame )
3476 {
3477 InvalidateParaTextSelection( *pTextFrame );
3478 }
3479 }
3480 }
3481 }
3482 }
3483 }
3484
3485 // second, handle previous selections - after the first step the data
3486 // structure of the previously known only contains the 'old' selections
3487 if ( !pPrevSelectedParas )
3488 return;
3489
3490 SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin();
3491 for ( ; aIter != pPrevSelectedParas->end(); ++aIter )
3492 {
3493 uno::Reference < XAccessible > xAcc( (*aIter).first );
3494 if ( xAcc.is() )
3495 {
3496 ::rtl::Reference < SwAccessibleContext > xAccImpl(
3497 static_cast<SwAccessibleContext*>( xAcc.get() ) );
3498 if ( xAccImpl.is() && xAccImpl->GetFrame() )
3499 {
3500 const SwTextFrame* pTextFrame(
3501 dynamic_cast<const SwTextFrame*>(xAccImpl->GetFrame()) );
3502 OSL_ENSURE( pTextFrame,do { if (true && (!(pTextFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "3503" ": "), "%s", "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexpected type of frame"
); } } while (false)
3503 "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexpected type of frame" )do { if (true && (!(pTextFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
":" "3503" ": "), "%s", "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexpected type of frame"
); } } while (false)
;
3504 if ( pTextFrame )
3505 {
3506 InvalidateParaTextSelection( *pTextFrame );
3507 }
3508 }
3509 }
3510 }
3511}
3512
3513const SwRect& SwAccessibleMap::GetVisArea() const
3514{
3515 assert(!GetShell()->IsPreview() || (mpPreview != nullptr))(static_cast <bool> (!GetShell()->IsPreview() || (mpPreview
!= nullptr)) ? void (0) : __assert_fail ("!GetShell()->IsPreview() || (mpPreview != nullptr)"
, "/home/maarten/src/libreoffice/core/sw/source/core/access/accmap.cxx"
, 3515, __extension__ __PRETTY_FUNCTION__))
;
3516
3517 return GetShell()->IsPreview()
3518 ? mpPreview->GetVisArea()
3519 : GetShell()->VisArea();
3520}
3521
3522bool SwAccessibleMap::IsDocumentSelAll()
3523{
3524 return GetShell()->GetDoc()->IsPrepareSelAll();
3525}
3526
3527/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
25
Returning zero, which participates in a condition later
29
Returning zero, which participates in a condition later
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */