1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_wasm_strip.h>
22 #include <svx/svdpage.hxx>
23 #include <editeng/brushitem.hxx>
24 #include <editeng/shaditem.hxx>
25 #include <editeng/ulspitem.hxx>
26 #include <editeng/boxitem.hxx>
27 #include <editeng/lspcitem.hxx>
28 #include <editeng/fhgtitem.hxx>
29 #include <sal/log.hxx>
30 #include <o3tl/deleter.hxx>
31 #include <osl/diagnose.h>
33 #include <drawdoc.hxx>
34 #include <fmtornt.hxx>
35 #include <fmthdft.hxx>
36 #include <fmtfsize.hxx>
37 #include <fmtsrnd.hxx>
39 #include <lineinfo.hxx>
40 #include <swmodule.hxx>
41 #include <pagefrm.hxx>
44 #include <viewimp.hxx>
45 #include <viewopt.hxx>
46 #include <dflyobj.hxx>
47 #include <dcontact.hxx>
49 #include <frmtool.hxx>
54 #include <notxtfrm.hxx>
55 #include <flyfrms.hxx>
57 #include <pagedesc.hxx>
58 #include <section.hxx>
59 #include <sectfrm.hxx>
60 #include <node2lay.hxx>
63 #include "layhelp.hxx"
64 #include <laycache.hxx>
65 #include <rootfrm.hxx>
67 #include <redline.hxx>
68 #include <sortedobjs.hxx>
69 #include <objectformatter.hxx>
73 #include <DocumentSettingManager.hxx>
74 #include <IDocumentDrawModelAccess.hxx>
75 #include <IDocumentLayoutAccess.hxx>
76 #include <IDocumentTimerAccess.hxx>
77 #include <IDocumentRedlineAccess.hxx>
78 #include <IDocumentFieldsAccess.hxx>
79 #include <IDocumentState.hxx>
80 #include <frameformats.hxx>
81 #include <boost/circular_buffer.hpp>
82 #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
84 using namespace ::com::sun::star
;
87 // FIXME: would likely better be a member of SwRootFrame instead of a global flag
88 bool isFlyCreationSuppressed
= false;
91 FlyCreationSuppressor::FlyCreationSuppressor(bool wasAlreadySuppressedAllowed
)
92 : m_wasAlreadySuppressed(isFlyCreationSuppressed
)
94 (void)wasAlreadySuppressedAllowed
;
95 assert(wasAlreadySuppressedAllowed
|| !isFlyCreationSuppressed
);
96 isFlyCreationSuppressed
= true;
98 FlyCreationSuppressor::~FlyCreationSuppressor()
100 isFlyCreationSuppressed
= m_wasAlreadySuppressed
;
104 bool bObjsDirect
= true;
105 bool bSetCompletePaintOnInvalidate
= false;
107 sal_uInt8
StackHack::s_nCnt
= 0;
108 bool StackHack::s_bLocked
= false;
110 SwFrameNotify::SwFrameNotify( SwFrame
*pF
) :
112 maFrame( pF
->getFrameArea() ),
113 maPrt( pF
->getFramePrintArea() ),
115 mbValidSize( pF
->isFrameAreaSizeValid() )
117 if ( pF
->IsTextFrame() )
119 mnFlyAnchorOfst
= static_cast<SwTextFrame
*>(pF
)->GetBaseOffsetForFly( true );
120 mnFlyAnchorOfstNoWrap
= static_cast<SwTextFrame
*>(pF
)->GetBaseOffsetForFly( false );
125 mnFlyAnchorOfstNoWrap
= 0;
128 mbHadFollow
= pF
->IsContentFrame() && static_cast<SwContentFrame
*>(pF
)->GetFollow();
131 SwFrameNotify::~SwFrameNotify()
133 suppress_fun_call_w_exception(ImplDestroy());
136 void SwFrameNotify::ImplDestroy()
138 SwRectFnSet
aRectFnSet(mpFrame
);
139 const bool bAbsP
= aRectFnSet
.PosDiff(maFrame
, mpFrame
->getFrameArea());
140 const bool bChgWidth
=
141 aRectFnSet
.GetWidth(maFrame
) != aRectFnSet
.GetWidth(mpFrame
->getFrameArea());
142 const bool bChgHeight
=
143 aRectFnSet
.GetHeight(maFrame
)!=aRectFnSet
.GetHeight(mpFrame
->getFrameArea());
144 const bool bChgFlyBasePos
= mpFrame
->IsTextFrame() &&
145 ( ( mnFlyAnchorOfst
!= static_cast<SwTextFrame
*>(mpFrame
)->GetBaseOffsetForFly( true ) ) ||
146 ( mnFlyAnchorOfstNoWrap
!= static_cast<SwTextFrame
*>(mpFrame
)->GetBaseOffsetForFly( false ) ) );
148 if ( mpFrame
->IsFlowFrame() && !mpFrame
->IsInFootnote() )
150 SwFlowFrame
*pFlow
= SwFlowFrame::CastFlowFrame( mpFrame
);
152 if ( !pFlow
->IsFollow() )
154 if ( !mpFrame
->GetIndPrev() )
158 SwFrame
*pPre
= pFlow
->FindPrevIgnoreHidden();
159 if ( pPre
&& pPre
->IsFlowFrame() )
161 // 1. pPre wants to keep with me:
162 bool bInvalidPrePos
= SwFlowFrame::CastFlowFrame(pPre
)->IsKeep(pPre
->GetAttrSet()->GetKeep(), pPre
->GetBreakItem())
163 && pPre
->GetIndPrev();
165 // 2. pPre is a table and the last row wants to keep with me:
166 if ( !bInvalidPrePos
&& pPre
->IsTabFrame() )
168 SwTabFrame
* pPreTab
= static_cast<SwTabFrame
*>(pPre
);
169 if ( pPreTab
->GetFormat()->GetDoc()->GetDocumentSettingManager().get(DocumentSettingId::TABLE_ROW_KEEP
) )
171 SwRowFrame
* pLastRow
= static_cast<SwRowFrame
*>(pPreTab
->GetLastLower());
172 if ( pLastRow
&& pLastRow
->ShouldRowKeepWithNext() )
173 bInvalidPrePos
= true;
177 if ( bInvalidPrePos
)
178 pPre
->InvalidatePos();
182 else if ( !pFlow
->HasFollow() )
184 tools::Long nOldHeight
= aRectFnSet
.GetHeight(maFrame
);
185 tools::Long nNewHeight
= aRectFnSet
.GetHeight(mpFrame
->getFrameArea());
186 if( (nOldHeight
> nNewHeight
) || (!nOldHeight
&& nNewHeight
) )
194 mpFrame
->SetCompletePaint();
196 SwFrame
* pNxt
= mpFrame
->GetIndNext();
197 // #121888# - skip empty section frames
199 pNxt
->IsSctFrame() && !static_cast<SwSectionFrame
*>(pNxt
)->GetSection() )
201 pNxt
= pNxt
->GetIndNext();
206 pNxt
->InvalidatePos();
207 if (pNxt
->IsTextFrame() && static_cast<SwTextFrame
*>(pNxt
)->IsUndersized())
208 { // tdf#137523 it could have more space at new pos
209 pNxt
->InvalidateSize();
210 pNxt
->Prepare(PrepareHint::AdjustSizeWithoutFormatting
);
215 // #104100# - correct condition for setting retouche
216 // flag for vertical layout.
217 if( mpFrame
->IsRetoucheFrame() &&
218 aRectFnSet
.TopDist( maFrame
, aRectFnSet
.GetTop(mpFrame
->getFrameArea()) ) > 0 )
220 mpFrame
->SetRetouche();
223 // A fresh follow frame does not have to be invalidated, because
224 // it is already formatted:
225 if ( mbHadFollow
|| !mpFrame
->IsContentFrame() || !static_cast<SwContentFrame
*>(mpFrame
)->GetFollow() )
227 if ( !mpFrame
->IsTabFrame() || !static_cast<SwTabFrame
*>(mpFrame
)->GetFollow() )
228 mpFrame
->InvalidateNextPos();
233 //For each resize of the background graphics is a repaint necessary.
234 const bool bPrtWidth
=
235 aRectFnSet
.GetWidth(maPrt
) != aRectFnSet
.GetWidth(mpFrame
->getFramePrintArea());
236 const bool bPrtHeight
=
237 aRectFnSet
.GetHeight(maPrt
)!=aRectFnSet
.GetHeight(mpFrame
->getFramePrintArea());
238 if ( bPrtWidth
|| bPrtHeight
)
240 bool bUseNewFillProperties(false);
241 if (mpFrame
->supportsFullDrawingLayerFillAttributeSet())
243 drawinglayer::attribute::SdrAllFillAttributesHelperPtr
aFillAttributes(mpFrame
->getSdrAllFillAttributesHelper());
244 if(aFillAttributes
&& aFillAttributes
->isUsed())
246 bUseNewFillProperties
= true;
247 // use SetCompletePaint if needed
248 if(aFillAttributes
->needCompleteRepaint())
250 mpFrame
->SetCompletePaint();
254 if (!bUseNewFillProperties
)
256 const SvxGraphicPosition ePos
= mpFrame
->GetAttrSet()->GetBackground().GetGraphicPos();
257 if(GPOS_NONE
!= ePos
&& GPOS_TILED
!= ePos
)
258 mpFrame
->SetCompletePaint();
263 // #97597# - consider case that *only* margins between
264 // frame and printing area has changed. Then, frame has to be repainted,
265 // in order to force paint of the margin areas.
266 if ( !bAbsP
&& (bChgWidth
|| bChgHeight
) )
268 mpFrame
->SetCompletePaint();
272 const bool bPrtP
= aRectFnSet
.PosDiff( maPrt
, mpFrame
->getFramePrintArea() );
273 if ( bAbsP
|| bPrtP
|| bChgWidth
|| bChgHeight
||
274 bPrtWidth
|| bPrtHeight
|| bChgFlyBasePos
)
276 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
277 if( mpFrame
->IsAccessibleFrame() )
279 SwRootFrame
*pRootFrame
= mpFrame
->getRootFrame();
280 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
281 pRootFrame
->GetCurrShell() )
283 pRootFrame
->GetCurrShell()->Imp()->MoveAccessibleFrame( mpFrame
, maFrame
);
288 // Notification of anchored objects
289 if ( mpFrame
->GetDrawObjs() )
291 const SwSortedObjs
&rObjs
= *mpFrame
->GetDrawObjs();
292 SwPageFrame
* pPageFrame
= nullptr;
293 for (SwAnchoredObject
* pObj
: rObjs
)
295 // OD 2004-03-31 #i26791# - no general distinction between
296 // Writer fly frames and drawing objects
297 bool bNotify
= false;
298 bool bNotifySize
= false;
299 SwContact
* pContact
= ::GetUserCall( pObj
->GetDrawObj() );
302 const bool bAnchoredAsChar
= pContact
->ObjAnchoredAsChar();
303 if ( !bAnchoredAsChar
)
305 // Notify object, which aren't anchored as-character:
307 // always notify objects, if frame position has changed
308 // or if the object is to-page|to-fly anchored.
310 pContact
->ObjAnchoredAtPage() ||
311 pContact
->ObjAnchoredAtFly() )
315 // assure that to-fly anchored Writer fly frames are
316 // registered at the correct page frame, if frame
317 // position has changed.
318 if ( bAbsP
&& pContact
->ObjAnchoredAtFly() &&
319 pObj
->DynCastFlyFrame() != nullptr )
321 // determine to-fly anchored Writer fly frame
322 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrame
*>(pObj
);
323 // determine page frame of to-fly anchored
325 SwPageFrame
* pFlyPageFrame
= pFlyFrame
->FindPageFrame();
326 // determine page frame, if needed.
329 pPageFrame
= mpFrame
->FindPageFrame();
331 if ( pPageFrame
!= pFlyPageFrame
)
333 OSL_ENSURE( pFlyPageFrame
, "~SwFrameNotify: Fly from Nowhere" );
335 pFlyPageFrame
->MoveFly( pFlyFrame
, pPageFrame
);
337 pPageFrame
->AppendFlyToPage( pFlyFrame
);
341 // otherwise the objects are notified in dependence to
342 // its positioning and alignment
345 const SwFormatVertOrient
& rVert
=
346 pContact
->GetFormat()->GetVertOrient();
347 if ( ( rVert
.GetVertOrient() == text::VertOrientation::CENTER
||
348 rVert
.GetVertOrient() == text::VertOrientation::BOTTOM
||
349 rVert
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
) &&
350 ( bChgHeight
|| bPrtHeight
) )
356 const SwFormatHoriOrient
& rHori
=
357 pContact
->GetFormat()->GetHoriOrient();
358 if ( ( rHori
.GetHoriOrient() != text::HoriOrientation::NONE
||
359 rHori
.GetRelationOrient()== text::RelOrientation::PRINT_AREA
||
360 rHori
.GetRelationOrient()== text::RelOrientation::FRAME
) &&
361 ( bChgWidth
|| bPrtWidth
|| bChgFlyBasePos
) )
368 else if ( bPrtWidth
)
370 // Notify as-character anchored objects, if printing area
371 // width has changed.
376 // perform notification via the corresponding invalidations
379 if ( auto pFlyFrame
= pObj
->DynCastFlyFrame() )
382 pFlyFrame
->InvalidateSize_();
383 // #115759# - no invalidation of
384 // position for as-character anchored objects.
385 if ( !bAnchoredAsChar
)
387 pFlyFrame
->InvalidatePos_();
389 pFlyFrame
->Invalidate_();
391 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pObj
) != nullptr )
393 // #115759# - no invalidation of
394 // position for as-character anchored objects.
395 if ( !bAnchoredAsChar
)
397 pObj
->InvalidateObjPos();
402 OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - unknown anchored object type." );
408 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
409 else if( mpFrame
->IsTextFrame() && mbValidSize
!= mpFrame
->isFrameAreaSizeValid() )
411 SwRootFrame
*pRootFrame
= mpFrame
->getRootFrame();
412 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
413 pRootFrame
->GetCurrShell() )
415 pRootFrame
->GetCurrShell()->Imp()->InvalidateAccessibleFrameContent( mpFrame
);
420 // #i9046# Automatic frame width
421 SwFlyFrame
* pFly
= nullptr;
422 // #i35879# Do not trust the inf flags. pFrame does not
423 // necessarily have to have an upper!
424 if ( mpFrame
->IsFlyFrame() || nullptr == ( pFly
= mpFrame
->ImplFindFlyFrame() ))
428 // no invalidation of columned Writer fly frames, because automatic
429 // width doesn't make sense for such Writer fly frames.
430 SwFrame
* pLower
= pFly
->Lower();
431 if ( !pLower
|| pLower
->IsColumnFrame() )
434 const SwFormatFrameSize
&rFrameSz
= pFly
->GetFormat()->GetFrameSize();
436 // This could be optimized. Basically the fly frame only has to
437 // be invalidated, if the first line of pFrame (if pFrame is a content
438 // frame, for other frame types it's the print area) has changed its
439 // size and pFrame was responsible for the current width of pFly. On
440 // the other hand, this is only rarely used and re-calculation of
441 // the fly frame does not cause too much trouble. So we keep it this
443 if ( SwFrameSize::Fixed
!= rFrameSz
.GetWidthSizeType() )
445 // #i50668#, #i50998# - invalidation of position
446 // of as-character anchored fly frames not needed and can cause
448 if ( dynamic_cast<const SwFlyInContentFrame
*>( pFly
) == nullptr )
450 pFly
->InvalidatePos();
452 pFly
->InvalidateSize();
456 SwLayNotify::SwLayNotify( SwLayoutFrame
*pLayFrame
) :
457 SwFrameNotify( pLayFrame
),
458 m_bLowersComplete( false )
462 // OD 2004-05-11 #i28701# - local method to invalidate the position of all
463 // frames inclusive its floating screen objects, which are lowers of the given
465 static void lcl_InvalidatePosOfLowers( SwLayoutFrame
& _rLayoutFrame
)
467 if( _rLayoutFrame
.IsFlyFrame() && _rLayoutFrame
.GetDrawObjs() )
469 _rLayoutFrame
.InvalidateObjs( false );
472 SwFrame
* pLowerFrame
= _rLayoutFrame
.Lower();
473 while ( pLowerFrame
)
475 pLowerFrame
->InvalidatePos();
476 if ( pLowerFrame
->IsTextFrame() )
478 static_cast<SwTextFrame
*>(pLowerFrame
)->Prepare( PrepareHint::FramePositionChanged
);
480 else if ( pLowerFrame
->IsTabFrame() )
482 pLowerFrame
->InvalidatePrt();
485 pLowerFrame
->InvalidateObjs( false );
487 pLowerFrame
= pLowerFrame
->GetNext();
491 void SwLayNotify::ImplDestroy()
493 SwLayoutFrame
*pLay
= static_cast<SwLayoutFrame
*>(mpFrame
);
494 SwRectFnSet
aRectFnSet(pLay
);
495 bool bNotify
= false;
496 if ( pLay
->getFramePrintArea().SSize() != maPrt
.SSize() )
498 if ( !IsLowersComplete() )
502 if ( pLay
->IsRowFrame() )
505 tools::Long nNew
= aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
506 if( nNew
!= aRectFnSet
.GetHeight(maPrt
) )
507 static_cast<SwRowFrame
*>(pLay
)->AdjustCells( nNew
, true);
508 if( aRectFnSet
.GetWidth(pLay
->getFramePrintArea())
509 != aRectFnSet
.GetWidth(maPrt
) )
510 static_cast<SwRowFrame
*>(pLay
)->AdjustCells( 0, false );
514 //Proportional adoption of the internal.
515 //1. If the formatted is no Fly
516 //2. If he contains no columns
517 //3. If the Fly has a fixed height and the columns
519 // Hoehe danebenliegen.
520 //4. Never at SectionFrames.
522 if( pLay
->IsFlyFrame() )
526 bLow
= !pLay
->Lower()->IsColumnFrame() ||
527 aRectFnSet
.GetHeight(pLay
->Lower()->getFrameArea())
528 != aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
533 else if( pLay
->IsSctFrame() )
537 if( pLay
->Lower()->IsColumnFrame() && pLay
->Lower()->GetNext() )
538 bLow
= pLay
->Lower()->getFrameArea().Height() != pLay
->getFramePrintArea().Height();
540 bLow
= pLay
->getFramePrintArea().Width() != maPrt
.Width();
545 else if( pLay
->IsFooterFrame() && !pLay
->HasFixSize() )
546 bLow
= pLay
->getFramePrintArea().Width() != maPrt
.Width();
552 pLay
->ChgLowersProp( maPrt
.SSize() );
554 // If the PrtArea has been extended, it might be possible that the chain of parts
555 // can take another frame. As a result, the "possible right one" needs to be
556 // invalidated. This only pays off if this or its Uppers are moveable sections.
557 // A PrtArea has been extended if width or height are larger than before.
558 if ( (pLay
->getFramePrintArea().Height() > maPrt
.Height() ||
559 pLay
->getFramePrintArea().Width() > maPrt
.Width()) &&
560 (pLay
->IsMoveable() || pLay
->IsFlyFrame()) )
562 SwFrame
*pTmpFrame
= pLay
->Lower();
563 if ( pTmpFrame
&& pTmpFrame
->IsFlowFrame() )
565 while ( pTmpFrame
->GetNext() )
566 pTmpFrame
= pTmpFrame
->GetNext();
567 pTmpFrame
->InvalidateNextPos();
572 //EXPENSIVE!! But how we do it more elegant?
574 pLay
->InvaPercentLowers( pLay
->getFramePrintArea().Height() - maPrt
.Height() );
576 if ( pLay
->IsTabFrame() )
577 //So that _only_ the shadow is drawn while resizing.
578 static_cast<SwTabFrame
*>(pLay
)->SetComplete();
581 const SwViewShell
*pSh
= pLay
->getRootFrame()->GetCurrShell();
582 if( !( pSh
&& pSh
->GetViewOptions()->getBrowseMode() ) ||
583 !(pLay
->GetType() & (SwFrameType::Body
| SwFrameType::Page
)) )
584 //Thereby the subordinates are retouched clean.
585 //Example problem: Take the Flys with the handles and downsize.
586 //Not for body and page, otherwise it flickers when loading HTML.
587 pLay
->SetCompletePaint();
590 //Notify Lower if the position has changed.
591 const bool bPrtPos
= aRectFnSet
.PosDiff( maPrt
, pLay
->getFramePrintArea() );
592 const bool bPos
= bPrtPos
|| aRectFnSet
.PosDiff( maFrame
, pLay
->getFrameArea() );
593 const bool bSize
= pLay
->getFrameArea().SSize() != maFrame
.SSize();
595 if ( bPos
&& pLay
->Lower() && !IsLowersComplete() )
597 pLay
->Lower()->InvalidatePos();
598 SwFootnoteFrame
* pFtnFrame
= pLay
->Lower()->IsFootnoteFrame() ?
599 static_cast<SwFootnoteFrame
*>(pLay
->Lower()) : nullptr;
600 SwFrame
* pFtnLower
= pFtnFrame
? pFtnFrame
->Lower() : nullptr;
602 pFtnLower
->InvalidatePos();
606 pLay
->SetCompletePaint();
608 //Inform the Follower if the SSize has changed.
611 if( pLay
->GetNext() )
613 if ( pLay
->GetNext()->IsLayoutFrame() )
614 pLay
->GetNext()->InvalidatePos_();
616 pLay
->GetNext()->InvalidatePos();
618 else if( pLay
->IsSctFrame() )
619 pLay
->InvalidateNextPos();
622 SwFrame
* pLower
= pLay
->Lower();
623 if ( !IsLowersComplete() &&
624 !(pLay
->GetType()&(SwFrameType::Fly
|SwFrameType::Section
) &&
625 pLower
&& pLower
->IsColumnFrame()) &&
627 !(pLay
->GetType() & (SwFrameType::Row
|SwFrameType::Tab
|SwFrameType::FtnCont
|SwFrameType::Page
|SwFrameType::Root
)))
629 // #i44016# - force unlock of position of lower objects.
630 // #i43913# - no unlock of position of objects,
631 // if <pLay> is a cell frame, and its table frame resp. its parent table
633 // #i47458# - force unlock of position of lower objects,
634 // only if position of layout frame has changed.
635 bool bUnlockPosOfObjs( bPos
);
636 if ( bUnlockPosOfObjs
&& pLay
->IsCellFrame() )
638 SwTabFrame
* pTabFrame( pLay
->FindTabFrame() );
640 ( pTabFrame
->IsJoinLocked() ||
641 ( pTabFrame
->IsFollow() &&
642 pTabFrame
->FindMaster()->IsJoinLocked() ) ) )
644 bUnlockPosOfObjs
= false;
647 // #i49383# - check for footnote frame, if unlock
648 // of position of lower objects is allowed.
649 else if ( bUnlockPosOfObjs
&& pLay
->IsFootnoteFrame() )
651 bUnlockPosOfObjs
= static_cast<SwFootnoteFrame
*>(pLay
)->IsUnlockPosOfLowerObjs();
653 // #i51303# - no unlock of object positions for sections
654 else if ( bUnlockPosOfObjs
&& pLay
->IsSctFrame() )
656 bUnlockPosOfObjs
= false;
658 pLay
->NotifyLowerObjs( bUnlockPosOfObjs
);
660 if ( bPos
&& pLay
->IsFootnoteFrame() && pLay
->Lower() )
662 // OD 2004-05-11 #i28701#
663 ::lcl_InvalidatePosOfLowers( *pLay
);
665 if( ( bPos
|| bSize
) && pLay
->IsFlyFrame() && static_cast<SwFlyFrame
*>(pLay
)->GetAnchorFrame()
666 && static_cast<SwFlyFrame
*>(pLay
)->GetAnchorFrame()->IsFlyFrame() )
667 static_cast<SwFlyFrame
*>(pLay
)->AnchorFrame()->InvalidateSize();
670 SwLayNotify::~SwLayNotify()
672 suppress_fun_call_w_exception(ImplDestroy());
675 SwFlyNotify::SwFlyNotify( SwFlyFrame
*pFlyFrame
) :
676 SwLayNotify( pFlyFrame
),
677 // #115759# - keep correct page frame - the page frame
678 // the Writer fly frame is currently registered at.
679 m_pOldPage( pFlyFrame
->GetPageFrame() ),
680 m_aFrameAndSpace( pFlyFrame
->GetObjRectWithSpaces() )
684 void SwFlyNotify::ImplDestroy()
686 SwFlyFrame
*pFly
= static_cast<SwFlyFrame
*>(mpFrame
);
687 if ( pFly
->IsNotifyBack() )
689 SwViewShell
*pSh
= pFly
->getRootFrame()->GetCurrShell();
690 SwViewShellImp
*pImp
= pSh
? pSh
->Imp() : nullptr;
691 if ( !pImp
|| !pImp
->IsAction() || !pImp
->GetLayAction().IsAgain() )
693 //If in the LayAction the IsAgain is set it can be
694 //that the old page is destroyed in the meantime!
695 ::Notify( pFly
, m_pOldPage
, m_aFrameAndSpace
, &maPrt
);
696 // #i35640# - additional notify anchor text frame,
697 // if Writer fly frame has changed its page
698 if ( pFly
->GetAnchorFrame()->IsTextFrame() &&
699 pFly
->GetPageFrame() != m_pOldPage
)
701 pFly
->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave
);
704 pFly
->ResetNotifyBack();
706 if (pFly
->IsForceNotifyNewBackground())
708 pFly
->NotifyBackground(pFly
->FindPageFrame(), pFly
->GetObjRectWithSpaces(), PrepareHint::FlyFrameArrive
);
709 pFly
->SetForceNotifyNewBackground(false);
712 //Have the size or the position changed,
713 //so should the view know this.
714 SwRectFnSet
aRectFnSet(pFly
);
715 const bool bPosChgd
= aRectFnSet
.PosDiff( maFrame
, pFly
->getFrameArea() );
716 const bool bFrameChgd
= pFly
->getFrameArea().SSize() != maFrame
.SSize();
717 const bool bPrtChgd
= maPrt
!= pFly
->getFramePrintArea();
718 if ( bPosChgd
|| bFrameChgd
|| bPrtChgd
)
720 pFly
->NotifyDrawObj();
722 if ( bPosChgd
&& maFrame
.Pos().X() != FAR_AWAY
)
724 // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
725 // reason: New positioning and alignment (e.g. to-paragraph anchored,
726 // but aligned at page) are introduced.
727 // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
728 // floating screen objects by calling method <SwLayoutFrame::NotifyLowerObjs()>.
730 if ( pFly
->IsFlyAtContentFrame() )
732 SwFrame
*pNxt
= pFly
->AnchorFrame()->FindNext();
735 pNxt
->InvalidatePos();
736 if (!pNxt
->IsSctFrame())
740 // invalidating pos of a section frame doesn't have much
741 // effect, so try again with its lower
742 pNxt
= static_cast<SwSectionFrame
*>(pNxt
)->Lower();
746 // #i26945# - notify anchor.
747 // Needed for negative positioned Writer fly frames
748 if ( pFly
->GetAnchorFrame()->IsTextFrame() )
750 pFly
->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave
);
754 // OD 2004-05-13 #i28701#
755 // #i45180# - no adjustment of layout process flags and
756 // further notifications/invalidations, if format is called by grow/shrink
757 if ( !pFly
->ConsiderObjWrapInfluenceOnObjPos() )
759 if (pFly
->IsFlyFreeFrame())
761 if (static_cast<SwFlyFreeFrame
*>(pFly
)->IsNoMoveOnCheckClip())
765 // #i54138# - suppress restart of the layout process
766 // on changed frame height.
767 // Note: It doesn't seem to be necessary and can cause layout loops.
770 // indicate a restart of the layout process
771 pFly
->SetRestartLayoutProcess( true );
776 pFly
->LockPosition();
779 if ( pFly
->ConsiderForTextWrap() )
782 // indicate that object has to be considered for text wrap
783 pFly
->SetConsiderForTextWrap( true );
784 // invalidate 'background' in order to allow its 'background'
785 // to wrap around it.
786 pFly
->NotifyBackground( pFly
->GetPageFrame(),
787 pFly
->GetObjRectWithSpaces(),
788 PrepareHint::FlyFrameArrive
);
789 // invalidate position of anchor frame in order to force
790 // a re-format of the anchor frame, which also causes a
791 // re-format of the invalid previous frames of the anchor frame.
792 pFly
->AnchorFrame()->InvalidatePos();
795 SwFlyNotify::~SwFlyNotify()
797 suppress_fun_call_w_exception(ImplDestroy());
800 SwContentNotify::SwContentNotify( SwContentFrame
*pContentFrame
) :
801 SwFrameNotify( pContentFrame
),
802 // OD 08.01.2004 #i11859#
803 mbChkHeightOfLastLine( false ),
804 mnHeightOfLastLine( 0 ),
805 // OD 2004-02-26 #i25029#
806 mbInvalidatePrevPrtArea( false ),
807 mbBordersJoinedWithPrev( false )
809 // OD 08.01.2004 #i11859#
810 if ( !pContentFrame
->IsTextFrame() )
813 SwTextFrame
* pTextFrame
= static_cast<SwTextFrame
*>(pContentFrame
);
814 if (!pTextFrame
->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::OLD_LINE_SPACING
))
816 const SvxLineSpacingItem
&rSpace
= pTextFrame
->GetAttrSet()->GetLineSpacing();
817 if ( rSpace
.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
)
819 mbChkHeightOfLastLine
= true;
820 mnHeightOfLastLine
= pTextFrame
->GetHeightOfLastLine();
825 void SwContentNotify::ImplDestroy()
827 SwContentFrame
*pCnt
= static_cast<SwContentFrame
*>(mpFrame
);
828 if ( bSetCompletePaintOnInvalidate
)
829 pCnt
->SetCompletePaint();
831 SwRectFnSet
aRectFnSet(pCnt
);
832 if ( pCnt
->IsInTab() && ( aRectFnSet
.PosDiff( pCnt
->getFrameArea(), maFrame
) ||
833 pCnt
->getFrameArea().SSize() != maFrame
.SSize()))
835 SwLayoutFrame
* pCell
= pCnt
->GetUpper();
836 while( !pCell
->IsCellFrame() && pCell
->GetUpper() )
837 pCell
= pCell
->GetUpper();
838 OSL_ENSURE( pCell
->IsCellFrame(), "Where's my cell?" );
839 if ( text::VertOrientation::NONE
!= pCell
->GetFormat()->GetVertOrient().GetVertOrient() )
840 pCell
->InvalidatePrt(); //for the vertical align.
843 // OD 2004-02-26 #i25029#
844 if ( mbInvalidatePrevPrtArea
&& mbBordersJoinedWithPrev
&&
845 pCnt
->IsTextFrame() &&
846 !pCnt
->IsFollow() && !pCnt
->GetIndPrev() )
848 // determine previous frame
849 SwFrame
* pPrevFrame
= pCnt
->FindPrev();
850 // skip empty section frames and hidden text frames
852 while (pPrevFrame
&& pPrevFrame
->IsHiddenNow())
854 pPrevFrame
= pPrevFrame
->FindPrev();
858 // Invalidate printing area of found previous frame
861 if ( pPrevFrame
->IsSctFrame() )
863 if ( pCnt
->IsInSct() )
865 // Note: found previous frame is a section frame and
866 // <pCnt> is also inside a section.
867 // Thus due to <mbBordersJoinedWithPrev>,
868 // <pCnt> had joined its borders/shadow with the
869 // last content of the found section.
870 // Invalidate printing area of last content in found section.
871 SwFrame
* pLstContentOfSctFrame
=
872 static_cast<SwSectionFrame
*>(pPrevFrame
)->FindLastContent();
873 if ( pLstContentOfSctFrame
)
875 pLstContentOfSctFrame
->InvalidatePrt();
881 pPrevFrame
->InvalidatePrt();
886 const bool bFirst
= aRectFnSet
.GetWidth(maFrame
) == 0;
888 if ( pCnt
->IsNoTextFrame() )
890 //Active PlugIn's or OLE-Objects should know something of the change
891 //thereby they move their window appropriate.
892 SwViewShell
*pSh
= pCnt
->getRootFrame()->GetCurrShell();
895 SwOLENode
*const pNd(static_cast<SwNoTextFrame
*>(pCnt
)->GetNode()->GetOLENode());
896 if (nullptr != pNd
&&
897 (pNd
->GetOLEObj().IsOleRef() ||
898 pNd
->IsOLESizeInvalid()) )
900 const bool bNoTextFramePrtAreaChanged
=
901 ( maPrt
.SSize().Width() != 0 &&
902 maPrt
.SSize().Height() != 0 ) &&
903 maPrt
.SSize() != pCnt
->getFramePrintArea().SSize();
904 OSL_ENSURE( pCnt
->IsInFly(), "OLE not in FlyFrame" );
905 SwFlyFrame
*pFly
= pCnt
->FindFlyFrame();
906 svt::EmbeddedObjectRef
& xObj
= pNd
->GetOLEObj().GetObject();
907 SwFEShell
*pFESh
= nullptr;
908 for(SwViewShell
& rCurrentShell
: pSh
->GetRingContainer())
909 { if ( dynamic_cast<const SwCursorShell
*>( &rCurrentShell
) != nullptr )
911 pFESh
= static_cast<SwFEShell
*>(&rCurrentShell
);
912 // #108369#: Here used to be the condition if (!bFirst).
913 // I think this should mean "do not call CalcAndSetScale"
914 // if the frame is formatted for the first time.
915 // Unfortunately this is not valid anymore since the
916 // SwNoTextFrame already gets a width during CalcLowerPreps.
917 // Nevertheless, the indention of !bFirst seemed to be
918 // to assure that the OLE objects have already been notified
919 // if necessary before calling CalcAndSetScale.
920 // So I replaced !bFirst by !IsOLESizeInvalid. There is
921 // one additional problem specific to the word import:
922 // The layout is calculated _before_ calling PrtOLENotify,
923 // and the OLE objects are not invalidated during import.
924 // Therefore I added the condition !IsUpdateExpField,
925 // have a look at the occurrence of CalcLayout in
927 if ( !pNd
->IsOLESizeInvalid() &&
928 !pSh
->GetDoc()->getIDocumentState().IsUpdateExpField() )
929 pFESh
->CalcAndSetScale( xObj
,
930 &pFly
->getFramePrintArea(), &pFly
->getFrameArea(),
931 bNoTextFramePrtAreaChanged
);
935 if ( pFESh
&& pNd
->IsOLESizeInvalid() )
937 pNd
->SetOLESizeInvalid( false );
938 pFESh
->CalcAndSetScale( xObj
); // create client
941 // ditto animated graphics
942 if ( getFrameArea().HasArea() && static_cast<SwNoTextFrame
*>(pCnt
)->HasAnimation() )
944 static_cast<SwNoTextFrame
*>(pCnt
)->StopAnimation();
945 pSh
->InvalidateWindows( getFrameArea() );
952 pCnt
->SetRetouche(); //fix(13870)
954 SwDoc
& rDoc
= pCnt
->IsTextFrame()
955 ? static_cast<SwTextFrame
*>(pCnt
)->GetDoc()
956 : static_cast<SwNoTextFrame
*>(pCnt
)->GetNode()->GetDoc();
957 if ( !rDoc
.GetSpzFrameFormats()->empty() &&
958 rDoc
.DoesContainAtPageObjWithContentAnchor() && !rDoc
.getIDocumentState().IsNewDoc() )
960 // If certain import filters for foreign file format import
961 // AT_PAGE anchored objects, the corresponding page number is
962 // typically not known. In this case the content position is
963 // stored at which the anchored object is found in the
964 // imported document.
965 // When this content is formatted it is the time at which
966 // the page is known. Thus, this data can be corrected now.
968 const SwPageFrame
*pPage
= nullptr;
969 for(sw::SpzFrameFormat
* pFormat
: *rDoc
.GetSpzFrameFormats())
971 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
972 if ( RndStdIds::FLY_AT_PAGE
!= rAnch
.GetAnchorId() ||
973 rAnch
.GetAnchorNode() == nullptr )
978 if (FrameContainsNode(*pCnt
, rAnch
.GetAnchorNode()->GetIndex()))
980 OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - to page anchored object with content position." );
983 pPage
= pCnt
->FindPageFrame();
985 SwFormatAnchor
aAnch( rAnch
);
986 aAnch
.SetAnchor( nullptr );
987 aAnch
.SetPageNum( pPage
->GetPhyPageNum() );
988 pFormat
->SetFormatAttr( aAnch
);
989 if ( RES_DRAWFRMFMT
!= pFormat
->Which() )
991 pFormat
->MakeFrames();
998 // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
999 // if height of last line has changed.
1000 if ( pCnt
->IsTextFrame() && mbChkHeightOfLastLine
)
1002 if ( mnHeightOfLastLine
!= static_cast<SwTextFrame
*>(pCnt
)->GetHeightOfLastLine() )
1004 pCnt
->InvalidateNextPrtArea();
1009 if ( pCnt
->IsTextFrame() && aRectFnSet
.PosDiff( maFrame
, pCnt
->getFrameArea() ) )
1011 pCnt
->InvalidateObjs();
1014 // #i43255# - move code to invalidate at-character
1015 // anchored objects due to a change of its anchor character from
1016 // method <SwTextFrame::Format(..)>.
1017 if ( !pCnt
->IsTextFrame() )
1020 SwTextFrame
* pMasterFrame
= pCnt
->IsFollow()
1021 ? static_cast<SwTextFrame
*>(pCnt
)->FindMaster()
1022 : static_cast<SwTextFrame
*>(pCnt
);
1023 if ( pMasterFrame
&& !pMasterFrame
->IsFlyLock() &&
1024 pMasterFrame
->GetDrawObjs() )
1026 SwSortedObjs
* pObjs
= pMasterFrame
->GetDrawObjs();
1027 for (SwAnchoredObject
* pAnchoredObj
: *pObjs
)
1029 if ( pAnchoredObj
->GetFrameFormat()->GetAnchor().GetAnchorId()
1030 == RndStdIds::FLY_AT_CHAR
)
1032 pAnchoredObj
->CheckCharRectAndTopOfLine( !pMasterFrame
->IsEmpty() );
1038 SwContentNotify::~SwContentNotify()
1040 suppress_fun_call_w_exception(ImplDestroy());
1043 // note this *cannot* be static because it's a friend
1044 void AppendObj(SwFrame
*const pFrame
, SwPageFrame
*const pPage
, SwFrameFormat
*const pFormat
, const SwFormatAnchor
& rAnch
)
1046 const bool bFlyAtFly
= rAnch
.GetAnchorId() == RndStdIds::FLY_AT_FLY
; // LAYER_IMPL
1047 //Is a frame or a SdrObject described?
1048 const bool bSdrObj
= RES_DRAWFRMFMT
== pFormat
->Which();
1049 // OD 23.06.2003 #108784# - append also drawing objects anchored
1051 const bool bDrawObjInContent
= bSdrObj
&&
1052 (rAnch
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
);
1055 (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_PARA
) ||
1056 (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
) ||
1057 bDrawObjInContent
) )
1060 SdrObject
* pSdrObj
= nullptr;
1061 if ( bSdrObj
&& nullptr == (pSdrObj
= pFormat
->FindSdrObject()) )
1063 OSL_ENSURE( !bSdrObj
, "DrawObject not found." );
1064 pFormat
->GetDoc()->DelFrameFormat( pFormat
);
1069 if ( !pSdrObj
->getSdrPageFromSdrObject() )
1071 pFormat
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
1072 InsertObject(pSdrObj
, pSdrObj
->GetOrdNumDirect());
1075 if (SwDrawContact
* pNew
= static_cast<SwDrawContact
*>(GetUserCall( pSdrObj
)))
1077 if ( !pNew
->GetAnchorFrame() )
1079 pFrame
->AppendDrawObj( *(pNew
->GetAnchoredObj( nullptr )) );
1081 // OD 19.06.2003 #108784# - add 'virtual' drawing object,
1082 // if necessary. But control objects have to be excluded.
1083 else if ( !::CheckControlLayer( pSdrObj
) &&
1084 pNew
->GetAnchorFrame() != pFrame
&&
1085 !pNew
->GetDrawObjectByAnchorFrame( *pFrame
) )
1087 SwDrawVirtObj
* pDrawVirtObj
= pNew
->AddVirtObj(*pFrame
);
1088 pFrame
->AppendDrawObj( *(pNew
->GetAnchoredObj( pDrawVirtObj
)) );
1090 pDrawVirtObj
->ActionChanged();
1098 pFly
= new SwFlyLayFrame( static_cast<SwFlyFrameFormat
*>(pFormat
), pFrame
, pFrame
);
1100 pFly
= new SwFlyAtContentFrame( static_cast<SwFlyFrameFormat
*>(pFormat
), pFrame
, pFrame
);
1102 pFrame
->AppendFly( pFly
);
1105 ::RegistFlys( pPage
, pFly
);
1109 static bool IsShown(SwNodeOffset
const nIndex
,
1110 const SwFormatAnchor
& rAnch
,
1111 std::vector
<sw::Extent
>::const_iterator
const*const pIter
,
1112 std::vector
<sw::Extent
>::const_iterator
const*const pEnd
,
1113 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
1115 assert(!pIter
|| *pIter
== *pEnd
|| (*pIter
)->pNode
->GetIndex() == nIndex
);
1116 SwNode
* pAnchorNode
= rAnch
.GetAnchorNode();
1117 if (pAnchorNode
->GetIndex() != nIndex
)
1121 if (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_PARA
)
1123 return pIter
== nullptr // not merged
1124 || pIter
!= pEnd
// at least one char visible in node
1125 || !IsSelectFrameAnchoredAtPara(*rAnch
.GetContentAnchor(),
1126 SwPosition(*pFirstNode
, 0),
1127 SwPosition(*pLastNode
, pLastNode
->Len()));
1131 // note: frames are not sorted by anchor position.
1135 assert(rAnch
.GetAnchorId() != RndStdIds::FLY_AT_FLY
);
1136 if (*pIter
== *pEnd
&& rAnch
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
)
1137 { // tdf#149595 special case - it *could* be shown if first == last
1138 return !IsDestroyFrameAnchoredAtChar(*rAnch
.GetContentAnchor(),
1139 SwPosition(*pFirstNode
, 0),
1140 SwPosition(*pLastNode
, pLastNode
->Len()));
1142 for (auto iter
= *pIter
; iter
!= *pEnd
; ++iter
)
1144 assert(iter
->nStart
!= iter
->nEnd
); // TODO possible?
1145 assert(iter
->pNode
->GetIndex() == nIndex
);
1146 if (rAnch
.GetAnchorContentOffset() < iter
->nStart
)
1150 if (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
)
1152 // if there is an extent then obviously the node was not
1154 // show if start <= pos <= end
1155 // *or* if first-node/0 *and* not StartOfSection
1156 // *or* if last-node/Len *and* not EndOfSection
1158 // first determine the extent to compare to, then
1159 // construct start/end positions for the deletion *before* the
1160 // extent and compare once.
1161 // the interesting corner cases are on the edge of the extent!
1162 // no need to check for > the last extent because those
1163 // are never visible.
1164 if (rAnch
.GetAnchorContentOffset() <= iter
->nEnd
)
1166 if (iter
->nStart
== 0)
1172 SwPosition
const start(
1174 ? *pFirstNode
// simplification
1176 iter
== *pIter
// first extent?
1177 ? iter
->pNode
== pFirstNode
1178 ? 0 // at start of 1st node
1179 : pFirstNode
->Len() // previous node; simplification but should get right result
1180 : (iter
-1)->nEnd
); // previous extent
1181 SwPosition
const end(*iter
->pNode
, iter
->nStart
);
1182 return !IsDestroyFrameAnchoredAtChar(*rAnch
.GetContentAnchor(), start
, end
);
1185 else if (iter
== *pEnd
- 1) // special case: after last extent
1187 if (iter
->nEnd
== iter
->pNode
->Len())
1189 return true; // special case: end of node
1193 SwPosition
const start(*iter
->pNode
, iter
->nEnd
);
1194 SwPosition
const end(
1195 *pLastNode
, // simplification
1196 iter
->pNode
== pLastNode
1197 ? iter
->pNode
->Len()
1199 return !IsDestroyFrameAnchoredAtChar(*rAnch
.GetContentAnchor(), start
, end
);
1205 assert(rAnch
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
);
1206 // for AS_CHAR obviously must be <
1207 if (rAnch
.GetAnchorContentOffset() < iter
->nEnd
)
1221 void RemoveHiddenObjsOfNode(SwTextNode
const& rNode
,
1222 std::vector
<sw::Extent
>::const_iterator
const*const pIter
,
1223 std::vector
<sw::Extent
>::const_iterator
const*const pEnd
,
1224 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
1226 std::vector
<SwFrameFormat
*> const & rFlys(rNode
.GetAnchoredFlys());
1227 for (SwFrameFormat
* pFrameFormat
: rFlys
)
1229 SwFormatAnchor
const& rAnchor
= pFrameFormat
->GetAnchor();
1230 if (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
1231 || rAnchor
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
1233 assert(rAnchor
.GetAnchorNode()->GetIndex() == rNode
.GetIndex());
1234 if (!IsShown(rNode
.GetIndex(), rAnchor
, pIter
, pEnd
, pFirstNode
, pLastNode
))
1236 pFrameFormat
->DelFrames();
1242 void AppendObjsOfNode(sw::FrameFormats
<sw::SpzFrameFormat
*> const*const pTable
, SwNodeOffset
const nIndex
,
1243 SwFrame
*const pFrame
, SwPageFrame
*const pPage
, SwDoc
*const pDoc
,
1244 std::vector
<sw::Extent
>::const_iterator
const*const pIter
,
1245 std::vector
<sw::Extent
>::const_iterator
const*const pEnd
,
1246 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
1248 #if OSL_DEBUG_LEVEL > 0
1249 std::vector
<SwFrameFormat
*> checkFormats
;
1250 for(auto pFormat
: *pTable
)
1252 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
1253 if ( rAnch
.GetAnchorNode() &&
1254 IsShown(nIndex
, rAnch
, pIter
, pEnd
, pFirstNode
, pLastNode
))
1256 checkFormats
.push_back( pFormat
);
1263 SwNode
const& rNode(*pDoc
->GetNodes()[nIndex
]);
1264 std::vector
<SwFrameFormat
*> const & rFlys(rNode
.GetAnchoredFlys());
1265 for (size_t it
= 0; it
!= rFlys
.size(); )
1267 SwFrameFormat
*const pFormat
= rFlys
[it
];
1268 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
1269 if ( rAnch
.GetAnchorNode() &&
1270 IsShown(nIndex
, rAnch
, pIter
, pEnd
, pFirstNode
, pLastNode
))
1272 #if OSL_DEBUG_LEVEL > 0
1273 std::vector
<SwFrameFormat
*>::iterator checkPos
= std::find( checkFormats
.begin(), checkFormats
.end(), pFormat
);
1274 assert( checkPos
!= checkFormats
.end());
1275 checkFormats
.erase( checkPos
);
1277 AppendObj(pFrame
, pPage
, pFormat
, rAnch
);
1282 #if OSL_DEBUG_LEVEL > 0
1283 assert( checkFormats
.empty());
1288 void AppendObjs(const sw::FrameFormats
<sw::SpzFrameFormat
*> *const pTable
, SwNodeOffset
const nIndex
,
1289 SwFrame
*const pFrame
, SwPageFrame
*const pPage
, SwDoc
*const pDoc
)
1291 if (pFrame
->IsTextFrame())
1293 SwTextFrame
const*const pTextFrame(static_cast<SwTextFrame
const*>(pFrame
));
1294 if (sw::MergedPara
const*const pMerged
= pTextFrame
->GetMergedPara())
1296 std::vector
<sw::Extent
>::const_iterator
iterFirst(pMerged
->extents
.begin());
1297 std::vector
<sw::Extent
>::const_iterator
iter(iterFirst
);
1298 SwTextNode
const* pNode(pMerged
->pFirstNode
);
1301 if (iter
== pMerged
->extents
.end()
1302 || iter
->pNode
!= pNode
)
1304 AppendObjsOfNode(pTable
, pNode
->GetIndex(), pFrame
, pPage
, pDoc
,
1305 &iterFirst
, &iter
, pMerged
->pFirstNode
, pMerged
->pLastNode
);
1306 SwNodeOffset
const until
= iter
== pMerged
->extents
.end()
1307 ? pMerged
->pLastNode
->GetIndex() + 1
1308 : iter
->pNode
->GetIndex();
1309 for (SwNodeOffset i
= pNode
->GetIndex() + 1; i
< until
; ++i
)
1311 // let's show at-para flys on nodes that contain start/end of
1312 // redline too, even if there's no text there
1313 SwNode
const*const pTmp(pNode
->GetNodes()[i
]);
1314 if (pTmp
->GetRedlineMergeFlag() == SwNode::Merge::NonFirst
)
1316 AppendObjsOfNode(pTable
, pTmp
->GetIndex(), pFrame
, pPage
, pDoc
, &iter
, &iter
, pMerged
->pFirstNode
, pMerged
->pLastNode
);
1319 if (iter
== pMerged
->extents
.end())
1323 pNode
= iter
->pNode
;
1330 return AppendObjsOfNode(pTable
, nIndex
, pFrame
, pPage
, pDoc
, nullptr, nullptr, nullptr, nullptr);
1335 return AppendObjsOfNode(pTable
, nIndex
, pFrame
, pPage
, pDoc
, nullptr, nullptr, nullptr, nullptr);
1339 bool IsAnchoredObjShown(SwTextFrame
const& rFrame
, SwFormatAnchor
const& rAnchor
)
1341 assert(rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
||
1342 rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
||
1343 rAnchor
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
);
1345 if (auto const pMergedPara
= rFrame
.GetMergedPara())
1348 SwNode
* pAnchorNode(rAnchor
.GetAnchorNode());
1349 auto iterFirst(pMergedPara
->extents
.cbegin());
1350 if (iterFirst
== pMergedPara
->extents
.end()
1351 && (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
1352 || rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
))
1354 ret
= (pAnchorNode
== pMergedPara
->pFirstNode
1355 && (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
1356 || rAnchor
.GetAnchorContentOffset() == 0))
1357 || (pAnchorNode
== pMergedPara
->pLastNode
1358 && (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
1359 || rAnchor
.GetAnchorContentOffset() == pMergedPara
->pLastNode
->Len()));
1361 auto iter(iterFirst
);
1362 SwTextNode
const* pNode(pMergedPara
->pFirstNode
);
1365 if (iter
== pMergedPara
->extents
.end()
1366 || iter
->pNode
!= pNode
)
1368 assert(pNode
->GetRedlineMergeFlag() != SwNode::Merge::Hidden
);
1369 if (pNode
== pAnchorNode
)
1371 ret
= IsShown(pNode
->GetIndex(), rAnchor
, &iterFirst
, &iter
,
1372 pMergedPara
->pFirstNode
, pMergedPara
->pLastNode
);
1375 if (iter
== pMergedPara
->extents
.end())
1379 pNode
= iter
->pNode
;
1380 if (pAnchorNode
->GetIndex() < pNode
->GetIndex())
1391 void AppendAllObjs(const sw::FrameFormats
<sw::SpzFrameFormat
*>* pTable
, const SwFrame
* pSib
)
1393 //Connecting of all Objects, which are described in the SpzTable with the
1396 boost::circular_buffer
<SwFrameFormat
*> vFormatsToConnect(pTable
->size());
1397 for(const auto& pFormat
: *pTable
)
1399 const auto& rAnch
= pFormat
->GetAnchor();
1400 // Formats can still remain, because we neither use character bound
1401 // frames nor objects which are anchored to character bounds.
1402 if ((rAnch
.GetAnchorId() != RndStdIds::FLY_AT_PAGE
) && (rAnch
.GetAnchorId() != RndStdIds::FLY_AS_CHAR
))
1404 const SwNode
* pAnchorNode
= rAnch
.GetAnchorNode();
1405 // formats in header/footer have no dependencies
1406 if(pAnchorNode
&& pFormat
->GetDoc()->IsInHeaderFooter(*pAnchorNode
))
1407 pFormat
->MakeFrames();
1409 vFormatsToConnect
.push_back(pFormat
);
1412 const SwRootFrame
* pRoot
= pSib
? pSib
->getRootFrame() : nullptr;
1413 const SwFrameFormat
* pFirstRequeued(nullptr);
1414 while(!vFormatsToConnect
.empty())
1416 SwFrameFormat
* pFormat
= vFormatsToConnect
.front();
1417 bool isConnected(false);
1418 pFormat
->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected
, pRoot
));
1421 pFormat
->MakeFrames();
1422 pFormat
->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected
, pRoot
));
1424 // do this *before* push_back! the circular_buffer can be "full"!
1425 vFormatsToConnect
.pop_front();
1428 if(pFirstRequeued
== pFormat
)
1429 // If nothing happens anymore we can stop.
1432 pFirstRequeued
= pFormat
;
1433 assert(!vFormatsToConnect
.full());
1434 vFormatsToConnect
.push_back(pFormat
);
1438 pFirstRequeued
= nullptr;
1445 void RecreateStartTextFrames(SwTextNode
& rNode
)
1447 std::vector
<SwTextFrame
*> frames
;
1448 SwIterator
<SwTextFrame
, SwTextNode
, sw::IteratorMode::UnwrapMulti
> aIter(rNode
);
1449 for (SwTextFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next())
1451 if (pFrame
->getRootFrame()->HasMergedParas())
1453 frames
.push_back(pFrame
);
1456 auto eMode(sw::FrameMode::Existing
);
1457 for (SwTextFrame
* pFrame
: frames
)
1459 // SplitNode could have moved the original frame to the start node
1460 // & created a new one on end, or could have created new frame on
1461 // start node... grab start node's frame and recreate MergedPara.
1462 SwTextNode
& rFirstNode(pFrame
->GetMergedPara()
1463 ? *pFrame
->GetMergedPara()->pFirstNode
1465 assert(rFirstNode
.GetIndex() <= rNode
.GetIndex());
1466 // clear old one first to avoid DelFrames confusing updates & asserts...
1467 pFrame
->SetMergedPara(nullptr);
1468 pFrame
->SetMergedPara(sw::CheckParaRedlineMerge(
1469 *pFrame
, rFirstNode
, eMode
));
1470 eMode
= sw::FrameMode::New
; // Existing is not idempotent!
1471 // note: this may or may not delete frames on the end node
1477 /** local method to set 'working' position for newly inserted frames
1479 OD 12.08.2003 #i17969#
1481 static void lcl_SetPos( SwFrame
& _rNewFrame
,
1482 const SwLayoutFrame
& _rLayFrame
)
1484 SwRectFnSet
aRectFnSet(&_rLayFrame
);
1485 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(_rNewFrame
);
1486 aRectFnSet
.SetPos( aFrm
, aRectFnSet
.GetPos(_rLayFrame
.getFrameArea()) );
1488 // move position by one SwTwip in text flow direction in order to get
1489 // notifications for a new calculated position after its formatting.
1490 if ( aRectFnSet
.IsVert() )
1492 aFrm
.Pos().AdjustX( -1 );
1496 aFrm
.Pos().AdjustY(1 );
1500 void InsertCnt_( SwLayoutFrame
*pLay
, SwDoc
*pDoc
,
1501 SwNodeOffset nIndex
, bool bPages
, SwNodeOffset nEndIndex
,
1502 SwFrame
*pPrv
, sw::FrameMode
const eMode
)
1504 pDoc
->getIDocumentTimerAccess().BlockIdling();
1505 SwRootFrame
* pLayout
= pLay
->getRootFrame();
1506 const bool bOldCallbackActionEnabled
= pLayout
&& pLayout
->IsCallbackActionEnabled();
1507 if( bOldCallbackActionEnabled
)
1508 pLayout
->SetCallbackActionEnabled( false );
1510 //In the generation of the Layout bPages=true will be handed over.
1511 //Then will be new pages generated all x paragraphs already times in advance.
1512 //On breaks and/or pagedescriptorchanges the corresponding will be generated
1514 //The advantage is, that on one hand already a nearly realistic number of
1515 //pages are created, but above all there are no almost endless long chain
1516 //of paragraphs, which must be moved expensively until it reaches a tolerable
1518 //We'd like to think that 20 Paragraphs fit on one page.
1519 //So that it does not become in extreme situations so violent we calculate depending
1520 //on the node something to it.
1521 //If in the DocStatistic a usable given pagenumber
1522 //(Will be cared for while writing), so it will be presumed that this will be
1524 const bool bStartPercent
= bPages
&& !nEndIndex
;
1526 SwPageFrame
*pPage
= pLay
->FindPageFrame();
1527 sw::SpzFrameFormats
* pTable
= pDoc
->GetSpzFrameFormats();
1528 SwFrame
*pFrame
= nullptr;
1529 std::unique_ptr
<SwActualSection
> pActualSection
;
1530 std::unique_ptr
<SwLayHelper
> pPageMaker
;
1532 //If the layout will be created (bPages == true) we do head on the progress
1533 //Flys and DrawObjects are not connected immediately, this
1534 //happens only at the end of the function.
1537 // Attention: the SwLayHelper class uses references to the content-,
1538 // page-, layout-frame etc. and may change them!
1539 pPageMaker
.reset(new SwLayHelper( pDoc
, pFrame
, pPrv
, pPage
, pLay
,
1540 pActualSection
, nIndex
, SwNodeOffset(0) == nEndIndex
));
1543 const sal_uLong nPageCount
= pPageMaker
->CalcPageCount();
1545 bObjsDirect
= false;
1549 if( pLay
->IsInSct() &&
1550 ( pLay
->IsSctFrame() || pLay
->GetUpper() ) ) // Hereby will newbies
1551 // be intercepted, of which flags could not determined yet,
1552 // for e.g. while inserting a table
1554 SwSectionFrame
* pSct
= pLay
->FindSctFrame();
1555 // If content will be inserted in a footnote, which in a column area,
1556 // the column area it is not allowed to be broken up.
1557 // Only if in the inner of the footnote lies an area, is this a candidate
1558 // for pActualSection.
1559 // The same applies for areas in tables, if inside the table will be
1560 // something inserted, it's only allowed to break up areas, which
1561 // lies in the inside also.
1562 if( ( !pLay
->IsInFootnote() || pSct
->IsInFootnote() ) &&
1563 ( !pLay
->IsInTab() || pSct
->IsInTab() ) )
1565 pActualSection
.reset(new SwActualSection(nullptr, pSct
, pSct
->GetSection()->GetFormat()->GetSectionNode()));
1566 // tdf#132236 for SwUndoDelete: find outer sections whose start
1567 // nodes aren't contained in the range but whose end nodes are,
1568 // because section frames may need to be created for them
1569 SwActualSection
* pUpperSection(pActualSection
.get());
1570 while (pUpperSection
->GetSectionNode()->EndOfSectionIndex() < nEndIndex
)
1572 SwStartNode
*const pStart(pUpperSection
->GetSectionNode()->StartOfSectionNode());
1573 if (!pStart
->IsSectionNode())
1577 // note: these don't have a section frame, check it in EndNode case!
1578 auto const pTmp(new SwActualSection(nullptr, nullptr, static_cast<SwSectionNode
*>(pStart
)));
1579 pUpperSection
->SetUpper(pTmp
);
1580 pUpperSection
= pTmp
;
1582 OSL_ENSURE( !pLay
->Lower() || !pLay
->Lower()->IsColumnFrame(),
1583 "InsertCnt_: Wrong Call" );
1587 //If a section is "open", the pActualSection points to an SwActualSection.
1588 //If the page breaks, for "open" sections a follow will created.
1589 //For nested sections (which have, however, not a nested layout),
1590 //the SwActualSection class has a member, which points to an upper(section).
1591 //When the "inner" section finishes, the upper will used instead.
1593 std::vector
<SwSectionFrame
*> newHiddenSections
;
1595 // Do not consider the end node. The caller (Section/MakeFrames()) has to
1596 // ensure that the end of this range is positioned before EndIndex!
1597 for ( ; nEndIndex
== SwNodeOffset(0) || nIndex
< nEndIndex
; ++nIndex
)
1600 SwNode
*pNd
= pDoc
->GetNodes()[nIndex
];
1601 if ( pNd
->IsContentNode() )
1603 SwContentNode
* pNode
= static_cast<SwContentNode
*>(pNd
);
1604 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1606 if (pNd
->IsTextNode()
1607 && pNd
->GetRedlineMergeFlag() == SwNode::Merge::NonFirst
)
1608 { // must have a frame already
1609 assert(static_cast<SwTextFrame
*>(pNode
->getLayoutFrame(pLayout
))->GetMergedPara());
1611 continue; // skip it
1613 pFrame
= pNode
->IsTextNode()
1614 ? sw::MakeTextFrame(*pNode
->GetTextNode(), pLay
, eMode
)
1615 : pNode
->MakeFrame(pLay
);
1616 if (pPageMaker
&& !pLay
->IsHiddenNow())
1617 pPageMaker
->CheckInsert( nIndex
);
1619 pFrame
->InsertBehind( pLay
, pPrv
);
1622 if (SwSectionFrame
*const pSection
= pLay
->FindSctFrame())
1624 if (pSection
->ContainsAny() == pFrame
)
1625 { // tdf#146258 section PrtArea depends on paragraph upper margin
1626 pSection
->InvalidatePrt();
1631 // notify accessibility paragraphs objects about changed
1632 // CONTENT_FLOWS_FROM/_TO relation.
1633 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1634 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1635 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1636 if ( pFrame
->IsTextFrame() )
1638 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1639 // no notification, if <SwViewShell> is in construction
1640 if ( pViewShell
&& !pViewShell
->IsInConstructor() &&
1641 pViewShell
->GetLayout() &&
1642 pViewShell
->GetLayout()->IsAnyShellAccessible() &&
1643 pFrame
->FindPageFrame() != nullptr)
1645 auto pNext
= pFrame
->FindNextCnt( true );
1646 auto pPrev
= pFrame
->FindPrevCnt();
1647 pViewShell
->InvalidateAccessibleParaFlowRelation(
1648 pNext
? pNext
->DynCastTextFrame() : nullptr,
1649 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1651 // The information flags of the text frame are validated
1652 // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
1653 // The information flags have to be invalidated, because
1654 // it is possible, that the one of its upper frames
1655 // isn't inserted into the layout.
1656 pFrame
->InvalidateInfFlags();
1660 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1661 // for setting position at newly inserted frame
1662 lcl_SetPos( *pFrame
, *pLay
);
1665 if ( !pTable
->empty() && bObjsDirect
&& !isFlyCreationSuppressed
)
1666 AppendObjs( pTable
, nIndex
, pFrame
, pPage
, pDoc
);
1668 else if ( pNd
->IsTableNode() )
1669 { //Should we have encountered a table?
1670 SwTableNode
*pTableNode
= static_cast<SwTableNode
*>(pNd
);
1671 if (pLayout
->IsHideRedlines())
1673 // in the problematic case, there can be only 1 redline...
1674 SwPosition
const tmp(*pNd
);
1675 SwRangeRedline
const*const pRedline(
1676 pDoc
->getIDocumentRedlineAccess().GetRedline(tmp
, nullptr));
1677 // pathology: redline that starts on a TableNode; cannot
1678 // be created in UI but by import filters...
1680 && pRedline
->GetType() == RedlineType::Delete
1681 && &pRedline
->Start()->GetNode() == pNd
)
1683 SAL_WARN("sw.pageframe", "skipping table frame creation on bizarre redline");
1686 pTableNode
->GetNodes()[nIndex
]->SetRedlineMergeFlag(SwNode::Merge::Hidden
);
1687 if (nIndex
== pTableNode
->EndOfSectionIndex())
1696 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1698 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1699 nIndex
= pTableNode
->EndOfSectionIndex();
1700 continue; // skip it
1703 pFrame
= pTableNode
->MakeFrame( pLay
);
1705 // skip tables deleted with track changes
1706 if ( !static_cast<SwTabFrame
*>(pFrame
)->Lower() )
1708 nIndex
= pTableNode
->EndOfSectionIndex();
1709 continue; // skip it
1712 // #108116# loading may produce table structures that GCLines
1713 // needs to clean up. To keep table formulas correct, change
1714 // all table formulas to internal (BOXPTR) representation.
1715 pTableNode
->GetTable().SwitchFormulasToInternalRepresentation();
1716 pTableNode
->GetTable().GCLines();
1719 pPageMaker
->CheckInsert( nIndex
);
1721 pFrame
->InsertBehind( pLay
, pPrv
);
1722 if (pPage
) // would null in SwCellFrame ctor
1723 { // tdf#134931 call ResetTurbo(); not sure if Paste() would be
1724 pFrame
->InvalidatePage(pPage
); // better than InsertBehind()?
1727 // notify accessibility paragraphs objects about changed
1728 // CONTENT_FLOWS_FROM/_TO relation.
1729 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1730 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1731 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1733 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1734 // no notification, if <SwViewShell> is in construction
1735 if ( pViewShell
&& !pViewShell
->IsInConstructor() &&
1736 pViewShell
->GetLayout() &&
1737 pViewShell
->GetLayout()->IsAnyShellAccessible() &&
1738 pFrame
->FindPageFrame() != nullptr)
1740 auto pNext
= pFrame
->FindNextCnt( true );
1741 auto pPrev
= pFrame
->FindPrevCnt();
1742 pViewShell
->InvalidateAccessibleParaFlowRelation(
1743 pNext
? pNext
->DynCastTextFrame() : nullptr,
1744 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1748 if ( bObjsDirect
&& !pTable
->empty() )
1749 static_cast<SwTabFrame
*>(pFrame
)->RegistFlys();
1750 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1751 // for setting position at newly inserted frame
1752 lcl_SetPos( *pFrame
, *pLay
);
1755 //Set the index to the endnode of the table section.
1756 nIndex
= pTableNode
->EndOfSectionIndex();
1758 SwTabFrame
* pTmpFrame
= static_cast<SwTabFrame
*>(pFrame
);
1761 pTmpFrame
->CheckDirChange();
1762 pTmpFrame
= pTmpFrame
->IsFollow() ? pTmpFrame
->FindMaster() : nullptr;
1766 else if ( pNd
->IsSectionNode() )
1768 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1770 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1771 continue; // skip it
1773 SwSectionNode
*pNode
= static_cast<SwSectionNode
*>(pNd
);
1776 pActualSection
->SetLastPos(pPrv
);
1778 pFrame
= pNode
->MakeFrame(pLay
, pNode
->GetSection().CalcHiddenFlag());
1779 pActualSection
.reset( new SwActualSection( pActualSection
.release(),
1780 static_cast<SwSectionFrame
*>(pFrame
), pNode
) );
1781 if ( pActualSection
->GetUpper() )
1783 //Insert behind the Upper, the "Follow" of the Upper will be
1784 //generated at the EndNode.
1785 SwSectionFrame
*pTmp
= pActualSection
->GetUpper()->GetSectionFrame();
1786 pFrame
->InsertBehind( pTmp
->GetUpper(), pTmp
);
1787 // OD 25.03.2003 #108339# - direct initialization of section
1788 // after insertion in the layout
1789 static_cast<SwSectionFrame
*>(pFrame
)->Init();
1793 pFrame
->InsertBehind( pLay
, pPrv
);
1794 // OD 25.03.2003 #108339# - direct initialization of section
1795 // after insertion in the layout
1796 static_cast<SwSectionFrame
*>(pFrame
)->Init();
1799 // Do not trust the IsInFootnote flag. If we are currently
1800 // building up a table, the upper of pPrv may be a cell
1801 // frame, but the cell frame does not have an upper yet.
1802 if( pPrv
&& nullptr != pPrv
->ImplFindFootnoteFrame() )
1804 if( pPrv
->IsSctFrame() )
1805 pPrv
= static_cast<SwSectionFrame
*>(pPrv
)->ContainsContent();
1806 if( pPrv
&& pPrv
->IsTextFrame() )
1807 static_cast<SwTextFrame
*>(pPrv
)->Prepare( PrepareHint::QuoVadis
, nullptr, false );
1811 if (nIndex
+ 1 == nEndIndex
1812 // tdf#136452 may also be needed at end of section
1813 || pNode
->EndOfSectionIndex() - 1 == nEndIndex
)
1814 { // tdf#131684 tdf#132236 fix upper of frame moved in
1815 // SwUndoDelete; can't be done there unfortunately
1816 // because empty section frames are deleted here
1817 SwFrame
*const pNext(
1818 // if there's a parent section, it has been split
1819 // into 2 SwSectionFrame already :(
1821 && pFrame
->GetNext()->IsSctFrame()
1822 && pActualSection
->GetUpper()
1823 && pActualSection
->GetUpper()->GetSectionNode() ==
1824 static_cast<SwSectionFrame
const*>(pFrame
->GetNext())->GetSection()->GetFormat()->GetSectionNode())
1825 ? static_cast<SwSectionFrame
*>(pFrame
->GetNext())->ContainsContent()
1826 : pFrame
->GetNext());
1828 && pNext
->IsTextFrame()
1829 && static_cast<SwTextFrame
*>(pNext
)->GetTextNodeFirst() == pDoc
->GetNodes()[nEndIndex
]
1830 && (pNext
->GetUpper() == pFrame
->GetUpper()
1831 || pFrame
->GetNext()->IsSctFrame())) // checked above
1834 pNext
->InvalidateInfFlags(); // mbInfSct changed
1835 // could have columns
1836 SwSectionFrame
*const pSection(static_cast<SwSectionFrame
*>(pFrame
));
1837 assert(!pSection
->Lower() || pSection
->Lower()->IsLayoutFrame());
1838 SwLayoutFrame
*const pParent(pSection
->Lower() ? pSection
->GetNextLayoutLeaf() : pSection
);
1839 assert(!pParent
->Lower());
1840 // paste invalidates, section could have indent...
1841 pNext
->Paste(pParent
, nullptr);
1845 // notify accessibility paragraphs objects about changed
1846 // CONTENT_FLOWS_FROM/_TO relation.
1847 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1848 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1849 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1851 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1852 // no notification, if <SwViewShell> is in construction
1853 if ( pViewShell
&& !pViewShell
->IsInConstructor() &&
1854 pViewShell
->GetLayout() &&
1855 pViewShell
->GetLayout()->IsAnyShellAccessible() &&
1856 pFrame
->FindPageFrame() != nullptr)
1858 auto pNext
= pFrame
->FindNextCnt( true );
1859 auto pPrev
= pFrame
->FindPrevCnt();
1860 pViewShell
->InvalidateAccessibleParaFlowRelation(
1861 pNext
? pNext
->DynCastTextFrame() : nullptr,
1862 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1866 pFrame
->CheckDirChange();
1868 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1869 // for setting position at newly inserted frame
1870 lcl_SetPos( *pFrame
, *pLay
);
1872 // OD 20.11.2002 #105405# - no page, no invalidate.
1875 // OD 18.09.2002 #100522#
1876 // invalidate page in order to force format and paint of
1877 // inserted section frame
1878 pFrame
->InvalidatePage( pPage
);
1880 // FME 10.11.2003 #112243#
1881 // Invalidate fly content flag:
1882 if ( pFrame
->IsInFly() )
1883 pPage
->InvalidateFlyContent();
1885 // OD 14.11.2002 #104684# - invalidate page content in order to
1886 // force format and paint of section content.
1887 pPage
->InvalidateContent();
1890 pLay
= static_cast<SwLayoutFrame
*>(pFrame
);
1891 if ( pLay
->Lower() && pLay
->Lower()->IsLayoutFrame() )
1892 pLay
= pLay
->GetNextLayoutLeaf();
1896 else if ( pNd
->IsEndNode() && pNd
->StartOfSectionNode()->IsSectionNode() )
1898 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1900 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1901 continue; // skip it
1903 if (pLayout
->HasMergedParas() && !pNd
->StartOfSectionNode()->IsCreateFrameWhenHidingRedlines())
1904 { // tdf#135014 section break in fieldmark (start inside, end outside)
1905 assert(pNd
->StartOfSectionNode()->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1906 continue; // skip it
1908 assert(pActualSection
&& "Section end without section start?");
1909 assert(pActualSection
->GetSectionNode() == pNd
->StartOfSectionNode());
1911 //Close the section, where appropriate activate the surrounding
1913 pActualSection
.reset(pActualSection
->GetUpper());
1914 pLay
= pLay
->FindSctFrame();
1915 if ( pActualSection
)
1917 //Could be, that the last SectionFrame remains empty.
1918 //Then now is the time to remove them.
1919 if ( !pLay
->ContainsContent() )
1921 SwFrame
*pTmpFrame
= pLay
;
1922 pLay
= pTmpFrame
->GetUpper();
1923 pPrv
= pTmpFrame
->GetPrev();
1924 pTmpFrame
->RemoveFromLayout();
1925 SwFrame::DestroyFrame(pTmpFrame
);
1929 if (pLay
->IsHiddenNow())
1931 newHiddenSections
.push_back(static_cast<SwSectionFrame
*>(pLay
));
1934 pLay
= pLay
->GetUpper();
1937 // new section frame
1938 if (SwSectionFrame
* pOuterSectionFrame
= pActualSection
->GetSectionFrame())
1940 // Splitting moves the trailing content to the next frame
1941 pFrame
= pOuterSectionFrame
->SplitSect(pActualSection
->GetLastPos(), pPrv
);
1943 // We don't want to leave empty parts back.
1944 if (! pOuterSectionFrame
->IsColLocked() &&
1945 ! pOuterSectionFrame
->ContainsContent() )
1947 pOuterSectionFrame
->DelEmpty( true );
1948 SwFrame::DestroyFrame(pOuterSectionFrame
);
1950 else if (pOuterSectionFrame
->IsHiddenNow())
1952 newHiddenSections
.push_back(pOuterSectionFrame
);
1957 pFrame
= pActualSection
->GetSectionNode()->MakeFrame(
1958 pLay
, pActualSection
->GetSectionNode()->GetSection().IsHiddenFlag());
1959 pFrame
->InsertBehind( pLay
, pPrv
);
1960 static_cast<SwSectionFrame
*>(pFrame
)->Init();
1962 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1963 // for setting position at newly inserted frame
1964 lcl_SetPos( *pFrame
, *pLay
);
1967 pActualSection
->SetSectionFrame( static_cast<SwSectionFrame
*>(pFrame
) );
1969 pLay
= static_cast<SwLayoutFrame
*>(pFrame
);
1970 if ( pLay
->Lower() && pLay
->Lower()->IsLayoutFrame() )
1971 pLay
= pLay
->GetNextLayoutLeaf();
1976 if (pLay
->IsHiddenNow())
1978 newHiddenSections
.push_back(static_cast<SwSectionFrame
*>(pLay
));
1980 //Nothing more with sections, it goes on right behind
1983 pLay
= pLay
->GetUpper();
1986 else if( pNd
->IsStartNode() &&
1987 SwFlyStartNode
== static_cast<SwStartNode
*>(pNd
)->GetStartNodeType() )
1989 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1991 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1992 assert(false); // actually a fly-section can't be deleted?
1993 continue; // skip it
1995 if ( !pTable
->empty() && bObjsDirect
&& !isFlyCreationSuppressed
)
1997 SwFlyFrame
* pFly
= pLay
->FindFlyFrame();
1999 AppendObjs( pTable
, nIndex
, pFly
, pPage
, pDoc
);
2004 assert(!pLayout
->HasMergedParas()
2005 || pNd
->GetRedlineMergeFlag() != SwNode::Merge::Hidden
);
2006 // Neither Content nor table nor section, so we are done.
2011 if ( pActualSection
)
2013 // Might happen that an empty (Follow-)Section is left over.
2014 if ( !(pLay
= pActualSection
->GetSectionFrame())->ContainsContent() )
2016 pLay
->RemoveFromLayout();
2017 SwFrame::DestroyFrame(pLay
);
2019 pActualSection
.reset();
2022 if ( bPages
) // let the Flys connect to each other
2024 if ( !isFlyCreationSuppressed
)
2025 AppendAllObjs( pTable
, pLayout
);
2029 // do it after AppendAllObjs()
2030 for (SwSectionFrame
* pNew
: newHiddenSections
)
2032 for (SwFlowFrame
* pSect
= pNew
; pSect
; pSect
= pSect
->GetPrecede())
2033 { // flys were created visible; section may be paginated so iterate
2034 pSect
->GetFrame().HideAndShowObjects();
2040 pPageMaker
->CheckFlyCache( pPage
);
2042 if( pDoc
->GetLayoutCache() )
2045 pDoc
->GetLayoutCache()->CompareLayout( *pDoc
);
2047 pDoc
->GetLayoutCache()->ClearImpl();
2051 pDoc
->getIDocumentTimerAccess().UnblockIdling();
2052 if( bOldCallbackActionEnabled
)
2053 pLayout
->SetCallbackActionEnabled( bOldCallbackActionEnabled
);
2056 void MakeFrames( SwDoc
*pDoc
, SwNode
&rSttIdx
, SwNode
&rEndIdx
)
2058 bObjsDirect
= false;
2060 SwNodeOffset nEndIdx
= rEndIdx
.GetIndex();
2061 // TODO for multiple layouts there should be a loop here
2062 SwNode
* pNd
= pDoc
->GetNodes().FindPrvNxtFrameNode( rSttIdx
,
2063 pDoc
->GetNodes()[ nEndIdx
-1 ],
2064 pDoc
->getIDocumentLayoutAccess().GetCurrentLayout());
2067 bool bAfter
= *pNd
< rSttIdx
;
2068 SwNode2Layout
aNode2Layout( *pNd
, rSttIdx
.GetIndex() );
2069 sw::FrameMode eMode
= sw::FrameMode::Existing
;
2070 ::std::vector
<SwFrame
*> frames
;
2071 while (SwFrame
* pFrame
= aNode2Layout
.NextFrame())
2072 { // tdf#150500 new frames may be created that end up merged on pNd
2073 // so copy the currently existing ones; they shouldn't get deleted
2074 frames
.push_back(pFrame
);
2076 for (SwFrame
*const pFrame
: frames
)
2078 SwLayoutFrame
*pUpper
= pFrame
->GetUpper();
2079 SwFootnoteFrame
* pFootnoteFrame
= pUpper
->FindFootnoteFrame();
2080 bool bOldLock
, bOldFootnote
;
2081 if( pFootnoteFrame
)
2083 bOldFootnote
= pFootnoteFrame
->IsColLocked();
2084 pFootnoteFrame
->ColLock();
2087 bOldFootnote
= true;
2088 SwSectionFrame
* pSct
= pUpper
->FindSctFrame();
2089 // Inside of footnotes only those areas are interesting that are inside of them. But
2090 // not the ones (e.g. column areas) in which are the footnote containers positioned.
2091 // #109767# Table frame is in section, insert section in cell frame.
2092 if( pSct
&& ((pFootnoteFrame
&& !pSct
->IsInFootnote()) || pUpper
->IsCellFrame()) )
2095 { // to prevent pTmp->MoveFwd from destroying the SectionFrame
2096 bOldLock
= pSct
->IsColLocked();
2102 // If pFrame cannot be moved, it is not possible to move it to the next page. This applies
2103 // also for frames (in the first column of a frame pFrame is moveable) and column
2104 // sections of tables (also here pFrame is moveable).
2105 bool bMoveNext
= nEndIdx
- rSttIdx
.GetIndex() > SwNodeOffset(120);
2106 bool bAllowMove
= !pFrame
->IsInFly() && pFrame
->IsMoveable() &&
2107 (!pFrame
->IsInTab() || pFrame
->IsTabFrame() );
2108 if ( bMoveNext
&& bAllowMove
)
2110 SwFrame
*pMove
= pFrame
;
2111 SwFrame
*pPrev
= pFrame
->GetPrev();
2112 SwFlowFrame
*pTmp
= SwFlowFrame::CastFlowFrame( pMove
);
2117 // The rest of this page should be empty. Thus, the following one has to move to
2118 // the next page (it might also be located in the following column).
2119 assert(!pTmp
->HasFollow() && "prev. node's frame is not last");
2121 // If the surrounding SectionFrame has a "next" one,
2122 // so this one needs to be moved as well.
2123 pMove
= pFrame
->GetIndNext();
2124 SwColumnFrame
* pCol
= static_cast<SwColumnFrame
*>(pFrame
->FindColFrame());
2126 pCol
= static_cast<SwColumnFrame
*>(pCol
->GetNext());
2129 if( pCol
&& !pMove
)
2130 { // No successor so far, look into the next column
2131 pMove
= pCol
->ContainsAny();
2132 if( pCol
->GetNext() )
2133 pCol
= static_cast<SwColumnFrame
*>(pCol
->GetNext());
2134 else if( pCol
->IsInSct() )
2135 { // If there is no following column but we are in a column frame,
2136 // there might be (page) columns outside of it.
2137 pCol
= static_cast<SwColumnFrame
*>(pCol
->FindSctFrame()->FindColFrame());
2139 pCol
= static_cast<SwColumnFrame
*>(pCol
->GetNext());
2144 // skip invalid SectionFrames
2145 while( pMove
&& pMove
->IsSctFrame() &&
2146 !static_cast<SwSectionFrame
*>(pMove
)->GetSection() )
2147 pMove
= pMove
->GetNext();
2148 } while( !pMove
&& pCol
);
2152 if ( pMove
->IsContentFrame() )
2153 pTmp
= static_cast<SwContentFrame
*>(pMove
);
2154 else if ( pMove
->IsTabFrame() )
2155 pTmp
= static_cast<SwTabFrame
*>(pMove
);
2156 else if ( pMove
->IsSctFrame() )
2158 pMove
= static_cast<SwSectionFrame
*>(pMove
)->ContainsAny();
2160 pTmp
= SwFlowFrame::CastFlowFrame( pMove
);
2170 assert(!pTmp
->IsFollow() && "next node's frame is not master");
2171 // move the _content_ of a section frame
2172 if( pMove
->IsSctFrame() )
2174 while( pMove
&& pMove
->IsSctFrame() &&
2175 !static_cast<SwSectionFrame
*>(pMove
)->GetSection() )
2176 pMove
= pMove
->GetNext();
2177 if( pMove
&& pMove
->IsSctFrame() )
2178 pMove
= static_cast<SwSectionFrame
*>(pMove
)->ContainsAny();
2180 pTmp
= SwFlowFrame::CastFlowFrame( pMove
);
2188 SwFrame
* pOldUp
= pTmp
->GetFrame().GetUpper();
2189 // MoveFwd==true means that we are still on the same page.
2190 // But since we want to move if possible!
2191 bool bTmpOldLock
= pTmp
->IsJoinLocked();
2193 while( pTmp
->MoveFwd( true, false, true ) )
2195 if( pOldUp
== pTmp
->GetFrame().GetUpper() )
2197 pOldUp
= pTmp
->GetFrame().GetUpper();
2202 ::InsertCnt_( pUpper
, pDoc
, rSttIdx
.GetIndex(),
2203 pFrame
->IsInDocBody(), nEndIdx
, pPrev
, eMode
);
2207 SwFrame
* pPrv
= bAfter
? pFrame
: pFrame
->GetPrev();
2209 ::InsertCnt_( pUpper
, pDoc
, rSttIdx
.GetIndex(), false,
2210 nEndIdx
, pPrv
, eMode
);
2211 // OD 23.06.2003 #108784# - correction: append objects doesn't
2212 // depend on value of <bAllowMove>
2213 if( !isFlyCreationSuppressed
)
2215 const sw::SpzFrameFormats
* pTable
= pDoc
->GetSpzFrameFormats();
2216 if( !pTable
->empty() )
2217 AppendAllObjs( pTable
, pUpper
);
2220 if( pFrame
->IsInFly() )
2221 pFrame
->FindFlyFrame()->Invalidate_();
2222 if( pFrame
->IsInTab() )
2223 pFrame
->InvalidateSize();
2226 SwPageFrame
*pPage
= pUpper
->FindPageFrame();
2227 SwFrame::CheckPageDescs( pPage
, false );
2229 pFootnoteFrame
->ColUnlock();
2233 // pSct might be empty (e.g. when inserting linked section containing further
2234 // sections) and can be destroyed in such cases.
2235 if( !pSct
->ContainsContent() )
2237 pSct
->DelEmpty( true );
2238 pUpper
->getRootFrame()->RemoveFromList( pSct
);
2239 SwFrame::DestroyFrame(pSct
);
2242 eMode
= sw::FrameMode::New
; // use Existing only once!
2249 SwBorderAttrs::SwBorderAttrs(const sw::BorderCacheOwner
* pOwner
, const SwFrame
* pConstructor
)
2250 : SwCacheObj(pOwner
)
2251 , m_rAttrSet(pConstructor
->IsContentFrame()
2252 ? pConstructor
->IsTextFrame()
2253 ? static_cast<const SwTextFrame
*>(pConstructor
)->GetTextNodeForParaProps()->GetSwAttrSet()
2254 : static_cast<const SwNoTextFrame
*>(pConstructor
)->GetNode()->GetSwAttrSet()
2255 : static_cast<const SwLayoutFrame
*>(pConstructor
)->GetFormat()->GetAttrSet())
2256 , m_rUL(m_rAttrSet
.GetULSpace())
2257 , m_rBox(m_rAttrSet
.GetBox())
2258 , m_rShadow(m_rAttrSet
.GetShadow())
2259 , m_aFrameSize(m_rAttrSet
.GetFrameSize().GetSize())
2261 , m_bJoinedWithPrev(false)
2262 , m_bJoinedWithNext(false)
2270 , m_nGetBottomLine(0)
2274 const SwTextFrame
* pTextFrame
= pConstructor
->DynCastTextFrame();
2277 m_pFirstLineIndent
.reset(m_rAttrSet
.GetFirstLineIndent().Clone());
2278 m_pTextLeftMargin
.reset(m_rAttrSet
.GetTextLeftMargin().Clone());
2279 m_pRightMargin
.reset(m_rAttrSet
.GetRightMargin().Clone());
2280 assert(m_pFirstLineIndent
);
2281 assert(m_pTextLeftMargin
);
2285 // LRSpaceItem is copied due to the possibility that it is adjusted
2286 m_xLR
.reset(m_rAttrSet
.GetLRSpace().Clone());
2287 if (pConstructor
->IsNoTextFrame())
2289 m_xLR
= std::make_shared
<SvxLRSpaceItem
>(RES_LR_SPACE
);
2294 // Caution: The USHORTs for the cached values are not initialized by intention!
2296 // everything needs to be calculated at least once:
2297 m_bTopLine
= m_bBottomLine
= m_bLeftLine
= m_bRightLine
=
2298 m_bTop
= m_bBottom
= m_bLine
= true;
2300 // except this one: calculate line spacing before cell border only for text frames
2301 m_bLineSpacing
= bool(pTextFrame
);
2303 m_bCacheGetLine
= m_bCachedGetTopLine
= m_bCachedGetBottomLine
= false;
2304 // OD 21.05.2003 #108789# - init cache status for values <m_bJoinedWithPrev>
2305 // and <m_bJoinedWithNext>, which aren't initialized by default.
2306 m_bCachedJoinedWithPrev
= false;
2307 m_bCachedJoinedWithNext
= false;
2310 SwBorderAttrs::~SwBorderAttrs()
2312 const_cast<sw::BorderCacheOwner
*>(static_cast<sw::BorderCacheOwner
const *>(m_pOwner
))->m_bInCache
= false;
2315 /* All calc methods calculate a safety distance in addition to the values given by the attributes.
2316 * This safety distance is only added when working with borders and/or shadows to prevent that
2317 * e.g. borders are painted over.
2320 void SwBorderAttrs::CalcTop_()
2322 m_nTop
= CalcTopLine() + m_rUL
.GetUpper();
2324 bool bGutterAtTop
= m_rAttrSet
.GetDoc()->getIDocumentSettingAccess().get(
2325 DocumentSettingId::GUTTER_AT_TOP
);
2326 if (bGutterAtTop
&& m_xLR
)
2328 // Decrease the print area: the top space is the sum of top and gutter margins.
2329 m_nTop
+= m_xLR
->GetGutterMargin();
2335 void SwBorderAttrs::CalcBottom_()
2337 m_nBottom
= CalcBottomLine() + m_rUL
.GetLower();
2341 tools::Long
SwBorderAttrs::CalcRight( const SwFrame
* pCaller
) const
2343 tools::Long nRight
=0;
2345 if (!pCaller
->IsTextFrame() || !static_cast<const SwTextFrame
*>(pCaller
)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING
)) {
2346 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2347 // and right border are painted on the right respectively left.
2348 if ( pCaller
->IsCellFrame() && pCaller
->IsRightToLeft() )
2349 nRight
= CalcLeftLine();
2351 nRight
= CalcRightLine();
2354 // for paragraphs, "left" is "before text" and "right" is "after text"
2355 if (pCaller
->IsTextFrame())
2357 // tdf#163913: Only apply the fixed-width part of the margin here.
2358 // Font-relative margins will be applied as an adjustment later on.
2359 if (pCaller
->IsRightToLeft())
2361 nRight
+= m_pTextLeftMargin
->ResolveLeftFixedPart(*m_pFirstLineIndent
);
2365 nRight
+= m_pRightMargin
->ResolveRightFixedPart();
2369 nRight
+= m_xLR
->ResolveRight({});
2371 // correction: retrieve left margin for numbering in R2L-layout
2372 if ( pCaller
->IsTextFrame() && pCaller
->IsRightToLeft() )
2374 nRight
+= static_cast<const SwTextFrame
*>(pCaller
)->GetTextNodeForParaProps()->GetLeftMarginWithNum();
2377 if (pCaller
->IsPageFrame())
2379 const auto pPageFrame
= static_cast<const SwPageFrame
*>(pCaller
);
2380 bool bGutterAtTop
= pPageFrame
->GetFormat()->getIDocumentSettingAccess().get(
2381 DocumentSettingId::GUTTER_AT_TOP
);
2384 bool bRtlGutter
= pPageFrame
->GetAttrSet()->GetItem
<SfxBoolItem
>(RES_RTL_GUTTER
)->GetValue();
2385 tools::Long nGutterMargin
= bRtlGutter
? m_xLR
->GetGutterMargin() : m_xLR
->GetRightGutterMargin();
2386 // Decrease the print area: the right space is the sum of right and right gutter
2388 nRight
+= nGutterMargin
;
2395 tools::Long
SwBorderAttrs::CalcLeft( const SwFrame
*pCaller
) const
2397 tools::Long nLeft
=0;
2399 if (!pCaller
->IsTextFrame() || !static_cast<const SwTextFrame
*>(pCaller
)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING
))
2401 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2402 // and right border are painted on the right respectively left.
2403 if ( pCaller
->IsCellFrame() && pCaller
->IsRightToLeft() )
2404 nLeft
= CalcRightLine();
2406 nLeft
= CalcLeftLine();
2409 // for paragraphs, "left" is "before text" and "right" is "after text"
2411 // tdf#163913: Only apply the fixed-width part of the margin here.
2412 // Font-relative margins will be applied as an adjustment later on.
2413 if (pCaller
->IsTextFrame() && pCaller
->IsRightToLeft())
2415 nLeft
+= m_pRightMargin
->ResolveRightFixedPart();
2419 if (pCaller
->IsTextFrame())
2421 nLeft
+= m_pTextLeftMargin
->ResolveLeftFixedPart(*m_pFirstLineIndent
);
2425 nLeft
+= m_xLR
->ResolveLeft({});
2429 // correction: do not retrieve left margin for numbering in R2L-layout
2430 if ( pCaller
->IsTextFrame() && !pCaller
->IsRightToLeft() )
2432 nLeft
+= static_cast<const SwTextFrame
*>(pCaller
)->GetTextNodeForParaProps()->GetLeftMarginWithNum();
2435 if (pCaller
->IsPageFrame())
2437 const auto pPageFrame
= static_cast<const SwPageFrame
*>(pCaller
);
2438 bool bGutterAtTop
= pPageFrame
->GetFormat()->getIDocumentSettingAccess().get(
2439 DocumentSettingId::GUTTER_AT_TOP
);
2442 bool bRtlGutter
= pPageFrame
->GetAttrSet()->GetItem
<SfxBoolItem
>(RES_RTL_GUTTER
)->GetValue();
2443 tools::Long nGutterMargin
= bRtlGutter
? m_xLR
->GetRightGutterMargin() : m_xLR
->GetGutterMargin();
2444 // Decrease the print area: the left space is the sum of left and gutter margins.
2445 nLeft
+= nGutterMargin
;
2452 /* Calculated values for borders and shadows.
2453 * It might be that a distance is wanted even without lines. This will be
2454 * considered here and not by the attribute (e.g. bBorderDist for cells).
2457 void SwBorderAttrs::CalcTopLine_()
2459 m_nTopLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::TOP
, /*bEvenIfNoLine*/true );
2460 m_nTopLine
= m_nTopLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::TOP
);
2464 void SwBorderAttrs::CalcBottomLine_()
2466 m_nBottomLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::BOTTOM
, true );
2467 m_nBottomLine
= m_nBottomLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::BOTTOM
);
2468 m_bBottomLine
= false;
2471 void SwBorderAttrs::CalcLeftLine_()
2473 m_nLeftLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::LEFT
, true);
2474 m_nLeftLine
= m_nLeftLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::LEFT
);
2475 m_bLeftLine
= false;
2478 void SwBorderAttrs::CalcRightLine_()
2480 m_nRightLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::RIGHT
, true );
2481 m_nRightLine
= m_nRightLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::RIGHT
);
2482 m_bRightLine
= false;
2485 void SwBorderAttrs::IsLine_()
2487 m_bIsLine
= m_rBox
.GetTop() || m_rBox
.GetBottom() ||
2488 m_rBox
.GetLeft()|| m_rBox
.GetRight();
2492 /* The borders of neighboring paragraphs are condensed by following algorithm:
2494 * 1. No top border if the predecessor has the same top border and (3) applies.
2495 * In addition, the paragraph needs to have a border at least one side (left/right/bottom).
2496 * 2. No bottom border if the successor has the same bottom border and (3) applies.
2497 * In addition, the paragraph needs to have a border at least one side (left/right/top).
2498 * 3. The borders on the left and right side are identical between the current and the
2499 * pre-/succeeding paragraph.
2502 static bool CmpLines( const editeng::SvxBorderLine
*pL1
, const editeng::SvxBorderLine
*pL2
)
2504 return ( ((pL1
&& pL2
) && (*pL1
== *pL2
)) || (!pL1
&& !pL2
) );
2507 // OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
2508 // OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
2509 // instead of only the right LR-spacing, because R2L-layout has to be
2511 bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs
&rCmpAttrs
,
2512 const SwFrame
*pCaller
,
2513 const SwFrame
*pCmp
) const
2515 return ( CmpLines( rCmpAttrs
.GetBox().GetLeft(), GetBox().GetLeft() ) &&
2516 CmpLines( rCmpAttrs
.GetBox().GetRight(),GetBox().GetRight() ) &&
2517 CalcLeft( pCaller
) == rCmpAttrs
.CalcLeft( pCmp
) &&
2518 // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
2519 CalcRight( pCaller
) == rCmpAttrs
.CalcRight( pCmp
) );
2522 bool SwBorderAttrs::JoinWithCmp( const SwFrame
& _rCallerFrame
,
2523 const SwFrame
& _rCmpFrame
) const
2525 bool bReturnVal
= false;
2527 SwBorderAttrAccess
aCmpAccess( SwFrame::GetCache(), &_rCmpFrame
);
2528 const SwBorderAttrs
&rCmpAttrs
= *aCmpAccess
.Get();
2529 if ( m_rShadow
== rCmpAttrs
.GetShadow() &&
2530 CmpLines( m_rBox
.GetTop(), rCmpAttrs
.GetBox().GetTop() ) &&
2531 CmpLines( m_rBox
.GetBottom(), rCmpAttrs
.GetBox().GetBottom() ) &&
2532 CmpLeftRight( rCmpAttrs
, &_rCallerFrame
, &_rCmpFrame
)
2541 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2542 // previous frame. Calculated value saved in cached value <m_bJoinedWithPrev>
2543 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame>
2544 void SwBorderAttrs::CalcJoinedWithPrev( const SwFrame
& _rFrame
,
2545 const SwFrame
* _pPrevFrame
) const
2548 m_bJoinedWithPrev
= false;
2550 if ( _rFrame
.IsTextFrame() )
2552 // text frame can potentially join with previous text frame, if
2553 // corresponding attribute set is set at previous text frame.
2554 // OD 2004-02-26 #i25029# - If parameter <_pPrevFrame> is set, take this
2555 // one as previous frame.
2556 const SwFrame
* pPrevFrame
= _pPrevFrame
? _pPrevFrame
: _rFrame
.GetPrev();
2557 // OD 2004-02-13 #i25029# - skip hidden text frames.
2558 while (pPrevFrame
&& pPrevFrame
->IsHiddenNow())
2560 pPrevFrame
= pPrevFrame
->GetPrev();
2562 if ( pPrevFrame
&& pPrevFrame
->IsTextFrame() &&
2563 pPrevFrame
->GetAttrSet()->GetParaConnectBorder().GetValue()
2566 m_bJoinedWithPrev
= JoinWithCmp( _rFrame
, *pPrevFrame
);
2570 // valid cache status, if demanded
2571 // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrame>
2573 m_bCachedJoinedWithPrev
= m_bCacheGetLine
&& !_pPrevFrame
;
2576 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2577 // next frame. Calculated value saved in cached value <m_bJoinedWithNext>
2578 void SwBorderAttrs::CalcJoinedWithNext( const SwFrame
& _rFrame
) const
2581 m_bJoinedWithNext
= false;
2583 if ( _rFrame
.IsTextFrame() )
2585 // text frame can potentially join with next text frame, if
2586 // corresponding attribute set is set at current text frame.
2587 // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
2588 const SwFrame
* pNextFrame
= _rFrame
.GetNext();
2589 while (pNextFrame
&& pNextFrame
->IsHiddenNow())
2591 pNextFrame
= pNextFrame
->GetNext();
2593 if ( pNextFrame
&& pNextFrame
->IsTextFrame() &&
2594 _rFrame
.GetAttrSet()->GetParaConnectBorder().GetValue()
2597 m_bJoinedWithNext
= JoinWithCmp( _rFrame
, *pNextFrame
);
2601 // valid cache status, if demanded
2602 m_bCachedJoinedWithNext
= m_bCacheGetLine
;
2605 // OD 21.05.2003 #108789# - accessor for cached values <m_bJoinedWithPrev>
2606 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame>, which is passed to
2607 // method <_CalcJoindWithPrev(..)>.
2608 bool SwBorderAttrs::JoinedWithPrev( const SwFrame
& _rFrame
,
2609 const SwFrame
* _pPrevFrame
) const
2611 if ( !m_bCachedJoinedWithPrev
|| _pPrevFrame
)
2613 // OD 2004-02-26 #i25029# - pass <_pPrevFrame> as 2nd parameter
2614 CalcJoinedWithPrev( _rFrame
, _pPrevFrame
);
2617 return m_bJoinedWithPrev
;
2620 bool SwBorderAttrs::JoinedWithNext( const SwFrame
& _rFrame
) const
2622 if ( !m_bCachedJoinedWithNext
)
2624 CalcJoinedWithNext( _rFrame
);
2627 return m_bJoinedWithNext
;
2630 // OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrame>, which is passed to
2631 // method <JoinedWithPrev>
2632 void SwBorderAttrs::GetTopLine_( const SwFrame
& _rFrame
,
2633 const SwFrame
* _pPrevFrame
)
2635 sal_uInt16 nRet
= CalcTopLine();
2637 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2638 // OD 2004-02-26 #i25029# - add 2nd parameter
2639 if ( JoinedWithPrev( _rFrame
, _pPrevFrame
) )
2644 m_bCachedGetTopLine
= m_bCacheGetLine
;
2646 m_nGetTopLine
= nRet
;
2649 void SwBorderAttrs::GetBottomLine_( const SwFrame
& _rFrame
)
2651 sal_uInt16 nRet
= CalcBottomLine();
2653 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2654 if ( JoinedWithNext( _rFrame
) )
2659 m_bCachedGetBottomLine
= m_bCacheGetLine
;
2661 m_nGetBottomLine
= nRet
;
2664 void SwBorderAttrs::CalcLineSpacing_()
2666 // tdf#125300 compatibility option AddParaLineSpacingToTableCells needs also line spacing
2667 const SvxLineSpacingItem
&rSpace
= m_rAttrSet
.GetLineSpacing();
2668 if ( rSpace
.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
&& rSpace
.GetPropLineSpace() > 100 )
2670 sal_Int32 nFontSize
= m_rAttrSet
.Get(RES_CHRATR_FONTSIZE
).GetHeight();
2671 m_nLineSpacing
= nFontSize
* (rSpace
.GetPropLineSpace() - 100) * 1.15 / 100;
2673 m_bLineSpacing
= false;
2676 static sw::BorderCacheOwner
const* GetBorderCacheOwner(SwFrame
const& rFrame
)
2678 return rFrame
.IsContentFrame()
2679 ? static_cast<sw::BorderCacheOwner
const*>(rFrame
.IsTextFrame()
2680 // sw_redlinehide: presumably this caches the border attrs at the model level and can be shared across different layouts so we want the ParaProps node here
2681 ? static_cast<const SwTextFrame
&>(rFrame
).GetTextNodeForParaProps()
2682 : static_cast<const SwNoTextFrame
&>(rFrame
).GetNode())
2683 : static_cast<sw::BorderCacheOwner
const*>(static_cast<const SwLayoutFrame
&>(rFrame
).GetFormat());
2686 SwBorderAttrAccess::SwBorderAttrAccess( SwCache
&rCach
, const SwFrame
*pFrame
) :
2687 SwCacheAccess( rCach
,
2688 static_cast<void const *>(GetBorderCacheOwner(*pFrame
)),
2689 GetBorderCacheOwner(*pFrame
)->IsInCache()),
2690 m_pConstructor( pFrame
)
2694 SwCacheObj
*SwBorderAttrAccess::NewObj()
2696 const_cast<sw::BorderCacheOwner
*>(static_cast<sw::BorderCacheOwner
const *>(m_pOwner
))->m_bInCache
= true;
2697 return new SwBorderAttrs( static_cast<sw::BorderCacheOwner
const *>(m_pOwner
), m_pConstructor
);
2700 SwBorderAttrs
*SwBorderAttrAccess::Get()
2702 return static_cast<SwBorderAttrs
*>(SwCacheAccess::Get());
2705 SwOrderIter::SwOrderIter( const SwPageFrame
*pPg
) :
2707 m_pCurrent( nullptr )
2711 void SwOrderIter::Top()
2713 m_pCurrent
= nullptr;
2714 if ( !m_pPage
->GetSortedObjs() )
2717 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2718 if ( !pObjs
->size() )
2721 sal_uInt32 nTopOrd
= 0;
2722 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2723 for (SwAnchoredObject
* i
: *pObjs
)
2725 const SdrObject
* pObj
= i
->GetDrawObj();
2726 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2728 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2729 if ( nTmp
>= nTopOrd
)
2737 const SdrObject
*SwOrderIter::Bottom()
2739 m_pCurrent
= nullptr;
2740 if ( m_pPage
->GetSortedObjs() )
2742 sal_uInt32 nBotOrd
= USHRT_MAX
;
2743 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2744 if ( pObjs
->size() )
2746 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2747 for (SwAnchoredObject
* i
: *pObjs
)
2749 const SdrObject
* pObj
= i
->GetDrawObj();
2750 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2752 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2753 if ( nTmp
< nBotOrd
)
2764 const SdrObject
*SwOrderIter::Next()
2766 const sal_uInt32 nCurOrd
= m_pCurrent
? m_pCurrent
->GetOrdNumDirect() : 0;
2767 m_pCurrent
= nullptr;
2768 if ( m_pPage
->GetSortedObjs() )
2770 sal_uInt32 nOrd
= USHRT_MAX
;
2771 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2772 if ( pObjs
->size() )
2774 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2775 for (SwAnchoredObject
* i
: *pObjs
)
2777 const SdrObject
* pObj
= i
->GetDrawObj();
2778 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2780 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2781 if ( nTmp
> nCurOrd
&& nTmp
< nOrd
)
2792 void SwOrderIter::Prev()
2794 const sal_uInt32 nCurOrd
= m_pCurrent
? m_pCurrent
->GetOrdNumDirect() : 0;
2795 m_pCurrent
= nullptr;
2796 if ( !m_pPage
->GetSortedObjs() )
2799 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2800 if ( !pObjs
->size() )
2803 sal_uInt32 nOrd
= 0;
2804 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2805 for (SwAnchoredObject
* i
: *pObjs
)
2807 const SdrObject
* pObj
= i
->GetDrawObj();
2808 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2810 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2811 if ( nTmp
< nCurOrd
&& nTmp
>= nOrd
)
2819 /// Keep and restore the substructure of a layout frame for an action.
2821 // Do not look at each neighbor one by one to set all pointers correctly.
2822 // It is sufficient to detach a part of a chain and check if another chain needs to be added
2823 // when attaching it again. Only the pointers necessary for the chain connection need to be
2824 // adjusted. The correction happens in RestoreContent(). In between all access is restricted.
2825 // During this action, the Flys are detached from the page.
2827 // #115759# - 'remove' also drawing object from page and
2828 // at-fly anchored objects from page
2829 static void lcl_RemoveObjsFromPage( SwFrame
* _pFrame
)
2831 OSL_ENSURE( _pFrame
->GetDrawObjs(), "no DrawObjs in lcl_RemoveObjsFromPage." );
2832 SwSortedObjs
&rObjs
= *_pFrame
->GetDrawObjs();
2833 for (SwAnchoredObject
* pObj
: rObjs
)
2835 // #115759# - reset member, at which the anchored
2836 // object orients its vertical position
2837 pObj
->ClearVertPosOrientFrame();
2839 pObj
->ResetLayoutProcessBools();
2840 // #115759# - remove also lower objects of as-character
2841 // anchored Writer fly frames from page
2842 if ( auto pFlyFrame
= pObj
->DynCastFlyFrame() )
2844 // #115759# - remove also direct lowers of Writer
2845 // fly frame from page
2846 if ( pFlyFrame
->GetDrawObjs() )
2848 ::lcl_RemoveObjsFromPage( pFlyFrame
);
2851 SwContentFrame
* pCnt
= pFlyFrame
->ContainsContent();
2854 if ( pCnt
->GetDrawObjs() )
2855 ::lcl_RemoveObjsFromPage( pCnt
);
2856 pCnt
= pCnt
->GetNextContentFrame();
2858 if ( pFlyFrame
->IsFlyFreeFrame() )
2860 // #i28701# - use new method <GetPageFrame()>
2861 if (SwPageFrame
*pPg
= pFlyFrame
->GetPageFrame())
2862 pPg
->RemoveFlyFromPage(pFlyFrame
);
2865 // #115759# - remove also drawing objects from page
2866 else if ( auto pDrawObj
= dynamic_cast<SwAnchoredDrawObject
*>( pObj
) )
2868 if (pObj
->GetFrameFormat()->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR
)
2870 if (SwPageFrame
*pPg
= pObj
->GetPageFrame())
2871 pPg
->RemoveDrawObjFromPage( *pDrawObj
);
2877 SwFrame
*SaveContent( SwLayoutFrame
*pLay
, SwFrame
*pStart
)
2879 if( pLay
->IsSctFrame() && pLay
->Lower() && pLay
->Lower()->IsColumnFrame() )
2880 sw_RemoveFootnotes( static_cast<SwColumnFrame
*>(pLay
->Lower()), true, true );
2882 SwFrame
*pSav
= pLay
->ContainsAny();
2883 if ( nullptr == pSav
)
2886 if( pSav
->IsInFootnote() && !pLay
->IsInFootnote() )
2889 pSav
= pSav
->FindNext();
2890 while( pSav
&& pSav
->IsInFootnote() );
2891 if( !pSav
|| !pLay
->IsAnLower( pSav
) )
2895 // Tables should be saved as a whole, exception:
2896 // The contents of a section or a cell inside a table should be saved
2897 if ( pSav
->IsInTab() && !( ( pLay
->IsSctFrame() || pLay
->IsCellFrame() ) && pLay
->IsInTab() ) )
2898 while ( !pSav
->IsTabFrame() )
2899 pSav
= pSav
->GetUpper();
2901 if( pSav
->IsInSct() )
2902 { // search the upmost section inside of pLay
2903 SwFrame
* pSect
= pLay
->FindSctFrame();
2904 SwFrame
*pTmp
= pSav
;
2908 pTmp
= (pSav
&& pSav
->GetUpper()) ? pSav
->GetUpper()->FindSctFrame() : nullptr;
2909 } while ( pTmp
!= pSect
);
2912 SwFrame
*pFloat
= pSav
;
2915 bool bGo
= pStart
== pSav
;
2919 pFloat
->GetUpper()->m_pLower
= nullptr; // detach the chain part
2921 // search the end of the chain part, remove Flys on the way
2926 if ( pFloat
->IsContentFrame() )
2928 if ( pFloat
->GetDrawObjs() )
2929 ::lcl_RemoveObjsFromPage( static_cast<SwContentFrame
*>(pFloat
) );
2931 else if ( pFloat
->IsTabFrame() || pFloat
->IsSctFrame() )
2933 SwContentFrame
*pCnt
= static_cast<SwLayoutFrame
*>(pFloat
)->ContainsContent();
2937 { if ( pCnt
->GetDrawObjs() )
2938 ::lcl_RemoveObjsFromPage( pCnt
);
2939 pCnt
= pCnt
->GetNextContentFrame();
2940 } while ( pCnt
&& static_cast<SwLayoutFrame
*>(pFloat
)->IsAnLower( pCnt
) );
2944 OSL_ENSURE( !pFloat
, "new FloatFrame?" );
2947 if ( pFloat
->GetNext() )
2950 pFloat
->mpUpper
= nullptr;
2951 pFloat
= pFloat
->GetNext();
2952 if( !bGo
&& pFloat
== pStart
)
2955 pFloat
->mpPrev
->mpNext
= nullptr;
2956 pFloat
->mpPrev
= nullptr;
2964 // search next chain part and connect both chains
2965 SwFrame
*pTmp
= pFloat
? pFloat
->FindNext() : nullptr;
2967 pFloat
->mpUpper
= nullptr;
2969 if( !pLay
->IsInFootnote() )
2970 while( pTmp
&& pTmp
->IsInFootnote() )
2971 pTmp
= pTmp
->FindNext();
2973 if ( !pLay
->IsAnLower( pTmp
) )
2978 pFloat
->mpNext
= pTmp
; // connect both chains
2979 pFloat
->mpNext
->mpPrev
= pFloat
;
2982 bGo
= bGo
|| ( pStart
== pFloat
);
2985 return bGo
? pStart
: nullptr;
2988 // #115759# - add also drawing objects to page and at-fly
2989 // anchored objects to page
2990 static void lcl_AddObjsToPage( SwFrame
* _pFrame
, SwPageFrame
* _pPage
)
2992 OSL_ENSURE( _pFrame
->GetDrawObjs(), "no DrawObjs in lcl_AddObjsToPage." );
2993 SwSortedObjs
&rObjs
= *_pFrame
->GetDrawObjs();
2994 for (SwAnchoredObject
* pObj
: rObjs
)
2996 // #115759# - unlock position of anchored object
2997 // in order to get the object's position calculated.
2998 pObj
->UnlockPosition();
2999 // #115759# - add also lower objects of as-character
3000 // anchored Writer fly frames from page
3001 if ( auto pFlyFrame
= pObj
->DynCastFlyFrame() )
3003 if (pFlyFrame
->IsFlyFreeFrame())
3005 _pPage
->AppendFlyToPage( pFlyFrame
);
3007 pFlyFrame
->InvalidatePos_();
3008 pFlyFrame
->InvalidateSize_();
3009 pFlyFrame
->InvalidatePage( _pPage
);
3011 // #115759# - add also at-fly anchored objects
3013 if ( pFlyFrame
->GetDrawObjs() )
3015 ::lcl_AddObjsToPage( pFlyFrame
, _pPage
);
3018 SwContentFrame
*pCnt
= pFlyFrame
->ContainsContent();
3021 if ( pCnt
->GetDrawObjs() )
3022 ::lcl_AddObjsToPage( pCnt
, _pPage
);
3023 pCnt
= pCnt
->GetNextContentFrame();
3026 // #115759# - remove also drawing objects from page
3027 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pObj
) != nullptr )
3029 if (pObj
->GetFrameFormat()->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR
)
3031 pObj
->InvalidateObjPos();
3032 _pPage
->AppendDrawObjToPage(
3033 *static_cast<SwAnchoredDrawObject
*>(pObj
) );
3039 void RestoreContent( SwFrame
*pSav
, SwLayoutFrame
*pParent
, SwFrame
*pSibling
)
3041 assert(pSav
&& pParent
&& "no Save or Parent provided for RestoreContent.");
3042 SwRectFnSet
aRectFnSet(pParent
);
3044 // If there are already FlowFrames below the new parent, so add the chain (starting with pSav)
3045 // after the last one. The parts are inserted and invalidated if needed.
3046 // On the way, the Flys of the ContentFrames are registered at the page.
3048 SwPageFrame
*pPage
= pParent
->FindPageFrame();
3051 pPage
->InvalidatePage( pPage
);
3053 // determine predecessor and establish connection or initialize
3054 pSav
->mpPrev
= pSibling
;
3058 pNxt
= pSibling
->mpNext
;
3059 pSibling
->mpNext
= pSav
;
3060 pSibling
->InvalidatePrt_();
3061 pSibling
->InvalidatePage( pPage
);
3062 SwFlowFrame
*pFlowFrame
= dynamic_cast<SwFlowFrame
*>(pSibling
);
3063 if (pFlowFrame
&& pFlowFrame
->GetFollow())
3064 pSibling
->Prepare( PrepareHint::Clear
, nullptr, false );
3067 { pNxt
= pParent
->m_pLower
;
3068 pParent
->m_pLower
= pSav
;
3069 pSav
->mpUpper
= pParent
; // set here already, so that it is explicit when invalidating
3071 if ( pSav
->IsContentFrame() )
3072 static_cast<SwContentFrame
*>(pSav
)->InvalidatePage( pPage
);
3074 { // pSav might be an empty SectFrame
3075 SwContentFrame
* pCnt
= pParent
->ContainsContent();
3077 pCnt
->InvalidatePage( pPage
);
3081 // the parent needs to grow appropriately
3082 SwTwips nGrowVal
= 0;
3085 { pSav
->mpUpper
= pParent
;
3086 nGrowVal
+= aRectFnSet
.GetHeight(pSav
->getFrameArea());
3087 pSav
->InvalidateAll_();
3089 // register Flys, if TextFrames than also invalidate appropriately
3090 if ( pSav
->IsContentFrame() )
3092 if ( pSav
->IsTextFrame() &&
3093 static_cast<SwTextFrame
*>(pSav
)->GetCacheIdx() != USHRT_MAX
)
3094 static_cast<SwTextFrame
*>(pSav
)->Init(); // I am its friend
3096 if ( pPage
&& pSav
->GetDrawObjs() )
3097 ::lcl_AddObjsToPage( static_cast<SwContentFrame
*>(pSav
), pPage
);
3100 { SwContentFrame
*pBlub
= static_cast<SwLayoutFrame
*>(pSav
)->ContainsContent();
3104 { if ( pPage
&& pBlub
->GetDrawObjs() )
3105 ::lcl_AddObjsToPage( pBlub
, pPage
);
3106 if( pBlub
->IsTextFrame() && static_cast<SwTextFrame
*>(pBlub
)->HasFootnote() &&
3107 static_cast<SwTextFrame
*>(pBlub
)->GetCacheIdx() != USHRT_MAX
)
3108 static_cast<SwTextFrame
*>(pBlub
)->Init(); // I am its friend
3109 pBlub
= pBlub
->GetNextContentFrame();
3110 } while ( pBlub
&& static_cast<SwLayoutFrame
*>(pSav
)->IsAnLower( pBlub
));
3114 pSav
= pSav
->GetNext();
3120 pLast
->mpNext
= pNxt
;
3121 pNxt
->mpPrev
= pLast
;
3124 pParent
->Grow( nGrowVal
);
3129 bool IsRightPageByNumber(SwRootFrame
const& rLayout
, sal_uInt16
const nPageNum
)
3131 assert(rLayout
.GetLower());
3132 // unfortunately can only get SwPageDesc, not SwFormatPageDesc here...
3133 auto const nFirstVirtPageNum(rLayout
.GetLower()->GetVirtPageNum());
3134 bool const isFirstPageOfLayoutOdd(nFirstVirtPageNum
% 2 == 1);
3135 return ((nPageNum
% 2) == 1) == isFirstPageOfLayoutOdd
;
3140 SwPageFrame
* InsertNewPage( SwPageDesc
&rDesc
, SwFrame
*pUpper
,
3141 bool const isRightPage
, bool const bFirst
, bool bInsertEmpty
,
3142 bool const bFootnote
,
3144 bool const bVeryFirstPage
)
3147 assert(pUpper
->IsRootFrame());
3148 assert(!pSibling
|| static_cast<SwLayoutFrame
const*>(pUpper
)->Lower() != pSibling
); // currently no insert before 1st page
3150 SwDoc
*pDoc
= static_cast<SwLayoutFrame
*>(pUpper
)->GetFormat()->GetDoc();
3153 if (rDesc
.IsFirstShared())
3155 // We need to fallback to left or right page format, decide it now.
3156 // FIXME: is this still needed?
3159 rDesc
.GetFirstMaster().SetFormatAttr( rDesc
.GetMaster().GetHeader() );
3160 rDesc
.GetFirstMaster().SetFormatAttr( rDesc
.GetMaster().GetFooter() );
3161 // fdo#60250 copy margins for mirrored pages
3162 rDesc
.GetFirstMaster().SetFormatAttr( rDesc
.GetMaster().GetLRSpace() );
3166 rDesc
.GetFirstLeft().SetFormatAttr( rDesc
.GetLeft().GetHeader() );
3167 rDesc
.GetFirstLeft().SetFormatAttr( rDesc
.GetLeft().GetFooter() );
3168 rDesc
.GetFirstLeft().SetFormatAttr( rDesc
.GetLeft().GetLRSpace() );
3172 SwFrameFormat
*pFormat(isRightPage
? rDesc
.GetRightFormat(bFirst
) : rDesc
.GetLeftFormat(bFirst
));
3173 // If there is no FrameFormat for this page, add an empty page
3176 pFormat
= isRightPage
? rDesc
.GetLeftFormat(bVeryFirstPage
) : rDesc
.GetRightFormat(bVeryFirstPage
);
3177 OSL_ENSURE( pFormat
, "Descriptor without any format?!" );
3178 bInsertEmpty
= !bInsertEmpty
;
3182 SwPageDesc
*pTmpDesc
= pSibling
&& pSibling
->GetPrev() ?
3183 static_cast<SwPageFrame
*>(pSibling
->GetPrev())->GetPageDesc() : &rDesc
;
3184 pRet
= new SwPageFrame( pDoc
->GetEmptyPageFormat(), pUpper
, pTmpDesc
);
3185 SAL_INFO( "sw.pageframe", "InsertNewPage - insert empty p: " << pRet
<< " d: " << pTmpDesc
);
3186 pRet
->Paste( pUpper
, pSibling
);
3187 pRet
->PreparePage( bFootnote
);
3189 pRet
= new SwPageFrame( pFormat
, pUpper
, &rDesc
);
3190 SAL_INFO( "sw.pageframe", "InsertNewPage p: " << pRet
<< " d: " << &rDesc
<< " f: " << pFormat
);
3191 pRet
->Paste( pUpper
, pSibling
);
3192 pRet
->PreparePage( bFootnote
);
3193 if ( pRet
->GetNext() )
3194 SwRootFrame::AssertPageFlys( pRet
);
3198 /* The following two methods search the layout structure recursively and
3199 * register all Flys at the page that have a Frame in this structure as an anchor.
3202 static void lcl_Regist( SwPageFrame
*pPage
, const SwFrame
*pAnch
)
3204 SwSortedObjs
*pObjs
= const_cast<SwSortedObjs
*>(pAnch
->GetDrawObjs());
3205 for (SwAnchoredObject
* pObj
: *pObjs
)
3207 if (SwFlyFrame
* pFly
= pObj
->DynCastFlyFrame())
3209 // register (not if already known)
3210 // #i28701# - use new method <GetPageFrame()>
3211 SwPageFrame
*pPg
= pFly
->IsFlyFreeFrame()
3212 ? pFly
->GetPageFrame() : pFly
->FindPageFrame();
3216 pPg
->RemoveFlyFromPage( pFly
);
3217 pPage
->AppendFlyToPage( pFly
);
3219 ::RegistFlys( pPage
, pFly
);
3224 if ( pPage
!= pObj
->GetPageFrame() )
3226 pObj
->RegisterAtPage(*pPage
);
3230 const SwFlyFrame
* pFly
= pAnch
->FindFlyFrame();
3232 pObj
->GetDrawObj()->GetOrdNum() < pFly
->GetVirtDrawObj()->GetOrdNum() &&
3233 pObj
->GetDrawObj()->getSdrPageFromSdrObject() )
3235 //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
3236 pObj
->DrawObj()->getSdrPageFromSdrObject()->SetObjectOrdNum( pFly
->GetVirtDrawObj()->GetOrdNumDirect(),
3237 pObj
->GetDrawObj()->GetOrdNumDirect() );
3242 void RegistFlys( SwPageFrame
*pPage
, const SwLayoutFrame
*pLay
)
3244 if ( pLay
->GetDrawObjs() )
3245 ::lcl_Regist( pPage
, pLay
);
3246 const SwFrame
*pFrame
= pLay
->Lower();
3249 if ( pFrame
->IsLayoutFrame() )
3250 ::RegistFlys( pPage
, static_cast<const SwLayoutFrame
*>(pFrame
) );
3251 else if ( pFrame
->GetDrawObjs() )
3252 ::lcl_Regist( pPage
, pFrame
);
3253 pFrame
= pFrame
->GetNext();
3257 /// Notify the background based on the difference between old and new rectangle
3258 void Notify( SwFlyFrame
*pFly
, SwPageFrame
*pOld
, const SwRect
&rOld
,
3259 const SwRect
* pOldPrt
)
3261 const SwRect
aFrame( pFly
->GetObjRectWithSpaces() );
3262 if ( rOld
.Pos() != aFrame
.Pos() )
3263 { // changed position, invalidate old and new area
3265 && rOld
.Left() + pFly
->GetFormat()->GetLRSpace().ResolveLeft({}) < FAR_AWAY
)
3267 pFly
->NotifyBackground( pOld
, rOld
, PrepareHint::FlyFrameLeave
);
3269 pFly
->NotifyBackground( pFly
->FindPageFrame(), aFrame
, PrepareHint::FlyFrameArrive
);
3271 else if ( rOld
.SSize() != aFrame
.SSize() )
3272 { // changed size, invalidate the area that was left or is now overlapped
3273 // For simplicity, we purposely invalidate a Twip even if not needed.
3275 SwViewShell
*pSh
= pFly
->getRootFrame()->GetCurrShell();
3276 if( pSh
&& rOld
.HasArea() )
3277 pSh
->InvalidateWindows( rOld
);
3279 // #i51941# - consider case that fly frame isn't
3280 // registered at the old page <pOld>
3281 SwPageFrame
* pPageFrame
= pFly
->FindPageFrame();
3282 if ( pOld
!= pPageFrame
)
3284 pFly
->NotifyBackground( pPageFrame
, aFrame
, PrepareHint::FlyFrameArrive
);
3287 if ( rOld
.Left() != aFrame
.Left() )
3289 SwRect
aTmp( rOld
);
3290 aTmp
.Union( aFrame
);
3291 aTmp
.Left( std::min(aFrame
.Left(), rOld
.Left()) );
3292 aTmp
.Right( std::max(aFrame
.Left(), rOld
.Left()) );
3293 pFly
->NotifyBackground( pOld
, aTmp
, PrepareHint::FlyFrameSizeChanged
);
3295 SwTwips nOld
= rOld
.Right();
3296 SwTwips nNew
= aFrame
.Right();
3299 SwRect
aTmp( rOld
);
3300 aTmp
.Union( aFrame
);
3301 aTmp
.Left( std::min(nNew
, nOld
) );
3302 aTmp
.Right( std::max(nNew
, nOld
) );
3303 pFly
->NotifyBackground( pOld
, aTmp
, PrepareHint::FlyFrameSizeChanged
);
3305 if ( rOld
.Top() != aFrame
.Top() )
3307 SwRect
aTmp( rOld
);
3308 aTmp
.Union( aFrame
);
3309 aTmp
.Top( std::min(aFrame
.Top(), rOld
.Top()) );
3310 aTmp
.Bottom( std::max(aFrame
.Top(), rOld
.Top()) );
3311 pFly
->NotifyBackground( pOld
, aTmp
, PrepareHint::FlyFrameSizeChanged
);
3313 nOld
= rOld
.Bottom();
3314 nNew
= aFrame
.Bottom();
3317 SwRect
aTmp( rOld
);
3318 aTmp
.Union( aFrame
);
3319 aTmp
.Top( std::min(nNew
, nOld
) );
3320 aTmp
.Bottom( std::max(nNew
, nOld
) );
3321 pFly
->NotifyBackground( pOld
, aTmp
, PrepareHint::FlyFrameSizeChanged
);
3324 else if(pOldPrt
&& *pOldPrt
!= pFly
->getFramePrintArea())
3326 bool bNotifyBackground(pFly
->GetFormat()->GetSurround().IsContour());
3328 if(!bNotifyBackground
&&
3329 pFly
->IsFlyFreeFrame() &&
3330 static_cast< const SwFlyFreeFrame
* >(pFly
)->supportsAutoContour())
3332 // RotateFlyFrame3: Also notify for FlyFrames which allow AutoContour
3333 bNotifyBackground
= true;
3336 if(bNotifyBackground
)
3339 pFly
->NotifyBackground( pFly
->FindPageFrame(), aFrame
, PrepareHint::FlyFrameArrive
);
3344 static void lcl_CheckFlowBack( SwFrame
* pFrame
, const SwRect
&rRect
)
3346 SwTwips nBottom
= rRect
.Bottom();
3349 if( pFrame
->IsLayoutFrame() )
3351 if( rRect
.Overlaps( pFrame
->getFrameArea() ) )
3352 lcl_CheckFlowBack( static_cast<SwLayoutFrame
*>(pFrame
)->Lower(), rRect
);
3354 else if( !pFrame
->GetNext() && nBottom
> pFrame
->getFrameArea().Bottom() )
3356 if( pFrame
->IsContentFrame() && static_cast<SwContentFrame
*>(pFrame
)->HasFollow() )
3357 pFrame
->InvalidateSize();
3359 pFrame
->InvalidateNextPos();
3361 pFrame
= pFrame
->GetNext();
3365 static void lcl_NotifyContent( const SdrObject
*pThis
, SwContentFrame
*pCnt
,
3366 const SwRect
&rRect
, const PrepareHint eHint
)
3368 if ( !pCnt
->IsTextFrame() )
3371 auto pTextFrame
= static_cast<SwTextFrame
*>(pCnt
);
3372 SwRect
aCntPrt( pCnt
->getFramePrintArea() );
3373 aCntPrt
.Pos() += pCnt
->getFrameArea().Pos();
3375 if (eHint
== PrepareHint::FlyFrameArrive
)
3377 SwTwips nLower
= pTextFrame
->GetLowerMarginForFlyIntersect();
3380 aCntPrt
.AddBottom(nLower
);
3384 if ( eHint
== PrepareHint::FlyFrameAttributesChanged
)
3386 // #i35640# - use given rectangle <rRect> instead
3387 // of current bound rectangle
3388 if ( aCntPrt
.Overlaps( rRect
) )
3389 pCnt
->Prepare( PrepareHint::FlyFrameAttributesChanged
);
3391 // #i23129# - only invalidate, if the text frame
3392 // printing area overlaps with the given rectangle.
3393 else if ( aCntPrt
.Overlaps( rRect
) )
3394 pCnt
->Prepare( eHint
, static_cast<void*>(&aCntPrt
.Intersection_( rRect
)) );
3395 if ( !pCnt
->GetDrawObjs() )
3398 const SwSortedObjs
&rObjs
= *pCnt
->GetDrawObjs();
3399 for (SwAnchoredObject
* pObj
: rObjs
)
3401 if ( auto pFly
= pObj
->DynCastFlyFrame() )
3403 if ( pFly
->IsFlyInContentFrame() )
3405 SwContentFrame
*pContent
= pFly
->ContainsContent();
3408 ::lcl_NotifyContent( pThis
, pContent
, rRect
, eHint
);
3409 pContent
= pContent
->GetNextContentFrame();
3416 void Notify_Background( const SdrObject
* pObj
,
3418 const SwRect
& rRect
,
3419 const PrepareHint eHint
,
3422 // If the frame was positioned correctly for the first time, do not inform the old area
3423 if ( eHint
== PrepareHint::FlyFrameLeave
&& rRect
.Top() == FAR_AWAY
)
3426 SwLayoutFrame
* pArea
;
3427 SwFlyFrame
*pFlyFrame
= nullptr;
3429 if( auto pVirtFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) )
3431 pFlyFrame
= const_cast<SwVirtFlyDrawObj
*>(pVirtFlyDrawObj
)->GetFlyFrame();
3432 pAnchor
= pFlyFrame
->AnchorFrame();
3436 pFlyFrame
= nullptr;
3437 if (SwDrawContact
* pC
= static_cast<SwDrawContact
*>(GetUserCall(pObj
)))
3438 pAnchor
= const_cast<SwFrame
*>(pC
->GetAnchoredObj(pObj
)->GetAnchorFrame());
3442 if( PrepareHint::FlyFrameLeave
!= eHint
&& pAnchor
->IsInFly() )
3443 pArea
= pAnchor
->FindFlyFrame();
3446 SwContentFrame
*pCnt
= nullptr;
3449 if( PrepareHint::FlyFrameArrive
!= eHint
)
3450 lcl_CheckFlowBack( pArea
, rRect
);
3452 // Only the Flys following this anchor are reacting. Thus, those do not
3453 // need to be processed.
3454 // An exception is LEAVE, since the Fly might come "from above".
3455 // If the anchor is positioned on the previous page, the whole page
3456 // needs to be processed (47722).
3457 // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
3458 // on the object positioning, the complete area has to be processed,
3459 // because content frames before the anchor frame also have to consider
3460 // the object for the text wrapping.
3461 // #i3317# - The complete area has always been
3464 pCnt
= pArea
->ContainsContent();
3467 SwFrame
*pLastTab
= nullptr;
3469 bool isValidTableBeforeAnchor(false);
3470 while ( pCnt
&& pArea
&& pArea
->IsAnLower( pCnt
) )
3472 ::lcl_NotifyContent( pObj
, pCnt
, rRect
, eHint
);
3473 if ( pCnt
->IsInTab() )
3475 SwTabFrame
*pTab
= pCnt
->FindTabFrame();
3476 if ( pTab
!= pLastTab
)
3479 isValidTableBeforeAnchor
= false;
3480 if (PrepareHint::FlyFrameArrive
== eHint
3481 && pFlyFrame
// TODO: do it for draw objects too?
3482 && pTab
->IsFollow() // table starts on previous page?
3483 // "through" means they will actually overlap anyway
3484 && css::text::WrapTextMode_THROUGH
!= pFlyFrame
->GetFormat()->GetSurround().GetSurround()
3485 // if it's anchored in footer it can't move to other page
3486 && !pAnchor
->FindFooterOrHeader())
3488 SwFrame
* pTmp(pAnchor
->GetPrev());
3493 // tdf#99460 the table shouldn't be moved by the fly
3494 isValidTableBeforeAnchor
= true;
3497 pTmp
= pTmp
->GetPrev();
3500 // #i40606# - use <GetLastBoundRect()>
3501 // instead of <GetCurrentBoundRect()>, because a recalculation
3502 // of the bounding rectangle isn't intended here.
3503 if (!isValidTableBeforeAnchor
3504 && (pTab
->getFrameArea().Overlaps(SwRect(pObj
->GetLastBoundRect())) ||
3505 pTab
->getFrameArea().Overlaps(rRect
)))
3507 if ( !pFlyFrame
|| !pFlyFrame
->IsLowerOf( pTab
) )
3508 pTab
->InvalidatePrt();
3511 SwLayoutFrame
* pCell
= pCnt
->GetUpper();
3512 // #i40606# - use <GetLastBoundRect()>
3513 // instead of <GetCurrentBoundRect()>, because a recalculation
3514 // of the bounding rectangle isn't intended here.
3515 if (!isValidTableBeforeAnchor
&& pCell
->IsCellFrame() &&
3516 ( pCell
->getFrameArea().Overlaps( SwRect(pObj
->GetLastBoundRect()) ) ||
3517 pCell
->getFrameArea().Overlaps( rRect
) ) )
3519 const SwFormatVertOrient
&rOri
= pCell
->GetFormat()->GetVertOrient();
3520 if ( text::VertOrientation::NONE
!= rOri
.GetVertOrient() )
3521 pCell
->InvalidatePrt();
3524 pCnt
= pCnt
->GetNextContentFrame();
3526 // #128702# - make code robust
3527 if ( pPage
&& pPage
->GetSortedObjs() )
3530 const SwSortedObjs
&rObjs
= *pPage
->GetSortedObjs();
3531 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
3533 if ( pAnchoredObj
->DynCastFlyFrame() != nullptr )
3535 if( pAnchoredObj
->GetDrawObj() == pObj
)
3537 SwFlyFrame
*pFly
= static_cast<SwFlyFrame
*>(pAnchoredObj
);
3538 if ( pFly
->getFrameArea().Top() == FAR_AWAY
)
3542 (!pFly
->IsLowerOf( pFlyFrame
) &&
3543 pFly
->GetVirtDrawObj()->GetOrdNumDirect() < pObj
->GetOrdNumDirect()))
3545 pCnt
= pFly
->ContainsContent();
3548 ::lcl_NotifyContent( pObj
, pCnt
, rRect
, eHint
);
3549 pCnt
= pCnt
->GetNextContentFrame();
3552 if( pFly
->IsFlyLayFrame() )
3554 SwFrame
* pLower
= pFly
->Lower();
3555 if( pLower
&& pLower
->IsColumnFrame() &&
3556 pFly
->getFrameArea().Bottom() >= rRect
.Top() &&
3557 pFly
->getFrameArea().Top() <= rRect
.Bottom() &&
3558 pFly
->getFrameArea().Right() >= rRect
.Left() &&
3559 pFly
->getFrameArea().Left() <= rRect
.Right() )
3561 pFly
->InvalidateSize();
3564 // Flys above myself might sidestep if they have an automatic
3565 // alignment. This happens independently of my attributes since
3566 // this might have been changed as well.
3567 else if ( pFly
->IsFlyAtContentFrame() &&
3568 pObj
->GetOrdNumDirect() <
3569 pFly
->GetVirtDrawObj()->GetOrdNumDirect() &&
3570 pFlyFrame
&& !pFly
->IsLowerOf( pFlyFrame
) )
3572 const SwFormatHoriOrient
&rH
= pFly
->GetFormat()->GetHoriOrient();
3573 if ( text::HoriOrientation::NONE
!= rH
.GetHoriOrient() &&
3574 text::HoriOrientation::CENTER
!= rH
.GetHoriOrient() &&
3575 ( !pFly
->IsAutoPos() || text::RelOrientation::CHAR
!= rH
.GetRelationOrient() ) &&
3576 (pFly
->getFrameArea().Bottom() >= rRect
.Top() &&
3577 pFly
->getFrameArea().Top() <= rRect
.Bottom()) )
3578 pFly
->InvalidatePos();
3583 if ( pFlyFrame
&& pAnchor
->GetUpper() && pAnchor
->IsInTab() )//MA_FLY_HEIGHT
3584 pAnchor
->GetUpper()->InvalidateSize();
3586 // #i82258# - make code robust
3587 SwViewShell
* pSh
= nullptr;
3588 if ( bInva
&& pPage
&&
3589 nullptr != (pSh
= pPage
->getRootFrame()->GetCurrShell()) )
3591 pSh
->InvalidateWindows( rRect
);
3595 /// Provides the Upper of an anchor in paragraph-bound objects. If the latter
3596 /// is a chained border or a footnote, the "virtual" Upper might be returned.
3597 const SwFrame
* GetVirtualUpper( const SwFrame
* pFrame
, const Point
& rPos
)
3599 if( pFrame
->IsTextFrame() )
3601 pFrame
= pFrame
->GetUpper();
3602 if( !pFrame
->getFrameArea().Contains( rPos
) )
3604 if( pFrame
->IsFootnoteFrame() )
3606 const SwFootnoteFrame
* pTmp
= static_cast<const SwFootnoteFrame
*>(pFrame
)->GetFollow();
3609 if( pTmp
->getFrameArea().Contains( rPos
) )
3611 pTmp
= pTmp
->GetFollow();
3616 SwFlyFrame
* pTmp
= const_cast<SwFlyFrame
*>(pFrame
->FindFlyFrame());
3619 if( pTmp
->getFrameArea().Contains( rPos
) )
3621 pTmp
= pTmp
->GetNextLink();
3629 bool Is_Lower_Of(const SwFrame
*pCurrFrame
, const SdrObject
* pObj
)
3632 const SwFrame
* pFrame
;
3633 if (const SwVirtFlyDrawObj
*pFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>(pObj
))
3635 const SwFlyFrame
* pFly
= pFlyDrawObj
->GetFlyFrame();
3636 pFrame
= pFly
->GetAnchorFrame();
3637 aPos
= pFly
->getFrameArea().Pos();
3641 if (SwDrawContact
* pC
= static_cast<SwDrawContact
*>(GetUserCall(pObj
)))
3643 pFrame
= pC
->GetAnchorFrame(pObj
);
3644 aPos
= pObj
->GetCurrentBoundRect().TopLeft();
3649 OSL_ENSURE( pFrame
, "8-( Fly is lost in Space." );
3650 pFrame
= GetVirtualUpper( pFrame
, aPos
);
3652 { if ( pFrame
== pCurrFrame
)
3654 if( pFrame
->IsFlyFrame() )
3656 aPos
= pFrame
->getFrameArea().Pos();
3657 pFrame
= GetVirtualUpper( static_cast<const SwFlyFrame
*>(pFrame
)->GetAnchorFrame(), aPos
);
3660 pFrame
= pFrame
->GetUpper();
3665 /// provides the area of a frame in that no Fly from another area can overlap
3666 const SwFrame
*FindContext( const SwFrame
*pFrame
, SwFrameType nAdditionalContextType
)
3668 const SwFrameType nTyp
= SwFrameType::Root
| SwFrameType::Header
| SwFrameType::Footer
| SwFrameType::FtnCont
|
3669 SwFrameType::Ftn
| SwFrameType::Fly
|
3670 SwFrameType::Tab
| SwFrameType::Row
| SwFrameType::Cell
|
3671 nAdditionalContextType
;
3673 { if ( pFrame
->GetType() & nTyp
)
3675 pFrame
= pFrame
->GetUpper();
3680 bool IsFrameInSameContext( const SwFrame
*pInnerFrame
, const SwFrame
*pFrame
)
3682 const SwFrame
*pContext
= FindContext( pInnerFrame
, SwFrameType::None
);
3684 const SwFrameType nTyp
= SwFrameType::Root
| SwFrameType::Header
| SwFrameType::Footer
| SwFrameType::FtnCont
|
3685 SwFrameType::Ftn
| SwFrameType::Fly
|
3686 SwFrameType::Tab
| SwFrameType::Row
| SwFrameType::Cell
;
3688 { if ( pFrame
->GetType() & nTyp
)
3690 if( pFrame
== pContext
)
3692 if( pFrame
->IsCellFrame() )
3695 if( pFrame
->IsFlyFrame() )
3697 Point
aPos( pFrame
->getFrameArea().Pos() );
3698 pFrame
= GetVirtualUpper( static_cast<const SwFlyFrame
*>(pFrame
)->GetAnchorFrame(), aPos
);
3701 pFrame
= pFrame
->GetUpper();
3707 static SwTwips
lcl_CalcCellRstHeight( SwLayoutFrame
*pCell
)
3709 SwFrame
*pLow
= pCell
->Lower();
3710 if ( pLow
&& (pLow
->IsContentFrame() || pLow
->IsSctFrame()) )
3712 tools::Long nHeight
= 0, nFlyAdd
= 0;
3715 tools::Long nLow
= pLow
->getFrameArea().Height();
3716 if( pLow
->IsTextFrame() && static_cast<SwTextFrame
*>(pLow
)->IsUndersized() )
3717 nLow
+= static_cast<SwTextFrame
*>(pLow
)->GetParHeight()-pLow
->getFramePrintArea().Height();
3718 else if( pLow
->IsSctFrame() && static_cast<SwSectionFrame
*>(pLow
)->IsUndersized() )
3719 nLow
+= static_cast<SwSectionFrame
*>(pLow
)->Undersize();
3720 nFlyAdd
= std::max( tools::Long(0), nFlyAdd
- nLow
);
3721 nFlyAdd
= std::max( nFlyAdd
, ::CalcHeightWithFlys( pLow
) );
3723 pLow
= pLow
->GetNext();
3728 // The border cannot be calculated based on PrtArea and Frame, since both can be invalid.
3729 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), pCell
);
3730 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
3731 nHeight
+= rAttrs
.CalcTop() + rAttrs
.CalcBottom();
3733 return pCell
->getFrameArea().Height() - nHeight
;
3737 tools::Long nRstHeight
= 0;
3738 while (pLow
&& pLow
->IsLayoutFrame())
3740 nRstHeight
+= ::CalcRowRstHeight(static_cast<SwLayoutFrame
*>(pLow
));
3741 pLow
= pLow
->GetNext();
3747 SwTwips
CalcRowRstHeight( SwLayoutFrame
*pRow
)
3749 SwFrame
*pLow
= pRow
->Lower();
3750 if (!(pLow
&& pLow
->IsLayoutFrame()))
3754 SwTwips nRstHeight
= LONG_MAX
;
3755 while (pLow
&& pLow
->IsLayoutFrame())
3757 nRstHeight
= std::min(nRstHeight
, ::lcl_CalcCellRstHeight(static_cast<SwLayoutFrame
*>(pLow
)));
3758 pLow
= pLow
->GetNext();
3763 const SwFrame
* FindPage( const SwRect
&rRect
, const SwFrame
*pPage
)
3765 if ( !rRect
.Overlaps( pPage
->getFrameArea() ) )
3767 const SwRootFrame
* pRootFrame
= static_cast<const SwRootFrame
*>(pPage
->GetUpper());
3768 const SwFrame
* pTmpPage
= pRootFrame
? pRootFrame
->GetPageAtPos( rRect
.TopLeft(), &rRect
.SSize(), true ) : nullptr;
3778 class SwFrameHolder
: private SfxListener
3782 virtual void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
) override
;
3789 void SetFrame( SwFrame
* pHold
);
3790 SwFrame
* GetFrame() { return m_pFrame
; }
3792 bool IsSet() const { return m_bSet
; }
3797 void SwFrameHolder::SetFrame( SwFrame
* pHold
)
3800 if (m_pFrame
!= pHold
)
3803 EndListening(*m_pFrame
);
3804 StartListening(*pHold
);
3809 void SwFrameHolder::Reset()
3812 EndListening(*m_pFrame
);
3817 void SwFrameHolder::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
3819 if (rHint
.GetId() == SfxHintId::Dying
&& &rBC
== m_pFrame
)
3825 static sal_uInt64
CalcCurrentDist(sal_Int64 nDiffX
, sal_Int64 nDiffY
)
3827 sal_Int64 nDiffX2
, nDiffY2
;
3828 if (o3tl::checked_multiply(nDiffX
, nDiffX
, nDiffX2
))
3830 SAL_WARN("sw.pageframe", "CalcCurrentDist overflow: X " << nDiffX
);
3831 return std::numeric_limits
<sal_uInt64
>::max();
3833 if (o3tl::checked_multiply(nDiffY
, nDiffY
, nDiffY2
))
3835 SAL_WARN("sw.pageframe", "CalcCurrentDist overflow: Y " << nDiffY
);
3836 return std::numeric_limits
<sal_uInt64
>::max();
3839 if (o3tl::checked_add
<sal_uInt64
>(nDiffX2
, nDiffY2
, ret
))
3841 SAL_WARN("sw.pageframe", "CalcCurrentDist overflow: " << nDiffX2
<< " + " << nDiffY2
);
3842 return std::numeric_limits
<sal_uInt64
>::max();
3847 SwFrame
* GetFrameOfModify(SwRootFrame
const*const pLayout
, sw::BroadcastingModify
const& rMod
,
3848 SwFrameType
const nFrameType
, SwPosition
const*const pPos
,
3849 std::pair
<Point
, bool> const*const pViewPosAndCalcFrame
)
3851 SwFrame
*pMinFrame
= nullptr, *pTmpFrame
;
3852 SwFrameHolder aHolder
;
3854 bool bClientIterChanged
= false;
3856 SwIterator
<SwFrame
, sw::BroadcastingModify
, sw::IteratorMode::UnwrapMulti
> aIter(rMod
);
3858 pMinFrame
= nullptr;
3860 sal_uInt64 nMinDist
= 0;
3861 bClientIterChanged
= false;
3863 for( pTmpFrame
= aIter
.First(); pTmpFrame
; pTmpFrame
= aIter
.Next() )
3865 if( pTmpFrame
->GetType() & nFrameType
&&
3866 ( !pLayout
|| pLayout
== pTmpFrame
->getRootFrame() ) &&
3867 (!pTmpFrame
->IsFlowFrame() ||
3868 !SwFlowFrame::CastFlowFrame( pTmpFrame
)->IsFollow() ))
3870 if (pViewPosAndCalcFrame
)
3872 // watch for Frame being deleted
3874 aHolder
.SetFrame( pMinFrame
);
3878 if (pViewPosAndCalcFrame
->second
)
3880 // tdf#108118 prevent recursion
3881 DisableCallbackAction
a(*pTmpFrame
->getRootFrame());
3882 // - format parent Writer
3883 // fly frame, if it isn't been formatted yet.
3884 // Note: The Writer fly frame could be the frame itself.
3885 SwFlyFrame
* pFlyFrame( pTmpFrame
->FindFlyFrame() );
3887 pFlyFrame
->getFrameArea().Pos().X() == FAR_AWAY
&&
3888 pFlyFrame
->getFrameArea().Pos().Y() == FAR_AWAY
)
3890 SwObjectFormatter::FormatObj( *pFlyFrame
);
3892 pTmpFrame
->Calc(pLayout
? pLayout
->GetCurrShell()->GetOut() : nullptr);
3895 // aIter.IsChanged checks if the current pTmpFrame has been deleted while
3896 // it is the current iterator
3897 // FrameHolder watches for deletion of the current pMinFrame
3898 if( aIter
.IsChanged() || ( aHolder
.IsSet() && !aHolder
.GetFrame() ) )
3900 // restart iteration
3901 bClientIterChanged
= true;
3905 // for Flys go via the parent if the Fly is not yet "formatted"
3906 if (!pViewPosAndCalcFrame
->second
&&
3907 pTmpFrame
->GetType() & SwFrameType::Fly
&&
3908 static_cast<SwFlyFrame
*>(pTmpFrame
)->GetAnchorFrame() &&
3909 FAR_AWAY
== pTmpFrame
->getFrameArea().Pos().getX() &&
3910 FAR_AWAY
== pTmpFrame
->getFrameArea().Pos().getY() )
3911 aCalcRect
= static_cast<SwFlyFrame
*>(pTmpFrame
)->GetAnchorFrame()->getFrameArea();
3913 aCalcRect
= pTmpFrame
->getFrameArea();
3915 if (aCalcRect
.Contains(pViewPosAndCalcFrame
->first
))
3917 pMinFrame
= pTmpFrame
;
3921 // Point not in rectangle. Compare distances:
3922 const Point aCalcRectCenter
= aCalcRect
.Center();
3923 const Point aDiff
= aCalcRectCenter
- pViewPosAndCalcFrame
->first
;
3924 const sal_uInt64 nCurrentDist
= CalcCurrentDist(aDiff
.getX(), aDiff
.getY());
3925 if ( !pMinFrame
|| nCurrentDist
< nMinDist
)
3927 pMinFrame
= pTmpFrame
;
3928 nMinDist
= nCurrentDist
;
3933 // if no pViewPosAndCalcFrame is provided, take the first one
3934 pMinFrame
= pTmpFrame
;
3939 } while( bClientIterChanged
);
3941 if( pPos
&& pMinFrame
&& pMinFrame
->IsTextFrame() )
3943 SwTextFrame
* pAtPos(static_cast<SwTextFrame
*>(pMinFrame
)->GetFrameAtPos(*pPos
));
3944 if (!pViewPosAndCalcFrame
)
3948 TextFrameIndex
nPos(pAtPos
->MapModelToViewPos(*pPos
));
3949 SwPageFrame
const*const pPage(pAtPos
->getRootFrame()->GetPageAtPos(
3950 pViewPosAndCalcFrame
->first
, nullptr, true));
3951 SwFrame
* pOnPage(pAtPos
); // if all else fails return first one
3952 ++nPos
; // follow field portions are on follow frames that have mnOffset
3953 // already incremented past the field, need to check that index too
3954 while (pAtPos
&& pAtPos
->GetOffset() <= nPos
)
3956 if (pAtPos
->getFrameArea().Contains(pViewPosAndCalcFrame
->first
))
3960 if (pAtPos
->FindPageFrame() == pPage
)
3964 pAtPos
= pAtPos
->GetFollow();
3972 bool IsExtraData( const SwDoc
*pDoc
)
3974 const SwLineNumberInfo
&rInf
= pDoc
->GetLineNumberInfo();
3975 if (rInf
.IsPaintLineNumbers() ||
3976 rInf
.IsCountInFlys() ||
3977 (static_cast<sal_Int16
>(SwModule::get()->GetRedlineMarkPos()) != text::HoriOrientation::NONE
&&
3978 !pDoc
->getIDocumentRedlineAccess().GetRedlineTable().empty()))
3983 const SwEditShell
* pSh
= pDoc
->GetEditShell();
3984 const SwViewOption
* pViewOptions
= pSh
? pSh
->GetViewOptions() : nullptr;
3985 return pViewOptions
&& pViewOptions
->IsShowOutlineContentVisibilityButton();
3988 // OD 22.09.2003 #110978#
3989 SwRect
SwPageFrame::PrtWithoutHeaderAndFooter() const
3991 SwRect
aPrtWithoutHeaderFooter( getFramePrintArea() );
3992 aPrtWithoutHeaderFooter
.Pos() += getFrameArea().Pos();
3994 const SwFrame
* pLowerFrame
= Lower();
3995 while ( pLowerFrame
)
3997 // Note: independent on text direction page header and page footer are
3998 // always at top respectively at bottom of the page frame.
3999 if ( pLowerFrame
->IsHeaderFrame() )
4001 aPrtWithoutHeaderFooter
.AddTop( pLowerFrame
->getFrameArea().Height() );
4003 if ( pLowerFrame
->IsFooterFrame() )
4005 aPrtWithoutHeaderFooter
.AddBottom( - pLowerFrame
->getFrameArea().Height() );
4008 pLowerFrame
= pLowerFrame
->GetNext();
4011 return aPrtWithoutHeaderFooter
;
4014 /** method to determine the spacing values of a frame
4016 OD 2004-03-10 #i28701#
4017 OD 2009-08-28 #i102458#
4018 Add output parameter <obIsLineSpacingProportional>
4020 void GetSpacingValuesOfFrame( const SwFrame
& rFrame
,
4021 SwTwips
& onLowerSpacing
,
4022 SwTwips
& onLineSpacing
,
4023 bool& obIsLineSpacingProportional
,
4024 bool bIdenticalStyles
)
4026 if ( !rFrame
.IsFlowFrame() )
4033 const SvxULSpaceItem
& rULSpace
= rFrame
.GetAttrSet()->GetULSpace();
4034 // check contextual spacing if the style of actual and next paragraphs are identical
4035 if (bIdenticalStyles
)
4036 onLowerSpacing
= (rULSpace
.GetContext() ? 0 : rULSpace
.GetLower());
4038 onLowerSpacing
= rULSpace
.GetLower();
4041 obIsLineSpacingProportional
= false;
4042 if ( rFrame
.IsTextFrame() )
4044 onLineSpacing
= static_cast<const SwTextFrame
&>(rFrame
).GetLineSpace();
4045 obIsLineSpacingProportional
=
4046 onLineSpacing
!= 0 &&
4047 static_cast<const SwTextFrame
&>(rFrame
).GetLineSpace( true ) == 0;
4050 OSL_ENSURE( onLowerSpacing
>= 0 && onLineSpacing
>= 0,
4051 "<GetSpacingValuesOfFrame(..)> - spacing values aren't positive!" );
4055 /// get the content of the table cell, skipping content from nested tables
4056 const SwContentFrame
* GetCellContent( const SwLayoutFrame
& rCell
)
4058 const SwContentFrame
* pContent
= rCell
.ContainsContent();
4059 const SwTabFrame
* pTab
= rCell
.FindTabFrame();
4061 while ( pContent
&& rCell
.IsAnLower( pContent
) )
4063 const SwTabFrame
* pTmpTab
= pContent
->FindTabFrame();
4064 if ( pTmpTab
!= pTab
)
4066 SwFrame
const*const pTmp
= pTmpTab
->FindLastContentOrTable();
4069 pContent
= pTmp
->FindNextCnt();
4082 SwDeletionChecker::SwDeletionChecker(const SwFrame
* pFrame
)
4085 ? pFrame
->IsTextFrame()
4086 // sw_redlinehide: GetDep() may be a member of SwTextFrame!
4087 ? static_cast<SwTextFrame
const*>(pFrame
)->GetTextNodeFirst()
4088 : const_cast<SwFrame
*>(pFrame
)->GetDep()
4093 /// Can be used to check if a frame has been deleted
4094 bool SwDeletionChecker::HasBeenDeleted() const
4096 if ( !mpFrame
|| !mpRegIn
)
4099 SwIterator
<SwFrame
, sw::BroadcastingModify
, sw::IteratorMode::UnwrapMulti
> aIter(*mpRegIn
);
4100 SwFrame
* pLast
= aIter
.First();
4103 if ( pLast
== mpFrame
)
4105 pLast
= aIter
.Next();
4111 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */