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
= mpFrame
->FindPrev();
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() );
300 const bool bAnchoredAsChar
= pContact
->ObjAnchoredAsChar();
301 if ( !bAnchoredAsChar
)
303 // Notify object, which aren't anchored as-character:
305 // always notify objects, if frame position has changed
306 // or if the object is to-page|to-fly anchored.
308 pContact
->ObjAnchoredAtPage() ||
309 pContact
->ObjAnchoredAtFly() )
313 // assure that to-fly anchored Writer fly frames are
314 // registered at the correct page frame, if frame
315 // position has changed.
316 if ( bAbsP
&& pContact
->ObjAnchoredAtFly() &&
317 pObj
->DynCastFlyFrame() != nullptr )
319 // determine to-fly anchored Writer fly frame
320 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrame
*>(pObj
);
321 // determine page frame of to-fly anchored
323 SwPageFrame
* pFlyPageFrame
= pFlyFrame
->FindPageFrame();
324 // determine page frame, if needed.
327 pPageFrame
= mpFrame
->FindPageFrame();
329 if ( pPageFrame
!= pFlyPageFrame
)
331 OSL_ENSURE( pFlyPageFrame
, "~SwFrameNotify: Fly from Nowhere" );
333 pFlyPageFrame
->MoveFly( pFlyFrame
, pPageFrame
);
335 pPageFrame
->AppendFlyToPage( pFlyFrame
);
339 // otherwise the objects are notified in dependence to
340 // its positioning and alignment
343 const SwFormatVertOrient
& rVert
=
344 pContact
->GetFormat()->GetVertOrient();
345 if ( ( rVert
.GetVertOrient() == text::VertOrientation::CENTER
||
346 rVert
.GetVertOrient() == text::VertOrientation::BOTTOM
||
347 rVert
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
) &&
348 ( bChgHeight
|| bPrtHeight
) )
354 const SwFormatHoriOrient
& rHori
=
355 pContact
->GetFormat()->GetHoriOrient();
356 if ( ( rHori
.GetHoriOrient() != text::HoriOrientation::NONE
||
357 rHori
.GetRelationOrient()== text::RelOrientation::PRINT_AREA
||
358 rHori
.GetRelationOrient()== text::RelOrientation::FRAME
) &&
359 ( bChgWidth
|| bPrtWidth
|| bChgFlyBasePos
) )
366 else if ( bPrtWidth
)
368 // Notify as-character anchored objects, if printing area
369 // width has changed.
374 // perform notification via the corresponding invalidations
377 if ( auto pFlyFrame
= pObj
->DynCastFlyFrame() )
380 pFlyFrame
->InvalidateSize_();
381 // #115759# - no invalidation of
382 // position for as-character anchored objects.
383 if ( !bAnchoredAsChar
)
385 pFlyFrame
->InvalidatePos_();
387 pFlyFrame
->Invalidate_();
389 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pObj
) != nullptr )
391 // #115759# - no invalidation of
392 // position for as-character anchored objects.
393 if ( !bAnchoredAsChar
)
395 pObj
->InvalidateObjPos();
400 OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - unknown anchored object type." );
406 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
407 else if( mpFrame
->IsTextFrame() && mbValidSize
!= mpFrame
->isFrameAreaSizeValid() )
409 SwRootFrame
*pRootFrame
= mpFrame
->getRootFrame();
410 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
411 pRootFrame
->GetCurrShell() )
413 pRootFrame
->GetCurrShell()->Imp()->InvalidateAccessibleFrameContent( mpFrame
);
418 // #i9046# Automatic frame width
419 SwFlyFrame
* pFly
= nullptr;
420 // #i35879# Do not trust the inf flags. pFrame does not
421 // necessarily have to have an upper!
422 if ( mpFrame
->IsFlyFrame() || nullptr == ( pFly
= mpFrame
->ImplFindFlyFrame() ))
426 // no invalidation of columned Writer fly frames, because automatic
427 // width doesn't make sense for such Writer fly frames.
428 if ( !pFly
->Lower() || pFly
->Lower()->IsColumnFrame() )
431 const SwFormatFrameSize
&rFrameSz
= pFly
->GetFormat()->GetFrameSize();
433 // This could be optimized. Basically the fly frame only has to
434 // be invalidated, if the first line of pFrame (if pFrame is a content
435 // frame, for other frame types it's the print area) has changed its
436 // size and pFrame was responsible for the current width of pFly. On
437 // the other hand, this is only rarely used and re-calculation of
438 // the fly frame does not cause too much trouble. So we keep it this
440 if ( SwFrameSize::Fixed
!= rFrameSz
.GetWidthSizeType() )
442 // #i50668#, #i50998# - invalidation of position
443 // of as-character anchored fly frames not needed and can cause
445 if ( dynamic_cast<const SwFlyInContentFrame
*>( pFly
) == nullptr )
447 pFly
->InvalidatePos();
449 pFly
->InvalidateSize();
453 SwLayNotify::SwLayNotify( SwLayoutFrame
*pLayFrame
) :
454 SwFrameNotify( pLayFrame
),
455 m_bLowersComplete( false )
459 // OD 2004-05-11 #i28701# - local method to invalidate the position of all
460 // frames inclusive its floating screen objects, which are lowers of the given
462 static void lcl_InvalidatePosOfLowers( SwLayoutFrame
& _rLayoutFrame
)
464 if( _rLayoutFrame
.IsFlyFrame() && _rLayoutFrame
.GetDrawObjs() )
466 _rLayoutFrame
.InvalidateObjs( false );
469 SwFrame
* pLowerFrame
= _rLayoutFrame
.Lower();
470 while ( pLowerFrame
)
472 pLowerFrame
->InvalidatePos();
473 if ( pLowerFrame
->IsTextFrame() )
475 static_cast<SwTextFrame
*>(pLowerFrame
)->Prepare( PrepareHint::FramePositionChanged
);
477 else if ( pLowerFrame
->IsTabFrame() )
479 pLowerFrame
->InvalidatePrt();
482 pLowerFrame
->InvalidateObjs( false );
484 pLowerFrame
= pLowerFrame
->GetNext();
488 void SwLayNotify::ImplDestroy()
490 SwLayoutFrame
*pLay
= static_cast<SwLayoutFrame
*>(mpFrame
);
491 SwRectFnSet
aRectFnSet(pLay
);
492 bool bNotify
= false;
493 if ( pLay
->getFramePrintArea().SSize() != maPrt
.SSize() )
495 if ( !IsLowersComplete() )
499 if ( pLay
->IsRowFrame() )
502 tools::Long nNew
= aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
503 if( nNew
!= aRectFnSet
.GetHeight(maPrt
) )
504 static_cast<SwRowFrame
*>(pLay
)->AdjustCells( nNew
, true);
505 if( aRectFnSet
.GetWidth(pLay
->getFramePrintArea())
506 != aRectFnSet
.GetWidth(maPrt
) )
507 static_cast<SwRowFrame
*>(pLay
)->AdjustCells( 0, false );
511 //Proportional adoption of the internal.
512 //1. If the formatted is no Fly
513 //2. If he contains no columns
514 //3. If the Fly has a fixed height and the columns
516 // Hoehe danebenliegen.
517 //4. Never at SectionFrames.
519 if( pLay
->IsFlyFrame() )
523 bLow
= !pLay
->Lower()->IsColumnFrame() ||
524 aRectFnSet
.GetHeight(pLay
->Lower()->getFrameArea())
525 != aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
530 else if( pLay
->IsSctFrame() )
534 if( pLay
->Lower()->IsColumnFrame() && pLay
->Lower()->GetNext() )
535 bLow
= pLay
->Lower()->getFrameArea().Height() != pLay
->getFramePrintArea().Height();
537 bLow
= pLay
->getFramePrintArea().Width() != maPrt
.Width();
542 else if( pLay
->IsFooterFrame() && !pLay
->HasFixSize() )
543 bLow
= pLay
->getFramePrintArea().Width() != maPrt
.Width();
549 pLay
->ChgLowersProp( maPrt
.SSize() );
551 // If the PrtArea has been extended, it might be possible that the chain of parts
552 // can take another frame. As a result, the "possible right one" needs to be
553 // invalidated. This only pays off if this or its Uppers are moveable sections.
554 // A PrtArea has been extended if width or height are larger than before.
555 if ( (pLay
->getFramePrintArea().Height() > maPrt
.Height() ||
556 pLay
->getFramePrintArea().Width() > maPrt
.Width()) &&
557 (pLay
->IsMoveable() || pLay
->IsFlyFrame()) )
559 SwFrame
*pTmpFrame
= pLay
->Lower();
560 if ( pTmpFrame
&& pTmpFrame
->IsFlowFrame() )
562 while ( pTmpFrame
->GetNext() )
563 pTmpFrame
= pTmpFrame
->GetNext();
564 pTmpFrame
->InvalidateNextPos();
569 //EXPENSIVE!! But how we do it more elegant?
571 pLay
->InvaPercentLowers( pLay
->getFramePrintArea().Height() - maPrt
.Height() );
573 if ( pLay
->IsTabFrame() )
574 //So that _only_ the shadow is drawn while resizing.
575 static_cast<SwTabFrame
*>(pLay
)->SetComplete();
578 const SwViewShell
*pSh
= pLay
->getRootFrame()->GetCurrShell();
579 if( !( pSh
&& pSh
->GetViewOptions()->getBrowseMode() ) ||
580 !(pLay
->GetType() & (SwFrameType::Body
| SwFrameType::Page
)) )
581 //Thereby the subordinates are retouched clean.
582 //Example problem: Take the Flys with the handles and downsize.
583 //Not for body and page, otherwise it flickers when loading HTML.
584 pLay
->SetCompletePaint();
587 //Notify Lower if the position has changed.
588 const bool bPrtPos
= aRectFnSet
.PosDiff( maPrt
, pLay
->getFramePrintArea() );
589 const bool bPos
= bPrtPos
|| aRectFnSet
.PosDiff( maFrame
, pLay
->getFrameArea() );
590 const bool bSize
= pLay
->getFrameArea().SSize() != maFrame
.SSize();
592 if ( bPos
&& pLay
->Lower() && !IsLowersComplete() )
594 pLay
->Lower()->InvalidatePos();
595 SwFootnoteFrame
* pFtnFrame
= pLay
->Lower()->IsFootnoteFrame() ?
596 static_cast<SwFootnoteFrame
*>(pLay
->Lower()) : nullptr;
597 SwFrame
* pFtnLower
= pFtnFrame
? pFtnFrame
->Lower() : nullptr;
599 pFtnLower
->InvalidatePos();
603 pLay
->SetCompletePaint();
605 //Inform the Follower if the SSize has changed.
608 if( pLay
->GetNext() )
610 if ( pLay
->GetNext()->IsLayoutFrame() )
611 pLay
->GetNext()->InvalidatePos_();
613 pLay
->GetNext()->InvalidatePos();
615 else if( pLay
->IsSctFrame() )
616 pLay
->InvalidateNextPos();
618 if ( !IsLowersComplete() &&
619 !(pLay
->GetType()&(SwFrameType::Fly
|SwFrameType::Section
) &&
620 pLay
->Lower() && pLay
->Lower()->IsColumnFrame()) &&
622 !(pLay
->GetType() & (SwFrameType::Row
|SwFrameType::Tab
|SwFrameType::FtnCont
|SwFrameType::Page
|SwFrameType::Root
)))
624 // #i44016# - force unlock of position of lower objects.
625 // #i43913# - no unlock of position of objects,
626 // if <pLay> is a cell frame, and its table frame resp. its parent table
628 // #i47458# - force unlock of position of lower objects,
629 // only if position of layout frame has changed.
630 bool bUnlockPosOfObjs( bPos
);
631 if ( bUnlockPosOfObjs
&& pLay
->IsCellFrame() )
633 SwTabFrame
* pTabFrame( pLay
->FindTabFrame() );
635 ( pTabFrame
->IsJoinLocked() ||
636 ( pTabFrame
->IsFollow() &&
637 pTabFrame
->FindMaster()->IsJoinLocked() ) ) )
639 bUnlockPosOfObjs
= false;
642 // #i49383# - check for footnote frame, if unlock
643 // of position of lower objects is allowed.
644 else if ( bUnlockPosOfObjs
&& pLay
->IsFootnoteFrame() )
646 bUnlockPosOfObjs
= static_cast<SwFootnoteFrame
*>(pLay
)->IsUnlockPosOfLowerObjs();
648 // #i51303# - no unlock of object positions for sections
649 else if ( bUnlockPosOfObjs
&& pLay
->IsSctFrame() )
651 bUnlockPosOfObjs
= false;
653 pLay
->NotifyLowerObjs( bUnlockPosOfObjs
);
655 if ( bPos
&& pLay
->IsFootnoteFrame() && pLay
->Lower() )
657 // OD 2004-05-11 #i28701#
658 ::lcl_InvalidatePosOfLowers( *pLay
);
660 if( ( bPos
|| bSize
) && pLay
->IsFlyFrame() && static_cast<SwFlyFrame
*>(pLay
)->GetAnchorFrame()
661 && static_cast<SwFlyFrame
*>(pLay
)->GetAnchorFrame()->IsFlyFrame() )
662 static_cast<SwFlyFrame
*>(pLay
)->AnchorFrame()->InvalidateSize();
665 SwLayNotify::~SwLayNotify()
667 suppress_fun_call_w_exception(ImplDestroy());
670 SwFlyNotify::SwFlyNotify( SwFlyFrame
*pFlyFrame
) :
671 SwLayNotify( pFlyFrame
),
672 // #115759# - keep correct page frame - the page frame
673 // the Writer fly frame is currently registered at.
674 m_pOldPage( pFlyFrame
->GetPageFrame() ),
675 m_aFrameAndSpace( pFlyFrame
->GetObjRectWithSpaces() )
679 void SwFlyNotify::ImplDestroy()
681 SwFlyFrame
*pFly
= static_cast<SwFlyFrame
*>(mpFrame
);
682 if ( pFly
->IsNotifyBack() )
684 SwViewShell
*pSh
= pFly
->getRootFrame()->GetCurrShell();
685 SwViewShellImp
*pImp
= pSh
? pSh
->Imp() : nullptr;
686 if ( !pImp
|| !pImp
->IsAction() || !pImp
->GetLayAction().IsAgain() )
688 //If in the LayAction the IsAgain is set it can be
689 //that the old page is destroyed in the meantime!
690 ::Notify( pFly
, m_pOldPage
, m_aFrameAndSpace
, &maPrt
);
691 // #i35640# - additional notify anchor text frame,
692 // if Writer fly frame has changed its page
693 if ( pFly
->GetAnchorFrame()->IsTextFrame() &&
694 pFly
->GetPageFrame() != m_pOldPage
)
696 pFly
->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave
);
699 pFly
->ResetNotifyBack();
701 if (pFly
->IsForceNotifyNewBackground())
703 pFly
->NotifyBackground(pFly
->FindPageFrame(), pFly
->GetObjRectWithSpaces(), PrepareHint::FlyFrameArrive
);
704 pFly
->SetForceNotifyNewBackground(false);
707 //Have the size or the position changed,
708 //so should the view know this.
709 SwRectFnSet
aRectFnSet(pFly
);
710 const bool bPosChgd
= aRectFnSet
.PosDiff( maFrame
, pFly
->getFrameArea() );
711 const bool bFrameChgd
= pFly
->getFrameArea().SSize() != maFrame
.SSize();
712 const bool bPrtChgd
= maPrt
!= pFly
->getFramePrintArea();
713 if ( bPosChgd
|| bFrameChgd
|| bPrtChgd
)
715 pFly
->NotifyDrawObj();
717 if ( bPosChgd
&& maFrame
.Pos().X() != FAR_AWAY
)
719 // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
720 // reason: New positioning and alignment (e.g. to-paragraph anchored,
721 // but aligned at page) are introduced.
722 // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
723 // floating screen objects by calling method <SwLayoutFrame::NotifyLowerObjs()>.
725 if ( pFly
->IsFlyAtContentFrame() )
727 SwFrame
*pNxt
= pFly
->AnchorFrame()->FindNext();
730 pNxt
->InvalidatePos();
731 if (!pNxt
->IsSctFrame())
735 // invalidating pos of a section frame doesn't have much
736 // effect, so try again with its lower
737 pNxt
= static_cast<SwSectionFrame
*>(pNxt
)->Lower();
741 // #i26945# - notify anchor.
742 // Needed for negative positioned Writer fly frames
743 if ( pFly
->GetAnchorFrame()->IsTextFrame() )
745 pFly
->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave
);
749 // OD 2004-05-13 #i28701#
750 // #i45180# - no adjustment of layout process flags and
751 // further notifications/invalidations, if format is called by grow/shrink
752 if ( !pFly
->ConsiderObjWrapInfluenceOnObjPos() )
754 if (pFly
->IsFlyFreeFrame())
756 if (static_cast<SwFlyFreeFrame
*>(pFly
)->IsNoMoveOnCheckClip())
760 // #i54138# - suppress restart of the layout process
761 // on changed frame height.
762 // Note: It doesn't seem to be necessary and can cause layout loops.
765 // indicate a restart of the layout process
766 pFly
->SetRestartLayoutProcess( true );
771 pFly
->LockPosition();
774 if ( pFly
->ConsiderForTextWrap() )
777 // indicate that object has to be considered for text wrap
778 pFly
->SetConsiderForTextWrap( true );
779 // invalidate 'background' in order to allow its 'background'
780 // to wrap around it.
781 pFly
->NotifyBackground( pFly
->GetPageFrame(),
782 pFly
->GetObjRectWithSpaces(),
783 PrepareHint::FlyFrameArrive
);
784 // invalidate position of anchor frame in order to force
785 // a re-format of the anchor frame, which also causes a
786 // re-format of the invalid previous frames of the anchor frame.
787 pFly
->AnchorFrame()->InvalidatePos();
790 SwFlyNotify::~SwFlyNotify()
792 suppress_fun_call_w_exception(ImplDestroy());
795 SwContentNotify::SwContentNotify( SwContentFrame
*pContentFrame
) :
796 SwFrameNotify( pContentFrame
),
797 // OD 08.01.2004 #i11859#
798 mbChkHeightOfLastLine( false ),
799 mnHeightOfLastLine( 0 ),
800 // OD 2004-02-26 #i25029#
801 mbInvalidatePrevPrtArea( false ),
802 mbBordersJoinedWithPrev( false )
804 // OD 08.01.2004 #i11859#
805 if ( !pContentFrame
->IsTextFrame() )
808 SwTextFrame
* pTextFrame
= static_cast<SwTextFrame
*>(pContentFrame
);
809 if (!pTextFrame
->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::OLD_LINE_SPACING
))
811 const SvxLineSpacingItem
&rSpace
= pTextFrame
->GetAttrSet()->GetLineSpacing();
812 if ( rSpace
.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
)
814 mbChkHeightOfLastLine
= true;
815 mnHeightOfLastLine
= pTextFrame
->GetHeightOfLastLine();
820 void SwContentNotify::ImplDestroy()
822 SwContentFrame
*pCnt
= static_cast<SwContentFrame
*>(mpFrame
);
823 if ( bSetCompletePaintOnInvalidate
)
824 pCnt
->SetCompletePaint();
826 SwRectFnSet
aRectFnSet(pCnt
);
827 if ( pCnt
->IsInTab() && ( aRectFnSet
.PosDiff( pCnt
->getFrameArea(), maFrame
) ||
828 pCnt
->getFrameArea().SSize() != maFrame
.SSize()))
830 SwLayoutFrame
* pCell
= pCnt
->GetUpper();
831 while( !pCell
->IsCellFrame() && pCell
->GetUpper() )
832 pCell
= pCell
->GetUpper();
833 OSL_ENSURE( pCell
->IsCellFrame(), "Where's my cell?" );
834 if ( text::VertOrientation::NONE
!= pCell
->GetFormat()->GetVertOrient().GetVertOrient() )
835 pCell
->InvalidatePrt(); //for the vertical align.
838 // OD 2004-02-26 #i25029#
839 if ( mbInvalidatePrevPrtArea
&& mbBordersJoinedWithPrev
&&
840 pCnt
->IsTextFrame() &&
841 !pCnt
->IsFollow() && !pCnt
->GetIndPrev() )
843 // determine previous frame
844 SwFrame
* pPrevFrame
= pCnt
->FindPrev();
845 // skip empty section frames and hidden text frames
847 while ( pPrevFrame
&&
848 ( ( pPrevFrame
->IsSctFrame() &&
849 !static_cast<SwSectionFrame
*>(pPrevFrame
)->GetSection() ) ||
850 ( pPrevFrame
->IsTextFrame() &&
851 static_cast<SwTextFrame
*>(pPrevFrame
)->IsHiddenNow() ) ) )
853 pPrevFrame
= pPrevFrame
->FindPrev();
857 // Invalidate printing area of found previous frame
860 if ( pPrevFrame
->IsSctFrame() )
862 if ( pCnt
->IsInSct() )
864 // Note: found previous frame is a section frame and
865 // <pCnt> is also inside a section.
866 // Thus due to <mbBordersJoinedWithPrev>,
867 // <pCnt> had joined its borders/shadow with the
868 // last content of the found section.
869 // Invalidate printing area of last content in found section.
870 SwFrame
* pLstContentOfSctFrame
=
871 static_cast<SwSectionFrame
*>(pPrevFrame
)->FindLastContent();
872 if ( pLstContentOfSctFrame
)
874 pLstContentOfSctFrame
->InvalidatePrt();
880 pPrevFrame
->InvalidatePrt();
885 const bool bFirst
= aRectFnSet
.GetWidth(maFrame
) == 0;
887 if ( pCnt
->IsNoTextFrame() )
889 //Active PlugIn's or OLE-Objects should know something of the change
890 //thereby they move their window appropriate.
891 SwViewShell
*pSh
= pCnt
->getRootFrame()->GetCurrShell();
894 SwOLENode
*const pNd(static_cast<SwNoTextFrame
*>(pCnt
)->GetNode()->GetOLENode());
895 if (nullptr != pNd
&&
896 (pNd
->GetOLEObj().IsOleRef() ||
897 pNd
->IsOLESizeInvalid()) )
899 const bool bNoTextFramePrtAreaChanged
=
900 ( maPrt
.SSize().Width() != 0 &&
901 maPrt
.SSize().Height() != 0 ) &&
902 maPrt
.SSize() != pCnt
->getFramePrintArea().SSize();
903 OSL_ENSURE( pCnt
->IsInFly(), "OLE not in FlyFrame" );
904 SwFlyFrame
*pFly
= pCnt
->FindFlyFrame();
905 svt::EmbeddedObjectRef
& xObj
= pNd
->GetOLEObj().GetObject();
906 SwFEShell
*pFESh
= nullptr;
907 for(SwViewShell
& rCurrentShell
: pSh
->GetRingContainer())
908 { if ( dynamic_cast<const SwCursorShell
*>( &rCurrentShell
) != nullptr )
910 pFESh
= static_cast<SwFEShell
*>(&rCurrentShell
);
911 // #108369#: Here used to be the condition if (!bFirst).
912 // I think this should mean "do not call CalcAndSetScale"
913 // if the frame is formatted for the first time.
914 // Unfortunately this is not valid anymore since the
915 // SwNoTextFrame already gets a width during CalcLowerPreps.
916 // Nevertheless, the indention of !bFirst seemed to be
917 // to assure that the OLE objects have already been notified
918 // if necessary before calling CalcAndSetScale.
919 // So I replaced !bFirst by !IsOLESizeInvalid. There is
920 // one additional problem specific to the word import:
921 // The layout is calculated _before_ calling PrtOLENotify,
922 // and the OLE objects are not invalidated during import.
923 // Therefore I added the condition !IsUpdateExpField,
924 // have a look at the occurrence of CalcLayout in
926 if ( !pNd
->IsOLESizeInvalid() &&
927 !pSh
->GetDoc()->getIDocumentState().IsUpdateExpField() )
928 pFESh
->CalcAndSetScale( xObj
,
929 &pFly
->getFramePrintArea(), &pFly
->getFrameArea(),
930 bNoTextFramePrtAreaChanged
);
934 if ( pFESh
&& pNd
->IsOLESizeInvalid() )
936 pNd
->SetOLESizeInvalid( false );
937 pFESh
->CalcAndSetScale( xObj
); // create client
940 // ditto animated graphics
941 if ( getFrameArea().HasArea() && static_cast<SwNoTextFrame
*>(pCnt
)->HasAnimation() )
943 static_cast<SwNoTextFrame
*>(pCnt
)->StopAnimation();
944 pSh
->InvalidateWindows( getFrameArea() );
951 pCnt
->SetRetouche(); //fix(13870)
953 SwDoc
& rDoc
= pCnt
->IsTextFrame()
954 ? static_cast<SwTextFrame
*>(pCnt
)->GetDoc()
955 : static_cast<SwNoTextFrame
*>(pCnt
)->GetNode()->GetDoc();
956 if ( !rDoc
.GetSpzFrameFormats()->empty() &&
957 rDoc
.DoesContainAtPageObjWithContentAnchor() && !rDoc
.getIDocumentState().IsNewDoc() )
959 // If certain import filters for foreign file format import
960 // AT_PAGE anchored objects, the corresponding page number is
961 // typically not known. In this case the content position is
962 // stored at which the anchored object is found in the
963 // imported document.
964 // When this content is formatted it is the time at which
965 // the page is known. Thus, this data can be corrected now.
967 const SwPageFrame
*pPage
= nullptr;
968 for(sw::SpzFrameFormat
* pFormat
: *rDoc
.GetSpzFrameFormats())
970 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
971 if ( RndStdIds::FLY_AT_PAGE
!= rAnch
.GetAnchorId() ||
972 rAnch
.GetAnchorNode() == nullptr )
977 if (FrameContainsNode(*pCnt
, rAnch
.GetAnchorNode()->GetIndex()))
979 OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - to page anchored object with content position." );
982 pPage
= pCnt
->FindPageFrame();
984 SwFormatAnchor
aAnch( rAnch
);
985 aAnch
.SetAnchor( nullptr );
986 aAnch
.SetPageNum( pPage
->GetPhyPageNum() );
987 pFormat
->SetFormatAttr( aAnch
);
988 if ( RES_DRAWFRMFMT
!= pFormat
->Which() )
990 pFormat
->MakeFrames();
997 // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
998 // if height of last line has changed.
999 if ( pCnt
->IsTextFrame() && mbChkHeightOfLastLine
)
1001 if ( mnHeightOfLastLine
!= static_cast<SwTextFrame
*>(pCnt
)->GetHeightOfLastLine() )
1003 pCnt
->InvalidateNextPrtArea();
1008 if ( pCnt
->IsTextFrame() && aRectFnSet
.PosDiff( maFrame
, pCnt
->getFrameArea() ) )
1010 pCnt
->InvalidateObjs();
1013 // #i43255# - move code to invalidate at-character
1014 // anchored objects due to a change of its anchor character from
1015 // method <SwTextFrame::Format(..)>.
1016 if ( !pCnt
->IsTextFrame() )
1019 SwTextFrame
* pMasterFrame
= pCnt
->IsFollow()
1020 ? static_cast<SwTextFrame
*>(pCnt
)->FindMaster()
1021 : static_cast<SwTextFrame
*>(pCnt
);
1022 if ( pMasterFrame
&& !pMasterFrame
->IsFlyLock() &&
1023 pMasterFrame
->GetDrawObjs() )
1025 SwSortedObjs
* pObjs
= pMasterFrame
->GetDrawObjs();
1026 for (SwAnchoredObject
* pAnchoredObj
: *pObjs
)
1028 if ( pAnchoredObj
->GetFrameFormat().GetAnchor().GetAnchorId()
1029 == RndStdIds::FLY_AT_CHAR
)
1031 pAnchoredObj
->CheckCharRectAndTopOfLine( !pMasterFrame
->IsEmpty() );
1037 SwContentNotify::~SwContentNotify()
1039 suppress_fun_call_w_exception(ImplDestroy());
1042 // note this *cannot* be static because it's a friend
1043 void AppendObj(SwFrame
*const pFrame
, SwPageFrame
*const pPage
, SwFrameFormat
*const pFormat
, const SwFormatAnchor
& rAnch
)
1045 const bool bFlyAtFly
= rAnch
.GetAnchorId() == RndStdIds::FLY_AT_FLY
; // LAYER_IMPL
1046 //Is a frame or a SdrObject described?
1047 const bool bSdrObj
= RES_DRAWFRMFMT
== pFormat
->Which();
1048 // OD 23.06.2003 #108784# - append also drawing objects anchored
1050 const bool bDrawObjInContent
= bSdrObj
&&
1051 (rAnch
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
);
1054 (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_PARA
) ||
1055 (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
) ||
1056 bDrawObjInContent
) )
1059 SdrObject
* pSdrObj
= nullptr;
1060 if ( bSdrObj
&& nullptr == (pSdrObj
= pFormat
->FindSdrObject()) )
1062 OSL_ENSURE( !bSdrObj
, "DrawObject not found." );
1063 pFormat
->GetDoc()->DelFrameFormat( pFormat
);
1068 if ( !pSdrObj
->getSdrPageFromSdrObject() )
1070 pFormat
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
1071 InsertObject(pSdrObj
, pSdrObj
->GetOrdNumDirect());
1074 SwDrawContact
* pNew
=
1075 static_cast<SwDrawContact
*>(GetUserCall( pSdrObj
));
1076 if ( !pNew
->GetAnchorFrame() )
1078 pFrame
->AppendDrawObj( *(pNew
->GetAnchoredObj( nullptr )) );
1080 // OD 19.06.2003 #108784# - add 'virtual' drawing object,
1081 // if necessary. But control objects have to be excluded.
1082 else if ( !::CheckControlLayer( pSdrObj
) &&
1083 pNew
->GetAnchorFrame() != pFrame
&&
1084 !pNew
->GetDrawObjectByAnchorFrame( *pFrame
) )
1086 SwDrawVirtObj
* pDrawVirtObj
= pNew
->AddVirtObj(*pFrame
);
1087 pFrame
->AppendDrawObj( *(pNew
->GetAnchoredObj( pDrawVirtObj
)) );
1089 pDrawVirtObj
->ActionChanged();
1096 pFly
= new SwFlyLayFrame( static_cast<SwFlyFrameFormat
*>(pFormat
), pFrame
, pFrame
);
1098 pFly
= new SwFlyAtContentFrame( static_cast<SwFlyFrameFormat
*>(pFormat
), pFrame
, pFrame
);
1100 pFrame
->AppendFly( pFly
);
1103 ::RegistFlys( pPage
, pFly
);
1107 static bool IsShown(SwNodeOffset
const nIndex
,
1108 const SwFormatAnchor
& rAnch
,
1109 std::vector
<sw::Extent
>::const_iterator
const*const pIter
,
1110 std::vector
<sw::Extent
>::const_iterator
const*const pEnd
,
1111 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
1113 assert(!pIter
|| *pIter
== *pEnd
|| (*pIter
)->pNode
->GetIndex() == nIndex
);
1114 SwNode
* pAnchorNode
= rAnch
.GetAnchorNode();
1115 if (pAnchorNode
->GetIndex() != nIndex
)
1119 if (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_PARA
)
1121 return pIter
== nullptr // not merged
1122 || pIter
!= pEnd
// at least one char visible in node
1123 || !IsSelectFrameAnchoredAtPara(*rAnch
.GetContentAnchor(),
1124 SwPosition(*pFirstNode
, 0),
1125 SwPosition(*pLastNode
, pLastNode
->Len()));
1129 // note: frames are not sorted by anchor position.
1133 assert(rAnch
.GetAnchorId() != RndStdIds::FLY_AT_FLY
);
1134 if (*pIter
== *pEnd
&& rAnch
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
)
1135 { // tdf#149595 special case - it *could* be shown if first == last
1136 return !IsDestroyFrameAnchoredAtChar(*rAnch
.GetContentAnchor(),
1137 SwPosition(*pFirstNode
, 0),
1138 SwPosition(*pLastNode
, pLastNode
->Len()));
1140 for (auto iter
= *pIter
; iter
!= *pEnd
; ++iter
)
1142 assert(iter
->nStart
!= iter
->nEnd
); // TODO possible?
1143 assert(iter
->pNode
->GetIndex() == nIndex
);
1144 if (rAnch
.GetAnchorContentOffset() < iter
->nStart
)
1148 if (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
)
1150 // if there is an extent then obviously the node was not
1152 // show if start <= pos <= end
1153 // *or* if first-node/0 *and* not StartOfSection
1154 // *or* if last-node/Len *and* not EndOfSection
1156 // first determine the extent to compare to, then
1157 // construct start/end positions for the deletion *before* the
1158 // extent and compare once.
1159 // the interesting corner cases are on the edge of the extent!
1160 // no need to check for > the last extent because those
1161 // are never visible.
1162 if (rAnch
.GetAnchorContentOffset() <= iter
->nEnd
)
1164 if (iter
->nStart
== 0)
1170 SwPosition
const start(
1172 ? *pFirstNode
// simplification
1174 iter
== *pIter
// first extent?
1175 ? iter
->pNode
== pFirstNode
1176 ? 0 // at start of 1st node
1177 : pFirstNode
->Len() // previous node; simplification but should get right result
1178 : (iter
-1)->nEnd
); // previous extent
1179 SwPosition
const end(*iter
->pNode
, iter
->nStart
);
1180 return !IsDestroyFrameAnchoredAtChar(*rAnch
.GetContentAnchor(), start
, end
);
1183 else if (iter
== *pEnd
- 1) // special case: after last extent
1185 if (iter
->nEnd
== iter
->pNode
->Len())
1187 return true; // special case: end of node
1191 SwPosition
const start(*iter
->pNode
, iter
->nEnd
);
1192 SwPosition
const end(
1193 *pLastNode
, // simplification
1194 iter
->pNode
== pLastNode
1195 ? iter
->pNode
->Len()
1197 return !IsDestroyFrameAnchoredAtChar(*rAnch
.GetContentAnchor(), start
, end
);
1203 assert(rAnch
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
);
1204 // for AS_CHAR obviously must be <
1205 if (rAnch
.GetAnchorContentOffset() < iter
->nEnd
)
1219 void RemoveHiddenObjsOfNode(SwTextNode
const& rNode
,
1220 std::vector
<sw::Extent
>::const_iterator
const*const pIter
,
1221 std::vector
<sw::Extent
>::const_iterator
const*const pEnd
,
1222 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
1224 std::vector
<SwFrameFormat
*> const & rFlys(rNode
.GetAnchoredFlys());
1225 for (SwFrameFormat
* pFrameFormat
: rFlys
)
1227 SwFormatAnchor
const& rAnchor
= pFrameFormat
->GetAnchor();
1228 if (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
1229 || rAnchor
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
)
1231 assert(rAnchor
.GetAnchorNode()->GetIndex() == rNode
.GetIndex());
1232 if (!IsShown(rNode
.GetIndex(), rAnchor
, pIter
, pEnd
, pFirstNode
, pLastNode
))
1234 pFrameFormat
->DelFrames();
1240 void AppendObjsOfNode(sw::FrameFormats
<sw::SpzFrameFormat
*> const*const pTable
, SwNodeOffset
const nIndex
,
1241 SwFrame
*const pFrame
, SwPageFrame
*const pPage
, SwDoc
*const pDoc
,
1242 std::vector
<sw::Extent
>::const_iterator
const*const pIter
,
1243 std::vector
<sw::Extent
>::const_iterator
const*const pEnd
,
1244 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
1246 #if OSL_DEBUG_LEVEL > 0
1247 std::vector
<SwFrameFormat
*> checkFormats
;
1248 for(auto pFormat
: *pTable
)
1250 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
1251 if ( rAnch
.GetAnchorNode() &&
1252 IsShown(nIndex
, rAnch
, pIter
, pEnd
, pFirstNode
, pLastNode
))
1254 checkFormats
.push_back( pFormat
);
1261 SwNode
const& rNode(*pDoc
->GetNodes()[nIndex
]);
1262 std::vector
<SwFrameFormat
*> const & rFlys(rNode
.GetAnchoredFlys());
1263 for (size_t it
= 0; it
!= rFlys
.size(); )
1265 SwFrameFormat
*const pFormat
= rFlys
[it
];
1266 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
1267 if ( rAnch
.GetAnchorNode() &&
1268 IsShown(nIndex
, rAnch
, pIter
, pEnd
, pFirstNode
, pLastNode
))
1270 #if OSL_DEBUG_LEVEL > 0
1271 std::vector
<SwFrameFormat
*>::iterator checkPos
= std::find( checkFormats
.begin(), checkFormats
.end(), pFormat
);
1272 assert( checkPos
!= checkFormats
.end());
1273 checkFormats
.erase( checkPos
);
1275 AppendObj(pFrame
, pPage
, pFormat
, rAnch
);
1280 #if OSL_DEBUG_LEVEL > 0
1281 assert( checkFormats
.empty());
1286 void AppendObjs(const sw::FrameFormats
<sw::SpzFrameFormat
*> *const pTable
, SwNodeOffset
const nIndex
,
1287 SwFrame
*const pFrame
, SwPageFrame
*const pPage
, SwDoc
*const pDoc
)
1289 if (pFrame
->IsTextFrame())
1291 SwTextFrame
const*const pTextFrame(static_cast<SwTextFrame
const*>(pFrame
));
1292 if (sw::MergedPara
const*const pMerged
= pTextFrame
->GetMergedPara())
1294 std::vector
<sw::Extent
>::const_iterator
iterFirst(pMerged
->extents
.begin());
1295 std::vector
<sw::Extent
>::const_iterator
iter(iterFirst
);
1296 SwTextNode
const* pNode(pMerged
->pFirstNode
);
1299 if (iter
== pMerged
->extents
.end()
1300 || iter
->pNode
!= pNode
)
1302 AppendObjsOfNode(pTable
, pNode
->GetIndex(), pFrame
, pPage
, pDoc
,
1303 &iterFirst
, &iter
, pMerged
->pFirstNode
, pMerged
->pLastNode
);
1304 SwNodeOffset
const until
= iter
== pMerged
->extents
.end()
1305 ? pMerged
->pLastNode
->GetIndex() + 1
1306 : iter
->pNode
->GetIndex();
1307 for (SwNodeOffset i
= pNode
->GetIndex() + 1; i
< until
; ++i
)
1309 // let's show at-para flys on nodes that contain start/end of
1310 // redline too, even if there's no text there
1311 SwNode
const*const pTmp(pNode
->GetNodes()[i
]);
1312 if (pTmp
->GetRedlineMergeFlag() == SwNode::Merge::NonFirst
)
1314 AppendObjsOfNode(pTable
, pTmp
->GetIndex(), pFrame
, pPage
, pDoc
, &iter
, &iter
, pMerged
->pFirstNode
, pMerged
->pLastNode
);
1317 if (iter
== pMerged
->extents
.end())
1321 pNode
= iter
->pNode
;
1328 return AppendObjsOfNode(pTable
, nIndex
, pFrame
, pPage
, pDoc
, nullptr, nullptr, nullptr, nullptr);
1333 return AppendObjsOfNode(pTable
, nIndex
, pFrame
, pPage
, pDoc
, nullptr, nullptr, nullptr, nullptr);
1337 bool IsAnchoredObjShown(SwTextFrame
const& rFrame
, SwFormatAnchor
const& rAnchor
)
1339 assert(rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
||
1340 rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
||
1341 rAnchor
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
);
1343 if (auto const pMergedPara
= rFrame
.GetMergedPara())
1346 SwNode
* pAnchorNode(rAnchor
.GetAnchorNode());
1347 auto iterFirst(pMergedPara
->extents
.cbegin());
1348 if (iterFirst
== pMergedPara
->extents
.end()
1349 && (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
1350 || rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
))
1352 ret
= (pAnchorNode
== pMergedPara
->pFirstNode
1353 && (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
1354 || rAnchor
.GetAnchorContentOffset() == 0))
1355 || (pAnchorNode
== pMergedPara
->pLastNode
1356 && (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
1357 || rAnchor
.GetAnchorContentOffset() == pMergedPara
->pLastNode
->Len()));
1359 auto iter(iterFirst
);
1360 SwTextNode
const* pNode(pMergedPara
->pFirstNode
);
1363 if (iter
== pMergedPara
->extents
.end()
1364 || iter
->pNode
!= pNode
)
1366 assert(pNode
->GetRedlineMergeFlag() != SwNode::Merge::Hidden
);
1367 if (pNode
== pAnchorNode
)
1369 ret
= IsShown(pNode
->GetIndex(), rAnchor
, &iterFirst
, &iter
,
1370 pMergedPara
->pFirstNode
, pMergedPara
->pLastNode
);
1373 if (iter
== pMergedPara
->extents
.end())
1377 pNode
= iter
->pNode
;
1378 if (pAnchorNode
->GetIndex() < pNode
->GetIndex())
1389 void AppendAllObjs(const sw::FrameFormats
<sw::SpzFrameFormat
*>* pTable
, const SwFrame
* pSib
)
1391 //Connecting of all Objects, which are described in the SpzTable with the
1394 boost::circular_buffer
<SwFrameFormat
*> vFormatsToConnect(pTable
->size());
1395 for(const auto& pFormat
: *pTable
)
1397 const auto& rAnch
= pFormat
->GetAnchor();
1398 // Formats can still remain, because we neither use character bound
1399 // frames nor objects which are anchored to character bounds.
1400 if ((rAnch
.GetAnchorId() != RndStdIds::FLY_AT_PAGE
) && (rAnch
.GetAnchorId() != RndStdIds::FLY_AS_CHAR
))
1402 const SwNode
* pAnchorNode
= rAnch
.GetAnchorNode();
1403 // formats in header/footer have no dependencies
1404 if(pAnchorNode
&& pFormat
->GetDoc()->IsInHeaderFooter(*pAnchorNode
))
1405 pFormat
->MakeFrames();
1407 vFormatsToConnect
.push_back(pFormat
);
1410 const SwRootFrame
* pRoot
= pSib
? pSib
->getRootFrame() : nullptr;
1411 const SwFrameFormat
* pFirstRequeued(nullptr);
1412 while(!vFormatsToConnect
.empty())
1414 SwFrameFormat
* pFormat
= vFormatsToConnect
.front();
1415 bool isConnected(false);
1416 pFormat
->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected
, pRoot
));
1419 pFormat
->MakeFrames();
1420 pFormat
->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected
, pRoot
));
1422 // do this *before* push_back! the circular_buffer can be "full"!
1423 vFormatsToConnect
.pop_front();
1426 if(pFirstRequeued
== pFormat
)
1427 // If nothing happens anymore we can stop.
1430 pFirstRequeued
= pFormat
;
1431 assert(!vFormatsToConnect
.full());
1432 vFormatsToConnect
.push_back(pFormat
);
1436 pFirstRequeued
= nullptr;
1443 void RecreateStartTextFrames(SwTextNode
& rNode
)
1445 std::vector
<SwTextFrame
*> frames
;
1446 SwIterator
<SwTextFrame
, SwTextNode
, sw::IteratorMode::UnwrapMulti
> aIter(rNode
);
1447 for (SwTextFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next())
1449 if (pFrame
->getRootFrame()->HasMergedParas())
1451 frames
.push_back(pFrame
);
1454 auto eMode(sw::FrameMode::Existing
);
1455 for (SwTextFrame
* pFrame
: frames
)
1457 // SplitNode could have moved the original frame to the start node
1458 // & created a new one on end, or could have created new frame on
1459 // start node... grab start node's frame and recreate MergedPara.
1460 SwTextNode
& rFirstNode(pFrame
->GetMergedPara()
1461 ? *pFrame
->GetMergedPara()->pFirstNode
1463 assert(rFirstNode
.GetIndex() <= rNode
.GetIndex());
1464 // clear old one first to avoid DelFrames confusing updates & asserts...
1465 pFrame
->SetMergedPara(nullptr);
1466 pFrame
->SetMergedPara(sw::CheckParaRedlineMerge(
1467 *pFrame
, rFirstNode
, eMode
));
1468 eMode
= sw::FrameMode::New
; // Existing is not idempotent!
1469 // note: this may or may not delete frames on the end node
1475 /** local method to set 'working' position for newly inserted frames
1477 OD 12.08.2003 #i17969#
1479 static void lcl_SetPos( SwFrame
& _rNewFrame
,
1480 const SwLayoutFrame
& _rLayFrame
)
1482 SwRectFnSet
aRectFnSet(&_rLayFrame
);
1483 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(_rNewFrame
);
1484 aRectFnSet
.SetPos( aFrm
, aRectFnSet
.GetPos(_rLayFrame
.getFrameArea()) );
1486 // move position by one SwTwip in text flow direction in order to get
1487 // notifications for a new calculated position after its formatting.
1488 if ( aRectFnSet
.IsVert() )
1490 aFrm
.Pos().AdjustX( -1 );
1494 aFrm
.Pos().AdjustY(1 );
1498 void InsertCnt_( SwLayoutFrame
*pLay
, SwDoc
*pDoc
,
1499 SwNodeOffset nIndex
, bool bPages
, SwNodeOffset nEndIndex
,
1500 SwFrame
*pPrv
, sw::FrameMode
const eMode
)
1502 pDoc
->getIDocumentTimerAccess().BlockIdling();
1503 SwRootFrame
* pLayout
= pLay
->getRootFrame();
1504 const bool bOldCallbackActionEnabled
= pLayout
&& pLayout
->IsCallbackActionEnabled();
1505 if( bOldCallbackActionEnabled
)
1506 pLayout
->SetCallbackActionEnabled( false );
1508 //In the generation of the Layout bPages=true will be handed over.
1509 //Then will be new pages generated all x paragraphs already times in advance.
1510 //On breaks and/or pagedescriptorchanges the corresponding will be generated
1512 //The advantage is, that on one hand already a nearly realistic number of
1513 //pages are created, but above all there are no almost endless long chain
1514 //of paragraphs, which must be moved expensively until it reaches a tolerable
1516 //We'd like to think that 20 Paragraphs fit on one page.
1517 //So that it does not become in extreme situations so violent we calculate depending
1518 //on the node something to it.
1519 //If in the DocStatistic a usable given pagenumber
1520 //(Will be cared for while writing), so it will be presumed that this will be
1522 const bool bStartPercent
= bPages
&& !nEndIndex
;
1524 SwPageFrame
*pPage
= pLay
->FindPageFrame();
1525 sw::SpzFrameFormats
* pTable
= pDoc
->GetSpzFrameFormats();
1526 SwFrame
*pFrame
= nullptr;
1527 std::unique_ptr
<SwActualSection
> pActualSection
;
1528 std::unique_ptr
<SwLayHelper
> pPageMaker
;
1530 //If the layout will be created (bPages == true) we do head on the progress
1531 //Flys and DrawObjects are not connected immediately, this
1532 //happens only at the end of the function.
1535 // Attention: the SwLayHelper class uses references to the content-,
1536 // page-, layout-frame etc. and may change them!
1537 pPageMaker
.reset(new SwLayHelper( pDoc
, pFrame
, pPrv
, pPage
, pLay
,
1538 pActualSection
, nIndex
, SwNodeOffset(0) == nEndIndex
));
1541 const sal_uLong nPageCount
= pPageMaker
->CalcPageCount();
1543 bObjsDirect
= false;
1547 if( pLay
->IsInSct() &&
1548 ( pLay
->IsSctFrame() || pLay
->GetUpper() ) ) // Hereby will newbies
1549 // be intercepted, of which flags could not determined yet,
1550 // for e.g. while inserting a table
1552 SwSectionFrame
* pSct
= pLay
->FindSctFrame();
1553 // If content will be inserted in a footnote, which in a column area,
1554 // the column area it is not allowed to be broken up.
1555 // Only if in the inner of the footnote lies an area, is this a candidate
1556 // for pActualSection.
1557 // The same applies for areas in tables, if inside the table will be
1558 // something inserted, it's only allowed to break up areas, which
1559 // lies in the inside also.
1560 if( ( !pLay
->IsInFootnote() || pSct
->IsInFootnote() ) &&
1561 ( !pLay
->IsInTab() || pSct
->IsInTab() ) )
1563 pActualSection
.reset(new SwActualSection(nullptr, pSct
, pSct
->GetSection()->GetFormat()->GetSectionNode()));
1564 // tdf#132236 for SwUndoDelete: find outer sections whose start
1565 // nodes aren't contained in the range but whose end nodes are,
1566 // because section frames may need to be created for them
1567 SwActualSection
* pUpperSection(pActualSection
.get());
1568 while (pUpperSection
->GetSectionNode()->EndOfSectionIndex() < nEndIndex
)
1570 SwStartNode
*const pStart(pUpperSection
->GetSectionNode()->StartOfSectionNode());
1571 if (!pStart
->IsSectionNode())
1575 // note: these don't have a section frame, check it in EndNode case!
1576 auto const pTmp(new SwActualSection(nullptr, nullptr, static_cast<SwSectionNode
*>(pStart
)));
1577 pUpperSection
->SetUpper(pTmp
);
1578 pUpperSection
= pTmp
;
1580 OSL_ENSURE( !pLay
->Lower() || !pLay
->Lower()->IsColumnFrame(),
1581 "InsertCnt_: Wrong Call" );
1585 //If a section is "open", the pActualSection points to an SwActualSection.
1586 //If the page breaks, for "open" sections a follow will created.
1587 //For nested sections (which have, however, not a nested layout),
1588 //the SwActualSection class has a member, which points to an upper(section).
1589 //When the "inner" section finishes, the upper will used instead.
1591 // Do not consider the end node. The caller (Section/MakeFrames()) has to
1592 // ensure that the end of this range is positioned before EndIndex!
1593 for ( ; nEndIndex
== SwNodeOffset(0) || nIndex
< nEndIndex
; ++nIndex
)
1595 SwNode
*pNd
= pDoc
->GetNodes()[nIndex
];
1596 if ( pNd
->IsContentNode() )
1598 SwContentNode
* pNode
= static_cast<SwContentNode
*>(pNd
);
1599 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1601 if (pNd
->IsTextNode()
1602 && pNd
->GetRedlineMergeFlag() == SwNode::Merge::NonFirst
)
1603 { // must have a frame already
1604 assert(static_cast<SwTextFrame
*>(pNode
->getLayoutFrame(pLayout
))->GetMergedPara());
1606 continue; // skip it
1608 pFrame
= pNode
->IsTextNode()
1609 ? sw::MakeTextFrame(*pNode
->GetTextNode(), pLay
, eMode
)
1610 : pNode
->MakeFrame(pLay
);
1612 pPageMaker
->CheckInsert( nIndex
);
1614 pFrame
->InsertBehind( pLay
, pPrv
);
1617 if (SwSectionFrame
*const pSection
= pLay
->FindSctFrame())
1619 if (pSection
&& pSection
->ContainsAny() == pFrame
)
1620 { // tdf#146258 section PrtArea depends on paragraph upper margin
1621 pSection
->InvalidatePrt();
1626 // notify accessibility paragraphs objects about changed
1627 // CONTENT_FLOWS_FROM/_TO relation.
1628 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1629 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1630 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1631 if ( pFrame
->IsTextFrame() )
1633 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1634 // no notification, if <SwViewShell> is in construction
1635 if ( pViewShell
&& !pViewShell
->IsInConstructor() &&
1636 pViewShell
->GetLayout() &&
1637 pViewShell
->GetLayout()->IsAnyShellAccessible() &&
1638 pFrame
->FindPageFrame() != nullptr)
1640 auto pNext
= pFrame
->FindNextCnt( true );
1641 auto pPrev
= pFrame
->FindPrevCnt();
1642 pViewShell
->InvalidateAccessibleParaFlowRelation(
1643 pNext
? pNext
->DynCastTextFrame() : nullptr,
1644 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1646 // The information flags of the text frame are validated
1647 // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
1648 // The information flags have to be invalidated, because
1649 // it is possible, that the one of its upper frames
1650 // isn't inserted into the layout.
1651 pFrame
->InvalidateInfFlags();
1655 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1656 // for setting position at newly inserted frame
1657 lcl_SetPos( *pFrame
, *pLay
);
1660 if ( !pTable
->empty() && bObjsDirect
&& !isFlyCreationSuppressed
)
1661 AppendObjs( pTable
, nIndex
, pFrame
, pPage
, pDoc
);
1663 else if ( pNd
->IsTableNode() )
1664 { //Should we have encountered a table?
1665 SwTableNode
*pTableNode
= static_cast<SwTableNode
*>(pNd
);
1666 if (pLayout
->IsHideRedlines())
1668 // in the problematic case, there can be only 1 redline...
1669 SwPosition
const tmp(*pNd
);
1670 SwRangeRedline
const*const pRedline(
1671 pDoc
->getIDocumentRedlineAccess().GetRedline(tmp
, nullptr));
1672 // pathology: redline that starts on a TableNode; cannot
1673 // be created in UI but by import filters...
1675 && pRedline
->GetType() == RedlineType::Delete
1676 && &pRedline
->Start()->GetNode() == pNd
)
1678 SAL_WARN("sw.pageframe", "skipping table frame creation on bizarre redline");
1681 pTableNode
->GetNodes()[nIndex
]->SetRedlineMergeFlag(SwNode::Merge::Hidden
);
1682 if (nIndex
== pTableNode
->EndOfSectionIndex())
1691 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1693 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1694 nIndex
= pTableNode
->EndOfSectionIndex();
1695 continue; // skip it
1698 pFrame
= pTableNode
->MakeFrame( pLay
);
1700 // skip tables deleted with track changes
1701 if ( !static_cast<SwTabFrame
*>(pFrame
)->Lower() )
1703 nIndex
= pTableNode
->EndOfSectionIndex();
1704 continue; // skip it
1707 // #108116# loading may produce table structures that GCLines
1708 // needs to clean up. To keep table formulas correct, change
1709 // all table formulas to internal (BOXPTR) representation.
1710 pTableNode
->GetTable().SwitchFormulasToInternalRepresentation();
1711 pTableNode
->GetTable().GCLines();
1714 pPageMaker
->CheckInsert( nIndex
);
1716 pFrame
->InsertBehind( pLay
, pPrv
);
1717 if (pPage
) // would null in SwCellFrame ctor
1718 { // tdf#134931 call ResetTurbo(); not sure if Paste() would be
1719 pFrame
->InvalidatePage(pPage
); // better than InsertBehind()?
1722 // notify accessibility paragraphs objects about changed
1723 // CONTENT_FLOWS_FROM/_TO relation.
1724 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1725 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1726 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1728 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1729 // no notification, if <SwViewShell> is in construction
1730 if ( pViewShell
&& !pViewShell
->IsInConstructor() &&
1731 pViewShell
->GetLayout() &&
1732 pViewShell
->GetLayout()->IsAnyShellAccessible() &&
1733 pFrame
->FindPageFrame() != nullptr)
1735 auto pNext
= pFrame
->FindNextCnt( true );
1736 auto pPrev
= pFrame
->FindPrevCnt();
1737 pViewShell
->InvalidateAccessibleParaFlowRelation(
1738 pNext
? pNext
->DynCastTextFrame() : nullptr,
1739 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1743 if ( bObjsDirect
&& !pTable
->empty() )
1744 static_cast<SwTabFrame
*>(pFrame
)->RegistFlys();
1745 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1746 // for setting position at newly inserted frame
1747 lcl_SetPos( *pFrame
, *pLay
);
1750 //Set the index to the endnode of the table section.
1751 nIndex
= pTableNode
->EndOfSectionIndex();
1753 SwTabFrame
* pTmpFrame
= static_cast<SwTabFrame
*>(pFrame
);
1756 pTmpFrame
->CheckDirChange();
1757 pTmpFrame
= pTmpFrame
->IsFollow() ? pTmpFrame
->FindMaster() : nullptr;
1761 else if ( pNd
->IsSectionNode() )
1763 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1765 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1766 continue; // skip it
1768 SwSectionNode
*pNode
= static_cast<SwSectionNode
*>(pNd
);
1769 if( pNode
->GetSection().CalcHiddenFlag() )
1770 // is hidden, skip the area
1771 nIndex
= pNode
->EndOfSectionIndex();
1775 pActualSection
->SetLastPos(pPrv
);
1777 pFrame
= pNode
->MakeFrame( pLay
);
1778 pActualSection
.reset( new SwActualSection( pActualSection
.release(),
1779 static_cast<SwSectionFrame
*>(pFrame
), pNode
) );
1780 if ( pActualSection
->GetUpper() )
1782 //Insert behind the Upper, the "Follow" of the Upper will be
1783 //generated at the EndNode.
1784 SwSectionFrame
*pTmp
= pActualSection
->GetUpper()->GetSectionFrame();
1785 pFrame
->InsertBehind( pTmp
->GetUpper(), pTmp
);
1786 // OD 25.03.2003 #108339# - direct initialization of section
1787 // after insertion in the layout
1788 static_cast<SwSectionFrame
*>(pFrame
)->Init();
1792 pFrame
->InsertBehind( pLay
, pPrv
);
1793 // OD 25.03.2003 #108339# - direct initialization of section
1794 // after insertion in the layout
1795 static_cast<SwSectionFrame
*>(pFrame
)->Init();
1798 // Do not trust the IsInFootnote flag. If we are currently
1799 // building up a table, the upper of pPrv may be a cell
1800 // frame, but the cell frame does not have an upper yet.
1801 if( pPrv
&& nullptr != pPrv
->ImplFindFootnoteFrame() )
1803 if( pPrv
->IsSctFrame() )
1804 pPrv
= static_cast<SwSectionFrame
*>(pPrv
)->ContainsContent();
1805 if( pPrv
&& pPrv
->IsTextFrame() )
1806 static_cast<SwTextFrame
*>(pPrv
)->Prepare( PrepareHint::QuoVadis
, nullptr, false );
1810 if (nIndex
+ 1 == nEndIndex
1811 // tdf#136452 may also be needed at end of section
1812 || pNode
->EndOfSectionIndex() - 1 == nEndIndex
)
1813 { // tdf#131684 tdf#132236 fix upper of frame moved in
1814 // SwUndoDelete; can't be done there unfortunately
1815 // because empty section frames are deleted here
1816 SwFrame
*const pNext(
1817 // if there's a parent section, it has been split
1818 // into 2 SwSectionFrame already :(
1820 && pFrame
->GetNext()->IsSctFrame()
1821 && pActualSection
->GetUpper()
1822 && pActualSection
->GetUpper()->GetSectionNode() ==
1823 static_cast<SwSectionFrame
const*>(pFrame
->GetNext())->GetSection()->GetFormat()->GetSectionNode())
1824 ? static_cast<SwSectionFrame
*>(pFrame
->GetNext())->ContainsContent()
1825 : pFrame
->GetNext());
1827 && pNext
->IsTextFrame()
1828 && static_cast<SwTextFrame
*>(pNext
)->GetTextNodeFirst() == pDoc
->GetNodes()[nEndIndex
]
1829 && (pNext
->GetUpper() == pFrame
->GetUpper()
1830 || pFrame
->GetNext()->IsSctFrame())) // checked above
1833 pNext
->InvalidateInfFlags(); // mbInfSct changed
1834 // could have columns
1835 SwSectionFrame
*const pSection(static_cast<SwSectionFrame
*>(pFrame
));
1836 assert(!pSection
->Lower() || pSection
->Lower()->IsLayoutFrame());
1837 SwLayoutFrame
*const pParent(pSection
->Lower() ? pSection
->GetNextLayoutLeaf() : pSection
);
1838 assert(!pParent
->Lower());
1839 // paste invalidates, section could have indent...
1840 pNext
->Paste(pParent
, nullptr);
1844 // notify accessibility paragraphs objects about changed
1845 // CONTENT_FLOWS_FROM/_TO relation.
1846 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1847 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1848 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1850 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1851 // no notification, if <SwViewShell> is in construction
1852 if ( pViewShell
&& !pViewShell
->IsInConstructor() &&
1853 pViewShell
->GetLayout() &&
1854 pViewShell
->GetLayout()->IsAnyShellAccessible() &&
1855 pFrame
->FindPageFrame() != nullptr)
1857 auto pNext
= pFrame
->FindNextCnt( true );
1858 auto pPrev
= pFrame
->FindPrevCnt();
1859 pViewShell
->InvalidateAccessibleParaFlowRelation(
1860 pNext
? pNext
->DynCastTextFrame() : nullptr,
1861 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1865 pFrame
->CheckDirChange();
1867 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1868 // for setting position at newly inserted frame
1869 lcl_SetPos( *pFrame
, *pLay
);
1871 // OD 20.11.2002 #105405# - no page, no invalidate.
1874 // OD 18.09.2002 #100522#
1875 // invalidate page in order to force format and paint of
1876 // inserted section frame
1877 pFrame
->InvalidatePage( pPage
);
1879 // FME 10.11.2003 #112243#
1880 // Invalidate fly content flag:
1881 if ( pFrame
->IsInFly() )
1882 pPage
->InvalidateFlyContent();
1884 // OD 14.11.2002 #104684# - invalidate page content in order to
1885 // force format and paint of section content.
1886 pPage
->InvalidateContent();
1889 pLay
= static_cast<SwLayoutFrame
*>(pFrame
);
1890 if ( pLay
->Lower() && pLay
->Lower()->IsLayoutFrame() )
1891 pLay
= pLay
->GetNextLayoutLeaf();
1895 else if ( pNd
->IsEndNode() && pNd
->StartOfSectionNode()->IsSectionNode() )
1897 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1899 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1900 continue; // skip it
1902 if (pLayout
->HasMergedParas() && !pNd
->StartOfSectionNode()->IsCreateFrameWhenHidingRedlines())
1903 { // tdf#135014 section break in fieldmark (start inside, end outside)
1904 assert(pNd
->StartOfSectionNode()->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1905 continue; // skip it
1907 assert(pActualSection
&& "Section end without section start?");
1908 assert(pActualSection
->GetSectionNode() == pNd
->StartOfSectionNode());
1910 //Close the section, where appropriate activate the surrounding
1912 pActualSection
.reset(pActualSection
->GetUpper());
1913 pLay
= pLay
->FindSctFrame();
1914 if ( pActualSection
)
1916 //Could be, that the last SectionFrame remains empty.
1917 //Then now is the time to remove them.
1918 if ( !pLay
->ContainsContent() )
1920 SwFrame
*pTmpFrame
= pLay
;
1921 pLay
= pTmpFrame
->GetUpper();
1922 pPrv
= pTmpFrame
->GetPrev();
1923 pTmpFrame
->RemoveFromLayout();
1924 SwFrame::DestroyFrame(pTmpFrame
);
1929 pLay
= pLay
->GetUpper();
1932 // new section frame
1933 if (SwSectionFrame
* pOuterSectionFrame
= pActualSection
->GetSectionFrame())
1935 // Splitting moves the trailing content to the next frame
1936 pFrame
= pOuterSectionFrame
->SplitSect(pActualSection
->GetLastPos(), pPrv
);
1938 // We don't want to leave empty parts back.
1939 if (! pOuterSectionFrame
->IsColLocked() &&
1940 ! pOuterSectionFrame
->ContainsContent() )
1942 pOuterSectionFrame
->DelEmpty( true );
1943 SwFrame::DestroyFrame(pOuterSectionFrame
);
1948 pFrame
= pActualSection
->GetSectionNode()->MakeFrame( pLay
);
1949 pFrame
->InsertBehind( pLay
, pPrv
);
1950 static_cast<SwSectionFrame
*>(pFrame
)->Init();
1952 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1953 // for setting position at newly inserted frame
1954 lcl_SetPos( *pFrame
, *pLay
);
1957 pActualSection
->SetSectionFrame( static_cast<SwSectionFrame
*>(pFrame
) );
1959 pLay
= static_cast<SwLayoutFrame
*>(pFrame
);
1960 if ( pLay
->Lower() && pLay
->Lower()->IsLayoutFrame() )
1961 pLay
= pLay
->GetNextLayoutLeaf();
1966 //Nothing more with sections, it goes on right behind
1969 pLay
= pLay
->GetUpper();
1972 else if( pNd
->IsStartNode() &&
1973 SwFlyStartNode
== static_cast<SwStartNode
*>(pNd
)->GetStartNodeType() )
1975 if (pLayout
->HasMergedParas() && !pNd
->IsCreateFrameWhenHidingRedlines())
1977 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1978 assert(false); // actually a fly-section can't be deleted?
1979 continue; // skip it
1981 if ( !pTable
->empty() && bObjsDirect
&& !isFlyCreationSuppressed
)
1983 SwFlyFrame
* pFly
= pLay
->FindFlyFrame();
1985 AppendObjs( pTable
, nIndex
, pFly
, pPage
, pDoc
);
1990 assert(!pLayout
->HasMergedParas()
1991 || pNd
->GetRedlineMergeFlag() != SwNode::Merge::Hidden
);
1992 // Neither Content nor table nor section, so we are done.
1997 if ( pActualSection
)
1999 // Might happen that an empty (Follow-)Section is left over.
2000 if ( !(pLay
= pActualSection
->GetSectionFrame())->ContainsContent() )
2002 pLay
->RemoveFromLayout();
2003 SwFrame::DestroyFrame(pLay
);
2005 pActualSection
.reset();
2008 if ( bPages
) // let the Flys connect to each other
2010 if ( !isFlyCreationSuppressed
)
2011 AppendAllObjs( pTable
, pLayout
);
2017 pPageMaker
->CheckFlyCache( pPage
);
2019 if( pDoc
->GetLayoutCache() )
2022 pDoc
->GetLayoutCache()->CompareLayout( *pDoc
);
2024 pDoc
->GetLayoutCache()->ClearImpl();
2028 pDoc
->getIDocumentTimerAccess().UnblockIdling();
2029 if( bOldCallbackActionEnabled
)
2030 pLayout
->SetCallbackActionEnabled( bOldCallbackActionEnabled
);
2033 void MakeFrames( SwDoc
*pDoc
, SwNode
&rSttIdx
, SwNode
&rEndIdx
)
2035 bObjsDirect
= false;
2037 SwNodeOffset nEndIdx
= rEndIdx
.GetIndex();
2038 // TODO for multiple layouts there should be a loop here
2039 SwNode
* pNd
= pDoc
->GetNodes().FindPrvNxtFrameNode( rSttIdx
,
2040 pDoc
->GetNodes()[ nEndIdx
-1 ],
2041 pDoc
->getIDocumentLayoutAccess().GetCurrentLayout());
2044 bool bAfter
= *pNd
< rSttIdx
;
2045 SwNode2Layout
aNode2Layout( *pNd
, rSttIdx
.GetIndex() );
2046 sw::FrameMode eMode
= sw::FrameMode::Existing
;
2047 ::std::vector
<SwFrame
*> frames
;
2048 while (SwFrame
* pFrame
= aNode2Layout
.NextFrame())
2049 { // tdf#150500 new frames may be created that end up merged on pNd
2050 // so copy the currently existing ones; they shouldn't get deleted
2051 frames
.push_back(pFrame
);
2053 for (SwFrame
*const pFrame
: frames
)
2055 SwLayoutFrame
*pUpper
= pFrame
->GetUpper();
2056 SwFootnoteFrame
* pFootnoteFrame
= pUpper
->FindFootnoteFrame();
2057 bool bOldLock
, bOldFootnote
;
2058 if( pFootnoteFrame
)
2060 bOldFootnote
= pFootnoteFrame
->IsColLocked();
2061 pFootnoteFrame
->ColLock();
2064 bOldFootnote
= true;
2065 SwSectionFrame
* pSct
= pUpper
->FindSctFrame();
2066 // Inside of footnotes only those areas are interesting that are inside of them. But
2067 // not the ones (e.g. column areas) in which are the footnote containers positioned.
2068 // #109767# Table frame is in section, insert section in cell frame.
2069 if( pSct
&& ((pFootnoteFrame
&& !pSct
->IsInFootnote()) || pUpper
->IsCellFrame()) )
2072 { // to prevent pTmp->MoveFwd from destroying the SectionFrame
2073 bOldLock
= pSct
->IsColLocked();
2079 // If pFrame cannot be moved, it is not possible to move it to the next page. This applies
2080 // also for frames (in the first column of a frame pFrame is moveable) and column
2081 // sections of tables (also here pFrame is moveable).
2082 bool bMoveNext
= nEndIdx
- rSttIdx
.GetIndex() > SwNodeOffset(120);
2083 bool bAllowMove
= !pFrame
->IsInFly() && pFrame
->IsMoveable() &&
2084 (!pFrame
->IsInTab() || pFrame
->IsTabFrame() );
2085 if ( bMoveNext
&& bAllowMove
)
2087 SwFrame
*pMove
= pFrame
;
2088 SwFrame
*pPrev
= pFrame
->GetPrev();
2089 SwFlowFrame
*pTmp
= SwFlowFrame::CastFlowFrame( pMove
);
2094 // The rest of this page should be empty. Thus, the following one has to move to
2095 // the next page (it might also be located in the following column).
2096 assert(!pTmp
->HasFollow() && "prev. node's frame is not last");
2098 // If the surrounding SectionFrame has a "next" one,
2099 // so this one needs to be moved as well.
2100 pMove
= pFrame
->GetIndNext();
2101 SwColumnFrame
* pCol
= static_cast<SwColumnFrame
*>(pFrame
->FindColFrame());
2103 pCol
= static_cast<SwColumnFrame
*>(pCol
->GetNext());
2106 if( pCol
&& !pMove
)
2107 { // No successor so far, look into the next column
2108 pMove
= pCol
->ContainsAny();
2109 if( pCol
->GetNext() )
2110 pCol
= static_cast<SwColumnFrame
*>(pCol
->GetNext());
2111 else if( pCol
->IsInSct() )
2112 { // If there is no following column but we are in a column frame,
2113 // there might be (page) columns outside of it.
2114 pCol
= static_cast<SwColumnFrame
*>(pCol
->FindSctFrame()->FindColFrame());
2116 pCol
= static_cast<SwColumnFrame
*>(pCol
->GetNext());
2121 // skip invalid SectionFrames
2122 while( pMove
&& pMove
->IsSctFrame() &&
2123 !static_cast<SwSectionFrame
*>(pMove
)->GetSection() )
2124 pMove
= pMove
->GetNext();
2125 } while( !pMove
&& pCol
);
2129 if ( pMove
->IsContentFrame() )
2130 pTmp
= static_cast<SwContentFrame
*>(pMove
);
2131 else if ( pMove
->IsTabFrame() )
2132 pTmp
= static_cast<SwTabFrame
*>(pMove
);
2133 else if ( pMove
->IsSctFrame() )
2135 pMove
= static_cast<SwSectionFrame
*>(pMove
)->ContainsAny();
2137 pTmp
= SwFlowFrame::CastFlowFrame( pMove
);
2147 assert(!pTmp
->IsFollow() && "next node's frame is not master");
2148 // move the _content_ of a section frame
2149 if( pMove
->IsSctFrame() )
2151 while( pMove
&& pMove
->IsSctFrame() &&
2152 !static_cast<SwSectionFrame
*>(pMove
)->GetSection() )
2153 pMove
= pMove
->GetNext();
2154 if( pMove
&& pMove
->IsSctFrame() )
2155 pMove
= static_cast<SwSectionFrame
*>(pMove
)->ContainsAny();
2157 pTmp
= SwFlowFrame::CastFlowFrame( pMove
);
2165 SwFrame
* pOldUp
= pTmp
->GetFrame().GetUpper();
2166 // MoveFwd==true means that we are still on the same page.
2167 // But since we want to move if possible!
2168 bool bTmpOldLock
= pTmp
->IsJoinLocked();
2170 while( pTmp
->MoveFwd( true, false, true ) )
2172 if( pOldUp
== pTmp
->GetFrame().GetUpper() )
2174 pOldUp
= pTmp
->GetFrame().GetUpper();
2179 ::InsertCnt_( pUpper
, pDoc
, rSttIdx
.GetIndex(),
2180 pFrame
->IsInDocBody(), nEndIdx
, pPrev
, eMode
);
2184 SwFrame
* pPrv
= bAfter
? pFrame
: pFrame
->GetPrev();
2186 ::InsertCnt_( pUpper
, pDoc
, rSttIdx
.GetIndex(), false,
2187 nEndIdx
, pPrv
, eMode
);
2188 // OD 23.06.2003 #108784# - correction: append objects doesn't
2189 // depend on value of <bAllowMove>
2190 if( !isFlyCreationSuppressed
)
2192 const sw::SpzFrameFormats
* pTable
= pDoc
->GetSpzFrameFormats();
2193 if( !pTable
->empty() )
2194 AppendAllObjs( pTable
, pUpper
);
2197 if( pFrame
->IsInFly() )
2198 pFrame
->FindFlyFrame()->Invalidate_();
2199 if( pFrame
->IsInTab() )
2200 pFrame
->InvalidateSize();
2203 SwPageFrame
*pPage
= pUpper
->FindPageFrame();
2204 SwFrame::CheckPageDescs( pPage
, false );
2206 pFootnoteFrame
->ColUnlock();
2210 // pSct might be empty (e.g. when inserting linked section containing further
2211 // sections) and can be destroyed in such cases.
2212 if( !pSct
->ContainsContent() )
2214 pSct
->DelEmpty( true );
2215 pUpper
->getRootFrame()->RemoveFromList( pSct
);
2216 SwFrame::DestroyFrame(pSct
);
2219 eMode
= sw::FrameMode::New
; // use Existing only once!
2226 SwBorderAttrs::SwBorderAttrs(const sw::BorderCacheOwner
* pOwner
, const SwFrame
* pConstructor
)
2227 : SwCacheObj(pOwner
)
2228 , m_rAttrSet(pConstructor
->IsContentFrame()
2229 ? pConstructor
->IsTextFrame()
2230 ? static_cast<const SwTextFrame
*>(pConstructor
)->GetTextNodeForParaProps()->GetSwAttrSet()
2231 : static_cast<const SwNoTextFrame
*>(pConstructor
)->GetNode()->GetSwAttrSet()
2232 : static_cast<const SwLayoutFrame
*>(pConstructor
)->GetFormat()->GetAttrSet())
2233 , m_rUL(m_rAttrSet
.GetULSpace())
2234 , m_rBox(m_rAttrSet
.GetBox())
2235 , m_rShadow(m_rAttrSet
.GetShadow())
2236 , m_aFrameSize(m_rAttrSet
.GetFrameSize().GetSize())
2238 , m_bJoinedWithPrev(false)
2239 , m_bJoinedWithNext(false)
2247 , m_nGetBottomLine(0)
2251 const SwTextFrame
* pTextFrame
= pConstructor
->DynCastTextFrame();
2254 m_pFirstLineIndent
.reset(m_rAttrSet
.GetFirstLineIndent().Clone());
2255 m_pTextLeftMargin
.reset(m_rAttrSet
.GetTextLeftMargin().Clone());
2256 m_pRightMargin
.reset(m_rAttrSet
.GetRightMargin().Clone());
2257 assert(m_pFirstLineIndent
);
2258 assert(m_pTextLeftMargin
);
2262 // LRSpaceItem is copied due to the possibility that it is adjusted
2263 m_xLR
.reset(m_rAttrSet
.GetLRSpace().Clone());
2264 if (pConstructor
->IsNoTextFrame())
2266 m_xLR
= std::make_shared
<SvxLRSpaceItem
>(RES_LR_SPACE
);
2271 // Caution: The USHORTs for the cached values are not initialized by intention!
2273 // everything needs to be calculated at least once:
2274 m_bTopLine
= m_bBottomLine
= m_bLeftLine
= m_bRightLine
=
2275 m_bTop
= m_bBottom
= m_bLine
= true;
2277 // except this one: calculate line spacing before cell border only for text frames
2278 m_bLineSpacing
= bool(pTextFrame
);
2280 m_bCacheGetLine
= m_bCachedGetTopLine
= m_bCachedGetBottomLine
= false;
2281 // OD 21.05.2003 #108789# - init cache status for values <m_bJoinedWithPrev>
2282 // and <m_bJoinedWithNext>, which aren't initialized by default.
2283 m_bCachedJoinedWithPrev
= false;
2284 m_bCachedJoinedWithNext
= false;
2287 SwBorderAttrs::~SwBorderAttrs()
2289 const_cast<sw::BorderCacheOwner
*>(static_cast<sw::BorderCacheOwner
const *>(m_pOwner
))->m_bInCache
= false;
2292 /* All calc methods calculate a safety distance in addition to the values given by the attributes.
2293 * This safety distance is only added when working with borders and/or shadows to prevent that
2294 * e.g. borders are painted over.
2297 void SwBorderAttrs::CalcTop_()
2299 m_nTop
= CalcTopLine() + m_rUL
.GetUpper();
2301 bool bGutterAtTop
= m_rAttrSet
.GetDoc()->getIDocumentSettingAccess().get(
2302 DocumentSettingId::GUTTER_AT_TOP
);
2303 if (bGutterAtTop
&& m_xLR
)
2305 // Decrease the print area: the top space is the sum of top and gutter margins.
2306 m_nTop
+= m_xLR
->GetGutterMargin();
2312 void SwBorderAttrs::CalcBottom_()
2314 m_nBottom
= CalcBottomLine() + m_rUL
.GetLower();
2318 tools::Long
SwBorderAttrs::CalcRight( const SwFrame
* pCaller
) const
2320 tools::Long nRight
=0;
2322 if (!pCaller
->IsTextFrame() || !static_cast<const SwTextFrame
*>(pCaller
)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING
)) {
2323 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2324 // and right border are painted on the right respectively left.
2325 if ( pCaller
->IsCellFrame() && pCaller
->IsRightToLeft() )
2326 nRight
= CalcLeftLine();
2328 nRight
= CalcRightLine();
2331 // for paragraphs, "left" is "before text" and "right" is "after text"
2332 if (pCaller
->IsTextFrame())
2334 if (pCaller
->IsRightToLeft())
2336 nRight
+= m_pTextLeftMargin
->GetLeft(*m_pFirstLineIndent
);
2340 nRight
+= m_pRightMargin
->GetRight();
2344 nRight
+= m_xLR
->GetRight();
2346 // correction: retrieve left margin for numbering in R2L-layout
2347 if ( pCaller
->IsTextFrame() && pCaller
->IsRightToLeft() )
2349 nRight
+= static_cast<const SwTextFrame
*>(pCaller
)->GetTextNodeForParaProps()->GetLeftMarginWithNum();
2352 if (pCaller
->IsPageFrame())
2354 const auto pPageFrame
= static_cast<const SwPageFrame
*>(pCaller
);
2355 bool bGutterAtTop
= pPageFrame
->GetFormat()->getIDocumentSettingAccess().get(
2356 DocumentSettingId::GUTTER_AT_TOP
);
2359 bool bRtlGutter
= pPageFrame
->GetAttrSet()->GetItem
<SfxBoolItem
>(RES_RTL_GUTTER
)->GetValue();
2360 tools::Long nGutterMargin
= bRtlGutter
? m_xLR
->GetGutterMargin() : m_xLR
->GetRightGutterMargin();
2361 // Decrease the print area: the right space is the sum of right and right gutter
2363 nRight
+= nGutterMargin
;
2370 tools::Long
SwBorderAttrs::CalcLeft( const SwFrame
*pCaller
) const
2372 tools::Long nLeft
=0;
2374 if (!pCaller
->IsTextFrame() || !static_cast<const SwTextFrame
*>(pCaller
)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING
))
2376 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2377 // and right border are painted on the right respectively left.
2378 if ( pCaller
->IsCellFrame() && pCaller
->IsRightToLeft() )
2379 nLeft
= CalcRightLine();
2381 nLeft
= CalcLeftLine();
2384 // for paragraphs, "left" is "before text" and "right" is "after text"
2385 if ( pCaller
->IsTextFrame() && pCaller
->IsRightToLeft() )
2386 nLeft
+= m_pRightMargin
->GetRight();
2389 if (pCaller
->IsTextFrame())
2391 nLeft
+= m_pTextLeftMargin
->GetLeft(*m_pFirstLineIndent
);
2394 nLeft
+= m_xLR
->GetLeft();
2397 // correction: do not retrieve left margin for numbering in R2L-layout
2398 if ( pCaller
->IsTextFrame() && !pCaller
->IsRightToLeft() )
2400 nLeft
+= static_cast<const SwTextFrame
*>(pCaller
)->GetTextNodeForParaProps()->GetLeftMarginWithNum();
2403 if (pCaller
->IsPageFrame())
2405 const auto pPageFrame
= static_cast<const SwPageFrame
*>(pCaller
);
2406 bool bGutterAtTop
= pPageFrame
->GetFormat()->getIDocumentSettingAccess().get(
2407 DocumentSettingId::GUTTER_AT_TOP
);
2410 bool bRtlGutter
= pPageFrame
->GetAttrSet()->GetItem
<SfxBoolItem
>(RES_RTL_GUTTER
)->GetValue();
2411 tools::Long nGutterMargin
= bRtlGutter
? m_xLR
->GetRightGutterMargin() : m_xLR
->GetGutterMargin();
2412 // Decrease the print area: the left space is the sum of left and gutter margins.
2413 nLeft
+= nGutterMargin
;
2420 /* Calculated values for borders and shadows.
2421 * It might be that a distance is wanted even without lines. This will be
2422 * considered here and not by the attribute (e.g. bBorderDist for cells).
2425 void SwBorderAttrs::CalcTopLine_()
2427 m_nTopLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::TOP
, /*bEvenIfNoLine*/true );
2428 m_nTopLine
= m_nTopLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::TOP
);
2432 void SwBorderAttrs::CalcBottomLine_()
2434 m_nBottomLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::BOTTOM
, true );
2435 m_nBottomLine
= m_nBottomLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::BOTTOM
);
2436 m_bBottomLine
= false;
2439 void SwBorderAttrs::CalcLeftLine_()
2441 m_nLeftLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::LEFT
, true);
2442 m_nLeftLine
= m_nLeftLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::LEFT
);
2443 m_bLeftLine
= false;
2446 void SwBorderAttrs::CalcRightLine_()
2448 m_nRightLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::RIGHT
, true );
2449 m_nRightLine
= m_nRightLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::RIGHT
);
2450 m_bRightLine
= false;
2453 void SwBorderAttrs::IsLine_()
2455 m_bIsLine
= m_rBox
.GetTop() || m_rBox
.GetBottom() ||
2456 m_rBox
.GetLeft()|| m_rBox
.GetRight();
2460 /* The borders of neighboring paragraphs are condensed by following algorithm:
2462 * 1. No top border if the predecessor has the same top border and (3) applies.
2463 * In addition, the paragraph needs to have a border at least one side (left/right/bottom).
2464 * 2. No bottom border if the successor has the same bottom border and (3) applies.
2465 * In addition, the paragraph needs to have a border at least one side (left/right/top).
2466 * 3. The borders on the left and right side are identical between the current and the
2467 * pre-/succeeding paragraph.
2470 static bool CmpLines( const editeng::SvxBorderLine
*pL1
, const editeng::SvxBorderLine
*pL2
)
2472 return ( ((pL1
&& pL2
) && (*pL1
== *pL2
)) || (!pL1
&& !pL2
) );
2475 // OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
2476 // OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
2477 // instead of only the right LR-spacing, because R2L-layout has to be
2479 bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs
&rCmpAttrs
,
2480 const SwFrame
*pCaller
,
2481 const SwFrame
*pCmp
) const
2483 return ( CmpLines( rCmpAttrs
.GetBox().GetLeft(), GetBox().GetLeft() ) &&
2484 CmpLines( rCmpAttrs
.GetBox().GetRight(),GetBox().GetRight() ) &&
2485 CalcLeft( pCaller
) == rCmpAttrs
.CalcLeft( pCmp
) &&
2486 // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
2487 CalcRight( pCaller
) == rCmpAttrs
.CalcRight( pCmp
) );
2490 bool SwBorderAttrs::JoinWithCmp( const SwFrame
& _rCallerFrame
,
2491 const SwFrame
& _rCmpFrame
) const
2493 bool bReturnVal
= false;
2495 SwBorderAttrAccess
aCmpAccess( SwFrame::GetCache(), &_rCmpFrame
);
2496 const SwBorderAttrs
&rCmpAttrs
= *aCmpAccess
.Get();
2497 if ( m_rShadow
== rCmpAttrs
.GetShadow() &&
2498 CmpLines( m_rBox
.GetTop(), rCmpAttrs
.GetBox().GetTop() ) &&
2499 CmpLines( m_rBox
.GetBottom(), rCmpAttrs
.GetBox().GetBottom() ) &&
2500 CmpLeftRight( rCmpAttrs
, &_rCallerFrame
, &_rCmpFrame
)
2509 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2510 // previous frame. Calculated value saved in cached value <m_bJoinedWithPrev>
2511 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame>
2512 void SwBorderAttrs::CalcJoinedWithPrev( const SwFrame
& _rFrame
,
2513 const SwFrame
* _pPrevFrame
)
2516 m_bJoinedWithPrev
= false;
2518 if ( _rFrame
.IsTextFrame() )
2520 // text frame can potentially join with previous text frame, if
2521 // corresponding attribute set is set at previous text frame.
2522 // OD 2004-02-26 #i25029# - If parameter <_pPrevFrame> is set, take this
2523 // one as previous frame.
2524 const SwFrame
* pPrevFrame
= _pPrevFrame
? _pPrevFrame
: _rFrame
.GetPrev();
2525 // OD 2004-02-13 #i25029# - skip hidden text frames.
2526 while ( pPrevFrame
&& pPrevFrame
->IsTextFrame() &&
2527 static_cast<const SwTextFrame
*>(pPrevFrame
)->IsHiddenNow() )
2529 pPrevFrame
= pPrevFrame
->GetPrev();
2531 if ( pPrevFrame
&& pPrevFrame
->IsTextFrame() &&
2532 pPrevFrame
->GetAttrSet()->GetParaConnectBorder().GetValue()
2535 m_bJoinedWithPrev
= JoinWithCmp( _rFrame
, *pPrevFrame
);
2539 // valid cache status, if demanded
2540 // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrame>
2542 m_bCachedJoinedWithPrev
= m_bCacheGetLine
&& !_pPrevFrame
;
2545 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2546 // next frame. Calculated value saved in cached value <m_bJoinedWithNext>
2547 void SwBorderAttrs::CalcJoinedWithNext( const SwFrame
& _rFrame
)
2550 m_bJoinedWithNext
= false;
2552 if ( _rFrame
.IsTextFrame() )
2554 // text frame can potentially join with next text frame, if
2555 // corresponding attribute set is set at current text frame.
2556 // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
2557 const SwFrame
* pNextFrame
= _rFrame
.GetNext();
2558 while ( pNextFrame
&& pNextFrame
->IsTextFrame() &&
2559 static_cast<const SwTextFrame
*>(pNextFrame
)->IsHiddenNow() )
2561 pNextFrame
= pNextFrame
->GetNext();
2563 if ( pNextFrame
&& pNextFrame
->IsTextFrame() &&
2564 _rFrame
.GetAttrSet()->GetParaConnectBorder().GetValue()
2567 m_bJoinedWithNext
= JoinWithCmp( _rFrame
, *pNextFrame
);
2571 // valid cache status, if demanded
2572 m_bCachedJoinedWithNext
= m_bCacheGetLine
;
2575 // OD 21.05.2003 #108789# - accessor for cached values <m_bJoinedWithPrev>
2576 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame>, which is passed to
2577 // method <_CalcJoindWithPrev(..)>.
2578 bool SwBorderAttrs::JoinedWithPrev( const SwFrame
& _rFrame
,
2579 const SwFrame
* _pPrevFrame
) const
2581 if ( !m_bCachedJoinedWithPrev
|| _pPrevFrame
)
2583 // OD 2004-02-26 #i25029# - pass <_pPrevFrame> as 2nd parameter
2584 const_cast<SwBorderAttrs
*>(this)->CalcJoinedWithPrev( _rFrame
, _pPrevFrame
);
2587 return m_bJoinedWithPrev
;
2590 bool SwBorderAttrs::JoinedWithNext( const SwFrame
& _rFrame
) const
2592 if ( !m_bCachedJoinedWithNext
)
2594 const_cast<SwBorderAttrs
*>(this)->CalcJoinedWithNext( _rFrame
);
2597 return m_bJoinedWithNext
;
2600 // OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrame>, which is passed to
2601 // method <JoinedWithPrev>
2602 void SwBorderAttrs::GetTopLine_( const SwFrame
& _rFrame
,
2603 const SwFrame
* _pPrevFrame
)
2605 sal_uInt16 nRet
= CalcTopLine();
2607 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2608 // OD 2004-02-26 #i25029# - add 2nd parameter
2609 if ( JoinedWithPrev( _rFrame
, _pPrevFrame
) )
2614 m_bCachedGetTopLine
= m_bCacheGetLine
;
2616 m_nGetTopLine
= nRet
;
2619 void SwBorderAttrs::GetBottomLine_( const SwFrame
& _rFrame
)
2621 sal_uInt16 nRet
= CalcBottomLine();
2623 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2624 if ( JoinedWithNext( _rFrame
) )
2629 m_bCachedGetBottomLine
= m_bCacheGetLine
;
2631 m_nGetBottomLine
= nRet
;
2634 void SwBorderAttrs::CalcLineSpacing_()
2636 // tdf#125300 compatibility option AddParaLineSpacingToTableCells needs also line spacing
2637 const SvxLineSpacingItem
&rSpace
= m_rAttrSet
.GetLineSpacing();
2638 if ( rSpace
.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
&& rSpace
.GetPropLineSpace() > 100 )
2640 sal_Int32 nFontSize
= m_rAttrSet
.Get(RES_CHRATR_FONTSIZE
).GetHeight();
2641 m_nLineSpacing
= nFontSize
* (rSpace
.GetPropLineSpace() - 100) * 1.15 / 100;
2643 m_bLineSpacing
= false;
2646 static sw::BorderCacheOwner
const* GetBorderCacheOwner(SwFrame
const& rFrame
)
2648 return rFrame
.IsContentFrame()
2649 ? static_cast<sw::BorderCacheOwner
const*>(rFrame
.IsTextFrame()
2650 // 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
2651 ? static_cast<const SwTextFrame
&>(rFrame
).GetTextNodeForParaProps()
2652 : static_cast<const SwNoTextFrame
&>(rFrame
).GetNode())
2653 : static_cast<sw::BorderCacheOwner
const*>(static_cast<const SwLayoutFrame
&>(rFrame
).GetFormat());
2656 SwBorderAttrAccess::SwBorderAttrAccess( SwCache
&rCach
, const SwFrame
*pFrame
) :
2657 SwCacheAccess( rCach
,
2658 static_cast<void const *>(GetBorderCacheOwner(*pFrame
)),
2659 GetBorderCacheOwner(*pFrame
)->IsInCache()),
2660 m_pConstructor( pFrame
)
2664 SwCacheObj
*SwBorderAttrAccess::NewObj()
2666 const_cast<sw::BorderCacheOwner
*>(static_cast<sw::BorderCacheOwner
const *>(m_pOwner
))->m_bInCache
= true;
2667 return new SwBorderAttrs( static_cast<sw::BorderCacheOwner
const *>(m_pOwner
), m_pConstructor
);
2670 SwBorderAttrs
*SwBorderAttrAccess::Get()
2672 return static_cast<SwBorderAttrs
*>(SwCacheAccess::Get());
2675 SwOrderIter::SwOrderIter( const SwPageFrame
*pPg
) :
2677 m_pCurrent( nullptr )
2681 void SwOrderIter::Top()
2683 m_pCurrent
= nullptr;
2684 if ( !m_pPage
->GetSortedObjs() )
2687 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2688 if ( !pObjs
->size() )
2691 sal_uInt32 nTopOrd
= 0;
2692 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2693 for (SwAnchoredObject
* i
: *pObjs
)
2695 const SdrObject
* pObj
= i
->GetDrawObj();
2696 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2698 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2699 if ( nTmp
>= nTopOrd
)
2707 const SdrObject
*SwOrderIter::Bottom()
2709 m_pCurrent
= nullptr;
2710 if ( m_pPage
->GetSortedObjs() )
2712 sal_uInt32 nBotOrd
= USHRT_MAX
;
2713 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2714 if ( pObjs
->size() )
2716 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2717 for (SwAnchoredObject
* i
: *pObjs
)
2719 const SdrObject
* pObj
= i
->GetDrawObj();
2720 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2722 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2723 if ( nTmp
< nBotOrd
)
2734 const SdrObject
*SwOrderIter::Next()
2736 const sal_uInt32 nCurOrd
= m_pCurrent
? m_pCurrent
->GetOrdNumDirect() : 0;
2737 m_pCurrent
= nullptr;
2738 if ( m_pPage
->GetSortedObjs() )
2740 sal_uInt32 nOrd
= USHRT_MAX
;
2741 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2742 if ( pObjs
->size() )
2744 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2745 for (SwAnchoredObject
* i
: *pObjs
)
2747 const SdrObject
* pObj
= i
->GetDrawObj();
2748 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2750 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2751 if ( nTmp
> nCurOrd
&& nTmp
< nOrd
)
2762 void SwOrderIter::Prev()
2764 const sal_uInt32 nCurOrd
= m_pCurrent
? m_pCurrent
->GetOrdNumDirect() : 0;
2765 m_pCurrent
= nullptr;
2766 if ( !m_pPage
->GetSortedObjs() )
2769 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2770 if ( !pObjs
->size() )
2773 sal_uInt32 nOrd
= 0;
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
)
2789 /// Keep and restore the substructure of a layout frame for an action.
2791 // Do not look at each neighbor one by one to set all pointers correctly.
2792 // It is sufficient to detach a part of a chain and check if another chain needs to be added
2793 // when attaching it again. Only the pointers necessary for the chain connection need to be
2794 // adjusted. The correction happens in RestoreContent(). In between all access is restricted.
2795 // During this action, the Flys are detached from the page.
2797 // #115759# - 'remove' also drawing object from page and
2798 // at-fly anchored objects from page
2799 static void lcl_RemoveObjsFromPage( SwFrame
* _pFrame
)
2801 OSL_ENSURE( _pFrame
->GetDrawObjs(), "no DrawObjs in lcl_RemoveObjsFromPage." );
2802 SwSortedObjs
&rObjs
= *_pFrame
->GetDrawObjs();
2803 for (SwAnchoredObject
* pObj
: rObjs
)
2805 // #115759# - reset member, at which the anchored
2806 // object orients its vertical position
2807 pObj
->ClearVertPosOrientFrame();
2809 pObj
->ResetLayoutProcessBools();
2810 // #115759# - remove also lower objects of as-character
2811 // anchored Writer fly frames from page
2812 if ( auto pFlyFrame
= pObj
->DynCastFlyFrame() )
2814 // #115759# - remove also direct lowers of Writer
2815 // fly frame from page
2816 if ( pFlyFrame
->GetDrawObjs() )
2818 ::lcl_RemoveObjsFromPage( pFlyFrame
);
2821 SwContentFrame
* pCnt
= pFlyFrame
->ContainsContent();
2824 if ( pCnt
->GetDrawObjs() )
2825 ::lcl_RemoveObjsFromPage( pCnt
);
2826 pCnt
= pCnt
->GetNextContentFrame();
2828 if ( pFlyFrame
->IsFlyFreeFrame() )
2830 // #i28701# - use new method <GetPageFrame()>
2831 if (SwPageFrame
*pPg
= pFlyFrame
->GetPageFrame())
2832 pPg
->RemoveFlyFromPage(pFlyFrame
);
2835 // #115759# - remove also drawing objects from page
2836 else if ( auto pDrawObj
= dynamic_cast<SwAnchoredDrawObject
*>( pObj
) )
2838 if (pObj
->GetFrameFormat().GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR
)
2840 if (SwPageFrame
*pPg
= pObj
->GetPageFrame())
2841 pPg
->RemoveDrawObjFromPage( *pDrawObj
);
2847 SwFrame
*SaveContent( SwLayoutFrame
*pLay
, SwFrame
*pStart
)
2849 if( pLay
->IsSctFrame() && pLay
->Lower() && pLay
->Lower()->IsColumnFrame() )
2850 sw_RemoveFootnotes( static_cast<SwColumnFrame
*>(pLay
->Lower()), true, true );
2852 SwFrame
*pSav
= pLay
->ContainsAny();
2853 if ( nullptr == pSav
)
2856 if( pSav
->IsInFootnote() && !pLay
->IsInFootnote() )
2859 pSav
= pSav
->FindNext();
2860 while( pSav
&& pSav
->IsInFootnote() );
2861 if( !pSav
|| !pLay
->IsAnLower( pSav
) )
2865 // Tables should be saved as a whole, exception:
2866 // The contents of a section or a cell inside a table should be saved
2867 if ( pSav
->IsInTab() && !( ( pLay
->IsSctFrame() || pLay
->IsCellFrame() ) && pLay
->IsInTab() ) )
2868 while ( !pSav
->IsTabFrame() )
2869 pSav
= pSav
->GetUpper();
2871 if( pSav
->IsInSct() )
2872 { // search the upmost section inside of pLay
2873 SwFrame
* pSect
= pLay
->FindSctFrame();
2874 SwFrame
*pTmp
= pSav
;
2878 pTmp
= (pSav
&& pSav
->GetUpper()) ? pSav
->GetUpper()->FindSctFrame() : nullptr;
2879 } while ( pTmp
!= pSect
);
2882 SwFrame
*pFloat
= pSav
;
2885 bool bGo
= pStart
== pSav
;
2889 pFloat
->GetUpper()->m_pLower
= nullptr; // detach the chain part
2891 // search the end of the chain part, remove Flys on the way
2896 if ( pFloat
->IsContentFrame() )
2898 if ( pFloat
->GetDrawObjs() )
2899 ::lcl_RemoveObjsFromPage( static_cast<SwContentFrame
*>(pFloat
) );
2901 else if ( pFloat
->IsTabFrame() || pFloat
->IsSctFrame() )
2903 SwContentFrame
*pCnt
= static_cast<SwLayoutFrame
*>(pFloat
)->ContainsContent();
2907 { if ( pCnt
->GetDrawObjs() )
2908 ::lcl_RemoveObjsFromPage( pCnt
);
2909 pCnt
= pCnt
->GetNextContentFrame();
2910 } while ( pCnt
&& static_cast<SwLayoutFrame
*>(pFloat
)->IsAnLower( pCnt
) );
2914 OSL_ENSURE( !pFloat
, "new FloatFrame?" );
2917 if ( pFloat
->GetNext() )
2920 pFloat
->mpUpper
= nullptr;
2921 pFloat
= pFloat
->GetNext();
2922 if( !bGo
&& pFloat
== pStart
)
2925 pFloat
->mpPrev
->mpNext
= nullptr;
2926 pFloat
->mpPrev
= nullptr;
2934 // search next chain part and connect both chains
2935 SwFrame
*pTmp
= pFloat
->FindNext();
2937 pFloat
->mpUpper
= nullptr;
2939 if( !pLay
->IsInFootnote() )
2940 while( pTmp
&& pTmp
->IsInFootnote() )
2941 pTmp
= pTmp
->FindNext();
2943 if ( !pLay
->IsAnLower( pTmp
) )
2948 pFloat
->mpNext
= pTmp
; // connect both chains
2949 pFloat
->mpNext
->mpPrev
= pFloat
;
2952 bGo
= bGo
|| ( pStart
== pFloat
);
2955 return bGo
? pStart
: nullptr;
2958 // #115759# - add also drawing objects to page and at-fly
2959 // anchored objects to page
2960 static void lcl_AddObjsToPage( SwFrame
* _pFrame
, SwPageFrame
* _pPage
)
2962 OSL_ENSURE( _pFrame
->GetDrawObjs(), "no DrawObjs in lcl_AddObjsToPage." );
2963 SwSortedObjs
&rObjs
= *_pFrame
->GetDrawObjs();
2964 for (SwAnchoredObject
* pObj
: rObjs
)
2966 // #115759# - unlock position of anchored object
2967 // in order to get the object's position calculated.
2968 pObj
->UnlockPosition();
2969 // #115759# - add also lower objects of as-character
2970 // anchored Writer fly frames from page
2971 if ( auto pFlyFrame
= pObj
->DynCastFlyFrame() )
2973 if (pFlyFrame
->IsFlyFreeFrame())
2975 _pPage
->AppendFlyToPage( pFlyFrame
);
2977 pFlyFrame
->InvalidatePos_();
2978 pFlyFrame
->InvalidateSize_();
2979 pFlyFrame
->InvalidatePage( _pPage
);
2981 // #115759# - add also at-fly anchored objects
2983 if ( pFlyFrame
->GetDrawObjs() )
2985 ::lcl_AddObjsToPage( pFlyFrame
, _pPage
);
2988 SwContentFrame
*pCnt
= pFlyFrame
->ContainsContent();
2991 if ( pCnt
->GetDrawObjs() )
2992 ::lcl_AddObjsToPage( pCnt
, _pPage
);
2993 pCnt
= pCnt
->GetNextContentFrame();
2996 // #115759# - remove also drawing objects from page
2997 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pObj
) != nullptr )
2999 if (pObj
->GetFrameFormat().GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR
)
3001 pObj
->InvalidateObjPos();
3002 _pPage
->AppendDrawObjToPage(
3003 *static_cast<SwAnchoredDrawObject
*>(pObj
) );
3009 void RestoreContent( SwFrame
*pSav
, SwLayoutFrame
*pParent
, SwFrame
*pSibling
)
3011 OSL_ENSURE( pSav
&& pParent
, "no Save or Parent provided for RestoreContent." );
3012 SwRectFnSet
aRectFnSet(pParent
);
3014 // If there are already FlowFrames below the new parent, so add the chain (starting with pSav)
3015 // after the last one. The parts are inserted and invalidated if needed.
3016 // On the way, the Flys of the ContentFrames are registered at the page.
3018 SwPageFrame
*pPage
= pParent
->FindPageFrame();
3021 pPage
->InvalidatePage( pPage
);
3023 // determine predecessor and establish connection or initialize
3024 pSav
->mpPrev
= pSibling
;
3028 pNxt
= pSibling
->mpNext
;
3029 pSibling
->mpNext
= pSav
;
3030 pSibling
->InvalidatePrt_();
3031 pSibling
->InvalidatePage( pPage
);
3032 SwFlowFrame
*pFlowFrame
= dynamic_cast<SwFlowFrame
*>(pSibling
);
3033 if (pFlowFrame
&& pFlowFrame
->GetFollow())
3034 pSibling
->Prepare( PrepareHint::Clear
, nullptr, false );
3037 { pNxt
= pParent
->m_pLower
;
3038 pParent
->m_pLower
= pSav
;
3039 pSav
->mpUpper
= pParent
; // set here already, so that it is explicit when invalidating
3041 if ( pSav
->IsContentFrame() )
3042 static_cast<SwContentFrame
*>(pSav
)->InvalidatePage( pPage
);
3044 { // pSav might be an empty SectFrame
3045 SwContentFrame
* pCnt
= pParent
->ContainsContent();
3047 pCnt
->InvalidatePage( pPage
);
3051 // the parent needs to grow appropriately
3052 SwTwips nGrowVal
= 0;
3055 { pSav
->mpUpper
= pParent
;
3056 nGrowVal
+= aRectFnSet
.GetHeight(pSav
->getFrameArea());
3057 pSav
->InvalidateAll_();
3059 // register Flys, if TextFrames than also invalidate appropriately
3060 if ( pSav
->IsContentFrame() )
3062 if ( pSav
->IsTextFrame() &&
3063 static_cast<SwTextFrame
*>(pSav
)->GetCacheIdx() != USHRT_MAX
)
3064 static_cast<SwTextFrame
*>(pSav
)->Init(); // I am its friend
3066 if ( pPage
&& pSav
->GetDrawObjs() )
3067 ::lcl_AddObjsToPage( static_cast<SwContentFrame
*>(pSav
), pPage
);
3070 { SwContentFrame
*pBlub
= static_cast<SwLayoutFrame
*>(pSav
)->ContainsContent();
3074 { if ( pPage
&& pBlub
->GetDrawObjs() )
3075 ::lcl_AddObjsToPage( pBlub
, pPage
);
3076 if( pBlub
->IsTextFrame() && static_cast<SwTextFrame
*>(pBlub
)->HasFootnote() &&
3077 static_cast<SwTextFrame
*>(pBlub
)->GetCacheIdx() != USHRT_MAX
)
3078 static_cast<SwTextFrame
*>(pBlub
)->Init(); // I am its friend
3079 pBlub
= pBlub
->GetNextContentFrame();
3080 } while ( pBlub
&& static_cast<SwLayoutFrame
*>(pSav
)->IsAnLower( pBlub
));
3084 pSav
= pSav
->GetNext();
3090 pLast
->mpNext
= pNxt
;
3091 pNxt
->mpPrev
= pLast
;
3094 pParent
->Grow( nGrowVal
);
3099 bool IsRightPageByNumber(SwRootFrame
const& rLayout
, sal_uInt16
const nPageNum
)
3101 assert(rLayout
.GetLower());
3102 // unfortunately can only get SwPageDesc, not SwFormatPageDesc here...
3103 auto const nFirstVirtPageNum(rLayout
.GetLower()->GetVirtPageNum());
3104 bool const isFirstPageOfLayoutOdd(nFirstVirtPageNum
% 2 == 1);
3105 return ((nPageNum
% 2) == 1) == isFirstPageOfLayoutOdd
;
3110 SwPageFrame
* InsertNewPage( SwPageDesc
&rDesc
, SwFrame
*pUpper
,
3111 bool const isRightPage
, bool const bFirst
, bool bInsertEmpty
,
3112 bool const bFootnote
,
3114 bool const bVeryFirstPage
)
3117 assert(pUpper
->IsRootFrame());
3118 assert(!pSibling
|| static_cast<SwLayoutFrame
const*>(pUpper
)->Lower() != pSibling
); // currently no insert before 1st page
3120 SwDoc
*pDoc
= static_cast<SwLayoutFrame
*>(pUpper
)->GetFormat()->GetDoc();
3123 if (rDesc
.IsFirstShared())
3125 // We need to fallback to left or right page format, decide it now.
3126 // FIXME: is this still needed?
3129 rDesc
.GetFirstMaster().SetFormatAttr( rDesc
.GetMaster().GetHeader() );
3130 rDesc
.GetFirstMaster().SetFormatAttr( rDesc
.GetMaster().GetFooter() );
3131 // fdo#60250 copy margins for mirrored pages
3132 rDesc
.GetFirstMaster().SetFormatAttr( rDesc
.GetMaster().GetLRSpace() );
3136 rDesc
.GetFirstLeft().SetFormatAttr( rDesc
.GetLeft().GetHeader() );
3137 rDesc
.GetFirstLeft().SetFormatAttr( rDesc
.GetLeft().GetFooter() );
3138 rDesc
.GetFirstLeft().SetFormatAttr( rDesc
.GetLeft().GetLRSpace() );
3142 SwFrameFormat
*pFormat(isRightPage
? rDesc
.GetRightFormat(bFirst
) : rDesc
.GetLeftFormat(bFirst
));
3143 // If there is no FrameFormat for this page, add an empty page
3146 pFormat
= isRightPage
? rDesc
.GetLeftFormat(bVeryFirstPage
) : rDesc
.GetRightFormat(bVeryFirstPage
);
3147 OSL_ENSURE( pFormat
, "Descriptor without any format?!" );
3148 bInsertEmpty
= !bInsertEmpty
;
3152 SwPageDesc
*pTmpDesc
= pSibling
&& pSibling
->GetPrev() ?
3153 static_cast<SwPageFrame
*>(pSibling
->GetPrev())->GetPageDesc() : &rDesc
;
3154 pRet
= new SwPageFrame( pDoc
->GetEmptyPageFormat(), pUpper
, pTmpDesc
);
3155 SAL_INFO( "sw.pageframe", "InsertNewPage - insert empty p: " << pRet
<< " d: " << pTmpDesc
);
3156 pRet
->Paste( pUpper
, pSibling
);
3157 pRet
->PreparePage( bFootnote
);
3159 pRet
= new SwPageFrame( pFormat
, pUpper
, &rDesc
);
3160 SAL_INFO( "sw.pageframe", "InsertNewPage p: " << pRet
<< " d: " << &rDesc
<< " f: " << pFormat
);
3161 pRet
->Paste( pUpper
, pSibling
);
3162 pRet
->PreparePage( bFootnote
);
3163 if ( pRet
->GetNext() )
3164 SwRootFrame::AssertPageFlys( pRet
);
3168 /* The following two methods search the layout structure recursively and
3169 * register all Flys at the page that have a Frame in this structure as an anchor.
3172 static void lcl_Regist( SwPageFrame
*pPage
, const SwFrame
*pAnch
)
3174 SwSortedObjs
*pObjs
= const_cast<SwSortedObjs
*>(pAnch
->GetDrawObjs());
3175 for (SwAnchoredObject
* pObj
: *pObjs
)
3177 if (SwFlyFrame
* pFly
= pObj
->DynCastFlyFrame())
3179 // register (not if already known)
3180 // #i28701# - use new method <GetPageFrame()>
3181 SwPageFrame
*pPg
= pFly
->IsFlyFreeFrame()
3182 ? pFly
->GetPageFrame() : pFly
->FindPageFrame();
3186 pPg
->RemoveFlyFromPage( pFly
);
3187 pPage
->AppendFlyToPage( pFly
);
3189 ::RegistFlys( pPage
, pFly
);
3194 if ( pPage
!= pObj
->GetPageFrame() )
3197 if (SwPageFrame
*pPg
= pObj
->GetPageFrame())
3198 pPg
->RemoveDrawObjFromPage( *pObj
);
3199 pPage
->AppendDrawObjToPage( *pObj
);
3203 const SwFlyFrame
* pFly
= pAnch
->FindFlyFrame();
3205 pObj
->GetDrawObj()->GetOrdNum() < pFly
->GetVirtDrawObj()->GetOrdNum() &&
3206 pObj
->GetDrawObj()->getSdrPageFromSdrObject() )
3208 //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
3209 pObj
->DrawObj()->getSdrPageFromSdrObject()->SetObjectOrdNum( pFly
->GetVirtDrawObj()->GetOrdNumDirect(),
3210 pObj
->GetDrawObj()->GetOrdNumDirect() );
3215 void RegistFlys( SwPageFrame
*pPage
, const SwLayoutFrame
*pLay
)
3217 if ( pLay
->GetDrawObjs() )
3218 ::lcl_Regist( pPage
, pLay
);
3219 const SwFrame
*pFrame
= pLay
->Lower();
3222 if ( pFrame
->IsLayoutFrame() )
3223 ::RegistFlys( pPage
, static_cast<const SwLayoutFrame
*>(pFrame
) );
3224 else if ( pFrame
->GetDrawObjs() )
3225 ::lcl_Regist( pPage
, pFrame
);
3226 pFrame
= pFrame
->GetNext();
3230 /// Notify the background based on the difference between old and new rectangle
3231 void Notify( SwFlyFrame
*pFly
, SwPageFrame
*pOld
, const SwRect
&rOld
,
3232 const SwRect
* pOldPrt
)
3234 const SwRect
aFrame( pFly
->GetObjRectWithSpaces() );
3235 if ( rOld
.Pos() != aFrame
.Pos() )
3236 { // changed position, invalidate old and new area
3237 if ( rOld
.HasArea() &&
3238 rOld
.Left()+pFly
->GetFormat()->GetLRSpace().GetLeft() < FAR_AWAY
)
3240 pFly
->NotifyBackground( pOld
, rOld
, PrepareHint::FlyFrameLeave
);
3242 pFly
->NotifyBackground( pFly
->FindPageFrame(), aFrame
, PrepareHint::FlyFrameArrive
);
3244 else if ( rOld
.SSize() != aFrame
.SSize() )
3245 { // changed size, invalidate the area that was left or is now overlapped
3246 // For simplicity, we purposely invalidate a Twip even if not needed.
3248 SwViewShell
*pSh
= pFly
->getRootFrame()->GetCurrShell();
3249 if( pSh
&& rOld
.HasArea() )
3250 pSh
->InvalidateWindows( rOld
);
3252 // #i51941# - consider case that fly frame isn't
3253 // registered at the old page <pOld>
3254 SwPageFrame
* pPageFrame
= pFly
->FindPageFrame();
3255 if ( pOld
!= pPageFrame
)
3257 pFly
->NotifyBackground( pPageFrame
, aFrame
, PrepareHint::FlyFrameArrive
);
3260 if ( rOld
.Left() != aFrame
.Left() )
3262 SwRect
aTmp( rOld
);
3263 aTmp
.Union( aFrame
);
3264 aTmp
.Left( std::min(aFrame
.Left(), rOld
.Left()) );
3265 aTmp
.Right( std::max(aFrame
.Left(), rOld
.Left()) );
3266 pFly
->NotifyBackground( pOld
, aTmp
, PrepareHint::FlyFrameSizeChanged
);
3268 SwTwips nOld
= rOld
.Right();
3269 SwTwips nNew
= aFrame
.Right();
3272 SwRect
aTmp( rOld
);
3273 aTmp
.Union( aFrame
);
3274 aTmp
.Left( std::min(nNew
, nOld
) );
3275 aTmp
.Right( std::max(nNew
, nOld
) );
3276 pFly
->NotifyBackground( pOld
, aTmp
, PrepareHint::FlyFrameSizeChanged
);
3278 if ( rOld
.Top() != aFrame
.Top() )
3280 SwRect
aTmp( rOld
);
3281 aTmp
.Union( aFrame
);
3282 aTmp
.Top( std::min(aFrame
.Top(), rOld
.Top()) );
3283 aTmp
.Bottom( std::max(aFrame
.Top(), rOld
.Top()) );
3284 pFly
->NotifyBackground( pOld
, aTmp
, PrepareHint::FlyFrameSizeChanged
);
3286 nOld
= rOld
.Bottom();
3287 nNew
= aFrame
.Bottom();
3290 SwRect
aTmp( rOld
);
3291 aTmp
.Union( aFrame
);
3292 aTmp
.Top( std::min(nNew
, nOld
) );
3293 aTmp
.Bottom( std::max(nNew
, nOld
) );
3294 pFly
->NotifyBackground( pOld
, aTmp
, PrepareHint::FlyFrameSizeChanged
);
3297 else if(pOldPrt
&& *pOldPrt
!= pFly
->getFramePrintArea())
3299 bool bNotifyBackground(pFly
->GetFormat()->GetSurround().IsContour());
3301 if(!bNotifyBackground
&&
3302 pFly
->IsFlyFreeFrame() &&
3303 static_cast< const SwFlyFreeFrame
* >(pFly
)->supportsAutoContour())
3305 // RotateFlyFrame3: Also notify for FlyFrames which allow AutoContour
3306 bNotifyBackground
= true;
3309 if(bNotifyBackground
)
3312 pFly
->NotifyBackground( pFly
->FindPageFrame(), aFrame
, PrepareHint::FlyFrameArrive
);
3317 static void lcl_CheckFlowBack( SwFrame
* pFrame
, const SwRect
&rRect
)
3319 SwTwips nBottom
= rRect
.Bottom();
3322 if( pFrame
->IsLayoutFrame() )
3324 if( rRect
.Overlaps( pFrame
->getFrameArea() ) )
3325 lcl_CheckFlowBack( static_cast<SwLayoutFrame
*>(pFrame
)->Lower(), rRect
);
3327 else if( !pFrame
->GetNext() && nBottom
> pFrame
->getFrameArea().Bottom() )
3329 if( pFrame
->IsContentFrame() && static_cast<SwContentFrame
*>(pFrame
)->HasFollow() )
3330 pFrame
->InvalidateSize();
3332 pFrame
->InvalidateNextPos();
3334 pFrame
= pFrame
->GetNext();
3338 static void lcl_NotifyContent( const SdrObject
*pThis
, SwContentFrame
*pCnt
,
3339 const SwRect
&rRect
, const PrepareHint eHint
)
3341 if ( !pCnt
->IsTextFrame() )
3344 auto pTextFrame
= static_cast<SwTextFrame
*>(pCnt
);
3345 SwRect
aCntPrt( pCnt
->getFramePrintArea() );
3346 aCntPrt
.Pos() += pCnt
->getFrameArea().Pos();
3348 if (eHint
== PrepareHint::FlyFrameArrive
)
3350 SwTwips nLower
= pTextFrame
->GetLowerMarginForFlyIntersect();
3353 aCntPrt
.AddBottom(nLower
);
3357 if ( eHint
== PrepareHint::FlyFrameAttributesChanged
)
3359 // #i35640# - use given rectangle <rRect> instead
3360 // of current bound rectangle
3361 if ( aCntPrt
.Overlaps( rRect
) )
3362 pCnt
->Prepare( PrepareHint::FlyFrameAttributesChanged
);
3364 // #i23129# - only invalidate, if the text frame
3365 // printing area overlaps with the given rectangle.
3366 else if ( aCntPrt
.Overlaps( rRect
) )
3367 pCnt
->Prepare( eHint
, static_cast<void*>(&aCntPrt
.Intersection_( rRect
)) );
3368 if ( !pCnt
->GetDrawObjs() )
3371 const SwSortedObjs
&rObjs
= *pCnt
->GetDrawObjs();
3372 for (SwAnchoredObject
* pObj
: rObjs
)
3374 if ( auto pFly
= pObj
->DynCastFlyFrame() )
3376 if ( pFly
->IsFlyInContentFrame() )
3378 SwContentFrame
*pContent
= pFly
->ContainsContent();
3381 ::lcl_NotifyContent( pThis
, pContent
, rRect
, eHint
);
3382 pContent
= pContent
->GetNextContentFrame();
3389 void Notify_Background( const SdrObject
* pObj
,
3391 const SwRect
& rRect
,
3392 const PrepareHint eHint
,
3395 // If the frame was positioned correctly for the first time, do not inform the old area
3396 if ( eHint
== PrepareHint::FlyFrameLeave
&& rRect
.Top() == FAR_AWAY
)
3399 SwLayoutFrame
* pArea
;
3400 SwFlyFrame
*pFlyFrame
= nullptr;
3402 if( auto pVirtFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) )
3404 pFlyFrame
= const_cast<SwVirtFlyDrawObj
*>(pVirtFlyDrawObj
)->GetFlyFrame();
3405 pAnchor
= pFlyFrame
->AnchorFrame();
3409 pFlyFrame
= nullptr;
3410 pAnchor
= const_cast<SwFrame
*>(
3411 GetUserCall(pObj
)->GetAnchoredObj( pObj
)->GetAnchorFrame() );
3413 if( PrepareHint::FlyFrameLeave
!= eHint
&& pAnchor
->IsInFly() )
3414 pArea
= pAnchor
->FindFlyFrame();
3417 SwContentFrame
*pCnt
= nullptr;
3420 if( PrepareHint::FlyFrameArrive
!= eHint
)
3421 lcl_CheckFlowBack( pArea
, rRect
);
3423 // Only the Flys following this anchor are reacting. Thus, those do not
3424 // need to be processed.
3425 // An exception is LEAVE, since the Fly might come "from above".
3426 // If the anchor is positioned on the previous page, the whole page
3427 // needs to be processed (47722).
3428 // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
3429 // on the object positioning, the complete area has to be processed,
3430 // because content frames before the anchor frame also have to consider
3431 // the object for the text wrapping.
3432 // #i3317# - The complete area has always been
3435 pCnt
= pArea
->ContainsContent();
3438 SwFrame
*pLastTab
= nullptr;
3440 bool isValidTableBeforeAnchor(false);
3441 while ( pCnt
&& pArea
&& pArea
->IsAnLower( pCnt
) )
3443 ::lcl_NotifyContent( pObj
, pCnt
, rRect
, eHint
);
3444 if ( pCnt
->IsInTab() )
3446 SwTabFrame
*pTab
= pCnt
->FindTabFrame();
3447 if ( pTab
!= pLastTab
)
3450 isValidTableBeforeAnchor
= false;
3451 if (PrepareHint::FlyFrameArrive
== eHint
3452 && pFlyFrame
// TODO: do it for draw objects too?
3453 && pTab
->IsFollow() // table starts on previous page?
3454 // "through" means they will actually overlap anyway
3455 && css::text::WrapTextMode_THROUGH
!= pFlyFrame
->GetFormat()->GetSurround().GetSurround()
3456 // if it's anchored in footer it can't move to other page
3457 && !pAnchor
->FindFooterOrHeader())
3459 SwFrame
* pTmp(pAnchor
->GetPrev());
3464 // tdf#99460 the table shouldn't be moved by the fly
3465 isValidTableBeforeAnchor
= true;
3468 pTmp
= pTmp
->GetPrev();
3471 // #i40606# - use <GetLastBoundRect()>
3472 // instead of <GetCurrentBoundRect()>, because a recalculation
3473 // of the bounding rectangle isn't intended here.
3474 if (!isValidTableBeforeAnchor
3475 && (pTab
->getFrameArea().Overlaps(SwRect(pObj
->GetLastBoundRect())) ||
3476 pTab
->getFrameArea().Overlaps(rRect
)))
3478 if ( !pFlyFrame
|| !pFlyFrame
->IsLowerOf( pTab
) )
3479 pTab
->InvalidatePrt();
3482 SwLayoutFrame
* pCell
= pCnt
->GetUpper();
3483 // #i40606# - use <GetLastBoundRect()>
3484 // instead of <GetCurrentBoundRect()>, because a recalculation
3485 // of the bounding rectangle isn't intended here.
3486 if (!isValidTableBeforeAnchor
&& pCell
->IsCellFrame() &&
3487 ( pCell
->getFrameArea().Overlaps( SwRect(pObj
->GetLastBoundRect()) ) ||
3488 pCell
->getFrameArea().Overlaps( rRect
) ) )
3490 const SwFormatVertOrient
&rOri
= pCell
->GetFormat()->GetVertOrient();
3491 if ( text::VertOrientation::NONE
!= rOri
.GetVertOrient() )
3492 pCell
->InvalidatePrt();
3495 pCnt
= pCnt
->GetNextContentFrame();
3497 // #128702# - make code robust
3498 if ( pPage
&& pPage
->GetSortedObjs() )
3501 const SwSortedObjs
&rObjs
= *pPage
->GetSortedObjs();
3502 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
3504 if ( pAnchoredObj
->DynCastFlyFrame() != nullptr )
3506 if( pAnchoredObj
->GetDrawObj() == pObj
)
3508 SwFlyFrame
*pFly
= static_cast<SwFlyFrame
*>(pAnchoredObj
);
3509 if ( pFly
->getFrameArea().Top() == FAR_AWAY
)
3513 (!pFly
->IsLowerOf( pFlyFrame
) &&
3514 pFly
->GetVirtDrawObj()->GetOrdNumDirect() < pObj
->GetOrdNumDirect()))
3516 pCnt
= pFly
->ContainsContent();
3519 ::lcl_NotifyContent( pObj
, pCnt
, rRect
, eHint
);
3520 pCnt
= pCnt
->GetNextContentFrame();
3523 if( pFly
->IsFlyLayFrame() )
3525 if( pFly
->Lower() && pFly
->Lower()->IsColumnFrame() &&
3526 pFly
->getFrameArea().Bottom() >= rRect
.Top() &&
3527 pFly
->getFrameArea().Top() <= rRect
.Bottom() &&
3528 pFly
->getFrameArea().Right() >= rRect
.Left() &&
3529 pFly
->getFrameArea().Left() <= rRect
.Right() )
3531 pFly
->InvalidateSize();
3534 // Flys above myself might sidestep if they have an automatic
3535 // alignment. This happens independently of my attributes since
3536 // this might have been changed as well.
3537 else if ( pFly
->IsFlyAtContentFrame() &&
3538 pObj
->GetOrdNumDirect() <
3539 pFly
->GetVirtDrawObj()->GetOrdNumDirect() &&
3540 pFlyFrame
&& !pFly
->IsLowerOf( pFlyFrame
) )
3542 const SwFormatHoriOrient
&rH
= pFly
->GetFormat()->GetHoriOrient();
3543 if ( text::HoriOrientation::NONE
!= rH
.GetHoriOrient() &&
3544 text::HoriOrientation::CENTER
!= rH
.GetHoriOrient() &&
3545 ( !pFly
->IsAutoPos() || text::RelOrientation::CHAR
!= rH
.GetRelationOrient() ) &&
3546 (pFly
->getFrameArea().Bottom() >= rRect
.Top() &&
3547 pFly
->getFrameArea().Top() <= rRect
.Bottom()) )
3548 pFly
->InvalidatePos();
3553 if ( pFlyFrame
&& pAnchor
->GetUpper() && pAnchor
->IsInTab() )//MA_FLY_HEIGHT
3554 pAnchor
->GetUpper()->InvalidateSize();
3556 // #i82258# - make code robust
3557 SwViewShell
* pSh
= nullptr;
3558 if ( bInva
&& pPage
&&
3559 nullptr != (pSh
= pPage
->getRootFrame()->GetCurrShell()) )
3561 pSh
->InvalidateWindows( rRect
);
3565 /// Provides the Upper of an anchor in paragraph-bound objects. If the latter
3566 /// is a chained border or a footnote, the "virtual" Upper might be returned.
3567 const SwFrame
* GetVirtualUpper( const SwFrame
* pFrame
, const Point
& rPos
)
3569 if( pFrame
->IsTextFrame() )
3571 pFrame
= pFrame
->GetUpper();
3572 if( !pFrame
->getFrameArea().Contains( rPos
) )
3574 if( pFrame
->IsFootnoteFrame() )
3576 const SwFootnoteFrame
* pTmp
= static_cast<const SwFootnoteFrame
*>(pFrame
)->GetFollow();
3579 if( pTmp
->getFrameArea().Contains( rPos
) )
3581 pTmp
= pTmp
->GetFollow();
3586 SwFlyFrame
* pTmp
= const_cast<SwFlyFrame
*>(pFrame
->FindFlyFrame());
3589 if( pTmp
->getFrameArea().Contains( rPos
) )
3591 pTmp
= pTmp
->GetNextLink();
3599 bool Is_Lower_Of(const SwFrame
*pCurrFrame
, const SdrObject
* pObj
)
3602 const SwFrame
* pFrame
;
3603 if (const SwVirtFlyDrawObj
*pFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>(pObj
))
3605 const SwFlyFrame
* pFly
= pFlyDrawObj
->GetFlyFrame();
3606 pFrame
= pFly
->GetAnchorFrame();
3607 aPos
= pFly
->getFrameArea().Pos();
3611 pFrame
= static_cast<SwDrawContact
*>(GetUserCall(pObj
))->GetAnchorFrame(pObj
);
3612 aPos
= pObj
->GetCurrentBoundRect().TopLeft();
3614 OSL_ENSURE( pFrame
, "8-( Fly is lost in Space." );
3615 pFrame
= GetVirtualUpper( pFrame
, aPos
);
3617 { if ( pFrame
== pCurrFrame
)
3619 if( pFrame
->IsFlyFrame() )
3621 aPos
= pFrame
->getFrameArea().Pos();
3622 pFrame
= GetVirtualUpper( static_cast<const SwFlyFrame
*>(pFrame
)->GetAnchorFrame(), aPos
);
3625 pFrame
= pFrame
->GetUpper();
3630 /// provides the area of a frame in that no Fly from another area can overlap
3631 const SwFrame
*FindContext( const SwFrame
*pFrame
, SwFrameType nAdditionalContextType
)
3633 const SwFrameType nTyp
= SwFrameType::Root
| SwFrameType::Header
| SwFrameType::Footer
| SwFrameType::FtnCont
|
3634 SwFrameType::Ftn
| SwFrameType::Fly
|
3635 SwFrameType::Tab
| SwFrameType::Row
| SwFrameType::Cell
|
3636 nAdditionalContextType
;
3638 { if ( pFrame
->GetType() & nTyp
)
3640 pFrame
= pFrame
->GetUpper();
3645 bool IsFrameInSameContext( const SwFrame
*pInnerFrame
, const SwFrame
*pFrame
)
3647 const SwFrame
*pContext
= FindContext( pInnerFrame
, SwFrameType::None
);
3649 const SwFrameType nTyp
= SwFrameType::Root
| SwFrameType::Header
| SwFrameType::Footer
| SwFrameType::FtnCont
|
3650 SwFrameType::Ftn
| SwFrameType::Fly
|
3651 SwFrameType::Tab
| SwFrameType::Row
| SwFrameType::Cell
;
3653 { if ( pFrame
->GetType() & nTyp
)
3655 if( pFrame
== pContext
)
3657 if( pFrame
->IsCellFrame() )
3660 if( pFrame
->IsFlyFrame() )
3662 Point
aPos( pFrame
->getFrameArea().Pos() );
3663 pFrame
= GetVirtualUpper( static_cast<const SwFlyFrame
*>(pFrame
)->GetAnchorFrame(), aPos
);
3666 pFrame
= pFrame
->GetUpper();
3672 static SwTwips
lcl_CalcCellRstHeight( SwLayoutFrame
*pCell
)
3674 SwFrame
*pLow
= pCell
->Lower();
3675 if ( pLow
&& (pLow
->IsContentFrame() || pLow
->IsSctFrame()) )
3677 tools::Long nHeight
= 0, nFlyAdd
= 0;
3680 tools::Long nLow
= pLow
->getFrameArea().Height();
3681 if( pLow
->IsTextFrame() && static_cast<SwTextFrame
*>(pLow
)->IsUndersized() )
3682 nLow
+= static_cast<SwTextFrame
*>(pLow
)->GetParHeight()-pLow
->getFramePrintArea().Height();
3683 else if( pLow
->IsSctFrame() && static_cast<SwSectionFrame
*>(pLow
)->IsUndersized() )
3684 nLow
+= static_cast<SwSectionFrame
*>(pLow
)->Undersize();
3685 nFlyAdd
= std::max( tools::Long(0), nFlyAdd
- nLow
);
3686 nFlyAdd
= std::max( nFlyAdd
, ::CalcHeightWithFlys( pLow
) );
3688 pLow
= pLow
->GetNext();
3693 // The border cannot be calculated based on PrtArea and Frame, since both can be invalid.
3694 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), pCell
);
3695 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
3696 nHeight
+= rAttrs
.CalcTop() + rAttrs
.CalcBottom();
3698 return pCell
->getFrameArea().Height() - nHeight
;
3702 tools::Long nRstHeight
= 0;
3703 while (pLow
&& pLow
->IsLayoutFrame())
3705 nRstHeight
+= ::CalcRowRstHeight(static_cast<SwLayoutFrame
*>(pLow
));
3706 pLow
= pLow
->GetNext();
3712 SwTwips
CalcRowRstHeight( SwLayoutFrame
*pRow
)
3714 SwFrame
*pLow
= pRow
->Lower();
3715 if (!(pLow
&& pLow
->IsLayoutFrame()))
3719 SwTwips nRstHeight
= LONG_MAX
;
3720 while (pLow
&& pLow
->IsLayoutFrame())
3722 nRstHeight
= std::min(nRstHeight
, ::lcl_CalcCellRstHeight(static_cast<SwLayoutFrame
*>(pLow
)));
3723 pLow
= pLow
->GetNext();
3728 const SwFrame
* FindPage( const SwRect
&rRect
, const SwFrame
*pPage
)
3730 if ( !rRect
.Overlaps( pPage
->getFrameArea() ) )
3732 const SwRootFrame
* pRootFrame
= static_cast<const SwRootFrame
*>(pPage
->GetUpper());
3733 const SwFrame
* pTmpPage
= pRootFrame
? pRootFrame
->GetPageAtPos( rRect
.TopLeft(), &rRect
.SSize(), true ) : nullptr;
3743 class SwFrameHolder
: private SfxListener
3747 virtual void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
) override
;
3754 void SetFrame( SwFrame
* pHold
);
3755 SwFrame
* GetFrame() { return m_pFrame
; }
3757 bool IsSet() const { return m_bSet
; }
3762 void SwFrameHolder::SetFrame( SwFrame
* pHold
)
3765 if (m_pFrame
!= pHold
)
3768 EndListening(*m_pFrame
);
3769 StartListening(*pHold
);
3774 void SwFrameHolder::Reset()
3777 EndListening(*m_pFrame
);
3782 void SwFrameHolder::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
3784 if (rHint
.GetId() == SfxHintId::Dying
&& &rBC
== m_pFrame
)
3790 SwFrame
* GetFrameOfModify(SwRootFrame
const*const pLayout
, sw::BroadcastingModify
const& rMod
,
3791 SwFrameType
const nFrameType
, SwPosition
const*const pPos
,
3792 std::pair
<Point
, bool> const*const pViewPosAndCalcFrame
)
3794 SwFrame
*pMinFrame
= nullptr, *pTmpFrame
;
3795 SwFrameHolder aHolder
;
3797 bool bClientIterChanged
= false;
3799 SwIterator
<SwFrame
, sw::BroadcastingModify
, sw::IteratorMode::UnwrapMulti
> aIter(rMod
);
3801 pMinFrame
= nullptr;
3803 sal_uInt64 nMinDist
= 0;
3804 bClientIterChanged
= false;
3806 for( pTmpFrame
= aIter
.First(); pTmpFrame
; pTmpFrame
= aIter
.Next() )
3808 if( pTmpFrame
->GetType() & nFrameType
&&
3809 ( !pLayout
|| pLayout
== pTmpFrame
->getRootFrame() ) &&
3810 (!pTmpFrame
->IsFlowFrame() ||
3811 !SwFlowFrame::CastFlowFrame( pTmpFrame
)->IsFollow() ))
3813 if (pViewPosAndCalcFrame
)
3815 // watch for Frame being deleted
3817 aHolder
.SetFrame( pMinFrame
);
3821 if (pViewPosAndCalcFrame
->second
)
3823 // tdf#108118 prevent recursion
3824 DisableCallbackAction
a(*pTmpFrame
->getRootFrame());
3825 // - format parent Writer
3826 // fly frame, if it isn't been formatted yet.
3827 // Note: The Writer fly frame could be the frame itself.
3828 SwFlyFrame
* pFlyFrame( pTmpFrame
->FindFlyFrame() );
3830 pFlyFrame
->getFrameArea().Pos().X() == FAR_AWAY
&&
3831 pFlyFrame
->getFrameArea().Pos().Y() == FAR_AWAY
)
3833 SwObjectFormatter::FormatObj( *pFlyFrame
);
3835 pTmpFrame
->Calc(pLayout
? pLayout
->GetCurrShell()->GetOut() : nullptr);
3838 // aIter.IsChanged checks if the current pTmpFrame has been deleted while
3839 // it is the current iterator
3840 // FrameHolder watches for deletion of the current pMinFrame
3841 if( aIter
.IsChanged() || ( aHolder
.IsSet() && !aHolder
.GetFrame() ) )
3843 // restart iteration
3844 bClientIterChanged
= true;
3848 // for Flys go via the parent if the Fly is not yet "formatted"
3849 if (!pViewPosAndCalcFrame
->second
&&
3850 pTmpFrame
->GetType() & SwFrameType::Fly
&&
3851 static_cast<SwFlyFrame
*>(pTmpFrame
)->GetAnchorFrame() &&
3852 FAR_AWAY
== pTmpFrame
->getFrameArea().Pos().getX() &&
3853 FAR_AWAY
== pTmpFrame
->getFrameArea().Pos().getY() )
3854 aCalcRect
= static_cast<SwFlyFrame
*>(pTmpFrame
)->GetAnchorFrame()->getFrameArea();
3856 aCalcRect
= pTmpFrame
->getFrameArea();
3858 if (aCalcRect
.Contains(pViewPosAndCalcFrame
->first
))
3860 pMinFrame
= pTmpFrame
;
3864 // Point not in rectangle. Compare distances:
3865 const Point aCalcRectCenter
= aCalcRect
.Center();
3866 const Point aDiff
= aCalcRectCenter
- pViewPosAndCalcFrame
->first
;
3867 const sal_uInt64 nCurrentDist
= sal_Int64(aDiff
.getX()) * sal_Int64(aDiff
.getX()) + sal_Int64(aDiff
.getY()) * sal_Int64(aDiff
.getY()); // opt: no sqrt
3868 if ( !pMinFrame
|| nCurrentDist
< nMinDist
)
3870 pMinFrame
= pTmpFrame
;
3871 nMinDist
= nCurrentDist
;
3876 // if no pViewPosAndCalcFrame is provided, take the first one
3877 pMinFrame
= pTmpFrame
;
3882 } while( bClientIterChanged
);
3884 if( pPos
&& pMinFrame
&& pMinFrame
->IsTextFrame() )
3885 return static_cast<SwTextFrame
*>(pMinFrame
)->GetFrameAtPos( *pPos
);
3890 bool IsExtraData( const SwDoc
*pDoc
)
3892 const SwLineNumberInfo
&rInf
= pDoc
->GetLineNumberInfo();
3893 if (rInf
.IsPaintLineNumbers() ||
3894 rInf
.IsCountInFlys() ||
3895 (static_cast<sal_Int16
>(SW_MOD()->GetRedlineMarkPos()) != text::HoriOrientation::NONE
&&
3896 !pDoc
->getIDocumentRedlineAccess().GetRedlineTable().empty()))
3901 const SwEditShell
* pSh
= pDoc
->GetEditShell();
3902 const SwViewOption
* pViewOptions
= pSh
? pSh
->GetViewOptions() : nullptr;
3903 return pViewOptions
&& pViewOptions
->IsShowOutlineContentVisibilityButton();
3906 // OD 22.09.2003 #110978#
3907 SwRect
SwPageFrame::PrtWithoutHeaderAndFooter() const
3909 SwRect
aPrtWithoutHeaderFooter( getFramePrintArea() );
3910 aPrtWithoutHeaderFooter
.Pos() += getFrameArea().Pos();
3912 const SwFrame
* pLowerFrame
= Lower();
3913 while ( pLowerFrame
)
3915 // Note: independent on text direction page header and page footer are
3916 // always at top respectively at bottom of the page frame.
3917 if ( pLowerFrame
->IsHeaderFrame() )
3919 aPrtWithoutHeaderFooter
.AddTop( pLowerFrame
->getFrameArea().Height() );
3921 if ( pLowerFrame
->IsFooterFrame() )
3923 aPrtWithoutHeaderFooter
.AddBottom( - pLowerFrame
->getFrameArea().Height() );
3926 pLowerFrame
= pLowerFrame
->GetNext();
3929 return aPrtWithoutHeaderFooter
;
3932 /** method to determine the spacing values of a frame
3934 OD 2004-03-10 #i28701#
3935 OD 2009-08-28 #i102458#
3936 Add output parameter <obIsLineSpacingProportional>
3938 void GetSpacingValuesOfFrame( const SwFrame
& rFrame
,
3939 SwTwips
& onLowerSpacing
,
3940 SwTwips
& onLineSpacing
,
3941 bool& obIsLineSpacingProportional
,
3942 bool bIdenticalStyles
)
3944 if ( !rFrame
.IsFlowFrame() )
3951 const SvxULSpaceItem
& rULSpace
= rFrame
.GetAttrSet()->GetULSpace();
3952 // check contextual spacing if the style of actual and next paragraphs are identical
3953 if (bIdenticalStyles
)
3954 onLowerSpacing
= (rULSpace
.GetContext() ? 0 : rULSpace
.GetLower());
3956 onLowerSpacing
= rULSpace
.GetLower();
3959 obIsLineSpacingProportional
= false;
3960 if ( rFrame
.IsTextFrame() )
3962 onLineSpacing
= static_cast<const SwTextFrame
&>(rFrame
).GetLineSpace();
3963 obIsLineSpacingProportional
=
3964 onLineSpacing
!= 0 &&
3965 static_cast<const SwTextFrame
&>(rFrame
).GetLineSpace( true ) == 0;
3968 OSL_ENSURE( onLowerSpacing
>= 0 && onLineSpacing
>= 0,
3969 "<GetSpacingValuesOfFrame(..)> - spacing values aren't positive!" );
3973 /// get the content of the table cell, skipping content from nested tables
3974 const SwContentFrame
* GetCellContent( const SwLayoutFrame
& rCell
)
3976 const SwContentFrame
* pContent
= rCell
.ContainsContent();
3977 const SwTabFrame
* pTab
= rCell
.FindTabFrame();
3979 while ( pContent
&& rCell
.IsAnLower( pContent
) )
3981 const SwTabFrame
* pTmpTab
= pContent
->FindTabFrame();
3982 if ( pTmpTab
!= pTab
)
3984 SwFrame
const*const pTmp
= pTmpTab
->FindLastContentOrTable();
3987 pContent
= pTmp
->FindNextCnt();
4000 SwDeletionChecker::SwDeletionChecker(const SwFrame
* pFrame
)
4003 ? pFrame
->IsTextFrame()
4004 // sw_redlinehide: GetDep() may be a member of SwTextFrame!
4005 ? static_cast<SwTextFrame
const*>(pFrame
)->GetTextNodeFirst()
4006 : const_cast<SwFrame
*>(pFrame
)->GetDep()
4011 /// Can be used to check if a frame has been deleted
4012 bool SwDeletionChecker::HasBeenDeleted() const
4014 if ( !mpFrame
|| !mpRegIn
)
4017 SwIterator
<SwFrame
, sw::BroadcastingModify
, sw::IteratorMode::UnwrapMulti
> aIter(*mpRegIn
);
4018 SwFrame
* pLast
= aIter
.First();
4021 if ( pLast
== mpFrame
)
4023 pLast
= aIter
.Next();
4029 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */