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 <svx/svdmodel.hxx>
21 #include <svx/svdpage.hxx>
22 #include <editeng/brushitem.hxx>
23 #include <editeng/shaditem.hxx>
24 #include <editeng/ulspitem.hxx>
25 #include <editeng/boxitem.hxx>
26 #include <editeng/lspcitem.hxx>
27 #include <editeng/fhgtitem.hxx>
28 #include <sal/log.hxx>
30 #include <drawdoc.hxx>
31 #include <fmtornt.hxx>
32 #include <fmthdft.hxx>
33 #include <fmtfsize.hxx>
34 #include <fmtsrnd.hxx>
36 #include <lineinfo.hxx>
37 #include <swmodule.hxx>
38 #include <pagefrm.hxx>
41 #include <viewimp.hxx>
42 #include <viewopt.hxx>
43 #include <dflyobj.hxx>
44 #include <dcontact.hxx>
46 #include <frmtool.hxx>
51 #include <notxtfrm.hxx>
52 #include <flyfrms.hxx>
54 #include <pagedesc.hxx>
55 #include <section.hxx>
56 #include <sectfrm.hxx>
57 #include <node2lay.hxx>
60 #include "layhelp.hxx"
61 #include <laycache.hxx>
62 #include <rootfrm.hxx>
64 #include <redline.hxx>
65 #include <sortedobjs.hxx>
66 #include <objectformatter.hxx>
70 #include <DocumentSettingManager.hxx>
71 #include <IDocumentDrawModelAccess.hxx>
72 #include <IDocumentTimerAccess.hxx>
73 #include <IDocumentRedlineAccess.hxx>
74 #include <IDocumentFieldsAccess.hxx>
75 #include <IDocumentState.hxx>
76 #include <boost/circular_buffer.hpp>
77 #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
79 using namespace ::com::sun::star
;
81 bool bObjsDirect
= true;
82 bool bDontCreateObjects
= false;
83 bool bSetCompletePaintOnInvalidate
= false;
85 sal_uInt8
StackHack::nCnt
= 0;
86 bool StackHack::bLocked
= false;
88 SwFrameNotify::SwFrameNotify( SwFrame
*pF
) :
90 maFrame( pF
->getFrameArea() ),
91 maPrt( pF
->getFramePrintArea() ),
93 mbValidSize( pF
->isFrameAreaSizeValid() )
95 if ( pF
->IsTextFrame() )
97 mnFlyAnchorOfst
= static_cast<SwTextFrame
*>(pF
)->GetBaseOfstForFly( true );
98 mnFlyAnchorOfstNoWrap
= static_cast<SwTextFrame
*>(pF
)->GetBaseOfstForFly( false );
103 mnFlyAnchorOfstNoWrap
= 0;
106 mbHadFollow
= pF
->IsContentFrame() && static_cast<SwContentFrame
*>(pF
)->GetFollow();
109 SwFrameNotify::~SwFrameNotify() COVERITY_NOEXCEPT_FALSE
111 SwRectFnSet
aRectFnSet(mpFrame
);
112 const bool bAbsP
= aRectFnSet
.PosDiff(maFrame
, mpFrame
->getFrameArea());
113 const bool bChgWidth
=
114 aRectFnSet
.GetWidth(maFrame
) != aRectFnSet
.GetWidth(mpFrame
->getFrameArea());
115 const bool bChgHeight
=
116 aRectFnSet
.GetHeight(maFrame
)!=aRectFnSet
.GetHeight(mpFrame
->getFrameArea());
117 const bool bChgFlyBasePos
= mpFrame
->IsTextFrame() &&
118 ( ( mnFlyAnchorOfst
!= static_cast<SwTextFrame
*>(mpFrame
)->GetBaseOfstForFly( true ) ) ||
119 ( mnFlyAnchorOfstNoWrap
!= static_cast<SwTextFrame
*>(mpFrame
)->GetBaseOfstForFly( false ) ) );
121 if ( mpFrame
->IsFlowFrame() && !mpFrame
->IsInFootnote() )
123 SwFlowFrame
*pFlow
= SwFlowFrame::CastFlowFrame( mpFrame
);
125 if ( !pFlow
->IsFollow() )
127 if ( !mpFrame
->GetIndPrev() )
131 SwFrame
*pPre
= mpFrame
->FindPrev();
132 if ( pPre
&& pPre
->IsFlowFrame() )
134 // 1. pPre wants to keep with me:
135 bool bInvalidPrePos
= SwFlowFrame::CastFlowFrame(pPre
)->IsKeep(pPre
->GetAttrSet()->GetKeep(), pPre
->GetBreakItem())
136 && pPre
->GetIndPrev();
138 // 2. pPre is a table and the last row wants to keep with me:
139 if ( !bInvalidPrePos
&& pPre
->IsTabFrame() )
141 SwTabFrame
* pPreTab
= static_cast<SwTabFrame
*>(pPre
);
142 if ( pPreTab
->GetFormat()->GetDoc()->GetDocumentSettingManager().get(DocumentSettingId::TABLE_ROW_KEEP
) )
144 SwRowFrame
* pLastRow
= static_cast<SwRowFrame
*>(pPreTab
->GetLastLower());
145 if ( pLastRow
&& pLastRow
->ShouldRowKeepWithNext() )
146 bInvalidPrePos
= true;
150 if ( bInvalidPrePos
)
151 pPre
->InvalidatePos();
155 else if ( !pFlow
->HasFollow() )
157 long nOldHeight
= aRectFnSet
.GetHeight(maFrame
);
158 long nNewHeight
= aRectFnSet
.GetHeight(mpFrame
->getFrameArea());
159 if( (nOldHeight
> nNewHeight
) || (!nOldHeight
&& nNewHeight
) )
167 mpFrame
->SetCompletePaint();
169 SwFrame
* pNxt
= mpFrame
->GetIndNext();
170 // #121888# - skip empty section frames
172 pNxt
->IsSctFrame() && !static_cast<SwSectionFrame
*>(pNxt
)->GetSection() )
174 pNxt
= pNxt
->GetIndNext();
178 pNxt
->InvalidatePos();
181 // #104100# - correct condition for setting retouche
182 // flag for vertical layout.
183 if( mpFrame
->IsRetoucheFrame() &&
184 aRectFnSet
.TopDist( maFrame
, aRectFnSet
.GetTop(mpFrame
->getFrameArea()) ) > 0 )
186 mpFrame
->SetRetouche();
189 // A fresh follow frame does not have to be invalidated, because
190 // it is already formatted:
191 if ( mbHadFollow
|| !mpFrame
->IsContentFrame() || !static_cast<SwContentFrame
*>(mpFrame
)->GetFollow() )
193 if ( !mpFrame
->IsTabFrame() || !static_cast<SwTabFrame
*>(mpFrame
)->GetFollow() )
194 mpFrame
->InvalidateNextPos();
199 //For each resize of the background graphics is a repaint necessary.
200 const bool bPrtWidth
=
201 aRectFnSet
.GetWidth(maPrt
) != aRectFnSet
.GetWidth(mpFrame
->getFramePrintArea());
202 const bool bPrtHeight
=
203 aRectFnSet
.GetHeight(maPrt
)!=aRectFnSet
.GetHeight(mpFrame
->getFramePrintArea());
204 if ( bPrtWidth
|| bPrtHeight
)
206 bool bUseNewFillProperties(false);
207 if (mpFrame
->supportsFullDrawingLayerFillAttributeSet())
209 drawinglayer::attribute::SdrAllFillAttributesHelperPtr
aFillAttributes(mpFrame
->getSdrAllFillAttributesHelper());
210 if(aFillAttributes
.get() && aFillAttributes
->isUsed())
212 bUseNewFillProperties
= true;
213 // use SetCompletePaint if needed
214 if(aFillAttributes
->needCompleteRepaint())
216 mpFrame
->SetCompletePaint();
220 if (!bUseNewFillProperties
)
222 const SvxGraphicPosition ePos
= mpFrame
->GetAttrSet()->GetBackground().GetGraphicPos();
223 if(GPOS_NONE
!= ePos
&& GPOS_TILED
!= ePos
)
224 mpFrame
->SetCompletePaint();
229 // #97597# - consider case that *only* margins between
230 // frame and printing area has changed. Then, frame has to be repainted,
231 // in order to force paint of the margin areas.
232 if ( !bAbsP
&& (bChgWidth
|| bChgHeight
) )
234 mpFrame
->SetCompletePaint();
238 const bool bPrtP
= aRectFnSet
.PosDiff( maPrt
, mpFrame
->getFramePrintArea() );
239 if ( bAbsP
|| bPrtP
|| bChgWidth
|| bChgHeight
||
240 bPrtWidth
|| bPrtHeight
|| bChgFlyBasePos
)
242 if( mpFrame
->IsAccessibleFrame() )
244 SwRootFrame
*pRootFrame
= mpFrame
->getRootFrame();
245 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
246 pRootFrame
->GetCurrShell() )
248 pRootFrame
->GetCurrShell()->Imp()->MoveAccessibleFrame( mpFrame
, maFrame
);
252 // Notification of anchored objects
253 if ( mpFrame
->GetDrawObjs() )
255 const SwSortedObjs
&rObjs
= *mpFrame
->GetDrawObjs();
256 SwPageFrame
* pPageFrame
= nullptr;
257 for (SwAnchoredObject
* pObj
: rObjs
)
259 // OD 2004-03-31 #i26791# - no general distinction between
260 // Writer fly frames and drawing objects
261 bool bNotify
= false;
262 bool bNotifySize
= false;
263 SwContact
* pContact
= ::GetUserCall( pObj
->GetDrawObj() );
264 const bool bAnchoredAsChar
= pContact
->ObjAnchoredAsChar();
265 if ( !bAnchoredAsChar
)
267 // Notify object, which aren't anchored as-character:
269 // always notify objects, if frame position has changed
270 // or if the object is to-page|to-fly anchored.
272 pContact
->ObjAnchoredAtPage() ||
273 pContact
->ObjAnchoredAtFly() )
277 // assure that to-fly anchored Writer fly frames are
278 // registered at the correct page frame, if frame
279 // position has changed.
280 if ( bAbsP
&& pContact
->ObjAnchoredAtFly() &&
281 dynamic_cast<const SwFlyFrame
*>( pObj
) != nullptr )
283 // determine to-fly anchored Writer fly frame
284 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrame
*>(pObj
);
285 // determine page frame of to-fly anchored
287 SwPageFrame
* pFlyPageFrame
= pFlyFrame
->FindPageFrame();
288 // determine page frame, if needed.
291 pPageFrame
= mpFrame
->FindPageFrame();
293 if ( pPageFrame
!= pFlyPageFrame
)
295 OSL_ENSURE( pFlyPageFrame
, "~SwFrameNotify: Fly from Nowhere" );
297 pFlyPageFrame
->MoveFly( pFlyFrame
, pPageFrame
);
299 pPageFrame
->AppendFlyToPage( pFlyFrame
);
303 // otherwise the objects are notified in dependence to
304 // its positioning and alignment
307 const SwFormatVertOrient
& rVert
=
308 pContact
->GetFormat()->GetVertOrient();
309 if ( ( rVert
.GetVertOrient() == text::VertOrientation::CENTER
||
310 rVert
.GetVertOrient() == text::VertOrientation::BOTTOM
||
311 rVert
.GetRelationOrient() == text::RelOrientation::PRINT_AREA
) &&
312 ( bChgHeight
|| bPrtHeight
) )
318 const SwFormatHoriOrient
& rHori
=
319 pContact
->GetFormat()->GetHoriOrient();
320 if ( ( rHori
.GetHoriOrient() != text::HoriOrientation::NONE
||
321 rHori
.GetRelationOrient()== text::RelOrientation::PRINT_AREA
||
322 rHori
.GetRelationOrient()== text::RelOrientation::FRAME
) &&
323 ( bChgWidth
|| bPrtWidth
|| bChgFlyBasePos
) )
330 else if ( bPrtWidth
)
332 // Notify as-character anchored objects, if printing area
333 // width has changed.
338 // perform notification via the corresponding invalidations
341 if ( dynamic_cast<const SwFlyFrame
*>( pObj
) != nullptr )
343 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrame
*>(pObj
);
345 pFlyFrame
->InvalidateSize_();
346 // #115759# - no invalidation of
347 // position for as-character anchored objects.
348 if ( !bAnchoredAsChar
)
350 pFlyFrame
->InvalidatePos_();
352 pFlyFrame
->Invalidate_();
354 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pObj
) != nullptr )
356 // #115759# - no invalidation of
357 // position for as-character anchored objects.
358 if ( !bAnchoredAsChar
)
360 pObj
->InvalidateObjPos();
365 OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - unknown anchored object type." );
371 else if( mpFrame
->IsTextFrame() && mbValidSize
!= mpFrame
->isFrameAreaSizeValid() )
373 SwRootFrame
*pRootFrame
= mpFrame
->getRootFrame();
374 if( pRootFrame
&& pRootFrame
->IsAnyShellAccessible() &&
375 pRootFrame
->GetCurrShell() )
377 pRootFrame
->GetCurrShell()->Imp()->InvalidateAccessibleFrameContent( mpFrame
);
381 // #i9046# Automatic frame width
382 SwFlyFrame
* pFly
= nullptr;
383 // #i35879# Do not trust the inf flags. pFrame does not
384 // necessarily have to have an upper!
385 if ( !mpFrame
->IsFlyFrame() && nullptr != ( pFly
= mpFrame
->ImplFindFlyFrame() ) )
388 // no invalidation of columned Writer fly frames, because automatic
389 // width doesn't make sense for such Writer fly frames.
390 if ( pFly
->Lower() && !pFly
->Lower()->IsColumnFrame() )
392 const SwFormatFrameSize
&rFrameSz
= pFly
->GetFormat()->GetFrameSize();
394 // This could be optimized. Basically the fly frame only has to
395 // be invalidated, if the first line of pFrame (if pFrame is a content
396 // frame, for other frame types it's the print area) has changed its
397 // size and pFrame was responsible for the current width of pFly. On
398 // the other hand, this is only rarely used and re-calculation of
399 // the fly frame does not cause too much trouble. So we keep it this
401 if ( ATT_FIX_SIZE
!= rFrameSz
.GetWidthSizeType() )
403 // #i50668#, #i50998# - invalidation of position
404 // of as-character anchored fly frames not needed and can cause
406 if ( dynamic_cast<const SwFlyInContentFrame
*>( pFly
) == nullptr )
408 pFly
->InvalidatePos();
410 pFly
->InvalidateSize();
416 SwLayNotify::SwLayNotify( SwLayoutFrame
*pLayFrame
) :
417 SwFrameNotify( pLayFrame
),
418 m_bLowersComplete( false )
422 // OD 2004-05-11 #i28701# - local method to invalidate the position of all
423 // frames inclusive its floating screen objects, which are lowers of the given
425 static void lcl_InvalidatePosOfLowers( SwLayoutFrame
& _rLayoutFrame
)
427 if( _rLayoutFrame
.IsFlyFrame() && _rLayoutFrame
.GetDrawObjs() )
429 _rLayoutFrame
.InvalidateObjs( false );
432 SwFrame
* pLowerFrame
= _rLayoutFrame
.Lower();
433 while ( pLowerFrame
)
435 pLowerFrame
->InvalidatePos();
436 if ( pLowerFrame
->IsTextFrame() )
438 static_cast<SwTextFrame
*>(pLowerFrame
)->Prepare( PREP_POS_CHGD
);
440 else if ( pLowerFrame
->IsTabFrame() )
442 pLowerFrame
->InvalidatePrt();
445 pLowerFrame
->InvalidateObjs( false );
447 pLowerFrame
= pLowerFrame
->GetNext();
451 SwLayNotify::~SwLayNotify()
453 SwLayoutFrame
*pLay
= static_cast<SwLayoutFrame
*>(mpFrame
);
454 SwRectFnSet
aRectFnSet(pLay
);
455 bool bNotify
= false;
456 if ( pLay
->getFramePrintArea().SSize() != maPrt
.SSize() )
458 if ( !IsLowersComplete() )
462 if ( pLay
->IsRowFrame() )
465 long nNew
= aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
466 if( nNew
!= aRectFnSet
.GetHeight(maPrt
) )
467 static_cast<SwRowFrame
*>(pLay
)->AdjustCells( nNew
, true);
468 if( aRectFnSet
.GetWidth(pLay
->getFramePrintArea())
469 != aRectFnSet
.GetWidth(maPrt
) )
470 static_cast<SwRowFrame
*>(pLay
)->AdjustCells( 0, false );
474 //Proportional adoption of the internal.
475 //1. If the formatted is no Fly
476 //2. If he contains no columns
477 //3. If the Fly has a fixed height and the columns
479 // Hoehe danebenliegen.
480 //4. Never at SectionFrames.
482 if( pLay
->IsFlyFrame() )
486 bLow
= !pLay
->Lower()->IsColumnFrame() ||
487 aRectFnSet
.GetHeight(pLay
->Lower()->getFrameArea())
488 != aRectFnSet
.GetHeight(pLay
->getFramePrintArea());
493 else if( pLay
->IsSctFrame() )
497 if( pLay
->Lower()->IsColumnFrame() && pLay
->Lower()->GetNext() )
498 bLow
= pLay
->Lower()->getFrameArea().Height() != pLay
->getFramePrintArea().Height();
500 bLow
= pLay
->getFramePrintArea().Width() != maPrt
.Width();
505 else if( pLay
->IsFooterFrame() && !pLay
->HasFixSize() )
506 bLow
= pLay
->getFramePrintArea().Width() != maPrt
.Width();
512 pLay
->ChgLowersProp( maPrt
.SSize() );
514 // If the PrtArea has been extended, it might be possible that the chain of parts
515 // can take another frame. As a result, the "possible right one" needs to be
516 // invalidated. This only pays off if this or its Uppers are moveable sections.
517 // A PrtArea has been extended if width or height are larger than before.
518 if ( (pLay
->getFramePrintArea().Height() > maPrt
.Height() ||
519 pLay
->getFramePrintArea().Width() > maPrt
.Width()) &&
520 (pLay
->IsMoveable() || pLay
->IsFlyFrame()) )
522 SwFrame
*pTmpFrame
= pLay
->Lower();
523 if ( pTmpFrame
&& pTmpFrame
->IsFlowFrame() )
525 while ( pTmpFrame
->GetNext() )
526 pTmpFrame
= pTmpFrame
->GetNext();
527 pTmpFrame
->InvalidateNextPos();
532 //EXPENSIVE!! But how we do it more elegant?
534 pLay
->InvaPercentLowers( pLay
->getFramePrintArea().Height() - maPrt
.Height() );
536 if ( pLay
->IsTabFrame() )
537 //So that _only_ the shadow is drawn while resizing.
538 static_cast<SwTabFrame
*>(pLay
)->SetComplete();
541 const SwViewShell
*pSh
= pLay
->getRootFrame()->GetCurrShell();
542 if( !( pSh
&& pSh
->GetViewOptions()->getBrowseMode() ) ||
543 !(pLay
->GetType() & (SwFrameType::Body
| SwFrameType::Page
)) )
544 //Thereby the subordinates are retouched clean.
545 //Example problem: Take the Flys with the handles and downsize.
546 //Not for body and page, otherwise it flickers when loading HTML.
547 pLay
->SetCompletePaint();
550 //Notify Lower if the position has changed.
551 const bool bPrtPos
= aRectFnSet
.PosDiff( maPrt
, pLay
->getFramePrintArea() );
552 const bool bPos
= bPrtPos
|| aRectFnSet
.PosDiff( maFrame
, pLay
->getFrameArea() );
553 const bool bSize
= pLay
->getFrameArea().SSize() != maFrame
.SSize();
555 if ( bPos
&& pLay
->Lower() && !IsLowersComplete() )
557 pLay
->Lower()->InvalidatePos();
558 SwFootnoteFrame
* pFtnFrame
= pLay
->Lower()->IsFootnoteFrame() ?
559 static_cast<SwFootnoteFrame
*>(pLay
->Lower()) : nullptr;
560 SwFrame
* pFtnLower
= pFtnFrame
? pFtnFrame
->Lower() : nullptr;
562 pFtnLower
->InvalidatePos();
566 pLay
->SetCompletePaint();
568 //Inform the Follower if the SSize has changed.
571 if( pLay
->GetNext() )
573 if ( pLay
->GetNext()->IsLayoutFrame() )
574 pLay
->GetNext()->InvalidatePos_();
576 pLay
->GetNext()->InvalidatePos();
578 else if( pLay
->IsSctFrame() )
579 pLay
->InvalidateNextPos();
581 if ( !IsLowersComplete() &&
582 !(pLay
->GetType()&(SwFrameType::Fly
|SwFrameType::Section
) &&
583 pLay
->Lower() && pLay
->Lower()->IsColumnFrame()) &&
585 !(pLay
->GetType() & (SwFrameType::Row
|SwFrameType::Tab
|SwFrameType::FtnCont
|SwFrameType::Page
|SwFrameType::Root
)))
587 // #i44016# - force unlock of position of lower objects.
588 // #i43913# - no unlock of position of objects,
589 // if <pLay> is a cell frame, and its table frame resp. its parent table
591 // #i47458# - force unlock of position of lower objects,
592 // only if position of layout frame has changed.
593 bool bUnlockPosOfObjs( bPos
);
594 if ( bUnlockPosOfObjs
&& pLay
->IsCellFrame() )
596 SwTabFrame
* pTabFrame( pLay
->FindTabFrame() );
598 ( pTabFrame
->IsJoinLocked() ||
599 ( pTabFrame
->IsFollow() &&
600 pTabFrame
->FindMaster()->IsJoinLocked() ) ) )
602 bUnlockPosOfObjs
= false;
605 // #i49383# - check for footnote frame, if unlock
606 // of position of lower objects is allowed.
607 else if ( bUnlockPosOfObjs
&& pLay
->IsFootnoteFrame() )
609 bUnlockPosOfObjs
= static_cast<SwFootnoteFrame
*>(pLay
)->IsUnlockPosOfLowerObjs();
611 // #i51303# - no unlock of object positions for sections
612 else if ( bUnlockPosOfObjs
&& pLay
->IsSctFrame() )
614 bUnlockPosOfObjs
= false;
616 pLay
->NotifyLowerObjs( bUnlockPosOfObjs
);
618 if ( bPos
&& pLay
->IsFootnoteFrame() && pLay
->Lower() )
620 // OD 2004-05-11 #i28701#
621 ::lcl_InvalidatePosOfLowers( *pLay
);
623 if( ( bPos
|| bSize
) && pLay
->IsFlyFrame() && static_cast<SwFlyFrame
*>(pLay
)->GetAnchorFrame()
624 && static_cast<SwFlyFrame
*>(pLay
)->GetAnchorFrame()->IsFlyFrame() )
625 static_cast<SwFlyFrame
*>(pLay
)->AnchorFrame()->InvalidateSize();
628 SwFlyNotify::SwFlyNotify( SwFlyFrame
*pFlyFrame
) :
629 SwLayNotify( pFlyFrame
),
630 // #115759# - keep correct page frame - the page frame
631 // the Writer fly frame is currently registered at.
632 pOldPage( pFlyFrame
->GetPageFrame() ),
633 aFrameAndSpace( pFlyFrame
->GetObjRectWithSpaces() )
637 SwFlyNotify::~SwFlyNotify()
639 SwFlyFrame
*pFly
= static_cast<SwFlyFrame
*>(mpFrame
);
640 if ( pFly
->IsNotifyBack() )
642 SwViewShell
*pSh
= pFly
->getRootFrame()->GetCurrShell();
643 SwViewShellImp
*pImp
= pSh
? pSh
->Imp() : nullptr;
644 if ( !pImp
|| !pImp
->IsAction() || !pImp
->GetLayAction().IsAgain() )
646 //If in the LayAction the IsAgain is set it can be
647 //that the old page is destroyed in the meantime!
648 ::Notify( pFly
, pOldPage
, aFrameAndSpace
, &maPrt
);
649 // #i35640# - additional notify anchor text frame,
650 // if Writer fly frame has changed its page
651 if ( pFly
->GetAnchorFrame()->IsTextFrame() &&
652 pFly
->GetPageFrame() != pOldPage
)
654 pFly
->AnchorFrame()->Prepare( PREP_FLY_LEAVE
);
657 pFly
->ResetNotifyBack();
660 //Have the size or the position changed,
661 //so should the view know this.
662 SwRectFnSet
aRectFnSet(pFly
);
663 const bool bPosChgd
= aRectFnSet
.PosDiff( maFrame
, pFly
->getFrameArea() );
664 const bool bFrameChgd
= pFly
->getFrameArea().SSize() != maFrame
.SSize();
665 const bool bPrtChgd
= maPrt
!= pFly
->getFramePrintArea();
666 if ( bPosChgd
|| bFrameChgd
|| bPrtChgd
)
668 pFly
->NotifyDrawObj();
670 if ( bPosChgd
&& maFrame
.Pos().X() != FAR_AWAY
)
672 // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
673 // reason: New positioning and alignment (e.g. to-paragraph anchored,
674 // but aligned at page) are introduced.
675 // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
676 // floating screen objects by calling method <SwLayoutFrame::NotifyLowerObjs()>.
678 if ( pFly
->IsFlyAtContentFrame() )
680 SwFrame
*pNxt
= pFly
->AnchorFrame()->FindNext();
683 pNxt
->InvalidatePos();
687 // #i26945# - notify anchor.
688 // Needed for negative positioned Writer fly frames
689 if ( pFly
->GetAnchorFrame()->IsTextFrame() )
691 pFly
->AnchorFrame()->Prepare( PREP_FLY_LEAVE
);
695 // OD 2004-05-13 #i28701#
696 // #i45180# - no adjustment of layout process flags and
697 // further notifications/invalidations, if format is called by grow/shrink
698 if ( pFly
->ConsiderObjWrapInfluenceOnObjPos() &&
699 ( dynamic_cast<const SwFlyFreeFrame
*>( pFly
) == nullptr ||
700 !static_cast<SwFlyFreeFrame
*>(pFly
)->IsNoMoveOnCheckClip() ) )
702 // #i54138# - suppress restart of the layout process
703 // on changed frame height.
704 // Note: It doesn't seem to be necessary and can cause layout loops.
707 // indicate a restart of the layout process
708 pFly
->SetRestartLayoutProcess( true );
713 pFly
->LockPosition();
715 if ( !pFly
->ConsiderForTextWrap() )
717 // indicate that object has to be considered for text wrap
718 pFly
->SetConsiderForTextWrap( true );
719 // invalidate 'background' in order to allow its 'background'
720 // to wrap around it.
721 pFly
->NotifyBackground( pFly
->GetPageFrame(),
722 pFly
->GetObjRectWithSpaces(),
724 // invalidate position of anchor frame in order to force
725 // a re-format of the anchor frame, which also causes a
726 // re-format of the invalid previous frames of the anchor frame.
727 pFly
->AnchorFrame()->InvalidatePos();
733 SwContentNotify::SwContentNotify( SwContentFrame
*pContentFrame
) :
734 SwFrameNotify( pContentFrame
),
735 // OD 08.01.2004 #i11859#
736 mbChkHeightOfLastLine( false ),
737 mnHeightOfLastLine( 0 ),
738 // OD 2004-02-26 #i25029#
739 mbInvalidatePrevPrtArea( false ),
740 mbBordersJoinedWithPrev( false )
742 // OD 08.01.2004 #i11859#
743 if ( pContentFrame
->IsTextFrame() )
745 SwTextFrame
* pTextFrame
= static_cast<SwTextFrame
*>(pContentFrame
);
746 if (!pTextFrame
->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::OLD_LINE_SPACING
))
748 const SvxLineSpacingItem
&rSpace
= pTextFrame
->GetAttrSet()->GetLineSpacing();
749 if ( rSpace
.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
)
751 mbChkHeightOfLastLine
= true;
752 mnHeightOfLastLine
= pTextFrame
->GetHeightOfLastLine();
758 SwContentNotify::~SwContentNotify()
760 SwContentFrame
*pCnt
= static_cast<SwContentFrame
*>(mpFrame
);
761 if ( bSetCompletePaintOnInvalidate
)
762 pCnt
->SetCompletePaint();
764 SwRectFnSet
aRectFnSet(pCnt
);
765 if ( pCnt
->IsInTab() && ( aRectFnSet
.PosDiff( pCnt
->getFrameArea(), maFrame
) ||
766 pCnt
->getFrameArea().SSize() != maFrame
.SSize()))
768 SwLayoutFrame
* pCell
= pCnt
->GetUpper();
769 while( !pCell
->IsCellFrame() && pCell
->GetUpper() )
770 pCell
= pCell
->GetUpper();
771 OSL_ENSURE( pCell
->IsCellFrame(), "Where's my cell?" );
772 if ( text::VertOrientation::NONE
!= pCell
->GetFormat()->GetVertOrient().GetVertOrient() )
773 pCell
->InvalidatePrt(); //for the vertical align.
776 // OD 2004-02-26 #i25029#
777 if ( mbInvalidatePrevPrtArea
&& mbBordersJoinedWithPrev
&&
778 pCnt
->IsTextFrame() &&
779 !pCnt
->IsFollow() && !pCnt
->GetIndPrev() )
781 // determine previous frame
782 SwFrame
* pPrevFrame
= pCnt
->FindPrev();
783 // skip empty section frames and hidden text frames
785 while ( pPrevFrame
&&
786 ( ( pPrevFrame
->IsSctFrame() &&
787 !static_cast<SwSectionFrame
*>(pPrevFrame
)->GetSection() ) ||
788 ( pPrevFrame
->IsTextFrame() &&
789 static_cast<SwTextFrame
*>(pPrevFrame
)->IsHiddenNow() ) ) )
791 pPrevFrame
= pPrevFrame
->FindPrev();
795 // Invalidate printing area of found previous frame
798 if ( pPrevFrame
->IsSctFrame() )
800 if ( pCnt
->IsInSct() )
802 // Note: found previous frame is a section frame and
803 // <pCnt> is also inside a section.
804 // Thus due to <mbBordersJoinedWithPrev>,
805 // <pCnt> had joined its borders/shadow with the
806 // last content of the found section.
807 // Invalidate printing area of last content in found section.
808 SwFrame
* pLstContentOfSctFrame
=
809 static_cast<SwSectionFrame
*>(pPrevFrame
)->FindLastContent();
810 if ( pLstContentOfSctFrame
)
812 pLstContentOfSctFrame
->InvalidatePrt();
818 pPrevFrame
->InvalidatePrt();
823 const bool bFirst
= aRectFnSet
.GetWidth(maFrame
) == 0;
825 if ( pCnt
->IsNoTextFrame() )
827 //Active PlugIn's or OLE-Objects should know something of the change
828 //thereby they move their window appropriate.
829 SwViewShell
*pSh
= pCnt
->getRootFrame()->GetCurrShell();
832 SwOLENode
*const pNd(static_cast<SwNoTextFrame
*>(pCnt
)->GetNode()->GetOLENode());
833 if (nullptr != pNd
&&
834 (pNd
->GetOLEObj().IsOleRef() ||
835 pNd
->IsOLESizeInvalid()) )
837 const bool bNoTextFramePrtAreaChanged
=
838 ( maPrt
.SSize().Width() != 0 &&
839 maPrt
.SSize().Height() != 0 ) &&
840 maPrt
.SSize() != pCnt
->getFramePrintArea().SSize();
841 OSL_ENSURE( pCnt
->IsInFly(), "OLE not in FlyFrame" );
842 SwFlyFrame
*pFly
= pCnt
->FindFlyFrame();
843 svt::EmbeddedObjectRef
& xObj
= pNd
->GetOLEObj().GetObject();
844 SwFEShell
*pFESh
= nullptr;
845 for(SwViewShell
& rCurrentShell
: pSh
->GetRingContainer())
846 { if ( dynamic_cast<const SwCursorShell
*>( &rCurrentShell
) != nullptr )
848 pFESh
= static_cast<SwFEShell
*>(&rCurrentShell
);
849 // #108369#: Here used to be the condition if (!bFirst).
850 // I think this should mean "do not call CalcAndSetScale"
851 // if the frame is formatted for the first time.
852 // Unfortunately this is not valid anymore since the
853 // SwNoTextFrame already gets a width during CalcLowerPreps.
854 // Nevertheless, the indention of !bFirst seemed to be
855 // to assure that the OLE objects have already been notified
856 // if necessary before calling CalcAndSetScale.
857 // So I replaced !bFirst by !IsOLESizeInvalid. There is
858 // one additional problem specific to the word import:
859 // The layout is calculated _before_ calling PrtOLENotify,
860 // and the OLE objects are not invalidated during import.
861 // Therefore I added the condition !IsUpdateExpField,
862 // have a look at the occurrence of CalcLayout in
864 if ( !pNd
->IsOLESizeInvalid() &&
865 !pSh
->GetDoc()->getIDocumentState().IsUpdateExpField() )
866 pFESh
->CalcAndSetScale( xObj
,
867 &pFly
->getFramePrintArea(), &pFly
->getFrameArea(),
868 bNoTextFramePrtAreaChanged
);
872 if ( pFESh
&& pNd
->IsOLESizeInvalid() )
874 pNd
->SetOLESizeInvalid( false );
875 pFESh
->CalcAndSetScale( xObj
); // create client
878 //dito animated graphics
879 if ( getFrameArea().HasArea() && static_cast<SwNoTextFrame
*>(pCnt
)->HasAnimation() )
881 static_cast<SwNoTextFrame
*>(pCnt
)->StopAnimation();
882 pSh
->InvalidateWindows( getFrameArea() );
889 pCnt
->SetRetouche(); //fix(13870)
891 SwDoc
*const pDoc
= pCnt
->IsTextFrame()
892 ? &static_cast<SwTextFrame
*>(pCnt
)->GetDoc()
893 : static_cast<SwNoTextFrame
*>(pCnt
)->GetNode()->GetDoc();
894 if ( !pDoc
->GetSpzFrameFormats()->empty() &&
895 pDoc
->DoesContainAtPageObjWithContentAnchor() && !pDoc
->getIDocumentState().IsNewDoc() )
897 // If certain import filters for foreign file format import
898 // AT_PAGE anchored objects, the corresponding page number is
899 // typically not known. In this case the content position is
900 // stored at which the anchored object is found in the
901 // imported document.
902 // When this content is formatted it is the time at which
903 // the page is known. Thus, this data can be corrected now.
905 const SwPageFrame
*pPage
= nullptr;
906 SwFrameFormats
*pTable
= pDoc
->GetSpzFrameFormats();
908 for ( size_t i
= 0; i
< pTable
->size(); ++i
)
910 SwFrameFormat
*pFormat
= (*pTable
)[i
];
911 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
912 if ( RndStdIds::FLY_AT_PAGE
!= rAnch
.GetAnchorId() ||
913 rAnch
.GetContentAnchor() == nullptr )
918 if (FrameContainsNode(*pCnt
, rAnch
.GetContentAnchor()->nNode
.GetIndex()))
920 OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - to page anchored object with content position." );
923 pPage
= pCnt
->FindPageFrame();
925 SwFormatAnchor
aAnch( rAnch
);
926 aAnch
.SetAnchor( nullptr );
927 aAnch
.SetPageNum( pPage
->GetPhyPageNum() );
928 pFormat
->SetFormatAttr( aAnch
);
929 if ( RES_DRAWFRMFMT
!= pFormat
->Which() )
931 pFormat
->MakeFrames();
938 // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
939 // if height of last line has changed.
940 if ( pCnt
->IsTextFrame() && mbChkHeightOfLastLine
)
942 if ( mnHeightOfLastLine
!= static_cast<SwTextFrame
*>(pCnt
)->GetHeightOfLastLine() )
944 pCnt
->InvalidateNextPrtArea();
949 if ( pCnt
->IsTextFrame() && aRectFnSet
.PosDiff( maFrame
, pCnt
->getFrameArea() ) )
951 pCnt
->InvalidateObjs();
954 // #i43255# - move code to invalidate at-character
955 // anchored objects due to a change of its anchor character from
956 // method <SwTextFrame::Format(..)>.
957 if ( pCnt
->IsTextFrame() )
959 SwTextFrame
* pMasterFrame
= pCnt
->IsFollow()
960 ? static_cast<SwTextFrame
*>(pCnt
)->FindMaster()
961 : static_cast<SwTextFrame
*>(pCnt
);
962 if ( pMasterFrame
&& !pMasterFrame
->IsFlyLock() &&
963 pMasterFrame
->GetDrawObjs() )
965 SwSortedObjs
* pObjs
= pMasterFrame
->GetDrawObjs();
966 for (SwAnchoredObject
* pAnchoredObj
: *pObjs
)
968 if ( pAnchoredObj
->GetFrameFormat().GetAnchor().GetAnchorId()
969 == RndStdIds::FLY_AT_CHAR
)
971 pAnchoredObj
->CheckCharRectAndTopOfLine( !pMasterFrame
->IsEmpty() );
978 // note this *cannot* be static because it's a friend
979 void AppendObj(SwFrame
*const pFrame
, SwPageFrame
*const pPage
, SwFrameFormat
*const pFormat
, const SwFormatAnchor
& rAnch
)
981 const bool bFlyAtFly
= rAnch
.GetAnchorId() == RndStdIds::FLY_AT_FLY
; // LAYER_IMPL
982 //Is a frame or a SdrObject described?
983 const bool bSdrObj
= RES_DRAWFRMFMT
== pFormat
->Which();
984 // OD 23.06.2003 #108784# - append also drawing objects anchored
986 const bool bDrawObjInContent
= bSdrObj
&&
987 (rAnch
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
);
990 (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_PARA
) ||
991 (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
) ||
994 SdrObject
* pSdrObj
= nullptr;
995 if ( bSdrObj
&& nullptr == (pSdrObj
= pFormat
->FindSdrObject()) )
997 OSL_ENSURE( !bSdrObj
, "DrawObject not found." );
998 pFormat
->GetDoc()->DelFrameFormat( pFormat
);
1003 if ( !pSdrObj
->getSdrPageFromSdrObject() )
1005 pFormat
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
1006 InsertObject(pSdrObj
, pSdrObj
->GetOrdNumDirect());
1009 SwDrawContact
* pNew
=
1010 static_cast<SwDrawContact
*>(GetUserCall( pSdrObj
));
1011 if ( !pNew
->GetAnchorFrame() )
1013 pFrame
->AppendDrawObj( *(pNew
->GetAnchoredObj( nullptr )) );
1015 // OD 19.06.2003 #108784# - add 'virtual' drawing object,
1016 // if necessary. But control objects have to be excluded.
1017 else if ( !::CheckControlLayer( pSdrObj
) &&
1018 pNew
->GetAnchorFrame() != pFrame
&&
1019 !pNew
->GetDrawObjectByAnchorFrame( *pFrame
) )
1021 SwDrawVirtObj
* pDrawVirtObj
= pNew
->AddVirtObj();
1022 pFrame
->AppendDrawObj( *(pNew
->GetAnchoredObj( pDrawVirtObj
)) );
1024 pDrawVirtObj
->ActionChanged();
1031 pFly
= new SwFlyLayFrame( static_cast<SwFlyFrameFormat
*>(pFormat
), pFrame
, pFrame
);
1033 pFly
= new SwFlyAtContentFrame( static_cast<SwFlyFrameFormat
*>(pFormat
), pFrame
, pFrame
);
1035 pFrame
->AppendFly( pFly
);
1038 ::RegistFlys( pPage
, pFly
);
1043 static bool IsShown(sal_uLong
const nIndex
,
1044 const SwFormatAnchor
& rAnch
,
1045 std::vector
<sw::Extent
>::const_iterator
const*const pIter
,
1046 std::vector
<sw::Extent
>::const_iterator
const*const pEnd
,
1047 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
1049 assert(!pIter
|| *pIter
== *pEnd
|| (*pIter
)->pNode
->GetIndex() == nIndex
);
1050 SwPosition
const& rAnchor(*rAnch
.GetContentAnchor());
1051 if (rAnchor
.nNode
.GetIndex() != nIndex
)
1055 if (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_PARA
)
1057 return pIter
== nullptr // not merged
1058 || pIter
!= pEnd
// at least one char visible in node
1059 || !IsSelectFrameAnchoredAtPara(rAnchor
,
1060 SwPosition(const_cast<SwTextNode
&>(*pFirstNode
), 0),
1061 SwPosition(const_cast<SwTextNode
&>(*pLastNode
), pLastNode
->Len()));
1065 // note: frames are not sorted by anchor position.
1069 assert(rAnch
.GetAnchorId() != RndStdIds::FLY_AT_FLY
);
1070 for (auto iter
= *pIter
; iter
!= *pEnd
; ++iter
)
1072 assert(iter
->nStart
!= iter
->nEnd
); // TODO possible?
1073 assert(iter
->pNode
->GetIndex() == nIndex
);
1074 if (rAnchor
.nContent
.GetIndex() < iter
->nStart
)
1078 if (rAnch
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
)
1080 // if there is an extent then obviously the node was not
1082 // show if start <= pos <= end
1083 // *or* if first-node/0 *and* not StartOfSection
1084 // *or* if last-node/Len *and* not EndOfSection
1086 // first determine the extent to compare to, then
1087 // construct start/end positions for the deletion *before* the
1088 // extent and compare once.
1089 // the interesting corner cases are on the edge of the extent!
1090 // no need to check for > the last extent because those
1091 // are never visible.
1092 if (rAnchor
.nContent
.GetIndex() <= iter
->nEnd
)
1094 if (iter
->nStart
== 0)
1100 SwPosition
const start(
1101 const_cast<SwTextNode
&>(
1103 ? *pFirstNode
// simplification
1105 iter
== *pIter
// first extent?
1106 ? iter
->pNode
== pFirstNode
1107 ? 0 // at start of 1st node
1108 : pFirstNode
->Len() // previous node; simplification but should get right result
1109 : (iter
-1)->nEnd
); // previous extent
1110 SwPosition
const end(*iter
->pNode
, iter
->nStart
);
1111 return !IsDestroyFrameAnchoredAtChar(rAnchor
, start
, end
);
1114 else if (iter
== *pEnd
- 1) // special case: after last extent
1116 if (iter
->nEnd
== iter
->pNode
->Len())
1118 return true; // special case: end of node
1122 SwPosition
const start(*iter
->pNode
, iter
->nEnd
);
1123 SwPosition
const end(
1124 const_cast<SwTextNode
&>(*pLastNode
), // simplification
1125 iter
->pNode
== pLastNode
1126 ? iter
->pNode
->Len()
1128 return !IsDestroyFrameAnchoredAtChar(rAnchor
, start
, end
);
1134 assert(rAnch
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
);
1135 // for AS_CHAR obviously must be <
1136 if (rAnchor
.nContent
.GetIndex() < iter
->nEnd
)
1150 void RemoveHiddenObjsOfNode(SwTextNode
const& rNode
,
1151 std::vector
<sw::Extent
>::const_iterator
const*const pIter
,
1152 std::vector
<sw::Extent
>::const_iterator
const*const pEnd
,
1153 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
1155 std::vector
<SwFrameFormat
*> const*const pFlys(rNode
.GetAnchoredFlys());
1160 for (SwFrameFormat
* pFrameFormat
: *pFlys
)
1162 SwFormatAnchor
const& rAnchor
= pFrameFormat
->GetAnchor();
1163 if (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
1164 || (rAnchor
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
1165 && RES_DRAWFRMFMT
== pFrameFormat
->Which()))
1167 assert(rAnchor
.GetContentAnchor()->nNode
.GetIndex() == rNode
.GetIndex());
1168 if (!IsShown(rNode
.GetIndex(), rAnchor
, pIter
, pEnd
, pFirstNode
, pLastNode
))
1170 pFrameFormat
->DelFrames();
1176 void AppendObjsOfNode(SwFrameFormats
const*const pTable
, sal_uLong
const nIndex
,
1177 SwFrame
*const pFrame
, SwPageFrame
*const pPage
, SwDoc
*const pDoc
,
1178 std::vector
<sw::Extent
>::const_iterator
const*const pIter
,
1179 std::vector
<sw::Extent
>::const_iterator
const*const pEnd
,
1180 SwTextNode
const*const pFirstNode
, SwTextNode
const*const pLastNode
)
1182 #if OSL_DEBUG_LEVEL > 0
1183 std::vector
<SwFrameFormat
*> checkFormats
;
1184 for ( size_t i
= 0; i
< pTable
->size(); ++i
)
1186 SwFrameFormat
*pFormat
= (*pTable
)[i
];
1187 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
1188 if ( rAnch
.GetContentAnchor() &&
1189 IsShown(nIndex
, rAnch
, pIter
, pEnd
, pFirstNode
, pLastNode
))
1191 checkFormats
.push_back( pFormat
);
1198 SwNode
const& rNode(*pDoc
->GetNodes()[nIndex
]);
1199 std::vector
<SwFrameFormat
*> const*const pFlys(rNode
.GetAnchoredFlys());
1200 for (size_t it
= 0; pFlys
&& it
!= pFlys
->size(); )
1202 SwFrameFormat
*const pFormat
= (*pFlys
)[it
];
1203 const SwFormatAnchor
&rAnch
= pFormat
->GetAnchor();
1204 if ( rAnch
.GetContentAnchor() &&
1205 IsShown(nIndex
, rAnch
, pIter
, pEnd
, pFirstNode
, pLastNode
))
1207 #if OSL_DEBUG_LEVEL > 0
1208 std::vector
<SwFrameFormat
*>::iterator checkPos
= std::find( checkFormats
.begin(), checkFormats
.end(), pFormat
);
1209 assert( checkPos
!= checkFormats
.end());
1210 checkFormats
.erase( checkPos
);
1212 AppendObj(pFrame
, pPage
, pFormat
, rAnch
);
1217 #if OSL_DEBUG_LEVEL > 0
1218 assert( checkFormats
.empty());
1223 void AppendObjs(const SwFrameFormats
*const pTable
, sal_uLong
const nIndex
,
1224 SwFrame
*const pFrame
, SwPageFrame
*const pPage
, SwDoc
*const pDoc
)
1226 if (pFrame
->IsTextFrame())
1228 SwTextFrame
const*const pTextFrame(static_cast<SwTextFrame
const*>(pFrame
));
1229 if (sw::MergedPara
const*const pMerged
= pTextFrame
->GetMergedPara())
1231 std::vector
<sw::Extent
>::const_iterator
iterFirst(pMerged
->extents
.begin());
1232 std::vector
<sw::Extent
>::const_iterator
iter(iterFirst
);
1233 SwTextNode
const* pNode(pMerged
->pFirstNode
);
1236 if (iter
== pMerged
->extents
.end()
1237 || iter
->pNode
!= pNode
)
1239 AppendObjsOfNode(pTable
, pNode
->GetIndex(), pFrame
, pPage
, pDoc
,
1240 &iterFirst
, &iter
, pMerged
->pFirstNode
, pMerged
->pLastNode
);
1241 sal_uLong
const until
= iter
== pMerged
->extents
.end()
1242 ? pMerged
->pLastNode
->GetIndex() + 1
1243 : iter
->pNode
->GetIndex();
1244 for (sal_uLong i
= pNode
->GetIndex() + 1; i
< until
; ++i
)
1246 // let's show at-para flys on nodes that contain start/end of
1247 // redline too, even if there's no text there
1248 SwNode
const*const pTmp(pNode
->GetNodes()[i
]);
1249 if (pTmp
->GetRedlineMergeFlag() == SwNode::Merge::NonFirst
)
1251 AppendObjsOfNode(pTable
, pTmp
->GetIndex(), pFrame
, pPage
, pDoc
, &iter
, &iter
, pMerged
->pFirstNode
, pMerged
->pLastNode
);
1254 if (iter
== pMerged
->extents
.end())
1258 pNode
= iter
->pNode
;
1265 return AppendObjsOfNode(pTable
, nIndex
, pFrame
, pPage
, pDoc
, nullptr, nullptr, nullptr, nullptr);
1270 return AppendObjsOfNode(pTable
, nIndex
, pFrame
, pPage
, pDoc
, nullptr, nullptr, nullptr, nullptr);
1274 bool IsAnchoredObjShown(SwTextFrame
const& rFrame
, SwFormatAnchor
const& rAnchor
)
1276 assert(rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
||
1277 rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
||
1278 rAnchor
.GetAnchorId() == RndStdIds::FLY_AS_CHAR
);
1280 if (auto const pMergedPara
= rFrame
.GetMergedPara())
1283 auto const pAnchor(rAnchor
.GetContentAnchor());
1284 auto iterFirst(pMergedPara
->extents
.cbegin());
1285 if (iterFirst
== pMergedPara
->extents
.end()
1286 && (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
1287 || rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_CHAR
))
1289 ret
= (&pAnchor
->nNode
.GetNode() == pMergedPara
->pFirstNode
1290 && (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
1291 || pAnchor
->nContent
== 0))
1292 || (&pAnchor
->nNode
.GetNode() == pMergedPara
->pLastNode
1293 && (rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PARA
1294 || pAnchor
->nContent
== pMergedPara
->pLastNode
->Len()));
1296 auto iter(iterFirst
);
1297 SwTextNode
const* pNode(pMergedPara
->pFirstNode
);
1300 if (iter
== pMergedPara
->extents
.end()
1301 || iter
->pNode
!= pNode
)
1303 assert(pNode
->GetRedlineMergeFlag() != SwNode::Merge::Hidden
);
1304 if (pNode
== &pAnchor
->nNode
.GetNode())
1306 ret
= IsShown(pNode
->GetIndex(), rAnchor
, &iterFirst
, &iter
,
1307 pMergedPara
->pFirstNode
, pMergedPara
->pLastNode
);
1310 if (iter
== pMergedPara
->extents
.end())
1314 pNode
= iter
->pNode
;
1315 if (pAnchor
->nNode
.GetIndex() < pNode
->GetIndex())
1326 void AppendAllObjs(const SwFrameFormats
* pTable
, const SwFrame
* pSib
)
1328 //Connecting of all Objects, which are described in the SpzTable with the
1331 boost::circular_buffer
<SwFrameFormat
*> vFormatsToConnect(pTable
->size());
1332 for(const auto& pFormat
: *pTable
)
1334 const auto& rAnch
= pFormat
->GetAnchor();
1335 // Formats can still remain, because we neither use character bound
1336 // frames nor objects which are anchored to character bounds.
1337 if ((rAnch
.GetAnchorId() != RndStdIds::FLY_AT_PAGE
) && (rAnch
.GetAnchorId() != RndStdIds::FLY_AS_CHAR
))
1339 auto pContentAnchor
= rAnch
.GetContentAnchor();
1340 // formats in header/footer have no dependencies
1341 if(pContentAnchor
&& pFormat
->GetDoc()->IsInHeaderFooter(pContentAnchor
->nNode
))
1342 pFormat
->MakeFrames();
1344 vFormatsToConnect
.push_back(pFormat
);
1347 const SwRootFrame
* pRoot
= pSib
? pSib
->getRootFrame() : nullptr;
1348 const SwFrameFormat
* pFirstRequeued(nullptr);
1349 while(!vFormatsToConnect
.empty())
1351 auto& pFormat
= vFormatsToConnect
.front();
1352 bool isConnected(false);
1353 pFormat
->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected
, pRoot
));
1356 pFormat
->MakeFrames();
1357 pFormat
->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected
, pRoot
));
1359 // do this *before* push_back! the circular_buffer can be "full"!
1360 vFormatsToConnect
.pop_front();
1363 if(pFirstRequeued
== pFormat
)
1364 // If nothing happens anymore we can stop.
1367 pFirstRequeued
= pFormat
;
1368 assert(!vFormatsToConnect
.full());
1369 vFormatsToConnect
.push_back(pFormat
);
1373 pFirstRequeued
= nullptr;
1380 void RecreateStartTextFrames(SwTextNode
& rNode
)
1382 std::vector
<SwTextFrame
*> frames
;
1383 SwIterator
<SwTextFrame
, SwTextNode
, sw::IteratorMode::UnwrapMulti
> aIter(rNode
);
1384 for (SwTextFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next())
1386 if (pFrame
->getRootFrame()->IsHideRedlines())
1388 frames
.push_back(pFrame
);
1391 auto eMode(sw::FrameMode::Existing
);
1392 for (SwTextFrame
* pFrame
: frames
)
1394 // SplitNode could have moved the original frame to the start node
1395 // & created a new one on end, or could have created new frame on
1396 // start node... grab start node's frame and recreate MergedPara.
1397 SwTextNode
& rFirstNode(pFrame
->GetMergedPara()
1398 ? *pFrame
->GetMergedPara()->pFirstNode
1400 assert(rFirstNode
.GetIndex() <= rNode
.GetIndex());
1401 // clear old one first to avoid DelFrames confusing updates & asserts...
1402 pFrame
->SetMergedPara(nullptr);
1403 pFrame
->SetMergedPara(sw::CheckParaRedlineMerge(
1404 *pFrame
, rFirstNode
, eMode
));
1405 eMode
= sw::FrameMode::New
; // Existing is not idempotent!
1406 // note: this may or may not delete frames on the end node
1412 /** local method to set 'working' position for newly inserted frames
1414 OD 12.08.2003 #i17969#
1416 static void lcl_SetPos( SwFrame
& _rNewFrame
,
1417 const SwLayoutFrame
& _rLayFrame
)
1419 SwRectFnSet
aRectFnSet(&_rLayFrame
);
1420 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(_rNewFrame
);
1421 aRectFnSet
.SetPos( aFrm
, aRectFnSet
.GetPos(_rLayFrame
.getFrameArea()) );
1423 // move position by one SwTwip in text flow direction in order to get
1424 // notifications for a new calculated position after its formatting.
1425 if ( aRectFnSet
.IsVert() )
1427 aFrm
.Pos().AdjustX( -1 );
1431 aFrm
.Pos().AdjustY(1 );
1435 void InsertCnt_( SwLayoutFrame
*pLay
, SwDoc
*pDoc
,
1436 sal_uLong nIndex
, bool bPages
, sal_uLong nEndIndex
,
1437 SwFrame
*pPrv
, sw::FrameMode
const eMode
)
1439 pDoc
->getIDocumentTimerAccess().BlockIdling();
1440 SwRootFrame
* pLayout
= pLay
->getRootFrame();
1441 const bool bOldCallbackActionEnabled
= pLayout
&& pLayout
->IsCallbackActionEnabled();
1442 if( bOldCallbackActionEnabled
)
1443 pLayout
->SetCallbackActionEnabled( false );
1445 //In the generation of the Layout bPages=true will be handed over.
1446 //Then will be new pages generated all x paragraphs already times in advance.
1447 //On breaks and/or pagedescriptorchanges the corresponding will be generated
1449 //The advantage is, that on one hand already a nearly realistic number of
1450 //pages are created, but above all there are no almost endless long chain
1451 //of paragraphs, which must be moved expensively until it reaches a tolerable
1453 //We'd like to think that 20 Paragraphs fit on one page.
1454 //So that it does not become in extreme situations so violent we calculate depending
1455 //on the node something to it.
1456 //If in the DocStatistic a usable given pagenumber
1457 //(Will be cared for while writing), so it will be presumed that this will be
1459 const bool bStartPercent
= bPages
&& !nEndIndex
;
1461 SwPageFrame
*pPage
= pLay
->FindPageFrame();
1462 const SwFrameFormats
*pTable
= pDoc
->GetSpzFrameFormats();
1463 SwFrame
*pFrame
= nullptr;
1464 std::unique_ptr
<SwActualSection
> pActualSection
;
1465 std::unique_ptr
<SwLayHelper
> pPageMaker
;
1467 //If the layout will be created (bPages == true) we do head on the progress
1468 //Flys and DrawObjects are not connected immediately, this
1469 //happens only at the end of the function.
1472 // Attention: the SwLayHelper class uses references to the content-,
1473 // page-, layout-frame etc. and may change them!
1474 pPageMaker
.reset(new SwLayHelper( pDoc
, pFrame
, pPrv
, pPage
, pLay
,
1475 pActualSection
, nIndex
, 0 == nEndIndex
));
1478 const sal_uLong nPageCount
= pPageMaker
->CalcPageCount();
1480 bObjsDirect
= false;
1484 pPageMaker
= nullptr;
1486 if( pLay
->IsInSct() &&
1487 ( pLay
->IsSctFrame() || pLay
->GetUpper() ) ) // Hereby will newbies
1488 // be intercepted, of which flags could not determined yet,
1489 // for e.g. while inserting a table
1491 SwSectionFrame
* pSct
= pLay
->FindSctFrame();
1492 // If content will be inserted in a footnote, which in a column area,
1493 // the column area it is not allowed to be broken up.
1494 // Only if in the inner of the footnote lies an area, is this a candidate
1495 // for pActualSection.
1496 // The same applies for areas in tables, if inside the table will be
1497 // something inserted, it's only allowed to break up areas, which
1498 // lies in the inside also.
1499 if( ( !pLay
->IsInFootnote() || pSct
->IsInFootnote() ) &&
1500 ( !pLay
->IsInTab() || pSct
->IsInTab() ) )
1502 pActualSection
.reset(new SwActualSection(nullptr, pSct
, pSct
->GetSection()->GetFormat()->GetSectionNode()));
1503 // tdf#132236 for SwUndoDelete: find outer sections whose start
1504 // nodes aren't contained in the range but whose end nodes are,
1505 // because section frames may need to be created for them
1506 SwActualSection
* pUpperSection(pActualSection
.get());
1507 while (pUpperSection
->GetSectionNode()->EndOfSectionIndex() < nEndIndex
)
1509 SwStartNode
*const pStart(pUpperSection
->GetSectionNode()->StartOfSectionNode());
1510 if (!pStart
->IsSectionNode())
1514 // note: these don't have a section frame, check it in EndNode case!
1515 auto const pTmp(new SwActualSection(nullptr, nullptr, static_cast<SwSectionNode
*>(pStart
)));
1516 pUpperSection
->SetUpper(pTmp
);
1517 pUpperSection
= pTmp
;
1519 OSL_ENSURE( !pLay
->Lower() || !pLay
->Lower()->IsColumnFrame(),
1520 "InsertCnt_: Wrong Call" );
1524 //If a section is "open", the pActualSection points to an SwActualSection.
1525 //If the page breaks, for "open" sections a follow will created.
1526 //For nested sections (which have, however, not a nested layout),
1527 //the SwActualSection class has a member, which points to an upper(section).
1528 //When the "inner" section finishes, the upper will used instead.
1530 // Do not consider the end node. The caller (Section/MakeFrames()) has to
1531 // ensure that the end of this range is positioned before EndIndex!
1532 for ( ; nEndIndex
== 0 || nIndex
< nEndIndex
; ++nIndex
)
1534 SwNode
*pNd
= pDoc
->GetNodes()[nIndex
];
1535 if ( pNd
->IsContentNode() )
1537 SwContentNode
* pNode
= static_cast<SwContentNode
*>(pNd
);
1538 if (pLayout
->IsHideRedlines() && !pNd
->IsCreateFrameWhenHidingRedlines())
1540 if (pNd
->IsTextNode()
1541 && pNd
->GetRedlineMergeFlag() == SwNode::Merge::NonFirst
)
1542 { // must have a frame already
1543 assert(static_cast<SwTextFrame
*>(pNode
->getLayoutFrame(pLayout
))->GetMergedPara());
1545 continue; // skip it
1547 pFrame
= pNode
->IsTextNode()
1548 ? sw::MakeTextFrame(*pNode
->GetTextNode(), pLay
, eMode
)
1549 : pNode
->MakeFrame(pLay
);
1551 pPageMaker
->CheckInsert( nIndex
);
1553 pFrame
->InsertBehind( pLay
, pPrv
);
1555 // notify accessibility paragraphs objects about changed
1556 // CONTENT_FLOWS_FROM/_TO relation.
1557 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1558 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1559 if ( pFrame
->IsTextFrame() )
1561 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1562 // no notification, if <SwViewShell> is in construction
1563 if ( pViewShell
&& !pViewShell
->IsInConstructor() &&
1564 pViewShell
->GetLayout() &&
1565 pViewShell
->GetLayout()->IsAnyShellAccessible() &&
1566 pFrame
->FindPageFrame() != nullptr)
1568 pViewShell
->InvalidateAccessibleParaFlowRelation(
1569 dynamic_cast<SwTextFrame
*>(pFrame
->FindNextCnt( true )),
1570 dynamic_cast<SwTextFrame
*>(pFrame
->FindPrevCnt()) );
1572 // The information flags of the text frame are validated
1573 // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
1574 // The information flags have to be invalidated, because
1575 // it is possible, that the one of its upper frames
1576 // isn't inserted into the layout.
1577 pFrame
->InvalidateInfFlags();
1580 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1581 // for setting position at newly inserted frame
1582 lcl_SetPos( *pFrame
, *pLay
);
1585 if ( !pTable
->empty() && bObjsDirect
&& !bDontCreateObjects
)
1586 AppendObjs( pTable
, nIndex
, pFrame
, pPage
, pDoc
);
1588 else if ( pNd
->IsTableNode() )
1589 { //Should we have encountered a table?
1590 SwTableNode
*pTableNode
= static_cast<SwTableNode
*>(pNd
);
1591 if (pLayout
->IsHideRedlines())
1593 // in the problematic case, there can be only 1 redline...
1594 SwPosition
const tmp(*pNd
);
1595 SwRangeRedline
const*const pRedline(
1596 pDoc
->getIDocumentRedlineAccess().GetRedline(tmp
, nullptr));
1597 // pathology: redline that starts on a TableNode; cannot
1598 // be created in UI but by import filters...
1600 && pRedline
->GetType() == RedlineType::Delete
1601 && &pRedline
->Start()->nNode
.GetNode() == pNd
)
1603 SAL_WARN("sw.pageframe", "skipping table frame creation on bizarre redline");
1606 pTableNode
->GetNodes()[nIndex
]->SetRedlineMergeFlag(SwNode::Merge::Hidden
);
1607 if (nIndex
== pTableNode
->EndOfSectionIndex())
1616 if (pLayout
->IsHideRedlines() && !pNd
->IsCreateFrameWhenHidingRedlines())
1618 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1619 nIndex
= pTableNode
->EndOfSectionIndex();
1620 continue; // skip it
1623 // #108116# loading may produce table structures that GCLines
1624 // needs to clean up. To keep table formulas correct, change
1625 // all table formulas to internal (BOXPTR) representation.
1626 SwTableFormulaUpdate
aMsgHint( &pTableNode
->GetTable() );
1627 aMsgHint
.m_eFlags
= TBL_BOXPTR
;
1628 pDoc
->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint
);
1629 pTableNode
->GetTable().GCLines();
1631 pFrame
= pTableNode
->MakeFrame( pLay
);
1634 pPageMaker
->CheckInsert( nIndex
);
1636 pFrame
->InsertBehind( pLay
, pPrv
);
1637 if (pPage
) // would null in SwCellFrame ctor
1638 { // tdf#134931 call ResetTurbo(); not sure if Paste() would be
1639 pFrame
->InvalidatePage(pPage
); // better than InsertBehind()?
1642 // notify accessibility paragraphs objects about changed
1643 // CONTENT_FLOWS_FROM/_TO relation.
1644 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1645 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1647 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1648 // no notification, if <SwViewShell> is in construction
1649 if ( pViewShell
&& !pViewShell
->IsInConstructor() &&
1650 pViewShell
->GetLayout() &&
1651 pViewShell
->GetLayout()->IsAnyShellAccessible() &&
1652 pFrame
->FindPageFrame() != nullptr)
1654 pViewShell
->InvalidateAccessibleParaFlowRelation(
1655 dynamic_cast<SwTextFrame
*>(pFrame
->FindNextCnt( true )),
1656 dynamic_cast<SwTextFrame
*>(pFrame
->FindPrevCnt()) );
1659 if ( bObjsDirect
&& !pTable
->empty() )
1660 static_cast<SwTabFrame
*>(pFrame
)->RegistFlys();
1661 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1662 // for setting position at newly inserted frame
1663 lcl_SetPos( *pFrame
, *pLay
);
1666 //Set the index to the endnode of the table section.
1667 nIndex
= pTableNode
->EndOfSectionIndex();
1669 SwTabFrame
* pTmpFrame
= static_cast<SwTabFrame
*>(pFrame
);
1672 pTmpFrame
->CheckDirChange();
1673 pTmpFrame
= pTmpFrame
->IsFollow() ? pTmpFrame
->FindMaster() : nullptr;
1677 else if ( pNd
->IsSectionNode() )
1679 if (pLayout
->IsHideRedlines() && !pNd
->IsCreateFrameWhenHidingRedlines())
1681 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1682 continue; // skip it
1684 SwSectionNode
*pNode
= static_cast<SwSectionNode
*>(pNd
);
1685 if( pNode
->GetSection().CalcHiddenFlag() )
1686 // is hidden, skip the area
1687 nIndex
= pNode
->EndOfSectionIndex();
1690 pFrame
= pNode
->MakeFrame( pLay
);
1691 pActualSection
.reset( new SwActualSection( pActualSection
.release(),
1692 static_cast<SwSectionFrame
*>(pFrame
), pNode
) );
1693 if ( pActualSection
->GetUpper() )
1695 //Insert behind the Upper, the "Follow" of the Upper will be
1696 //generated at the EndNode.
1697 SwSectionFrame
*pTmp
= pActualSection
->GetUpper()->GetSectionFrame();
1698 pFrame
->InsertBehind( pTmp
->GetUpper(), pTmp
);
1699 // OD 25.03.2003 #108339# - direct initialization of section
1700 // after insertion in the layout
1701 static_cast<SwSectionFrame
*>(pFrame
)->Init();
1705 pFrame
->InsertBehind( pLay
, pPrv
);
1706 // OD 25.03.2003 #108339# - direct initialization of section
1707 // after insertion in the layout
1708 static_cast<SwSectionFrame
*>(pFrame
)->Init();
1711 // Do not trust the IsInFootnote flag. If we are currently
1712 // building up a table, the upper of pPrv may be a cell
1713 // frame, but the cell frame does not have an upper yet.
1714 if( pPrv
&& nullptr != pPrv
->ImplFindFootnoteFrame() )
1716 if( pPrv
->IsSctFrame() )
1717 pPrv
= static_cast<SwSectionFrame
*>(pPrv
)->ContainsContent();
1718 if( pPrv
&& pPrv
->IsTextFrame() )
1719 static_cast<SwTextFrame
*>(pPrv
)->Prepare( PREP_QUOVADIS
, nullptr, false );
1722 if (nIndex
+ 1 == nEndIndex
)
1723 { // tdf#131684 tdf#132236 fix upper of frame moved in
1724 // SwUndoDelete; can't be done there unfortunately
1725 // because empty section frames are deleted here
1726 SwFrame
*const pNext(
1727 // if there's a parent section, it has been split
1728 // into 2 SwSectionFrame already :(
1730 && pFrame
->GetNext()->IsSctFrame()
1731 && pActualSection
->GetUpper()
1732 && pActualSection
->GetUpper()->GetSectionNode() ==
1733 static_cast<SwSectionFrame
const*>(pFrame
->GetNext())->GetSection()->GetFormat()->GetSectionNode())
1734 ? static_cast<SwSectionFrame
*>(pFrame
->GetNext())->ContainsContent()
1735 : pFrame
->GetNext());
1737 && pNext
->IsTextFrame()
1738 && static_cast<SwTextFrame
*>(pNext
)->GetTextNodeFirst() == pDoc
->GetNodes()[nEndIndex
]
1739 && (pNext
->GetUpper() == pFrame
->GetUpper()
1740 || pFrame
->GetNext()->IsSctFrame())) // checked above
1743 pNext
->InvalidateInfFlags(); // mbInfSct changed
1744 // could have columns
1745 SwSectionFrame
*const pSection(static_cast<SwSectionFrame
*>(pFrame
));
1746 assert(!pSection
->Lower() || pSection
->Lower()->IsLayoutFrame());
1747 SwLayoutFrame
*const pParent(pSection
->Lower() ? pSection
->GetNextLayoutLeaf() : pSection
);
1748 assert(!pParent
->Lower());
1749 // paste invalidates, section could have indent...
1750 pNext
->Paste(pParent
, nullptr);
1754 // notify accessibility paragraphs objects about changed
1755 // CONTENT_FLOWS_FROM/_TO relation.
1756 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1757 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1759 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1760 // no notification, if <SwViewShell> is in construction
1761 if ( pViewShell
&& !pViewShell
->IsInConstructor() &&
1762 pViewShell
->GetLayout() &&
1763 pViewShell
->GetLayout()->IsAnyShellAccessible() &&
1764 pFrame
->FindPageFrame() != nullptr)
1766 pViewShell
->InvalidateAccessibleParaFlowRelation(
1767 dynamic_cast<SwTextFrame
*>(pFrame
->FindNextCnt( true )),
1768 dynamic_cast<SwTextFrame
*>(pFrame
->FindPrevCnt()) );
1771 pFrame
->CheckDirChange();
1773 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1774 // for setting position at newly inserted frame
1775 lcl_SetPos( *pFrame
, *pLay
);
1777 // OD 20.11.2002 #105405# - no page, no invalidate.
1780 // OD 18.09.2002 #100522#
1781 // invalidate page in order to force format and paint of
1782 // inserted section frame
1783 pFrame
->InvalidatePage( pPage
);
1785 // FME 10.11.2003 #112243#
1786 // Invalidate fly content flag:
1787 if ( pFrame
->IsInFly() )
1788 pPage
->InvalidateFlyContent();
1790 // OD 14.11.2002 #104684# - invalidate page content in order to
1791 // force format and paint of section content.
1792 pPage
->InvalidateContent();
1795 pLay
= static_cast<SwLayoutFrame
*>(pFrame
);
1796 if ( pLay
->Lower() && pLay
->Lower()->IsLayoutFrame() )
1797 pLay
= pLay
->GetNextLayoutLeaf();
1801 else if ( pNd
->IsEndNode() && pNd
->StartOfSectionNode()->IsSectionNode() )
1803 if (pLayout
->IsHideRedlines() && !pNd
->IsCreateFrameWhenHidingRedlines())
1805 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1806 continue; // skip it
1808 assert(pActualSection
&& "Section end without section start?");
1809 assert(pActualSection
->GetSectionNode() == pNd
->StartOfSectionNode());
1811 //Close the section, where appropriate activate the surrounding
1813 pActualSection
.reset(pActualSection
->GetUpper());
1814 pLay
= pLay
->FindSctFrame();
1815 if ( pActualSection
)
1817 //Could be, that the last SectionFrame remains empty.
1818 //Then now is the time to remove them.
1819 if ( !pLay
->ContainsContent() )
1821 SwFrame
*pTmpFrame
= pLay
;
1822 pLay
= pTmpFrame
->GetUpper();
1823 pPrv
= pTmpFrame
->GetPrev();
1824 pTmpFrame
->RemoveFromLayout();
1825 SwFrame::DestroyFrame(pTmpFrame
);
1830 pLay
= pLay
->GetUpper();
1833 // new section frame
1834 pFrame
= pActualSection
->GetSectionNode()->MakeFrame( pLay
);
1835 pFrame
->InsertBehind( pLay
, pPrv
);
1836 static_cast<SwSectionFrame
*>(pFrame
)->Init();
1838 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1839 // for setting position at newly inserted frame
1840 lcl_SetPos( *pFrame
, *pLay
);
1842 SwSectionFrame
* pOuterSectionFrame
= pActualSection
->GetSectionFrame();
1844 // a follow has to be appended to the new section frame
1845 SwSectionFrame
* pFollow
= pOuterSectionFrame
? pOuterSectionFrame
->GetFollow() : nullptr;
1848 pOuterSectionFrame
->SetFollow( nullptr );
1849 pOuterSectionFrame
->InvalidateSize();
1850 static_cast<SwSectionFrame
*>(pFrame
)->SetFollow( pFollow
);
1853 // We don't want to leave empty parts back.
1854 if (pOuterSectionFrame
&&
1855 ! pOuterSectionFrame
->IsColLocked() &&
1856 ! pOuterSectionFrame
->ContainsContent() )
1858 pOuterSectionFrame
->DelEmpty( true );
1859 SwFrame::DestroyFrame(pOuterSectionFrame
);
1861 pActualSection
->SetSectionFrame( static_cast<SwSectionFrame
*>(pFrame
) );
1863 pLay
= static_cast<SwLayoutFrame
*>(pFrame
);
1864 if ( pLay
->Lower() && pLay
->Lower()->IsLayoutFrame() )
1865 pLay
= pLay
->GetNextLayoutLeaf();
1870 //Nothing more with sections, it goes on right behind
1873 pLay
= pLay
->GetUpper();
1876 else if( pNd
->IsStartNode() &&
1877 SwFlyStartNode
== static_cast<SwStartNode
*>(pNd
)->GetStartNodeType() )
1879 if (pLayout
->IsHideRedlines() && !pNd
->IsCreateFrameWhenHidingRedlines())
1881 assert(pNd
->GetRedlineMergeFlag() == SwNode::Merge::Hidden
);
1882 assert(false); // actually a fly-section can't be deleted?
1883 continue; // skip it
1885 if ( !pTable
->empty() && bObjsDirect
&& !bDontCreateObjects
)
1887 SwFlyFrame
* pFly
= pLay
->FindFlyFrame();
1889 AppendObjs( pTable
, nIndex
, pFly
, pPage
, pDoc
);
1894 assert(!pLayout
->IsHideRedlines()
1895 || pNd
->GetRedlineMergeFlag() != SwNode::Merge::Hidden
);
1896 // Neither Content nor table nor section, so we are done.
1901 if ( pActualSection
)
1903 // Might happen that an empty (Follow-)Section is left over.
1904 if ( !(pLay
= pActualSection
->GetSectionFrame())->ContainsContent() )
1906 pLay
->RemoveFromLayout();
1907 SwFrame::DestroyFrame(pLay
);
1909 pActualSection
.reset();
1912 if ( bPages
) // let the Flys connect to each other
1914 if ( !bDontCreateObjects
)
1915 AppendAllObjs( pTable
, pLayout
);
1921 pPageMaker
->CheckFlyCache( pPage
);
1923 if( pDoc
->GetLayoutCache() )
1926 pDoc
->GetLayoutCache()->CompareLayout( *pDoc
);
1928 pDoc
->GetLayoutCache()->ClearImpl();
1932 pDoc
->getIDocumentTimerAccess().UnblockIdling();
1933 if( bOldCallbackActionEnabled
)
1934 pLayout
->SetCallbackActionEnabled( bOldCallbackActionEnabled
);
1937 void MakeFrames( SwDoc
*pDoc
, const SwNodeIndex
&rSttIdx
,
1938 const SwNodeIndex
&rEndIdx
)
1940 bObjsDirect
= false;
1942 SwNodeIndex
aTmp( rSttIdx
);
1943 sal_uLong nEndIdx
= rEndIdx
.GetIndex();
1944 SwNode
* pNd
= pDoc
->GetNodes().FindPrvNxtFrameNode( aTmp
,
1945 pDoc
->GetNodes()[ nEndIdx
-1 ]);
1948 bool bApres
= aTmp
< rSttIdx
;
1949 SwNode2Layout
aNode2Layout( *pNd
, rSttIdx
.GetIndex() );
1951 sw::FrameMode eMode
= sw::FrameMode::Existing
;
1952 while( nullptr != (pFrame
= aNode2Layout
.NextFrame()) )
1954 SwLayoutFrame
*pUpper
= pFrame
->GetUpper();
1955 SwFootnoteFrame
* pFootnoteFrame
= pUpper
->FindFootnoteFrame();
1956 bool bOldLock
, bOldFootnote
;
1957 if( pFootnoteFrame
)
1959 bOldFootnote
= pFootnoteFrame
->IsColLocked();
1960 pFootnoteFrame
->ColLock();
1963 bOldFootnote
= true;
1964 SwSectionFrame
* pSct
= pUpper
->FindSctFrame();
1965 // Inside of footnotes only those areas are interesting that are inside of them. But
1966 // not the ones (e.g. column areas) in which are the footnote containers positioned.
1967 // #109767# Table frame is in section, insert section in cell frame.
1968 if( pSct
&& ((pFootnoteFrame
&& !pSct
->IsInFootnote()) || pUpper
->IsCellFrame()) )
1971 { // to prevent pTmp->MoveFwd from destroying the SectionFrame
1972 bOldLock
= pSct
->IsColLocked();
1978 // If pFrame cannot be moved, it is not possible to move it to the next page. This applies
1979 // also for frames (in the first column of a frame pFrame is moveable) and column
1980 // sections of tables (also here pFrame is moveable).
1981 bool bMoveNext
= nEndIdx
- rSttIdx
.GetIndex() > 120;
1982 bool bAllowMove
= !pFrame
->IsInFly() && pFrame
->IsMoveable() &&
1983 (!pFrame
->IsInTab() || pFrame
->IsTabFrame() );
1984 if ( bMoveNext
&& bAllowMove
)
1986 SwFrame
*pMove
= pFrame
;
1987 SwFrame
*pPrev
= pFrame
->GetPrev();
1988 SwFlowFrame
*pTmp
= SwFlowFrame::CastFlowFrame( pMove
);
1993 // The rest of this page should be empty. Thus, the following one has to move to
1994 // the next page (it might also be located in the following column).
1995 assert(!pTmp
->HasFollow() && "prev. node's frame is not last");
1997 // If the surrounding SectionFrame has a "next" one,
1998 // so this one needs to be moved as well.
1999 pMove
= pFrame
->GetIndNext();
2000 SwColumnFrame
* pCol
= static_cast<SwColumnFrame
*>(pFrame
->FindColFrame());
2002 pCol
= static_cast<SwColumnFrame
*>(pCol
->GetNext());
2005 if( pCol
&& !pMove
)
2006 { // No successor so far, look into the next column
2007 pMove
= pCol
->ContainsAny();
2008 if( pCol
->GetNext() )
2009 pCol
= static_cast<SwColumnFrame
*>(pCol
->GetNext());
2010 else if( pCol
->IsInSct() )
2011 { // If there is no following column but we are in a column frame,
2012 // there might be (page) columns outside of it.
2013 pCol
= static_cast<SwColumnFrame
*>(pCol
->FindSctFrame()->FindColFrame());
2015 pCol
= static_cast<SwColumnFrame
*>(pCol
->GetNext());
2020 // skip invalid SectionFrames
2021 while( pMove
&& pMove
->IsSctFrame() &&
2022 !static_cast<SwSectionFrame
*>(pMove
)->GetSection() )
2023 pMove
= pMove
->GetNext();
2024 } while( !pMove
&& pCol
);
2028 if ( pMove
->IsContentFrame() )
2029 pTmp
= static_cast<SwContentFrame
*>(pMove
);
2030 else if ( pMove
->IsTabFrame() )
2031 pTmp
= static_cast<SwTabFrame
*>(pMove
);
2032 else if ( pMove
->IsSctFrame() )
2034 pMove
= static_cast<SwSectionFrame
*>(pMove
)->ContainsAny();
2036 pTmp
= SwFlowFrame::CastFlowFrame( pMove
);
2046 assert(!pTmp
->IsFollow() && "next node's frame is not master");
2047 // move the _content_ of a section frame
2048 if( pMove
->IsSctFrame() )
2050 while( pMove
&& pMove
->IsSctFrame() &&
2051 !static_cast<SwSectionFrame
*>(pMove
)->GetSection() )
2052 pMove
= pMove
->GetNext();
2053 if( pMove
&& pMove
->IsSctFrame() )
2054 pMove
= static_cast<SwSectionFrame
*>(pMove
)->ContainsAny();
2056 pTmp
= SwFlowFrame::CastFlowFrame( pMove
);
2064 SwFrame
* pOldUp
= pTmp
->GetFrame().GetUpper();
2065 // MoveFwd==true means that we are still on the same page.
2066 // But since we want to move if possible!
2067 bool bTmpOldLock
= pTmp
->IsJoinLocked();
2069 while( pTmp
->MoveFwd( true, false, true ) )
2071 if( pOldUp
== pTmp
->GetFrame().GetUpper() )
2073 pOldUp
= pTmp
->GetFrame().GetUpper();
2078 ::InsertCnt_( pUpper
, pDoc
, rSttIdx
.GetIndex(),
2079 pFrame
->IsInDocBody(), nEndIdx
, pPrev
, eMode
);
2084 SwFrame
* pPrv
= bApres
? pFrame
: pFrame
->GetPrev();
2085 // If the section frame is inserted into another one, it must be split.
2086 if( pSct
&& rSttIdx
.GetNode().IsSectionNode() )
2088 bSplit
= pSct
->SplitSect( pFrame
, bApres
);
2089 if( !bSplit
&& !bApres
)
2091 pUpper
= pSct
->GetUpper();
2092 pPrv
= pSct
->GetPrev();
2098 ::InsertCnt_( pUpper
, pDoc
, rSttIdx
.GetIndex(), false,
2099 nEndIdx
, pPrv
, eMode
);
2100 // OD 23.06.2003 #108784# - correction: append objects doesn't
2101 // depend on value of <bAllowMove>
2102 if( !bDontCreateObjects
)
2104 const SwFrameFormats
*pTable
= pDoc
->GetSpzFrameFormats();
2105 if( !pTable
->empty() )
2106 AppendAllObjs( pTable
, pUpper
);
2109 // If nothing was added (e.g. a hidden section), the split must be reversed.
2110 if( bSplit
&& pSct
&& pSct
->GetNext()
2111 && pSct
->GetNext()->IsSctFrame() )
2112 pSct
->MergeNext( static_cast<SwSectionFrame
*>(pSct
->GetNext()) );
2113 if( pFrame
->IsInFly() )
2114 pFrame
->FindFlyFrame()->Invalidate_();
2115 if( pFrame
->IsInTab() )
2116 pFrame
->InvalidateSize();
2119 SwPageFrame
*pPage
= pUpper
->FindPageFrame();
2120 SwFrame::CheckPageDescs( pPage
, false );
2122 pFootnoteFrame
->ColUnlock();
2126 // pSct might be empty (e.g. when inserting linked section containing further
2127 // sections) and can be destroyed in such cases.
2128 if( !pSct
->ContainsContent() )
2130 pSct
->DelEmpty( true );
2131 pUpper
->getRootFrame()->RemoveFromList( pSct
);
2132 SwFrame::DestroyFrame(pSct
);
2135 eMode
= sw::FrameMode::New
; // use Existing only once!
2142 SwBorderAttrs::SwBorderAttrs(const SwModify
*pMod
, const SwFrame
*pConstructor
)
2144 , m_rAttrSet(pConstructor
->IsContentFrame()
2145 ? pConstructor
->IsTextFrame()
2146 ? static_cast<const SwTextFrame
*>(pConstructor
)->GetTextNodeForParaProps()->GetSwAttrSet()
2147 : static_cast<const SwNoTextFrame
*>(pConstructor
)->GetNode()->GetSwAttrSet()
2148 : static_cast<const SwLayoutFrame
*>(pConstructor
)->GetFormat()->GetAttrSet())
2149 , m_rUL(m_rAttrSet
.GetULSpace())
2151 // LRSpaceItem is copied due to the possibility that it is adjusted - see below
2152 , m_rLR(static_cast<SvxLRSpaceItem
*>(m_rAttrSet
.GetLRSpace().Clone()))
2153 , m_rBox(m_rAttrSet
.GetBox())
2154 , m_rShadow(m_rAttrSet
.GetShadow())
2155 , m_aFrameSize(m_rAttrSet
.GetFrameSize().GetSize())
2157 , m_bJoinedWithPrev(false)
2158 , m_bJoinedWithNext(false)
2166 , m_nGetBottomLine(0)
2170 const SwTextFrame
* pTextFrame
= dynamic_cast<const SwTextFrame
*>(pConstructor
);
2173 pTextFrame
->GetTextNodeForParaProps()->ClearLRSpaceItemDueToListLevelIndents( m_rLR
);
2175 else if ( pConstructor
->IsNoTextFrame() )
2177 m_rLR
= std::make_shared
<SvxLRSpaceItem
>(RES_LR_SPACE
);
2180 // Caution: The USHORTs for the cached values are not initialized by intention!
2182 // everything needs to be calculated at least once:
2183 m_bTopLine
= m_bBottomLine
= m_bLeftLine
= m_bRightLine
=
2184 m_bTop
= m_bBottom
= m_bLine
= true;
2186 // except this one: calculate line spacing before cell border only for text frames
2187 m_bLineSpacing
= bool(pTextFrame
);
2189 m_bCacheGetLine
= m_bCachedGetTopLine
= m_bCachedGetBottomLine
= false;
2190 // OD 21.05.2003 #108789# - init cache status for values <m_bJoinedWithPrev>
2191 // and <m_bJoinedWithNext>, which aren't initialized by default.
2192 m_bCachedJoinedWithPrev
= false;
2193 m_bCachedJoinedWithNext
= false;
2196 SwBorderAttrs::~SwBorderAttrs()
2198 const_cast<SwModify
*>(static_cast<SwModify
const *>(m_pOwner
))->SetInCache( false );
2201 /* All calc methods calculate a safety distance in addition to the values given by the attributes.
2202 * This safety distance is only added when working with borders and/or shadows to prevent that
2203 * e.g. borders are painted over.
2206 void SwBorderAttrs::CalcTop_()
2208 m_nTop
= CalcTopLine() + m_rUL
.GetUpper();
2212 bool bGutterAtTop
= m_rAttrSet
.GetDoc()->getIDocumentSettingAccess().get(
2213 DocumentSettingId::GUTTER_AT_TOP
);
2216 // Decrease the print area: the top space is the sum of top and gutter margins.
2217 m_nTop
+= m_rLR
->GetGutterMargin();
2224 void SwBorderAttrs::CalcBottom_()
2226 m_nBottom
= CalcBottomLine() + m_rUL
.GetLower();
2230 long SwBorderAttrs::CalcRight( const SwFrame
* pCaller
) const
2234 if (!pCaller
->IsTextFrame() || !static_cast<const SwTextFrame
*>(pCaller
)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING
)) {
2235 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2236 // and right border are painted on the right respectively left.
2237 if ( pCaller
->IsCellFrame() && pCaller
->IsRightToLeft() )
2238 nRight
= CalcLeftLine();
2240 nRight
= CalcRightLine();
2243 // for paragraphs, "left" is "before text" and "right" is "after text"
2244 if ( pCaller
->IsTextFrame() && pCaller
->IsRightToLeft() )
2245 nRight
+= m_rLR
->GetLeft();
2247 nRight
+= m_rLR
->GetRight();
2249 // correction: retrieve left margin for numbering in R2L-layout
2250 if ( pCaller
->IsTextFrame() && pCaller
->IsRightToLeft() )
2252 nRight
+= static_cast<const SwTextFrame
*>(pCaller
)->GetTextNodeForParaProps()->GetLeftMarginWithNum();
2255 if (pCaller
->IsPageFrame() && m_rLR
)
2257 const auto pPageFrame
= static_cast<const SwPageFrame
*>(pCaller
);
2258 bool bGutterAtTop
= pPageFrame
->GetFormat()->getIDocumentSettingAccess().get(
2259 DocumentSettingId::GUTTER_AT_TOP
);
2262 // Decrease the print area: the right space is the sum of right and right gutter
2264 nRight
+= m_rLR
->GetRightGutterMargin();
2271 /// Tries to detect if this paragraph has a floating table attached.
2272 static bool lcl_hasTabFrame(const SwTextFrame
* pTextFrame
)
2274 if (pTextFrame
->GetDrawObjs())
2276 const SwSortedObjs
* pSortedObjs
= pTextFrame
->GetDrawObjs();
2277 if (pSortedObjs
->size() > 0)
2279 SwAnchoredObject
* pObject
= (*pSortedObjs
)[0];
2280 if (dynamic_cast<const SwFlyFrame
*>(pObject
) != nullptr)
2282 SwFlyFrame
* pFly
= static_cast<SwFlyFrame
*>(pObject
);
2283 if (pFly
->Lower() && pFly
->Lower()->IsTabFrame())
2291 long SwBorderAttrs::CalcLeft( const SwFrame
*pCaller
) const
2295 if (!pCaller
->IsTextFrame() || !static_cast<const SwTextFrame
*>(pCaller
)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING
))
2297 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2298 // and right border are painted on the right respectively left.
2299 if ( pCaller
->IsCellFrame() && pCaller
->IsRightToLeft() )
2300 nLeft
= CalcRightLine();
2302 nLeft
= CalcLeftLine();
2305 // for paragraphs, "left" is "before text" and "right" is "after text"
2306 if ( pCaller
->IsTextFrame() && pCaller
->IsRightToLeft() )
2307 nLeft
+= m_rLR
->GetRight();
2310 bool bIgnoreMargin
= false;
2311 if (pCaller
->IsTextFrame())
2313 const SwTextFrame
* pTextFrame
= static_cast<const SwTextFrame
*>(pCaller
);
2314 if (pTextFrame
->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::FLOATTABLE_NOMARGINS
))
2316 // If this is explicitly requested, ignore the margins next to the floating table.
2317 if (lcl_hasTabFrame(pTextFrame
))
2318 bIgnoreMargin
= true;
2319 // TODO here we only handle the first two paragraphs, would be nice to generalize this.
2320 else if (pTextFrame
->FindPrev() && pTextFrame
->FindPrev()->IsTextFrame() && lcl_hasTabFrame(static_cast<const SwTextFrame
*>(pTextFrame
->FindPrev())))
2321 bIgnoreMargin
= true;
2325 nLeft
+= m_rLR
->GetLeft();
2328 // correction: do not retrieve left margin for numbering in R2L-layout
2329 if ( pCaller
->IsTextFrame() && !pCaller
->IsRightToLeft() )
2331 nLeft
+= static_cast<const SwTextFrame
*>(pCaller
)->GetTextNodeForParaProps()->GetLeftMarginWithNum();
2334 if (pCaller
->IsPageFrame() && m_rLR
)
2336 const auto pPageFrame
= static_cast<const SwPageFrame
*>(pCaller
);
2337 bool bGutterAtTop
= pPageFrame
->GetFormat()->getIDocumentSettingAccess().get(
2338 DocumentSettingId::GUTTER_AT_TOP
);
2341 // Decrease the print area: the left space is the sum of left and gutter margins.
2342 nLeft
+= m_rLR
->GetGutterMargin();
2349 /* Calculated values for borders and shadows.
2350 * It might be that a distance is wanted even without lines. This will be
2351 * considered here and not by the attribute (e.g. bBorderDist for cells).
2354 void SwBorderAttrs::CalcTopLine_()
2356 m_nTopLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::TOP
, /*bEvenIfNoLine*/true );
2357 m_nTopLine
= m_nTopLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::TOP
);
2361 void SwBorderAttrs::CalcBottomLine_()
2363 m_nBottomLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::BOTTOM
, true );
2364 m_nBottomLine
= m_nBottomLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::BOTTOM
);
2365 m_bBottomLine
= false;
2368 void SwBorderAttrs::CalcLeftLine_()
2370 m_nLeftLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::LEFT
, true);
2371 m_nLeftLine
= m_nLeftLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::LEFT
);
2372 m_bLeftLine
= false;
2375 void SwBorderAttrs::CalcRightLine_()
2377 m_nRightLine
= m_rBox
.CalcLineSpace( SvxBoxItemLine::RIGHT
, true );
2378 m_nRightLine
= m_nRightLine
+ m_rShadow
.CalcShadowSpace(SvxShadowItemSide::RIGHT
);
2379 m_bRightLine
= false;
2382 void SwBorderAttrs::IsLine_()
2384 m_bIsLine
= m_rBox
.GetTop() || m_rBox
.GetBottom() ||
2385 m_rBox
.GetLeft()|| m_rBox
.GetRight();
2389 /* The borders of neighboring paragraphs are condensed by following algorithm:
2391 * 1. No top border if the predecessor has the same top border and (3) applies.
2392 * In addition, the paragraph needs to have a border at least one side (left/right/bottom).
2393 * 2. No bottom border if the successor has the same bottom border and (3) applies.
2394 * In addition, the paragraph needs to have a border at least one side (left/right/top).
2395 * 3. The borders on the left and right side are identical between the current and the
2396 * pre-/succeeding paragraph.
2399 static bool CmpLines( const editeng::SvxBorderLine
*pL1
, const editeng::SvxBorderLine
*pL2
)
2401 return ( ((pL1
&& pL2
) && (*pL1
== *pL2
)) || (!pL1
&& !pL2
) );
2404 // OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
2405 // OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
2406 // instead of only the right LR-spacing, because R2L-layout has to be
2408 bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs
&rCmpAttrs
,
2409 const SwFrame
*pCaller
,
2410 const SwFrame
*pCmp
) const
2412 return ( CmpLines( rCmpAttrs
.GetBox().GetLeft(), GetBox().GetLeft() ) &&
2413 CmpLines( rCmpAttrs
.GetBox().GetRight(),GetBox().GetRight() ) &&
2414 CalcLeft( pCaller
) == rCmpAttrs
.CalcLeft( pCmp
) &&
2415 // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
2416 CalcRight( pCaller
) == rCmpAttrs
.CalcRight( pCmp
) );
2419 bool SwBorderAttrs::JoinWithCmp( const SwFrame
& _rCallerFrame
,
2420 const SwFrame
& _rCmpFrame
) const
2422 bool bReturnVal
= false;
2424 SwBorderAttrAccess
aCmpAccess( SwFrame::GetCache(), &_rCmpFrame
);
2425 const SwBorderAttrs
&rCmpAttrs
= *aCmpAccess
.Get();
2426 if ( m_rShadow
== rCmpAttrs
.GetShadow() &&
2427 CmpLines( m_rBox
.GetTop(), rCmpAttrs
.GetBox().GetTop() ) &&
2428 CmpLines( m_rBox
.GetBottom(), rCmpAttrs
.GetBox().GetBottom() ) &&
2429 CmpLeftRight( rCmpAttrs
, &_rCallerFrame
, &_rCmpFrame
)
2438 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2439 // previous frame. Calculated value saved in cached value <m_bJoinedWithPrev>
2440 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame>
2441 void SwBorderAttrs::CalcJoinedWithPrev( const SwFrame
& _rFrame
,
2442 const SwFrame
* _pPrevFrame
)
2445 m_bJoinedWithPrev
= false;
2447 if ( _rFrame
.IsTextFrame() )
2449 // text frame can potentially join with previous text frame, if
2450 // corresponding attribute set is set at previous text frame.
2451 // OD 2004-02-26 #i25029# - If parameter <_pPrevFrame> is set, take this
2452 // one as previous frame.
2453 const SwFrame
* pPrevFrame
= _pPrevFrame
? _pPrevFrame
: _rFrame
.GetPrev();
2454 // OD 2004-02-13 #i25029# - skip hidden text frames.
2455 while ( pPrevFrame
&& pPrevFrame
->IsTextFrame() &&
2456 static_cast<const SwTextFrame
*>(pPrevFrame
)->IsHiddenNow() )
2458 pPrevFrame
= pPrevFrame
->GetPrev();
2460 if ( pPrevFrame
&& pPrevFrame
->IsTextFrame() &&
2461 pPrevFrame
->GetAttrSet()->GetParaConnectBorder().GetValue()
2464 m_bJoinedWithPrev
= JoinWithCmp( _rFrame
, *pPrevFrame
);
2468 // valid cache status, if demanded
2469 // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrame>
2471 m_bCachedJoinedWithPrev
= m_bCacheGetLine
&& !_pPrevFrame
;
2474 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2475 // next frame. Calculated value saved in cached value <m_bJoinedWithNext>
2476 void SwBorderAttrs::CalcJoinedWithNext( const SwFrame
& _rFrame
)
2479 m_bJoinedWithNext
= false;
2481 if ( _rFrame
.IsTextFrame() )
2483 // text frame can potentially join with next text frame, if
2484 // corresponding attribute set is set at current text frame.
2485 // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
2486 const SwFrame
* pNextFrame
= _rFrame
.GetNext();
2487 while ( pNextFrame
&& pNextFrame
->IsTextFrame() &&
2488 static_cast<const SwTextFrame
*>(pNextFrame
)->IsHiddenNow() )
2490 pNextFrame
= pNextFrame
->GetNext();
2492 if ( pNextFrame
&& pNextFrame
->IsTextFrame() &&
2493 _rFrame
.GetAttrSet()->GetParaConnectBorder().GetValue()
2496 m_bJoinedWithNext
= JoinWithCmp( _rFrame
, *pNextFrame
);
2500 // valid cache status, if demanded
2501 m_bCachedJoinedWithNext
= m_bCacheGetLine
;
2504 // OD 21.05.2003 #108789# - accessor for cached values <m_bJoinedWithPrev>
2505 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame>, which is passed to
2506 // method <_CalcJoindWithPrev(..)>.
2507 bool SwBorderAttrs::JoinedWithPrev( const SwFrame
& _rFrame
,
2508 const SwFrame
* _pPrevFrame
) const
2510 if ( !m_bCachedJoinedWithPrev
|| _pPrevFrame
)
2512 // OD 2004-02-26 #i25029# - pass <_pPrevFrame> as 2nd parameter
2513 const_cast<SwBorderAttrs
*>(this)->CalcJoinedWithPrev( _rFrame
, _pPrevFrame
);
2516 return m_bJoinedWithPrev
;
2519 bool SwBorderAttrs::JoinedWithNext( const SwFrame
& _rFrame
) const
2521 if ( !m_bCachedJoinedWithNext
)
2523 const_cast<SwBorderAttrs
*>(this)->CalcJoinedWithNext( _rFrame
);
2526 return m_bJoinedWithNext
;
2529 // OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrame>, which is passed to
2530 // method <JoinedWithPrev>
2531 void SwBorderAttrs::GetTopLine_( const SwFrame
& _rFrame
,
2532 const SwFrame
* _pPrevFrame
)
2534 sal_uInt16 nRet
= CalcTopLine();
2536 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2537 // OD 2004-02-26 #i25029# - add 2nd parameter
2538 if ( JoinedWithPrev( _rFrame
, _pPrevFrame
) )
2543 m_bCachedGetTopLine
= m_bCacheGetLine
;
2545 m_nGetTopLine
= nRet
;
2548 void SwBorderAttrs::GetBottomLine_( const SwFrame
& _rFrame
)
2550 sal_uInt16 nRet
= CalcBottomLine();
2552 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2553 if ( JoinedWithNext( _rFrame
) )
2558 m_bCachedGetBottomLine
= m_bCacheGetLine
;
2560 m_nGetBottomLine
= nRet
;
2563 void SwBorderAttrs::CalcLineSpacing_()
2565 // tdf#125300 compatibility option AddParaLineSpacingToTableCells needs also line spacing
2566 const SvxLineSpacingItem
&rSpace
= m_rAttrSet
.GetLineSpacing();
2567 if ( rSpace
.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
&& rSpace
.GetPropLineSpace() > 100 )
2569 sal_Int32 nFontSize
= m_rAttrSet
.Get(RES_CHRATR_FONTSIZE
).GetHeight();
2570 m_nLineSpacing
= nFontSize
* (rSpace
.GetPropLineSpace() - 100) * 1.15 / 100;
2572 m_bLineSpacing
= false;
2575 static SwModify
const* GetCacheOwner(SwFrame
const& rFrame
)
2577 return rFrame
.IsContentFrame()
2578 ? static_cast<SwModify
const*>(rFrame
.IsTextFrame()
2579 // 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
2580 ? static_cast<const SwTextFrame
&>(rFrame
).GetTextNodeForParaProps()
2581 : static_cast<const SwNoTextFrame
&>(rFrame
).GetNode())
2582 : static_cast<SwModify
const*>(static_cast<const SwLayoutFrame
&>(rFrame
).GetFormat());
2585 SwBorderAttrAccess::SwBorderAttrAccess( SwCache
&rCach
, const SwFrame
*pFrame
) :
2586 SwCacheAccess( rCach
,
2587 static_cast<void const *>(GetCacheOwner(*pFrame
)),
2588 GetCacheOwner(*pFrame
)->IsInCache()),
2589 m_pConstructor( pFrame
)
2593 SwCacheObj
*SwBorderAttrAccess::NewObj()
2595 const_cast<SwModify
*>(static_cast<SwModify
const *>(m_pOwner
))->SetInCache( true );
2596 return new SwBorderAttrs( static_cast<SwModify
const *>(m_pOwner
), m_pConstructor
);
2599 SwBorderAttrs
*SwBorderAttrAccess::Get()
2601 return static_cast<SwBorderAttrs
*>(SwCacheAccess::Get());
2604 SwOrderIter::SwOrderIter( const SwPageFrame
*pPg
) :
2606 m_pCurrent( nullptr )
2610 void SwOrderIter::Top()
2612 m_pCurrent
= nullptr;
2613 if ( m_pPage
->GetSortedObjs() )
2615 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2616 if ( pObjs
->size() )
2618 sal_uInt32 nTopOrd
= 0;
2619 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2620 for (SwAnchoredObject
* i
: *pObjs
)
2622 const SdrObject
* pObj
= i
->GetDrawObj();
2623 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2625 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2626 if ( nTmp
>= nTopOrd
)
2636 const SdrObject
*SwOrderIter::Bottom()
2638 m_pCurrent
= nullptr;
2639 if ( m_pPage
->GetSortedObjs() )
2641 sal_uInt32 nBotOrd
= USHRT_MAX
;
2642 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2643 if ( pObjs
->size() )
2645 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2646 for (SwAnchoredObject
* i
: *pObjs
)
2648 const SdrObject
* pObj
= i
->GetDrawObj();
2649 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2651 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2652 if ( nTmp
< nBotOrd
)
2663 const SdrObject
*SwOrderIter::Next()
2665 const sal_uInt32 nCurOrd
= m_pCurrent
? m_pCurrent
->GetOrdNumDirect() : 0;
2666 m_pCurrent
= nullptr;
2667 if ( m_pPage
->GetSortedObjs() )
2669 sal_uInt32 nOrd
= USHRT_MAX
;
2670 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2671 if ( pObjs
->size() )
2673 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2674 for (SwAnchoredObject
* i
: *pObjs
)
2676 const SdrObject
* pObj
= i
->GetDrawObj();
2677 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2679 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2680 if ( nTmp
> nCurOrd
&& nTmp
< nOrd
)
2691 void SwOrderIter::Prev()
2693 const sal_uInt32 nCurOrd
= m_pCurrent
? m_pCurrent
->GetOrdNumDirect() : 0;
2694 m_pCurrent
= nullptr;
2695 if ( m_pPage
->GetSortedObjs() )
2697 const SwSortedObjs
*pObjs
= m_pPage
->GetSortedObjs();
2698 if ( pObjs
->size() )
2700 sal_uInt32 nOrd
= 0;
2701 (*pObjs
)[0]->GetDrawObj()->GetOrdNum(); // force updating
2702 for (SwAnchoredObject
* i
: *pObjs
)
2704 const SdrObject
* pObj
= i
->GetDrawObj();
2705 if ( dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) == nullptr )
2707 sal_uInt32 nTmp
= pObj
->GetOrdNumDirect();
2708 if ( nTmp
< nCurOrd
&& nTmp
>= nOrd
)
2718 /// Keep and restore the substructure of a layout frame for an action.
2720 // Do not look at each neighbor one by one to set all pointers correctly.
2721 // It is sufficient to detach a part of a chain and check if another chain needs to be added
2722 // when attaching it again. Only the pointers necessary for the chain connection need to be
2723 // adjusted. The correction happens in RestoreContent(). In between all access is restricted.
2724 // During this action, the Flys are detached from the page.
2726 // #115759# - 'remove' also drawing object from page and
2727 // at-fly anchored objects from page
2728 static void lcl_RemoveObjsFromPage( SwFrame
* _pFrame
)
2730 OSL_ENSURE( _pFrame
->GetDrawObjs(), "no DrawObjs in lcl_RemoveObjsFromPage." );
2731 SwSortedObjs
&rObjs
= *_pFrame
->GetDrawObjs();
2732 for (SwAnchoredObject
* pObj
: rObjs
)
2734 // #115759# - reset member, at which the anchored
2735 // object orients its vertical position
2736 pObj
->ClearVertPosOrientFrame();
2738 pObj
->ResetLayoutProcessBools();
2739 // #115759# - remove also lower objects of as-character
2740 // anchored Writer fly frames from page
2741 if ( dynamic_cast<const SwFlyFrame
*>( pObj
) != nullptr )
2743 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrame
*>(pObj
);
2745 // #115759# - remove also direct lowers of Writer
2746 // fly frame from page
2747 if ( pFlyFrame
->GetDrawObjs() )
2749 ::lcl_RemoveObjsFromPage( pFlyFrame
);
2752 SwContentFrame
* pCnt
= pFlyFrame
->ContainsContent();
2755 if ( pCnt
->GetDrawObjs() )
2756 ::lcl_RemoveObjsFromPage( pCnt
);
2757 pCnt
= pCnt
->GetNextContentFrame();
2759 if ( pFlyFrame
->IsFlyFreeFrame() )
2761 // #i28701# - use new method <GetPageFrame()>
2762 pFlyFrame
->GetPageFrame()->RemoveFlyFromPage( pFlyFrame
);
2765 // #115759# - remove also drawing objects from page
2766 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pObj
) != nullptr )
2768 if (pObj
->GetFrameFormat().GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR
)
2770 if (SwPageFrame
*pPg
= pObj
->GetPageFrame())
2771 pPg
->RemoveDrawObjFromPage(
2772 *static_cast<SwAnchoredDrawObject
*>(pObj
) );
2778 SwFrame
*SaveContent( SwLayoutFrame
*pLay
, SwFrame
*pStart
)
2780 if( pLay
->IsSctFrame() && pLay
->Lower() && pLay
->Lower()->IsColumnFrame() )
2781 sw_RemoveFootnotes( static_cast<SwColumnFrame
*>(pLay
->Lower()), true, true );
2784 if ( nullptr == (pSav
= pLay
->ContainsAny()) )
2787 if( pSav
->IsInFootnote() && !pLay
->IsInFootnote() )
2790 pSav
= pSav
->FindNext();
2791 while( pSav
&& pSav
->IsInFootnote() );
2792 if( !pSav
|| !pLay
->IsAnLower( pSav
) )
2796 // Tables should be saved as a whole, exception:
2797 // The contents of a section or a cell inside a table should be saved
2798 if ( pSav
->IsInTab() && !( ( pLay
->IsSctFrame() || pLay
->IsCellFrame() ) && pLay
->IsInTab() ) )
2799 while ( !pSav
->IsTabFrame() )
2800 pSav
= pSav
->GetUpper();
2802 if( pSav
->IsInSct() )
2803 { // search the upmost section inside of pLay
2804 SwFrame
* pSect
= pLay
->FindSctFrame();
2805 SwFrame
*pTmp
= pSav
;
2809 pTmp
= (pSav
&& pSav
->GetUpper()) ? pSav
->GetUpper()->FindSctFrame() : nullptr;
2810 } while ( pTmp
!= pSect
);
2813 SwFrame
*pFloat
= pSav
;
2816 bool bGo
= pStart
== pSav
;
2820 pFloat
->GetUpper()->m_pLower
= nullptr; // detach the chain part
2822 // search the end of the chain part, remove Flys on the way
2827 if ( pFloat
->IsContentFrame() )
2829 if ( pFloat
->GetDrawObjs() )
2830 ::lcl_RemoveObjsFromPage( static_cast<SwContentFrame
*>(pFloat
) );
2832 else if ( pFloat
->IsTabFrame() || pFloat
->IsSctFrame() )
2834 SwContentFrame
*pCnt
= static_cast<SwLayoutFrame
*>(pFloat
)->ContainsContent();
2838 { if ( pCnt
->GetDrawObjs() )
2839 ::lcl_RemoveObjsFromPage( pCnt
);
2840 pCnt
= pCnt
->GetNextContentFrame();
2841 } while ( pCnt
&& static_cast<SwLayoutFrame
*>(pFloat
)->IsAnLower( pCnt
) );
2845 OSL_ENSURE( !pFloat
, "new FloatFrame?" );
2848 if ( pFloat
->GetNext() )
2851 pFloat
->mpUpper
= nullptr;
2852 pFloat
= pFloat
->GetNext();
2853 if( !bGo
&& pFloat
== pStart
)
2856 pFloat
->mpPrev
->mpNext
= nullptr;
2857 pFloat
->mpPrev
= nullptr;
2865 // search next chain part and connect both chains
2866 SwFrame
*pTmp
= pFloat
->FindNext();
2868 pFloat
->mpUpper
= nullptr;
2870 if( !pLay
->IsInFootnote() )
2871 while( pTmp
&& pTmp
->IsInFootnote() )
2872 pTmp
= pTmp
->FindNext();
2874 if ( !pLay
->IsAnLower( pTmp
) )
2879 pFloat
->mpNext
= pTmp
; // connect both chains
2880 pFloat
->mpNext
->mpPrev
= pFloat
;
2883 bGo
= bGo
|| ( pStart
== pFloat
);
2886 return bGo
? pStart
: nullptr;
2889 // #115759# - add also drawing objects to page and at-fly
2890 // anchored objects to page
2891 static void lcl_AddObjsToPage( SwFrame
* _pFrame
, SwPageFrame
* _pPage
)
2893 OSL_ENSURE( _pFrame
->GetDrawObjs(), "no DrawObjs in lcl_AddObjsToPage." );
2894 SwSortedObjs
&rObjs
= *_pFrame
->GetDrawObjs();
2895 for (SwAnchoredObject
* pObj
: rObjs
)
2897 // #115759# - unlock position of anchored object
2898 // in order to get the object's position calculated.
2899 pObj
->UnlockPosition();
2900 // #115759# - add also lower objects of as-character
2901 // anchored Writer fly frames from page
2902 if ( dynamic_cast<const SwFlyFrame
*>( pObj
) != nullptr )
2904 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrame
*>(pObj
);
2905 if ( dynamic_cast<const SwFlyFreeFrame
*>( pObj
) != nullptr )
2907 _pPage
->AppendFlyToPage( pFlyFrame
);
2909 pFlyFrame
->InvalidatePos_();
2910 pFlyFrame
->InvalidateSize_();
2911 pFlyFrame
->InvalidatePage( _pPage
);
2913 // #115759# - add also at-fly anchored objects
2915 if ( pFlyFrame
->GetDrawObjs() )
2917 ::lcl_AddObjsToPage( pFlyFrame
, _pPage
);
2920 SwContentFrame
*pCnt
= pFlyFrame
->ContainsContent();
2923 if ( pCnt
->GetDrawObjs() )
2924 ::lcl_AddObjsToPage( pCnt
, _pPage
);
2925 pCnt
= pCnt
->GetNextContentFrame();
2928 // #115759# - remove also drawing objects from page
2929 else if ( dynamic_cast<const SwAnchoredDrawObject
*>( pObj
) != nullptr )
2931 if (pObj
->GetFrameFormat().GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR
)
2933 pObj
->InvalidateObjPos();
2934 _pPage
->AppendDrawObjToPage(
2935 *static_cast<SwAnchoredDrawObject
*>(pObj
) );
2941 void RestoreContent( SwFrame
*pSav
, SwLayoutFrame
*pParent
, SwFrame
*pSibling
)
2943 OSL_ENSURE( pSav
&& pParent
, "no Save or Parent provided for RestoreContent." );
2944 SwRectFnSet
aRectFnSet(pParent
);
2946 // If there are already FlowFrames below the new parent, so add the chain (starting with pSav)
2947 // after the last one. The parts are inserted and invalidated if needed.
2948 // On the way, the Flys of the ContentFrames are registered at the page.
2950 SwPageFrame
*pPage
= pParent
->FindPageFrame();
2953 pPage
->InvalidatePage( pPage
);
2955 // determine predecessor and establish connection or initialize
2956 pSav
->mpPrev
= pSibling
;
2960 pNxt
= pSibling
->mpNext
;
2961 pSibling
->mpNext
= pSav
;
2962 pSibling
->InvalidatePrt_();
2963 pSibling
->InvalidatePage( pPage
);
2964 SwFlowFrame
*pFlowFrame
= dynamic_cast<SwFlowFrame
*>(pSibling
);
2965 if (pFlowFrame
&& pFlowFrame
->GetFollow())
2966 pSibling
->Prepare( PREP_CLEAR
, nullptr, false );
2969 { pNxt
= pParent
->m_pLower
;
2970 pParent
->m_pLower
= pSav
;
2971 pSav
->mpUpper
= pParent
; // set here already, so that it is explicit when invalidating
2973 if ( pSav
->IsContentFrame() )
2974 static_cast<SwContentFrame
*>(pSav
)->InvalidatePage( pPage
);
2976 { // pSav might be an empty SectFrame
2977 SwContentFrame
* pCnt
= pParent
->ContainsContent();
2979 pCnt
->InvalidatePage( pPage
);
2983 // the parent needs to grow appropriately
2984 SwTwips nGrowVal
= 0;
2987 { pSav
->mpUpper
= pParent
;
2988 nGrowVal
+= aRectFnSet
.GetHeight(pSav
->getFrameArea());
2989 pSav
->InvalidateAll_();
2991 // register Flys, if TextFrames than also invalidate appropriately
2992 if ( pSav
->IsContentFrame() )
2994 if ( pSav
->IsTextFrame() &&
2995 static_cast<SwTextFrame
*>(pSav
)->GetCacheIdx() != USHRT_MAX
)
2996 static_cast<SwTextFrame
*>(pSav
)->Init(); // I am its friend
2998 if ( pPage
&& pSav
->GetDrawObjs() )
2999 ::lcl_AddObjsToPage( static_cast<SwContentFrame
*>(pSav
), pPage
);
3002 { SwContentFrame
*pBlub
= static_cast<SwLayoutFrame
*>(pSav
)->ContainsContent();
3006 { if ( pPage
&& pBlub
->GetDrawObjs() )
3007 ::lcl_AddObjsToPage( pBlub
, pPage
);
3008 if( pBlub
->IsTextFrame() && static_cast<SwTextFrame
*>(pBlub
)->HasFootnote() &&
3009 static_cast<SwTextFrame
*>(pBlub
)->GetCacheIdx() != USHRT_MAX
)
3010 static_cast<SwTextFrame
*>(pBlub
)->Init(); // I am its friend
3011 pBlub
= pBlub
->GetNextContentFrame();
3012 } while ( pBlub
&& static_cast<SwLayoutFrame
*>(pSav
)->IsAnLower( pBlub
));
3016 pSav
= pSav
->GetNext();
3022 pLast
->mpNext
= pNxt
;
3023 pNxt
->mpPrev
= pLast
;
3026 pParent
->Grow( nGrowVal
);
3031 bool IsRightPageByNumber(SwRootFrame
const& rLayout
, sal_uInt16
const nPageNum
)
3033 assert(rLayout
.GetLower());
3034 // unfortunately can only get SwPageDesc, not SwFormatPageDesc here...
3035 auto const nFirstVirtPageNum(rLayout
.GetLower()->GetVirtPageNum());
3036 bool const isFirstPageOfLayoutOdd(nFirstVirtPageNum
% 2 == 1);
3037 return ((nPageNum
% 2) == 1) == isFirstPageOfLayoutOdd
;
3042 SwPageFrame
* InsertNewPage( SwPageDesc
&rDesc
, SwFrame
*pUpper
,
3043 bool const isRightPage
, bool const bFirst
, bool bInsertEmpty
,
3044 bool const bFootnote
,
3048 assert(pUpper
->IsRootFrame());
3049 assert(!pSibling
|| static_cast<SwLayoutFrame
const*>(pUpper
)->Lower() != pSibling
); // currently no insert before 1st page
3051 SwDoc
*pDoc
= static_cast<SwLayoutFrame
*>(pUpper
)->GetFormat()->GetDoc();
3054 if (rDesc
.IsFirstShared())
3056 // We need to fallback to left or right page format, decide it now.
3057 // FIXME: is this still needed?
3060 rDesc
.GetFirstMaster().SetFormatAttr( rDesc
.GetMaster().GetHeader() );
3061 rDesc
.GetFirstMaster().SetFormatAttr( rDesc
.GetMaster().GetFooter() );
3062 // fdo#60250 copy margins for mirrored pages
3063 rDesc
.GetFirstMaster().SetFormatAttr( rDesc
.GetMaster().GetLRSpace() );
3067 rDesc
.GetFirstLeft().SetFormatAttr( rDesc
.GetLeft().GetHeader() );
3068 rDesc
.GetFirstLeft().SetFormatAttr( rDesc
.GetLeft().GetFooter() );
3069 rDesc
.GetFirstLeft().SetFormatAttr( rDesc
.GetLeft().GetLRSpace() );
3073 SwFrameFormat
*pFormat(isRightPage
? rDesc
.GetRightFormat(bFirst
) : rDesc
.GetLeftFormat(bFirst
));
3074 // If there is no FrameFormat for this page, add an empty page
3077 pFormat
= isRightPage
? rDesc
.GetLeftFormat() : rDesc
.GetRightFormat();
3078 OSL_ENSURE( pFormat
, "Descriptor without any format?!" );
3079 bInsertEmpty
= !bInsertEmpty
;
3083 SwPageDesc
*pTmpDesc
= pSibling
&& pSibling
->GetPrev() ?
3084 static_cast<SwPageFrame
*>(pSibling
->GetPrev())->GetPageDesc() : &rDesc
;
3085 pRet
= new SwPageFrame( pDoc
->GetEmptyPageFormat(), pUpper
, pTmpDesc
);
3086 SAL_INFO( "sw.pageframe", "InsertNewPage - insert empty p: " << pRet
<< " d: " << pTmpDesc
);
3087 pRet
->Paste( pUpper
, pSibling
);
3088 pRet
->PreparePage( bFootnote
);
3090 pRet
= new SwPageFrame( pFormat
, pUpper
, &rDesc
);
3091 SAL_INFO( "sw.pageframe", "InsertNewPage p: " << pRet
<< " d: " << &rDesc
<< " f: " << pFormat
);
3092 pRet
->Paste( pUpper
, pSibling
);
3093 pRet
->PreparePage( bFootnote
);
3094 if ( pRet
->GetNext() )
3095 SwRootFrame::AssertPageFlys( pRet
);
3099 /* The following two methods search the layout structure recursively and
3100 * register all Flys at the page that have a Frame in this structure as an anchor.
3103 static void lcl_Regist( SwPageFrame
*pPage
, const SwFrame
*pAnch
)
3105 SwSortedObjs
*pObjs
= const_cast<SwSortedObjs
*>(pAnch
->GetDrawObjs());
3106 for (SwAnchoredObject
* pObj
: *pObjs
)
3108 if ( dynamic_cast<const SwFlyFrame
*>( pObj
) != nullptr )
3110 SwFlyFrame
*pFly
= static_cast<SwFlyFrame
*>(pObj
);
3111 // register (not if already known)
3112 // #i28701# - use new method <GetPageFrame()>
3113 SwPageFrame
*pPg
= pFly
->IsFlyFreeFrame()
3114 ? pFly
->GetPageFrame() : pFly
->FindPageFrame();
3118 pPg
->RemoveFlyFromPage( pFly
);
3119 pPage
->AppendFlyToPage( pFly
);
3121 ::RegistFlys( pPage
, pFly
);
3126 if ( pPage
!= pObj
->GetPageFrame() )
3129 if (SwPageFrame
*pPg
= pObj
->GetPageFrame())
3130 pPg
->RemoveDrawObjFromPage( *pObj
);
3131 pPage
->AppendDrawObjToPage( *pObj
);
3135 const SwFlyFrame
* pFly
= pAnch
->FindFlyFrame();
3137 pObj
->GetDrawObj()->GetOrdNum() < pFly
->GetVirtDrawObj()->GetOrdNum() &&
3138 pObj
->GetDrawObj()->getSdrPageFromSdrObject() )
3140 //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
3141 pObj
->DrawObj()->getSdrPageFromSdrObject()->SetObjectOrdNum( pFly
->GetVirtDrawObj()->GetOrdNumDirect(),
3142 pObj
->GetDrawObj()->GetOrdNumDirect() );
3147 void RegistFlys( SwPageFrame
*pPage
, const SwLayoutFrame
*pLay
)
3149 if ( pLay
->GetDrawObjs() )
3150 ::lcl_Regist( pPage
, pLay
);
3151 const SwFrame
*pFrame
= pLay
->Lower();
3154 if ( pFrame
->IsLayoutFrame() )
3155 ::RegistFlys( pPage
, static_cast<const SwLayoutFrame
*>(pFrame
) );
3156 else if ( pFrame
->GetDrawObjs() )
3157 ::lcl_Regist( pPage
, pFrame
);
3158 pFrame
= pFrame
->GetNext();
3162 /// Notify the background based on the difference between old and new rectangle
3163 void Notify( SwFlyFrame
*pFly
, SwPageFrame
*pOld
, const SwRect
&rOld
,
3164 const SwRect
* pOldPrt
)
3166 const SwRect
aFrame( pFly
->GetObjRectWithSpaces() );
3167 if ( rOld
.Pos() != aFrame
.Pos() )
3168 { // changed position, invalidate old and new area
3169 if ( rOld
.HasArea() &&
3170 rOld
.Left()+pFly
->GetFormat()->GetLRSpace().GetLeft() < FAR_AWAY
)
3172 pFly
->NotifyBackground( pOld
, rOld
, PREP_FLY_LEAVE
);
3174 pFly
->NotifyBackground( pFly
->FindPageFrame(), aFrame
, PREP_FLY_ARRIVE
);
3176 else if ( rOld
.SSize() != aFrame
.SSize() )
3177 { // changed size, invalidate the area that was left or is now overlapped
3178 // For simplicity, we purposely invalidate a Twip even if not needed.
3180 SwViewShell
*pSh
= pFly
->getRootFrame()->GetCurrShell();
3181 if( pSh
&& rOld
.HasArea() )
3182 pSh
->InvalidateWindows( rOld
);
3184 // #i51941# - consider case that fly frame isn't
3185 // registered at the old page <pOld>
3186 SwPageFrame
* pPageFrame
= pFly
->FindPageFrame();
3187 if ( pOld
!= pPageFrame
)
3189 pFly
->NotifyBackground( pPageFrame
, aFrame
, PREP_FLY_ARRIVE
);
3192 if ( rOld
.Left() != aFrame
.Left() )
3194 SwRect
aTmp( rOld
);
3195 aTmp
.Union( aFrame
);
3196 aTmp
.Left( std::min(aFrame
.Left(), rOld
.Left()) );
3197 aTmp
.Right( std::max(aFrame
.Left(), rOld
.Left()) );
3198 pFly
->NotifyBackground( pOld
, aTmp
, PREP_FLY_CHGD
);
3200 SwTwips nOld
= rOld
.Right();
3201 SwTwips nNew
= aFrame
.Right();
3204 SwRect
aTmp( rOld
);
3205 aTmp
.Union( aFrame
);
3206 aTmp
.Left( std::min(nNew
, nOld
) );
3207 aTmp
.Right( std::max(nNew
, nOld
) );
3208 pFly
->NotifyBackground( pOld
, aTmp
, PREP_FLY_CHGD
);
3210 if ( rOld
.Top() != aFrame
.Top() )
3212 SwRect
aTmp( rOld
);
3213 aTmp
.Union( aFrame
);
3214 aTmp
.Top( std::min(aFrame
.Top(), rOld
.Top()) );
3215 aTmp
.Bottom( std::max(aFrame
.Top(), rOld
.Top()) );
3216 pFly
->NotifyBackground( pOld
, aTmp
, PREP_FLY_CHGD
);
3218 nOld
= rOld
.Bottom();
3219 nNew
= aFrame
.Bottom();
3222 SwRect
aTmp( rOld
);
3223 aTmp
.Union( aFrame
);
3224 aTmp
.Top( std::min(nNew
, nOld
) );
3225 aTmp
.Bottom( std::max(nNew
, nOld
) );
3226 pFly
->NotifyBackground( pOld
, aTmp
, PREP_FLY_CHGD
);
3229 else if(pOldPrt
&& *pOldPrt
!= pFly
->getFramePrintArea())
3231 bool bNotifyBackground(pFly
->GetFormat()->GetSurround().IsContour());
3233 if(!bNotifyBackground
&&
3234 pFly
->IsFlyFreeFrame() &&
3235 static_cast< const SwFlyFreeFrame
* >(pFly
)->supportsAutoContour())
3237 // RotateFlyFrame3: Also notify for FlyFrames which allow AutoContour
3238 bNotifyBackground
= true;
3241 if(bNotifyBackground
)
3244 pFly
->NotifyBackground( pFly
->FindPageFrame(), aFrame
, PREP_FLY_ARRIVE
);
3249 static void lcl_CheckFlowBack( SwFrame
* pFrame
, const SwRect
&rRect
)
3251 SwTwips nBottom
= rRect
.Bottom();
3254 if( pFrame
->IsLayoutFrame() )
3256 if( rRect
.IsOver( pFrame
->getFrameArea() ) )
3257 lcl_CheckFlowBack( static_cast<SwLayoutFrame
*>(pFrame
)->Lower(), rRect
);
3259 else if( !pFrame
->GetNext() && nBottom
> pFrame
->getFrameArea().Bottom() )
3261 if( pFrame
->IsContentFrame() && static_cast<SwContentFrame
*>(pFrame
)->HasFollow() )
3262 pFrame
->InvalidateSize();
3264 pFrame
->InvalidateNextPos();
3266 pFrame
= pFrame
->GetNext();
3270 static void lcl_NotifyContent( const SdrObject
*pThis
, SwContentFrame
*pCnt
,
3271 const SwRect
&rRect
, const PrepareHint eHint
)
3273 if ( pCnt
->IsTextFrame() )
3275 SwRect
aCntPrt( pCnt
->getFramePrintArea() );
3276 aCntPrt
.Pos() += pCnt
->getFrameArea().Pos();
3277 if ( eHint
== PREP_FLY_ATTR_CHG
)
3279 // #i35640# - use given rectangle <rRect> instead
3280 // of current bound rectangle
3281 if ( aCntPrt
.IsOver( rRect
) )
3282 pCnt
->Prepare( PREP_FLY_ATTR_CHG
);
3284 // #i23129# - only invalidate, if the text frame
3285 // printing area overlaps with the given rectangle.
3286 else if ( aCntPrt
.IsOver( rRect
) )
3287 pCnt
->Prepare( eHint
, static_cast<void*>(&aCntPrt
.Intersection_( rRect
)) );
3288 if ( pCnt
->GetDrawObjs() )
3290 const SwSortedObjs
&rObjs
= *pCnt
->GetDrawObjs();
3291 for (SwAnchoredObject
* pObj
: rObjs
)
3293 if ( dynamic_cast<const SwFlyFrame
*>( pObj
) != nullptr )
3295 SwFlyFrame
*pFly
= static_cast<SwFlyFrame
*>(pObj
);
3296 if ( pFly
->IsFlyInContentFrame() )
3298 SwContentFrame
*pContent
= pFly
->ContainsContent();
3301 ::lcl_NotifyContent( pThis
, pContent
, rRect
, eHint
);
3302 pContent
= pContent
->GetNextContentFrame();
3311 void Notify_Background( const SdrObject
* pObj
,
3313 const SwRect
& rRect
,
3314 const PrepareHint eHint
,
3317 // If the frame was positioned correctly for the first time, do not inform the old area
3318 if ( eHint
== PREP_FLY_LEAVE
&& rRect
.Top() == FAR_AWAY
)
3321 SwLayoutFrame
* pArea
;
3322 SwFlyFrame
*pFlyFrame
= nullptr;
3324 if( auto pVirtFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>( pObj
) )
3326 pFlyFrame
= const_cast<SwVirtFlyDrawObj
*>(pVirtFlyDrawObj
)->GetFlyFrame();
3327 pAnchor
= pFlyFrame
->AnchorFrame();
3331 pFlyFrame
= nullptr;
3332 pAnchor
= const_cast<SwFrame
*>(
3333 GetUserCall(pObj
)->GetAnchoredObj( pObj
)->GetAnchorFrame() );
3335 if( PREP_FLY_LEAVE
!= eHint
&& pAnchor
->IsInFly() )
3336 pArea
= pAnchor
->FindFlyFrame();
3339 SwContentFrame
*pCnt
= nullptr;
3342 if( PREP_FLY_ARRIVE
!= eHint
)
3343 lcl_CheckFlowBack( pArea
, rRect
);
3345 // Only the Flys following this anchor are reacting. Thus, those do not
3346 // need to be processed.
3347 // An exception is LEAVE, since the Fly might come "from above".
3348 // If the anchor is positioned on the previous page, the whole page
3349 // needs to be processed (47722).
3350 // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
3351 // on the object positioning, the complete area has to be processed,
3352 // because content frames before the anchor frame also have to consider
3353 // the object for the text wrapping.
3354 // #i3317# - The complete area has always been
3357 pCnt
= pArea
->ContainsContent();
3360 SwFrame
*pLastTab
= nullptr;
3362 bool isValidTableBeforeAnchor(false);
3363 while ( pCnt
&& pArea
&& pArea
->IsAnLower( pCnt
) )
3365 ::lcl_NotifyContent( pObj
, pCnt
, rRect
, eHint
);
3366 if ( pCnt
->IsInTab() )
3368 SwTabFrame
*pTab
= pCnt
->FindTabFrame();
3369 if ( pTab
!= pLastTab
)
3372 isValidTableBeforeAnchor
= false;
3373 if (PREP_FLY_ARRIVE
== eHint
3374 && pFlyFrame
// TODO: do it for draw objects too?
3375 && pTab
->IsFollow() // table starts on previous page?
3376 // "through" means they will actually overlap anyway
3377 && css::text::WrapTextMode_THROUGH
!= pFlyFrame
->GetFormat()->GetSurround().GetSurround()
3378 // if it's anchored in footer it can't move to other page
3379 && !pAnchor
->FindFooterOrHeader())
3381 SwFrame
* pTmp(pAnchor
->GetPrev());
3386 // tdf#99460 the table shouldn't be moved by the fly
3387 isValidTableBeforeAnchor
= true;
3390 pTmp
= pTmp
->GetPrev();
3393 // #i40606# - use <GetLastBoundRect()>
3394 // instead of <GetCurrentBoundRect()>, because a recalculation
3395 // of the bounding rectangle isn't intended here.
3396 if (!isValidTableBeforeAnchor
3397 && (pTab
->getFrameArea().IsOver(pObj
->GetLastBoundRect()) ||
3398 pTab
->getFrameArea().IsOver(rRect
)))
3400 if ( !pFlyFrame
|| !pFlyFrame
->IsLowerOf( pTab
) )
3401 pTab
->InvalidatePrt();
3404 SwLayoutFrame
* pCell
= pCnt
->GetUpper();
3405 // #i40606# - use <GetLastBoundRect()>
3406 // instead of <GetCurrentBoundRect()>, because a recalculation
3407 // of the bounding rectangle isn't intended here.
3408 if (!isValidTableBeforeAnchor
&& pCell
->IsCellFrame() &&
3409 ( pCell
->getFrameArea().IsOver( pObj
->GetLastBoundRect() ) ||
3410 pCell
->getFrameArea().IsOver( rRect
) ) )
3412 const SwFormatVertOrient
&rOri
= pCell
->GetFormat()->GetVertOrient();
3413 if ( text::VertOrientation::NONE
!= rOri
.GetVertOrient() )
3414 pCell
->InvalidatePrt();
3417 pCnt
= pCnt
->GetNextContentFrame();
3419 // #128702# - make code robust
3420 if ( pPage
&& pPage
->GetSortedObjs() )
3423 const SwSortedObjs
&rObjs
= *pPage
->GetSortedObjs();
3424 for (SwAnchoredObject
* pAnchoredObj
: rObjs
)
3426 if ( dynamic_cast<const SwFlyFrame
*>( pAnchoredObj
) != nullptr )
3428 if( pAnchoredObj
->GetDrawObj() == pObj
)
3430 SwFlyFrame
*pFly
= static_cast<SwFlyFrame
*>(pAnchoredObj
);
3431 if ( pFly
->getFrameArea().Top() == FAR_AWAY
)
3435 (!pFly
->IsLowerOf( pFlyFrame
) &&
3436 pFly
->GetVirtDrawObj()->GetOrdNumDirect() < pObj
->GetOrdNumDirect()))
3438 pCnt
= pFly
->ContainsContent();
3441 ::lcl_NotifyContent( pObj
, pCnt
, rRect
, eHint
);
3442 pCnt
= pCnt
->GetNextContentFrame();
3445 if( pFly
->IsFlyLayFrame() )
3447 if( pFly
->Lower() && pFly
->Lower()->IsColumnFrame() &&
3448 pFly
->getFrameArea().Bottom() >= rRect
.Top() &&
3449 pFly
->getFrameArea().Top() <= rRect
.Bottom() &&
3450 pFly
->getFrameArea().Right() >= rRect
.Left() &&
3451 pFly
->getFrameArea().Left() <= rRect
.Right() )
3453 pFly
->InvalidateSize();
3456 // Flys above myself might sidestep if they have an automatic
3457 // alignment. This happens independently of my attributes since
3458 // this might have been changed as well.
3459 else if ( pFly
->IsFlyAtContentFrame() &&
3460 pObj
->GetOrdNumDirect() <
3461 pFly
->GetVirtDrawObj()->GetOrdNumDirect() &&
3462 pFlyFrame
&& !pFly
->IsLowerOf( pFlyFrame
) )
3464 const SwFormatHoriOrient
&rH
= pFly
->GetFormat()->GetHoriOrient();
3465 if ( text::HoriOrientation::NONE
!= rH
.GetHoriOrient() &&
3466 text::HoriOrientation::CENTER
!= rH
.GetHoriOrient() &&
3467 ( !pFly
->IsAutoPos() || text::RelOrientation::CHAR
!= rH
.GetRelationOrient() ) &&
3468 (pFly
->getFrameArea().Bottom() >= rRect
.Top() &&
3469 pFly
->getFrameArea().Top() <= rRect
.Bottom()) )
3470 pFly
->InvalidatePos();
3475 if ( pFlyFrame
&& pAnchor
->GetUpper() && pAnchor
->IsInTab() )//MA_FLY_HEIGHT
3476 pAnchor
->GetUpper()->InvalidateSize();
3478 // #i82258# - make code robust
3479 SwViewShell
* pSh
= nullptr;
3480 if ( bInva
&& pPage
&&
3481 nullptr != (pSh
= pPage
->getRootFrame()->GetCurrShell()) )
3483 pSh
->InvalidateWindows( rRect
);
3487 /// Provides the Upper of an anchor in paragraph-bound objects. If the latter
3488 /// is a chained border or a footnote, the "virtual" Upper might be returned.
3489 const SwFrame
* GetVirtualUpper( const SwFrame
* pFrame
, const Point
& rPos
)
3491 if( pFrame
->IsTextFrame() )
3493 pFrame
= pFrame
->GetUpper();
3494 if( !pFrame
->getFrameArea().IsInside( rPos
) )
3496 if( pFrame
->IsFootnoteFrame() )
3498 const SwFootnoteFrame
* pTmp
= static_cast<const SwFootnoteFrame
*>(pFrame
)->GetFollow();
3501 if( pTmp
->getFrameArea().IsInside( rPos
) )
3503 pTmp
= pTmp
->GetFollow();
3508 SwFlyFrame
* pTmp
= const_cast<SwFlyFrame
*>(pFrame
->FindFlyFrame());
3511 if( pTmp
->getFrameArea().IsInside( rPos
) )
3513 pTmp
= pTmp
->GetNextLink();
3521 bool Is_Lower_Of(const SwFrame
*pCurrFrame
, const SdrObject
* pObj
)
3524 const SwFrame
* pFrame
;
3525 if (const SwVirtFlyDrawObj
*pFlyDrawObj
= dynamic_cast<const SwVirtFlyDrawObj
*>(pObj
))
3527 const SwFlyFrame
* pFly
= pFlyDrawObj
->GetFlyFrame();
3528 pFrame
= pFly
->GetAnchorFrame();
3529 aPos
= pFly
->getFrameArea().Pos();
3533 pFrame
= static_cast<SwDrawContact
*>(GetUserCall(pObj
))->GetAnchorFrame(pObj
);
3534 aPos
= pObj
->GetCurrentBoundRect().TopLeft();
3536 OSL_ENSURE( pFrame
, "8-( Fly is lost in Space." );
3537 pFrame
= GetVirtualUpper( pFrame
, aPos
);
3539 { if ( pFrame
== pCurrFrame
)
3541 if( pFrame
->IsFlyFrame() )
3543 aPos
= pFrame
->getFrameArea().Pos();
3544 pFrame
= GetVirtualUpper( static_cast<const SwFlyFrame
*>(pFrame
)->GetAnchorFrame(), aPos
);
3547 pFrame
= pFrame
->GetUpper();
3552 /// provides the area of a frame in that no Fly from another area can overlap
3553 const SwFrame
*FindContext( const SwFrame
*pFrame
, SwFrameType nAdditionalContextType
)
3555 const SwFrameType nTyp
= SwFrameType::Root
| SwFrameType::Header
| SwFrameType::Footer
| SwFrameType::FtnCont
|
3556 SwFrameType::Ftn
| SwFrameType::Fly
|
3557 SwFrameType::Tab
| SwFrameType::Row
| SwFrameType::Cell
|
3558 nAdditionalContextType
;
3560 { if ( pFrame
->GetType() & nTyp
)
3562 pFrame
= pFrame
->GetUpper();
3567 bool IsFrameInSameContext( const SwFrame
*pInnerFrame
, const SwFrame
*pFrame
)
3569 const SwFrame
*pContext
= FindContext( pInnerFrame
, SwFrameType::None
);
3571 const SwFrameType nTyp
= SwFrameType::Root
| SwFrameType::Header
| SwFrameType::Footer
| SwFrameType::FtnCont
|
3572 SwFrameType::Ftn
| SwFrameType::Fly
|
3573 SwFrameType::Tab
| SwFrameType::Row
| SwFrameType::Cell
;
3575 { if ( pFrame
->GetType() & nTyp
)
3577 if( pFrame
== pContext
)
3579 if( pFrame
->IsCellFrame() )
3582 if( pFrame
->IsFlyFrame() )
3584 Point
aPos( pFrame
->getFrameArea().Pos() );
3585 pFrame
= GetVirtualUpper( static_cast<const SwFlyFrame
*>(pFrame
)->GetAnchorFrame(), aPos
);
3588 pFrame
= pFrame
->GetUpper();
3594 static SwTwips
lcl_CalcCellRstHeight( SwLayoutFrame
*pCell
)
3596 SwFrame
*pLow
= pCell
->Lower();
3597 if ( pLow
&& (pLow
->IsContentFrame() || pLow
->IsSctFrame()) )
3599 long nHeight
= 0, nFlyAdd
= 0;
3602 long nLow
= pLow
->getFrameArea().Height();
3603 if( pLow
->IsTextFrame() && static_cast<SwTextFrame
*>(pLow
)->IsUndersized() )
3604 nLow
+= static_cast<SwTextFrame
*>(pLow
)->GetParHeight()-pLow
->getFramePrintArea().Height();
3605 else if( pLow
->IsSctFrame() && static_cast<SwSectionFrame
*>(pLow
)->IsUndersized() )
3606 nLow
+= static_cast<SwSectionFrame
*>(pLow
)->Undersize();
3607 nFlyAdd
= std::max( 0L, nFlyAdd
- nLow
);
3608 nFlyAdd
= std::max( nFlyAdd
, ::CalcHeightWithFlys( pLow
) );
3610 pLow
= pLow
->GetNext();
3615 // The border cannot be calculated based on PrtArea and Frame, since both can be invalid.
3616 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), pCell
);
3617 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
3618 nHeight
+= rAttrs
.CalcTop() + rAttrs
.CalcBottom();
3620 return pCell
->getFrameArea().Height() - nHeight
;
3624 long nRstHeight
= 0;
3625 while (pLow
&& pLow
->IsLayoutFrame())
3627 nRstHeight
+= ::CalcRowRstHeight(static_cast<SwLayoutFrame
*>(pLow
));
3628 pLow
= pLow
->GetNext();
3634 SwTwips
CalcRowRstHeight( SwLayoutFrame
*pRow
)
3636 SwFrame
*pLow
= pRow
->Lower();
3637 if (!(pLow
&& pLow
->IsLayoutFrame()))
3641 SwTwips nRstHeight
= LONG_MAX
;
3642 while (pLow
&& pLow
->IsLayoutFrame())
3644 nRstHeight
= std::min(nRstHeight
, ::lcl_CalcCellRstHeight(static_cast<SwLayoutFrame
*>(pLow
)));
3645 pLow
= pLow
->GetNext();
3650 const SwFrame
* FindPage( const SwRect
&rRect
, const SwFrame
*pPage
)
3652 if ( !rRect
.IsOver( pPage
->getFrameArea() ) )
3654 const SwRootFrame
* pRootFrame
= static_cast<const SwRootFrame
*>(pPage
->GetUpper());
3655 const SwFrame
* pTmpPage
= pRootFrame
? pRootFrame
->GetPageAtPos( rRect
.TopLeft(), &rRect
.SSize(), true ) : nullptr;
3663 class SwFrameHolder
: private SfxListener
3667 virtual void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
) override
;
3669 SwFrameHolder() : pFrame(nullptr), bSet(false) {}
3670 void SetFrame( SwFrame
* pHold
);
3671 SwFrame
* GetFrame() { return pFrame
; }
3673 bool IsSet() const { return bSet
; }
3676 void SwFrameHolder::SetFrame( SwFrame
* pHold
)
3679 if (pFrame
!= pHold
)
3682 EndListening(*pFrame
);
3683 StartListening(*pHold
);
3688 void SwFrameHolder::Reset()
3691 EndListening(*pFrame
);
3696 void SwFrameHolder::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
3698 if ( rHint
.GetId() == SfxHintId::Dying
&& &rBC
== pFrame
)
3704 SwFrame
* GetFrameOfModify(SwRootFrame
const*const pLayout
, SwModify
const& rMod
,
3705 SwFrameType
const nFrameType
, SwPosition
const*const pPos
,
3706 std::pair
<Point
, bool> const*const pViewPosAndCalcFrame
)
3708 SwFrame
*pMinFrame
= nullptr, *pTmpFrame
;
3709 SwFrameHolder aHolder
;
3711 bool bClientIterChanged
= false;
3713 SwIterator
<SwFrame
, SwModify
, sw::IteratorMode::UnwrapMulti
> aIter(rMod
);
3715 pMinFrame
= nullptr;
3717 sal_uInt64 nMinDist
= 0;
3718 bClientIterChanged
= false;
3720 for( pTmpFrame
= aIter
.First(); pTmpFrame
; pTmpFrame
= aIter
.Next() )
3722 if( pTmpFrame
->GetType() & nFrameType
&&
3723 ( !pLayout
|| pLayout
== pTmpFrame
->getRootFrame() ) &&
3724 (!pTmpFrame
->IsFlowFrame() ||
3725 !SwFlowFrame::CastFlowFrame( pTmpFrame
)->IsFollow() ))
3727 if (pViewPosAndCalcFrame
)
3729 // watch for Frame being deleted
3731 aHolder
.SetFrame( pMinFrame
);
3735 if (pViewPosAndCalcFrame
->second
)
3737 // tdf#108118 prevent recursion
3738 DisableCallbackAction
a(*pTmpFrame
->getRootFrame());
3739 // - format parent Writer
3740 // fly frame, if it isn't been formatted yet.
3741 // Note: The Writer fly frame could be the frame itself.
3742 SwFlyFrame
* pFlyFrame( pTmpFrame
->FindFlyFrame() );
3744 pFlyFrame
->getFrameArea().Pos().X() == FAR_AWAY
&&
3745 pFlyFrame
->getFrameArea().Pos().Y() == FAR_AWAY
)
3747 SwObjectFormatter::FormatObj( *pFlyFrame
);
3749 pTmpFrame
->Calc(pLayout
? pLayout
->GetCurrShell()->GetOut() : nullptr);
3752 // aIter.IsChanged checks if the current pTmpFrame has been deleted while
3753 // it is the current iterator
3754 // FrameHolder watches for deletion of the current pMinFrame
3755 if( aIter
.IsChanged() || ( aHolder
.IsSet() && !aHolder
.GetFrame() ) )
3757 // restart iteration
3758 bClientIterChanged
= true;
3762 // for Flys go via the parent if the Fly is not yet "formatted"
3763 if (!pViewPosAndCalcFrame
->second
&&
3764 pTmpFrame
->GetType() & SwFrameType::Fly
&&
3765 static_cast<SwFlyFrame
*>(pTmpFrame
)->GetAnchorFrame() &&
3766 FAR_AWAY
== pTmpFrame
->getFrameArea().Pos().getX() &&
3767 FAR_AWAY
== pTmpFrame
->getFrameArea().Pos().getY() )
3768 aCalcRect
= static_cast<SwFlyFrame
*>(pTmpFrame
)->GetAnchorFrame()->getFrameArea();
3770 aCalcRect
= pTmpFrame
->getFrameArea();
3772 if (aCalcRect
.IsInside(pViewPosAndCalcFrame
->first
))
3774 pMinFrame
= pTmpFrame
;
3778 // Point not in rectangle. Compare distances:
3779 const Point aCalcRectCenter
= aCalcRect
.Center();
3780 const Point aDiff
= aCalcRectCenter
- pViewPosAndCalcFrame
->first
;
3781 const sal_uInt64 nCurrentDist
= sal_Int64(aDiff
.getX()) * sal_Int64(aDiff
.getX()) + sal_Int64(aDiff
.getY()) * sal_Int64(aDiff
.getY()); // opt: no sqrt
3782 if ( !pMinFrame
|| nCurrentDist
< nMinDist
)
3784 pMinFrame
= pTmpFrame
;
3785 nMinDist
= nCurrentDist
;
3790 // if no pViewPosAndCalcFrame is provided, take the first one
3791 pMinFrame
= pTmpFrame
;
3796 } while( bClientIterChanged
);
3798 if( pPos
&& pMinFrame
&& pMinFrame
->IsTextFrame() )
3799 return static_cast<SwTextFrame
*>(pMinFrame
)->GetFrameAtPos( *pPos
);
3804 bool IsExtraData( const SwDoc
*pDoc
)
3806 const SwLineNumberInfo
&rInf
= pDoc
->GetLineNumberInfo();
3807 return rInf
.IsPaintLineNumbers() ||
3808 rInf
.IsCountInFlys() ||
3809 (static_cast<sal_Int16
>(SW_MOD()->GetRedlineMarkPos()) != text::HoriOrientation::NONE
&&
3810 !pDoc
->getIDocumentRedlineAccess().GetRedlineTable().empty());
3813 // OD 22.09.2003 #110978#
3814 SwRect
SwPageFrame::PrtWithoutHeaderAndFooter() const
3816 SwRect
aPrtWithoutHeaderFooter( getFramePrintArea() );
3817 aPrtWithoutHeaderFooter
.Pos() += getFrameArea().Pos();
3819 const SwFrame
* pLowerFrame
= Lower();
3820 while ( pLowerFrame
)
3822 // Note: independent on text direction page header and page footer are
3823 // always at top respectively at bottom of the page frame.
3824 if ( pLowerFrame
->IsHeaderFrame() )
3826 aPrtWithoutHeaderFooter
.Top( aPrtWithoutHeaderFooter
.Top() +
3827 pLowerFrame
->getFrameArea().Height() );
3829 if ( pLowerFrame
->IsFooterFrame() )
3831 aPrtWithoutHeaderFooter
.Bottom( aPrtWithoutHeaderFooter
.Bottom() -
3832 pLowerFrame
->getFrameArea().Height() );
3835 pLowerFrame
= pLowerFrame
->GetNext();
3838 return aPrtWithoutHeaderFooter
;
3841 /** method to determine the spacing values of a frame
3843 OD 2004-03-10 #i28701#
3844 OD 2009-08-28 #i102458#
3845 Add output parameter <obIsLineSpacingProportional>
3847 void GetSpacingValuesOfFrame( const SwFrame
& rFrame
,
3848 SwTwips
& onLowerSpacing
,
3849 SwTwips
& onLineSpacing
,
3850 bool& obIsLineSpacingProportional
)
3852 if ( !rFrame
.IsFlowFrame() )
3859 const SvxULSpaceItem
& rULSpace
= rFrame
.GetAttrSet()->GetULSpace();
3860 onLowerSpacing
= rULSpace
.GetLower();
3863 obIsLineSpacingProportional
= false;
3864 if ( rFrame
.IsTextFrame() )
3866 onLineSpacing
= static_cast<const SwTextFrame
&>(rFrame
).GetLineSpace();
3867 obIsLineSpacingProportional
=
3868 onLineSpacing
!= 0 &&
3869 static_cast<const SwTextFrame
&>(rFrame
).GetLineSpace( true ) == 0;
3872 OSL_ENSURE( onLowerSpacing
>= 0 && onLineSpacing
>= 0,
3873 "<GetSpacingValuesOfFrame(..)> - spacing values aren't positive!" );
3877 /// get the content of the table cell, skipping content from nested tables
3878 const SwContentFrame
* GetCellContent( const SwLayoutFrame
& rCell
)
3880 const SwContentFrame
* pContent
= rCell
.ContainsContent();
3881 const SwTabFrame
* pTab
= rCell
.FindTabFrame();
3883 while ( pContent
&& rCell
.IsAnLower( pContent
) )
3885 const SwTabFrame
* pTmpTab
= pContent
->FindTabFrame();
3886 if ( pTmpTab
!= pTab
)
3888 SwFrame
const*const pTmp
= pTmpTab
->FindLastContentOrTable();
3891 pContent
= pTmp
->FindNextCnt();
3904 SwDeletionChecker::SwDeletionChecker(const SwFrame
* pFrame
)
3907 ? pFrame
->IsTextFrame()
3908 // sw_redlinehide: GetDep() may be a member of SwTextFrame!
3909 ? static_cast<SwTextFrame
const*>(pFrame
)->GetTextNodeFirst()
3910 : const_cast<SwFrame
*>(pFrame
)->GetDep()
3915 /// Can be used to check if a frame has been deleted
3916 bool SwDeletionChecker::HasBeenDeleted() const
3918 if ( !mpFrame
|| !mpRegIn
)
3921 SwIterator
<SwFrame
, SwModify
, sw::IteratorMode::UnwrapMulti
> aIter(*mpRegIn
);
3922 SwFrame
* pLast
= aIter
.First();
3925 if ( pLast
== mpFrame
)
3927 pLast
= aIter
.Next();
3933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */