Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx
Warning:line 3373, column 50
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

/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() )
18
Taking true branch
3238 return;
19
Returning without writing to 'pCnt->mbInfTab', which participates in a condition later
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) )
1
Assuming 'eHint' is not equal to FlyFrameLeave
3283 return;
3284
3285 SwLayoutFrame* pArea;
3286 SwFlyFrame *pFlyFrame = nullptr;
3287 SwFrame* pAnchor;
3288 if( auto pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>( pObj) )
2
Assuming 'pVirtFlyDrawObj' is null
3
Taking false branch
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
3.1
'eHint' is not equal to FlyFrameLeave
3.1
'eHint' is not equal to FlyFrameLeave
&& pAnchor->IsInFly() )
4
Calling 'SwFrame::IsInFly'
8
Returning from 'SwFrame::IsInFly'
9
Assuming the condition is false
10
Taking false branch
3300 pArea = pAnchor->FindFlyFrame();
3301 else
3302 pArea = pPage;
3303 SwContentFrame *pCnt = nullptr;
3304 if ( pArea )
11
Assuming 'pArea' is non-null
12
Taking true branch
3305 {
3306 if( PrepareHint::FlyFrameArrive != eHint )
13
Assuming 'eHint' is equal to FlyFrameArrive
14
Taking false branch
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
15.1
'pArea' is non-null
15.1
'pArea' is non-null
&& pArea->IsAnLower( pCnt ) )
15
Assuming 'pCnt' is non-null
16
Loop condition is true. Entering loop body
3328 {
3329 ::lcl_NotifyContent( pObj, pCnt, rRect, eHint );
17
Calling 'lcl_NotifyContent'
20
Returning from 'lcl_NotifyContent'
3330 if ( pCnt->IsInTab() )
21
Calling 'SwFrame::IsInTab'
25
Returning from 'SwFrame::IsInTab'
26
Assuming the condition is true
27
Taking true branch
3331 {
3332 SwTabFrame *pTab = pCnt->FindTabFrame();
3333 if ( pTab != pLastTab )
28
Assuming 'pTab' is equal to 'pLastTab'
29
Taking false branch
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
29.1
'isValidTableBeforeAnchor' is false
29.1
'isValidTableBeforeAnchor' is false
&& pCell->IsCellFrame() &&
30
Calling 'SwFrame::IsCellFrame'
33
Returning from 'SwFrame::IsCellFrame'
3373 ( pCell->getFrameArea().IsOver( pObj->GetLastBoundRect() ) ||
34
Called C++ object pointer is null
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))
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();
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: */

/home/maarten/src/libreoffice/core/sw/source/core/inc/frame.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX
21#define INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX
22
23#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
24#include <editeng/borderline.hxx>
25#include <svl/poolitem.hxx>
26#include <swtypes.hxx>
27#include <swrect.hxx>
28#include <calbck.hxx>
29#include <svl/SfxBroadcaster.hxx>
30#include <o3tl/typed_flags_set.hxx>
31#include <com/sun/star/style/TabStop.hpp>
32#include <basegfx/matrix/b2dhommatrix.hxx>
33#include <vcl/outdev.hxx>
34
35#include <memory>
36
37namespace drawinglayer::processor2d { class BaseProcessor2D; }
38
39class SwLayoutFrame;
40class SwRootFrame;
41class SwPageFrame;
42class SwBodyFrame;
43class SwFlyFrame;
44class SwSectionFrame;
45class SwFootnoteFrame;
46class SwFootnoteBossFrame;
47class SwTabFrame;
48class SwRowFrame;
49class SwContentFrame;
50class SwAttrSet;
51class Color;
52class SwBorderAttrs;
53class SwCache;
54class SvxBrushItem;
55class SvxFormatBreakItem;
56class SwFormatPageDesc;
57class SwSelectionList;
58struct SwPosition;
59struct SwCursorMoveState;
60class SwFormat;
61class SwPrintData;
62class SwSortedObjs;
63class SwAnchoredObject;
64enum class SvxFrameDirection;
65class IDocumentDrawModelAccess;
66
67// Each FrameType is represented here as a bit.
68// The bits must be set in a way that it can be determined with masking of
69// which kind of FrameType an instance is _and_ from what classes it was derived.
70// Each frame has in its base class a member that must be set by the
71// constructors accordingly.
72enum class SwFrameType
73{
74 None = 0x0000,
75 Root = 0x0001,
76 Page = 0x0002,
77 Column = 0x0004,
78 Header = 0x0008,
79 Footer = 0x0010,
80 FtnCont = 0x0020,
81 Ftn = 0x0040,
82 Body = 0x0080,
83 Fly = 0x0100,
84 Section = 0x0200,
85// UNUSED 0x0400
86 Tab = 0x0800,
87 Row = 0x1000,
88 Cell = 0x2000,
89 Txt = 0x4000,
90 NoTxt = 0x8000,
91};
92
93namespace o3tl
94{
95 template<> struct typed_flags<SwFrameType> : is_typed_flags<SwFrameType, 0xfbff> {};
96};
97
98// for internal use some common combinations
99#define FRM_LAYOUTSwFrameType(0x3bFF) SwFrameType(0x3bFF)
100#define FRM_ALLSwFrameType(0xfbff) SwFrameType(0xfbff)
101#define FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt) (SwFrameType::Txt | SwFrameType::NoTxt)
102#define FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column) (SwFrameType::Page | SwFrameType::Column)
103#define FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header |
SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType
::Tab | SwFrameType::Cell | SwFrameType::Txt)
(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType::Tab | SwFrameType::Cell | SwFrameType::Txt)
104#define FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell) (SwFrameType::Column | SwFrameType::Cell)
105#define FRM_NOTE_VERT(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section
| SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType
::Txt)
(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType::Txt)
106#define FRM_HEADFOOT(SwFrameType::Header | SwFrameType::Footer) (SwFrameType::Header | SwFrameType::Footer)
107#define FRM_BODYFTNC(SwFrameType::FtnCont | SwFrameType::Body) (SwFrameType::FtnCont | SwFrameType::Body)
108
109// for GetNextLeaf/GetPrevLeaf.
110enum MakePageType
111{
112 MAKEPAGE_NONE, // do not create page/footnote
113 MAKEPAGE_APPEND, // only append page if needed
114 MAKEPAGE_INSERT, // add or append page if needed
115 MAKEPAGE_FTN, // add footnote if needed
116 MAKEPAGE_NOSECTION // Don't create section frames
117};
118
119namespace drawinglayer::attribute {
120 class SdrAllFillAttributesHelper;
121 typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr;
122}
123
124/// Helper class to isolate geometry-defining members of SwFrame
125/// and to control their accesses. Moved to own class to have no
126/// hidden accesses to 'private' members anymore.
127///
128/// Added most important flags about the state of this geometric
129/// information and if it is valid or not
130class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwFrameAreaDefinition
131{
132private:
133 friend void FriendHackInvalidateRowFrame(SwFrameAreaDefinition &);
134
135 // The absolute position and size of the SwFrame in the document.
136 // This values are set by the layouter implementations
137 SwRect maFrameArea;
138
139 // The 'inner' Frame Area defined by a SwRect relative to FrameArea:
140 // When identical to FrameArea, Pos() will be (0, 0) and Size identical.
141 SwRect maFramePrintArea;
142
143 // bitfield
144 bool mbFrameAreaPositionValid : 1;
145 bool mbFrameAreaSizeValid : 1;
146 bool mbFramePrintAreaValid : 1;
147
148 // #i65250#
149 // frame ID is now in general available - used for layout loop control
150 static sal_uInt32 mnLastFrameId;
151 const sal_uInt32 mnFrameId;
152
153protected:
154 // write access to mb*Valid flags
155 void setFrameAreaPositionValid(bool bNew);
156 void setFrameAreaSizeValid(bool bNew);
157 void setFramePrintAreaValid(bool bNew);
158
159public:
160 SwFrameAreaDefinition();
161 virtual ~SwFrameAreaDefinition();
162
163 // read access to mb*Valid flags
164 bool isFrameAreaPositionValid() const { return mbFrameAreaPositionValid; }
165 bool isFrameAreaSizeValid() const { return mbFrameAreaSizeValid; }
166 bool isFramePrintAreaValid() const { return mbFramePrintAreaValid; }
167
168 // syntactic sugar: test whole FrameAreaDefinition
169 bool isFrameAreaDefinitionValid() const { return isFrameAreaPositionValid() && isFrameAreaSizeValid() && isFramePrintAreaValid(); }
170
171 // #i65250#
172 sal_uInt32 GetFrameId() const { return mnFrameId; }
173
174 // read accesses to FrameArea definitions - only const access allowed.
175 // Do *not* const_cast results, it is necessary to track changes. use
176 // the below offered WriteAccess helper classes instead
177 const SwRect& getFrameArea() const { return maFrameArea; }
178 const SwRect& getFramePrintArea() const { return maFramePrintArea; }
179
180 // helper class(es) for FrameArea manipulation. These
181 // have to be used to apply changes to FrameAreas. They hold a copy of the
182 // SwRect for manipulation. It gets written back at destruction. Thus, this
183 // mechanism depends on scope usage, take care. It prevents errors using
184 // different instances of SwFrame in get/set methods which is more safe
185 class FrameAreaWriteAccess : public SwRect
186 {
187 private:
188 SwFrameAreaDefinition& mrTarget;
189
190 FrameAreaWriteAccess(const FrameAreaWriteAccess&) = delete;
191 FrameAreaWriteAccess& operator=(const FrameAreaWriteAccess&) = delete;
192
193 public:
194 FrameAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFrameArea()), mrTarget(rTarget) {}
195 ~FrameAreaWriteAccess();
196 void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; }
197 };
198
199 // same helper for FramePrintArea
200 class FramePrintAreaWriteAccess : public SwRect
201 {
202 private:
203 SwFrameAreaDefinition& mrTarget;
204
205 FramePrintAreaWriteAccess(const FramePrintAreaWriteAccess&) = delete;
206 FramePrintAreaWriteAccess& operator=(const FramePrintAreaWriteAccess&) = delete;
207
208 public:
209 FramePrintAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFramePrintArea()), mrTarget(rTarget) {}
210 ~FramePrintAreaWriteAccess();
211 void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; }
212 };
213
214 // RotateFlyFrame3 - Support for Transformations
215 // Hand out the Transformations for the current FrameAreaDefinition
216 // for the FrameArea and FramePrintArea.
217 // FramePrintArea is not relative to FrameArea in this
218 // transformation representation (to make it easier to use and understand).
219 // There is no 'set' method since SwFrame is a layout object. For
220 // some cases rotation will be included (used for SwGrfNode in inner
221 // SwFrame of a SwFlyFrame)
222 virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const;
223 virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
224
225 // RotateFlyFrame3 - Support for Transformations
226 // Modify current transformations by applying given translation
227 virtual void transform_translate(const Point& rOffset);
228};
229
230/// RotateFlyFrame3: Helper class when you want to make your SwFrame derivate
231/// transformable. It provides some tooling to do so. To use, add as member
232/// (see e.g. SwFlyFreeFrame which uses 'std::unique_ptr< TransformableSwFrame >')
233class TransformableSwFrame
234{
235private:
236 // The SwFrameAreaDefinition to work on
237 SwFrameAreaDefinition& mrSwFrameAreaDefinition;
238
239 // FrameAreaTransformation and FramePrintAreaTransformation
240 // !identity when needed (translate/scale is used (e.g. rotation))
241 basegfx::B2DHomMatrix maFrameAreaTransformation;
242 basegfx::B2DHomMatrix maFramePrintAreaTransformation;
243
244public:
245 TransformableSwFrame(SwFrameAreaDefinition& rSwFrameAreaDefinition)
246 : mrSwFrameAreaDefinition(rSwFrameAreaDefinition),
247 maFrameAreaTransformation(),
248 maFramePrintAreaTransformation()
249 {
250 }
251
252 // get SwFrameArea in transformation form
253 const basegfx::B2DHomMatrix& getLocalFrameAreaTransformation() const
254 {
255 return maFrameAreaTransformation;
256 }
257
258 // get SwFramePrintArea in transformation form
259 const basegfx::B2DHomMatrix& getLocalFramePrintAreaTransformation() const
260 {
261 return maFramePrintAreaTransformation;
262 }
263
264 // Helpers to re-create the untransformed SwRect(s) originally
265 // in the SwFrameAreaDefinition, based on the current Transformations.
266 SwRect getUntransformedFrameArea() const;
267 SwRect getUntransformedFramePrintArea() const;
268
269 // Helper method to re-create FrameAreaTransformations based on the
270 // current FrameAreaDefinition transformed by given rotation and Center
271 void createFrameAreaTransformations(
272 double fRotation,
273 const basegfx::B2DPoint& rCenter);
274
275 // Tooling method to reset the SwRect(s) in the current
276 // SwFrameAreaDefinition which are already adapted to
277 // Transformation back to the untransformed state, using
278 // the getUntransformedFrame*Area calls above when needed.
279 // Only the SwRect(s) are changed back, not the transformations.
280 void restoreFrameAreas();
281
282 // Re-Creates the SwRect(s) as BoundAreas based on the current
283 // set Transformations.
284 void adaptFrameAreasToTransformations();
285
286 // Modify current definitions by applying the given transformation
287 void transform(const basegfx::B2DHomMatrix& aTransform);
288};
289
290/**
291 * Base class of the Writer layout elements.
292 *
293 * This includes not only fly frames, but everything down to the paragraph
294 * level: pages, headers, footers, etc. (Inside a paragraph SwLinePortion
295 * instances are used.)
296 */
297class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwFrame : public SwFrameAreaDefinition, public SwClient, public SfxBroadcaster
298{
299 // the hidden Frame
300 friend class SwFlowFrame;
301 friend class SwLayoutFrame;
302 friend class SwLooping;
303 friend class SwDeletionChecker; // for GetDep()
304
305 // voids lower during creation of a column
306 friend SwFrame *SaveContent( SwLayoutFrame *, SwFrame* pStart );
307 friend void RestoreContent( SwFrame *, SwLayoutFrame *, SwFrame *pSibling );
308
309 // for validating a mistakenly invalidated one in SwContentFrame::MakeAll
310 friend void ValidateSz( SwFrame *pFrame );
311 // implemented in text/txtftn.cxx, prevents Footnote oscillation
312 friend void ValidateText( SwFrame *pFrame );
313
314 friend void MakeNxt( SwFrame *pFrame, SwFrame *pNxt );
315
316 // cache for (border) attributes
317 static SwCache *mpCache;
318
319 SwRootFrame *mpRoot;
320 SwLayoutFrame *mpUpper;
321 SwFrame *mpNext;
322 SwFrame *mpPrev;
323
324 // sw_redlinehide: hide these dangerous SwClient functions
325 using SwClient::GetRegisteredInNonConst;
326 using SwClient::GetRegisteredIn;
327
328 SwFrame *FindNext_();
329 SwFrame *FindPrev_();
330
331 /** method to determine next content frame in the same environment
332 for a flow frame (content frame, table frame, section frame)
333
334 #i27138# - adding documentation:
335 Travelling downwards through the layout to determine the next content
336 frame in the same environment. There are several environments in a
337 document, which form a closed context regarding this function. These
338 environments are:
339 - Each page header
340 - Each page footer
341 - Each unlinked fly frame
342 - Each group of linked fly frames
343 - All footnotes
344 - All document body frames
345 #i27138# - adding parameter <_bInSameFootnote>
346 Its default value is <false>. If its value is <true>, the environment
347 'All footnotes' is no longer treated. Instead each footnote is treated
348 as an own environment.
349
350 @param _bInSameFootnote
351 input parameter - boolean indicating, that the found next content
352 frame has to be in the same footnote frame. This parameter is only
353 relevant for flow frames in footnotes.
354
355 @return SwContentFrame*
356 pointer to the found next content frame. It's NULL, if none exists.
357 */
358 SwContentFrame* FindNextCnt_( const bool _bInSameFootnote );
359
360 /** method to determine previous content frame in the same environment
361 for a flow frame (content frame, table frame, section frame)
362
363 #i27138#
364 Travelling upwards through the layout to determine the previous content
365 frame in the same environment. There are several environments in a
366 document, which form a closed context regarding this function. These
367 environments are:
368 - Each page header
369 - Each page footer
370 - Each unlinked fly frame
371 - Each group of linked fly frames
372 - All footnotes
373 - All document body frames
374 #i27138# - adding parameter <_bInSameFootnote>
375 Its default value is <false>. If its value is <true>, the environment
376 'All footnotes' is no longer treated. Instead each footnote is treated
377 as an own environment.
378
379 The found previous content frame has to be in the same footnote frame. This is only
380 relevant for flow frames in footnotes.
381
382 @return SwContentFrame*
383 pointer to the found previous content frame. It's NULL, if none exists.
384 */
385 SwContentFrame* FindPrevCnt_();
386
387 void UpdateAttrFrame( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 & );
388 SwFrame* GetIndNext_();
389 void SetDirFlags( bool bVert );
390
391 const SwLayoutFrame* ImplGetNextLayoutLeaf( bool bFwd ) const;
392
393 SwPageFrame* ImplFindPageFrame();
394
395protected:
396 std::unique_ptr<SwSortedObjs> m_pDrawObjs; // draw objects, can be null
397 SwFrameType mnFrameType; //Who am I?
398
399 bool mbInDtor : 1;
400 bool mbInvalidR2L : 1;
401 bool mbDerivedR2L : 1;
402 bool mbRightToLeft : 1;
403 bool mbInvalidVert : 1;
404 bool mbDerivedVert : 1;
405 bool mbVertical : 1;
406
407 bool mbVertLR : 1;
408 bool mbVertLRBT : 1;
409
410 bool mbValidLineNum : 1;
411 bool mbFixSize : 1;
412
413 // if true, frame will be painted completely even content was changed
414 // only partially. For ContentFrames a border (from Action) will exclusively
415 // painted if <mbCompletePaint> is true.
416 bool mbCompletePaint : 1;
417
418 bool mbRetouche : 1; // frame is responsible for retouching
419
420 bool mbInfInvalid : 1; // InfoFlags are invalid
421 bool mbInfBody : 1; // Frame is in document body
422 bool mbInfTab : 1; // Frame is in a table
423 bool mbInfFly : 1; // Frame is in a Fly
424 bool mbInfFootnote : 1; // Frame is in a footnote
425 bool mbInfSct : 1; // Frame is in a section
426 bool mbColLocked : 1; // lock Grow/Shrink for column-wise section
427 // or fly frames, will be set in Format
428 bool m_isInDestroy : 1;
429 bool mbForbidDelete : 1;
430
431 void ColLock() { mbColLocked = true; }
432 void ColUnlock() { mbColLocked = false; }
433
434 virtual void DestroyImpl();
435 virtual ~SwFrame() override;
436
437 // Only used by SwRootFrame Ctor to get 'this' into mpRoot...
438 void setRootFrame( SwRootFrame* pRoot ) { mpRoot = pRoot; }
439
440 SwPageFrame *InsertPage( SwPageFrame *pSibling, bool bFootnote );
441 void PrepareMake(vcl::RenderContext* pRenderContext);
442 void OptPrepareMake();
443 virtual void MakePos();
444 // Format next frame of table frame to assure keeping attributes.
445 // In case of nested tables method <SwFrame::MakeAll()> is called to
446 // avoid formatting of superior table frame.
447 friend SwFrame* sw_FormatNextContentForKeep( SwTabFrame* pTabFrame );
448
449 virtual void MakeAll(vcl::RenderContext* pRenderContext) = 0;
450 // adjust frames of a page
451 SwTwips AdjustNeighbourhood( SwTwips nDiff, bool bTst = false );
452
453 // change only frame size not the size of PrtArea
454 virtual SwTwips ShrinkFrame( SwTwips, bool bTst = false, bool bInfo = false ) = 0;
455 virtual SwTwips GrowFrame ( SwTwips, bool bTst = false, bool bInfo = false ) = 0;
456
457 /// use these so we can grep for SwFrame's GetRegisteredIn accesses
458 /// beware that SwTextFrame may return sw::WriterMultiListener
459 SwModify *GetDep() { return GetRegisteredInNonConst(); }
460 const SwModify *GetDep() const { return GetRegisteredIn(); }
461
462 SwFrame( SwModify*, SwFrame* );
463
464 void CheckDir( SvxFrameDirection nDir, bool bVert, bool bOnlyBiDi, bool bBrowse );
465
466 /** enumeration for the different invalidations
467 #i28701#
468 */
469 enum InvalidationType
470 {
471 INVALID_SIZE, INVALID_PRTAREA, INVALID_POS, INVALID_LINENUM, INVALID_ALL
472 };
473
474 /** method to determine, if an invalidation is allowed.
475 #i28701
476 */
477 virtual bool InvalidationAllowed( const InvalidationType _nInvalid ) const;
478
479 /** method to perform additional actions on an invalidation
480
481 #i28701#
482 Method has *only* to contain actions, which has to be performed on
483 *every* assignment of the corresponding flag to <false>.
484 */
485 virtual void ActionOnInvalidation( const InvalidationType _nInvalid );
486
487 // draw shadow and borders
488 void PaintShadow( const SwRect&, SwRect&, const SwBorderAttrs& ) const;
489 virtual void Modify( const SfxPoolItem*, const SfxPoolItem* ) override;
490
491 virtual const IDocumentDrawModelAccess& getIDocumentDrawModelAccess( );
492
493public:
494 virtual css::uno::Sequence< css::style::TabStop > GetTabStopInfo( SwTwips )
495 {
496 return css::uno::Sequence< css::style::TabStop >();
497 }
498
499
500 SwFrameType GetType() const { return mnFrameType; }
501
502 static SwCache &GetCache() { return *mpCache; }
503 static SwCache *GetCachePtr() { return mpCache; }
504 static void SetCache( SwCache *pNew ) { mpCache = pNew; }
505
506 // change PrtArea size and FrameSize
507 SwTwips Shrink( SwTwips, bool bTst = false, bool bInfo = false );
508 SwTwips Grow ( SwTwips, bool bTst = false, bool bInfo = false );
509
510 // different methods for inserting in layout tree (for performance reasons)
511
512 // insert before pBehind or at the end of the chain below mpUpper
513 void InsertBefore( SwLayoutFrame* pParent, SwFrame* pBehind );
514 // insert after pBefore or at the beginning of the chain below mpUpper
515 void InsertBehind( SwLayoutFrame *pParent, SwFrame *pBefore );
516 // insert before pBehind or at the end of the chain while considering
517 // the siblings of pSct
518 bool InsertGroupBefore( SwFrame* pParent, SwFrame* pWhere, SwFrame* pSct );
519 void RemoveFromLayout();
520
521 // For internal use only - who ignores this will be put in a sack and has
522 // to stay there for two days
523 // Does special treatment for Get_[Next|Prev]Leaf() (for tables).
524 SwLayoutFrame *GetLeaf( MakePageType eMakePage, bool bFwd );
525 SwLayoutFrame *GetNextLeaf ( MakePageType eMakePage );
526 SwLayoutFrame *GetNextFootnoteLeaf( MakePageType eMakePage );
527 SwLayoutFrame *GetNextSctLeaf( MakePageType eMakePage );
528 SwLayoutFrame *GetNextCellLeaf();
529 SwLayoutFrame *GetPrevLeaf ();
530 SwLayoutFrame *GetPrevFootnoteLeaf( MakePageType eMakeFootnote );
531 SwLayoutFrame *GetPrevSctLeaf();
532 SwLayoutFrame *GetPrevCellLeaf();
533 const SwLayoutFrame *GetLeaf ( MakePageType eMakePage, bool bFwd,
534 const SwFrame *pAnch ) const;
535
536 bool WrongPageDesc( SwPageFrame* pNew );
537
538 //#i28701# - new methods to append/remove drawing objects
539 void AppendDrawObj( SwAnchoredObject& _rNewObj );
540 void RemoveDrawObj( SwAnchoredObject& _rToRemoveObj );
541
542 // work with chain of FlyFrames
543 void AppendFly( SwFlyFrame *pNew );
544 void RemoveFly( SwFlyFrame *pToRemove );
545 const SwSortedObjs *GetDrawObjs() const { return m_pDrawObjs.get(); }
546 SwSortedObjs *GetDrawObjs() { return m_pDrawObjs.get(); }
547 // #i28701# - change purpose of method and adjust its name
548 void InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs = true );
549
550 virtual void PaintSwFrameShadowAndBorder(
551 const SwRect&,
552 const SwPageFrame* pPage,
553 const SwBorderAttrs&) const;
554 void PaintBaBo( const SwRect&, const SwPageFrame *pPage,
555 const bool bOnlyTextBackground = false) const;
556 void PaintSwFrameBackground( const SwRect&, const SwPageFrame *pPage,
557 const SwBorderAttrs &,
558 const bool bLowerMode = false,
559 const bool bLowerBorder = false,
560 const bool bOnlyTextBackground = false ) const;
561 void PaintBorderLine( const SwRect&, const SwRect&, const SwPageFrame*,
562 const Color *pColor,
563 const SvxBorderLineStyle = SvxBorderLineStyle::SOLID ) const;
564
565 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> CreateProcessor2D( ) const;
566 void ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DContainer& rSequence ) const;
567
568 // retouch, not in the area of the given Rect!
569 void Retouch( const SwPageFrame *pPage, const SwRect &rRect ) const;
570
571 bool GetBackgroundBrush(
572 drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes,
573 const SvxBrushItem*& rpBrush,
574 const Color*& rpColor,
575 SwRect &rOrigRect,
576 bool bLowerMode,
577 bool bConsiderTextBox ) const;
578
579 inline void SetCompletePaint() const;
580 inline void ResetCompletePaint() const;
581 bool IsCompletePaint() const { return mbCompletePaint; }
582
583 inline void SetRetouche() const;
584 inline void ResetRetouche() const;
585 bool IsRetouche() const { return mbRetouche; }
586
587 void SetInfFlags();
588 void InvalidateInfFlags() { mbInfInvalid = true; }
589 inline bool IsInDocBody() const; // use InfoFlags, determine flags
590 inline bool IsInFootnote() const; // if necessary
591 inline bool IsInTab() const;
592 inline bool IsInFly() const;
593 inline bool IsInSct() const;
594
595 // If frame is inside a split table row, this function returns
596 // the corresponding row frame in the follow table.
597 const SwRowFrame* IsInSplitTableRow() const;
598
599 // If frame is inside a follow flow row, this function returns
600 // the corresponding row frame master table
601 const SwRowFrame* IsInFollowFlowRow() const;
602
603 bool IsInBalancedSection() const;
604
605 inline bool IsVertical() const;
606 inline bool IsVertLR() const;
607 inline bool IsVertLRBT() const;
608
609 void SetDerivedVert( bool bNew ){ mbDerivedVert = bNew; }
610 void SetInvalidVert( bool bNew) { mbInvalidVert = bNew; }
611 inline bool IsRightToLeft() const;
612 void SetDerivedR2L( bool bNew ) { mbDerivedR2L = bNew; }
613
614 void CheckDirChange();
615 // returns upper left frame position for LTR and
616 // upper right frame position for Asian / RTL frames
617 Point GetFrameAnchorPos( bool bIgnoreFlysAnchoredAtThisFrame ) const;
618
619 /** determine, if frame is moveable in given environment
620
621 method replaced 'old' method <bool IsMoveable() const>.
622 Determines, if frame is moveable in given environment. if no environment
623 is given (parameter _pLayoutFrame == 0), the movability in the actual
624 environment (<GetUpper()) is checked.
625
626 @param _pLayoutFrame
627 input parameter - given environment (layout frame), in which the movability
628 will be checked. If not set ( == 0 ), actual environment is taken.
629
630 @return boolean, indicating, if frame is moveable in given environment
631 */
632 bool IsMoveable( const SwLayoutFrame* _pLayoutFrame = nullptr ) const;
633
634 // Is it permitted for the (Text)Frame to add a footnote in the current
635 // environment (not e.g. for repeating table headlines)
636 bool IsFootnoteAllowed() const;
637
638 virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr );
639
640 virtual void CheckDirection( bool bVert );
641
642 void ReinitializeFrameSizeAttrFlags();
643
644 /// WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for
645 /// SwTextFrame, use GetBreakItem()/GetPageDescItem() instead
646 const SwAttrSet *GetAttrSet() const;
647 virtual const SvxFormatBreakItem& GetBreakItem() const;
648 virtual const SwFormatPageDesc& GetPageDescItem() const;
649
650 bool HasFixSize() const { return mbFixSize; }
651
652 // check all pages (starting from the given) and correct them if needed
653 static void CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields = true, SwPageFrame** ppPrev = nullptr);
654
655 // might return 0, with and without const
656 SwFrame *GetNext() { return mpNext; }
657 SwFrame *GetPrev() { return mpPrev; }
658 SwLayoutFrame *GetUpper() { return mpUpper; }
659 SwRootFrame *getRootFrame(){ return mpRoot; }
660 SwPageFrame *FindPageFrame() { return IsPageFrame() ? reinterpret_cast<SwPageFrame*>(this) : ImplFindPageFrame(); }
661 SwFrame *FindColFrame();
662 SwRowFrame *FindRowFrame();
663 SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnotes = false );
664 SwTabFrame *ImplFindTabFrame();
665 SwFootnoteFrame *ImplFindFootnoteFrame();
666 SwFlyFrame *ImplFindFlyFrame();
667 SwSectionFrame *ImplFindSctFrame();
668 const SwBodyFrame *ImplFindBodyFrame() const;
669 SwFrame *FindFooterOrHeader();
670 SwFrame *GetLower();
671 const SwFrame *GetNext() const { return mpNext; }
672 const SwFrame *GetPrev() const { return mpPrev; }
673 const SwLayoutFrame *GetUpper() const { return mpUpper; }
674 const SwRootFrame *getRootFrame() const { return mpRoot; }
675 inline SwTabFrame *FindTabFrame();
676 inline SwFootnoteFrame *FindFootnoteFrame();
677 inline SwFlyFrame *FindFlyFrame();
678 inline SwSectionFrame *FindSctFrame();
679 inline SwFrame *FindNext();
680 // #i27138# - add parameter <_bInSameFootnote>
681 SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false );
682 inline SwFrame *FindPrev();
683 inline const SwPageFrame *FindPageFrame() const;
684 inline const SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnote = false ) const;
685 inline const SwFrame *FindColFrame() const;
686 inline const SwFrame *FindFooterOrHeader() const;
687 inline const SwTabFrame *FindTabFrame() const;
688 inline const SwFootnoteFrame *FindFootnoteFrame() const;
689 inline const SwFlyFrame *FindFlyFrame() const;
690 inline const SwSectionFrame *FindSctFrame() const;
691 inline const SwBodyFrame *FindBodyFrame() const;
692 inline const SwFrame *FindNext() const;
693 // #i27138# - add parameter <_bInSameFootnote>
694 const SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false ) const;
695 inline const SwFrame *FindPrev() const;
696 const SwFrame *GetLower() const;
697
698 SwContentFrame* FindPrevCnt();
699
700 const SwContentFrame* FindPrevCnt() const;
701
702 // #i79774#
703 SwFrame* GetIndPrev_() const;
704 SwFrame* GetIndPrev() const
705 { return ( mpPrev || !IsInSct() ) ? mpPrev : GetIndPrev_(); }
706
707 SwFrame* GetIndNext()
708 { return ( mpNext || !IsInSct() ) ? mpNext : GetIndNext_(); }
709 const SwFrame* GetIndNext() const { return const_cast<SwFrame*>(this)->GetIndNext(); }
710
711 sal_uInt16 GetPhyPageNum() const; // page number without offset
712 sal_uInt16 GetVirtPageNum() const; // page number with offset
713 bool OnRightPage() const { return 0 != GetPhyPageNum() % 2; };
714 bool WannaRightPage() const;
715 bool OnFirstPage() const;
716
717 inline const SwLayoutFrame *GetPrevLayoutLeaf() const;
718 inline const SwLayoutFrame *GetNextLayoutLeaf() const;
719 inline SwLayoutFrame *GetPrevLayoutLeaf();
720 inline SwLayoutFrame *GetNextLayoutLeaf();
721
722 virtual void Calc(vcl::RenderContext* pRenderContext) const; // here might be "formatted"
723 inline void OptCalc() const; // here we assume (for optimization) that
724 // the predecessors are already formatted
725 Point GetRelPos() const;
726
727 // PaintArea is the area where content might be displayed.
728 // The margin of a page or the space between columns belongs to it.
729 SwRect GetPaintArea() const;
730
731 // UnionFrame is the union of Frame- and PrtArea, normally identical
732 // to the FrameArea except in case of negative Prt margins.
733 SwRect UnionFrame( bool bBorder = false ) const;
734
735 virtual Size ChgSize( const Size& aNewSize );
736
737 virtual void Cut() = 0;
738 virtual void Paste( SwFrame* pParent, SwFrame* pSibling = nullptr ) = 0;
739
740 void ValidateLineNum() { mbValidLineNum = true; }
741
742 bool GetValidLineNumFlag()const { return mbValidLineNum; }
743
744 // Only invalidate Frame
745 // #i28701# - add call to method <ActionOnInvalidation(..)>
746 // for all invalidation methods.
747 // #i28701# - use method <InvalidationAllowed(..)> to
748 // decide, if invalidation will to be performed or not.
749 // #i26945# - no additional invalidation, if it's already
750 // invalidate.
751 void InvalidateSize_()
752 {
753 if ( isFrameAreaSizeValid() && InvalidationAllowed( INVALID_SIZE ) )
754 {
755 setFrameAreaSizeValid(false);
756 ActionOnInvalidation( INVALID_SIZE );
757 }
758 }
759 void InvalidatePrt_()
760 {
761 if ( isFramePrintAreaValid() && InvalidationAllowed( INVALID_PRTAREA ) )
762 {
763 setFramePrintAreaValid(false);
764 ActionOnInvalidation( INVALID_PRTAREA );
765 }
766 }
767 void InvalidatePos_()
768 {
769 if ( isFrameAreaPositionValid() && InvalidationAllowed( INVALID_POS ) )
770 {
771 setFrameAreaPositionValid(false);
772 ActionOnInvalidation( INVALID_POS );
773 }
774 }
775 void InvalidateLineNum_()
776 {
777 if ( mbValidLineNum && InvalidationAllowed( INVALID_LINENUM ) )
778 {
779 mbValidLineNum = false;
780 ActionOnInvalidation( INVALID_LINENUM );
781 }
782 }
783 void InvalidateAll_()
784 {
785 if ( ( isFrameAreaSizeValid() || isFramePrintAreaValid() || isFrameAreaPositionValid() ) && InvalidationAllowed( INVALID_ALL ) )
786 {
787 setFrameAreaSizeValid(false);
788 setFrameAreaPositionValid(false);
789 setFramePrintAreaValid(false);
790 ActionOnInvalidation( INVALID_ALL );
791 }
792 }
793 // also notify page at the same time
794 inline void InvalidateSize();
795 inline void InvalidatePrt();
796 inline void InvalidatePos();
797 inline void InvalidateLineNum();
798 inline void InvalidateAll();
799 void ImplInvalidateSize();
800 void ImplInvalidatePrt();
801 void ImplInvalidatePos();
802 void ImplInvalidateLineNum();
803
804 inline void InvalidateNextPos( bool bNoFootnote = false );
805 void ImplInvalidateNextPos( bool bNoFootnote );
806
807 /** method to invalidate printing area of next frame
808 #i11859#
809 */
810 void InvalidateNextPrtArea();
811
812 void InvalidatePage( const SwPageFrame *pPage = nullptr ) const;
813
814 virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
815
816 virtual bool GetModelPositionForViewPoint( SwPosition *, Point&,
817 SwCursorMoveState* = nullptr, bool bTestBackground = false ) const;
818 virtual bool GetCharRect( SwRect &, const SwPosition&,
819 SwCursorMoveState* = nullptr, bool bAllowFarAway = true ) const;
820 virtual void PaintSwFrame( vcl::RenderContext& rRenderContext, SwRect const&,
821 SwPrintData const*const pPrintData = nullptr ) const;
822
823 // HACK: shortcut between frame and formatting
824 // It's your own fault if you cast void* incorrectly! In any case check
825 // the void* for 0.
826 virtual bool Prepare( const PrepareHint ePrep = PrepareHint::Clear,
827 const void *pVoid = nullptr, bool bNotify = true );
828
829 // true if it is the correct class, false otherwise
830 inline bool IsLayoutFrame() const;
831 inline bool IsRootFrame() const;
832 inline bool IsPageFrame() const;
833 inline bool IsColumnFrame() const;
834 inline bool IsFootnoteBossFrame() const; // footnote bosses might be PageFrames or ColumnFrames
835 inline bool IsHeaderFrame() const;
836 inline bool IsFooterFrame() const;
837 inline bool IsFootnoteContFrame() const;
838 inline bool IsFootnoteFrame() const;
839 inline bool IsBodyFrame() const;
840 inline bool IsColBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above ColumnFrame
841 inline bool IsPageBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above PageFrame
842 inline bool IsFlyFrame() const;
843 inline bool IsSctFrame() const;
844 inline bool IsTabFrame() const;
845 inline bool IsRowFrame() const;
846 inline bool IsCellFrame() const;
847 inline bool IsContentFrame() const;
848 inline bool IsTextFrame() const;
849 inline bool IsNoTextFrame() const;
850 // Frames where its PrtArea depends on their neighbors and that are
851 // positioned in the content flow
852 inline bool IsFlowFrame() const;
853 // Frames that are capable of retouching or that might need to retouch behind
854 // themselves
855 inline bool IsRetoucheFrame() const;
856 inline bool IsAccessibleFrame() const;
857
858 void PrepareCursor(); // CursorShell is allowed to call this
859
860 // Is the Frame (or the section containing it) protected? Same for Fly in
861 // Fly in ... and footnotes
862 bool IsProtected() const;
863
864 bool IsColLocked() const { return mbColLocked; }
865 virtual bool IsDeleteForbidden() const { return mbForbidDelete; }
866
867 /// this is the only way to delete a SwFrame instance
868 static void DestroyFrame(SwFrame *const pFrame);
869
870 bool IsInDtor() const { return mbInDtor; }
871
872 // No inline cause we need the function pointers
873 long GetTopMargin() const;
874 long GetBottomMargin() const;
875 long GetLeftMargin() const;
876 long GetRightMargin() const;
877 void SetTopBottomMargins( long, long );
878 void SetLeftRightMargins( long, long );
879 void SetRightLeftMargins( long, long );
880 long GetPrtLeft() const;
881 long GetPrtBottom() const;
882 long GetPrtRight() const;
883 long GetPrtTop() const;
884 bool SetMinLeft( long );
885 bool SetMaxBottom( long );
886 bool SetMaxRight( long );
887 void MakeBelowPos( const SwFrame*, const SwFrame*, bool );
888 void MakeLeftPos( const SwFrame*, const SwFrame*, bool );
889 void MakeRightPos( const SwFrame*, const SwFrame*, bool );
890 bool IsNeighbourFrame() const
891 { return bool(GetType() & FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell)); }
892
893 // NEW TABLES
894 // Some functions for covered/covering table cells. This way unnecessary
895 // includes can be avoided
896 virtual bool IsLeaveUpperAllowed() const;
897 virtual bool IsCoveredCell() const;
898 bool IsInCoveredCell() const;
899
900 // #i81146# new loop control
901 bool KnowsFormat( const SwFormat& rFormat ) const;
902 void RegisterToFormat( SwFormat& rFormat );
903 void ValidateThisAndAllLowers( const sal_uInt16 nStage );
904
905 void ForbidDelete() { mbForbidDelete = true; }
906 void AllowDelete() { mbForbidDelete = false; }
907
908 drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const;
909 bool supportsFullDrawingLayerFillAttributeSet() const;
910
911public:
912 // if writer is NULL, dumps the layout structure as XML in layout.xml
913 virtual void dumpAsXml(xmlTextWriterPtr writer = nullptr) const;
914 void dumpTopMostAsXml(xmlTextWriterPtr writer = nullptr) const;
915 void dumpInfosAsXml(xmlTextWriterPtr writer) const;
916 virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const;
917 void dumpChildrenAsXml(xmlTextWriterPtr writer) const;
918 bool IsCollapse() const;
919};
920
921inline bool SwFrame::IsInDocBody() const
922{
923 if ( mbInfInvalid )
924 const_cast<SwFrame*>(this)->SetInfFlags();
925 return mbInfBody;
926}
927inline bool SwFrame::IsInFootnote() const
928{
929 if ( mbInfInvalid )
930 const_cast<SwFrame*>(this)->SetInfFlags();
931 return mbInfFootnote;
932}
933inline bool SwFrame::IsInTab() const
934{
935 if ( mbInfInvalid )
22
Assuming field 'mbInfInvalid' is false
23
Taking false branch
936 const_cast<SwFrame*>(this)->SetInfFlags();
937 return mbInfTab;
24
Returning value, which participates in a condition later
938}
939inline bool SwFrame::IsInFly() const
940{
941 if ( mbInfInvalid )
5
Assuming field 'mbInfInvalid' is false
6
Taking false branch
942 const_cast<SwFrame*>(this)->SetInfFlags();
943 return mbInfFly;
7
Returning value, which participates in a condition later
944}
945inline bool SwFrame::IsInSct() const
946{
947 if ( mbInfInvalid )
948 const_cast<SwFrame*>(this)->SetInfFlags();
949 return mbInfSct;
950}
951bool SwFrame::IsVertical() const
952{
953 if( mbInvalidVert )
954 const_cast<SwFrame*>(this)->SetDirFlags( true );
955 return mbVertical;
956}
957inline bool SwFrame::IsVertLR() const
958{
959 return mbVertLR;
960}
961inline bool SwFrame::IsVertLRBT() const
962{
963 return mbVertLRBT;
964}
965inline bool SwFrame::IsRightToLeft() const
966{
967 if( mbInvalidR2L )
968 const_cast<SwFrame*>(this)->SetDirFlags( false );
969 return mbRightToLeft;
970}
971
972inline void SwFrame::SetCompletePaint() const
973{
974 const_cast<SwFrame*>(this)->mbCompletePaint = true;
975}
976inline void SwFrame::ResetCompletePaint() const
977{
978 const_cast<SwFrame*>(this)->mbCompletePaint = false;
979}
980
981inline void SwFrame::SetRetouche() const
982{
983 const_cast<SwFrame*>(this)->mbRetouche = true;
984}
985inline void SwFrame::ResetRetouche() const
986{
987 const_cast<SwFrame*>(this)->mbRetouche = false;
988}
989
990inline SwLayoutFrame *SwFrame::GetNextLayoutLeaf()
991{
992 return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetNextLayoutLeaf());
993}
994inline SwLayoutFrame *SwFrame::GetPrevLayoutLeaf()
995{
996 return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetPrevLayoutLeaf());
997}
998inline const SwLayoutFrame *SwFrame::GetNextLayoutLeaf() const
999{
1000 return ImplGetNextLayoutLeaf( true );
1001}
1002inline const SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() const
1003{
1004 return ImplGetNextLayoutLeaf( false );
1005}
1006
1007inline void SwFrame::InvalidateSize()
1008{
1009 if ( isFrameAreaSizeValid() )
1010 {
1011 ImplInvalidateSize();
1012 }
1013}
1014inline void SwFrame::InvalidatePrt()
1015{
1016 if ( isFramePrintAreaValid() )
1017 {
1018 ImplInvalidatePrt();
1019 }
1020}
1021inline void SwFrame::InvalidatePos()
1022{
1023 if ( isFrameAreaPositionValid() )
1024 {
1025 ImplInvalidatePos();
1026 }
1027}
1028inline void SwFrame::InvalidateLineNum()
1029{
1030 if ( mbValidLineNum )
1031 ImplInvalidateLineNum();
1032}
1033inline void SwFrame::InvalidateAll()
1034{
1035 if ( InvalidationAllowed( INVALID_ALL ) )
1036 {
1037 if ( isFrameAreaDefinitionValid() )
1038 {
1039 ImplInvalidatePos();
1040 }
1041
1042 setFrameAreaSizeValid(false);
1043 setFrameAreaPositionValid(false);
1044 setFramePrintAreaValid(false);
1045
1046 // #i28701#
1047 ActionOnInvalidation( INVALID_ALL );
1048 }
1049}
1050inline void SwFrame::InvalidateNextPos( bool bNoFootnote )
1051{
1052 if ( mpNext && !mpNext->IsSctFrame() )
1053 mpNext->InvalidatePos();
1054 else
1055 ImplInvalidateNextPos( bNoFootnote );
1056}
1057
1058inline void SwFrame::OptCalc() const
1059{
1060 if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() )
1061 {
1062 const_cast<SwFrame*>(this)->OptPrepareMake();
1063 }
1064}
1065inline const SwPageFrame *SwFrame::FindPageFrame() const
1066{
1067 return const_cast<SwFrame*>(this)->FindPageFrame();
1068}
1069inline const SwFrame *SwFrame::FindColFrame() const
1070{
1071 return const_cast<SwFrame*>(this)->FindColFrame();
1072}
1073inline const SwFrame *SwFrame::FindFooterOrHeader() const
1074{
1075 return const_cast<SwFrame*>(this)->FindFooterOrHeader();
1076}
1077inline SwTabFrame *SwFrame::FindTabFrame()
1078{
1079 return IsInTab() ? ImplFindTabFrame() : nullptr;
1080}
1081inline const SwFootnoteBossFrame *SwFrame::FindFootnoteBossFrame( bool bFootnote ) const
1082{
1083 return const_cast<SwFrame*>(this)->FindFootnoteBossFrame( bFootnote );
1084}
1085inline SwFootnoteFrame *SwFrame::FindFootnoteFrame()
1086{
1087 return IsInFootnote() ? ImplFindFootnoteFrame() : nullptr;
1088}
1089inline SwFlyFrame *SwFrame::FindFlyFrame()
1090{
1091 return IsInFly() ? ImplFindFlyFrame() : nullptr;
1092}
1093inline SwSectionFrame *SwFrame::FindSctFrame()
1094{
1095 return IsInSct() ? ImplFindSctFrame() : nullptr;
1096}
1097
1098inline const SwBodyFrame *SwFrame::FindBodyFrame() const
1099{
1100 return IsInDocBody() ? ImplFindBodyFrame() : nullptr;
1101}
1102
1103inline const SwTabFrame *SwFrame::FindTabFrame() const
1104{
1105 return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr;
1106}
1107inline const SwFootnoteFrame *SwFrame::FindFootnoteFrame() const
1108{
1109 return IsInFootnote() ? const_cast<SwFrame*>(this)->ImplFindFootnoteFrame() : nullptr;
1110}
1111inline const SwFlyFrame *SwFrame::FindFlyFrame() const
1112{
1113 return IsInFly() ? const_cast<SwFrame*>(this)->ImplFindFlyFrame() : nullptr;
1114}
1115inline const SwSectionFrame *SwFrame::FindSctFrame() const
1116{
1117 return IsInSct() ? const_cast<SwFrame*>(this)->ImplFindSctFrame() : nullptr;
1118}
1119inline SwFrame *SwFrame::FindNext()
1120{
1121 if ( mpNext )
1122 return mpNext;
1123 else
1124 return FindNext_();
1125}
1126inline const SwFrame *SwFrame::FindNext() const
1127{
1128 if ( mpNext )
1129 return mpNext;
1130 else
1131 return const_cast<SwFrame*>(this)->FindNext_();
1132}
1133inline SwFrame *SwFrame::FindPrev()
1134{
1135 if ( mpPrev && !mpPrev->IsSctFrame() )
1136 return mpPrev;
1137 else
1138 return FindPrev_();
1139}
1140inline const SwFrame *SwFrame::FindPrev() const
1141{
1142 if ( mpPrev && !mpPrev->IsSctFrame() )
1143 return mpPrev;
1144 else
1145 return const_cast<SwFrame*>(this)->FindPrev_();
1146}
1147
1148inline bool SwFrame::IsLayoutFrame() const
1149{
1150 return bool(GetType() & FRM_LAYOUTSwFrameType(0x3bFF));
1151}
1152inline bool SwFrame::IsRootFrame() const
1153{
1154 return mnFrameType == SwFrameType::Root;
1155}
1156inline bool SwFrame::IsPageFrame() const
1157{
1158 return mnFrameType == SwFrameType::Page;
1159}
1160inline bool SwFrame::IsColumnFrame() const
1161{
1162 return mnFrameType == SwFrameType::Column;
1163}
1164inline bool SwFrame::IsFootnoteBossFrame() const
1165{
1166 return bool(GetType() & FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column));
1167}
1168inline bool SwFrame::IsHeaderFrame() const
1169{
1170 return mnFrameType == SwFrameType::Header;
1171}
1172inline bool SwFrame::IsFooterFrame() const
1173{
1174 return mnFrameType == SwFrameType::Footer;
1175}
1176inline bool SwFrame::IsFootnoteContFrame() const
1177{
1178 return mnFrameType == SwFrameType::FtnCont;
1179}
1180inline bool SwFrame::IsFootnoteFrame() const
1181{
1182 return mnFrameType == SwFrameType::Ftn;
1183}
1184inline bool SwFrame::IsBodyFrame() const
1185{
1186 return mnFrameType == SwFrameType::Body;
1187}
1188inline bool SwFrame::IsFlyFrame() const
1189{
1190 return mnFrameType == SwFrameType::Fly;
1191}
1192inline bool SwFrame::IsSctFrame() const
1193{
1194 return mnFrameType == SwFrameType::Section;
1195}
1196inline bool SwFrame::IsTabFrame() const
1197{
1198 return mnFrameType == SwFrameType::Tab;
1199}
1200inline bool SwFrame::IsRowFrame() const
1201{
1202 return mnFrameType == SwFrameType::Row;
1203}
1204inline bool SwFrame::IsCellFrame() const
1205{
1206 return mnFrameType == SwFrameType::Cell;
31
Assuming field 'mnFrameType' is equal to Cell
32
Returning the value 1, which participates in a condition later
1207}
1208inline bool SwFrame::IsContentFrame() const
1209{
1210 return bool(GetType() & FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt));
1211}
1212inline bool SwFrame::IsTextFrame() const
1213{
1214 return mnFrameType == SwFrameType::Txt;
1215}
1216inline bool SwFrame::IsNoTextFrame() const
1217{
1218 return mnFrameType == SwFrameType::NoTxt;
1219}
1220inline bool SwFrame::IsFlowFrame() const
1221{
1222 return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section));
1223}
1224inline bool SwFrame::IsRetoucheFrame() const
1225{
1226 return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section|SwFrameType::Ftn));
1227}
1228inline bool SwFrame::IsAccessibleFrame() const
1229{
1230 return bool(GetType() & FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header |
SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType
::Tab | SwFrameType::Cell | SwFrameType::Txt)
);
1231}
1232
1233//use this to protect a SwFrame for a given scope from getting deleted
1234class SwFrameDeleteGuard
1235{
1236private:
1237 SwFrame *m_pForbidFrame;
1238public:
1239 //Flag pFrame for SwFrameDeleteGuard lifetime that we shouldn't delete
1240 //it in e.g. SwSectionFrame::MergeNext etc because we will need it
1241 //again after the SwFrameDeleteGuard dtor
1242 explicit SwFrameDeleteGuard(SwFrame* pFrame)
1243 : m_pForbidFrame((pFrame && !pFrame->IsDeleteForbidden()) ?
1244 pFrame : nullptr)
1245 {
1246 if (m_pForbidFrame)
1247 m_pForbidFrame->ForbidDelete();
1248 }
1249
1250 SwFrameDeleteGuard(const SwFrameDeleteGuard&) =delete;
1251
1252 ~SwFrameDeleteGuard()
1253 {
1254 if (m_pForbidFrame)
1255 m_pForbidFrame->AllowDelete();
1256 }
1257
1258 SwFrameDeleteGuard& operator=(const SwFrameDeleteGuard&) =delete;
1259};
1260
1261typedef long (SwFrame::*SwFrameGet)() const;
1262typedef bool (SwFrame::*SwFrameMax)( long );
1263typedef void (SwFrame::*SwFrameMakePos)( const SwFrame*, const SwFrame*, bool );
1264typedef long (*SwOperator)( long, long );
1265typedef void (SwFrame::*SwFrameSet)( long, long );
1266
1267struct SwRectFnCollection
1268{
1269 SwRectGet fnGetTop;
1270 SwRectGet fnGetBottom;
1271 SwRectGet fnGetLeft;
1272 SwRectGet fnGetRight;
1273 SwRectGet fnGetWidth;
1274 SwRectGet fnGetHeight;
1275 SwRectPoint fnGetPos;
1276 SwRectSize fnGetSize;
1277
1278 SwRectSet fnSetTop;
1279 SwRectSet fnSetBottom;
1280 SwRectSet fnSetLeft;
1281 SwRectSet fnSetRight;
1282 SwRectSet fnSetWidth;
1283 SwRectSet fnSetHeight;
1284
1285 SwRectSet fnSubTop;
1286 SwRectSet fnAddBottom;
1287 SwRectSet fnSubLeft;
1288 SwRectSet fnAddRight;
1289 SwRectSet fnAddWidth;
1290 SwRectSet fnAddHeight;
1291
1292 SwRectSet fnSetPosX;
1293 SwRectSet fnSetPosY;
1294
1295 SwFrameGet fnGetTopMargin;
1296 SwFrameGet fnGetBottomMargin;
1297 SwFrameGet fnGetLeftMargin;
1298 SwFrameGet fnGetRightMargin;
1299 SwFrameSet fnSetXMargins;
1300 SwFrameSet fnSetYMargins;
1301 SwFrameGet fnGetPrtTop;
1302 SwFrameGet fnGetPrtBottom;
1303 SwFrameGet fnGetPrtLeft;
1304 SwFrameGet fnGetPrtRight;
1305 SwRectDist fnTopDist;
1306 SwRectDist fnBottomDist;
1307 SwRectDist fnLeftDist;
1308 SwRectDist fnRightDist;
1309 SwFrameMax fnSetLimit;
1310 SwRectMax fnOverStep;
1311
1312 SwRectSetPos fnSetPos;
1313 SwFrameMakePos fnMakePos;
1314 SwOperator fnXDiff;
1315 SwOperator fnYDiff;
1316 SwOperator fnXInc;
1317 SwOperator fnYInc;
1318
1319 SwRectSetTwice fnSetLeftAndWidth;
1320 SwRectSetTwice fnSetTopAndHeight;
1321};
1322
1323typedef SwRectFnCollection* SwRectFn;
1324
1325// This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical)
1326extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T;
1327class SwRectFnSet {
1328public:
1329 explicit SwRectFnSet(const SwFrame *pFrame)
1330 : m_bVert(pFrame->IsVertical())
1331 , m_bVertL2R(pFrame->IsVertLR())
1332 , m_bVertL2RB2T(pFrame->IsVertLRBT())
1333 {
1334 m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori;
1335 }
1336
1337 void Refresh(const SwFrame *pFrame)
1338 {
1339 m_bVert = pFrame->IsVertical();
1340 m_bVertL2R = pFrame->IsVertLR();
1341 m_bVertL2RB2T = pFrame->IsVertLRBT();
1342 m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori;
1343 }
1344
1345 bool IsVert() const { return m_bVert; }
1346 bool IsVertL2R() const { return m_bVertL2R; }
1347 SwRectFn FnRect() const { return m_fnRect; }
1348
1349 bool PosDiff(const SwRect &rRect1, const SwRect &rRect2) const
1350 {
1351 return ((rRect1.*m_fnRect->fnGetTop)() != (rRect2.*m_fnRect->fnGetTop)()
1352 || (rRect1.*m_fnRect->fnGetLeft)() != (rRect2.*m_fnRect->fnGetLeft)());
1353 }
1354
1355 long GetTop (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetTop) (); }
1356 long GetBottom(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetBottom)(); }
1357 long GetLeft (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetLeft) (); }
1358 long GetRight (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetRight) (); }
1359 long GetWidth (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetWidth) (); }
1360 long GetHeight(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetHeight)(); }
1361 Point GetPos (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetPos) (); }
1362 Size GetSize (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetSize) (); }
1363
1364 void SetTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetTop) (nNew); }
1365 void SetBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetBottom)(nNew); }
1366 void SetLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetLeft) (nNew); }
1367 void SetRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetRight) (nNew); }
1368 void SetWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetWidth) (nNew); }
1369 void SetHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetHeight)(nNew); }
1370
1371 void SubTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubTop) (nNew); }
1372 void AddBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddBottom)(nNew); }
1373 void SubLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubLeft) (nNew); }
1374 void AddRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddRight) (nNew); }
1375 void AddWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddWidth) (nNew); }
1376 void AddHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddHeight)(nNew); }
1377
1378 void SetPosX(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosX)(nNew); }
1379 void SetPosY(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosY)(nNew); }
1380
1381 long GetTopMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetTopMargin) (); }
1382 long GetBottomMargin(const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetBottomMargin)(); }
1383 long GetLeftMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetLeftMargin) (); }
1384 long GetRightMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetRightMargin) (); }
1385 void SetXMargins(SwFrame& rFrame, long nLeft, long nRight) const { (rFrame.*m_fnRect->fnSetXMargins)(nLeft, nRight); }
1386 void SetYMargins(SwFrame& rFrame, long nTop, long nBottom) const { (rFrame.*m_fnRect->fnSetYMargins)(nTop, nBottom); }
1387 long GetPrtTop (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtTop) (); }
1388 long GetPrtBottom (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtBottom) (); }
1389 long GetPrtLeft (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtLeft) (); }
1390 long GetPrtRight (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtRight) (); }
1391 long TopDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnTopDist) (nPos); }
1392 long BottomDist(const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnBottomDist) (nPos); }
1393 long LeftDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnLeftDist) (nPos); }
1394 long RightDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnRightDist) (nPos); }
1395 void SetLimit (SwFrame& rFrame, long nNew) const { (rFrame.*m_fnRect->fnSetLimit) (nNew); }
1396 bool OverStep (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnOverStep) (nPos); }
1397
1398 void SetPos(SwRect& rRect, const Point& rNew) const { (rRect.*m_fnRect->fnSetPos)(rNew); }
1399 void MakePos(SwFrame& rFrame, const SwFrame* pUp, const SwFrame* pPrv, bool bNotify) const { (rFrame.*m_fnRect->fnMakePos)(pUp, pPrv, bNotify); }
1400 long XDiff(long n1, long n2) const { return (m_fnRect->fnXDiff) (n1, n2); }
1401 long YDiff(long n1, long n2) const { return (m_fnRect->fnYDiff) (n1, n2); }
1402 long XInc (long n1, long n2) const { return (m_fnRect->fnXInc) (n1, n2); }
1403 long YInc (long n1, long n2) const { return (m_fnRect->fnYInc) (n1, n2); }
1404
1405 void SetLeftAndWidth(SwRect& rRect, long nLeft, long nWidth) const { (rRect.*m_fnRect->fnSetLeftAndWidth)(nLeft, nWidth); }
1406 void SetTopAndHeight(SwRect& rRect, long nTop, long nHeight) const { (rRect.*m_fnRect->fnSetTopAndHeight)(nTop, nHeight); }
1407
1408private:
1409 bool m_bVert;
1410 bool m_bVertL2R;
1411 bool m_bVertL2RB2T;
1412 SwRectFn m_fnRect;
1413};
1414
1415#endif
1416
1417/* vim:set shiftwidth=4 softtabstop=4 expandtab: */