Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx
Warning:line 3854, column 31
Division by zero

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 wsfrm.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/wsfrm.cxx

/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.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 <hints.hxx>
21#include <o3tl/safeint.hxx>
22#include <svl/itemiter.hxx>
23#include <editeng/brushitem.hxx>
24#include <fmtornt.hxx>
25#include <pagefrm.hxx>
26#include <section.hxx>
27#include <rootfrm.hxx>
28#include <anchoreddrawobject.hxx>
29#include <fmtanchr.hxx>
30#include <viewimp.hxx>
31#include <viewopt.hxx>
32#include <IDocumentSettingAccess.hxx>
33#include <IDocumentFieldsAccess.hxx>
34#include <IDocumentRedlineAccess.hxx>
35#include <redline.hxx>
36#include <docsh.hxx>
37#include <ftninfo.hxx>
38#include <ftnidx.hxx>
39#include <fmtclbl.hxx>
40#include <fmtfsize.hxx>
41#include <fmtpdsc.hxx>
42#include <txtftn.hxx>
43#include <fmtftn.hxx>
44#include <fmtsrnd.hxx>
45#include <fmtcntnt.hxx>
46#include <ftnfrm.hxx>
47#include <tabfrm.hxx>
48#include <flyfrm.hxx>
49#include <sectfrm.hxx>
50#include <fmtclds.hxx>
51#include <txtfrm.hxx>
52#include <bodyfrm.hxx>
53#include <cellfrm.hxx>
54#include <dbg_lay.hxx>
55#include <editeng/frmdiritem.hxx>
56#include <sortedobjs.hxx>
57#include <frmatr.hxx>
58#include <frmtool.hxx>
59#include <ndtxt.hxx>
60#include <swtable.hxx>
61
62// RotateFlyFrame3
63#include <basegfx/matrix/b2dhommatrixtools.hxx>
64
65using namespace ::com::sun::star;
66
67SwFrameAreaDefinition::SwFrameAreaDefinition()
68: maFrameArea(),
69 maFramePrintArea(),
70 mbFrameAreaPositionValid(false),
71 mbFrameAreaSizeValid(false),
72 mbFramePrintAreaValid(false),
73 mnFrameId(SwFrameAreaDefinition::mnLastFrameId++)
74{
75}
76
77SwFrameAreaDefinition::~SwFrameAreaDefinition()
78{
79}
80
81void SwFrameAreaDefinition::setFrameAreaPositionValid(bool bNew)
82{
83 if(mbFrameAreaPositionValid != bNew)
84 {
85 mbFrameAreaPositionValid = bNew;
86 }
87}
88
89void SwFrameAreaDefinition::setFrameAreaSizeValid(bool bNew)
90{
91 if(mbFrameAreaSizeValid != bNew)
92 {
93 mbFrameAreaSizeValid = bNew;
94 }
95}
96
97void SwFrameAreaDefinition::setFramePrintAreaValid(bool bNew)
98{
99 if(mbFramePrintAreaValid != bNew)
100 {
101 mbFramePrintAreaValid = bNew;
102 }
103}
104
105SwFrameAreaDefinition::FrameAreaWriteAccess::~FrameAreaWriteAccess()
106{
107 if(mrTarget.maFrameArea != *this)
108 {
109 mrTarget.maFrameArea = *this;
110 }
111}
112
113SwFrameAreaDefinition::FramePrintAreaWriteAccess::~FramePrintAreaWriteAccess()
114{
115 if(mrTarget.maFramePrintArea != *this)
116 {
117 mrTarget.maFramePrintArea = *this;
118 }
119}
120
121// RotateFlyFrame3 - Support for Transformations
122basegfx::B2DHomMatrix SwFrameAreaDefinition::getFrameAreaTransformation() const
123{
124 // default implementation hands out FrameArea (outer frame)
125 const SwRect& rFrameArea(getFrameArea());
126
127 return basegfx::utils::createScaleTranslateB2DHomMatrix(
128 rFrameArea.Width(), rFrameArea.Height(),
129 rFrameArea.Left(), rFrameArea.Top());
130}
131
132basegfx::B2DHomMatrix SwFrameAreaDefinition::getFramePrintAreaTransformation() const
133{
134 // default implementation hands out FramePrintArea (outer frame)
135 // Take into account that FramePrintArea is relative to FrameArea
136 const SwRect& rFrameArea(getFrameArea());
137 const SwRect& rFramePrintArea(getFramePrintArea());
138
139 return basegfx::utils::createScaleTranslateB2DHomMatrix(
140 rFramePrintArea.Width(), rFramePrintArea.Height(),
141 rFramePrintArea.Left() + rFrameArea.Left(),
142 rFramePrintArea.Top() + rFrameArea.Top());
143}
144
145void SwFrameAreaDefinition::transform_translate(const Point& rOffset)
146{
147 // RotateFlyFrame3: default is to change the FrameArea, FramePrintArea needs no
148 // change since it is relative to FrameArea
149 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
150
151 if (aFrm.Pos().X() != FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000))
152 {
153 aFrm.Pos().AdjustX(rOffset.X() );
154 }
155
156 if (aFrm.Pos().Y() != FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000))
157 {
158 aFrm.Pos().AdjustY(rOffset.Y() );
159 }
160}
161
162SwRect TransformableSwFrame::getUntransformedFrameArea() const
163{
164 const basegfx::B2DHomMatrix& rSource(getLocalFrameAreaTransformation());
165
166 if(rSource.isIdentity())
167 {
168 return mrSwFrameAreaDefinition.getFrameArea();
169 }
170 else
171 {
172 basegfx::B2DVector aScale, aTranslate;
173 double fRotate, fShearX;
174 rSource.decompose(aScale, aTranslate, fRotate, fShearX);
175 const basegfx::B2DPoint aCenter(rSource * basegfx::B2DPoint(0.5, 0.5));
176 const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale));
177
178 return SwRect(
179 basegfx::fround(aCenter.getX() - (0.5 * aAbsScale.getX())),
180 basegfx::fround(aCenter.getY() - (0.5 * aAbsScale.getY())),
181 basegfx::fround(aAbsScale.getX()),
182 basegfx::fround(aAbsScale.getY()));
183 }
184}
185
186SwRect TransformableSwFrame::getUntransformedFramePrintArea() const
187{
188 const basegfx::B2DHomMatrix& rSource(getLocalFramePrintAreaTransformation());
189
190 if(rSource.isIdentity())
191 {
192 return mrSwFrameAreaDefinition.getFramePrintArea();
193 }
194 else
195 {
196 basegfx::B2DVector aScale, aTranslate;
197 double fRotate, fShearX;
198 rSource.decompose(aScale, aTranslate, fRotate, fShearX);
199 const basegfx::B2DPoint aCenter(rSource * basegfx::B2DPoint(0.5, 0.5));
200 const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale));
201 const SwRect aUntransformedFrameArea(getUntransformedFrameArea());
202
203 return SwRect(
204 basegfx::fround(aCenter.getX() - (0.5 * aAbsScale.getX())) - aUntransformedFrameArea.Left(),
205 basegfx::fround(aCenter.getY() - (0.5 * aAbsScale.getY())) - aUntransformedFrameArea.Top(),
206 basegfx::fround(aAbsScale.getX()),
207 basegfx::fround(aAbsScale.getY()));
208 }
209}
210
211void TransformableSwFrame::createFrameAreaTransformations(
212 double fRotation,
213 const basegfx::B2DPoint& rCenter)
214{
215 const basegfx::B2DHomMatrix aRotateAroundCenter(
216 basegfx::utils::createRotateAroundPoint(
217 rCenter.getX(),
218 rCenter.getY(),
219 fRotation));
220 const SwRect& rFrameArea(mrSwFrameAreaDefinition.getFrameArea());
221 const SwRect& rFramePrintArea(mrSwFrameAreaDefinition.getFramePrintArea());
222
223 maFrameAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix(
224 rFrameArea.Width(), rFrameArea.Height(),
225 rFrameArea.Left(), rFrameArea.Top());
226 maFramePrintAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix(
227 rFramePrintArea.Width(), rFramePrintArea.Height(),
228 rFramePrintArea.Left() + rFrameArea.Left(), rFramePrintArea.Top() + rFrameArea.Top());
229}
230
231void TransformableSwFrame::adaptFrameAreasToTransformations()
232{
233 if(!getLocalFrameAreaTransformation().isIdentity())
234 {
235 basegfx::B2DRange aRangeFrameArea(0.0, 0.0, 1.0, 1.0);
236 aRangeFrameArea.transform(getLocalFrameAreaTransformation());
237 const SwRect aNewFrm(
238 basegfx::fround(aRangeFrameArea.getMinX()), basegfx::fround(aRangeFrameArea.getMinY()),
239 basegfx::fround(aRangeFrameArea.getWidth()), basegfx::fround(aRangeFrameArea.getHeight()));
240
241 if(aNewFrm != mrSwFrameAreaDefinition.getFrameArea())
242 {
243 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition);
244 aFrm.setSwRect(aNewFrm);
245 }
246 }
247
248 if(getLocalFramePrintAreaTransformation().isIdentity())
249 return;
250
251 basegfx::B2DRange aRangeFramePrintArea(0.0, 0.0, 1.0, 1.0);
252 aRangeFramePrintArea.transform(getLocalFramePrintAreaTransformation());
253 const SwRect aNewPrt(
254 basegfx::fround(aRangeFramePrintArea.getMinX()) - mrSwFrameAreaDefinition.getFrameArea().Left(),
255 basegfx::fround(aRangeFramePrintArea.getMinY()) - mrSwFrameAreaDefinition.getFrameArea().Top(),
256 basegfx::fround(aRangeFramePrintArea.getWidth()),
257 basegfx::fround(aRangeFramePrintArea.getHeight()));
258
259 if(aNewPrt != mrSwFrameAreaDefinition.getFramePrintArea())
260 {
261 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition);
262 aPrt.setSwRect(aNewPrt);
263 }
264}
265
266void TransformableSwFrame::restoreFrameAreas()
267{
268 // This can be done fully based on the Transformations currently
269 // set, so use this. Only needed when transformation *is* used
270 if(!getLocalFrameAreaTransformation().isIdentity())
271 {
272 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition);
273 aFrm.setSwRect(getUntransformedFrameArea());
274 }
275
276 if(!getLocalFramePrintAreaTransformation().isIdentity())
277 {
278 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition);
279 aPrt.setSwRect(getUntransformedFramePrintArea());
280 }
281}
282
283// transform by given B2DHomMatrix
284void TransformableSwFrame::transform(const basegfx::B2DHomMatrix& aTransform)
285{
286 maFrameAreaTransformation *= aTransform;
287 maFramePrintAreaTransformation *= aTransform;
288}
289
290SwFrame::SwFrame( SwModify *pMod, SwFrame* pSib )
291: SwFrameAreaDefinition(),
292 SwClient( pMod ),
293 SfxBroadcaster(),
294 mpRoot( pSib ? pSib->getRootFrame() : nullptr ),
295 mpUpper(nullptr),
296 mpNext(nullptr),
297 mpPrev(nullptr),
298 mnFrameType(SwFrameType::None),
299 mbInDtor(false),
300 mbInvalidR2L(true),
301 mbDerivedR2L(false),
302 mbRightToLeft(false),
303 mbInvalidVert(true),
304 mbDerivedVert(false),
305 mbVertical(false),
306 mbVertLR(false),
307 mbVertLRBT(false),
308 mbValidLineNum(false),
309 mbFixSize(false),
310 mbCompletePaint(true),
311 mbRetouche(false),
312 mbInfInvalid(true),
313 mbInfBody( false ),
314 mbInfTab ( false ),
315 mbInfFly ( false ),
316 mbInfFootnote ( false ),
317 mbInfSct ( false ),
318 mbColLocked(false),
319 m_isInDestroy(false),
320 mbForbidDelete(false)
321{
322 OSL_ENSURE( pMod, "No frame format given." )do { if (true && (!(pMod))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "322" ": "), "%s", "No frame format given."); } } while (
false)
;
323}
324
325const IDocumentDrawModelAccess& SwFrame::getIDocumentDrawModelAccess()
326{
327 return GetUpper()->GetFormat()->getIDocumentDrawModelAccess();
328}
329
330bool SwFrame::KnowsFormat( const SwFormat& rFormat ) const
331{
332 return GetRegisteredIn() == &rFormat;
333}
334
335void SwFrame::RegisterToFormat( SwFormat& rFormat )
336{
337 rFormat.Add( this );
338}
339
340void SwFrame::CheckDir( SvxFrameDirection nDir, bool bVert, bool bOnlyBiDi, bool bBrowse )
341{
342 if( SvxFrameDirection::Environment == nDir || ( bVert && bOnlyBiDi ) )
343 {
344 mbDerivedVert = true;
345 if( SvxFrameDirection::Environment == nDir )
346 mbDerivedR2L = true;
347 SetDirFlags( bVert );
348 }
349 else if( bVert )
350 {
351 mbInvalidVert = false;
352 if( SvxFrameDirection::Horizontal_LR_TB == nDir || SvxFrameDirection::Horizontal_RL_TB == nDir
353 || bBrowse )
354 {
355 mbVertical = false;
356 mbVertLR = false;
357 mbVertLRBT = false;
358 }
359 else
360 {
361 mbVertical = true;
362 if(SvxFrameDirection::Vertical_RL_TB == nDir)
363 {
364 mbVertLR = false;
365 mbVertLRBT = false;
366 }
367 else if(SvxFrameDirection::Vertical_LR_TB==nDir)
368 {
369 mbVertLR = true;
370 mbVertLRBT = false;
371 }
372 else if (nDir == SvxFrameDirection::Vertical_LR_BT)
373 {
374 mbVertLR = true;
375 mbVertLRBT = true;
376 }
377 }
378 }
379 else
380 {
381 mbInvalidR2L = false;
382 if( SvxFrameDirection::Horizontal_RL_TB == nDir )
383 mbRightToLeft = true;
384 else
385 mbRightToLeft = false;
386 }
387}
388
389void SwFrame::CheckDirection( bool bVert )
390{
391 if( bVert )
392 {
393 if( !IsHeaderFrame() && !IsFooterFrame() )
394 {
395 mbDerivedVert = true;
396 SetDirFlags( bVert );
397 }
398 }
399 else
400 {
401 mbDerivedR2L = true;
402 SetDirFlags( bVert );
403 }
404}
405
406void SwSectionFrame::CheckDirection( bool bVert )
407{
408 const SwFrameFormat* pFormat = GetFormat();
409 if( pFormat )
410 {
411 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
412 const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
413 CheckDir(pFormat->GetFormatAttr(RES_FRAMEDIR).GetValue(),
414 bVert, true, bBrowseMode );
415 }
416 else
417 SwFrame::CheckDirection( bVert );
418}
419
420void SwFlyFrame::CheckDirection( bool bVert )
421{
422 const SwFrameFormat* pFormat = GetFormat();
423 if( pFormat )
424 {
425 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
426 const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
427 CheckDir(pFormat->GetFormatAttr(RES_FRAMEDIR).GetValue(),
428 bVert, false, bBrowseMode );
429 }
430 else
431 SwFrame::CheckDirection( bVert );
432}
433
434void SwTabFrame::CheckDirection( bool bVert )
435{
436 const SwFrameFormat* pFormat = GetFormat();
437 if( pFormat )
438 {
439 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
440 const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
441 CheckDir(pFormat->GetFormatAttr(RES_FRAMEDIR).GetValue(),
442 bVert, true, bBrowseMode );
443 }
444 else
445 SwFrame::CheckDirection( bVert );
446}
447
448void SwCellFrame::CheckDirection( bool bVert )
449{
450 const SwFrameFormat* pFormat = GetFormat();
451 const SfxPoolItem* pItem;
452 // Check if the item is set, before actually
453 // using it. Otherwise the dynamic pool default is used, which may be set
454 // to LTR in case of OOo 1.0 documents.
455 if( pFormat && SfxItemState::SET == pFormat->GetItemState( RES_FRAMEDIR, true, &pItem ) )
456 {
457 const SvxFrameDirectionItem* pFrameDirItem = static_cast<const SvxFrameDirectionItem*>(pItem);
458 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
459 const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
460 CheckDir( pFrameDirItem->GetValue(), bVert, false, bBrowseMode );
461 }
462 else
463 SwFrame::CheckDirection( bVert );
464}
465
466void SwTextFrame::CheckDirection( bool bVert )
467{
468 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
469 const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
470 CheckDir(GetTextNodeForParaProps()->GetSwAttrSet().GetFrameDir().GetValue(),
471 bVert, true, bBrowseMode);
472}
473
474void SwFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
475{
476 sal_uInt8 nInvFlags = 0;
477
478 if( pOld && pNew && RES_ATTRSET_CHG == pNew->Which() )
479 {
480 SfxItemIter aNIter( *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet() );
481 SfxItemIter aOIter( *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet() );
482 const SfxPoolItem* pNItem = aNIter.GetCurItem();
483 const SfxPoolItem* pOItem = aOIter.GetCurItem();
484 do
485 {
486 UpdateAttrFrame(pOItem, pNItem, nInvFlags);
487 pNItem = aNIter.NextItem();
488 pOItem = aOIter.NextItem();
489 } while (pNItem);
490 }
491 else
492 UpdateAttrFrame( pOld, pNew, nInvFlags );
493
494 if ( nInvFlags == 0 )
495 return;
496
497 SwPageFrame *pPage = FindPageFrame();
498 InvalidatePage( pPage );
499 if ( nInvFlags & 0x01 )
500 {
501 InvalidatePrt_();
502 if( !GetPrev() && IsTabFrame() && IsInSct() )
503 FindSctFrame()->InvalidatePrt_();
504 }
505 if ( nInvFlags & 0x02 )
506 InvalidateSize_();
507 if ( nInvFlags & 0x04 )
508 InvalidatePos_();
509 if ( nInvFlags & 0x08 )
510 SetCompletePaint();
511 SwFrame *pNxt;
512 if ( nInvFlags & 0x30 && nullptr != (pNxt = GetNext()) )
513 {
514 pNxt->InvalidatePage( pPage );
515 if ( nInvFlags & 0x10 )
516 pNxt->InvalidatePos_();
517 if ( nInvFlags & 0x20 )
518 pNxt->SetCompletePaint();
519 }
520}
521
522void SwFrame::UpdateAttrFrame( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
523 sal_uInt8 &rInvFlags )
524{
525 sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
526 switch( nWhich )
527 {
528 case RES_BOX:
529 case RES_SHADOW:
530 Prepare( PrepareHint::FixSizeChanged );
531 [[fallthrough]];
532 case RES_LR_SPACE:
533 case RES_UL_SPACE:
534 rInvFlags |= 0x0B;
535 break;
536
537 case RES_HEADER_FOOTER_EAT_SPACING:
538 rInvFlags |= 0x03;
539 break;
540
541 case RES_BACKGROUND:
542 rInvFlags |= 0x28;
543 break;
544
545 case RES_KEEP:
546 rInvFlags |= 0x04;
547 break;
548
549 case RES_FRM_SIZE:
550 ReinitializeFrameSizeAttrFlags();
551 rInvFlags |= 0x13;
552 break;
553
554 case RES_FMT_CHG:
555 rInvFlags |= 0x0F;
556 break;
557
558 case RES_ROW_SPLIT:
559 {
560 if ( IsRowFrame() )
561 {
562 bool bInFollowFlowRow = nullptr != IsInFollowFlowRow();
563 if ( bInFollowFlowRow || nullptr != IsInSplitTableRow() )
564 {
565 SwTabFrame* pTab = FindTabFrame();
566 if ( bInFollowFlowRow )
567 pTab = pTab->FindMaster();
568 pTab->SetRemoveFollowFlowLinePending( true );
569 }
570 }
571 break;
572 }
573 case RES_COL:
574 OSL_FAIL( "Columns for new FrameType?" )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/wsfrm.cxx"
":" "574" ": "), "%s", "Columns for new FrameType?"); } } while
(false)
;
575 break;
576
577 default:
578 // the new FillStyle has to do the same as previous RES_BACKGROUND
579 if(nWhich >= XATTR_FILL_FIRST && nWhich <= XATTR_FILL_LAST)
580 {
581 rInvFlags |= 0x28;
582 }
583 /* do Nothing */;
584 }
585}
586
587bool SwFrame::Prepare( const PrepareHint, const void *, bool )
588{
589 /* Do nothing */
590 return false;
591}
592
593/**
594 * Invalidates the page in which the Frame is currently placed.
595 * The page is invalidated depending on the type (Layout, Content, FlyFrame)
596 */
597void SwFrame::InvalidatePage( const SwPageFrame *pPage ) const
598{
599 if ( !pPage )
600 {
601 pPage = FindPageFrame();
602 // #i28701# - for at-character and as-character
603 // anchored Writer fly frames additionally invalidate also page frame
604 // its 'anchor character' is on.
605 if ( pPage && pPage->GetUpper() && IsFlyFrame() )
606 {
607 const SwFlyFrame* pFlyFrame = static_cast<const SwFlyFrame*>(this);
608 if ( pFlyFrame->IsAutoPos() || pFlyFrame->IsFlyInContentFrame() )
609 {
610 // #i33751#, #i34060# - method <GetPageFrameOfAnchor()>
611 // is replaced by method <FindPageFrameOfAnchor()>. It's return value
612 // have to be checked.
613 SwPageFrame* pPageFrameOfAnchor =
614 const_cast<SwFlyFrame*>(pFlyFrame)->FindPageFrameOfAnchor();
615 if ( pPageFrameOfAnchor && pPageFrameOfAnchor != pPage )
616 {
617 InvalidatePage( pPageFrameOfAnchor );
618 }
619 }
620 }
621 }
622
623 if ( !(pPage && pPage->GetUpper()) )
624 return;
625
626 if ( pPage->GetFormat()->GetDoc()->IsInDtor() )
627 return;
628
629 SwRootFrame *pRoot = const_cast<SwRootFrame*>(static_cast<const SwRootFrame*>(pPage->GetUpper()));
630 const SwFlyFrame *pFly = FindFlyFrame();
631 if ( IsContentFrame() )
632 {
633 if ( pRoot->IsTurboAllowed() )
634 {
635 // If a ContentFrame wants to register for a second time, make it a TurboAction.
636 if ( !pRoot->GetTurbo() || this == pRoot->GetTurbo() )
637 pRoot->SetTurbo( static_cast<const SwContentFrame*>(this) );
638 else
639 {
640 pRoot->DisallowTurbo();
641 //The page of the Turbo could be a different one then mine,
642 //therefore we have to invalidate it.
643 const SwFrame *pTmp = pRoot->GetTurbo();
644 pRoot->ResetTurbo();
645 pTmp->InvalidatePage();
646 }
647 }
648 if ( !pRoot->GetTurbo() )
649 {
650 if ( pFly )
651 { if( !pFly->IsLocked() )
652 {
653 if ( pFly->IsFlyInContentFrame() )
654 { pPage->InvalidateFlyInCnt();
655 pFly->GetAnchorFrame()->InvalidatePage();
656 }
657 else
658 pPage->InvalidateFlyContent();
659 }
660 }
661 else
662 pPage->InvalidateContent();
663 }
664 }
665 else
666 {
667 pRoot->DisallowTurbo();
668 if ( pFly )
669 {
670 if ( !pFly->IsLocked() )
671 {
672 if ( pFly->IsFlyInContentFrame() )
673 {
674 pPage->InvalidateFlyInCnt();
675 pFly->GetAnchorFrame()->InvalidatePage();
676 }
677 else
678 pPage->InvalidateFlyLayout();
679 }
680 }
681 else
682 pPage->InvalidateLayout();
683
684 if ( pRoot->GetTurbo() )
685 { const SwFrame *pTmp = pRoot->GetTurbo();
686 pRoot->ResetTurbo();
687 pTmp->InvalidatePage();
688 }
689 }
690 pRoot->SetIdleFlags();
691
692 if (!IsTextFrame())
693 return;
694
695 SwTextFrame const*const pText(static_cast<SwTextFrame const*>(this));
696 if (sw::MergedPara const*const pMergedPara = pText->GetMergedPara())
697 {
698 SwTextNode const* pNode(nullptr);
699 for (auto const& e : pMergedPara->extents)
700 {
701 if (e.pNode != pNode)
702 {
703 pNode = e.pNode;
704 if (pNode->IsGrammarCheckDirty())
705 {
706 pRoot->SetNeedGrammarCheck( true );
707 break;
708 }
709 }
710 }
711 }
712 else
713 {
714 if (pText->GetTextNodeFirst()->IsGrammarCheckDirty())
715 {
716 pRoot->SetNeedGrammarCheck( true );
717 }
718 }
719}
720
721Size SwFrame::ChgSize( const Size& aNewSize )
722{
723 mbFixSize = true;
724 const Size aOldSize( getFrameArea().SSize() );
725 if ( aNewSize == aOldSize )
726 return aOldSize;
727
728 if ( GetUpper() )
729 {
730 bool bNeighb = IsNeighbourFrame();
731 SwRectFn fnRect = IsVertical() == bNeighb ? fnRectHori : ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert );
732 SwRect aNew( Point(0,0), aNewSize );
733
734 {
735 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
736 (aFrm.*fnRect->fnSetWidth)( (aNew.*fnRect->fnGetWidth)() );
737 }
738
739 long nNew = (aNew.*fnRect->fnGetHeight)();
740 long nDiff = nNew - (getFrameArea().*fnRect->fnGetHeight)();
741
742 if( nDiff )
743 {
744 if ( GetUpper()->IsFootnoteBossFrame() && HasFixSize() &&
745 SwNeighbourAdjust::GrowShrink !=
746 static_cast<SwFootnoteBossFrame*>(GetUpper())->NeighbourhoodAdjustment() )
747 {
748 {
749 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
750 (aFrm.*fnRect->fnSetHeight)( nNew );
751 }
752
753 SwTwips nReal = static_cast<SwLayoutFrame*>(this)->AdjustNeighbourhood(nDiff);
754
755 if ( nReal != nDiff )
756 {
757 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
758 (aFrm.*fnRect->fnSetHeight)( nNew - nDiff + nReal );
759 }
760 }
761 else
762 {
763 // OD 24.10.2002 #97265# - grow/shrink not for neighbour frames
764 // NOTE: neighbour frames are cell and column frames.
765 if ( !bNeighb )
766 {
767 if ( nDiff > 0 )
768 Grow( nDiff );
769 else
770 Shrink( -nDiff );
771
772 if ( GetUpper() && (getFrameArea().*fnRect->fnGetHeight)() != nNew )
773 {
774 GetUpper()->InvalidateSize_();
775 }
776 }
777
778 // Even if grow/shrink did not yet set the desired width, for
779 // example when called by ChgColumns to set the column width, we
780 // set the right width now.
781 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
782 (aFrm.*fnRect->fnSetHeight)( nNew );
783 }
784 }
785 }
786 else
787 {
788 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
789 aFrm.SSize( aNewSize );
790 }
791
792 if ( getFrameArea().SSize() != aOldSize )
793 {
794 SwPageFrame *pPage = FindPageFrame();
795 if ( GetNext() )
796 {
797 GetNext()->InvalidatePos_();
798 GetNext()->InvalidatePage( pPage );
799 }
800 if( IsLayoutFrame() )
801 {
802 if( IsRightToLeft() )
803 InvalidatePos_();
804 if( static_cast<SwLayoutFrame*>(this)->Lower() )
805 static_cast<SwLayoutFrame*>(this)->Lower()->InvalidateSize_();
806 }
807 InvalidatePrt_();
808 InvalidateSize_();
809 InvalidatePage( pPage );
810 }
811
812 return getFrameArea().SSize();
813}
814
815/** Insert SwFrame into existing structure.
816 *
817 * Insertion is done below the parent either before pBehind or
818 * at the end of the chain if pBehind is empty.
819 */
820void SwFrame::InsertBefore( SwLayoutFrame* pParent, SwFrame* pBehind )
821{
822 OSL_ENSURE( pParent, "No parent for insert." )do { if (true && (!(pParent))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "822" ": "), "%s", "No parent for insert."); } } while (
false)
;
823 OSL_ENSURE( (!pBehind || pParent == pBehind->GetUpper()),do { if (true && (!((!pBehind || pParent == pBehind->
GetUpper())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "824" ": "), "%s", "Frame tree is inconsistent."); } } while
(false)
824 "Frame tree is inconsistent." )do { if (true && (!((!pBehind || pParent == pBehind->
GetUpper())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "824" ": "), "%s", "Frame tree is inconsistent."); } } while
(false)
;
825
826 mpUpper = pParent;
827 mpNext = pBehind;
828 if( pBehind )
829 { //Insert before pBehind.
830 mpPrev = pBehind->mpPrev;
831 if( nullptr != mpPrev )
832 mpPrev->mpNext = this;
833 else
834 mpUpper->m_pLower = this;
835 pBehind->mpPrev = this;
836 }
837 else
838 { //Insert at the end, or as first node in the sub tree
839 mpPrev = mpUpper->Lower();
840 if ( mpPrev )
841 {
842 while( mpPrev->mpNext )
843 mpPrev = mpPrev->mpNext;
844 mpPrev->mpNext = this;
845 }
846 else
847 mpUpper->m_pLower = this;
848 }
849}
850
851/** Insert SwFrame into existing structure.
852 *
853 * Insertion is done below the parent either after pBehind or
854 * at the beginning of the chain if pBehind is empty.
855 */
856void SwFrame::InsertBehind( SwLayoutFrame *pParent, SwFrame *pBefore )
857{
858 OSL_ENSURE( pParent, "No Parent for Insert." )do { if (true && (!(pParent))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "858" ": "), "%s", "No Parent for Insert."); } } while (
false)
;
859 OSL_ENSURE( (!pBefore || pParent == pBefore->GetUpper()),do { if (true && (!((!pBefore || pParent == pBefore->
GetUpper())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "860" ": "), "%s", "Frame tree is inconsistent."); } } while
(false)
860 "Frame tree is inconsistent." )do { if (true && (!((!pBefore || pParent == pBefore->
GetUpper())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "860" ": "), "%s", "Frame tree is inconsistent."); } } while
(false)
;
861
862 mpUpper = pParent;
863 mpPrev = pBefore;
864 if ( pBefore )
865 {
866 //Insert after pBefore
867 mpNext = pBefore->mpNext;
868 if ( nullptr != mpNext )
869 mpNext->mpPrev = this;
870 pBefore->mpNext = this;
871 }
872 else
873 {
874 //Insert at the beginning of the chain
875 mpNext = pParent->Lower();
876 if ( pParent->Lower() )
877 pParent->Lower()->mpPrev = this;
878 pParent->m_pLower = this;
879 }
880}
881
882/** Insert a chain of SwFrames into an existing structure
883 *
884 * Currently, this method is used to insert a SectionFrame (which may have some siblings) into an
885 * existing structure. If the third parameter is NULL, this method is (besides handling the
886 * siblings) equal to SwFrame::InsertBefore(..).
887 *
888 * If the third parameter is passed, the following happens:
889 * - this becomes mpNext of pParent
890 * - pSct becomes mpNext of the last one in the this-chain
891 * - pBehind is reconnected from pParent to pSct
892 * The purpose is: a SectionFrame (this) won't become a child of another SectionFrame (pParent), but
893 * pParent gets split into two siblings (pParent+pSect) and this is inserted between.
894 */
895bool SwFrame::InsertGroupBefore( SwFrame* pParent, SwFrame* pBehind, SwFrame* pSct )
896{
897 OSL_ENSURE( pParent, "No parent for insert." )do { if (true && (!(pParent))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "897" ": "), "%s", "No parent for insert."); } } while (
false)
;
898 OSL_ENSURE( (!pBehind || ( (pBehind && (pParent == pBehind->GetUpper()))do { if (true && (!((!pBehind || ( (pBehind &&
(pParent == pBehind->GetUpper())) || ((pParent->IsSctFrame
() && pBehind->GetUpper()->IsColBodyFrame())) )
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "900" ": "), "%s", "Frame tree inconsistent."); } } while
(false)
899 || ((pParent->IsSctFrame() && pBehind->GetUpper()->IsColBodyFrame())) ) ),do { if (true && (!((!pBehind || ( (pBehind &&
(pParent == pBehind->GetUpper())) || ((pParent->IsSctFrame
() && pBehind->GetUpper()->IsColBodyFrame())) )
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "900" ": "), "%s", "Frame tree inconsistent."); } } while
(false)
900 "Frame tree inconsistent." )do { if (true && (!((!pBehind || ( (pBehind &&
(pParent == pBehind->GetUpper())) || ((pParent->IsSctFrame
() && pBehind->GetUpper()->IsColBodyFrame())) )
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "900" ": "), "%s", "Frame tree inconsistent."); } } while
(false)
;
901 if( pSct )
902 {
903 mpUpper = pParent->GetUpper();
904 SwFrame *pLast = this;
905 while( pLast->GetNext() )
906 {
907 pLast = pLast->GetNext();
908 pLast->mpUpper = GetUpper();
909 }
910 if( pBehind )
911 {
912 pLast->mpNext = pSct;
913 pSct->mpPrev = pLast;
914 pSct->mpNext = pParent->GetNext();
915 }
916 else
917 {
918 pLast->mpNext = pParent->GetNext();
919 if( pLast->GetNext() )
920 pLast->GetNext()->mpPrev = pLast;
921 }
922 pParent->mpNext = this;
923 mpPrev = pParent;
924 if( pSct->GetNext() )
925 pSct->GetNext()->mpPrev = pSct;
926 while( pLast->GetNext() )
927 {
928 pLast = pLast->GetNext();
929 pLast->mpUpper = GetUpper();
930 }
931 if( pBehind )
932 { // Insert before pBehind.
933 if( pBehind->GetPrev() )
934 pBehind->GetPrev()->mpNext = nullptr;
935 else
936 pBehind->GetUpper()->m_pLower = nullptr;
937 pBehind->mpPrev = nullptr;
938 SwLayoutFrame* pTmp = static_cast<SwLayoutFrame*>(pSct);
939 if( pTmp->Lower() )
940 {
941 OSL_ENSURE( pTmp->Lower()->IsColumnFrame(), "InsertGrp: Used SectionFrame" )do { if (true && (!(pTmp->Lower()->IsColumnFrame
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "941" ": "), "%s", "InsertGrp: Used SectionFrame"); } } while
(false)
;
942 pTmp = static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(pTmp->Lower())->Lower());
943 OSL_ENSURE( pTmp, "InsertGrp: Missing ColBody" )do { if (true && (!(pTmp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "943" ": "), "%s", "InsertGrp: Missing ColBody"); } } while
(false)
;
944 }
945 pBehind->mpUpper = pTmp;
946 pBehind->GetUpper()->m_pLower = pBehind;
947 pLast = pBehind->GetNext();
948 while ( pLast )
949 {
950 pLast->mpUpper = pBehind->GetUpper();
951 pLast = pLast->GetNext();
952 }
953 }
954 else
955 {
956 OSL_ENSURE( pSct->IsSctFrame(), "InsertGroup: For SectionFrames only" )do { if (true && (!(pSct->IsSctFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "956" ": "), "%s", "InsertGroup: For SectionFrames only"
); } } while (false)
;
957 SwFrame::DestroyFrame(pSct);
958 return false;
959 }
960 }
961 else
962 {
963 mpUpper = static_cast<SwLayoutFrame*>(pParent);
964 SwFrame *pLast = this;
965 while( pLast->GetNext() )
966 {
967 pLast = pLast->GetNext();
968 pLast->mpUpper = GetUpper();
969 }
970 pLast->mpNext = pBehind;
971 if( pBehind )
972 { // Insert before pBehind.
973 mpPrev = pBehind->mpPrev;
974 if( nullptr != mpPrev )
975 mpPrev->mpNext = this;
976 else
977 mpUpper->m_pLower = this;
978 pBehind->mpPrev = pLast;
979 }
980 else
981 {
982 //Insert at the end, or ... the first node in the subtree
983 mpPrev = mpUpper->Lower();
984 if ( mpPrev )
985 {
986 while( mpPrev->mpNext )
987 mpPrev = mpPrev->mpNext;
988 mpPrev->mpNext = this;
989 }
990 else
991 mpUpper->m_pLower = this;
992 }
993 }
994 return true;
995}
996
997void SwFrame::RemoveFromLayout()
998{
999 OSL_ENSURE( mpUpper, "Remove without upper?" )do { if (true && (!(mpUpper))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "999" ": "), "%s", "Remove without upper?"); } } while (
false)
;
1000
1001 if (mpPrev)
1002 // one out of the middle is removed
1003 mpPrev->mpNext = mpNext;
1004 else if (mpUpper)
1005 { // the first in a list is removed //TODO
1006 OSL_ENSURE( mpUpper->m_pLower == this, "Layout is inconsistent." )do { if (true && (!(mpUpper->m_pLower == this))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1006" ": "), "%s", "Layout is inconsistent."); } } while
(false)
;
1007 mpUpper->m_pLower = mpNext;
1008 }
1009 if( mpNext )
1010 mpNext->mpPrev = mpPrev;
1011
1012 // Remove link
1013 mpNext = mpPrev = nullptr;
1014 mpUpper = nullptr;
1015}
1016
1017void SwContentFrame::Paste( SwFrame* pParent, SwFrame* pSibling)
1018{
1019 OSL_ENSURE( pParent, "No parent for pasting." )do { if (true && (!(pParent))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1019" ": "), "%s", "No parent for pasting."); } } while
(false)
;
1020 OSL_ENSURE( pParent->IsLayoutFrame(), "Parent is ContentFrame." )do { if (true && (!(pParent->IsLayoutFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1020" ": "), "%s", "Parent is ContentFrame."); } } while
(false)
;
1021 OSL_ENSURE( pParent != this, "I'm the parent." )do { if (true && (!(pParent != this))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1021" ": "), "%s", "I'm the parent."); } } while (false
)
;
1022 OSL_ENSURE( pSibling != this, "I'm my own neighbour." )do { if (true && (!(pSibling != this))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1022" ": "), "%s", "I'm my own neighbour."); } } while (
false)
;
1023 OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),do { if (true && (!(!GetPrev() && !GetNext() &&
!GetUpper()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1024" ": "), "%s", "I'm still registered somewhere"); }
} while (false)
1024 "I'm still registered somewhere" )do { if (true && (!(!GetPrev() && !GetNext() &&
!GetUpper()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1024" ": "), "%s", "I'm still registered somewhere"); }
} while (false)
;
1025 OSL_ENSURE( !pSibling || pSibling->IsFlowFrame(),do { if (true && (!(!pSibling || pSibling->IsFlowFrame
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1026" ": "), "%s", "<SwContentFrame::Paste(..)> - sibling not of expected type."
); } } while (false)
1026 "<SwContentFrame::Paste(..)> - sibling not of expected type." )do { if (true && (!(!pSibling || pSibling->IsFlowFrame
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1026" ": "), "%s", "<SwContentFrame::Paste(..)> - sibling not of expected type."
); } } while (false)
;
1027
1028 //Insert in the tree.
1029 InsertBefore( static_cast<SwLayoutFrame*>(pParent), pSibling );
1030
1031 SwPageFrame *pPage = FindPageFrame();
1032 InvalidateAll_();
1033 InvalidatePage( pPage );
1034
1035 if( pPage )
1036 {
1037 pPage->InvalidateSpelling();
1038 pPage->InvalidateSmartTags();
1039 pPage->InvalidateAutoCompleteWords();
1040 pPage->InvalidateWordCount();
1041 }
1042
1043 if ( GetNext() )
1044 {
1045 SwFrame* pNxt = GetNext();
1046 pNxt->InvalidatePrt_();
1047 pNxt->InvalidatePos_();
1048 pNxt->InvalidatePage( pPage );
1049 if( pNxt->IsSctFrame() )
1050 pNxt = static_cast<SwSectionFrame*>(pNxt)->ContainsContent();
1051 if( pNxt && pNxt->IsTextFrame() && pNxt->IsInFootnote() )
1052 pNxt->Prepare( PrepareHint::FootnoteInvalidation, nullptr, false );
1053 }
1054
1055 if ( getFrameArea().Height() )
1056 pParent->Grow( getFrameArea().Height() );
1057
1058 if ( getFrameArea().Width() != pParent->getFramePrintArea().Width() )
1059 Prepare( PrepareHint::FixSizeChanged );
1060
1061 if ( GetPrev() )
1062 {
1063 if ( IsFollow() )
1064 //I'm a direct follower of my master now
1065 static_cast<SwContentFrame*>(GetPrev())->Prepare( PrepareHint::FollowFollows );
1066 else
1067 {
1068 if ( GetPrev()->getFrameArea().Height() !=
1069 GetPrev()->getFramePrintArea().Height() + GetPrev()->getFramePrintArea().Top() )
1070 {
1071 // Take the border into account?
1072 GetPrev()->InvalidatePrt_();
1073 }
1074 // OD 18.02.2003 #104989# - force complete paint of previous frame,
1075 // if frame is inserted at the end of a section frame, in order to
1076 // get subsidiary lines repainted for the section.
1077 if ( pParent->IsSctFrame() && !GetNext() )
1078 {
1079 // force complete paint of previous frame, if new inserted frame
1080 // in the section is the last one.
1081 GetPrev()->SetCompletePaint();
1082 }
1083 GetPrev()->InvalidatePage( pPage );
1084 }
1085 }
1086 if ( IsInFootnote() )
1087 {
1088 SwFrame* pFrame = GetIndPrev();
1089 if( pFrame && pFrame->IsSctFrame() )
1090 pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
1091 if( pFrame )
1092 pFrame->Prepare( PrepareHint::QuoVadis, nullptr, false );
1093 if( !GetNext() )
1094 {
1095 pFrame = FindFootnoteFrame()->GetNext();
1096 if( pFrame && nullptr != (pFrame=static_cast<SwLayoutFrame*>(pFrame)->ContainsAny()) )
1097 pFrame->InvalidatePrt_();
1098 }
1099 }
1100
1101 InvalidateLineNum_();
1102 SwFrame *pNxt = FindNextCnt();
1103 if ( !pNxt )
1104 return;
1105
1106 while ( pNxt && pNxt->IsInTab() )
1107 {
1108 pNxt = pNxt->FindTabFrame();
1109 if( nullptr != pNxt )
1110 pNxt = pNxt->FindNextCnt();
1111 }
1112 if ( pNxt )
1113 {
1114 pNxt->InvalidateLineNum_();
1115 if ( pNxt != GetNext() )
1116 pNxt->InvalidatePage();
1117 }
1118}
1119
1120void SwContentFrame::Cut()
1121{
1122 OSL_ENSURE( GetUpper(), "Cut without Upper()." )do { if (true && (!(GetUpper()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1122" ": "), "%s", "Cut without Upper()."); } } while (
false)
;
1123
1124 SwPageFrame *pPage = FindPageFrame();
1125 InvalidatePage( pPage );
1126 SwFrame *pFrame = GetIndPrev();
1127 if( pFrame )
1128 {
1129 if( pFrame->IsSctFrame() )
1130 pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
1131 if ( pFrame && pFrame->IsContentFrame() )
1132 {
1133 pFrame->InvalidatePrt_();
1134 if( IsInFootnote() )
1135 pFrame->Prepare( PrepareHint::QuoVadis, nullptr, false );
1136 }
1137 // #i26250# - invalidate printing area of previous
1138 // table frame.
1139 else if ( pFrame && pFrame->IsTabFrame() )
1140 {
1141 pFrame->InvalidatePrt();
1142 }
1143 }
1144
1145 SwFrame *pNxt = FindNextCnt();
1146 if ( pNxt )
1147 {
1148 while ( pNxt && pNxt->IsInTab() )
1149 {
1150 pNxt = pNxt->FindTabFrame();
1151 if( nullptr != pNxt )
1152 pNxt = pNxt->FindNextCnt();
1153 }
1154 if ( pNxt )
1155 {
1156 pNxt->InvalidateLineNum_();
1157 if ( pNxt != GetNext() )
1158 pNxt->InvalidatePage();
1159 }
1160 }
1161
1162 pFrame = GetIndNext();
1163 if( pFrame )
1164 {
1165 // The old follow may have calculated a gap to the predecessor which
1166 // now becomes obsolete or different as it becomes the first one itself
1167 pFrame->InvalidatePrt_();
1168 pFrame->InvalidatePos_();
1169 pFrame->InvalidatePage( pPage );
1170 if( pFrame->IsSctFrame() )
1171 {
1172 pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
1173 if( pFrame )
1174 {
1175 pFrame->InvalidatePrt_();
1176 pFrame->InvalidatePos_();
1177 pFrame->InvalidatePage( pPage );
1178 }
1179 }
1180 if( pFrame && IsInFootnote() )
1181 pFrame->Prepare( PrepareHint::ErgoSum, nullptr, false );
1182 if( IsInSct() && !GetPrev() )
1183 {
1184 SwSectionFrame* pSct = FindSctFrame();
1185 if( !pSct->IsFollow() )
1186 {
1187 pSct->InvalidatePrt_();
1188 pSct->InvalidatePage( pPage );
1189 }
1190 }
1191 }
1192 else
1193 {
1194 InvalidateNextPos();
1195 //Someone needs to do the retouching: predecessor or upper
1196 pFrame = GetPrev();
1197 if ( nullptr != pFrame )
1198 { pFrame->SetRetouche();
1199 pFrame->Prepare( PrepareHint::WidowsOrphans );
1200 pFrame->InvalidatePos_();
1201 pFrame->InvalidatePage( pPage );
1202 }
1203 // If I'm (was) the only ContentFrame in my upper, it has to do the
1204 // retouching. Also, perhaps a page became empty.
1205 else
1206 { SwRootFrame *pRoot = getRootFrame();
1207 if ( pRoot )
1208 {
1209 pRoot->SetSuperfluous();
1210 GetUpper()->SetCompletePaint();
1211 GetUpper()->InvalidatePage( pPage );
1212 }
1213 if( IsInSct() )
1214 {
1215 SwSectionFrame* pSct = FindSctFrame();
1216 if( !pSct->IsFollow() )
1217 {
1218 pSct->InvalidatePrt_();
1219 pSct->InvalidatePage( pPage );
1220 }
1221 }
1222 // #i52253# The master table should take care
1223 // of removing the follow flow line.
1224 if ( IsInTab() )
1225 {
1226 SwTabFrame* pThisTab = FindTabFrame();
1227 SwTabFrame* pMasterTab = pThisTab && pThisTab->IsFollow() ? pThisTab->FindMaster() : nullptr;
1228 if ( pMasterTab )
1229 {
1230 pMasterTab->InvalidatePos_();
1231 pMasterTab->SetRemoveFollowFlowLinePending( true );
1232 }
1233 }
1234 }
1235 }
1236 //Remove first, then shrink the upper.
1237 SwLayoutFrame *pUp = GetUpper();
1238 RemoveFromLayout();
1239 if ( !pUp )
1240 return;
1241
1242 SwSectionFrame *pSct = nullptr;
1243 if ( !pUp->Lower() &&
1244 ( ( pUp->IsFootnoteFrame() && !pUp->IsColLocked() ) ||
1245 ( pUp->IsInSct() &&
1246 // #i29438#
1247 // We have to consider the case that the section may be "empty"
1248 // except from a temporary empty table frame.
1249 // This can happen due to the new cell split feature.
1250 !pUp->IsCellFrame() &&
1251 // #126020# - adjust check for empty section
1252 // #130797# - correct fix #126020#
1253 !(pSct = pUp->FindSctFrame())->ContainsContent() &&
1254 !pSct->ContainsAny( true ) ) ) )
1255 {
1256 if ( pUp->GetUpper() )
1257 {
1258
1259 // prevent delete of <ColLocked> footnote frame
1260 if ( pUp->IsFootnoteFrame() && !pUp->IsColLocked())
1261 {
1262 if( pUp->GetNext() && !pUp->GetPrev() )
1263 {
1264 SwFrame* pTmp = static_cast<SwLayoutFrame*>(pUp->GetNext())->ContainsAny();
1265 if( pTmp )
1266 pTmp->InvalidatePrt_();
1267 }
1268 if (!pUp->IsDeleteForbidden())
1269 {
1270 pUp->Cut();
1271 SwFrame::DestroyFrame(pUp);
1272 }
1273 }
1274 else
1275 {
1276
1277 if ( pSct->IsColLocked() || !pSct->IsInFootnote() ||
1278 ( pUp->IsFootnoteFrame() && pUp->IsColLocked() ) )
1279 {
1280 pSct->DelEmpty( false );
1281 // If a locked section may not be deleted then at least
1282 // its size became invalid after removing its last
1283 // content.
1284 pSct->InvalidateSize_();
1285 }
1286 else
1287 {
1288 pSct->DelEmpty( true );
1289 SwFrame::DestroyFrame(pSct);
1290 }
1291 }
1292 }
1293 }
1294 else
1295 {
1296 SwRectFnSet aRectFnSet(this);
1297 long nFrameHeight = aRectFnSet.GetHeight(getFrameArea());
1298 if( nFrameHeight )
1299 pUp->Shrink( nFrameHeight );
1300 }
1301}
1302
1303void SwLayoutFrame::Paste( SwFrame* pParent, SwFrame* pSibling)
1304{
1305 OSL_ENSURE( pParent, "No parent for pasting." )do { if (true && (!(pParent))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1305" ": "), "%s", "No parent for pasting."); } } while
(false)
;
1306 OSL_ENSURE( pParent->IsLayoutFrame(), "Parent is ContentFrame." )do { if (true && (!(pParent->IsLayoutFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1306" ": "), "%s", "Parent is ContentFrame."); } } while
(false)
;
1307 OSL_ENSURE( pParent != this, "I'm the parent oneself." )do { if (true && (!(pParent != this))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1307" ": "), "%s", "I'm the parent oneself."); } } while
(false)
;
1308 OSL_ENSURE( pSibling != this, "I'm my own neighbour." )do { if (true && (!(pSibling != this))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1308" ": "), "%s", "I'm my own neighbour."); } } while (
false)
;
1309 OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),do { if (true && (!(!GetPrev() && !GetNext() &&
!GetUpper()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1310" ": "), "%s", "I'm still registered somewhere."); }
} while (false)
1310 "I'm still registered somewhere." )do { if (true && (!(!GetPrev() && !GetNext() &&
!GetUpper()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1310" ": "), "%s", "I'm still registered somewhere."); }
} while (false)
;
1311
1312 //Insert in the tree.
1313 InsertBefore( static_cast<SwLayoutFrame*>(pParent), pSibling );
1314
1315 // OD 24.10.2002 #103517# - correct setting of variable <fnRect>
1316 // <fnRect> is used for the following:
1317 // (1) To invalidate the frame's size, if its size, which has to be the
1318 // same as its upper/parent, differs from its upper's/parent's.
1319 // (2) To adjust/grow the frame's upper/parent, if it has a dimension in its
1320 // size, which is not determined by its upper/parent.
1321 // Which size is which depends on the frame type and the layout direction
1322 // (vertical or horizontal).
1323 // There are the following cases:
1324 // (A) Header and footer frames both in vertical and in horizontal layout
1325 // have to size the width to the upper/parent. A dimension in the height
1326 // has to cause an adjustment/grow of the upper/parent.
1327 // --> <fnRect> = fnRectHori
1328 // (B) Cell and column frames in vertical layout, the width has to be the
1329 // same as upper/parent and a dimension in height causes adjustment/grow
1330 // of the upper/parent.
1331 // --> <fnRect> = fnRectHori
1332 // in horizontal layout the other way around
1333 // --> <fnRect> = fnRectVert
1334 // (C) Other frames in vertical layout, the height has to be the
1335 // same as upper/parent and a dimension in width causes adjustment/grow
1336 // of the upper/parent.
1337 // --> <fnRect> = fnRectVert
1338 // in horizontal layout the other way around
1339 // --> <fnRect> = fnRectHori
1340 //SwRectFn fnRect = IsVertical() ? fnRectHori : fnRectVert;
1341 SwRectFn fnRect;
1342 if ( IsHeaderFrame() || IsFooterFrame() )
1343 fnRect = fnRectHori;
1344 else if ( IsCellFrame() || IsColumnFrame() )
1345 fnRect = GetUpper()->IsVertical() ? fnRectHori : ( GetUpper()->IsVertLR() ? (GetUpper()->IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert );
1346 else
1347 fnRect = GetUpper()->IsVertical() ? ( GetUpper()->IsVertLR() ? (GetUpper()->IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori;
1348
1349 if( (getFrameArea().*fnRect->fnGetWidth)() != (pParent->getFramePrintArea().*fnRect->fnGetWidth)())
1350 InvalidateSize_();
1351 InvalidatePos_();
1352 const SwPageFrame *pPage = FindPageFrame();
1353 InvalidatePage( pPage );
1354 if( !IsColumnFrame() )
1355 {
1356 SwFrame *pFrame = GetIndNext();
1357 if( nullptr != pFrame )
1358 {
1359 pFrame->InvalidatePos_();
1360 if( IsInFootnote() )
1361 {
1362 if( pFrame->IsSctFrame() )
1363 pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
1364 if( pFrame )
1365 pFrame->Prepare( PrepareHint::ErgoSum, nullptr, false );
1366 }
1367 }
1368 if ( IsInFootnote() && nullptr != ( pFrame = GetIndPrev() ) )
1369 {
1370 if( pFrame->IsSctFrame() )
1371 pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
1372 if( pFrame )
1373 pFrame->Prepare( PrepareHint::QuoVadis, nullptr, false );
1374 }
1375 }
1376
1377 if( !(getFrameArea().*fnRect->fnGetHeight)() )
1378 return;
1379
1380 // AdjustNeighbourhood is now also called in columns which are not
1381 // placed inside a frame
1382 SwNeighbourAdjust nAdjust = GetUpper()->IsFootnoteBossFrame() ?
1383 static_cast<SwFootnoteBossFrame*>(GetUpper())->NeighbourhoodAdjustment()
1384 : SwNeighbourAdjust::GrowShrink;
1385 SwTwips nGrow = (getFrameArea().*fnRect->fnGetHeight)();
1386 if( SwNeighbourAdjust::OnlyAdjust == nAdjust )
1387 AdjustNeighbourhood( nGrow );
1388 else
1389 {
1390 SwTwips nReal = 0;
1391 if( SwNeighbourAdjust::AdjustGrow == nAdjust )
1392 nReal = AdjustNeighbourhood( nGrow );
1393 if( nReal < nGrow )
1394 nReal += pParent->Grow( nGrow - nReal );
1395 if( SwNeighbourAdjust::GrowAdjust == nAdjust && nReal < nGrow )
1396 AdjustNeighbourhood( nGrow - nReal );
1397 }
1398}
1399
1400void SwLayoutFrame::Cut()
1401{
1402 if ( GetNext() )
1403 GetNext()->InvalidatePos_();
1404
1405 SwRectFnSet aRectFnSet(this);
1406 SwTwips nShrink = aRectFnSet.GetHeight(getFrameArea());
1407
1408 // Remove first, then shrink upper.
1409 SwLayoutFrame *pUp = GetUpper();
1410
1411 // AdjustNeighbourhood is now also called in columns which are not
1412 // placed inside a frame.
1413
1414 // Remove must not be called before an AdjustNeighbourhood, but it has to
1415 // be called before the upper-shrink-call, if the upper-shrink takes care
1416 // of its content.
1417 if ( pUp && nShrink )
1418 {
1419 if( pUp->IsFootnoteBossFrame() )
1420 {
1421 SwNeighbourAdjust nAdjust= static_cast<SwFootnoteBossFrame*>(pUp)->NeighbourhoodAdjustment();
1422 if( SwNeighbourAdjust::OnlyAdjust == nAdjust )
1423 AdjustNeighbourhood( -nShrink );
1424 else
1425 {
1426 SwTwips nReal = 0;
1427 if( SwNeighbourAdjust::AdjustGrow == nAdjust )
1428 nReal = -AdjustNeighbourhood( -nShrink );
1429 if( nReal < nShrink )
1430 {
1431 const SwTwips nOldHeight = aRectFnSet.GetHeight(getFrameArea());
1432
1433 // seems as if this needs to be forwarded to the SwFrame already here,
1434 // changing to zero seems temporary anyways
1435 {
1436 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1437 aRectFnSet.SetHeight( aFrm, 0 );
1438 }
1439
1440 nReal += pUp->Shrink( nShrink - nReal );
1441
1442 {
1443 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1444 aRectFnSet.SetHeight( aFrm, nOldHeight );
1445 }
1446 }
1447
1448 if( SwNeighbourAdjust::GrowAdjust == nAdjust && nReal < nShrink )
1449 AdjustNeighbourhood( nReal - nShrink );
1450 }
1451 RemoveFromLayout();
1452 }
1453 else
1454 {
1455 RemoveFromLayout();
1456 pUp->Shrink( nShrink );
1457 }
1458 }
1459 else
1460 RemoveFromLayout();
1461
1462 if( pUp && !pUp->Lower() )
1463 {
1464 pUp->SetCompletePaint();
1465 pUp->InvalidatePage();
1466 }
1467}
1468
1469SwTwips SwFrame::Grow( SwTwips nDist, bool bTst, bool bInfo )
1470{
1471 OSL_ENSURE( nDist >= 0, "Negative growth?" )do { if (true && (!(nDist >= 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1471" ": "), "%s", "Negative growth?"); } } while (false
)
;
1472
1473 PROTOCOL_ENTER( this, bTst ? PROT::GrowTest : PROT::Grow, DbgAction::NONE, &nDist )
1474
1475 if ( nDist )
1476 {
1477 SwRectFnSet aRectFnSet(this);
1478
1479 SwTwips nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea());
1480 if( nPrtHeight > 0 && nDist > (LONG_MAX9223372036854775807L - nPrtHeight) )
1481 nDist = LONG_MAX9223372036854775807L - nPrtHeight;
1482
1483 if ( IsFlyFrame() )
1484 return static_cast<SwFlyFrame*>(this)->Grow_( nDist, bTst );
1485 else if( IsSctFrame() )
1486 return static_cast<SwSectionFrame*>(this)->Grow_( nDist, bTst );
1487 else
1488 {
1489 const SwCellFrame* pThisCell = dynamic_cast<const SwCellFrame*>(this);
1490 if ( pThisCell )
1491 {
1492 const SwTabFrame* pTab = FindTabFrame();
1493
1494 // NEW TABLES
1495 if ( pTab->IsVertical() != IsVertical() ||
1496 pThisCell->GetLayoutRowSpan() < 1 )
1497 return 0;
1498 }
1499
1500 const SwTwips nReal = GrowFrame( nDist, bTst, bInfo );
1501 if( !bTst )
1502 {
1503 nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea());
1504
1505 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1506 aRectFnSet.SetHeight( aPrt, nPrtHeight + ( IsContentFrame() ? nDist : nReal ) );
1507 }
1508 return nReal;
1509 }
1510 }
1511 return 0;
1512}
1513
1514SwTwips SwFrame::Shrink( SwTwips nDist, bool bTst, bool bInfo )
1515{
1516 OSL_ENSURE( nDist >= 0, "Negative reduction?" )do { if (true && (!(nDist >= 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1516" ": "), "%s", "Negative reduction?"); } } while (false
)
;
1517
1518 PROTOCOL_ENTER( this, bTst ? PROT::ShrinkTest : PROT::Shrink, DbgAction::NONE, &nDist )
1519
1520 if ( nDist )
1521 {
1522 if ( IsFlyFrame() )
1523 return static_cast<SwFlyFrame*>(this)->Shrink_( nDist, bTst );
1524 else if( IsSctFrame() )
1525 return static_cast<SwSectionFrame*>(this)->Shrink_( nDist, bTst );
1526 else
1527 {
1528 const SwCellFrame* pThisCell = dynamic_cast<const SwCellFrame*>(this);
1529 if ( pThisCell )
1530 {
1531 const SwTabFrame* pTab = FindTabFrame();
1532
1533 // NEW TABLES
1534 if ( (pTab && pTab->IsVertical() != IsVertical()) ||
1535 pThisCell->GetLayoutRowSpan() < 1 )
1536 return 0;
1537 }
1538
1539 SwRectFnSet aRectFnSet(this);
1540 SwTwips nReal = aRectFnSet.GetHeight(getFrameArea());
1541 ShrinkFrame( nDist, bTst, bInfo );
1542 nReal -= aRectFnSet.GetHeight(getFrameArea());
1543 if( !bTst )
1544 {
1545 const SwTwips nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea());
1546 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1547 aRectFnSet.SetHeight( aPrt, nPrtHeight - ( IsContentFrame() ? nDist : nReal ) );
1548 }
1549 return nReal;
1550 }
1551 }
1552 return 0;
1553}
1554
1555/** Adjust surrounding neighbourhood after insertion
1556 *
1557 * A Frame needs "normalization" if it is directly placed below a footnote boss (page/column) and its
1558 * size changes. There is always a frame that takes the maximum possible space (the frame that
1559 * contains the Body text) and zero or more frames which only take the space needed (header/footer
1560 * area, footnote container). If one of these frames changes, the body-text-frame has to grow or
1561 * shrink accordingly, even though it's fixed.
1562 *
1563 * !! Is it possible to do this in a generic way and not restrict it to the page and a distinct
1564 * frame which takes the maximum space (controlled using the FrameSize attribute)?
1565 * Problems:
1566 * - What if multiple frames taking the maximum space are placed next to each other?
1567 * - How is the maximum space calculated?
1568 * - How small can those frames become?
1569 *
1570 * In any case, only a certain amount of space is allowed, so we never go below a minimum value for
1571 * the height of the body.
1572 *
1573 * @param nDiff the value around which the space has to be allocated
1574 */
1575SwTwips SwFrame::AdjustNeighbourhood( SwTwips nDiff, bool bTst )
1576{
1577 PROTOCOL_ENTER( this, PROT::AdjustN, DbgAction::NONE, &nDiff );
1578
1579 if ( !nDiff || !GetUpper()->IsFootnoteBossFrame() ) // only inside pages/columns
1580 return 0;
1581
1582 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
1583 const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1584
1585 //The (Page-)Body only changes in BrowseMode, but only if it does not
1586 //contain columns.
1587 if ( IsPageBodyFrame() && (!bBrowse ||
1588 (static_cast<SwLayoutFrame*>(this)->Lower() &&
1589 static_cast<SwLayoutFrame*>(this)->Lower()->IsColumnFrame())) )
1590 return 0;
1591
1592 //In BrowseView mode the PageFrame can handle some of the requests.
1593 long nBrowseAdd = 0;
1594 if ( bBrowse && GetUpper()->IsPageFrame() ) // only (Page-)BodyFrames
1595 {
1596 SwViewShell *pViewShell = getRootFrame()->GetCurrShell();
1597 SwLayoutFrame *pUp = GetUpper();
1598 long nChg;
1599 const long nUpPrtBottom = pUp->getFrameArea().Height() -
1600 pUp->getFramePrintArea().Height() - pUp->getFramePrintArea().Top();
1601 SwRect aInva( pUp->getFrameArea() );
1602 if ( pViewShell )
1603 {
1604 aInva.Pos().setX( pViewShell->VisArea().Left() );
1605 aInva.Width( pViewShell->VisArea().Width() );
1606 }
1607 if ( nDiff > 0 )
1608 {
1609 nChg = BROWSE_HEIGHT(56700L * 10L) - pUp->getFrameArea().Height();
1610 nChg = std::min( nDiff, nChg );
1611
1612 if ( !IsBodyFrame() )
1613 {
1614 SetCompletePaint();
1615 if ( !pViewShell || pViewShell->VisArea().Height() >= pUp->getFrameArea().Height() )
1616 {
1617 //First minimize Body, it will grow again later.
1618 SwFrame *pBody = static_cast<SwFootnoteBossFrame*>(pUp)->FindBodyCont();
1619 const long nTmp = nChg - pBody->getFramePrintArea().Height();
1620 if ( !bTst )
1621 {
1622 {
1623 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pBody);
1624 aFrm.Height(std::max( 0L, aFrm.Height() - nChg ));
1625 }
1626
1627 pBody->InvalidatePrt_();
1628 pBody->InvalidateSize_();
1629 if ( pBody->GetNext() )
1630 pBody->GetNext()->InvalidatePos_();
1631 if ( !IsHeaderFrame() )
1632 pBody->SetCompletePaint();
1633 }
1634 nChg = nTmp <= 0 ? 0 : nTmp;
1635 }
1636 }
1637
1638 const long nTmp = nUpPrtBottom + 20;
1639 aInva.Top( aInva.Bottom() - nTmp );
1640 aInva.Height( nChg + nTmp );
1641 }
1642 else
1643 {
1644 //The page can shrink to 0. The first page keeps the same size like
1645 //VisArea.
1646 nChg = nDiff;
1647 long nInvaAdd = 0;
1648 if ( pViewShell && !pUp->GetPrev() &&
1649 pUp->getFrameArea().Height() + nDiff < pViewShell->VisArea().Height() )
1650 {
1651 // This means that we have to invalidate adequately.
1652 nChg = pViewShell->VisArea().Height() - pUp->getFrameArea().Height();
1653 nInvaAdd = -(nDiff - nChg);
1654 }
1655
1656 //Invalidate including bottom border.
1657 long nBorder = nUpPrtBottom + 20;
1658 nBorder -= nChg;
1659 aInva.Top( aInva.Bottom() - (nBorder+nInvaAdd) );
1660 if ( !IsBodyFrame() )
1661 {
1662 SetCompletePaint();
1663 if ( !IsHeaderFrame() )
1664 static_cast<SwFootnoteBossFrame*>(pUp)->FindBodyCont()->SetCompletePaint();
1665 }
1666 //Invalidate the page because of the frames. Thereby the page becomes
1667 //the right size again if a frame didn't fit. This only works
1668 //randomly for paragraph bound frames otherwise (NotifyFlys).
1669 pUp->InvalidateSize();
1670 }
1671 if ( !bTst )
1672 {
1673 //Independent from nChg
1674 if ( pViewShell && aInva.HasArea() && pUp->GetUpper() )
1675 pViewShell->InvalidateWindows( aInva );
1676 }
1677 if ( !bTst && nChg )
1678 {
1679 {
1680 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pUp);
1681 aFrm.AddHeight(nChg );
1682 }
1683
1684 {
1685 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*pUp);
1686 aPrt.AddHeight(nChg );
1687 }
1688
1689 if ( pViewShell )
1690 pViewShell->Imp()->SetFirstVisPageInvalid();
1691
1692 if ( GetNext() )
1693 GetNext()->InvalidatePos_();
1694
1695 //Trigger a repaint if necessary.
1696 std::unique_ptr<SvxBrushItem> aBack(pUp->GetFormat()->makeBackgroundBrushItem());
1697 const SvxGraphicPosition ePos = aBack ? aBack->GetGraphicPos() : GPOS_NONE;
1698 if ( ePos != GPOS_NONE && ePos != GPOS_TILED )
1699 pViewShell->InvalidateWindows( pUp->getFrameArea() );
1700
1701 if ( pUp->GetUpper() )
1702 {
1703 if ( pUp->GetNext() )
1704 pUp->GetNext()->InvalidatePos();
1705
1706 //Sad but true: during notify on ViewImp a Calc on the page and
1707 //its Lower may be called. The values should not be changed
1708 //because the caller takes care of the adjustment of Frame and
1709 //Prt.
1710 const long nOldFrameHeight = getFrameArea().Height();
1711 const long nOldPrtHeight = getFramePrintArea().Height();
1712 const bool bOldComplete = IsCompletePaint();
1713
1714 if ( IsBodyFrame() )
1715 {
1716 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1717 aPrt.Height( nOldFrameHeight );
1718 }
1719
1720 if ( pUp->GetUpper() )
1721 {
1722 static_cast<SwRootFrame*>(pUp->GetUpper())->CheckViewLayout( nullptr, nullptr );
1723 }
1724
1725 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
1726 aFrm.Height( nOldFrameHeight );
1727
1728 SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
1729 aPrt.Height( nOldPrtHeight );
1730
1731 mbCompletePaint = bOldComplete;
1732 }
1733 if ( !IsBodyFrame() )
1734 pUp->InvalidateSize_();
1735 InvalidatePage( static_cast<SwPageFrame*>(pUp) );
1736 }
1737 nDiff -= nChg;
1738 if ( !nDiff )
1739 return nChg;
1740 else
1741 nBrowseAdd = nChg;
1742 }
1743
1744 const SwFootnoteBossFrame *pBoss = static_cast<SwFootnoteBossFrame*>(GetUpper());
1745
1746 SwTwips nReal = 0,
1747 nAdd = 0;
1748 SwFrame *pFrame = nullptr;
1749 SwRectFnSet aRectFnSet(this);
1750
1751 if( IsBodyFrame() )
1752 {
1753 if( IsInSct() )
1754 {
1755 SwSectionFrame *pSect = FindSctFrame();
1756 if( nDiff > 0 && pSect->IsEndnAtEnd() && GetNext() &&
1757 GetNext()->IsFootnoteContFrame() )
1758 {
1759 SwFootnoteContFrame* pCont = static_cast<SwFootnoteContFrame*>(GetNext());
1760 SwTwips nMinH = 0;
1761 SwFootnoteFrame* pFootnote = static_cast<SwFootnoteFrame*>(pCont->Lower());
1762 bool bFootnote = false;
1763 while( pFootnote )
1764 {
1765 if( !pFootnote->GetAttr()->GetFootnote().IsEndNote() )
1766 {
1767 nMinH += aRectFnSet.GetHeight(pFootnote->getFrameArea());
1768 bFootnote = true;
1769 }
1770 pFootnote = static_cast<SwFootnoteFrame*>(pFootnote->GetNext());
1771 }
1772 if( bFootnote )
1773 nMinH += aRectFnSet.GetTop(pCont->getFramePrintArea());
1774 nReal = aRectFnSet.GetHeight(pCont->getFrameArea()) - nMinH;
1775 if( nReal > nDiff )
1776 nReal = nDiff;
1777 if( nReal > 0 )
1778 pFrame = GetNext();
1779 else
1780 nReal = 0;
1781 }
1782 if( !bTst && !pSect->IsColLocked() )
1783 pSect->InvalidateSize();
1784 }
1785 if( !pFrame )
1786 return nBrowseAdd;
1787 }
1788 else
1789 {
1790 const bool bFootnotePage = pBoss->IsPageFrame() && static_cast<const SwPageFrame*>(pBoss)->IsFootnotePage();
1791 if ( bFootnotePage && !IsFootnoteContFrame() )
1792 pFrame = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoss->FindFootnoteCont()));
1793 if ( !pFrame )
1794 pFrame = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoss->FindBodyCont()));
1795
1796 if ( !pFrame )
1797 return 0;
1798
1799 //If not one is found, everything else is solved.
1800 nReal = aRectFnSet.GetHeight(pFrame->getFrameArea());
1801 if( nReal > nDiff )
1802 nReal = nDiff;
1803 if( !bFootnotePage )
1804 {
1805 //Respect the minimal boundary!
1806 if( nReal )
1807 {
1808 const SwTwips nMax = pBoss->GetVarSpace();
1809 if ( nReal > nMax )
1810 nReal = nMax;
1811 }
1812 if( !IsFootnoteContFrame() && nDiff > nReal &&
1813 pFrame->GetNext() && pFrame->GetNext()->IsFootnoteContFrame()
1814 && ( pFrame->GetNext()->IsVertical() == IsVertical() )
1815 )
1816 {
1817 //If the Body doesn't return enough, we look for a footnote, if
1818 //there is one, we steal there accordingly.
1819 const SwTwips nAddMax = aRectFnSet.GetHeight(pFrame->GetNext()->getFrameArea());
1820 nAdd = nDiff - nReal;
1821 if ( nAdd > nAddMax )
1822 nAdd = nAddMax;
1823 if ( !bTst )
1824 {
1825 {
1826 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pFrame->GetNext());
1827 aRectFnSet.SetHeight(aFrm, nAddMax-nAdd);
1828
1829 if( aRectFnSet.IsVert() && !aRectFnSet.IsVertL2R() )
1830 {
1831 aFrm.Pos().AdjustX(nAdd );
1832 }
1833 }
1834
1835 pFrame->GetNext()->InvalidatePrt();
1836
1837 if ( pFrame->GetNext()->GetNext() )
1838 {
1839 pFrame->GetNext()->GetNext()->InvalidatePos_();
1840 }
1841 }
1842 }
1843 }
1844 }
1845
1846 if ( !bTst && nReal )
1847 {
1848 SwTwips nTmp = aRectFnSet.GetHeight(pFrame->getFrameArea());
1849
1850 {
1851 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pFrame);
1852 aRectFnSet.SetHeight( aFrm, nTmp - nReal );
1853
1854 if( aRectFnSet.IsVert() && !aRectFnSet.IsVertL2R() )
1855 {
1856 aFrm.Pos().AdjustX(nReal );
1857 }
1858 }
1859
1860 pFrame->InvalidatePrt();
1861
1862 if ( pFrame->GetNext() )
1863 pFrame->GetNext()->InvalidatePos_();
1864
1865 if( nReal < 0 && pFrame->IsInSct() )
1866 {
1867 SwLayoutFrame* pUp = pFrame->GetUpper();
1868 if( pUp && nullptr != ( pUp = pUp->GetUpper() ) && pUp->IsSctFrame() &&
1869 !pUp->IsColLocked() )
1870 pUp->InvalidateSize();
1871 }
1872 if( ( IsHeaderFrame() || IsFooterFrame() ) && pBoss->GetDrawObjs() )
1873 {
1874 const SwSortedObjs &rObjs = *pBoss->GetDrawObjs();
1875 OSL_ENSURE( pBoss->IsPageFrame(), "Header/Footer out of page?" )do { if (true && (!(pBoss->IsPageFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1875" ": "), "%s", "Header/Footer out of page?"); } } while
(false)
;
1876 for (SwAnchoredObject* pAnchoredObj : rObjs)
1877 {
1878 if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
1879 {
1880 SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
1881 OSL_ENSURE( !pFly->IsFlyInContentFrame(), "FlyInCnt at Page?" )do { if (true && (!(!pFly->IsFlyInContentFrame()))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1881" ": "), "%s", "FlyInCnt at Page?"); } } while (false
)
;
1882 const SwFormatVertOrient &rVert =
1883 pFly->GetFormat()->GetVertOrient();
1884 // When do we have to invalidate?
1885 // If a frame is aligned on a PageTextArea and the header
1886 // changes a TOP, MIDDLE or NONE aligned frame needs to
1887 // recalculate it's position; if the footer changes a BOTTOM
1888 // or MIDDLE aligned frame needs to recalculate it's
1889 // position.
1890 if( ( rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ||
1891 rVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) &&
1892 ((IsHeaderFrame() && rVert.GetVertOrient()!=text::VertOrientation::BOTTOM) ||
1893 (IsFooterFrame() && rVert.GetVertOrient()!=text::VertOrientation::NONE &&
1894 rVert.GetVertOrient() != text::VertOrientation::TOP)) )
1895 {
1896 pFly->InvalidatePos_();
1897 pFly->Invalidate_();
1898 }
1899 }
1900 }
1901 }
1902 }
1903 return (nBrowseAdd + nReal + nAdd);
1904}
1905
1906/** method to perform additional actions on an invalidation (2004-05-19 #i28701#) */
1907void SwFrame::ActionOnInvalidation( const InvalidationType )
1908{
1909 // default behaviour is to perform no additional action
1910}
1911
1912/** method to determine, if an invalidation is allowed (2004-05-19 #i28701#) */
1913bool SwFrame::InvalidationAllowed( const InvalidationType ) const
1914{
1915 // default behaviour is to allow invalidation
1916 return true;
1917}
1918
1919void SwFrame::ImplInvalidateSize()
1920{
1921 if ( InvalidationAllowed( INVALID_SIZE ) )
1922 {
1923 setFrameAreaSizeValid(false);
1924
1925 if ( IsFlyFrame() )
1926 static_cast<SwFlyFrame*>(this)->Invalidate_();
1927 else
1928 InvalidatePage();
1929
1930 // OD 2004-05-19 #i28701#
1931 ActionOnInvalidation( INVALID_SIZE );
1932 }
1933}
1934
1935void SwFrame::ImplInvalidatePrt()
1936{
1937 if ( InvalidationAllowed( INVALID_PRTAREA ) )
1938 {
1939 setFramePrintAreaValid(false);
1940
1941 if ( IsFlyFrame() )
1942 static_cast<SwFlyFrame*>(this)->Invalidate_();
1943 else
1944 InvalidatePage();
1945
1946 // OD 2004-05-19 #i28701#
1947 ActionOnInvalidation( INVALID_PRTAREA );
1948 }
1949}
1950
1951void SwFrame::ImplInvalidatePos()
1952{
1953 if ( !InvalidationAllowed( INVALID_POS ) )
1954 return;
1955
1956 setFrameAreaPositionValid(false);
1957
1958 if ( IsFlyFrame() )
1959 {
1960 static_cast<SwFlyFrame*>(this)->Invalidate_();
1961 }
1962 else
1963 {
1964 InvalidatePage();
1965 }
1966
1967 // OD 2004-05-19 #i28701#
1968 ActionOnInvalidation( INVALID_POS );
1969}
1970
1971void SwFrame::ImplInvalidateLineNum()
1972{
1973 if ( InvalidationAllowed( INVALID_LINENUM ) )
1974 {
1975 mbValidLineNum = false;
1976 OSL_ENSURE( IsTextFrame(), "line numbers are implemented for text only" )do { if (true && (!(IsTextFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "1976" ": "), "%s", "line numbers are implemented for text only"
); } } while (false)
;
1977 InvalidatePage();
1978
1979 // OD 2004-05-19 #i28701#
1980 ActionOnInvalidation( INVALID_LINENUM );
1981 }
1982}
1983
1984void SwFrame::ReinitializeFrameSizeAttrFlags()
1985{
1986 const SwFormatFrameSize &rFormatSize = GetAttrSet()->GetFrameSize();
1987 if ( SwFrameSize::Variable == rFormatSize.GetHeightSizeType() ||
1988 SwFrameSize::Minimum == rFormatSize.GetHeightSizeType())
1989 {
1990 mbFixSize = false;
1991 if ( GetType() & (SwFrameType::Header | SwFrameType::Footer | SwFrameType::Row) )
1992 {
1993 SwFrame *pFrame = static_cast<SwLayoutFrame*>(this)->Lower();
1994 while ( pFrame )
1995 { pFrame->InvalidateSize_();
1996 pFrame->InvalidatePrt_();
1997 pFrame = pFrame->GetNext();
1998 }
1999 SwContentFrame *pCnt = static_cast<SwLayoutFrame*>(this)->ContainsContent();
2000 // #i36991# - be save.
2001 // E.g., a row can contain *no* content.
2002 if ( pCnt )
2003 {
2004 pCnt->InvalidatePage();
2005 do
2006 {
2007 pCnt->Prepare( PrepareHint::AdjustSizeWithoutFormatting );
2008 pCnt->InvalidateSize_();
2009 pCnt = pCnt->GetNextContentFrame();
2010 } while ( static_cast<SwLayoutFrame*>(this)->IsAnLower( pCnt ) );
2011 }
2012 }
2013 }
2014 else if ( rFormatSize.GetHeightSizeType() == SwFrameSize::Fixed )
2015 {
2016 if( IsVertical() )
2017 ChgSize( Size( rFormatSize.GetWidth(), getFrameArea().Height()));
2018 else
2019 ChgSize( Size( getFrameArea().Width(), rFormatSize.GetHeight()));
2020 }
2021}
2022
2023void SwFrame::ValidateThisAndAllLowers( const sal_uInt16 nStage )
2024{
2025 // Stage 0: Only validate frames. Do not process any objects.
2026 // Stage 1: Only validate fly frames and all of their contents.
2027 // Stage 2: Validate all.
2028
2029 const bool bOnlyObject = 1 == nStage;
2030 const bool bIncludeObjects = 1 <= nStage;
2031
2032 if ( !bOnlyObject || dynamic_cast< const SwFlyFrame *>( this ) != nullptr )
2033 {
2034 setFrameAreaSizeValid(true);
2035 setFramePrintAreaValid(true);
2036 setFrameAreaPositionValid(true);
2037 }
2038
2039 if ( bIncludeObjects )
2040 {
2041 const SwSortedObjs* pObjs = GetDrawObjs();
2042 if ( pObjs )
2043 {
2044 const size_t nCnt = pObjs->size();
2045 for ( size_t i = 0; i < nCnt; ++i )
2046 {
2047 SwAnchoredObject* pAnchObj = (*pObjs)[i];
2048 if ( dynamic_cast< const SwFlyFrame *>( pAnchObj ) != nullptr )
2049 static_cast<SwFlyFrame*>(pAnchObj)->ValidateThisAndAllLowers( 2 );
2050 else if ( dynamic_cast< const SwAnchoredDrawObject *>( pAnchObj ) != nullptr )
2051 static_cast<SwAnchoredDrawObject*>(pAnchObj)->ValidateThis();
2052 }
2053 }
2054 }
2055
2056 if ( IsLayoutFrame() )
2057 {
2058 SwFrame* pLower = static_cast<SwLayoutFrame*>(this)->Lower();
2059 while ( pLower )
2060 {
2061 pLower->ValidateThisAndAllLowers( nStage );
2062 pLower = pLower->GetNext();
2063 }
2064 }
2065}
2066
2067SwTwips SwContentFrame::GrowFrame( SwTwips nDist, bool bTst, bool bInfo )
2068{
2069 SwRectFnSet aRectFnSet(this);
2070
2071 SwTwips nFrameHeight = aRectFnSet.GetHeight(getFrameArea());
2072 if( nFrameHeight > 0 &&
2073 nDist > (LONG_MAX9223372036854775807L - nFrameHeight ) )
2074 nDist = LONG_MAX9223372036854775807L - nFrameHeight;
2075
2076 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
2077 const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
2078 SwFrameType nTmpType = SwFrameType::Cell | SwFrameType::Column;
2079 if (bBrowse)
2080 nTmpType |= SwFrameType::Body;
2081 if( !(GetUpper()->GetType() & nTmpType) && GetUpper()->HasFixSize() )
2082 {
2083 if ( !bTst )
2084 {
2085 {
2086 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2087 aRectFnSet.SetHeight( aFrm, nFrameHeight + nDist );
2088
2089 if( IsVertical() && !IsVertLR() )
2090 {
2091 aFrm.Pos().AdjustX( -nDist );
2092 }
2093 }
2094
2095 if ( GetNext() )
2096 {
2097 GetNext()->InvalidatePos();
2098 }
2099 // #i28701# - Due to the new object positioning the
2100 // frame on the next page/column can flow backward (e.g. it was moved forward
2101 // due to the positioning of its objects ). Thus, invalivate this next frame,
2102 // if document compatibility option 'Consider wrapping style influence on
2103 // object positioning' is ON.
2104 else if ( GetUpper()->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2105 {
2106 InvalidateNextPos();
2107 }
2108 }
2109 return 0;
2110 }
2111
2112 SwTwips nReal = aRectFnSet.GetHeight(GetUpper()->getFramePrintArea());
2113 SwFrame *pFrame = GetUpper()->Lower();
2114 while( pFrame && nReal > 0 )
2115 { nReal -= aRectFnSet.GetHeight(pFrame->getFrameArea());
2116 pFrame = pFrame->GetNext();
2117 }
2118
2119 if ( !bTst )
2120 {
2121 //Contents are always resized to the wished value.
2122 long nOld = aRectFnSet.GetHeight(getFrameArea());
2123
2124 {
2125 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2126
2127 aRectFnSet.SetHeight( aFrm, nOld + nDist );
2128
2129 if( IsVertical()&& !IsVertLR() )
2130 {
2131 aFrm.Pos().AdjustX( -nDist );
2132 }
2133 }
2134
2135 SwTabFrame *pTab = (nOld && IsInTab()) ? FindTabFrame() : nullptr;
2136 if (pTab)
2137 {
2138 if ( pTab->GetTable()->GetHTMLTableLayout() &&
2139 !pTab->IsJoinLocked() &&
2140 !pTab->GetFormat()->GetDoc()->GetDocShell()->IsReadOnly() )
2141 {
2142 pTab->InvalidatePos();
2143 pTab->SetResizeHTMLTable();
2144 }
2145 }
2146 }
2147
2148 //Only grow Upper if necessary.
2149 if ( nReal < nDist )
2150 {
2151 if( GetUpper() )
2152 {
2153 if( bTst || !GetUpper()->IsFooterFrame() )
2154 nReal = GetUpper()->Grow( nDist - std::max<long>(nReal, 0),
2155 bTst, bInfo );
2156 else
2157 {
2158 nReal = 0;
2159 GetUpper()->InvalidateSize();
2160 }
2161 }
2162 else
2163 nReal = 0;
2164 }
2165 else
2166 nReal = nDist;
2167
2168 // #i28701# - Due to the new object positioning the
2169 // frame on the next page/column can flow backward (e.g. it was moved forward
2170 // due to the positioning of its objects ). Thus, invalivate this next frame,
2171 // if document compatibility option 'Consider wrapping style influence on
2172 // object positioning' is ON.
2173 if ( !bTst )
2174 {
2175 if ( GetNext() )
2176 {
2177 GetNext()->InvalidatePos();
2178 }
2179 else if ( GetUpper()->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2180 {
2181 InvalidateNextPos();
2182 }
2183 }
2184
2185 return nReal;
2186}
2187
2188SwTwips SwContentFrame::ShrinkFrame( SwTwips nDist, bool bTst, bool bInfo )
2189{
2190 SwRectFnSet aRectFnSet(this);
2191 OSL_ENSURE( nDist >= 0, "nDist < 0" )do { if (true && (!(nDist >= 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "2191" ": "), "%s", "nDist < 0"); } } while (false)
;
2192 OSL_ENSURE( nDist <= aRectFnSet.GetHeight(getFrameArea()),do { if (true && (!(nDist <= aRectFnSet.GetHeight(
getFrameArea())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "2193" ": "), "%s", "nDist > than current size."); } }
while (false)
2193 "nDist > than current size." )do { if (true && (!(nDist <= aRectFnSet.GetHeight(
getFrameArea())))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "2193" ": "), "%s", "nDist > than current size."); } }
while (false)
;
2194
2195 if ( !bTst )
2196 {
2197 SwTwips nRstHeight;
2198 if( GetUpper() )
2199 nRstHeight = aRectFnSet.BottomDist( getFrameArea(), aRectFnSet.GetPrtBottom(*GetUpper()) );
2200 else
2201 nRstHeight = 0;
2202 if( nRstHeight < 0 )
2203 {
2204 SwTwips nNextHeight = 0;
2205 if( GetUpper()->IsSctFrame() && nDist > LONG_MAX9223372036854775807L/2 )
2206 {
2207 SwFrame *pNxt = GetNext();
2208 while( pNxt )
2209 {
2210 nNextHeight += aRectFnSet.GetHeight(pNxt->getFrameArea());
2211 pNxt = pNxt->GetNext();
2212 }
2213 }
2214 nRstHeight = nDist + nRstHeight - nNextHeight;
2215 }
2216 else
2217 {
2218 nRstHeight = nDist;
2219 }
2220
2221 {
2222 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2223 aRectFnSet.SetHeight( aFrm, aRectFnSet.GetHeight(aFrm) - nDist );
2224
2225 if( IsVertical() && !IsVertLR() )
2226 {
2227 aFrm.Pos().AdjustX(nDist );
2228 }
2229 }
2230
2231 nDist = nRstHeight;
2232 SwTabFrame *pTab = IsInTab() ? FindTabFrame() : nullptr;
2233 if (pTab)
2234 {
2235 if ( pTab->GetTable()->GetHTMLTableLayout() &&
2236 !pTab->IsJoinLocked() &&
2237 !pTab->GetFormat()->GetDoc()->GetDocShell()->IsReadOnly() )
2238 {
2239 pTab->InvalidatePos();
2240 pTab->SetResizeHTMLTable();
2241 }
2242 }
2243 }
2244
2245 SwTwips nReal;
2246 if( GetUpper() && nDist > 0 )
2247 {
2248 if( bTst || !GetUpper()->IsFooterFrame() )
2249 nReal = GetUpper()->Shrink( nDist, bTst, bInfo );
2250 else
2251 {
2252 nReal = 0;
2253
2254 // #108745# Sorry, dear old footer friend, I'm not gonna invalidate you,
2255 // if there are any objects anchored inside your content, which
2256 // overlap with the shrinking frame.
2257 // This may lead to a footer frame that is too big, but this is better
2258 // than looping.
2259 // #109722# : The fix for #108745# was too strict.
2260
2261 bool bInvalidate = true;
2262 const SwRect aRect( getFrameArea() );
2263 const SwPageFrame* pPage = FindPageFrame();
2264 const SwSortedObjs* pSorted = pPage ? pPage->GetSortedObjs() : nullptr;
2265 if( pSorted )
2266 {
2267 for (SwAnchoredObject* pAnchoredObj : *pSorted)
2268 {
2269 const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );
2270
2271 if( aBound.Left() > aRect.Right() )
2272 continue;
2273
2274 if( aBound.IsOver( aRect ) )
2275 {
2276 const SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
2277 if( css::text::WrapTextMode_THROUGH != rFormat.GetSurround().GetSurround() )
2278 {
2279 const SwFrame* pAnchor = pAnchoredObj->GetAnchorFrame();
2280 if ( pAnchor && pAnchor->FindFooterOrHeader() == GetUpper() )
2281 {
2282 bInvalidate = false;
2283 break;
2284 }
2285 }
2286 }
2287 }
2288 }
2289
2290 if ( bInvalidate )
2291 GetUpper()->InvalidateSize();
2292 }
2293 }
2294 else
2295 nReal = 0;
2296
2297 if ( !bTst )
2298 {
2299 //The position of the next Frame changes for sure.
2300 InvalidateNextPos();
2301
2302 //If I don't have a successor I have to do the retouch by myself.
2303 if ( !GetNext() )
2304 SetRetouche();
2305 }
2306 return nReal;
2307}
2308
2309void SwContentFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
2310{
2311 sal_uInt8 nInvFlags = 0;
2312
2313 if( pNew && RES_ATTRSET_CHG == pNew->Which() && pOld )
2314 {
2315 SfxItemIter aNIter( *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet() );
2316 SfxItemIter aOIter( *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet() );
2317 const SfxPoolItem* pNItem = aNIter.GetCurItem();
2318 const SfxPoolItem* pOItem = aOIter.GetCurItem();
2319 SwAttrSetChg aOldSet( *static_cast<const SwAttrSetChg*>(pOld) );
2320 SwAttrSetChg aNewSet( *static_cast<const SwAttrSetChg*>(pNew) );
2321 do
2322 {
2323 UpdateAttr_(pOItem, pNItem, nInvFlags, &aOldSet, &aNewSet);
2324 pNItem = aNIter.NextItem();
2325 pOItem = aOIter.NextItem();
2326 } while (pNItem);
2327 if ( aOldSet.Count() || aNewSet.Count() )
2328 SwFrame::Modify( &aOldSet, &aNewSet );
2329 }
2330 else
2331 UpdateAttr_( pOld, pNew, nInvFlags );
2332
2333 if ( nInvFlags == 0 )
2334 return;
2335
2336 SwPageFrame *pPage = FindPageFrame();
2337 InvalidatePage( pPage );
2338 if ( nInvFlags & 0x01 )
2339 SetCompletePaint();
2340 if ( nInvFlags & 0x02 )
2341 InvalidatePos_();
2342 if ( nInvFlags & 0x04 )
2343 InvalidateSize_();
2344 if ( nInvFlags & 0x88 )
2345 {
2346 if( IsInSct() && !GetPrev() )
2347 {
2348 SwSectionFrame *pSect = FindSctFrame();
2349 if( pSect->ContainsAny() == this )
2350 {
2351 pSect->InvalidatePrt_();
2352 pSect->InvalidatePage( pPage );
2353 }
2354 }
2355 InvalidatePrt_();
2356 }
2357 SwFrame* pNextFrame = GetIndNext();
2358 if ( pNextFrame && nInvFlags & 0x10)
2359 {
2360 pNextFrame->InvalidatePrt_();
2361 pNextFrame->InvalidatePage( pPage );
2362 }
2363 if ( pNextFrame && nInvFlags & 0x80 )
2364 {
2365 pNextFrame->SetCompletePaint();
2366 }
2367 if ( nInvFlags & 0x20 )
2368 {
2369 SwFrame* pPrevFrame = GetPrev();
2370 if ( pPrevFrame )
2371 {
2372 pPrevFrame->InvalidatePrt_();
2373 pPrevFrame->InvalidatePage( pPage );
2374 }
2375 }
2376 if ( nInvFlags & 0x40 )
2377 InvalidateNextPos();
2378
2379}
2380
2381void SwContentFrame::UpdateAttr_( const SfxPoolItem* pOld, const SfxPoolItem* pNew,
2382 sal_uInt8 &rInvFlags,
2383 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2384{
2385 bool bClear = true;
2386 sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2387 switch ( nWhich )
2388 {
2389 case RES_FMT_CHG:
2390 rInvFlags = 0xFF;
2391 [[fallthrough]];
2392
2393 case RES_PAGEDESC: //attribute changes (on/off)
2394 if ( IsInDocBody() && !IsInTab() )
2395 {
2396 rInvFlags |= 0x02;
2397 SwPageFrame *pPage = FindPageFrame();
2398 if ( !GetPrev() )
2399 CheckPageDescs( pPage );
2400 if (GetPageDescItem().GetNumOffset())
2401 static_cast<SwRootFrame*>(pPage->GetUpper())->SetVirtPageNum( true );
2402 SwDocPosUpdate aMsgHint( pPage->getFrameArea().Top() );
2403 pPage->GetFormat()->GetDoc()->getIDocumentFieldsAccess().UpdatePageFields( &aMsgHint );
2404 }
2405 break;
2406
2407 case RES_UL_SPACE:
2408 {
2409 // OD 2004-02-18 #106629# - correction
2410 // Invalidation of the printing area of next frame, not only
2411 // for footnote content.
2412 if ( !GetIndNext() )
2413 {
2414 SwFrame* pNxt = FindNext();
2415 if ( pNxt )
2416 {
2417 SwPageFrame* pPg = pNxt->FindPageFrame();
2418 pNxt->InvalidatePage( pPg );
2419 pNxt->InvalidatePrt_();
2420 if( pNxt->IsSctFrame() )
2421 {
2422 SwFrame* pCnt = static_cast<SwSectionFrame*>(pNxt)->ContainsAny();
2423 if( pCnt )
2424 {
2425 pCnt->InvalidatePrt_();
2426 pCnt->InvalidatePage( pPg );
2427 }
2428 }
2429 pNxt->SetCompletePaint();
2430 }
2431 }
2432 // OD 2004-03-17 #i11860#
2433 if ( GetIndNext() &&
2434 !GetUpper()->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::USE_FORMER_OBJECT_POS) )
2435 {
2436 // OD 2004-07-01 #i28701# - use new method <InvalidateObjs(..)>
2437 GetIndNext()->InvalidateObjs();
2438 }
2439 Prepare( PrepareHint::ULSpaceChanged ); //TextFrame has to correct line spacing.
2440 rInvFlags |= 0x80;
2441 [[fallthrough]];
2442 }
2443 case RES_LR_SPACE:
2444 case RES_BOX:
2445 case RES_SHADOW:
2446 Prepare( PrepareHint::FixSizeChanged );
2447 SwFrame::Modify( pOld, pNew );
2448 rInvFlags |= 0x30;
2449 break;
2450
2451 case RES_BREAK:
2452 {
2453 rInvFlags |= 0x42;
2454 const IDocumentSettingAccess& rIDSA = GetUpper()->GetFormat()->getIDocumentSettingAccess();
2455 if( rIDSA.get(DocumentSettingId::PARA_SPACE_MAX) ||
2456 rIDSA.get(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES) )
2457 {
2458 rInvFlags |= 0x1;
2459 SwFrame* pNxt = FindNext();
2460 if( pNxt )
2461 {
2462 SwPageFrame* pPg = pNxt->FindPageFrame();
2463 pNxt->InvalidatePage( pPg );
2464 pNxt->InvalidatePrt_();
2465 if( pNxt->IsSctFrame() )
2466 {
2467 SwFrame* pCnt = static_cast<SwSectionFrame*>(pNxt)->ContainsAny();
2468 if( pCnt )
2469 {
2470 pCnt->InvalidatePrt_();
2471 pCnt->InvalidatePage( pPg );
2472 }
2473 }
2474 pNxt->SetCompletePaint();
2475 }
2476 }
2477 }
2478 break;
2479
2480 // OD 2004-02-26 #i25029#
2481 case RES_PARATR_CONNECT_BORDER:
2482 {
2483 rInvFlags |= 0x01;
2484 if ( IsTextFrame() )
2485 {
2486 InvalidateNextPrtArea();
2487 }
2488 if ( !GetIndNext() && IsInTab() && IsInSplitTableRow() )
2489 {
2490 FindTabFrame()->InvalidateSize();
2491 }
2492 }
2493 break;
2494
2495 case RES_PARATR_TABSTOP:
2496 case RES_CHRATR_SHADOWED:
2497 case RES_CHRATR_AUTOKERN:
2498 case RES_CHRATR_UNDERLINE:
2499 case RES_CHRATR_OVERLINE:
2500 case RES_CHRATR_KERNING:
2501 case RES_CHRATR_FONT:
2502 case RES_CHRATR_FONTSIZE:
2503 case RES_CHRATR_ESCAPEMENT:
2504 case RES_CHRATR_CONTOUR:
2505 case RES_PARATR_NUMRULE:
2506 rInvFlags |= 0x01;
2507 break;
2508
2509 case RES_FRM_SIZE:
2510 rInvFlags |= 0x01;
2511 [[fallthrough]];
2512
2513 default:
2514 bClear = false;
2515 }
2516 if ( bClear )
2517 {
2518 if ( pOldSet || pNewSet )
2519 {
2520 if ( pOldSet )
2521 pOldSet->ClearItem( nWhich );
2522 if ( pNewSet )
2523 pNewSet->ClearItem( nWhich );
2524 }
2525 else
2526 SwFrame::Modify( pOld, pNew );
2527 }
2528}
2529
2530SwLayoutFrame::SwLayoutFrame(SwFrameFormat *const pFormat, SwFrame *const pSib)
2531 : SwFrame(pFormat, pSib)
2532 , m_pLower(nullptr)
2533{
2534 const SwFormatFrameSize &rFormatSize = pFormat->GetFrameSize();
2535 if ( rFormatSize.GetHeightSizeType() == SwFrameSize::Fixed )
2536 mbFixSize = true;
2537}
2538
2539// #i28701#
2540
2541SwTwips SwLayoutFrame::InnerHeight() const
2542{
2543 const SwFrame* pCnt = Lower();
2544 if (!pCnt)
2545 return 0;
2546
2547 SwRectFnSet aRectFnSet(this);
2548 SwTwips nRet = 0;
2549 if( pCnt->IsColumnFrame() || pCnt->IsCellFrame() )
2550 {
2551 do
2552 {
2553 SwTwips nTmp = static_cast<const SwLayoutFrame*>(pCnt)->InnerHeight();
2554 if( pCnt->isFramePrintAreaValid() )
2555 nTmp += aRectFnSet.GetHeight(pCnt->getFrameArea()) -
2556 aRectFnSet.GetHeight(pCnt->getFramePrintArea());
2557 if( nRet < nTmp )
2558 nRet = nTmp;
2559 pCnt = pCnt->GetNext();
2560 } while ( pCnt );
2561 }
2562 else
2563 {
2564 do
2565 {
2566 nRet += aRectFnSet.GetHeight(pCnt->getFrameArea());
2567 if( pCnt->IsContentFrame() && static_cast<const SwTextFrame*>(pCnt)->IsUndersized() )
2568 nRet += static_cast<const SwTextFrame*>(pCnt)->GetParHeight() -
2569 aRectFnSet.GetHeight(pCnt->getFramePrintArea());
2570 if( pCnt->IsLayoutFrame() && !pCnt->IsTabFrame() )
2571 nRet += static_cast<const SwLayoutFrame*>(pCnt)->InnerHeight() -
2572 aRectFnSet.GetHeight(pCnt->getFramePrintArea());
2573 pCnt = pCnt->GetNext();
2574 } while( pCnt );
2575
2576 }
2577 return nRet;
2578}
2579
2580SwTwips SwLayoutFrame::GrowFrame( SwTwips nDist, bool bTst, bool bInfo )
2581{
2582 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
2583 const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
2584 SwFrameType nTmpType = SwFrameType::Cell | SwFrameType::Column;
2585 if (bBrowse)
2586 nTmpType |= SwFrameType::Body;
2587 if( !(GetType() & nTmpType) && HasFixSize() )
2588 return 0;
2589
2590 SwRectFnSet aRectFnSet(this);
2591 const SwTwips nFrameHeight = aRectFnSet.GetHeight(getFrameArea());
2592 const SwTwips nFramePos = getFrameArea().Pos().X();
2593
2594 if ( nFrameHeight > 0 && nDist > (LONG_MAX9223372036854775807L - nFrameHeight) )
2595 nDist = LONG_MAX9223372036854775807L - nFrameHeight;
2596
2597 SwTwips nMin = 0;
2598 if ( GetUpper() && !IsCellFrame() )
2599 {
2600 SwFrame *pFrame = GetUpper()->Lower();
2601 while( pFrame )
2602 { nMin += aRectFnSet.GetHeight(pFrame->getFrameArea());
2603 pFrame = pFrame->GetNext();
2604 }
2605 nMin = aRectFnSet.GetHeight(GetUpper()->getFramePrintArea()) - nMin;
2606 if ( nMin < 0 )
2607 nMin = 0;
2608 }
2609
2610 SwRect aOldFrame( getFrameArea() );
2611 bool bMoveAccFrame = false;
2612
2613 bool bChgPos = IsVertical();
2614 if ( !bTst )
2615 {
2616 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2617 aRectFnSet.SetHeight( aFrm, nFrameHeight + nDist );
2618
2619 if( bChgPos && !IsVertLR() )
2620 {
2621 aFrm.Pos().AdjustX( -nDist );
2622 }
2623
2624 bMoveAccFrame = true;
2625 }
2626
2627 SwTwips nReal = nDist - nMin;
2628 if ( nReal > 0 )
2629 {
2630 if ( GetUpper() )
2631 { // AdjustNeighbourhood now only for the columns (but not in frames)
2632 SwNeighbourAdjust nAdjust = GetUpper()->IsFootnoteBossFrame() ?
2633 static_cast<SwFootnoteBossFrame*>(GetUpper())->NeighbourhoodAdjustment()
2634 : SwNeighbourAdjust::GrowShrink;
2635 if( SwNeighbourAdjust::OnlyAdjust == nAdjust )
2636 nReal = AdjustNeighbourhood( nReal, bTst );
2637 else
2638 {
2639 if( SwNeighbourAdjust::AdjustGrow == nAdjust )
2640 nReal += AdjustNeighbourhood( nReal, bTst );
2641
2642 SwTwips nGrow = 0;
2643 if( 0 < nReal )
2644 {
2645 SwFrame* pToGrow = GetUpper();
2646 // NEW TABLES
2647 // A cell with a row span of > 1 is allowed to grow the
2648 // line containing the end of the row span if it is
2649 // located in the same table frame:
2650 const SwCellFrame* pThisCell = dynamic_cast<const SwCellFrame*>(this);
2651 if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
2652 {
2653 SwCellFrame& rEndCell = const_cast<SwCellFrame&>(pThisCell->FindStartEndOfRowSpanCell( false ));
2654 if ( -1 == rEndCell.GetTabBox()->getRowSpan() )
2655 pToGrow = rEndCell.GetUpper();
2656 else
2657 pToGrow = nullptr;
2658 }
2659
2660 nGrow = pToGrow ? pToGrow->Grow( nReal, bTst, bInfo ) : 0;
2661 }
2662
2663 if( SwNeighbourAdjust::GrowAdjust == nAdjust && nGrow < nReal )
2664 nReal = o3tl::saturating_add(nReal, AdjustNeighbourhood( nReal - nGrow, bTst ));
2665
2666 if ( IsFootnoteFrame() && (nGrow != nReal) && GetNext() )
2667 {
2668 //Footnotes can replace their successor.
2669 SwTwips nSpace = bTst ? 0 : -nDist;
2670 const SwFrame *pFrame = GetUpper()->Lower();
2671 do
2672 { nSpace += aRectFnSet.GetHeight(pFrame->getFrameArea());
2673 pFrame = pFrame->GetNext();
2674 } while ( pFrame != GetNext() );
2675 nSpace = aRectFnSet.GetHeight(GetUpper()->getFramePrintArea()) -nSpace;
2676 if ( nSpace < 0 )
2677 nSpace = 0;
2678 nSpace += nGrow;
2679 if ( nReal > nSpace )
2680 nReal = nSpace;
2681 if ( nReal && !bTst )
2682 static_cast<SwFootnoteFrame*>(this)->InvalidateNxtFootnoteCnts( FindPageFrame() );
2683 }
2684 else
2685 nReal = nGrow;
2686 }
2687 }
2688 else
2689 nReal = 0;
2690
2691 nReal += nMin;
2692 }
2693 else
2694 nReal = nDist;
2695
2696 if ( !bTst )
2697 {
2698 if( nReal != nDist &&
2699 // NEW TABLES
2700 ( !IsCellFrame() || static_cast<SwCellFrame*>(this)->GetLayoutRowSpan() > 1 ) )
2701 {
2702 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2703 aRectFnSet.SetHeight( aFrm, nFrameHeight + nReal );
2704
2705 if( bChgPos && !IsVertLR() )
2706 {
2707 aFrm.Pos().setX( nFramePos - nReal );
2708 }
2709
2710 bMoveAccFrame = true;
2711 }
2712
2713 if ( nReal )
2714 {
2715 SwPageFrame *pPage = FindPageFrame();
2716 if ( GetNext() )
2717 {
2718 GetNext()->InvalidatePos_();
2719 if ( GetNext()->IsContentFrame() )
2720 GetNext()->InvalidatePage( pPage );
2721 }
2722 if ( !IsPageBodyFrame() )
2723 {
2724 InvalidateAll_();
2725 InvalidatePage( pPage );
2726 }
2727 if (!(GetType() & (SwFrameType::Row|SwFrameType::Tab|SwFrameType::FtnCont|SwFrameType::Page|SwFrameType::Root)))
2728 NotifyLowerObjs();
2729
2730 if( IsCellFrame() )
2731 InvaPercentLowers( nReal );
2732
2733 std::unique_ptr<SvxBrushItem> aBack(GetFormat()->makeBackgroundBrushItem());
2734 const SvxGraphicPosition ePos = aBack ? aBack->GetGraphicPos() : GPOS_NONE;
2735 if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
2736 SetCompletePaint();
2737 }
2738 }
2739
2740 if( bMoveAccFrame && IsAccessibleFrame() )
2741 {
2742 SwRootFrame *pRootFrame = getRootFrame();
2743 if( pRootFrame && pRootFrame->IsAnyShellAccessible() &&
2744 pRootFrame->GetCurrShell() )
2745 {
2746 pRootFrame->GetCurrShell()->Imp()->MoveAccessibleFrame( this, aOldFrame );
2747 }
2748 }
2749 return nReal;
2750}
2751
2752SwTwips SwLayoutFrame::ShrinkFrame( SwTwips nDist, bool bTst, bool bInfo )
2753{
2754 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
2755 const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
2756 SwFrameType nTmpType = SwFrameType::Cell | SwFrameType::Column;
2757 if (bBrowse)
2758 nTmpType |= SwFrameType::Body;
2759
2760 if (pSh && pSh->GetViewOptions()->IsWhitespaceHidden())
2761 {
2762 if (IsBodyFrame())
2763 {
2764 // Whitespace is hidden and this body frame will not shrink, as it
2765 // has a fix size.
2766 // Invalidate the page frame size, so in case the reason for the
2767 // shrink was that there is more whitespace on this page, the size
2768 // without whitespace will be recalculated correctly.
2769 SwPageFrame* pPageFrame = FindPageFrame();
2770 pPageFrame->InvalidateSize();
2771 }
2772 }
2773
2774 if( !(GetType() & nTmpType) && HasFixSize() )
2775 return 0;
2776
2777 OSL_ENSURE( nDist >= 0, "nDist < 0" )do { if (true && (!(nDist >= 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "2777" ": "), "%s", "nDist < 0"); } } while (false)
;
2778 SwRectFnSet aRectFnSet(this);
2779 SwTwips nFrameHeight = aRectFnSet.GetHeight(getFrameArea());
2780 if ( nDist > nFrameHeight )
2781 nDist = nFrameHeight;
2782
2783 SwTwips nMin = 0;
2784 bool bChgPos = IsVertical();
2785 if ( Lower() )
2786 {
2787 if( !Lower()->IsNeighbourFrame() )
2788 { const SwFrame *pFrame = Lower();
2789 const long nTmp = aRectFnSet.GetHeight(getFramePrintArea());
2790 while( pFrame && nMin < nTmp )
2791 { nMin += aRectFnSet.GetHeight(pFrame->getFrameArea());
2792 pFrame = pFrame->GetNext();
2793 }
2794 }
2795 }
2796 SwTwips nReal = nDist;
2797 SwTwips nMinDiff = aRectFnSet.GetHeight(getFramePrintArea()) - nMin;
2798 if( nReal > nMinDiff )
2799 nReal = nMinDiff;
2800 if( nReal <= 0 )
2801 return nDist;
2802
2803 SwRect aOldFrame( getFrameArea() );
2804 bool bMoveAccFrame = false;
2805
2806 SwTwips nRealDist = nReal;
2807 if ( !bTst )
2808 {
2809 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2810 aRectFnSet.SetHeight( aFrm, nFrameHeight - nReal );
2811
2812 if( bChgPos && !IsVertLR() )
2813 {
2814 aFrm.Pos().AdjustX(nReal );
2815 }
2816
2817 bMoveAccFrame = true;
2818 }
2819
2820 SwNeighbourAdjust nAdjust = GetUpper() && GetUpper()->IsFootnoteBossFrame() ?
2821 static_cast<SwFootnoteBossFrame*>(GetUpper())->NeighbourhoodAdjustment()
2822 : SwNeighbourAdjust::GrowShrink;
2823
2824 // AdjustNeighbourhood also in columns (but not in frames)
2825 if( SwNeighbourAdjust::OnlyAdjust == nAdjust )
2826 {
2827 if ( IsPageBodyFrame() && !bBrowse )
2828 nReal = nDist;
2829 else
2830 { nReal = AdjustNeighbourhood( -nReal, bTst );
2831 nReal *= -1;
2832 if ( !bTst && IsBodyFrame() && nReal < nRealDist )
2833 {
2834 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2835 aRectFnSet.SetHeight( aFrm, aRectFnSet.GetHeight(aFrm) + nRealDist - nReal );
2836
2837 if( bChgPos && !IsVertLR() )
2838 {
2839 aFrm.Pos().AdjustX(nRealDist - nReal );
2840 }
2841
2842 OSL_ENSURE( !IsAccessibleFrame(), "bMoveAccFrame has to be set!" )do { if (true && (!(!IsAccessibleFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "2842" ": "), "%s", "bMoveAccFrame has to be set!"); } }
while (false)
;
2843 }
2844 }
2845 }
2846 else if( IsColumnFrame() || IsColBodyFrame() )
2847 {
2848 SwTwips nTmp = GetUpper()->Shrink( nReal, bTst, bInfo );
2849 if ( nTmp != nReal )
2850 {
2851 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
2852 aRectFnSet.SetHeight( aFrm, aRectFnSet.GetHeight(aFrm) + nReal - nTmp );
2853
2854 if( bChgPos && !IsVertLR() )
2855 {
2856 aFrm.Pos().AdjustX(nTmp - nReal );
2857 }
2858
2859 OSL_ENSURE( !IsAccessibleFrame(), "bMoveAccFrame has to be set!" )do { if (true && (!(!IsAccessibleFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "2859" ": "), "%s", "bMoveAccFrame has to be set!"); } }
while (false)
;
2860 nReal = nTmp;
2861 }
2862 }
2863 else
2864 {
2865 SwTwips nShrink = nReal;
2866 SwFrame* pToShrink = GetUpper();
2867 const SwCellFrame* pThisCell = dynamic_cast<const SwCellFrame*>(this);
2868 // NEW TABLES
2869 if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
2870 {
2871 SwCellFrame& rEndCell = const_cast<SwCellFrame&>(pThisCell->FindStartEndOfRowSpanCell( false ));
2872 pToShrink = rEndCell.GetUpper();
2873 }
2874
2875 nReal = pToShrink ? pToShrink->Shrink( nShrink, bTst, bInfo ) : 0;
2876 if( ( SwNeighbourAdjust::GrowAdjust == nAdjust || SwNeighbourAdjust::AdjustGrow == nAdjust )
2877 && nReal < nShrink )
2878 AdjustNeighbourhood( nReal - nShrink );
2879 }
2880
2881 if( bMoveAccFrame && IsAccessibleFrame() )
2882 {
2883 SwRootFrame *pRootFrame = getRootFrame();
2884 if( pRootFrame && pRootFrame->IsAnyShellAccessible() &&
2885 pRootFrame->GetCurrShell() )
2886 {
2887 pRootFrame->GetCurrShell()->Imp()->MoveAccessibleFrame( this, aOldFrame );
2888 }
2889 }
2890 if ( !bTst && (IsCellFrame() || IsColumnFrame() ? nReal : nRealDist) )
2891 {
2892 SwPageFrame *pPage = FindPageFrame();
2893 if ( GetNext() )
2894 {
2895 GetNext()->InvalidatePos_();
2896 if ( GetNext()->IsContentFrame() )
2897 GetNext()->InvalidatePage( pPage );
2898 if ( IsTabFrame() )
2899 static_cast<SwTabFrame*>(this)->SetComplete();
2900 }
2901 else
2902 { if ( IsRetoucheFrame() )
2903 SetRetouche();
2904 if ( IsTabFrame() )
2905 {
2906 static_cast<SwTabFrame*>(this)->SetComplete();
2907 if ( Lower() ) // Can also be in the Join and be empty!
2908 InvalidateNextPos();
2909 }
2910 }
2911 if ( !IsBodyFrame() )
2912 {
2913 InvalidateAll_();
2914 InvalidatePage( pPage );
2915 bool bCompletePaint = true;
2916 const SwFrameFormat* pFormat = GetFormat();
2917 if (pFormat)
2918 {
2919 std::unique_ptr<SvxBrushItem> aBack(pFormat->makeBackgroundBrushItem());
2920 const SvxGraphicPosition ePos = aBack ? aBack->GetGraphicPos() : GPOS_NONE;
2921 if ( GPOS_NONE == ePos || GPOS_TILED == ePos )
2922 bCompletePaint = false;
2923 }
2924 if (bCompletePaint)
2925 SetCompletePaint();
2926 }
2927
2928 if (!(GetType() & (SwFrameType::Row|SwFrameType::Tab|SwFrameType::FtnCont|SwFrameType::Page|SwFrameType::Root)))
2929 NotifyLowerObjs();
2930
2931 if( IsCellFrame() )
2932 InvaPercentLowers( nReal );
2933
2934 SwContentFrame *pCnt;
2935 if( IsFootnoteFrame() && !static_cast<SwFootnoteFrame*>(this)->GetAttr()->GetFootnote().IsEndNote() &&
2936 ( GetFormat()->GetDoc()->GetFootnoteInfo().m_ePos != FTNPOS_CHAPTER ||
2937 ( IsInSct() && FindSctFrame()->IsFootnoteAtEnd() ) ) &&
2938 nullptr != (pCnt = static_cast<SwFootnoteFrame*>(this)->GetRefFromAttr() ) )
2939 {
2940 if ( pCnt->IsFollow() )
2941 { // If we are in another column/page than the frame with the
2942 // reference, we don't need to invalidate its master.
2943 SwFrame *pTmp = pCnt->FindFootnoteBossFrame(true) == FindFootnoteBossFrame(true)
2944 ? &pCnt->FindMaster()->GetFrame() : pCnt;
2945 pTmp->Prepare( PrepareHint::AdjustSizeWithoutFormatting );
2946 pTmp->InvalidateSize();
2947 }
2948 else
2949 pCnt->InvalidatePos();
2950 }
2951 }
2952 return nReal;
2953}
2954
2955/**
2956 * Changes the size of the directly subsidiary Frame's that have a fixed size, proportionally to the
2957 * size change of the PrtArea of the Frame's.
2958 *
2959 * The variable Frames are also proportionally adapted; they will grow/shrink again by themselves.
2960 */
2961void SwLayoutFrame::ChgLowersProp( const Size& rOldSize )
2962{
2963 // no change of lower properties for root frame or if no lower exists.
2964 if ( IsRootFrame() || !Lower() )
2965 return;
2966
2967 // declare and init <SwFrame* pLowerFrame> with first lower
2968 SwFrame *pLowerFrame = Lower();
2969
2970 // declare and init const booleans <bHeightChgd> and <bWidthChg>
2971 const bool bHeightChgd = rOldSize.Height() != getFramePrintArea().Height();
2972 const bool bWidthChgd = rOldSize.Width() != getFramePrintArea().Width();
2973
2974 SwRectFnSet aRectFnSet(this);
2975
2976 // This shortcut basically tries to handle only lower frames that
2977 // are affected by the size change. Otherwise much more lower frames
2978 // are invalidated.
2979 if ( !( aRectFnSet.IsVert() ? bHeightChgd : bWidthChgd ) &&
2980 ! Lower()->IsColumnFrame() &&
2981 ( ( IsBodyFrame() && IsInDocBody() && ( !IsInSct() || !FindSctFrame()->IsColLocked() ) ) ||
2982 // #i10826# Section frames without columns should not
2983 // invalidate all lowers!
2984 IsSctFrame() ) )
2985 {
2986 // Determine page frame the body frame resp. the section frame belongs to.
2987 SwPageFrame *pPage = FindPageFrame();
2988 // Determine last lower by traveling through them using <GetNext()>.
2989 // During travel check each section frame, if it will be sized to
2990 // maximum. If Yes, invalidate size of section frame and set
2991 // corresponding flags at the page.
2992 do
2993 {
2994 if( pLowerFrame->IsSctFrame() && static_cast<SwSectionFrame*>(pLowerFrame)->ToMaximize_() )
2995 {
2996 pLowerFrame->InvalidateSize_();
2997 pLowerFrame->InvalidatePage( pPage );
2998 }
2999 if( pLowerFrame->GetNext() )
3000 pLowerFrame = pLowerFrame->GetNext();
3001 else
3002 break;
3003 } while( true );
3004 // If found last lower is a section frame containing no section
3005 // (section frame isn't valid and will be deleted in the future),
3006 // travel backwards.
3007 while( pLowerFrame->IsSctFrame() && !static_cast<SwSectionFrame*>(pLowerFrame)->GetSection() &&
3008 pLowerFrame->GetPrev() )
3009 pLowerFrame = pLowerFrame->GetPrev();
3010 // If found last lower is a section frame, set <pLowerFrame> to its last
3011 // content, if the section frame is valid and is not sized to maximum.
3012 // Otherwise set <pLowerFrame> to NULL - In this case body frame only
3013 // contains invalid section frames.
3014 if( pLowerFrame->IsSctFrame() )
3015 pLowerFrame = static_cast<SwSectionFrame*>(pLowerFrame)->GetSection() &&
3016 !static_cast<SwSectionFrame*>(pLowerFrame)->ToMaximize( false ) ?
3017 static_cast<SwSectionFrame*>(pLowerFrame)->FindLastContent() : nullptr;
3018
3019 // continue with found last lower, probably the last content of a section
3020 if ( pLowerFrame )
3021 {
3022 // If <pLowerFrame> is in a table frame, set <pLowerFrame> to this table
3023 // frame and continue.
3024 if ( pLowerFrame->IsInTab() )
3025 {
3026 // OD 28.10.2002 #97265# - safeguard for setting <pLowerFrame> to
3027 // its table frame - check, if the table frame is also a lower
3028 // of the body frame, in order to assure that <pLowerFrame> is not
3029 // set to a frame, which is an *upper* of the body frame.
3030 SwFrame* pTableFrame = pLowerFrame->FindTabFrame();
3031 if ( IsAnLower( pTableFrame ) )
3032 {
3033 pLowerFrame = pTableFrame;
3034 }
3035 }
3036 // Check, if variable size of body frame resp. section frame has grown
3037 // OD 28.10.2002 #97265# - correct check, if variable size has grown.
3038 SwTwips nOldHeight = aRectFnSet.IsVert() ? rOldSize.Width() : rOldSize.Height();
3039 if( nOldHeight < aRectFnSet.GetHeight(getFramePrintArea()) )
3040 {
3041 // If variable size of body|section frame has grown, only found
3042 // last lower and the position of the its next have to be invalidated.
3043 pLowerFrame->InvalidateAll_();
3044 pLowerFrame->InvalidatePage( pPage );
3045 if( !pLowerFrame->IsFlowFrame() ||
3046 !SwFlowFrame::CastFlowFrame( pLowerFrame )->HasFollow() )
3047 pLowerFrame->InvalidateNextPos( true );
3048 if ( pLowerFrame->IsTextFrame() )
3049 static_cast<SwContentFrame*>(pLowerFrame)->Prepare( PrepareHint::AdjustSizeWithoutFormatting );
3050 }
3051 else
3052 {
3053 // variable size of body|section frame has shrunk. Thus,
3054 // invalidate all lowers not matching the new body|section size
3055 // and the dedicated new last lower.
3056 if( aRectFnSet.IsVert() )
3057 {
3058 SwTwips nBot = getFrameArea().Left() + getFramePrintArea().Left();
3059 while ( pLowerFrame && pLowerFrame->GetPrev() && pLowerFrame->getFrameArea().Left() < nBot )
3060 {
3061 pLowerFrame->InvalidateAll_();
3062 pLowerFrame->InvalidatePage( pPage );
3063 pLowerFrame = pLowerFrame->GetPrev();
3064 }
3065 }
3066 else
3067 {
3068 SwTwips nBot = getFrameArea().Top() + getFramePrintArea().Bottom();
3069 while ( pLowerFrame && pLowerFrame->GetPrev() && pLowerFrame->getFrameArea().Top() > nBot )
3070 {
3071 pLowerFrame->InvalidateAll_();
3072 pLowerFrame->InvalidatePage( pPage );
3073 pLowerFrame = pLowerFrame->GetPrev();
3074 }
3075 }
3076 if ( pLowerFrame )
3077 {
3078 pLowerFrame->InvalidateSize_();
3079 pLowerFrame->InvalidatePage( pPage );
3080 if ( pLowerFrame->IsTextFrame() )
3081 static_cast<SwContentFrame*>(pLowerFrame)->Prepare( PrepareHint::AdjustSizeWithoutFormatting );
3082 }
3083 }
3084 // #i41694# - improvement by removing duplicates
3085 if ( pLowerFrame )
3086 {
3087 if ( pLowerFrame->IsInSct() )
3088 {
3089 // #i41694# - follow-up of issue #i10826#
3090 // No invalidation of section frame, if it's the this.
3091 SwFrame* pSectFrame = pLowerFrame->FindSctFrame();
3092 if( pSectFrame != this && IsAnLower( pSectFrame ) )
3093 {
3094 pSectFrame->InvalidateSize_();
3095 pSectFrame->InvalidatePage( pPage );
3096 }
3097 }
3098 }
3099 }
3100 return;
3101 } // end of { special case }
3102
3103 // Invalidate page for content only once.
3104 bool bInvaPageForContent = true;
3105
3106 // Declare booleans <bFixChgd> and <bVarChgd>, indicating for text frame
3107 // adjustment, if fixed/variable size has changed.
3108 bool bFixChgd, bVarChgd;
3109 if( aRectFnSet.IsVert() == pLowerFrame->IsNeighbourFrame() )
3110 {
3111 bFixChgd = bWidthChgd;
3112 bVarChgd = bHeightChgd;
3113 }
3114 else
3115 {
3116 bFixChgd = bHeightChgd;
3117 bVarChgd = bWidthChgd;
3118 }
3119
3120 // Declare const unsigned short <nFixWidth> and init it this frame types
3121 // which has fixed width in vertical respectively horizontal layout.
3122 // In vertical layout these are neighbour frames (cell and column frames),
3123 // header frames and footer frames.
3124 // In horizontal layout these are all frames, which aren't neighbour frames.
3125 const SwFrameType nFixWidth = aRectFnSet.IsVert() ? (FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell) | FRM_HEADFOOT(SwFrameType::Header | SwFrameType::Footer))
3126 : ~SwFrameType(FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell));
3127
3128 // Declare const unsigned short <nFixHeight> and init it this frame types
3129 // which has fixed height in vertical respectively horizontal layout.
3130 // In vertical layout these are all frames, which aren't neighbour frames,
3131 // header frames, footer frames, body frames or foot note container frames.
3132 // In horizontal layout these are neighbour frames.
3133 const SwFrameType nFixHeight = aRectFnSet.IsVert() ? ~SwFrameType(FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell) | FRM_HEADFOOT(SwFrameType::Header | SwFrameType::Footer) | FRM_BODYFTNC(SwFrameType::FtnCont | SwFrameType::Body))
3134 : FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell);
3135
3136 // Travel through all lowers using <GetNext()>
3137 while ( pLowerFrame )
3138 {
3139 if ( pLowerFrame->IsTextFrame() )
3140 {
3141 // Text frames will only be invalidated - prepare invalidation
3142 if ( bFixChgd )
3143 static_cast<SwContentFrame*>(pLowerFrame)->Prepare( PrepareHint::FixSizeChanged );
3144 if ( bVarChgd )
3145 static_cast<SwContentFrame*>(pLowerFrame)->Prepare( PrepareHint::AdjustSizeWithoutFormatting );
3146 }
3147 else
3148 {
3149 // If lower isn't a table, row, cell or section frame, adjust its
3150 // frame size.
3151 const SwFrameType nLowerType = pLowerFrame->GetType();
3152 if ( !(nLowerType & (SwFrameType::Tab|SwFrameType::Row|SwFrameType::Cell|SwFrameType::Section)) )
3153 {
3154 if ( bWidthChgd )
3155 {
3156 if( nLowerType & nFixWidth )
3157 {
3158 // Considering previous conditions:
3159 // In vertical layout set width of column, header and
3160 // footer frames to its upper width.
3161 // In horizontal layout set width of header, footer,
3162 // foot note container, foot note, body and no-text
3163 // frames to its upper width.
3164 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pLowerFrame);
3165 aFrm.Width( getFramePrintArea().Width() );
3166 }
3167 else if( rOldSize.Width() && !pLowerFrame->IsFootnoteFrame() )
3168 {
3169 // Adjust frame width proportional, if lower isn't a
3170 // foot note frame and condition <nLowerType & nFixWidth>
3171 // isn't true.
3172 // Considering previous conditions:
3173 // In vertical layout these are foot note container,
3174 // body and no-text frames.
3175 // In horizontal layout these are column and no-text frames.
3176 // OD 24.10.2002 #97265# - <double> calculation
3177 // Perform <double> calculation of new width, if
3178 // one of the coefficients is greater than 50000
3179 SwTwips nNewWidth;
3180 if ( (pLowerFrame->getFrameArea().Width() > 50000) ||
3181 (getFramePrintArea().Width() > 50000) )
3182 {
3183 double nNewWidthTmp =
3184 ( double(pLowerFrame->getFrameArea().Width())
3185 * double(getFramePrintArea().Width()) )
3186 / double(rOldSize.Width());
3187 nNewWidth = SwTwips(nNewWidthTmp);
3188 }
3189 else
3190 {
3191 nNewWidth =
3192 (pLowerFrame->getFrameArea().Width() * getFramePrintArea().Width()) / rOldSize.Width();
3193 }
3194
3195 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pLowerFrame);
3196 aFrm.Width( nNewWidth );
3197 }
3198 }
3199 if ( bHeightChgd )
3200 {
3201 if( nLowerType & nFixHeight )
3202 {
3203 // Considering previous conditions:
3204 // In vertical layout set height of foot note and
3205 // no-text frames to its upper height.
3206 // In horizontal layout set height of column frames
3207 // to its upper height.
3208 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pLowerFrame);
3209 aFrm.Height( getFramePrintArea().Height() );
3210 }
3211 // OD 01.10.2002 #102211#
3212 // add conditions <!pLowerFrame->IsHeaderFrame()> and
3213 // <!pLowerFrame->IsFooterFrame()> in order to avoid that
3214 // the <Grow> of header or footer are overwritten.
3215 // NOTE: Height of header/footer frame is determined by contents.
3216 else if ( rOldSize.Height() &&
3217 !pLowerFrame->IsFootnoteFrame() &&
3218 !pLowerFrame->IsHeaderFrame() &&
3219 !pLowerFrame->IsFooterFrame()
3220 )
3221 {
3222 // Adjust frame height proportional, if lower isn't a
3223 // foot note, a header or a footer frame and
3224 // condition <nLowerType & nFixHeight> isn't true.
3225 // Considering previous conditions:
3226 // In vertical layout these are column, foot note container,
3227 // body and no-text frames.
3228 // In horizontal layout these are column, foot note
3229 // container, body and no-text frames.
3230
3231 // OD 29.10.2002 #97265# - special case for page lowers
3232 // The page lowers that have to be adjusted on page height
3233 // change are the body frame and the foot note container
3234 // frame.
3235 // In vertical layout the height of both is directly
3236 // adjusted to the page height change.
3237 // In horizontal layout the height of the body frame is
3238 // directly adjusted to the page height change and the
3239 // foot note frame height isn't touched, because its
3240 // determined by its content.
3241 // OD 31.03.2003 #108446# - apply special case for page
3242 // lowers - see description above - also for section columns.
3243 if ( IsPageFrame() ||
3244 ( IsColumnFrame() && IsInSct() )
3245 )
3246 {
3247 OSL_ENSURE( pLowerFrame->IsBodyFrame() || pLowerFrame->IsFootnoteContFrame(),do { if (true && (!(pLowerFrame->IsBodyFrame() || pLowerFrame
->IsFootnoteContFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3248" ": "), "%s", "ChgLowersProp - only for body or foot note container"
); } } while (false)
3248 "ChgLowersProp - only for body or foot note container" )do { if (true && (!(pLowerFrame->IsBodyFrame() || pLowerFrame
->IsFootnoteContFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3248" ": "), "%s", "ChgLowersProp - only for body or foot note container"
); } } while (false)
;
3249 if ( pLowerFrame->IsBodyFrame() || pLowerFrame->IsFootnoteContFrame() )
3250 {
3251 if ( IsVertical() || pLowerFrame->IsBodyFrame() )
3252 {
3253 SwTwips nNewHeight =
3254 pLowerFrame->getFrameArea().Height() +
3255 ( getFramePrintArea().Height() - rOldSize.Height() );
3256 if ( nNewHeight < 0)
3257 {
3258 // OD 01.04.2003 #108446# - adjust assertion condition and text
3259 OSL_ENSURE( !( IsPageFrame() &&do { if (true && (!(!( IsPageFrame() && (pLowerFrame
->getFrameArea().Height()>0) && (pLowerFrame->
isFrameAreaDefinitionValid()) )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3262" ": "), "%s", "ChgLowersProg - negative height for lower."
); } } while (false)
3260 (pLowerFrame->getFrameArea().Height()>0) &&do { if (true && (!(!( IsPageFrame() && (pLowerFrame
->getFrameArea().Height()>0) && (pLowerFrame->
isFrameAreaDefinitionValid()) )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3262" ": "), "%s", "ChgLowersProg - negative height for lower."
); } } while (false)
3261 (pLowerFrame->isFrameAreaDefinitionValid()) ),do { if (true && (!(!( IsPageFrame() && (pLowerFrame
->getFrameArea().Height()>0) && (pLowerFrame->
isFrameAreaDefinitionValid()) )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3262" ": "), "%s", "ChgLowersProg - negative height for lower."
); } } while (false)
3262 "ChgLowersProg - negative height for lower.")do { if (true && (!(!( IsPageFrame() && (pLowerFrame
->getFrameArea().Height()>0) && (pLowerFrame->
isFrameAreaDefinitionValid()) )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3262" ": "), "%s", "ChgLowersProg - negative height for lower."
); } } while (false)
;
3263 nNewHeight = 0;
3264 }
3265
3266 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pLowerFrame);
3267 aFrm.Height( nNewHeight );
3268 }
3269 }
3270 }
3271 else
3272 {
3273 SwTwips nNewHeight;
3274 // OD 24.10.2002 #97265# - <double> calculation
3275 // Perform <double> calculation of new height, if
3276 // one of the coefficients is greater than 50000
3277 if ( (pLowerFrame->getFrameArea().Height() > 50000) ||
3278 (getFramePrintArea().Height() > 50000) )
3279 {
3280 double nNewHeightTmp =
3281 ( double(pLowerFrame->getFrameArea().Height())
3282 * double(getFramePrintArea().Height()) )
3283 / double(rOldSize.Height());
3284 nNewHeight = SwTwips(nNewHeightTmp);
3285 }
3286 else
3287 {
3288 nNewHeight = ( pLowerFrame->getFrameArea().Height()
3289 * getFramePrintArea().Height() ) / rOldSize.Height();
3290 }
3291 if( !pLowerFrame->GetNext() )
3292 {
3293 SwTwips nSum = getFramePrintArea().Height();
3294 SwFrame* pTmp = Lower();
3295 while( pTmp->GetNext() )
3296 {
3297 if( !pTmp->IsFootnoteContFrame() || !pTmp->IsVertical() )
3298 nSum -= pTmp->getFrameArea().Height();
3299 pTmp = pTmp->GetNext();
3300 }
3301 if( nSum - nNewHeight == 1 &&
3302 nSum == pLowerFrame->getFrameArea().Height() )
3303 nNewHeight = nSum;
3304 }
3305
3306 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pLowerFrame);
3307 aFrm.Height( nNewHeight );
3308 }
3309 }
3310 }
3311 }
3312 } // end of else { NOT text frame }
3313
3314 pLowerFrame->InvalidateAll_();
3315 if ( bInvaPageForContent && pLowerFrame->IsContentFrame() )
3316 {
3317 pLowerFrame->InvalidatePage();
3318 bInvaPageForContent = false;
3319 }
3320
3321 if ( !pLowerFrame->GetNext() && pLowerFrame->IsRetoucheFrame() )
3322 {
3323 //If a growth took place and the subordinate elements can retouch
3324 //itself (currently Tabs, Sections and Content) we trigger it.
3325 if ( rOldSize.Height() < getFramePrintArea().SSize().Height() ||
3326 rOldSize.Width() < getFramePrintArea().SSize().Width() )
3327 pLowerFrame->SetRetouche();
3328 }
3329 pLowerFrame = pLowerFrame->GetNext();
3330 }
3331
3332 // Finally adjust the columns if width is set to auto
3333 // Possible optimization: execute this code earlier in this function and
3334 // return???
3335 if ( !(( (aRectFnSet.IsVert() && bHeightChgd) || (! aRectFnSet.IsVert() && bWidthChgd) ) &&
3336 Lower()->IsColumnFrame()) )
3337 return;
3338
3339 // get column attribute
3340 const SwFormatCol* pColAttr = nullptr;
3341 if ( IsPageBodyFrame() )
3342 {
3343 OSL_ENSURE( GetUpper()->IsPageFrame(), "Upper is not page frame" )do { if (true && (!(GetUpper()->IsPageFrame()))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3343" ": "), "%s", "Upper is not page frame"); } } while
(false)
;
3344 pColAttr = &GetUpper()->GetFormat()->GetCol();
3345 }
3346 else
3347 {
3348 OSL_ENSURE( IsFlyFrame() || IsSctFrame(), "Columns not in fly or section" )do { if (true && (!(IsFlyFrame() || IsSctFrame()))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3348" ": "), "%s", "Columns not in fly or section"); } }
while (false)
;
3349 pColAttr = &GetFormat()->GetCol();
3350 }
3351
3352 if ( pColAttr->IsOrtho() && pColAttr->GetNumCols() > 1 )
3353 AdjustColumns( pColAttr, false );
3354}
3355
3356/** "Formats" the Frame; Frame and PrtArea.
3357 *
3358 * The Fixsize is not set here.
3359 */
3360void SwLayoutFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderAttrs *pAttrs )
3361{
3362 OSL_ENSURE( pAttrs, "LayoutFrame::Format, pAttrs is 0." )do { if (true && (!(pAttrs))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3362" ": "), "%s", "LayoutFrame::Format, pAttrs is 0.")
; } } while (false)
;
3363
3364 if ( isFramePrintAreaValid() && isFrameAreaSizeValid() )
3365 return;
3366
3367 bool bHideWhitespace = false;
3368 if (IsPageFrame())
3369 {
3370 SwViewShell* pShell = getRootFrame()->GetCurrShell();
3371 if (pShell && pShell->GetViewOptions()->IsWhitespaceHidden())
3372 {
3373 // This is needed so that no space is reserved for the margin on
3374 // the last page of the document. Other pages would have no margin
3375 // set even without this, as their frame height is the content
3376 // height already.
3377 bHideWhitespace = true;
3378 }
3379 }
3380
3381 const sal_uInt16 nLeft = static_cast<sal_uInt16>(pAttrs->CalcLeft(this));
3382 const sal_uInt16 nUpper = bHideWhitespace ? 0 : pAttrs->CalcTop();
3383
3384 const sal_uInt16 nRight = static_cast<sal_uInt16>(pAttrs->CalcRight(this));
3385 const sal_uInt16 nLower = bHideWhitespace ? 0 : pAttrs->CalcBottom();
3386
3387 const bool bVert = IsVertical() && !IsPageFrame();
3388 SwRectFn fnRect = bVert ? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori;
3389 if ( !isFramePrintAreaValid() )
3390 {
3391 setFramePrintAreaValid(true);
3392 (this->*fnRect->fnSetXMargins)( nLeft, nRight );
3393 (this->*fnRect->fnSetYMargins)( nUpper, nLower );
3394 }
3395
3396 if ( isFrameAreaSizeValid() )
3397 return;
3398
3399 if ( !HasFixSize() )
3400 {
3401 const SwTwips nBorder = nUpper + nLower;
3402 const SwFormatFrameSize &rSz = GetFormat()->GetFrameSize();
3403 SwTwips nMinHeight = rSz.GetHeightSizeType() == SwFrameSize::Minimum ? rSz.GetHeight() : 0;
3404 do
3405 {
3406 setFrameAreaSizeValid(true);
3407
3408 //The size in VarSize is calculated using the content plus the
3409 // borders.
3410 SwTwips nRemaining = 0;
3411 SwFrame *pFrame = Lower();
3412 while ( pFrame )
3413 { nRemaining += (pFrame->getFrameArea().*fnRect->fnGetHeight)();
3414 if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsUndersized() )
3415 // This TextFrame would like to be a bit bigger
3416 nRemaining += static_cast<SwTextFrame*>(pFrame)->GetParHeight()
3417 - (pFrame->getFramePrintArea().*fnRect->fnGetHeight)();
3418 else if( pFrame->IsSctFrame() && static_cast<SwSectionFrame*>(pFrame)->IsUndersized() )
3419 nRemaining += static_cast<SwSectionFrame*>(pFrame)->Undersize();
3420 pFrame = pFrame->GetNext();
3421 }
3422 nRemaining += nBorder;
3423 nRemaining = std::max( nRemaining, nMinHeight );
3424 const SwTwips nDiff = nRemaining-(getFrameArea().*fnRect->fnGetHeight)();
3425 const long nOldLeft = (getFrameArea().*fnRect->fnGetLeft)();
3426 const long nOldTop = (getFrameArea().*fnRect->fnGetTop)();
3427 if ( nDiff )
3428 {
3429 if ( nDiff > 0 )
3430 Grow( nDiff );
3431 else
3432 Shrink( -nDiff );
3433 //Updates the positions using the fast channel.
3434 MakePos();
3435 }
3436 //Don't exceed the bottom edge of the Upper.
3437 if ( GetUpper() && (getFrameArea().*fnRect->fnGetHeight)() )
3438 {
3439 const SwTwips nLimit = (GetUpper()->*fnRect->fnGetPrtBottom)();
3440 if( (this->*fnRect->fnSetLimit)( nLimit ) &&
3441 nOldLeft == (getFrameArea().*fnRect->fnGetLeft)() &&
3442 nOldTop == (getFrameArea().*fnRect->fnGetTop)() )
3443 {
3444 setFrameAreaSizeValid(true);
3445 setFramePrintAreaValid(true);
3446 }
3447 }
3448 } while ( !isFrameAreaSizeValid() );
3449 }
3450 else if (GetType() & FRM_HEADFOOT(SwFrameType::Header | SwFrameType::Footer))
3451 {
3452 do
3453 { if ( getFrameArea().Height() != pAttrs->GetSize().Height() )
3454 {
3455 ChgSize( Size( getFrameArea().Width(), pAttrs->GetSize().Height()));
3456 }
3457
3458 setFrameAreaSizeValid(true);
3459 MakePos();
3460 } while ( !isFrameAreaSizeValid() );
3461 }
3462 else
3463 {
3464 setFrameAreaSizeValid(true);
3465 }
3466
3467 // While updating the size, PrtArea might be invalidated.
3468 if (!isFramePrintAreaValid())
3469 {
3470 setFramePrintAreaValid(true);
3471 (this->*fnRect->fnSetXMargins)(nLeft, nRight);
3472 (this->*fnRect->fnSetYMargins)(nUpper, nLower);
3473 }
3474}
3475
3476static void InvaPercentFlys( SwFrame *pFrame, SwTwips nDiff )
3477{
3478 OSL_ENSURE( pFrame->GetDrawObjs(), "Can't find any Objects" )do { if (true && (!(pFrame->GetDrawObjs()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3478" ": "), "%s", "Can't find any Objects"); } } while
(false)
;
3479 for (SwAnchoredObject* pAnchoredObj : *pFrame->GetDrawObjs())
3480 {
3481 if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
3482 {
3483 SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
3484 const SwFormatFrameSize &rSz = pFly->GetFormat()->GetFrameSize();
3485 if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
3486 {
3487 bool bNotify = true;
3488 // If we've a fly with more than 90% relative height...
3489 if( rSz.GetHeightPercent() > 90 && pFly->GetAnchorFrame() &&
3490 rSz.GetHeightPercent() != SwFormatFrameSize::SYNCED && nDiff )
3491 {
3492 const SwFrame *pRel = pFly->IsFlyLayFrame() ? pFly->GetAnchorFrame():
3493 pFly->GetAnchorFrame()->GetUpper();
3494 // ... and we have already more than 90% height and we
3495 // not allow the text to go through...
3496 // then a notification could cause an endless loop, e.g.
3497 // 100% height and no text wrap inside a cell of a table.
3498 if( pFly->getFrameArea().Height()*10 >
3499 ( nDiff + pRel->getFramePrintArea().Height() )*9 &&
3500 pFly->GetFormat()->GetSurround().GetSurround() !=
3501 css::text::WrapTextMode_THROUGH )
3502 bNotify = false;
3503 }
3504 if( bNotify )
3505 pFly->InvalidateSize();
3506 }
3507 }
3508 }
3509}
3510
3511void SwLayoutFrame::InvaPercentLowers( SwTwips nDiff )
3512{
3513 if ( GetDrawObjs() )
3514 ::InvaPercentFlys( this, nDiff );
3515
3516 SwFrame *pFrame = ContainsContent();
3517 if ( !pFrame )
3518 return;
3519
3520 do
3521 {
3522 if ( pFrame->IsInTab() && !IsTabFrame() )
3523 {
3524 SwFrame *pTmp = pFrame->FindTabFrame();
3525 OSL_ENSURE( pTmp, "Where's my TabFrame?" )do { if (true && (!(pTmp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3525" ": "), "%s", "Where's my TabFrame?"); } } while (
false)
;
3526 if( IsAnLower( pTmp ) )
3527 pFrame = pTmp;
3528 }
3529
3530 if ( pFrame->IsTabFrame() )
3531 {
3532 const SwFormatFrameSize &rSz = static_cast<SwLayoutFrame*>(pFrame)->GetFormat()->GetFrameSize();
3533 if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
3534 pFrame->InvalidatePrt();
3535 }
3536 else if ( pFrame->GetDrawObjs() )
3537 ::InvaPercentFlys( pFrame, nDiff );
3538 pFrame = pFrame->FindNextCnt();
3539 } while ( pFrame && IsAnLower( pFrame ) ) ;
3540}
3541
3542long SwLayoutFrame::CalcRel( const SwFormatFrameSize &rSz ) const
3543{
3544 long nRet = rSz.GetWidth(),
3545 nPercent = rSz.GetWidthPercent();
3546
3547 if ( nPercent )
3548 {
3549 const SwFrame *pRel = GetUpper();
3550 long nRel = LONG_MAX9223372036854775807L;
3551 const SwViewShell *pSh = getRootFrame()->GetCurrShell();
3552 const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
3553 if( pRel->IsPageBodyFrame() && pSh && bBrowseMode && pSh->VisArea().Width() )
3554 {
3555 nRel = pSh->GetBrowseWidth();
3556 long nDiff = nRel - pRel->getFramePrintArea().Width();
3557 if ( nDiff > 0 )
3558 nRel -= nDiff;
3559 }
3560 nRel = std::min( nRel, pRel->getFramePrintArea().Width() );
3561 nRet = nRel * nPercent / 100;
3562 }
3563 return nRet;
3564}
3565
3566// Local helpers for SwLayoutFrame::FormatWidthCols()
3567
3568static long lcl_CalcMinColDiff( SwLayoutFrame *pLayFrame )
3569{
3570 long nDiff = 0, nFirstDiff = 0;
3571 SwLayoutFrame *pCol = static_cast<SwLayoutFrame*>(pLayFrame->Lower());
3572 OSL_ENSURE( pCol, "Where's the columnframe?" )do { if (true && (!(pCol))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3572" ": "), "%s", "Where's the columnframe?"); } } while
(false)
;
3573 SwFrame *pFrame = pCol->Lower();
3574 do
3575 {
3576 if( pFrame && pFrame->IsBodyFrame() )
3577 pFrame = static_cast<SwBodyFrame*>(pFrame)->Lower();
3578 if ( pFrame && pFrame->IsTextFrame() )
3579 {
3580 const long nTmp = static_cast<SwTextFrame*>(pFrame)->FirstLineHeight();
3581 if ( nTmp != USHRT_MAX(32767 *2 +1) )
3582 {
3583 if ( pCol == pLayFrame->Lower() )
3584 nFirstDiff = nTmp;
3585 else
3586 nDiff = nDiff ? std::min( nDiff, nTmp ) : nTmp;
3587 }
3588 }
3589 //Skip empty columns!
3590 pCol = static_cast<SwLayoutFrame*>(pCol->GetNext());
3591 while ( pCol && nullptr == (pFrame = pCol->Lower()) )
3592 pCol = static_cast<SwLayoutFrame*>(pCol->GetNext());
3593
3594 } while ( pFrame && pCol );
3595
3596 return nDiff ? nDiff : nFirstDiff ? nFirstDiff : 240;
3597}
3598
3599static bool lcl_IsFlyHeightClipped( SwLayoutFrame *pLay )
3600{
3601 SwFrame *pFrame = pLay->ContainsContent();
3602 while ( pFrame )
42
Loop condition is false. Execution continues on line 3624
3603 {
3604 if ( pFrame->IsInTab() )
3605 pFrame = pFrame->FindTabFrame();
3606
3607 if ( pFrame->GetDrawObjs() )
3608 {
3609 const size_t nCnt = pFrame->GetDrawObjs()->size();
3610 for ( size_t i = 0; i < nCnt; ++i )
3611 {
3612 SwAnchoredObject* pAnchoredObj = (*pFrame->GetDrawObjs())[i];
3613 if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
3614 {
3615 SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
3616 if ( pFly->IsHeightClipped() &&
3617 ( !pFly->IsFlyFreeFrame() || pFly->GetPageFrame() ) )
3618 return true;
3619 }
3620 }
3621 }
3622 pFrame = pFrame->FindNextCnt();
3623 }
3624 return false;
43
Returning zero, which participates in a condition later
3625}
3626
3627void SwLayoutFrame::FormatWidthCols( const SwBorderAttrs &rAttrs,
3628 const SwTwips nBorder, const SwTwips nMinHeight )
3629{
3630 //If there are columns involved, the size is adjusted using the last column.
3631 //1. Format content.
3632 //2. Calculate height of the last column: if it's too big, the Fly has to
3633 // grow. The amount by which the Fly grows is not the amount of the
3634 // overhang because we have to act on the assumption that some text flows
3635 // back which will generate some more space.
3636 // The amount which we grow by equals the overhang
3637 // divided by the amount of columns or the overhang itself if it's smaller
3638 // than the amount of columns.
3639 //3. Go back to 1. until everything is stable.
3640
3641 const SwFormatCol &rCol = rAttrs.GetAttrSet().GetCol();
3642 const sal_uInt16 nNumCols = rCol.GetNumCols();
1
'nNumCols' initialized here
3643
3644 bool bEnd = false;
3645 bool bBackLock = false;
3646 SwViewShell *pSh = getRootFrame()->GetCurrShell();
3647 SwViewShellImp *pImp = pSh ? pSh->Imp() : nullptr;
2
Assuming 'pSh' is null
3
'?' condition is false
3648 vcl::RenderContext* pRenderContext = pSh
3.1
'pSh' is null
3.1
'pSh' is null
3.1
'pSh' is null
? pSh->GetOut() : nullptr;
4
'?' condition is false
3649 {
3650 // Underlying algorithm
3651 // We try to find the optimal height for the column.
3652 // nMinimum starts with the passed minimum height and is then remembered
3653 // as the maximum height on which column content still juts out of a
3654 // column.
3655 // nMaximum starts with LONG_MAX and is then remembered as the minimum
3656 // width on which the content fitted.
3657 // In column based sections nMaximum starts at the maximum value which
3658 // the surrounding defines, this can certainly be a value on which
3659 // content still juts out.
3660 // The columns are formatted. If content still juts out, nMinimum is
3661 // adjusted accordingly, then we grow, at least by uMinDiff but not
3662 // over a certain nMaximum. If no content juts out but there is still
3663 // some space left in the column, shrinking is done accordingly, at
3664 // least by nMindIff but not below the nMinimum.
3665 // Cancel as soon as no content juts out and the difference from minimum
3666 // to maximum is less than MinDiff or the maximum which was defined by
3667 // the surrounding is reached even if some content still juts out.
3668
3669 // Criticism of this implementation
3670 // 1. Theoretically situations are possible in which the content fits in
3671 // a lower height but not in a higher height. To ensure that the code
3672 // handles such situations the code contains a few checks concerning
3673 // minimum and maximum which probably are never triggered.
3674 // 2. We use the same nMinDiff for shrinking and growing, but nMinDiff
3675 // is more or less the smallest first line height and doesn't seem ideal
3676 // as minimum value.
3677
3678 long nMinimum = nMinHeight;
3679 long nMaximum;
3680 bool bNoBalance = false;
3681 SwRectFnSet aRectFnSet(this);
3682 if( IsSctFrame() )
5
Taking false branch
3683 {
3684 nMaximum = aRectFnSet.GetHeight(getFrameArea()) - nBorder +
3685 aRectFnSet.BottomDist(getFrameArea(), aRectFnSet.GetPrtBottom(*GetUpper()));
3686 nMaximum += GetUpper()->Grow( LONG_MAX9223372036854775807L, true );
3687 if( nMaximum < nMinimum )
3688 {
3689 if( nMaximum < 0 )
3690 nMinimum = nMaximum = 0;
3691 else
3692 nMinimum = nMaximum;
3693 }
3694 if( nMaximum > BROWSE_HEIGHT(56700L * 10L) )
3695 nMaximum = BROWSE_HEIGHT(56700L * 10L);
3696
3697 bNoBalance = static_cast<SwSectionFrame*>(this)->GetSection()->GetFormat()->
3698 GetBalancedColumns().GetValue();
3699 SwFrame* pAny = ContainsAny();
3700 if( bNoBalance ||
3701 ( !aRectFnSet.GetHeight(getFrameArea()) && pAny ) )
3702 {
3703 long nTop = aRectFnSet.GetTopMargin(*this);
3704 // #i23129# - correction
3705 // to the calculated maximum height.
3706 {
3707 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
3708 aRectFnSet.AddBottom( aFrm, nMaximum - aRectFnSet.GetHeight(getFrameArea()) );
3709 }
3710
3711 if( nTop > nMaximum )
3712 nTop = nMaximum;
3713 aRectFnSet.SetYMargins( *this, nTop, 0 );
3714 }
3715 if( !pAny && !static_cast<SwSectionFrame*>(this)->IsFootnoteLock() )
3716 {
3717 SwFootnoteContFrame* pFootnoteCont = static_cast<SwSectionFrame*>(this)->ContainsFootnoteCont();
3718 if( pFootnoteCont )
3719 {
3720 SwFrame* pFootnoteAny = pFootnoteCont->ContainsAny();
3721 if( pFootnoteAny && pFootnoteAny->isFrameAreaDefinitionValid() )
3722 {
3723 bBackLock = true;
3724 static_cast<SwSectionFrame*>(this)->SetFootnoteLock( true );
3725 }
3726 }
3727 }
3728 }
3729 else
3730 nMaximum = LONG_MAX9223372036854775807L;
3731
3732 // #i3317# - reset temporarily consideration
3733 // of wrapping style influence
3734 SwPageFrame* pPageFrame = FindPageFrame();
3735 SwSortedObjs* pObjs = pPageFrame ? pPageFrame->GetSortedObjs() : nullptr;
6
Assuming 'pPageFrame' is null
7
'?' condition is false
3736 if ( pObjs
7.1
'pObjs' is null
7.1
'pObjs' is null
7.1
'pObjs' is null
)
8
Taking false branch
3737 {
3738 for (SwAnchoredObject* pAnchoredObj : *pObjs)
3739 {
3740 if ( IsAnLower( pAnchoredObj->GetAnchorFrame() ) )
3741 {
3742 pAnchoredObj->SetTmpConsiderWrapInfluence( false );
3743 }
3744 }
3745 }
3746 do
3747 {
3748 //Could take a while therefore check for Waitcrsr here.
3749 if ( pImp
8.1
'pImp' is null
8.1
'pImp' is null
8.1
'pImp' is null
)
9
Taking false branch
3750 pImp->CheckWaitCursor();
3751
3752 setFrameAreaSizeValid(true);
3753 //First format the column as this will relieve the stack a bit.
3754 //Also set width and height of the column (if they are wrong)
3755 //while we are at it.
3756 SwLayoutFrame *pCol = static_cast<SwLayoutFrame*>(Lower());
3757
3758 // #i27399#
3759 // Simply setting the column width based on the values returned by
3760 // CalcColWidth does not work for automatic column width.
3761 AdjustColumns( &rCol, false );
3762
3763 for ( sal_uInt16 i = 0; i < nNumCols; ++i )
10
Assuming 'i' is >= 'nNumCols'
11
Loop condition is false. Execution continues on line 3773
3764 {
3765 pCol->Calc(pRenderContext);
3766 // ColumnFrames have a BodyFrame now, which needs to be calculated
3767 pCol->Lower()->Calc(pRenderContext);
3768 if( pCol->Lower()->GetNext() )
3769 pCol->Lower()->GetNext()->Calc(pRenderContext); // SwFootnoteCont
3770 pCol = static_cast<SwLayoutFrame*>(pCol->GetNext());
3771 }
3772
3773 ::CalcContent( this );
3774
3775 pCol = static_cast<SwLayoutFrame*>(Lower());
3776 OSL_ENSURE( pCol && pCol->GetNext(), ":-( column making holidays?")do { if (true && (!(pCol && pCol->GetNext(
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3776" ": "), "%s", ":-( column making holidays?"); } } while
(false)
;
12
Assuming 'pCol' is non-null
13
Assuming the condition is false
14
Taking false branch
15
Loop condition is false. Exiting loop
3777 // set bMinDiff if no empty columns exist
3778 bool bMinDiff = true;
3779 // OD 28.03.2003 #108446# - check for all column content and all columns
3780 while ( bMinDiff
15.1
'bMinDiff' is true
17.1
'bMinDiff' is false
15.1
'bMinDiff' is true
17.1
'bMinDiff' is false
15.1
'bMinDiff' is true
17.1
'bMinDiff' is false
&& pCol )
16
Loop condition is true. Entering loop body
3781 {
3782 bMinDiff = nullptr != pCol->ContainsContent();
17
Assuming the condition is false
3783 pCol = static_cast<SwLayoutFrame*>(pCol->GetNext());
3784 }
3785 pCol = static_cast<SwLayoutFrame*>(Lower());
3786 // OD 28.03.2003 #108446# - initialize local variable
3787 SwTwips nDiff = 0;
3788 SwTwips nMaxFree = 0;
3789 SwTwips nAllFree = LONG_MAX9223372036854775807L;
3790 // set bFoundLower if there is at least one non-empty column
3791 bool bFoundLower = false;
3792 while( pCol )
18
Loop condition is true. Entering loop body
31
Loop condition is false. Execution continues on line 3830
3793 {
3794 SwLayoutFrame* pLay = static_cast<SwLayoutFrame*>(pCol->Lower());
3795 SwTwips nInnerHeight = aRectFnSet.GetHeight(pLay->getFrameArea()) -
3796 aRectFnSet.GetHeight(pLay->getFramePrintArea());
3797 if( pLay->Lower() )
19
Assuming the condition is false
20
Taking false branch
3798 {
3799 bFoundLower = true;
3800 nInnerHeight += pLay->InnerHeight();
3801 }
3802 else if( nInnerHeight < 0 )
21
Assuming 'nInnerHeight' is >= 0
22
Taking false branch
3803 nInnerHeight = 0;
3804
3805 if( pLay->GetNext() )
23
Assuming the condition is false
24
Taking false branch
3806 {
3807 bFoundLower = true;
3808 pLay = static_cast<SwLayoutFrame*>(pLay->GetNext());
3809 OSL_ENSURE( pLay->IsFootnoteContFrame(),"FootnoteContainer expected" )do { if (true && (!(pLay->IsFootnoteContFrame())))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "3809" ": "), "%s", "FootnoteContainer expected"); } } while
(false)
;
3810 nInnerHeight += pLay->InnerHeight();
3811 nInnerHeight += aRectFnSet.GetHeight(pLay->getFrameArea()) -
3812 aRectFnSet.GetHeight(pLay->getFramePrintArea());
3813 }
3814 nInnerHeight -= aRectFnSet.GetHeight(pCol->getFramePrintArea());
3815 if( nInnerHeight > nDiff )
25
Assuming 'nInnerHeight' is <= 'nDiff'
26
Taking false branch
3816 {
3817 nDiff = nInnerHeight;
3818 nAllFree = 0;
3819 }
3820 else
3821 {
3822 if( nMaxFree < -nInnerHeight )
27
Assuming the condition is false
28
Taking false branch
3823 nMaxFree = -nInnerHeight;
3824 if( nAllFree > -nInnerHeight )
29
Assuming the condition is false
30
Taking false branch
3825 nAllFree = -nInnerHeight;
3826 }
3827 pCol = static_cast<SwLayoutFrame*>(pCol->GetNext());
3828 }
3829
3830 if ( bFoundLower
31.1
'bFoundLower' is false
31.1
'bFoundLower' is false
31.1
'bFoundLower' is false
|| ( IsSctFrame() && static_cast<SwSectionFrame*>(this)->HasFollow() ) )
32
Calling 'SwFrame::IsSctFrame'
35
Returning from 'SwFrame::IsSctFrame'
36
Calling 'SwFlowFrame::HasFollow'
39
Returning from 'SwFlowFrame::HasFollow'
40
Taking true branch
3831 {
3832 SwTwips nMinDiff = ::lcl_CalcMinColDiff( this );
3833 // Here we decide if growing is needed - this is the case, if
3834 // column content (nDiff) or a Fly juts over.
3835 // In sections with columns we take into account to set the size
3836 // when having a non-empty Follow.
3837 if ( nDiff
40.1
'nDiff' is 0
40.1
'nDiff' is 0
40.1
'nDiff' is 0
|| ::lcl_IsFlyHeightClipped( this ) ||
41
Calling 'lcl_IsFlyHeightClipped'
44
Returning from 'lcl_IsFlyHeightClipped'
49
Taking true branch
3838 ( IsSctFrame() && static_cast<SwSectionFrame*>(this)->CalcMinDiff( nMinDiff ) ) )
45
Calling 'SwFrame::IsSctFrame'
47
Returning from 'SwFrame::IsSctFrame'
48
Assuming the condition is true
3839 {
3840 long nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea());
3841 // The minimum must not be smaller than our PrtHeight as
3842 // long as something juts over.
3843 if( nMinimum < nPrtHeight )
50
Assuming 'nMinimum' is >= 'nPrtHeight'
51
Taking false branch
3844 nMinimum = nPrtHeight;
3845 // The maximum must not be smaller than PrtHeight if
3846 // something still juts over.
3847 if( nMaximum
51.1
'nMaximum' is >= 'nPrtHeight'
51.1
'nMaximum' is >= 'nPrtHeight'
51.1
'nMaximum' is >= 'nPrtHeight'
< nPrtHeight )
52
Taking false branch
3848 nMaximum = nPrtHeight; // Robust, but will this ever happen?
3849 if( !nDiff
52.1
'nDiff' is 0
52.1
'nDiff' is 0
52.1
'nDiff' is 0
) // If only Flys jut over, we grow by nMinDiff
53
Taking true branch
3850 nDiff = nMinDiff;
3851 // If we should grow more than by nMinDiff we split it over
3852 // the columns
3853 if ( std::abs(nDiff - nMinDiff) > nNumCols && nDiff > static_cast<long>(nNumCols) )
54
Assuming the condition is true
55
Assuming 'nDiff' is > 'nNumCols'
56
Taking true branch
3854 nDiff /= nNumCols;
57
Division by zero
3855
3856 if ( bMinDiff )
3857 { // If no empty column exists, we want to grow at least
3858 // by nMinDiff. Special case: If we are smaller than the
3859 // minimal FrameHeight and PrtHeight is smaller than
3860 // nMindiff we grow in a way that PrtHeight is exactly
3861 // nMinDiff afterwards.
3862 long nFrameHeight = aRectFnSet.GetHeight(getFrameArea());
3863 if ( nFrameHeight > nMinHeight || nPrtHeight >= nMinDiff )
3864 nDiff = std::max( nDiff, nMinDiff );
3865 else if( nDiff < nMinDiff )
3866 nDiff = nMinDiff - nPrtHeight + 1;
3867 }
3868 // nMaximum has a size which fits the content or the
3869 // requested value from the surrounding therefore we don't
3870 // need to exceed this value.
3871 if( nDiff + nPrtHeight > nMaximum )
3872 nDiff = nMaximum - nPrtHeight;
3873 }
3874 else if( nMaximum > nMinimum ) // We fit, do we still have some margin?
3875 {
3876 long nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea());
3877 if ( nMaximum < nPrtHeight )
3878 nDiff = nMaximum - nPrtHeight; // We grew over a working
3879 // height and shrink back to it, but will this ever
3880 // happen?
3881 else
3882 { // We have a new maximum, a size which fits for the content.
3883 nMaximum = nPrtHeight;
3884 // If the margin in the column is bigger than nMinDiff
3885 // and we therefore drop under the minimum, we deflate
3886 // a bit.
3887 if ( !bNoBalance &&
3888 // #i23129# - <nMinDiff> can be
3889 // big, because of an object at the beginning of
3890 // a column. Thus, decrease optimization here.
3891 //nMaxFree >= nMinDiff &&
3892 nMaxFree > 0 &&
3893 ( !nAllFree ||
3894 nMinimum < nPrtHeight - nMinDiff ) )
3895 {
3896 nMaxFree /= nNumCols; // disperse over the columns
3897 nDiff = nMaxFree < nMinDiff ? -nMinDiff : -nMaxFree; // min nMinDiff
3898 if( nPrtHeight + nDiff <= nMinimum ) // below the minimum?
3899 nDiff = ( nMinimum - nMaximum ) / 2; // Take the center
3900 }
3901 else if( nAllFree )
3902 {
3903 nDiff = -nAllFree;
3904 if( nPrtHeight + nDiff <= nMinimum ) // Less than minimum?
3905 nDiff = ( nMinimum - nMaximum ) / 2; // Take the center
3906 }
3907 }
3908 }
3909 if( nDiff ) // now we shrink or grow...
3910 {
3911 Size aOldSz( getFramePrintArea().SSize() );
3912 long nTop = aRectFnSet.GetTopMargin(*this);
3913 nDiff = aRectFnSet.GetHeight(getFramePrintArea()) + nDiff + nBorder - aRectFnSet.GetHeight(getFrameArea());
3914
3915 {
3916 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
3917 aRectFnSet.AddBottom( aFrm, nDiff );
3918 }
3919
3920 // #i68520#
3921 SwFlyFrame *pFlyFrame = dynamic_cast<SwFlyFrame*>(this);
3922 if (pFlyFrame)
3923 {
3924 pFlyFrame->InvalidateObjRectWithSpaces();
3925 }
3926 aRectFnSet.SetYMargins( *this, nTop, nBorder - nTop );
3927 ChgLowersProp( aOldSz );
3928 NotifyLowerObjs();
3929
3930 // #i3317# - reset temporarily consideration
3931 // of wrapping style influence
3932 SwPageFrame* pTmpPageFrame = FindPageFrame();
3933 SwSortedObjs* pTmpObjs = pTmpPageFrame ? pTmpPageFrame->GetSortedObjs() : nullptr;
3934 if ( pTmpObjs )
3935 {
3936 for (SwAnchoredObject* pAnchoredObj : *pTmpObjs)
3937 {
3938 if ( IsAnLower( pAnchoredObj->GetAnchorFrame() ) )
3939 {
3940 pAnchoredObj->SetTmpConsiderWrapInfluence( false );
3941 }
3942 }
3943 }
3944 //Invalidate suitable to nicely balance the Frames.
3945 //- Every first one after the second column gets a
3946 // InvalidatePos();
3947 pCol = static_cast<SwLayoutFrame*>(Lower()->GetNext());
3948 while ( pCol )
3949 {
3950 SwFrame *pLow = pCol->Lower();
3951 if ( pLow )
3952 pLow->InvalidatePos_();
3953 pCol = static_cast<SwLayoutFrame*>(pCol->GetNext());
3954 }
3955 if( IsSctFrame() && static_cast<SwSectionFrame*>(this)->HasFollow() )
3956 {
3957 // If we created a Follow, we need to give its content
3958 // the opportunity to flow back inside the CalcContent
3959 SwContentFrame* pTmpContent =
3960 static_cast<SwSectionFrame*>(this)->GetFollow()->ContainsContent();
3961 if( pTmpContent )
3962 pTmpContent->InvalidatePos_();
3963 }
3964 }
3965 else
3966 bEnd = true;
3967 }
3968 else
3969 bEnd = true;
3970
3971 } while ( !bEnd || !isFrameAreaSizeValid() );
3972 }
3973 // OD 01.04.2003 #108446# - Don't collect endnotes for sections. Thus, set
3974 // 2nd parameter to <true>.
3975 ::CalcContent( this, true );
3976 if( IsSctFrame() )
3977 {
3978 // OD 14.03.2003 #i11760# - adjust 2nd parameter - sal_True --> true
3979 ::CalcContent( this, true );
3980 if( bBackLock )
3981 static_cast<SwSectionFrame*>(this)->SetFootnoteLock( false );
3982 }
3983}
3984
3985static SwContentFrame* lcl_InvalidateSection( SwFrame *pCnt, SwInvalidateFlags nInv )
3986{
3987 SwSectionFrame* pSect = pCnt->FindSctFrame();
3988 // If our ContentFrame is placed inside a table or a footnote, only sections
3989 // which are also placed inside are meant.
3990 // Exception: If a table is directly passed.
3991 if( ( ( pCnt->IsInTab() && !pSect->IsInTab() ) ||
3992 ( pCnt->IsInFootnote() && !pSect->IsInFootnote() ) ) && !pCnt->IsTabFrame() )
3993 return nullptr;
3994 if( nInv & SwInvalidateFlags::Size )
3995 pSect->InvalidateSize_();
3996 if( nInv & SwInvalidateFlags::Pos )
3997 pSect->InvalidatePos_();
3998 if( nInv & SwInvalidateFlags::PrtArea )
3999 pSect->InvalidatePrt_();
4000 SwFlowFrame *pFoll = pSect->GetFollow();
4001 // Temporary separation from follow
4002 pSect->SetFollow( nullptr );
4003 SwContentFrame* pRet = pSect->FindLastContent();
4004 pSect->SetFollow( pFoll );
4005 return pRet;
4006}
4007
4008static SwContentFrame* lcl_InvalidateTable( SwTabFrame *pTable, SwInvalidateFlags nInv )
4009{
4010 if( ( nInv & SwInvalidateFlags::Section ) && pTable->IsInSct() )
4011 lcl_InvalidateSection( pTable, nInv );
4012 if( nInv & SwInvalidateFlags::Size )
4013 pTable->InvalidateSize_();
4014 if( nInv & SwInvalidateFlags::Pos )
4015 pTable->InvalidatePos_();
4016 if( nInv & SwInvalidateFlags::PrtArea )
4017 pTable->InvalidatePrt_();
4018 return pTable->FindLastContent();
4019}
4020
4021static void lcl_InvalidateAllContent( SwContentFrame *pCnt, SwInvalidateFlags nInv );
4022
4023static void lcl_InvalidateContent( SwContentFrame *pCnt, SwInvalidateFlags nInv )
4024{
4025 SwContentFrame *pLastTabCnt = nullptr;
4026 SwContentFrame *pLastSctCnt = nullptr;
4027 while ( pCnt )
4028 {
4029 if( nInv & SwInvalidateFlags::Section )
4030 {
4031 if( pCnt->IsInSct() )
4032 {
4033 // See above at tables
4034 if( !pLastSctCnt )
4035 pLastSctCnt = lcl_InvalidateSection( pCnt, nInv );
4036 if( pLastSctCnt == pCnt )
4037 pLastSctCnt = nullptr;
4038 }
4039#if OSL_DEBUG_LEVEL1 > 0
4040 else
4041 OSL_ENSURE( !pLastSctCnt, "Where's the last SctContent?" )do { if (true && (!(!pLastSctCnt))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "4041" ": "), "%s", "Where's the last SctContent?"); } }
while (false)
;
4042#endif
4043 }
4044 if( nInv & SwInvalidateFlags::Table )
4045 {
4046 if( pCnt->IsInTab() )
4047 {
4048 // To not call FindTabFrame() for each ContentFrame of a table and
4049 // then invalidate the table, we remember the last ContentFrame of
4050 // the table and ignore IsInTab() until we are past it.
4051 // When entering the table, LastSctCnt is set to null, so
4052 // sections inside the table are correctly invalidated.
4053 // If the table itself is in a section the
4054 // invalidation is done three times, which is acceptable.
4055 if( !pLastTabCnt )
4056 {
4057 pLastTabCnt = lcl_InvalidateTable( pCnt->FindTabFrame(), nInv );
4058 pLastSctCnt = nullptr;
4059 }
4060 if( pLastTabCnt == pCnt )
4061 {
4062 pLastTabCnt = nullptr;
4063 pLastSctCnt = nullptr;
4064 }
4065 }
4066#if OSL_DEBUG_LEVEL1 > 0
4067 else
4068 OSL_ENSURE( !pLastTabCnt, "Where's the last TabContent?" )do { if (true && (!(!pLastTabCnt))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
":" "4068" ": "), "%s", "Where's the last TabContent?"); } }
while (false)
;
4069#endif
4070 }
4071
4072 if( nInv & SwInvalidateFlags::Size )
4073 pCnt->Prepare( PrepareHint::Clear, nullptr, false );
4074 if( nInv & SwInvalidateFlags::Pos )
4075 pCnt->InvalidatePos_();
4076 if( nInv & SwInvalidateFlags::PrtArea )
4077 pCnt->InvalidatePrt_();
4078 if ( nInv & SwInvalidateFlags::LineNum )
4079 pCnt->InvalidateLineNum();
4080 if ( pCnt->GetDrawObjs() )
4081 lcl_InvalidateAllContent( pCnt, nInv );
4082 pCnt = pCnt->GetNextContentFrame();
4083 }
4084}
4085
4086static void lcl_InvalidateAllContent( SwContentFrame *pCnt, SwInvalidateFlags nInv )
4087{
4088 SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
4089 for (SwAnchoredObject* pAnchoredObj : rObjs)
4090 {
4091 if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
4092 {
4093 SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
4094 if ( pFly->IsFlyInContentFrame() )
4095 {
4096 ::lcl_InvalidateContent( pFly->ContainsContent(), nInv );
4097 if( nInv & SwInvalidateFlags::Direction )
4098 pFly->CheckDirChange();
4099 }
4100 }
4101 }
4102}
4103
4104void SwRootFrame::InvalidateAllContent( SwInvalidateFlags nInv )
4105{
4106 // First process all page bound FlyFrames.
4107 SwPageFrame *pPage = static_cast<SwPageFrame*>(Lower());
4108 while( pPage )
4109 {
4110 pPage->InvalidateFlyLayout();
4111 pPage->InvalidateFlyContent();
4112 pPage->InvalidateFlyInCnt();
4113 pPage->InvalidateLayout();
4114 pPage->InvalidateContent();
4115 pPage->InvalidatePage( pPage ); // So even the Turbo disappears if applicable
4116
4117 if ( pPage->GetSortedObjs() )
4118 {
4119 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
4120 for (SwAnchoredObject* pAnchoredObj : rObjs)
4121 {
4122 if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
4123 {
4124 SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
4125 ::lcl_InvalidateContent( pFly->ContainsContent(), nInv );
4126 if ( nInv & SwInvalidateFlags::Direction )
4127 pFly->CheckDirChange();
4128 }
4129 }
4130 }
4131 if( nInv & SwInvalidateFlags::Direction )
4132 pPage->CheckDirChange();
4133 pPage = static_cast<SwPageFrame*>(pPage->GetNext());
4134 }
4135
4136 //Invalidate the whole document content and the character bound Flys here.
4137 ::lcl_InvalidateContent( ContainsContent(), nInv );
4138
4139 if( nInv & SwInvalidateFlags::PrtArea )
4140 {
4141 SwViewShell *pSh = getRootFrame()->GetCurrShell();
4142 if( pSh )
4143 pSh->InvalidateWindows( getFrameArea() );
4144 }
4145}
4146
4147/**
4148 * Invalidate/re-calculate the position of all floating screen objects (Writer fly frames and
4149 * drawing objects), that are anchored to paragraph or to character. (2004-03-16 #i11860#)
4150 */
4151void SwRootFrame::InvalidateAllObjPos()
4152{
4153 const SwPageFrame* pPageFrame = static_cast<const SwPageFrame*>(Lower());
4154 while( pPageFrame )
4155 {
4156 pPageFrame->InvalidateFlyLayout();
4157
4158 if ( pPageFrame->GetSortedObjs() )
4159 {
4160 const SwSortedObjs& rObjs = *(pPageFrame->GetSortedObjs());
4161 for (SwAnchoredObject* pAnchoredObj : rObjs)
4162 {
4163 const SwFormatAnchor& rAnch = pAnchoredObj->GetFrameFormat().GetAnchor();
4164 if ((rAnch.GetAnchorId() != RndStdIds::FLY_AT_PARA) &&
4165 (rAnch.GetAnchorId() != RndStdIds::FLY_AT_CHAR))
4166 {
4167 // only to paragraph and to character anchored objects are considered.
4168 continue;
4169 }
4170 // #i28701# - special invalidation for anchored
4171 // objects, whose wrapping style influence has to be considered.
4172 if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
4173 pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence();
4174 else
4175 pAnchoredObj->InvalidateObjPos();
4176 }
4177 }
4178
4179 pPageFrame = static_cast<const SwPageFrame*>(pPageFrame->GetNext());
4180 }
4181}
4182
4183static void AddRemoveFlysForNode(
4184 SwTextFrame & rFrame, SwTextNode & rTextNode,
4185 std::set<sal_uLong> *const pSkipped,
4186 SwFrameFormats & rTable,
4187 SwPageFrame *const pPage,
4188 SwTextNode const*const pNode,
4189 std::vector<sw::Extent>::const_iterator & rIterFirst,
4190 std::vector<sw::Extent>::const_iterator const& rIterEnd,
4191 SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode)
4192{
4193 if (pNode == &rTextNode)
4194 { // remove existing hidden at-char anchored flys
4195 RemoveHiddenObjsOfNode(rTextNode, &rIterFirst, &rIterEnd, pFirstNode, pLastNode);
4196 }
4197 else if (rTextNode.GetIndex() < pNode->GetIndex())
4198 {
4199 // pNode's frame has been deleted by CheckParaRedlineMerge()
4200 AppendObjsOfNode(&rTable,
4201 pNode->GetIndex(), &rFrame, pPage, &rTextNode.GetDoc(),
4202 &rIterFirst, &rIterEnd, pFirstNode, pLastNode);
4203 if (pSkipped)
4204 {
4205 // if a fly has been added by AppendObjsOfNode, it must be skipped; if not, then it doesn't matter if it's skipped or not because it has no frames and because of that it would be skipped anyway
4206 if (auto const pFlys = pNode->GetAnchoredFlys())
4207 {
4208 for (auto const pFly : *pFlys)
4209 {
4210 if (pFly->Which() != RES_DRAWFRMFMT)
4211 {
4212 pSkipped->insert(pFly->GetContent().GetContentIdx()->GetIndex());
4213 }
4214 }
4215 }
4216 }
4217 }
4218}
4219
4220namespace sw {
4221
4222/// rTextNode is the first one of the "new" merge - if rTextNode isn't the same
4223/// as MergedPara::pFirstNode, then nodes before rTextNode have their flys
4224/// already properly attached, so only the other nodes need handling here.
4225void AddRemoveFlysAnchoredToFrameStartingAtNode(
4226 SwTextFrame & rFrame, SwTextNode & rTextNode,
4227 std::set<sal_uLong> *const pSkipped)
4228{
4229 auto const pMerged(rFrame.GetMergedPara());
4230 if (!pMerged
4231 // do this only *once*, for the *last* frame
4232 // otherwise AppendObj would create multiple frames for fly-frames!
4233 || rFrame.GetFollow())
4234 return;
4235
4236 assert(pMerged->pFirstNode->GetIndex() <= rTextNode.GetIndex()(static_cast <bool> (pMerged->pFirstNode->GetIndex
() <= rTextNode.GetIndex() && rTextNode.GetIndex()
<= pMerged->pLastNode->GetIndex()) ? void (0) : __assert_fail
("pMerged->pFirstNode->GetIndex() <= rTextNode.GetIndex() && rTextNode.GetIndex() <= pMerged->pLastNode->GetIndex()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4237, __extension__ __PRETTY_FUNCTION__))
4237 && rTextNode.GetIndex() <= pMerged->pLastNode->GetIndex())(static_cast <bool> (pMerged->pFirstNode->GetIndex
() <= rTextNode.GetIndex() && rTextNode.GetIndex()
<= pMerged->pLastNode->GetIndex()) ? void (0) : __assert_fail
("pMerged->pFirstNode->GetIndex() <= rTextNode.GetIndex() && rTextNode.GetIndex() <= pMerged->pLastNode->GetIndex()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4237, __extension__ __PRETTY_FUNCTION__))
;
4238 // add visible flys in non-first node to merged frame
4239 // (hidden flys remain and are deleted via DelFrames())
4240 SwFrameFormats& rTable(*rTextNode.GetDoc().GetSpzFrameFormats());
4241 SwPageFrame *const pPage(rFrame.FindPageFrame());
4242 std::vector<sw::Extent>::const_iterator iterFirst(pMerged->extents.begin());
4243 std::vector<sw::Extent>::const_iterator iter(iterFirst);
4244 SwTextNode const* pNode(pMerged->pFirstNode);
4245 for ( ; ; ++iter)
4246 {
4247 if (iter == pMerged->extents.end()
4248 || iter->pNode != pNode)
4249 {
4250 AddRemoveFlysForNode(rFrame, rTextNode, pSkipped, rTable, pPage,
4251 pNode, iterFirst, iter,
4252 pMerged->pFirstNode, pMerged->pLastNode);
4253 sal_uLong const until = iter == pMerged->extents.end()
4254 ? pMerged->pLastNode->GetIndex() + 1
4255 : iter->pNode->GetIndex();
4256 for (sal_uLong i = pNode->GetIndex() + 1; i < until; ++i)
4257 {
4258 // let's show at-para flys on nodes that contain start/end of
4259 // redline too, even if there's no text there
4260 SwNode const*const pTmp(pNode->GetNodes()[i]);
4261 if (pTmp->GetRedlineMergeFlag() == SwNode::Merge::NonFirst)
4262 {
4263 AddRemoveFlysForNode(rFrame, rTextNode, pSkipped,
4264 rTable, pPage, pTmp->GetTextNode(), iter, iter,
4265 pMerged->pFirstNode, pMerged->pLastNode);
4266 }
4267 }
4268 if (iter == pMerged->extents.end())
4269 {
4270 break;
4271 }
4272 pNode = iter->pNode;
4273 iterFirst = iter;
4274 }
4275 }
4276}
4277
4278} // namespace sw
4279
4280static void UnHideRedlines(SwRootFrame & rLayout,
4281 SwNodes & rNodes, SwNode const& rEndOfSectionNode,
4282 std::set<sal_uLong> *const pSkipped)
4283{
4284 assert(rEndOfSectionNode.IsEndNode())(static_cast <bool> (rEndOfSectionNode.IsEndNode()) ? void
(0) : __assert_fail ("rEndOfSectionNode.IsEndNode()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4284, __extension__ __PRETTY_FUNCTION__))
;
4285 assert(rNodes[rEndOfSectionNode.StartOfSectionNode()->GetIndex() + 1]->IsCreateFrameWhenHidingRedlines())(static_cast <bool> (rNodes[rEndOfSectionNode.StartOfSectionNode
()->GetIndex() + 1]->IsCreateFrameWhenHidingRedlines())
? void (0) : __assert_fail ("rNodes[rEndOfSectionNode.StartOfSectionNode()->GetIndex() + 1]->IsCreateFrameWhenHidingRedlines()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4285, __extension__ __PRETTY_FUNCTION__))
; // first node is never hidden
4286 for (sal_uLong i = rEndOfSectionNode.StartOfSectionNode()->GetIndex() + 1;
4287 i < rEndOfSectionNode.GetIndex(); ++i)
4288 {
4289 SwNode & rNode(*rNodes[i]);
4290 if (rNode.IsTextNode()) // only text nodes are 1st node of a merge
4291 {
4292 SwTextNode & rTextNode(*rNode.GetTextNode());
4293 SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rTextNode);
4294 std::vector<SwTextFrame*> frames;
4295 for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
4296 {
4297 if (pFrame->getRootFrame() == &rLayout)
4298 {
4299 if (pFrame->IsFollow())
4300 {
4301 frames.push_back(pFrame);
4302 } // when hiding, the loop must remove the anchored flys
4303 else // *before* resetting SetMergedPara anywhere - else
4304 { // the fly deletion code will access multiple of the
4305 // frames with inconsistent MergedPara and assert
4306 frames.insert(frames.begin(), pFrame);
4307 }
4308 }
4309 }
4310 // this messes with pRegisteredIn so do it outside SwIterator
4311 auto eMode(sw::FrameMode::Existing);
4312 for (SwTextFrame * pFrame : frames)
4313 {
4314 if (rLayout.IsHideRedlines())
4315 {
4316 assert(!pFrame->GetMergedPara() ||(static_cast <bool> (!pFrame->GetMergedPara() || !rNode
.IsCreateFrameWhenHidingRedlines()) ? void (0) : __assert_fail
("!pFrame->GetMergedPara() || !rNode.IsCreateFrameWhenHidingRedlines()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4317, __extension__ __PRETTY_FUNCTION__))
4317 !rNode.IsCreateFrameWhenHidingRedlines())(static_cast <bool> (!pFrame->GetMergedPara() || !rNode
.IsCreateFrameWhenHidingRedlines()) ? void (0) : __assert_fail
("!pFrame->GetMergedPara() || !rNode.IsCreateFrameWhenHidingRedlines()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4317, __extension__ __PRETTY_FUNCTION__))
;
4318 if (rNode.IsCreateFrameWhenHidingRedlines())
4319 {
4320 {
4321 auto pMerged(CheckParaRedlineMerge(*pFrame,
4322 rTextNode, eMode));
4323 pFrame->SetMergedPara(std::move(pMerged));
4324 }
4325 auto const pMerged(pFrame->GetMergedPara());
4326 if (pMerged)
4327 {
4328 // invalidate SwInvalidateFlags::Size
4329 pFrame->Prepare(PrepareHint::Clear, nullptr, false);
4330 pFrame->InvalidatePage();
4331 if (auto const pObjs = pFrame->GetDrawObjs())
4332 { // also invalidate position of existing flys
4333 // because they may need to be moved
4334 for (auto const pObject : *pObjs)
4335 {
4336 pObject->InvalidateObjPos();
4337 }
4338 }
4339 }
4340 sw::AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame, rTextNode, pSkipped);
4341 // only *first* frame of node gets Existing because it
4342 eMode = sw::FrameMode::New; // is not idempotent!
4343 }
4344 }
4345 else
4346 {
4347 if (auto const& pMergedPara = pFrame->GetMergedPara())
4348 {
4349 // invalidate SwInvalidateFlags::Size
4350 pFrame->Prepare(PrepareHint::Clear, nullptr, false);
4351 pFrame->InvalidatePage();
4352 if (auto const pObjs = pFrame->GetDrawObjs())
4353 { // also invalidate position of existing flys
4354 for (auto const pObject : *pObjs)
4355 {
4356 pObject->InvalidateObjPos();
4357 }
4358 }
4359 // SwFlyAtContentFrame::Modify() always appends to
4360 // the master frame, so do the same here.
4361 // (RemoveFootnotesForNode must be called at least once)
4362 if (!pFrame->IsFollow())
4363 {
4364 // the new text frames don't exist yet, so at this point
4365 // we can only delete the footnote frames so they don't
4366 // point to the merged SwTextFrame any more...
4367 assert(&rTextNode == pMergedPara->pFirstNode)(static_cast <bool> (&rTextNode == pMergedPara->
pFirstNode) ? void (0) : __assert_fail ("&rTextNode == pMergedPara->pFirstNode"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4367, __extension__ __PRETTY_FUNCTION__))
;
4368 // iterate over nodes, not extents: if a node has
4369 // no extents now but did have extents initially,
4370 // its flys need their frames deleted too!
4371 for (sal_uLong j = rTextNode.GetIndex() + 1;
4372 j <= pMergedPara->pLastNode->GetIndex(); ++j)
4373 {
4374 SwNode *const pNode(rTextNode.GetNodes()[j]);
4375 assert(!pNode->IsEndNode())(static_cast <bool> (!pNode->IsEndNode()) ? void (0)
: __assert_fail ("!pNode->IsEndNode()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4375, __extension__ __PRETTY_FUNCTION__))
;
4376 if (pNode->IsStartNode())
4377 {
4378 j = pNode->EndOfSectionIndex();
4379 }
4380 else if (pNode->IsTextNode())
4381 {
4382 sw::RemoveFootnotesForNode(rLayout, *pNode->GetTextNode(), nullptr);
4383 // similarly, remove the anchored flys
4384 if (auto const pFlys = pNode->GetAnchoredFlys())
4385 {
4386 for (SwFrameFormat * pFormat : *pFlys)
4387 {
4388 pFormat->DelFrames(/*&rLayout*/);
4389 }
4390 }
4391 }
4392 }
4393 // rely on AppendAllObjs call at the end to add
4394 // all flys in first node that are hidden
4395 }
4396 pFrame->SetMergedPara(nullptr);
4397 }
4398 }
4399 pFrame->Broadcast(SfxHint()); // notify SwAccessibleParagraph
4400 }
4401 // all nodes, not just merged ones! it may be in the same list as
4402 if (rTextNode.IsNumbered(nullptr)) // a preceding merged one...
4403 { // notify frames so they reformat numbering portions
4404 rTextNode.NumRuleChgd();
4405 }
4406 }
4407 else if (rNode.IsTableNode() && rLayout.IsHideRedlines())
4408 {
4409 SwPosition const tmp(rNode);
4410 SwRangeRedline const*const pRedline(
4411 rLayout.GetFormat()->GetDoc()->getIDocumentRedlineAccess().GetRedline(tmp, nullptr));
4412 // pathology: redline that starts on a TableNode; cannot
4413 // be created in UI but by import filters...
4414 if (pRedline
4415 && pRedline->GetType() == RedlineType::Delete
4416 && &pRedline->Start()->nNode.GetNode() == &rNode)
4417 {
4418 for (sal_uLong j = rNode.GetIndex(); j <= rNode.EndOfSectionIndex(); ++j)
4419 {
4420 rNode.GetNodes()[j]->SetRedlineMergeFlag(SwNode::Merge::Hidden);
4421 }
4422 rNode.GetTableNode()->DelFrames(&rLayout);
4423 }
4424 }
4425 if (!rNode.IsCreateFrameWhenHidingRedlines())
4426 {
4427 if (rLayout.IsHideRedlines())
4428 {
4429 if (rNode.IsContentNode())
4430 {
4431 // note: nothing to do here, already done
4432#ifndef NDEBUG
4433 auto const pFrame(static_cast<SwContentNode&>(rNode).getLayoutFrame(&rLayout));
4434 assert(!pFrame || static_cast<SwTextFrame*>(pFrame)->GetMergedPara()->pFirstNode != &rNode)(static_cast <bool> (!pFrame || static_cast<SwTextFrame
*>(pFrame)->GetMergedPara()->pFirstNode != &rNode
) ? void (0) : __assert_fail ("!pFrame || static_cast<SwTextFrame*>(pFrame)->GetMergedPara()->pFirstNode != &rNode"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4434, __extension__ __PRETTY_FUNCTION__))
;
4435#endif
4436 }
4437 }
4438 else
4439 {
4440 assert(!rNode.IsContentNode() || !rNode.GetContentNode()->getLayoutFrame(&rLayout))(static_cast <bool> (!rNode.IsContentNode() || !rNode.GetContentNode
()->getLayoutFrame(&rLayout)) ? void (0) : __assert_fail
("!rNode.IsContentNode() || !rNode.GetContentNode()->getLayoutFrame(&rLayout)"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4440, __extension__ __PRETTY_FUNCTION__))
;
4441 sal_uLong j = i + 1;
4442 for ( ; j < rEndOfSectionNode.GetIndex(); ++j)
4443 {
4444 if (rNodes[j]->IsCreateFrameWhenHidingRedlines())
4445 {
4446 break;
4447 }
4448 }
4449 // call MakeFrames once, because sections/tables
4450 // InsertCnt_ also checks for hidden sections
4451 SwNodeIndex const start(rNodes, i);
4452 SwNodeIndex const end(rNodes, j);
4453 assert(!bDontCreateObjects)(static_cast <bool> (!bDontCreateObjects) ? void (0) : __assert_fail
("!bDontCreateObjects", "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4453, __extension__ __PRETTY_FUNCTION__))
;
4454 bDontCreateObjects = true; // suppress here, to be called once
4455 ::MakeFrames(rLayout.GetFormat()->GetDoc(), start, end);
4456 bDontCreateObjects = false;
4457 i = j - 1; // will be incremented again
4458 }
4459 }
4460 }
4461}
4462
4463static void UnHideRedlinesExtras(SwRootFrame & rLayout,
4464 SwNodes & rNodes, SwNode const& rEndOfExtraSectionNode,
4465 std::set<sal_uLong> *const pSkipped)
4466{
4467 assert(rEndOfExtraSectionNode.IsEndNode())(static_cast <bool> (rEndOfExtraSectionNode.IsEndNode()
) ? void (0) : __assert_fail ("rEndOfExtraSectionNode.IsEndNode()"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4467, __extension__ __PRETTY_FUNCTION__))
;
4468 for (sal_uLong i = rEndOfExtraSectionNode.StartOfSectionNode()->GetIndex()
4469 + 1; i < rEndOfExtraSectionNode.GetIndex(); ++i)
4470 {
4471 SwNode const& rStartNode(*rNodes[i]);
4472 assert(rStartNode.IsStartNode())(static_cast <bool> (rStartNode.IsStartNode()) ? void (
0) : __assert_fail ("rStartNode.IsStartNode()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4472, __extension__ __PRETTY_FUNCTION__))
;
4473 assert(rStartNode.GetRedlineMergeFlag() == SwNode::Merge::None)(static_cast <bool> (rStartNode.GetRedlineMergeFlag() ==
SwNode::Merge::None) ? void (0) : __assert_fail ("rStartNode.GetRedlineMergeFlag() == SwNode::Merge::None"
, "/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4473, __extension__ __PRETTY_FUNCTION__))
;
4474 SwNode const& rEndNode(*rStartNode.EndOfSectionNode());
4475 bool bSkip(pSkipped && pSkipped->find(i) != pSkipped->end());
4476 i = rEndNode.GetIndex();
4477 for (sal_uLong j = rStartNode.GetIndex() + 1; j < i; ++j)
4478 {
4479 // note: SwStartNode has no way to access the frames, so check
4480 // whether the first content-node inside the section has frames
4481 SwNode const& rNode(*rNodes[j]);
4482 if (rNode.IsSectionNode() &&
4483 static_cast<SwSectionNode const&>(rNode).GetSection().IsHiddenFlag())
4484 { // skip hidden sections - they can be inserted in fly-frames :(
4485 j = rNode.EndOfSectionNode()->GetIndex();
4486 continue;
4487 }
4488 if (rNode.IsContentNode())
4489 {
4490 SwContentNode const& rCNode(static_cast<SwContentNode const&>(rNode));
4491 if (!rCNode.getLayoutFrame(&rLayout))
4492 { // ignore footnote/fly/header/footer with no layout frame
4493 bSkip = true; // they will be created from scratch later if needed
4494 }
4495 break;
4496 }
4497 }
4498 if (!bSkip)
4499 {
4500 UnHideRedlines(rLayout, rNodes, rEndNode, pSkipped);
4501 }
4502 }
4503}
4504
4505void SwRootFrame::SetHideRedlines(bool const bHideRedlines)
4506{
4507 if (bHideRedlines == mbHideRedlines)
4508 {
4509 return;
4510 }
4511 mbHideRedlines = bHideRedlines;
4512 assert(GetCurrShell()->ActionPend())(static_cast <bool> (GetCurrShell()->ActionPend()) ?
void (0) : __assert_fail ("GetCurrShell()->ActionPend()",
"/home/maarten/src/libreoffice/core/sw/source/core/layout/wsfrm.cxx"
, 4512, __extension__ __PRETTY_FUNCTION__))
; // tdf#125754 avoid recursive layout
4513 SwDoc & rDoc(*GetFormat()->GetDoc());
4514 // don't do early return if there are no redlines:
4515 // Show->Hide must init hidden number trees
4516 // Hide->Show may be called after all redlines have been deleted but there
4517 // may still be MergedParas because those aren't deleted yet...
4518#if 0
4519 if (!bHideRedlines
4520 && rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty())
4521 {
4522 return;
4523 }
4524#endif
4525 // Hide->Show: clear MergedPara, create frames
4526 // Show->Hide: call CheckParaRedlineMerge, delete frames
4527 // Traverse the document via the nodes-array; traversing via the layout
4528 // wouldn't find the nodes that don't have frames in the ->Show case.
4529 // In-order traversal of each nodes array section should init the flags
4530 // in nodes before they are iterated.
4531 // Actual creation of frames should be done with existing functions
4532 // if possible, particularly InsertCnt_() or its wrapper ::MakeFrames().
4533 SwNodes /*const*/& rNodes(rDoc.GetNodes());
4534 // Flys/footnotes: must iterate and find all the ones that already exist
4535 // with frames and have redlines inside them; if any don't have frames at
4536 // all, they will be created (if necessary) from scratch and completely by
4537 // MakeFrames().
4538 //
4539 // Flys before footnotes: because footnotes may contain flys but not
4540 // vice-versa; alas flys may contain flys, so we skip some of them
4541 // if they have already been created from scratch via their anchor flys.
4542 std::set<sal_uLong> skippedFlys;
4543 UnHideRedlinesExtras(*this, rNodes, rNodes.GetEndOfAutotext(),
4544 // when un-hiding, delay all fly frame creation to AppendAllObjs below
4545 IsHideRedlines() ? &skippedFlys : nullptr);
4546 // Footnotes are created automatically (after invalidation etc.) by
4547 // ConnectFootnote(), but need to be deleted manually. Footnotes do not
4548 // occur in flys or headers/footers.
4549 UnHideRedlinesExtras(*this, rNodes, rNodes.GetEndOfInserts(), nullptr);
4550 UnHideRedlines(*this, rNodes, rNodes.GetEndOfContent(), nullptr);
4551
4552 if (!IsHideRedlines())
4553 { // create all previously hidden flys at once:
4554 // * Flys on first node of pre-existing merged frames that are hidden
4555 // (in delete redline), to be added to the existing frame
4556 // * Flys on non-first (hidden/merged) nodes of pre-existing merged
4557 // frames, to be added to the new frame of their node
4558 // * Flys anchored in other flys that are hidden
4559 AppendAllObjs(rDoc.GetSpzFrameFormats(), this);
4560 }
4561
4562 for (auto const pRedline : rDoc.getIDocumentRedlineAccess().GetRedlineTable())
4563 { // DELETE are handled by the code above; for other types, need to
4564 // trigger repaint of text frames to add/remove the redline color font
4565 if (pRedline->GetType() != RedlineType::Delete)
4566 {
4567 pRedline->InvalidateRange(SwRangeRedline::Invalidation::Add);
4568 }
4569 }
4570
4571 SwFootnoteIdxs & rFootnotes(rDoc.GetFootnoteIdxs());
4572 if (rDoc.GetFootnoteInfo().m_eNum == FTNNUM_CHAPTER)
4573 {
4574 // sadly determining which node is outline node requires hidden layout
4575 rFootnotes.UpdateAllFootnote();
4576 }
4577 // invalidate all footnotes to reformat their numbers
4578 for (SwTextFootnote *const pFootnote : rFootnotes)
4579 {
4580 SwFormatFootnote const& rFootnote(pFootnote->GetFootnote());
4581 if (rFootnote.GetNumber() != rFootnote.GetNumberRLHidden()
4582 && rFootnote.GetNumStr().isEmpty())
4583 {
4584 pFootnote->InvalidateNumberInLayout();
4585 }
4586 }
4587 // update various fields to re-expand them with the new layout
4588 IDocumentFieldsAccess & rIDFA(rDoc.getIDocumentFieldsAccess());
4589 auto const pAuthType(rIDFA.GetFieldType(
4590 SwFieldIds::TableOfAuthorities, OUString(), false));
4591 if (pAuthType) // created on demand...
4592 { // calling DelSequenceArray() should be unnecessary here since the
4593 // sequence doesn't depend on frames
4594 pAuthType->UpdateFields();
4595 }
4596 rIDFA.GetFieldType(SwFieldIds::RefPageGet, OUString(), false)->UpdateFields();
4597 rIDFA.GetSysFieldType(SwFieldIds::Chapter)->UpdateFields();
4598 rIDFA.UpdateExpFields(nullptr, false);
4599 rIDFA.UpdateRefFields();
4600
4601 // update SwPostItMgr / notes in the margin
4602 // note: as long as all shells share layout, broadcast to all shells!
4603 rDoc.GetDocShell()->Broadcast( SwFormatFieldHint(nullptr, bHideRedlines
4604 ? SwFormatFieldHintWhich::REMOVED
4605 : SwFormatFieldHintWhich::INSERTED) );
4606
4607
4608// InvalidateAllContent(SwInvalidateFlags::Size); // ??? TODO what to invalidate? this is the big hammer
4609}
4610
4611/* 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 )
936 const_cast<SwFrame*>(this)->SetInfFlags();
937 return mbInfTab;
938}
939inline bool SwFrame::IsInFly() const
940{
941 if ( mbInfInvalid )
942 const_cast<SwFrame*>(this)->SetInfFlags();
943 return mbInfFly;
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;
33
Assuming field 'mnFrameType' is equal to Section
34
Returning the value 1, which participates in a condition later
46
Returning the value 1, which participates in a condition later
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;
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: */

/home/maarten/src/libreoffice/core/sw/source/core/inc/flowfrm.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_FLOWFRM_HXX
21#define INCLUDED_SW_SOURCE_CORE_INC_FLOWFRM_HXX
22
23#include "frame.hxx"
24#include "layfrm.hxx"
25#include <swtypes.hxx>
26
27class SvxFormatKeepItem;
28class SvxFormatBreakItem;
29class SwPageFrame;
30class SwRect;
31class SwBorderAttrs;
32class SwDoc;
33class SwNodeIndex;
34
35/** Base class that provides the general functionalities for frames that are
36 allowed at page breaks (flow) and shall continue on the next page (can be
37 split), e.g. paragraphs (ContentFrame) or tables (TabFrame).
38
39 Some parts of these functionalities are implemented in FlowFrame while the
40 specific ones are done in the corresponding Frame classes. The FlowFrame has to
41 be seen as a base class. As such it is no Frame by itself and thus no direct
42 instances of FlowFrame can exist.
43
44 Actually it is not even a real Frame. The obvious implementation would be a
45 FlowFrame that is virtually inherited from SwFrame and that works with its own
46 member data. Further classes would need to inherit from FlowFrame and (via
47 multiple base classes since the class tree splits exactly at the branch
48 from SwFrame to SwContentFrame and SwLayoutFrame) also virtually from SwFrame as
49 well. Unfortunately, this leads - besides problems with compilers and
50 debugging programs - to high additional costs, that we IMHO are not able to
51 afford nowadays.
52
53 Hence, we use another technique: A FlowFrame keeps a reference to a SwFrame
54 - which it is actually itself - and they are friends. As a result, the
55 FlowFrame can work with the reference to the SwFrame instead of working with
56 its own this-pointer.
57 */
58class SwFlowFrame
59{
60 // PrepareMake is allowed to lock/unlock (robustness)
61 friend inline void PrepareLock ( SwFlowFrame * );
62 friend inline void PrepareUnlock( SwFlowFrame * );
63 friend inline void TableSplitRecalcLock( SwFlowFrame * );
64 friend inline void TableSplitRecalcUnlock( SwFlowFrame * );
65 // #i44049#
66 friend class SwObjectFormatterTextFrame;
67 friend class FlowFrameJoinLockGuard;
68
69 // TableSel is allowed to reset the follow-bit
70 friend inline void UnsetFollow( SwFlowFrame *pFlow );
71
72 friend void MakeFrames( SwDoc *, const SwNodeIndex &, const SwNodeIndex & );
73
74 friend class SwNode2LayImpl;
75
76 SwFrame& m_rThis;
77
78 // helper methods for MoveSubTree()
79 static SwLayoutFrame *CutTree( SwFrame* );
80 static bool PasteTree( SwFrame *, SwLayoutFrame *, SwFrame *, SwFrame* );
81
82 /** indicates that a backward move was done over multiple pages
83
84 Needed for the interaction of _GetPrevxxx and MoveBwd so that multiple
85 pages can be skipped at the same time. In addition, it is evaluated by
86 the MoveBwd() method in TabFrame.
87 */
88 static bool m_bMoveBwdJump;
89
90 /** helper method to determine previous frame for calculation of the
91 upper space
92
93 #i11860#
94
95 @param _pProposedPrevFrame
96 optional input parameter - pointer to frame, which should be used
97 instead of the direct previous frame.
98 */
99 const SwFrame* GetPrevFrameForUpperSpaceCalc_( const SwFrame* _pProposedPrevFrame = nullptr ) const;
100
101 /** method to determine the upper space amount, which is considered for
102 the previous frame
103
104 #i11860#
105 */
106 SwTwips GetUpperSpaceAmountConsideredForPrevFrame() const;
107
108 /** method to determine the upper space amount, which is considered for
109 the page grid
110
111 #i11860#
112 */
113 SwTwips GetUpperSpaceAmountConsideredForPageGrid_(
114 const SwTwips _nUpperSpaceWithoutGrid ) const;
115
116protected:
117 SwFlowFrame *m_pFollow;
118 SwFlowFrame *m_pPrecede;
119
120 bool m_bLockJoin :1; // if true than joins (and thus deletes) are prohibited!
121 bool m_bUndersized:1; // I am smaller than needed
122 bool m_bFlyLock :1; // stop positioning of at-character flyframes
123
124 // checks if forward flow makes sense to prevent infinite moves
125 inline bool IsFwdMoveAllowed() const;
126 // #i44049# - method <CalcContent(..)> has to check this property.
127 friend void CalcContent( SwLayoutFrame *pLay, bool bNoColl );
128 bool IsKeepFwdMoveAllowed( bool bIgnoreMyOwnKeepValue = false ); // like above, forward flow for Keep.
129
130 /** method to determine overlapping of an object that requests floating
131
132 0: no overlapping
133 1: objects that are anchored at the FlowFrame overlap
134 2: objects that are anchored somewhere else overlap
135 3: both types of objects overlap
136 */
137 sal_uInt8 BwdMoveNecessary( const SwPageFrame *pPage, const SwRect &rRect );
138
139 void LockJoin() { m_bLockJoin = true; }
140 void UnlockJoin() { m_bLockJoin = false; }
141
142 bool CheckMoveFwd( bool& rbMakePage, bool bKeep, bool bIgnoreMyOwnKeepValue );
143 bool MoveFwd( bool bMakePage, bool bPageBreak, bool bMoveAlways = false );
144 bool MoveBwd( bool &rbReformat );
145 virtual bool ShouldBwdMoved( SwLayoutFrame *pNewUpper, bool &rReformat )=0;
146
147public:
148 SwFlowFrame( SwFrame &rFrame );
149 virtual ~SwFlowFrame();
150
151 const SwFrame& GetFrame() const { return m_rThis; }
152 SwFrame& GetFrame() { return m_rThis; }
153
154 static bool IsMoveBwdJump() { return m_bMoveBwdJump; }
155 static void SetMoveBwdJump( bool bNew ){ m_bMoveBwdJump = bNew; }
156
157 void SetUndersized( const bool bNew ) { m_bUndersized = bNew; }
158 bool IsUndersized() const { return m_bUndersized; }
159
160 bool IsPrevObjMove() const;
161
162 /** hook tree onto new parent with minimal operations and notifications */
163 void MoveSubTree( SwLayoutFrame* pParent, SwFrame* pSibling = nullptr );
164
165 bool HasFollow() const { return m_pFollow != nullptr; }
37
Assuming the condition is true
38
Returning the value 1, which participates in a condition later
166 bool IsFollow() const { return nullptr != m_pPrecede; }
167 bool IsAnFollow( const SwFlowFrame *pFlow ) const;
168 const SwFlowFrame *GetFollow() const { return m_pFollow; }
169 SwFlowFrame *GetFollow() { return m_pFollow; }
170 void SetFollow(SwFlowFrame *const pFollow);
171
172 const SwFlowFrame *GetPrecede() const { return m_pPrecede; }
173 SwFlowFrame *GetPrecede() { return m_pPrecede; }
174
175 bool IsJoinLocked() const { return m_bLockJoin; }
176 bool IsAnyJoinLocked() const { return m_bLockJoin || HasLockedFollow(); }
177
178 bool IsPageBreak( bool bAct ) const;
179 bool IsColBreak( bool bAct ) const;
180
181 /** method to determine if a Keep needs to be considered (Breaks!) */
182 bool IsKeep(SvxFormatKeepItem const& rKeep,
183 SvxFormatBreakItem const& rBreak,
184 bool bBreakCheck = false ) const;
185
186 bool HasLockedFollow() const;
187
188 bool HasParaSpaceAtPages( bool bSct ) const;
189
190 /** method to determine the upper space hold by the frame
191
192 #i11860#
193
194 @param _bConsiderGrid
195 optional input parameter - consider the page grid while calculating?
196 */
197 SwTwips CalcUpperSpace( const SwBorderAttrs *pAttrs = nullptr,
198 const SwFrame* pPr = nullptr,
199 const bool _bConsiderGrid = true ) const;
200
201 /** method to determine the upper space amount, which is considered for
202 the previous frame and the page grid, if option 'Use former object
203 positioning' is OFF
204
205 #i11860#
206 */
207 SwTwips GetUpperSpaceAmountConsideredForPrevFrameAndPageGrid() const;
208
209 /** calculation of lower space */
210 SwTwips CalcLowerSpace( const SwBorderAttrs* _pAttrs = nullptr ) const;
211
212 /** calculation of the additional space to be considered, if flow frame
213 is the last inside a table cell
214
215 #i26250
216
217 @param _pAttrs
218 optional input parameter - border attributes of the flow frame.
219 Used for optimization, if caller has already determined the border
220 attributes.
221
222 @return SwTwips
223 */
224 SwTwips CalcAddLowerSpaceAsLastInTableCell(
225 const SwBorderAttrs* _pAttrs = nullptr ) const;
226
227 void CheckKeep();
228
229 void SetFlyLock( bool bNew ){ m_bFlyLock = bNew; }
230 bool IsFlyLock() const { return m_bFlyLock; }
231
232 bool ForbiddenForFootnoteCntFwd() const;
233
234 // Casting of a Frame into a FlowFrame (if it is one, otherwise 0)
235 // These methods need to be customized in subclasses!
236 static SwFlowFrame *CastFlowFrame( SwFrame *pFrame );
237 static const SwFlowFrame *CastFlowFrame( const SwFrame *pFrame );
238};
239
240inline bool SwFlowFrame::IsFwdMoveAllowed() const
241{
242 return m_rThis.GetIndPrev() != nullptr;
243}
244
245//use this to protect a SwLayoutFrame for a given scope from getting merged with
246//its neighbour and thus deleted
247class FlowFrameJoinLockGuard
248{
249private:
250 SwFlowFrame *m_pFlow;
251 bool m_bOldJoinLocked;
252public:
253 //JoinLock pParent for the lifetime of the Cut/Paste call, etc. to avoid
254 //SwSectionFrame::MergeNext removing the pParent we're trying to reparent
255 //into
256 FlowFrameJoinLockGuard(SwLayoutFrame* pFrame)
257 {
258 m_pFlow = SwFlowFrame::CastFlowFrame(pFrame);
259 if (m_pFlow)
260 {
261 m_bOldJoinLocked = m_pFlow->IsJoinLocked();
262 m_pFlow->LockJoin();
263 }
264 else
265 {
266 m_bOldJoinLocked = false;
267 }
268 }
269
270 ~FlowFrameJoinLockGuard()
271 {
272 if (m_pFlow && !m_bOldJoinLocked)
273 m_pFlow->UnlockJoin();
274 }
275};
276
277#endif
278
279/* vim:set shiftwidth=4 softtabstop=4 expandtab: */