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