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