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