/* -*- 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 .
*/
/// Searches the first ContentFrame in BodyText below the page.
SwLayoutFrame *SwFootnoteBossFrame::FindBodyCont()
{
SwFrame *pLay = Lower(); while ( pLay && !pLay->IsBodyFrame() )
pLay = pLay->GetNext(); returnstatic_cast<SwLayoutFrame*>(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;
}
auto pLastSection = static_cast<SwSectionFrame*>(pLast); if (!pLastSection->IsEndNoteSection())
{ return nullptr;
}
return pLastSection;
}
/** * 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.
/** * 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(); returnstatic_cast<const SwCellFrame*>(pCnt);
}
/** return ContentFrames, sections, and tables. * * @param _bInvestigateFootnoteForSections controls investigation of content of footnotes for sections. * @see ContainsContent
*/ const SwFrame *SwLayoutFrame::ContainsAny( constbool _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.
if( ( pLayLeaf->IsTabFrame() || pLayLeaf->IsSctFrame() )
&& pLayLeaf != this )
{ // Now we also return "deleted" SectionFrames so they can be // maintained on SaveContent and RestoreContent return pLayLeaf;
} elseif ( pLower ) returnstatic_cast<const SwContentFrame*>(pLower);
/** method to check relative position of layout frame to a given layout frame.
OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in <txtftn.cxx> for #104840#.
@param _aCheckRefLayFrame constant reference of an instance of class <SwLayoutFrame> which is used as the reference for the relative position check.
@return true, if <this> is positioned before the layout frame <p>
*/ 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 <pUp>, 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 <this> is a fly frm
bReturn = false;
} else
{ // travel through the next's of <pUp> and check if one of these // contain the check reference. const SwLayoutFrame* pUpNext = static_cast<const SwLayoutFrame*>(pUp->GetNext()); while ( pUpNext &&
!pUpNext->IsAnLower( _pCheckRefLayFrame ) )
{
pUpNext = static_cast<const SwLayoutFrame*>(pUpNext->GetNext());
}
bReturn = pUpNext != nullptr;
}
}
return bReturn;
}
// Local helper functions for GetNextLayoutLeaf
staticconst SwFrame* lcl_FindLayoutFrame( const SwFrame* pFrame, bool bNext )
{ const SwFrame* pRet = nullptr; if ( pFrame->IsFlyFrame() )
{ auto pFlyFrame = static_cast<const SwFlyFrame*>(pFrame); if (pFlyFrame->IsFlySplitAllowed())
{ // This is a flow frame, look up the follow/precede. auto pFlyAtContent = static_cast<const SwFlyAtContentFrame*>(pFlyFrame);
pRet = bNext ? pFlyAtContent->GetFollow() : pFlyAtContent->GetPrecede();
} else
{
pRet = bNext ? pFlyFrame->GetNextLink() : pFlyFrame->GetPrevLink();
}
} else
pRet = bNext ? pFrame->GetNext() : pFrame->GetPrev();
/** * 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 // The anchor is this frame, unless we traverse the anchor of a split fly. const SwFrame* pAnchor = this; do {
bool bGoingFwdOrBwd = false;
bool bGoingDown = !bGoingUp; if (bGoingDown)
{
p = lcl_GetLower( pFrame, bFwd );
bGoingDown = nullptr != p;
} 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:
p = lcl_FindLayoutFrame( pFrame, bFwd );
bGoingFwdOrBwd = nullptr != p; if ( !bGoingFwdOrBwd )
{ // I cannot go forward, because there is no next frame. // I'll try to go up:
p = pFrame->GetUpper();
if (!p && pFrame->IsFlyFrame())
{ const SwFlyFrame* pFlyFrame = pFrame->FindFlyFrame(); if (pFlyFrame->IsFlySplitAllowed())
{
p = const_cast<SwFlyFrame*>(pFlyFrame)->FindAnchorCharFrame(); // Remember the anchor frame, so if we look for the leaf of a frame in a // split fly (anchored in the master of a text frame, but rendered on the // next page), we won't return a frame on the next page, rather return // nullptr.
pAnchor = p;
}
}
bGoingUp = nullptr != p; 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;
/** * 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; if (bGoingDown)
{
p = lcl_GetLower( pFrame, true ) ;
bGoingDown = nullptr != p;
} if ( !bGoingDown )
{
p = lcl_FindLayoutFrame( pFrame, bFwd );
bGoingFwdOrBwd = nullptr != p; if ( !bGoingFwdOrBwd )
{
p = pFrame->GetUpper();
bGoingUp = nullptr != p; if ( !bGoingUp )
{ return nullptr;
}
}
}
bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
assert(p); if (!bFwd && bGoingDown)
{ while ( p->GetNext() )
p = p->GetNext();
}
SwPageFrame* SwFrame::ImplFindPageFrame()
{
SwFrame *pRet = this; while ( pRet )
{ if (pRet->IsInDtor()) return nullptr;
if (pRet->IsPageFrame()) break;
if ( pRet->GetUpper() )
pRet = pRet->GetUpper(); elseif ( pRet->IsFlyFrame() )
{ // #i28701# - use new method <GetPageFrame()> constauto pFly(static_cast<SwFlyFrame*>(pRet));
pRet = pFly->GetPageFrame(); if (pRet == nullptr)
pRet = pFly->AnchorFrame();
} else return nullptr;
} returnstatic_cast<SwPageFrame*>(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 (SwFrame *pTabFrame = pRet->IsInTab() ? pRet->FindTabFrame() : nullptr)
pRet = pTabFrame;
// tdf139336: put the footnotes into the page frame (instead of a column frame) // to avoid maximizing the section to the full page.... if: // - it is in a section // - collect footnotes at section end (FootnoteAtEnd) is not set // - columns are evenly distributed (=balanced) is not set // Note 1: at page end, the footnotes have no multi-column-capability, // so this fix is used only where there is better chance to help // Note 2: If balanced is not set, there is a higher chance that the 1. column will reach // the end of the page... if that happens the section will be maximized anyway. // Note 3: The user will be able to easily choose the old layout (with multi-column footnotes) // with this setting. // similar case can be reached with a page break + FootnoteAtEnd setting
SwSectionFrame* pSectframe = pRet->FindSctFrame(); bool bMoveToPageFrame = false; // tdf146704: only if it is really a footnote, not an endnote. // tdf54465: compatibility flag to make old odt files keep these full page sections. if (bFootnotes && pSectframe
&& pSectframe->GetFormat()->getIDocumentSettingAccess().get(
DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND))
{
SwSection* pSect = pSectframe->GetSection(); if (pSect) { bool bNoBalance = pSect->GetFormat()->GetBalancedColumns().GetValue(); bool bFAtEnd = pSectframe->IsFootnoteAtEnd();
bMoveToPageFrame = !bFAtEnd && !bNoBalance;
}
} while (pRet && !pRet->IsInDtor()
&& ((!bMoveToPageFrame && !pRet->IsFootnoteBossFrame())
|| (bMoveToPageFrame && !pRet->IsPageFrame())))
{ if ( pRet->GetUpper() )
pRet = pRet->GetUpper(); elseif ( pRet->IsFlyFrame() )
{ // #i28701# - use new method <GetPageFrame()> if ( static_cast<SwFlyFrame*>(pRet)->GetPageFrame() )
pRet = static_cast<SwFlyFrame*>(pRet)->GetPageFrame(); else
pRet = static_cast<SwFlyFrame*>(pRet)->AnchorFrame();
} else return nullptr;
} if( bFootnotes && pRet && pRet->IsColumnFrame() &&
!pRet->GetNext() && !pRet->GetPrev() )
{
SwSectionFrame* pSct = pRet->FindSctFrame();
assert(pSct && "FindFootnoteBossFrame: Single column outside section?"); if( !pSct->IsFootnoteAtEnd() ) return pSct->FindFootnoteBossFrame( true );
} returnstatic_cast<SwFootnoteBossFrame*>(pRet);
}
SwTabFrame* SwFrame::ImplFindTabFrame()
{
SwFrame *pRet = this; if (pRet->IsInDtor()) return nullptr; while ( !pRet->IsTabFrame() )
{
pRet = pRet->GetUpper(); if ( !pRet ) return nullptr; if (pRet->IsInDtor()) return nullptr;
} returnstatic_cast<SwTabFrame*>(pRet);
}
SwSectionFrame* SwFrame::ImplFindSctFrame()
{
SwFrame *pRet = this; if (pRet->IsInDtor()) return nullptr; while ( !pRet->IsSctFrame() )
{
pRet = pRet->GetUpper(); if ( !pRet ) return nullptr; if (pRet->IsInDtor()) return nullptr;
} returnstatic_cast<SwSectionFrame*>(pRet);
}
const SwBodyFrame* SwFrame::ImplFindBodyFrame() const
{ const SwFrame *pRet = this; while ( !pRet->IsBodyFrame() )
{
pRet = pRet->GetUpper(); if ( !pRet ) return nullptr;
} returnstatic_cast<const SwBodyFrame*>(pRet);
}
SwFootnoteFrame *SwFrame::ImplFindFootnoteFrame()
{
SwFrame *pRet = this; while ( !pRet->IsFootnoteFrame() )
{
pRet = pRet->GetUpper(); if ( !pRet ) return nullptr;
} returnstatic_cast<SwFootnoteFrame*>(pRet);
}
SwFlyFrame *SwFrame::ImplFindFlyFrame()
{
SwFrame *pRet = this; do
{ if ( pRet->IsFlyFrame() ) returnstatic_cast<SwFlyFrame*>(pRet); else
pRet = pRet->GetUpper();
} while ( pRet ); return nullptr;
}
if (pPage &&
rPt.X() >= pPage->getFrameArea().Left() &&
rPt.X() <= pPage->getFrameArea().Right())
{ // Trivial case when we're right in between. if (!pPage->getFrameArea().Contains(rPt)) returntrue;
// 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())
{
constexpr SwTwips constMargin = o3tl::convert(tools::Long(2), o3tl::Length::mm, o3tl::Length::twip);
// If we are really close to the bottom or top of a page. constauto toEdge = std::min(std::abs(pPage->getFrameArea().Top() - rPt.Y()),
std::abs(pPage->getFrameArea().Bottom() - rPt.Y())); return toEdge <= constMargin;
}
}
/* * 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;
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<SwTabFrame*>(this)->GetFollow() ) returnstatic_cast<SwTabFrame*>(this)->GetFollow();
pThis = static_cast<SwTabFrame*>(this)->FindLastContentOrTable(); if ( !pThis )
pThis = this;
bIgnoreTab = true;
} elseif ( IsSctFrame() )
{ //The last Content of the section gets picked and his follower is returned. if ( static_cast<SwSectionFrame*>(this)->GetFollow() ) returnstatic_cast<SwSectionFrame*>(this)->GetFollow();
if ( pThis->IsContentFrame() )
{ constbool bBody = pThis->IsInDocBody(); constbool bFootnote = pThis->IsInFootnote();
SwContentFrame *pNxtCnt = static_cast<SwContentFrame*>(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# elseif ( bFootnote && _bInSameFootnote )
{ // handling for environments 'each footnote': // Assure that found next content frame belongs to the same footnotes const SwFootnoteFrame* pFootnoteFrameOfNext( pNxtCnt->FindFootnoteFrame() );
SwFootnoteFrame* pFootnoteFrameOfCurr(pThis->FindFootnoteFrame());
OSL_ENSURE( pFootnoteFrameOfCurr, " ); if ( pFootnoteFrameOfNext == pFootnoteFrameOfCurr )
{ return pNxtCnt;
} elseif ( pFootnoteFrameOfCurr->GetFollow() )
{ // next content frame has to be the first content frame // in the follow footnote, which contains a content frame.
SwFootnoteFrame* pFollowFootnoteFrameOfCurr(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;
}
} elseif ( 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_()
{ if ( !IsFlowFrame() )
{ // nothing to do, if current frame isn't a flow frame. return nullptr;
}
SwContentFrame* pPrevContentFrame( nullptr );
// Because method <SwContentFrame::GetPrevContentFrame()> is used to travel // through the layout, a content frame, at which the travel starts, is needed.
SwContentFrame* pCurrContentFrame = dynamic_cast<SwContentFrame*>(this);
// perform shortcut, if current frame is a follow, and // determine <pCurrContentFrame>, if current frame is a table or section frame if ( pCurrContentFrame && pCurrContentFrame->IsFollow() )
{ // previous content frame is its master content frame
pPrevContentFrame = pCurrContentFrame->FindMaster();
} elseif ( IsTabFrame() )
{
SwTabFrame* pTabFrame( static_cast<SwTabFrame*>(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();
}
} elseif ( IsSctFrame() )
{
SwSectionFrame* pSectFrame( static_cast<SwSectionFrame*>(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, <pPrevContentFrame> is the one
} else
{ constbool bInDocBody = pCurrContentFrame->IsInDocBody(); constbool bInFootnote = pCurrContentFrame->IsInFootnote(); if ( bInDocBody )
{ // 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();
}
} elseif ( bInFootnote )
{ // handling for environments 'each footnote': // Assure that found next content frame belongs to the same footnotes const SwFootnoteFrame* pFootnoteFrameOfPrev( pPrevContentFrame->FindFootnoteFrame() );
SwFootnoteFrame* pFootnoteFrameOfCurr(pCurrContentFrame->FindFootnoteFrame()); if ( pFootnoteFrameOfPrev != pFootnoteFrameOfCurr )
{ if ( pFootnoteFrameOfCurr->GetMaster() )
{
SwFootnoteFrame* pMasterFootnoteFrameOfCurr(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 <pCurrContentFrame> // Note: At this point it's clear that <pCurrContentFrame> has // to be inside a page header or page footer and that // neither <pCurrContentFrame> nor <pPrevContentFrame> are // inside a fly frame. // Thus, method <FindFooterOrHeader()> 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;
}
}
}
}
}
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<SwTabFrame*>(this)->IsFollow() ) returnstatic_cast<SwTabFrame*>(this)->FindMaster(); else
pThis = static_cast<SwTabFrame*>(this)->ContainsContent();
bIgnoreTab = true;
}
if ( pThis && pThis->IsContentFrame() )
{
SwContentFrame *pPrvCnt = static_cast<SwContentFrame*>(pThis)->GetPrevContentFrame(); if( !pPrvCnt ) return nullptr; if ( !bIgnoreTab && pThis->IsInTab() )
{
SwLayoutFrame *pUp = pThis->GetUpper(); while (pUp && !pUp->IsCellFrame())
pUp = pUp->GetUpper();
assert(pUp && "Content flag says it's in table but it's not in cell."); if (pUp && pUp->IsAnLower(pPrvCnt)) return pPrvCnt;
} else
{
SwFrame* pRet; constbool bBody = pThis->IsInDocBody(); constbool bFootnote = !bBody && pThis->IsInFootnote(); if ( bBody || bFootnote )
{ while ( pPrvCnt )
{ if ( (bBody && pPrvCnt->IsInDocBody()) ||
(bFootnote && pPrvCnt->IsInFootnote()) )
{
pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame()
: static_cast<SwFrame*>(pPrvCnt); return pRet;
}
pPrvCnt = pPrvCnt->GetPrevContentFrame();
}
} elseif ( pThis->IsInFly() )
{
pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame()
: static_cast<SwFrame*>(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<SwFrame*>(pPrvCnt); return pRet;
}
}
}
} return nullptr;
}
if( pFrame->IsSctFrame() )
{ while( pFrame && pFrame->IsSctFrame() )
{ if( static_cast<SwSectionFrame*>(pFrame)->GetSection() )
{
SwFrame* pTmp = static_cast<SwSectionFrame*>(pFrame)->ContainsAny(); if( pTmp )
pTmp->InvalidatePos(); elseif( !bNoFootnote ) static_cast<SwSectionFrame*>(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<SwSectionFrame*>(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->IsHiddenNow())
{
pNextFrame = pNextFrame->FindNext();
}
}
// Invalidate printing area of found next frame if ( !pNextFrame ) return;
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<SwSectionFrame*>(pNextFrame)->ContainsAny(); if ( pFstContentOfSctFrame )
{
pFstContentOfSctFrame->InvalidatePrt();
}
} else
{
pNextFrame->InvalidatePrt();
}
}
/// @returns true if the frame _directly_ sits in a section /// but not if it sits in a table which itself sits in a section. staticbool lcl_IsInSectionDirectly( const SwFrame *pUp )
{ bool bSeenColumn = false;
while( pUp )
{ if( pUp->IsColumnFrame() )
bSeenColumn = true; elseif( pUp->IsSctFrame() )
{ auto pSection = static_cast<const SwSectionFrame*>(pUp); const SwFrame* pHeaderFooter = pSection->FindFooterOrHeader(); // When the section frame is not in header/footer: // Allow move of frame in case our only column is not growable. // Also allow if there is a previous section frame (to move back). bool bAllowOutsideHeaderFooter = !pSection->Growable() || pSection->GetPrecede(); return bSeenColumn || (!pHeaderFooter && bAllowOutsideHeaderFooter);
} elseif( pUp->IsTabFrame() ) returnfalse;
pUp = pUp->GetUpper();
} returnfalse;
}
/** determine, if frame is moveable in given environment
OD 08.08.2003 #110978# method replaced 'old' method <sal_Bool IsMoveable() const>. Determines, if frame is moveable in given environment. if no environment is given (parameter _pLayoutFrame == 0), 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_IsInSectionDirectly( _pLayoutFrame ) )
{
bRetVal = true;
} elseif ( _pLayoutFrame->IsInFly() ||
_pLayoutFrame->IsInDocBody() ||
_pLayoutFrame->IsInFootnote() )
{ // If IsMovable() is called before a MoveFwd() the method // may return false if there is no NextCellLeaf. If // IsMovable() is called before a MoveBwd() the method may // return false if there is no PrevCellLeaf. if ( _pLayoutFrame->IsInTab() && !IsTabFrame() &&
( !IsContentFrame() || (!const_cast<SwFrame*>(this)->GetNextCellLeaf()
&& !const_cast<SwFrame*>(this)->GetPrevCellLeaf()) )
)
{
bRetVal = false;
} else
{ if ( _pLayoutFrame->IsInFly() )
{ // if fly frame has a follow (next linked fly frame) or can split, // frame is moveable. const SwFlyFrame* pFlyFrame = _pLayoutFrame->FindFlyFrame(); if ( pFlyFrame->GetNextLink() || pFlyFrame->IsFlySplitAllowed() )
{
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;
}
}
} elseif (!(_pLayoutFrame->IsInFootnote() && (IsTabFrame() || IsInTab())))
{
bRetVal = true;
}
}
}
}
return bRetVal;
}
void SwFrame::SetInfFlags()
{ if ( !IsFlyFrame() && !GetUpper() ) //not yet pasted, no information available return;
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; elseif ( pFrame->IsTabFrame() || pFrame->IsCellFrame() )
{
mbInfTab = true;
} elseif ( pFrame->IsFlyFrame() )
mbInfFly = true; elseif ( pFrame->IsSctFrame() )
mbInfSct = true; elseif ( 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<SwFlyFrame*>(this)->GetAnchorFrame() : GetUpper();
OSL_ENSURE( pAsk != this, "Autsch! Stack overflow is about to happen" );
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: const SwFrame* pLower = pCell->Lower();
assert(pLower && pLower->IsRowFrame() && "lcl_FindCorrespondingCellFrame does not work");
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 tools::Long nRowSpan = GetLayoutRowSpan(); if ( nRowSpan < 1 ) return nullptr;
// 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?
tools::Long nMax = 0; while ( pRow->GetNext() && ++nMax < nRowSpan )
pRow = pRow->GetNext();
// 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;
// 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;
// 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 );
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.67Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.