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 : mbFrameAreaPositionValid(false),
76 mbFrameAreaSizeValid(false),
77 mbFramePrintAreaValid(false),
78 mnFrameId(SwFrameAreaDefinition::snLastFrameId
++)
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(aCenter
.getX() - (0.5 * aAbsScale
.getX())),
185 basegfx::fround(aCenter
.getY() - (0.5 * aAbsScale
.getY())),
186 basegfx::fround(aAbsScale
.getX()),
187 basegfx::fround(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(aCenter
.getX() - (0.5 * aAbsScale
.getX())) - aUntransformedFrameArea
.Left(),
210 basegfx::fround(aCenter
.getY() - (0.5 * aAbsScale
.getY())) - aUntransformedFrameArea
.Top(),
211 basegfx::fround(aAbsScale
.getX()),
212 basegfx::fround(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(aRangeFrameArea
.getMinX()), basegfx::fround(aRangeFrameArea
.getMinY()),
244 basegfx::fround(aRangeFrameArea
.getWidth()), basegfx::fround(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(aRangeFramePrintArea
.getMinX()) - mrSwFrameAreaDefinition
.getFrameArea().Left(),
260 basegfx::fround(aRangeFramePrintArea
.getMinY()) - mrSwFrameAreaDefinition
.getFrameArea().Top(),
261 basegfx::fround(aRangeFramePrintArea
.getWidth()),
262 basegfx::fround(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 SwFrame::SwFrame( sw::BroadcastingModify
*pMod
, SwFrame
* pSib
)
297 mpRoot( pSib
? pSib
->getRootFrame() : nullptr ),
301 mnFrameType(SwFrameType::None
),
305 mbRightToLeft(false),
307 mbDerivedVert(false),
311 mbValidLineNum(false),
313 mbCompletePaint(true),
319 mbInfFootnote ( false ),
322 m_isInDestroy(false),
325 OSL_ENSURE( pMod
, "No frame format given." );
328 const IDocumentDrawModelAccess
& SwFrame::getIDocumentDrawModelAccess()
330 return GetUpper()->GetFormat()->getIDocumentDrawModelAccess();
333 bool SwFrame::KnowsFormat( const SwFormat
& rFormat
) const
335 return GetRegisteredIn() == &rFormat
;
338 void SwFrame::RegisterToFormat( SwFormat
& rFormat
)
343 void SwFrame::CheckDir( SvxFrameDirection nDir
, bool bVert
, bool bOnlyBiDi
, bool bBrowse
)
345 if( SvxFrameDirection::Environment
== nDir
|| ( bVert
&& bOnlyBiDi
) )
347 mbDerivedVert
= true;
348 if( SvxFrameDirection::Environment
== nDir
)
350 SetDirFlags( bVert
);
354 mbInvalidVert
= false;
355 if( SvxFrameDirection::Horizontal_LR_TB
== nDir
|| SvxFrameDirection::Horizontal_RL_TB
== nDir
365 if(SvxFrameDirection::Vertical_RL_TB
== nDir
)
370 else if(SvxFrameDirection::Vertical_LR_TB
==nDir
)
375 else if (nDir
== SvxFrameDirection::Vertical_LR_BT
)
380 else if (nDir
== SvxFrameDirection::Vertical_RL_TB90
)
382 // not yet implemented, render as RL_TB
390 mbInvalidR2L
= false;
391 if( SvxFrameDirection::Horizontal_RL_TB
== nDir
)
392 mbRightToLeft
= true;
394 mbRightToLeft
= false;
398 void SwFrame::CheckDirection( bool bVert
)
402 if( !IsHeaderFrame() && !IsFooterFrame() )
404 mbDerivedVert
= true;
405 SetDirFlags( bVert
);
411 SetDirFlags( bVert
);
415 void SwSectionFrame::CheckDirection( bool bVert
)
417 const SwFrameFormat
* pFormat
= GetFormat();
420 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
421 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
422 CheckDir(pFormat
->GetFormatAttr(RES_FRAMEDIR
).GetValue(),
423 bVert
, true, bBrowseMode
);
426 SwFrame::CheckDirection( bVert
);
429 void SwFlyFrame::CheckDirection( bool bVert
)
431 const SwFrameFormat
* pFormat
= GetFormat();
434 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
435 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
436 CheckDir(pFormat
->GetFormatAttr(RES_FRAMEDIR
).GetValue(),
437 bVert
, false, bBrowseMode
);
440 SwFrame::CheckDirection( bVert
);
443 void SwTabFrame::CheckDirection( bool bVert
)
445 const SwFrameFormat
* pFormat
= GetFormat();
448 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
449 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
450 CheckDir(pFormat
->GetFormatAttr(RES_FRAMEDIR
).GetValue(),
451 bVert
, true, bBrowseMode
);
454 SwFrame::CheckDirection( bVert
);
457 void SwCellFrame::CheckDirection( bool bVert
)
459 const SwFrameFormat
* pFormat
= GetFormat();
460 const SvxFrameDirectionItem
* pFrameDirItem
;
461 // Check if the item is set, before actually
462 // using it. Otherwise the dynamic pool default is used, which may be set
463 // to LTR in case of OOo 1.0 documents.
464 if( pFormat
&& (pFrameDirItem
= pFormat
->GetItemIfSet( RES_FRAMEDIR
) ) )
466 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
467 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
468 CheckDir( pFrameDirItem
->GetValue(), bVert
, false, bBrowseMode
);
471 SwFrame::CheckDirection( bVert
);
474 void SwTextFrame::CheckDirection( bool bVert
)
476 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
477 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
478 CheckDir(GetTextNodeForParaProps()->GetSwAttrSet().GetFrameDir().GetValue(),
479 bVert
, true, bBrowseMode
);
482 void SwFrame::SwClientNotify(const SwModify
&, const SfxHint
& rHint
)
484 if (rHint
.GetId() != SfxHintId::SwLegacyModify
)
486 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
487 SwFrameInvFlags eInvFlags
= SwFrameInvFlags::NONE
;
489 if(pLegacy
->m_pOld
&& pLegacy
->m_pNew
&& RES_ATTRSET_CHG
== pLegacy
->m_pNew
->Which())
491 SfxItemIter
aNIter(*static_cast<const SwAttrSetChg
*>(pLegacy
->m_pNew
)->GetChgSet());
492 SfxItemIter
aOIter(*static_cast<const SwAttrSetChg
*>(pLegacy
->m_pOld
)->GetChgSet());
493 const SfxPoolItem
* pNItem
= aNIter
.GetCurItem();
494 const SfxPoolItem
* pOItem
= aOIter
.GetCurItem();
497 UpdateAttrFrame(pOItem
, pNItem
, eInvFlags
);
498 pNItem
= aNIter
.NextItem();
499 pOItem
= aOIter
.NextItem();
503 UpdateAttrFrame(pLegacy
->m_pOld
, pLegacy
->m_pNew
, eInvFlags
);
505 if(eInvFlags
== SwFrameInvFlags::NONE
)
508 SwPageFrame
* pPage
= FindPageFrame();
509 InvalidatePage(pPage
);
510 if(eInvFlags
& SwFrameInvFlags::InvalidatePrt
)
513 if(!GetPrev() && IsTabFrame() && IsInSct())
514 FindSctFrame()->InvalidatePrt_();
516 if(eInvFlags
& SwFrameInvFlags::InvalidateSize
)
518 if(eInvFlags
& SwFrameInvFlags::InvalidatePos
)
520 if(eInvFlags
& SwFrameInvFlags::SetCompletePaint
)
523 if (eInvFlags
& (SwFrameInvFlags::NextInvalidatePos
| SwFrameInvFlags::NextSetCompletePaint
)
524 && nullptr != (pNxt
= GetNext()))
526 pNxt
->InvalidatePage(pPage
);
527 if(eInvFlags
& SwFrameInvFlags::NextInvalidatePos
)
528 pNxt
->InvalidatePos_();
529 if(eInvFlags
& SwFrameInvFlags::NextSetCompletePaint
)
530 pNxt
->SetCompletePaint();
534 void SwFrame::UpdateAttrFrame( const SfxPoolItem
*pOld
, const SfxPoolItem
*pNew
,
535 SwFrameInvFlags
&rInvFlags
)
537 sal_uInt16 nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
542 Prepare( PrepareHint::FixSizeChanged
);
544 case RES_MARGIN_FIRSTLINE
:
545 case RES_MARGIN_TEXTLEFT
:
546 case RES_MARGIN_RIGHT
:
550 rInvFlags
|= SwFrameInvFlags::InvalidatePrt
| SwFrameInvFlags::InvalidateSize
551 | SwFrameInvFlags::SetCompletePaint
;
554 case RES_HEADER_FOOTER_EAT_SPACING
:
555 rInvFlags
|= SwFrameInvFlags::InvalidatePrt
| SwFrameInvFlags::InvalidateSize
;
559 case RES_BACKGROUND_FULL_SIZE
:
560 rInvFlags
|= SwFrameInvFlags::SetCompletePaint
| SwFrameInvFlags::NextSetCompletePaint
;
564 rInvFlags
|= SwFrameInvFlags::InvalidatePos
;
568 ReinitializeFrameSizeAttrFlags();
569 rInvFlags
|= SwFrameInvFlags::InvalidatePrt
| SwFrameInvFlags::InvalidateSize
570 | SwFrameInvFlags::NextInvalidatePos
;
574 rInvFlags
|= SwFrameInvFlags::InvalidatePrt
| SwFrameInvFlags::InvalidateSize
575 | SwFrameInvFlags::InvalidatePos
| SwFrameInvFlags::SetCompletePaint
;
582 bool bInFollowFlowRow
= nullptr != IsInFollowFlowRow();
583 if ( bInFollowFlowRow
|| nullptr != IsInSplitTableRow() )
585 SwTabFrame
* pTab
= FindTabFrame();
586 if ( bInFollowFlowRow
)
587 pTab
= pTab
->FindMaster();
588 pTab
->SetRemoveFollowFlowLinePending( true );
594 OSL_FAIL( "Columns for new FrameType?" );
598 // the new FillStyle has to do the same as previous RES_BACKGROUND
599 if(nWhich
>= XATTR_FILL_FIRST
&& nWhich
<= XATTR_FILL_LAST
)
602 |= SwFrameInvFlags::SetCompletePaint
| SwFrameInvFlags::NextSetCompletePaint
;
608 bool SwFrame::Prepare( const PrepareHint
, const void *, bool )
615 * Invalidates the page in which the Frame is currently placed.
616 * The page is invalidated depending on the type (Layout, Content, FlyFrame)
618 void SwFrame::InvalidatePage( const SwPageFrame
*pPage
) const
622 pPage
= FindPageFrame();
623 // #i28701# - for at-character and as-character
624 // anchored Writer fly frames additionally invalidate also page frame
625 // its 'anchor character' is on.
626 if ( pPage
&& pPage
->GetUpper() && IsFlyFrame() )
628 const SwFlyFrame
* pFlyFrame
= static_cast<const SwFlyFrame
*>(this);
629 if ( pFlyFrame
->IsAutoPos() || pFlyFrame
->IsFlyInContentFrame() )
631 // #i33751#, #i34060# - method <GetPageFrameOfAnchor()>
632 // is replaced by method <FindPageFrameOfAnchor()>. It's return value
633 // have to be checked.
634 SwPageFrame
* pPageFrameOfAnchor
=
635 const_cast<SwFlyFrame
*>(pFlyFrame
)->FindPageFrameOfAnchor();
636 if ( pPageFrameOfAnchor
&& pPageFrameOfAnchor
!= pPage
)
638 InvalidatePage( pPageFrameOfAnchor
);
644 if ( !(pPage
&& pPage
->GetUpper()) )
647 if ( pPage
->GetFormat()->GetDoc()->IsInDtor() )
650 SwRootFrame
*pRoot
= const_cast<SwRootFrame
*>(static_cast<const SwRootFrame
*>(pPage
->GetUpper()));
651 const SwFlyFrame
*pFly
= FindFlyFrame();
652 if ( IsContentFrame() )
654 if ( pRoot
->IsTurboAllowed() )
656 // If a ContentFrame wants to register for a second time, make it a TurboAction.
657 if ( !pRoot
->GetTurbo() || this == pRoot
->GetTurbo() )
658 pRoot
->SetTurbo( static_cast<const SwContentFrame
*>(this) );
661 pRoot
->DisallowTurbo();
662 //The page of the Turbo could be a different one then mine,
663 //therefore we have to invalidate it.
664 const SwFrame
*pTmp
= pRoot
->GetTurbo();
666 pTmp
->InvalidatePage();
669 if ( !pRoot
->GetTurbo() )
672 { if( !pFly
->IsLocked() )
674 if ( pFly
->IsFlyInContentFrame() )
675 { pPage
->InvalidateFlyInCnt();
676 pFly
->GetAnchorFrame()->InvalidatePage();
679 pPage
->InvalidateFlyContent();
683 pPage
->InvalidateContent();
688 pRoot
->DisallowTurbo();
691 if ( !pFly
->IsLocked() )
693 if ( pFly
->IsFlyInContentFrame() )
695 pPage
->InvalidateFlyInCnt();
696 pFly
->GetAnchorFrame()->InvalidatePage();
699 pPage
->InvalidateFlyLayout();
703 pPage
->InvalidateLayout();
705 if ( pRoot
->GetTurbo() )
706 { const SwFrame
*pTmp
= pRoot
->GetTurbo();
708 pTmp
->InvalidatePage();
711 pRoot
->SetIdleFlags();
716 SwTextFrame
const*const pText(static_cast<SwTextFrame
const*>(this));
717 if (sw::MergedPara
const*const pMergedPara
= pText
->GetMergedPara())
719 SwTextNode
const* pNode(nullptr);
720 for (auto const& e
: pMergedPara
->extents
)
722 if (e
.pNode
!= pNode
)
725 if (pNode
->IsGrammarCheckDirty())
727 pRoot
->SetNeedGrammarCheck( true );
735 if (pText
->GetTextNodeFirst()->IsGrammarCheckDirty())
737 pRoot
->SetNeedGrammarCheck( true );
742 Size
SwFrame::ChgSize( const Size
& aNewSize
)
745 const Size
aOldSize( getFrameArea().SSize() );
746 if ( aNewSize
== aOldSize
)
751 bool bNeighb
= IsNeighbourFrame();
752 SwRectFn fnRect
= IsVertical() == bNeighb
? fnRectHori
: ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T
: fnRectVertL2R
) : fnRectVert
);
753 SwRect
aNew( Point(0,0), aNewSize
);
756 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
757 (aFrm
.*fnRect
->fnSetWidth
)( (aNew
.*fnRect
->fnGetWidth
)() );
760 tools::Long nNew
= (aNew
.*fnRect
->fnGetHeight
)();
761 tools::Long nDiff
= nNew
- (getFrameArea().*fnRect
->fnGetHeight
)();
765 if ( GetUpper()->IsFootnoteBossFrame() && HasFixSize() &&
766 SwNeighbourAdjust::GrowShrink
!=
767 static_cast<SwFootnoteBossFrame
*>(GetUpper())->NeighbourhoodAdjustment() )
770 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
771 (aFrm
.*fnRect
->fnSetHeight
)( nNew
);
774 SwTwips nReal
= static_cast<SwLayoutFrame
*>(this)->AdjustNeighbourhood(nDiff
);
776 if ( nReal
!= nDiff
)
778 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
779 (aFrm
.*fnRect
->fnSetHeight
)( nNew
- nDiff
+ nReal
);
784 // OD 24.10.2002 #97265# - grow/shrink not for neighbour frames
785 // NOTE: neighbour frames are cell and column frames.
793 if ( GetUpper() && (getFrameArea().*fnRect
->fnGetHeight
)() != nNew
)
795 GetUpper()->InvalidateSize_();
799 // Even if grow/shrink did not yet set the desired width, for
800 // example when called by ChgColumns to set the column width, we
801 // set the right width now.
802 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
803 (aFrm
.*fnRect
->fnSetHeight
)( nNew
);
809 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
810 aFrm
.SSize( aNewSize
);
813 if ( getFrameArea().SSize() != aOldSize
)
815 SwPageFrame
*pPage
= FindPageFrame();
818 GetNext()->InvalidatePos_();
819 GetNext()->InvalidatePage( pPage
);
821 if( IsLayoutFrame() )
823 if( IsRightToLeft() )
825 if( static_cast<SwLayoutFrame
*>(this)->Lower() )
826 static_cast<SwLayoutFrame
*>(this)->Lower()->InvalidateSize_();
830 InvalidatePage( pPage
);
833 return getFrameArea().SSize();
836 /** Insert SwFrame into existing structure.
838 * Insertion is done below the parent either before pBehind or
839 * at the end of the chain if pBehind is empty.
841 void SwFrame::InsertBefore( SwLayoutFrame
* pParent
, SwFrame
* pBehind
)
843 OSL_ENSURE( pParent
, "No parent for insert." );
844 OSL_ENSURE( (!pBehind
|| pParent
== pBehind
->GetUpper()),
845 "Frame tree is inconsistent." );
850 { //Insert before pBehind.
851 mpPrev
= pBehind
->mpPrev
;
852 if( nullptr != mpPrev
)
853 mpPrev
->mpNext
= this;
855 mpUpper
->m_pLower
= this;
856 pBehind
->mpPrev
= this;
859 { //Insert at the end, or as first node in the sub tree
860 mpPrev
= mpUpper
->Lower();
863 while( mpPrev
->mpNext
)
864 mpPrev
= mpPrev
->mpNext
;
865 mpPrev
->mpNext
= this;
868 mpUpper
->m_pLower
= this;
872 /** Insert SwFrame into existing structure.
874 * Insertion is done below the parent either after pBehind or
875 * at the beginning of the chain if pBehind is empty.
877 void SwFrame::InsertBehind( SwLayoutFrame
*pParent
, SwFrame
*pBefore
)
879 OSL_ENSURE( pParent
, "No Parent for Insert." );
880 OSL_ENSURE( (!pBefore
|| pParent
== pBefore
->GetUpper()),
881 "Frame tree is inconsistent." );
887 //Insert after pBefore
888 mpNext
= pBefore
->mpNext
;
889 if ( nullptr != mpNext
)
890 mpNext
->mpPrev
= this;
891 pBefore
->mpNext
= this;
895 //Insert at the beginning of the chain
896 mpNext
= pParent
->Lower();
897 if ( pParent
->Lower() )
898 pParent
->Lower()->mpPrev
= this;
899 pParent
->m_pLower
= this;
903 /** Insert a chain of SwFrames into an existing structure
905 * Currently, this method is used to insert a SectionFrame (which may have some siblings) into an
906 * existing structure. If the third parameter is NULL, this method is (besides handling the
907 * siblings) equal to SwFrame::InsertBefore(..).
909 * If the third parameter is passed, the following happens:
910 * - this becomes mpNext of pParent
911 * - pSct becomes mpNext of the last one in the this-chain
912 * - pBehind is reconnected from pParent to pSct
913 * The purpose is: a SectionFrame (this) won't become a child of another SectionFrame (pParent), but
914 * pParent gets split into two siblings (pParent+pSect) and this is inserted between.
916 bool SwFrame::InsertGroupBefore( SwFrame
* pParent
, SwFrame
* pBehind
, SwFrame
* pSct
)
918 OSL_ENSURE( pParent
, "No parent for insert." );
919 OSL_ENSURE( (!pBehind
|| ( (pBehind
&& (pParent
== pBehind
->GetUpper()))
920 || ((pParent
->IsSctFrame() && pBehind
->GetUpper()->IsColBodyFrame())) ) ),
921 "Frame tree inconsistent." );
924 mpUpper
= pParent
->GetUpper();
925 SwFrame
*pLast
= this;
926 while( pLast
->GetNext() )
928 pLast
= pLast
->GetNext();
929 pLast
->mpUpper
= GetUpper();
933 pLast
->mpNext
= pSct
;
934 pSct
->mpPrev
= pLast
;
935 pSct
->mpNext
= pParent
->GetNext();
939 pLast
->mpNext
= pParent
->GetNext();
940 if( pLast
->GetNext() )
941 pLast
->GetNext()->mpPrev
= pLast
;
943 pParent
->mpNext
= this;
945 if( pSct
->GetNext() )
946 pSct
->GetNext()->mpPrev
= pSct
;
947 while( pLast
->GetNext() )
949 pLast
= pLast
->GetNext();
950 pLast
->mpUpper
= GetUpper();
953 { // Insert before pBehind.
954 if( pBehind
->GetPrev() )
955 pBehind
->GetPrev()->mpNext
= nullptr;
957 pBehind
->GetUpper()->m_pLower
= nullptr;
958 pBehind
->mpPrev
= nullptr;
959 SwLayoutFrame
* pTmp
= static_cast<SwLayoutFrame
*>(pSct
);
962 OSL_ENSURE( pTmp
->Lower()->IsColumnFrame(), "InsertGrp: Used SectionFrame" );
963 pTmp
= static_cast<SwLayoutFrame
*>(static_cast<SwLayoutFrame
*>(pTmp
->Lower())->Lower());
964 OSL_ENSURE( pTmp
, "InsertGrp: Missing ColBody" );
966 pBehind
->mpUpper
= pTmp
;
967 pBehind
->GetUpper()->m_pLower
= pBehind
;
968 pLast
= pBehind
->GetNext();
971 pLast
->mpUpper
= pBehind
->GetUpper();
972 pLast
= pLast
->GetNext();
977 OSL_ENSURE( pSct
->IsSctFrame(), "InsertGroup: For SectionFrames only" );
978 SwFrame::DestroyFrame(pSct
);
984 mpUpper
= static_cast<SwLayoutFrame
*>(pParent
);
985 SwFrame
*pLast
= this;
986 while( pLast
->GetNext() )
988 pLast
= pLast
->GetNext();
989 pLast
->mpUpper
= GetUpper();
991 pLast
->mpNext
= pBehind
;
993 { // Insert before pBehind.
994 mpPrev
= pBehind
->mpPrev
;
995 if( nullptr != mpPrev
)
996 mpPrev
->mpNext
= this;
998 mpUpper
->m_pLower
= this;
999 pBehind
->mpPrev
= pLast
;
1003 //Insert at the end, or ... the first node in the subtree
1004 mpPrev
= mpUpper
->Lower();
1007 while( mpPrev
->mpNext
)
1008 mpPrev
= mpPrev
->mpNext
;
1009 mpPrev
->mpNext
= this;
1012 mpUpper
->m_pLower
= this;
1018 void SwFrame::RemoveFromLayout()
1020 OSL_ENSURE( mpUpper
, "Remove without upper?" );
1023 // one out of the middle is removed
1024 mpPrev
->mpNext
= mpNext
;
1026 { // the first in a list is removed //TODO
1027 OSL_ENSURE( mpUpper
->m_pLower
== this, "Layout is inconsistent." );
1028 mpUpper
->m_pLower
= mpNext
;
1031 mpNext
->mpPrev
= mpPrev
;
1034 mpNext
= mpPrev
= nullptr;
1038 void SwContentFrame::Paste( SwFrame
* pParent
, SwFrame
* pSibling
)
1040 OSL_ENSURE( pParent
, "No parent for pasting." );
1041 OSL_ENSURE( pParent
->IsLayoutFrame(), "Parent is ContentFrame." );
1042 OSL_ENSURE( pParent
!= this, "I'm the parent." );
1043 OSL_ENSURE( pSibling
!= this, "I'm my own neighbour." );
1044 OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
1045 "I'm still registered somewhere" );
1046 OSL_ENSURE( !pSibling
|| pSibling
->IsFlowFrame(),
1047 "<SwContentFrame::Paste(..)> - sibling not of expected type." );
1049 //Insert in the tree.
1050 InsertBefore( static_cast<SwLayoutFrame
*>(pParent
), pSibling
);
1052 SwPageFrame
*pPage
= FindPageFrame();
1054 InvalidatePage( pPage
);
1058 pPage
->InvalidateSpelling();
1059 pPage
->InvalidateSmartTags();
1060 pPage
->InvalidateAutoCompleteWords();
1061 pPage
->InvalidateWordCount();
1066 SwFrame
* pNxt
= GetNext();
1067 pNxt
->InvalidatePrt_();
1068 pNxt
->InvalidatePos_();
1069 pNxt
->InvalidatePage( pPage
);
1070 if( pNxt
->IsSctFrame() )
1071 pNxt
= static_cast<SwSectionFrame
*>(pNxt
)->ContainsContent();
1072 if( pNxt
&& pNxt
->IsTextFrame() && pNxt
->IsInFootnote() )
1073 pNxt
->Prepare( PrepareHint::FootnoteInvalidation
, nullptr, false );
1076 if ( getFrameArea().Height() )
1077 pParent
->Grow( getFrameArea().Height() );
1079 if ( getFrameArea().Width() != pParent
->getFramePrintArea().Width() )
1080 Prepare( PrepareHint::FixSizeChanged
);
1085 //I'm a direct follower of my master now
1086 static_cast<SwContentFrame
*>(GetPrev())->Prepare( PrepareHint::FollowFollows
);
1089 if ( GetPrev()->getFrameArea().Height() !=
1090 GetPrev()->getFramePrintArea().Height() + GetPrev()->getFramePrintArea().Top() )
1092 // Take the border into account?
1093 GetPrev()->InvalidatePrt_();
1095 // OD 18.02.2003 #104989# - force complete paint of previous frame,
1096 // if frame is inserted at the end of a section frame, in order to
1097 // get subsidiary lines repainted for the section.
1098 if ( pParent
->IsSctFrame() && !GetNext() )
1100 // force complete paint of previous frame, if new inserted frame
1101 // in the section is the last one.
1102 GetPrev()->SetCompletePaint();
1104 GetPrev()->InvalidatePage( pPage
);
1107 if ( IsInFootnote() )
1109 SwFrame
* pFrame
= GetIndPrev();
1110 if( pFrame
&& pFrame
->IsSctFrame() )
1111 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1113 pFrame
->Prepare( PrepareHint::QuoVadis
, nullptr, false );
1116 pFrame
= FindFootnoteFrame()->GetNext();
1117 if( pFrame
&& nullptr != (pFrame
=static_cast<SwLayoutFrame
*>(pFrame
)->ContainsAny()) )
1118 pFrame
->InvalidatePrt_();
1122 InvalidateLineNum_();
1123 SwFrame
*pNxt
= FindNextCnt();
1127 while ( pNxt
&& pNxt
->IsInTab() )
1129 pNxt
= pNxt
->FindTabFrame();
1130 if( nullptr != pNxt
)
1131 pNxt
= pNxt
->FindNextCnt();
1135 pNxt
->InvalidateLineNum_();
1136 if ( pNxt
!= GetNext() )
1137 pNxt
->InvalidatePage();
1141 void SwContentFrame::Cut()
1143 OSL_ENSURE( GetUpper(), "Cut without Upper()." );
1145 SwPageFrame
*pPage
= FindPageFrame();
1146 InvalidatePage( pPage
);
1147 SwFrame
*pFrame
= GetIndPrev();
1150 if( pFrame
->IsSctFrame() )
1151 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1152 if ( pFrame
&& pFrame
->IsContentFrame() )
1154 pFrame
->InvalidatePrt_();
1155 if( IsInFootnote() )
1156 pFrame
->Prepare( PrepareHint::QuoVadis
, nullptr, false );
1158 // #i26250# - invalidate printing area of previous
1160 else if ( pFrame
&& pFrame
->IsTabFrame() )
1162 pFrame
->InvalidatePrt();
1166 SwFrame
*pNxt
= FindNextCnt();
1169 while ( pNxt
&& pNxt
->IsInTab() )
1171 pNxt
= pNxt
->FindTabFrame();
1172 if( nullptr != pNxt
)
1173 pNxt
= pNxt
->FindNextCnt();
1177 pNxt
->InvalidateLineNum_();
1178 if ( pNxt
!= GetNext() )
1179 pNxt
->InvalidatePage();
1183 SwTabFrame
* pMasterTab(nullptr);
1184 pFrame
= GetIndNext();
1187 // The old follow may have calculated a gap to the predecessor which
1188 // now becomes obsolete or different as it becomes the first one itself
1189 pFrame
->InvalidatePrt_();
1190 pFrame
->InvalidatePos_();
1191 pFrame
->InvalidatePage( pPage
);
1192 if( pFrame
->IsSctFrame() )
1194 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1197 pFrame
->InvalidatePrt_();
1198 pFrame
->InvalidatePos_();
1199 pFrame
->InvalidatePage( pPage
);
1202 if( pFrame
&& IsInFootnote() )
1203 pFrame
->Prepare( PrepareHint::ErgoSum
, nullptr, false );
1204 if( IsInSct() && !GetPrev() )
1206 SwSectionFrame
* pSct
= FindSctFrame();
1207 if( !pSct
->IsFollow() )
1209 pSct
->InvalidatePrt_();
1210 pSct
->InvalidatePage( pPage
);
1216 InvalidateNextPos();
1217 //Someone needs to do the retouching: predecessor or upper
1219 if ( nullptr != pFrame
)
1220 { pFrame
->SetRetouche();
1221 pFrame
->Prepare( PrepareHint::WidowsOrphans
);
1222 pFrame
->InvalidatePos_();
1223 pFrame
->InvalidatePage( pPage
);
1225 // If I'm (was) the only ContentFrame in my upper, it has to do the
1226 // retouching. Also, perhaps a page became empty.
1228 { SwRootFrame
*pRoot
= getRootFrame();
1231 pRoot
->SetSuperfluous();
1232 // RemoveSuperfluous can only remove empty pages at the end;
1233 // find if there are pages without content following pPage
1234 // and if so request a call to CheckPageDescs()
1235 SwViewShell
*pSh
= pRoot
->GetCurrShell();
1236 // tdf#152983 pPage is null when called from SwHeadFootFrame ctor
1237 if (pPage
&& pSh
&& pSh
->Imp()->IsAction())
1239 SwPageFrame
const* pNext(pPage
);
1240 while ((pNext
= static_cast<SwPageFrame
const*>(pNext
->GetNext())))
1242 if (!sw::IsPageFrameEmpty(*pNext
) && !pNext
->IsFootnotePage())
1244 pSh
->Imp()->GetLayAction().SetCheckPageNum(pPage
->GetPhyPageNum());
1249 GetUpper()->SetCompletePaint();
1250 GetUpper()->InvalidatePage( pPage
);
1254 SwSectionFrame
* pSct
= FindSctFrame();
1255 if( !pSct
->IsFollow() )
1257 pSct
->InvalidatePrt_();
1258 pSct
->InvalidatePage( pPage
);
1261 // #i52253# The master table should take care
1262 // of removing the follow flow line.
1265 SwTabFrame
* pThisTab
= FindTabFrame();
1266 if (pThisTab
&& pThisTab
->IsFollow())
1268 pMasterTab
= pThisTab
->FindMaster();
1273 //Remove first, then shrink the upper.
1274 SwLayoutFrame
*pUp
= GetUpper();
1278 assert(!pMasterTab
);
1283 && !pMasterTab
->GetFollow()->GetFirstNonHeadlineRow()->ContainsContent())
1284 { // only do this if there's no content in other cells of the row!
1285 pMasterTab
->InvalidatePos_();
1286 pMasterTab
->SetRemoveFollowFlowLinePending(true);
1289 SwSectionFrame
*pSct
= nullptr;
1290 if ( !pUp
->Lower() &&
1291 ( ( pUp
->IsFootnoteFrame() && !pUp
->IsColLocked() ) ||
1294 // We have to consider the case that the section may be "empty"
1295 // except from a temporary empty table frame.
1296 // This can happen due to the new cell split feature.
1297 !pUp
->IsCellFrame() &&
1298 // #126020# - adjust check for empty section
1299 // #130797# - correct fix #126020#
1300 !(pSct
= pUp
->FindSctFrame())->ContainsContent() &&
1301 !pSct
->ContainsAny( true ) ) ) )
1303 if ( pUp
->GetUpper() )
1306 // prevent delete of <ColLocked> footnote frame
1307 if ( pUp
->IsFootnoteFrame() && !pUp
->IsColLocked())
1309 if( pUp
->GetNext() && !pUp
->GetPrev() )
1311 SwFrame
* pTmp
= static_cast<SwLayoutFrame
*>(pUp
->GetNext())->ContainsAny();
1313 pTmp
->InvalidatePrt_();
1315 if (!pUp
->IsDeleteForbidden())
1318 SwFrame::DestroyFrame(pUp
);
1324 if ( pSct
->IsColLocked() || !pSct
->IsInFootnote() ||
1325 ( pUp
->IsFootnoteFrame() && pUp
->IsColLocked() ) )
1327 pSct
->DelEmpty( false );
1328 // If a locked section may not be deleted then at least
1329 // its size became invalid after removing its last
1331 pSct
->InvalidateSize_();
1335 pSct
->DelEmpty( true );
1336 SwFrame::DestroyFrame(pSct
);
1343 SwRectFnSet
aRectFnSet(this);
1344 tools::Long nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
1346 pUp
->Shrink( nFrameHeight
);
1350 void SwLayoutFrame::Paste( SwFrame
* pParent
, SwFrame
* pSibling
)
1352 OSL_ENSURE( pParent
, "No parent for pasting." );
1353 OSL_ENSURE( pParent
->IsLayoutFrame(), "Parent is ContentFrame." );
1354 OSL_ENSURE( pParent
!= this, "I'm the parent oneself." );
1355 OSL_ENSURE( pSibling
!= this, "I'm my own neighbour." );
1356 OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
1357 "I'm still registered somewhere." );
1359 //Insert in the tree.
1360 InsertBefore( static_cast<SwLayoutFrame
*>(pParent
), pSibling
);
1362 // OD 24.10.2002 #103517# - correct setting of variable <fnRect>
1363 // <fnRect> is used for the following:
1364 // (1) To invalidate the frame's size, if its size, which has to be the
1365 // same as its upper/parent, differs from its upper's/parent's.
1366 // (2) To adjust/grow the frame's upper/parent, if it has a dimension in its
1367 // size, which is not determined by its upper/parent.
1368 // Which size is which depends on the frame type and the layout direction
1369 // (vertical or horizontal).
1370 // There are the following cases:
1371 // (A) Header and footer frames both in vertical and in horizontal layout
1372 // have to size the width to the upper/parent. A dimension in the height
1373 // has to cause an adjustment/grow of the upper/parent.
1374 // --> <fnRect> = fnRectHori
1375 // (B) Cell and column frames in vertical layout, the width has to be the
1376 // same as upper/parent and a dimension in height causes adjustment/grow
1377 // of the upper/parent.
1378 // --> <fnRect> = fnRectHori
1379 // in horizontal layout the other way around
1380 // --> <fnRect> = fnRectVert
1381 // (C) Other frames in vertical layout, the height has to be the
1382 // same as upper/parent and a dimension in width causes adjustment/grow
1383 // of the upper/parent.
1384 // --> <fnRect> = fnRectVert
1385 // in horizontal layout the other way around
1386 // --> <fnRect> = fnRectHori
1387 //SwRectFn fnRect = IsVertical() ? fnRectHori : fnRectVert;
1389 if ( IsHeaderFrame() || IsFooterFrame() )
1390 fnRect
= fnRectHori
;
1391 else if ( IsCellFrame() || IsColumnFrame() )
1392 fnRect
= GetUpper()->IsVertical() ? fnRectHori
: ( GetUpper()->IsVertLR() ? (GetUpper()->IsVertLRBT() ? fnRectVertL2RB2T
: fnRectVertL2R
) : fnRectVert
);
1394 fnRect
= GetUpper()->IsVertical() ? ( GetUpper()->IsVertLR() ? (GetUpper()->IsVertLRBT() ? fnRectVertL2RB2T
: fnRectVertL2R
) : fnRectVert
) : fnRectHori
;
1396 if( (getFrameArea().*fnRect
->fnGetWidth
)() != (pParent
->getFramePrintArea().*fnRect
->fnGetWidth
)())
1399 const SwPageFrame
*pPage
= FindPageFrame();
1400 InvalidatePage( pPage
);
1401 if( !IsColumnFrame() )
1403 SwFrame
*pFrame
= GetIndNext();
1404 if( nullptr != pFrame
)
1406 pFrame
->InvalidatePos_();
1407 if( IsInFootnote() )
1409 if( pFrame
->IsSctFrame() )
1410 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1412 pFrame
->Prepare( PrepareHint::ErgoSum
, nullptr, false );
1415 if ( IsInFootnote() && nullptr != ( pFrame
= GetIndPrev() ) )
1417 if( pFrame
->IsSctFrame() )
1418 pFrame
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1420 pFrame
->Prepare( PrepareHint::QuoVadis
, nullptr, false );
1424 if( !(getFrameArea().*fnRect
->fnGetHeight
)() )
1427 // AdjustNeighbourhood is now also called in columns which are not
1428 // placed inside a frame
1429 SwNeighbourAdjust nAdjust
= GetUpper()->IsFootnoteBossFrame() ?
1430 static_cast<SwFootnoteBossFrame
*>(GetUpper())->NeighbourhoodAdjustment()
1431 : SwNeighbourAdjust::GrowShrink
;
1432 SwTwips nGrow
= (getFrameArea().*fnRect
->fnGetHeight
)();
1433 if( SwNeighbourAdjust::OnlyAdjust
== nAdjust
)
1434 AdjustNeighbourhood( nGrow
);
1438 if( SwNeighbourAdjust::AdjustGrow
== nAdjust
)
1439 nReal
= AdjustNeighbourhood( nGrow
);
1441 nReal
+= pParent
->Grow( nGrow
- nReal
);
1442 if( SwNeighbourAdjust::GrowAdjust
== nAdjust
&& nReal
< nGrow
)
1443 AdjustNeighbourhood( nGrow
- nReal
);
1447 void SwLayoutFrame::Cut()
1450 GetNext()->InvalidatePos_();
1452 SwRectFnSet
aRectFnSet(this);
1453 SwTwips nShrink
= aRectFnSet
.GetHeight(getFrameArea());
1455 // Remove first, then shrink upper.
1456 SwLayoutFrame
*pUp
= GetUpper();
1458 // AdjustNeighbourhood is now also called in columns which are not
1459 // placed inside a frame.
1461 // Remove must not be called before an AdjustNeighbourhood, but it has to
1462 // be called before the upper-shrink-call, if the upper-shrink takes care
1464 if ( pUp
&& nShrink
)
1466 if( pUp
->IsFootnoteBossFrame() )
1468 SwNeighbourAdjust nAdjust
= static_cast<SwFootnoteBossFrame
*>(pUp
)->NeighbourhoodAdjustment();
1469 if( SwNeighbourAdjust::OnlyAdjust
== nAdjust
)
1470 AdjustNeighbourhood( -nShrink
);
1474 if( SwNeighbourAdjust::AdjustGrow
== nAdjust
)
1475 nReal
= -AdjustNeighbourhood( -nShrink
);
1476 if( nReal
< nShrink
)
1478 const SwTwips nOldHeight
= aRectFnSet
.GetHeight(getFrameArea());
1480 // seems as if this needs to be forwarded to the SwFrame already here,
1481 // changing to zero seems temporary anyways
1483 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1484 aRectFnSet
.SetHeight( aFrm
, 0 );
1487 nReal
+= pUp
->Shrink( nShrink
- nReal
);
1490 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1491 aRectFnSet
.SetHeight( aFrm
, nOldHeight
);
1495 if( SwNeighbourAdjust::GrowAdjust
== nAdjust
&& nReal
< nShrink
)
1496 AdjustNeighbourhood( nReal
- nShrink
);
1503 pUp
->Shrink( nShrink
);
1509 if( pUp
&& !pUp
->Lower() )
1511 pUp
->SetCompletePaint();
1512 pUp
->InvalidatePage();
1516 SwTwips
SwFrame::Grow( SwTwips nDist
, bool bTst
, bool bInfo
)
1518 OSL_ENSURE( nDist
>= 0, "Negative growth?" );
1520 PROTOCOL_ENTER( this, bTst
? PROT::GrowTest
: PROT::Grow
, DbgAction::NONE
, &nDist
)
1524 SwRectFnSet
aRectFnSet(this);
1526 SwTwips nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
1527 if( nPrtHeight
> 0 && nDist
> (LONG_MAX
- nPrtHeight
) )
1528 nDist
= LONG_MAX
- nPrtHeight
;
1531 return static_cast<SwFlyFrame
*>(this)->Grow_( nDist
, bTst
);
1532 else if( IsSctFrame() )
1533 return static_cast<SwSectionFrame
*>(this)->Grow_( nDist
, bTst
);
1538 const SwCellFrame
* pThisCell
= static_cast<const SwCellFrame
*>(this);
1539 const SwTabFrame
* pTab
= FindTabFrame();
1542 if ( pTab
->IsVertical() != IsVertical() ||
1543 pThisCell
->GetLayoutRowSpan() < 1 )
1546 const SwTwips nReal
= GrowFrame( nDist
, bTst
, bInfo
);
1549 nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
1551 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1552 aRectFnSet
.SetHeight( aPrt
, nPrtHeight
+ ( IsContentFrame() ? nDist
: nReal
) );
1560 SwTwips
SwFrame::Shrink( SwTwips nDist
, bool bTst
, bool bInfo
)
1562 OSL_ENSURE( nDist
>= 0, "Negative reduction?" );
1564 PROTOCOL_ENTER( this, bTst
? PROT::ShrinkTest
: PROT::Shrink
, DbgAction::NONE
, &nDist
)
1569 return static_cast<SwFlyFrame
*>(this)->Shrink_( nDist
, bTst
);
1570 else if( IsSctFrame() )
1571 return static_cast<SwSectionFrame
*>(this)->Shrink_( nDist
, bTst
);
1576 const SwCellFrame
* pThisCell
= static_cast<const SwCellFrame
*>(this);
1577 const SwTabFrame
* pTab
= FindTabFrame();
1580 if ( (pTab
&& pTab
->IsVertical() != IsVertical()) ||
1581 pThisCell
->GetLayoutRowSpan() < 1 )
1584 SwRectFnSet
aRectFnSet(this);
1585 SwTwips nReal
= aRectFnSet
.GetHeight(getFrameArea());
1586 ShrinkFrame( nDist
, bTst
, bInfo
);
1587 nReal
-= aRectFnSet
.GetHeight(getFrameArea());
1590 const SwTwips nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
1591 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1592 aRectFnSet
.SetHeight( aPrt
, nPrtHeight
- ( IsContentFrame() ? nDist
: nReal
) );
1600 /** Adjust surrounding neighbourhood after insertion
1602 * A Frame needs "normalization" if it is directly placed below a footnote boss (page/column) and its
1603 * size changes. There is always a frame that takes the maximum possible space (the frame that
1604 * contains the Body text) and zero or more frames which only take the space needed (header/footer
1605 * area, footnote container). If one of these frames changes, the body-text-frame has to grow or
1606 * shrink accordingly, even though it's fixed.
1608 * !! Is it possible to do this in a generic way and not restrict it to the page and a distinct
1609 * frame which takes the maximum space (controlled using the FrameSize attribute)?
1611 * - What if multiple frames taking the maximum space are placed next to each other?
1612 * - How is the maximum space calculated?
1613 * - How small can those frames become?
1615 * In any case, only a certain amount of space is allowed, so we never go below a minimum value for
1616 * the height of the body.
1618 * @param nDiff the value around which the space has to be allocated
1620 SwTwips
SwFrame::AdjustNeighbourhood( SwTwips nDiff
, bool bTst
)
1622 PROTOCOL_ENTER( this, PROT::AdjustN
, DbgAction::NONE
, &nDiff
);
1624 if ( !nDiff
|| !GetUpper()->IsFootnoteBossFrame() ) // only inside pages/columns
1627 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
1628 const bool bBrowse
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
1630 //The (Page-)Body only changes in BrowseMode, but only if it does not
1632 if ( IsPageBodyFrame() && (!bBrowse
||
1633 (static_cast<SwLayoutFrame
*>(this)->Lower() &&
1634 static_cast<SwLayoutFrame
*>(this)->Lower()->IsColumnFrame())) )
1637 //In BrowseView mode the PageFrame can handle some of the requests.
1638 tools::Long nBrowseAdd
= 0;
1639 if ( bBrowse
&& GetUpper()->IsPageFrame() ) // only (Page-)BodyFrames
1641 SwViewShell
*pViewShell
= getRootFrame()->GetCurrShell();
1642 SwLayoutFrame
*pUp
= GetUpper();
1644 const tools::Long nUpPrtBottom
= pUp
->getFrameArea().Height() -
1645 pUp
->getFramePrintArea().Height() - pUp
->getFramePrintArea().Top();
1646 SwRect
aInva( pUp
->getFrameArea() );
1649 aInva
.Pos().setX( pViewShell
->VisArea().Left() );
1650 aInva
.Width( pViewShell
->VisArea().Width() );
1654 nChg
= BROWSE_HEIGHT
- pUp
->getFrameArea().Height();
1655 nChg
= std::min( nDiff
, SwTwips(nChg
) );
1657 if ( !IsBodyFrame() )
1660 if ( !pViewShell
|| pViewShell
->VisArea().Height() >= pUp
->getFrameArea().Height() )
1662 //First minimize Body, it will grow again later.
1663 SwFrame
*pBody
= static_cast<SwFootnoteBossFrame
*>(pUp
)->FindBodyCont();
1664 const tools::Long nTmp
= nChg
- pBody
->getFramePrintArea().Height();
1668 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pBody
);
1669 aFrm
.Height(std::max( tools::Long(0), aFrm
.Height() - nChg
));
1672 pBody
->InvalidatePrt_();
1673 pBody
->InvalidateSize_();
1674 if ( pBody
->GetNext() )
1675 pBody
->GetNext()->InvalidatePos_();
1676 if ( !IsHeaderFrame() )
1677 pBody
->SetCompletePaint();
1679 nChg
= nTmp
<= 0 ? 0 : nTmp
;
1683 const tools::Long nTmp
= nUpPrtBottom
+ 20;
1684 aInva
.Top( aInva
.Bottom() - nTmp
);
1685 aInva
.Height( nChg
+ nTmp
);
1689 //The page can shrink to 0. The first page keeps the same size like
1692 tools::Long nInvaAdd
= 0;
1693 if ( pViewShell
&& !pUp
->GetPrev() &&
1694 pUp
->getFrameArea().Height() + nDiff
< pViewShell
->VisArea().Height() )
1696 // This means that we have to invalidate adequately.
1697 nChg
= pViewShell
->VisArea().Height() - pUp
->getFrameArea().Height();
1698 nInvaAdd
= -(nDiff
- nChg
);
1701 //Invalidate including bottom border.
1702 tools::Long nBorder
= nUpPrtBottom
+ 20;
1704 aInva
.Top( aInva
.Bottom() - (nBorder
+nInvaAdd
) );
1705 if ( !IsBodyFrame() )
1708 if ( !IsHeaderFrame() )
1709 static_cast<SwFootnoteBossFrame
*>(pUp
)->FindBodyCont()->SetCompletePaint();
1711 //Invalidate the page because of the frames. Thereby the page becomes
1712 //the right size again if a frame didn't fit. This only works
1713 //randomly for paragraph bound frames otherwise (NotifyFlys).
1714 pUp
->InvalidateSize();
1718 //Independent from nChg
1719 if ( pViewShell
&& aInva
.HasArea() && pUp
->GetUpper() )
1720 pViewShell
->InvalidateWindows( aInva
);
1722 if ( !bTst
&& nChg
)
1725 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pUp
);
1726 aFrm
.AddHeight(nChg
);
1730 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*pUp
);
1731 aPrt
.AddHeight(nChg
);
1735 pViewShell
->Imp()->SetFirstVisPageInvalid();
1738 GetNext()->InvalidatePos_();
1740 //Trigger a repaint if necessary.
1741 std::unique_ptr
<SvxBrushItem
> aBack(pUp
->GetFormat()->makeBackgroundBrushItem());
1742 const SvxGraphicPosition ePos
= aBack
->GetGraphicPos();
1743 if ( ePos
!= GPOS_NONE
&& ePos
!= GPOS_TILED
)
1744 pViewShell
->InvalidateWindows( pUp
->getFrameArea() );
1746 if ( pUp
->GetUpper() )
1748 if ( pUp
->GetNext() )
1749 pUp
->GetNext()->InvalidatePos();
1751 //Sad but true: during notify on ViewImp a Calc on the page and
1752 //its Lower may be called. The values should not be changed
1753 //because the caller takes care of the adjustment of Frame and
1755 const tools::Long nOldFrameHeight
= getFrameArea().Height();
1756 const tools::Long nOldPrtHeight
= getFramePrintArea().Height();
1757 const bool bOldComplete
= IsCompletePaint();
1759 if ( IsBodyFrame() )
1761 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1762 aPrt
.Height( nOldFrameHeight
);
1765 if ( pUp
->GetUpper() )
1767 static_cast<SwRootFrame
*>(pUp
->GetUpper())->CheckViewLayout( nullptr, nullptr );
1770 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
1771 aFrm
.Height( nOldFrameHeight
);
1773 SwFrameAreaDefinition::FramePrintAreaWriteAccess
aPrt(*this);
1774 aPrt
.Height( nOldPrtHeight
);
1776 mbCompletePaint
= bOldComplete
;
1778 if ( !IsBodyFrame() )
1779 pUp
->InvalidateSize_();
1780 InvalidatePage( static_cast<SwPageFrame
*>(pUp
) );
1789 const SwFootnoteBossFrame
*pBoss
= static_cast<SwFootnoteBossFrame
*>(GetUpper());
1793 SwFrame
*pFrame
= nullptr;
1794 SwRectFnSet
aRectFnSet(this);
1800 SwSectionFrame
*pSect
= FindSctFrame();
1801 if( nDiff
> 0 && pSect
->IsEndnAtEnd() && GetNext() &&
1802 GetNext()->IsFootnoteContFrame() )
1804 SwFootnoteContFrame
* pCont
= static_cast<SwFootnoteContFrame
*>(GetNext());
1806 SwFootnoteFrame
* pFootnote
= static_cast<SwFootnoteFrame
*>(pCont
->Lower());
1807 bool bFootnote
= false;
1810 if( !pFootnote
->GetAttr()->GetFootnote().IsEndNote() )
1812 nMinH
+= aRectFnSet
.GetHeight(pFootnote
->getFrameArea());
1815 pFootnote
= static_cast<SwFootnoteFrame
*>(pFootnote
->GetNext());
1818 nMinH
+= aRectFnSet
.GetTop(pCont
->getFramePrintArea());
1819 nReal
= aRectFnSet
.GetHeight(pCont
->getFrameArea()) - nMinH
;
1827 if( !bTst
&& !pSect
->IsColLocked() )
1828 pSect
->InvalidateSize();
1835 const bool bFootnotePage
= pBoss
->IsPageFrame() && static_cast<const SwPageFrame
*>(pBoss
)->IsFootnotePage();
1836 if ( bFootnotePage
&& !IsFootnoteContFrame() )
1837 pFrame
= const_cast<SwFrame
*>(static_cast<SwFrame
const *>(pBoss
->FindFootnoteCont()));
1839 pFrame
= const_cast<SwFrame
*>(static_cast<SwFrame
const *>(pBoss
->FindBodyCont()));
1844 //If not one is found, everything else is solved.
1845 nReal
= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
1848 if( !bFootnotePage
)
1850 //Respect the minimal boundary!
1853 const SwTwips nMax
= pBoss
->GetVarSpace();
1857 if( !IsFootnoteContFrame() && nDiff
> nReal
&&
1858 pFrame
->GetNext() && pFrame
->GetNext()->IsFootnoteContFrame()
1859 && ( pFrame
->GetNext()->IsVertical() == IsVertical() )
1862 //If the Body doesn't return enough, we look for a footnote, if
1863 //there is one, we steal there accordingly.
1864 const SwTwips nAddMax
= aRectFnSet
.GetHeight(pFrame
->GetNext()->getFrameArea());
1865 nAdd
= nDiff
- nReal
;
1866 if ( nAdd
> nAddMax
)
1871 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pFrame
->GetNext());
1872 aRectFnSet
.SetHeight(aFrm
, nAddMax
-nAdd
);
1874 if( aRectFnSet
.IsVert() && !aRectFnSet
.IsVertL2R() )
1876 aFrm
.Pos().AdjustX(nAdd
);
1880 pFrame
->GetNext()->InvalidatePrt();
1882 if ( pFrame
->GetNext()->GetNext() )
1884 pFrame
->GetNext()->GetNext()->InvalidatePos_();
1891 if ( !bTst
&& nReal
)
1893 SwTwips nTmp
= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
1896 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pFrame
);
1897 aRectFnSet
.SetHeight( aFrm
, nTmp
- nReal
);
1899 if( aRectFnSet
.IsVert() && !aRectFnSet
.IsVertL2R() )
1901 aFrm
.Pos().AdjustX(nReal
);
1905 pFrame
->InvalidatePrt();
1907 if ( pFrame
->GetNext() )
1908 pFrame
->GetNext()->InvalidatePos_();
1910 if( nReal
< 0 && pFrame
->IsInSct() )
1912 SwLayoutFrame
* pUp
= pFrame
->GetUpper();
1913 if( pUp
&& nullptr != ( pUp
= pUp
->GetUpper() ) && pUp
->IsSctFrame() &&
1914 !pUp
->IsColLocked() )
1915 pUp
->InvalidateSize();
1917 if( ( IsHeaderFrame() || IsFooterFrame() ) && pBoss
->GetDrawObjs() )
1919 const SwSortedObjs
&rObjs
= *pBoss
->GetDrawObjs();
1920 OSL_ENSURE( pBoss
->IsPageFrame(), "Header/Footer out of page?" );
1921 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
1923 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
1925 OSL_ENSURE( !pFly
->IsFlyInContentFrame(), "FlyInCnt at Page?" );
1926 const SwFormatVertOrient
&rVert
=
1927 pFly
->GetFormat()->GetVertOrient();
1928 // When do we have to invalidate?
1929 // If a frame is aligned on a PageTextArea and the header
1930 // changes a TOP, MIDDLE or NONE aligned frame needs to
1931 // recalculate it's position; if the footer changes a BOTTOM
1932 // or MIDDLE aligned frame needs to recalculate it's
1934 if( ( rVert
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
||
1935 rVert
.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA
) &&
1936 ((IsHeaderFrame() && rVert
.GetVertOrient()!=text::VertOrientation::BOTTOM
) ||
1937 (IsFooterFrame() && rVert
.GetVertOrient()!=text::VertOrientation::NONE
&&
1938 rVert
.GetVertOrient() != text::VertOrientation::TOP
)) )
1940 pFly
->InvalidatePos_();
1941 pFly
->Invalidate_();
1947 return (nBrowseAdd
+ nReal
+ nAdd
);
1950 /** method to perform additional actions on an invalidation (2004-05-19 #i28701#) */
1951 void SwFrame::ActionOnInvalidation( const InvalidationType
)
1953 // default behaviour is to perform no additional action
1956 /** method to determine, if an invalidation is allowed (2004-05-19 #i28701#) */
1957 bool SwFrame::InvalidationAllowed( const InvalidationType
) const
1959 // default behaviour is to allow invalidation
1963 void SwFrame::ImplInvalidateSize()
1965 if ( InvalidationAllowed( INVALID_SIZE
) )
1967 setFrameAreaSizeValid(false);
1970 static_cast<SwFlyFrame
*>(this)->Invalidate_();
1974 // OD 2004-05-19 #i28701#
1975 ActionOnInvalidation( INVALID_SIZE
);
1979 void SwFrame::ImplInvalidatePrt()
1981 if ( InvalidationAllowed( INVALID_PRTAREA
) )
1983 setFramePrintAreaValid(false);
1986 static_cast<SwFlyFrame
*>(this)->Invalidate_();
1990 // OD 2004-05-19 #i28701#
1991 ActionOnInvalidation( INVALID_PRTAREA
);
1995 void SwFrame::ImplInvalidatePos()
1997 if ( !InvalidationAllowed( INVALID_POS
) )
2000 setFrameAreaPositionValid(false);
2004 static_cast<SwFlyFrame
*>(this)->Invalidate_();
2011 // OD 2004-05-19 #i28701#
2012 ActionOnInvalidation( INVALID_POS
);
2015 void SwFrame::ImplInvalidateLineNum()
2017 if ( InvalidationAllowed( INVALID_LINENUM
) )
2019 mbValidLineNum
= false;
2020 OSL_ENSURE( IsTextFrame(), "line numbers are implemented for text only" );
2023 // OD 2004-05-19 #i28701#
2024 ActionOnInvalidation( INVALID_LINENUM
);
2028 void SwFrame::ReinitializeFrameSizeAttrFlags()
2030 const SwFormatFrameSize
&rFormatSize
= GetAttrSet()->GetFrameSize();
2031 if ( SwFrameSize::Variable
== rFormatSize
.GetHeightSizeType() ||
2032 SwFrameSize::Minimum
== rFormatSize
.GetHeightSizeType())
2035 if ( GetType() & (SwFrameType::Header
| SwFrameType::Footer
| SwFrameType::Row
) )
2037 SwFrame
*pFrame
= static_cast<SwLayoutFrame
*>(this)->Lower();
2039 { pFrame
->InvalidateSize_();
2040 pFrame
->InvalidatePrt_();
2041 pFrame
= pFrame
->GetNext();
2043 SwContentFrame
*pCnt
= static_cast<SwLayoutFrame
*>(this)->ContainsContent();
2044 // #i36991# - be save.
2045 // E.g., a row can contain *no* content.
2048 pCnt
->InvalidatePage();
2051 pCnt
->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
2052 pCnt
->InvalidateSize_();
2053 pCnt
= pCnt
->GetNextContentFrame();
2054 } while ( static_cast<SwLayoutFrame
*>(this)->IsAnLower( pCnt
) );
2058 else if ( rFormatSize
.GetHeightSizeType() == SwFrameSize::Fixed
)
2061 ChgSize( Size( rFormatSize
.GetWidth(), getFrameArea().Height()));
2063 ChgSize( Size( getFrameArea().Width(), rFormatSize
.GetHeight()));
2067 void SwFrame::ValidateThisAndAllLowers( const sal_uInt16 nStage
)
2069 // Stage 0: Only validate frames. Do not process any objects.
2070 // Stage 1: Only validate fly frames and all of their contents.
2071 // Stage 2: Validate all.
2073 const bool bOnlyObject
= 1 == nStage
;
2074 const bool bIncludeObjects
= 1 <= nStage
;
2076 if ( !bOnlyObject
|| IsFlyFrame() )
2078 setFrameAreaSizeValid(true);
2079 setFramePrintAreaValid(true);
2080 setFrameAreaPositionValid(true);
2083 if ( bIncludeObjects
)
2085 const SwSortedObjs
* pObjs
= GetDrawObjs();
2088 const size_t nCnt
= pObjs
->size();
2089 for ( size_t i
= 0; i
< nCnt
; ++i
)
2091 SwAnchoredObject
* pAnchObj
= (*pObjs
)[i
];
2092 if ( auto pFlyFrame
= pAnchObj
->DynCastFlyFrame() )
2093 pFlyFrame
->ValidateThisAndAllLowers( 2 );
2094 else if ( auto pAnchoredDrawObj
= dynamic_cast<SwAnchoredDrawObject
*>( pAnchObj
) )
2095 pAnchoredDrawObj
->ValidateThis();
2100 if ( IsLayoutFrame() )
2102 SwFrame
* pLower
= static_cast<SwLayoutFrame
*>(this)->Lower();
2105 pLower
->ValidateThisAndAllLowers( nStage
);
2106 pLower
= pLower
->GetNext();
2111 SwTwips
SwContentFrame::GrowFrame( SwTwips nDist
, bool bTst
, bool bInfo
)
2113 SwRectFnSet
aRectFnSet(this);
2115 SwTwips nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
2116 if( nFrameHeight
> 0 &&
2117 nDist
> (LONG_MAX
- nFrameHeight
) )
2118 nDist
= LONG_MAX
- nFrameHeight
;
2120 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
2121 const bool bBrowse
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
2122 SwFrameType nTmpType
= SwFrameType::Cell
| SwFrameType::Column
;
2124 nTmpType
|= SwFrameType::Body
;
2125 if( !(GetUpper()->GetType() & nTmpType
) && GetUpper()->HasFixSize() )
2130 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2131 aRectFnSet
.SetHeight( aFrm
, nFrameHeight
+ nDist
);
2133 if( IsVertical() && !IsVertLR() )
2135 aFrm
.Pos().AdjustX( -nDist
);
2141 GetNext()->InvalidatePos();
2143 // #i28701# - Due to the new object positioning the
2144 // frame on the next page/column can flow backward (e.g. it was moved forward
2145 // due to the positioning of its objects ). Thus, invalivate this next frame,
2146 // if document compatibility option 'Consider wrapping style influence on
2147 // object positioning' is ON.
2148 else if ( GetUpper()->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
) )
2150 InvalidateNextPos();
2156 SwTwips nReal
= aRectFnSet
.GetHeight(GetUpper()->getFramePrintArea());
2157 SwFrame
*pFrame
= GetUpper()->Lower();
2158 while( pFrame
&& nReal
> 0 )
2159 { nReal
-= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
2160 pFrame
= pFrame
->GetNext();
2165 //Contents are always resized to the wished value.
2166 tools::Long nOld
= aRectFnSet
.GetHeight(getFrameArea());
2169 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2171 aRectFnSet
.SetHeight( aFrm
, nOld
+ nDist
);
2173 if( IsVertical()&& !IsVertLR() )
2175 aFrm
.Pos().AdjustX( -nDist
);
2179 SwTabFrame
*pTab
= (nOld
&& IsInTab()) ? FindTabFrame() : nullptr;
2182 if ( pTab
->GetTable()->GetHTMLTableLayout() &&
2183 !pTab
->IsJoinLocked() &&
2184 !pTab
->GetFormat()->GetDoc()->GetDocShell()->IsReadOnly() )
2186 pTab
->InvalidatePos();
2187 pTab
->SetResizeHTMLTable();
2192 //Only grow Upper if necessary.
2193 if ( nReal
< nDist
)
2197 if( bTst
|| !GetUpper()->IsFooterFrame() )
2198 nReal
= GetUpper()->Grow( nDist
- std::max
<tools::Long
>(nReal
, 0),
2203 GetUpper()->InvalidateSize();
2212 // #i28701# - Due to the new object positioning the
2213 // frame on the next page/column can flow backward (e.g. it was moved forward
2214 // due to the positioning of its objects ). Thus, invalivate this next frame,
2215 // if document compatibility option 'Consider wrapping style influence on
2216 // object positioning' is ON.
2221 GetNext()->InvalidatePos();
2223 else if ( GetUpper()->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
) )
2225 InvalidateNextPos();
2232 SwTwips
SwContentFrame::ShrinkFrame( SwTwips nDist
, bool bTst
, bool bInfo
)
2234 SwRectFnSet
aRectFnSet(this);
2235 OSL_ENSURE( nDist
>= 0, "nDist < 0" );
2236 OSL_ENSURE( nDist
<= aRectFnSet
.GetHeight(getFrameArea()),
2237 "nDist > than current size." );
2243 nRstHeight
= aRectFnSet
.BottomDist( getFrameArea(), aRectFnSet
.GetPrtBottom(*GetUpper()) );
2246 if( nRstHeight
< 0 )
2248 SwTwips nNextHeight
= 0;
2249 if( GetUpper()->IsSctFrame() && nDist
> LONG_MAX
/2 )
2251 SwFrame
*pNxt
= GetNext();
2254 nNextHeight
+= aRectFnSet
.GetHeight(pNxt
->getFrameArea());
2255 pNxt
= pNxt
->GetNext();
2258 nRstHeight
= nDist
+ nRstHeight
- nNextHeight
;
2266 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2267 aRectFnSet
.SetHeight( aFrm
, aRectFnSet
.GetHeight(aFrm
) - nDist
);
2269 if( IsVertical() && !IsVertLR() )
2271 aFrm
.Pos().AdjustX(nDist
);
2276 SwTabFrame
*pTab
= IsInTab() ? FindTabFrame() : nullptr;
2279 if ( pTab
->GetTable()->GetHTMLTableLayout() &&
2280 !pTab
->IsJoinLocked() &&
2281 !pTab
->GetFormat()->GetDoc()->GetDocShell()->IsReadOnly() )
2283 pTab
->InvalidatePos();
2284 pTab
->SetResizeHTMLTable();
2290 if( GetUpper() && nDist
> 0 )
2292 if( bTst
|| !GetUpper()->IsFooterFrame() )
2293 nReal
= GetUpper()->Shrink( nDist
, bTst
, bInfo
);
2298 // #108745# Sorry, dear old footer friend, I'm not gonna invalidate you,
2299 // if there are any objects anchored inside your content, which
2300 // overlap with the shrinking frame.
2301 // This may lead to a footer frame that is too big, but this is better
2303 // #109722# : The fix for #108745# was too strict.
2305 bool bInvalidate
= true;
2306 const SwRect
aRect( getFrameArea() );
2307 const SwPageFrame
* pPage
= FindPageFrame();
2308 const SwSortedObjs
* pSorted
= pPage
? pPage
->GetSortedObjs() : nullptr;
2311 for (SwAnchoredObject
* pAnchoredObj
: *pSorted
)
2313 const SwRect
aBound( pAnchoredObj
->GetObjRectWithSpaces() );
2315 if( aBound
.Left() > aRect
.Right() )
2318 if( aBound
.Overlaps( aRect
) )
2320 const SwFrameFormat
& rFormat
= pAnchoredObj
->GetFrameFormat();
2321 if( css::text::WrapTextMode_THROUGH
!= rFormat
.GetSurround().GetSurround() )
2323 const SwFrame
* pAnchor
= pAnchoredObj
->GetAnchorFrame();
2324 if ( pAnchor
&& pAnchor
->FindFooterOrHeader() == GetUpper() )
2326 bInvalidate
= false;
2335 GetUpper()->InvalidateSize();
2343 //The position of the next Frame changes for sure.
2344 InvalidateNextPos();
2346 //If I don't have a successor I have to do the retouch by myself.
2353 void SwContentFrame::SwClientNotify(const SwModify
& rMod
, const SfxHint
& rHint
)
2355 if (rHint
.GetId() != SfxHintId::SwLegacyModify
)
2357 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
2358 SwContentFrameInvFlags eInvFlags
= SwContentFrameInvFlags::NONE
;
2359 if(pLegacy
->m_pNew
&& RES_ATTRSET_CHG
== pLegacy
->m_pNew
->Which() && pLegacy
->m_pOld
)
2361 auto& rOldSetChg
= *static_cast<const SwAttrSetChg
*>(pLegacy
->m_pOld
);
2362 auto& rNewSetChg
= *static_cast<const SwAttrSetChg
*>(pLegacy
->m_pNew
);
2363 SfxItemIter
aOIter(*rOldSetChg
.GetChgSet());
2364 SfxItemIter
aNIter(*rNewSetChg
.GetChgSet());
2365 const SfxPoolItem
* pNItem
= aNIter
.GetCurItem();
2366 const SfxPoolItem
* pOItem
= aOIter
.GetCurItem();
2367 SwAttrSetChg
aOldSet(rOldSetChg
);
2368 SwAttrSetChg
aNewSet(rNewSetChg
);
2371 UpdateAttr_(pOItem
, pNItem
, eInvFlags
, &aOldSet
, &aNewSet
);
2372 pNItem
= aNIter
.NextItem();
2373 pOItem
= aOIter
.NextItem();
2375 if(aOldSet
.Count() || aNewSet
.Count())
2376 SwFrame::SwClientNotify(rMod
, sw::LegacyModifyHint(&aOldSet
, &aNewSet
));
2379 UpdateAttr_(pLegacy
->m_pOld
, pLegacy
->m_pNew
, eInvFlags
);
2381 if(eInvFlags
== SwContentFrameInvFlags::NONE
)
2384 SwPageFrame
* pPage
= FindPageFrame();
2385 InvalidatePage(pPage
);
2386 if(eInvFlags
& SwContentFrameInvFlags::SetCompletePaint
)
2388 if(eInvFlags
& SwContentFrameInvFlags::InvalidatePos
)
2390 if(eInvFlags
& SwContentFrameInvFlags::InvalidateSize
)
2392 if(eInvFlags
& (SwContentFrameInvFlags::InvalidateSectPrt
| SwContentFrameInvFlags::SetNextCompletePaint
))
2394 if(IsInSct() && !GetPrev())
2396 SwSectionFrame
* pSect
= FindSctFrame();
2397 if(pSect
->ContainsAny() == this)
2399 pSect
->InvalidatePrt_();
2400 pSect
->InvalidatePage(pPage
);
2405 SwFrame
* pNextFrame
= GetIndNext();
2406 if(pNextFrame
&& eInvFlags
& SwContentFrameInvFlags::InvalidateNextPrt
)
2408 pNextFrame
->InvalidatePrt_();
2409 pNextFrame
->InvalidatePage(pPage
);
2411 if(pNextFrame
&& eInvFlags
& SwContentFrameInvFlags::SetNextCompletePaint
)
2413 pNextFrame
->SetCompletePaint();
2415 if(eInvFlags
& SwContentFrameInvFlags::InvalidatePrevPrt
)
2417 SwFrame
* pPrevFrame
= GetPrev();
2420 pPrevFrame
->InvalidatePrt_();
2421 pPrevFrame
->InvalidatePage(pPage
);
2424 if(eInvFlags
& SwContentFrameInvFlags::InvalidateNextPos
)
2425 InvalidateNextPos();
2428 void SwContentFrame::UpdateAttr_( const SfxPoolItem
* pOld
, const SfxPoolItem
* pNew
,
2429 SwContentFrameInvFlags
&rInvFlags
,
2430 SwAttrSetChg
*pOldSet
, SwAttrSetChg
*pNewSet
)
2433 sal_uInt16 nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
2437 rInvFlags
= SwContentFrameInvFlags::SetCompletePaint
2438 | SwContentFrameInvFlags::InvalidatePos
2439 | SwContentFrameInvFlags::InvalidateSize
2440 | SwContentFrameInvFlags::InvalidateSectPrt
2441 | SwContentFrameInvFlags::InvalidateNextPrt
2442 | SwContentFrameInvFlags::InvalidatePrevPrt
2443 | SwContentFrameInvFlags::InvalidateNextPos
2444 | SwContentFrameInvFlags::SetNextCompletePaint
;
2447 case RES_PAGEDESC
: //attribute changes (on/off)
2448 if ( IsInDocBody() && !IsInTab() )
2450 rInvFlags
|= SwContentFrameInvFlags::InvalidatePos
;
2451 SwPageFrame
*pPage
= FindPageFrame();
2453 CheckPageDescs( pPage
);
2454 if (GetPageDescItem().GetNumOffset())
2455 static_cast<SwRootFrame
*>(pPage
->GetUpper())->SetVirtPageNum( true );
2456 pPage
->GetFormat()->GetDoc()->getIDocumentFieldsAccess().UpdatePageFields(pPage
->getFrameArea().Top());
2462 // OD 2004-02-18 #106629# - correction
2463 // Invalidation of the printing area of next frame, not only
2464 // for footnote content.
2465 if ( !GetIndNext() )
2467 SwFrame
* pNxt
= FindNext();
2470 SwPageFrame
* pPg
= pNxt
->FindPageFrame();
2471 pNxt
->InvalidatePage( pPg
);
2472 pNxt
->InvalidatePrt_();
2473 if( pNxt
->IsSctFrame() )
2475 SwFrame
* pCnt
= static_cast<SwSectionFrame
*>(pNxt
)->ContainsAny();
2478 pCnt
->InvalidatePrt_();
2479 pCnt
->InvalidatePage( pPg
);
2482 pNxt
->SetCompletePaint();
2485 // OD 2004-03-17 #i11860#
2486 if ( GetIndNext() &&
2487 !GetUpper()->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::USE_FORMER_OBJECT_POS
) )
2489 // OD 2004-07-01 #i28701# - use new method <InvalidateObjs(..)>
2490 GetIndNext()->InvalidateObjs();
2492 Prepare( PrepareHint::ULSpaceChanged
); //TextFrame has to correct line spacing.
2493 rInvFlags
|= SwContentFrameInvFlags::SetNextCompletePaint
;
2496 case RES_MARGIN_FIRSTLINE
:
2497 case RES_MARGIN_TEXTLEFT
:
2498 case RES_MARGIN_RIGHT
:
2503 Prepare( PrepareHint::FixSizeChanged
);
2505 SwFrame::SwClientNotify(aMod
, sw::LegacyModifyHint(pOld
, pNew
));
2506 rInvFlags
|= SwContentFrameInvFlags::InvalidateNextPrt
| SwContentFrameInvFlags::InvalidatePrevPrt
;
2511 rInvFlags
|= SwContentFrameInvFlags::InvalidatePos
| SwContentFrameInvFlags::InvalidateNextPos
;
2512 const IDocumentSettingAccess
& rIDSA
= GetUpper()->GetFormat()->getIDocumentSettingAccess();
2513 if( rIDSA
.get(DocumentSettingId::PARA_SPACE_MAX
) ||
2514 rIDSA
.get(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES
) )
2516 rInvFlags
|= SwContentFrameInvFlags::SetCompletePaint
;
2517 SwFrame
* pNxt
= FindNext();
2520 SwPageFrame
* pPg
= pNxt
->FindPageFrame();
2521 pNxt
->InvalidatePage( pPg
);
2522 pNxt
->InvalidatePrt_();
2523 if( pNxt
->IsSctFrame() )
2525 SwFrame
* pCnt
= static_cast<SwSectionFrame
*>(pNxt
)->ContainsAny();
2528 pCnt
->InvalidatePrt_();
2529 pCnt
->InvalidatePage( pPg
);
2532 pNxt
->SetCompletePaint();
2538 // OD 2004-02-26 #i25029#
2539 case RES_PARATR_CONNECT_BORDER
:
2541 rInvFlags
|= SwContentFrameInvFlags::SetCompletePaint
;
2542 if ( IsTextFrame() )
2544 InvalidateNextPrtArea();
2546 if ( !GetIndNext() && IsInTab() && IsInSplitTableRow() )
2548 FindTabFrame()->InvalidateSize();
2553 case RES_PARATR_TABSTOP
:
2554 case RES_CHRATR_SHADOWED
:
2555 case RES_CHRATR_AUTOKERN
:
2556 case RES_CHRATR_UNDERLINE
:
2557 case RES_CHRATR_OVERLINE
:
2558 case RES_CHRATR_KERNING
:
2559 case RES_CHRATR_FONT
:
2560 case RES_CHRATR_FONTSIZE
:
2561 case RES_CHRATR_ESCAPEMENT
:
2562 case RES_CHRATR_CONTOUR
:
2563 case RES_PARATR_NUMRULE
:
2564 rInvFlags
|= SwContentFrameInvFlags::SetCompletePaint
;
2568 rInvFlags
|= SwContentFrameInvFlags::SetCompletePaint
;
2577 if ( pOldSet
|| pNewSet
)
2580 pOldSet
->ClearItem( nWhich
);
2582 pNewSet
->ClearItem( nWhich
);
2587 SwFrame::SwClientNotify(aMod
, sw::LegacyModifyHint(pOld
, pNew
));
2591 SwLayoutFrame::SwLayoutFrame(SwFrameFormat
*const pFormat
, SwFrame
*const pSib
)
2592 : SwFrame(pFormat
, pSib
)
2595 const SwFormatFrameSize
&rFormatSize
= pFormat
->GetFrameSize();
2596 if ( rFormatSize
.GetHeightSizeType() == SwFrameSize::Fixed
)
2602 SwTwips
SwLayoutFrame::InnerHeight() const
2604 const SwFrame
* pCnt
= Lower();
2608 SwRectFnSet
aRectFnSet(this);
2610 if( pCnt
->IsColumnFrame() || pCnt
->IsCellFrame() )
2614 SwTwips nTmp
= static_cast<const SwLayoutFrame
*>(pCnt
)->InnerHeight();
2615 if( pCnt
->isFramePrintAreaValid() )
2616 nTmp
+= aRectFnSet
.GetHeight(pCnt
->getFrameArea()) -
2617 aRectFnSet
.GetHeight(pCnt
->getFramePrintArea());
2620 pCnt
= pCnt
->GetNext();
2627 nRet
+= aRectFnSet
.GetHeight(pCnt
->getFrameArea());
2628 if( pCnt
->IsContentFrame() && static_cast<const SwTextFrame
*>(pCnt
)->IsUndersized() )
2629 nRet
+= static_cast<const SwTextFrame
*>(pCnt
)->GetParHeight() -
2630 aRectFnSet
.GetHeight(pCnt
->getFramePrintArea());
2631 if( pCnt
->IsLayoutFrame() && !pCnt
->IsTabFrame() )
2632 nRet
+= static_cast<const SwLayoutFrame
*>(pCnt
)->InnerHeight() -
2633 aRectFnSet
.GetHeight(pCnt
->getFramePrintArea());
2634 pCnt
= pCnt
->GetNext();
2641 SwTwips
SwLayoutFrame::GrowFrame( SwTwips nDist
, bool bTst
, bool bInfo
)
2643 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
2644 const bool bBrowse
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
2645 SwFrameType nTmpType
= SwFrameType::Cell
| SwFrameType::Column
;
2647 nTmpType
|= SwFrameType::Body
;
2648 if( !(GetType() & nTmpType
) && HasFixSize() )
2651 SwRectFnSet
aRectFnSet(this);
2652 const SwTwips nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
2653 const SwTwips nFramePos
= getFrameArea().Pos().X();
2655 if ( nFrameHeight
> 0 && nDist
> (LONG_MAX
- nFrameHeight
) )
2656 nDist
= LONG_MAX
- nFrameHeight
;
2659 if ( GetUpper() && !IsCellFrame() )
2661 SwFrame
*pFrame
= GetUpper()->Lower();
2663 { nMin
+= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
2664 pFrame
= pFrame
->GetNext();
2666 nMin
= aRectFnSet
.GetHeight(GetUpper()->getFramePrintArea()) - nMin
;
2671 SwRect
aOldFrame( getFrameArea() );
2672 bool bMoveAccFrame
= false;
2674 bool bChgPos
= IsVertical();
2677 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2678 aRectFnSet
.SetHeight( aFrm
, nFrameHeight
+ nDist
);
2680 if( bChgPos
&& !IsVertLR() )
2682 aFrm
.Pos().AdjustX( -nDist
);
2685 bMoveAccFrame
= true;
2688 SwTwips nReal
= nDist
- nMin
;
2692 { // AdjustNeighbourhood now only for the columns (but not in frames)
2693 SwNeighbourAdjust nAdjust
= GetUpper()->IsFootnoteBossFrame() ?
2694 static_cast<SwFootnoteBossFrame
*>(GetUpper())->NeighbourhoodAdjustment()
2695 : SwNeighbourAdjust::GrowShrink
;
2696 if( SwNeighbourAdjust::OnlyAdjust
== nAdjust
)
2697 nReal
= AdjustNeighbourhood( nReal
, bTst
);
2700 if( SwNeighbourAdjust::AdjustGrow
== nAdjust
)
2701 nReal
+= AdjustNeighbourhood( nReal
, bTst
);
2706 SwFrame
* pToGrow
= GetUpper();
2708 // A cell with a row span of > 1 is allowed to grow the
2709 // line containing the end of the row span if it is
2710 // located in the same table frame:
2713 const SwCellFrame
* pThisCell
= static_cast<const SwCellFrame
*>(this);
2714 if ( pThisCell
->GetLayoutRowSpan() > 1 )
2716 SwCellFrame
& rEndCell
= const_cast<SwCellFrame
&>(pThisCell
->FindStartEndOfRowSpanCell( false ));
2717 if ( -1 == rEndCell
.GetTabBox()->getRowSpan() )
2718 pToGrow
= rEndCell
.GetUpper();
2723 nGrow
= pToGrow
? pToGrow
->Grow( nReal
, bTst
, bInfo
) : 0;
2726 if( SwNeighbourAdjust::GrowAdjust
== nAdjust
&& nGrow
< nReal
)
2727 nReal
= o3tl::saturating_add(nReal
, AdjustNeighbourhood( nReal
- nGrow
, bTst
));
2729 if ( IsFootnoteFrame() && (nGrow
!= nReal
) && GetNext() )
2731 //Footnotes can replace their successor.
2732 SwTwips nSpace
= bTst
? 0 : -nDist
;
2733 const SwFrame
*pFrame
= GetUpper()->Lower();
2735 { nSpace
+= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
2736 pFrame
= pFrame
->GetNext();
2737 } while ( pFrame
!= GetNext() );
2738 nSpace
= aRectFnSet
.GetHeight(GetUpper()->getFramePrintArea()) -nSpace
;
2742 if ( nReal
> nSpace
)
2744 if ( nReal
&& !bTst
)
2745 static_cast<SwFootnoteFrame
*>(this)->InvalidateNxtFootnoteCnts( FindPageFrame() );
2761 if( nReal
!= nDist
&&
2763 ( !IsCellFrame() || static_cast<SwCellFrame
*>(this)->GetLayoutRowSpan() > 1 ) )
2765 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2766 aRectFnSet
.SetHeight( aFrm
, nFrameHeight
+ nReal
);
2768 if( bChgPos
&& !IsVertLR() )
2770 aFrm
.Pos().setX( nFramePos
- nReal
);
2773 bMoveAccFrame
= true;
2778 SwPageFrame
*pPage
= FindPageFrame();
2781 GetNext()->InvalidatePos_();
2782 if (GetNext()->IsRowFrame())
2783 { // also invalidate first cell
2784 static_cast<SwLayoutFrame
*>(GetNext())->Lower()->InvalidatePos_();
2786 if ( GetNext()->IsContentFrame() )
2787 GetNext()->InvalidatePage( pPage
);
2789 if ( !IsPageBodyFrame() )
2792 InvalidatePage( pPage
);
2794 if (!(GetType() & (SwFrameType::Row
|SwFrameType::Tab
|SwFrameType::FtnCont
|SwFrameType::Page
|SwFrameType::Root
)))
2798 InvaPercentLowers( nReal
);
2800 std::unique_ptr
<SvxBrushItem
> aBack(GetFormat()->makeBackgroundBrushItem());
2801 const SvxGraphicPosition ePos
= aBack
->GetGraphicPos();
2802 if ( GPOS_NONE
!= ePos
&& GPOS_TILED
!= ePos
)
2807 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2808 if( bMoveAccFrame
&& IsAccessibleFrame() )
2810 SwRootFrame
*pRootFrame
= getRootFrame();
2811 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
2812 pRootFrame
->GetCurrShell() )
2814 pRootFrame
->GetCurrShell()->Imp()->MoveAccessibleFrame( this, aOldFrame
);
2818 (void)bMoveAccFrame
;
2825 SwTwips
SwLayoutFrame::ShrinkFrame( SwTwips nDist
, bool bTst
, bool bInfo
)
2827 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
2828 const bool bBrowse
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
2829 SwFrameType nTmpType
= SwFrameType::Cell
| SwFrameType::Column
;
2831 nTmpType
|= SwFrameType::Body
;
2833 if (pSh
&& pSh
->GetViewOptions()->IsWhitespaceHidden())
2837 // Whitespace is hidden and this body frame will not shrink, as it
2839 // Invalidate the page frame size, so in case the reason for the
2840 // shrink was that there is more whitespace on this page, the size
2841 // without whitespace will be recalculated correctly.
2842 SwPageFrame
* pPageFrame
= FindPageFrame();
2843 pPageFrame
->InvalidateSize();
2847 if( !(GetType() & nTmpType
) && HasFixSize() )
2850 OSL_ENSURE( nDist
>= 0, "nDist < 0" );
2851 SwRectFnSet
aRectFnSet(this);
2852 SwTwips nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
2853 if ( nDist
> nFrameHeight
)
2854 nDist
= nFrameHeight
;
2857 bool bChgPos
= IsVertical();
2860 if( !Lower()->IsNeighbourFrame() )
2861 { const SwFrame
*pFrame
= Lower();
2862 const tools::Long nTmp
= aRectFnSet
.GetHeight(getFramePrintArea());
2863 while( pFrame
&& nMin
< nTmp
)
2864 { nMin
+= aRectFnSet
.GetHeight(pFrame
->getFrameArea());
2865 pFrame
= pFrame
->GetNext();
2869 SwTwips nReal
= nDist
;
2870 SwTwips nMinDiff
= aRectFnSet
.GetHeight(getFramePrintArea()) - nMin
;
2871 if( nReal
> nMinDiff
)
2876 SwRect
aOldFrame( getFrameArea() );
2877 bool bMoveAccFrame
= false;
2879 SwTwips nRealDist
= nReal
;
2882 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2883 aRectFnSet
.SetHeight( aFrm
, nFrameHeight
- nReal
);
2885 if( bChgPos
&& !IsVertLR() )
2887 aFrm
.Pos().AdjustX(nReal
);
2890 bMoveAccFrame
= true;
2893 SwNeighbourAdjust nAdjust
= GetUpper() && GetUpper()->IsFootnoteBossFrame() ?
2894 static_cast<SwFootnoteBossFrame
*>(GetUpper())->NeighbourhoodAdjustment()
2895 : SwNeighbourAdjust::GrowShrink
;
2897 // AdjustNeighbourhood also in columns (but not in frames)
2898 if( SwNeighbourAdjust::OnlyAdjust
== nAdjust
)
2900 if ( IsPageBodyFrame() && !bBrowse
)
2903 { nReal
= AdjustNeighbourhood( -nReal
, bTst
);
2905 if ( !bTst
&& IsBodyFrame() && nReal
< nRealDist
)
2907 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2908 aRectFnSet
.SetHeight( aFrm
, aRectFnSet
.GetHeight(aFrm
) + nRealDist
- nReal
);
2910 if( bChgPos
&& !IsVertLR() )
2912 aFrm
.Pos().AdjustX(nRealDist
- nReal
);
2915 OSL_ENSURE( !IsAccessibleFrame(), "bMoveAccFrame has to be set!" );
2919 else if( IsColumnFrame() || IsColBodyFrame() )
2921 SwTwips nTmp
= GetUpper()->Shrink( nReal
, bTst
, bInfo
);
2922 if ( nTmp
!= nReal
)
2924 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
2925 aRectFnSet
.SetHeight( aFrm
, aRectFnSet
.GetHeight(aFrm
) + nReal
- nTmp
);
2927 if( bChgPos
&& !IsVertLR() )
2929 aFrm
.Pos().AdjustX(nTmp
- nReal
);
2932 OSL_ENSURE( !IsAccessibleFrame(), "bMoveAccFrame has to be set!" );
2938 SwTwips nShrink
= nReal
;
2939 SwFrame
* pToShrink
= GetUpper();
2941 if ( IsCellFrame() )
2943 const SwCellFrame
* pThisCell
= static_cast<const SwCellFrame
*>(this);
2944 if ( pThisCell
->GetLayoutRowSpan() > 1 )
2946 SwCellFrame
& rEndCell
= const_cast<SwCellFrame
&>(pThisCell
->FindStartEndOfRowSpanCell( false ));
2947 pToShrink
= rEndCell
.GetUpper();
2951 nReal
= pToShrink
? pToShrink
->Shrink( nShrink
, bTst
, bInfo
) : 0;
2952 if( ( SwNeighbourAdjust::GrowAdjust
== nAdjust
|| SwNeighbourAdjust::AdjustGrow
== nAdjust
)
2953 && nReal
< nShrink
)
2954 AdjustNeighbourhood( nReal
- nShrink
);
2957 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2958 if( bMoveAccFrame
&& IsAccessibleFrame() )
2960 SwRootFrame
*pRootFrame
= getRootFrame();
2961 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
2962 pRootFrame
->GetCurrShell() )
2964 pRootFrame
->GetCurrShell()->Imp()->MoveAccessibleFrame( this, aOldFrame
);
2969 (void)bMoveAccFrame
;
2972 if ( !bTst
&& (IsCellFrame() || IsColumnFrame() ? nReal
: nRealDist
) )
2974 SwPageFrame
*pPage
= FindPageFrame();
2977 GetNext()->InvalidatePos_();
2978 if ( GetNext()->IsContentFrame() )
2979 GetNext()->InvalidatePage( pPage
);
2981 static_cast<SwTabFrame
*>(this)->SetComplete();
2984 { if ( IsRetoucheFrame() )
2988 static_cast<SwTabFrame
*>(this)->SetComplete();
2989 if ( Lower() ) // Can also be in the Join and be empty!
2990 InvalidateNextPos();
2993 if ( !IsBodyFrame() )
2996 InvalidatePage( pPage
);
2997 bool bCompletePaint
= true;
2998 const SwFrameFormat
* pFormat
= GetFormat();
3001 std::unique_ptr
<SvxBrushItem
> aBack(pFormat
->makeBackgroundBrushItem());
3002 const SvxGraphicPosition ePos
= aBack
->GetGraphicPos();
3003 if ( GPOS_NONE
== ePos
|| GPOS_TILED
== ePos
)
3004 bCompletePaint
= false;
3010 if (!(GetType() & (SwFrameType::Row
|SwFrameType::Tab
|SwFrameType::FtnCont
|SwFrameType::Page
|SwFrameType::Root
)))
3014 InvaPercentLowers( nReal
);
3016 SwContentFrame
*pCnt
;
3017 if( IsFootnoteFrame() && !static_cast<SwFootnoteFrame
*>(this)->GetAttr()->GetFootnote().IsEndNote() &&
3018 ( GetFormat()->GetDoc()->GetFootnoteInfo().m_ePos
!= FTNPOS_CHAPTER
||
3019 ( IsInSct() && FindSctFrame()->IsFootnoteAtEnd() ) ) &&
3020 nullptr != (pCnt
= static_cast<SwFootnoteFrame
*>(this)->GetRefFromAttr() ) )
3022 if ( pCnt
->IsFollow() )
3023 { // If we are in another column/page than the frame with the
3024 // reference, we don't need to invalidate its master.
3025 SwFrame
*pTmp
= pCnt
->FindFootnoteBossFrame(true) == FindFootnoteBossFrame(true)
3026 ? &pCnt
->FindMaster()->GetFrame() : pCnt
;
3027 pTmp
->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
3028 pTmp
->InvalidateSize();
3032 if (pCnt
->FindPageFrame() == FindPageFrame())
3034 pCnt
->InvalidatePos();
3038 SAL_WARN("sw.layout", "footnote frame on different page than ref frame?");
3047 * Changes the size of the directly subsidiary Frame's that have a fixed size, proportionally to the
3048 * size change of the PrtArea of the Frame's.
3050 * The variable Frames are also proportionally adapted; they will grow/shrink again by themselves.
3052 void SwLayoutFrame::ChgLowersProp( const Size
& rOldSize
)
3054 // no change of lower properties for root frame or if no lower exists.
3055 if ( IsRootFrame() || !Lower() )
3058 // declare and init <SwFrame* pLowerFrame> with first lower
3059 SwFrame
*pLowerFrame
= Lower();
3061 // declare and init const booleans <bHeightChgd> and <bWidthChg>
3062 const bool bHeightChgd
= rOldSize
.Height() != getFramePrintArea().Height();
3063 const bool bWidthChgd
= rOldSize
.Width() != getFramePrintArea().Width();
3065 SwRectFnSet
aRectFnSet(this);
3067 // This shortcut basically tries to handle only lower frames that
3068 // are affected by the size change. Otherwise much more lower frames
3070 if ( !( aRectFnSet
.IsVert() ? bHeightChgd
: bWidthChgd
) &&
3071 ! Lower()->IsColumnFrame() &&
3072 ( ( IsBodyFrame() && IsInDocBody() && ( !IsInSct() || !FindSctFrame()->IsColLocked() ) ) ||
3073 // #i10826# Section frames without columns should not
3074 // invalidate all lowers!
3077 // Determine page frame the body frame resp. the section frame belongs to.
3078 SwPageFrame
*pPage
= FindPageFrame();
3079 // Determine last lower by traveling through them using <GetNext()>.
3080 // During travel check each section frame, if it will be sized to
3081 // maximum. If Yes, invalidate size of section frame and set
3082 // corresponding flags at the page.
3085 if( pLowerFrame
->IsSctFrame() && static_cast<SwSectionFrame
*>(pLowerFrame
)->ToMaximize_() )
3087 pLowerFrame
->InvalidateSize_();
3088 pLowerFrame
->InvalidatePage( pPage
);
3090 if( pLowerFrame
->GetNext() )
3091 pLowerFrame
= pLowerFrame
->GetNext();
3095 // If found last lower is a section frame containing no section
3096 // (section frame isn't valid and will be deleted in the future),
3097 // travel backwards.
3098 while( pLowerFrame
->IsSctFrame() && !static_cast<SwSectionFrame
*>(pLowerFrame
)->GetSection() &&
3099 pLowerFrame
->GetPrev() )
3100 pLowerFrame
= pLowerFrame
->GetPrev();
3101 // If found last lower is a section frame, set <pLowerFrame> to its last
3102 // content, if the section frame is valid and is not sized to maximum.
3103 // Otherwise set <pLowerFrame> to NULL - In this case body frame only
3104 // contains invalid section frames.
3105 if( pLowerFrame
->IsSctFrame() )
3106 pLowerFrame
= static_cast<SwSectionFrame
*>(pLowerFrame
)->GetSection() &&
3107 !static_cast<SwSectionFrame
*>(pLowerFrame
)->ToMaximize( false ) ?
3108 static_cast<SwSectionFrame
*>(pLowerFrame
)->FindLastContent() : nullptr;
3110 // continue with found last lower, probably the last content of a section
3113 // If <pLowerFrame> is in a table frame, set <pLowerFrame> to this table
3114 // frame and continue.
3115 if ( pLowerFrame
->IsInTab() )
3117 // OD 28.10.2002 #97265# - safeguard for setting <pLowerFrame> to
3118 // its table frame - check, if the table frame is also a lower
3119 // of the body frame, in order to assure that <pLowerFrame> is not
3120 // set to a frame, which is an *upper* of the body frame.
3121 SwFrame
* pTableFrame
= pLowerFrame
->FindTabFrame();
3122 if ( IsAnLower( pTableFrame
) )
3124 pLowerFrame
= pTableFrame
;
3127 // Check, if variable size of body frame resp. section frame has grown
3128 // OD 28.10.2002 #97265# - correct check, if variable size has grown.
3129 SwTwips nOldHeight
= aRectFnSet
.IsVert() ? rOldSize
.Width() : rOldSize
.Height();
3130 if( nOldHeight
< aRectFnSet
.GetHeight(getFramePrintArea()) )
3132 // If variable size of body|section frame has grown, only found
3133 // last lower and the position of the its next have to be invalidated.
3134 pLowerFrame
->InvalidateAll_();
3135 pLowerFrame
->InvalidatePage( pPage
);
3136 if( !pLowerFrame
->IsFlowFrame() ||
3137 !SwFlowFrame::CastFlowFrame( pLowerFrame
)->HasFollow() )
3138 pLowerFrame
->InvalidateNextPos( true );
3139 if ( pLowerFrame
->IsTextFrame() )
3140 static_cast<SwContentFrame
*>(pLowerFrame
)->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
3144 SwFrame
const* pFirstInvalid(nullptr);
3145 for (SwFrame
const* pLow
= Lower();
3146 pLow
&& pLow
!= pLowerFrame
; pLow
= pLow
->GetNext())
3148 if (!pLow
->isFrameAreaDefinitionValid())
3150 pFirstInvalid
= pLow
;
3154 // variable size of body|section frame has shrunk. Thus,
3155 // invalidate all lowers not matching the new body|section size
3156 // and the dedicated new last lower.
3157 if( aRectFnSet
.IsVert() )
3159 SwTwips nBot
= getFrameArea().Left() + getFramePrintArea().Left();
3160 while (pLowerFrame
&& pLowerFrame
->GetPrev()
3161 && (pFirstInvalid
!= nullptr // tdf#152307 trust nothing after invalid frame
3162 || pLowerFrame
->getFrameArea().Left() < nBot
))
3164 pLowerFrame
->InvalidateAll_();
3165 pLowerFrame
->InvalidatePage( pPage
);
3166 if (pLowerFrame
== pFirstInvalid
)
3168 pFirstInvalid
= nullptr; // continue checking nBot
3170 pLowerFrame
= pLowerFrame
->GetPrev();
3175 SwTwips nBot
= getFrameArea().Top() + getFramePrintArea().Bottom();
3176 while (pLowerFrame
&& pLowerFrame
->GetPrev()
3177 && (pFirstInvalid
!= nullptr // tdf#152307 trust nothing after invalid frame
3178 || nBot
< pLowerFrame
->getFrameArea().Top()))
3180 pLowerFrame
->InvalidateAll_();
3181 pLowerFrame
->InvalidatePage( pPage
);
3182 if (pLowerFrame
== pFirstInvalid
)
3184 pFirstInvalid
= nullptr; // continue checking nBot
3186 pLowerFrame
= pLowerFrame
->GetPrev();
3191 pLowerFrame
->InvalidateSize_();
3192 pLowerFrame
->InvalidatePage( pPage
);
3193 if ( pLowerFrame
->IsTextFrame() )
3194 static_cast<SwContentFrame
*>(pLowerFrame
)->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
3197 // #i41694# - improvement by removing duplicates
3200 if ( pLowerFrame
->IsInSct() )
3202 // #i41694# - follow-up of issue #i10826#
3203 // No invalidation of section frame, if it's the this.
3204 SwFrame
* pSectFrame
= pLowerFrame
->FindSctFrame();
3205 if( pSectFrame
!= this && IsAnLower( pSectFrame
) )
3207 pSectFrame
->InvalidateSize_();
3208 pSectFrame
->InvalidatePage( pPage
);
3214 } // end of { special case }
3216 // Invalidate page for content only once.
3217 bool bInvaPageForContent
= true;
3219 // Declare booleans <bFixChgd> and <bVarChgd>, indicating for text frame
3220 // adjustment, if fixed/variable size has changed.
3221 bool bFixChgd
, bVarChgd
;
3222 if( aRectFnSet
.IsVert() == pLowerFrame
->IsNeighbourFrame() )
3224 bFixChgd
= bWidthChgd
;
3225 bVarChgd
= bHeightChgd
;
3229 bFixChgd
= bHeightChgd
;
3230 bVarChgd
= bWidthChgd
;
3233 // Declare const unsigned short <nFixWidth> and init it this frame types
3234 // which has fixed width in vertical respectively horizontal layout.
3235 // In vertical layout these are neighbour frames (cell and column frames),
3236 // header frames and footer frames.
3237 // In horizontal layout these are all frames, which aren't neighbour frames.
3238 const SwFrameType nFixWidth
= aRectFnSet
.IsVert() ? (FRM_NEIGHBOUR
| FRM_HEADFOOT
)
3239 : ~SwFrameType(FRM_NEIGHBOUR
);
3241 // Declare const unsigned short <nFixHeight> and init it this frame types
3242 // which has fixed height in vertical respectively horizontal layout.
3243 // In vertical layout these are all frames, which aren't neighbour frames,
3244 // header frames, footer frames, body frames or foot note container frames.
3245 // In horizontal layout these are neighbour frames.
3246 const SwFrameType nFixHeight
= aRectFnSet
.IsVert() ? ~SwFrameType(FRM_NEIGHBOUR
| FRM_HEADFOOT
| FRM_BODYFTNC
)
3249 // Travel through all lowers using <GetNext()>
3250 while ( pLowerFrame
)
3252 if ( pLowerFrame
->IsTextFrame() )
3254 // Text frames will only be invalidated - prepare invalidation
3256 static_cast<SwContentFrame
*>(pLowerFrame
)->Prepare( PrepareHint::FixSizeChanged
);
3258 static_cast<SwContentFrame
*>(pLowerFrame
)->Prepare( PrepareHint::AdjustSizeWithoutFormatting
);
3262 // If lower isn't a table, row, cell or section frame, adjust its
3264 const SwFrameType nLowerType
= pLowerFrame
->GetType();
3265 if ( !(nLowerType
& (SwFrameType::Tab
|SwFrameType::Row
|SwFrameType::Cell
|SwFrameType::Section
)) )
3269 if( nLowerType
& nFixWidth
)
3271 // Considering previous conditions:
3272 // In vertical layout set width of column, header and
3273 // footer frames to its upper width.
3274 // In horizontal layout set width of header, footer,
3275 // foot note container, foot note, body and no-text
3276 // frames to its upper width.
3277 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3278 aFrm
.Width( getFramePrintArea().Width() );
3280 else if( rOldSize
.Width() && !pLowerFrame
->IsFootnoteFrame() )
3282 // Adjust frame width proportional, if lower isn't a
3283 // foot note frame and condition <nLowerType & nFixWidth>
3285 // Considering previous conditions:
3286 // In vertical layout these are foot note container,
3287 // body and no-text frames.
3288 // In horizontal layout these are column and no-text frames.
3289 // OD 24.10.2002 #97265# - <double> calculation
3290 // Perform <double> calculation of new width, if
3291 // one of the coefficients is greater than 50000
3293 if ( (pLowerFrame
->getFrameArea().Width() > 50000) ||
3294 (getFramePrintArea().Width() > 50000) )
3296 double nNewWidthTmp
=
3297 ( double(pLowerFrame
->getFrameArea().Width())
3298 * double(getFramePrintArea().Width()) )
3299 / double(rOldSize
.Width());
3300 nNewWidth
= SwTwips(nNewWidthTmp
);
3305 (pLowerFrame
->getFrameArea().Width() * getFramePrintArea().Width()) / rOldSize
.Width();
3308 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3309 aFrm
.Width( nNewWidth
);
3314 if( nLowerType
& nFixHeight
)
3316 // Considering previous conditions:
3317 // In vertical layout set height of foot note and
3318 // no-text frames to its upper height.
3319 // In horizontal layout set height of column frames
3320 // to its upper height.
3321 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3322 aFrm
.Height( getFramePrintArea().Height() );
3324 // OD 01.10.2002 #102211#
3325 // add conditions <!pLowerFrame->IsHeaderFrame()> and
3326 // <!pLowerFrame->IsFooterFrame()> in order to avoid that
3327 // the <Grow> of header or footer are overwritten.
3328 // NOTE: Height of header/footer frame is determined by contents.
3329 else if ( rOldSize
.Height() &&
3330 !pLowerFrame
->IsFootnoteFrame() &&
3331 !pLowerFrame
->IsHeaderFrame() &&
3332 !pLowerFrame
->IsFooterFrame()
3335 // Adjust frame height proportional, if lower isn't a
3336 // foot note, a header or a footer frame and
3337 // condition <nLowerType & nFixHeight> isn't true.
3338 // Considering previous conditions:
3339 // In vertical layout these are column, foot note container,
3340 // body and no-text frames.
3341 // In horizontal layout these are column, foot note
3342 // container, body and no-text frames.
3344 // OD 29.10.2002 #97265# - special case for page lowers
3345 // The page lowers that have to be adjusted on page height
3346 // change are the body frame and the foot note container
3348 // In vertical layout the height of both is directly
3349 // adjusted to the page height change.
3350 // In horizontal layout the height of the body frame is
3351 // directly adjusted to the page height change and the
3352 // foot note frame height isn't touched, because its
3353 // determined by its content.
3354 // OD 31.03.2003 #108446# - apply special case for page
3355 // lowers - see description above - also for section columns.
3356 if ( IsPageFrame() ||
3357 ( IsColumnFrame() && IsInSct() )
3360 OSL_ENSURE( pLowerFrame
->IsBodyFrame() || pLowerFrame
->IsFootnoteContFrame(),
3361 "ChgLowersProp - only for body or foot note container" );
3362 if ( pLowerFrame
->IsBodyFrame() || pLowerFrame
->IsFootnoteContFrame() )
3364 if ( IsVertical() || pLowerFrame
->IsBodyFrame() )
3366 SwTwips nNewHeight
=
3367 pLowerFrame
->getFrameArea().Height() +
3368 ( getFramePrintArea().Height() - rOldSize
.Height() );
3369 if ( nNewHeight
< 0)
3371 // OD 01.04.2003 #108446# - adjust assertion condition and text
3372 OSL_ENSURE( !( IsPageFrame() &&
3373 (pLowerFrame
->getFrameArea().Height()>0) &&
3374 (pLowerFrame
->isFrameAreaDefinitionValid()) ),
3375 "ChgLowersProg - negative height for lower.");
3379 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3380 aFrm
.Height( nNewHeight
);
3387 // OD 24.10.2002 #97265# - <double> calculation
3388 // Perform <double> calculation of new height, if
3389 // one of the coefficients is greater than 50000
3390 if ( (pLowerFrame
->getFrameArea().Height() > 50000) ||
3391 (getFramePrintArea().Height() > 50000) )
3393 double nNewHeightTmp
=
3394 ( double(pLowerFrame
->getFrameArea().Height())
3395 * double(getFramePrintArea().Height()) )
3396 / double(rOldSize
.Height());
3397 nNewHeight
= SwTwips(nNewHeightTmp
);
3401 nNewHeight
= ( pLowerFrame
->getFrameArea().Height()
3402 * getFramePrintArea().Height() ) / rOldSize
.Height();
3404 if( !pLowerFrame
->GetNext() )
3406 SwTwips nSum
= getFramePrintArea().Height();
3407 SwFrame
* pTmp
= Lower();
3408 while( pTmp
->GetNext() )
3410 if( !pTmp
->IsFootnoteContFrame() || !pTmp
->IsVertical() )
3411 nSum
-= pTmp
->getFrameArea().Height();
3412 pTmp
= pTmp
->GetNext();
3414 if( nSum
- nNewHeight
== 1 &&
3415 nSum
== pLowerFrame
->getFrameArea().Height() )
3419 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*pLowerFrame
);
3420 aFrm
.Height( nNewHeight
);
3425 } // end of else { NOT text frame }
3427 pLowerFrame
->InvalidateAll_();
3428 if ( bInvaPageForContent
&& pLowerFrame
->IsContentFrame() )
3430 pLowerFrame
->InvalidatePage();
3431 bInvaPageForContent
= false;
3434 if ( !pLowerFrame
->GetNext() && pLowerFrame
->IsRetoucheFrame() )
3436 //If a growth took place and the subordinate elements can retouch
3437 //itself (currently Tabs, Sections and Content) we trigger it.
3438 if ( rOldSize
.Height() < getFramePrintArea().SSize().Height() ||
3439 rOldSize
.Width() < getFramePrintArea().SSize().Width() )
3440 pLowerFrame
->SetRetouche();
3442 pLowerFrame
= pLowerFrame
->GetNext();
3445 // Finally adjust the columns if width is set to auto
3446 // Possible optimization: execute this code earlier in this function and
3448 if ( !(( (aRectFnSet
.IsVert() && bHeightChgd
) || (! aRectFnSet
.IsVert() && bWidthChgd
) ) &&
3449 Lower()->IsColumnFrame()) )
3452 // get column attribute
3453 const SwFormatCol
* pColAttr
= nullptr;
3454 if ( IsPageBodyFrame() )
3456 OSL_ENSURE( GetUpper()->IsPageFrame(), "Upper is not page frame" );
3457 pColAttr
= &GetUpper()->GetFormat()->GetCol();
3461 OSL_ENSURE( IsFlyFrame() || IsSctFrame(), "Columns not in fly or section" );
3462 pColAttr
= &GetFormat()->GetCol();
3465 if ( pColAttr
->IsOrtho() && pColAttr
->GetNumCols() > 1 )
3466 AdjustColumns( pColAttr
, false );
3469 /** "Formats" the Frame; Frame and PrtArea.
3471 * The Fixsize is not set here.
3473 void SwLayoutFrame::Format( vcl::RenderContext
* /*pRenderContext*/, const SwBorderAttrs
*pAttrs
)
3475 OSL_ENSURE( pAttrs
, "LayoutFrame::Format, pAttrs is 0." );
3477 if ( isFramePrintAreaValid() && isFrameAreaSizeValid() )
3480 bool bHideWhitespace
= false;
3483 SwViewShell
* pShell
= getRootFrame()->GetCurrShell();
3484 if (pShell
&& pShell
->GetViewOptions()->IsWhitespaceHidden())
3486 // This is needed so that no space is reserved for the margin on
3487 // the last page of the document. Other pages would have no margin
3488 // set even without this, as their frame height is the content
3490 bHideWhitespace
= true;
3494 const sal_uInt16 nLeft
= o3tl::narrowing
<sal_uInt16
>(pAttrs
->CalcLeft(this));
3495 const sal_uInt16 nUpper
= bHideWhitespace
? 0 : pAttrs
->CalcTop();
3497 const sal_uInt16 nRight
= o3tl::narrowing
<sal_uInt16
>(pAttrs
->CalcRight(this));
3498 const sal_uInt16 nLower
= bHideWhitespace
? 0 : pAttrs
->CalcBottom();
3500 const bool bVert
= IsVertical() && !IsPageFrame();
3501 SwRectFn fnRect
= bVert
? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T
: fnRectVertL2R
) : fnRectVert
) : fnRectHori
;
3502 if ( !isFramePrintAreaValid() )
3504 setFramePrintAreaValid(true);
3505 (this->*fnRect
->fnSetXMargins
)( nLeft
, nRight
);
3506 (this->*fnRect
->fnSetYMargins
)( nUpper
, nLower
);
3509 if ( isFrameAreaSizeValid() )
3512 if ( !HasFixSize() )
3514 const SwTwips nBorder
= nUpper
+ nLower
;
3515 const SwFormatFrameSize
&rSz
= GetFormat()->GetFrameSize();
3516 SwTwips nMinHeight
= rSz
.GetHeightSizeType() == SwFrameSize::Minimum
? rSz
.GetHeight() : 0;
3519 setFrameAreaSizeValid(true);
3521 //The size in VarSize is calculated using the content plus the
3523 SwTwips nRemaining
= 0;
3524 SwFrame
*pFrame
= Lower();
3526 { nRemaining
+= (pFrame
->getFrameArea().*fnRect
->fnGetHeight
)();
3527 if( pFrame
->IsTextFrame() && static_cast<SwTextFrame
*>(pFrame
)->IsUndersized() )
3528 // This TextFrame would like to be a bit bigger
3529 nRemaining
+= static_cast<SwTextFrame
*>(pFrame
)->GetParHeight()
3530 - (pFrame
->getFramePrintArea().*fnRect
->fnGetHeight
)();
3531 else if( pFrame
->IsSctFrame() && static_cast<SwSectionFrame
*>(pFrame
)->IsUndersized() )
3532 nRemaining
+= static_cast<SwSectionFrame
*>(pFrame
)->Undersize();
3533 pFrame
= pFrame
->GetNext();
3535 nRemaining
+= nBorder
;
3536 nRemaining
= std::max( nRemaining
, nMinHeight
);
3537 const SwTwips nDiff
= nRemaining
-(getFrameArea().*fnRect
->fnGetHeight
)();
3538 const tools::Long nOldLeft
= (getFrameArea().*fnRect
->fnGetLeft
)();
3539 const tools::Long nOldTop
= (getFrameArea().*fnRect
->fnGetTop
)();
3546 //Updates the positions using the fast channel.
3549 //Don't exceed the bottom edge of the Upper.
3550 if ( GetUpper() && (getFrameArea().*fnRect
->fnGetHeight
)() )
3552 const SwTwips nLimit
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
3553 if( (this->*fnRect
->fnSetLimit
)( nLimit
) &&
3554 nOldLeft
== (getFrameArea().*fnRect
->fnGetLeft
)() &&
3555 nOldTop
== (getFrameArea().*fnRect
->fnGetTop
)() )
3557 setFrameAreaSizeValid(true);
3558 setFramePrintAreaValid(true);
3561 } while ( !isFrameAreaSizeValid() );
3563 else if (GetType() & FRM_HEADFOOT
)
3566 { if ( getFrameArea().Height() != pAttrs
->GetSize().Height() )
3568 ChgSize( Size( getFrameArea().Width(), pAttrs
->GetSize().Height()));
3571 setFrameAreaSizeValid(true);
3573 } while ( !isFrameAreaSizeValid() );
3577 setFrameAreaSizeValid(true);
3580 // While updating the size, PrtArea might be invalidated.
3581 if (!isFramePrintAreaValid())
3583 setFramePrintAreaValid(true);
3584 (this->*fnRect
->fnSetXMargins
)(nLeft
, nRight
);
3585 (this->*fnRect
->fnSetYMargins
)(nUpper
, nLower
);
3589 static void InvaPercentFlys( SwFrame
*pFrame
, SwTwips nDiff
)
3591 OSL_ENSURE( pFrame
->GetDrawObjs(), "Can't find any Objects" );
3592 for (SwAnchoredObject
* pAnchoredObj
: *pFrame
->GetDrawObjs())
3594 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
3596 const SwFormatFrameSize
&rSz
= pFly
->GetFormat()->GetFrameSize();
3597 if ( rSz
.GetWidthPercent() || rSz
.GetHeightPercent() )
3599 bool bNotify
= true;
3600 // If we've a fly with more than 90% relative height...
3601 if( rSz
.GetHeightPercent() > 90 && pFly
->GetAnchorFrame() &&
3602 rSz
.GetHeightPercent() != SwFormatFrameSize::SYNCED
&& nDiff
)
3604 const SwFrame
*pRel
= pFly
->IsFlyLayFrame() ? pFly
->GetAnchorFrame():
3605 pFly
->GetAnchorFrame()->GetUpper();
3606 // ... and we have already more than 90% height and we
3607 // not allow the text to go through...
3608 // then a notification could cause an endless loop, e.g.
3609 // 100% height and no text wrap inside a cell of a table.
3610 if( pFly
->getFrameArea().Height()*10 >
3611 ( nDiff
+ pRel
->getFramePrintArea().Height() )*9 &&
3612 pFly
->GetFormat()->GetSurround().GetSurround() !=
3613 css::text::WrapTextMode_THROUGH
)
3617 pFly
->InvalidateSize();
3623 void SwLayoutFrame::InvaPercentLowers( SwTwips nDiff
)
3625 if ( GetDrawObjs() )
3626 ::InvaPercentFlys( this, nDiff
);
3628 SwFrame
*pFrame
= ContainsContent();
3634 if ( pFrame
->IsInTab() && !IsTabFrame() )
3636 SwFrame
*pTmp
= pFrame
->FindTabFrame();
3637 OSL_ENSURE( pTmp
, "Where's my TabFrame?" );
3638 if( IsAnLower( pTmp
) )
3642 if ( pFrame
->IsTabFrame() )
3644 const SwFormatFrameSize
&rSz
= static_cast<SwLayoutFrame
*>(pFrame
)->GetFormat()->GetFrameSize();
3645 if ( rSz
.GetWidthPercent() || rSz
.GetHeightPercent() )
3646 pFrame
->InvalidatePrt();
3648 else if ( pFrame
->GetDrawObjs() )
3649 ::InvaPercentFlys( pFrame
, nDiff
);
3650 pFrame
= pFrame
->FindNextCnt();
3651 } while ( pFrame
&& IsAnLower( pFrame
) ) ;
3654 tools::Long
SwLayoutFrame::CalcRel( const SwFormatFrameSize
&rSz
) const
3656 tools::Long nRet
= rSz
.GetWidth(),
3657 nPercent
= rSz
.GetWidthPercent();
3661 const SwFrame
*pRel
= GetUpper();
3662 tools::Long nRel
= LONG_MAX
;
3663 const SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
3664 const bool bBrowseMode
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
3665 if( pRel
->IsPageBodyFrame() && pSh
&& bBrowseMode
&& pSh
->VisArea().Width() )
3667 nRel
= pSh
->GetBrowseWidth();
3668 tools::Long nDiff
= nRel
- pRel
->getFramePrintArea().Width();
3672 nRel
= std::min( nRel
, pRel
->getFramePrintArea().Width() );
3673 nRet
= nRel
* nPercent
/ 100;
3678 // Local helpers for SwLayoutFrame::FormatWidthCols()
3680 static tools::Long
lcl_CalcMinColDiff( SwLayoutFrame
*pLayFrame
)
3682 tools::Long nDiff
= 0, nFirstDiff
= 0;
3683 SwLayoutFrame
*pCol
= static_cast<SwLayoutFrame
*>(pLayFrame
->Lower());
3684 OSL_ENSURE( pCol
, "Where's the columnframe?" );
3685 SwFrame
*pFrame
= pCol
->Lower();
3688 if( pFrame
&& pFrame
->IsBodyFrame() )
3689 pFrame
= static_cast<SwBodyFrame
*>(pFrame
)->Lower();
3690 if ( pFrame
&& pFrame
->IsTextFrame() )
3692 const tools::Long nTmp
= static_cast<SwTextFrame
*>(pFrame
)->FirstLineHeight();
3693 if ( nTmp
!= USHRT_MAX
)
3695 if ( pCol
== pLayFrame
->Lower() )
3698 nDiff
= nDiff
? std::min( nDiff
, nTmp
) : nTmp
;
3701 //Skip empty columns!
3702 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
3703 while ( pCol
&& nullptr == (pFrame
= pCol
->Lower()) )
3704 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
3706 } while ( pFrame
&& pCol
);
3708 return nDiff
? nDiff
: nFirstDiff
? nFirstDiff
: 240;
3711 static bool lcl_IsFlyHeightClipped( SwLayoutFrame
*pLay
)
3713 SwFrame
*pFrame
= pLay
->ContainsContent();
3716 if ( pFrame
->IsInTab() )
3717 pFrame
= pFrame
->FindTabFrame();
3719 if ( pFrame
->GetDrawObjs() )
3721 const size_t nCnt
= pFrame
->GetDrawObjs()->size();
3722 for ( size_t i
= 0; i
< nCnt
; ++i
)
3724 SwAnchoredObject
* pAnchoredObj
= (*pFrame
->GetDrawObjs())[i
];
3725 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
3727 if ( pFly
->IsHeightClipped() &&
3728 ( !pFly
->IsFlyFreeFrame() || pFly
->GetPageFrame() ) )
3733 pFrame
= pFrame
->FindNextCnt();
3738 void SwLayoutFrame::FormatWidthCols( const SwBorderAttrs
&rAttrs
,
3739 const SwTwips nBorder
, const SwTwips nMinHeight
)
3741 //If there are columns involved, the size is adjusted using the last column.
3742 //1. Format content.
3743 //2. Calculate height of the last column: if it's too big, the Fly has to
3744 // grow. The amount by which the Fly grows is not the amount of the
3745 // overhang because we have to act on the assumption that some text flows
3746 // back which will generate some more space.
3747 // The amount which we grow by equals the overhang
3748 // divided by the amount of columns or the overhang itself if it's smaller
3749 // than the amount of columns.
3750 //3. Go back to 1. until everything is stable.
3752 const SwFormatCol
&rCol
= rAttrs
.GetAttrSet().GetCol();
3753 const sal_uInt16 nNumCols
= rCol
.GetNumCols();
3756 bool bBackLock
= false;
3757 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
3758 SwViewShellImp
*pImp
= pSh
? pSh
->Imp() : nullptr;
3759 vcl::RenderContext
* pRenderContext
= pSh
? pSh
->GetOut() : nullptr;
3761 // Underlying algorithm
3762 // We try to find the optimal height for the column.
3763 // nMinimum starts with the passed minimum height and is then remembered
3764 // as the maximum height on which column content still juts out of a
3766 // nMaximum starts with LONG_MAX and is then remembered as the minimum
3767 // width on which the content fitted.
3768 // In column based sections nMaximum starts at the maximum value which
3769 // the surrounding defines, this can certainly be a value on which
3770 // content still juts out.
3771 // The columns are formatted. If content still juts out, nMinimum is
3772 // adjusted accordingly, then we grow, at least by uMinDiff but not
3773 // over a certain nMaximum. If no content juts out but there is still
3774 // some space left in the column, shrinking is done accordingly, at
3775 // least by nMindIff but not below the nMinimum.
3776 // Cancel as soon as no content juts out and the difference from minimum
3777 // to maximum is less than MinDiff or the maximum which was defined by
3778 // the surrounding is reached even if some content still juts out.
3780 // Criticism of this implementation
3781 // 1. Theoretically situations are possible in which the content fits in
3782 // a lower height but not in a higher height. To ensure that the code
3783 // handles such situations the code contains a few checks concerning
3784 // minimum and maximum which probably are never triggered.
3785 // 2. We use the same nMinDiff for shrinking and growing, but nMinDiff
3786 // is more or less the smallest first line height and doesn't seem ideal
3787 // as minimum value.
3789 tools::Long nMinimum
= nMinHeight
;
3790 tools::Long nMaximum
;
3791 bool bNoBalance
= false;
3792 SwRectFnSet
aRectFnSet(this);
3795 nMaximum
= aRectFnSet
.GetHeight(getFrameArea()) - nBorder
+
3796 aRectFnSet
.BottomDist(getFrameArea(), aRectFnSet
.GetPrtBottom(*GetUpper()));
3797 nMaximum
+= GetUpper()->Grow( LONG_MAX
, true );
3798 if( nMaximum
< nMinimum
)
3801 nMinimum
= nMaximum
= 0;
3803 nMinimum
= nMaximum
;
3805 if( nMaximum
> BROWSE_HEIGHT
)
3806 nMaximum
= BROWSE_HEIGHT
;
3808 bNoBalance
= static_cast<SwSectionFrame
*>(this)->GetSection()->GetFormat()->
3809 GetBalancedColumns().GetValue();
3810 SwFrame
* pAny
= ContainsAny();
3812 ( !aRectFnSet
.GetHeight(getFrameArea()) && pAny
) )
3814 tools::Long nTop
= aRectFnSet
.GetTopMargin(*this);
3815 // #i23129# - correction
3816 // to the calculated maximum height.
3818 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
3819 aRectFnSet
.AddBottom( aFrm
, nMaximum
- aRectFnSet
.GetHeight(getFrameArea()) );
3822 if( nTop
> nMaximum
)
3824 aRectFnSet
.SetYMargins( *this, nTop
, 0 );
3826 if( !pAny
&& !static_cast<SwSectionFrame
*>(this)->IsFootnoteLock() )
3828 SwFootnoteContFrame
* pFootnoteCont
= static_cast<SwSectionFrame
*>(this)->ContainsFootnoteCont();
3831 SwFrame
* pFootnoteAny
= pFootnoteCont
->ContainsAny();
3832 if( pFootnoteAny
&& pFootnoteAny
->isFrameAreaDefinitionValid() )
3835 static_cast<SwSectionFrame
*>(this)->SetFootnoteLock( true );
3841 nMaximum
= LONG_MAX
;
3843 // #i3317# - reset temporarily consideration
3844 // of wrapping style influence
3845 SwPageFrame
* pPageFrame
= FindPageFrame();
3846 SwSortedObjs
* pObjs
= pPageFrame
? pPageFrame
->GetSortedObjs() : nullptr;
3849 for (SwAnchoredObject
* pAnchoredObj
: *pObjs
)
3851 if ( IsAnLower( pAnchoredObj
->GetAnchorFrame() ) )
3853 pAnchoredObj
->SetTmpConsiderWrapInfluence( false );
3859 //Could take a while therefore check for Waitcrsr here.
3861 pImp
->CheckWaitCursor();
3863 setFrameAreaSizeValid(true);
3864 //First format the column as this will relieve the stack a bit.
3865 //Also set width and height of the column (if they are wrong)
3866 //while we are at it.
3867 SwLayoutFrame
*pCol
= static_cast<SwLayoutFrame
*>(Lower());
3870 // Simply setting the column width based on the values returned by
3871 // CalcColWidth does not work for automatic column width.
3872 AdjustColumns( &rCol
, false );
3874 for ( sal_uInt16 i
= 0; i
< nNumCols
; ++i
)
3876 pCol
->Calc(pRenderContext
);
3877 // ColumnFrames have a BodyFrame now, which needs to be calculated
3878 pCol
->Lower()->Calc(pRenderContext
);
3879 if( pCol
->Lower()->GetNext() )
3880 pCol
->Lower()->GetNext()->Calc(pRenderContext
); // SwFootnoteCont
3881 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
3884 ::CalcContent( this );
3886 pCol
= static_cast<SwLayoutFrame
*>(Lower());
3887 OSL_ENSURE( pCol
&& pCol
->GetNext(), ":-( column making holidays?");
3888 // set bMinDiff if no empty columns exist
3889 bool bMinDiff
= true;
3890 // OD 28.03.2003 #108446# - check for all column content and all columns
3891 while ( bMinDiff
&& pCol
)
3893 bMinDiff
= nullptr != pCol
->ContainsContent();
3894 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
3896 pCol
= static_cast<SwLayoutFrame
*>(Lower());
3897 // OD 28.03.2003 #108446# - initialize local variable
3899 SwTwips nMaxFree
= 0;
3900 SwTwips nAllFree
= LONG_MAX
;
3901 // set bFoundLower if there is at least one non-empty column
3902 bool bFoundLower
= false;
3905 SwLayoutFrame
* pLay
= static_cast<SwLayoutFrame
*>(pCol
->Lower());
3906 SwTwips nInnerHeight
= aRectFnSet
.GetHeight(pLay
->getFrameArea()) -
3907 aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
3911 nInnerHeight
+= pLay
->InnerHeight();
3913 else if( nInnerHeight
< 0 )
3916 if( pLay
->GetNext() )
3919 pLay
= static_cast<SwLayoutFrame
*>(pLay
->GetNext());
3920 OSL_ENSURE( pLay
->IsFootnoteContFrame(),"FootnoteContainer expected" );
3921 nInnerHeight
+= pLay
->InnerHeight();
3922 nInnerHeight
+= aRectFnSet
.GetHeight(pLay
->getFrameArea()) -
3923 aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
3925 nInnerHeight
-= aRectFnSet
.GetHeight(pCol
->getFramePrintArea());
3926 if( nInnerHeight
> nDiff
)
3928 nDiff
= nInnerHeight
;
3933 if( nMaxFree
< -nInnerHeight
)
3934 nMaxFree
= -nInnerHeight
;
3935 if( nAllFree
> -nInnerHeight
)
3936 nAllFree
= -nInnerHeight
;
3938 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
3941 if ( bFoundLower
|| ( IsSctFrame() && static_cast<SwSectionFrame
*>(this)->HasFollow() ) )
3943 SwTwips nMinDiff
= ::lcl_CalcMinColDiff( this );
3944 // Here we decide if growing is needed - this is the case, if
3945 // column content (nDiff) or a Fly juts over.
3946 // In sections with columns we take into account to set the size
3947 // when having a non-empty Follow.
3948 if ( nDiff
|| ::lcl_IsFlyHeightClipped( this ) ||
3949 ( IsSctFrame() && static_cast<SwSectionFrame
*>(this)->CalcMinDiff( nMinDiff
) ) )
3951 tools::Long nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
3952 // The minimum must not be smaller than our PrtHeight as
3953 // long as something juts over.
3954 if( nMinimum
< nPrtHeight
)
3955 nMinimum
= nPrtHeight
;
3956 // The maximum must not be smaller than PrtHeight if
3957 // something still juts over.
3958 if( nMaximum
< nPrtHeight
)
3959 nMaximum
= nPrtHeight
; // Robust, but will this ever happen?
3960 if( !nDiff
) // If only Flys jut over, we grow by nMinDiff
3962 // If we should grow more than by nMinDiff we split it over
3964 if ( std::abs(nDiff
- nMinDiff
) > nNumCols
&& nDiff
> static_cast<tools::Long
>(nNumCols
) )
3968 { // If no empty column exists, we want to grow at least
3969 // by nMinDiff. Special case: If we are smaller than the
3970 // minimal FrameHeight and PrtHeight is smaller than
3971 // nMindiff we grow in a way that PrtHeight is exactly
3972 // nMinDiff afterwards.
3973 tools::Long nFrameHeight
= aRectFnSet
.GetHeight(getFrameArea());
3974 if ( nFrameHeight
> nMinHeight
|| nPrtHeight
>= nMinDiff
)
3975 nDiff
= std::max( nDiff
, nMinDiff
);
3976 else if( nDiff
< nMinDiff
)
3977 nDiff
= nMinDiff
- nPrtHeight
+ 1;
3979 // nMaximum has a size which fits the content or the
3980 // requested value from the surrounding therefore we don't
3981 // need to exceed this value.
3982 if( nDiff
+ nPrtHeight
> nMaximum
)
3983 nDiff
= nMaximum
- nPrtHeight
;
3985 else if( nMaximum
> nMinimum
) // We fit, do we still have some margin?
3987 tools::Long nPrtHeight
= aRectFnSet
.GetHeight(getFramePrintArea());
3988 if ( nMaximum
< nPrtHeight
)
3989 nDiff
= nMaximum
- nPrtHeight
; // We grew over a working
3990 // height and shrink back to it, but will this ever
3993 { // We have a new maximum, a size which fits for the content.
3994 nMaximum
= nPrtHeight
;
3995 // If the margin in the column is bigger than nMinDiff
3996 // and we therefore drop under the minimum, we deflate
3999 // #i23129# - <nMinDiff> can be
4000 // big, because of an object at the beginning of
4001 // a column. Thus, decrease optimization here.
4002 //nMaxFree >= nMinDiff &&
4005 nMinimum
< nPrtHeight
- nMinDiff
) )
4007 nMaxFree
/= nNumCols
; // disperse over the columns
4008 nDiff
= nMaxFree
< nMinDiff
? -nMinDiff
: -nMaxFree
; // min nMinDiff
4009 if( nPrtHeight
+ nDiff
<= nMinimum
) // below the minimum?
4010 nDiff
= ( nMinimum
- nMaximum
) / 2; // Take the center
4015 if( nPrtHeight
+ nDiff
<= nMinimum
) // Less than minimum?
4016 nDiff
= ( nMinimum
- nMaximum
) / 2; // Take the center
4020 if( nDiff
) // now we shrink or grow...
4022 Size
aOldSz( getFramePrintArea().SSize() );
4023 tools::Long nTop
= aRectFnSet
.GetTopMargin(*this);
4024 nDiff
= aRectFnSet
.GetHeight(getFramePrintArea()) + nDiff
+ nBorder
- aRectFnSet
.GetHeight(getFrameArea());
4027 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*this);
4028 aRectFnSet
.AddBottom( aFrm
, nDiff
);
4032 SwFlyFrame
*pFlyFrame
= IsFlyFrame() ? static_cast<SwFlyFrame
*>(this) : nullptr;
4035 pFlyFrame
->InvalidateObjRectWithSpaces();
4037 aRectFnSet
.SetYMargins( *this, nTop
, nBorder
- nTop
);
4038 ChgLowersProp( aOldSz
);
4041 // #i3317# - reset temporarily consideration
4042 // of wrapping style influence
4043 SwPageFrame
* pTmpPageFrame
= FindPageFrame();
4044 SwSortedObjs
* pTmpObjs
= pTmpPageFrame
? pTmpPageFrame
->GetSortedObjs() : nullptr;
4047 for (SwAnchoredObject
* pAnchoredObj
: *pTmpObjs
)
4049 if ( IsAnLower( pAnchoredObj
->GetAnchorFrame() ) )
4051 pAnchoredObj
->SetTmpConsiderWrapInfluence( false );
4055 //Invalidate suitable to nicely balance the Frames.
4056 //- Every first one after the second column gets a
4058 pCol
= static_cast<SwLayoutFrame
*>(Lower()->GetNext());
4061 SwFrame
*pLow
= pCol
->Lower();
4063 pLow
->InvalidatePos_();
4064 pCol
= static_cast<SwLayoutFrame
*>(pCol
->GetNext());
4066 if( IsSctFrame() && static_cast<SwSectionFrame
*>(this)->HasFollow() )
4068 // If we created a Follow, we need to give its content
4069 // the opportunity to flow back inside the CalcContent
4070 SwContentFrame
* pTmpContent
=
4071 static_cast<SwSectionFrame
*>(this)->GetFollow()->ContainsContent();
4073 pTmpContent
->InvalidatePos_();
4082 } while ( !bEnd
|| !isFrameAreaSizeValid() );
4084 // OD 01.04.2003 #108446# - Don't collect endnotes for sections. Thus, set
4085 // 2nd parameter to <true>.
4086 ::CalcContent( this, true );
4089 // OD 14.03.2003 #i11760# - adjust 2nd parameter - sal_True --> true
4090 setFrameAreaSizeValid(true);
4091 ::CalcContent( this, true );
4093 static_cast<SwSectionFrame
*>(this)->SetFootnoteLock( false );
4097 static SwContentFrame
* lcl_InvalidateSection( SwFrame
*pCnt
, SwInvalidateFlags nInv
)
4099 SwSectionFrame
* pSect
= pCnt
->FindSctFrame();
4100 // If our ContentFrame is placed inside a table or a footnote, only sections
4101 // which are also placed inside are meant.
4102 // Exception: If a table is directly passed.
4103 if( ( ( pCnt
->IsInTab() && !pSect
->IsInTab() ) ||
4104 ( pCnt
->IsInFootnote() && !pSect
->IsInFootnote() ) ) && !pCnt
->IsTabFrame() )
4106 if( nInv
& SwInvalidateFlags::Size
)
4107 pSect
->InvalidateSize_();
4108 if( nInv
& SwInvalidateFlags::Pos
)
4109 pSect
->InvalidatePos_();
4110 if( nInv
& SwInvalidateFlags::PrtArea
)
4111 pSect
->InvalidatePrt_();
4112 SwFlowFrame
*pFoll
= pSect
->GetFollow();
4113 // Temporary separation from follow
4114 pSect
->SetFollow( nullptr );
4115 SwContentFrame
* pRet
= pSect
->FindLastContent();
4116 pSect
->SetFollow( pFoll
);
4120 static SwContentFrame
* lcl_InvalidateTable( SwTabFrame
*pTable
, SwInvalidateFlags nInv
)
4122 if( ( nInv
& SwInvalidateFlags::Section
) && pTable
->IsInSct() )
4123 lcl_InvalidateSection( pTable
, nInv
);
4124 if( nInv
& SwInvalidateFlags::Size
)
4125 pTable
->InvalidateSize_();
4126 if( nInv
& SwInvalidateFlags::Pos
)
4127 pTable
->InvalidatePos_();
4128 if( nInv
& SwInvalidateFlags::PrtArea
)
4129 pTable
->InvalidatePrt_();
4130 return pTable
->FindLastContent();
4133 static void lcl_InvalidateAllContent( SwContentFrame
*pCnt
, SwInvalidateFlags nInv
);
4135 static void lcl_InvalidateContent( SwContentFrame
*pCnt
, SwInvalidateFlags nInv
)
4137 SwContentFrame
*pLastTabCnt
= nullptr;
4138 SwContentFrame
*pLastSctCnt
= nullptr;
4141 if( nInv
& SwInvalidateFlags::Section
)
4143 if( pCnt
->IsInSct() )
4145 // See above at tables
4147 pLastSctCnt
= lcl_InvalidateSection( pCnt
, nInv
);
4148 if( pLastSctCnt
== pCnt
)
4149 pLastSctCnt
= nullptr;
4151 #if OSL_DEBUG_LEVEL > 0
4153 OSL_ENSURE( !pLastSctCnt
, "Where's the last SctContent?" );
4156 if( nInv
& SwInvalidateFlags::Table
)
4158 if( pCnt
->IsInTab() )
4160 // To not call FindTabFrame() for each ContentFrame of a table and
4161 // then invalidate the table, we remember the last ContentFrame of
4162 // the table and ignore IsInTab() until we are past it.
4163 // When entering the table, LastSctCnt is set to null, so
4164 // sections inside the table are correctly invalidated.
4165 // If the table itself is in a section the
4166 // invalidation is done three times, which is acceptable.
4169 pLastTabCnt
= lcl_InvalidateTable( pCnt
->FindTabFrame(), nInv
);
4170 pLastSctCnt
= nullptr;
4172 if( pLastTabCnt
== pCnt
)
4174 pLastTabCnt
= nullptr;
4175 pLastSctCnt
= nullptr;
4178 #if OSL_DEBUG_LEVEL > 0
4180 OSL_ENSURE( !pLastTabCnt
, "Where's the last TabContent?" );
4184 if( nInv
& SwInvalidateFlags::Size
)
4185 pCnt
->Prepare( PrepareHint::Clear
, nullptr, false );
4186 if( nInv
& SwInvalidateFlags::Pos
)
4187 pCnt
->InvalidatePos_();
4188 if( nInv
& SwInvalidateFlags::PrtArea
)
4189 pCnt
->InvalidatePrt_();
4190 if ( nInv
& SwInvalidateFlags::LineNum
)
4191 pCnt
->InvalidateLineNum();
4192 if ( pCnt
->GetDrawObjs() )
4193 lcl_InvalidateAllContent( pCnt
, nInv
);
4194 pCnt
= pCnt
->GetNextContentFrame();
4198 static void lcl_InvalidateAllContent( SwContentFrame
*pCnt
, SwInvalidateFlags nInv
)
4200 SwSortedObjs
&rObjs
= *pCnt
->GetDrawObjs();
4201 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
4203 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
4205 if ( pFly
->IsFlyInContentFrame() )
4207 ::lcl_InvalidateContent( pFly
->ContainsContent(), nInv
);
4208 if( nInv
& SwInvalidateFlags::Direction
)
4209 pFly
->CheckDirChange();
4215 void SwRootFrame::InvalidateAllContent( SwInvalidateFlags nInv
)
4217 // First process all page bound FlyFrames.
4218 SwPageFrame
*pPage
= static_cast<SwPageFrame
*>(Lower());
4221 pPage
->InvalidateFlyLayout();
4222 pPage
->InvalidateFlyContent();
4223 pPage
->InvalidateFlyInCnt();
4224 pPage
->InvalidateLayout();
4225 pPage
->InvalidateContent();
4226 pPage
->InvalidatePage( pPage
); // So even the Turbo disappears if applicable
4228 if ( pPage
->GetSortedObjs() )
4230 const SwSortedObjs
&rObjs
= *pPage
->GetSortedObjs();
4231 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
4233 if ( auto pFly
= pAnchoredObj
->DynCastFlyFrame() )
4235 ::lcl_InvalidateContent( pFly
->ContainsContent(), nInv
);
4236 if ( nInv
& SwInvalidateFlags::Direction
)
4237 pFly
->CheckDirChange();
4241 if( nInv
& SwInvalidateFlags::Direction
)
4242 pPage
->CheckDirChange();
4243 pPage
= static_cast<SwPageFrame
*>(pPage
->GetNext());
4246 //Invalidate the whole document content and the character bound Flys here.
4247 ::lcl_InvalidateContent( ContainsContent(), nInv
);
4249 if( nInv
& SwInvalidateFlags::PrtArea
)
4251 SwViewShell
*pSh
= getRootFrame()->GetCurrShell();
4253 pSh
->InvalidateWindows( getFrameArea() );
4258 * Invalidate/re-calculate the position of all floating screen objects (Writer fly frames and
4259 * drawing objects), that are anchored to paragraph or to character. (2004-03-16 #i11860#)
4261 void SwRootFrame::InvalidateAllObjPos()
4263 const SwPageFrame
* pPageFrame
= static_cast<const SwPageFrame
*>(Lower());
4266 pPageFrame
->InvalidateFlyLayout();
4268 if ( pPageFrame
->GetSortedObjs() )
4270 const SwSortedObjs
& rObjs
= *(pPageFrame
->GetSortedObjs());
4271 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
4273 const SwFormatAnchor
& rAnch
= pAnchoredObj
->GetFrameFormat().GetAnchor();
4274 if ((rAnch
.GetAnchorId() != RndStdIds::FLY_AT_PARA
) &&
4275 (rAnch
.GetAnchorId() != RndStdIds::FLY_AT_CHAR
))
4277 // only to paragraph and to character anchored objects are considered.
4280 // #i28701# - special invalidation for anchored
4281 // objects, whose wrapping style influence has to be considered.
4282 if ( pAnchoredObj
->ConsiderObjWrapInfluenceOnObjPos() )
4283 pAnchoredObj
->InvalidateObjPosForConsiderWrapInfluence();
4285 pAnchoredObj
->InvalidateObjPos();
4289 pPageFrame
= static_cast<const SwPageFrame
*>(pPageFrame
->GetNext());
4293 static void AddRemoveFlysForNode(
4294 SwTextFrame
& rFrame
, SwTextNode
& rTextNode
,
4295 std::set
<SwNodeOffset
> *const pSkipped
,
4296 const sw::FrameFormats
<sw::SpzFrameFormat
*>& rTable
,
4297 SwPageFrame
*const pPage
,
4298 SwTextNode
const*const pNode
,
4299 std::vector
<sw::Extent
>::const_iterator
const& rIterFirst
,
4300 std::vector
<sw::Extent
>::const_iterator
const& rIterEnd
,
4301 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
4303 if (pNode
== &rTextNode
)
4304 { // remove existing hidden at-char anchored flys
4305 RemoveHiddenObjsOfNode(rTextNode
, &rIterFirst
, &rIterEnd
, pFirstNode
, pLastNode
);
4307 else if (rTextNode
.GetIndex() < pNode
->GetIndex())
4309 // pNode's frame has been deleted by CheckParaRedlineMerge()
4310 AppendObjsOfNode(&rTable
,
4311 pNode
->GetIndex(), &rFrame
, pPage
, &rTextNode
.GetDoc(),
4312 &rIterFirst
, &rIterEnd
, pFirstNode
, pLastNode
);
4315 // 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
4316 for (auto const pFly
: pNode
->GetAnchoredFlys())
4318 if (pFly
->Which() != RES_DRAWFRMFMT
)
4320 pSkipped
->insert(pFly
->GetContent().GetContentIdx()->GetIndex());
4329 /// rTextNode is the first one of the "new" merge - if rTextNode isn't the same
4330 /// as MergedPara::pFirstNode, then nodes before rTextNode have their flys
4331 /// already properly attached, so only the other nodes need handling here.
4332 void AddRemoveFlysAnchoredToFrameStartingAtNode(
4333 SwTextFrame
& rFrame
, SwTextNode
& rTextNode
,
4334 std::set
<SwNodeOffset
> *const pSkipped
)
4336 auto const pMerged(rFrame
.GetMergedPara());
4338 // do this only *once*, for the *last* frame
4339 // otherwise AppendObj would create multiple frames for fly-frames!
4340 || rFrame
.GetFollow())
4343 assert(pMerged
->pFirstNode
->GetIndex() <= rTextNode
.GetIndex()
4344 && rTextNode
.GetIndex() <= pMerged
->pLastNode
->GetIndex());
4345 // add visible flys in non-first node to merged frame
4346 // (hidden flys remain and are deleted via DelFrames())
4347 sw::SpzFrameFormats
& rTable(*rTextNode
.GetDoc().GetSpzFrameFormats());
4348 SwPageFrame
*const pPage(rFrame
.FindPageFrame());
4349 std::vector
<sw::Extent
>::const_iterator
iterFirst(pMerged
->extents
.begin());
4350 std::vector
<sw::Extent
>::const_iterator
iter(iterFirst
);
4351 SwTextNode
const* pNode(pMerged
->pFirstNode
);
4354 if (iter
== pMerged
->extents
.end()
4355 || iter
->pNode
!= pNode
)
4357 AddRemoveFlysForNode(rFrame
, rTextNode
, pSkipped
, rTable
, pPage
,
4358 pNode
, iterFirst
, iter
,
4359 pMerged
->pFirstNode
, pMerged
->pLastNode
);
4360 SwNodeOffset
const until
= iter
== pMerged
->extents
.end()
4361 ? pMerged
->pLastNode
->GetIndex() + 1
4362 : iter
->pNode
->GetIndex();
4363 for (SwNodeOffset i
= pNode
->GetIndex() + 1; i
< until
; ++i
)
4365 // let's show at-para flys on nodes that contain start/end of
4366 // redline too, even if there's no text there
4367 SwNode
const*const pTmp(pNode
->GetNodes()[i
]);
4368 if (pTmp
->GetRedlineMergeFlag() == SwNode::Merge::NonFirst
)
4370 AddRemoveFlysForNode(rFrame
, rTextNode
, pSkipped
,
4371 rTable
, pPage
, pTmp
->GetTextNode(), iter
, iter
,
4372 pMerged
->pFirstNode
, pMerged
->pLastNode
);
4375 if (iter
== pMerged
->extents
.end())
4379 pNode
= iter
->pNode
;
4387 static void UnHideRedlines(SwRootFrame
& rLayout
,
4388 SwNodes
& rNodes
, SwNode
const& rEndOfSectionNode
,
4389 std::set
<SwNodeOffset
> *const pSkipped
)
4391 assert(rEndOfSectionNode
.IsEndNode());
4392 assert(rNodes
[rEndOfSectionNode
.StartOfSectionNode()->GetIndex() + 1]->IsCreateFrameWhenHidingRedlines()); // first node is never hidden
4393 for (SwNodeOffset i
= rEndOfSectionNode
.StartOfSectionNode()->GetIndex() + 1;
4394 i
< rEndOfSectionNode
.GetIndex(); ++i
)
4396 SwNode
& rNode(*rNodes
[i
]);
4397 if (rNode
.IsTextNode()) // only text nodes are 1st node of a merge
4399 SwTextNode
& rTextNode(*rNode
.GetTextNode());
4400 SwIterator
<SwTextFrame
, SwTextNode
, sw::IteratorMode::UnwrapMulti
> aIter(rTextNode
);
4401 std::vector
<SwTextFrame
*> frames
;
4402 for (SwTextFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next())
4404 if (pFrame
->getRootFrame() == &rLayout
)
4406 if (pFrame
->IsFollow())
4408 frames
.push_back(pFrame
);
4409 } // when hiding, the loop must remove the anchored flys
4410 else // *before* resetting SetMergedPara anywhere - else
4411 { // the fly deletion code will access multiple of the
4412 // frames with inconsistent MergedPara and assert
4413 frames
.insert(frames
.begin(), pFrame
);
4417 // this messes with pRegisteredIn so do it outside SwIterator
4418 auto eMode(sw::FrameMode::Existing
);
4419 for (SwTextFrame
* pFrame
: frames
)
4421 if (rLayout
.HasMergedParas())
4423 assert(!pFrame
->GetMergedPara() ||
4424 !rNode
.IsCreateFrameWhenHidingRedlines() ||
4425 // FIXME: skip this assert in tables with deleted rows
4427 if (rNode
.IsCreateFrameWhenHidingRedlines())
4430 auto pMerged(CheckParaRedlineMerge(*pFrame
,
4432 pFrame
->SetMergedPara(std::move(pMerged
));
4434 auto const pMerged(pFrame
->GetMergedPara());
4437 // invalidate SwInvalidateFlags::Size
4438 pFrame
->Prepare(PrepareHint::Clear
, nullptr, false);
4439 pFrame
->InvalidatePage();
4440 if (auto const pObjs
= pFrame
->GetDrawObjs())
4441 { // also invalidate position of existing flys
4442 // because they may need to be moved
4443 for (auto const pObject
: *pObjs
)
4445 pObject
->InvalidateObjPos();
4449 sw::AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame
, rTextNode
, pSkipped
);
4450 // only *first* frame of node gets Existing because it
4451 eMode
= sw::FrameMode::New
; // is not idempotent!
4456 if (auto const& pMergedPara
= pFrame
->GetMergedPara())
4458 // invalidate SwInvalidateFlags::Size
4459 pFrame
->Prepare(PrepareHint::Clear
, nullptr, false);
4460 pFrame
->InvalidatePage();
4461 if (auto const pObjs
= pFrame
->GetDrawObjs())
4462 { // also invalidate position of existing flys
4463 for (auto const pObject
: *pObjs
)
4465 pObject
->InvalidateObjPos();
4468 // SwFlyAtContentFrame::SwClientNotify() always appends to
4469 // the master frame, so do the same here.
4470 // (RemoveFootnotesForNode must be called at least once)
4471 if (!pFrame
->IsFollow())
4473 // the new text frames don't exist yet, so at this point
4474 // we can only delete the footnote frames so they don't
4475 // point to the merged SwTextFrame any more...
4476 assert(&rTextNode
== pMergedPara
->pFirstNode
);
4477 // iterate over nodes, not extents: if a node has
4478 // no extents now but did have extents initially,
4479 // its flys need their frames deleted too!
4480 for (SwNodeOffset j
= rTextNode
.GetIndex() + 1;
4481 j
<= pMergedPara
->pLastNode
->GetIndex(); ++j
)
4483 SwNode
*const pNode(rTextNode
.GetNodes()[j
]);
4484 assert(!pNode
->IsEndNode());
4485 if (pNode
->IsStartNode())
4487 j
= pNode
->EndOfSectionIndex();
4489 else if (pNode
->IsTextNode())
4491 sw::RemoveFootnotesForNode(rLayout
, *pNode
->GetTextNode(), nullptr);
4492 // similarly, remove the anchored flys
4493 for (SwFrameFormat
* pFormat
: pNode
->GetAnchoredFlys())
4495 pFormat
->DelFrames(/*&rLayout*/);
4499 // rely on AppendAllObjs call at the end to add
4500 // all flys in first node that are hidden
4502 pFrame
->SetMergedPara(nullptr);
4505 pFrame
->Broadcast(SfxHint()); // notify SwAccessibleParagraph
4507 // all nodes, not just merged ones! it may be in the same list as
4508 if (rTextNode
.IsNumbered(nullptr)) // a preceding merged one...
4509 { // notify frames so they reformat numbering portions
4510 rTextNode
.NumRuleChgd();
4513 else if (rNode
.IsTableNode() && rLayout
.IsHideRedlines())
4515 SwTableNode
* pTableNd
= rNode
.GetTableNode();
4516 SwPosition
const tmp(rNode
);
4517 SwRangeRedline
const*const pRedline(
4518 rLayout
.GetFormat()->GetDoc()->getIDocumentRedlineAccess().GetRedline(tmp
, nullptr));
4519 // pathology: redline that starts on a TableNode; cannot
4520 // be created in UI but by import filters...
4522 && pRedline
->GetType() == RedlineType::Delete
4523 && &pRedline
->Start()->GetNode() == &rNode
)
4525 for (SwNodeOffset j
= rNode
.GetIndex(); j
<= rNode
.EndOfSectionIndex(); ++j
)
4527 rNode
.GetNodes()[j
]->SetRedlineMergeFlag(SwNode::Merge::Hidden
);
4529 pTableNd
->DelFrames(&rLayout
);
4531 else if ( pTableNd
->GetTable().HasDeletedRowOrCell() )
4533 pTableNd
->DelFrames(&rLayout
);
4534 if ( !pTableNd
->GetTable().IsDeleted() )
4536 pTableNd
->MakeOwnFrames();
4540 else if (rNode
.IsTableNode() && !rLayout
.IsHideRedlines() &&
4541 rNode
.GetTableNode()->GetTable().HasDeletedRowOrCell() )
4543 SwTableNode
* pTableNd
= rNode
.GetTableNode();
4544 pTableNd
->DelFrames(&rLayout
);
4545 pTableNd
->MakeOwnFrames();
4548 if (!rNode
.IsCreateFrameWhenHidingRedlines())
4550 if (rLayout
.HasMergedParas())
4552 if (rNode
.IsContentNode())
4554 // note: nothing to do here, already done
4556 auto const pFrame(static_cast<SwContentNode
&>(rNode
).getLayoutFrame(&rLayout
));
4557 assert(!pFrame
|| static_cast<SwTextFrame
*>(pFrame
)->GetMergedPara()->pFirstNode
!= &rNode
);
4563 assert(!rNode
.IsContentNode() || !rNode
.GetContentNode()->getLayoutFrame(&rLayout
) ||
4564 // FIXME: skip this assert in tables with deleted rows
4565 rNode
.GetContentNode()->getLayoutFrame(&rLayout
)->IsInTab());
4566 SwNodeOffset j
= i
+ 1;
4567 for ( ; j
< rEndOfSectionNode
.GetIndex(); ++j
)
4569 if (rNodes
[j
]->IsCreateFrameWhenHidingRedlines())
4574 // call MakeFrames once, because sections/tables
4575 // InsertCnt_ also checks for hidden sections
4577 sw::FlyCreationSuppressor
aSuppressor(false);
4578 ::MakeFrames(rLayout
.GetFormat()->GetDoc(), *rNodes
[i
], *rNodes
[j
]);
4580 i
= j
- 1; // will be incremented again
4586 static void UnHideRedlinesExtras(SwRootFrame
& rLayout
,
4587 SwNodes
& rNodes
, SwNode
const& rEndOfExtraSectionNode
,
4588 std::set
<SwNodeOffset
> *const pSkipped
)
4590 assert(rEndOfExtraSectionNode
.IsEndNode());
4591 for (SwNodeOffset i
= rEndOfExtraSectionNode
.StartOfSectionNode()->GetIndex()
4592 + 1; i
< rEndOfExtraSectionNode
.GetIndex(); ++i
)
4594 SwNode
const& rStartNode(*rNodes
[i
]);
4595 assert(rStartNode
.IsStartNode());
4596 assert(rStartNode
.GetRedlineMergeFlag() == SwNode::Merge::None
);
4597 SwNode
const& rEndNode(*rStartNode
.EndOfSectionNode());
4598 bool bSkip(pSkipped
&& pSkipped
->find(i
) != pSkipped
->end());
4599 i
= rEndNode
.GetIndex();
4600 for (SwNodeOffset j
= rStartNode
.GetIndex() + 1; j
< i
; ++j
)
4602 // note: SwStartNode has no way to access the frames, so check
4603 // whether the first content-node inside the section has frames
4604 SwNode
const& rNode(*rNodes
[j
]);
4605 if (rNode
.IsSectionNode() &&
4606 static_cast<SwSectionNode
const&>(rNode
).GetSection().IsHiddenFlag())
4607 { // skip hidden sections - they can be inserted in fly-frames :(
4608 j
= rNode
.EndOfSectionNode()->GetIndex();
4611 if (rNode
.IsContentNode())
4613 SwContentNode
const& rCNode(static_cast<SwContentNode
const&>(rNode
));
4614 if (!rCNode
.getLayoutFrame(&rLayout
))
4615 { // ignore footnote/fly/header/footer with no layout frame
4616 bSkip
= true; // they will be created from scratch later if needed
4623 UnHideRedlines(rLayout
, rNodes
, rEndNode
, pSkipped
);
4628 static void UnHide(SwRootFrame
& rLayout
)
4630 assert(rLayout
.GetCurrShell()->ActionPend()); // tdf#125754 avoid recursive layout
4631 SwDoc
& rDoc(*rLayout
.GetFormat()->GetDoc());
4632 // don't do early return if there are no redlines:
4633 // Show->Hide must init hidden number trees
4634 // Hide->Show may be called after all redlines have been deleted but there
4635 // may still be MergedParas because those aren't deleted yet...
4638 && rDoc
.getIDocumentRedlineAccess().GetRedlineTable().empty())
4643 // Hide->Show: clear MergedPara, create frames
4644 // Show->Hide: call CheckParaRedlineMerge, delete frames
4645 // Traverse the document via the nodes-array; traversing via the layout
4646 // wouldn't find the nodes that don't have frames in the ->Show case.
4647 // In-order traversal of each nodes array section should init the flags
4648 // in nodes before they are iterated.
4649 // Actual creation of frames should be done with existing functions
4650 // if possible, particularly InsertCnt_() or its wrapper ::MakeFrames().
4651 SwNodes
/*const*/& rNodes(rDoc
.GetNodes());
4652 // Flys/footnotes: must iterate and find all the ones that already exist
4653 // with frames and have redlines inside them; if any don't have frames at
4654 // all, they will be created (if necessary) from scratch and completely by
4657 // Flys before footnotes: because footnotes may contain flys but not
4658 // vice-versa; alas flys may contain flys, so we skip some of them
4659 // if they have already been created from scratch via their anchor flys.
4660 std::set
<SwNodeOffset
> skippedFlys
;
4661 UnHideRedlinesExtras(rLayout
, rNodes
, rNodes
.GetEndOfAutotext(),
4662 // when un-hiding, delay all fly frame creation to AppendAllObjs below
4663 rLayout
.HasMergedParas() ? &skippedFlys
: nullptr);
4664 // Footnotes are created automatically (after invalidation etc.) by
4665 // ConnectFootnote(), but need to be deleted manually. Footnotes do not
4666 // occur in flys or headers/footers.
4667 UnHideRedlinesExtras(rLayout
, rNodes
, rNodes
.GetEndOfInserts(), nullptr);
4668 UnHideRedlines(rLayout
, rNodes
, rNodes
.GetEndOfContent(), nullptr);
4670 if (!rLayout
.HasMergedParas())
4671 { // create all previously hidden flys at once:
4672 // * Flys on first node of pre-existing merged frames that are hidden
4673 // (in delete redline), to be added to the existing frame
4674 // * Flys on non-first (hidden/merged) nodes of pre-existing merged
4675 // frames, to be added to the new frame of their node
4676 // * Flys anchored in other flys that are hidden
4677 AppendAllObjs(rDoc
.GetSpzFrameFormats(), &rLayout
);
4680 const bool bIsShowChangesInMargin
= rLayout
.GetCurrShell()->GetViewOptions()->IsShowChangesInMargin();
4681 for (auto const pRedline
: rDoc
.getIDocumentRedlineAccess().GetRedlineTable())
4682 { // DELETE are handled by the code above; for other types, need to
4683 // trigger repaint of text frames to add/remove the redline color font
4684 // (handle deletions showed in margin also here)
4685 if (bIsShowChangesInMargin
|| pRedline
->GetType() != RedlineType::Delete
)
4687 pRedline
->InvalidateRange(SwRangeRedline::Invalidation::Add
);
4691 SwFootnoteIdxs
& rFootnotes(rDoc
.GetFootnoteIdxs());
4692 if (rDoc
.GetFootnoteInfo().m_eNum
== FTNNUM_CHAPTER
)
4694 // sadly determining which node is outline node requires hidden layout
4695 rFootnotes
.UpdateAllFootnote();
4697 // invalidate all footnotes to reformat their numbers
4698 for (SwTextFootnote
*const pFootnote
: rFootnotes
)
4700 SwFormatFootnote
const& rFootnote(pFootnote
->GetFootnote());
4701 if (rFootnote
.GetNumber() != rFootnote
.GetNumberRLHidden()
4702 && rFootnote
.GetNumStr().isEmpty())
4704 pFootnote
->InvalidateNumberInLayout();
4707 // update various fields to re-expand them with the new layout
4708 IDocumentFieldsAccess
& rIDFA(rDoc
.getIDocumentFieldsAccess());
4709 auto const pAuthType(rIDFA
.GetFieldType(
4710 SwFieldIds::TableOfAuthorities
, OUString(), false));
4711 if (pAuthType
) // created on demand...
4712 { // calling DelSequenceArray() should be unnecessary here since the
4713 // sequence doesn't depend on frames
4714 pAuthType
->UpdateFields();
4716 rIDFA
.GetFieldType(SwFieldIds::RefPageGet
, OUString(), false)->UpdateFields();
4717 rIDFA
.GetSysFieldType(SwFieldIds::Chapter
)->UpdateFields();
4718 rIDFA
.UpdateExpFields(nullptr, false);
4719 rIDFA
.UpdateRefFields();
4721 // update SwPostItMgr / notes in the margin
4722 // note: as long as all shells share layout, broadcast to all shells!
4723 rDoc
.GetDocShell()->Broadcast( SwFormatFieldHint(nullptr, rLayout
.HasMergedParas()
4724 ? SwFormatFieldHintWhich::REMOVED
4725 : SwFormatFieldHintWhich::INSERTED
) );
4728 // InvalidateAllContent(SwInvalidateFlags::Size); // ??? TODO what to invalidate? this is the big hammer
4731 void SwRootFrame::SetHideRedlines(bool const bHideRedlines
)
4733 if (bHideRedlines
== mbHideRedlines
)
4737 // TODO: remove temporary ShowBoth
4738 sw::FieldmarkMode
const eMode(m_FieldmarkMode
);
4739 sw::ParagraphBreakMode
const ePBMode(m_ParagraphBreakMode
);
4740 if (HasMergedParas())
4742 m_FieldmarkMode
= sw::FieldmarkMode::ShowBoth
;
4743 m_ParagraphBreakMode
= sw::ParagraphBreakMode::Shown
;
4744 mbHideRedlines
= false;
4747 if (bHideRedlines
|| eMode
!= m_FieldmarkMode
|| ePBMode
!= m_ParagraphBreakMode
)
4749 m_FieldmarkMode
= eMode
;
4750 m_ParagraphBreakMode
= ePBMode
;
4751 mbHideRedlines
= bHideRedlines
;
4756 void SwRootFrame::SetFieldmarkMode(sw::FieldmarkMode
const eFMMode
, sw::ParagraphBreakMode
const ePBMode
)
4758 if (eFMMode
== m_FieldmarkMode
&& ePBMode
== m_ParagraphBreakMode
)
4762 // TODO: remove temporary ShowBoth
4763 bool const isHideRedlines(mbHideRedlines
);
4764 if (HasMergedParas())
4766 mbHideRedlines
= false;
4767 m_FieldmarkMode
= sw::FieldmarkMode::ShowBoth
;
4768 m_ParagraphBreakMode
= sw::ParagraphBreakMode::Shown
;
4771 if (isHideRedlines
|| eFMMode
!= sw::FieldmarkMode::ShowBoth
|| ePBMode
== sw::ParagraphBreakMode::Hidden
)
4773 mbHideRedlines
= isHideRedlines
;
4774 m_FieldmarkMode
= eFMMode
;
4775 m_ParagraphBreakMode
= ePBMode
;
4780 bool SwRootFrame::HasMergedParas() const
4782 return IsHideRedlines()
4783 || GetFieldmarkMode() != sw::FieldmarkMode::ShowBoth
4784 || GetParagraphBreakMode() == sw::ParagraphBreakMode::Hidden
;
4788 xmlTextWriterPtr
lcl_createDefaultWriter()
4790 xmlTextWriterPtr writer
= xmlNewTextWriterFilename( "layout.xml", 0 );
4791 xmlTextWriterSetIndent(writer
,1);
4792 (void)xmlTextWriterSetIndentString(writer
, BAD_CAST(" "));
4793 (void)xmlTextWriterStartDocument( writer
, nullptr, nullptr, nullptr );
4797 void lcl_freeWriter( xmlTextWriterPtr writer
)
4799 (void)xmlTextWriterEndDocument( writer
);
4800 xmlFreeTextWriter( writer
);
4804 void SwRootFrame::dumpAsXml(xmlTextWriterPtr writer
) const
4806 bool bCreateWriter
= (nullptr == writer
);
4808 writer
= lcl_createDefaultWriter();
4810 (void)xmlTextWriterStartElement(writer
, reinterpret_cast<const xmlChar
*>("root"));
4811 dumpAsXmlAttributes(writer
);
4813 (void)xmlTextWriterStartElement(writer
, BAD_CAST("sfxViewShells"));
4814 SwView
* pView
= static_cast<SwView
*>(SfxViewShell::GetFirst(true, checkSfxViewShell
<SwView
>));
4817 if (GetCurrShell()->GetSfxViewShell() && pView
->GetObjectShell() == GetCurrShell()->GetSfxViewShell()->GetObjectShell())
4818 pView
->dumpAsXml(writer
);
4819 pView
= static_cast<SwView
*>(SfxViewShell::GetNext(*pView
, true, checkSfxViewShell
<SwView
>));
4821 (void)xmlTextWriterEndElement(writer
);
4823 (void)xmlTextWriterStartElement(writer
, BAD_CAST("infos"));
4824 dumpInfosAsXml(writer
);
4825 (void)xmlTextWriterEndElement(writer
);
4826 dumpChildrenAsXml(writer
);
4827 (void)xmlTextWriterEndElement(writer
);
4830 lcl_freeWriter(writer
);
4833 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */