Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx
Warning:line 3498, column 16
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 frmtool.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/layout/frmtool.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 <svx/svdpage.hxx>
21#include <editeng/brushitem.hxx>
22#include <editeng/shaditem.hxx>
23#include <editeng/ulspitem.hxx>
24#include <editeng/boxitem.hxx>
25#include <editeng/lspcitem.hxx>
26#include <editeng/fhgtitem.hxx>
27#include <sal/log.hxx>
28
29#include <drawdoc.hxx>
30#include <fmtornt.hxx>
31#include <fmthdft.hxx>
32#include <fmtfsize.hxx>
33#include <fmtsrnd.hxx>
34#include <docary.hxx>
35#include <lineinfo.hxx>
36#include <swmodule.hxx>
37#include <pagefrm.hxx>
38#include <colfrm.hxx>
39#include <fesh.hxx>
40#include <viewimp.hxx>
41#include <viewopt.hxx>
42#include <dflyobj.hxx>
43#include <dcontact.hxx>
44#include <frmatr.hxx>
45#include <frmtool.hxx>
46#include <tabfrm.hxx>
47#include <rowfrm.hxx>
48#include <ftnfrm.hxx>
49#include <txtfrm.hxx>
50#include <notxtfrm.hxx>
51#include <flyfrms.hxx>
52#include <layact.hxx>
53#include <pagedesc.hxx>
54#include <section.hxx>
55#include <sectfrm.hxx>
56#include <node2lay.hxx>
57#include <ndole.hxx>
58#include <hints.hxx>
59#include "layhelp.hxx"
60#include <laycache.hxx>
61#include <rootfrm.hxx>
62#include <paratr.hxx>
63#include <redline.hxx>
64#include <sortedobjs.hxx>
65#include <objectformatter.hxx>
66#include <calbck.hxx>
67#include <ndtxt.hxx>
68#include <undobj.hxx>
69#include <DocumentSettingManager.hxx>
70#include <IDocumentDrawModelAccess.hxx>
71#include <IDocumentTimerAccess.hxx>
72#include <IDocumentRedlineAccess.hxx>
73#include <IDocumentFieldsAccess.hxx>
74#include <IDocumentState.hxx>
75#include <frameformats.hxx>
76#include <boost/circular_buffer.hpp>
77#include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
78
79using namespace ::com::sun::star;
80
81bool bObjsDirect = true;
82bool bDontCreateObjects = false;
83bool bSetCompletePaintOnInvalidate = false;
84
85sal_uInt8 StackHack::nCnt = 0;
86bool StackHack::bLocked = false;
87
88SwFrameNotify::SwFrameNotify( SwFrame *pF ) :
89 mpFrame( pF ),
90 maFrame( pF->getFrameArea() ),
91 maPrt( pF->getFramePrintArea() ),
92 mbInvaKeep( false ),
93 mbValidSize( pF->isFrameAreaSizeValid() )
94{
95 if ( pF->IsTextFrame() )
96 {
97 mnFlyAnchorOfst = static_cast<SwTextFrame*>(pF)->GetBaseOffsetForFly( true );
98 mnFlyAnchorOfstNoWrap = static_cast<SwTextFrame*>(pF)->GetBaseOffsetForFly( false );
99 }
100 else
101 {
102 mnFlyAnchorOfst = 0;
103 mnFlyAnchorOfstNoWrap = 0;
104 }
105
106 mbHadFollow = pF->IsContentFrame() && static_cast<SwContentFrame*>(pF)->GetFollow();
107}
108
109SwFrameNotify::~SwFrameNotify() COVERITY_NOEXCEPT_FALSE
110{
111 SwRectFnSet aRectFnSet(mpFrame);
112 const bool bAbsP = aRectFnSet.PosDiff(maFrame, mpFrame->getFrameArea());
113 const bool bChgWidth =
114 aRectFnSet.GetWidth(maFrame) != aRectFnSet.GetWidth(mpFrame->getFrameArea());
115 const bool bChgHeight =
116 aRectFnSet.GetHeight(maFrame)!=aRectFnSet.GetHeight(mpFrame->getFrameArea());
117 const bool bChgFlyBasePos = mpFrame->IsTextFrame() &&
118 ( ( mnFlyAnchorOfst != static_cast<SwTextFrame*>(mpFrame)->GetBaseOffsetForFly( true ) ) ||
119 ( mnFlyAnchorOfstNoWrap != static_cast<SwTextFrame*>(mpFrame)->GetBaseOffsetForFly( false ) ) );
120
121 if ( mpFrame->IsFlowFrame() && !mpFrame->IsInFootnote() )
122 {
123 SwFlowFrame *pFlow = SwFlowFrame::CastFlowFrame( mpFrame );
124
125 if ( !pFlow->IsFollow() )
126 {
127 if ( !mpFrame->GetIndPrev() )
128 {
129 if ( mbInvaKeep )
130 {
131 SwFrame *pPre = mpFrame->FindPrev();
132 if ( pPre && pPre->IsFlowFrame() )
133 {
134 // 1. pPre wants to keep with me:
135 bool bInvalidPrePos = SwFlowFrame::CastFlowFrame(pPre)->IsKeep(pPre->GetAttrSet()->GetKeep(), pPre->GetBreakItem())
136 && pPre->GetIndPrev();
137
138 // 2. pPre is a table and the last row wants to keep with me:
139 if ( !bInvalidPrePos && pPre->IsTabFrame() )
140 {
141 SwTabFrame* pPreTab = static_cast<SwTabFrame*>(pPre);
142 if ( pPreTab->GetFormat()->GetDoc()->GetDocumentSettingManager().get(DocumentSettingId::TABLE_ROW_KEEP) )
143 {
144 SwRowFrame* pLastRow = static_cast<SwRowFrame*>(pPreTab->GetLastLower());
145 if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
146 bInvalidPrePos = true;
147 }
148 }
149
150 if ( bInvalidPrePos )
151 pPre->InvalidatePos();
152 }
153 }
154 }
155 else if ( !pFlow->HasFollow() )
156 {
157 long nOldHeight = aRectFnSet.GetHeight(maFrame);
158 long nNewHeight = aRectFnSet.GetHeight(mpFrame->getFrameArea());
159 if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) )
160 pFlow->CheckKeep();
161 }
162 }
163 }
164
165 if ( bAbsP )
166 {
167 mpFrame->SetCompletePaint();
168
169 SwFrame* pNxt = mpFrame->GetIndNext();
170 // #121888# - skip empty section frames
171 while ( pNxt &&
172 pNxt->IsSctFrame() && !static_cast<SwSectionFrame*>(pNxt)->GetSection() )
173 {
174 pNxt = pNxt->GetIndNext();
175 }
176
177 if ( pNxt )
178 pNxt->InvalidatePos();
179 else
180 {
181 // #104100# - correct condition for setting retouche
182 // flag for vertical layout.
183 if( mpFrame->IsRetoucheFrame() &&
184 aRectFnSet.TopDist( maFrame, aRectFnSet.GetTop(mpFrame->getFrameArea()) ) > 0 )
185 {
186 mpFrame->SetRetouche();
187 }
188
189 // A fresh follow frame does not have to be invalidated, because
190 // it is already formatted:
191 if ( mbHadFollow || !mpFrame->IsContentFrame() || !static_cast<SwContentFrame*>(mpFrame)->GetFollow() )
192 {
193 if ( !mpFrame->IsTabFrame() || !static_cast<SwTabFrame*>(mpFrame)->GetFollow() )
194 mpFrame->InvalidateNextPos();
195 }
196 }
197 }
198
199 //For each resize of the background graphics is a repaint necessary.
200 const bool bPrtWidth =
201 aRectFnSet.GetWidth(maPrt) != aRectFnSet.GetWidth(mpFrame->getFramePrintArea());
202 const bool bPrtHeight =
203 aRectFnSet.GetHeight(maPrt)!=aRectFnSet.GetHeight(mpFrame->getFramePrintArea());
204 if ( bPrtWidth || bPrtHeight )
205 {
206 bool bUseNewFillProperties(false);
207 if (mpFrame->supportsFullDrawingLayerFillAttributeSet())
208 {
209 drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(mpFrame->getSdrAllFillAttributesHelper());
210 if(aFillAttributes && aFillAttributes->isUsed())
211 {
212 bUseNewFillProperties = true;
213 // use SetCompletePaint if needed
214 if(aFillAttributes->needCompleteRepaint())
215 {
216 mpFrame->SetCompletePaint();
217 }
218 }
219 }
220 if (!bUseNewFillProperties)
221 {
222 const SvxGraphicPosition ePos = mpFrame->GetAttrSet()->GetBackground().GetGraphicPos();
223 if(GPOS_NONE != ePos && GPOS_TILED != ePos)
224 mpFrame->SetCompletePaint();
225 }
226 }
227 else
228 {
229 // #97597# - consider case that *only* margins between
230 // frame and printing area has changed. Then, frame has to be repainted,
231 // in order to force paint of the margin areas.
232 if ( !bAbsP && (bChgWidth || bChgHeight) )
233 {
234 mpFrame->SetCompletePaint();
235 }
236 }
237
238 const bool bPrtP = aRectFnSet.PosDiff( maPrt, mpFrame->getFramePrintArea() );
239 if ( bAbsP || bPrtP || bChgWidth || bChgHeight ||
240 bPrtWidth || bPrtHeight || bChgFlyBasePos )
241 {
242 if( mpFrame->IsAccessibleFrame() )
243 {
244 SwRootFrame *pRootFrame = mpFrame->getRootFrame();
245 if( pRootFrame && pRootFrame->IsAnyShellAccessible() &&
246 pRootFrame->GetCurrShell() )
247 {
248 pRootFrame->GetCurrShell()->Imp()->MoveAccessibleFrame( mpFrame, maFrame );
249 }
250 }
251
252 // Notification of anchored objects
253 if ( mpFrame->GetDrawObjs() )
254 {
255 const SwSortedObjs &rObjs = *mpFrame->GetDrawObjs();
256 SwPageFrame* pPageFrame = nullptr;
257 for (SwAnchoredObject* pObj : rObjs)
258 {
259 // OD 2004-03-31 #i26791# - no general distinction between
260 // Writer fly frames and drawing objects
261 bool bNotify = false;
262 bool bNotifySize = false;
263 SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() );
264 const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar();
265 if ( !bAnchoredAsChar )
266 {
267 // Notify object, which aren't anchored as-character:
268
269 // always notify objects, if frame position has changed
270 // or if the object is to-page|to-fly anchored.
271 if ( bAbsP ||
272 pContact->ObjAnchoredAtPage() ||
273 pContact->ObjAnchoredAtFly() )
274 {
275 bNotify = true;
276
277 // assure that to-fly anchored Writer fly frames are
278 // registered at the correct page frame, if frame
279 // position has changed.
280 if ( bAbsP && pContact->ObjAnchoredAtFly() &&
281 dynamic_cast<const SwFlyFrame*>( pObj) != nullptr )
282 {
283 // determine to-fly anchored Writer fly frame
284 SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj);
285 // determine page frame of to-fly anchored
286 // Writer fly frame
287 SwPageFrame* pFlyPageFrame = pFlyFrame->FindPageFrame();
288 // determine page frame, if needed.
289 if ( !pPageFrame )
290 {
291 pPageFrame = mpFrame->FindPageFrame();
292 }
293 if ( pPageFrame != pFlyPageFrame )
294 {
295 OSL_ENSURE( pFlyPageFrame, "~SwFrameNotify: Fly from Nowhere" )do { if (true && (!(pFlyPageFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "295" ": "), "%s", "~SwFrameNotify: Fly from Nowhere"); }
} while (false)
;
296 if( pFlyPageFrame )
297 pFlyPageFrame->MoveFly( pFlyFrame, pPageFrame );
298 else
299 pPageFrame->AppendFlyToPage( pFlyFrame );
300 }
301 }
302 }
303 // otherwise the objects are notified in dependence to
304 // its positioning and alignment
305 else
306 {
307 const SwFormatVertOrient& rVert =
308 pContact->GetFormat()->GetVertOrient();
309 if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
310 rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
311 rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
312 ( bChgHeight || bPrtHeight ) )
313 {
314 bNotify = true;
315 }
316 if ( !bNotify )
317 {
318 const SwFormatHoriOrient& rHori =
319 pContact->GetFormat()->GetHoriOrient();
320 if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
321 rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
322 rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
323 ( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
324 {
325 bNotify = true;
326 }
327 }
328 }
329 }
330 else if ( bPrtWidth )
331 {
332 // Notify as-character anchored objects, if printing area
333 // width has changed.
334 bNotify = true;
335 bNotifySize = true;
336 }
337
338 // perform notification via the corresponding invalidations
339 if ( bNotify )
340 {
341 if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr )
342 {
343 SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj);
344 if ( bNotifySize )
345 pFlyFrame->InvalidateSize_();
346 // #115759# - no invalidation of
347 // position for as-character anchored objects.
348 if ( !bAnchoredAsChar )
349 {
350 pFlyFrame->InvalidatePos_();
351 }
352 pFlyFrame->Invalidate_();
353 }
354 else if ( dynamic_cast<const SwAnchoredDrawObject*>( pObj) != nullptr )
355 {
356 // #115759# - no invalidation of
357 // position for as-character anchored objects.
358 if ( !bAnchoredAsChar )
359 {
360 pObj->InvalidateObjPos();
361 }
362 }
363 else
364 {
365 OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - unknown anchored object type." )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "365" ": "), "%s", "<SwContentNotify::~SwContentNotify()> - unknown anchored object type."
); } } while (false)
;
366 }
367 }
368 }
369 }
370 }
371 else if( mpFrame->IsTextFrame() && mbValidSize != mpFrame->isFrameAreaSizeValid() )
372 {
373 SwRootFrame *pRootFrame = mpFrame->getRootFrame();
374 if( pRootFrame && pRootFrame->IsAnyShellAccessible() &&
375 pRootFrame->GetCurrShell() )
376 {
377 pRootFrame->GetCurrShell()->Imp()->InvalidateAccessibleFrameContent( mpFrame );
378 }
379 }
380
381 // #i9046# Automatic frame width
382 SwFlyFrame* pFly = nullptr;
383 // #i35879# Do not trust the inf flags. pFrame does not
384 // necessarily have to have an upper!
385 if ( mpFrame->IsFlyFrame() || nullptr == ( pFly = mpFrame->ImplFindFlyFrame() ))
386 return;
387
388 // #i61999#
389 // no invalidation of columned Writer fly frames, because automatic
390 // width doesn't make sense for such Writer fly frames.
391 if ( !pFly->Lower() || pFly->Lower()->IsColumnFrame() )
392 return;
393
394 const SwFormatFrameSize &rFrameSz = pFly->GetFormat()->GetFrameSize();
395
396 // This could be optimized. Basically the fly frame only has to
397 // be invalidated, if the first line of pFrame (if pFrame is a content
398 // frame, for other frame types it's the print area) has changed its
399 // size and pFrame was responsible for the current width of pFly. On
400 // the other hand, this is only rarely used and re-calculation of
401 // the fly frame does not cause too much trouble. So we keep it this
402 // way:
403 if ( SwFrameSize::Fixed != rFrameSz.GetWidthSizeType() )
404 {
405 // #i50668#, #i50998# - invalidation of position
406 // of as-character anchored fly frames not needed and can cause
407 // layout loops
408 if ( dynamic_cast<const SwFlyInContentFrame*>( pFly) == nullptr )
409 {
410 pFly->InvalidatePos();
411 }
412 pFly->InvalidateSize();
413 }
414}
415
416SwLayNotify::SwLayNotify( SwLayoutFrame *pLayFrame ) :
417 SwFrameNotify( pLayFrame ),
418 m_bLowersComplete( false )
419{
420}
421
422// OD 2004-05-11 #i28701# - local method to invalidate the position of all
423// frames inclusive its floating screen objects, which are lowers of the given
424// layout frame
425static void lcl_InvalidatePosOfLowers( SwLayoutFrame& _rLayoutFrame )
426{
427 if( _rLayoutFrame.IsFlyFrame() && _rLayoutFrame.GetDrawObjs() )
428 {
429 _rLayoutFrame.InvalidateObjs( false );
430 }
431
432 SwFrame* pLowerFrame = _rLayoutFrame.Lower();
433 while ( pLowerFrame )
434 {
435 pLowerFrame->InvalidatePos();
436 if ( pLowerFrame->IsTextFrame() )
437 {
438 static_cast<SwTextFrame*>(pLowerFrame)->Prepare( PrepareHint::FramePositionChanged );
439 }
440 else if ( pLowerFrame->IsTabFrame() )
441 {
442 pLowerFrame->InvalidatePrt();
443 }
444
445 pLowerFrame->InvalidateObjs( false );
446
447 pLowerFrame = pLowerFrame->GetNext();
448 }
449}
450
451SwLayNotify::~SwLayNotify()
452{
453 SwLayoutFrame *pLay = static_cast<SwLayoutFrame*>(mpFrame);
454 SwRectFnSet aRectFnSet(pLay);
455 bool bNotify = false;
456 if ( pLay->getFramePrintArea().SSize() != maPrt.SSize() )
457 {
458 if ( !IsLowersComplete() )
459 {
460 bool bInvaPercent;
461
462 if ( pLay->IsRowFrame() )
463 {
464 bInvaPercent = true;
465 long nNew = aRectFnSet.GetHeight(pLay->getFramePrintArea());
466 if( nNew != aRectFnSet.GetHeight(maPrt) )
467 static_cast<SwRowFrame*>(pLay)->AdjustCells( nNew, true);
468 if( aRectFnSet.GetWidth(pLay->getFramePrintArea())
469 != aRectFnSet.GetWidth(maPrt) )
470 static_cast<SwRowFrame*>(pLay)->AdjustCells( 0, false );
471 }
472 else
473 {
474 //Proportional adoption of the internal.
475 //1. If the formatted is no Fly
476 //2. If he contains no columns
477 //3. If the Fly has a fixed height and the columns
478 // are next to be.
479 // Hoehe danebenliegen.
480 //4. Never at SectionFrames.
481 bool bLow;
482 if( pLay->IsFlyFrame() )
483 {
484 if ( pLay->Lower() )
485 {
486 bLow = !pLay->Lower()->IsColumnFrame() ||
487 aRectFnSet.GetHeight(pLay->Lower()->getFrameArea())
488 != aRectFnSet.GetHeight(pLay->getFramePrintArea());
489 }
490 else
491 bLow = false;
492 }
493 else if( pLay->IsSctFrame() )
494 {
495 if ( pLay->Lower() )
496 {
497 if( pLay->Lower()->IsColumnFrame() && pLay->Lower()->GetNext() )
498 bLow = pLay->Lower()->getFrameArea().Height() != pLay->getFramePrintArea().Height();
499 else
500 bLow = pLay->getFramePrintArea().Width() != maPrt.Width();
501 }
502 else
503 bLow = false;
504 }
505 else if( pLay->IsFooterFrame() && !pLay->HasFixSize() )
506 bLow = pLay->getFramePrintArea().Width() != maPrt.Width();
507 else
508 bLow = true;
509 bInvaPercent = bLow;
510 if ( bLow )
511 {
512 pLay->ChgLowersProp( maPrt.SSize() );
513 }
514 // If the PrtArea has been extended, it might be possible that the chain of parts
515 // can take another frame. As a result, the "possible right one" needs to be
516 // invalidated. This only pays off if this or its Uppers are moveable sections.
517 // A PrtArea has been extended if width or height are larger than before.
518 if ( (pLay->getFramePrintArea().Height() > maPrt.Height() ||
519 pLay->getFramePrintArea().Width() > maPrt.Width()) &&
520 (pLay->IsMoveable() || pLay->IsFlyFrame()) )
521 {
522 SwFrame *pTmpFrame = pLay->Lower();
523 if ( pTmpFrame && pTmpFrame->IsFlowFrame() )
524 {
525 while ( pTmpFrame->GetNext() )
526 pTmpFrame = pTmpFrame->GetNext();
527 pTmpFrame->InvalidateNextPos();
528 }
529 }
530 }
531 bNotify = true;
532 //EXPENSIVE!! But how we do it more elegant?
533 if( bInvaPercent )
534 pLay->InvaPercentLowers( pLay->getFramePrintArea().Height() - maPrt.Height() );
535 }
536 if ( pLay->IsTabFrame() )
537 //So that _only_ the shadow is drawn while resizing.
538 static_cast<SwTabFrame*>(pLay)->SetComplete();
539 else
540 {
541 const SwViewShell *pSh = pLay->getRootFrame()->GetCurrShell();
542 if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ||
543 !(pLay->GetType() & (SwFrameType::Body | SwFrameType::Page)) )
544 //Thereby the subordinates are retouched clean.
545 //Example problem: Take the Flys with the handles and downsize.
546 //Not for body and page, otherwise it flickers when loading HTML.
547 pLay->SetCompletePaint();
548 }
549 }
550 //Notify Lower if the position has changed.
551 const bool bPrtPos = aRectFnSet.PosDiff( maPrt, pLay->getFramePrintArea() );
552 const bool bPos = bPrtPos || aRectFnSet.PosDiff( maFrame, pLay->getFrameArea() );
553 const bool bSize = pLay->getFrameArea().SSize() != maFrame.SSize();
554
555 if ( bPos && pLay->Lower() && !IsLowersComplete() )
556 {
557 pLay->Lower()->InvalidatePos();
558 SwFootnoteFrame* pFtnFrame = pLay->Lower()->IsFootnoteFrame() ?
559 static_cast<SwFootnoteFrame*>(pLay->Lower()) : nullptr;
560 SwFrame* pFtnLower = pFtnFrame ? pFtnFrame->Lower() : nullptr;
561 if (pFtnLower)
562 pFtnLower->InvalidatePos();
563 }
564
565 if ( bPrtPos )
566 pLay->SetCompletePaint();
567
568 //Inform the Follower if the SSize has changed.
569 if ( bSize )
570 {
571 if( pLay->GetNext() )
572 {
573 if ( pLay->GetNext()->IsLayoutFrame() )
574 pLay->GetNext()->InvalidatePos_();
575 else
576 pLay->GetNext()->InvalidatePos();
577 }
578 else if( pLay->IsSctFrame() )
579 pLay->InvalidateNextPos();
580 }
581 if ( !IsLowersComplete() &&
582 !(pLay->GetType()&(SwFrameType::Fly|SwFrameType::Section) &&
583 pLay->Lower() && pLay->Lower()->IsColumnFrame()) &&
584 (bPos || bNotify) &&
585 !(pLay->GetType() & (SwFrameType::Row|SwFrameType::Tab|SwFrameType::FtnCont|SwFrameType::Page|SwFrameType::Root)))
586 {
587 // #i44016# - force unlock of position of lower objects.
588 // #i43913# - no unlock of position of objects,
589 // if <pLay> is a cell frame, and its table frame resp. its parent table
590 // frame is locked.
591 // #i47458# - force unlock of position of lower objects,
592 // only if position of layout frame has changed.
593 bool bUnlockPosOfObjs( bPos );
594 if ( bUnlockPosOfObjs && pLay->IsCellFrame() )
595 {
596 SwTabFrame* pTabFrame( pLay->FindTabFrame() );
597 if ( pTabFrame &&
598 ( pTabFrame->IsJoinLocked() ||
599 ( pTabFrame->IsFollow() &&
600 pTabFrame->FindMaster()->IsJoinLocked() ) ) )
601 {
602 bUnlockPosOfObjs = false;
603 }
604 }
605 // #i49383# - check for footnote frame, if unlock
606 // of position of lower objects is allowed.
607 else if ( bUnlockPosOfObjs && pLay->IsFootnoteFrame() )
608 {
609 bUnlockPosOfObjs = static_cast<SwFootnoteFrame*>(pLay)->IsUnlockPosOfLowerObjs();
610 }
611 // #i51303# - no unlock of object positions for sections
612 else if ( bUnlockPosOfObjs && pLay->IsSctFrame() )
613 {
614 bUnlockPosOfObjs = false;
615 }
616 pLay->NotifyLowerObjs( bUnlockPosOfObjs );
617 }
618 if ( bPos && pLay->IsFootnoteFrame() && pLay->Lower() )
619 {
620 // OD 2004-05-11 #i28701#
621 ::lcl_InvalidatePosOfLowers( *pLay );
622 }
623 if( ( bPos || bSize ) && pLay->IsFlyFrame() && static_cast<SwFlyFrame*>(pLay)->GetAnchorFrame()
624 && static_cast<SwFlyFrame*>(pLay)->GetAnchorFrame()->IsFlyFrame() )
625 static_cast<SwFlyFrame*>(pLay)->AnchorFrame()->InvalidateSize();
626}
627
628SwFlyNotify::SwFlyNotify( SwFlyFrame *pFlyFrame ) :
629 SwLayNotify( pFlyFrame ),
630 // #115759# - keep correct page frame - the page frame
631 // the Writer fly frame is currently registered at.
632 pOldPage( pFlyFrame->GetPageFrame() ),
633 aFrameAndSpace( pFlyFrame->GetObjRectWithSpaces() )
634{
635}
636
637SwFlyNotify::~SwFlyNotify()
638{
639 SwFlyFrame *pFly = static_cast<SwFlyFrame*>(mpFrame);
640 if ( pFly->IsNotifyBack() )
641 {
642 SwViewShell *pSh = pFly->getRootFrame()->GetCurrShell();
643 SwViewShellImp *pImp = pSh ? pSh->Imp() : nullptr;
644 if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
645 {
646 //If in the LayAction the IsAgain is set it can be
647 //that the old page is destroyed in the meantime!
648 ::Notify( pFly, pOldPage, aFrameAndSpace, &maPrt );
649 // #i35640# - additional notify anchor text frame,
650 // if Writer fly frame has changed its page
651 if ( pFly->GetAnchorFrame()->IsTextFrame() &&
652 pFly->GetPageFrame() != pOldPage )
653 {
654 pFly->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave );
655 }
656 }
657 pFly->ResetNotifyBack();
658 }
659
660 //Have the size or the position changed,
661 //so should the view know this.
662 SwRectFnSet aRectFnSet(pFly);
663 const bool bPosChgd = aRectFnSet.PosDiff( maFrame, pFly->getFrameArea() );
664 const bool bFrameChgd = pFly->getFrameArea().SSize() != maFrame.SSize();
665 const bool bPrtChgd = maPrt != pFly->getFramePrintArea();
666 if ( bPosChgd || bFrameChgd || bPrtChgd )
667 {
668 pFly->NotifyDrawObj();
669 }
670 if ( bPosChgd && maFrame.Pos().X() != FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) )
671 {
672 // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
673 // reason: New positioning and alignment (e.g. to-paragraph anchored,
674 // but aligned at page) are introduced.
675 // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
676 // floating screen objects by calling method <SwLayoutFrame::NotifyLowerObjs()>.
677
678 if ( pFly->IsFlyAtContentFrame() )
679 {
680 SwFrame *pNxt = pFly->AnchorFrame()->FindNext();
681 if ( pNxt )
682 {
683 pNxt->InvalidatePos();
684 }
685 }
686
687 // #i26945# - notify anchor.
688 // Needed for negative positioned Writer fly frames
689 if ( pFly->GetAnchorFrame()->IsTextFrame() )
690 {
691 pFly->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave );
692 }
693 }
694
695 // OD 2004-05-13 #i28701#
696 // #i45180# - no adjustment of layout process flags and
697 // further notifications/invalidations, if format is called by grow/shrink
698 if ( !(pFly->ConsiderObjWrapInfluenceOnObjPos() &&
699 ( dynamic_cast<const SwFlyFreeFrame*>( pFly) == nullptr ||
700 !static_cast<SwFlyFreeFrame*>(pFly)->IsNoMoveOnCheckClip() )) )
701 return;
702
703 // #i54138# - suppress restart of the layout process
704 // on changed frame height.
705 // Note: It doesn't seem to be necessary and can cause layout loops.
706 if ( bPosChgd )
707 {
708 // indicate a restart of the layout process
709 pFly->SetRestartLayoutProcess( true );
710 }
711 else
712 {
713 // lock position
714 pFly->LockPosition();
715 }
716
717 if ( pFly->ConsiderForTextWrap() )
718 return;
719
720 // indicate that object has to be considered for text wrap
721 pFly->SetConsiderForTextWrap( true );
722 // invalidate 'background' in order to allow its 'background'
723 // to wrap around it.
724 pFly->NotifyBackground( pFly->GetPageFrame(),
725 pFly->GetObjRectWithSpaces(),
726 PrepareHint::FlyFrameArrive );
727 // invalidate position of anchor frame in order to force
728 // a re-format of the anchor frame, which also causes a
729 // re-format of the invalid previous frames of the anchor frame.
730 pFly->AnchorFrame()->InvalidatePos();
731}
732
733SwContentNotify::SwContentNotify( SwContentFrame *pContentFrame ) :
734 SwFrameNotify( pContentFrame ),
735 // OD 08.01.2004 #i11859#
736 mbChkHeightOfLastLine( false ),
737 mnHeightOfLastLine( 0 ),
738 // OD 2004-02-26 #i25029#
739 mbInvalidatePrevPrtArea( false ),
740 mbBordersJoinedWithPrev( false )
741{
742 // OD 08.01.2004 #i11859#
743 if ( !pContentFrame->IsTextFrame() )
744 return;
745
746 SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pContentFrame);
747 if (!pTextFrame->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::OLD_LINE_SPACING))
748 {
749 const SvxLineSpacingItem &rSpace = pTextFrame->GetAttrSet()->GetLineSpacing();
750 if ( rSpace.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop )
751 {
752 mbChkHeightOfLastLine = true;
753 mnHeightOfLastLine = pTextFrame->GetHeightOfLastLine();
754 }
755 }
756}
757
758SwContentNotify::~SwContentNotify()
759{
760 SwContentFrame *pCnt = static_cast<SwContentFrame*>(mpFrame);
761 if ( bSetCompletePaintOnInvalidate )
762 pCnt->SetCompletePaint();
763
764 SwRectFnSet aRectFnSet(pCnt);
765 if ( pCnt->IsInTab() && ( aRectFnSet.PosDiff( pCnt->getFrameArea(), maFrame ) ||
766 pCnt->getFrameArea().SSize() != maFrame.SSize()))
767 {
768 SwLayoutFrame* pCell = pCnt->GetUpper();
769 while( !pCell->IsCellFrame() && pCell->GetUpper() )
770 pCell = pCell->GetUpper();
771 OSL_ENSURE( pCell->IsCellFrame(), "Where's my cell?" )do { if (true && (!(pCell->IsCellFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "771" ": "), "%s", "Where's my cell?"); } } while (false
)
;
772 if ( text::VertOrientation::NONE != pCell->GetFormat()->GetVertOrient().GetVertOrient() )
773 pCell->InvalidatePrt(); //for the vertical align.
774 }
775
776 // OD 2004-02-26 #i25029#
777 if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
778 pCnt->IsTextFrame() &&
779 !pCnt->IsFollow() && !pCnt->GetIndPrev() )
780 {
781 // determine previous frame
782 SwFrame* pPrevFrame = pCnt->FindPrev();
783 // skip empty section frames and hidden text frames
784 {
785 while ( pPrevFrame &&
786 ( ( pPrevFrame->IsSctFrame() &&
787 !static_cast<SwSectionFrame*>(pPrevFrame)->GetSection() ) ||
788 ( pPrevFrame->IsTextFrame() &&
789 static_cast<SwTextFrame*>(pPrevFrame)->IsHiddenNow() ) ) )
790 {
791 pPrevFrame = pPrevFrame->FindPrev();
792 }
793 }
794
795 // Invalidate printing area of found previous frame
796 if ( pPrevFrame )
797 {
798 if ( pPrevFrame->IsSctFrame() )
799 {
800 if ( pCnt->IsInSct() )
801 {
802 // Note: found previous frame is a section frame and
803 // <pCnt> is also inside a section.
804 // Thus due to <mbBordersJoinedWithPrev>,
805 // <pCnt> had joined its borders/shadow with the
806 // last content of the found section.
807 // Invalidate printing area of last content in found section.
808 SwFrame* pLstContentOfSctFrame =
809 static_cast<SwSectionFrame*>(pPrevFrame)->FindLastContent();
810 if ( pLstContentOfSctFrame )
811 {
812 pLstContentOfSctFrame->InvalidatePrt();
813 }
814 }
815 }
816 else
817 {
818 pPrevFrame->InvalidatePrt();
819 }
820 }
821 }
822
823 const bool bFirst = aRectFnSet.GetWidth(maFrame) == 0;
824
825 if ( pCnt->IsNoTextFrame() )
826 {
827 //Active PlugIn's or OLE-Objects should know something of the change
828 //thereby they move their window appropriate.
829 SwViewShell *pSh = pCnt->getRootFrame()->GetCurrShell();
830 if ( pSh )
831 {
832 SwOLENode *const pNd(static_cast<SwNoTextFrame*>(pCnt)->GetNode()->GetOLENode());
833 if (nullptr != pNd &&
834 (pNd->GetOLEObj().IsOleRef() ||
835 pNd->IsOLESizeInvalid()) )
836 {
837 const bool bNoTextFramePrtAreaChanged =
838 ( maPrt.SSize().Width() != 0 &&
839 maPrt.SSize().Height() != 0 ) &&
840 maPrt.SSize() != pCnt->getFramePrintArea().SSize();
841 OSL_ENSURE( pCnt->IsInFly(), "OLE not in FlyFrame" )do { if (true && (!(pCnt->IsInFly()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "841" ": "), "%s", "OLE not in FlyFrame"); } } while (false
)
;
842 SwFlyFrame *pFly = pCnt->FindFlyFrame();
843 svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
844 SwFEShell *pFESh = nullptr;
845 for(SwViewShell& rCurrentShell : pSh->GetRingContainer())
846 { if ( dynamic_cast<const SwCursorShell*>( &rCurrentShell) != nullptr )
847 {
848 pFESh = static_cast<SwFEShell*>(&rCurrentShell);
849 // #108369#: Here used to be the condition if (!bFirst).
850 // I think this should mean "do not call CalcAndSetScale"
851 // if the frame is formatted for the first time.
852 // Unfortunately this is not valid anymore since the
853 // SwNoTextFrame already gets a width during CalcLowerPreps.
854 // Nevertheless, the indention of !bFirst seemed to be
855 // to assure that the OLE objects have already been notified
856 // if necessary before calling CalcAndSetScale.
857 // So I replaced !bFirst by !IsOLESizeInvalid. There is
858 // one additional problem specific to the word import:
859 // The layout is calculated _before_ calling PrtOLENotify,
860 // and the OLE objects are not invalidated during import.
861 // Therefore I added the condition !IsUpdateExpField,
862 // have a look at the occurrence of CalcLayout in
863 // uiview/view.cxx.
864 if ( !pNd->IsOLESizeInvalid() &&
865 !pSh->GetDoc()->getIDocumentState().IsUpdateExpField() )
866 pFESh->CalcAndSetScale( xObj,
867 &pFly->getFramePrintArea(), &pFly->getFrameArea(),
868 bNoTextFramePrtAreaChanged );
869 }
870 }
871
872 if ( pFESh && pNd->IsOLESizeInvalid() )
873 {
874 pNd->SetOLESizeInvalid( false );
875 pFESh->CalcAndSetScale( xObj ); // create client
876 }
877 }
878 // ditto animated graphics
879 if ( getFrameArea().HasArea() && static_cast<SwNoTextFrame*>(pCnt)->HasAnimation() )
880 {
881 static_cast<SwNoTextFrame*>(pCnt)->StopAnimation();
882 pSh->InvalidateWindows( getFrameArea() );
883 }
884 }
885 }
886
887 if ( bFirst )
888 {
889 pCnt->SetRetouche(); //fix(13870)
890
891 SwDoc& rDoc = pCnt->IsTextFrame()
892 ? static_cast<SwTextFrame*>(pCnt)->GetDoc()
893 : static_cast<SwNoTextFrame*>(pCnt)->GetNode()->GetDoc();
894 if ( !rDoc.GetSpzFrameFormats()->empty() &&
895 rDoc.DoesContainAtPageObjWithContentAnchor() && !rDoc.getIDocumentState().IsNewDoc() )
896 {
897 // If certain import filters for foreign file format import
898 // AT_PAGE anchored objects, the corresponding page number is
899 // typically not known. In this case the content position is
900 // stored at which the anchored object is found in the
901 // imported document.
902 // When this content is formatted it is the time at which
903 // the page is known. Thus, this data can be corrected now.
904
905 const SwPageFrame *pPage = nullptr;
906 SwFrameFormats *pTable = rDoc.GetSpzFrameFormats();
907
908 for ( size_t i = 0; i < pTable->size(); ++i )
909 {
910 SwFrameFormat *pFormat = (*pTable)[i];
911 const SwFormatAnchor &rAnch = pFormat->GetAnchor();
912 if ( RndStdIds::FLY_AT_PAGE != rAnch.GetAnchorId() ||
913 rAnch.GetContentAnchor() == nullptr )
914 {
915 continue;
916 }
917
918 if (FrameContainsNode(*pCnt, rAnch.GetContentAnchor()->nNode.GetIndex()))
919 {
920 OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - to page anchored object with content position." )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "920" ": "), "%s", "<SwContentNotify::~SwContentNotify()> - to page anchored object with content position."
); } } while (false)
;
921 if ( !pPage )
922 {
923 pPage = pCnt->FindPageFrame();
924 }
925 SwFormatAnchor aAnch( rAnch );
926 aAnch.SetAnchor( nullptr );
927 aAnch.SetPageNum( pPage->GetPhyPageNum() );
928 pFormat->SetFormatAttr( aAnch );
929 if ( RES_DRAWFRMFMT != pFormat->Which() )
930 {
931 pFormat->MakeFrames();
932 }
933 }
934 }
935 }
936 }
937
938 // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
939 // if height of last line has changed.
940 if ( pCnt->IsTextFrame() && mbChkHeightOfLastLine )
941 {
942 if ( mnHeightOfLastLine != static_cast<SwTextFrame*>(pCnt)->GetHeightOfLastLine() )
943 {
944 pCnt->InvalidateNextPrtArea();
945 }
946 }
947
948 // #i44049#
949 if ( pCnt->IsTextFrame() && aRectFnSet.PosDiff( maFrame, pCnt->getFrameArea() ) )
950 {
951 pCnt->InvalidateObjs();
952 }
953
954 // #i43255# - move code to invalidate at-character
955 // anchored objects due to a change of its anchor character from
956 // method <SwTextFrame::Format(..)>.
957 if ( !pCnt->IsTextFrame() )
958 return;
959
960 SwTextFrame* pMasterFrame = pCnt->IsFollow()
961 ? static_cast<SwTextFrame*>(pCnt)->FindMaster()
962 : static_cast<SwTextFrame*>(pCnt);
963 if ( pMasterFrame && !pMasterFrame->IsFlyLock() &&
964 pMasterFrame->GetDrawObjs() )
965 {
966 SwSortedObjs* pObjs = pMasterFrame->GetDrawObjs();
967 for (SwAnchoredObject* pAnchoredObj : *pObjs)
968 {
969 if ( pAnchoredObj->GetFrameFormat().GetAnchor().GetAnchorId()
970 == RndStdIds::FLY_AT_CHAR )
971 {
972 pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrame->IsEmpty() );
973 }
974 }
975 }
976}
977
978// note this *cannot* be static because it's a friend
979void AppendObj(SwFrame *const pFrame, SwPageFrame *const pPage, SwFrameFormat *const pFormat, const SwFormatAnchor & rAnch)
980{
981 const bool bFlyAtFly = rAnch.GetAnchorId() == RndStdIds::FLY_AT_FLY; // LAYER_IMPL
982 //Is a frame or a SdrObject described?
983 const bool bSdrObj = RES_DRAWFRMFMT == pFormat->Which();
984 // OD 23.06.2003 #108784# - append also drawing objects anchored
985 // as character.
986 const bool bDrawObjInContent = bSdrObj &&
987 (rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR);
988
989 if( !(bFlyAtFly ||
990 (rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA) ||
991 (rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR) ||
992 bDrawObjInContent) )
993 return;
994
995 SdrObject* pSdrObj = nullptr;
996 if ( bSdrObj && nullptr == (pSdrObj = pFormat->FindSdrObject()) )
997 {
998 OSL_ENSURE( !bSdrObj, "DrawObject not found." )do { if (true && (!(!bSdrObj))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "998" ": "), "%s", "DrawObject not found."); } } while (
false)
;
999 pFormat->GetDoc()->DelFrameFormat( pFormat );
1000 return;
1001 }
1002 if ( pSdrObj )
1003 {
1004 if ( !pSdrObj->getSdrPageFromSdrObject() )
1005 {
1006 pFormat->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
1007 InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect());
1008 }
1009
1010 SwDrawContact* pNew =
1011 static_cast<SwDrawContact*>(GetUserCall( pSdrObj ));
1012 if ( !pNew->GetAnchorFrame() )
1013 {
1014 pFrame->AppendDrawObj( *(pNew->GetAnchoredObj( nullptr )) );
1015 }
1016 // OD 19.06.2003 #108784# - add 'virtual' drawing object,
1017 // if necessary. But control objects have to be excluded.
1018 else if ( !::CheckControlLayer( pSdrObj ) &&
1019 pNew->GetAnchorFrame() != pFrame &&
1020 !pNew->GetDrawObjectByAnchorFrame( *pFrame ) )
1021 {
1022 SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj();
1023 pFrame->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) );
1024
1025 pDrawVirtObj->ActionChanged();
1026 }
1027 }
1028 else
1029 {
1030 SwFlyFrame *pFly;
1031 if( bFlyAtFly )
1032 pFly = new SwFlyLayFrame( static_cast<SwFlyFrameFormat*>(pFormat), pFrame, pFrame );
1033 else
1034 pFly = new SwFlyAtContentFrame( static_cast<SwFlyFrameFormat*>(pFormat), pFrame, pFrame );
1035 pFly->Lock();
1036 pFrame->AppendFly( pFly );
1037 pFly->Unlock();
1038 if ( pPage )
1039 ::RegistFlys( pPage, pFly );
1040 }
1041}
1042
1043static bool IsShown(sal_uLong const nIndex,
1044 const SwFormatAnchor & rAnch,
1045 std::vector<sw::Extent>::const_iterator const*const pIter,
1046 std::vector<sw::Extent>::const_iterator const*const pEnd,
1047 SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode)
1048{
1049 assert(!pIter || *pIter == *pEnd || (*pIter)->pNode->GetIndex() == nIndex)(static_cast <bool> (!pIter || *pIter == *pEnd || (*pIter
)->pNode->GetIndex() == nIndex) ? void (0) : __assert_fail
("!pIter || *pIter == *pEnd || (*pIter)->pNode->GetIndex() == nIndex"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1049, __extension__ __PRETTY_FUNCTION__))
;
1050 SwPosition const& rAnchor(*rAnch.GetContentAnchor());
1051 if (rAnchor.nNode.GetIndex() != nIndex)
1052 {
1053 return false;
1054 }
1055 if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA)
1056 {
1057 return pIter == nullptr // not merged
1058 || pIter != pEnd // at least one char visible in node
1059 || !IsSelectFrameAnchoredAtPara(rAnchor,
1060 SwPosition(const_cast<SwTextNode&>(*pFirstNode), 0),
1061 SwPosition(const_cast<SwTextNode&>(*pLastNode), pLastNode->Len()));
1062 }
1063 if (pIter)
1064 {
1065 // note: frames are not sorted by anchor position.
1066 assert(pEnd)(static_cast <bool> (pEnd) ? void (0) : __assert_fail (
"pEnd", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1066, __extension__ __PRETTY_FUNCTION__))
;
1067 assert(pFirstNode)(static_cast <bool> (pFirstNode) ? void (0) : __assert_fail
("pFirstNode", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1067, __extension__ __PRETTY_FUNCTION__))
;
1068 assert(pLastNode)(static_cast <bool> (pLastNode) ? void (0) : __assert_fail
("pLastNode", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1068, __extension__ __PRETTY_FUNCTION__))
;
1069 assert(rAnch.GetAnchorId() != RndStdIds::FLY_AT_FLY)(static_cast <bool> (rAnch.GetAnchorId() != RndStdIds::
FLY_AT_FLY) ? void (0) : __assert_fail ("rAnch.GetAnchorId() != RndStdIds::FLY_AT_FLY"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1069, __extension__ __PRETTY_FUNCTION__))
;
1070 for (auto iter = *pIter; iter != *pEnd; ++iter)
1071 {
1072 assert(iter->nStart != iter->nEnd)(static_cast <bool> (iter->nStart != iter->nEnd) ?
void (0) : __assert_fail ("iter->nStart != iter->nEnd"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1072, __extension__ __PRETTY_FUNCTION__))
; // TODO possible?
1073 assert(iter->pNode->GetIndex() == nIndex)(static_cast <bool> (iter->pNode->GetIndex() == nIndex
) ? void (0) : __assert_fail ("iter->pNode->GetIndex() == nIndex"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1073, __extension__ __PRETTY_FUNCTION__))
;
1074 if (rAnchor.nContent.GetIndex() < iter->nStart)
1075 {
1076 return false;
1077 }
1078 if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
1079 {
1080 // if there is an extent then obviously the node was not
1081 // deleted fully...
1082 // show if start <= pos <= end
1083 // *or* if first-node/0 *and* not StartOfSection
1084 // *or* if last-node/Len *and* not EndOfSection
1085
1086 // first determine the extent to compare to, then
1087 // construct start/end positions for the deletion *before* the
1088 // extent and compare once.
1089 // the interesting corner cases are on the edge of the extent!
1090 // no need to check for > the last extent because those
1091 // are never visible.
1092 if (rAnchor.nContent.GetIndex() <= iter->nEnd)
1093 {
1094 if (iter->nStart == 0)
1095 {
1096 return true;
1097 }
1098 else
1099 {
1100 SwPosition const start(
1101 const_cast<SwTextNode&>(
1102 iter == *pIter
1103 ? *pFirstNode // simplification
1104 : *iter->pNode),
1105 iter == *pIter // first extent?
1106 ? iter->pNode == pFirstNode
1107 ? 0 // at start of 1st node
1108 : pFirstNode->Len() // previous node; simplification but should get right result
1109 : (iter-1)->nEnd); // previous extent
1110 SwPosition const end(*iter->pNode, iter->nStart);
1111 return !IsDestroyFrameAnchoredAtChar(rAnchor, start, end);
1112 }
1113 }
1114 else if (iter == *pEnd - 1) // special case: after last extent
1115 {
1116 if (iter->nEnd == iter->pNode->Len())
1117 {
1118 return true; // special case: end of node
1119 }
1120 else
1121 {
1122 SwPosition const start(*iter->pNode, iter->nEnd);
1123 SwPosition const end(
1124 const_cast<SwTextNode&>(*pLastNode), // simplification
1125 iter->pNode == pLastNode
1126 ? iter->pNode->Len()
1127 : 0);
1128 return !IsDestroyFrameAnchoredAtChar(rAnchor, start, end);
1129 }
1130 }
1131 }
1132 else
1133 {
1134 assert(rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR)(static_cast <bool> (rAnch.GetAnchorId() == RndStdIds::
FLY_AS_CHAR) ? void (0) : __assert_fail ("rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1134, __extension__ __PRETTY_FUNCTION__))
;
1135 // for AS_CHAR obviously must be <
1136 if (rAnchor.nContent.GetIndex() < iter->nEnd)
1137 {
1138 return true;
1139 }
1140 }
1141 }
1142 return false;
1143 }
1144 else
1145 {
1146 return true;
1147 }
1148}
1149
1150void RemoveHiddenObjsOfNode(SwTextNode const& rNode,
1151 std::vector<sw::Extent>::const_iterator const*const pIter,
1152 std::vector<sw::Extent>::const_iterator const*const pEnd,
1153 SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode)
1154{
1155 std::vector<SwFrameFormat*> const*const pFlys(rNode.GetAnchoredFlys());
1156 if (!pFlys)
1157 {
1158 return;
1159 }
1160 for (SwFrameFormat * pFrameFormat : *pFlys)
1161 {
1162 SwFormatAnchor const& rAnchor = pFrameFormat->GetAnchor();
1163 if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR
1164 || (rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR
1165 && RES_DRAWFRMFMT == pFrameFormat->Which()))
1166 {
1167 assert(rAnchor.GetContentAnchor()->nNode.GetIndex() == rNode.GetIndex())(static_cast <bool> (rAnchor.GetContentAnchor()->nNode
.GetIndex() == rNode.GetIndex()) ? void (0) : __assert_fail (
"rAnchor.GetContentAnchor()->nNode.GetIndex() == rNode.GetIndex()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1167, __extension__ __PRETTY_FUNCTION__))
;
1168 if (!IsShown(rNode.GetIndex(), rAnchor, pIter, pEnd, pFirstNode, pLastNode))
1169 {
1170 pFrameFormat->DelFrames();
1171 }
1172 }
1173 }
1174}
1175
1176void AppendObjsOfNode(SwFrameFormats const*const pTable, sal_uLong const nIndex,
1177 SwFrame *const pFrame, SwPageFrame *const pPage, SwDoc *const pDoc,
1178 std::vector<sw::Extent>::const_iterator const*const pIter,
1179 std::vector<sw::Extent>::const_iterator const*const pEnd,
1180 SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode)
1181{
1182#if OSL_DEBUG_LEVEL1 > 0
1183 std::vector<SwFrameFormat*> checkFormats;
1184 for ( size_t i = 0; i < pTable->size(); ++i )
1185 {
1186 SwFrameFormat *pFormat = (*pTable)[i];
1187 const SwFormatAnchor &rAnch = pFormat->GetAnchor();
1188 if ( rAnch.GetContentAnchor() &&
1189 IsShown(nIndex, rAnch, pIter, pEnd, pFirstNode, pLastNode))
1190 {
1191 checkFormats.push_back( pFormat );
1192 }
1193 }
1194#else
1195 (void)pTable;
1196#endif
1197
1198 SwNode const& rNode(*pDoc->GetNodes()[nIndex]);
1199 std::vector<SwFrameFormat*> const*const pFlys(rNode.GetAnchoredFlys());
1200 for (size_t it = 0; pFlys && it != pFlys->size(); )
1201 {
1202 SwFrameFormat *const pFormat = (*pFlys)[it];
1203 const SwFormatAnchor &rAnch = pFormat->GetAnchor();
1204 if ( rAnch.GetContentAnchor() &&
1205 IsShown(nIndex, rAnch, pIter, pEnd, pFirstNode, pLastNode))
1206 {
1207#if OSL_DEBUG_LEVEL1 > 0
1208 std::vector<SwFrameFormat*>::iterator checkPos = std::find( checkFormats.begin(), checkFormats.end(), pFormat );
1209 assert( checkPos != checkFormats.end())(static_cast <bool> (checkPos != checkFormats.end()) ? void
(0) : __assert_fail ("checkPos != checkFormats.end()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1209, __extension__ __PRETTY_FUNCTION__))
;
1210 checkFormats.erase( checkPos );
1211#endif
1212 AppendObj(pFrame, pPage, pFormat, rAnch);
1213 }
1214 ++it;
1215 }
1216
1217#if OSL_DEBUG_LEVEL1 > 0
1218 assert( checkFormats.empty())(static_cast <bool> (checkFormats.empty()) ? void (0) :
__assert_fail ("checkFormats.empty()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1218, __extension__ __PRETTY_FUNCTION__))
;
1219#endif
1220}
1221
1222
1223void AppendObjs(const SwFrameFormats *const pTable, sal_uLong const nIndex,
1224 SwFrame *const pFrame, SwPageFrame *const pPage, SwDoc *const pDoc)
1225{
1226 if (pFrame->IsTextFrame())
1227 {
1228 SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(pFrame));
1229 if (sw::MergedPara const*const pMerged = pTextFrame->GetMergedPara())
1230 {
1231 std::vector<sw::Extent>::const_iterator iterFirst(pMerged->extents.begin());
1232 std::vector<sw::Extent>::const_iterator iter(iterFirst);
1233 SwTextNode const* pNode(pMerged->pFirstNode);
1234 for ( ; ; ++iter)
1235 {
1236 if (iter == pMerged->extents.end()
1237 || iter->pNode != pNode)
1238 {
1239 AppendObjsOfNode(pTable, pNode->GetIndex(), pFrame, pPage, pDoc,
1240 &iterFirst, &iter, pMerged->pFirstNode, pMerged->pLastNode);
1241 sal_uLong const until = iter == pMerged->extents.end()
1242 ? pMerged->pLastNode->GetIndex() + 1
1243 : iter->pNode->GetIndex();
1244 for (sal_uLong i = pNode->GetIndex() + 1; i < until; ++i)
1245 {
1246 // let's show at-para flys on nodes that contain start/end of
1247 // redline too, even if there's no text there
1248 SwNode const*const pTmp(pNode->GetNodes()[i]);
1249 if (pTmp->GetRedlineMergeFlag() == SwNode::Merge::NonFirst)
1250 {
1251 AppendObjsOfNode(pTable, pTmp->GetIndex(), pFrame, pPage, pDoc, &iter, &iter, pMerged->pFirstNode, pMerged->pLastNode);
1252 }
1253 }
1254 if (iter == pMerged->extents.end())
1255 {
1256 break;
1257 }
1258 pNode = iter->pNode;
1259 iterFirst = iter;
1260 }
1261 }
1262 }
1263 else
1264 {
1265 return AppendObjsOfNode(pTable, nIndex, pFrame, pPage, pDoc, nullptr, nullptr, nullptr, nullptr);
1266 }
1267 }
1268 else
1269 {
1270 return AppendObjsOfNode(pTable, nIndex, pFrame, pPage, pDoc, nullptr, nullptr, nullptr, nullptr);
1271 }
1272}
1273
1274bool IsAnchoredObjShown(SwTextFrame const& rFrame, SwFormatAnchor const& rAnchor)
1275{
1276 assert(rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA ||(static_cast <bool> (rAnchor.GetAnchorId() == RndStdIds
::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR
|| rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) ? void (
0) : __assert_fail ("rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1278, __extension__ __PRETTY_FUNCTION__))
1277 rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR ||(static_cast <bool> (rAnchor.GetAnchorId() == RndStdIds
::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR
|| rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) ? void (
0) : __assert_fail ("rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1278, __extension__ __PRETTY_FUNCTION__))
1278 rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)(static_cast <bool> (rAnchor.GetAnchorId() == RndStdIds
::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR
|| rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) ? void (
0) : __assert_fail ("rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1278, __extension__ __PRETTY_FUNCTION__))
;
1279 bool ret(true);
1280 if (auto const pMergedPara = rFrame.GetMergedPara())
1281 {
1282 ret = false;
1283 auto const pAnchor(rAnchor.GetContentAnchor());
1284 auto iterFirst(pMergedPara->extents.cbegin());
1285 if (iterFirst == pMergedPara->extents.end()
1286 && (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA
1287 || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR))
1288 {
1289 ret = (&pAnchor->nNode.GetNode() == pMergedPara->pFirstNode
1290 && (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA
1291 || pAnchor->nContent == 0))
1292 || (&pAnchor->nNode.GetNode() == pMergedPara->pLastNode
1293 && (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA
1294 || pAnchor->nContent == pMergedPara->pLastNode->Len()));
1295 }
1296 auto iter(iterFirst);
1297 SwTextNode const* pNode(pMergedPara->pFirstNode);
1298 for ( ; ; ++iter)
1299 {
1300 if (iter == pMergedPara->extents.end()
1301 || iter->pNode != pNode)
1302 {
1303 assert(pNode->GetRedlineMergeFlag() != SwNode::Merge::Hidden)(static_cast <bool> (pNode->GetRedlineMergeFlag() !=
SwNode::Merge::Hidden) ? void (0) : __assert_fail ("pNode->GetRedlineMergeFlag() != SwNode::Merge::Hidden"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1303, __extension__ __PRETTY_FUNCTION__))
;
1304 if (pNode == &pAnchor->nNode.GetNode())
1305 {
1306 ret = IsShown(pNode->GetIndex(), rAnchor, &iterFirst, &iter,
1307 pMergedPara->pFirstNode, pMergedPara->pLastNode);
1308 break;
1309 }
1310 if (iter == pMergedPara->extents.end())
1311 {
1312 break;
1313 }
1314 pNode = iter->pNode;
1315 if (pAnchor->nNode.GetIndex() < pNode->GetIndex())
1316 {
1317 break;
1318 }
1319 iterFirst = iter;
1320 }
1321 }
1322 }
1323 return ret;
1324}
1325
1326void AppendAllObjs(const SwFrameFormats* pTable, const SwFrame* pSib)
1327{
1328 //Connecting of all Objects, which are described in the SpzTable with the
1329 //layout.
1330
1331 boost::circular_buffer<SwFrameFormat*> vFormatsToConnect(pTable->size());
1332 for(const auto& pFormat : *pTable)
1333 {
1334 const auto& rAnch = pFormat->GetAnchor();
1335 // Formats can still remain, because we neither use character bound
1336 // frames nor objects which are anchored to character bounds.
1337 if ((rAnch.GetAnchorId() != RndStdIds::FLY_AT_PAGE) && (rAnch.GetAnchorId() != RndStdIds::FLY_AS_CHAR))
1338 {
1339 auto pContentAnchor = rAnch.GetContentAnchor();
1340 // formats in header/footer have no dependencies
1341 if(pContentAnchor && pFormat->GetDoc()->IsInHeaderFooter(pContentAnchor->nNode))
1342 pFormat->MakeFrames();
1343 else
1344 vFormatsToConnect.push_back(pFormat);
1345 }
1346 }
1347 const SwRootFrame* pRoot = pSib ? pSib->getRootFrame() : nullptr;
1348 const SwFrameFormat* pFirstRequeued(nullptr);
1349 while(!vFormatsToConnect.empty())
1350 {
1351 auto& pFormat = vFormatsToConnect.front();
1352 bool isConnected(false);
1353 pFormat->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected, pRoot));
1354 if(!isConnected)
1355 {
1356 pFormat->MakeFrames();
1357 pFormat->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected, pRoot));
1358 }
1359 // do this *before* push_back! the circular_buffer can be "full"!
1360 vFormatsToConnect.pop_front();
1361 if (!isConnected)
1362 {
1363 if(pFirstRequeued == pFormat)
1364 // If nothing happens anymore we can stop.
1365 break;
1366 if(!pFirstRequeued)
1367 pFirstRequeued = pFormat;
1368 assert(!vFormatsToConnect.full())(static_cast <bool> (!vFormatsToConnect.full()) ? void (
0) : __assert_fail ("!vFormatsToConnect.full()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1368, __extension__ __PRETTY_FUNCTION__))
;
1369 vFormatsToConnect.push_back(pFormat);
1370 }
1371 else
1372 {
1373 pFirstRequeued = nullptr;
1374 }
1375 }
1376}
1377
1378namespace sw {
1379
1380void RecreateStartTextFrames(SwTextNode & rNode)
1381{
1382 std::vector<SwTextFrame*> frames;
1383 SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rNode);
1384 for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
1385 {
1386 if (pFrame->getRootFrame()->IsHideRedlines())
1387 {
1388 frames.push_back(pFrame);
1389 }
1390 }
1391 auto eMode(sw::FrameMode::Existing);
1392 for (SwTextFrame * pFrame : frames)
1393 {
1394 // SplitNode could have moved the original frame to the start node
1395 // & created a new one on end, or could have created new frame on
1396 // start node... grab start node's frame and recreate MergedPara.
1397 SwTextNode & rFirstNode(pFrame->GetMergedPara()
1398 ? *pFrame->GetMergedPara()->pFirstNode
1399 : rNode);
1400 assert(rFirstNode.GetIndex() <= rNode.GetIndex())(static_cast <bool> (rFirstNode.GetIndex() <= rNode.
GetIndex()) ? void (0) : __assert_fail ("rFirstNode.GetIndex() <= rNode.GetIndex()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1400, __extension__ __PRETTY_FUNCTION__))
;
1401 // clear old one first to avoid DelFrames confusing updates & asserts...
1402 pFrame->SetMergedPara(nullptr);
1403 pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
1404 *pFrame, rFirstNode, eMode));
1405 eMode = sw::FrameMode::New; // Existing is not idempotent!
1406 // note: this may or may not delete frames on the end node
1407 }
1408}
1409
1410} // namespace sw
1411
1412/** local method to set 'working' position for newly inserted frames
1413
1414 OD 12.08.2003 #i17969#
1415*/
1416static void lcl_SetPos( SwFrame& _rNewFrame,
1417 const SwLayoutFrame& _rLayFrame )
1418{
1419 SwRectFnSet aRectFnSet(&_rLayFrame);
1420 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(_rNewFrame);
1421 aRectFnSet.SetPos( aFrm, aRectFnSet.GetPos(_rLayFrame.getFrameArea()) );
1422
1423 // move position by one SwTwip in text flow direction in order to get
1424 // notifications for a new calculated position after its formatting.
1425 if ( aRectFnSet.IsVert() )
1426 {
1427 aFrm.Pos().AdjustX( -1 );
1428 }
1429 else
1430 {
1431 aFrm.Pos().AdjustY(1 );
1432 }
1433}
1434
1435void InsertCnt_( SwLayoutFrame *pLay, SwDoc *pDoc,
1436 sal_uLong nIndex, bool bPages, sal_uLong nEndIndex,
1437 SwFrame *pPrv, sw::FrameMode const eMode )
1438{
1439 pDoc->getIDocumentTimerAccess().BlockIdling();
1440 SwRootFrame* pLayout = pLay->getRootFrame();
1441 const bool bOldCallbackActionEnabled = pLayout && pLayout->IsCallbackActionEnabled();
1442 if( bOldCallbackActionEnabled )
1443 pLayout->SetCallbackActionEnabled( false );
1444
1445 //In the generation of the Layout bPages=true will be handed over.
1446 //Then will be new pages generated all x paragraphs already times in advance.
1447 //On breaks and/or pagedescriptorchanges the corresponding will be generated
1448 //immediately.
1449 //The advantage is, that on one hand already a nearly realistic number of
1450 //pages are created, but above all there are no almost endless long chain
1451 //of paragraphs, which must be moved expensively until it reaches a tolerable
1452 //reduced level.
1453 //We'd like to think that 20 Paragraphs fit on one page.
1454 //So that it does not become in extreme situations so violent we calculate depending
1455 //on the node something to it.
1456 //If in the DocStatistic a usable given pagenumber
1457 //(Will be cared for while writing), so it will be presumed that this will be
1458 //number of pages.
1459 const bool bStartPercent = bPages && !nEndIndex;
1460
1461 SwPageFrame *pPage = pLay->FindPageFrame();
1462 const SwFrameFormats *pTable = pDoc->GetSpzFrameFormats();
1463 SwFrame *pFrame = nullptr;
1464 std::unique_ptr<SwActualSection> pActualSection;
1465 std::unique_ptr<SwLayHelper> pPageMaker;
1466
1467 //If the layout will be created (bPages == true) we do head on the progress
1468 //Flys and DrawObjects are not connected immediately, this
1469 //happens only at the end of the function.
1470 if ( bPages )
1471 {
1472 // Attention: the SwLayHelper class uses references to the content-,
1473 // page-, layout-frame etc. and may change them!
1474 pPageMaker.reset(new SwLayHelper( pDoc, pFrame, pPrv, pPage, pLay,
1475 pActualSection, nIndex, 0 == nEndIndex ));
1476 if( bStartPercent )
1477 {
1478 const sal_uLong nPageCount = pPageMaker->CalcPageCount();
1479 if( nPageCount )
1480 bObjsDirect = false;
1481 }
1482 }
1483 else
1484 pPageMaker = nullptr;
1485
1486 if( pLay->IsInSct() &&
1487 ( pLay->IsSctFrame() || pLay->GetUpper() ) ) // Hereby will newbies
1488 // be intercepted, of which flags could not determined yet,
1489 // for e.g. while inserting a table
1490 {
1491 SwSectionFrame* pSct = pLay->FindSctFrame();
1492 // If content will be inserted in a footnote, which in a column area,
1493 // the column area it is not allowed to be broken up.
1494 // Only if in the inner of the footnote lies an area, is this a candidate
1495 // for pActualSection.
1496 // The same applies for areas in tables, if inside the table will be
1497 // something inserted, it's only allowed to break up areas, which
1498 // lies in the inside also.
1499 if( ( !pLay->IsInFootnote() || pSct->IsInFootnote() ) &&
1500 ( !pLay->IsInTab() || pSct->IsInTab() ) )
1501 {
1502 pActualSection.reset(new SwActualSection(nullptr, pSct, pSct->GetSection()->GetFormat()->GetSectionNode()));
1503 // tdf#132236 for SwUndoDelete: find outer sections whose start
1504 // nodes aren't contained in the range but whose end nodes are,
1505 // because section frames may need to be created for them
1506 SwActualSection * pUpperSection(pActualSection.get());
1507 while (pUpperSection->GetSectionNode()->EndOfSectionIndex() < nEndIndex)
1508 {
1509 SwStartNode *const pStart(pUpperSection->GetSectionNode()->StartOfSectionNode());
1510 if (!pStart->IsSectionNode())
1511 {
1512 break;
1513 }
1514 // note: these don't have a section frame, check it in EndNode case!
1515 auto const pTmp(new SwActualSection(nullptr, nullptr, static_cast<SwSectionNode*>(pStart)));
1516 pUpperSection->SetUpper(pTmp);
1517 pUpperSection = pTmp;
1518 }
1519 OSL_ENSURE( !pLay->Lower() || !pLay->Lower()->IsColumnFrame(),do { if (true && (!(!pLay->Lower() || !pLay->Lower
()->IsColumnFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "1520" ": "), "%s", "InsertCnt_: Wrong Call"); } } while
(false)
1520 "InsertCnt_: Wrong Call" )do { if (true && (!(!pLay->Lower() || !pLay->Lower
()->IsColumnFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "1520" ": "), "%s", "InsertCnt_: Wrong Call"); } } while
(false)
;
1521 }
1522 }
1523
1524 //If a section is "open", the pActualSection points to an SwActualSection.
1525 //If the page breaks, for "open" sections a follow will created.
1526 //For nested sections (which have, however, not a nested layout),
1527 //the SwActualSection class has a member, which points to an upper(section).
1528 //When the "inner" section finishes, the upper will used instead.
1529
1530 // Do not consider the end node. The caller (Section/MakeFrames()) has to
1531 // ensure that the end of this range is positioned before EndIndex!
1532 for ( ; nEndIndex == 0 || nIndex < nEndIndex; ++nIndex)
1533 {
1534 SwNode *pNd = pDoc->GetNodes()[nIndex];
1535 if ( pNd->IsContentNode() )
1536 {
1537 SwContentNode* pNode = static_cast<SwContentNode*>(pNd);
1538 if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines())
1539 {
1540 if (pNd->IsTextNode()
1541 && pNd->GetRedlineMergeFlag() == SwNode::Merge::NonFirst)
1542 { // must have a frame already
1543 assert(static_cast<SwTextFrame*>(pNode->getLayoutFrame(pLayout))->GetMergedPara())(static_cast <bool> (static_cast<SwTextFrame*>(pNode
->getLayoutFrame(pLayout))->GetMergedPara()) ? void (0)
: __assert_fail ("static_cast<SwTextFrame*>(pNode->getLayoutFrame(pLayout))->GetMergedPara()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1543, __extension__ __PRETTY_FUNCTION__))
;
1544 }
1545 continue; // skip it
1546 }
1547 pFrame = pNode->IsTextNode()
1548 ? sw::MakeTextFrame(*pNode->GetTextNode(), pLay, eMode)
1549 : pNode->MakeFrame(pLay);
1550 if( pPageMaker )
1551 pPageMaker->CheckInsert( nIndex );
1552
1553 pFrame->InsertBehind( pLay, pPrv );
1554 // #i27138#
1555 // notify accessibility paragraphs objects about changed
1556 // CONTENT_FLOWS_FROM/_TO relation.
1557 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1558 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1559 if ( pFrame->IsTextFrame() )
1560 {
1561 SwViewShell* pViewShell( pFrame->getRootFrame()->GetCurrShell() );
1562 // no notification, if <SwViewShell> is in construction
1563 if ( pViewShell && !pViewShell->IsInConstructor() &&
1564 pViewShell->GetLayout() &&
1565 pViewShell->GetLayout()->IsAnyShellAccessible() &&
1566 pFrame->FindPageFrame() != nullptr)
1567 {
1568 pViewShell->InvalidateAccessibleParaFlowRelation(
1569 dynamic_cast<SwTextFrame*>(pFrame->FindNextCnt( true )),
1570 dynamic_cast<SwTextFrame*>(pFrame->FindPrevCnt()) );
1571 // #i68958#
1572 // The information flags of the text frame are validated
1573 // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
1574 // The information flags have to be invalidated, because
1575 // it is possible, that the one of its upper frames
1576 // isn't inserted into the layout.
1577 pFrame->InvalidateInfFlags();
1578 }
1579 }
1580 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1581 // for setting position at newly inserted frame
1582 lcl_SetPos( *pFrame, *pLay );
1583 pPrv = pFrame;
1584
1585 if ( !pTable->empty() && bObjsDirect && !bDontCreateObjects )
1586 AppendObjs( pTable, nIndex, pFrame, pPage, pDoc );
1587 }
1588 else if ( pNd->IsTableNode() )
1589 { //Should we have encountered a table?
1590 SwTableNode *pTableNode = static_cast<SwTableNode*>(pNd);
1591 if (pLayout->IsHideRedlines())
1592 {
1593 // in the problematic case, there can be only 1 redline...
1594 SwPosition const tmp(*pNd);
1595 SwRangeRedline const*const pRedline(
1596 pDoc->getIDocumentRedlineAccess().GetRedline(tmp, nullptr));
1597 // pathology: redline that starts on a TableNode; cannot
1598 // be created in UI but by import filters...
1599 if (pRedline
1600 && pRedline->GetType() == RedlineType::Delete
1601 && &pRedline->Start()->nNode.GetNode() == pNd)
1602 {
1603 SAL_WARN("sw.pageframe", "skipping table frame creation on bizarre redline")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.pageframe")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "skipping table frame creation on bizarre redline"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.pageframe"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "1603" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "skipping table frame creation on bizarre redline"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "skipping table frame creation on bizarre redline";
::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.pageframe"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "1603" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "skipping table frame creation on bizarre redline"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.pageframe"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "1603" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "skipping table frame creation on bizarre redline"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "skipping table frame creation on bizarre redline";
::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.pageframe"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "1603" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1604 while (true)
1605 {
1606 pTableNode->GetNodes()[nIndex]->SetRedlineMergeFlag(SwNode::Merge::Hidden);
1607 if (nIndex == pTableNode->EndOfSectionIndex())
1608 {
1609 break;
1610 }
1611 ++nIndex;
1612 }
1613 continue;
1614 }
1615 }
1616 if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines())
1617 {
1618 assert(pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)(static_cast <bool> (pNd->GetRedlineMergeFlag() == SwNode
::Merge::Hidden) ? void (0) : __assert_fail ("pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1618, __extension__ __PRETTY_FUNCTION__))
;
1619 nIndex = pTableNode->EndOfSectionIndex();
1620 continue; // skip it
1621 }
1622
1623 // #108116# loading may produce table structures that GCLines
1624 // needs to clean up. To keep table formulas correct, change
1625 // all table formulas to internal (BOXPTR) representation.
1626 SwTableFormulaUpdate aMsgHint( &pTableNode->GetTable() );
1627 aMsgHint.m_eFlags = TBL_BOXPTR;
1628 pDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
1629 pTableNode->GetTable().GCLines();
1630
1631 pFrame = pTableNode->MakeFrame( pLay );
1632
1633 if( pPageMaker )
1634 pPageMaker->CheckInsert( nIndex );
1635
1636 pFrame->InsertBehind( pLay, pPrv );
1637 if (pPage) // would null in SwCellFrame ctor
1638 { // tdf#134931 call ResetTurbo(); not sure if Paste() would be
1639 pFrame->InvalidatePage(pPage); // better than InsertBehind()?
1640 }
1641 // #i27138#
1642 // notify accessibility paragraphs objects about changed
1643 // CONTENT_FLOWS_FROM/_TO relation.
1644 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1645 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1646 {
1647 SwViewShell* pViewShell( pFrame->getRootFrame()->GetCurrShell() );
1648 // no notification, if <SwViewShell> is in construction
1649 if ( pViewShell && !pViewShell->IsInConstructor() &&
1650 pViewShell->GetLayout() &&
1651 pViewShell->GetLayout()->IsAnyShellAccessible() &&
1652 pFrame->FindPageFrame() != nullptr)
1653 {
1654 pViewShell->InvalidateAccessibleParaFlowRelation(
1655 dynamic_cast<SwTextFrame*>(pFrame->FindNextCnt( true )),
1656 dynamic_cast<SwTextFrame*>(pFrame->FindPrevCnt()) );
1657 }
1658 }
1659 if ( bObjsDirect && !pTable->empty() )
1660 static_cast<SwTabFrame*>(pFrame)->RegistFlys();
1661 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1662 // for setting position at newly inserted frame
1663 lcl_SetPos( *pFrame, *pLay );
1664
1665 pPrv = pFrame;
1666 //Set the index to the endnode of the table section.
1667 nIndex = pTableNode->EndOfSectionIndex();
1668
1669 SwTabFrame* pTmpFrame = static_cast<SwTabFrame*>(pFrame);
1670 while ( pTmpFrame )
1671 {
1672 pTmpFrame->CheckDirChange();
1673 pTmpFrame = pTmpFrame->IsFollow() ? pTmpFrame->FindMaster() : nullptr;
1674 }
1675
1676 }
1677 else if ( pNd->IsSectionNode() )
1678 {
1679 if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines())
1680 {
1681 assert(pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)(static_cast <bool> (pNd->GetRedlineMergeFlag() == SwNode
::Merge::Hidden) ? void (0) : __assert_fail ("pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1681, __extension__ __PRETTY_FUNCTION__))
;
1682 continue; // skip it
1683 }
1684 SwSectionNode *pNode = static_cast<SwSectionNode*>(pNd);
1685 if( pNode->GetSection().CalcHiddenFlag() )
1686 // is hidden, skip the area
1687 nIndex = pNode->EndOfSectionIndex();
1688 else
1689 {
1690 pFrame = pNode->MakeFrame( pLay );
1691 pActualSection.reset( new SwActualSection( pActualSection.release(),
1692 static_cast<SwSectionFrame*>(pFrame), pNode ) );
1693 if ( pActualSection->GetUpper() )
1694 {
1695 //Insert behind the Upper, the "Follow" of the Upper will be
1696 //generated at the EndNode.
1697 SwSectionFrame *pTmp = pActualSection->GetUpper()->GetSectionFrame();
1698 pFrame->InsertBehind( pTmp->GetUpper(), pTmp );
1699 // OD 25.03.2003 #108339# - direct initialization of section
1700 // after insertion in the layout
1701 static_cast<SwSectionFrame*>(pFrame)->Init();
1702 }
1703 else
1704 {
1705 pFrame->InsertBehind( pLay, pPrv );
1706 // OD 25.03.2003 #108339# - direct initialization of section
1707 // after insertion in the layout
1708 static_cast<SwSectionFrame*>(pFrame)->Init();
1709
1710 // #i33963#
1711 // Do not trust the IsInFootnote flag. If we are currently
1712 // building up a table, the upper of pPrv may be a cell
1713 // frame, but the cell frame does not have an upper yet.
1714 if( pPrv && nullptr != pPrv->ImplFindFootnoteFrame() )
1715 {
1716 if( pPrv->IsSctFrame() )
1717 pPrv = static_cast<SwSectionFrame*>(pPrv)->ContainsContent();
1718 if( pPrv && pPrv->IsTextFrame() )
1719 static_cast<SwTextFrame*>(pPrv)->Prepare( PrepareHint::QuoVadis, nullptr, false );
1720 }
1721 }
1722 if (nIndex + 1 == nEndIndex)
1723 { // tdf#131684 tdf#132236 fix upper of frame moved in
1724 // SwUndoDelete; can't be done there unfortunately
1725 // because empty section frames are deleted here
1726 SwFrame *const pNext(
1727 // if there's a parent section, it has been split
1728 // into 2 SwSectionFrame already :(
1729 ( pFrame->GetNext()
1730 && pFrame->GetNext()->IsSctFrame()
1731 && pActualSection->GetUpper()
1732 && pActualSection->GetUpper()->GetSectionNode() ==
1733 static_cast<SwSectionFrame const*>(pFrame->GetNext())->GetSection()->GetFormat()->GetSectionNode())
1734 ? static_cast<SwSectionFrame *>(pFrame->GetNext())->ContainsContent()
1735 : pFrame->GetNext());
1736 if (pNext
1737 && pNext->IsTextFrame()
1738 && static_cast<SwTextFrame*>(pNext)->GetTextNodeFirst() == pDoc->GetNodes()[nEndIndex]
1739 && (pNext->GetUpper() == pFrame->GetUpper()
1740 || pFrame->GetNext()->IsSctFrame())) // checked above
1741 {
1742 pNext->Cut();
1743 pNext->InvalidateInfFlags(); // mbInfSct changed
1744 // could have columns
1745 SwSectionFrame *const pSection(static_cast<SwSectionFrame*>(pFrame));
1746 assert(!pSection->Lower() || pSection->Lower()->IsLayoutFrame())(static_cast <bool> (!pSection->Lower() || pSection->
Lower()->IsLayoutFrame()) ? void (0) : __assert_fail ("!pSection->Lower() || pSection->Lower()->IsLayoutFrame()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1746, __extension__ __PRETTY_FUNCTION__))
;
1747 SwLayoutFrame *const pParent(pSection->Lower() ? pSection->GetNextLayoutLeaf() : pSection);
1748 assert(!pParent->Lower())(static_cast <bool> (!pParent->Lower()) ? void (0) :
__assert_fail ("!pParent->Lower()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1748, __extension__ __PRETTY_FUNCTION__))
;
1749 // paste invalidates, section could have indent...
1750 pNext->Paste(pParent, nullptr);
1751 }
1752 }
1753 // #i27138#
1754 // notify accessibility paragraphs objects about changed
1755 // CONTENT_FLOWS_FROM/_TO relation.
1756 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1757 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1758 {
1759 SwViewShell* pViewShell( pFrame->getRootFrame()->GetCurrShell() );
1760 // no notification, if <SwViewShell> is in construction
1761 if ( pViewShell && !pViewShell->IsInConstructor() &&
1762 pViewShell->GetLayout() &&
1763 pViewShell->GetLayout()->IsAnyShellAccessible() &&
1764 pFrame->FindPageFrame() != nullptr)
1765 {
1766 pViewShell->InvalidateAccessibleParaFlowRelation(
1767 dynamic_cast<SwTextFrame*>(pFrame->FindNextCnt( true )),
1768 dynamic_cast<SwTextFrame*>(pFrame->FindPrevCnt()) );
1769 }
1770 }
1771 pFrame->CheckDirChange();
1772
1773 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1774 // for setting position at newly inserted frame
1775 lcl_SetPos( *pFrame, *pLay );
1776
1777 // OD 20.11.2002 #105405# - no page, no invalidate.
1778 if ( pPage )
1779 {
1780 // OD 18.09.2002 #100522#
1781 // invalidate page in order to force format and paint of
1782 // inserted section frame
1783 pFrame->InvalidatePage( pPage );
1784
1785 // FME 10.11.2003 #112243#
1786 // Invalidate fly content flag:
1787 if ( pFrame->IsInFly() )
1788 pPage->InvalidateFlyContent();
1789
1790 // OD 14.11.2002 #104684# - invalidate page content in order to
1791 // force format and paint of section content.
1792 pPage->InvalidateContent();
1793 }
1794
1795 pLay = static_cast<SwLayoutFrame*>(pFrame);
1796 if ( pLay->Lower() && pLay->Lower()->IsLayoutFrame() )
1797 pLay = pLay->GetNextLayoutLeaf();
1798 pPrv = nullptr;
1799 }
1800 }
1801 else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )
1802 {
1803 if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines())
1804 {
1805 assert(pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)(static_cast <bool> (pNd->GetRedlineMergeFlag() == SwNode
::Merge::Hidden) ? void (0) : __assert_fail ("pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1805, __extension__ __PRETTY_FUNCTION__))
;
1806 continue; // skip it
1807 }
1808 assert(pActualSection && "Section end without section start?")(static_cast <bool> (pActualSection && "Section end without section start?"
) ? void (0) : __assert_fail ("pActualSection && \"Section end without section start?\""
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1808, __extension__ __PRETTY_FUNCTION__))
;
1809 assert(pActualSection->GetSectionNode() == pNd->StartOfSectionNode())(static_cast <bool> (pActualSection->GetSectionNode(
) == pNd->StartOfSectionNode()) ? void (0) : __assert_fail
("pActualSection->GetSectionNode() == pNd->StartOfSectionNode()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1809, __extension__ __PRETTY_FUNCTION__))
;
1810
1811 //Close the section, where appropriate activate the surrounding
1812 //section again.
1813 pActualSection.reset(pActualSection->GetUpper());
1814 pLay = pLay->FindSctFrame();
1815 if ( pActualSection )
1816 {
1817 //Could be, that the last SectionFrame remains empty.
1818 //Then now is the time to remove them.
1819 if ( !pLay->ContainsContent() )
1820 {
1821 SwFrame *pTmpFrame = pLay;
1822 pLay = pTmpFrame->GetUpper();
1823 pPrv = pTmpFrame->GetPrev();
1824 pTmpFrame->RemoveFromLayout();
1825 SwFrame::DestroyFrame(pTmpFrame);
1826 }
1827 else
1828 {
1829 pPrv = pLay;
1830 pLay = pLay->GetUpper();
1831 }
1832
1833 // new section frame
1834 pFrame = pActualSection->GetSectionNode()->MakeFrame( pLay );
1835 pFrame->InsertBehind( pLay, pPrv );
1836 static_cast<SwSectionFrame*>(pFrame)->Init();
1837
1838 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1839 // for setting position at newly inserted frame
1840 lcl_SetPos( *pFrame, *pLay );
1841
1842 SwSectionFrame* pOuterSectionFrame = pActualSection->GetSectionFrame();
1843
1844 // a follow has to be appended to the new section frame
1845 SwSectionFrame* pFollow = pOuterSectionFrame ? pOuterSectionFrame->GetFollow() : nullptr;
1846 if ( pFollow )
1847 {
1848 pOuterSectionFrame->SetFollow( nullptr );
1849 pOuterSectionFrame->InvalidateSize();
1850 static_cast<SwSectionFrame*>(pFrame)->SetFollow( pFollow );
1851 }
1852
1853 // We don't want to leave empty parts back.
1854 if (pOuterSectionFrame &&
1855 ! pOuterSectionFrame->IsColLocked() &&
1856 ! pOuterSectionFrame->ContainsContent() )
1857 {
1858 pOuterSectionFrame->DelEmpty( true );
1859 SwFrame::DestroyFrame(pOuterSectionFrame);
1860 }
1861 pActualSection->SetSectionFrame( static_cast<SwSectionFrame*>(pFrame) );
1862
1863 pLay = static_cast<SwLayoutFrame*>(pFrame);
1864 if ( pLay->Lower() && pLay->Lower()->IsLayoutFrame() )
1865 pLay = pLay->GetNextLayoutLeaf();
1866 pPrv = nullptr;
1867 }
1868 else
1869 {
1870 //Nothing more with sections, it goes on right behind
1871 //the SectionFrame.
1872 pPrv = pLay;
1873 pLay = pLay->GetUpper();
1874 }
1875 }
1876 else if( pNd->IsStartNode() &&
1877 SwFlyStartNode == static_cast<SwStartNode*>(pNd)->GetStartNodeType() )
1878 {
1879 if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines())
1880 {
1881 assert(pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)(static_cast <bool> (pNd->GetRedlineMergeFlag() == SwNode
::Merge::Hidden) ? void (0) : __assert_fail ("pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1881, __extension__ __PRETTY_FUNCTION__))
;
1882 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1882, __extension__ __PRETTY_FUNCTION__))
; // actually a fly-section can't be deleted?
1883 continue; // skip it
1884 }
1885 if ( !pTable->empty() && bObjsDirect && !bDontCreateObjects )
1886 {
1887 SwFlyFrame* pFly = pLay->FindFlyFrame();
1888 if( pFly )
1889 AppendObjs( pTable, nIndex, pFly, pPage, pDoc );
1890 }
1891 }
1892 else
1893 {
1894 assert(!pLayout->IsHideRedlines()(static_cast <bool> (!pLayout->IsHideRedlines() || pNd
->GetRedlineMergeFlag() != SwNode::Merge::Hidden) ? void (
0) : __assert_fail ("!pLayout->IsHideRedlines() || pNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1895, __extension__ __PRETTY_FUNCTION__))
1895 || pNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden)(static_cast <bool> (!pLayout->IsHideRedlines() || pNd
->GetRedlineMergeFlag() != SwNode::Merge::Hidden) ? void (
0) : __assert_fail ("!pLayout->IsHideRedlines() || pNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1895, __extension__ __PRETTY_FUNCTION__))
;
1896 // Neither Content nor table nor section, so we are done.
1897 break;
1898 }
1899 }
1900
1901 if ( pActualSection )
1902 {
1903 // Might happen that an empty (Follow-)Section is left over.
1904 if ( !(pLay = pActualSection->GetSectionFrame())->ContainsContent() )
1905 {
1906 pLay->RemoveFromLayout();
1907 SwFrame::DestroyFrame(pLay);
1908 }
1909 pActualSection.reset();
1910 }
1911
1912 if ( bPages ) // let the Flys connect to each other
1913 {
1914 if ( !bDontCreateObjects )
1915 AppendAllObjs( pTable, pLayout );
1916 bObjsDirect = true;
1917 }
1918
1919 if( pPageMaker )
1920 {
1921 pPageMaker->CheckFlyCache( pPage );
1922 pPageMaker.reset();
1923 if( pDoc->GetLayoutCache() )
1924 {
1925#ifdef DBG_UTIL
1926 pDoc->GetLayoutCache()->CompareLayout( *pDoc );
1927#endif
1928 pDoc->GetLayoutCache()->ClearImpl();
1929 }
1930 }
1931
1932 pDoc->getIDocumentTimerAccess().UnblockIdling();
1933 if( bOldCallbackActionEnabled )
1934 pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled );
1935}
1936
1937void MakeFrames( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
1938 const SwNodeIndex &rEndIdx )
1939{
1940 bObjsDirect = false;
1941
1942 SwNodeIndex aTmp( rSttIdx );
1943 sal_uLong nEndIdx = rEndIdx.GetIndex();
1944 SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrameNode( aTmp,
1945 pDoc->GetNodes()[ nEndIdx-1 ]);
1946 if ( pNd )
1947 {
1948 bool bApres = aTmp < rSttIdx;
1949 SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() );
1950 SwFrame* pFrame;
1951 sw::FrameMode eMode = sw::FrameMode::Existing;
1952 while( nullptr != (pFrame = aNode2Layout.NextFrame()) )
1953 {
1954 SwLayoutFrame *pUpper = pFrame->GetUpper();
1955 SwFootnoteFrame* pFootnoteFrame = pUpper->FindFootnoteFrame();
1956 bool bOldLock, bOldFootnote;
1957 if( pFootnoteFrame )
1958 {
1959 bOldFootnote = pFootnoteFrame->IsColLocked();
1960 pFootnoteFrame->ColLock();
1961 }
1962 else
1963 bOldFootnote = true;
1964 SwSectionFrame* pSct = pUpper->FindSctFrame();
1965 // Inside of footnotes only those areas are interesting that are inside of them. But
1966 // not the ones (e.g. column areas) in which are the footnote containers positioned.
1967 // #109767# Table frame is in section, insert section in cell frame.
1968 if( pSct && ((pFootnoteFrame && !pSct->IsInFootnote()) || pUpper->IsCellFrame()) )
1969 pSct = nullptr;
1970 if( pSct )
1971 { // to prevent pTmp->MoveFwd from destroying the SectionFrame
1972 bOldLock = pSct->IsColLocked();
1973 pSct->ColLock();
1974 }
1975 else
1976 bOldLock = true;
1977
1978 // If pFrame cannot be moved, it is not possible to move it to the next page. This applies
1979 // also for frames (in the first column of a frame pFrame is moveable) and column
1980 // sections of tables (also here pFrame is moveable).
1981 bool bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120;
1982 bool bAllowMove = !pFrame->IsInFly() && pFrame->IsMoveable() &&
1983 (!pFrame->IsInTab() || pFrame->IsTabFrame() );
1984 if ( bMoveNext && bAllowMove )
1985 {
1986 SwFrame *pMove = pFrame;
1987 SwFrame *pPrev = pFrame->GetPrev();
1988 SwFlowFrame *pTmp = SwFlowFrame::CastFlowFrame( pMove );
1989 assert(pTmp)(static_cast <bool> (pTmp) ? void (0) : __assert_fail (
"pTmp", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1989, __extension__ __PRETTY_FUNCTION__))
;
1990
1991 if ( bApres )
1992 {
1993 // The rest of this page should be empty. Thus, the following one has to move to
1994 // the next page (it might also be located in the following column).
1995 assert(!pTmp->HasFollow() && "prev. node's frame is not last")(static_cast <bool> (!pTmp->HasFollow() && "prev. node's frame is not last"
) ? void (0) : __assert_fail ("!pTmp->HasFollow() && \"prev. node's frame is not last\""
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 1995, __extension__ __PRETTY_FUNCTION__))
;
1996 pPrev = pFrame;
1997 // If the surrounding SectionFrame has a "next" one,
1998 // so this one needs to be moved as well.
1999 pMove = pFrame->GetIndNext();
2000 SwColumnFrame* pCol = static_cast<SwColumnFrame*>(pFrame->FindColFrame());
2001 if( pCol )
2002 pCol = static_cast<SwColumnFrame*>(pCol->GetNext());
2003 do
2004 {
2005 if( pCol && !pMove )
2006 { // No successor so far, look into the next column
2007 pMove = pCol->ContainsAny();
2008 if( pCol->GetNext() )
2009 pCol = static_cast<SwColumnFrame*>(pCol->GetNext());
2010 else if( pCol->IsInSct() )
2011 { // If there is no following column but we are in a column frame,
2012 // there might be (page) columns outside of it.
2013 pCol = static_cast<SwColumnFrame*>(pCol->FindSctFrame()->FindColFrame());
2014 if( pCol )
2015 pCol = static_cast<SwColumnFrame*>(pCol->GetNext());
2016 }
2017 else
2018 pCol = nullptr;
2019 }
2020 // skip invalid SectionFrames
2021 while( pMove && pMove->IsSctFrame() &&
2022 !static_cast<SwSectionFrame*>(pMove)->GetSection() )
2023 pMove = pMove->GetNext();
2024 } while( !pMove && pCol );
2025
2026 if( pMove )
2027 {
2028 if ( pMove->IsContentFrame() )
2029 pTmp = static_cast<SwContentFrame*>(pMove);
2030 else if ( pMove->IsTabFrame() )
2031 pTmp = static_cast<SwTabFrame*>(pMove);
2032 else if ( pMove->IsSctFrame() )
2033 {
2034 pMove = static_cast<SwSectionFrame*>(pMove)->ContainsAny();
2035 if( pMove )
2036 pTmp = SwFlowFrame::CastFlowFrame( pMove );
2037 else
2038 pTmp = nullptr;
2039 }
2040 }
2041 else
2042 pTmp = nullptr;
2043 }
2044 else
2045 {
2046 assert(!pTmp->IsFollow() && "next node's frame is not master")(static_cast <bool> (!pTmp->IsFollow() && "next node's frame is not master"
) ? void (0) : __assert_fail ("!pTmp->IsFollow() && \"next node's frame is not master\""
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 2046, __extension__ __PRETTY_FUNCTION__))
;
2047 // move the _content_ of a section frame
2048 if( pMove->IsSctFrame() )
2049 {
2050 while( pMove && pMove->IsSctFrame() &&
2051 !static_cast<SwSectionFrame*>(pMove)->GetSection() )
2052 pMove = pMove->GetNext();
2053 if( pMove && pMove->IsSctFrame() )
2054 pMove = static_cast<SwSectionFrame*>(pMove)->ContainsAny();
2055 if( pMove )
2056 pTmp = SwFlowFrame::CastFlowFrame( pMove );
2057 else
2058 pTmp = nullptr;
2059 }
2060 }
2061
2062 if( pTmp )
2063 {
2064 SwFrame* pOldUp = pTmp->GetFrame().GetUpper();
2065 // MoveFwd==true means that we are still on the same page.
2066 // But since we want to move if possible!
2067 bool bTmpOldLock = pTmp->IsJoinLocked();
2068 pTmp->LockJoin();
2069 while( pTmp->MoveFwd( true, false, true ) )
2070 {
2071 if( pOldUp == pTmp->GetFrame().GetUpper() )
2072 break;
2073 pOldUp = pTmp->GetFrame().GetUpper();
2074 }
2075 if( !bTmpOldLock )
2076 pTmp->UnlockJoin();
2077 }
2078 ::InsertCnt_( pUpper, pDoc, rSttIdx.GetIndex(),
2079 pFrame->IsInDocBody(), nEndIdx, pPrev, eMode );
2080 }
2081 else
2082 {
2083 bool bSplit;
2084 SwFrame* pPrv = bApres ? pFrame : pFrame->GetPrev();
2085 // If the section frame is inserted into another one, it must be split.
2086 if( pSct && rSttIdx.GetNode().IsSectionNode() )
2087 {
2088 bSplit = pSct->SplitSect( pFrame, bApres );
2089 if( !bSplit && !bApres )
2090 {
2091 pUpper = pSct->GetUpper();
2092 pPrv = pSct->GetPrev();
2093 }
2094 }
2095 else
2096 bSplit = false;
2097
2098 ::InsertCnt_( pUpper, pDoc, rSttIdx.GetIndex(), false,
2099 nEndIdx, pPrv, eMode );
2100 // OD 23.06.2003 #108784# - correction: append objects doesn't
2101 // depend on value of <bAllowMove>
2102 if( !bDontCreateObjects )
2103 {
2104 const SwFrameFormats *pTable = pDoc->GetSpzFrameFormats();
2105 if( !pTable->empty() )
2106 AppendAllObjs( pTable, pUpper );
2107 }
2108
2109 // If nothing was added (e.g. a hidden section), the split must be reversed.
2110 if( bSplit && pSct && pSct->GetNext()
2111 && pSct->GetNext()->IsSctFrame() )
2112 pSct->MergeNext( static_cast<SwSectionFrame*>(pSct->GetNext()) );
2113 if( pFrame->IsInFly() )
2114 pFrame->FindFlyFrame()->Invalidate_();
2115 if( pFrame->IsInTab() )
2116 pFrame->InvalidateSize();
2117 }
2118
2119 SwPageFrame *pPage = pUpper->FindPageFrame();
2120 SwFrame::CheckPageDescs( pPage, false );
2121 if( !bOldFootnote )
2122 pFootnoteFrame->ColUnlock();
2123 if( !bOldLock )
2124 {
2125 pSct->ColUnlock();
2126 // pSct might be empty (e.g. when inserting linked section containing further
2127 // sections) and can be destroyed in such cases.
2128 if( !pSct->ContainsContent() )
2129 {
2130 pSct->DelEmpty( true );
2131 pUpper->getRootFrame()->RemoveFromList( pSct );
2132 SwFrame::DestroyFrame(pSct);
2133 }
2134 }
2135 eMode = sw::FrameMode::New; // use Existing only once!
2136 }
2137 }
2138
2139 bObjsDirect = true;
2140}
2141
2142SwBorderAttrs::SwBorderAttrs(const SwModify *pMod, const SwFrame *pConstructor)
2143 : SwCacheObj(pMod)
2144 , m_rAttrSet(pConstructor->IsContentFrame()
2145 ? pConstructor->IsTextFrame()
2146 ? static_cast<const SwTextFrame*>(pConstructor)->GetTextNodeForParaProps()->GetSwAttrSet()
2147 : static_cast<const SwNoTextFrame*>(pConstructor)->GetNode()->GetSwAttrSet()
2148 : static_cast<const SwLayoutFrame*>(pConstructor)->GetFormat()->GetAttrSet())
2149 , m_rUL(m_rAttrSet.GetULSpace())
2150 // #i96772#
2151 // LRSpaceItem is copied due to the possibility that it is adjusted - see below
2152 , m_rLR(m_rAttrSet.GetLRSpace().Clone())
2153 , m_rBox(m_rAttrSet.GetBox())
2154 , m_rShadow(m_rAttrSet.GetShadow())
2155 , m_aFrameSize(m_rAttrSet.GetFrameSize().GetSize())
2156 , m_bIsLine(false)
2157 , m_bJoinedWithPrev(false)
2158 , m_bJoinedWithNext(false)
2159 , m_nTopLine(0)
2160 , m_nBottomLine(0)
2161 , m_nLeftLine(0)
2162 , m_nRightLine(0)
2163 , m_nTop(0)
2164 , m_nBottom(0)
2165 , m_nGetTopLine(0)
2166 , m_nGetBottomLine(0)
2167 , m_nLineSpacing(0)
2168{
2169 // #i96772#
2170 const SwTextFrame* pTextFrame = dynamic_cast<const SwTextFrame*>(pConstructor);
2171 if ( pTextFrame )
2172 {
2173 pTextFrame->GetTextNodeForParaProps()->ClearLRSpaceItemDueToListLevelIndents( m_rLR );
2174 }
2175 else if ( pConstructor->IsNoTextFrame() )
2176 {
2177 m_rLR = std::make_shared<SvxLRSpaceItem>(RES_LR_SPACE);
2178 }
2179
2180 // Caution: The USHORTs for the cached values are not initialized by intention!
2181
2182 // everything needs to be calculated at least once:
2183 m_bTopLine = m_bBottomLine = m_bLeftLine = m_bRightLine =
2184 m_bTop = m_bBottom = m_bLine = true;
2185
2186 // except this one: calculate line spacing before cell border only for text frames
2187 m_bLineSpacing = bool(pTextFrame);
2188
2189 m_bCacheGetLine = m_bCachedGetTopLine = m_bCachedGetBottomLine = false;
2190 // OD 21.05.2003 #108789# - init cache status for values <m_bJoinedWithPrev>
2191 // and <m_bJoinedWithNext>, which aren't initialized by default.
2192 m_bCachedJoinedWithPrev = false;
2193 m_bCachedJoinedWithNext = false;
2194}
2195
2196SwBorderAttrs::~SwBorderAttrs()
2197{
2198 const_cast<SwModify *>(static_cast<SwModify const *>(m_pOwner))->SetInCache( false );
2199}
2200
2201/* All calc methods calculate a safety distance in addition to the values given by the attributes.
2202 * This safety distance is only added when working with borders and/or shadows to prevent that
2203 * e.g. borders are painted over.
2204 */
2205
2206void SwBorderAttrs::CalcTop_()
2207{
2208 m_nTop = CalcTopLine() + m_rUL.GetUpper();
2209 m_bTop = false;
2210}
2211
2212void SwBorderAttrs::CalcBottom_()
2213{
2214 m_nBottom = CalcBottomLine() + m_rUL.GetLower();
2215 m_bBottom = false;
2216}
2217
2218long SwBorderAttrs::CalcRight( const SwFrame* pCaller ) const
2219{
2220 long nRight=0;
2221
2222 if (!pCaller->IsTextFrame() || !static_cast<const SwTextFrame*>(pCaller)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING)) {
2223 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2224 // and right border are painted on the right respectively left.
2225 if ( pCaller->IsCellFrame() && pCaller->IsRightToLeft() )
2226 nRight = CalcLeftLine();
2227 else
2228 nRight = CalcRightLine();
2229
2230 }
2231 // for paragraphs, "left" is "before text" and "right" is "after text"
2232 if ( pCaller->IsTextFrame() && pCaller->IsRightToLeft() )
2233 nRight += m_rLR->GetLeft();
2234 else
2235 nRight += m_rLR->GetRight();
2236
2237 // correction: retrieve left margin for numbering in R2L-layout
2238 if ( pCaller->IsTextFrame() && pCaller->IsRightToLeft() )
2239 {
2240 nRight += static_cast<const SwTextFrame*>(pCaller)->GetTextNodeForParaProps()->GetLeftMarginWithNum();
2241 }
2242
2243 return nRight;
2244}
2245
2246/// Tries to detect if this paragraph has a floating table attached.
2247static bool lcl_hasTabFrame(const SwTextFrame* pTextFrame)
2248{
2249 if (pTextFrame->GetDrawObjs())
2250 {
2251 const SwSortedObjs* pSortedObjs = pTextFrame->GetDrawObjs();
2252 if (pSortedObjs->size() > 0)
2253 {
2254 SwAnchoredObject* pObject = (*pSortedObjs)[0];
2255 if (dynamic_cast<const SwFlyFrame*>(pObject) != nullptr)
2256 {
2257 SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pObject);
2258 if (pFly->Lower() && pFly->Lower()->IsTabFrame())
2259 return true;
2260 }
2261 }
2262 }
2263 return false;
2264}
2265
2266long SwBorderAttrs::CalcLeft( const SwFrame *pCaller ) const
2267{
2268 long nLeft=0;
2269
2270 if (!pCaller->IsTextFrame() || !static_cast<const SwTextFrame*>(pCaller)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING))
2271 {
2272 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2273 // and right border are painted on the right respectively left.
2274 if ( pCaller->IsCellFrame() && pCaller->IsRightToLeft() )
2275 nLeft = CalcRightLine();
2276 else
2277 nLeft = CalcLeftLine();
2278 }
2279
2280 // for paragraphs, "left" is "before text" and "right" is "after text"
2281 if ( pCaller->IsTextFrame() && pCaller->IsRightToLeft() )
2282 nLeft += m_rLR->GetRight();
2283 else
2284 {
2285 bool bIgnoreMargin = false;
2286 if (pCaller->IsTextFrame())
2287 {
2288 const SwTextFrame* pTextFrame = static_cast<const SwTextFrame*>(pCaller);
2289 if (pTextFrame->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::FLOATTABLE_NOMARGINS))
2290 {
2291 // If this is explicitly requested, ignore the margins next to the floating table.
2292 if (lcl_hasTabFrame(pTextFrame))
2293 bIgnoreMargin = true;
2294 // TODO here we only handle the first two paragraphs, would be nice to generalize this.
2295 else if (pTextFrame->FindPrev() && pTextFrame->FindPrev()->IsTextFrame() && lcl_hasTabFrame(static_cast<const SwTextFrame*>(pTextFrame->FindPrev())))
2296 bIgnoreMargin = true;
2297 }
2298 }
2299 if (!bIgnoreMargin)
2300 nLeft += m_rLR->GetLeft();
2301 }
2302
2303 // correction: do not retrieve left margin for numbering in R2L-layout
2304 if ( pCaller->IsTextFrame() && !pCaller->IsRightToLeft() )
2305 {
2306 nLeft += static_cast<const SwTextFrame*>(pCaller)->GetTextNodeForParaProps()->GetLeftMarginWithNum();
2307 }
2308
2309 return nLeft;
2310}
2311
2312/* Calculated values for borders and shadows.
2313 * It might be that a distance is wanted even without lines. This will be
2314 * considered here and not by the attribute (e.g. bBorderDist for cells).
2315 */
2316
2317void SwBorderAttrs::CalcTopLine_()
2318{
2319 m_nTopLine = m_rBox.CalcLineSpace( SvxBoxItemLine::TOP, /*bEvenIfNoLine*/true );
2320 m_nTopLine = m_nTopLine + m_rShadow.CalcShadowSpace(SvxShadowItemSide::TOP);
2321 m_bTopLine = false;
2322}
2323
2324void SwBorderAttrs::CalcBottomLine_()
2325{
2326 m_nBottomLine = m_rBox.CalcLineSpace( SvxBoxItemLine::BOTTOM, true );
2327 m_nBottomLine = m_nBottomLine + m_rShadow.CalcShadowSpace(SvxShadowItemSide::BOTTOM);
2328 m_bBottomLine = false;
2329}
2330
2331void SwBorderAttrs::CalcLeftLine_()
2332{
2333 m_nLeftLine = m_rBox.CalcLineSpace( SvxBoxItemLine::LEFT, true);
2334 m_nLeftLine = m_nLeftLine + m_rShadow.CalcShadowSpace(SvxShadowItemSide::LEFT);
2335 m_bLeftLine = false;
2336}
2337
2338void SwBorderAttrs::CalcRightLine_()
2339{
2340 m_nRightLine = m_rBox.CalcLineSpace( SvxBoxItemLine::RIGHT, true );
2341 m_nRightLine = m_nRightLine + m_rShadow.CalcShadowSpace(SvxShadowItemSide::RIGHT);
2342 m_bRightLine = false;
2343}
2344
2345void SwBorderAttrs::IsLine_()
2346{
2347 m_bIsLine = m_rBox.GetTop() || m_rBox.GetBottom() ||
2348 m_rBox.GetLeft()|| m_rBox.GetRight();
2349 m_bLine = false;
2350}
2351
2352/* The borders of neighboring paragraphs are condensed by following algorithm:
2353 *
2354 * 1. No top border if the predecessor has the same top border and (3) applies.
2355 * In addition, the paragraph needs to have a border at least one side (left/right/bottom).
2356 * 2. No bottom border if the successor has the same bottom border and (3) applies.
2357 * In addition, the paragraph needs to have a border at least one side (left/right/top).
2358 * 3. The borders on the left and right side are identical between the current and the
2359 * pre-/succeeding paragraph.
2360 */
2361
2362static bool CmpLines( const editeng::SvxBorderLine *pL1, const editeng::SvxBorderLine *pL2 )
2363{
2364 return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) );
2365}
2366
2367// OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
2368// OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
2369// instead of only the right LR-spacing, because R2L-layout has to be
2370// considered.
2371bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
2372 const SwFrame *pCaller,
2373 const SwFrame *pCmp ) const
2374{
2375 return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft() ) &&
2376 CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) &&
2377 CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) &&
2378 // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
2379 CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) );
2380}
2381
2382bool SwBorderAttrs::JoinWithCmp( const SwFrame& _rCallerFrame,
2383 const SwFrame& _rCmpFrame ) const
2384{
2385 bool bReturnVal = false;
2386
2387 SwBorderAttrAccess aCmpAccess( SwFrame::GetCache(), &_rCmpFrame );
2388 const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get();
2389 if ( m_rShadow == rCmpAttrs.GetShadow() &&
2390 CmpLines( m_rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) &&
2391 CmpLines( m_rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) &&
2392 CmpLeftRight( rCmpAttrs, &_rCallerFrame, &_rCmpFrame )
2393 )
2394 {
2395 bReturnVal = true;
2396 }
2397
2398 return bReturnVal;
2399}
2400
2401// OD 21.05.2003 #108789# - method to determine, if borders are joined with
2402// previous frame. Calculated value saved in cached value <m_bJoinedWithPrev>
2403// OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame>
2404void SwBorderAttrs::CalcJoinedWithPrev( const SwFrame& _rFrame,
2405 const SwFrame* _pPrevFrame )
2406{
2407 // set default
2408 m_bJoinedWithPrev = false;
2409
2410 if ( _rFrame.IsTextFrame() )
2411 {
2412 // text frame can potentially join with previous text frame, if
2413 // corresponding attribute set is set at previous text frame.
2414 // OD 2004-02-26 #i25029# - If parameter <_pPrevFrame> is set, take this
2415 // one as previous frame.
2416 const SwFrame* pPrevFrame = _pPrevFrame ? _pPrevFrame : _rFrame.GetPrev();
2417 // OD 2004-02-13 #i25029# - skip hidden text frames.
2418 while ( pPrevFrame && pPrevFrame->IsTextFrame() &&
2419 static_cast<const SwTextFrame*>(pPrevFrame)->IsHiddenNow() )
2420 {
2421 pPrevFrame = pPrevFrame->GetPrev();
2422 }
2423 if ( pPrevFrame && pPrevFrame->IsTextFrame() &&
2424 pPrevFrame->GetAttrSet()->GetParaConnectBorder().GetValue()
2425 )
2426 {
2427 m_bJoinedWithPrev = JoinWithCmp( _rFrame, *pPrevFrame );
2428 }
2429 }
2430
2431 // valid cache status, if demanded
2432 // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrame>
2433 // is set.
2434 m_bCachedJoinedWithPrev = m_bCacheGetLine && !_pPrevFrame;
2435}
2436
2437// OD 21.05.2003 #108789# - method to determine, if borders are joined with
2438// next frame. Calculated value saved in cached value <m_bJoinedWithNext>
2439void SwBorderAttrs::CalcJoinedWithNext( const SwFrame& _rFrame )
2440{
2441 // set default
2442 m_bJoinedWithNext = false;
2443
2444 if ( _rFrame.IsTextFrame() )
2445 {
2446 // text frame can potentially join with next text frame, if
2447 // corresponding attribute set is set at current text frame.
2448 // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
2449 const SwFrame* pNextFrame = _rFrame.GetNext();
2450 while ( pNextFrame && pNextFrame->IsTextFrame() &&
2451 static_cast<const SwTextFrame*>(pNextFrame)->IsHiddenNow() )
2452 {
2453 pNextFrame = pNextFrame->GetNext();
2454 }
2455 if ( pNextFrame && pNextFrame->IsTextFrame() &&
2456 _rFrame.GetAttrSet()->GetParaConnectBorder().GetValue()
2457 )
2458 {
2459 m_bJoinedWithNext = JoinWithCmp( _rFrame, *pNextFrame );
2460 }
2461 }
2462
2463 // valid cache status, if demanded
2464 m_bCachedJoinedWithNext = m_bCacheGetLine;
2465}
2466
2467// OD 21.05.2003 #108789# - accessor for cached values <m_bJoinedWithPrev>
2468// OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame>, which is passed to
2469// method <_CalcJoindWithPrev(..)>.
2470bool SwBorderAttrs::JoinedWithPrev( const SwFrame& _rFrame,
2471 const SwFrame* _pPrevFrame ) const
2472{
2473 if ( !m_bCachedJoinedWithPrev || _pPrevFrame )
2474 {
2475 // OD 2004-02-26 #i25029# - pass <_pPrevFrame> as 2nd parameter
2476 const_cast<SwBorderAttrs*>(this)->CalcJoinedWithPrev( _rFrame, _pPrevFrame );
2477 }
2478
2479 return m_bJoinedWithPrev;
2480}
2481
2482bool SwBorderAttrs::JoinedWithNext( const SwFrame& _rFrame ) const
2483{
2484 if ( !m_bCachedJoinedWithNext )
2485 {
2486 const_cast<SwBorderAttrs*>(this)->CalcJoinedWithNext( _rFrame );
2487 }
2488
2489 return m_bJoinedWithNext;
2490}
2491
2492// OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrame>, which is passed to
2493// method <JoinedWithPrev>
2494void SwBorderAttrs::GetTopLine_( const SwFrame& _rFrame,
2495 const SwFrame* _pPrevFrame )
2496{
2497 sal_uInt16 nRet = CalcTopLine();
2498
2499 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2500 // OD 2004-02-26 #i25029# - add 2nd parameter
2501 if ( JoinedWithPrev( _rFrame, _pPrevFrame ) )
2502 {
2503 nRet = 0;
2504 }
2505
2506 m_bCachedGetTopLine = m_bCacheGetLine;
2507
2508 m_nGetTopLine = nRet;
2509}
2510
2511void SwBorderAttrs::GetBottomLine_( const SwFrame& _rFrame )
2512{
2513 sal_uInt16 nRet = CalcBottomLine();
2514
2515 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2516 if ( JoinedWithNext( _rFrame ) )
2517 {
2518 nRet = 0;
2519 }
2520
2521 m_bCachedGetBottomLine = m_bCacheGetLine;
2522
2523 m_nGetBottomLine = nRet;
2524}
2525
2526void SwBorderAttrs::CalcLineSpacing_()
2527{
2528 // tdf#125300 compatibility option AddParaLineSpacingToTableCells needs also line spacing
2529 const SvxLineSpacingItem &rSpace = m_rAttrSet.GetLineSpacing();
2530 if ( rSpace.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop && rSpace.GetPropLineSpace() > 100 )
2531 {
2532 sal_Int32 nFontSize = m_rAttrSet.Get(RES_CHRATR_FONTSIZE).GetHeight();
2533 m_nLineSpacing = nFontSize * (rSpace.GetPropLineSpace() - 100) * 1.15 / 100;
2534 }
2535 m_bLineSpacing = false;
2536}
2537
2538static SwModify const* GetCacheOwner(SwFrame const& rFrame)
2539{
2540 return rFrame.IsContentFrame()
2541 ? static_cast<SwModify const*>(rFrame.IsTextFrame()
2542 // sw_redlinehide: presumably this caches the border attrs at the model level and can be shared across different layouts so we want the ParaProps node here
2543 ? static_cast<const SwTextFrame&>(rFrame).GetTextNodeForParaProps()
2544 : static_cast<const SwNoTextFrame&>(rFrame).GetNode())
2545 : static_cast<SwModify const*>(static_cast<const SwLayoutFrame&>(rFrame).GetFormat());
2546}
2547
2548SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrame *pFrame ) :
2549 SwCacheAccess( rCach,
2550 static_cast<void const *>(GetCacheOwner(*pFrame)),
2551 GetCacheOwner(*pFrame)->IsInCache()),
2552 m_pConstructor( pFrame )
2553{
2554}
2555
2556SwCacheObj *SwBorderAttrAccess::NewObj()
2557{
2558 const_cast<SwModify *>(static_cast<SwModify const *>(m_pOwner))->SetInCache( true );
2559 return new SwBorderAttrs( static_cast<SwModify const *>(m_pOwner), m_pConstructor );
2560}
2561
2562SwBorderAttrs *SwBorderAttrAccess::Get()
2563{
2564 return static_cast<SwBorderAttrs*>(SwCacheAccess::Get());
2565}
2566
2567SwOrderIter::SwOrderIter( const SwPageFrame *pPg ) :
2568 m_pPage( pPg ),
2569 m_pCurrent( nullptr )
2570{
2571}
2572
2573void SwOrderIter::Top()
2574{
2575 m_pCurrent = nullptr;
2576 if ( !m_pPage->GetSortedObjs() )
2577 return;
2578
2579 const SwSortedObjs *pObjs = m_pPage->GetSortedObjs();
2580 if ( !pObjs->size() )
2581 return;
2582
2583 sal_uInt32 nTopOrd = 0;
2584 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating
2585 for (SwAnchoredObject* i : *pObjs)
2586 {
2587 const SdrObject* pObj = i->GetDrawObj();
2588 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr )
2589 continue;
2590 sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2591 if ( nTmp >= nTopOrd )
2592 {
2593 nTopOrd = nTmp;
2594 m_pCurrent = pObj;
2595 }
2596 }
2597}
2598
2599const SdrObject *SwOrderIter::Bottom()
2600{
2601 m_pCurrent = nullptr;
2602 if ( m_pPage->GetSortedObjs() )
2603 {
2604 sal_uInt32 nBotOrd = USHRT_MAX(32767 *2 +1);
2605 const SwSortedObjs *pObjs = m_pPage->GetSortedObjs();
2606 if ( pObjs->size() )
2607 {
2608 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating
2609 for (SwAnchoredObject* i : *pObjs)
2610 {
2611 const SdrObject* pObj = i->GetDrawObj();
2612 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr )
2613 continue;
2614 sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2615 if ( nTmp < nBotOrd )
2616 {
2617 nBotOrd = nTmp;
2618 m_pCurrent = pObj;
2619 }
2620 }
2621 }
2622 }
2623 return m_pCurrent;
2624}
2625
2626const SdrObject *SwOrderIter::Next()
2627{
2628 const sal_uInt32 nCurOrd = m_pCurrent ? m_pCurrent->GetOrdNumDirect() : 0;
2629 m_pCurrent = nullptr;
2630 if ( m_pPage->GetSortedObjs() )
2631 {
2632 sal_uInt32 nOrd = USHRT_MAX(32767 *2 +1);
2633 const SwSortedObjs *pObjs = m_pPage->GetSortedObjs();
2634 if ( pObjs->size() )
2635 {
2636 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating
2637 for (SwAnchoredObject* i : *pObjs)
2638 {
2639 const SdrObject* pObj = i->GetDrawObj();
2640 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr )
2641 continue;
2642 sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2643 if ( nTmp > nCurOrd && nTmp < nOrd )
2644 {
2645 nOrd = nTmp;
2646 m_pCurrent = pObj;
2647 }
2648 }
2649 }
2650 }
2651 return m_pCurrent;
2652}
2653
2654void SwOrderIter::Prev()
2655{
2656 const sal_uInt32 nCurOrd = m_pCurrent ? m_pCurrent->GetOrdNumDirect() : 0;
2657 m_pCurrent = nullptr;
2658 if ( !m_pPage->GetSortedObjs() )
2659 return;
2660
2661 const SwSortedObjs *pObjs = m_pPage->GetSortedObjs();
2662 if ( !pObjs->size() )
2663 return;
2664
2665 sal_uInt32 nOrd = 0;
2666 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating
2667 for (SwAnchoredObject* i : *pObjs)
2668 {
2669 const SdrObject* pObj = i->GetDrawObj();
2670 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr )
2671 continue;
2672 sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2673 if ( nTmp < nCurOrd && nTmp >= nOrd )
2674 {
2675 nOrd = nTmp;
2676 m_pCurrent = pObj;
2677 }
2678 }
2679}
2680
2681/// Keep and restore the substructure of a layout frame for an action.
2682// New algorithm:
2683// Do not look at each neighbor one by one to set all pointers correctly.
2684// It is sufficient to detach a part of a chain and check if another chain needs to be added
2685// when attaching it again. Only the pointers necessary for the chain connection need to be
2686// adjusted. The correction happens in RestoreContent(). In between all access is restricted.
2687// During this action, the Flys are detached from the page.
2688
2689// #115759# - 'remove' also drawing object from page and
2690// at-fly anchored objects from page
2691static void lcl_RemoveObjsFromPage( SwFrame* _pFrame )
2692{
2693 OSL_ENSURE( _pFrame->GetDrawObjs(), "no DrawObjs in lcl_RemoveObjsFromPage." )do { if (true && (!(_pFrame->GetDrawObjs()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "2693" ": "), "%s", "no DrawObjs in lcl_RemoveObjsFromPage."
); } } while (false)
;
2694 SwSortedObjs &rObjs = *_pFrame->GetDrawObjs();
2695 for (SwAnchoredObject* pObj : rObjs)
2696 {
2697 // #115759# - reset member, at which the anchored
2698 // object orients its vertical position
2699 pObj->ClearVertPosOrientFrame();
2700 // #i43913#
2701 pObj->ResetLayoutProcessBools();
2702 // #115759# - remove also lower objects of as-character
2703 // anchored Writer fly frames from page
2704 if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr )
2705 {
2706 SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj);
2707
2708 // #115759# - remove also direct lowers of Writer
2709 // fly frame from page
2710 if ( pFlyFrame->GetDrawObjs() )
2711 {
2712 ::lcl_RemoveObjsFromPage( pFlyFrame );
2713 }
2714
2715 SwContentFrame* pCnt = pFlyFrame->ContainsContent();
2716 while ( pCnt )
2717 {
2718 if ( pCnt->GetDrawObjs() )
2719 ::lcl_RemoveObjsFromPage( pCnt );
2720 pCnt = pCnt->GetNextContentFrame();
2721 }
2722 if ( pFlyFrame->IsFlyFreeFrame() )
2723 {
2724 // #i28701# - use new method <GetPageFrame()>
2725 if (SwPageFrame *pPg = pFlyFrame->GetPageFrame())
2726 pPg->RemoveFlyFromPage(pFlyFrame);
2727 }
2728 }
2729 // #115759# - remove also drawing objects from page
2730 else if ( dynamic_cast<const SwAnchoredDrawObject*>( pObj) != nullptr )
2731 {
2732 if (pObj->GetFrameFormat().GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR)
2733 {
2734 if (SwPageFrame *pPg = pObj->GetPageFrame())
2735 pPg->RemoveDrawObjFromPage(
2736 *static_cast<SwAnchoredDrawObject*>(pObj) );
2737 }
2738 }
2739 }
2740}
2741
2742SwFrame *SaveContent( SwLayoutFrame *pLay, SwFrame *pStart )
2743{
2744 if( pLay->IsSctFrame() && pLay->Lower() && pLay->Lower()->IsColumnFrame() )
2745 sw_RemoveFootnotes( static_cast<SwColumnFrame*>(pLay->Lower()), true, true );
2746
2747 SwFrame *pSav = pLay->ContainsAny();
2748 if ( nullptr == pSav )
2749 return nullptr;
2750
2751 if( pSav->IsInFootnote() && !pLay->IsInFootnote() )
2752 {
2753 do
2754 pSav = pSav->FindNext();
2755 while( pSav && pSav->IsInFootnote() );
2756 if( !pSav || !pLay->IsAnLower( pSav ) )
2757 return nullptr;
2758 }
2759
2760 // Tables should be saved as a whole, exception:
2761 // The contents of a section or a cell inside a table should be saved
2762 if ( pSav->IsInTab() && !( ( pLay->IsSctFrame() || pLay->IsCellFrame() ) && pLay->IsInTab() ) )
2763 while ( !pSav->IsTabFrame() )
2764 pSav = pSav->GetUpper();
2765
2766 if( pSav->IsInSct() )
2767 { // search the upmost section inside of pLay
2768 SwFrame* pSect = pLay->FindSctFrame();
2769 SwFrame *pTmp = pSav;
2770 do
2771 {
2772 pSav = pTmp;
2773 pTmp = (pSav && pSav->GetUpper()) ? pSav->GetUpper()->FindSctFrame() : nullptr;
2774 } while ( pTmp != pSect );
2775 }
2776
2777 SwFrame *pFloat = pSav;
2778 if( !pStart )
2779 pStart = pSav;
2780 bool bGo = pStart == pSav;
2781 do
2782 {
2783 if( bGo )
2784 pFloat->GetUpper()->m_pLower = nullptr; // detach the chain part
2785
2786 // search the end of the chain part, remove Flys on the way
2787 do
2788 {
2789 if( bGo )
2790 {
2791 if ( pFloat->IsContentFrame() )
2792 {
2793 if ( pFloat->GetDrawObjs() )
2794 ::lcl_RemoveObjsFromPage( static_cast<SwContentFrame*>(pFloat) );
2795 }
2796 else if ( pFloat->IsTabFrame() || pFloat->IsSctFrame() )
2797 {
2798 SwContentFrame *pCnt = static_cast<SwLayoutFrame*>(pFloat)->ContainsContent();
2799 if( pCnt )
2800 {
2801 do
2802 { if ( pCnt->GetDrawObjs() )
2803 ::lcl_RemoveObjsFromPage( pCnt );
2804 pCnt = pCnt->GetNextContentFrame();
2805 } while ( pCnt && static_cast<SwLayoutFrame*>(pFloat)->IsAnLower( pCnt ) );
2806 }
2807 }
2808 else {
2809 OSL_ENSURE( !pFloat, "new FloatFrame?" )do { if (true && (!(!pFloat))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "2809" ": "), "%s", "new FloatFrame?"); } } while (false
)
;
2810 }
2811 }
2812 if ( pFloat->GetNext() )
2813 {
2814 if( bGo )
2815 pFloat->mpUpper = nullptr;
2816 pFloat = pFloat->GetNext();
2817 if( !bGo && pFloat == pStart )
2818 {
2819 bGo = true;
2820 pFloat->mpPrev->mpNext = nullptr;
2821 pFloat->mpPrev = nullptr;
2822 }
2823 }
2824 else
2825 break;
2826
2827 } while ( pFloat );
2828
2829 // search next chain part and connect both chains
2830 SwFrame *pTmp = pFloat->FindNext();
2831 if( bGo )
2832 pFloat->mpUpper = nullptr;
2833
2834 if( !pLay->IsInFootnote() )
2835 while( pTmp && pTmp->IsInFootnote() )
2836 pTmp = pTmp->FindNext();
2837
2838 if ( !pLay->IsAnLower( pTmp ) )
2839 pTmp = nullptr;
2840
2841 if ( pTmp && bGo )
2842 {
2843 pFloat->mpNext = pTmp; // connect both chains
2844 pFloat->mpNext->mpPrev = pFloat;
2845 }
2846 pFloat = pTmp;
2847 bGo = bGo || ( pStart == pFloat );
2848 } while ( pFloat );
2849
2850 return bGo ? pStart : nullptr;
2851}
2852
2853// #115759# - add also drawing objects to page and at-fly
2854// anchored objects to page
2855static void lcl_AddObjsToPage( SwFrame* _pFrame, SwPageFrame* _pPage )
2856{
2857 OSL_ENSURE( _pFrame->GetDrawObjs(), "no DrawObjs in lcl_AddObjsToPage." )do { if (true && (!(_pFrame->GetDrawObjs()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "2857" ": "), "%s", "no DrawObjs in lcl_AddObjsToPage.")
; } } while (false)
;
2858 SwSortedObjs &rObjs = *_pFrame->GetDrawObjs();
2859 for (SwAnchoredObject* pObj : rObjs)
2860 {
2861 // #115759# - unlock position of anchored object
2862 // in order to get the object's position calculated.
2863 pObj->UnlockPosition();
2864 // #115759# - add also lower objects of as-character
2865 // anchored Writer fly frames from page
2866 if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr )
2867 {
2868 SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj);
2869 if ( dynamic_cast<const SwFlyFreeFrame*>( pObj) != nullptr )
2870 {
2871 _pPage->AppendFlyToPage( pFlyFrame );
2872 }
2873 pFlyFrame->InvalidatePos_();
2874 pFlyFrame->InvalidateSize_();
2875 pFlyFrame->InvalidatePage( _pPage );
2876
2877 // #115759# - add also at-fly anchored objects
2878 // to page
2879 if ( pFlyFrame->GetDrawObjs() )
2880 {
2881 ::lcl_AddObjsToPage( pFlyFrame, _pPage );
2882 }
2883
2884 SwContentFrame *pCnt = pFlyFrame->ContainsContent();
2885 while ( pCnt )
2886 {
2887 if ( pCnt->GetDrawObjs() )
2888 ::lcl_AddObjsToPage( pCnt, _pPage );
2889 pCnt = pCnt->GetNextContentFrame();
2890 }
2891 }
2892 // #115759# - remove also drawing objects from page
2893 else if ( dynamic_cast<const SwAnchoredDrawObject*>( pObj) != nullptr )
2894 {
2895 if (pObj->GetFrameFormat().GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR)
2896 {
2897 pObj->InvalidateObjPos();
2898 _pPage->AppendDrawObjToPage(
2899 *static_cast<SwAnchoredDrawObject*>(pObj) );
2900 }
2901 }
2902 }
2903}
2904
2905void RestoreContent( SwFrame *pSav, SwLayoutFrame *pParent, SwFrame *pSibling )
2906{
2907 OSL_ENSURE( pSav && pParent, "no Save or Parent provided for RestoreContent." )do { if (true && (!(pSav && pParent))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "2907" ": "), "%s", "no Save or Parent provided for RestoreContent."
); } } while (false)
;
2908 SwRectFnSet aRectFnSet(pParent);
2909
2910 // If there are already FlowFrames below the new parent, so add the chain (starting with pSav)
2911 // after the last one. The parts are inserted and invalidated if needed.
2912 // On the way, the Flys of the ContentFrames are registered at the page.
2913
2914 SwPageFrame *pPage = pParent->FindPageFrame();
2915
2916 if ( pPage )
2917 pPage->InvalidatePage( pPage );
2918
2919 // determine predecessor and establish connection or initialize
2920 pSav->mpPrev = pSibling;
2921 SwFrame* pNxt;
2922 if ( pSibling )
2923 {
2924 pNxt = pSibling->mpNext;
2925 pSibling->mpNext = pSav;
2926 pSibling->InvalidatePrt_();
2927 pSibling->InvalidatePage( pPage );
2928 SwFlowFrame *pFlowFrame = dynamic_cast<SwFlowFrame*>(pSibling);
2929 if (pFlowFrame && pFlowFrame->GetFollow())
2930 pSibling->Prepare( PrepareHint::Clear, nullptr, false );
2931 }
2932 else
2933 { pNxt = pParent->m_pLower;
2934 pParent->m_pLower = pSav;
2935 pSav->mpUpper = pParent; // set here already, so that it is explicit when invalidating
2936
2937 if ( pSav->IsContentFrame() )
2938 static_cast<SwContentFrame*>(pSav)->InvalidatePage( pPage );
2939 else
2940 { // pSav might be an empty SectFrame
2941 SwContentFrame* pCnt = pParent->ContainsContent();
2942 if( pCnt )
2943 pCnt->InvalidatePage( pPage );
2944 }
2945 }
2946
2947 // the parent needs to grow appropriately
2948 SwTwips nGrowVal = 0;
2949 SwFrame* pLast;
2950 do
2951 { pSav->mpUpper = pParent;
2952 nGrowVal += aRectFnSet.GetHeight(pSav->getFrameArea());
2953 pSav->InvalidateAll_();
2954
2955 // register Flys, if TextFrames than also invalidate appropriately
2956 if ( pSav->IsContentFrame() )
2957 {
2958 if ( pSav->IsTextFrame() &&
2959 static_cast<SwTextFrame*>(pSav)->GetCacheIdx() != USHRT_MAX(32767 *2 +1) )
2960 static_cast<SwTextFrame*>(pSav)->Init(); // I am its friend
2961
2962 if ( pPage && pSav->GetDrawObjs() )
2963 ::lcl_AddObjsToPage( static_cast<SwContentFrame*>(pSav), pPage );
2964 }
2965 else
2966 { SwContentFrame *pBlub = static_cast<SwLayoutFrame*>(pSav)->ContainsContent();
2967 if( pBlub )
2968 {
2969 do
2970 { if ( pPage && pBlub->GetDrawObjs() )
2971 ::lcl_AddObjsToPage( pBlub, pPage );
2972 if( pBlub->IsTextFrame() && static_cast<SwTextFrame*>(pBlub)->HasFootnote() &&
2973 static_cast<SwTextFrame*>(pBlub)->GetCacheIdx() != USHRT_MAX(32767 *2 +1) )
2974 static_cast<SwTextFrame*>(pBlub)->Init(); // I am its friend
2975 pBlub = pBlub->GetNextContentFrame();
2976 } while ( pBlub && static_cast<SwLayoutFrame*>(pSav)->IsAnLower( pBlub ));
2977 }
2978 }
2979 pLast = pSav;
2980 pSav = pSav->GetNext();
2981
2982 } while ( pSav );
2983
2984 if( pNxt )
2985 {
2986 pLast->mpNext = pNxt;
2987 pNxt->mpPrev = pLast;
2988 }
2989
2990 pParent->Grow( nGrowVal );
2991}
2992
2993namespace sw {
2994
2995bool IsRightPageByNumber(SwRootFrame const& rLayout, sal_uInt16 const nPageNum)
2996{
2997 assert(rLayout.GetLower())(static_cast <bool> (rLayout.GetLower()) ? void (0) : __assert_fail
("rLayout.GetLower()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 2997, __extension__ __PRETTY_FUNCTION__))
;
2998 // unfortunately can only get SwPageDesc, not SwFormatPageDesc here...
2999 auto const nFirstVirtPageNum(rLayout.GetLower()->GetVirtPageNum());
3000 bool const isFirstPageOfLayoutOdd(nFirstVirtPageNum % 2 == 1);
3001 return ((nPageNum % 2) == 1) == isFirstPageOfLayoutOdd;
3002}
3003
3004} // namespace sw
3005
3006SwPageFrame * InsertNewPage( SwPageDesc &rDesc, SwFrame *pUpper,
3007 bool const isRightPage, bool const bFirst, bool bInsertEmpty,
3008 bool const bFootnote,
3009 SwFrame *pSibling,
3010 bool const bVeryFirstPage )
3011{
3012 assert(pUpper)(static_cast <bool> (pUpper) ? void (0) : __assert_fail
("pUpper", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 3012, __extension__ __PRETTY_FUNCTION__))
;
3013 assert(pUpper->IsRootFrame())(static_cast <bool> (pUpper->IsRootFrame()) ? void (
0) : __assert_fail ("pUpper->IsRootFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 3013, __extension__ __PRETTY_FUNCTION__))
;
3014 assert(!pSibling || static_cast<SwLayoutFrame const*>(pUpper)->Lower() != pSibling)(static_cast <bool> (!pSibling || static_cast<SwLayoutFrame
const*>(pUpper)->Lower() != pSibling) ? void (0) : __assert_fail
("!pSibling || static_cast<SwLayoutFrame const*>(pUpper)->Lower() != pSibling"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
, 3014, __extension__ __PRETTY_FUNCTION__))
; // currently no insert before 1st page
3015 SwPageFrame *pRet;
3016 SwDoc *pDoc = static_cast<SwLayoutFrame*>(pUpper)->GetFormat()->GetDoc();
3017 if (bFirst)
3018 {
3019 if (rDesc.IsFirstShared())
3020 {
3021 // We need to fallback to left or right page format, decide it now.
3022 // FIXME: is this still needed?
3023 if (isRightPage)
3024 {
3025 rDesc.GetFirstMaster().SetFormatAttr( rDesc.GetMaster().GetHeader() );
3026 rDesc.GetFirstMaster().SetFormatAttr( rDesc.GetMaster().GetFooter() );
3027 // fdo#60250 copy margins for mirrored pages
3028 rDesc.GetFirstMaster().SetFormatAttr( rDesc.GetMaster().GetLRSpace() );
3029 }
3030 else
3031 {
3032 rDesc.GetFirstLeft().SetFormatAttr( rDesc.GetLeft().GetHeader() );
3033 rDesc.GetFirstLeft().SetFormatAttr( rDesc.GetLeft().GetFooter() );
3034 rDesc.GetFirstLeft().SetFormatAttr( rDesc.GetLeft().GetLRSpace() );
3035 }
3036 }
3037 }
3038 SwFrameFormat *pFormat(isRightPage ? rDesc.GetRightFormat(bFirst) : rDesc.GetLeftFormat(bFirst));
3039 // If there is no FrameFormat for this page, add an empty page
3040 if ( !pFormat )
3041 {
3042 pFormat = isRightPage ? rDesc.GetLeftFormat(bVeryFirstPage) : rDesc.GetRightFormat(bVeryFirstPage);
3043 OSL_ENSURE( pFormat, "Descriptor without any format?!" )do { if (true && (!(pFormat))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3043" ": "), "%s", "Descriptor without any format?!"); }
} while (false)
;
3044 bInsertEmpty = !bInsertEmpty;
3045 }
3046 if( bInsertEmpty )
3047 {
3048 SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ?
3049 static_cast<SwPageFrame*>(pSibling->GetPrev())->GetPageDesc() : &rDesc;
3050 pRet = new SwPageFrame( pDoc->GetEmptyPageFormat(), pUpper, pTmpDesc );
3051 SAL_INFO( "sw.pageframe", "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.pageframe")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "InsertNewPage - insert empty p: "
<< pRet << " d: " << pTmpDesc) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3051" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "InsertNewPage - insert empty p: " <<
pRet << " d: " << pTmpDesc), 0); } else { ::std::
ostringstream sal_detail_stream; sal_detail_stream << "InsertNewPage - insert empty p: "
<< pRet << " d: " << pTmpDesc; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3051" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "InsertNewPage - insert empty p: " << pRet <<
" d: " << pTmpDesc) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3051" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "InsertNewPage - insert empty p: " <<
pRet << " d: " << pTmpDesc), 0); } else { ::std::
ostringstream sal_detail_stream; sal_detail_stream << "InsertNewPage - insert empty p: "
<< pRet << " d: " << pTmpDesc; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3051" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3052 pRet->Paste( pUpper, pSibling );
3053 pRet->PreparePage( bFootnote );
3054 }
3055 pRet = new SwPageFrame( pFormat, pUpper, &rDesc );
3056 SAL_INFO( "sw.pageframe", "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.pageframe")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "InsertNewPage p: " <<
pRet << " d: " << &rDesc << " f: " <<
pFormat) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3056" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "InsertNewPage p: " << pRet <<
" d: " << &rDesc << " f: " << pFormat)
, 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "InsertNewPage p: " << pRet << " d: " <<
&rDesc << " f: " << pFormat; ::sal::detail::
log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3056" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "InsertNewPage p: " << pRet << " d: "
<< &rDesc << " f: " << pFormat) == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3056" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "InsertNewPage p: " << pRet <<
" d: " << &rDesc << " f: " << pFormat)
, 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "InsertNewPage p: " << pRet << " d: " <<
&rDesc << " f: " << pFormat; ::sal::detail::
log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3056" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3057 pRet->Paste( pUpper, pSibling );
3058 pRet->PreparePage( bFootnote );
3059 if ( pRet->GetNext() )
3060 SwRootFrame::AssertPageFlys( pRet );
3061 return pRet;
3062}
3063
3064/* The following two methods search the layout structure recursively and
3065 * register all Flys at the page that have a Frame in this structure as an anchor.
3066 */
3067
3068static void lcl_Regist( SwPageFrame *pPage, const SwFrame *pAnch )
3069{
3070 SwSortedObjs *pObjs = const_cast<SwSortedObjs*>(pAnch->GetDrawObjs());
3071 for (SwAnchoredObject* pObj : *pObjs)
3072 {
3073 if (SwFlyFrame* pFly = dynamic_cast<SwFlyFrame*>(pObj))
3074 {
3075 // register (not if already known)
3076 // #i28701# - use new method <GetPageFrame()>
3077 SwPageFrame *pPg = pFly->IsFlyFreeFrame()
3078 ? pFly->GetPageFrame() : pFly->FindPageFrame();
3079 if ( pPg != pPage )
3080 {
3081 if ( pPg )
3082 pPg->RemoveFlyFromPage( pFly );
3083 pPage->AppendFlyToPage( pFly );
3084 }
3085 ::RegistFlys( pPage, pFly );
3086 }
3087 else
3088 {
3089 // #i87493#
3090 if ( pPage != pObj->GetPageFrame() )
3091 {
3092 // #i28701#
3093 if (SwPageFrame *pPg = pObj->GetPageFrame())
3094 pPg->RemoveDrawObjFromPage( *pObj );
3095 pPage->AppendDrawObjToPage( *pObj );
3096 }
3097 }
3098
3099 const SwFlyFrame* pFly = pAnch->FindFlyFrame();
3100 if ( pFly &&
3101 pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() &&
3102 pObj->GetDrawObj()->getSdrPageFromSdrObject() )
3103 {
3104 //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
3105 pObj->DrawObj()->getSdrPageFromSdrObject()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(),
3106 pObj->GetDrawObj()->GetOrdNumDirect() );
3107 }
3108 }
3109}
3110
3111void RegistFlys( SwPageFrame *pPage, const SwLayoutFrame *pLay )
3112{
3113 if ( pLay->GetDrawObjs() )
3114 ::lcl_Regist( pPage, pLay );
3115 const SwFrame *pFrame = pLay->Lower();
3116 while ( pFrame )
3117 {
3118 if ( pFrame->IsLayoutFrame() )
3119 ::RegistFlys( pPage, static_cast<const SwLayoutFrame*>(pFrame) );
3120 else if ( pFrame->GetDrawObjs() )
3121 ::lcl_Regist( pPage, pFrame );
3122 pFrame = pFrame->GetNext();
3123 }
3124}
3125
3126/// Notify the background based on the difference between old and new rectangle
3127void Notify( SwFlyFrame *pFly, SwPageFrame *pOld, const SwRect &rOld,
3128 const SwRect* pOldPrt )
3129{
3130 const SwRect aFrame( pFly->GetObjRectWithSpaces() );
3131 if ( rOld.Pos() != aFrame.Pos() )
3132 { // changed position, invalidate old and new area
3133 if ( rOld.HasArea() &&
3134 rOld.Left()+pFly->GetFormat()->GetLRSpace().GetLeft() < FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) )
3135 {
3136 pFly->NotifyBackground( pOld, rOld, PrepareHint::FlyFrameLeave );
3137 }
3138 pFly->NotifyBackground( pFly->FindPageFrame(), aFrame, PrepareHint::FlyFrameArrive );
3139 }
3140 else if ( rOld.SSize() != aFrame.SSize() )
3141 { // changed size, invalidate the area that was left or is now overlapped
3142 // For simplicity, we purposely invalidate a Twip even if not needed.
3143
3144 SwViewShell *pSh = pFly->getRootFrame()->GetCurrShell();
3145 if( pSh && rOld.HasArea() )
3146 pSh->InvalidateWindows( rOld );
3147
3148 // #i51941# - consider case that fly frame isn't
3149 // registered at the old page <pOld>
3150 SwPageFrame* pPageFrame = pFly->FindPageFrame();
3151 if ( pOld != pPageFrame )
3152 {
3153 pFly->NotifyBackground( pPageFrame, aFrame, PrepareHint::FlyFrameArrive );
3154 }
3155
3156 if ( rOld.Left() != aFrame.Left() )
3157 {
3158 SwRect aTmp( rOld );
3159 aTmp.Union( aFrame );
3160 aTmp.Left( std::min(aFrame.Left(), rOld.Left()) );
3161 aTmp.Right( std::max(aFrame.Left(), rOld.Left()) );
3162 pFly->NotifyBackground( pOld, aTmp, PrepareHint::FlyFrameSizeChanged );
3163 }
3164 SwTwips nOld = rOld.Right();
3165 SwTwips nNew = aFrame.Right();
3166 if ( nOld != nNew )
3167 {
3168 SwRect aTmp( rOld );
3169 aTmp.Union( aFrame );
3170 aTmp.Left( std::min(nNew, nOld) );
3171 aTmp.Right( std::max(nNew, nOld) );
3172 pFly->NotifyBackground( pOld, aTmp, PrepareHint::FlyFrameSizeChanged );
3173 }
3174 if ( rOld.Top() != aFrame.Top() )
3175 {
3176 SwRect aTmp( rOld );
3177 aTmp.Union( aFrame );
3178 aTmp.Top( std::min(aFrame.Top(), rOld.Top()) );
3179 aTmp.Bottom( std::max(aFrame.Top(), rOld.Top()) );
3180 pFly->NotifyBackground( pOld, aTmp, PrepareHint::FlyFrameSizeChanged );
3181 }
3182 nOld = rOld.Bottom();
3183 nNew = aFrame.Bottom();
3184 if ( nOld != nNew )
3185 {
3186 SwRect aTmp( rOld );
3187 aTmp.Union( aFrame );
3188 aTmp.Top( std::min(nNew, nOld) );
3189 aTmp.Bottom( std::max(nNew, nOld) );
3190 pFly->NotifyBackground( pOld, aTmp, PrepareHint::FlyFrameSizeChanged );
3191 }
3192 }
3193 else if(pOldPrt && *pOldPrt != pFly->getFramePrintArea())
3194 {
3195 bool bNotifyBackground(pFly->GetFormat()->GetSurround().IsContour());
3196
3197 if(!bNotifyBackground &&
3198 pFly->IsFlyFreeFrame() &&
3199 static_cast< const SwFlyFreeFrame* >(pFly)->supportsAutoContour())
3200 {
3201 // RotateFlyFrame3: Also notify for FlyFrames which allow AutoContour
3202 bNotifyBackground = true;
3203 }
3204
3205 if(bNotifyBackground)
3206 {
3207 // #i24097#
3208 pFly->NotifyBackground( pFly->FindPageFrame(), aFrame, PrepareHint::FlyFrameArrive );
3209 }
3210 }
3211}
3212
3213static void lcl_CheckFlowBack( SwFrame* pFrame, const SwRect &rRect )
3214{
3215 SwTwips nBottom = rRect.Bottom();
3216 while( pFrame )
3217 {
3218 if( pFrame->IsLayoutFrame() )
3219 {
3220 if( rRect.IsOver( pFrame->getFrameArea() ) )
3221 lcl_CheckFlowBack( static_cast<SwLayoutFrame*>(pFrame)->Lower(), rRect );
3222 }
3223 else if( !pFrame->GetNext() && nBottom > pFrame->getFrameArea().Bottom() )
3224 {
3225 if( pFrame->IsContentFrame() && static_cast<SwContentFrame*>(pFrame)->HasFollow() )
3226 pFrame->InvalidateSize();
3227 else
3228 pFrame->InvalidateNextPos();
3229 }
3230 pFrame = pFrame->GetNext();
3231 }
3232}
3233
3234static void lcl_NotifyContent( const SdrObject *pThis, SwContentFrame *pCnt,
3235 const SwRect &rRect, const PrepareHint eHint )
3236{
3237 if ( !pCnt->IsTextFrame() )
3238 return;
3239
3240 SwRect aCntPrt( pCnt->getFramePrintArea() );
3241 aCntPrt.Pos() += pCnt->getFrameArea().Pos();
3242 if ( eHint == PrepareHint::FlyFrameAttributesChanged )
3243 {
3244 // #i35640# - use given rectangle <rRect> instead
3245 // of current bound rectangle
3246 if ( aCntPrt.IsOver( rRect ) )
3247 pCnt->Prepare( PrepareHint::FlyFrameAttributesChanged );
3248 }
3249 // #i23129# - only invalidate, if the text frame
3250 // printing area overlaps with the given rectangle.
3251 else if ( aCntPrt.IsOver( rRect ) )
3252 pCnt->Prepare( eHint, static_cast<void*>(&aCntPrt.Intersection_( rRect )) );
3253 if ( !pCnt->GetDrawObjs() )
3254 return;
3255
3256 const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
3257 for (SwAnchoredObject* pObj : rObjs)
3258 {
3259 if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr )
3260 {
3261 SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pObj);
3262 if ( pFly->IsFlyInContentFrame() )
3263 {
3264 SwContentFrame *pContent = pFly->ContainsContent();
3265 while ( pContent )
3266 {
3267 ::lcl_NotifyContent( pThis, pContent, rRect, eHint );
3268 pContent = pContent->GetNextContentFrame();
3269 }
3270 }
3271 }
3272 }
3273}
3274
3275void Notify_Background( const SdrObject* pObj,
3276 SwPageFrame* pPage,
3277 const SwRect& rRect,
3278 const PrepareHint eHint,
3279 const bool bInva )
3280{
3281 // If the frame was positioned correctly for the first time, do not inform the old area
3282 if ( eHint == PrepareHint::FlyFrameLeave && rRect.Top() == FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) )
3283 return;
3284
3285 SwLayoutFrame* pArea;
3286 SwFlyFrame *pFlyFrame = nullptr;
3287 SwFrame* pAnchor;
3288 if( auto pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>( pObj) )
3289 {
3290 pFlyFrame = const_cast<SwVirtFlyDrawObj*>(pVirtFlyDrawObj)->GetFlyFrame();
3291 pAnchor = pFlyFrame->AnchorFrame();
3292 }
3293 else
3294 {
3295 pFlyFrame = nullptr;
3296 pAnchor = const_cast<SwFrame*>(
3297 GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrame() );
3298 }
3299 if( PrepareHint::FlyFrameLeave != eHint && pAnchor->IsInFly() )
3300 pArea = pAnchor->FindFlyFrame();
3301 else
3302 pArea = pPage;
3303 SwContentFrame *pCnt = nullptr;
3304 if ( pArea )
3305 {
3306 if( PrepareHint::FlyFrameArrive != eHint )
3307 lcl_CheckFlowBack( pArea, rRect );
3308
3309 // Only the Flys following this anchor are reacting. Thus, those do not
3310 // need to be processed.
3311 // An exception is LEAVE, since the Fly might come "from above".
3312 // If the anchor is positioned on the previous page, the whole page
3313 // needs to be processed (47722).
3314 // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
3315 // on the object positioning, the complete area has to be processed,
3316 // because content frames before the anchor frame also have to consider
3317 // the object for the text wrapping.
3318 // #i3317# - The complete area has always been
3319 // processed.
3320 {
3321 pCnt = pArea->ContainsContent();
3322 }
3323 }
3324 SwFrame *pLastTab = nullptr;
3325
3326 bool isValidTableBeforeAnchor(false);
3327 while ( pCnt && pArea && pArea->IsAnLower( pCnt ) )
3328 {
3329 ::lcl_NotifyContent( pObj, pCnt, rRect, eHint );
3330 if ( pCnt->IsInTab() )
3331 {
3332 SwTabFrame *pTab = pCnt->FindTabFrame();
3333 if ( pTab != pLastTab )
3334 {
3335 pLastTab = pTab;
3336 isValidTableBeforeAnchor = false;
3337 if (PrepareHint::FlyFrameArrive == eHint
3338 && pFlyFrame // TODO: do it for draw objects too?
3339 && pTab->IsFollow() // table starts on previous page?
3340 // "through" means they will actually overlap anyway
3341 && css::text::WrapTextMode_THROUGH != pFlyFrame->GetFormat()->GetSurround().GetSurround()
3342 // if it's anchored in footer it can't move to other page
3343 && !pAnchor->FindFooterOrHeader())
3344 {
3345 SwFrame * pTmp(pAnchor->GetPrev());
3346 while (pTmp)
3347 {
3348 if (pTmp == pTab)
3349 {
3350 // tdf#99460 the table shouldn't be moved by the fly
3351 isValidTableBeforeAnchor = true;
3352 break;
3353 }
3354 pTmp = pTmp->GetPrev();
3355 }
3356 }
3357 // #i40606# - use <GetLastBoundRect()>
3358 // instead of <GetCurrentBoundRect()>, because a recalculation
3359 // of the bounding rectangle isn't intended here.
3360 if (!isValidTableBeforeAnchor
3361 && (pTab->getFrameArea().IsOver(pObj->GetLastBoundRect()) ||
3362 pTab->getFrameArea().IsOver(rRect)))
3363 {
3364 if ( !pFlyFrame || !pFlyFrame->IsLowerOf( pTab ) )
3365 pTab->InvalidatePrt();
3366 }
3367 }
3368 SwLayoutFrame* pCell = pCnt->GetUpper();
3369 // #i40606# - use <GetLastBoundRect()>
3370 // instead of <GetCurrentBoundRect()>, because a recalculation
3371 // of the bounding rectangle isn't intended here.
3372 if (!isValidTableBeforeAnchor && pCell->IsCellFrame() &&
3373 ( pCell->getFrameArea().IsOver( pObj->GetLastBoundRect() ) ||
3374 pCell->getFrameArea().IsOver( rRect ) ) )
3375 {
3376 const SwFormatVertOrient &rOri = pCell->GetFormat()->GetVertOrient();
3377 if ( text::VertOrientation::NONE != rOri.GetVertOrient() )
3378 pCell->InvalidatePrt();
3379 }
3380 }
3381 pCnt = pCnt->GetNextContentFrame();
3382 }
3383 // #128702# - make code robust
3384 if ( pPage && pPage->GetSortedObjs() )
3385 {
3386 pObj->GetOrdNum();
3387 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
3388 for (SwAnchoredObject* pAnchoredObj : rObjs)
3389 {
3390 if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) != nullptr )
3391 {
3392 if( pAnchoredObj->GetDrawObj() == pObj )
3393 continue;
3394 SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
3395 if ( pFly->getFrameArea().Top() == FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) )
3396 continue;
3397
3398 if ( !pFlyFrame ||
3399 (!pFly->IsLowerOf( pFlyFrame ) &&
3400 pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect()))
3401 {
3402 pCnt = pFly->ContainsContent();
3403 while ( pCnt )
3404 {
3405 ::lcl_NotifyContent( pObj, pCnt, rRect, eHint );
3406 pCnt = pCnt->GetNextContentFrame();
3407 }
3408 }
3409 if( pFly->IsFlyLayFrame() )
3410 {
3411 if( pFly->Lower() && pFly->Lower()->IsColumnFrame() &&
3412 pFly->getFrameArea().Bottom() >= rRect.Top() &&
3413 pFly->getFrameArea().Top() <= rRect.Bottom() &&
3414 pFly->getFrameArea().Right() >= rRect.Left() &&
3415 pFly->getFrameArea().Left() <= rRect.Right() )
3416 {
3417 pFly->InvalidateSize();
3418 }
3419 }
3420 // Flys above myself might sidestep if they have an automatic
3421 // alignment. This happens independently of my attributes since
3422 // this might have been changed as well.
3423 else if ( pFly->IsFlyAtContentFrame() &&
3424 pObj->GetOrdNumDirect() <
3425 pFly->GetVirtDrawObj()->GetOrdNumDirect() &&
3426 pFlyFrame && !pFly->IsLowerOf( pFlyFrame ) )
3427 {
3428 const SwFormatHoriOrient &rH = pFly->GetFormat()->GetHoriOrient();
3429 if ( text::HoriOrientation::NONE != rH.GetHoriOrient() &&
3430 text::HoriOrientation::CENTER != rH.GetHoriOrient() &&
3431 ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) &&
3432 (pFly->getFrameArea().Bottom() >= rRect.Top() &&
3433 pFly->getFrameArea().Top() <= rRect.Bottom()) )
3434 pFly->InvalidatePos();
3435 }
3436 }
3437 }
3438 }
3439 if ( pFlyFrame && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT
3440 pAnchor->GetUpper()->InvalidateSize();
3441
3442 // #i82258# - make code robust
3443 SwViewShell* pSh = nullptr;
3444 if ( bInva && pPage &&
3445 nullptr != (pSh = pPage->getRootFrame()->GetCurrShell()) )
3446 {
3447 pSh->InvalidateWindows( rRect );
3448 }
3449}
3450
3451/// Provides the Upper of an anchor in paragraph-bound objects. If the latter
3452/// is a chained border or a footnote, the "virtual" Upper might be returned.
3453const SwFrame* GetVirtualUpper( const SwFrame* pFrame, const Point& rPos )
3454{
3455 if( pFrame->IsTextFrame() )
3456 {
3457 pFrame = pFrame->GetUpper();
3458 if( !pFrame->getFrameArea().IsInside( rPos ) )
3459 {
3460 if( pFrame->IsFootnoteFrame() )
3461 {
3462 const SwFootnoteFrame* pTmp = static_cast<const SwFootnoteFrame*>(pFrame)->GetFollow();
3463 while( pTmp )
3464 {
3465 if( pTmp->getFrameArea().IsInside( rPos ) )
3466 return pTmp;
3467 pTmp = pTmp->GetFollow();
3468 }
3469 }
3470 else
3471 {
3472 SwFlyFrame* pTmp = const_cast<SwFlyFrame*>(pFrame->FindFlyFrame());
3473 while( pTmp )
3474 {
3475 if( pTmp->getFrameArea().IsInside( rPos ) )
3476 return pTmp;
3477 pTmp = pTmp->GetNextLink();
3478 }
3479 }
3480 }
3481 }
3482 return pFrame;
3483}
3484
3485bool Is_Lower_Of(const SwFrame *pCurrFrame, const SdrObject* pObj)
3486{
3487 Point aPos;
3488 const SwFrame* pFrame;
3489 if (const SwVirtFlyDrawObj *pFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>(pObj))
1
Assuming 'pFlyDrawObj' is null
2
Taking false branch
3490 {
3491 const SwFlyFrame* pFly = pFlyDrawObj->GetFlyFrame();
3492 pFrame = pFly->GetAnchorFrame();
3493 aPos = pFly->getFrameArea().Pos();
3494 }
3495 else
3496 {
3497 pFrame = static_cast<SwDrawContact*>(GetUserCall(pObj))->GetAnchorFrame(pObj);
3498 aPos = pObj->GetCurrentBoundRect().TopLeft();
3
Called C++ object pointer is null
3499 }
3500 OSL_ENSURE( pFrame, "8-( Fly is lost in Space." )do { if (true && (!(pFrame))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3500" ": "), "%s", "8-( Fly is lost in Space."); } } while
(false)
;
3501 pFrame = GetVirtualUpper( pFrame, aPos );
3502 do
3503 { if ( pFrame == pCurrFrame )
3504 return true;
3505 if( pFrame->IsFlyFrame() )
3506 {
3507 aPos = pFrame->getFrameArea().Pos();
3508 pFrame = GetVirtualUpper( static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame(), aPos );
3509 }
3510 else
3511 pFrame = pFrame->GetUpper();
3512 } while ( pFrame );
3513 return false;
3514}
3515
3516/// provides the area of a frame in that no Fly from another area can overlap
3517const SwFrame *FindContext( const SwFrame *pFrame, SwFrameType nAdditionalContextType )
3518{
3519 const SwFrameType nTyp = SwFrameType::Root | SwFrameType::Header | SwFrameType::Footer | SwFrameType::FtnCont |
3520 SwFrameType::Ftn | SwFrameType::Fly |
3521 SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell |
3522 nAdditionalContextType;
3523 do
3524 { if ( pFrame->GetType() & nTyp )
3525 break;
3526 pFrame = pFrame->GetUpper();
3527 } while( pFrame );
3528 return pFrame;
3529}
3530
3531bool IsFrameInSameContext( const SwFrame *pInnerFrame, const SwFrame *pFrame )
3532{
3533 const SwFrame *pContext = FindContext( pInnerFrame, SwFrameType::None );
3534
3535 const SwFrameType nTyp = SwFrameType::Root | SwFrameType::Header | SwFrameType::Footer | SwFrameType::FtnCont |
3536 SwFrameType::Ftn | SwFrameType::Fly |
3537 SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell;
3538 do
3539 { if ( pFrame->GetType() & nTyp )
3540 {
3541 if( pFrame == pContext )
3542 return true;
3543 if( pFrame->IsCellFrame() )
3544 return false;
3545 }
3546 if( pFrame->IsFlyFrame() )
3547 {
3548 Point aPos( pFrame->getFrameArea().Pos() );
3549 pFrame = GetVirtualUpper( static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame(), aPos );
3550 }
3551 else
3552 pFrame = pFrame->GetUpper();
3553 } while( pFrame );
3554
3555 return false;
3556}
3557
3558static SwTwips lcl_CalcCellRstHeight( SwLayoutFrame *pCell )
3559{
3560 SwFrame *pLow = pCell->Lower();
3561 if ( pLow && (pLow->IsContentFrame() || pLow->IsSctFrame()) )
3562 {
3563 long nHeight = 0, nFlyAdd = 0;
3564 do
3565 {
3566 long nLow = pLow->getFrameArea().Height();
3567 if( pLow->IsTextFrame() && static_cast<SwTextFrame*>(pLow)->IsUndersized() )
3568 nLow += static_cast<SwTextFrame*>(pLow)->GetParHeight()-pLow->getFramePrintArea().Height();
3569 else if( pLow->IsSctFrame() && static_cast<SwSectionFrame*>(pLow)->IsUndersized() )
3570 nLow += static_cast<SwSectionFrame*>(pLow)->Undersize();
3571 nFlyAdd = std::max( 0L, nFlyAdd - nLow );
3572 nFlyAdd = std::max( nFlyAdd, ::CalcHeightWithFlys( pLow ) );
3573 nHeight += nLow;
3574 pLow = pLow->GetNext();
3575 } while ( pLow );
3576 if ( nFlyAdd )
3577 nHeight += nFlyAdd;
3578
3579 // The border cannot be calculated based on PrtArea and Frame, since both can be invalid.
3580 SwBorderAttrAccess aAccess( SwFrame::GetCache(), pCell );
3581 const SwBorderAttrs &rAttrs = *aAccess.Get();
3582 nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
3583
3584 return pCell->getFrameArea().Height() - nHeight;
3585 }
3586 else
3587 {
3588 long nRstHeight = 0;
3589 while (pLow && pLow->IsLayoutFrame())
3590 {
3591 nRstHeight += ::CalcRowRstHeight(static_cast<SwLayoutFrame*>(pLow));
3592 pLow = pLow->GetNext();
3593 }
3594 return nRstHeight;
3595 }
3596}
3597
3598SwTwips CalcRowRstHeight( SwLayoutFrame *pRow )
3599{
3600 SwFrame *pLow = pRow->Lower();
3601 if (!(pLow && pLow->IsLayoutFrame()))
3602 {
3603 return 0;
3604 }
3605 SwTwips nRstHeight = LONG_MAX9223372036854775807L;
3606 while (pLow && pLow->IsLayoutFrame())
3607 {
3608 nRstHeight = std::min(nRstHeight, ::lcl_CalcCellRstHeight(static_cast<SwLayoutFrame*>(pLow)));
3609 pLow = pLow->GetNext();
3610 }
3611 return nRstHeight;
3612}
3613
3614const SwFrame* FindPage( const SwRect &rRect, const SwFrame *pPage )
3615{
3616 if ( !rRect.IsOver( pPage->getFrameArea() ) )
3617 {
3618 const SwRootFrame* pRootFrame = static_cast<const SwRootFrame*>(pPage->GetUpper());
3619 const SwFrame* pTmpPage = pRootFrame ? pRootFrame->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : nullptr;
3620 if ( pTmpPage )
3621 pPage = pTmpPage;
3622 }
3623
3624 return pPage;
3625}
3626
3627namespace {
3628
3629class SwFrameHolder : private SfxListener
3630{
3631 SwFrame* pFrame;
3632 bool bSet;
3633 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
3634public:
3635 SwFrameHolder() : pFrame(nullptr), bSet(false) {}
3636 void SetFrame( SwFrame* pHold );
3637 SwFrame* GetFrame() { return pFrame; }
3638 void Reset();
3639 bool IsSet() const { return bSet; }
3640};
3641
3642}
3643
3644void SwFrameHolder::SetFrame( SwFrame* pHold )
3645{
3646 bSet = true;
3647 if (pFrame != pHold)
3648 {
3649 if (pFrame)
3650 EndListening(*pFrame);
3651 StartListening(*pHold);
3652 pFrame = pHold;
3653 }
3654}
3655
3656void SwFrameHolder::Reset()
3657{
3658 if (pFrame)
3659 EndListening(*pFrame);
3660 bSet = false;
3661 pFrame = nullptr;
3662}
3663
3664void SwFrameHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
3665{
3666 if ( rHint.GetId() == SfxHintId::Dying && &rBC == pFrame )
3667 {
3668 pFrame = nullptr;
3669 }
3670}
3671
3672SwFrame* GetFrameOfModify(SwRootFrame const*const pLayout, SwModify const& rMod,
3673 SwFrameType const nFrameType, SwPosition const*const pPos,
3674 std::pair<Point, bool> const*const pViewPosAndCalcFrame)
3675{
3676 SwFrame *pMinFrame = nullptr, *pTmpFrame;
3677 SwFrameHolder aHolder;
3678 SwRect aCalcRect;
3679 bool bClientIterChanged = false;
3680
3681 SwIterator<SwFrame, SwModify, sw::IteratorMode::UnwrapMulti> aIter(rMod);
3682 do {
3683 pMinFrame = nullptr;
3684 aHolder.Reset();
3685 sal_uInt64 nMinDist = 0;
3686 bClientIterChanged = false;
3687
3688 for( pTmpFrame = aIter.First(); pTmpFrame; pTmpFrame = aIter.Next() )
3689 {
3690 if( pTmpFrame->GetType() & nFrameType &&
3691 ( !pLayout || pLayout == pTmpFrame->getRootFrame() ) &&
3692 (!pTmpFrame->IsFlowFrame() ||
3693 !SwFlowFrame::CastFlowFrame( pTmpFrame )->IsFollow() ))
3694 {
3695 if (pViewPosAndCalcFrame)
3696 {
3697 // watch for Frame being deleted
3698 if ( pMinFrame )
3699 aHolder.SetFrame( pMinFrame );
3700 else
3701 aHolder.Reset();
3702
3703 if (pViewPosAndCalcFrame->second)
3704 {
3705 // tdf#108118 prevent recursion
3706 DisableCallbackAction a(*pTmpFrame->getRootFrame());
3707 // - format parent Writer
3708 // fly frame, if it isn't been formatted yet.
3709 // Note: The Writer fly frame could be the frame itself.
3710 SwFlyFrame* pFlyFrame( pTmpFrame->FindFlyFrame() );
3711 if ( pFlyFrame &&
3712 pFlyFrame->getFrameArea().Pos().X() == FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) &&
3713 pFlyFrame->getFrameArea().Pos().Y() == FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) )
3714 {
3715 SwObjectFormatter::FormatObj( *pFlyFrame );
3716 }
3717 pTmpFrame->Calc(pLayout ? pLayout->GetCurrShell()->GetOut() : nullptr);
3718 }
3719
3720 // aIter.IsChanged checks if the current pTmpFrame has been deleted while
3721 // it is the current iterator
3722 // FrameHolder watches for deletion of the current pMinFrame
3723 if( aIter.IsChanged() || ( aHolder.IsSet() && !aHolder.GetFrame() ) )
3724 {
3725 // restart iteration
3726 bClientIterChanged = true;
3727 break;
3728 }
3729
3730 // for Flys go via the parent if the Fly is not yet "formatted"
3731 if (!pViewPosAndCalcFrame->second &&
3732 pTmpFrame->GetType() & SwFrameType::Fly &&
3733 static_cast<SwFlyFrame*>(pTmpFrame)->GetAnchorFrame() &&
3734 FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) == pTmpFrame->getFrameArea().Pos().getX() &&
3735 FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) == pTmpFrame->getFrameArea().Pos().getY() )
3736 aCalcRect = static_cast<SwFlyFrame*>(pTmpFrame)->GetAnchorFrame()->getFrameArea();
3737 else
3738 aCalcRect = pTmpFrame->getFrameArea();
3739
3740 if (aCalcRect.IsInside(pViewPosAndCalcFrame->first))
3741 {
3742 pMinFrame = pTmpFrame;
3743 break;
3744 }
3745
3746 // Point not in rectangle. Compare distances:
3747 const Point aCalcRectCenter = aCalcRect.Center();
3748 const Point aDiff = aCalcRectCenter - pViewPosAndCalcFrame->first;
3749 const sal_uInt64 nCurrentDist = sal_Int64(aDiff.getX()) * sal_Int64(aDiff.getX()) + sal_Int64(aDiff.getY()) * sal_Int64(aDiff.getY()); // opt: no sqrt
3750 if ( !pMinFrame || nCurrentDist < nMinDist )
3751 {
3752 pMinFrame = pTmpFrame;
3753 nMinDist = nCurrentDist;
3754 }
3755 }
3756 else
3757 {
3758 // if no pViewPosAndCalcFrame is provided, take the first one
3759 pMinFrame = pTmpFrame;
3760 break;
3761 }
3762 }
3763 }
3764 } while( bClientIterChanged );
3765
3766 if( pPos && pMinFrame && pMinFrame->IsTextFrame() )
3767 return static_cast<SwTextFrame*>(pMinFrame)->GetFrameAtPos( *pPos );
3768
3769 return pMinFrame;
3770}
3771
3772bool IsExtraData( const SwDoc *pDoc )
3773{
3774 const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo();
3775 return rInf.IsPaintLineNumbers() ||
3776 rInf.IsCountInFlys() ||
3777 (static_cast<sal_Int16>(SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetRedlineMarkPos()) != text::HoriOrientation::NONE &&
3778 !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty());
3779}
3780
3781// OD 22.09.2003 #110978#
3782SwRect SwPageFrame::PrtWithoutHeaderAndFooter() const
3783{
3784 SwRect aPrtWithoutHeaderFooter( getFramePrintArea() );
3785 aPrtWithoutHeaderFooter.Pos() += getFrameArea().Pos();
3786
3787 const SwFrame* pLowerFrame = Lower();
3788 while ( pLowerFrame )
3789 {
3790 // Note: independent on text direction page header and page footer are
3791 // always at top respectively at bottom of the page frame.
3792 if ( pLowerFrame->IsHeaderFrame() )
3793 {
3794 aPrtWithoutHeaderFooter.AddTop( pLowerFrame->getFrameArea().Height() );
3795 }
3796 if ( pLowerFrame->IsFooterFrame() )
3797 {
3798 aPrtWithoutHeaderFooter.AddBottom( - pLowerFrame->getFrameArea().Height() );
3799 }
3800
3801 pLowerFrame = pLowerFrame->GetNext();
3802 }
3803
3804 return aPrtWithoutHeaderFooter;
3805}
3806
3807/** method to determine the spacing values of a frame
3808
3809 OD 2004-03-10 #i28701#
3810 OD 2009-08-28 #i102458#
3811 Add output parameter <obIsLineSpacingProportional>
3812*/
3813void GetSpacingValuesOfFrame( const SwFrame& rFrame,
3814 SwTwips& onLowerSpacing,
3815 SwTwips& onLineSpacing,
3816 bool& obIsLineSpacingProportional,
3817 bool bIdenticalStyles )
3818{
3819 if ( !rFrame.IsFlowFrame() )
3820 {
3821 onLowerSpacing = 0;
3822 onLineSpacing = 0;
3823 }
3824 else
3825 {
3826 const SvxULSpaceItem& rULSpace = rFrame.GetAttrSet()->GetULSpace();
3827 // check contextual spacing if the style of actual and next paragraphs are identical
3828 if (bIdenticalStyles)
3829 onLowerSpacing = (rULSpace.GetContext() ? 0 : rULSpace.GetLower());
3830 else
3831 onLowerSpacing = rULSpace.GetLower();
3832
3833 onLineSpacing = 0;
3834 obIsLineSpacingProportional = false;
3835 if ( rFrame.IsTextFrame() )
3836 {
3837 onLineSpacing = static_cast<const SwTextFrame&>(rFrame).GetLineSpace();
3838 obIsLineSpacingProportional =
3839 onLineSpacing != 0 &&
3840 static_cast<const SwTextFrame&>(rFrame).GetLineSpace( true ) == 0;
3841 }
3842
3843 OSL_ENSURE( onLowerSpacing >= 0 && onLineSpacing >= 0,do { if (true && (!(onLowerSpacing >= 0 &&
onLineSpacing >= 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3844" ": "), "%s", "<GetSpacingValuesOfFrame(..)> - spacing values aren't positive!"
); } } while (false)
3844 "<GetSpacingValuesOfFrame(..)> - spacing values aren't positive!" )do { if (true && (!(onLowerSpacing >= 0 &&
onLineSpacing >= 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx"
":" "3844" ": "), "%s", "<GetSpacingValuesOfFrame(..)> - spacing values aren't positive!"
); } } while (false)
;
3845 }
3846}
3847
3848/// get the content of the table cell, skipping content from nested tables
3849const SwContentFrame* GetCellContent( const SwLayoutFrame& rCell )
3850{
3851 const SwContentFrame* pContent = rCell.ContainsContent();
3852 const SwTabFrame* pTab = rCell.FindTabFrame();
3853
3854 while ( pContent && rCell.IsAnLower( pContent ) )
3855 {
3856 const SwTabFrame* pTmpTab = pContent->FindTabFrame();
3857 if ( pTmpTab != pTab )
3858 {
3859 SwFrame const*const pTmp = pTmpTab->FindLastContentOrTable();
3860 if (pTmp)
3861 {
3862 pContent = pTmp->FindNextCnt();
3863 }
3864 else
3865 {
3866 pContent = nullptr;
3867 }
3868 }
3869 else
3870 break;
3871 }
3872 return pContent;
3873}
3874
3875SwDeletionChecker::SwDeletionChecker(const SwFrame* pFrame)
3876 : mpFrame( pFrame )
3877 , mpRegIn( pFrame
3878 ? pFrame->IsTextFrame()
3879 // sw_redlinehide: GetDep() may be a member of SwTextFrame!
3880 ? static_cast<SwTextFrame const*>(pFrame)->GetTextNodeFirst()
3881 : const_cast<SwFrame*>(pFrame)->GetDep()
3882 : nullptr )
3883{
3884}
3885
3886/// Can be used to check if a frame has been deleted
3887bool SwDeletionChecker::HasBeenDeleted() const
3888{
3889 if ( !mpFrame || !mpRegIn )
3890 return false;
3891
3892 SwIterator<SwFrame, SwModify, sw::IteratorMode::UnwrapMulti> aIter(*mpRegIn);
3893 SwFrame* pLast = aIter.First();
3894 while ( pLast )
3895 {
3896 if ( pLast == mpFrame )
3897 return false;
3898 pLast = aIter.Next();
3899 }
3900
3901 return true;
3902}
3903
3904/* vim:set shiftwidth=4 softtabstop=4 expandtab: */