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 <pagefrm.hxx>
21 #include <rootfrm.hxx>
22 #include <cellfrm.hxx>
24 #include <swtable.hxx>
25 #include <notxtfrm.hxx>
27 #include <sectfrm.hxx>
33 #include <fmtpdsc.hxx>
34 #include <fmtclbl.hxx>
36 #include <bodyfrm.hxx>
38 #include <viewopt.hxx>
40 #include <osl/diagnose.h>
41 #include <sal/log.hxx>
42 #include <IDocumentSettingAccess.hxx>
43 #include <formatflysplit.hxx>
44 #include <flyfrms.hxx>
47 /// Searches the first ContentFrame in BodyText below the page.
48 SwLayoutFrame
*SwFootnoteBossFrame::FindBodyCont()
50 SwFrame
*pLay
= Lower();
51 while ( pLay
&& !pLay
->IsBodyFrame() )
52 pLay
= pLay
->GetNext();
53 return static_cast<SwLayoutFrame
*>(pLay
);
56 /// Searches the last ContentFrame in BodyText below the page.
57 SwContentFrame
*SwPageFrame::FindLastBodyContent()
59 SwContentFrame
*pRet
= FindFirstBodyContent();
60 SwContentFrame
*pNxt
= pRet
;
61 while ( pNxt
&& pNxt
->IsInDocBody() && IsAnLower( pNxt
) )
63 pNxt
= pNxt
->FindNextCnt();
69 * Checks if the frame contains one or more ContentFrame's anywhere in his
70 * subsidiary structure; if so the first found ContentFrame is returned.
72 const SwContentFrame
*SwLayoutFrame::ContainsContent() const
74 //Search downwards the layout leaf and if there is no content, jump to the
75 //next leaf until content is found or we leave "this".
76 //Sections: Content next to sections would not be found this way (empty
77 //sections directly next to ContentFrame) therefore we need to recursively
78 //search for them even if it's more complex.
80 const SwLayoutFrame
*pLayLeaf
= this;
83 while ( (!pLayLeaf
->IsSctFrame() || pLayLeaf
== this ) &&
84 pLayLeaf
->Lower() && pLayLeaf
->Lower()->IsLayoutFrame() )
85 pLayLeaf
= static_cast<const SwLayoutFrame
*>(pLayLeaf
->Lower());
87 if( pLayLeaf
->IsSctFrame() && pLayLeaf
!= this )
89 const SwContentFrame
*pCnt
= pLayLeaf
->ContainsContent();
92 if( pLayLeaf
->GetNext() )
94 if( pLayLeaf
->GetNext()->IsLayoutFrame() )
96 pLayLeaf
= static_cast<const SwLayoutFrame
*>(pLayLeaf
->GetNext());
100 return static_cast<const SwContentFrame
*>(pLayLeaf
->GetNext());
103 else if ( pLayLeaf
->Lower() )
104 return static_cast<const SwContentFrame
*>(pLayLeaf
->Lower());
106 pLayLeaf
= pLayLeaf
->GetNextLayoutLeaf();
107 if( !IsAnLower( pLayLeaf
) )
114 * Calls ContainsAny first to reach the innermost cell. From there we walk back
115 * up to the first SwCellFrame. Since we use SectionFrames, ContainsContent()->GetUpper()
116 * is not enough anymore.
118 const SwCellFrame
*SwLayoutFrame::FirstCell() const
120 const SwFrame
* pCnt
= ContainsAny();
121 while( pCnt
&& !pCnt
->IsCellFrame() )
122 pCnt
= pCnt
->GetUpper();
123 return static_cast<const SwCellFrame
*>(pCnt
);
126 /** return ContentFrames, sections, and tables.
128 * @param _bInvestigateFootnoteForSections controls investigation of content of footnotes for sections.
129 * @see ContainsContent
131 const SwFrame
*SwLayoutFrame::ContainsAny( const bool _bInvestigateFootnoteForSections
) const
133 //Search downwards the layout leaf and if there is no content, jump to the
134 //next leaf until content is found, we leave "this" or until we found
135 //a SectionFrame or a TabFrame.
137 const SwLayoutFrame
*pLayLeaf
= this;
138 const bool bNoFootnote
= IsSctFrame() && !_bInvestigateFootnoteForSections
;
141 while ( ( (!pLayLeaf
->IsSctFrame() && !pLayLeaf
->IsTabFrame())
142 || pLayLeaf
== this ) &&
143 pLayLeaf
->Lower() && pLayLeaf
->Lower()->IsLayoutFrame() )
144 pLayLeaf
= static_cast<const SwLayoutFrame
*>(pLayLeaf
->Lower());
146 if( ( pLayLeaf
->IsTabFrame() || pLayLeaf
->IsSctFrame() )
147 && pLayLeaf
!= this )
149 // Now we also return "deleted" SectionFrames so they can be
150 // maintained on SaveContent and RestoreContent
153 else if ( pLayLeaf
->Lower() )
154 return static_cast<const SwContentFrame
*>(pLayLeaf
->Lower());
156 pLayLeaf
= pLayLeaf
->GetNextLayoutLeaf();
157 if( bNoFootnote
&& pLayLeaf
&& pLayLeaf
->IsInFootnote() )
161 pLayLeaf
= pLayLeaf
->GetNextLayoutLeaf();
162 } while( pLayLeaf
&& pLayLeaf
->IsInFootnote() );
164 if( !IsAnLower( pLayLeaf
) )
170 bool SwLayoutFrame::ContainsDeleteForbiddenLayFrame() const
172 if (IsDeleteForbidden())
176 for (SwFrame
const* pFrame
= Lower(); pFrame
; pFrame
= pFrame
->GetNext())
178 if (!pFrame
->IsLayoutFrame())
182 SwLayoutFrame
const*const pLay(static_cast<SwLayoutFrame
const*>(pFrame
));
183 if (pLay
->ContainsDeleteForbiddenLayFrame() || pLay
->IsColLocked())
191 const SwFrame
* SwFrame::GetLower() const
193 return IsLayoutFrame() ? static_cast<const SwLayoutFrame
*>(this)->Lower() : nullptr;
196 SwFrame
* SwFrame::GetLower()
198 return IsLayoutFrame() ? static_cast<SwLayoutFrame
*>(this)->Lower() : nullptr;
201 SwContentFrame
* SwFrame::FindPrevCnt( )
203 if ( GetPrev() && GetPrev()->IsContentFrame() )
204 return static_cast<SwContentFrame
*>(GetPrev());
206 return FindPrevCnt_();
209 const SwContentFrame
* SwFrame::FindPrevCnt() const
211 if ( GetPrev() && GetPrev()->IsContentFrame() )
212 return static_cast<const SwContentFrame
*>(GetPrev());
214 return const_cast<SwFrame
*>(this)->FindPrevCnt_();
217 SwContentFrame
*SwFrame::FindNextCnt( const bool _bInSameFootnote
)
219 if ( mpNext
&& mpNext
->IsContentFrame() )
220 return static_cast<SwContentFrame
*>(mpNext
);
222 return FindNextCnt_( _bInSameFootnote
);
225 const SwContentFrame
*SwFrame::FindNextCnt( const bool _bInSameFootnote
) const
227 if ( mpNext
&& mpNext
->IsContentFrame() )
228 return static_cast<SwContentFrame
*>(mpNext
);
230 return const_cast<SwFrame
*>(this)->FindNextCnt_( _bInSameFootnote
);
233 bool SwLayoutFrame::IsAnLower( const SwFrame
*pAssumed
) const
235 const SwFrame
*pUp
= pAssumed
;
240 if ( pUp
->IsFlyFrame() )
241 pUp
= static_cast<const SwFlyFrame
*>(pUp
)->GetAnchorFrame();
243 pUp
= pUp
->GetUpper();
248 /** method to check relative position of layout frame to
249 a given layout frame.
251 OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in
252 <txtftn.cxx> for #104840#.
254 @param _aCheckRefLayFrame
255 constant reference of an instance of class <SwLayoutFrame> which
256 is used as the reference for the relative position check.
258 @return true, if <this> is positioned before the layout frame <p>
260 bool SwLayoutFrame::IsBefore( const SwLayoutFrame
* _pCheckRefLayFrame
) const
262 OSL_ENSURE( !IsRootFrame() , "<IsBefore> called at a <SwRootFrame>.");
263 OSL_ENSURE( !_pCheckRefLayFrame
->IsRootFrame() , "<IsBefore> called with a <SwRootFrame>.");
267 // check, if on different pages
268 const SwPageFrame
*pMyPage
= FindPageFrame();
269 const SwPageFrame
*pCheckRefPage
= _pCheckRefLayFrame
->FindPageFrame();
270 if( pMyPage
!= pCheckRefPage
)
272 // being on different page as check reference
273 bReturn
= pMyPage
->GetPhyPageNum() < pCheckRefPage
->GetPhyPageNum();
277 // being on same page as check reference
278 // --> search my supreme parent <pUp>, which doesn't contain check reference.
279 const SwLayoutFrame
* pUp
= this;
280 while ( pUp
->GetUpper() &&
281 !pUp
->GetUpper()->IsAnLower( _pCheckRefLayFrame
)
283 pUp
= pUp
->GetUpper();
284 if( !pUp
->GetUpper() )
286 // can occur, if <this> is a fly frm
291 // travel through the next's of <pUp> and check if one of these
292 // contain the check reference.
293 const SwLayoutFrame
* pUpNext
= static_cast<const SwLayoutFrame
*>(pUp
->GetNext());
295 !pUpNext
->IsAnLower( _pCheckRefLayFrame
) )
297 pUpNext
= static_cast<const SwLayoutFrame
*>(pUpNext
->GetNext());
299 bReturn
= pUpNext
!= nullptr;
306 // Local helper functions for GetNextLayoutLeaf
308 static const SwFrame
* lcl_FindLayoutFrame( const SwFrame
* pFrame
, bool bNext
)
310 const SwFrame
* pRet
= nullptr;
311 if ( pFrame
->IsFlyFrame() )
313 auto pFlyFrame
= static_cast<const SwFlyFrame
*>(pFrame
);
314 if (pFlyFrame
->IsFlySplitAllowed())
316 // This is a flow frame, look up the follow/precede.
317 auto pFlyAtContent
= static_cast<const SwFlyAtContentFrame
*>(pFlyFrame
);
318 pRet
= bNext
? pFlyAtContent
->GetFollow() : pFlyAtContent
->GetPrecede();
322 pRet
= bNext
? pFlyFrame
->GetNextLink() : pFlyFrame
->GetPrevLink();
326 pRet
= bNext
? pFrame
->GetNext() : pFrame
->GetPrev();
331 static const SwFrame
* lcl_GetLower( const SwFrame
* pFrame
, bool bFwd
)
333 if ( !pFrame
->IsLayoutFrame() )
337 static_cast<const SwLayoutFrame
*>(pFrame
)->Lower() :
338 static_cast<const SwLayoutFrame
*>(pFrame
)->GetLastLower();
342 * Finds the next layout leaf. This is a layout frame, which does not
343 * have a lower which is a LayoutFrame. That means, pLower can be 0 or a
346 * However, pLower may be a TabFrame
348 const SwLayoutFrame
*SwFrame::ImplGetNextLayoutLeaf( bool bFwd
) const
350 const SwFrame
*pFrame
= this;
351 const SwLayoutFrame
*pLayoutFrame
= nullptr;
352 const SwFrame
*p
= nullptr;
353 bool bGoingUp
= !bFwd
; // false for forward, true for backward
354 // The anchor is this frame, unless we traverse the anchor of a split fly.
355 const SwFrame
* pAnchor
= this;
358 bool bGoingFwdOrBwd
= false;
360 bool bGoingDown
= !bGoingUp
;
363 p
= lcl_GetLower( pFrame
, bFwd
);
364 bGoingDown
= nullptr != p
;
368 // I cannot go down, because either I'm currently going up or
369 // because the is no lower.
370 // I'll try to go forward:
371 p
= lcl_FindLayoutFrame( pFrame
, bFwd
);
372 bGoingFwdOrBwd
= nullptr != p
;
373 if ( !bGoingFwdOrBwd
)
375 // I cannot go forward, because there is no next frame.
376 // I'll try to go up:
377 p
= pFrame
->GetUpper();
379 if (!p
&& pFrame
->IsFlyFrame())
381 const SwFlyFrame
* pFlyFrame
= pFrame
->FindFlyFrame();
382 if (pFlyFrame
->IsFlySplitAllowed())
384 p
= const_cast<SwFlyFrame
*>(pFlyFrame
)->FindAnchorCharFrame();
385 // Remember the anchor frame, so if we look for the leaf of a frame in a
386 // split fly (anchored in the master of a text frame, but rendered on the
387 // next page), we won't return a frame on the next page, rather return
393 bGoingUp
= nullptr != p
;
396 // I cannot go up, because there is no upper frame.
402 // If I could not go down or forward, I'll have to go up
403 bGoingUp
= !bGoingFwdOrBwd
&& !bGoingDown
;
406 p
= lcl_GetLower( pFrame
, true );
408 } while( ( p
&& !p
->IsFlowFrame() ) ||
410 nullptr == ( pLayoutFrame
= pFrame
->IsLayoutFrame() ? static_cast<const SwLayoutFrame
*>(pFrame
) : nullptr ) ||
411 pLayoutFrame
->IsAnLower( pAnchor
) );
417 * Walk back inside the tree: grab the subordinate Frame if one exists and the
418 * last step was not moving up a level (this would lead to an infinite up/down
419 * loop!). With this we ensure that during walking back we search through all
420 * sub trees. If we walked downwards we have to go to the end of the chain first
421 * because we go backwards from the last Frame inside another Frame. Walking
422 * forward works the same.
424 * @warning fixes here may also need to be applied to the @{lcl_NextFrame} method above
426 const SwContentFrame
* SwContentFrame::ImplGetNextContentFrame( bool bFwd
) const
428 const SwFrame
*pFrame
= this;
429 const SwContentFrame
*pContentFrame
= nullptr;
430 bool bGoingUp
= false;
432 const SwFrame
*p
= nullptr;
433 bool bGoingFwdOrBwd
= false;
435 bool bGoingDown
= !bGoingUp
;
438 p
= lcl_GetLower( pFrame
, true ) ;
439 bGoingDown
= nullptr != p
;
443 p
= lcl_FindLayoutFrame( pFrame
, bFwd
);
444 bGoingFwdOrBwd
= nullptr != p
;
445 if ( !bGoingFwdOrBwd
)
447 p
= pFrame
->GetUpper();
448 bGoingUp
= nullptr != p
;
456 bGoingUp
= !(bGoingFwdOrBwd
|| bGoingDown
);
458 if (!bFwd
&& bGoingDown
)
460 while ( p
->GetNext() )
465 } while ( nullptr == (pContentFrame
= (pFrame
->IsContentFrame() ? static_cast<const SwContentFrame
*>(pFrame
) : nullptr) ));
467 return pContentFrame
;
470 SwPageFrame
* SwFrame::ImplFindPageFrame()
472 SwFrame
*pRet
= this;
473 while ( pRet
&& !pRet
->IsPageFrame() )
475 if ( pRet
->GetUpper() )
476 pRet
= pRet
->GetUpper();
477 else if ( pRet
->IsFlyFrame() )
479 // #i28701# - use new method <GetPageFrame()>
480 const auto pFly(static_cast<SwFlyFrame
*>(pRet
));
481 pRet
= pFly
->GetPageFrame();
483 pRet
= pFly
->AnchorFrame();
488 return static_cast<SwPageFrame
*>(pRet
);
491 SwFootnoteBossFrame
* SwFrame::FindFootnoteBossFrame( bool bFootnotes
)
493 SwFrame
*pRet
= this;
494 // Footnote bosses can't exist inside a table; also sections with columns
495 // don't contain footnote texts there
496 if (SwFrame
*pTabFrame
= pRet
->IsInTab() ? pRet
->FindTabFrame() : nullptr)
499 // tdf139336: put the footnotes into the page frame (instead of a column frame)
500 // to avoid maximizing the section to the full page.... if:
501 // - it is in a section
502 // - collect footnotes at section end (FootnoteAtEnd) is not set
503 // - columns are evenly distributed (=balanced) is not set
504 // Note 1: at page end, the footnotes have no multi-column-capability,
505 // so this fix is used only where there is better chance to help
506 // Note 2: If balanced is not set, there is a higher chance that the 1. column will reach
507 // the end of the page... if that happens the section will be maximized anyway.
508 // Note 3: The user will be able to easily choose the old layout (with multi-column footnotes)
509 // with this setting.
510 // similar case can be reached with a page break + FootnoteAtEnd setting
511 SwSectionFrame
* pSectframe
= pRet
->FindSctFrame();
512 bool bMoveToPageFrame
= false;
513 // tdf146704: only if it is really a footnote, not an endnote.
514 // tdf54465: compatibility flag to make old odt files keep these full page sections.
515 if (bFootnotes
&& pSectframe
516 && pSectframe
->GetFormat()->getIDocumentSettingAccess().get(
517 DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND
))
519 SwSection
* pSect
= pSectframe
->GetSection();
521 bool bNoBalance
= pSect
->GetFormat()->GetBalancedColumns().GetValue();
522 bool bFAtEnd
= pSectframe
->IsFootnoteAtEnd();
523 bMoveToPageFrame
= !bFAtEnd
&& !bNoBalance
;
527 && ((!bMoveToPageFrame
&& !pRet
->IsFootnoteBossFrame())
528 || (bMoveToPageFrame
&& !pRet
->IsPageFrame())))
530 if ( pRet
->GetUpper() )
531 pRet
= pRet
->GetUpper();
532 else if ( pRet
->IsFlyFrame() )
534 // #i28701# - use new method <GetPageFrame()>
535 if ( static_cast<SwFlyFrame
*>(pRet
)->GetPageFrame() )
536 pRet
= static_cast<SwFlyFrame
*>(pRet
)->GetPageFrame();
538 pRet
= static_cast<SwFlyFrame
*>(pRet
)->AnchorFrame();
543 if( bFootnotes
&& pRet
&& pRet
->IsColumnFrame() &&
544 !pRet
->GetNext() && !pRet
->GetPrev() )
546 SwSectionFrame
* pSct
= pRet
->FindSctFrame();
547 OSL_ENSURE( pSct
, "FindFootnoteBossFrame: Single column outside section?" );
548 if( !pSct
->IsFootnoteAtEnd() )
549 return pSct
->FindFootnoteBossFrame( true );
551 return static_cast<SwFootnoteBossFrame
*>(pRet
);
554 SwTabFrame
* SwFrame::ImplFindTabFrame()
556 SwFrame
*pRet
= this;
557 while ( !pRet
->IsTabFrame() )
559 pRet
= pRet
->GetUpper();
563 return static_cast<SwTabFrame
*>(pRet
);
566 SwSectionFrame
* SwFrame::ImplFindSctFrame()
568 SwFrame
*pRet
= this;
569 while ( !pRet
->IsSctFrame() )
571 pRet
= pRet
->GetUpper();
575 return static_cast<SwSectionFrame
*>(pRet
);
578 const SwBodyFrame
* SwFrame::ImplFindBodyFrame() const
580 const SwFrame
*pRet
= this;
581 while ( !pRet
->IsBodyFrame() )
583 pRet
= pRet
->GetUpper();
587 return static_cast<const SwBodyFrame
*>(pRet
);
590 SwFootnoteFrame
*SwFrame::ImplFindFootnoteFrame()
592 SwFrame
*pRet
= this;
593 while ( !pRet
->IsFootnoteFrame() )
595 pRet
= pRet
->GetUpper();
599 return static_cast<SwFootnoteFrame
*>(pRet
);
602 SwFlyFrame
*SwFrame::ImplFindFlyFrame()
604 SwFrame
*pRet
= this;
607 if ( pRet
->IsFlyFrame() )
608 return static_cast<SwFlyFrame
*>(pRet
);
610 pRet
= pRet
->GetUpper();
615 SwFrame
*SwFrame::FindColFrame()
617 SwFrame
*pFrame
= this;
619 { pFrame
= pFrame
->GetUpper();
620 } while ( pFrame
&& !pFrame
->IsColumnFrame() );
624 SwRowFrame
*SwFrame::FindRowFrame()
626 SwFrame
*pFrame
= this;
628 { pFrame
= pFrame
->GetUpper();
629 } while ( pFrame
&& !pFrame
->IsRowFrame() );
630 return dynamic_cast< SwRowFrame
* >( pFrame
);
633 SwFrame
* SwFrame::FindFooterOrHeader()
635 SwFrame
* pRet
= this;
638 if (pRet
->GetType() & FRM_HEADFOOT
) //header and footer
640 else if ( pRet
->GetUpper() )
641 pRet
= pRet
->GetUpper();
642 else if ( pRet
->IsFlyFrame() )
643 pRet
= static_cast<SwFlyFrame
*>(pRet
)->AnchorFrame();
650 const SwFootnoteFrame
* SwFootnoteContFrame::FindFootNote() const
652 const SwFootnoteFrame
* pRet
= static_cast<const SwFootnoteFrame
*>(Lower());
653 if( pRet
&& !pRet
->GetAttr()->GetFootnote().IsEndNote() )
658 const SwPageFrame
* SwRootFrame::GetPageAtPos( const Point
& rPt
, const Size
* pSize
, bool bExtend
) const
660 const SwPageFrame
* pRet
= nullptr;
666 aRect
.SSize( *pSize
);
669 const SwFrame
* pPage
= Lower();
673 if( !getFrameArea().Contains( rPt
) )
676 // skip pages above point:
677 while( pPage
&& rPt
.Y() > pPage
->getFrameArea().Bottom() )
678 pPage
= pPage
->GetNext();
681 OSL_ENSURE( GetPageNum() <= maPageRects
.size(), "number of pages differs from page rect array size" );
684 while ( pPage
&& !pRet
)
686 const SwRect
& rBoundRect
= bExtend
? maPageRects
[ nPageIdx
++ ] : pPage
->getFrameArea();
688 if ( (!pSize
&& rBoundRect
.Contains(rPt
)) ||
689 (pSize
&& rBoundRect
.Overlaps(aRect
)) )
691 pRet
= static_cast<const SwPageFrame
*>(pPage
);
694 pPage
= pPage
->GetNext();
700 bool SwRootFrame::IsBetweenPages(const Point
& rPt
) const
702 if (!getFrameArea().Contains(rPt
))
706 const SwFrame
* pPage
= Lower();
707 if (pPage
== nullptr)
710 // skip pages above point:
711 while (pPage
&& rPt
.Y() > pPage
->getFrameArea().Bottom())
712 pPage
= pPage
->GetNext();
715 rPt
.X() >= pPage
->getFrameArea().Left() &&
716 rPt
.X() <= pPage
->getFrameArea().Right())
718 // Trivial case when we're right in between.
719 if (!pPage
->getFrameArea().Contains(rPt
))
722 // In normal mode the gap is large enough and
723 // header/footer mouse interaction competes with
724 // handling hide-whitespace within them.
725 // In hide-whitespace, however, the gap is too small
726 // for convenience and there are no headers/footers.
727 const SwViewShell
*pSh
= GetCurrShell();
728 if (pSh
&& pSh
->GetViewOptions()->IsWhitespaceHidden())
730 constexpr SwTwips constMargin
= o3tl::convert(tools::Long(2), o3tl::Length::mm
, o3tl::Length::twip
);
732 // If we are really close to the bottom or top of a page.
733 const auto toEdge
= std::min(std::abs(pPage
->getFrameArea().Top() - rPt
.Y()),
734 std::abs(pPage
->getFrameArea().Bottom() - rPt
.Y()));
735 return toEdge
<= constMargin
;
742 const SvxFormatBreakItem
& SwFrame::GetBreakItem() const
744 return GetAttrSet()->GetBreak();
747 const SwFormatPageDesc
& SwFrame::GetPageDescItem() const
749 return GetAttrSet()->GetPageDesc();
752 const SvxFormatBreakItem
& SwTextFrame::GetBreakItem() const
754 return GetTextNodeFirst()->GetSwAttrSet().GetBreak();
757 const SwFormatPageDesc
& SwTextFrame::GetPageDescItem() const
759 return GetTextNodeFirst()->GetSwAttrSet().GetPageDesc();
762 const SwAttrSet
* SwFrame::GetAttrSet() const
766 return &static_cast<const SwTextFrame
*>(this)->GetTextNodeForParaProps()->GetSwAttrSet();
768 else if (IsNoTextFrame())
770 return &static_cast<const SwNoTextFrame
*>(this)->GetNode()->GetSwAttrSet();
774 assert(IsLayoutFrame());
775 return &static_cast<const SwLayoutFrame
*>(this)->GetFormat()->GetAttrSet();
779 drawinglayer::attribute::SdrAllFillAttributesHelperPtr
SwFrame::getSdrAllFillAttributesHelper() const
783 return static_cast<const SwTextFrame
*>(this)->GetTextNodeForParaProps()->getSdrAllFillAttributesHelper();
785 else if (IsNoTextFrame())
787 return static_cast<const SwNoTextFrame
*>(this)->GetNode()->getSdrAllFillAttributesHelper();
791 return static_cast< const SwLayoutFrame
* >(this)->GetFormat()->getSdrAllFillAttributesHelper();
795 bool SwFrame::supportsFullDrawingLayerFillAttributeSet() const
797 if (IsContentFrame())
803 return static_cast< const SwLayoutFrame
* >(this)->GetFormat()->supportsFullDrawingLayerFillAttributeSet();
808 * SwFrame::FindNext_(), FindPrev_(), InvalidateNextPos()
809 * FindNextCnt_() visits tables and sections and only returns SwContentFrames.
811 * Description Invalidates the position of the next frame.
812 * This is the direct successor or in case of ContentFrames the next
813 * ContentFrame which sits in the same flow as I do:
816 * - in headers/footers the notification only needs to be forwarded
819 * - Contents in tabs remain only inside their cell
820 * - in principle tables behave exactly like the Contents
823 // This helper function is an equivalent to the ImplGetNextContentFrame() method,
824 // besides ContentFrames this function also returns TabFrames and SectionFrames.
825 static SwFrame
* lcl_NextFrame( SwFrame
* pFrame
)
827 SwFrame
*pRet
= nullptr;
828 bool bGoingUp
= false;
830 SwFrame
*p
= nullptr;
832 bool bGoingFwd
= false;
833 bool bGoingDown
= !bGoingUp
&& pFrame
->IsLayoutFrame();
836 p
= static_cast<SwLayoutFrame
*>(pFrame
)->Lower();
837 bGoingDown
= nullptr != p
;
841 p
= pFrame
->IsFlyFrame() ? static_cast<SwFlyFrame
*>(pFrame
)->GetNextLink() : pFrame
->GetNext();
842 bGoingFwd
= nullptr != p
;
845 p
= pFrame
->GetUpper();
846 bGoingUp
= nullptr != p
;
853 bGoingUp
= !(bGoingFwd
|| bGoingDown
);
855 } while ( nullptr == (pRet
= ( ( pFrame
->IsContentFrame() || ( !bGoingUp
&&
856 ( pFrame
->IsTabFrame() || pFrame
->IsSctFrame() ) ) )? pFrame
: nullptr ) ) );
860 SwFrame
*SwFrame::FindNext_()
862 bool bIgnoreTab
= false;
863 SwFrame
*pThis
= this;
867 //The last Content of the table gets picked up and his follower is
868 //returned. To be able to deactivate the special case for tables
869 //(see below) bIgnoreTab will be set.
870 if ( static_cast<SwTabFrame
*>(this)->GetFollow() )
871 return static_cast<SwTabFrame
*>(this)->GetFollow();
873 pThis
= static_cast<SwTabFrame
*>(this)->FindLastContentOrTable();
878 else if ( IsSctFrame() )
880 //The last Content of the section gets picked and his follower is returned.
881 if ( static_cast<SwSectionFrame
*>(this)->GetFollow() )
882 return static_cast<SwSectionFrame
*>(this)->GetFollow();
884 pThis
= static_cast<SwSectionFrame
*>(this)->FindLastContent();
888 else if ( IsContentFrame() )
890 if( static_cast<SwContentFrame
*>(this)->GetFollow() )
891 return static_cast<SwContentFrame
*>(this)->GetFollow();
893 else if ( IsRowFrame() )
895 SwFrame
* pMyUpper
= GetUpper();
896 if ( pMyUpper
->IsTabFrame() && static_cast<SwTabFrame
*>(pMyUpper
)->GetFollow() )
897 return static_cast<SwTabFrame
*>(pMyUpper
)->GetFollow()->GetLower();
903 SwFrame
* pRet
= nullptr;
904 const bool bFootnote
= pThis
->IsInFootnote();
905 if ( !bIgnoreTab
&& pThis
->IsInTab() )
907 SwLayoutFrame
*pUp
= pThis
->GetUpper();
908 while (pUp
&& !pUp
->IsCellFrame())
909 pUp
= pUp
->GetUpper();
910 assert(pUp
&& "Content flag says it's in table but it's not in cell.");
911 SwFrame
* pNxt
= pUp
? static_cast<SwCellFrame
*>(pUp
)->GetFollowCell() : nullptr;
913 pNxt
= static_cast<SwCellFrame
*>(pNxt
)->ContainsContent();
916 pNxt
= lcl_NextFrame( pThis
);
917 if (pUp
&& pUp
->IsAnLower(pNxt
))
925 const bool bBody
= pThis
->IsInDocBody();
926 SwFrame
*pNxtCnt
= lcl_NextFrame( pThis
);
929 if ( bBody
|| bFootnote
)
933 // OD 02.04.2003 #108446# - check for endnote, only if found
934 // next content isn't contained in a section, that collect its
935 // endnotes at its end.
936 bool bEndn
= IsInSct() && !IsSctFrame() &&
937 ( !pNxtCnt
->IsInSct() ||
938 !pNxtCnt
->FindSctFrame()->IsEndnAtEnd()
940 if ( ( bBody
&& pNxtCnt
->IsInDocBody() ) ||
941 ( pNxtCnt
->IsInFootnote() &&
943 ( bEndn
&& pNxtCnt
->FindFootnoteFrame()->GetAttr()->GetFootnote().IsEndNote() )
948 if (pNxtCnt
->IsInTab())
950 if (!IsTabFrame() || !static_cast<SwLayoutFrame
*>(this)->IsAnLower(pNxtCnt
))
952 pRet
= pNxtCnt
->FindTabFrame();
962 pNxtCnt
= lcl_NextFrame( pNxtCnt
);
965 else if ( pThis
->IsInFly() )
967 pRet
= pNxtCnt
->IsInTab() ? pNxtCnt
->FindTabFrame()
970 else //footer-/or header section
972 const SwFrame
*pUp
= pThis
->GetUpper();
973 const SwFrame
*pCntUp
= pNxtCnt
->GetUpper();
974 while ( pUp
&& pUp
->GetUpper() &&
975 !pUp
->IsHeaderFrame() && !pUp
->IsFooterFrame() )
976 pUp
= pUp
->GetUpper();
977 while ( pCntUp
&& pCntUp
->GetUpper() &&
978 !pCntUp
->IsHeaderFrame() && !pCntUp
->IsFooterFrame() )
979 pCntUp
= pCntUp
->GetUpper();
982 pRet
= pNxtCnt
->IsInTab() ? pNxtCnt
->FindTabFrame()
988 if( pRet
&& pRet
->IsInSct() )
990 SwSectionFrame
* pSct
= pRet
->FindSctFrame();
991 //Footnotes in frames with columns must not return the section which
992 //contains the footnote
993 if( !pSct
->IsAnLower( this ) &&
994 (!bFootnote
|| pSct
->IsInFootnote() ) )
1000 // #i27138# - add parameter <_bInSameFootnote>
1001 SwContentFrame
*SwFrame::FindNextCnt_( const bool _bInSameFootnote
)
1003 SwFrame
*pThis
= this;
1007 if ( static_cast<SwTabFrame
*>(this)->GetFollow() )
1009 pThis
= static_cast<SwTabFrame
*>(this)->GetFollow()->ContainsContent();
1011 return static_cast<SwContentFrame
*>(pThis
);
1013 pThis
= static_cast<SwTabFrame
*>(this)->FindLastContentOrTable();
1017 else if ( IsSctFrame() )
1019 if ( static_cast<SwSectionFrame
*>(this)->GetFollow() )
1021 pThis
= static_cast<SwSectionFrame
*>(this)->GetFollow()->ContainsContent();
1023 return static_cast<SwContentFrame
*>(pThis
);
1025 pThis
= static_cast<SwSectionFrame
*>(this)->FindLastContent();
1029 else if ( IsContentFrame() && static_cast<SwContentFrame
*>(this)->GetFollow() )
1030 return static_cast<SwContentFrame
*>(this)->GetFollow();
1032 if ( pThis
->IsContentFrame() )
1034 const bool bBody
= pThis
->IsInDocBody();
1035 const bool bFootnote
= pThis
->IsInFootnote();
1036 SwContentFrame
*pNxtCnt
= static_cast<SwContentFrame
*>(pThis
)->GetNextContentFrame();
1040 if ( bBody
|| ( bFootnote
&& !_bInSameFootnote
) )
1042 // handling for environments 'footnotes' and 'document body frames':
1045 if ( (bBody
&& pNxtCnt
->IsInDocBody()) ||
1046 (bFootnote
&& pNxtCnt
->IsInFootnote()) )
1048 pNxtCnt
= pNxtCnt
->GetNextContentFrame();
1052 else if ( bFootnote
&& _bInSameFootnote
)
1054 // handling for environments 'each footnote':
1055 // Assure that found next content frame belongs to the same footnotes
1056 const SwFootnoteFrame
* pFootnoteFrameOfNext( pNxtCnt
->FindFootnoteFrame() );
1057 const SwFootnoteFrame
* pFootnoteFrameOfCurr( pThis
->FindFootnoteFrame() );
1058 OSL_ENSURE( pFootnoteFrameOfCurr
,
1059 "<SwFrame::FindNextCnt_() - unknown layout situation: current frame has to have an upper footnote frame." );
1060 if ( pFootnoteFrameOfNext
== pFootnoteFrameOfCurr
)
1064 else if ( pFootnoteFrameOfCurr
->GetFollow() )
1066 // next content frame has to be the first content frame
1067 // in the follow footnote, which contains a content frame.
1068 SwFootnoteFrame
* pFollowFootnoteFrameOfCurr(
1069 const_cast<SwFootnoteFrame
*>(pFootnoteFrameOfCurr
) );
1072 pFollowFootnoteFrameOfCurr
= pFollowFootnoteFrameOfCurr
->GetFollow();
1073 pNxtCnt
= pFollowFootnoteFrameOfCurr
->ContainsContent();
1074 } while ( !pNxtCnt
&& pFollowFootnoteFrameOfCurr
->GetFollow() );
1079 // current content frame is the last content frame in the
1080 // footnote - no next content frame exists.
1084 else if ( pThis
->IsInFly() )
1085 // handling for environments 'unlinked fly frame' and
1086 // 'group of linked fly frames':
1090 // handling for environments 'page header' and 'page footer':
1091 const SwFrame
*pUp
= pThis
->GetUpper();
1092 const SwFrame
*pCntUp
= pNxtCnt
->GetUpper();
1093 while ( pUp
&& pUp
->GetUpper() &&
1094 !pUp
->IsHeaderFrame() && !pUp
->IsFooterFrame() )
1095 pUp
= pUp
->GetUpper();
1096 while ( pCntUp
&& pCntUp
->GetUpper() &&
1097 !pCntUp
->IsHeaderFrame() && !pCntUp
->IsFooterFrame() )
1098 pCntUp
= pCntUp
->GetUpper();
1099 if ( pCntUp
== pUp
)
1107 /** method to determine previous content frame in the same environment
1108 for a flow frame (content frame, table frame, section frame)
1110 OD 2005-11-30 #i27138#
1112 SwContentFrame
* SwFrame::FindPrevCnt_()
1114 if ( !IsFlowFrame() )
1116 // nothing to do, if current frame isn't a flow frame.
1120 SwContentFrame
* pPrevContentFrame( nullptr );
1122 // Because method <SwContentFrame::GetPrevContentFrame()> is used to travel
1123 // through the layout, a content frame, at which the travel starts, is needed.
1124 SwContentFrame
* pCurrContentFrame
= dynamic_cast<SwContentFrame
*>(this);
1126 // perform shortcut, if current frame is a follow, and
1127 // determine <pCurrContentFrame>, if current frame is a table or section frame
1128 if ( pCurrContentFrame
&& pCurrContentFrame
->IsFollow() )
1130 // previous content frame is its master content frame
1131 pPrevContentFrame
= pCurrContentFrame
->FindMaster();
1133 else if ( IsTabFrame() )
1135 SwTabFrame
* pTabFrame( static_cast<SwTabFrame
*>(this) );
1136 if ( pTabFrame
->IsFollow() )
1138 // previous content frame is the last content of its master table frame
1139 pPrevContentFrame
= pTabFrame
->FindMaster()->FindLastContent();
1143 // start content frame for the search is the first content frame of
1145 pCurrContentFrame
= pTabFrame
->ContainsContent();
1148 else if ( IsSctFrame() )
1150 SwSectionFrame
* pSectFrame( static_cast<SwSectionFrame
*>(this) );
1151 if ( pSectFrame
->IsFollow() )
1153 // previous content frame is the last content of its master section frame
1154 pPrevContentFrame
= pSectFrame
->FindMaster()->FindLastContent();
1158 // start content frame for the search is the first content frame of
1159 // the section frame.
1160 pCurrContentFrame
= pSectFrame
->ContainsContent();
1164 // search for next content frame, depending on the environment, in which
1165 // the current frame is in.
1166 if ( !pPrevContentFrame
&& pCurrContentFrame
)
1168 pPrevContentFrame
= pCurrContentFrame
->GetPrevContentFrame();
1169 if ( pPrevContentFrame
)
1171 if ( pCurrContentFrame
->IsInFly() )
1173 // handling for environments 'unlinked fly frame' and
1174 // 'group of linked fly frames':
1175 // Nothing to do, <pPrevContentFrame> is the one
1179 const bool bInDocBody
= pCurrContentFrame
->IsInDocBody();
1180 const bool bInFootnote
= pCurrContentFrame
->IsInFootnote();
1183 // handling for environments 'footnotes' and 'document body frames':
1184 // Assure that found previous frame is also in one of these
1185 // environments. Otherwise, travel further
1186 while ( pPrevContentFrame
)
1188 if ( ( bInDocBody
&& pPrevContentFrame
->IsInDocBody() ) ||
1189 ( bInFootnote
&& pPrevContentFrame
->IsInFootnote() ) )
1193 pPrevContentFrame
= pPrevContentFrame
->GetPrevContentFrame();
1196 else if ( bInFootnote
)
1198 // handling for environments 'each footnote':
1199 // Assure that found next content frame belongs to the same footnotes
1200 const SwFootnoteFrame
* pFootnoteFrameOfPrev( pPrevContentFrame
->FindFootnoteFrame() );
1201 const SwFootnoteFrame
* pFootnoteFrameOfCurr( pCurrContentFrame
->FindFootnoteFrame() );
1202 if ( pFootnoteFrameOfPrev
!= pFootnoteFrameOfCurr
)
1204 if ( pFootnoteFrameOfCurr
->GetMaster() )
1206 SwFootnoteFrame
* pMasterFootnoteFrameOfCurr(
1207 const_cast<SwFootnoteFrame
*>(pFootnoteFrameOfCurr
) );
1208 pPrevContentFrame
= nullptr;
1209 // correct wrong loop-condition
1211 pMasterFootnoteFrameOfCurr
= pMasterFootnoteFrameOfCurr
->GetMaster();
1212 pPrevContentFrame
= pMasterFootnoteFrameOfCurr
->FindLastContent();
1213 } while ( !pPrevContentFrame
&&
1214 pMasterFootnoteFrameOfCurr
->GetMaster() );
1218 // current content frame is the first content in the
1219 // footnote - no previous content exists.
1220 pPrevContentFrame
= nullptr;
1226 // handling for environments 'page header' and 'page footer':
1227 // Assure that found previous frame is also in the same
1228 // page header respectively page footer as <pCurrContentFrame>
1229 // Note: At this point it's clear that <pCurrContentFrame> has
1230 // to be inside a page header or page footer and that
1231 // neither <pCurrContentFrame> nor <pPrevContentFrame> are
1232 // inside a fly frame.
1233 // Thus, method <FindFooterOrHeader()> can be used.
1234 OSL_ENSURE( pCurrContentFrame
->FindFooterOrHeader(),
1235 "<SwFrame::FindPrevCnt_()> - unknown layout situation: current frame should be in page header or page footer" );
1236 OSL_ENSURE( !pPrevContentFrame
->IsInFly(),
1237 "<SwFrame::FindPrevCnt_()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
1238 if ( pPrevContentFrame
->FindFooterOrHeader() !=
1239 pCurrContentFrame
->FindFooterOrHeader() )
1241 pPrevContentFrame
= nullptr;
1248 return pPrevContentFrame
;
1251 SwFrame
*SwFrame::FindPrev_()
1253 bool bIgnoreTab
= false;
1254 SwFrame
*pThis
= this;
1258 //The first Content of the table gets picked up and his predecessor is
1259 //returned. To be able to deactivate the special case for tables
1260 //(see below) bIgnoreTab will be set.
1261 if ( static_cast<SwTabFrame
*>(this)->IsFollow() )
1262 return static_cast<SwTabFrame
*>(this)->FindMaster();
1264 pThis
= static_cast<SwTabFrame
*>(this)->ContainsContent();
1268 if ( pThis
&& pThis
->IsContentFrame() )
1270 SwContentFrame
*pPrvCnt
= static_cast<SwContentFrame
*>(pThis
)->GetPrevContentFrame();
1273 if ( !bIgnoreTab
&& pThis
->IsInTab() )
1275 SwLayoutFrame
*pUp
= pThis
->GetUpper();
1276 while (pUp
&& !pUp
->IsCellFrame())
1277 pUp
= pUp
->GetUpper();
1278 assert(pUp
&& "Content flag says it's in table but it's not in cell.");
1279 if (pUp
&& pUp
->IsAnLower(pPrvCnt
))
1285 const bool bBody
= pThis
->IsInDocBody();
1286 const bool bFootnote
= !bBody
&& pThis
->IsInFootnote();
1287 if ( bBody
|| bFootnote
)
1291 if ( (bBody
&& pPrvCnt
->IsInDocBody()) ||
1292 (bFootnote
&& pPrvCnt
->IsInFootnote()) )
1294 pRet
= pPrvCnt
->IsInTab() ? pPrvCnt
->FindTabFrame()
1295 : static_cast<SwFrame
*>(pPrvCnt
);
1298 pPrvCnt
= pPrvCnt
->GetPrevContentFrame();
1301 else if ( pThis
->IsInFly() )
1303 pRet
= pPrvCnt
->IsInTab() ? pPrvCnt
->FindTabFrame()
1304 : static_cast<SwFrame
*>(pPrvCnt
);
1307 else // footer or header or Fly
1309 const SwFrame
*pUp
= pThis
->GetUpper();
1310 const SwFrame
*pCntUp
= pPrvCnt
->GetUpper();
1311 while ( pUp
&& pUp
->GetUpper() &&
1312 !pUp
->IsHeaderFrame() && !pUp
->IsFooterFrame() )
1313 pUp
= pUp
->GetUpper();
1314 while ( pCntUp
&& pCntUp
->GetUpper() )
1315 pCntUp
= pCntUp
->GetUpper();
1316 if ( pCntUp
== pUp
)
1318 pRet
= pPrvCnt
->IsInTab() ? pPrvCnt
->FindTabFrame()
1319 : static_cast<SwFrame
*>(pPrvCnt
);
1328 void SwFrame::ImplInvalidateNextPos( bool bNoFootnote
)
1330 SwFrame
*pFrame
= FindNext_();
1331 if ( nullptr == pFrame
)
1334 if( pFrame
->IsSctFrame() )
1336 while( pFrame
&& pFrame
->IsSctFrame() )
1338 if( static_cast<SwSectionFrame
*>(pFrame
)->GetSection() )
1340 SwFrame
* pTmp
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1342 pTmp
->InvalidatePos();
1343 else if( !bNoFootnote
)
1344 static_cast<SwSectionFrame
*>(pFrame
)->InvalidateFootnotePos();
1345 if( !IsInSct() || FindSctFrame()->GetFollow() != pFrame
)
1346 pFrame
->InvalidatePos();
1349 pFrame
= pFrame
->FindNext();
1353 if ( pFrame
->IsSctFrame())
1355 // We need to invalidate the section's content so it gets
1356 // the chance to flow to a different page.
1357 SwFrame
* pTmp
= static_cast<SwSectionFrame
*>(pFrame
)->ContainsAny();
1359 pTmp
->InvalidatePos();
1360 if( !IsInSct() || FindSctFrame()->GetFollow() != pFrame
)
1361 pFrame
->InvalidatePos();
1364 pFrame
->InvalidatePos();
1368 pFrame
->InvalidatePos();
1371 /** method to invalidate printing area of next frame
1373 OD 09.01.2004 #i11859#
1375 FME 2004-04-19 #i27145# Moved function from SwTextFrame to SwFrame
1377 void SwFrame::InvalidateNextPrtArea()
1379 // determine next frame
1380 SwFrame
* pNextFrame
= FindNext();
1381 // skip empty section frames and hidden text frames
1383 while ( pNextFrame
&&
1384 ( ( pNextFrame
->IsSctFrame() &&
1385 !static_cast<SwSectionFrame
*>(pNextFrame
)->GetSection() ) ||
1386 ( pNextFrame
->IsTextFrame() &&
1387 static_cast<SwTextFrame
*>(pNextFrame
)->IsHiddenNow() ) ) )
1389 pNextFrame
= pNextFrame
->FindNext();
1393 // Invalidate printing area of found next frame
1397 if ( pNextFrame
->IsSctFrame() )
1399 // Invalidate printing area of found section frame, if
1400 // (1) this text frame isn't in a section OR
1401 // (2) found section frame isn't a follow of the section frame this
1402 // text frame is in.
1403 if ( !IsInSct() || FindSctFrame()->GetFollow() != pNextFrame
)
1405 pNextFrame
->InvalidatePrt();
1408 // Invalidate printing area of first content in found section.
1409 SwFrame
* pFstContentOfSctFrame
=
1410 static_cast<SwSectionFrame
*>(pNextFrame
)->ContainsAny();
1411 if ( pFstContentOfSctFrame
)
1413 pFstContentOfSctFrame
->InvalidatePrt();
1418 pNextFrame
->InvalidatePrt();
1422 /// @returns true if the frame _directly_ sits in a section
1423 /// but not if it sits in a table which itself sits in a section.
1424 static bool lcl_IsInSectionDirectly( const SwFrame
*pUp
)
1426 bool bSeenColumn
= false;
1430 if( pUp
->IsColumnFrame() )
1432 else if( pUp
->IsSctFrame() )
1434 auto pSection
= static_cast<const SwSectionFrame
*>(pUp
);
1435 const SwFrame
* pHeaderFooter
= pSection
->FindFooterOrHeader();
1436 // When the section frame is not in header/footer:
1437 // Allow move of frame in case our only column is not growable.
1438 // Also allow if there is a previous section frame (to move back).
1439 bool bAllowOutsideHeaderFooter
= !pSection
->Growable() || pSection
->GetPrecede();
1440 return bSeenColumn
|| (!pHeaderFooter
&& bAllowOutsideHeaderFooter
);
1442 else if( pUp
->IsTabFrame() )
1444 pUp
= pUp
->GetUpper();
1449 /** determine, if frame is moveable in given environment
1451 OD 08.08.2003 #110978#
1452 method replaced 'old' method <sal_Bool IsMoveable() const>.
1453 Determines, if frame is moveable in given environment. if no environment
1454 is given (parameter _pLayoutFrame == 0), the movability in the actual
1455 environment (<GetUpper()) is checked.
1457 bool SwFrame::IsMoveable( const SwLayoutFrame
* _pLayoutFrame
) const
1459 bool bRetVal
= false;
1461 if ( !_pLayoutFrame
)
1463 _pLayoutFrame
= GetUpper();
1466 if ( _pLayoutFrame
&& IsFlowFrame() )
1468 if ( _pLayoutFrame
->IsInSct() && lcl_IsInSectionDirectly( _pLayoutFrame
) )
1472 else if ( _pLayoutFrame
->IsInFly() ||
1473 _pLayoutFrame
->IsInDocBody() ||
1474 _pLayoutFrame
->IsInFootnote() )
1476 // If IsMovable() is called before a MoveFwd() the method
1477 // may return false if there is no NextCellLeaf. If
1478 // IsMovable() is called before a MoveBwd() the method may
1479 // return false if there is no PrevCellLeaf.
1480 if ( _pLayoutFrame
->IsInTab() && !IsTabFrame() &&
1481 ( !IsContentFrame() || (!const_cast<SwFrame
*>(this)->GetNextCellLeaf()
1482 && !const_cast<SwFrame
*>(this)->GetPrevCellLeaf()) )
1489 if ( _pLayoutFrame
->IsInFly() )
1491 // if fly frame has a follow (next linked fly frame) or can split,
1492 // frame is moveable.
1493 SwFlyFrame
* pFlyFrame
= const_cast<SwLayoutFrame
*>(_pLayoutFrame
)->FindFlyFrame();
1494 if ( pFlyFrame
->GetNextLink() || pFlyFrame
->IsFlySplitAllowed() )
1500 // if environment is columned, frame is moveable, if
1501 // it isn't in last column.
1502 // search for column frame
1503 const SwFrame
* pCol
= _pLayoutFrame
;
1504 while ( pCol
&& !pCol
->IsColumnFrame() )
1506 pCol
= pCol
->GetUpper();
1508 // frame is moveable, if found column frame isn't last one.
1509 if ( pCol
&& pCol
->GetNext() )
1515 else if (!(_pLayoutFrame
->IsInFootnote() && (IsTabFrame() || IsInTab())))
1526 void SwFrame::SetInfFlags()
1528 if ( !IsFlyFrame() && !GetUpper() ) //not yet pasted, no information available
1531 mbInfInvalid
= mbInfBody
= mbInfTab
= mbInfFly
= mbInfFootnote
= mbInfSct
= false;
1533 SwFrame
*pFrame
= this;
1534 if( IsFootnoteContFrame() )
1535 mbInfFootnote
= true;
1538 // mbInfBody is only set in the page body, but not in the column body
1539 if ( pFrame
->IsBodyFrame() && !mbInfFootnote
&& pFrame
->GetUpper()
1540 && pFrame
->GetUpper()->IsPageFrame() )
1542 else if ( pFrame
->IsTabFrame() || pFrame
->IsCellFrame() )
1546 else if ( pFrame
->IsFlyFrame() )
1548 else if ( pFrame
->IsSctFrame() )
1550 else if ( pFrame
->IsFootnoteFrame() )
1551 mbInfFootnote
= true;
1553 pFrame
= pFrame
->GetUpper();
1555 } while ( pFrame
&& !pFrame
->IsPageFrame() ); //there is nothing above the page
1558 /** Updates the vertical or the righttoleft-flags.
1560 * If the property is derived, it's from the upper or (for fly frames) from
1561 * the anchor. Otherwise we've to call a virtual method to check the property.
1563 void SwFrame::SetDirFlags( bool bVert
)
1567 // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
1568 // vertical flag of upper/anchor is valid.
1571 const SwFrame
* pAsk
= IsFlyFrame() ?
1572 static_cast<SwFlyFrame
*>(this)->GetAnchorFrame() : GetUpper();
1574 OSL_ENSURE( pAsk
!= this, "Autsch! Stack overflow is about to happen" );
1578 mbVertical
= pAsk
->IsVertical();
1579 mbVertLR
= pAsk
->IsVertLR();
1580 mbVertLRBT
= pAsk
->IsVertLRBT();
1582 if ( !pAsk
->mbInvalidVert
)
1583 mbInvalidVert
= false;
1585 if ( IsCellFrame() )
1587 SwCellFrame
* pPrv
= static_cast<SwCellFrame
*>(this)->GetPreviousCell();
1588 if ( pPrv
&& !mbVertical
&& pPrv
->IsVertical() )
1590 mbVertical
= pPrv
->IsVertical();
1591 mbVertLR
= pPrv
->IsVertLR();
1592 mbVertLRBT
= pPrv
->IsVertLRBT();
1598 CheckDirection( bVert
);
1603 if( !mbDerivedR2L
) // CheckDirection is able to set bDerivedR2L!
1604 CheckDirection( bVert
);
1607 const SwFrame
* pAsk
= IsFlyFrame() ?
1608 static_cast<SwFlyFrame
*>(this)->GetAnchorFrame() : GetUpper();
1610 OSL_ENSURE( pAsk
!= this, "Oops! Stack overflow is about to happen" );
1613 mbRightToLeft
= pAsk
->IsRightToLeft();
1614 if( !pAsk
|| pAsk
->mbInvalidR2L
)
1615 bInv
= mbInvalidR2L
;
1617 mbInvalidR2L
= bInv
;
1621 SwLayoutFrame
* SwFrame::GetNextCellLeaf()
1623 SwFrame
* pTmpFrame
= this;
1624 while (pTmpFrame
&& !pTmpFrame
->IsCellFrame())
1625 pTmpFrame
= pTmpFrame
->GetUpper();
1627 SAL_WARN_IF(!pTmpFrame
, "sw.core", "SwFrame::GetNextCellLeaf() without cell");
1628 return pTmpFrame
? static_cast<SwCellFrame
*>(pTmpFrame
)->GetFollowCell() : nullptr;
1631 SwLayoutFrame
* SwFrame::GetPrevCellLeaf()
1633 SwFrame
* pTmpFrame
= this;
1634 while (pTmpFrame
&& !pTmpFrame
->IsCellFrame())
1635 pTmpFrame
= pTmpFrame
->GetUpper();
1637 SAL_WARN_IF(!pTmpFrame
, "sw.core", "SwFrame::GetNextPreviousLeaf() without cell");
1638 return pTmpFrame
? static_cast<SwCellFrame
*>(pTmpFrame
)->GetPreviousCell() : nullptr;
1641 static SwCellFrame
* lcl_FindCorrespondingCellFrame( const SwRowFrame
& rOrigRow
,
1642 const SwCellFrame
& rOrigCell
,
1643 const SwRowFrame
& rCorrRow
,
1646 SwCellFrame
* pRet
= nullptr;
1647 const SwCellFrame
* pCell
= static_cast<const SwCellFrame
*>(rOrigRow
.Lower());
1648 SwCellFrame
* pCorrCell
= const_cast<SwCellFrame
*>(static_cast<const SwCellFrame
*>(rCorrRow
.Lower()));
1650 while ( pCell
!= &rOrigCell
&& !pCell
->IsAnLower( &rOrigCell
) )
1652 pCell
= static_cast<const SwCellFrame
*>(pCell
->GetNext());
1653 pCorrCell
= static_cast<SwCellFrame
*>(pCorrCell
->GetNext());
1656 assert(pCell
&& pCorrCell
&& "lcl_FindCorrespondingCellFrame does not work");
1658 if ( pCell
!= &rOrigCell
)
1660 // rOrigCell must be a lower of pCell. We need to recurse into the rows:
1661 assert(pCell
->Lower() && pCell
->Lower()->IsRowFrame() &&
1662 "lcl_FindCorrespondingCellFrame does not work");
1664 const SwRowFrame
* pRow
= static_cast<const SwRowFrame
*>(pCell
->Lower());
1665 while ( !pRow
->IsAnLower( &rOrigCell
) )
1666 pRow
= static_cast<const SwRowFrame
*>(pRow
->GetNext());
1668 SwRowFrame
* pCorrRow
= nullptr;
1670 pCorrRow
= pRow
->GetFollowRow();
1673 SwRowFrame
* pTmpRow
= static_cast<SwRowFrame
*>(pCorrCell
->GetLastLower());
1675 if ( pTmpRow
&& pTmpRow
->GetFollowRow() == pRow
)
1680 pRet
= lcl_FindCorrespondingCellFrame( *pRow
, rOrigCell
, *pCorrRow
, bInFollow
);
1688 // VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
1689 SwCellFrame
* SwCellFrame::GetFollowCell() const
1691 SwCellFrame
* pRet
= nullptr;
1694 // Covered cells do not have follow cells!
1695 const tools::Long nRowSpan
= GetLayoutRowSpan();
1699 // find most upper row frame
1700 const SwFrame
* pRow
= GetUpper();
1702 while (pRow
&& (!pRow
->IsRowFrame() || !pRow
->GetUpper()->IsTabFrame()))
1703 pRow
= pRow
->GetUpper();
1708 const SwTabFrame
* pTabFrame
= static_cast<const SwTabFrame
*>(pRow
->GetUpper());
1709 if (!pTabFrame
|| !pTabFrame
->GetFollow() || !pTabFrame
->HasFollowFlowLine())
1712 const SwCellFrame
* pThisCell
= this;
1714 // Get last cell of the current table frame that belongs to the rowspan:
1717 // optimization: Will end of row span be in last row or exceed row?
1718 tools::Long nMax
= 0;
1719 while ( pRow
->GetNext() && ++nMax
< nRowSpan
)
1720 pRow
= pRow
->GetNext();
1722 if ( !pRow
->GetNext() )
1724 pThisCell
= &pThisCell
->FindStartEndOfRowSpanCell( false );
1725 pRow
= pThisCell
->GetUpper();
1729 const SwRowFrame
* pFollowRow
= nullptr;
1730 if ( !pRow
->GetNext() &&
1731 nullptr != ( pFollowRow
= pRow
->IsInSplitTableRow() ) &&
1732 ( !pFollowRow
->IsRowSpanLine() || nRowSpan
> 1 ) )
1733 pRet
= lcl_FindCorrespondingCellFrame( *static_cast<const SwRowFrame
*>(pRow
), *pThisCell
, *pFollowRow
, true );
1738 // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
1739 SwCellFrame
* SwCellFrame::GetPreviousCell() const
1741 SwCellFrame
* pRet
= nullptr;
1744 // Covered cells do not have previous cells!
1745 if ( GetLayoutRowSpan() < 1 )
1748 // find most upper row frame
1749 const SwFrame
* pRow
= GetUpper();
1750 while( !pRow
->IsRowFrame() || (pRow
->GetUpper() && !pRow
->GetUpper()->IsTabFrame()) )
1751 pRow
= pRow
->GetUpper();
1753 OSL_ENSURE( pRow
->GetUpper() && pRow
->GetUpper()->IsTabFrame(), "GetPreviousCell without Table" );
1755 const SwTabFrame
* pTab
= static_cast<const SwTabFrame
*>(pRow
->GetUpper());
1757 if ( pTab
&& pTab
->IsFollow() )
1759 const SwFrame
* pTmp
= pTab
->GetFirstNonHeadlineRow();
1760 const bool bIsInFirstLine
= ( pTmp
== pRow
);
1762 if ( bIsInFirstLine
)
1764 SwTabFrame
*pMaster
= pTab
->FindMaster();
1765 if ( pMaster
&& pMaster
->HasFollowFlowLine() )
1767 SwRowFrame
* pMasterRow
= static_cast<SwRowFrame
*>(pMaster
->GetLastLower());
1769 pRet
= lcl_FindCorrespondingCellFrame( *static_cast<const SwRowFrame
*>(pRow
), *this, *pMasterRow
, false );
1770 if ( pRet
&& pRet
->GetTabBox()->getRowSpan() < 1 )
1771 pRet
= &const_cast<SwCellFrame
&>(pRet
->FindStartEndOfRowSpanCell( true ));
1780 const SwCellFrame
& SwCellFrame::FindStartEndOfRowSpanCell( bool bStart
) const
1782 const SwTabFrame
* pTableFrame
= dynamic_cast<const SwTabFrame
*>(GetUpper()->GetUpper());
1784 if ( !bStart
&& pTableFrame
&& pTableFrame
->IsFollow() && pTableFrame
->IsInHeadline( *this ) )
1787 OSL_ENSURE( pTableFrame
&&
1788 ( (bStart
&& GetTabBox()->getRowSpan() < 1) ||
1789 (!bStart
&& GetLayoutRowSpan() > 1) ),
1790 "SwCellFrame::FindStartRowSpanCell: No rowspan, no table, no cookies" );
1794 const SwTable
* pTable
= pTableFrame
->GetTable();
1796 sal_uInt16 nMax
= USHRT_MAX
;
1797 const SwFrame
* pCurrentRow
= GetUpper();
1798 const bool bDoNotEnterHeadline
= bStart
&& pTableFrame
->IsFollow() &&
1799 !pTableFrame
->IsInHeadline( *pCurrentRow
);
1801 // check how many rows we are allowed to go up or down until we reach the end of
1802 // the current table frame:
1804 while ( bStart
? pCurrentRow
->GetPrev() : pCurrentRow
->GetNext() )
1808 // do not enter a repeated headline:
1809 if ( bDoNotEnterHeadline
&& pTableFrame
->IsFollow() &&
1810 pTableFrame
->IsInHeadline( *pCurrentRow
->GetPrev() ) )
1813 pCurrentRow
= pCurrentRow
->GetPrev();
1816 pCurrentRow
= pCurrentRow
->GetNext();
1821 // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly
1822 // is set) we assure that we find a rMasterBox that has a SwCellFrame in
1823 // the current table frame:
1824 const SwTableBox
& rMasterBox
= bStart
?
1825 GetTabBox()->FindStartOfRowSpan( *pTable
, nMax
) :
1826 GetTabBox()->FindEndOfRowSpan( *pTable
, nMax
);
1828 SwIterator
<SwCellFrame
,SwFormat
> aIter( *rMasterBox
.GetFrameFormat() );
1830 for ( SwCellFrame
* pMasterCell
= aIter
.First(); pMasterCell
; pMasterCell
= aIter
.Next() )
1832 if ( pMasterCell
->GetTabBox() == &rMasterBox
)
1834 const SwTabFrame
* pMasterTable
= static_cast<const SwTabFrame
*>(pMasterCell
->GetUpper()->GetUpper());
1836 if ( pMasterTable
== pTableFrame
)
1838 return *pMasterCell
;
1844 SAL_WARN("sw.core", "SwCellFrame::FindStartRowSpanCell: No result");
1851 const SwRowFrame
* SwFrame::IsInSplitTableRow() const
1853 OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
1855 const SwFrame
* pRow
= this;
1857 // find most upper row frame
1858 while( pRow
&& ( !pRow
->IsRowFrame() || !pRow
->GetUpper()->IsTabFrame() ) )
1859 pRow
= pRow
->GetUpper();
1861 if ( !pRow
) return nullptr;
1863 OSL_ENSURE( pRow
->GetUpper()->IsTabFrame(), "Confusion in table layout" );
1865 const SwTabFrame
* pTab
= static_cast<const SwTabFrame
*>(pRow
->GetUpper());
1867 // If most upper row frame is a headline row, the current frame
1868 // can't be in a split table row. Thus, add corresponding condition.
1869 if ( pRow
->GetNext() ||
1870 pTab
->GetTable()->IsHeadline(
1871 *(static_cast<const SwRowFrame
*>(pRow
)->GetTabLine()) ) ||
1872 !pTab
->HasFollowFlowLine() ||
1873 !pTab
->GetFollow() )
1877 const SwRowFrame
* pFollowRow
= pTab
->GetFollow()->GetFirstNonHeadlineRow();
1879 OSL_ENSURE( pFollowRow
, "SwFrame::IsInSplitTableRow() does not work" );
1884 const SwRowFrame
* SwFrame::IsInFollowFlowRow() const
1886 OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
1888 // find most upper row frame
1889 const SwFrame
* pRow
= this;
1890 while( pRow
&& ( !pRow
->IsRowFrame() || !pRow
->GetUpper()->IsTabFrame() ) )
1891 pRow
= pRow
->GetUpper();
1893 if ( !pRow
) return nullptr;
1895 OSL_ENSURE( pRow
->GetUpper()->IsTabFrame(), "Confusion in table layout" );
1897 const SwTabFrame
* pTab
= static_cast<const SwTabFrame
*>(pRow
->GetUpper());
1899 const SwTabFrame
* pMaster
= pTab
->IsFollow() ? pTab
->FindMaster() : nullptr;
1901 if ( !pMaster
|| !pMaster
->HasFollowFlowLine() )
1904 const SwFrame
* pTmp
= pTab
->GetFirstNonHeadlineRow();
1905 const bool bIsInFirstLine
= ( pTmp
== pRow
);
1907 if ( !bIsInFirstLine
)
1910 const SwRowFrame
* pMasterRow
= static_cast<const SwRowFrame
*>(pMaster
->GetLastLower());
1914 bool SwFrame::IsInBalancedSection() const
1920 const SwSectionFrame
* pSectionFrame
= FindSctFrame();
1921 if ( pSectionFrame
)
1922 bRet
= pSectionFrame
->IsBalancedSection();
1927 const SwFrame
* SwLayoutFrame::GetLastLower() const
1929 const SwFrame
* pRet
= Lower();
1932 while ( pRet
->GetNext() )
1933 pRet
= pRet
->GetNext();
1937 SwTextFrame
* SwFrame::DynCastTextFrame()
1939 return IsTextFrame() ? static_cast<SwTextFrame
*>(this) : nullptr;
1942 const SwTextFrame
* SwFrame::DynCastTextFrame() const
1944 return IsTextFrame() ? static_cast<const SwTextFrame
*>(this) : nullptr;
1947 SwPageFrame
* SwFrame::DynCastPageFrame()
1949 return IsPageFrame() ? static_cast<SwPageFrame
*>(this) : nullptr;
1952 const SwPageFrame
* SwFrame::DynCastPageFrame() const
1954 return IsPageFrame() ? static_cast<const SwPageFrame
*>(this) : nullptr;
1957 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */