/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "pagefrm.hxx" #include "rootfrm.hxx" #include #include #include #include "tabfrm.hxx" #include "sectfrm.hxx" #include "flyfrms.hxx" #include "ftnfrm.hxx" #include "txtftn.hxx" #include "fmtftn.hxx" #include #include #include /// Searches the first ContentFrame in BodyText below the page. SwLayoutFrame *SwFootnoteBossFrame::FindBodyCont() { SwFrame *pLay = Lower(); while ( pLay && !pLay->IsBodyFrame() ) pLay = pLay->GetNext(); return static_cast(pLay); } /// Searches the last ContentFrame in BodyText below the page. SwContentFrame *SwPageFrame::FindLastBodyContent() { SwContentFrame *pRet = FindFirstBodyContent(); SwContentFrame *pNxt = pRet; while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) ) { pRet = pNxt; pNxt = pNxt->FindNextCnt(); } return pRet; } /** * Checks if the frame contains one or more ContentFrame's anywhere in his * subsidiary structure; if so the first found ContentFrame is returned. */ const SwContentFrame *SwLayoutFrame::ContainsContent() const { //Search downwards the layout leaf and if there is no content, jump to the //next leaf until content is found or we leave "this". //Sections: Content next to sections would not be found this way (empty //sections directly next to ContentFrame) therefore we need to recursively //search for them even if it's more complex. const SwLayoutFrame *pLayLeaf = this; do { while ( (!pLayLeaf->IsSctFrame() || pLayLeaf == this ) && pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrame() ) pLayLeaf = static_cast(pLayLeaf->Lower()); if( pLayLeaf->IsSctFrame() && pLayLeaf != this ) { const SwContentFrame *pCnt = pLayLeaf->ContainsContent(); if( pCnt ) return pCnt; if( pLayLeaf->GetNext() ) { if( pLayLeaf->GetNext()->IsLayoutFrame() ) { pLayLeaf = static_cast(pLayLeaf->GetNext()); continue; } else return static_cast(pLayLeaf->GetNext()); } } else if ( pLayLeaf->Lower() ) return static_cast(pLayLeaf->Lower()); pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); if( !IsAnLower( pLayLeaf) ) return nullptr; } while( pLayLeaf ); return nullptr; } /** * Calls ContainsAny first to reach the innermost cell. From there we walk back * up to the first SwCellFrame. Since we use SectionFrames, ContainsContent()->GetUpper() * is not enough anymore. */ const SwCellFrame *SwLayoutFrame::FirstCell() const { const SwFrame* pCnt = ContainsAny(); while( pCnt && !pCnt->IsCellFrame() ) pCnt = pCnt->GetUpper(); return static_cast(pCnt); } /** return ContentFrames, sections, and tables. * * @param _bInvestigateFootnoteForSections controls investigation of content of footnotes for sections. * @see ContainsContent */ const SwFrame *SwLayoutFrame::ContainsAny( const bool _bInvestigateFootnoteForSections ) const { //Search downwards the layout leaf and if there is no content, jump to the //next leaf until content is found, we leave "this" or until we found //a SectionFrame or a TabFrame. const SwLayoutFrame *pLayLeaf = this; const bool bNoFootnote = IsSctFrame() && !_bInvestigateFootnoteForSections; do { while ( ( (!pLayLeaf->IsSctFrame() && !pLayLeaf->IsTabFrame()) || pLayLeaf == this ) && pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrame() ) pLayLeaf = static_cast(pLayLeaf->Lower()); if( ( pLayLeaf->IsTabFrame() || pLayLeaf->IsSctFrame() ) && pLayLeaf != this ) { // Now we also return "deleted" SectionFrames so they can be // maintained on SaveContent and RestoreContent return pLayLeaf; } else if ( pLayLeaf->Lower() ) return static_cast(pLayLeaf->Lower()); pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); if( bNoFootnote && pLayLeaf && pLayLeaf->IsInFootnote() ) { do { pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); } while( pLayLeaf && pLayLeaf->IsInFootnote() ); } if( !IsAnLower( pLayLeaf) ) return nullptr; } while( pLayLeaf ); return nullptr; } const SwFrame* SwFrame::GetLower() const { return IsLayoutFrame() ? static_cast(this)->Lower() : nullptr; } SwFrame* SwFrame::GetLower() { return IsLayoutFrame() ? static_cast(this)->Lower() : nullptr; } SwContentFrame* SwFrame::FindPrevCnt( const bool _bInSameFootnote ) { if ( GetPrev() && GetPrev()->IsContentFrame() ) return static_cast(GetPrev()); else return _FindPrevCnt( _bInSameFootnote ); } const SwContentFrame* SwFrame::FindPrevCnt( const bool _bInSameFootnote ) const { if ( GetPrev() && GetPrev()->IsContentFrame() ) return static_cast(GetPrev()); else return const_cast(this)->_FindPrevCnt( _bInSameFootnote ); } SwContentFrame *SwFrame::FindNextCnt( const bool _bInSameFootnote ) { if ( mpNext && mpNext->IsContentFrame() ) return static_cast(mpNext); else return _FindNextCnt( _bInSameFootnote ); } const SwContentFrame *SwFrame::FindNextCnt( const bool _bInSameFootnote ) const { if ( mpNext && mpNext->IsContentFrame() ) return static_cast(mpNext); else return const_cast(this)->_FindNextCnt( _bInSameFootnote ); } bool SwLayoutFrame::IsAnLower( const SwFrame *pAssumed ) const { const SwFrame *pUp = pAssumed; while ( pUp ) { if ( pUp == this ) return true; if ( pUp->IsFlyFrame() ) pUp = static_cast(pUp)->GetAnchorFrame(); else pUp = pUp->GetUpper(); } return false; } /** method to check relative position of layout frame to a given layout frame. OD 08.11.2002 - refactoring of pseudo-local method in for #104840#. @param _aCheckRefLayFrame constant reference of an instance of class which is used as the reference for the relative position check. @return true, if is positioned before the layout frame

*/ bool SwLayoutFrame::IsBefore( const SwLayoutFrame* _pCheckRefLayFrame ) const { OSL_ENSURE( !IsRootFrame() , " called at a ."); OSL_ENSURE( !_pCheckRefLayFrame->IsRootFrame() , " called with a ."); bool bReturn; // check, if on different pages const SwPageFrame *pMyPage = FindPageFrame(); const SwPageFrame *pCheckRefPage = _pCheckRefLayFrame->FindPageFrame(); if( pMyPage != pCheckRefPage ) { // being on different page as check reference bReturn = pMyPage->GetPhyPageNum() < pCheckRefPage->GetPhyPageNum(); } else { // being on same page as check reference // --> search my supreme parent , which doesn't contain check reference. const SwLayoutFrame* pUp = this; while ( pUp->GetUpper() && !pUp->GetUpper()->IsAnLower( _pCheckRefLayFrame ) ) pUp = pUp->GetUpper(); if( !pUp->GetUpper() ) { // can occur, if is a fly frm bReturn = false; } else { // travel through the next's of and check if one of these // contain the check reference. const SwLayoutFrame* pUpNext = static_cast(pUp->GetNext()); while ( pUpNext && !pUpNext->IsAnLower( _pCheckRefLayFrame ) ) { pUpNext = static_cast(pUpNext->GetNext()); } bReturn = pUpNext != nullptr; } } return bReturn; } // Local helper functions for GetNextLayoutLeaf static const SwFrame* lcl_FindLayoutFrame( const SwFrame* pFrame, bool bNext ) { const SwFrame* pRet = nullptr; if ( pFrame->IsFlyFrame() ) pRet = bNext ? static_cast(pFrame)->GetNextLink() : static_cast(pFrame)->GetPrevLink(); else pRet = bNext ? pFrame->GetNext() : pFrame->GetPrev(); return pRet; } static const SwFrame* lcl_GetLower( const SwFrame* pFrame, bool bFwd ) { if ( !pFrame->IsLayoutFrame() ) return nullptr; return bFwd ? static_cast(pFrame)->Lower() : static_cast(pFrame)->GetLastLower(); } /** * Finds the next layout leaf. This is a layout frame, which does not * have a lower which is a LayoutFrame. That means, pLower can be 0 or a * content frame. * * However, pLower may be a TabFrame */ const SwLayoutFrame *SwFrame::ImplGetNextLayoutLeaf( bool bFwd ) const { const SwFrame *pFrame = this; const SwLayoutFrame *pLayoutFrame = nullptr; const SwFrame *p = nullptr; bool bGoingUp = !bFwd; // false for forward, true for backward do { bool bGoingFwdOrBwd = false; bool bGoingDown = ( !bGoingUp && ( nullptr != (p = lcl_GetLower( pFrame, bFwd ) ) ) ); if ( !bGoingDown ) { // I cannot go down, because either I'm currently going up or // because the is no lower. // I'll try to go forward: bGoingFwdOrBwd = (nullptr != (p = lcl_FindLayoutFrame( pFrame, bFwd ) ) ); if ( !bGoingFwdOrBwd ) { // I cannot go forward, because there is no next frame. // I'll try to go up: bGoingUp = (nullptr != (p = pFrame->GetUpper() ) ); if ( !bGoingUp ) { // I cannot go up, because there is no upper frame. return nullptr; } } } // If I could not go down or forward, I'll have to go up bGoingUp = !bGoingFwdOrBwd && !bGoingDown; pFrame = p; p = lcl_GetLower( pFrame, true ); } while( ( p && !p->IsFlowFrame() ) || pFrame == this || nullptr == ( pLayoutFrame = pFrame->IsLayoutFrame() ? static_cast(pFrame) : nullptr ) || pLayoutFrame->IsAnLower( this ) ); return pLayoutFrame; } /** * Walk back inside the tree: grab the subordinate Frame if one exists and the * last step was not moving up a level (this would lead to an infinite up/down * loop!). With this we ensure that during walking back we search through all * sub trees. If we walked downwards we have to go to the end of the chain first * because we go backwards from the last Frame inside another Frame. Walking * forward works the same. * * @warning fixes here may also need to be applied to the @{lcl_NextFrame} method above */ const SwContentFrame* SwContentFrame::ImplGetNextContentFrame( bool bFwd ) const { const SwFrame *pFrame = this; const SwContentFrame *pContentFrame = nullptr; bool bGoingUp = false; do { const SwFrame *p = nullptr; bool bGoingFwdOrBwd = false; bool bGoingDown = ( !bGoingUp && ( nullptr != ( p = lcl_GetLower( pFrame, true ) ) ) ); if ( !bGoingDown ) { bGoingFwdOrBwd = ( nullptr != ( p = lcl_FindLayoutFrame( pFrame, bFwd ) ) ); if ( !bGoingFwdOrBwd ) { bGoingUp = ( nullptr != ( p = pFrame->GetUpper() ) ); if ( !bGoingUp ) { return nullptr; } } } bGoingUp = !(bGoingFwdOrBwd || bGoingDown); if ( !bFwd ) { if( bGoingDown && p ) while ( p->GetNext() ) p = p->GetNext(); } pFrame = p; } while ( nullptr == (pContentFrame = (pFrame->IsContentFrame() ? static_cast(pFrame) : nullptr) )); return pContentFrame; } SwPageFrame* SwFrame::ImplFindPageFrame() { SwFrame *pRet = this; while ( pRet && !pRet->IsPageFrame() ) { if ( pRet->GetUpper() ) pRet = pRet->GetUpper(); else if ( pRet->IsFlyFrame() ) { // #i28701# - use new method const auto pFly(static_cast(pRet)); pRet = pFly->GetPageFrame(); if (pRet == nullptr) pRet = pFly->AnchorFrame(); } else return nullptr; } return static_cast(pRet); } SwFootnoteBossFrame* SwFrame::FindFootnoteBossFrame( bool bFootnotes ) { SwFrame *pRet = this; // Footnote bosses can't exist inside a table; also sections with columns // don't contain footnote texts there if( pRet->IsInTab() ) pRet = pRet->FindTabFrame(); while ( pRet && !pRet->IsFootnoteBossFrame() ) { if ( pRet->GetUpper() ) pRet = pRet->GetUpper(); else if ( pRet->IsFlyFrame() ) { // #i28701# - use new method if ( static_cast(pRet)->GetPageFrame() ) pRet = static_cast(pRet)->GetPageFrame(); else pRet = static_cast(pRet)->AnchorFrame(); } else return nullptr; } if( bFootnotes && pRet && pRet->IsColumnFrame() && !pRet->GetNext() && !pRet->GetPrev() ) { SwSectionFrame* pSct = pRet->FindSctFrame(); OSL_ENSURE( pSct, "FindFootnoteBossFrame: Single column outside section?" ); if( !pSct->IsFootnoteAtEnd() ) return pSct->FindFootnoteBossFrame( true ); } return static_cast(pRet); } SwTabFrame* SwFrame::ImplFindTabFrame() { SwFrame *pRet = this; while ( !pRet->IsTabFrame() ) { pRet = pRet->GetUpper(); if ( !pRet ) return nullptr; } return static_cast(pRet); } SwSectionFrame* SwFrame::ImplFindSctFrame() { SwFrame *pRet = this; while ( !pRet->IsSctFrame() ) { pRet = pRet->GetUpper(); if ( !pRet ) return nullptr; } return static_cast(pRet); } SwFootnoteFrame *SwFrame::ImplFindFootnoteFrame() { SwFrame *pRet = this; while ( !pRet->IsFootnoteFrame() ) { pRet = pRet->GetUpper(); if ( !pRet ) return nullptr; } return static_cast(pRet); } SwFlyFrame *SwFrame::ImplFindFlyFrame() { SwFrame *pRet = this; do { if ( pRet->IsFlyFrame() ) return static_cast(pRet); else pRet = pRet->GetUpper(); } while ( pRet ); return nullptr; } SwFrame *SwFrame::FindColFrame() { SwFrame *pFrame = this; do { pFrame = pFrame->GetUpper(); } while ( pFrame && !pFrame->IsColumnFrame() ); return pFrame; } SwRowFrame *SwFrame::FindRowFrame() { SwFrame *pFrame = this; do { pFrame = pFrame->GetUpper(); } while ( pFrame && !pFrame->IsRowFrame() ); return dynamic_cast< SwRowFrame* >( pFrame ); } SwFrame* SwFrame::FindFooterOrHeader() { SwFrame* pRet = this; do { if (pRet->GetType() & FRM_HEADFOOT) //header and footer return pRet; else if ( pRet->GetUpper() ) pRet = pRet->GetUpper(); else if ( pRet->IsFlyFrame() ) pRet = static_cast(pRet)->AnchorFrame(); else return nullptr; } while ( pRet ); return pRet; } const SwFootnoteFrame* SwFootnoteContFrame::FindFootNote() const { const SwFootnoteFrame* pRet = static_cast(Lower()); if( pRet && !pRet->GetAttr()->GetFootnote().IsEndNote() ) return pRet; return nullptr; } const SwPageFrame* SwRootFrame::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const { const SwPageFrame* pRet = nullptr; SwRect aRect; if ( pSize ) { aRect.Pos() = rPt; aRect.SSize() = *pSize; } const SwFrame* pPage = Lower(); if ( !bExtend ) { if( !Frame().IsInside( rPt ) ) return nullptr; // skip pages above point: while( pPage && rPt.Y() > pPage->Frame().Bottom() ) pPage = pPage->GetNext(); } OSL_ENSURE( GetPageNum() <= maPageRects.size(), "number of pages differes from page rect array size" ); size_t nPageIdx = 0; while ( pPage && !pRet ) { const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->Frame(); if ( (!pSize && rBoundRect.IsInside(rPt)) || (pSize && rBoundRect.IsOver(aRect)) ) { pRet = static_cast(pPage); } pPage = pPage->GetNext(); } return pRet; } bool SwRootFrame::IsBetweenPages(const Point& rPt) const { if (!Frame().IsInside(rPt)) return false; // top visible page const SwFrame* pPage = Lower(); if (pPage == nullptr) return false; // skip pages above point: while (pPage && rPt.Y() > pPage->Frame().Bottom()) pPage = pPage->GetNext(); if (pPage && rPt.X() >= pPage->Frame().Left() && rPt.X() <= pPage->Frame().Right()) { // Trivial case when we're right in between. if (!pPage->Frame().IsInside(rPt)) return true; // In normal mode the gap is large enough and // header/footer mouse interaction competes with // handling hide-whitespace within them. // In hide-whitespace, however, the gap is too small // for convenience and there are no headers/footers. const SwViewShell *pSh = GetCurrShell(); if (pSh && pSh->GetViewOptions()->IsWhitespaceHidden()) { // If we are really close to the bottom or top of a page. const auto toEdge = std::min(std::abs(pPage->Frame().Top() - rPt.Y()), std::abs(pPage->Frame().Bottom() - rPt.Y())); return toEdge <= MmToTwips(2.0); } } return false; } const SwAttrSet* SwFrame::GetAttrSet() const { if ( IsContentFrame() ) return &static_cast(this)->GetNode()->GetSwAttrSet(); else return &static_cast(this)->GetFormat()->GetAttrSet(); } //UUUU drawinglayer::attribute::SdrAllFillAttributesHelperPtr SwFrame::getSdrAllFillAttributesHelper() const { if(IsContentFrame()) { return static_cast< const SwContentFrame* >(this)->GetNode()->getSdrAllFillAttributesHelper(); } else { return static_cast< const SwLayoutFrame* >(this)->GetFormat()->getSdrAllFillAttributesHelper(); } } bool SwFrame::supportsFullDrawingLayerFillAttributeSet() const { if (IsContentFrame()) { return true; } else { return static_cast< const SwLayoutFrame* >(this)->GetFormat()->supportsFullDrawingLayerFillAttributeSet(); } } /* * SwFrame::_FindNext(), _FindPrev(), InvalidateNextPos() * _FindNextCnt() visits tables and sections and only returns SwContentFrames. * * Description Invalidates the position of the next frame. * This is the direct successor or in case of ContentFrames the next * ContentFrame which sits in the same flow as I do: * - body, * - footnote, * - in headers/footers the notification only needs to be forwarded * inside the section * - same for Flys * - Contents in tabs remain only inside their cell * - in principle tables behave exactly like the Contents * - sections also */ // This helper function is an equivalent to the ImplGetNextContentFrame() method, // besides ContentFrames this function also returns TabFrames and SectionFrames. static SwFrame* lcl_NextFrame( SwFrame* pFrame ) { SwFrame *pRet = nullptr; bool bGoingUp = false; do { SwFrame *p = nullptr; bool bGoingFwd = false; bool bGoingDown = (!bGoingUp && ( nullptr != (p = pFrame->IsLayoutFrame() ? static_cast(pFrame)->Lower() : nullptr))); if( !bGoingDown ) { bGoingFwd = (nullptr != (p = ( pFrame->IsFlyFrame() ? static_cast(pFrame)->GetNextLink() : pFrame->GetNext()))); if ( !bGoingFwd ) { bGoingUp = (nullptr != (p = pFrame->GetUpper())); if ( !bGoingUp ) { return nullptr; } } } bGoingUp = !(bGoingFwd || bGoingDown); pFrame = p; } while ( nullptr == (pRet = ( ( pFrame->IsContentFrame() || ( !bGoingUp && ( pFrame->IsTabFrame() || pFrame->IsSctFrame() ) ) )? pFrame : nullptr ) ) ); return pRet; } SwFrame *SwFrame::_FindNext() { bool bIgnoreTab = false; SwFrame *pThis = this; if ( IsTabFrame() ) { //The last Content of the table gets picked up and his follower is //returned. To be able to deactivate the special case for tables //(see below) bIgnoreTab will be set. if ( static_cast(this)->GetFollow() ) return static_cast(this)->GetFollow(); pThis = static_cast(this)->FindLastContent(); if ( !pThis ) pThis = this; bIgnoreTab = true; } else if ( IsSctFrame() ) { //The last Content of the section gets picked and his follower is returned. if ( static_cast(this)->GetFollow() ) return static_cast(this)->GetFollow(); pThis = static_cast(this)->FindLastContent(); if ( !pThis ) pThis = this; } else if ( IsContentFrame() ) { if( static_cast(this)->GetFollow() ) return static_cast(this)->GetFollow(); } else if ( IsRowFrame() ) { SwFrame* pMyUpper = GetUpper(); if ( pMyUpper->IsTabFrame() && static_cast(pMyUpper)->GetFollow() ) return static_cast(pMyUpper)->GetFollow()->GetLower(); else return nullptr; } else return nullptr; SwFrame* pRet = nullptr; const bool bFootnote = pThis->IsInFootnote(); if ( !bIgnoreTab && pThis->IsInTab() ) { SwLayoutFrame *pUp = pThis->GetUpper(); while (pUp && !pUp->IsCellFrame()) pUp = pUp->GetUpper(); SAL_WARN_IF(!pUp, "sw.core", "Content in table but not in cell."); SwFrame* pNxt = pUp ? static_cast(pUp)->GetFollowCell() : nullptr; if ( pNxt ) pNxt = static_cast(pNxt)->ContainsContent(); if ( !pNxt ) { pNxt = lcl_NextFrame( pThis ); if (pUp && pUp->IsAnLower(pNxt)) pRet = pNxt; } else pRet = pNxt; } else { const bool bBody = pThis->IsInDocBody(); SwFrame *pNxtCnt = lcl_NextFrame( pThis ); if ( pNxtCnt ) { if ( bBody || bFootnote ) { while ( pNxtCnt ) { // OD 02.04.2003 #108446# - check for endnote, only if found // next content isn't contained in a section, that collect its // endnotes at its end. bool bEndn = IsInSct() && !IsSctFrame() && ( !pNxtCnt->IsInSct() || !pNxtCnt->FindSctFrame()->IsEndnAtEnd() ); if ( ( bBody && pNxtCnt->IsInDocBody() ) || ( pNxtCnt->IsInFootnote() && ( bFootnote || ( bEndn && pNxtCnt->FindFootnoteFrame()->GetAttr()->GetFootnote().IsEndNote() ) ) ) ) { pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrame() : pNxtCnt; break; } pNxtCnt = lcl_NextFrame( pNxtCnt ); } } else if ( pThis->IsInFly() ) { pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrame() : pNxtCnt; } else //footer-/or header section { const SwFrame *pUp = pThis->GetUpper(); const SwFrame *pCntUp = pNxtCnt->GetUpper(); while ( pUp && pUp->GetUpper() && !pUp->IsHeaderFrame() && !pUp->IsFooterFrame() ) pUp = pUp->GetUpper(); while ( pCntUp && pCntUp->GetUpper() && !pCntUp->IsHeaderFrame() && !pCntUp->IsFooterFrame() ) pCntUp = pCntUp->GetUpper(); if ( pCntUp == pUp ) { pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrame() : pNxtCnt; } } } } if( pRet && pRet->IsInSct() ) { SwSectionFrame* pSct = pRet->FindSctFrame(); //Footnotes in frames with columns must not return the section which //contains the footnote if( !pSct->IsAnLower( this ) && (!bFootnote || pSct->IsInFootnote() ) ) return pSct; } return pRet; } // #i27138# - add parameter <_bInSameFootnote> SwContentFrame *SwFrame::_FindNextCnt( const bool _bInSameFootnote ) { SwFrame *pThis = this; if ( IsTabFrame() ) { if ( static_cast(this)->GetFollow() ) { pThis = static_cast(this)->GetFollow()->ContainsContent(); if( pThis ) return static_cast(pThis); } pThis = static_cast(this)->FindLastContent(); if ( !pThis ) return nullptr; } else if ( IsSctFrame() ) { if ( static_cast(this)->GetFollow() ) { pThis = static_cast(this)->GetFollow()->ContainsContent(); if( pThis ) return static_cast(pThis); } pThis = static_cast(this)->FindLastContent(); if ( !pThis ) return nullptr; } else if ( IsContentFrame() && static_cast(this)->GetFollow() ) return static_cast(this)->GetFollow(); if ( pThis->IsContentFrame() ) { const bool bBody = pThis->IsInDocBody(); const bool bFootnote = pThis->IsInFootnote(); SwContentFrame *pNxtCnt = static_cast(pThis)->GetNextContentFrame(); if ( pNxtCnt ) { // #i27138# if ( bBody || ( bFootnote && !_bInSameFootnote ) ) { // handling for environments 'footnotes' and 'document body frames': while ( pNxtCnt ) { if ( (bBody && pNxtCnt->IsInDocBody()) || (bFootnote && pNxtCnt->IsInFootnote()) ) return pNxtCnt; pNxtCnt = pNxtCnt->GetNextContentFrame(); } } // #i27138# else if ( bFootnote && _bInSameFootnote ) { // handling for environments 'each footnote': // Assure that found next content frame belongs to the same footnotes const SwFootnoteFrame* pFootnoteFrameOfNext( pNxtCnt->FindFootnoteFrame() ); const SwFootnoteFrame* pFootnoteFrameOfCurr( pThis->FindFootnoteFrame() ); OSL_ENSURE( pFootnoteFrameOfCurr, "GetFollow() ) { // next content frame has to be the first content frame // in the follow footnote, which contains a content frame. SwFootnoteFrame* pFollowFootnoteFrameOfCurr( const_cast(pFootnoteFrameOfCurr) ); pNxtCnt = nullptr; do { pFollowFootnoteFrameOfCurr = pFollowFootnoteFrameOfCurr->GetFollow(); pNxtCnt = pFollowFootnoteFrameOfCurr->ContainsContent(); } while ( !pNxtCnt && pFollowFootnoteFrameOfCurr->GetFollow() ); return pNxtCnt; } else { // current content frame is the last content frame in the // footnote - no next content frame exists. return nullptr; } } else if ( pThis->IsInFly() ) // handling for environments 'unlinked fly frame' and // 'group of linked fly frames': return pNxtCnt; else { // handling for environments 'page header' and 'page footer': const SwFrame *pUp = pThis->GetUpper(); const SwFrame *pCntUp = pNxtCnt->GetUpper(); while ( pUp && pUp->GetUpper() && !pUp->IsHeaderFrame() && !pUp->IsFooterFrame() ) pUp = pUp->GetUpper(); while ( pCntUp && pCntUp->GetUpper() && !pCntUp->IsHeaderFrame() && !pCntUp->IsFooterFrame() ) pCntUp = pCntUp->GetUpper(); if ( pCntUp == pUp ) return pNxtCnt; } } } return nullptr; } /** method to determine previous content frame in the same environment for a flow frame (content frame, table frame, section frame) OD 2005-11-30 #i27138# */ SwContentFrame* SwFrame::_FindPrevCnt( const bool _bInSameFootnote ) { if ( !IsFlowFrame() ) { // nothing to do, if current frame isn't a flow frame. return nullptr; } SwContentFrame* pPrevContentFrame( nullptr ); // Because method is used to travel // through the layout, a content frame, at which the travel starts, is needed. SwContentFrame* pCurrContentFrame = dynamic_cast(this); // perform shortcut, if current frame is a follow, and // determine , if current frame is a table or section frame if ( pCurrContentFrame && pCurrContentFrame->IsFollow() ) { // previous content frame is its master content frame pPrevContentFrame = pCurrContentFrame->FindMaster(); } else if ( IsTabFrame() ) { SwTabFrame* pTabFrame( static_cast(this) ); if ( pTabFrame->IsFollow() ) { // previous content frame is the last content of its master table frame pPrevContentFrame = pTabFrame->FindMaster()->FindLastContent(); } else { // start content frame for the search is the first content frame of // the table frame. pCurrContentFrame = pTabFrame->ContainsContent(); } } else if ( IsSctFrame() ) { SwSectionFrame* pSectFrame( static_cast(this) ); if ( pSectFrame->IsFollow() ) { // previous content frame is the last content of its master section frame pPrevContentFrame = pSectFrame->FindMaster()->FindLastContent(); } else { // start content frame for the search is the first content frame of // the section frame. pCurrContentFrame = pSectFrame->ContainsContent(); } } // search for next content frame, depending on the environment, in which // the current frame is in. if ( !pPrevContentFrame && pCurrContentFrame ) { pPrevContentFrame = pCurrContentFrame->GetPrevContentFrame(); if ( pPrevContentFrame ) { if ( pCurrContentFrame->IsInFly() ) { // handling for environments 'unlinked fly frame' and // 'group of linked fly frames': // Nothing to do, is the one } else { const bool bInDocBody = pCurrContentFrame->IsInDocBody(); const bool bInFootnote = pCurrContentFrame->IsInFootnote(); if ( bInDocBody || ( bInFootnote && !_bInSameFootnote ) ) { // handling for environments 'footnotes' and 'document body frames': // Assure that found previous frame is also in one of these // environments. Otherwise, travel further while ( pPrevContentFrame ) { if ( ( bInDocBody && pPrevContentFrame->IsInDocBody() ) || ( bInFootnote && pPrevContentFrame->IsInFootnote() ) ) { break; } pPrevContentFrame = pPrevContentFrame->GetPrevContentFrame(); } } else if ( bInFootnote && _bInSameFootnote ) { // handling for environments 'each footnote': // Assure that found next content frame belongs to the same footnotes const SwFootnoteFrame* pFootnoteFrameOfPrev( pPrevContentFrame->FindFootnoteFrame() ); const SwFootnoteFrame* pFootnoteFrameOfCurr( pCurrContentFrame->FindFootnoteFrame() ); if ( pFootnoteFrameOfPrev != pFootnoteFrameOfCurr ) { if ( pFootnoteFrameOfCurr->GetMaster() ) { SwFootnoteFrame* pMasterFootnoteFrameOfCurr( const_cast(pFootnoteFrameOfCurr) ); pPrevContentFrame = nullptr; // correct wrong loop-condition do { pMasterFootnoteFrameOfCurr = pMasterFootnoteFrameOfCurr->GetMaster(); pPrevContentFrame = pMasterFootnoteFrameOfCurr->FindLastContent(); } while ( !pPrevContentFrame && pMasterFootnoteFrameOfCurr->GetMaster() ); } else { // current content frame is the first content in the // footnote - no previous content exists. pPrevContentFrame = nullptr; } } } else { // handling for environments 'page header' and 'page footer': // Assure that found previous frame is also in the same // page header respectively page footer as // Note: At this point its clear, that has // to be inside a page header or page footer and that // neither nor are // inside a fly frame. // Thus, method can be used. OSL_ENSURE( pCurrContentFrame->FindFooterOrHeader(), " - unknown layout situation: current frame should be in page header or page footer" ); OSL_ENSURE( !pPrevContentFrame->IsInFly(), " - unknown layout situation: found previous frame should *not* be inside a fly frame." ); if ( pPrevContentFrame->FindFooterOrHeader() != pCurrContentFrame->FindFooterOrHeader() ) { pPrevContentFrame = nullptr; } } } } } return pPrevContentFrame; } SwFrame *SwFrame::_FindPrev() { bool bIgnoreTab = false; SwFrame *pThis = this; if ( IsTabFrame() ) { //The first Content of the table gets picked up and his predecessor is //returned. To be able to deactivate the special case for tables //(see below) bIgnoreTab will be set. if ( static_cast(this)->IsFollow() ) return static_cast(this)->FindMaster(); else pThis = static_cast(this)->ContainsContent(); bIgnoreTab = true; } if ( pThis && pThis->IsContentFrame() ) { SwContentFrame *pPrvCnt = static_cast(pThis)->GetPrevContentFrame(); if( !pPrvCnt ) return nullptr; if ( !bIgnoreTab && pThis->IsInTab() ) { SwLayoutFrame *pUp = pThis->GetUpper(); while (pUp && !pUp->IsCellFrame()) pUp = pUp->GetUpper(); SAL_WARN_IF(!pUp, "sw.core", "Content in table but not in cell."); if (pUp && pUp->IsAnLower(pPrvCnt)) return pPrvCnt; } else { SwFrame* pRet; const bool bBody = pThis->IsInDocBody(); const bool bFootnote = !bBody && pThis->IsInFootnote(); if ( bBody || bFootnote ) { while ( pPrvCnt ) { if ( (bBody && pPrvCnt->IsInDocBody()) || (bFootnote && pPrvCnt->IsInFootnote()) ) { pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame() : static_cast(pPrvCnt); return pRet; } pPrvCnt = pPrvCnt->GetPrevContentFrame(); } } else if ( pThis->IsInFly() ) { pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame() : static_cast(pPrvCnt); return pRet; } else // footer or header or Fly { const SwFrame *pUp = pThis->GetUpper(); const SwFrame *pCntUp = pPrvCnt->GetUpper(); while ( pUp && pUp->GetUpper() && !pUp->IsHeaderFrame() && !pUp->IsFooterFrame() ) pUp = pUp->GetUpper(); while ( pCntUp && pCntUp->GetUpper() ) pCntUp = pCntUp->GetUpper(); if ( pCntUp == pUp ) { pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame() : static_cast(pPrvCnt); return pRet; } } } } return nullptr; } void SwFrame::ImplInvalidateNextPos( bool bNoFootnote ) { SwFrame *pFrame; if ( nullptr != (pFrame = _FindNext()) ) { if( pFrame->IsSctFrame() ) { while( pFrame && pFrame->IsSctFrame() ) { if( static_cast(pFrame)->GetSection() ) { SwFrame* pTmp = static_cast(pFrame)->ContainsAny(); if( pTmp ) pTmp->InvalidatePos(); else if( !bNoFootnote ) static_cast(pFrame)->InvalidateFootnotePos(); if( !IsInSct() || FindSctFrame()->GetFollow() != pFrame ) pFrame->InvalidatePos(); return; } pFrame = pFrame->FindNext(); } if( pFrame ) { if ( pFrame->IsSctFrame()) { // We need to invalidate the section's content so it gets // the chance to flow to a different page. SwFrame* pTmp = static_cast(pFrame)->ContainsAny(); if( pTmp ) pTmp->InvalidatePos(); if( !IsInSct() || FindSctFrame()->GetFollow() != pFrame ) pFrame->InvalidatePos(); } else pFrame->InvalidatePos(); } } else pFrame->InvalidatePos(); } } /** method to invalidate printing area of next frame OD 09.01.2004 #i11859# FME 2004-04-19 #i27145# Moved function from SwTextFrame to SwFrame */ void SwFrame::InvalidateNextPrtArea() { // determine next frame SwFrame* pNextFrame = FindNext(); // skip empty section frames and hidden text frames { while ( pNextFrame && ( ( pNextFrame->IsSctFrame() && !static_cast(pNextFrame)->GetSection() ) || ( pNextFrame->IsTextFrame() && static_cast(pNextFrame)->IsHiddenNow() ) ) ) { pNextFrame = pNextFrame->FindNext(); } } // Invalidate printing area of found next frame if ( pNextFrame ) { if ( pNextFrame->IsSctFrame() ) { // Invalidate printing area of found section frame, if // (1) this text frame isn't in a section OR // (2) found section frame isn't a follow of the section frame this // text frame is in. if ( !IsInSct() || FindSctFrame()->GetFollow() != pNextFrame ) { pNextFrame->InvalidatePrt(); } // Invalidate printing area of first content in found section. SwFrame* pFstContentOfSctFrame = static_cast(pNextFrame)->ContainsAny(); if ( pFstContentOfSctFrame ) { pFstContentOfSctFrame->InvalidatePrt(); } } else { pNextFrame->InvalidatePrt(); } } } /// @returns true if the frame _directly_ sits in a section with columns /// but not if it sits in a table which itself sits in a section with columns. static bool lcl_IsInColSct( const SwFrame *pUp ) { bool bRet = false; while( pUp ) { if( pUp->IsColumnFrame() ) bRet = true; else if( pUp->IsSctFrame() ) return bRet; else if( pUp->IsTabFrame() ) return false; pUp = pUp->GetUpper(); } return false; } /** determine, if frame is moveable in given environment OD 08.08.2003 #110978# method replaced 'old' method . Determines, if frame is moveable in given environment. if no environment is given (parameter _pLayoutFrame == 0L), the movability in the actual environment (GetUpper()) is checked. */ bool SwFrame::IsMoveable( const SwLayoutFrame* _pLayoutFrame ) const { bool bRetVal = false; if ( !_pLayoutFrame ) { _pLayoutFrame = GetUpper(); } if ( _pLayoutFrame && IsFlowFrame() ) { if ( _pLayoutFrame->IsInSct() && lcl_IsInColSct( _pLayoutFrame ) ) { bRetVal = true; } else if ( _pLayoutFrame->IsInFly() || _pLayoutFrame->IsInDocBody() || _pLayoutFrame->IsInFootnote() ) { if ( _pLayoutFrame->IsInTab() && !IsTabFrame() && ( !IsContentFrame() || !const_cast(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) ) { bRetVal = false; } else { if ( _pLayoutFrame->IsInFly() ) { // if fly frame has a follow (next linked fly frame), // frame is moveable. if ( const_cast(_pLayoutFrame)->FindFlyFrame()->GetNextLink() ) { bRetVal = true; } else { // if environment is columned, frame is moveable, if // it isn't in last column. // search for column frame const SwFrame* pCol = _pLayoutFrame; while ( pCol && !pCol->IsColumnFrame() ) { pCol = pCol->GetUpper(); } // frame is moveable, if found column frame isn't last one. if ( pCol && pCol->GetNext() ) { bRetVal = true; } } } else { bRetVal = true; } } } } return bRetVal; } void SwFrame::SetInfFlags() { if ( !IsFlyFrame() && !GetUpper() ) //not yet pasted, no information available return; mbInfInvalid = mbInfBody = mbInfTab = mbInfFly = mbInfFootnote = mbInfSct = false; SwFrame *pFrame = this; if( IsFootnoteContFrame() ) mbInfFootnote = true; do { // mbInfBody is only set in the page body, but not in the column body if ( pFrame->IsBodyFrame() && !mbInfFootnote && pFrame->GetUpper() && pFrame->GetUpper()->IsPageFrame() ) mbInfBody = true; else if ( pFrame->IsTabFrame() || pFrame->IsCellFrame() ) { mbInfTab = true; } else if ( pFrame->IsFlyFrame() ) mbInfFly = true; else if ( pFrame->IsSctFrame() ) mbInfSct = true; else if ( pFrame->IsFootnoteFrame() ) mbInfFootnote = true; pFrame = pFrame->GetUpper(); } while ( pFrame && !pFrame->IsPageFrame() ); //there is nothing above the page } /** Updates the vertical or the righttoleft-flags. * * If the property is derived, it's from the upper or (for fly frames) from * the anchor. Otherwise we've to call a virtual method to check the property. */ void SwFrame::SetDirFlags( bool bVert ) { if( bVert ) { // OD 2004-01-21 #114969# - if derived, valid vertical flag only if // vertical flag of upper/anchor is valid. if( mbDerivedVert ) { const SwFrame* pAsk = IsFlyFrame() ? static_cast(this)->GetAnchorFrame() : GetUpper(); OSL_ENSURE( pAsk != this, "Autsch! Stack overflow is about to happen" ); if( pAsk ) { mbVertical = pAsk->IsVertical(); mbReverse = pAsk->IsReverse(); mbVertLR = pAsk->IsVertLR(); if ( !pAsk->mbInvalidVert ) mbInvalidVert = false; } } else CheckDirection( bVert ); } else { bool bInv = false; if( !mbDerivedR2L ) // CheckDirection is able to set bDerivedR2L! CheckDirection( bVert ); if( mbDerivedR2L ) { const SwFrame* pAsk = IsFlyFrame() ? static_cast(this)->GetAnchorFrame() : GetUpper(); OSL_ENSURE( pAsk != this, "Oops! Stack overflow is about to happen" ); if( pAsk ) mbRightToLeft = pAsk->IsRightToLeft(); if( !pAsk || pAsk->mbInvalidR2L ) bInv = mbInvalidR2L; } mbInvalidR2L = bInv; } } SwLayoutFrame* SwFrame::GetNextCellLeaf( MakePageType ) { SwFrame* pTmpFrame = this; while (pTmpFrame && !pTmpFrame->IsCellFrame()) pTmpFrame = pTmpFrame->GetUpper(); SAL_WARN_IF(!pTmpFrame, "sw.core", "SwFrame::GetNextCellLeaf() without cell"); return pTmpFrame ? static_cast(pTmpFrame)->GetFollowCell() : nullptr; } SwLayoutFrame* SwFrame::GetPrevCellLeaf( MakePageType ) { SwFrame* pTmpFrame = this; while ( !pTmpFrame->IsCellFrame() ) pTmpFrame = pTmpFrame->GetUpper(); OSL_ENSURE( pTmpFrame, "SwFrame::GetNextPreviousLeaf() without cell" ); return static_cast(pTmpFrame)->GetPreviousCell(); } static SwCellFrame* lcl_FindCorrespondingCellFrame( const SwRowFrame& rOrigRow, const SwCellFrame& rOrigCell, const SwRowFrame& rCorrRow, bool bInFollow ) { SwCellFrame* pRet = nullptr; const SwCellFrame* pCell = static_cast(rOrigRow.Lower()); SwCellFrame* pCorrCell = const_cast(static_cast(rCorrRow.Lower())); while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) ) { pCell = static_cast(pCell->GetNext()); pCorrCell = static_cast(pCorrCell->GetNext()); } assert(pCell && pCorrCell && "lcl_FindCorrespondingCellFrame does not work"); if ( pCell != &rOrigCell ) { // rOrigCell must be a lower of pCell. We need to recurse into the rows: assert(pCell->Lower() && pCell->Lower()->IsRowFrame() && "lcl_FindCorrespondingCellFrame does not work"); const SwRowFrame* pRow = static_cast(pCell->Lower()); while ( !pRow->IsAnLower( &rOrigCell ) ) pRow = static_cast(pRow->GetNext()); SwRowFrame* pCorrRow = nullptr; if ( bInFollow ) pCorrRow = pRow->GetFollowRow(); else { SwRowFrame* pTmpRow = static_cast(pCorrCell->GetLastLower()); if ( pTmpRow && pTmpRow->GetFollowRow() == pRow ) pCorrRow = pTmpRow; } if ( pCorrRow ) pRet = lcl_FindCorrespondingCellFrame( *pRow, rOrigCell, *pCorrRow, bInFollow ); } else pRet = pCorrCell; return pRet; } // VERSION OF GetFollowCell() that assumes that we always have a follow flow line: SwCellFrame* SwCellFrame::GetFollowCell() const { SwCellFrame* pRet = nullptr; // NEW TABLES // Covered cells do not have follow cells! const long nRowSpan = GetLayoutRowSpan(); if ( nRowSpan < 1 ) return nullptr; // find most upper row frame const SwFrame* pRow = GetUpper(); while (pRow && (!pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame())) pRow = pRow->GetUpper(); if (!pRow) return nullptr; const SwTabFrame* pTabFrame = static_cast(pRow->GetUpper()); if (!pTabFrame || !pTabFrame->GetFollow() || !pTabFrame->HasFollowFlowLine()) return nullptr; const SwCellFrame* pThisCell = this; // Get last cell of the current table frame that belongs to the rowspan: if ( nRowSpan > 1 ) { // optimization: Will end of row span be in last row or exceed row? long nMax = 0; while ( pRow->GetNext() && ++nMax < nRowSpan ) pRow = pRow->GetNext(); if ( !pRow->GetNext() ) { pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false, true ); pRow = pThisCell->GetUpper(); } } const SwRowFrame* pFollowRow = nullptr; if ( !pRow->GetNext() && nullptr != ( pFollowRow = pRow->IsInSplitTableRow() ) && ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) ) pRet = lcl_FindCorrespondingCellFrame( *static_cast(pRow), *pThisCell, *pFollowRow, true ); return pRet; } // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL SwCellFrame* SwCellFrame::GetPreviousCell() const { SwCellFrame* pRet = nullptr; // NEW TABLES // Covered cells do not have previous cells! if ( GetLayoutRowSpan() < 1 ) return nullptr; // find most upper row frame const SwFrame* pRow = GetUpper(); while( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() ) pRow = pRow->GetUpper(); OSL_ENSURE( pRow->GetUpper() && pRow->GetUpper()->IsTabFrame(), "GetPreviousCell without Table" ); const SwTabFrame* pTab = static_cast(pRow->GetUpper()); if ( pTab->IsFollow() ) { const SwFrame* pTmp = pTab->GetFirstNonHeadlineRow(); const bool bIsInFirstLine = ( pTmp == pRow ); if ( bIsInFirstLine ) { SwTabFrame *pMaster = pTab->FindMaster(); if ( pMaster && pMaster->HasFollowFlowLine() ) { SwRowFrame* pMasterRow = static_cast(pMaster->GetLastLower()); if ( pMasterRow ) pRet = lcl_FindCorrespondingCellFrame( *static_cast(pRow), *this, *pMasterRow, false ); if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 ) pRet = &const_cast(pRet->FindStartEndOfRowSpanCell( true, true )); } } } return pRet; } // --> NEW TABLES const SwCellFrame& SwCellFrame::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const { const SwCellFrame* pRet = nullptr; const SwTabFrame* pTableFrame = dynamic_cast(GetUpper()->GetUpper()); if ( !bStart && pTableFrame && pTableFrame->IsFollow() && pTableFrame->IsInHeadline( *this ) ) return *this; OSL_ENSURE( pTableFrame && ( (bStart && GetTabBox()->getRowSpan() < 1) || (!bStart && GetLayoutRowSpan() > 1) ), "SwCellFrame::FindStartRowSpanCell: No rowspan, no table, no cookies" ); if ( pTableFrame ) { const SwTable* pTable = pTableFrame->GetTable(); sal_uInt16 nMax = USHRT_MAX; if ( bCurrentTableOnly ) { const SwFrame* pCurrentRow = GetUpper(); const bool bDoNotEnterHeadline = bStart && pTableFrame->IsFollow() && !pTableFrame->IsInHeadline( *pCurrentRow ); // check how many rows we are allowed to go up or down until we reach the end of // the current table frame: nMax = 0; while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() ) { if ( bStart ) { // do not enter a repeated headline: if ( bDoNotEnterHeadline && pTableFrame->IsFollow() && pTableFrame->IsInHeadline( *pCurrentRow->GetPrev() ) ) break; pCurrentRow = pCurrentRow->GetPrev(); } else pCurrentRow = pCurrentRow->GetNext(); ++nMax; } } // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly // is set) we assure that we find a rMasterBox that has a SwCellFrame in // the current table frame: const SwTableBox& rMasterBox = bStart ? GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) : GetTabBox()->FindEndOfRowSpan( *pTable, nMax ); SwIterator aIter( *rMasterBox.GetFrameFormat() ); for ( SwCellFrame* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() ) { if ( pMasterCell->GetTabBox() == &rMasterBox ) { const SwTabFrame* pMasterTable = static_cast(pMasterCell->GetUpper()->GetUpper()); if ( bCurrentTableOnly ) { if ( pMasterTable == pTableFrame ) { pRet = pMasterCell; break; } } else { if ( pMasterTable == pTableFrame || ( (bStart && pMasterTable->IsAnFollow(pTableFrame)) || (!bStart && pTableFrame->IsAnFollow(pMasterTable)) ) ) { pRet = pMasterCell; break; } } } } } assert(pRet && "SwCellFrame::FindStartRowSpanCell: No result"); return *pRet; } // <-- NEW TABLES const SwRowFrame* SwFrame::IsInSplitTableRow() const { OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" ); const SwFrame* pRow = this; // find most upper row frame while( pRow && ( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() ) ) pRow = pRow->GetUpper(); if ( !pRow ) return nullptr; OSL_ENSURE( pRow->GetUpper()->IsTabFrame(), "Confusion in table layout" ); const SwTabFrame* pTab = static_cast(pRow->GetUpper()); // If most upper row frame is a headline row, the current frame // can't be in a splitted table row. Thus, add corresponding condition. if ( pRow->GetNext() || pTab->GetTable()->IsHeadline( *(static_cast(pRow)->GetTabLine()) ) || !pTab->HasFollowFlowLine() || !pTab->GetFollow() ) return nullptr; // skip headline const SwRowFrame* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow(); OSL_ENSURE( pFollowRow, "SwFrame::IsInSplitTableRow() does not work" ); return pFollowRow; } const SwRowFrame* SwFrame::IsInFollowFlowRow() const { OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" ); // find most upper row frame const SwFrame* pRow = this; while( pRow && ( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() ) ) pRow = pRow->GetUpper(); if ( !pRow ) return nullptr; OSL_ENSURE( pRow->GetUpper()->IsTabFrame(), "Confusion in table layout" ); const SwTabFrame* pTab = static_cast(pRow->GetUpper()); const SwTabFrame* pMaster = pTab->IsFollow() ? pTab->FindMaster() : nullptr; if ( !pMaster || !pMaster->HasFollowFlowLine() ) return nullptr; const SwFrame* pTmp = pTab->GetFirstNonHeadlineRow(); const bool bIsInFirstLine = ( pTmp == pRow ); if ( !bIsInFirstLine ) return nullptr; const SwRowFrame* pMasterRow = static_cast(pMaster->GetLastLower()); return pMasterRow; } bool SwFrame::IsInBalancedSection() const { bool bRet = false; if ( IsInSct() ) { const SwSectionFrame* pSectionFrame = FindSctFrame(); if ( pSectionFrame ) bRet = pSectionFrame->IsBalancedSection(); } return bRet; } const SwFrame* SwLayoutFrame::GetLastLower() const { const SwFrame* pRet = Lower(); if ( !pRet ) return nullptr; while ( pRet->GetNext() ) pRet = pRet->GetNext(); return pRet; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */