Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/draw/dview.cxx
Warning:line 700, column 19
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 dview.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/draw/dview.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 <hintids.hxx>
21#include <svx/svdpage.hxx>
22#include <svx/svdpagv.hxx>
23#include <svx/fmmodel.hxx>
24#include <sot/exchange.hxx>
25#include <svx/sdrundomanager.hxx>
26#include <tools/globname.hxx>
27#include <editeng/outliner.hxx>
28#include <com/sun/star/embed/EmbedMisc.hpp>
29#include <com/sun/star/embed/XEmbeddedObject.hpp>
30
31#include <pagefrm.hxx>
32#include <rootfrm.hxx>
33#include <cntfrm.hxx>
34#include <notxtfrm.hxx>
35#include <flyfrm.hxx>
36#include <frmfmt.hxx>
37#include <dflyobj.hxx>
38#include <dcontact.hxx>
39#include <textboxhelper.hxx>
40#include <viewsh.hxx>
41#include <viewimp.hxx>
42#include <dview.hxx>
43#include <doc.hxx>
44#include <mdiexp.hxx>
45#include <ndole.hxx>
46#include <ndgrf.hxx>
47#include <fmtanchr.hxx>
48#include <IDocumentUndoRedo.hxx>
49#include <DocumentSettingManager.hxx>
50#include <IDocumentLayoutAccess.hxx>
51
52#include <com/sun/star/embed/Aspects.hpp>
53
54#include <vector>
55
56#include <sortedobjs.hxx>
57#include <UndoManager.hxx>
58
59using namespace com::sun::star;
60
61namespace {
62
63class SwSdrHdl : public SdrHdl
64{
65public:
66 SwSdrHdl(const Point& rPnt, bool bTopRight ) :
67 SdrHdl( rPnt, bTopRight ? SdrHdlKind::Anchor_TR : SdrHdlKind::Anchor ) {}
68 virtual bool IsFocusHdl() const override;
69};
70
71}
72
73bool SwSdrHdl::IsFocusHdl() const
74{
75 if( SdrHdlKind::Anchor == eKind || SdrHdlKind::Anchor_TR == eKind )
76 return true;
77 return SdrHdl::IsFocusHdl();
78}
79
80static const SwFrame *lcl_FindAnchor( const SdrObject *pObj, bool bAll )
81{
82 const SwVirtFlyDrawObj *pVirt = dynamic_cast< const SwVirtFlyDrawObj *>( pObj ) != nullptr ?
83 static_cast<const SwVirtFlyDrawObj*>(pObj) : nullptr;
84 if ( pVirt )
85 {
86 if ( bAll || !pVirt->GetFlyFrame()->IsFlyInContentFrame() )
87 return pVirt->GetFlyFrame()->GetAnchorFrame();
88 }
89 else
90 {
91 const SwDrawContact *pCont = static_cast<const SwDrawContact*>(GetUserCall(pObj));
92 if ( pCont )
93 return pCont->GetAnchorFrame( pObj );
94 }
95 return nullptr;
96}
97
98SwDrawView::SwDrawView(
99 SwViewShellImp& rI,
100 FmFormModel& rFmFormModel,
101 OutputDevice* pOutDev)
102: FmFormView(rFmFormModel, pOutDev),
103 m_rImp( rI )
104{
105 SetPageVisible( false );
106 SetBordVisible( false );
107 SetGridVisible( false );
108 SetHlplVisible( false );
109 SetGlueVisible( false );
110 SetFrameDragSingles();
111 SetSwapAsynchron();
112
113 EnableExtendedKeyInputDispatcher( false );
114 EnableExtendedMouseEventDispatcher( false );
115
116 SetHitTolerancePixel( GetMarkHdlSizePixel()/2 );
117
118 SetPrintPreview( rI.GetShell()->IsPreview() );
119
120 // #i73602# Use default from the configuration
121 SetBufferedOverlayAllowed(getOptionsDrawinglayer().IsOverlayBuffer_Writer());
122
123 // #i74769#, #i75172# Use default from the configuration
124 SetBufferedOutputAllowed(getOptionsDrawinglayer().IsPaintBuffer_Writer());
125}
126
127// #i99665#
128bool SwDrawView::IsAntiAliasing() const
129{
130 return getOptionsDrawinglayer().IsAntiAliasing();
131}
132
133static SdrObject* impLocalHitCorrection(SdrObject* pRetval, const Point& rPnt, sal_uInt16 nTol, const SdrMarkList &rMrkList)
134{
135 if(!nTol)
136 {
137 // the old method forced back to outer bounds test when nTol == 0, so
138 // do not try to correct when nTol is not set (used from HelpContent)
139 }
140 else
141 {
142 // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since
143 // the SdrObject-specific CheckHit implementations are now replaced with primitives and
144 // 'tricks' like in the old implementation (e.g. using a view from a model-data class to
145 // detect if object is selected) are no longer valid.
146 // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old
147 // implementation reduced this excluding the inner bound when the object was not selected.
148 SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(pRetval);
149
150 if(pSwVirtFlyDrawObj)
151 {
152 if(pSwVirtFlyDrawObj->GetFlyFrame()->Lower() && pSwVirtFlyDrawObj->GetFlyFrame()->Lower()->IsNoTextFrame())
153 {
154 // the old method used IsNoTextFrame (should be for SW's own OLE and
155 // graphic's) to accept hit only based on outer bounds; nothing to do
156 }
157 else
158 {
159 // check if the object is selected in this view
160 const size_t nMarkCount(rMrkList.GetMarkCount());
161 bool bSelected(false);
162
163 for(size_t a = 0; !bSelected && a < nMarkCount; ++a)
164 {
165 if(pSwVirtFlyDrawObj == rMrkList.GetMark(a)->GetMarkedSdrObj())
166 {
167 bSelected = true;
168 }
169 }
170
171 if(!bSelected)
172 {
173 // when not selected, the object is not hit when hit position is inside
174 // inner range. Get and shrink inner range
175 basegfx::B2DRange aInnerBound(pSwVirtFlyDrawObj->getInnerBound());
176
177 aInnerBound.grow(-1.0 * nTol);
178
179 if(aInnerBound.isInside(basegfx::B2DPoint(rPnt.X(), rPnt.Y())))
180 {
181 // exclude this hit
182 pRetval = nullptr;
183 }
184 }
185 }
186 }
187 }
188
189 return pRetval;
190}
191
192SdrObject* SwDrawView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay) const
193{
194 // call parent
195 SdrObject* pRetval = FmFormView::CheckSingleSdrObjectHit(rPnt, nTol, pObj, pPV, nOptions, pMVisLay);
196
197 if(pRetval)
198 {
199 // override to allow extra handling when picking SwVirtFlyDrawObj's
200 pRetval = impLocalHitCorrection(pRetval, rPnt, nTol, GetMarkedObjectList());
201 }
202
203 return pRetval;
204}
205
206/// Gets called every time the handles need to be build
207void SwDrawView::AddCustomHdl()
208{
209 const SdrMarkList &rMrkList = GetMarkedObjectList();
210
211 if(rMrkList.GetMarkCount() != 1 || !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()))
212 return;
213
214 SdrObject *pObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
215 // make code robust
216 SwFrameFormat* pFrameFormat( ::FindFrameFormat( pObj ) );
217 if ( !pFrameFormat )
218 {
219 OSL_FAIL( "<SwDrawView::AddCustomHdl()> - missing frame format!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/draw/dview.cxx"
":" "219" ": "), "%s", "<SwDrawView::AddCustomHdl()> - missing frame format!"
); } } while (false)
;
220 return;
221 }
222 const SwFormatAnchor &rAnchor = pFrameFormat->GetAnchor();
223
224 if (RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId())
225 return;
226
227 const SwFrame* pAnch = CalcAnchor();
228 if(nullptr == pAnch)
229 return;
230
231 Point aPos(m_aAnchorPoint);
232
233 if ( RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId() )
234 {
235 // #i28701# - use last character rectangle saved at object
236 // in order to avoid a format of the anchor frame
237 SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
238 SwRect aAutoPos = pAnchoredObj->GetLastCharRect();
239 if ( aAutoPos.Height() )
240 {
241 aPos = aAutoPos.Pos();
242 }
243 }
244
245 // add anchor handle:
246 maHdlList.AddHdl( std::make_unique<SwSdrHdl>( aPos, ( pAnch->IsVertical() && !pAnch->IsVertLR() ) ||
247 pAnch->IsRightToLeft() ) );
248}
249
250SdrObject* SwDrawView::GetMaxToTopObj( SdrObject* pObj ) const
251{
252 if ( GetUserCall(pObj) )
253 {
254 const SwFrame *pAnch = ::lcl_FindAnchor( pObj, false );
255 if ( pAnch )
256 {
257 //The topmost Obj within the anchor must not be overtaken.
258 const SwFlyFrame *pFly = pAnch->FindFlyFrame();
259 if ( pFly )
260 {
261 const SwPageFrame *pPage = pFly->FindPageFrame();
262 if ( pPage->GetSortedObjs() )
263 {
264 size_t nOrdNum = 0;
265 for (SwAnchoredObject* i : *pPage->GetSortedObjs())
266 {
267 const SdrObject *pO = i->GetDrawObj();
268
269 if ( pO->GetOrdNumDirect() > nOrdNum )
270 {
271 const SwFrame *pTmpAnch = ::lcl_FindAnchor( pO, false );
272 if ( pFly->IsAnLower( pTmpAnch ) )
273 {
274 nOrdNum = pO->GetOrdNumDirect();
275 }
276 }
277 }
278 if ( nOrdNum )
279 {
280 SdrPage *pTmpPage = GetModel()->GetPage( 0 );
281 ++nOrdNum;
282 if ( nOrdNum < pTmpPage->GetObjCount() )
283 {
284 return pTmpPage->GetObj( nOrdNum );
285 }
286 }
287 }
288 }
289 }
290 }
291 return nullptr;
292}
293
294SdrObject* SwDrawView::GetMaxToBtmObj(SdrObject* pObj) const
295{
296 if ( GetUserCall(pObj) )
297 {
298 const SwFrame *pAnch = ::lcl_FindAnchor( pObj, false );
299 if ( pAnch )
300 {
301 //The Fly of the anchor must not be "flying under".
302 const SwFlyFrame *pFly = pAnch->FindFlyFrame();
303 if ( pFly )
304 {
305 SdrObject *pRet = const_cast<SdrObject*>(static_cast<SdrObject const *>(pFly->GetVirtDrawObj()));
306 return pRet != pObj ? pRet : nullptr;
307 }
308 }
309 }
310 return nullptr;
311}
312
313/// determine maximal order number for a 'child' object of given 'parent' object
314sal_uInt32 SwDrawView::GetMaxChildOrdNum( const SwFlyFrame& _rParentObj,
315 const SdrObject* _pExclChildObj )
316{
317 sal_uInt32 nMaxChildOrdNum = _rParentObj.GetDrawObj()->GetOrdNum();
318
319 const SdrPage* pDrawPage = _rParentObj.GetDrawObj()->getSdrPageFromSdrObject();
320 OSL_ENSURE( pDrawPage,do { if (true && (!(pDrawPage))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/draw/dview.cxx"
":" "321" ": "), "%s", "<SwDrawView::GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!"
); } } while (false)
321 "<SwDrawView::GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!" )do { if (true && (!(pDrawPage))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/draw/dview.cxx"
":" "321" ": "), "%s", "<SwDrawView::GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!"
); } } while (false)
;
322
323 const size_t nObjCount = pDrawPage->GetObjCount();
324 for ( size_t i = nObjCount-1; i > _rParentObj.GetDrawObj()->GetOrdNum() ; --i )
325 {
326 const SdrObject* pObj = pDrawPage->GetObj( i );
327
328 // Don't consider 'child' object <_pExclChildObj>
329 if ( pObj == _pExclChildObj )
330 {
331 continue;
332 }
333
334 if ( pObj->GetOrdNum() > nMaxChildOrdNum &&
335 _rParentObj.IsAnLower( lcl_FindAnchor( pObj, true ) ) )
336 {
337 nMaxChildOrdNum = pObj->GetOrdNum();
338 break;
339 }
340 }
341
342 return nMaxChildOrdNum;
343}
344
345/// method to move 'repeated' objects of the given moved object to the according level
346void SwDrawView::MoveRepeatedObjs( const SwAnchoredObject& _rMovedAnchoredObj,
347 const std::vector<SdrObject*>& _rMovedChildObjs ) const
348{
349 // determine 'repeated' objects of already moved object <_rMovedAnchoredObj>
350 std::vector<SwAnchoredObject*> aAnchoredObjs;
351 {
352 const SwContact* pContact = ::GetUserCall( _rMovedAnchoredObj.GetDrawObj() );
353 assert(pContact && "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.")(static_cast <bool> (pContact && "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash."
) ? void (0) : __assert_fail ("pContact && \"SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.\""
, "/home/maarten/src/libreoffice/core/sw/source/core/draw/dview.cxx"
, 353, __extension__ __PRETTY_FUNCTION__))
;
354 pContact->GetAnchoredObjs( aAnchoredObjs );
355 }
356
357 // check, if 'repeated' objects exists.
358 if ( aAnchoredObjs.size() <= 1 )
359 return;
360
361 SdrPage* pDrawPage = GetModel()->GetPage( 0 );
362
363 // move 'repeated' ones to the same order number as the already moved one.
364 const size_t nNewPos = _rMovedAnchoredObj.GetDrawObj()->GetOrdNum();
365 while ( !aAnchoredObjs.empty() )
366 {
367 SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
368 if ( pAnchoredObj != &_rMovedAnchoredObj )
369 {
370 pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
371 nNewPos );
372 pDrawPage->RecalcObjOrdNums();
373 // adjustments for accessibility API
374 if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
375 {
376 const SwFlyFrame *pTmpFlyFrame = static_cast<SwFlyFrame*>(pAnchoredObj);
377 m_rImp.DisposeAccessibleFrame( pTmpFlyFrame );
378 m_rImp.AddAccessibleFrame( pTmpFlyFrame );
379 }
380 else
381 {
382 m_rImp.DisposeAccessibleObj(pAnchoredObj->GetDrawObj(), true);
383 m_rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
384 }
385 }
386 aAnchoredObjs.pop_back();
387 }
388
389 // move 'repeated' ones of 'child' objects
390 for ( SdrObject* pChildObj : _rMovedChildObjs )
391 {
392 {
393 const SwContact* pContact = ::GetUserCall( pChildObj );
394 assert(pContact && "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.")(static_cast <bool> (pContact && "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash."
) ? void (0) : __assert_fail ("pContact && \"SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash.\""
, "/home/maarten/src/libreoffice/core/sw/source/core/draw/dview.cxx"
, 394, __extension__ __PRETTY_FUNCTION__))
;
395 pContact->GetAnchoredObjs( aAnchoredObjs );
396 }
397 // move 'repeated' ones to the same order number as the already moved one.
398 const size_t nTmpNewPos = pChildObj->GetOrdNum();
399 while ( !aAnchoredObjs.empty() )
400 {
401 SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
402 if ( pAnchoredObj->GetDrawObj() != pChildObj )
403 {
404 pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
405 nTmpNewPos );
406 pDrawPage->RecalcObjOrdNums();
407 // adjustments for accessibility API
408 if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
409 {
410 const SwFlyFrame *pTmpFlyFrame = static_cast<SwFlyFrame*>(pAnchoredObj);
411 m_rImp.DisposeAccessibleFrame( pTmpFlyFrame );
412 m_rImp.AddAccessibleFrame( pTmpFlyFrame );
413 }
414 else
415 {
416 m_rImp.DisposeAccessibleObj(pAnchoredObj->GetDrawObj(), true);
417 m_rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
418 }
419 }
420 aAnchoredObjs.pop_back();
421 }
422 }
423}
424
425// --> adjustment and re-factoring of method
426void SwDrawView::ObjOrderChanged( SdrObject* pObj, size_t nOldPos,
427 size_t nNewPos )
428{
429 // nothing to do for group members
430 if ( pObj->getParentSdrObjectFromSdrObject() )
431 {
432 return;
433 }
434
435 // determine drawing page and assure that the order numbers are correct.
436 SdrPage* pDrawPage = GetModel()->GetPage( 0 );
437 if ( pDrawPage->IsObjOrdNumsDirty() )
438 pDrawPage->RecalcObjOrdNums();
439 const size_t nObjCount = pDrawPage->GetObjCount();
440
441 SwAnchoredObject* pMovedAnchoredObj =
442 ::GetUserCall( pObj )->GetAnchoredObj( pObj );
443 const SwFlyFrame* pParentAnchoredObj =
444 pMovedAnchoredObj->GetAnchorFrame()->FindFlyFrame();
445
446 const bool bMovedForward = nOldPos < nNewPos;
447
448 // assure for a 'child' object, that it doesn't exceed the limits of its 'parent'
449 if ( pParentAnchoredObj )
450 {
451 if ( bMovedForward )
452 {
453 const size_t nMaxChildOrdNumWithoutMoved =
454 GetMaxChildOrdNum( *pParentAnchoredObj, pMovedAnchoredObj->GetDrawObj() );
455 if ( nNewPos > nMaxChildOrdNumWithoutMoved+1 )
456 {
457 // set position to the top of the 'child' object group
458 pDrawPage->SetObjectOrdNum( nNewPos, nMaxChildOrdNumWithoutMoved+1 );
459 nNewPos = nMaxChildOrdNumWithoutMoved+1;
460 }
461 }
462 else
463 {
464 const size_t nParentOrdNum = pParentAnchoredObj->GetDrawObj()->GetOrdNum();
465 if ( nNewPos < nParentOrdNum )
466 {
467 // set position to the bottom of the 'child' object group
468 pDrawPage->SetObjectOrdNum( nNewPos, nParentOrdNum );
469 nNewPos = nParentOrdNum;
470 }
471 }
472 if ( pDrawPage->IsObjOrdNumsDirty() )
473 pDrawPage->RecalcObjOrdNums();
474 }
475
476 // Assure, that object isn't positioned between 'repeated' ones
477 if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
478 ( !bMovedForward && nNewPos > 0 ) )
479 {
480 const SdrObject* pTmpObj =
481 pDrawPage->GetObj( bMovedForward ? nNewPos - 1 : nNewPos + 1 );
482 if ( pTmpObj )
483 {
484 size_t nTmpNewPos( nNewPos );
485 if ( bMovedForward )
486 {
487 // move before the top 'repeated' object
488 const sal_uInt32 nTmpMaxOrdNum =
489 ::GetUserCall( pTmpObj )->GetMaxOrdNum();
490 if ( nTmpMaxOrdNum > nNewPos )
491 nTmpNewPos = nTmpMaxOrdNum;
492 }
493 else
494 {
495 // move behind the bottom 'repeated' object
496 const sal_uInt32 nTmpMinOrdNum =
497 ::GetUserCall( pTmpObj )->GetMinOrdNum();
498 if ( nTmpMinOrdNum < nNewPos )
499 nTmpNewPos = nTmpMinOrdNum;
500 }
501 if ( nTmpNewPos != nNewPos )
502 {
503 pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
504 nNewPos = nTmpNewPos;
505 pDrawPage->RecalcObjOrdNums();
506 }
507 }
508 }
509
510 // On move forward, assure that object is moved before its own children.
511 // Only Writer fly frames can have children.
512 if ( dynamic_cast< const SwFlyFrame *>( pMovedAnchoredObj ) != nullptr &&
513 bMovedForward && nNewPos < nObjCount - 1 )
514 {
515 sal_uInt32 nMaxChildOrdNum =
516 GetMaxChildOrdNum( *static_cast<const SwFlyFrame*>(pMovedAnchoredObj) );
517 if ( nNewPos < nMaxChildOrdNum )
518 {
519 // determine position before the object before its top 'child' object
520 const SdrObject* pTmpObj = pDrawPage->GetObj( nMaxChildOrdNum );
521 size_t nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum() + 1;
522 if ( nTmpNewPos >= nObjCount )
523 {
524 --nTmpNewPos;
525 }
526 // assure, that determined position isn't between 'repeated' objects
527 pTmpObj = pDrawPage->GetObj( nTmpNewPos );
528 nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
529 // apply new position
530 pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
531 nNewPos = nTmpNewPos;
532 pDrawPage->RecalcObjOrdNums();
533 }
534 }
535
536 // Assure, that object isn't positioned between nested objects
537 if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
538 ( !bMovedForward && nNewPos > 0 ) )
539 {
540 size_t nTmpNewPos( nNewPos );
541 const SwFrameFormat* pParentFrameFormat =
542 pParentAnchoredObj ? &(pParentAnchoredObj->GetFrameFormat()) : nullptr;
543 const SdrObject* pTmpObj = pDrawPage->GetObj( nNewPos + 1 );
544 while ( pTmpObj )
545 {
546 // #i38563# - assure, that anchor frame exists.
547 // If object is anchored inside an invisible part of the document
548 // (e.g. page header, whose page style isn't applied, or hidden
549 // section), no anchor frame exists.
550 const SwFrame* pTmpAnchorFrame = lcl_FindAnchor( pTmpObj, true );
551 const SwFlyFrame* pTmpParentObj = pTmpAnchorFrame
552 ? pTmpAnchorFrame->FindFlyFrame() : nullptr;
553 if ( pTmpParentObj &&
554 &(pTmpParentObj->GetFrameFormat()) != pParentFrameFormat )
555 {
556 if ( bMovedForward )
557 {
558 nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
559 pTmpObj = pDrawPage->GetObj( nTmpNewPos + 1 );
560 }
561 else
562 {
563 nTmpNewPos = ::GetUserCall( pTmpParentObj->GetDrawObj() )
564 ->GetMinOrdNum();
565 pTmpObj = pTmpParentObj->GetDrawObj();
566 }
567 }
568 else
569 break;
570 }
571 if ( nTmpNewPos != nNewPos )
572 {
573 pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
574 nNewPos = nTmpNewPos;
575 pDrawPage->RecalcObjOrdNums();
576 }
577 }
578
579 // setup collection of moved 'child' objects to move its 'repeated' objects.
580 std::vector< SdrObject* > aMovedChildObjs;
581
582 // move 'children' accordingly
583 if ( dynamic_cast< const SwFlyFrame *>( pMovedAnchoredObj ) != nullptr )
584 {
585 const SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pMovedAnchoredObj);
586
587 // adjustments for accessibility API
588 m_rImp.DisposeAccessibleFrame( pFlyFrame );
589 m_rImp.AddAccessibleFrame( pFlyFrame );
590
591 const sal_uInt32 nChildNewPos = bMovedForward ? nNewPos : nNewPos+1;
592 size_t i = bMovedForward ? nOldPos : nObjCount-1;
593 do
594 {
595 SdrObject* pTmpObj = pDrawPage->GetObj( i );
596 if ( pTmpObj == pObj )
597 break;
598
599 // #i38563# - assure, that anchor frame exists.
600 // If object is anchored inside an invisible part of the document
601 // (e.g. page header, whose page style isn't applied, or hidden
602 // section), no anchor frame exists.
603 const SwFrame* pTmpAnchorFrame = lcl_FindAnchor( pTmpObj, true );
604 const SwFlyFrame* pTmpParentObj = pTmpAnchorFrame
605 ? pTmpAnchorFrame->FindFlyFrame() : nullptr;
606 if ( pTmpParentObj &&
607 ( ( pTmpParentObj == pFlyFrame ) ||
608 ( pFlyFrame->IsUpperOf( *pTmpParentObj ) ) ) )
609 {
610 // move child object.,
611 pDrawPage->SetObjectOrdNum( i, nChildNewPos );
612 pDrawPage->RecalcObjOrdNums();
613 // collect 'child' object
614 aMovedChildObjs.push_back( pTmpObj );
615 // adjustments for accessibility API
616 if ( dynamic_cast< const SwVirtFlyDrawObj *>( pTmpObj ) != nullptr )
617 {
618 const SwFlyFrame *pTmpFlyFrame =
619 static_cast<SwVirtFlyDrawObj*>(pTmpObj)->GetFlyFrame();
620 m_rImp.DisposeAccessibleFrame( pTmpFlyFrame );
621 m_rImp.AddAccessibleFrame( pTmpFlyFrame );
622 }
623 else
624 {
625 m_rImp.DisposeAccessibleObj(pTmpObj, true);
626 m_rImp.AddAccessibleObj( pTmpObj );
627 }
628 }
629 else
630 {
631 // adjust loop counter
632 if ( bMovedForward )
633 ++i;
634 else if (i > 0)
635 --i;
636 }
637
638 } while ( ( bMovedForward && i < ( nObjCount - aMovedChildObjs.size() ) ) ||
639 ( !bMovedForward && i > ( nNewPos + aMovedChildObjs.size() ) ) );
640 }
641 else
642 {
643 // adjustments for accessibility API
644 m_rImp.DisposeAccessibleObj(pObj, true);
645 m_rImp.AddAccessibleObj( pObj );
646 }
647
648 MoveRepeatedObjs( *pMovedAnchoredObj, aMovedChildObjs );
649}
650
651bool SwDrawView::TakeDragLimit( SdrDragMode eMode,
652 tools::Rectangle& rRect ) const
653{
654 const SdrMarkList &rMrkList = GetMarkedObjectList();
655 bool bRet = false;
656 if( 1 == rMrkList.GetMarkCount() )
657 {
658 const SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
659 SwRect aRect;
660 if( ::CalcClipRect( pObj, aRect, eMode == SdrDragMode::Move ) )
661 {
662 rRect = aRect.SVRect();
663 bRet = true;
664 }
665 }
666 return bRet;
667}
668
669const SwFrame* SwDrawView::CalcAnchor()
670{
671 const SdrMarkList &rMrkList = GetMarkedObjectList();
672 if ( rMrkList.GetMarkCount() != 1 )
5
Assuming the condition is false
6
Taking false branch
673 return nullptr;
674
675 SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
7
'pObj' initialized here
676
677 //Search for paragraph bound objects, otherwise only the
678 //current anchor. Search only if we currently drag.
679 const SwFrame* pAnch;
680 tools::Rectangle aMyRect;
681 const bool bFly = dynamic_cast< const SwVirtFlyDrawObj *>( pObj ) != nullptr;
8
Assuming pointer value is null
682 if ( bFly
8.1
'bFly' is false
)
9
Taking false branch
683 {
684 pAnch = static_cast<SwVirtFlyDrawObj*>(pObj)->GetFlyFrame()->GetAnchorFrame();
685 aMyRect = static_cast<SwVirtFlyDrawObj*>(pObj)->GetFlyFrame()->getFrameArea().SVRect();
686 }
687 else
688 {
689 SwDrawContact *pC = static_cast<SwDrawContact*>(GetUserCall(pObj));
690 // determine correct anchor position for 'virtual' drawing objects.
691 // #i26791#
692 pAnch = pC->GetAnchorFrame( pObj );
693 if( !pAnch )
10
Assuming 'pAnch' is non-null
11
Taking false branch
694 {
695 pC->ConnectToLayout();
696 // determine correct anchor position for 'virtual' drawing objects.
697 // #i26791#
698 pAnch = pC->GetAnchorFrame( pObj );
699 }
700 aMyRect = pObj->GetSnapRect();
12
Called C++ object pointer is null
701 }
702
703 const bool bTopRight = pAnch && ( ( pAnch->IsVertical() &&
704 !pAnch->IsVertLR() ) ||
705 pAnch->IsRightToLeft() );
706 const Point aMyPt = bTopRight ? aMyRect.TopRight() : aMyRect.TopLeft();
707
708 Point aPt;
709 if ( IsAction() )
710 {
711 if ( !TakeDragObjAnchorPos( aPt, bTopRight ) )
712 return nullptr;
713 }
714 else
715 {
716 tools::Rectangle aRect = pObj->GetSnapRect();
717 aPt = bTopRight ? aRect.TopRight() : aRect.TopLeft();
718 }
719
720 if ( aPt != aMyPt )
721 {
722 if ( pAnch && pAnch->IsContentFrame() )
723 {
724 // allow drawing objects in header/footer,
725 // but exclude control objects.
726 bool bBodyOnly = CheckControlLayer( pObj );
727 pAnch = ::FindAnchor( static_cast<const SwContentFrame*>(pAnch), aPt, bBodyOnly );
728 }
729 else if ( !bFly )
730 {
731 const SwRect aRect( aPt.getX(), aPt.getY(), 1, 1 );
732
733 SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
734 if ( pContact->GetAnchorFrame( pObj ) &&
735 pContact->GetAnchorFrame( pObj )->IsPageFrame() )
736 pAnch = pContact->GetPageFrame();
737 else
738 pAnch = pContact->FindPage( aRect );
739 }
740 }
741 if( pAnch && !pAnch->IsProtected() )
742 m_aAnchorPoint = pAnch->GetFrameAnchorPos( ::HasWrap( pObj ) );
743 else
744 pAnch = nullptr;
745 return pAnch;
746}
747
748void SwDrawView::ShowDragAnchor()
749{
750 SdrHdl* pHdl = maHdlList.GetHdl(SdrHdlKind::Anchor);
751 if ( ! pHdl )
1
Assuming 'pHdl' is non-null
2
Taking false branch
752 pHdl = maHdlList.GetHdl(SdrHdlKind::Anchor_TR);
753
754 if(pHdl
2.1
'pHdl' is non-null
)
3
Taking true branch
755 {
756 CalcAnchor();
4
Calling 'SwDrawView::CalcAnchor'
757 pHdl->SetPos(m_aAnchorPoint);
758 }
759}
760
761void SwDrawView::MarkListHasChanged()
762{
763 Imp().GetShell()->DrawSelChanged();
764 FmFormView::MarkListHasChanged();
765}
766
767// #i7672#
768void SwDrawView::ModelHasChanged()
769{
770 // The ModelHasChanged() call in DrawingLayer also updates
771 // an eventually active text edit view (OutlinerView). This also leads
772 // to newly setting the background color for that edit view. Thus,
773 // this method rescues the current background color if an OutlinerView
774 // exists and re-establishes it then. To be more safe, the OutlinerView
775 // will be fetched again (maybe textedit has ended).
776 OutlinerView* pView = GetTextEditOutlinerView();
777 Color aBackColor;
778 bool bColorWasSaved(false);
779
780 if(pView)
781 {
782 aBackColor = pView->GetBackgroundColor();
783 bColorWasSaved = true;
784 }
785
786 // call parent
787 FmFormView::ModelHasChanged();
788
789 if(bColorWasSaved)
790 {
791 pView = GetTextEditOutlinerView();
792
793 if(pView)
794 {
795 pView->SetBackgroundColor(aBackColor);
796 }
797 }
798}
799
800void SwDrawView::MakeVisible( const tools::Rectangle &rRect, vcl::Window & )
801{
802 OSL_ENSURE( m_rImp.GetShell()->GetWin(), "MakeVisible, unknown Window")do { if (true && (!(m_rImp.GetShell()->GetWin())))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/draw/dview.cxx"
":" "802" ": "), "%s", "MakeVisible, unknown Window"); } } while
(false)
;
803 m_rImp.GetShell()->MakeVisible( SwRect( rRect ) );
804}
805
806void SwDrawView::CheckPossibilities()
807{
808 FmFormView::CheckPossibilities();
809
810 //In addition to the existing flags of the objects themselves,
811 //which are evaluated by the DrawingEngine, other circumstances
812 //lead to a protection.
813 //Objects that are anchored in frames need to be protected
814 //if the content of the frame is protected.
815 //OLE-Objects may themselves wish a resize protection (StarMath)
816
817 const SdrMarkList &rMrkList = GetMarkedObjectList();
818 bool bProtect = false;
819 bool bSzProtect = false;
820 bool bRotate(false);
821
822 for ( size_t i = 0; !bProtect && i < rMrkList.GetMarkCount(); ++i )
823 {
824 const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
825 const SwFrame *pFrame = nullptr;
826 if ( auto pVirtFlyDrawObj = dynamic_cast< const SwVirtFlyDrawObj *>( pObj ) )
827 {
828 const SwFlyFrame *pFly = pVirtFlyDrawObj->GetFlyFrame();
829 if ( pFly )
830 {
831 pFrame = pFly->GetAnchorFrame();
832 if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
833 {
834 const SwNoTextFrame *const pNTF(static_cast<const SwNoTextFrame*>(pFly->Lower()));
835 const SwOLENode *const pOLENd = pNTF->GetNode()->GetOLENode();
836 const SwGrfNode *const pGrfNd = pNTF->GetNode()->GetGrfNode();
837
838 if ( pOLENd )
839 {
840 const uno::Reference < embed::XEmbeddedObject > xObj = const_cast< SwOLEObj& >(pOLENd->GetOLEObj()).GetOleRef();
841
842 if ( xObj.is() )
843 {
844 // --> improvement for the future, when more
845 // than one Writer fly frame can be selected.
846
847 // TODO/LATER: retrieve Aspect - from where?!
848 bSzProtect |= ( embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ) ) != 0;
849
850 // #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated
851 SwDoc* pDoc = Imp().GetShell()->GetDoc();
852 const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
853 && RndStdIds::FLY_AS_CHAR == pFly->GetFormat()->GetAnchor().GetAnchorId()
854 && pDoc->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT );
855 if (bProtectMathPos)
856 m_bMoveProtect = true;
857 }
858 }
859 else if(pGrfNd)
860 {
861 // RotGrfFlyFrame: GraphicNode allows rotation(s). The loop ew are in stops
862 // as soon as bMoveProtect is set, but since rotation is valid only with
863 // a single object selected this makes no difference
864 bRotate = true;
865 }
866 }
867 }
868 }
869 else
870 {
871 SwDrawContact *pC = static_cast<SwDrawContact*>(GetUserCall(pObj));
872 if ( pC )
873 pFrame = pC->GetAnchorFrame( pObj );
874 }
875 if ( pFrame )
876 bProtect = pFrame->IsProtected(); //Frames, areas etc.
877 {
878 SwFrameFormat* pFrameFormat( ::FindFrameFormat( const_cast<SdrObject*>(pObj) ) );
879 if ( !pFrameFormat )
880 {
881 OSL_FAIL( "<SwDrawView::CheckPossibilities()> - missing frame format" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/draw/dview.cxx"
":" "881" ": "), "%s", "<SwDrawView::CheckPossibilities()> - missing frame format"
); } } while (false)
;
882 bProtect = true;
883 }
884 else if ((RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId()) &&
885 rMrkList.GetMarkCount() > 1 )
886 {
887 bProtect = true;
888 }
889 }
890 }
891 m_bMoveProtect |= bProtect;
892 m_bResizeProtect |= bProtect || bSzProtect;
893
894 // RotGrfFlyFrame: allow rotation when SwGrfNode is selected and not size protected
895 m_bRotateFreeAllowed |= bRotate && !bProtect;
896 m_bRotate90Allowed |= m_bRotateFreeAllowed;
897}
898
899/// replace marked <SwDrawVirtObj>-objects by its reference object for delete marked objects.
900void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView& _rMarkView )
901{
902 SdrPageView* pDrawPageView = _rMarkView.GetSdrPageView();
903 const SdrMarkList& rMarkList = _rMarkView.GetMarkedObjectList();
904
905 if( !rMarkList.GetMarkCount() )
906 return;
907
908 // collect marked objects in a local data structure
909 std::vector<SdrObject*> aMarkedObjs;
910 for( size_t i = 0; i < rMarkList.GetMarkCount(); ++i )
911 {
912 SdrObject* pMarkedObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
913 aMarkedObjs.push_back( pMarkedObj );
914 }
915 // unmark all objects
916 _rMarkView.UnmarkAllObj();
917 // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its
918 // reference object.
919 while ( !aMarkedObjs.empty() )
920 {
921 SdrObject* pMarkObj = aMarkedObjs.back();
922 if ( dynamic_cast< const SwDrawVirtObj *>( pMarkObj ) != nullptr )
923 {
924 SdrObject* pRefObj = &(static_cast<SwDrawVirtObj*>(pMarkObj)->ReferencedObj());
925 if ( !_rMarkView.IsObjMarked( pRefObj ) )
926 {
927 _rMarkView.MarkObj( pRefObj, pDrawPageView );
928 }
929 }
930 else
931 {
932 _rMarkView.MarkObj( pMarkObj, pDrawPageView );
933 }
934
935 aMarkedObjs.pop_back();
936 }
937 // sort marked list in order to assure consistent state in drawing layer
938 _rMarkView.SortMarkedObjects();
939}
940
941SfxViewShell* SwDrawView::GetSfxViewShell() const
942{
943 return m_rImp.GetShell()->GetSfxViewShell();
944}
945
946void SwDrawView::DeleteMarked()
947{
948 SwDoc* pDoc = Imp().GetShell()->GetDoc();
949 SwRootFrame *pTmpRoot = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
950 if ( pTmpRoot )
951 pTmpRoot->StartAllAction();
952 pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
953 // replace marked <SwDrawVirtObj>-objects by its reference objects.
954 if (SdrPageView* pDrawPageView = m_rImp.GetPageView())
955 {
956 ReplaceMarkedDrawVirtObjs(pDrawPageView->GetView());
957 }
958
959 // Check what textboxes have to be deleted afterwards.
960 const SdrMarkList& rMarkList = GetMarkedObjectList();
961 std::vector<SwFrameFormat*> aTextBoxesToDelete;
962 for (size_t i = 0; i < rMarkList.GetMarkCount(); ++i)
963 {
964 SdrObject *pObject = rMarkList.GetMark(i)->GetMarkedSdrObj();
965 SwContact* pContact = GetUserCall(pObject);
966 SwFrameFormat* pFormat = pContact->GetFormat();
967 if (SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT))
968 aTextBoxesToDelete.push_back(pTextBox);
969 }
970
971 if ( pDoc->DeleteSelection( *this ) )
972 {
973 FmFormView::DeleteMarked();
974 ::FrameNotify( Imp().GetShell(), FLY_DRAG_END );
975 }
976
977 // Only delete these now: earlier deletion would clear the mark list as well.
978 // Delete in reverse order, assuming that the container is sorted by anchor positions.
979 for (int i = aTextBoxesToDelete.size() - 1; i >= 0; --i)
980 {
981 SwFrameFormat*& rpTextBox = aTextBoxesToDelete[i];
982 pDoc->getIDocumentLayoutAccess().DelLayoutFormat(rpTextBox);
983 }
984
985 pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
986 if( pTmpRoot )
987 pTmpRoot->EndAllAction();
988}
989
990// support enhanced text edit for draw objects
991SdrUndoManager* SwDrawView::getSdrUndoManagerForEnhancedTextEdit() const
992{
993 SwDoc* pDoc = Imp().GetShell()->GetDoc();
994
995 return pDoc ? dynamic_cast< SdrUndoManager* >(&(pDoc->GetUndoManager())) : nullptr;
996}
997
998/* vim:set shiftwidth=4 softtabstop=4 expandtab: */