1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_wasm_strip.h>
23 #include <osl/diagnose.h>
24 #include <o3tl/safeint.hxx>
25 #include <svl/itemiter.hxx>
26 #include <editeng/brushitem.hxx>
27 #include <sfx2/viewsh.hxx>
28 #include <fmtornt.hxx>
29 #include <pagefrm.hxx>
30 #include <section.hxx>
31 #include <rootfrm.hxx>
32 #include <anchoreddrawobject.hxx>
33 #include <fmtanchr.hxx>
34 #include <viewimp.hxx>
35 #include <viewopt.hxx>
36 #include <IDocumentSettingAccess.hxx>
37 #include <IDocumentFieldsAccess.hxx>
38 #include <IDocumentRedlineAccess.hxx>
39 #include <redline.hxx>
41 #include <ftninfo.hxx>
43 #include <fmtclbl.hxx>
44 #include <fmtfsize.hxx>
45 #include <fmtpdsc.hxx>
48 #include <fmtsrnd.hxx>
49 #include <fmtcntnt.hxx>
54 #include <sectfrm.hxx>
55 #include <fmtclds.hxx>
57 #include <bodyfrm.hxx>
58 #include <cellfrm.hxx>
59 #include <dbg_lay.hxx>
60 #include <editeng/frmdiritem.hxx>
61 #include <sortedobjs.hxx>
63 #include <frmtool.hxx>
66 #include <swtable.hxx>
70 #include <basegfx/matrix/b2dhommatrixtools.hxx>
72 using namespace ::com::sun::star
;
74 SwFrameAreaDefinition::SwFrameAreaDefinition()
75 : mnFrameId(SwFrameAreaDefinition::snLastFrameId
++),
76 mbFrameAreaPositionValid(false),
77 mbFrameAreaSizeValid(false),
78 mbFramePrintAreaValid(false)
82 SwFrameAreaDefinition::~SwFrameAreaDefinition()
86 void SwFrameAreaDefinition::setFrameAreaPositionValid(bool bNew
)
88 if(mbFrameAreaPositionValid
!= bNew
)
90 mbFrameAreaPositionValid
= bNew
;
94 void SwFrameAreaDefinition::setFrameAreaSizeValid(bool bNew
)
96 if(mbFrameAreaSizeValid
!= bNew
)
98 mbFrameAreaSizeValid
= bNew
;
102 void SwFrameAreaDefinition::setFramePrintAreaValid(bool bNew
)
104 if(mbFramePrintAreaValid
!= bNew
)
106 mbFramePrintAreaValid
= bNew
;
110 SwFrameAreaDefinition::FrameAreaWriteAccess::~FrameAreaWriteAccess()
112 if(mrTarget
.maFrameArea
!= *this)
114 mrTarget
.maFrameArea
= *this;
118 SwFrameAreaDefinition::FramePrintAreaWriteAccess::~FramePrintAreaWriteAccess()
120 if(mrTarget
.maFramePrintArea
!= *this)
122 mrTarget
.maFramePrintArea
= *this;
126 // RotateFlyFrame3 - Support for Transformations
127 basegfx::B2DHomMatrix
SwFrameAreaDefinition::getFrameAreaTransformation() const
129 // default implementation hands out FrameArea (outer frame)
130 const SwRect
& rFrameArea(getFrameArea());
132 return basegfx::utils::createScaleTranslateB2DHomMatrix(
133 rFrameArea
.Width(), rFrameArea
.Height(),
134 rFrameArea
.Left(), rFrameArea
.Top());
137 basegfx::B2DHomMatrix
SwFrameAreaDefinition::getFramePrintAreaTransformation() const
139 // default implementation hands out FramePrintArea (outer frame)
140 // Take into account that FramePrintArea is relative to FrameArea
141 const SwRect
& rFrameArea(getFrameArea());
142 const SwRect
& rFramePrintArea(getFramePrintArea());
144 return basegfx::utils::createScaleTranslateB2DHomMatrix(
145 rFramePrintArea
.Width(), rFramePrintArea
.Height(),
146 rFramePrintArea
.Left() + rFrameArea
.Left(),
147 rFramePrintArea
.Top() + rFrameArea
.Top());
150 void SwFrameAreaDefinition::transform_translate(const Point
& rOffset
)
152 // RotateFlyFrame3: default is to change the FrameArea, FramePrintArea needs no
153 // change since it is relative to FrameArea
154 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
156 if (aFrm
.Pos().X() != FAR_AWAY
)
158 aFrm
.Pos().AdjustX(rOffset
.X() );
161 if (aFrm
.Pos().Y() != FAR_AWAY
)
163 aFrm
.Pos().AdjustY(rOffset
.Y() );
167 SwRect
TransformableSwFrame::getUntransformedFrameArea() const
169 const basegfx::B2DHomMatrix
& rSource(getLocalFrameAreaTransformation());
171 if(rSource
.isIdentity())
173 return mrSwFrameAreaDefinition
.getFrameArea();
177 basegfx::B2DVector aScale
, aTranslate
;
178 double fRotate
, fShearX
;
179 rSource
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
180 const basegfx::B2DPoint
aCenter(rSource
* basegfx::B2DPoint(0.5, 0.5));
181 const basegfx::B2DVector
aAbsScale(basegfx::absolute(aScale
));
184 basegfx::fround
<tools::Long
>(aCenter
.getX() - (0.5 * aAbsScale
.getX())),
185 basegfx::fround
<tools::Long
>(aCenter
.getY() - (0.5 * aAbsScale
.getY())),
186 basegfx::fround
<tools::Long
>(aAbsScale
.getX()),
187 basegfx::fround
<tools::Long
>(aAbsScale
.getY()));
191 SwRect
TransformableSwFrame::getUntransformedFramePrintArea() const
193 const basegfx::B2DHomMatrix
& rSource(getLocalFramePrintAreaTransformation());
195 if(rSource
.isIdentity())
197 return mrSwFrameAreaDefinition
.getFramePrintArea();
201 basegfx::B2DVector aScale
, aTranslate
;
202 double fRotate
, fShearX
;
203 rSource
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
204 const basegfx::B2DPoint
aCenter(rSource
* basegfx::B2DPoint(0.5, 0.5));
205 const basegfx::B2DVector
aAbsScale(basegfx::absolute(aScale
));
206 const SwRect
aUntransformedFrameArea(getUntransformedFrameArea());
209 basegfx::fround
<tools::Long
>(aCenter
.getX() - (0.5 * aAbsScale
.getX())) - aUntransformedFrameArea
.Left(),
210 basegfx::fround
<tools::Long
>(aCenter
.getY() - (0.5 * aAbsScale
.getY())) - aUntransformedFrameArea
.Top(),
211 basegfx::fround
<tools::Long
>(aAbsScale
.getX()),
212 basegfx::fround
<tools::Long
>(aAbsScale
.getY()));
216 void TransformableSwFrame::createFrameAreaTransformations(
218 const basegfx::B2DPoint
& rCenter
)
220 const basegfx::B2DHomMatrix
aRotateAroundCenter(
221 basegfx::utils::createRotateAroundPoint(
225 const SwRect
& rFrameArea(mrSwFrameAreaDefinition
.getFrameArea());
226 const SwRect
& rFramePrintArea(mrSwFrameAreaDefinition
.getFramePrintArea());
228 maFrameAreaTransformation
= aRotateAroundCenter
* basegfx::utils::createScaleTranslateB2DHomMatrix(
229 rFrameArea
.Width(), rFrameArea
.Height(),
230 rFrameArea
.Left(), rFrameArea
.Top());
231 maFramePrintAreaTransformation
= aRotateAroundCenter
* basegfx::utils::createScaleTranslateB2DHomMatrix(
232 rFramePrintArea
.Width(), rFramePrintArea
.Height(),
233 rFramePrintArea
.Left() + rFrameArea
.Left(), rFramePrintArea
.Top() + rFrameArea
.Top());
236 void TransformableSwFrame::adaptFrameAreasToTransformations()
238 if(!getLocalFrameAreaTransformation().isIdentity())
240 basegfx::B2DRange
aRangeFrameArea(0.0, 0.0, 1.0, 1.0);
241 aRangeFrameArea
.transform(getLocalFrameAreaTransformation());
242 const SwRect
aNewFrm(
243 basegfx::fround
<tools::Long
>(aRangeFrameArea
.getMinX()), basegfx::fround
<tools::Long
>(aRangeFrameArea
.getMinY()),
244 basegfx::fround
<tools::Long
>(aRangeFrameArea
.getWidth()), basegfx::fround
<tools::Long
>(aRangeFrameArea
.getHeight()));
246 if(aNewFrm
!= mrSwFrameAreaDefinition
.getFrameArea())
248 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(mrSwFrameAreaDefinition
);
249 aFrm
.setSwRect(aNewFrm
);
253 if(getLocalFramePrintAreaTransformation().isIdentity())
256 basegfx::B2DRange
aRangeFramePrintArea(0.0, 0.0, 1.0, 1.0);
257 aRangeFramePrintArea
.transform(getLocalFramePrintAreaTransformation());
258 const SwRect
aNewPrt(
259 basegfx::fround
<tools::Long
>(aRangeFramePrintArea
.getMinX()) - mrSwFrameAreaDefinition
.getFrameArea().Left(),
260 basegfx::fround
<tools::Long
>(aRangeFramePrintArea
.getMinY()) - mrSwFrameAreaDefinition
.getFrameArea().Top(),
261 basegfx::fround
<tools::Long
>(aRangeFramePrintArea
.getWidth()),
262 basegfx::fround
<tools::Long
>(aRangeFramePrintArea
.getHeight()));
264 if(aNewPrt
!= mrSwFrameAreaDefinition
.getFramePrintArea())
266 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(mrSwFrameAreaDefinition
);
267 aPrt
.setSwRect(aNewPrt
);
271 void TransformableSwFrame::restoreFrameAreas()
273 // This can be done fully based on the Transformations currently
274 // set, so use this. Only needed when transformation *is* used
275 if(!getLocalFrameAreaTransformation().isIdentity())
277 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(mrSwFrameAreaDefinition
);
278 aFrm
.setSwRect(getUntransformedFrameArea());
281 if(!getLocalFramePrintAreaTransformation().isIdentity())
283 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(mrSwFrameAreaDefinition
);
284 aPrt
.setSwRect(getUntransformedFramePrintArea());
288 // transform by given B2DHomMatrix
289 void TransformableSwFrame::transform(const basegfx::B2DHomMatrix
& aTransform
)
291 maFrameAreaTransformation
*= aTransform
;
292 maFramePrintAreaTransformation
*= aTransform
;
295 void SwFrame::dumpAsXml(xmlTextWriterPtr pWriter
) const
297 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("infos"));
298 dumpInfosAsXml(pWriter
);
299 (void)xmlTextWriterEndElement(pWriter
);
301 if ( m_pDrawObjs
&& m_pDrawObjs
->size() > 0 )
303 (void)xmlTextWriterStartElement( pWriter
, BAD_CAST( "anchored" ) );
305 for (SwAnchoredObject
* pObject
: *m_pDrawObjs
)
307 pObject
->dumpAsXml( pWriter
);
310 (void)xmlTextWriterEndElement( pWriter
);
313 dumpChildrenAsXml(pWriter
);
316 void SwFrame::dumpChildrenAsXml( xmlTextWriterPtr writer
) const
318 const SwFrame
*pFrame
= GetLower( );
319 for ( ; pFrame
!= nullptr; pFrame
= pFrame
->GetNext( ) )
321 pFrame
->dumpAsXml( writer
);
325 SwFrame::SwFrame( sw::BroadcastingModify
*pMod
, SwFrame
* pSib
)
327 mpRoot( pSib
? pSib
->getRootFrame() : nullptr ),
331 mnFrameType(SwFrameType::None
),
335 mbRightToLeft(false),
337 mbDerivedVert(false),
341 mbValidLineNum(false),
343 mbCompletePaint(true),
349 mbInfFootnote ( false ),
352 m_isInDestroy(false),
355 OSL_ENSURE( pMod
, "No frame format given." );
358 const IDocumentDrawModelAccess
& SwFrame::getIDocumentDrawModelAccess()
360 return GetUpper()->GetFormat()->getIDocumentDrawModelAccess();
363 bool SwFrame::KnowsFormat( const SwFormat
& rFormat
) const
365 return GetRegisteredIn() == &rFormat
;
368 void SwFrame::RegisterToFormat( SwFormat
& rFormat
)
373 void SwFrame::CheckDir( SvxFrameDirection nDir
, bool bVert
, bool bOnlyBiDi
, bool bBrowse
)
375 if( SvxFrameDirection::Environment
== nDir
|| ( bVert
&& bOnlyBiDi
) )
377 mbDerivedVert
= true;
378 if( SvxFrameDirection::Environment
== nDir
)
380 SetDirFlags( bVert
);
384 mbInvalidVert
= false;
385 if( SvxFrameDirection::Horizontal_LR_TB
== nDir
|| SvxFrameDirection::Horizontal_RL_TB
== nDir
395 if(SvxFrameDirection::Vertical_RL_TB
== nDir
)
400 else if(SvxFrameDirection::Vertical_LR_TB
==nDir
)
405 else if (nDir
== SvxFrameDirection::Vertical_LR_BT
)
410 else if (nDir
== SvxFrameDirection::Vertical_RL_TB90
)
412 // not yet implemented, render as RL_TB
420 mbInvalidR2L
= false;
421 if( SvxFrameDirection::Horizontal_RL_TB
== nDir
)
422 mbRightToLeft
= true;
424 mbRightToLeft
= false;
428 void SwFrame::CheckDirection( bool bVert
)
432 if( !IsHeaderFrame() && !IsFooterFrame() )
434 mbDerivedVert
= true;
435 SetDirFlags( bVert
);
441 SetDirFlags( bVert
);
445 void SwSectionFrame::CheckDirection( bool bVert
)
447 const SwFrameFormat
* pFormat
= GetFormat();
450 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
451 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
452 CheckDir(pFormat
->GetFormatAttr(RES_FRAMEDIR
).GetValue(),
453 bVert
, true, bBrowseMode
);
456 SwFrame::CheckDirection( bVert
);
459 void SwFlyFrame::CheckDirection( bool bVert
)
461 const SwFrameFormat
* pFormat
= GetFormat();
464 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
465 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
466 CheckDir(pFormat
->GetFormatAttr(RES_FRAMEDIR
).GetValue(),
467 bVert
, false, bBrowseMode
);
470 SwFrame::CheckDirection( bVert
);
473 void SwTabFrame::CheckDirection( bool bVert
)
475 const SwFrameFormat
* pFormat
= GetFormat();
478 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
479 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
480 CheckDir(pFormat
->GetFormatAttr(RES_FRAMEDIR
).GetValue(),
481 bVert
, true, bBrowseMode
);
484 SwFrame::CheckDirection( bVert
);
487 void SwCellFrame::CheckDirection( bool bVert
)
489 const SwFrameFormat
* pFormat
= GetFormat();
490 const SvxFrameDirectionItem
* pFrameDirItem
;
491 // Check if the item is set, before actually
492 // using it. Otherwise the dynamic pool default is used, which may be set
493 // to LTR in case of OOo 1.0 documents.
494 if( pFormat
&& (pFrameDirItem
= pFormat
->GetItemIfSet( RES_FRAMEDIR
) ) )
496 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
497 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
498 CheckDir( pFrameDirItem
->GetValue(), bVert
, false, bBrowseMode
);
501 SwFrame::CheckDirection( bVert
);
504 void SwTextFrame::CheckDirection( bool bVert
)
506 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
507 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
508 CheckDir(GetTextNodeForParaProps()->GetSwAttrSet().GetFrameDir().GetValue(),
509 bVert
, true, bBrowseMode
);
512 void SwFrame::SwClientNotify(const SwModify
&, const SfxHint
& rHint
)
514 if (rHint
.GetId() != SfxHintId::SwLegacyModify
&& rHint
.GetId() != SfxHintId::SwFormatChange
515 && rHint
.GetId() != SfxHintId::SwAttrSetChange
)
518 SwFrameInvFlags eInvFlags
= SwFrameInvFlags::NONE
;
519 if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
521 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
522 UpdateAttrFrame(pLegacy
->m_pOld
, pLegacy
->m_pNew
, eInvFlags
);
524 else if (rHint
.GetId() == SfxHintId::SwAttrSetChange
)
526 auto pChangeHint
= static_cast<const sw::AttrSetChangeHint
*>(&rHint
);
527 if(pChangeHint
->m_pOld
&& pChangeHint
->m_pNew
)
529 SfxItemIter
aNIter(*pChangeHint
->m_pNew
->GetChgSet());
530 SfxItemIter
aOIter(*pChangeHint
->m_pOld
->GetChgSet());
531 const SfxPoolItem
* pNItem
= aNIter
.GetCurItem();
532 const SfxPoolItem
* pOItem
= aOIter
.GetCurItem();
535 UpdateAttrFrame(pOItem
, pNItem
, eInvFlags
);
536 pNItem
= aNIter
.NextItem();
537 pOItem
= aOIter
.NextItem();
541 else // rHint.GetId() == SfxHintId::SwFormatChange
543 UpdateAttrFrameForFormatChange(eInvFlags
);
546 if(eInvFlags
== SwFrameInvFlags::NONE
)
549 SwPageFrame
* pPage
= FindPageFrame();
550 InvalidatePage(pPage
);
551 if(eInvFlags
& SwFrameInvFlags::InvalidatePrt
)
554 if(!GetPrev() && IsTabFrame() && IsInSct())
555 FindSctFrame()->InvalidatePrt_();
557 if(eInvFlags
& SwFrameInvFlags::InvalidateSize
)
559 if(eInvFlags
& SwFrameInvFlags::InvalidatePos
)
561 if(eInvFlags
& SwFrameInvFlags::SetCompletePaint
)
564 if (eInvFlags
& (SwFrameInvFlags::NextInvalidatePos
| SwFrameInvFlags::NextSetCompletePaint
)
565 && nullptr != (pNxt
= GetNext()))
567 pNxt
->InvalidatePage(pPage
);
568 if(eInvFlags
& SwFrameInvFlags::NextInvalidatePos
)
569 pNxt
->InvalidatePos_();
570 if(eInvFlags
& SwFrameInvFlags::NextSetCompletePaint
)
571 pNxt
->SetCompletePaint();
575 void SwFrame::UpdateAttrFrame( const SfxPoolItem
*pOld
, const SfxPoolItem
*pNew
,
576 SwFrameInvFlags
&rInvFlags
)
578 sal_uInt16 nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
583 Prepare( PrepareHint::FixSizeChanged
);
585 case RES_MARGIN_FIRSTLINE
:
586 case RES_MARGIN_TEXTLEFT
:
587 case RES_MARGIN_RIGHT
:
591 rInvFlags
|= SwFrameInvFlags::InvalidatePrt
| SwFrameInvFlags::InvalidateSize
592 | SwFrameInvFlags::SetCompletePaint
;
595 case RES_HEADER_FOOTER_EAT_SPACING
:
596 rInvFlags
|= SwFrameInvFlags::InvalidatePrt
| SwFrameInvFlags::InvalidateSize
;
600 case RES_BACKGROUND_FULL_SIZE
:
601 rInvFlags
|= SwFrameInvFlags::SetCompletePaint
| SwFrameInvFlags::NextSetCompletePaint
;
605 rInvFlags
|= SwFrameInvFlags::InvalidatePos
;
609 ReinitializeFrameSizeAttrFlags();
610 rInvFlags
|= SwFrameInvFlags::InvalidatePrt
| SwFrameInvFlags::InvalidateSize
611 | SwFrameInvFlags::NextInvalidatePos
;
618 bool bInFollowFlowRow
= nullptr != IsInFollowFlowRow();
619 if ( bInFollowFlowRow
|| nullptr != IsInSplitTableRow() )
621 SwTabFrame
* pTab
= FindTabFrame();
622 if ( bInFollowFlowRow
)
623 pTab
= pTab
->FindMaster();
624 pTab
->SetRemoveFollowFlowLinePending( true );
630 OSL_FAIL( "Columns for new FrameType?" );
634 // the new FillStyle has to do the same as previous RES_BACKGROUND
635 if(nWhich
>= XATTR_FILL_FIRST
&& nWhich
<= XATTR_FILL_LAST
)
638 |= SwFrameInvFlags::SetCompletePaint
| SwFrameInvFlags::NextSetCompletePaint
;
645 void SwFrame::UpdateAttrFrameForFormatChange( SwFrameInvFlags
&rInvFlags
)
647 rInvFlags
|= SwFrameInvFlags::InvalidatePrt
| SwFrameInvFlags::InvalidateSize
648 | SwFrameInvFlags::InvalidatePos
| SwFrameInvFlags::SetCompletePaint
;
651 bool SwFrame::Prepare( const PrepareHint
, const void *, bool )
658 * Invalidates the page in which the Frame is currently placed.
659 * The page is invalidated depending on the type (Layout, Content, FlyFrame)
661 void SwFrame::InvalidatePage( const SwPageFrame
*pPage
) const
665 pPage
= FindPageFrame();
666 // #i28701# - for at-character and as-character
667 // anchored Writer fly frames additionally invalidate also page frame
668 // its 'anchor character' is on.
669 if ( pPage
&& pPage
->GetUpper() && IsFlyFrame() )
671 const SwFlyFrame
* pFlyFrame
= static_cast<const SwFlyFrame
*>(this);
672 if ( pFlyFrame
->IsAutoPos() || pFlyFrame
->IsFlyInContentFrame() )
674 // #i33751#, #i34060# - method <GetPageFrameOfAnchor()>
675 // is replaced by method <FindPageFrameOfAnchor()>. It's return value
676 // have to be checked.
677 SwPageFrame
* pPageFrameOfAnchor
=
678 const_cast<SwFlyFrame
*>(pFlyFrame
)->FindPageFrameOfAnchor();
679 if ( pPageFrameOfAnchor
&& pPageFrameOfAnchor
!= pPage
)
681 InvalidatePage( pPageFrameOfAnchor
);
687 if ( !(pPage
&& pPage
->GetUpper()) )
690 if ( pPage
->GetFormat()->GetDoc()->IsInDtor() )
693 SwRootFrame
*pRoot
= const_cast<SwRootFrame
*>(static_cast<const SwRootFrame
*>(pPage
->GetUpper()));
694 const SwFlyFrame
*pFly
= FindFlyFrame();
695 if ( IsContentFrame() )
697 if ( pRoot
->IsTurboAllowed() )
699 // If a ContentFrame wants to register for a second time, make it a TurboAction.
700 if ( !pRoot
->GetTurbo() || this == pRoot
->GetTurbo() )
701 pRoot
->SetTurbo( static_cast<const SwContentFrame
*>(this) );
704 pRoot
->DisallowTurbo();
705 //The page of the Turbo could be a different one then mine,
706 //therefore we have to invalidate it.
707 const SwFrame
*pTmp
= pRoot
->GetTurbo();
709 pTmp
->InvalidatePage();
712 if ( !pRoot
->GetTurbo() )
715 { if( !pFly
->IsLocked() )
717 if ( pFly
->IsFlyInContentFrame() )
718 { pPage
->InvalidateFlyInCnt();
719 pFly
->GetAnchorFrame()->InvalidatePage();
722 pPage
->InvalidateFlyContent();
726 pPage
->InvalidateContent();
731 pRoot
->DisallowTurbo();
734 if ( !pFly
->IsLocked() )
736 if ( pFly
->IsFlyInContentFrame() )
738 pPage
->InvalidateFlyInCnt();
739 pFly
->GetAnchorFrame()->InvalidatePage();
742 pPage
->InvalidateFlyLayout();
746 pPage
->InvalidateLayout();
748 if ( pRoot
->GetTurbo() )
749 { const SwFrame
*pTmp
= pRoot
->GetTurbo();
751 pTmp
->InvalidatePage();
754 pRoot
->SetIdleFlags();
759 SwTextFrame
const*const pText(static_cast<SwTextFrame
const*>(this));
760 if (sw::MergedPara
const*const pMergedPara
= pText
->GetMergedPara())
762 SwTextNode
const* pNode(nullptr);
763 for (auto const& e
: pMergedPara
->extents
)
765 if (e
.pNode
!= pNode
)
768 if (pNode
->IsGrammarCheckDirty())
770 pRoot
->SetNeedGrammarCheck( true );
778 if (pText
->GetTextNodeFirst()->IsGrammarCheckDirty())
780 pRoot
->SetNeedGrammarCheck( true );
785 Size
SwFrame::ChgSize( const Size
& aNewSize
)
788 const Size
aOldSize( getFrameArea().SSize() );
789 if ( aNewSize
== aOldSize
)
794 bool bNeighb
= IsNeighbourFrame();
795 SwRectFnSet
fnRect(IsVertical() != bNeighb
, IsVertLR(), IsVertLRBT());
796 SwRect
aNew( Point(0,0), aNewSize
);
799 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
800 fnRect
.SetWidth(aFrm
, fnRect
.GetWidth(aNew
));
803 tools::Long nNew
= fnRect
.GetHeight(aNew
);
804 tools::Long nDiff
= nNew
- fnRect
.GetHeight(getFrameArea());
808 if ( GetUpper()->IsFootnoteBossFrame() && HasFixSize() &&
809 SwNeighbourAdjust::GrowShrink
!=
810 static_cast<SwFootnoteBossFrame
*>(GetUpper())->NeighbourhoodAdjustment() )
813 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
814 fnRect
.SetHeight(aFrm
, nNew
);
817 SwTwips nReal
= static_cast<SwLayoutFrame
*>(this)->AdjustNeighbourhood(nDiff
);
819 if ( nReal
!= nDiff
)
821 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
822 fnRect
.SetHeight(aFrm
, nNew
- nDiff
+ nReal
);
827 // OD 24.10.2002 #97265# - grow/shrink not for neighbour frames
828 // NOTE: neighbour frames are cell and column frames.
836 if (GetUpper() && fnRect
.GetHeight(getFrameArea()) != nNew
)
838 GetUpper()->InvalidateSize_();
842 // Even if grow/shrink did not yet set the desired width, for
843 // example when called by ChgColumns to set the column width, we
844 // set the right width now.
845 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
846 fnRect
.SetHeight(aFrm
, nNew
);
852 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
853 aFrm
.SSize( aNewSize
);
856 if ( getFrameArea().SSize() != aOldSize
)
858 SwPageFrame
*pPage
= FindPageFrame();
861 GetNext()->InvalidatePos_();
862 GetNext()->InvalidatePage( pPage
);
864 if( IsLayoutFrame() )
866 if( IsRightToLeft() )
868 if( static_cast<SwLayoutFrame
*>(this)->Lower() )
869 static_cast<SwLayoutFrame
*>(this)->Lower()->InvalidateSize_();
873 InvalidatePage( pPage
);
876 return getFrameArea().SSize();
879 /** Insert SwFrame into existing structure.
881 * Insertion is done below the parent either before pBehind or
882 * at the end of the chain if pBehind is empty.
884 void SwFrame::InsertBefore( SwLayoutFrame
* pParent
, SwFrame
* pBehind
)
886 OSL_ENSURE( pParent
, "No parent for insert." );
887 OSL_ENSURE( (!pBehind
|| pParent
== pBehind
->GetUpper()),
888 "Frame tree is inconsistent." );
893 { //Insert before pBehind.
894 mpPrev
= pBehind
->mpPrev
;
895 if( nullptr != mpPrev
)
896 mpPrev
->mpNext
= this;
898 mpUpper
->m_pLower
= this;
899 pBehind
->mpPrev
= this;
902 { //Insert at the end, or as first node in the sub tree
903 mpPrev
= mpUpper
->Lower();
906 while( mpPrev
->mpNext
)
907 mpPrev
= mpPrev
->mpNext
;
908 mpPrev
->mpNext
= this;
911 mpUpper
->m_pLower
= this;
915 /** Insert SwFrame into existing structure.
917 * Insertion is done below the parent either after pBehind or
918 * at the beginning of the chain if pBehind is empty.
920 void SwFrame::InsertBehind( SwLayoutFrame
*pParent
, SwFrame
*pBefore
)
922 OSL_ENSURE( (!pBefore
|| pParent
== pBefore
->GetUpper()),
923 "Frame tree is inconsistent." );
929 //Insert after pBefore
930 mpNext
= pBefore
->mpNext
;
931 if ( nullptr != mpNext
)
932 mpNext
->mpPrev
= this;
933 pBefore
->mpNext
= this;
937 assert(pParent
&& "No Parent for Insert.");
938 //Insert at the beginning of the chain
939 mpNext
= pParent
->Lower();
941 mpNext
->mpPrev
= this;
942 pParent
->m_pLower
= this;
946 /** Insert a chain of SwFrames into an existing structure
948 * Currently, this method is used to insert a SectionFrame (which may have some siblings) into an
949 * existing structure. If the third parameter is NULL, this method is (besides handling the
950 * siblings) equal to SwFrame::InsertBefore(..).
952 * If the third parameter is passed, the following happens:
953 * - this becomes mpNext of pParent
954 * - pSct becomes mpNext of the last one in the this-chain
955 * - pBehind is reconnected from pParent to pSct
956 * The purpose is: a SectionFrame (this) won't become a child of another SectionFrame (pParent), but
957 * pParent gets split into two siblings (pParent+pSect) and this is inserted between.
959 bool SwFrame::InsertGroupBefore( SwFrame
* pParent
, SwFrame
* pBehind
, SwFrame
* pSct
)
961 OSL_ENSURE( pParent
, "No parent for insert." );
962 OSL_ENSURE( (!pBehind
|| ( (pBehind
&& (pParent
== pBehind
->GetUpper()))
963 || ((pParent
->IsSctFrame() && pBehind
->GetUpper()->IsColBodyFrame())) ) ),
964 "Frame tree inconsistent." );
967 mpUpper
= pParent
->GetUpper();
968 SwFrame
*pLast
= this;
969 while( pLast
->GetNext() )
971 pLast
= pLast
->GetNext();
972 pLast
->mpUpper
= GetUpper();
976 pLast
->mpNext
= pSct
;
977 pSct
->mpPrev
= pLast
;
978 pSct
->mpNext
= pParent
->GetNext();
982 pLast
->mpNext
= pParent
->GetNext();
983 if( pLast
->GetNext() )
984 pLast
->GetNext()->mpPrev
= pLast
;
986 pParent
->mpNext
= this;
988 if( pSct
->GetNext() )
989 pSct
->GetNext()->mpPrev
= pSct
;
990 while( pLast
->GetNext() )
992 pLast
= pLast
->GetNext();
993 pLast
->mpUpper
= GetUpper();
996 { // Insert before pBehind.
997 if( pBehind
->GetPrev() )
998 pBehind
->GetPrev()->mpNext
= nullptr;
1000 pBehind
->GetUpper()->m_pLower
= nullptr;
1001 pBehind
->mpPrev
= nullptr;
1002 SwLayoutFrame
* pTmp
= static_cast<SwLayoutFrame
*>(pSct
);
1003 SwFrame
* pLower
= pTmp
->Lower();
1006 OSL_ENSURE( pLower
->IsColumnFrame(), "InsertGrp: Used SectionFrame" );
1007 pTmp
= static_cast<SwLayoutFrame
*>(static_cast<SwLayoutFrame
*>(pLower
)->Lower());
1008 OSL_ENSURE( pTmp
, "InsertGrp: Missing ColBody" );
1010 pBehind
->mpUpper
= pTmp
;
1011 pBehind
->GetUpper()->m_pLower
= pBehind
;
1012 pLast
= pBehind
->GetNext();
1015 pLast
->mpUpper
= pBehind
->GetUpper();
1016 pLast
= pLast
->GetNext();
1021 OSL_ENSURE( pSct
->IsSctFrame(), "InsertGroup: For SectionFrames only" );
1022 SwFrame::DestroyFrame(pSct
);
1028 mpUpper
= static_cast<SwLayoutFrame
*>(pParent
);
1029 SwFrame
*pLast
= this;
1030 while( pLast
->GetNext() )
1032 pLast
= pLast
->GetNext();
1033 pLast
->mpUpper
= GetUpper();
1035 pLast
->mpNext
= pBehind
;
1037 { // Insert before pBehind.
1038 mpPrev
= pBehind
->mpPrev
;
1039 if( nullptr != mpPrev
)
1040 mpPrev
->mpNext
= this;
1042 mpUpper
->m_pLower
= this;
1043 pBehind
->mpPrev
= pLast
;
1047 //Insert at the end, or ... the first node in the subtree
1048 mpPrev
= mpUpper
->Lower();
1051 while( mpPrev
->mpNext
)
1052 mpPrev
= mpPrev
->mpNext
;
1053 mpPrev
->mpNext
= this;
1056 mpUpper
->m_pLower
= this;
1062 void SwFrame::RemoveFromLayout()
1064 OSL_ENSURE( mpUpper
, "Remove without upper?" );
1067 // one out of the middle is removed
1068 mpPrev
->mpNext
= mpNext
;
1070 { // the first in a list is removed //TODO
1071 OSL_ENSURE( mpUpper
->m_pLower
== this, "Layout is inconsistent." );
1072 mpUpper
->m_pLower
= mpNext
;
1075 mpNext
->mpPrev
= mpPrev
;
1078 mpNext
= mpPrev
= nullptr;
1082 void SwContentFrame::Paste( SwFrame
* pParent
, SwFrame
* pSibling
)
1084 OSL_ENSURE( pParent
, "No parent for pasting." );
1085 OSL_ENSURE( pParent
->IsLayoutFrame(), "Parent is ContentFrame." );
1086 OSL_ENSURE( pParent
!= this, "I'm the parent." );
1087 OSL_ENSURE( pSibling
!= this, "I'm my own neighbour." );
1088 OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
1089 "I'm still registered somewhere" );
1090 OSL_ENSURE( !pSibling
|| pSibling
->IsFlowFrame(),
1091 "<SwContentFrame::Paste(..)> - sibling not of expected type." );
1093 //Insert in the tree.
1094 InsertBefore( static_cast<SwLayoutFrame
*>(pParent
), pSibling
);
1096 SwPageFrame
*pPage
= FindPageFrame();
1098 InvalidatePage( pPage
);
1102 pPage
->InvalidateSpelling();
1103 pPage
->InvalidateSmartTags();
1104 pPage
->InvalidateAutoCompleteWords();
1105 pPage
->InvalidateWordCount();
1110 SwFrame
* pNxt
= GetNext();
1111 pNxt
->InvalidatePrt_();
1112 pNxt
->InvalidatePos_();
1113 pNxt
->InvalidatePage( pPage
);
1114 if( pNxt
->IsSctFrame() )
1115 pNxt
= static_cast<SwSectionFrame
*>(pNxt
)->ContainsContent();
1116 if( pNxt
&& pNxt
->IsTextFrame() && pNxt
->IsInFootnote() )
1117 pNxt
->Prepare( PrepareHint::FootnoteInvalidation
, nullptr, false );
1120 if ( getFrameArea().Height() )
1121 pParent
->Grow( getFrameArea().Height() );
1123 if ( getFrameArea().Width() != pParent
->getFramePrintArea().Width() )
1124 Prepare( PrepareHint::FixSizeChanged
);
1129 //I'm a direct follower of my master now
1130 static_cast<SwContentFrame
*>(GetPrev())->Prepare( PrepareHint::FollowFollows
);
1133 if ( GetPrev()->getFrameArea().Height() !=
1134 GetPrev()->getFramePrintArea().Height() + GetPrev()->getFramePrintArea().Top() )
1136 // Take the border into account?
1137 GetPrev()->InvalidatePrt_();
1139 // OD 18.02.2003 #104989# - force complete paint of previous frame,
1140 // if frame is inserted at the end of a section frame, in order to
1141 // get subsidiary lines repainted for the section.
1142 if ( pParent
->IsSctFrame() && !GetNext() )
1144 // force complete paint of previous frame, if new inserted frame
1145 // in the section is the last one.
1146 GetPrev()->SetCompletePaint();
1148 GetPrev()->InvalidatePage( pPage
);
1151 if ( IsInFootnote() )
1153 SwFrame
* pFrame
= GetIndPrev();
1154 if( pFrame
&& pFrame
->IsSctFrame() )
1155 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1157 pFrame
->Prepare( PrepareHint::QuoVadis
, nullptr, false );
1160 pFrame
= FindFootnoteFrame()->GetNext();
1161 if( pFrame
&& nullptr != (pFrame
=static_cast<SwLayoutFrame
*>(pFrame
)->ContainsAny()) )
1162 pFrame
->InvalidatePrt_();
1166 InvalidateLineNum_();
1167 SwFrame
*pNxt
= FindNextCnt();
1171 while ( pNxt
&& pNxt
->IsInTab() )
1173 pNxt
= pNxt
->FindTabFrame();
1174 if( nullptr != pNxt
)
1175 pNxt
= pNxt
->FindNextCnt();
1179 pNxt
->InvalidateLineNum_();
1180 if ( pNxt
!= GetNext() )
1181 pNxt
->InvalidatePage();
1185 void SwContentFrame::Cut()
1187 OSL_ENSURE( GetUpper(), "Cut without Upper()." );
1189 SwPageFrame
*pPage
= FindPageFrame();
1190 InvalidatePage( pPage
);
1191 SwFrame
*pFrame
= GetIndPrev();
1194 if( pFrame
->IsSctFrame() )
1195 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1196 if ( pFrame
&& pFrame
->IsContentFrame() )
1198 pFrame
->InvalidatePrt_();
1199 if( IsInFootnote() )
1200 pFrame
->Prepare( PrepareHint::QuoVadis
, nullptr, false );
1202 // #i26250# - invalidate printing area of previous
1204 else if ( pFrame
&& pFrame
->IsTabFrame() )
1206 pFrame
->InvalidatePrt();
1210 SwFrame
*pNxt
= FindNextCnt();
1213 while ( pNxt
&& pNxt
->IsInTab() )
1215 pNxt
= pNxt
->FindTabFrame();
1216 if( nullptr != pNxt
)
1217 pNxt
= pNxt
->FindNextCnt();
1221 pNxt
->InvalidateLineNum_();
1222 if ( pNxt
!= GetNext() )
1223 pNxt
->InvalidatePage();
1227 SwTabFrame
* pMasterTab(nullptr);
1228 pFrame
= GetIndNext();
1231 // The old follow may have calculated a gap to the predecessor which
1232 // now becomes obsolete or different as it becomes the first one itself
1233 pFrame
->InvalidatePrt_();
1234 pFrame
->InvalidatePos_();
1235 pFrame
->InvalidatePage( pPage
);
1236 if( pFrame
->IsSctFrame() )
1238 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1241 pFrame
->InvalidatePrt_();
1242 pFrame
->InvalidatePos_();
1243 pFrame
->InvalidatePage( pPage
);
1246 if( pFrame
&& IsInFootnote() )
1247 pFrame
->Prepare( PrepareHint::ErgoSum
, nullptr, false );
1248 if( IsInSct() && !GetPrev() )
1250 SwSectionFrame
* pSct
= FindSctFrame();
1251 if( !pSct
->IsFollow() )
1253 pSct
->InvalidatePrt_();
1254 pSct
->InvalidatePage( pPage
);
1260 InvalidateNextPos();
1261 //Someone needs to do the retouching: predecessor or upper
1263 if ( nullptr != pFrame
)
1264 { pFrame
->SetRetouche();
1265 pFrame
->Prepare( PrepareHint::WidowsOrphans
);
1266 pFrame
->InvalidatePos_();
1267 pFrame
->InvalidatePage( pPage
);
1269 // If I'm (was) the only ContentFrame in my upper, it has to do the
1270 // retouching. Also, perhaps a page became empty.
1272 { SwRootFrame
*pRoot
= getRootFrame();
1275 pRoot
->SetSuperfluous();
1276 // RemoveSuperfluous can only remove empty pages at the end;
1277 // find if there are pages without content following pPage
1278 // and if so request a call to CheckPageDescs()
1279 SwViewShell
*pSh
= pRoot
->GetCurrShell();
1280 // tdf#152983 pPage is null when called from SwHeadFootFrame ctor
1281 if (pPage
&& pSh
&& pSh
->Imp()->IsAction())
1283 SwPageFrame
const* pNext(pPage
);
1284 while ((pNext
= static_cast<SwPageFrame
const*>(pNext
->GetNext())))
1286 if (!sw::IsPageFrameEmpty(*pNext
) && !pNext
->IsFootnotePage())
1288 pSh
->Imp()->GetLayAction().SetCheckPageNum(pPage
->GetPhyPageNum());
1293 GetUpper()->SetCompletePaint();
1294 GetUpper()->InvalidatePage( pPage
);
1298 SwSectionFrame
* pSct
= FindSctFrame();
1299 if( !pSct
->IsFollow() )
1301 pSct
->InvalidatePrt_();
1302 pSct
->InvalidatePage( pPage
);
1305 // #i52253# The master table should take care
1306 // of removing the follow flow line.
1309 SwTabFrame
* pThisTab
= FindTabFrame();
1310 if (pThisTab
&& pThisTab
->IsFollow())
1312 pMasterTab
= pThisTab
->FindMaster();
1317 //Remove first, then shrink the upper.
1318 SwLayoutFrame
*pUp
= GetUpper();
1322 assert(!pMasterTab
);
1327 && !pMasterTab
->GetFollow()->GetFirstNonHeadlineRow()->ContainsContent())
1328 { // only do this if there's no content in other cells of the row!
1329 pMasterTab
->InvalidatePos_();
1330 pMasterTab
->SetRemoveFollowFlowLinePending(true);
1333 SwSectionFrame
*pSct
= nullptr;
1334 if ( !pUp
->Lower() &&
1335 ( ( pUp
->IsFootnoteFrame() && !pUp
->IsColLocked() ) ||
1338 // We have to consider the case that the section may be "empty"
1339 // except from a temporary empty table frame.
1340 // This can happen due to the new cell split feature.
1341 !pUp
->IsCellFrame() &&
1342 // #126020# - adjust check for empty section
1343 // #130797# - correct fix #126020#
1344 !(pSct
= pUp
->FindSctFrame())->ContainsContent() &&
1345 !pSct
->ContainsAny( true ) ) ) )
1347 if ( pUp
->GetUpper() )
1350 // prevent delete of <ColLocked> footnote frame
1351 if ( pUp
->IsFootnoteFrame() && !pUp
->IsColLocked())
1353 if( pUp
->GetNext() && !pUp
->GetPrev() )
1355 SwFrame
* pTmp
= static_cast<SwLayoutFrame
*>(pUp
->GetNext())->ContainsAny();
1357 pTmp
->InvalidatePrt_();
1359 if (!pUp
->IsDeleteForbidden())
1362 SwFrame::DestroyFrame(pUp
);
1368 if ( pSct
->IsColLocked() || !pSct
->IsInFootnote() ||
1369 ( pUp
->IsFootnoteFrame() && pUp
->IsColLocked() ) )
1371 pSct
->DelEmpty( false );
1372 // If a locked section may not be deleted then at least
1373 // its size became invalid after removing its last
1375 pSct
->InvalidateSize_();
1379 pSct
->DelEmpty( true );
1380 SwFrame::DestroyFrame(pSct
);
1387 SwRectFnSet
aRectFnSet(this);
1388 tools::Long nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
1390 pUp
->Shrink( nFrameHeight
);
1394 void SwLayoutFrame::Paste( SwFrame
* pParent
, SwFrame
* pSibling
)
1396 OSL_ENSURE( pParent
, "No parent for pasting." );
1397 OSL_ENSURE( pParent
->IsLayoutFrame(), "Parent is ContentFrame." );
1398 OSL_ENSURE( pParent
!= this, "I'm the parent oneself." );
1399 OSL_ENSURE( pSibling
!= this, "I'm my own neighbour." );
1400 OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
1401 "I'm still registered somewhere." );
1403 //Insert in the tree.
1404 InsertBefore( static_cast<SwLayoutFrame
*>(pParent
), pSibling
);
1406 // OD 24.10.2002 #103517# - correct setting of variable <fnRect>
1407 // <fnRect> is used for the following:
1408 // (1) To invalidate the frame's size, if its size, which has to be the
1409 // same as its upper/parent, differs from its upper's/parent's.
1410 // (2) To adjust/grow the frame's upper/parent, if it has a dimension in its
1411 // size, which is not determined by its upper/parent.
1412 // Which size is which depends on the frame type and the layout direction
1413 // (vertical or horizontal).
1414 // There are the following cases:
1415 // (A) Header and footer frames both in vertical and in horizontal layout
1416 // have to size the width to the upper/parent. A dimension in the height
1417 // has to cause an adjustment/grow of the upper/parent.
1418 // --> <fnRect> = fnRectHori
1419 // (B) Cell and column frames in vertical layout, the width has to be the
1420 // same as upper/parent and a dimension in height causes adjustment/grow
1421 // of the upper/parent.
1422 // --> <fnRect> = fnRectHori
1423 // in horizontal layout the other way around
1424 // --> <fnRect> = fnRectVert
1425 // (C) Other frames in vertical layout, the height has to be the
1426 // same as upper/parent and a dimension in width causes adjustment/grow
1427 // of the upper/parent.
1428 // --> <fnRect> = fnRectVert
1429 // in horizontal layout the other way around
1430 // --> <fnRect> = fnRectHori
1431 //SwRectFn fnRect = IsVertical() ? fnRectHori : fnRectVert;
1432 bool bVert
, bVertL2R
, bVertL2RB2T
;
1433 if ( IsHeaderFrame() || IsFooterFrame() )
1434 bVert
= bVertL2R
= bVertL2RB2T
= false;
1437 bVert
= (IsCellFrame() || IsColumnFrame()) ? !GetUpper()->IsVertical() : GetUpper()->IsVertical();
1438 bVertL2R
= GetUpper()->IsVertLR();
1439 bVertL2RB2T
= GetUpper()->IsVertLRBT();
1441 SwRectFnSet
fnRect(bVert
, bVertL2R
, bVertL2RB2T
);
1443 if (fnRect
.GetWidth(getFrameArea()) != fnRect
.GetWidth(pParent
->getFramePrintArea()))
1446 const SwPageFrame
*pPage
= FindPageFrame();
1447 InvalidatePage( pPage
);
1448 if( !IsColumnFrame() )
1450 SwFrame
*pFrame
= GetIndNext();
1451 if( nullptr != pFrame
)
1453 pFrame
->InvalidatePos_();
1454 if( IsInFootnote() )
1456 if( pFrame
->IsSctFrame() )
1457 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1459 pFrame
->Prepare( PrepareHint::ErgoSum
, nullptr, false );
1462 if ( IsInFootnote() && nullptr != ( pFrame
= GetIndPrev() ) )
1464 if( pFrame
->IsSctFrame() )
1465 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1467 pFrame
->Prepare( PrepareHint::QuoVadis
, nullptr, false );
1471 if (!fnRect
.GetHeight(getFrameArea()))
1474 // AdjustNeighbourhood is now also called in columns which are not
1475 // placed inside a frame
1476 SwNeighbourAdjust nAdjust
= GetUpper()->IsFootnoteBossFrame() ?
1477 static_cast<SwFootnoteBossFrame
*>(GetUpper())->NeighbourhoodAdjustment()
1478 : SwNeighbourAdjust::GrowShrink
;
1479 SwTwips nGrow
= fnRect
.GetHeight(getFrameArea());
1480 if( SwNeighbourAdjust::OnlyAdjust
== nAdjust
)
1481 AdjustNeighbourhood( nGrow
);
1485 if( SwNeighbourAdjust::AdjustGrow
== nAdjust
)
1486 nReal
= AdjustNeighbourhood( nGrow
);
1488 nReal
+= pParent
->Grow( nGrow
- nReal
);
1489 if( SwNeighbourAdjust::GrowAdjust
== nAdjust
&& nReal
< nGrow
)
1490 AdjustNeighbourhood( nGrow
- nReal
);
1494 void SwLayoutFrame::Cut()
1497 GetNext()->InvalidatePos_();
1499 SwRectFnSet
aRectFnSet(this);
1500 SwTwips nShrink
= aRectFnSet
.GetHeight(getFrameArea());
1502 // Remove first, then shrink upper.
1503 SwLayoutFrame
*pUp
= GetUpper();
1505 // AdjustNeighbourhood is now also called in columns which are not
1506 // placed inside a frame.
1508 // Remove must not be called before an AdjustNeighbourhood, but it has to
1509 // be called before the upper-shrink-call, if the upper-shrink takes care
1511 if ( pUp
&& nShrink
)
1513 if( pUp
->IsFootnoteBossFrame() )
1515 SwNeighbourAdjust nAdjust
= static_cast<SwFootnoteBossFrame
*>(pUp
)->NeighbourhoodAdjustment();
1516 if( SwNeighbourAdjust::OnlyAdjust
== nAdjust
)
1517 AdjustNeighbourhood( -nShrink
);
1521 if( SwNeighbourAdjust::AdjustGrow
== nAdjust
)
1522 nReal
= -AdjustNeighbourhood( -nShrink
);
1523 if( nReal
< nShrink
)
1525 const SwTwips nOldHeight
= aRectFnSet
.GetHeight(getFrameArea());
1527 // seems as if this needs to be forwarded to the SwFrame already here,
1528 // changing to zero seems temporary anyways
1530 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1531 aRectFnSet
.SetHeight( aFrm
, 0 );
1534 nReal
+= pUp
->Shrink( nShrink
- nReal
);
1537 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1538 aRectFnSet
.SetHeight( aFrm
, nOldHeight
);
1542 if( SwNeighbourAdjust::GrowAdjust
== nAdjust
&& nReal
< nShrink
)
1543 AdjustNeighbourhood( nReal
- nShrink
);
1550 pUp
->Shrink( nShrink
);
1556 if( pUp
&& !pUp
->Lower() )
1558 pUp
->SetCompletePaint();
1559 pUp
->InvalidatePage();
1563 SwTwips
SwFrame::Grow(SwTwips nDist
, SwResizeLimitReason
& reason
, bool bTst
, bool bInfo
)
1565 OSL_ENSURE( nDist
>= 0, "Negative growth?" );
1567 PROTOCOL_ENTER( this, bTst
? PROT::GrowTest
: PROT::Grow
, DbgAction::NONE
, &nDist
)
1571 reason
= SwResizeLimitReason::Unspecified
;
1575 return static_cast<SwFlyFrame
*>(this)->Grow_(nDist
, reason
, bTst
);
1577 return static_cast<SwSectionFrame
*>(this)->Grow_(nDist
, reason
, bTst
);
1580 const SwCellFrame
* pThisCell
= static_cast<const SwCellFrame
*>(this);
1581 const SwTabFrame
* pTab
= FindTabFrame();
1584 if ( pTab
->IsVertical() != IsVertical() ||
1585 pThisCell
->GetLayoutRowSpan() < 1 )
1587 reason
= SwResizeLimitReason::FixedSizeFrame
;
1592 SwRectFnSet
aRectFnSet(this);
1594 SwTwips nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
1595 if( nPrtHeight
> 0 && nDist
> (LONG_MAX
- nPrtHeight
) )
1596 nDist
= LONG_MAX
- nPrtHeight
;
1598 const SwTwips nReal
= GrowFrame(nDist
, reason
, bTst
, bInfo
);
1601 nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
1603 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1604 aRectFnSet
.SetHeight( aPrt
, nPrtHeight
+ ( IsContentFrame() ? nDist
: nReal
) );
1609 SwTwips
SwFrame::Shrink( SwTwips nDist
, bool bTst
, bool bInfo
)
1611 OSL_ENSURE( nDist
>= 0, "Negative reduction?" );
1613 PROTOCOL_ENTER( this, bTst
? PROT::ShrinkTest
: PROT::Shrink
, DbgAction::NONE
, &nDist
)
1618 return static_cast<SwFlyFrame
*>(this)->Shrink_( nDist
, bTst
);
1619 else if( IsSctFrame() )
1620 return static_cast<SwSectionFrame
*>(this)->Shrink_( nDist
, bTst
);
1625 const SwCellFrame
* pThisCell
= static_cast<const SwCellFrame
*>(this);
1626 const SwTabFrame
* pTab
= FindTabFrame();
1629 if ( (pTab
&& pTab
->IsVertical() != IsVertical()) ||
1630 pThisCell
->GetLayoutRowSpan() < 1 )
1633 SwRectFnSet
aRectFnSet(this);
1634 SwTwips nReal
= aRectFnSet
.GetHeight(getFrameArea());
1635 ShrinkFrame( nDist
, bTst
, bInfo
);
1636 nReal
-= aRectFnSet
.GetHeight(getFrameArea());
1639 const SwTwips nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
1640 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1641 aRectFnSet
.SetHeight( aPrt
, nPrtHeight
- ( IsContentFrame() ? nDist
: nReal
) );
1649 /** Adjust surrounding neighbourhood after insertion
1651 * A Frame needs "normalization" if it is directly placed below a footnote boss (page/column) and its
1652 * size changes. There is always a frame that takes the maximum possible space (the frame that
1653 * contains the Body text) and zero or more frames which only take the space needed (header/footer
1654 * area, footnote container). If one of these frames changes, the body-text-frame has to grow or
1655 * shrink accordingly, even though it's fixed.
1657 * !! Is it possible to do this in a generic way and not restrict it to the page and a distinct
1658 * frame which takes the maximum space (controlled using the FrameSize attribute)?
1660 * - What if multiple frames taking the maximum space are placed next to each other?
1661 * - How is the maximum space calculated?
1662 * - How small can those frames become?
1664 * In any case, only a certain amount of space is allowed, so we never go below a minimum value for
1665 * the height of the body.
1667 * @param nDiff the value around which the space has to be allocated
1669 SwTwips
SwFrame::AdjustNeighbourhood( SwTwips nDiff
, bool bTst
)
1671 PROTOCOL_ENTER( this, PROT::AdjustN
, DbgAction::NONE
, &nDiff
);
1673 if ( !nDiff
|| !GetUpper()->IsFootnoteBossFrame() ) // only inside pages/columns
1676 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
1677 const bool bBrowse
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
1679 //The (Page-)Body only changes in BrowseMode, but only if it does not
1681 if ( IsPageBodyFrame() && (!bBrowse
||
1682 (static_cast<SwLayoutFrame
*>(this)->Lower() &&
1683 static_cast<SwLayoutFrame
*>(this)->Lower()->IsColumnFrame())) )
1686 //In BrowseView mode the PageFrame can handle some of the requests.
1687 tools::Long nBrowseAdd
= 0;
1688 if ( bBrowse
&& GetUpper()->IsPageFrame() ) // only (Page-)BodyFrames
1690 SwViewShell
*pViewShell
= getRootFrame()->GetCurrShell();
1691 SwLayoutFrame
*pUp
= GetUpper();
1693 const tools::Long nUpPrtBottom
= pUp
->getFrameArea().Height() -
1694 pUp
->getFramePrintArea().Height() - pUp
->getFramePrintArea().Top();
1695 SwRect
aInva( pUp
->getFrameArea() );
1698 aInva
.Pos().setX( pViewShell
->VisArea().Left() );
1699 aInva
.Width( pViewShell
->VisArea().Width() );
1703 nChg
= BROWSE_HEIGHT
- pUp
->getFrameArea().Height();
1704 nChg
= std::min( nDiff
, SwTwips(nChg
) );
1706 if ( !IsBodyFrame() )
1709 if ( !pViewShell
|| pViewShell
->VisArea().Height() >= pUp
->getFrameArea().Height() )
1711 //First minimize Body, it will grow again later.
1712 SwFrame
*pBody
= static_cast<SwFootnoteBossFrame
*>(pUp
)->FindBodyCont();
1713 const tools::Long nTmp
= nChg
- pBody
->getFramePrintArea().Height();
1717 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pBody
);
1718 aFrm
.Height(std::max( tools::Long(0), aFrm
.Height() - nChg
));
1721 pBody
->InvalidatePrt_();
1722 pBody
->InvalidateSize_();
1723 if ( pBody
->GetNext() )
1724 pBody
->GetNext()->InvalidatePos_();
1725 if ( !IsHeaderFrame() )
1726 pBody
->SetCompletePaint();
1728 nChg
= nTmp
<= 0 ? 0 : nTmp
;
1732 const tools::Long nTmp
= nUpPrtBottom
+ 20;
1733 aInva
.Top( aInva
.Bottom() - nTmp
);
1734 aInva
.Height( nChg
+ nTmp
);
1738 //The page can shrink to 0. The first page keeps the same size like
1741 tools::Long nInvaAdd
= 0;
1742 if ( pViewShell
&& !pUp
->GetPrev() &&
1743 pUp
->getFrameArea().Height() + nDiff
< pViewShell
->VisArea().Height() )
1745 // This means that we have to invalidate adequately.
1746 nChg
= pViewShell
->VisArea().Height() - pUp
->getFrameArea().Height();
1747 nInvaAdd
= -(nDiff
- nChg
);
1750 //Invalidate including bottom border.
1751 tools::Long nBorder
= nUpPrtBottom
+ 20;
1753 aInva
.Top( aInva
.Bottom() - (nBorder
+nInvaAdd
) );
1754 if ( !IsBodyFrame() )
1757 if ( !IsHeaderFrame() )
1758 static_cast<SwFootnoteBossFrame
*>(pUp
)->FindBodyCont()->SetCompletePaint();
1760 //Invalidate the page because of the frames. Thereby the page becomes
1761 //the right size again if a frame didn't fit. This only works
1762 //randomly for paragraph bound frames otherwise (NotifyFlys).
1763 pUp
->InvalidateSize();
1767 //Independent from nChg
1768 if ( pViewShell
&& aInva
.HasArea() && pUp
->GetUpper() )
1769 pViewShell
->InvalidateWindows( aInva
);
1771 if ( !bTst
&& nChg
)
1774 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pUp
);
1775 aFrm
.AddHeight(nChg
);
1779 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*pUp
);
1780 aPrt
.AddHeight(nChg
);
1784 pViewShell
->Imp()->SetFirstVisPageInvalid();
1787 GetNext()->InvalidatePos_();
1789 //Trigger a repaint if necessary.
1790 std::unique_ptr
<SvxBrushItem
> aBack(pUp
->GetFormat()->makeBackgroundBrushItem());
1791 const SvxGraphicPosition ePos
= aBack
->GetGraphicPos();
1792 if ( ePos
!= GPOS_NONE
&& ePos
!= GPOS_TILED
)
1793 pViewShell
->InvalidateWindows( pUp
->getFrameArea() );
1795 if ( pUp
->GetUpper() )
1797 if ( pUp
->GetNext() )
1798 pUp
->GetNext()->InvalidatePos();
1800 //Sad but true: during notify on ViewImp a Calc on the page and
1801 //its Lower may be called. The values should not be changed
1802 //because the caller takes care of the adjustment of Frame and
1804 const tools::Long nOldFrameHeight
= getFrameArea().Height();
1805 const tools::Long nOldPrtHeight
= getFramePrintArea().Height();
1806 const bool bOldComplete
= IsCompletePaint();
1808 if ( IsBodyFrame() )
1810 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1811 aPrt
.Height( nOldFrameHeight
);
1814 if ( pUp
->GetUpper() )
1816 static_cast<SwRootFrame
*>(pUp
->GetUpper())->CheckViewLayout( nullptr, nullptr );
1819 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1820 aFrm
.Height( nOldFrameHeight
);
1822 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1823 aPrt
.Height( nOldPrtHeight
);
1825 mbCompletePaint
= bOldComplete
;
1827 if ( !IsBodyFrame() )
1828 pUp
->InvalidateSize_();
1829 InvalidatePage( static_cast<SwPageFrame
*>(pUp
) );
1838 const SwFootnoteBossFrame
*pBoss
= static_cast<SwFootnoteBossFrame
*>(GetUpper());
1842 SwFrame
*pFrame
= nullptr;
1843 SwRectFnSet
aRectFnSet(this);
1849 SwSectionFrame
*pSect
= FindSctFrame();
1850 if( nDiff
> 0 && pSect
->IsEndnAtEnd() && GetNext() &&
1851 GetNext()->IsFootnoteContFrame() )
1853 SwFootnoteContFrame
* pCont
= static_cast<SwFootnoteContFrame
*>(GetNext());
1855 SwFootnoteFrame
* pFootnote
= static_cast<SwFootnoteFrame
*>(pCont
->Lower());
1856 bool bFootnote
= false;
1859 if( !pFootnote
->GetAttr()->GetFootnote().IsEndNote() )
1861 nMinH
+= aRectFnSet
.GetHeight(pFootnote
->getFrameArea());
1864 pFootnote
= static_cast<SwFootnoteFrame
*>(pFootnote
->GetNext());
1867 nMinH
+= aRectFnSet
.GetTop(pCont
->getFramePrintArea());
1868 nReal
= aRectFnSet
.GetHeight(pCont
->getFrameArea()) - nMinH
;
1876 if( !bTst
&& !pSect
->IsColLocked() )
1877 pSect
->InvalidateSize();
1884 const bool bFootnotePage
= pBoss
->IsPageFrame() && static_cast<const SwPageFrame
*>(pBoss
)->IsFootnotePage();
1885 if ( bFootnotePage
&& !IsFootnoteContFrame() )
1886 pFrame
= const_cast<SwFrame
*>(static_cast<SwFrame
const *>(pBoss
->FindFootnoteCont()));
1888 pFrame
= const_cast<SwFrame
*>(static_cast<SwFrame
const *>(pBoss
->FindBodyCont()));
1893 //If not one is found, everything else is solved.
1894 nReal
= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
1897 if( !bFootnotePage
)
1899 //Respect the minimal boundary!
1902 const SwTwips nMax
= pBoss
->GetVarSpace();
1906 if( !IsFootnoteContFrame() && nDiff
> nReal
&&
1907 pFrame
->GetNext() && pFrame
->GetNext()->IsFootnoteContFrame()
1908 && ( pFrame
->GetNext()->IsVertical() == IsVertical() )
1911 //If the Body doesn't return enough, we look for a footnote, if
1912 //there is one, we steal there accordingly.
1913 const SwTwips nAddMax
= aRectFnSet
.GetHeight(pFrame
->GetNext()->getFrameArea());
1914 nAdd
= nDiff
- nReal
;
1915 if ( nAdd
> nAddMax
)
1920 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pFrame
->GetNext());
1921 aRectFnSet
.SetHeight(aFrm
, nAddMax
-nAdd
);
1923 if( aRectFnSet
.IsVert() && !aRectFnSet
.IsVertL2R() )
1925 aFrm
.Pos().AdjustX(nAdd
);
1929 pFrame
->GetNext()->InvalidatePrt();
1931 if ( pFrame
->GetNext()->GetNext() )
1933 pFrame
->GetNext()->GetNext()->InvalidatePos_();
1940 if ( !bTst
&& nReal
)
1942 SwTwips nTmp
= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
1945 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pFrame
);
1946 aRectFnSet
.SetHeight( aFrm
, nTmp
- nReal
);
1948 if( aRectFnSet
.IsVert() && !aRectFnSet
.IsVertL2R() )
1950 aFrm
.Pos().AdjustX(nReal
);
1954 pFrame
->InvalidatePrt();
1956 if ( pFrame
->GetNext() )
1957 pFrame
->GetNext()->InvalidatePos_();
1959 if( nReal
< 0 && pFrame
->IsInSct() )
1961 SwLayoutFrame
* pUp
= pFrame
->GetUpper();
1962 if( pUp
&& nullptr != ( pUp
= pUp
->GetUpper() ) && pUp
->IsSctFrame() &&
1963 !pUp
->IsColLocked() )
1964 pUp
->InvalidateSize();
1966 if( ( IsHeaderFrame() || IsFooterFrame() ) && pBoss
->GetDrawObjs() )
1968 const SwSortedObjs
&rObjs
= *pBoss
->GetDrawObjs();
1969 OSL_ENSURE( pBoss
->IsPageFrame(), "Header/Footer out of page?" );
1970 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
1972 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
1974 OSL_ENSURE( !pFly
->IsFlyInContentFrame(), "FlyInCnt at Page?" );
1975 const SwFormatVertOrient
&rVert
=
1976 pFly
->GetFormat()->GetVertOrient();
1977 // When do we have to invalidate?
1978 // If a frame is aligned on a PageTextArea and the header
1979 // changes a TOP, MIDDLE or NONE aligned frame needs to
1980 // recalculate it's position; if the footer changes a BOTTOM
1981 // or MIDDLE aligned frame needs to recalculate it's
1983 if( ( rVert
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
||
1984 rVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA
) &&
1985 ((IsHeaderFrame() && rVert
.GetVertOrient()!=text::VertOrientation::BOTTOM
) ||
1986 (IsFooterFrame() && rVert
.GetVertOrient()!=text::VertOrientation::NONE
&&
1987 rVert
.GetVertOrient() != text::VertOrientation::TOP
)) )
1989 pFly
->InvalidatePos_();
1990 pFly
->Invalidate_();
1996 return (nBrowseAdd
+ nReal
+ nAdd
);
1999 /** method to perform additional actions on an invalidation (2004-05-19 #i28701#) */
2000 void SwFrame::ActionOnInvalidation( const InvalidationType
)
2002 // default behaviour is to perform no additional action
2005 /** method to determine, if an invalidation is allowed (2004-05-19 #i28701#) */
2006 bool SwFrame::InvalidationAllowed( const InvalidationType
) const
2008 // default behaviour is to allow invalidation
2012 void SwFrame::ImplInvalidateSize()
2014 if ( InvalidationAllowed( INVALID_SIZE
) )
2016 setFrameAreaSizeValid(false);
2019 static_cast<SwFlyFrame
*>(this)->Invalidate_();
2023 // OD 2004-05-19 #i28701#
2024 ActionOnInvalidation( INVALID_SIZE
);
2028 void SwFrame::ImplInvalidatePrt()
2030 if ( InvalidationAllowed( INVALID_PRTAREA
) )
2032 setFramePrintAreaValid(false);
2035 static_cast<SwFlyFrame
*>(this)->Invalidate_();
2039 // OD 2004-05-19 #i28701#
2040 ActionOnInvalidation( INVALID_PRTAREA
);
2044 void SwFrame::ImplInvalidatePos()
2046 if ( !InvalidationAllowed( INVALID_POS
) )
2049 setFrameAreaPositionValid(false);
2053 static_cast<SwFlyFrame
*>(this)->Invalidate_();
2060 // OD 2004-05-19 #i28701#
2061 ActionOnInvalidation( INVALID_POS
);
2064 void SwFrame::ImplInvalidateLineNum()
2066 if ( InvalidationAllowed( INVALID_LINENUM
) )
2068 mbValidLineNum
= false;
2069 OSL_ENSURE( IsTextFrame(), "line numbers are implemented for text only" );
2072 // OD 2004-05-19 #i28701#
2073 ActionOnInvalidation( INVALID_LINENUM
);
2077 void SwFrame::ReinitializeFrameSizeAttrFlags()
2079 const SwFormatFrameSize
&rFormatSize
= GetAttrSet()->GetFrameSize();
2080 if ( SwFrameSize::Variable
== rFormatSize
.GetHeightSizeType() ||
2081 SwFrameSize::Minimum
== rFormatSize
.GetHeightSizeType())
2084 if ( GetType() & (SwFrameType::Header
| SwFrameType::Footer
| SwFrameType::Row
) )
2086 SwFrame
*pFrame
= static_cast<SwLayoutFrame
*>(this)->Lower();
2088 { pFrame
->InvalidateSize_();
2089 pFrame
->InvalidatePrt_();
2090 pFrame
= pFrame
->GetNext();
2092 SwContentFrame
*pCnt
= static_cast<SwLayoutFrame
*>(this)->ContainsContent();
2093 // #i36991# - be save.
2094 // E.g., a row can contain *no* content.
2097 pCnt
->InvalidatePage();
2100 pCnt
->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
2101 pCnt
->InvalidateSize_();
2102 pCnt
= pCnt
->GetNextContentFrame();
2103 } while ( static_cast<SwLayoutFrame
*>(this)->IsAnLower( pCnt
) );
2107 else if ( rFormatSize
.GetHeightSizeType() == SwFrameSize::Fixed
)
2110 ChgSize( Size( rFormatSize
.GetWidth(), getFrameArea().Height()));
2112 ChgSize( Size( getFrameArea().Width(), rFormatSize
.GetHeight()));
2116 void SwFrame::ValidateThisAndAllLowers( const sal_uInt16 nStage
)
2118 // Stage 0: Only validate frames. Do not process any objects.
2119 // Stage 1: Only validate fly frames and all of their contents.
2120 // Stage 2: Validate all.
2122 const bool bOnlyObject
= 1 == nStage
;
2123 const bool bIncludeObjects
= 1 <= nStage
;
2125 if ( !bOnlyObject
|| IsFlyFrame() )
2127 setFrameAreaSizeValid(true);
2128 setFramePrintAreaValid(true);
2129 setFrameAreaPositionValid(true);
2132 if ( bIncludeObjects
)
2134 const SwSortedObjs
* pObjs
= GetDrawObjs();
2137 const size_t nCnt
= pObjs
->size();
2138 for ( size_t i
= 0; i
< nCnt
; ++i
)
2140 SwAnchoredObject
* pAnchObj
= (*pObjs
)[i
];
2141 if ( auto pFlyFrame
= pAnchObj
->DynCastFlyFrame() )
2142 pFlyFrame
->ValidateThisAndAllLowers( 2 );
2143 else if ( auto pAnchoredDrawObj
= dynamic_cast<SwAnchoredDrawObject
*>( pAnchObj
) )
2144 pAnchoredDrawObj
->ValidateThis();
2149 if ( IsLayoutFrame() )
2151 SwFrame
* pLower
= static_cast<SwLayoutFrame
*>(this)->Lower();
2154 pLower
->ValidateThisAndAllLowers( nStage
);
2155 pLower
= pLower
->GetNext();
2160 SwTwips
SwContentFrame::GrowFrame(SwTwips nDist
, SwResizeLimitReason
& reason
, bool bTst
, bool bInfo
)
2162 SwRectFnSet
aRectFnSet(this);
2164 SwTwips nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
2165 if( nFrameHeight
> 0 &&
2166 nDist
> (LONG_MAX
- nFrameHeight
) )
2167 nDist
= LONG_MAX
- nFrameHeight
;
2169 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
2170 const bool bBrowse
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
2171 SwFrameType nTmpType
= SwFrameType::Cell
| SwFrameType::Column
;
2173 nTmpType
|= SwFrameType::Body
;
2174 if( !(GetUpper()->GetType() & nTmpType
) && GetUpper()->HasFixSize() )
2179 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2180 aRectFnSet
.SetHeight( aFrm
, nFrameHeight
+ nDist
);
2182 if( IsVertical() && !IsVertLR() )
2184 aFrm
.Pos().AdjustX( -nDist
);
2190 GetNext()->InvalidatePos();
2192 // #i28701# - Due to the new object positioning the
2193 // frame on the next page/column can flow backward (e.g. it was moved forward
2194 // due to the positioning of its objects ). Thus, invalivate this next frame,
2195 // if document compatibility option 'Consider wrapping style influence on
2196 // object positioning' is ON.
2197 else if ( GetUpper()->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
) )
2199 InvalidateNextPos();
2203 reason
= SwResizeLimitReason::Unspecified
;
2204 else if (GetUpper()->IsBodyFrame() // Page / column body
2205 || (GetUpper()->IsFlyFrame()
2206 && static_cast<SwFlyFrame
*>(GetUpper())->GetNextLink()))
2207 reason
= SwResizeLimitReason::FlowToFollow
;
2209 reason
= SwResizeLimitReason::FixedSizeFrame
;
2213 reason
= SwResizeLimitReason::Unspecified
;
2214 SwTwips nReal
= aRectFnSet
.GetHeight(GetUpper()->getFramePrintArea());
2215 for (SwFrame
* pFrame
= GetUpper()->Lower(); pFrame
&& nReal
> 0; pFrame
= pFrame
->GetNext())
2216 nReal
-= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
2220 //Contents are always resized to the wished value.
2221 tools::Long nOld
= aRectFnSet
.GetHeight(getFrameArea());
2224 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2226 aRectFnSet
.SetHeight( aFrm
, nOld
+ nDist
);
2228 if( IsVertical()&& !IsVertLR() )
2230 aFrm
.Pos().AdjustX( -nDist
);
2234 SwTabFrame
*pTab
= (nOld
&& IsInTab()) ? FindTabFrame() : nullptr;
2237 SwDocShell
* pShell
= pTab
->GetFormat()->GetDoc()->GetDocShell();
2238 if ( pTab
->GetTable()->GetHTMLTableLayout() &&
2239 !pTab
->IsJoinLocked() &&
2240 pShell
&& !pShell
->IsReadOnly() )
2242 pTab
->InvalidatePos();
2243 pTab
->SetResizeHTMLTable();
2248 //Only grow Upper if necessary.
2249 if ( nReal
< nDist
)
2253 if( bTst
|| !GetUpper()->IsFooterFrame() )
2254 nReal
= GetUpper()->Grow(nDist
- std::max(nReal
, SwTwips(0)), reason
, bTst
, bInfo
);
2258 GetUpper()->InvalidateSize();
2267 // #i28701# - Due to the new object positioning the
2268 // frame on the next page/column can flow backward (e.g. it was moved forward
2269 // due to the positioning of its objects ). Thus, invalivate this next frame,
2270 // if document compatibility option 'Consider wrapping style influence on
2271 // object positioning' is ON.
2276 GetNext()->InvalidatePos();
2278 else if ( GetUpper()->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
) )
2280 InvalidateNextPos();
2287 SwTwips
SwContentFrame::ShrinkFrame( SwTwips nDist
, bool bTst
, bool bInfo
)
2289 SwRectFnSet
aRectFnSet(this);
2290 OSL_ENSURE( nDist
>= 0, "nDist < 0" );
2291 OSL_ENSURE( nDist
<= aRectFnSet
.GetHeight(getFrameArea()),
2292 "nDist > than current size." );
2298 nRstHeight
= aRectFnSet
.BottomDist( getFrameArea(), aRectFnSet
.GetPrtBottom(*GetUpper()) );
2301 if( nRstHeight
< 0 )
2303 SwTwips nNextHeight
= 0;
2304 // i#94666 if WIDOW_MAGIC was set as height, nDist is wrong, need
2305 // to take into account all the frames in the section.
2306 if (GetUpper()->IsSctFrame()
2307 && sw::WIDOW_MAGIC
- 20000 - getFrameArea().Top() < nDist
)
2309 SwFrame
*pNxt
= GetNext();
2312 nNextHeight
+= aRectFnSet
.GetHeight(pNxt
->getFrameArea());
2313 pNxt
= pNxt
->GetNext();
2316 nRstHeight
= nDist
+ nRstHeight
- nNextHeight
;
2324 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2325 aRectFnSet
.SetHeight( aFrm
, aRectFnSet
.GetHeight(aFrm
) - nDist
);
2327 if( IsVertical() && !IsVertLR() )
2329 aFrm
.Pos().AdjustX(nDist
);
2334 SwTabFrame
*pTab
= IsInTab() ? FindTabFrame() : nullptr;
2337 SwDocShell
* pShell
= pTab
->GetFormat()->GetDoc()->GetDocShell();
2338 if ( pTab
->GetTable()->GetHTMLTableLayout() &&
2339 !pTab
->IsJoinLocked() &&
2340 pShell
&& !pShell
->IsReadOnly() )
2342 pTab
->InvalidatePos();
2343 pTab
->SetResizeHTMLTable();
2349 if( GetUpper() && nDist
> 0 )
2351 if( bTst
|| !GetUpper()->IsFooterFrame() )
2352 nReal
= GetUpper()->Shrink( nDist
, bTst
, bInfo
);
2357 // #108745# Sorry, dear old footer friend, I'm not gonna invalidate you,
2358 // if there are any objects anchored inside your content, which
2359 // overlap with the shrinking frame.
2360 // This may lead to a footer frame that is too big, but this is better
2362 // #109722# : The fix for #108745# was too strict.
2364 bool bInvalidate
= true;
2365 const SwRect
aRect( getFrameArea() );
2366 const SwPageFrame
* pPage
= FindPageFrame();
2367 const SwSortedObjs
* pSorted
= pPage
? pPage
->GetSortedObjs() : nullptr;
2370 for (SwAnchoredObject
* pAnchoredObj
: *pSorted
)
2372 const SwRect
aBound( pAnchoredObj
->GetObjRectWithSpaces() );
2374 if( aBound
.Left() > aRect
.Right() )
2377 if( aBound
.Overlaps( aRect
) )
2379 const SwFrameFormat
* pFormat
= pAnchoredObj
->GetFrameFormat();
2380 if( css::text::WrapTextMode_THROUGH
!= pFormat
->GetSurround().GetSurround() )
2382 const SwFrame
* pAnchor
= pAnchoredObj
->GetAnchorFrame();
2383 if ( pAnchor
&& pAnchor
->FindFooterOrHeader() == GetUpper() )
2385 bInvalidate
= false;
2394 GetUpper()->InvalidateSize();
2402 //The position of the next Frame changes for sure.
2403 InvalidateNextPos();
2405 //If I don't have a successor I have to do the retouch by myself.
2412 void SwContentFrame::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
2414 if (rHint
.GetId() != SfxHintId::SwLegacyModify
&& rHint
.GetId() != SfxHintId::SwFormatChange
2415 && rHint
.GetId() != SfxHintId::SwAttrSetChange
)
2418 SwContentFrameInvFlags eInvFlags
= SwContentFrameInvFlags::NONE
;
2419 if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
2421 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
2422 UpdateAttr_(pLegacy
->m_pOld
, pLegacy
->m_pNew
, eInvFlags
);
2424 else if (rHint
.GetId() == SfxHintId::SwAttrSetChange
)
2426 auto pChangeHint
= static_cast<const sw::AttrSetChangeHint
*>(&rHint
);
2427 if(pChangeHint
->m_pNew
&& pChangeHint
->m_pOld
)
2429 const SwAttrSetChg
& rOldSetChg
= *pChangeHint
->m_pOld
;
2430 const SwAttrSetChg
& rNewSetChg
= *pChangeHint
->m_pNew
;
2431 SfxItemIter
aOIter(*rOldSetChg
.GetChgSet());
2432 SfxItemIter
aNIter(*rNewSetChg
.GetChgSet());
2433 const SfxPoolItem
* pNItem
= aNIter
.GetCurItem();
2434 const SfxPoolItem
* pOItem
= aOIter
.GetCurItem();
2435 SwAttrSetChg
aOldSet(rOldSetChg
);
2436 SwAttrSetChg
aNewSet(rNewSetChg
);
2439 UpdateAttr_(pOItem
, pNItem
, eInvFlags
, &aOldSet
, &aNewSet
);
2440 pNItem
= aNIter
.NextItem();
2441 pOItem
= aOIter
.NextItem();
2443 if(aOldSet
.Count() || aNewSet
.Count())
2444 SwFrame::SwClientNotify(rMod
, sw::AttrSetChangeHint(&aOldSet
, &aNewSet
));
2447 else // rHint.GetId() == SfxHintId::SwFormatChange
2449 auto pChangeHint
= static_cast<const SwFormatChangeHint
*>(&rHint
);
2450 UpdateAttrForFormatChange(pChangeHint
->m_pOldFormat
, pChangeHint
->m_pNewFormat
, eInvFlags
);
2453 if(eInvFlags
== SwContentFrameInvFlags::NONE
)
2456 SwPageFrame
* pPage
= FindPageFrame();
2457 InvalidatePage(pPage
);
2458 if(eInvFlags
& SwContentFrameInvFlags::SetCompletePaint
)
2460 if(eInvFlags
& SwContentFrameInvFlags::InvalidatePos
)
2462 if(eInvFlags
& SwContentFrameInvFlags::InvalidateSize
)
2464 if(eInvFlags
& (SwContentFrameInvFlags::InvalidateSectPrt
| SwContentFrameInvFlags::SetNextCompletePaint
))
2466 if(IsInSct() && !GetPrev())
2468 SwSectionFrame
* pSect
= FindSctFrame();
2469 if(pSect
->ContainsAny() == this)
2471 pSect
->InvalidatePrt_();
2472 pSect
->InvalidatePage(pPage
);
2477 SwFrame
* pNextFrame
= GetIndNext();
2478 if(pNextFrame
&& eInvFlags
& SwContentFrameInvFlags::InvalidateNextPrt
)
2480 pNextFrame
->InvalidatePrt_();
2481 pNextFrame
->InvalidatePage(pPage
);
2483 if(pNextFrame
&& eInvFlags
& SwContentFrameInvFlags::SetNextCompletePaint
)
2485 pNextFrame
->SetCompletePaint();
2487 if(eInvFlags
& SwContentFrameInvFlags::InvalidatePrevPrt
)
2489 SwFrame
* pPrevFrame
= GetPrev();
2492 pPrevFrame
->InvalidatePrt_();
2493 pPrevFrame
->InvalidatePage(pPage
);
2496 if(eInvFlags
& SwContentFrameInvFlags::InvalidateNextPos
)
2497 InvalidateNextPos();
2500 void SwContentFrame::UpdateAttr_( const SfxPoolItem
* pOld
, const SfxPoolItem
* pNew
,
2501 SwContentFrameInvFlags
&rInvFlags
,
2502 SwAttrSetChg
*pOldSet
, SwAttrSetChg
*pNewSet
)
2505 sal_uInt16 nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
2508 case RES_PAGEDESC
: //attribute changes (on/off)
2509 if ( IsInDocBody() && !IsInTab() )
2511 rInvFlags
|= SwContentFrameInvFlags::InvalidatePos
;
2512 SwPageFrame
*pPage
= FindPageFrame();
2514 CheckPageDescs( pPage
);
2515 if (GetPageDescItem().GetNumOffset())
2516 static_cast<SwRootFrame
*>(pPage
->GetUpper())->SetVirtPageNum( true );
2517 pPage
->GetFormat()->GetDoc()->getIDocumentFieldsAccess().UpdatePageFields(pPage
->getFrameArea().Top());
2523 // OD 2004-02-18 #106629# - correction
2524 // Invalidation of the printing area of next frame, not only
2525 // for footnote content.
2526 if ( !GetIndNext() )
2528 SwFrame
* pNxt
= FindNext();
2531 SwPageFrame
* pPg
= pNxt
->FindPageFrame();
2532 pNxt
->InvalidatePage( pPg
);
2533 pNxt
->InvalidatePrt_();
2534 if( pNxt
->IsSctFrame() )
2536 SwFrame
* pCnt
= static_cast<SwSectionFrame
*>(pNxt
)->ContainsAny();
2539 pCnt
->InvalidatePrt_();
2540 pCnt
->InvalidatePage( pPg
);
2543 pNxt
->SetCompletePaint();
2546 // OD 2004-03-17 #i11860#
2547 if ( GetIndNext() &&
2548 !GetUpper()->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::USE_FORMER_OBJECT_POS
) )
2550 // OD 2004-07-01 #i28701# - use new method <InvalidateObjs(..)>
2551 GetIndNext()->InvalidateObjs();
2553 Prepare( PrepareHint::ULSpaceChanged
); //TextFrame has to correct line spacing.
2554 rInvFlags
|= SwContentFrameInvFlags::SetNextCompletePaint
;
2557 case RES_MARGIN_FIRSTLINE
:
2558 case RES_MARGIN_TEXTLEFT
:
2559 case RES_MARGIN_RIGHT
:
2564 Prepare( PrepareHint::FixSizeChanged
);
2566 SwFrame::SwClientNotify(aMod
, sw::LegacyModifyHint(pOld
, pNew
));
2567 rInvFlags
|= SwContentFrameInvFlags::InvalidateNextPrt
| SwContentFrameInvFlags::InvalidatePrevPrt
;
2572 rInvFlags
|= SwContentFrameInvFlags::InvalidatePos
| SwContentFrameInvFlags::InvalidateNextPos
;
2573 const IDocumentSettingAccess
& rIDSA
= GetUpper()->GetFormat()->getIDocumentSettingAccess();
2574 if( rIDSA
.get(DocumentSettingId::PARA_SPACE_MAX
) ||
2575 rIDSA
.get(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES
) )
2577 rInvFlags
|= SwContentFrameInvFlags::SetCompletePaint
;
2578 SwFrame
* pNxt
= FindNext();
2581 SwPageFrame
* pPg
= pNxt
->FindPageFrame();
2582 pNxt
->InvalidatePage( pPg
);
2583 pNxt
->InvalidatePrt_();
2584 if( pNxt
->IsSctFrame() )
2586 SwFrame
* pCnt
= static_cast<SwSectionFrame
*>(pNxt
)->ContainsAny();
2589 pCnt
->InvalidatePrt_();
2590 pCnt
->InvalidatePage( pPg
);
2593 pNxt
->SetCompletePaint();
2599 // OD 2004-02-26 #i25029#
2600 case RES_PARATR_CONNECT_BORDER
:
2602 rInvFlags
|= SwContentFrameInvFlags::SetCompletePaint
;
2603 if ( IsTextFrame() )
2605 InvalidateNextPrtArea();
2607 if ( !GetIndNext() && IsInTab() && IsInSplitTableRow() )
2609 FindTabFrame()->InvalidateSize();
2614 case RES_PARATR_TABSTOP
:
2615 case RES_CHRATR_SHADOWED
:
2616 case RES_CHRATR_AUTOKERN
:
2617 case RES_CHRATR_UNDERLINE
:
2618 case RES_CHRATR_OVERLINE
:
2619 case RES_CHRATR_KERNING
:
2620 case RES_CHRATR_FONT
:
2621 case RES_CHRATR_FONTSIZE
:
2622 case RES_CHRATR_ESCAPEMENT
:
2623 case RES_CHRATR_CONTOUR
:
2624 case RES_CHRATR_NOHYPHEN
:
2625 case RES_PARATR_NUMRULE
:
2626 rInvFlags
|= SwContentFrameInvFlags::SetCompletePaint
;
2630 rInvFlags
|= SwContentFrameInvFlags::SetCompletePaint
;
2639 if ( pOldSet
|| pNewSet
)
2642 pOldSet
->ClearItem( nWhich
);
2644 pNewSet
->ClearItem( nWhich
);
2649 SwFrame::SwClientNotify(aMod
, sw::LegacyModifyHint(pOld
, pNew
));
2653 void SwContentFrame::UpdateAttrForFormatChange( SwFormat
* pOldFormat
, SwFormat
* pNewFormat
,
2654 SwContentFrameInvFlags
&rInvFlags
)
2656 rInvFlags
= SwContentFrameInvFlags::SetCompletePaint
2657 | SwContentFrameInvFlags::InvalidatePos
2658 | SwContentFrameInvFlags::InvalidateSize
2659 | SwContentFrameInvFlags::InvalidateSectPrt
2660 | SwContentFrameInvFlags::InvalidateNextPrt
2661 | SwContentFrameInvFlags::InvalidatePrevPrt
2662 | SwContentFrameInvFlags::InvalidateNextPos
2663 | SwContentFrameInvFlags::SetNextCompletePaint
;
2665 if ( IsInDocBody() && !IsInTab() )
2667 rInvFlags
|= SwContentFrameInvFlags::InvalidatePos
;
2668 SwPageFrame
*pPage
= FindPageFrame();
2670 CheckPageDescs( pPage
);
2671 if (GetPageDescItem().GetNumOffset())
2672 static_cast<SwRootFrame
*>(pPage
->GetUpper())->SetVirtPageNum( true );
2673 pPage
->GetFormat()->GetDoc()->getIDocumentFieldsAccess().UpdatePageFields(pPage
->getFrameArea().Top());
2677 SwFrame::SwClientNotify(aMod
, SwFormatChangeHint(pOldFormat
, pNewFormat
));
2680 SwLayoutFrame::SwLayoutFrame(SwFrameFormat
*const pFormat
, SwFrame
*const pSib
)
2681 : SwFrame(pFormat
, pSib
)
2684 const SwFormatFrameSize
&rFormatSize
= pFormat
->GetFrameSize();
2685 if ( rFormatSize
.GetHeightSizeType() == SwFrameSize::Fixed
)
2691 SwTwips
SwLayoutFrame::InnerHeight() const
2693 const SwFrame
* pCnt
= Lower();
2697 SwRectFnSet
aRectFnSet(this);
2699 if( pCnt
->IsColumnFrame() || pCnt
->IsCellFrame() )
2703 SwTwips nTmp
= static_cast<const SwLayoutFrame
*>(pCnt
)->InnerHeight();
2704 if( pCnt
->isFramePrintAreaValid() )
2705 nTmp
+= aRectFnSet
.GetHeight(pCnt
->getFrameArea()) -
2706 aRectFnSet
.GetHeight(pCnt
->getFramePrintArea());
2709 pCnt
= pCnt
->GetNext();
2716 nRet
+= aRectFnSet
.GetHeight(pCnt
->getFrameArea());
2717 if( pCnt
->IsContentFrame() && static_cast<const SwTextFrame
*>(pCnt
)->IsUndersized() )
2718 nRet
+= static_cast<const SwTextFrame
*>(pCnt
)->GetParHeight() -
2719 aRectFnSet
.GetHeight(pCnt
->getFramePrintArea());
2720 if( pCnt
->IsLayoutFrame() && !pCnt
->IsTabFrame() )
2721 nRet
+= static_cast<const SwLayoutFrame
*>(pCnt
)->InnerHeight() -
2722 aRectFnSet
.GetHeight(pCnt
->getFramePrintArea());
2723 pCnt
= pCnt
->GetNext();
2730 SwTwips
SwLayoutFrame::GrowFrame(SwTwips nDist
, SwResizeLimitReason
& reason
, bool bTst
, bool bInfo
)
2732 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
2733 const bool bBrowse
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
2734 SwFrameType nTmpType
= SwFrameType::Cell
| SwFrameType::Column
;
2736 nTmpType
|= SwFrameType::Body
;
2737 if( !(GetType() & nTmpType
) && HasFixSize() )
2740 reason
= SwResizeLimitReason::Unspecified
;
2742 reason
= IsBodyFrame() ? SwResizeLimitReason::FlowToFollow
// Page / column body
2743 : SwResizeLimitReason::FixedSizeFrame
;
2747 SwRectFnSet
aRectFnSet(this);
2748 const SwTwips nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
2749 const SwTwips nFramePos
= getFrameArea().Pos().X();
2751 if ( nFrameHeight
> 0 && nDist
> (LONG_MAX
- nFrameHeight
) )
2752 nDist
= LONG_MAX
- nFrameHeight
;
2755 if ( GetUpper() && !IsCellFrame() )
2757 for (SwFrame
* pFrame
= GetUpper()->Lower(); pFrame
; pFrame
= pFrame
->GetNext())
2758 nMin
+= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
2759 nMin
= aRectFnSet
.GetHeight(GetUpper()->getFramePrintArea()) - nMin
;
2764 SwRect
aOldFrame( getFrameArea() );
2765 bool bMoveAccFrame
= false;
2767 bool bChgPos
= IsVertical();
2770 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2771 aRectFnSet
.SetHeight( aFrm
, nFrameHeight
+ nDist
);
2773 if( bChgPos
&& !IsVertLR() )
2775 aFrm
.Pos().AdjustX( -nDist
);
2778 bMoveAccFrame
= true;
2781 reason
= SwResizeLimitReason::Unspecified
;
2782 SwTwips nReal
= nDist
- nMin
;
2786 { // AdjustNeighbourhood now only for the columns (but not in frames)
2787 SwNeighbourAdjust nAdjust
= GetUpper()->IsFootnoteBossFrame() ?
2788 static_cast<SwFootnoteBossFrame
*>(GetUpper())->NeighbourhoodAdjustment()
2789 : SwNeighbourAdjust::GrowShrink
;
2790 if( SwNeighbourAdjust::OnlyAdjust
== nAdjust
)
2791 nReal
= AdjustNeighbourhood( nReal
, bTst
);
2794 if( SwNeighbourAdjust::AdjustGrow
== nAdjust
)
2795 nReal
+= AdjustNeighbourhood( nReal
, bTst
);
2800 SwFrame
* pToGrow
= GetUpper();
2802 // A cell with a row span of > 1 is allowed to grow the
2803 // line containing the end of the row span if it is
2804 // located in the same table frame:
2807 const SwCellFrame
* pThisCell
= static_cast<const SwCellFrame
*>(this);
2808 if ( pThisCell
->GetLayoutRowSpan() > 1 )
2810 SwCellFrame
& rEndCell
= const_cast<SwCellFrame
&>(pThisCell
->FindStartEndOfRowSpanCell( false ));
2811 if ( -1 == rEndCell
.GetTabBox()->getRowSpan() )
2812 pToGrow
= rEndCell
.GetUpper();
2816 reason
= SwResizeLimitReason::FlowToFollow
;
2820 nGrow
= pToGrow
? pToGrow
->Grow(nReal
, reason
, bTst
, bInfo
) : 0;
2823 if( SwNeighbourAdjust::GrowAdjust
== nAdjust
&& nGrow
< nReal
)
2824 nReal
= o3tl::saturating_add(nReal
, AdjustNeighbourhood( nReal
- nGrow
, bTst
));
2826 if ( IsFootnoteFrame() && (nGrow
!= nReal
) && GetNext() )
2828 //Footnotes can replace their successor.
2829 SwTwips nSpace
= bTst
? 0 : -nDist
;
2830 if (const SwFrame
*pFrame
= GetUpper()->Lower())
2833 { nSpace
+= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
2834 pFrame
= pFrame
->GetNext();
2835 } while ( pFrame
!= GetNext() );
2837 nSpace
= aRectFnSet
.GetHeight(GetUpper()->getFramePrintArea()) -nSpace
;
2841 if ( nReal
> nSpace
)
2843 if ( nReal
&& !bTst
)
2844 static_cast<SwFootnoteFrame
*>(this)->InvalidateNxtFootnoteCnts( FindPageFrame() );
2860 if( nReal
!= nDist
&&
2862 ( !IsCellFrame() || static_cast<SwCellFrame
*>(this)->GetLayoutRowSpan() > 1 ) )
2864 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2865 aRectFnSet
.SetHeight( aFrm
, nFrameHeight
+ nReal
);
2867 if( bChgPos
&& !IsVertLR() )
2869 aFrm
.Pos().setX( nFramePos
- nReal
);
2872 bMoveAccFrame
= true;
2877 SwPageFrame
*pPage
= FindPageFrame();
2880 SwFrame
* pNext
= GetNext();
2883 pNext
->InvalidatePos_();
2884 if (pNext
->IsRowFrame())
2885 { // also invalidate first cell
2886 static_cast<SwLayoutFrame
*>(pNext
)->Lower()->InvalidatePos_();
2888 else if (pNext
->IsContentFrame())
2890 pNext
->InvalidatePage(pPage
);
2892 if (pNext
->HasFixSize())
2893 { // continue to invalidate because growing pNext won't do it!
2894 pNext
= pNext
->GetNext();
2903 if ( !IsPageBodyFrame() )
2906 InvalidatePage( pPage
);
2908 if (!(GetType() & (SwFrameType::Row
|SwFrameType::Tab
|SwFrameType::FtnCont
|SwFrameType::Page
|SwFrameType::Root
)))
2912 InvaPercentLowers( nReal
);
2914 std::unique_ptr
<SvxBrushItem
> aBack(GetFormat()->makeBackgroundBrushItem());
2915 const SvxGraphicPosition ePos
= aBack
->GetGraphicPos();
2916 if ( GPOS_NONE
!= ePos
&& GPOS_TILED
!= ePos
)
2921 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2922 if( bMoveAccFrame
&& IsAccessibleFrame() )
2924 SwRootFrame
*pRootFrame
= getRootFrame();
2925 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
2926 pRootFrame
->GetCurrShell() )
2928 pRootFrame
->GetCurrShell()->Imp()->MoveAccessibleFrame( this, aOldFrame
);
2932 (void)bMoveAccFrame
;
2936 if (reason
== SwResizeLimitReason::Unspecified
&& nReal
< nDist
&& IsBodyFrame()) // Page / column body
2937 reason
= SwResizeLimitReason::FlowToFollow
;
2942 SwTwips
SwLayoutFrame::ShrinkFrame( SwTwips nDist
, bool bTst
, bool bInfo
)
2944 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
2945 const bool bBrowse
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
2946 SwFrameType nTmpType
= SwFrameType::Cell
| SwFrameType::Column
;
2948 nTmpType
|= SwFrameType::Body
;
2950 if (pSh
&& pSh
->GetViewOptions()->IsWhitespaceHidden())
2954 // Whitespace is hidden and this body frame will not shrink, as it
2956 // Invalidate the page frame size, so in case the reason for the
2957 // shrink was that there is more whitespace on this page, the size
2958 // without whitespace will be recalculated correctly.
2959 SwPageFrame
* pPageFrame
= FindPageFrame();
2960 pPageFrame
->InvalidateSize();
2964 if( !(GetType() & nTmpType
) && HasFixSize() )
2967 OSL_ENSURE( nDist
>= 0, "nDist < 0" );
2968 SwRectFnSet
aRectFnSet(this);
2969 SwTwips nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
2970 if ( nDist
> nFrameHeight
)
2971 nDist
= nFrameHeight
;
2974 bool bChgPos
= IsVertical();
2975 if (const SwFrame
*pFrame
= Lower())
2977 if( !pFrame
->IsNeighbourFrame() )
2979 const tools::Long nTmp
= aRectFnSet
.GetHeight(getFramePrintArea());
2980 while( pFrame
&& nMin
< nTmp
)
2981 { nMin
+= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
2982 pFrame
= pFrame
->GetNext();
2986 SwTwips nReal
= nDist
;
2987 SwTwips nMinDiff
= aRectFnSet
.GetHeight(getFramePrintArea()) - nMin
;
2988 if( nReal
> nMinDiff
)
2993 SwRect
aOldFrame( getFrameArea() );
2994 bool bMoveAccFrame
= false;
2996 SwTwips nRealDist
= nReal
;
2999 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
3000 aRectFnSet
.SetHeight( aFrm
, nFrameHeight
- nReal
);
3002 if( bChgPos
&& !IsVertLR() )
3004 aFrm
.Pos().AdjustX(nReal
);
3007 bMoveAccFrame
= true;
3010 SwNeighbourAdjust nAdjust
= GetUpper() && GetUpper()->IsFootnoteBossFrame() ?
3011 static_cast<SwFootnoteBossFrame
*>(GetUpper())->NeighbourhoodAdjustment()
3012 : SwNeighbourAdjust::GrowShrink
;
3014 // AdjustNeighbourhood also in columns (but not in frames)
3015 if( SwNeighbourAdjust::OnlyAdjust
== nAdjust
)
3017 if ( IsPageBodyFrame() && !bBrowse
)
3020 { nReal
= AdjustNeighbourhood( -nReal
, bTst
);
3022 if ( !bTst
&& IsBodyFrame() && nReal
< nRealDist
)
3024 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
3025 aRectFnSet
.SetHeight( aFrm
, aRectFnSet
.GetHeight(aFrm
) + nRealDist
- nReal
);
3027 if( bChgPos
&& !IsVertLR() )
3029 aFrm
.Pos().AdjustX(nRealDist
- nReal
);
3032 OSL_ENSURE( !IsAccessibleFrame(), "bMoveAccFrame has to be set!" );
3036 else if( IsColumnFrame() || IsColBodyFrame() )
3038 SwTwips nTmp
= GetUpper()->Shrink( nReal
, bTst
, bInfo
);
3039 if ( nTmp
!= nReal
)
3041 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
3042 aRectFnSet
.SetHeight( aFrm
, aRectFnSet
.GetHeight(aFrm
) + nReal
- nTmp
);
3044 if( bChgPos
&& !IsVertLR() )
3046 aFrm
.Pos().AdjustX(nTmp
- nReal
);
3049 OSL_ENSURE( !IsAccessibleFrame(), "bMoveAccFrame has to be set!" );
3055 SwTwips nShrink
= nReal
;
3056 SwFrame
* pToShrink
= GetUpper();
3058 if ( IsCellFrame() )
3060 const SwCellFrame
* pThisCell
= static_cast<const SwCellFrame
*>(this);
3061 if ( pThisCell
->GetLayoutRowSpan() > 1 )
3063 SwCellFrame
& rEndCell
= const_cast<SwCellFrame
&>(pThisCell
->FindStartEndOfRowSpanCell( false ));
3064 pToShrink
= rEndCell
.GetUpper();
3068 // A table frame may have grown beyond its parent frame after
3069 // RemoveFollowFlowLine(), which is a problem in case the parent is a
3070 // section: prevent shrinking the section smaller than the contained
3073 && static_cast<SwTabFrame
*>(this)->IsRebuildLastLine()
3074 && pToShrink
== GetUpper()
3075 && pToShrink
->IsSctFrame()) // not required for page body, unsure about others
3077 SwTwips nUpperMin
{0};
3078 for (SwFrame
const* pFrame
= pToShrink
->GetLower();
3079 pFrame
!= GetNext(); pFrame
= pFrame
->GetNext())
3081 nUpperMin
+= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
3083 if (aRectFnSet
.GetHeight(pToShrink
->getFramePrintArea()) - nShrink
< nUpperMin
)
3085 nShrink
= aRectFnSet
.GetHeight(pToShrink
->getFramePrintArea()) - nUpperMin
;
3088 return 0; // nothing to do
3092 nReal
= pToShrink
? pToShrink
->Shrink( nShrink
, bTst
, bInfo
) : 0;
3093 if( ( SwNeighbourAdjust::GrowAdjust
== nAdjust
|| SwNeighbourAdjust::AdjustGrow
== nAdjust
)
3094 && nReal
< nShrink
)
3095 AdjustNeighbourhood( nReal
- nShrink
);
3098 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
3099 if( bMoveAccFrame
&& IsAccessibleFrame() )
3101 SwRootFrame
*pRootFrame
= getRootFrame();
3102 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
3103 pRootFrame
->GetCurrShell() )
3105 pRootFrame
->GetCurrShell()->Imp()->MoveAccessibleFrame( this, aOldFrame
);
3110 (void)bMoveAccFrame
;
3113 if ( !bTst
&& (IsCellFrame() || IsColumnFrame() ? nReal
: nRealDist
) )
3115 SwPageFrame
*pPage
= FindPageFrame();
3118 GetNext()->InvalidatePos_();
3119 if ( GetNext()->IsContentFrame() )
3120 GetNext()->InvalidatePage( pPage
);
3122 static_cast<SwTabFrame
*>(this)->SetComplete();
3125 { if ( IsRetoucheFrame() )
3129 static_cast<SwTabFrame
*>(this)->SetComplete();
3130 if ( Lower() ) // Can also be in the Join and be empty!
3131 InvalidateNextPos();
3134 if ( !IsBodyFrame() )
3137 InvalidatePage( pPage
);
3138 bool bCompletePaint
= true;
3139 const SwFrameFormat
* pFormat
= GetFormat();
3142 std::unique_ptr
<SvxBrushItem
> aBack(pFormat
->makeBackgroundBrushItem());
3143 const SvxGraphicPosition ePos
= aBack
->GetGraphicPos();
3144 if ( GPOS_NONE
== ePos
|| GPOS_TILED
== ePos
)
3145 bCompletePaint
= false;
3151 if (!(GetType() & (SwFrameType::Row
|SwFrameType::Tab
|SwFrameType::FtnCont
|SwFrameType::Page
|SwFrameType::Root
)))
3155 InvaPercentLowers( nReal
);
3157 SwContentFrame
*pCnt
;
3158 if( IsFootnoteFrame() && !static_cast<SwFootnoteFrame
*>(this)->GetAttr()->GetFootnote().IsEndNote() &&
3159 ( GetFormat()->GetDoc()->GetFootnoteInfo().m_ePos
!= FTNPOS_CHAPTER
||
3160 ( IsInSct() && FindSctFrame()->IsFootnoteAtEnd() ) ) &&
3161 nullptr != (pCnt
= static_cast<SwFootnoteFrame
*>(this)->GetRefFromAttr() ) )
3163 if ( pCnt
->IsFollow() )
3164 { // If we are in another column/page than the frame with the
3165 // reference, we don't need to invalidate its master.
3166 SwFrame
*pTmp
= pCnt
->FindFootnoteBossFrame(true) == FindFootnoteBossFrame(true)
3167 ? &pCnt
->FindMaster()->GetFrame() : pCnt
;
3168 pTmp
->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
3169 pTmp
->InvalidateSize();
3173 if (pCnt
->FindPageFrame() == FindPageFrame())
3175 pCnt
->InvalidatePos();
3179 SAL_WARN("sw.layout", "footnote frame on different page than ref frame?");
3188 * Changes the size of the directly subsidiary Frame's that have a fixed size, proportionally to the
3189 * size change of the PrtArea of the Frame's.
3191 * The variable Frames are also proportionally adapted; they will grow/shrink again by themselves.
3193 void SwLayoutFrame::ChgLowersProp( const Size
& rOldSize
)
3195 // no change of lower properties for root frame or if no lower exists.
3196 if ( IsRootFrame() || !Lower() )
3199 // declare and init <SwFrame* pLowerFrame> with first lower
3200 SwFrame
*pLowerFrame
= Lower();
3202 // declare and init const booleans <bHeightChgd> and <bWidthChg>
3203 const bool bHeightChgd
= rOldSize
.Height() != getFramePrintArea().Height();
3204 const bool bWidthChgd
= rOldSize
.Width() != getFramePrintArea().Width();
3206 SwRectFnSet
aRectFnSet(this);
3208 // This shortcut basically tries to handle only lower frames that
3209 // are affected by the size change. Otherwise much more lower frames
3211 if ( !( aRectFnSet
.IsVert() ? bHeightChgd
: bWidthChgd
) &&
3212 ! Lower()->IsColumnFrame() &&
3213 ( ( IsBodyFrame() && IsInDocBody() && ( !IsInSct() || !FindSctFrame()->IsColLocked() ) ) ||
3214 // #i10826# Section frames without columns should not
3215 // invalidate all lowers!
3218 // Determine page frame the body frame resp. the section frame belongs to.
3219 SwPageFrame
*pPage
= FindPageFrame();
3220 // Determine last lower by traveling through them using <GetNext()>.
3221 // During travel check each section frame, if it will be sized to
3222 // maximum. If Yes, invalidate size of section frame and set
3223 // corresponding flags at the page.
3226 if( pLowerFrame
->IsSctFrame() && static_cast<SwSectionFrame
*>(pLowerFrame
)->ToMaximize_() )
3228 pLowerFrame
->InvalidateSize_();
3229 pLowerFrame
->InvalidatePage( pPage
);
3231 if( pLowerFrame
->GetNext() )
3232 pLowerFrame
= pLowerFrame
->GetNext();
3236 // If found last lower is a section frame containing no section
3237 // (section frame isn't valid and will be deleted in the future),
3238 // travel backwards.
3239 while( pLowerFrame
->IsSctFrame() && !static_cast<SwSectionFrame
*>(pLowerFrame
)->GetSection() &&
3240 pLowerFrame
->GetPrev() )
3241 pLowerFrame
= pLowerFrame
->GetPrev();
3242 // If found last lower is a section frame, set <pLowerFrame> to its last
3243 // content, if the section frame is valid and is not sized to maximum.
3244 // Otherwise set <pLowerFrame> to NULL - In this case body frame only
3245 // contains invalid section frames.
3246 if( pLowerFrame
->IsSctFrame() )
3247 pLowerFrame
= static_cast<SwSectionFrame
*>(pLowerFrame
)->GetSection() &&
3248 !static_cast<SwSectionFrame
*>(pLowerFrame
)->ToMaximize( false ) ?
3249 static_cast<SwSectionFrame
*>(pLowerFrame
)->FindLastContent() : nullptr;
3251 // continue with found last lower, probably the last content of a section
3254 // If <pLowerFrame> is in a table frame, set <pLowerFrame> to this table
3255 // frame and continue.
3256 if ( pLowerFrame
->IsInTab() )
3258 // OD 28.10.2002 #97265# - safeguard for setting <pLowerFrame> to
3259 // its table frame - check, if the table frame is also a lower
3260 // of the body frame, in order to assure that <pLowerFrame> is not
3261 // set to a frame, which is an *upper* of the body frame.
3262 SwFrame
* pTableFrame
= pLowerFrame
->FindTabFrame();
3263 if ( IsAnLower( pTableFrame
) )
3265 pLowerFrame
= pTableFrame
;
3268 // Check, if variable size of body frame resp. section frame has grown
3269 // OD 28.10.2002 #97265# - correct check, if variable size has grown.
3270 SwTwips nOldHeight
= aRectFnSet
.IsVert() ? rOldSize
.Width() : rOldSize
.Height();
3271 if( nOldHeight
< aRectFnSet
.GetHeight(getFramePrintArea()) )
3273 // If variable size of body|section frame has grown, only found
3274 // last lower and the position of the its next have to be invalidated.
3275 pLowerFrame
->InvalidateAll_();
3276 pLowerFrame
->InvalidatePage( pPage
);
3277 if( !pLowerFrame
->IsFlowFrame() ||
3278 !SwFlowFrame::CastFlowFrame( pLowerFrame
)->HasFollow() )
3279 pLowerFrame
->InvalidateNextPos( true );
3280 if ( pLowerFrame
->IsTextFrame() )
3281 static_cast<SwContentFrame
*>(pLowerFrame
)->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
3285 SwFrame
const* pFirstInvalid(nullptr);
3286 for (SwFrame
const* pLow
= Lower();
3287 pLow
&& pLow
!= pLowerFrame
; pLow
= pLow
->GetNext())
3289 if (!pLow
->isFrameAreaDefinitionValid())
3291 pFirstInvalid
= pLow
;
3295 // variable size of body|section frame has shrunk. Thus,
3296 // invalidate all lowers not matching the new body|section size
3297 // and the dedicated new last lower.
3298 if( aRectFnSet
.IsVert() )
3300 SwTwips nBot
= getFrameArea().Left() + getFramePrintArea().Left();
3301 while (pLowerFrame
&& pLowerFrame
->GetPrev()
3302 && (pFirstInvalid
!= nullptr // tdf#152307 trust nothing after invalid frame
3303 || pLowerFrame
->getFrameArea().Left() < nBot
))
3305 pLowerFrame
->InvalidateAll_();
3306 pLowerFrame
->InvalidatePage( pPage
);
3307 if (pLowerFrame
== pFirstInvalid
)
3309 pFirstInvalid
= nullptr; // continue checking nBot
3311 pLowerFrame
= pLowerFrame
->GetPrev();
3316 SwTwips nBot
= getFrameArea().Top() + getFramePrintArea().Bottom();
3317 while (pLowerFrame
&& pLowerFrame
->GetPrev()
3318 && (pFirstInvalid
!= nullptr // tdf#152307 trust nothing after invalid frame
3319 || nBot
< pLowerFrame
->getFrameArea().Top()))
3321 pLowerFrame
->InvalidateAll_();
3322 pLowerFrame
->InvalidatePage( pPage
);
3323 if (pLowerFrame
== pFirstInvalid
)
3325 pFirstInvalid
= nullptr; // continue checking nBot
3327 pLowerFrame
= pLowerFrame
->GetPrev();
3332 pLowerFrame
->InvalidateSize_();
3333 pLowerFrame
->InvalidatePage( pPage
);
3334 if ( pLowerFrame
->IsTextFrame() )
3335 static_cast<SwContentFrame
*>(pLowerFrame
)->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
3338 // #i41694# - improvement by removing duplicates
3341 if ( pLowerFrame
->IsInSct() )
3343 // #i41694# - follow-up of issue #i10826#
3344 // No invalidation of section frame, if it's the this.
3345 SwFrame
* pSectFrame
= pLowerFrame
->FindSctFrame();
3346 if( pSectFrame
!= this && IsAnLower( pSectFrame
) )
3348 pSectFrame
->InvalidateSize_();
3349 pSectFrame
->InvalidatePage( pPage
);
3355 } // end of { special case }
3357 // Invalidate page for content only once.
3358 bool bInvaPageForContent
= true;
3360 // Declare booleans <bFixChgd> and <bVarChgd>, indicating for text frame
3361 // adjustment, if fixed/variable size has changed.
3362 bool bFixChgd
, bVarChgd
;
3363 if( aRectFnSet
.IsVert() == pLowerFrame
->IsNeighbourFrame() )
3365 bFixChgd
= bWidthChgd
;
3366 bVarChgd
= bHeightChgd
;
3370 bFixChgd
= bHeightChgd
;
3371 bVarChgd
= bWidthChgd
;
3374 // Declare const unsigned short <nFixWidth> and init it this frame types
3375 // which has fixed width in vertical respectively horizontal layout.
3376 // In vertical layout these are neighbour frames (cell and column frames),
3377 // header frames and footer frames.
3378 // In horizontal layout these are all frames, which aren't neighbour frames.
3379 const SwFrameType nFixWidth
= aRectFnSet
.IsVert() ? (FRM_NEIGHBOUR
| FRM_HEADFOOT
)
3380 : ~SwFrameType(FRM_NEIGHBOUR
);
3382 // Declare const unsigned short <nFixHeight> and init it this frame types
3383 // which has fixed height in vertical respectively horizontal layout.
3384 // In vertical layout these are all frames, which aren't neighbour frames,
3385 // header frames, footer frames, body frames or foot note container frames.
3386 // In horizontal layout these are neighbour frames.
3387 const SwFrameType nFixHeight
= aRectFnSet
.IsVert() ? ~SwFrameType(FRM_NEIGHBOUR
| FRM_HEADFOOT
| FRM_BODYFTNC
)
3390 // Travel through all lowers using <GetNext()>
3391 while ( pLowerFrame
)
3393 if ( pLowerFrame
->IsTextFrame() )
3395 // Text frames will only be invalidated - prepare invalidation
3397 static_cast<SwContentFrame
*>(pLowerFrame
)->Prepare( PrepareHint::FixSizeChanged
);
3399 static_cast<SwContentFrame
*>(pLowerFrame
)->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
3403 // If lower isn't a table, row, cell or section frame, adjust its
3405 const SwFrameType nLowerType
= pLowerFrame
->GetType();
3406 if ( !(nLowerType
& (SwFrameType::Tab
|SwFrameType::Row
|SwFrameType::Cell
|SwFrameType::Section
)) )
3410 if( nLowerType
& nFixWidth
)
3412 // Considering previous conditions:
3413 // In vertical layout set width of column, header and
3414 // footer frames to its upper width.
3415 // In horizontal layout set width of header, footer,
3416 // foot note container, foot note, body and no-text
3417 // frames to its upper width.
3418 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3419 aFrm
.Width( getFramePrintArea().Width() );
3421 else if( rOldSize
.Width() && !pLowerFrame
->IsFootnoteFrame() )
3423 // Adjust frame width proportional, if lower isn't a
3424 // foot note frame and condition <nLowerType & nFixWidth>
3426 // Considering previous conditions:
3427 // In vertical layout these are foot note container,
3428 // body and no-text frames.
3429 // In horizontal layout these are column and no-text frames.
3430 // OD 24.10.2002 #97265# - <double> calculation
3431 // Perform <double> calculation of new width, if
3432 // one of the coefficients is greater than 50000
3434 if ( (pLowerFrame
->getFrameArea().Width() > 50000) ||
3435 (getFramePrintArea().Width() > 50000) )
3437 double nNewWidthTmp
=
3438 ( double(pLowerFrame
->getFrameArea().Width())
3439 * double(getFramePrintArea().Width()) )
3440 / double(rOldSize
.Width());
3441 nNewWidth
= SwTwips(nNewWidthTmp
);
3446 (pLowerFrame
->getFrameArea().Width() * getFramePrintArea().Width()) / rOldSize
.Width();
3449 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3450 aFrm
.Width( nNewWidth
);
3455 if( nLowerType
& nFixHeight
)
3457 // Considering previous conditions:
3458 // In vertical layout set height of foot note and
3459 // no-text frames to its upper height.
3460 // In horizontal layout set height of column frames
3461 // to its upper height.
3462 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3463 aFrm
.Height( getFramePrintArea().Height() );
3465 // OD 01.10.2002 #102211#
3466 // add conditions <!pLowerFrame->IsHeaderFrame()> and
3467 // <!pLowerFrame->IsFooterFrame()> in order to avoid that
3468 // the <Grow> of header or footer are overwritten.
3469 // NOTE: Height of header/footer frame is determined by contents.
3470 else if ( rOldSize
.Height() &&
3471 !pLowerFrame
->IsFootnoteFrame() &&
3472 !pLowerFrame
->IsHeaderFrame() &&
3473 !pLowerFrame
->IsFooterFrame()
3476 // Adjust frame height proportional, if lower isn't a
3477 // foot note, a header or a footer frame and
3478 // condition <nLowerType & nFixHeight> isn't true.
3479 // Considering previous conditions:
3480 // In vertical layout these are column, foot note container,
3481 // body and no-text frames.
3482 // In horizontal layout these are column, foot note
3483 // container, body and no-text frames.
3485 // OD 29.10.2002 #97265# - special case for page lowers
3486 // The page lowers that have to be adjusted on page height
3487 // change are the body frame and the foot note container
3489 // In vertical layout the height of both is directly
3490 // adjusted to the page height change.
3491 // In horizontal layout the height of the body frame is
3492 // directly adjusted to the page height change and the
3493 // foot note frame height isn't touched, because its
3494 // determined by its content.
3495 // OD 31.03.2003 #108446# - apply special case for page
3496 // lowers - see description above - also for section columns.
3497 if ( IsPageFrame() ||
3498 ( IsColumnFrame() && IsInSct() )
3501 OSL_ENSURE( pLowerFrame
->IsBodyFrame() || pLowerFrame
->IsFootnoteContFrame(),
3502 "ChgLowersProp - only for body or foot note container" );
3503 if ( pLowerFrame
->IsBodyFrame() || pLowerFrame
->IsFootnoteContFrame() )
3505 if ( IsVertical() || pLowerFrame
->IsBodyFrame() )
3507 SwTwips nNewHeight
=
3508 pLowerFrame
->getFrameArea().Height() +
3509 ( getFramePrintArea().Height() - rOldSize
.Height() );
3510 if ( nNewHeight
< 0)
3512 // OD 01.04.2003 #108446# - adjust assertion condition and text
3513 OSL_ENSURE( !( IsPageFrame() &&
3514 (pLowerFrame
->getFrameArea().Height()>0) &&
3515 (pLowerFrame
->isFrameAreaDefinitionValid()) ),
3516 "ChgLowersProg - negative height for lower.");
3520 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3521 aFrm
.Height( nNewHeight
);
3528 // OD 24.10.2002 #97265# - <double> calculation
3529 // Perform <double> calculation of new height, if
3530 // one of the coefficients is greater than 50000
3531 if ( (pLowerFrame
->getFrameArea().Height() > 50000) ||
3532 (getFramePrintArea().Height() > 50000) )
3534 double nNewHeightTmp
=
3535 ( double(pLowerFrame
->getFrameArea().Height())
3536 * double(getFramePrintArea().Height()) )
3537 / double(rOldSize
.Height());
3538 nNewHeight
= SwTwips(nNewHeightTmp
);
3542 nNewHeight
= ( pLowerFrame
->getFrameArea().Height()
3543 * getFramePrintArea().Height() ) / rOldSize
.Height();
3545 if( !pLowerFrame
->GetNext() )
3547 SwTwips nSum
= getFramePrintArea().Height();
3548 SwFrame
* pTmp
= Lower();
3549 while( pTmp
->GetNext() )
3551 if( !pTmp
->IsFootnoteContFrame() || !pTmp
->IsVertical() )
3552 nSum
-= pTmp
->getFrameArea().Height();
3553 pTmp
= pTmp
->GetNext();
3555 if( nSum
- nNewHeight
== 1 &&
3556 nSum
== pLowerFrame
->getFrameArea().Height() )
3560 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3561 aFrm
.Height( nNewHeight
);
3566 } // end of else { NOT text frame }
3568 pLowerFrame
->InvalidateAll_();
3569 if ( bInvaPageForContent
&& pLowerFrame
->IsContentFrame() )
3571 pLowerFrame
->InvalidatePage();
3572 bInvaPageForContent
= false;
3575 if ( !pLowerFrame
->GetNext() && pLowerFrame
->IsRetoucheFrame() )
3577 //If a growth took place and the subordinate elements can retouch
3578 //itself (currently Tabs, Sections and Content) we trigger it.
3579 if ( rOldSize
.Height() < getFramePrintArea().SSize().Height() ||
3580 rOldSize
.Width() < getFramePrintArea().SSize().Width() )
3581 pLowerFrame
->SetRetouche();
3583 pLowerFrame
= pLowerFrame
->GetNext();
3586 // Finally adjust the columns if width is set to auto
3587 // Possible optimization: execute this code earlier in this function and
3589 if ( !(( (aRectFnSet
.IsVert() && bHeightChgd
) || (! aRectFnSet
.IsVert() && bWidthChgd
) ) &&
3590 Lower()->IsColumnFrame()) )
3593 // get column attribute
3594 const SwFormatCol
* pColAttr
= nullptr;
3595 if ( IsPageBodyFrame() )
3597 OSL_ENSURE( GetUpper()->IsPageFrame(), "Upper is not page frame" );
3598 pColAttr
= &GetUpper()->GetFormat()->GetCol();
3602 OSL_ENSURE( IsFlyFrame() || IsSctFrame(), "Columns not in fly or section" );
3603 pColAttr
= &GetFormat()->GetCol();
3606 if ( pColAttr
->IsOrtho() && pColAttr
->GetNumCols() > 1 )
3607 AdjustColumns( pColAttr
, false );
3610 /** "Formats" the Frame; Frame and PrtArea.
3612 * The Fixsize is not set here.
3614 void SwLayoutFrame::Format( vcl::RenderContext
* /*pRenderContext*/, const SwBorderAttrs
*pAttrs
)
3616 OSL_ENSURE( pAttrs
, "LayoutFrame::Format, pAttrs is 0." );
3618 if ( isFramePrintAreaValid() && isFrameAreaSizeValid() )
3621 bool bHideWhitespace
= false;
3624 SwViewShell
* pShell
= getRootFrame()->GetCurrShell();
3625 if (pShell
&& pShell
->GetViewOptions()->IsWhitespaceHidden())
3627 // This is needed so that no space is reserved for the margin on
3628 // the last page of the document. Other pages would have no margin
3629 // set even without this, as their frame height is the content
3631 bHideWhitespace
= true;
3635 const sal_uInt16 nLeft
= o3tl::narrowing
<sal_uInt16
>(pAttrs
->CalcLeft(this));
3636 const sal_uInt16 nUpper
= bHideWhitespace
? 0 : pAttrs
->CalcTop();
3638 const sal_uInt16 nRight
= o3tl::narrowing
<sal_uInt16
>(pAttrs
->CalcRight(this));
3639 const sal_uInt16 nLower
= bHideWhitespace
? 0 : pAttrs
->CalcBottom();
3641 SwRectFnSet
fnRect(IsVertical() && !IsPageFrame(), IsVertLR(), IsVertLRBT());
3642 if ( !isFramePrintAreaValid() )
3644 setFramePrintAreaValid(true);
3645 fnRect
.SetXMargins(*this, nLeft
, nRight
);
3646 fnRect
.SetYMargins(*this, nUpper
, nLower
);
3649 if ( isFrameAreaSizeValid() )
3652 if ( !HasFixSize() )
3654 const SwTwips nBorder
= nUpper
+ nLower
;
3655 const SwFormatFrameSize
&rSz
= GetFormat()->GetFrameSize();
3656 SwTwips nMinHeight
= rSz
.GetHeightSizeType() == SwFrameSize::Minimum
? rSz
.GetHeight() : 0;
3659 setFrameAreaSizeValid(true);
3661 //The size in VarSize is calculated using the content plus the
3663 SwTwips nRemaining
= 0;
3664 SwFrame
*pFrame
= Lower();
3666 { nRemaining
+= fnRect
.GetHeight(pFrame
->getFrameArea());
3667 if( pFrame
->IsTextFrame() && static_cast<SwTextFrame
*>(pFrame
)->IsUndersized() )
3668 // This TextFrame would like to be a bit bigger
3669 nRemaining
+= static_cast<SwTextFrame
*>(pFrame
)->GetParHeight()
3670 - fnRect
.GetHeight(pFrame
->getFramePrintArea());
3671 else if( pFrame
->IsSctFrame() && static_cast<SwSectionFrame
*>(pFrame
)->IsUndersized() )
3672 nRemaining
+= static_cast<SwSectionFrame
*>(pFrame
)->Undersize();
3673 pFrame
= pFrame
->GetNext();
3675 nRemaining
+= nBorder
;
3676 nRemaining
= std::max( nRemaining
, nMinHeight
);
3677 const SwTwips nDiff
= nRemaining
- fnRect
.GetHeight(getFrameArea());
3678 const tools::Long nOldLeft
= fnRect
.GetLeft(getFrameArea());
3679 const tools::Long nOldTop
= fnRect
.GetTop(getFrameArea());
3686 //Updates the positions using the fast channel.
3689 //Don't exceed the bottom edge of the Upper.
3690 if (GetUpper() && fnRect
.GetHeight(getFrameArea()))
3692 const SwTwips nLimit
= fnRect
.GetPrtBottom(*GetUpper());
3693 if( fnRect
.SetLimit(*this, nLimit
) &&
3694 nOldLeft
== fnRect
.GetLeft(getFrameArea()) &&
3695 nOldTop
== fnRect
.GetTop(getFrameArea()) )
3697 setFrameAreaSizeValid(true);
3698 setFramePrintAreaValid(true);
3701 } while ( !isFrameAreaSizeValid() );
3703 else if (GetType() & FRM_HEADFOOT
)
3706 { if ( getFrameArea().Height() != pAttrs
->GetSize().Height() )
3708 ChgSize( Size( getFrameArea().Width(), pAttrs
->GetSize().Height()));
3711 setFrameAreaSizeValid(true);
3713 } while ( !isFrameAreaSizeValid() );
3717 setFrameAreaSizeValid(true);
3720 // While updating the size, PrtArea might be invalidated.
3721 if (!isFramePrintAreaValid())
3723 setFramePrintAreaValid(true);
3724 fnRect
.SetXMargins(*this, nLeft
, nRight
);
3725 fnRect
.SetYMargins(*this, nUpper
, nLower
);
3729 static void InvaPercentFlys( SwFrame
*pFrame
, SwTwips nDiff
)
3731 OSL_ENSURE( pFrame
->GetDrawObjs(), "Can't find any Objects" );
3732 for (SwAnchoredObject
* pAnchoredObj
: *pFrame
->GetDrawObjs())
3734 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
3736 const SwFormatFrameSize
&rSz
= pFly
->GetFormat()->GetFrameSize();
3737 if ( rSz
.GetWidthPercent() || rSz
.GetHeightPercent() )
3739 bool bNotify
= true;
3740 // If we've a fly with more than 90% relative height...
3741 if( rSz
.GetHeightPercent() > 90 && pFly
->GetAnchorFrame() &&
3742 rSz
.GetHeightPercent() != SwFormatFrameSize::SYNCED
&& nDiff
)
3744 const SwFrame
*pRel
= pFly
->IsFlyLayFrame() ? pFly
->GetAnchorFrame():
3745 pFly
->GetAnchorFrame()->GetUpper();
3746 // ... and we have already more than 90% height and we
3747 // not allow the text to go through...
3748 // then a notification could cause an endless loop, e.g.
3749 // 100% height and no text wrap inside a cell of a table.
3750 if( pFly
->getFrameArea().Height()*10 >
3751 ( nDiff
+ pRel
->getFramePrintArea().Height() )*9 &&
3752 pFly
->GetFormat()->GetSurround().GetSurround() !=
3753 css::text::WrapTextMode_THROUGH
)
3757 pFly
->InvalidateSize();
3763 void SwLayoutFrame::InvaPercentLowers( SwTwips nDiff
)
3765 if ( GetDrawObjs() )
3766 ::InvaPercentFlys( this, nDiff
);
3768 SwFrame
*pFrame
= ContainsContent();
3774 if ( pFrame
->IsInTab() && !IsTabFrame() )
3776 SwFrame
*pTmp
= pFrame
->FindTabFrame();
3777 OSL_ENSURE( pTmp
, "Where's my TabFrame?" );
3778 if( IsAnLower( pTmp
) )
3782 if ( pFrame
->IsTabFrame() )
3784 const SwFormatFrameSize
&rSz
= static_cast<SwLayoutFrame
*>(pFrame
)->GetFormat()->GetFrameSize();
3785 if ( rSz
.GetWidthPercent() || rSz
.GetHeightPercent() )
3786 pFrame
->InvalidatePrt();
3788 else if ( pFrame
->GetDrawObjs() )
3789 ::InvaPercentFlys( pFrame
, nDiff
);
3790 pFrame
= pFrame
->FindNextCnt();
3791 } while ( pFrame
&& IsAnLower( pFrame
) ) ;
3794 tools::Long
SwLayoutFrame::CalcRel( const SwFormatFrameSize
&rSz
) const
3796 tools::Long nRet
= rSz
.GetWidth(),
3797 nPercent
= rSz
.GetWidthPercent();
3801 const SwFrame
*pRel
= GetUpper();
3802 tools::Long nRel
= LONG_MAX
;
3803 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
3804 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
3805 if( pRel
->IsPageBodyFrame() && pSh
&& bBrowseMode
&& pSh
->VisArea().Width() )
3807 nRel
= pSh
->GetBrowseWidth();
3808 tools::Long nDiff
= nRel
- pRel
->getFramePrintArea().Width();
3812 nRel
= std::min( nRel
, pRel
->getFramePrintArea().Width() );
3813 nRet
= nRel
* nPercent
/ 100;
3818 // Local helpers for SwLayoutFrame::FormatWidthCols()
3820 static tools::Long
lcl_CalcMinColDiff( SwLayoutFrame
*pLayFrame
)
3822 tools::Long nDiff
= 0, nFirstDiff
= 0;
3823 SwLayoutFrame
*pCol
= static_cast<SwLayoutFrame
*>(pLayFrame
->Lower());
3824 OSL_ENSURE( pCol
, "Where's the columnframe?" );
3825 SwFrame
*pFrame
= pCol
->Lower();
3828 if( pFrame
&& pFrame
->IsBodyFrame() )
3829 pFrame
= static_cast<SwBodyFrame
*>(pFrame
)->Lower();
3830 if ( pFrame
&& pFrame
->IsTextFrame() )
3832 const tools::Long nTmp
= static_cast<SwTextFrame
*>(pFrame
)->FirstLineHeight();
3833 if (nTmp
!= std::numeric_limits
<SwTwips
>::max())
3835 if ( pCol
== pLayFrame
->Lower() )
3838 nDiff
= nDiff
? std::min( nDiff
, nTmp
) : nTmp
;
3841 //Skip empty columns!
3842 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
3843 while ( pCol
&& nullptr == (pFrame
= pCol
->Lower()) )
3844 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
3846 } while ( pFrame
&& pCol
);
3848 return nDiff
? nDiff
: nFirstDiff
? nFirstDiff
: 240;
3851 static bool lcl_IsFlyHeightClipped( SwLayoutFrame
*pLay
)
3853 SwFrame
*pFrame
= pLay
->ContainsContent();
3856 if ( pFrame
->IsInTab() )
3857 pFrame
= pFrame
->FindTabFrame();
3859 if ( pFrame
->GetDrawObjs() )
3861 const size_t nCnt
= pFrame
->GetDrawObjs()->size();
3862 for ( size_t i
= 0; i
< nCnt
; ++i
)
3864 SwAnchoredObject
* pAnchoredObj
= (*pFrame
->GetDrawObjs())[i
];
3865 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
3867 if ( pFly
->IsHeightClipped() &&
3868 ( !pFly
->IsFlyFreeFrame() || pFly
->GetPageFrame() ) )
3873 pFrame
= pFrame
->FindNextCnt();
3878 void SwLayoutFrame::FormatWidthCols( const SwBorderAttrs
&rAttrs
,
3879 const SwTwips nBorder
, const SwTwips nMinHeight
)
3881 //If there are columns involved, the size is adjusted using the last column.
3882 //1. Format content.
3883 //2. Calculate height of the last column: if it's too big, the Fly has to
3884 // grow. The amount by which the Fly grows is not the amount of the
3885 // overhang because we have to act on the assumption that some text flows
3886 // back which will generate some more space.
3887 // The amount which we grow by equals the overhang
3888 // divided by the amount of columns or the overhang itself if it's smaller
3889 // than the amount of columns.
3890 //3. Go back to 1. until everything is stable.
3892 const SwFormatCol
&rCol
= rAttrs
.GetAttrSet().GetCol();
3893 const sal_uInt16 nNumCols
= rCol
.GetNumCols();
3896 bool bBackLock
= false;
3897 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
3898 SwViewShellImp
*pImp
= pSh
? pSh
->Imp() : nullptr;
3899 vcl::RenderContext
* pRenderContext
= pSh
? pSh
->GetOut() : nullptr;
3901 // Underlying algorithm
3902 // We try to find the optimal height for the column.
3903 // nMinimum starts with the passed minimum height and is then maintained
3904 // as the maximum height on which column content did not fit into a
3906 // nMaximum starts with LONG_MAX and is then maintained as the minimum
3907 // height on which the content fit into the columns.
3908 // In column based sections nMaximum starts at the maximum value which
3909 // the environment defines, this can certainly be a value on which
3910 // content doesn't fit.
3911 // The columns are formatted. If content still juts out, nMinimum is
3912 // adjusted accordingly, then we grow, at least by nMinDiff but not
3913 // over a certain nMaximum. If no content juts out but there is still
3914 // some space left in a column, shrinking is done accordingly, at
3915 // least by nMinDiff but not below the nMinimum.
3916 // Cancel as soon as no content juts out and the difference from minimum
3917 // to maximum is less than nMinDiff or the maximum which was defined by
3918 // the environment is reached and some content still doesn't fit.
3920 // Criticism of this implementation
3921 // 1. Theoretically situations are possible in which the content fits in
3922 // a lower height but not in a higher height. To ensure that the code
3923 // handles such situations the code contains a few checks concerning
3924 // minimum and maximum which probably are never triggered.
3925 // 2. We use the same nMinDiff for shrinking and growing, but nMinDiff
3926 // is more or less the smallest first line height and doesn't seem ideal
3927 // as minimum value for shrinking.
3929 tools::Long nMinimum
= nMinHeight
;
3930 tools::Long nMaximum
;
3931 bool bNoBalance
= false;
3932 SwRectFnSet
aRectFnSet(this);
3935 nMaximum
= aRectFnSet
.GetHeight(getFrameArea()) - nBorder
+
3936 aRectFnSet
.BottomDist(getFrameArea(), aRectFnSet
.GetPrtBottom(*GetUpper()));
3937 nMaximum
+= GetUpper()->Grow( LONG_MAX
, true );
3938 if( nMaximum
< nMinimum
)
3941 nMinimum
= nMaximum
= 0;
3943 nMinimum
= nMaximum
;
3945 if( nMaximum
> BROWSE_HEIGHT
)
3946 nMaximum
= BROWSE_HEIGHT
;
3948 bNoBalance
= static_cast<SwSectionFrame
*>(this)->GetSection()->GetFormat()->
3949 GetBalancedColumns().GetValue();
3950 SwFrame
* pAny
= ContainsAny();
3952 ( !aRectFnSet
.GetHeight(getFrameArea()) && pAny
) )
3954 tools::Long nTop
= aRectFnSet
.GetTopMargin(*this);
3955 // #i23129# - correction
3956 // to the calculated maximum height.
3958 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
3959 aRectFnSet
.AddBottom( aFrm
, nMaximum
- aRectFnSet
.GetHeight(getFrameArea()) );
3962 if( nTop
> nMaximum
)
3964 aRectFnSet
.SetYMargins( *this, nTop
, 0 );
3966 if( !pAny
&& !static_cast<SwSectionFrame
*>(this)->IsFootnoteLock() )
3968 SwFootnoteContFrame
* pFootnoteCont
= static_cast<SwSectionFrame
*>(this)->ContainsFootnoteCont();
3971 SwFrame
* pFootnoteAny
= pFootnoteCont
->ContainsAny();
3972 if( pFootnoteAny
&& pFootnoteAny
->isFrameAreaDefinitionValid() )
3975 static_cast<SwSectionFrame
*>(this)->SetFootnoteLock( true );
3981 nMaximum
= LONG_MAX
;
3983 // #i3317# - reset temporarily consideration
3984 // of wrapping style influence
3985 SwPageFrame
* pPageFrame
= FindPageFrame();
3986 SwSortedObjs
* pObjs
= pPageFrame
? pPageFrame
->GetSortedObjs() : nullptr;
3989 for (SwAnchoredObject
* pAnchoredObj
: *pObjs
)
3991 if ( IsAnLower( pAnchoredObj
->GetAnchorFrame() ) )
3993 pAnchoredObj
->SetTmpConsiderWrapInfluence( false );
3999 //Could take a while therefore check for Waitcrsr here.
4001 pImp
->CheckWaitCursor();
4003 setFrameAreaSizeValid(true);
4004 //First format the column, before using lots of stack space here.
4005 //Also set width and height of the column (if they are wrong)
4006 //while we are at it.
4007 SwLayoutFrame
*pCol
= static_cast<SwLayoutFrame
*>(Lower());
4010 // Simply setting the column width based on the values returned by
4011 // CalcColWidth does not work for automatic column width.
4012 AdjustColumns( &rCol
, false );
4014 for ( sal_uInt16 i
= 0; i
< nNumCols
; ++i
)
4016 pCol
->Calc(pRenderContext
);
4017 // ColumnFrames have a BodyFrame now, which needs to be calculated
4018 pCol
->Lower()->Calc(pRenderContext
);
4019 if( pCol
->Lower()->GetNext() )
4020 pCol
->Lower()->GetNext()->Calc(pRenderContext
); // SwFootnoteCont
4021 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
4024 ::CalcContent( this );
4026 pCol
= static_cast<SwLayoutFrame
*>(Lower());
4027 OSL_ENSURE( pCol
&& pCol
->GetNext(), ":-( column making holidays?");
4028 // set bMinDiff if no empty columns exist
4029 bool bMinDiff
= true;
4030 // OD 28.03.2003 #108446# - check for all column content and all columns
4031 while ( bMinDiff
&& pCol
)
4033 bMinDiff
= nullptr != pCol
->ContainsContent();
4034 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
4036 pCol
= static_cast<SwLayoutFrame
*>(Lower());
4039 SwTwips nMaxFree
= 0;
4040 SwTwips nAllFree
= LONG_MAX
;
4041 // set bFoundLower if there is at least one non-empty column
4042 bool bFoundLower
= false;
4045 SwLayoutFrame
* pLay
= static_cast<SwLayoutFrame
*>(pCol
->Lower());
4046 SwTwips nInnerHeight
= aRectFnSet
.GetHeight(pLay
->getFrameArea()) -
4047 aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
4051 nInnerHeight
+= pLay
->InnerHeight();
4053 else if( nInnerHeight
< 0 )
4056 if( pLay
->GetNext() )
4059 pLay
= static_cast<SwLayoutFrame
*>(pLay
->GetNext());
4060 OSL_ENSURE( pLay
->IsFootnoteContFrame(),"FootnoteContainer expected" );
4061 nInnerHeight
+= pLay
->InnerHeight();
4062 nInnerHeight
+= aRectFnSet
.GetHeight(pLay
->getFrameArea()) -
4063 aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
4065 nInnerHeight
-= aRectFnSet
.GetHeight(pCol
->getFramePrintArea());
4066 if( nInnerHeight
> nDiff
)
4068 nDiff
= nInnerHeight
;
4073 if( nMaxFree
< -nInnerHeight
)
4074 nMaxFree
= -nInnerHeight
;
4075 if( nAllFree
> -nInnerHeight
)
4076 nAllFree
= -nInnerHeight
;
4078 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
4081 if ( bFoundLower
|| ( IsSctFrame() && static_cast<SwSectionFrame
*>(this)->HasFollow() ) )
4083 SwTwips nMinDiff
= ::lcl_CalcMinColDiff( this );
4084 // Here we decide if growing is needed - this is the case, if
4085 // column content (nDiff) or a Fly juts over.
4086 // In sections with columns we take into account to set the size
4087 // when having a non-empty Follow.
4088 if ( nDiff
|| ::lcl_IsFlyHeightClipped( this ) ||
4089 ( IsSctFrame() && static_cast<SwSectionFrame
*>(this)->CalcMinDiff( nMinDiff
) ) )
4091 tools::Long nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
4092 // The minimum must not be smaller than our PrtHeight as
4093 // long as something juts over.
4094 if( nMinimum
< nPrtHeight
)
4095 nMinimum
= nPrtHeight
;
4096 // The maximum must not be smaller than PrtHeight if
4097 // something still juts over.
4098 if( nMaximum
< nPrtHeight
)
4099 nMaximum
= nPrtHeight
; // Robust, but will this ever happen?
4100 if( !nDiff
) // If only Flys jut over, we grow by nMinDiff
4102 // If we should grow more than by nMinDiff we split it over
4104 if ( std::abs(nDiff
- nMinDiff
) > nNumCols
&& nDiff
> static_cast<tools::Long
>(nNumCols
) )
4108 { // If no empty column exists, we want to grow at least
4109 // by nMinDiff. Special case: If we are smaller than the
4110 // minimal FrameHeight and PrtHeight is smaller than
4111 // nMindiff we grow in a way that PrtHeight is exactly
4112 // nMinDiff afterwards.
4113 tools::Long nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
4114 if ( nFrameHeight
> nMinHeight
|| nPrtHeight
>= nMinDiff
)
4115 nDiff
= std::max( nDiff
, nMinDiff
);
4116 else if( nDiff
< nMinDiff
)
4117 nDiff
= nMinDiff
- nPrtHeight
+ 1;
4119 // nMaximum is a size in which the content fit or the
4120 // requested value from the environment, therefore we don't
4121 // should not exceed this value.
4122 if( nDiff
+ nPrtHeight
> nMaximum
)
4123 nDiff
= nMaximum
- nPrtHeight
;
4125 else if (nMaximum
> nMinimum
) // We fit, do we still have some opportunity to shrink?
4127 tools::Long nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
4128 if ( nMaximum
< nPrtHeight
)
4129 nDiff
= nMaximum
- nPrtHeight
; // We grew over a working
4130 // height and shrink back to it, but will this ever
4133 { // We have a new maximum, a size where the content fits.
4134 nMaximum
= nPrtHeight
;
4135 // If the extra space in the column is bigger than
4136 // nMinDiff, we shrink a bit, unless size would drop
4137 // below the minimum.
4139 // #i23129# - <nMinDiff> can be
4140 // big, because of an object at the beginning of
4141 // a column. Thus, decrease optimization here.
4142 //nMaxFree >= nMinDiff &&
4145 nMinimum
< nPrtHeight
- nMinDiff
) )
4147 nMaxFree
/= nNumCols
; // disperse over the columns
4148 nDiff
= nMaxFree
< nMinDiff
? -nMinDiff
: -nMaxFree
; // min nMinDiff
4149 if( nPrtHeight
+ nDiff
<= nMinimum
) // below the minimum?
4150 nDiff
= ( nMinimum
- nMaximum
) / 2; // Take the center
4155 if( nPrtHeight
+ nDiff
<= nMinimum
) // Less than minimum?
4156 nDiff
= ( nMinimum
- nMaximum
) / 2; // Take the center
4160 if( nDiff
) // now we shrink or grow...
4162 Size
aOldSz( getFramePrintArea().SSize() );
4163 tools::Long nTop
= aRectFnSet
.GetTopMargin(*this);
4164 nDiff
= aRectFnSet
.GetHeight(getFramePrintArea()) + nDiff
+ nBorder
- aRectFnSet
.GetHeight(getFrameArea());
4167 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
4168 aRectFnSet
.AddBottom( aFrm
, nDiff
);
4172 SwFlyFrame
*pFlyFrame
= IsFlyFrame() ? static_cast<SwFlyFrame
*>(this) : nullptr;
4175 pFlyFrame
->InvalidateObjRectWithSpaces();
4177 aRectFnSet
.SetYMargins( *this, nTop
, nBorder
- nTop
);
4178 ChgLowersProp( aOldSz
);
4181 // #i3317# - reset temporarily consideration
4182 // of wrapping style influence
4183 SwPageFrame
* pTmpPageFrame
= FindPageFrame();
4184 SwSortedObjs
* pTmpObjs
= pTmpPageFrame
? pTmpPageFrame
->GetSortedObjs() : nullptr;
4187 for (SwAnchoredObject
* pAnchoredObj
: *pTmpObjs
)
4189 if ( IsAnLower( pAnchoredObj
->GetAnchorFrame() ) )
4191 pAnchoredObj
->SetTmpConsiderWrapInfluence( false );
4195 //Invalidate suitable to nicely balance the Frames.
4196 //- Every first lower starting from the second column gets a
4198 pCol
= static_cast<SwLayoutFrame
*>(Lower()->GetNext());
4201 SwFrame
*pLow
= pCol
->Lower();
4203 pLow
->InvalidatePos_();
4204 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
4206 if( IsSctFrame() && static_cast<SwSectionFrame
*>(this)->HasFollow() )
4208 // If we created a Follow, we need to give its content
4209 // the opportunity to flow back inside the CalcContent
4210 SwContentFrame
* pTmpContent
=
4211 static_cast<SwSectionFrame
*>(this)->GetFollow()->ContainsContent();
4213 pTmpContent
->InvalidatePos_();
4222 } while ( !bEnd
|| !isFrameAreaSizeValid() );
4224 // OD 01.04.2003 #108446# - Don't collect endnotes for sections. Thus, set
4225 // 2nd parameter to <true>.
4226 ::CalcContent( this, true );
4229 // OD 14.03.2003 #i11760# - adjust 2nd parameter - sal_True --> true
4230 setFrameAreaSizeValid(true);
4231 ::CalcContent( this, true );
4233 static_cast<SwSectionFrame
*>(this)->SetFootnoteLock( false );
4237 void SwLayoutFrame::dumpAsXmlAttributes(xmlTextWriterPtr writer
) const
4239 SwFrame::dumpAsXmlAttributes(writer
);
4241 const SwFrameFormat
* pFormat
= GetFormat();
4244 (void)xmlTextWriterWriteFormatAttribute( writer
, BAD_CAST( "format" ), "%p", pFormat
);
4245 (void)xmlTextWriterWriteFormatAttribute( writer
, BAD_CAST( "formatName" ), "%s", BAD_CAST(pFormat
->GetName().toUtf8().getStr()));
4249 static SwContentFrame
* lcl_InvalidateSection( SwFrame
*pCnt
, SwInvalidateFlags nInv
)
4251 SwSectionFrame
* pSect
= pCnt
->FindSctFrame();
4252 // If our ContentFrame is placed inside a table or a footnote, only sections
4253 // which are also placed inside are meant.
4254 // Exception: If a table is directly passed.
4255 if( ( ( pCnt
->IsInTab() && !pSect
->IsInTab() ) ||
4256 ( pCnt
->IsInFootnote() && !pSect
->IsInFootnote() ) ) && !pCnt
->IsTabFrame() )
4258 if( nInv
& SwInvalidateFlags::Size
)
4259 pSect
->InvalidateSize_();
4260 if( nInv
& SwInvalidateFlags::Pos
)
4261 pSect
->InvalidatePos_();
4262 if( nInv
& SwInvalidateFlags::PrtArea
)
4263 pSect
->InvalidatePrt_();
4264 SwFlowFrame
*pFoll
= pSect
->GetFollow();
4265 // Temporary separation from follow
4266 pSect
->SetFollow( nullptr );
4267 SwContentFrame
* pRet
= pSect
->FindLastContent();
4268 pSect
->SetFollow( pFoll
);
4272 static SwContentFrame
* lcl_InvalidateTable( SwTabFrame
*pTable
, SwInvalidateFlags nInv
)
4274 if( ( nInv
& SwInvalidateFlags::Section
) && pTable
->IsInSct() )
4275 lcl_InvalidateSection( pTable
, nInv
);
4276 if( nInv
& SwInvalidateFlags::Size
)
4277 pTable
->InvalidateSize_();
4278 if( nInv
& SwInvalidateFlags::Pos
)
4279 pTable
->InvalidatePos_();
4280 if( nInv
& SwInvalidateFlags::PrtArea
)
4281 pTable
->InvalidatePrt_();
4282 return pTable
->FindLastContent();
4285 static void lcl_InvalidateAllContent( SwContentFrame
*pCnt
, SwInvalidateFlags nInv
);
4287 static void lcl_InvalidateContent( SwContentFrame
*pCnt
, SwInvalidateFlags nInv
)
4289 SwContentFrame
*pLastTabCnt
= nullptr;
4290 SwContentFrame
*pLastSctCnt
= nullptr;
4293 if( nInv
& SwInvalidateFlags::Section
)
4295 if( pCnt
->IsInSct() )
4297 // See above at tables
4299 pLastSctCnt
= lcl_InvalidateSection( pCnt
, nInv
);
4300 if( pLastSctCnt
== pCnt
)
4301 pLastSctCnt
= nullptr;
4303 #if OSL_DEBUG_LEVEL > 0
4305 OSL_ENSURE( !pLastSctCnt
, "Where's the last SctContent?" );
4308 if( nInv
& SwInvalidateFlags::Table
)
4310 if( pCnt
->IsInTab() )
4312 // To not call FindTabFrame() for each ContentFrame of a table and
4313 // then invalidate the table, we remember the last ContentFrame of
4314 // the table and ignore IsInTab() until we are past it.
4315 // When entering the table, LastSctCnt is set to null, so
4316 // sections inside the table are correctly invalidated.
4317 // If the table itself is in a section the
4318 // invalidation is done three times, which is acceptable.
4321 pLastTabCnt
= lcl_InvalidateTable( pCnt
->FindTabFrame(), nInv
);
4322 pLastSctCnt
= nullptr;
4324 if( pLastTabCnt
== pCnt
)
4326 pLastTabCnt
= nullptr;
4327 pLastSctCnt
= nullptr;
4330 #if OSL_DEBUG_LEVEL > 0
4332 OSL_ENSURE( !pLastTabCnt
, "Where's the last TabContent?" );
4336 if( nInv
& SwInvalidateFlags::Size
)
4337 pCnt
->Prepare( PrepareHint::Clear
, nullptr, false );
4338 if( nInv
& SwInvalidateFlags::Pos
)
4339 pCnt
->InvalidatePos_();
4340 if( nInv
& SwInvalidateFlags::PrtArea
)
4341 pCnt
->InvalidatePrt_();
4342 if ( nInv
& SwInvalidateFlags::LineNum
)
4343 pCnt
->InvalidateLineNum();
4344 if ( pCnt
->GetDrawObjs() )
4345 lcl_InvalidateAllContent( pCnt
, nInv
);
4346 pCnt
= pCnt
->GetNextContentFrame();
4350 static void lcl_InvalidateAllContent( SwContentFrame
*pCnt
, SwInvalidateFlags nInv
)
4352 SwSortedObjs
&rObjs
= *pCnt
->GetDrawObjs();
4353 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
4355 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
4357 if ( pFly
->IsFlyInContentFrame() )
4359 ::lcl_InvalidateContent( pFly
->ContainsContent(), nInv
);
4360 if( nInv
& SwInvalidateFlags::Direction
)
4361 pFly
->CheckDirChange();
4367 void SwRootFrame::InvalidateAllContent( SwInvalidateFlags nInv
)
4369 // First process all page bound FlyFrames.
4370 SwPageFrame
*pPage
= static_cast<SwPageFrame
*>(Lower());
4373 pPage
->InvalidateFlyLayout();
4374 pPage
->InvalidateFlyContent();
4375 pPage
->InvalidateFlyInCnt();
4376 pPage
->InvalidateLayout();
4377 pPage
->InvalidateContent();
4378 pPage
->InvalidatePage( pPage
); // So even the Turbo disappears if applicable
4380 if ( pPage
->GetSortedObjs() )
4382 const SwSortedObjs
&rObjs
= *pPage
->GetSortedObjs();
4383 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
4385 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
4387 ::lcl_InvalidateContent( pFly
->ContainsContent(), nInv
);
4388 if ( nInv
& SwInvalidateFlags::Direction
)
4389 pFly
->CheckDirChange();
4393 if( nInv
& SwInvalidateFlags::Direction
)
4394 pPage
->CheckDirChange();
4395 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
4398 //Invalidate the whole document content and the character bound Flys here.
4399 ::lcl_InvalidateContent( ContainsContent(), nInv
);
4401 if( nInv
& SwInvalidateFlags::PrtArea
)
4403 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
4405 pSh
->InvalidateWindows( getFrameArea() );
4410 * Invalidate/re-calculate the position of all floating screen objects (Writer fly frames and
4411 * drawing objects), that are anchored to paragraph or to character. (2004-03-16 #i11860#)
4413 void SwRootFrame::InvalidateAllObjPos()
4415 const SwPageFrame
* pPageFrame
= static_cast<const SwPageFrame
*>(Lower());
4418 pPageFrame
->InvalidateFlyLayout();
4420 if ( pPageFrame
->GetSortedObjs() )
4422 const SwSortedObjs
& rObjs
= *(pPageFrame
->GetSortedObjs());
4423 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
4425 const SwFormatAnchor
& rAnch
= pAnchoredObj
->GetFrameFormat()->GetAnchor();
4426 if ((rAnch
.GetAnchorId() != RndStdIds::FLY_AT_PARA
) &&
4427 (rAnch
.GetAnchorId() != RndStdIds::FLY_AT_CHAR
))
4429 // only to paragraph and to character anchored objects are considered.
4432 // #i28701# - special invalidation for anchored
4433 // objects, whose wrapping style influence has to be considered.
4434 if ( pAnchoredObj
->ConsiderObjWrapInfluenceOnObjPos() )
4435 pAnchoredObj
->InvalidateObjPosForConsiderWrapInfluence();
4437 pAnchoredObj
->InvalidateObjPos();
4441 pPageFrame
= static_cast<const SwPageFrame
*>(pPageFrame
->GetNext());
4445 static void AddRemoveFlysForNode(
4446 SwTextFrame
& rFrame
, SwTextNode
& rTextNode
,
4447 std::set
<SwNodeOffset
> *const pSkipped
,
4448 const sw::FrameFormats
<sw::SpzFrameFormat
*>& rTable
,
4449 SwPageFrame
*const pPage
,
4450 SwTextNode
const*const pNode
,
4451 std::vector
<sw::Extent
>::const_iterator
const& rIterFirst
,
4452 std::vector
<sw::Extent
>::const_iterator
const& rIterEnd
,
4453 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
4455 if (pNode
== &rTextNode
)
4456 { // remove existing hidden at-char anchored flys
4457 RemoveHiddenObjsOfNode(rTextNode
, &rIterFirst
, &rIterEnd
, pFirstNode
, pLastNode
);
4459 else if (rTextNode
.GetIndex() < pNode
->GetIndex())
4461 // pNode's frame has been deleted by CheckParaRedlineMerge()
4462 AppendObjsOfNode(&rTable
,
4463 pNode
->GetIndex(), &rFrame
, pPage
, &rTextNode
.GetDoc(),
4464 &rIterFirst
, &rIterEnd
, pFirstNode
, pLastNode
);
4467 // 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
4468 for (auto const pFly
: pNode
->GetAnchoredFlys())
4470 if (pFly
->Which() != RES_DRAWFRMFMT
)
4472 pSkipped
->insert(pFly
->GetContent().GetContentIdx()->GetIndex());
4481 /// rTextNode is the first one of the "new" merge - if rTextNode isn't the same
4482 /// as MergedPara::pFirstNode, then nodes before rTextNode have their flys
4483 /// already properly attached, so only the other nodes need handling here.
4484 void AddRemoveFlysAnchoredToFrameStartingAtNode(
4485 SwTextFrame
& rFrame
, SwTextNode
& rTextNode
,
4486 std::set
<SwNodeOffset
> *const pSkipped
)
4488 auto const pMerged(rFrame
.GetMergedPara());
4490 // do this only *once*, for the *last* frame
4491 // otherwise AppendObj would create multiple frames for fly-frames!
4492 || rFrame
.GetFollow())
4495 assert(pMerged
->pFirstNode
->GetIndex() <= rTextNode
.GetIndex()
4496 && rTextNode
.GetIndex() <= pMerged
->pLastNode
->GetIndex());
4497 // add visible flys in non-first node to merged frame
4498 // (hidden flys remain and are deleted via DelFrames())
4499 sw::SpzFrameFormats
& rTable(*rTextNode
.GetDoc().GetSpzFrameFormats());
4500 SwPageFrame
*const pPage(rFrame
.FindPageFrame());
4501 std::vector
<sw::Extent
>::const_iterator
iterFirst(pMerged
->extents
.begin());
4502 std::vector
<sw::Extent
>::const_iterator
iter(iterFirst
);
4503 SwTextNode
const* pNode(pMerged
->pFirstNode
);
4506 if (iter
== pMerged
->extents
.end()
4507 || iter
->pNode
!= pNode
)
4509 AddRemoveFlysForNode(rFrame
, rTextNode
, pSkipped
, rTable
, pPage
,
4510 pNode
, iterFirst
, iter
,
4511 pMerged
->pFirstNode
, pMerged
->pLastNode
);
4512 SwNodeOffset
const until
= iter
== pMerged
->extents
.end()
4513 ? pMerged
->pLastNode
->GetIndex() + 1
4514 : iter
->pNode
->GetIndex();
4515 for (SwNodeOffset i
= pNode
->GetIndex() + 1; i
< until
; ++i
)
4517 // let's show at-para flys on nodes that contain start/end of
4518 // redline too, even if there's no text there
4519 SwNode
const*const pTmp(pNode
->GetNodes()[i
]);
4520 if (pTmp
->GetRedlineMergeFlag() == SwNode::Merge::NonFirst
)
4522 AddRemoveFlysForNode(rFrame
, rTextNode
, pSkipped
,
4523 rTable
, pPage
, pTmp
->GetTextNode(), iter
, iter
,
4524 pMerged
->pFirstNode
, pMerged
->pLastNode
);
4527 if (iter
== pMerged
->extents
.end())
4531 pNode
= iter
->pNode
;
4539 static void UnHideRedlines(SwRootFrame
& rLayout
,
4540 SwNodes
& rNodes
, SwNode
const& rEndOfSectionNode
,
4541 std::set
<SwNodeOffset
> *const pSkipped
)
4543 assert(rEndOfSectionNode
.IsEndNode());
4544 assert(rNodes
[rEndOfSectionNode
.StartOfSectionNode()->GetIndex() + 1]->IsCreateFrameWhenHidingRedlines()); // first node is never hidden
4545 for (SwNodeOffset i
= rEndOfSectionNode
.StartOfSectionNode()->GetIndex() + 1;
4546 i
< rEndOfSectionNode
.GetIndex(); ++i
)
4548 SwNode
& rNode(*rNodes
[i
]);
4549 if (rNode
.IsTextNode()) // only text nodes are 1st node of a merge
4551 SwTextNode
& rTextNode(*rNode
.GetTextNode());
4552 SwIterator
<SwTextFrame
, SwTextNode
, sw::IteratorMode::UnwrapMulti
> aIter(rTextNode
);
4553 std::vector
<SwTextFrame
*> frames
;
4554 for (SwTextFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next())
4556 if (pFrame
->getRootFrame() == &rLayout
)
4558 if (pFrame
->IsFollow())
4560 frames
.push_back(pFrame
);
4561 } // when hiding, the loop must remove the anchored flys
4562 else // *before* resetting SetMergedPara anywhere - else
4563 { // the fly deletion code will access multiple of the
4564 // frames with inconsistent MergedPara and assert
4565 frames
.insert(frames
.begin(), pFrame
);
4569 // this messes with pRegisteredIn so do it outside SwIterator
4570 auto eMode(sw::FrameMode::Existing
);
4571 for (SwTextFrame
* pFrame
: frames
)
4573 if (rLayout
.HasMergedParas())
4575 assert(!pFrame
->GetMergedPara() ||
4576 !rNode
.IsCreateFrameWhenHidingRedlines() ||
4577 // FIXME: skip this assert in tables with deleted rows
4579 if (rNode
.IsCreateFrameWhenHidingRedlines())
4582 auto pMerged(CheckParaRedlineMerge(*pFrame
,
4584 pFrame
->SetMergedPara(std::move(pMerged
));
4586 auto const pMerged(pFrame
->GetMergedPara());
4589 // invalidate SwInvalidateFlags::Size
4590 pFrame
->Prepare(PrepareHint::Clear
, nullptr, false);
4591 pFrame
->InvalidatePage();
4592 if (auto const pObjs
= pFrame
->GetDrawObjs())
4593 { // also invalidate position of existing flys
4594 // because they may need to be moved
4595 for (auto const pObject
: *pObjs
)
4597 pObject
->InvalidateObjPos();
4601 sw::AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame
, rTextNode
, pSkipped
);
4602 // only *first* frame of node gets Existing because it
4603 eMode
= sw::FrameMode::New
; // is not idempotent!
4608 if (auto const pMergedPara
= pFrame
->GetMergedPara())
4610 // invalidate SwInvalidateFlags::Size
4611 pFrame
->Prepare(PrepareHint::Clear
, nullptr, false);
4612 pFrame
->InvalidatePage();
4613 if (auto const pObjs
= pFrame
->GetDrawObjs())
4614 { // also invalidate position of existing flys
4615 for (auto const pObject
: *pObjs
)
4617 pObject
->InvalidateObjPos();
4620 // SwFlyAtContentFrame::SwClientNotify() always appends to
4621 // the master frame, so do the same here.
4622 // (RemoveFootnotesForNode must be called at least once)
4623 if (!pFrame
->IsFollow())
4625 // the new text frames don't exist yet, so at this point
4626 // we can only delete the footnote frames so they don't
4627 // point to the merged SwTextFrame any more...
4628 assert(&rTextNode
== pMergedPara
->pFirstNode
);
4629 // iterate over nodes, not extents: if a node has
4630 // no extents now but did have extents initially,
4631 // its flys need their frames deleted too!
4632 for (SwNodeOffset j
= rTextNode
.GetIndex() + 1;
4633 j
<= pMergedPara
->pLastNode
->GetIndex(); ++j
)
4635 SwNode
*const pNode(rTextNode
.GetNodes()[j
]);
4636 assert(!pNode
->IsEndNode());
4637 if (pNode
->IsStartNode())
4639 j
= pNode
->EndOfSectionIndex();
4641 else if (pNode
->IsTextNode())
4643 sw::RemoveFootnotesForNode(rLayout
, *pNode
->GetTextNode(), nullptr);
4644 // similarly, remove the anchored flys
4645 for (SwFrameFormat
* pFormat
: pNode
->GetAnchoredFlys())
4647 pFormat
->DelFrames(/*&rLayout*/);
4651 // rely on AppendAllObjs call at the end to add
4652 // all flys in first node that are hidden
4654 pFrame
->SetMergedPara(nullptr);
4657 pFrame
->Broadcast(SfxHint()); // notify SwAccessibleParagraph
4659 // all nodes, not just merged ones! it may be in the same list as
4660 if (rTextNode
.IsNumbered(nullptr)) // a preceding merged one...
4661 { // notify frames so they reformat numbering portions
4662 rTextNode
.NumRuleChgd();
4665 else if (rNode
.IsTableNode() && rLayout
.IsHideRedlines())
4667 SwTableNode
* pTableNd
= rNode
.GetTableNode();
4668 SwPosition
const tmp(rNode
);
4669 SwRangeRedline
const*const pRedline(
4670 rLayout
.GetFormat()->GetDoc()->getIDocumentRedlineAccess().GetRedline(tmp
, nullptr));
4671 // pathology: redline that starts on a TableNode; cannot
4672 // be created in UI but by import filters...
4674 && pRedline
->GetType() == RedlineType::Delete
4675 && &pRedline
->Start()->GetNode() == &rNode
)
4677 for (SwNodeOffset j
= rNode
.GetIndex(); j
<= rNode
.EndOfSectionIndex(); ++j
)
4679 rNode
.GetNodes()[j
]->SetRedlineMergeFlag(SwNode::Merge::Hidden
);
4681 pTableNd
->DelFrames(&rLayout
);
4683 else if ( pTableNd
->GetTable().HasDeletedRowOrCell() )
4685 pTableNd
->DelFrames(&rLayout
);
4686 if ( !pTableNd
->GetTable().IsDeleted() )
4688 pTableNd
->MakeOwnFrames();
4692 else if (rNode
.IsTableNode() && !rLayout
.IsHideRedlines() &&
4693 rNode
.GetTableNode()->GetTable().HasDeletedRowOrCell() )
4695 SwTableNode
* pTableNd
= rNode
.GetTableNode();
4696 pTableNd
->DelFrames(&rLayout
);
4697 pTableNd
->MakeOwnFrames();
4700 if (!rNode
.IsCreateFrameWhenHidingRedlines())
4702 if (rLayout
.HasMergedParas())
4704 if (rNode
.IsContentNode())
4706 // note: nothing to do here, already done
4708 auto const pFrame(static_cast<SwContentNode
&>(rNode
).getLayoutFrame(&rLayout
));
4709 assert(!pFrame
|| static_cast<SwTextFrame
*>(pFrame
)->GetMergedPara()->pFirstNode
!= &rNode
);
4715 assert(!rNode
.IsContentNode() || !rNode
.GetContentNode()->getLayoutFrame(&rLayout
) ||
4716 // FIXME: skip this assert in tables with deleted rows
4717 rNode
.GetContentNode()->getLayoutFrame(&rLayout
)->IsInTab());
4718 SwNodeOffset j
= i
+ 1;
4719 for ( ; j
< rEndOfSectionNode
.GetIndex(); ++j
)
4721 if (rNodes
[j
]->IsCreateFrameWhenHidingRedlines())
4726 // call MakeFrames once, because sections/tables
4727 // InsertCnt_ also checks for hidden sections
4729 sw::FlyCreationSuppressor
aSuppressor(false);
4730 ::MakeFrames(rLayout
.GetFormat()->GetDoc(), *rNodes
[i
], *rNodes
[j
]);
4732 i
= j
- 1; // will be incremented again
4738 static void UnHideRedlinesExtras(SwRootFrame
& rLayout
,
4739 SwNodes
& rNodes
, SwNode
const& rEndOfExtraSectionNode
,
4740 std::set
<SwNodeOffset
> *const pSkipped
)
4742 assert(rEndOfExtraSectionNode
.IsEndNode());
4743 for (SwNodeOffset i
= rEndOfExtraSectionNode
.StartOfSectionNode()->GetIndex()
4744 + 1; i
< rEndOfExtraSectionNode
.GetIndex(); ++i
)
4746 SwNode
const& rStartNode(*rNodes
[i
]);
4747 assert(rStartNode
.IsStartNode());
4748 assert(rStartNode
.GetRedlineMergeFlag() == SwNode::Merge::None
);
4749 SwNode
const& rEndNode(*rStartNode
.EndOfSectionNode());
4750 bool bSkip(pSkipped
&& pSkipped
->find(i
) != pSkipped
->end());
4751 i
= rEndNode
.GetIndex();
4752 for (SwNodeOffset j
= rStartNode
.GetIndex() + 1; j
< i
; ++j
)
4754 // note: SwStartNode has no way to access the frames, so check
4755 // whether the first content-node inside the section has frames
4756 SwNode
const& rNode(*rNodes
[j
]);
4757 if (rNode
.IsSectionNode() &&
4758 static_cast<SwSectionNode
const&>(rNode
).GetSection().IsHiddenFlag())
4759 { // skip hidden sections - they can be inserted in fly-frames :(
4760 j
= rNode
.EndOfSectionNode()->GetIndex();
4763 if (rNode
.IsContentNode())
4765 SwContentNode
const& rCNode(static_cast<SwContentNode
const&>(rNode
));
4766 if (!rCNode
.getLayoutFrame(&rLayout
))
4767 { // ignore footnote/fly/header/footer with no layout frame
4768 bSkip
= true; // they will be created from scratch later if needed
4775 UnHideRedlines(rLayout
, rNodes
, rEndNode
, pSkipped
);
4780 static void UnHide(SwRootFrame
& rLayout
)
4782 assert(rLayout
.GetCurrShell()->ActionPend()); // tdf#125754 avoid recursive layout
4783 SwDoc
& rDoc(*rLayout
.GetFormat()->GetDoc());
4784 // don't do early return if there are no redlines:
4785 // Show->Hide must init hidden number trees
4786 // Hide->Show may be called after all redlines have been deleted but there
4787 // may still be MergedParas because those aren't deleted yet...
4790 && rDoc
.getIDocumentRedlineAccess().GetRedlineTable().empty())
4795 // Hide->Show: clear MergedPara, create frames
4796 // Show->Hide: call CheckParaRedlineMerge, delete frames
4797 // Traverse the document via the nodes-array; traversing via the layout
4798 // wouldn't find the nodes that don't have frames in the ->Show case.
4799 // In-order traversal of each nodes array section should init the flags
4800 // in nodes before they are iterated.
4801 // Actual creation of frames should be done with existing functions
4802 // if possible, particularly InsertCnt_() or its wrapper ::MakeFrames().
4803 SwNodes
/*const*/& rNodes(rDoc
.GetNodes());
4804 // Flys/footnotes: must iterate and find all the ones that already exist
4805 // with frames and have redlines inside them; if any don't have frames at
4806 // all, they will be created (if necessary) from scratch and completely by
4809 // Flys before footnotes: because footnotes may contain flys but not
4810 // vice-versa; alas flys may contain flys, so we skip some of them
4811 // if they have already been created from scratch via their anchor flys.
4812 std::set
<SwNodeOffset
> skippedFlys
;
4813 UnHideRedlinesExtras(rLayout
, rNodes
, rNodes
.GetEndOfAutotext(),
4814 // when un-hiding, delay all fly frame creation to AppendAllObjs below
4815 rLayout
.HasMergedParas() ? &skippedFlys
: nullptr);
4816 // Footnotes are created automatically (after invalidation etc.) by
4817 // ConnectFootnote(), but need to be deleted manually. Footnotes do not
4818 // occur in flys or headers/footers.
4819 UnHideRedlinesExtras(rLayout
, rNodes
, rNodes
.GetEndOfInserts(), nullptr);
4820 UnHideRedlines(rLayout
, rNodes
, rNodes
.GetEndOfContent(), nullptr);
4822 if (!rLayout
.HasMergedParas())
4823 { // create all previously hidden flys at once:
4824 // * Flys on first node of pre-existing merged frames that are hidden
4825 // (in delete redline), to be added to the existing frame
4826 // * Flys on non-first (hidden/merged) nodes of pre-existing merged
4827 // frames, to be added to the new frame of their node
4828 // * Flys anchored in other flys that are hidden
4829 AppendAllObjs(rDoc
.GetSpzFrameFormats(), &rLayout
);
4832 const bool bIsShowChangesInMargin
= rLayout
.GetCurrShell()->GetViewOptions()->IsShowChangesInMargin();
4833 for (auto const pRedline
: rDoc
.getIDocumentRedlineAccess().GetRedlineTable())
4834 { // DELETE are handled by the code above; for other types, need to
4835 // trigger repaint of text frames to add/remove the redline color font
4836 // (handle deletions showed in margin also here)
4837 if (bIsShowChangesInMargin
|| pRedline
->GetType() != RedlineType::Delete
)
4839 pRedline
->InvalidateRange(SwRangeRedline::Invalidation::Add
);
4843 SwFootnoteIdxs
& rFootnotes(rDoc
.GetFootnoteIdxs());
4844 if (rDoc
.GetFootnoteInfo().m_eNum
== FTNNUM_CHAPTER
)
4846 // sadly determining which node is outline node requires hidden layout
4847 rFootnotes
.UpdateAllFootnote();
4849 // invalidate all footnotes to reformat their numbers
4850 for (SwTextFootnote
*const pFootnote
: rFootnotes
)
4852 SwFormatFootnote
const& rFootnote(pFootnote
->GetFootnote());
4853 if (rFootnote
.GetNumber() != rFootnote
.GetNumberRLHidden()
4854 && rFootnote
.GetNumStr().isEmpty())
4856 pFootnote
->InvalidateNumberInLayout();
4859 // update various fields to re-expand them with the new layout
4860 IDocumentFieldsAccess
& rIDFA(rDoc
.getIDocumentFieldsAccess());
4861 auto const pAuthType(rIDFA
.GetFieldType(
4862 SwFieldIds::TableOfAuthorities
, OUString(), false));
4863 if (pAuthType
) // created on demand...
4864 { // calling DelSequenceArray() should be unnecessary here since the
4865 // sequence doesn't depend on frames
4866 pAuthType
->UpdateFields();
4868 rIDFA
.GetFieldType(SwFieldIds::RefPageGet
, OUString(), false)->UpdateFields();
4869 rIDFA
.GetSysFieldType(SwFieldIds::Chapter
)->UpdateFields();
4870 rIDFA
.UpdateExpFields(nullptr, false);
4871 rIDFA
.UpdateRefFields();
4873 // update SwPostItMgr / notes in the margin
4874 // note: as long as all shells share layout, broadcast to all shells!
4875 rDoc
.GetDocShell()->Broadcast( SwFormatFieldHint(nullptr, rLayout
.HasMergedParas()
4876 ? SwFormatFieldHintWhich::REMOVED
4877 : SwFormatFieldHintWhich::INSERTED
) );
4880 // InvalidateAllContent(SwInvalidateFlags::Size); // ??? TODO what to invalidate? this is the big hammer
4883 void SwRootFrame::SetHideRedlines(bool const bHideRedlines
)
4885 if (bHideRedlines
== mbHideRedlines
)
4889 // TODO: remove temporary ShowBoth
4890 sw::FieldmarkMode
const eMode(m_FieldmarkMode
);
4891 sw::ParagraphBreakMode
const ePBMode(m_ParagraphBreakMode
);
4892 if (HasMergedParas())
4894 m_FieldmarkMode
= sw::FieldmarkMode::ShowBoth
;
4895 m_ParagraphBreakMode
= sw::ParagraphBreakMode::Shown
;
4896 mbHideRedlines
= false;
4899 if (bHideRedlines
|| eMode
!= m_FieldmarkMode
|| ePBMode
!= m_ParagraphBreakMode
)
4901 m_FieldmarkMode
= eMode
;
4902 m_ParagraphBreakMode
= ePBMode
;
4903 mbHideRedlines
= bHideRedlines
;
4908 void SwRootFrame::SetFieldmarkMode(sw::FieldmarkMode
const eFMMode
, sw::ParagraphBreakMode
const ePBMode
)
4910 if (eFMMode
== m_FieldmarkMode
&& ePBMode
== m_ParagraphBreakMode
)
4914 // TODO: remove temporary ShowBoth
4915 bool const isHideRedlines(mbHideRedlines
);
4916 if (HasMergedParas())
4918 mbHideRedlines
= false;
4919 m_FieldmarkMode
= sw::FieldmarkMode::ShowBoth
;
4920 m_ParagraphBreakMode
= sw::ParagraphBreakMode::Shown
;
4923 if (isHideRedlines
|| eFMMode
!= sw::FieldmarkMode::ShowBoth
|| ePBMode
== sw::ParagraphBreakMode::Hidden
)
4925 mbHideRedlines
= isHideRedlines
;
4926 m_FieldmarkMode
= eFMMode
;
4927 m_ParagraphBreakMode
= ePBMode
;
4932 bool SwRootFrame::HasMergedParas() const
4934 return IsHideRedlines()
4935 || GetFieldmarkMode() != sw::FieldmarkMode::ShowBoth
4936 || GetParagraphBreakMode() == sw::ParagraphBreakMode::Hidden
;
4940 xmlTextWriterPtr
lcl_createDefaultWriter()
4942 xmlTextWriterPtr writer
= xmlNewTextWriterFilename( "layout.xml", 0 );
4943 xmlTextWriterSetIndent(writer
,1);
4944 (void)xmlTextWriterSetIndentString(writer
, BAD_CAST(" "));
4945 (void)xmlTextWriterStartDocument( writer
, nullptr, nullptr, nullptr );
4949 void lcl_freeWriter( xmlTextWriterPtr writer
)
4951 (void)xmlTextWriterEndDocument( writer
);
4952 xmlFreeTextWriter( writer
);
4956 void SwRootFrame::dumpAsXml(xmlTextWriterPtr writer
) const
4958 bool bCreateWriter
= (nullptr == writer
);
4960 writer
= lcl_createDefaultWriter();
4962 (void)xmlTextWriterStartElement(writer
, reinterpret_cast<const xmlChar
*>("root"));
4963 dumpAsXmlAttributes(writer
);
4965 (void)xmlTextWriterStartElement(writer
, BAD_CAST("sfxViewShells"));
4966 SwView
* pView
= static_cast<SwView
*>(SfxViewShell::GetFirst(true, checkSfxViewShell
<SwView
>));
4969 if (GetCurrShell()->GetSfxViewShell() && pView
->GetObjectShell() == GetCurrShell()->GetSfxViewShell()->GetObjectShell())
4970 pView
->dumpAsXml(writer
);
4971 pView
= static_cast<SwView
*>(SfxViewShell::GetNext(*pView
, true, checkSfxViewShell
<SwView
>));
4973 (void)xmlTextWriterEndElement(writer
);
4975 (void)xmlTextWriterStartElement(writer
, BAD_CAST("infos"));
4976 dumpInfosAsXml(writer
);
4977 (void)xmlTextWriterEndElement(writer
);
4978 dumpChildrenAsXml(writer
);
4979 (void)xmlTextWriterEndElement(writer
);
4982 lcl_freeWriter(writer
);
4985 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */