blob: 2414e4e913fb8fb75a5c27435345f20e32e6cadc [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include "pagefrm.hxx"
#include "rootfrm.hxx"
#include "cntfrm.hxx"
#include "node.hxx"
#include "doc.hxx"
#include "frmtool.hxx"
#include "flyfrm.hxx"
#include <frmfmt.hxx>
#include <cellfrm.hxx>
#include <rowfrm.hxx>
#include <swtable.hxx>
#include "tabfrm.hxx"
#include "sectfrm.hxx"
#include "flyfrms.hxx"
#include "ftnfrm.hxx"
#include "txtftn.hxx"
#include "fmtftn.hxx"
#include <txtfrm.hxx> // SwTxtFrm
#include <switerator.hxx>
/*************************************************************************
|*
|* FindBodyCont, FindLastBodyCntnt()
|*
|* Beschreibung Sucht den ersten/letzten CntntFrm im BodyText unterhalb
|* der Seite.
|* Ersterstellung MA 15. Feb. 93
|* Letzte Aenderung MA 18. Apr. 94
|*
|*************************************************************************/
SwLayoutFrm *SwFtnBossFrm::FindBodyCont()
{
SwFrm *pLay = Lower();
while ( pLay && !pLay->IsBodyFrm() )
pLay = pLay->GetNext();
return (SwLayoutFrm*)pLay;
}
SwCntntFrm *SwPageFrm::FindLastBodyCntnt()
{
SwCntntFrm *pRet = FindFirstBodyCntnt();
SwCntntFrm *pNxt = pRet;
while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) )
{ pRet = pNxt;
pNxt = pNxt->FindNextCnt();
}
return pRet;
}
/*************************************************************************
|*
|* SwLayoutFrm::ContainsCntnt
|*
|* Beschreibung Prueft, ob der Frame irgendwo in seiner
|* untergeordneten Struktur einen oder mehrere CntntFrm's enthaelt;
|* Falls ja wird der erste gefundene CntntFrm zurueckgegeben.
|*
|* Ersterstellung MA 13. May. 92
|* Letzte Aenderung MA 20. Apr. 94
|*
|*************************************************************************/
const SwCntntFrm *SwLayoutFrm::ContainsCntnt() const
{
//LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
//solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
//this verlassen wird.
//Sections: Cntnt neben Sections wuerde so nicht gefunden (leere Section
//direct neben CntntFrm), deshalb muss fuer diese Aufwendiger rekursiv gesucht
//werden.
const SwLayoutFrm *pLayLeaf = this;
do
{
while ( (!pLayLeaf->IsSctFrm() || pLayLeaf == this ) &&
pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
if( pLayLeaf->IsSctFrm() && pLayLeaf != this )
{
const SwCntntFrm *pCnt = pLayLeaf->ContainsCntnt();
if( pCnt )
return pCnt;
if( pLayLeaf->GetNext() )
{
if( pLayLeaf->GetNext()->IsLayoutFrm() )
{
pLayLeaf = (SwLayoutFrm*)pLayLeaf->GetNext();
continue;
}
else
return (SwCntntFrm*)pLayLeaf->GetNext();
}
}
else if ( pLayLeaf->Lower() )
return (SwCntntFrm*)pLayLeaf->Lower();
pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
if( !IsAnLower( pLayLeaf) )
return 0;
} while( pLayLeaf );
return 0;
}
/*************************************************************************
|*
|* SwLayoutFrm::FirstCell
|*
|* Beschreibung ruft zunaechst ContainsAny auf, um in die innerste Zelle
|* hineinzukommen. Dort hangelt es sich wieder hoch zum
|* ersten SwCellFrm, seit es SectionFrms gibt, reicht kein
|* ContainsCntnt()->GetUpper() mehr...
|* Ersterstellung AMA 17. Mar. 99
|* Letzte Aenderung AMA 17. Mar. 99
|*
|*************************************************************************/
const SwCellFrm *SwLayoutFrm::FirstCell() const
{
const SwFrm* pCnt = ContainsAny();
while( pCnt && !pCnt->IsCellFrm() )
pCnt = pCnt->GetUpper();
return (const SwCellFrm*)pCnt;
}
/*************************************************************************
|*
|* SwLayoutFrm::ContainsAny
|*
|* Beschreibung wie ContainsCntnt, nur dass nicht nur CntntFrms, sondern auch
|* Bereiche und Tabellen zurueckgegeben werden.
|* Ersterstellung AMA 10. Mar. 99
|* Letzte Aenderung AMA 10. Mar. 99
|*
|*************************************************************************/
// --> OD 2006-02-01 #130797#
// New parameter <_bInvestigateFtnForSections> controls investigation of
// content of footnotes for sections.
const SwFrm *SwLayoutFrm::ContainsAny( const bool _bInvestigateFtnForSections ) const
{
//LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
//solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
//this verlassen wird.
// Oder bis wir einen SectionFrm oder TabFrm gefunden haben
const SwLayoutFrm *pLayLeaf = this;
// --> OD 2006-02-01 #130797#
const bool bNoFtn = IsSctFrm() && !_bInvestigateFtnForSections;
// <--
do
{
while ( ( (!pLayLeaf->IsSctFrm() && !pLayLeaf->IsTabFrm())
|| pLayLeaf == this ) &&
pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
if( ( pLayLeaf->IsTabFrm() || pLayLeaf->IsSctFrm() )
&& pLayLeaf != this )
{
// Wir liefern jetzt auch "geloeschte" SectionFrms zurueck,
// damit diese beim SaveCntnt und RestoreCntnt mitgepflegt werden.
return pLayLeaf;
}
else if ( pLayLeaf->Lower() )
return (SwCntntFrm*)pLayLeaf->Lower();
pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
if( bNoFtn && pLayLeaf && pLayLeaf->IsInFtn() )
{
do
{
pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
} while( pLayLeaf && pLayLeaf->IsInFtn() );
}
if( !IsAnLower( pLayLeaf) )
return 0;
} while( pLayLeaf );
return 0;
}
/*************************************************************************
|*
|* SwFrm::GetLower()
|*
|* Ersterstellung MA 27. Jul. 92
|* Letzte Aenderung MA 09. Oct. 97
|*
|*************************************************************************/
const SwFrm* SwFrm::GetLower() const
{
return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
}
SwFrm* SwFrm::GetLower()
{
return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
}
/*************************************************************************
|*
|* SwLayoutFrm::IsAnLower()
|*
|* Ersterstellung MA 18. Mar. 93
|* Letzte Aenderung MA 18. Mar. 93
|*
|*************************************************************************/
sal_Bool SwLayoutFrm::IsAnLower( const SwFrm *pAssumed ) const
{
const SwFrm *pUp = pAssumed;
while ( pUp )
{
if ( pUp == this )
return sal_True;
if ( pUp->IsFlyFrm() )
pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
else
pUp = pUp->GetUpper();
}
return sal_False;
}
/** 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 _aCheckRefLayFrm
constant reference of an instance of class <SwLayoutFrm> which
is used as the reference for the relative position check.
@author OD
@return true, if <this> is positioned before the layout frame <p>
*/
bool SwLayoutFrm::IsBefore( const SwLayoutFrm* _pCheckRefLayFrm ) const
{
ASSERT( !IsRootFrm() , "<IsBefore> called at a <SwRootFrm>.");
ASSERT( !_pCheckRefLayFrm->IsRootFrm() , "<IsBefore> called with a <SwRootFrm>.");
bool bReturn;
// check, if on different pages
const SwPageFrm *pMyPage = FindPageFrm();
const SwPageFrm *pCheckRefPage = _pCheckRefLayFrm->FindPageFrm();
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 SwLayoutFrm* pUp = this;
while ( pUp->GetUpper() &&
!pUp->GetUpper()->IsAnLower( _pCheckRefLayFrm )
)
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.
SwLayoutFrm* pUpNext = (SwLayoutFrm*)pUp->GetNext();
while ( pUpNext &&
!pUpNext->IsAnLower( _pCheckRefLayFrm ) )
{
pUpNext = (SwLayoutFrm*)pUpNext->GetNext();
}
bReturn = pUpNext != 0;
}
}
return bReturn;
}
//
// Local helper functions for GetNextLayoutLeaf
//
const SwFrm* lcl_FindLayoutFrame( const SwFrm* pFrm, bool bNext )
{
const SwFrm* pRet = 0;
if ( pFrm->IsFlyFrm() )
pRet = bNext ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink();
else
pRet = bNext ? pFrm->GetNext() : pFrm->GetPrev();
return pRet;
}
const SwFrm* lcl_GetLower( const SwFrm* pFrm, bool bFwd )
{
if ( !pFrm->IsLayoutFrm() )
return 0;
return bFwd ?
static_cast<const SwLayoutFrm*>(pFrm)->Lower() :
static_cast<const SwLayoutFrm*>(pFrm)->GetLastLower();
}
/*************************************************************************
|*
|* SwFrm::ImplGetNextLayoutLeaf
|*
|* 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 TabFrm
*
|*************************************************************************/
const SwLayoutFrm *SwFrm::ImplGetNextLayoutLeaf( bool bFwd ) const
{
const SwFrm *pFrm = this;
const SwLayoutFrm *pLayoutFrm = 0;
const SwFrm *p = 0;
bool bGoingUp = !bFwd; // false for forward, true for backward
do {
bool bGoingFwdOrBwd = false, bGoingDown = false;
bGoingDown = ( !bGoingUp && ( 0 != (p = lcl_GetLower( pFrm, 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 = (0 != (p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
if ( !bGoingFwdOrBwd )
{
// I cannot go forward, because there is no next frame.
// I'll try to go up:
bGoingUp = (0 != (p = pFrm->GetUpper() ) );
if ( !bGoingUp )
{
// I cannot go up, because there is no upper frame.
return 0;
}
}
}
// If I could not go down or forward, I'll have to go up
bGoingUp = !bGoingFwdOrBwd && !bGoingDown;
pFrm = p;
p = lcl_GetLower( pFrm, true );
} while( ( p && !p->IsFlowFrm() ) ||
pFrm == this ||
0 == ( pLayoutFrm = pFrm->IsLayoutFrm() ? (SwLayoutFrm*)pFrm : 0 ) ||
pLayoutFrm->IsAnLower( this ) );
return pLayoutFrm;
}
/*************************************************************************
|*
|* SwFrm::ImplGetNextCntntFrm( bool )
|*
|* Rueckwaertswandern im Baum: Den untergeordneten Frm greifen,
|* wenn es einen gibt und nicht gerade zuvor um eine Ebene
|* aufgestiegen wurde (das wuerde zu einem endlosen Auf und Ab
|* fuehren!). Damit wird sichergestellt, dass beim
|* Rueckwaertswandern alle Unterbaeume durchsucht werden. Wenn
|* abgestiegen wurde, wird zuerst an das Ende der Kette gegangen,
|* weil im weiteren ja vom letzten Frm innerhalb eines anderen
|* Frms rueckwaerts gegangen wird.
|* Vorwaetzwander funktioniert analog.
|*
|* Ersterstellung ??
|* Letzte Aenderung MA 30. Oct. 97
|*
|*************************************************************************/
// Achtung: Fixes in ImplGetNextCntntFrm() muessen moeglicherweise auch in
// die weiter oben stehende Methode lcl_NextFrm(..) eingepflegt werden
const SwCntntFrm* SwCntntFrm::ImplGetNextCntntFrm( bool bFwd ) const
{
const SwFrm *pFrm = this;
// #100926#
SwCntntFrm *pCntntFrm = 0;
sal_Bool bGoingUp = sal_False;
do {
const SwFrm *p = 0;
sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;
bGoingDown = ( !bGoingUp && ( 0 != ( p = lcl_GetLower( pFrm, true ) ) ) );
if ( !bGoingDown )
{
bGoingFwdOrBwd = ( 0 != ( p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
if ( !bGoingFwdOrBwd )
{
bGoingUp = ( 0 != ( p = pFrm->GetUpper() ) );
if ( !bGoingUp )
{
return 0;
}
}
}
bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
if ( !bFwd )
{
if( bGoingDown && p )
while ( p->GetNext() )
p = p->GetNext();
}
pFrm = p;
} while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
return pCntntFrm;
}
/*************************************************************************
|*
|* SwFrm::FindRootFrm(), FindTabFrm(), FindFtnFrm(), FindFlyFrm(),
|* FindPageFrm(), FindColFrm()
|*
|* Ersterstellung ??
|* Letzte Aenderung MA 05. Sep. 93
|*
|*************************************************************************/
SwPageFrm* SwFrm::FindPageFrm()
{
SwFrm *pRet = this;
while ( pRet && !pRet->IsPageFrm() )
{
if ( pRet->GetUpper() )
pRet = pRet->GetUpper();
else if ( pRet->IsFlyFrm() )
{
// --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
else
pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
}
else
return 0;
}
return (SwPageFrm*)pRet;
}
SwFtnBossFrm* SwFrm::FindFtnBossFrm( sal_Bool bFootnotes )
{
SwFrm *pRet = this;
// Innerhalb einer Tabelle gibt es keine Fussnotenbosse, auch spaltige
// Bereiche enthalten dort keine Fussnotentexte
if( pRet->IsInTab() )
pRet = pRet->FindTabFrm();
while ( pRet && !pRet->IsFtnBossFrm() )
{
if ( pRet->GetUpper() )
pRet = pRet->GetUpper();
else if ( pRet->IsFlyFrm() )
{
// --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
else
pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
}
else
return 0;
}
if( bFootnotes && pRet && pRet->IsColumnFrm() &&
!pRet->GetNext() && !pRet->GetPrev() )
{
SwSectionFrm* pSct = pRet->FindSctFrm();
ASSERT( pSct, "FindFtnBossFrm: Single column outside section?" );
if( !pSct->IsFtnAtEnd() )
return pSct->FindFtnBossFrm( sal_True );
}
return (SwFtnBossFrm*)pRet;
}
SwTabFrm* SwFrm::ImplFindTabFrm()
{
SwFrm *pRet = this;
while ( !pRet->IsTabFrm() )
{
pRet = pRet->GetUpper();
if ( !pRet )
return 0;
}
return (SwTabFrm*)pRet;
}
SwSectionFrm* SwFrm::ImplFindSctFrm()
{
SwFrm *pRet = this;
while ( !pRet->IsSctFrm() )
{
pRet = pRet->GetUpper();
if ( !pRet )
return 0;
}
return (SwSectionFrm*)pRet;
}
SwFtnFrm *SwFrm::ImplFindFtnFrm()
{
SwFrm *pRet = this;
while ( !pRet->IsFtnFrm() )
{
pRet = pRet->GetUpper();
if ( !pRet )
return 0;
}
return (SwFtnFrm*)pRet;
}
SwFlyFrm *SwFrm::ImplFindFlyFrm()
{
const SwFrm *pRet = this;
do
{
if ( pRet->IsFlyFrm() )
return (SwFlyFrm*)pRet;
else
pRet = pRet->GetUpper();
} while ( pRet );
return 0;
}
SwFrm *SwFrm::FindColFrm()
{
SwFrm *pFrm = this;
do
{ pFrm = pFrm->GetUpper();
} while ( pFrm && !pFrm->IsColumnFrm() );
return pFrm;
}
SwFrm* SwFrm::FindFooterOrHeader()
{
SwFrm* pRet = this;
do
{ if ( pRet->GetType() & 0x0018 ) //Header und Footer
return pRet;
else if ( pRet->GetUpper() )
pRet = pRet->GetUpper();
else if ( pRet->IsFlyFrm() )
pRet = ((SwFlyFrm*)pRet)->AnchorFrm();
else
return 0;
} while ( pRet );
return pRet;
}
const SwFtnFrm* SwFtnContFrm::FindFootNote() const
{
const SwFtnFrm* pRet = (SwFtnFrm*)Lower();
if( pRet && !pRet->GetAttr()->GetFtn().IsEndNote() )
return pRet;
return NULL;
}
const SwPageFrm* SwRootFrm::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const
{
const SwPageFrm* pRet = 0;
SwRect aRect;
if ( pSize )
{
aRect.Pos() = rPt;
aRect.SSize() = *pSize;
}
const SwFrm* pPage = Lower();
if ( !bExtend )
{
if( !Frm().IsInside( rPt ) )
return 0;
// skip pages above point:
while( pPage && rPt.Y() > pPage->Frm().Bottom() )
pPage = pPage->GetNext();
}
ASSERT( GetPageNum() <= maPageRects.size(), "number of pages differes from page rect array size" )
sal_uInt16 nPageIdx = 0;
while ( pPage && !pRet )
{
const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->Frm();
if ( (!pSize && rBoundRect.IsInside(rPt)) ||
(pSize && rBoundRect.IsOver(aRect)) )
{
pRet = static_cast<const SwPageFrm*>(pPage);
}
pPage = pPage->GetNext();
}
return pRet;
}
/*************************************************************************
|*
|* SwFrmFrm::GetAttrSet()
|*
|* Ersterstellung MA 02. Aug. 93
|* Letzte Aenderung MA 02. Aug. 93
|*
|*************************************************************************/
const SwAttrSet* SwFrm::GetAttrSet() const
{
if ( IsCntntFrm() )
return &((const SwCntntFrm*)this)->GetNode()->GetSwAttrSet();
else
return &((const SwLayoutFrm*)this)->GetFmt()->GetAttrSet();
}
/*************************************************************************
|*
|* SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos()
|* _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert
|* nur SwCntntFrms.
|*
|* Beschreibung Invalidiert die Position des Naechsten Frames.
|* Dies ist der direkte Nachfolger, oder bei CntntFrm's der naechste
|* CntntFrm der im gleichen Fluss liegt wie ich:
|* - Body,
|* - Fussnoten,
|* - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des
|* Bereiches weiterzuleiten.
|* - dito fuer Flys.
|* - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle
|* auf.
|* - Tabellen verhalten sich prinzipiell analog zu den Cntnts
|* - Bereiche ebenfalls
|* Ersterstellung AK 14-Feb-1991
|* Letzte Aenderung AMA 10. Mar. 99
|*
|*************************************************************************/
// Diese Hilfsfunktion ist ein Aequivalent zur ImplGetNextCntntFrm()-Methode,
// sie liefert allerdings neben ContentFrames auch TabFrms und SectionFrms.
SwFrm* lcl_NextFrm( SwFrm* pFrm )
{
SwFrm *pRet = 0;
sal_Bool bGoingUp = sal_False;
do {
SwFrm *p = 0;
sal_Bool bGoingFwd = sal_False;
sal_Bool bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0)));
if( !bGoingDown )
{
bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext())));
if ( !bGoingFwd )
{
bGoingUp = (0 != (p = pFrm->GetUpper()));
if ( !bGoingUp )
{
return 0;
}
}
}
bGoingUp = !(bGoingFwd || bGoingDown);
pFrm = p;
} while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp &&
( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) );
return pRet;
}
SwFrm *SwFrm::_FindNext()
{
sal_Bool bIgnoreTab = sal_False;
SwFrm *pThis = this;
if ( IsTabFrm() )
{
//Der letzte Cntnt der Tabelle wird
//gegriffen und dessen Nachfolger geliefert. Um die Spezialbeh.
//Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
if ( ((SwTabFrm*)this)->GetFollow() )
return ((SwTabFrm*)this)->GetFollow();
pThis = ((SwTabFrm*)this)->FindLastCntnt();
if ( !pThis )
pThis = this;
bIgnoreTab = sal_True;
}
else if ( IsSctFrm() )
{
//Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger
// geliefert.
if ( ((SwSectionFrm*)this)->GetFollow() )
return ((SwSectionFrm*)this)->GetFollow();
pThis = ((SwSectionFrm*)this)->FindLastCntnt();
if ( !pThis )
pThis = this;
}
else if ( IsCntntFrm() )
{
if( ((SwCntntFrm*)this)->GetFollow() )
return ((SwCntntFrm*)this)->GetFollow();
}
else if ( IsRowFrm() )
{
SwFrm* pMyUpper = GetUpper();
if ( pMyUpper->IsTabFrm() && ((SwTabFrm*)pMyUpper)->GetFollow() )
return ((SwTabFrm*)pMyUpper)->GetFollow()->GetLower();
else return NULL;
}
else
return NULL;
SwFrm* pRet = NULL;
const sal_Bool bFtn = pThis->IsInFtn();
if ( !bIgnoreTab && pThis->IsInTab() )
{
SwLayoutFrm *pUp = pThis->GetUpper();
while ( !pUp->IsCellFrm() )
pUp = pUp->GetUpper();
ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
SwFrm* pNxt = ((SwCellFrm*)pUp)->GetFollowCell();
if ( pNxt )
pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt();
if ( !pNxt )
{
pNxt = lcl_NextFrm( pThis );
if ( pUp->IsAnLower( pNxt ) )
pRet = pNxt;
}
else
pRet = pNxt;
}
else
{
const sal_Bool bBody = pThis->IsInDocBody();
SwFrm *pNxtCnt = lcl_NextFrm( pThis );
if ( pNxtCnt )
{
if ( bBody || bFtn )
{
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() && !IsSctFrm() &&
( !pNxtCnt->IsInSct() ||
!pNxtCnt->FindSctFrm()->IsEndnAtEnd()
);
if ( ( bBody && pNxtCnt->IsInDocBody() ) ||
( pNxtCnt->IsInFtn() &&
( bFtn ||
( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
)
)
)
{
pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
: (SwFrm*)pNxtCnt;
break;
}
pNxtCnt = lcl_NextFrm( pNxtCnt );
}
}
else if ( pThis->IsInFly() )
{
pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
: (SwFrm*)pNxtCnt;
}
else //Fuss-/oder Kopfbereich
{
const SwFrm *pUp = pThis->GetUpper();
const SwFrm *pCntUp = pNxtCnt->GetUpper();
while ( pUp && pUp->GetUpper() &&
!pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
pUp = pUp->GetUpper();
while ( pCntUp && pCntUp->GetUpper() &&
!pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
pCntUp = pCntUp->GetUpper();
if ( pCntUp == pUp )
{
pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
: (SwFrm*)pNxtCnt;
}
}
}
}
if( pRet && pRet->IsInSct() )
{
SwSectionFrm* pSct = pRet->FindSctFrm();
//Fussnoten in spaltigen Rahmen duerfen nicht den Bereich
//liefern, der die Fussnoten umfasst
if( !pSct->IsAnLower( this ) &&
(!bFtn || pSct->IsInFtn() ) )
return pSct;
}
return pRet;
}
// --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn )
{
SwFrm *pThis = this;
if ( IsTabFrm() )
{
if ( ((SwTabFrm*)this)->GetFollow() )
{
pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt();
if( pThis )
return (SwCntntFrm*)pThis;
}
pThis = ((SwTabFrm*)this)->FindLastCntnt();
if ( !pThis )
return 0;
}
else if ( IsSctFrm() )
{
if ( ((SwSectionFrm*)this)->GetFollow() )
{
pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
if( pThis )
return (SwCntntFrm*)pThis;
}
pThis = ((SwSectionFrm*)this)->FindLastCntnt();
if ( !pThis )
return 0;
}
else if ( IsCntntFrm() && ((SwCntntFrm*)this)->GetFollow() )
return ((SwCntntFrm*)this)->GetFollow();
if ( pThis->IsCntntFrm() )
{
const sal_Bool bBody = pThis->IsInDocBody();
const sal_Bool bFtn = pThis->IsInFtn();
SwCntntFrm *pNxtCnt = ((SwCntntFrm*)pThis)->GetNextCntntFrm();
if ( pNxtCnt )
{
// --> OD 2005-12-01 #i27138#
if ( bBody || ( bFtn && !_bInSameFtn ) )
// <--
{
// handling for environments 'footnotes' and 'document body frames':
while ( pNxtCnt )
{
if ( (bBody && pNxtCnt->IsInDocBody()) ||
(bFtn && pNxtCnt->IsInFtn()) )
return pNxtCnt;
pNxtCnt = pNxtCnt->GetNextCntntFrm();
}
}
// --> OD 2005-12-01 #i27138#
else if ( bFtn && _bInSameFtn )
{
// handling for environments 'each footnote':
// Assure that found next content frame belongs to the same footnotes
const SwFtnFrm* pFtnFrmOfNext( pNxtCnt->FindFtnFrm() );
const SwFtnFrm* pFtnFrmOfCurr( pThis->FindFtnFrm() );
ASSERT( pFtnFrmOfCurr,
"<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." );
if ( pFtnFrmOfNext == pFtnFrmOfCurr )
{
return pNxtCnt;
}
else if ( pFtnFrmOfCurr->GetFollow() )
{
// next content frame has to be the first content frame
// in the follow footnote, which contains a content frame.
SwFtnFrm* pFollowFtnFrmOfCurr(
const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
pNxtCnt = 0L;
do {
pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow();
pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt();
} while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() );
return pNxtCnt;
}
else
{
// current content frame is the last content frame in the
// footnote - no next content frame exists.
return 0L;
}
}
// <--
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 SwFrm *pUp = pThis->GetUpper();
const SwFrm *pCntUp = pNxtCnt->GetUpper();
while ( pUp && pUp->GetUpper() &&
!pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
pUp = pUp->GetUpper();
while ( pCntUp && pCntUp->GetUpper() &&
!pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
pCntUp = pCntUp->GetUpper();
if ( pCntUp == pUp )
return pNxtCnt;
}
}
}
return 0;
}
/** 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#
@author OD
*/
SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn )
{
if ( !IsFlowFrm() )
{
// nothing to do, if current frame isn't a flow frame.
return 0L;
}
SwCntntFrm* pPrevCntntFrm( 0L );
// Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel
// through the layout, a content frame, at which the travel starts, is needed.
SwCntntFrm* pCurrCntntFrm = dynamic_cast<SwCntntFrm*>(this);
// perform shortcut, if current frame is a follow, and
// determine <pCurrCntntFrm>, if current frame is a table or section frame
if ( pCurrCntntFrm && pCurrCntntFrm->IsFollow() )
{
// previous content frame is its master content frame
pPrevCntntFrm = pCurrCntntFrm->FindMaster();
}
else if ( IsTabFrm() )
{
SwTabFrm* pTabFrm( static_cast<SwTabFrm*>(this) );
if ( pTabFrm->IsFollow() )
{
// previous content frame is the last content of its master table frame
pPrevCntntFrm = pTabFrm->FindMaster()->FindLastCntnt();
}
else
{
// start content frame for the search is the first content frame of
// the table frame.
pCurrCntntFrm = pTabFrm->ContainsCntnt();
}
}
else if ( IsSctFrm() )
{
SwSectionFrm* pSectFrm( static_cast<SwSectionFrm*>(this) );
if ( pSectFrm->IsFollow() )
{
// previous content frame is the last content of its master section frame
pPrevCntntFrm = pSectFrm->FindMaster()->FindLastCntnt();
}
else
{
// start content frame for the search is the first content frame of
// the section frame.
pCurrCntntFrm = pSectFrm->ContainsCntnt();
}
}
// search for next content frame, depending on the environment, in which
// the current frame is in.
if ( !pPrevCntntFrm && pCurrCntntFrm )
{
pPrevCntntFrm = pCurrCntntFrm->GetPrevCntntFrm();
if ( pPrevCntntFrm )
{
if ( pCurrCntntFrm->IsInFly() )
{
// handling for environments 'unlinked fly frame' and
// 'group of linked fly frames':
// Nothing to do, <pPrevCntntFrm> is the one
}
else
{
const bool bInDocBody = pCurrCntntFrm->IsInDocBody();
const bool bInFtn = pCurrCntntFrm->IsInFtn();
if ( bInDocBody || ( bInFtn && !_bInSameFtn ) )
{
// handling for environments 'footnotes' and 'document body frames':
// Assure that found previous frame is also in one of these
// environments. Otherwise, travel further
while ( pPrevCntntFrm )
{
if ( ( bInDocBody && pPrevCntntFrm->IsInDocBody() ) ||
( bInFtn && pPrevCntntFrm->IsInFtn() ) )
{
break;
}
pPrevCntntFrm = pPrevCntntFrm->GetPrevCntntFrm();
}
}
else if ( bInFtn && _bInSameFtn )
{
// handling for environments 'each footnote':
// Assure that found next content frame belongs to the same footnotes
const SwFtnFrm* pFtnFrmOfPrev( pPrevCntntFrm->FindFtnFrm() );
const SwFtnFrm* pFtnFrmOfCurr( pCurrCntntFrm->FindFtnFrm() );
if ( pFtnFrmOfPrev != pFtnFrmOfCurr )
{
if ( pFtnFrmOfCurr->GetMaster() )
{
SwFtnFrm* pMasterFtnFrmOfCurr(
const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
pPrevCntntFrm = 0L;
// --> OD 2007-07-05 #146872#
// correct wrong loop-condition
do {
pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster();
pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt();
} while ( !pPrevCntntFrm &&
pMasterFtnFrmOfCurr->GetMaster() );
// <--
}
else
{
// current content frame is the first content in the
// footnote - no previous content exists.
pPrevCntntFrm = 0L;;
}
}
}
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 <pCurrCntntFrm>
// Note: At this point its clear, that <pCurrCntntFrm> has
// to be inside a page header or page footer and that
// neither <pCurrCntntFrm> nor <pPrevCntntFrm> are
// inside a fly frame.
// Thus, method <FindFooterOrHeader()> can be used.
ASSERT( pCurrCntntFrm->FindFooterOrHeader(),
"<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" );
ASSERT( !pPrevCntntFrm->IsInFly(),
"<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
if ( pPrevCntntFrm->FindFooterOrHeader() !=
pCurrCntntFrm->FindFooterOrHeader() )
{
pPrevCntntFrm = 0L;
}
}
}
}
}
return pPrevCntntFrm;
}
SwFrm *SwFrm::_FindPrev()
{
sal_Bool bIgnoreTab = sal_False;
SwFrm *pThis = this;
if ( IsTabFrm() )
{
//Der erste Cntnt der Tabelle wird
//gegriffen und dessen Vorgaenger geliefert. Um die Spezialbeh.
//Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
if ( ((SwTabFrm*)this)->IsFollow() )
return ((SwTabFrm*)this)->FindMaster();
else
pThis = ((SwTabFrm*)this)->ContainsCntnt();
bIgnoreTab = sal_True;
}
if ( pThis && pThis->IsCntntFrm() )
{
SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm();
if( !pPrvCnt )
return 0;
if ( !bIgnoreTab && pThis->IsInTab() )
{
SwLayoutFrm *pUp = pThis->GetUpper();
while ( !pUp->IsCellFrm() )
pUp = pUp->GetUpper();
ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
if ( pUp->IsAnLower( pPrvCnt ) )
return pPrvCnt;
}
else
{
SwFrm* pRet;
const sal_Bool bBody = pThis->IsInDocBody();
const sal_Bool bFtn = bBody ? sal_False : pThis->IsInFtn();
if ( bBody || bFtn )
{
while ( pPrvCnt )
{
if ( (bBody && pPrvCnt->IsInDocBody()) ||
(bFtn && pPrvCnt->IsInFtn()) )
{
pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
: (SwFrm*)pPrvCnt;
return pRet;
}
pPrvCnt = pPrvCnt->GetPrevCntntFrm();
}
}
else if ( pThis->IsInFly() )
{
pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
: (SwFrm*)pPrvCnt;
return pRet;
}
else //Fuss-/oder Kopfbereich oder Fly
{
const SwFrm *pUp = pThis->GetUpper();
const SwFrm *pCntUp = pPrvCnt->GetUpper();
while ( pUp && pUp->GetUpper() &&
!pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
pUp = pUp->GetUpper();
while ( pCntUp && pCntUp->GetUpper() )
pCntUp = pCntUp->GetUpper();
if ( pCntUp == pUp )
{
pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
: (SwFrm*)pPrvCnt;
return pRet;
}
}
}
}
return 0;
}
void SwFrm::ImplInvalidateNextPos( sal_Bool bNoFtn )
{
SwFrm *pFrm;
if ( 0 != (pFrm = _FindNext()) )
{
if( pFrm->IsSctFrm() )
{
while( pFrm && pFrm->IsSctFrm() )
{
if( ((SwSectionFrm*)pFrm)->GetSection() )
{
SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
if( pTmp )
pTmp->InvalidatePos();
else if( !bNoFtn )
((SwSectionFrm*)pFrm)->InvalidateFtnPos();
if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
pFrm->InvalidatePos();
return;
}
pFrm = pFrm->FindNext();
}
if( pFrm )
{
if ( pFrm->IsSctFrm())
{ // Damit der Inhalt eines Bereichs die Chance erhaelt,
// die Seite zu wechseln, muss er ebenfalls invalidiert werden.
SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
if( pTmp )
pTmp->InvalidatePos();
if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
pFrm->InvalidatePos();
}
else
pFrm->InvalidatePos();
}
}
else
pFrm->InvalidatePos();
}
}
/** method to invalidate printing area of next frame
OD 09.01.2004 #i11859#
@author OD
FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm
*/
void SwFrm::InvalidateNextPrtArea()
{
// determine next frame
SwFrm* pNextFrm = FindNext();
// skip empty section frames and hidden text frames
{
while ( pNextFrm &&
( ( pNextFrm->IsSctFrm() &&
!static_cast<SwSectionFrm*>(pNextFrm)->GetSection() ) ||
( pNextFrm->IsTxtFrm() &&
static_cast<SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) ) )
{
pNextFrm = pNextFrm->FindNext();
}
}
// Invalidate printing area of found next frame
if ( pNextFrm )
{
if ( pNextFrm->IsSctFrm() )
{
// 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() || FindSctFrm()->GetFollow() != pNextFrm )
{
pNextFrm->InvalidatePrt();
}
// Invalidate printing area of first content in found section.
SwFrm* pFstCntntOfSctFrm =
static_cast<SwSectionFrm*>(pNextFrm)->ContainsAny();
if ( pFstCntntOfSctFrm )
{
pFstCntntOfSctFrm->InvalidatePrt();
}
}
else
{
pNextFrm->InvalidatePrt();
}
}
}
/*************************************************************************
|*
|* lcl_IsInColSect()
|* liefert nur sal_True, wenn der Frame _direkt_ in einem spaltigen Bereich steht,
|* nicht etwa, wenn er in einer Tabelle steht, die in einem spaltigen Bereich ist.
|*
|*************************************************************************/
sal_Bool lcl_IsInColSct( const SwFrm *pUp )
{
sal_Bool bRet = sal_False;
while( pUp )
{
if( pUp->IsColumnFrm() )
bRet = sal_True;
else if( pUp->IsSctFrm() )
return bRet;
else if( pUp->IsTabFrm() )
return sal_False;
pUp = pUp->GetUpper();
}
return sal_False;
}
/*************************************************************************
|*
|* SwFrm::IsMoveable();
|*
|* Ersterstellung MA 09. Mar. 93
|* Letzte Aenderung MA 05. May. 95
|*
|*************************************************************************/
/** 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 _pLayoutFrm == 0L), the movability in the actual
environment (<this->GetUpper()) is checked.
@author OD
*/
bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const
{
bool bRetVal = false;
if ( !_pLayoutFrm )
{
_pLayoutFrm = GetUpper();
}
if ( _pLayoutFrm && IsFlowFrm() )
{
if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) )
{
bRetVal = true;
}
else if ( _pLayoutFrm->IsInFly() ||
_pLayoutFrm->IsInDocBody() ||
_pLayoutFrm->IsInFtn() )
{
if ( _pLayoutFrm->IsInTab() && !IsTabFrm() &&
( !IsCntntFrm() || !const_cast<SwFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) )
{
bRetVal = false;
}
else
{
if ( _pLayoutFrm->IsInFly() )
{
// if fly frame has a follow (next linked fly frame),
// frame is moveable.
if ( const_cast<SwLayoutFrm*>(_pLayoutFrm)->FindFlyFrm()->GetNextLink() )
{
bRetVal = true;
}
else
{
// if environment is columned, frame is moveable, if
// it isn't in last column.
// search for column frame
const SwFrm* pCol = _pLayoutFrm;
while ( pCol && !pCol->IsColumnFrm() )
{
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;
}
/*************************************************************************
|*
|* SwFrm::SetInfFlags();
|*
|* Ersterstellung MA 05. Apr. 94
|* Letzte Aenderung MA 05. Apr. 94
|*
|*************************************************************************/
void SwFrm::SetInfFlags()
{
if ( !IsFlyFrm() && !GetUpper() ) //noch nicht gepastet, keine Informationen
return; //lieferbar
bInfInvalid = bInfBody = bInfTab = bInfFly = bInfFtn = bInfSct = sal_False;
SwFrm *pFrm = this;
if( IsFtnContFrm() )
bInfFtn = sal_True;
do
{ // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt
if ( pFrm->IsBodyFrm() && !bInfFtn && pFrm->GetUpper()
&& pFrm->GetUpper()->IsPageFrm() )
bInfBody = sal_True;
else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() )
{
bInfTab = sal_True;
}
else if ( pFrm->IsFlyFrm() )
bInfFly = sal_True;
else if ( pFrm->IsSctFrm() )
bInfSct = sal_True;
else if ( pFrm->IsFtnFrm() )
bInfFtn = sal_True;
pFrm = pFrm->GetUpper();
} while ( pFrm && !pFrm->IsPageFrm() ); //Oberhalb der Seite kommt nix
}
/*-----------------22.8.2001 14:30------------------
* SwFrm::SetDirFlags( sal_Bool )
* actualizes 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 SwFrm::SetDirFlags( sal_Bool bVert )
{
if( bVert )
{
// OD 2004-01-21 #114969# - if derived, valid vertical flag only if
// vertical flag of upper/anchor is valid.
if( bDerivedVert )
{
const SwFrm* pAsk = IsFlyFrm() ?
((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" )
if( pAsk )
{
bVertical = pAsk->IsVertical() ? 1 : 0;
bReverse = pAsk->IsReverse() ? 1 : 0;
bVertLR = pAsk->IsVertLR() ? 1 : 0;
//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
if ( !pAsk->bInvalidVert )
bInvalidVert = sal_False;
}
}
else
CheckDirection( bVert );
}
else
{
sal_Bool bInv = 0;
if( !bDerivedR2L ) // CheckDirection is able to set bDerivedR2L!
CheckDirection( bVert );
if( bDerivedR2L )
{
const SwFrm* pAsk = IsFlyFrm() ?
((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" )
if( pAsk )
bRightToLeft = pAsk->IsRightToLeft() ? 1 : 0;
if( !pAsk || pAsk->bInvalidR2L )
bInv = bInvalidR2L;
}
bInvalidR2L = bInv;
}
}
SwLayoutFrm* SwFrm::GetNextCellLeaf( MakePageType )
{
SwFrm* pTmpFrm = this;
while ( !pTmpFrm->IsCellFrm() )
pTmpFrm = pTmpFrm->GetUpper();
ASSERT( pTmpFrm, "SwFrm::GetNextCellLeaf() without cell" )
return ((SwCellFrm*)pTmpFrm)->GetFollowCell();
}
SwLayoutFrm* SwFrm::GetPrevCellLeaf( MakePageType )
{
SwFrm* pTmpFrm = this;
while ( !pTmpFrm->IsCellFrm() )
pTmpFrm = pTmpFrm->GetUpper();
ASSERT( pTmpFrm, "SwFrm::GetNextPreviousLeaf() without cell" )
return ((SwCellFrm*)pTmpFrm)->GetPreviousCell();
}
SwCellFrm* lcl_FindCorrespondingCellFrm( const SwRowFrm& rOrigRow,
const SwCellFrm& rOrigCell,
const SwRowFrm& rCorrRow,
bool bInFollow )
{
SwCellFrm* pRet = NULL;
SwCellFrm* pCell = (SwCellFrm*)rOrigRow.Lower();
SwCellFrm* pCorrCell = (SwCellFrm*)rCorrRow.Lower();
while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) )
{
pCell = (SwCellFrm*)pCell->GetNext();
pCorrCell = (SwCellFrm*)pCorrCell->GetNext();
}
ASSERT( pCell && pCorrCell, "lcl_FindCorrespondingCellFrm 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()->IsRowFrm(),
"lcl_FindCorrespondingCellFrm does not work" )
SwRowFrm* pRow = (SwRowFrm*)pCell->Lower();
while ( !pRow->IsAnLower( &rOrigCell ) )
pRow = (SwRowFrm*)pRow->GetNext();
SwRowFrm* pCorrRow = 0;
if ( bInFollow )
pCorrRow = pRow->GetFollowRow();
else
{
SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower());
if ( pTmpRow && pTmpRow->GetFollowRow() == pRow )
pCorrRow = pTmpRow;
}
if ( pCorrRow )
pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow );
}
else
pRet = pCorrCell;
return pRet;
}
// VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
SwCellFrm* SwCellFrm::GetFollowCell() const
{
SwCellFrm* pRet = NULL;
// NEW TABLES
// Covered cells do not have follow cells!
const long nRowSpan = GetLayoutRowSpan();
if ( nRowSpan < 1 )
return NULL;
// find most upper row frame
const SwFrm* pRow = GetUpper();
while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
pRow = pRow->GetUpper();
if ( !pRow )
return NULL;
const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() );
if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() )
return NULL;
const SwCellFrm* 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 SwRowFrm* pFollowRow = NULL;
if ( !pRow->GetNext() &&
NULL != ( pFollowRow = pRow->IsInSplitTableRow() ) &&
( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) )
pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *pThisCell, *pFollowRow, true );
return pRet;
}
// VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
SwCellFrm* SwCellFrm::GetPreviousCell() const
{
SwCellFrm* pRet = NULL;
// NEW TABLES
// Covered cells do not have previous cells!
if ( GetLayoutRowSpan() < 1 )
return NULL;
// find most upper row frame
const SwFrm* pRow = GetUpper();
while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
pRow = pRow->GetUpper();
ASSERT( pRow->GetUpper() && pRow->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" );
SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
if ( pTab->IsFollow() )
{
const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
const bool bIsInFirstLine = ( pTmp == pRow );
if ( bIsInFirstLine )
{
SwTabFrm *pMaster = (SwTabFrm*)pTab->FindMaster();
if ( pMaster && pMaster->HasFollowFlowLine() )
{
SwRowFrm* pMasterRow = static_cast<SwRowFrm*>(pMaster->GetLastLower());
if ( pMasterRow )
pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *this, *pMasterRow, false );
if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 )
pRet = &const_cast<SwCellFrm&>(pRet->FindStartEndOfRowSpanCell( true, true ));
}
}
}
return pRet;
}
// --> NEW TABLES
const SwCellFrm& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const
{
const SwCellFrm* pRet = 0;
const SwTabFrm* pTableFrm = dynamic_cast<const SwTabFrm*>(GetUpper()->GetUpper());
if ( !bStart && pTableFrm->IsFollow() && pTableFrm->IsInHeadline( *this ) )
return *this;
ASSERT( pTableFrm &&
( bStart && GetTabBox()->getRowSpan() < 1 ||
!bStart && GetLayoutRowSpan() > 1 ),
"SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" )
if ( pTableFrm )
{
const SwTable* pTable = pTableFrm->GetTable();
sal_uInt16 nMax = USHRT_MAX;
if ( bCurrentTableOnly )
{
const SwFrm* pCurrentRow = GetUpper();
const bool bDoNotEnterHeadline = bStart && pTableFrm->IsFollow() &&
!pTableFrm->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 && pTableFrm->IsFollow() &&
pTableFrm->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 SwCellFrm in
// the current table frame:
const SwTableBox& rMasterBox = bStart ?
GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) :
GetTabBox()->FindEndOfRowSpan( *pTable, nMax );
SwIterator<SwCellFrm,SwFmt> aIter( *rMasterBox.GetFrmFmt() );
for ( SwCellFrm* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() )
{
if ( pMasterCell->GetTabBox() == &rMasterBox )
{
const SwTabFrm* pMasterTable = static_cast<const SwTabFrm*>(pMasterCell->GetUpper()->GetUpper());
if ( bCurrentTableOnly )
{
if ( pMasterTable == pTableFrm )
{
pRet = pMasterCell;
break;
}
}
else
{
if ( pMasterTable == pTableFrm ||
( (bStart && pMasterTable->IsAnFollow(pTableFrm)) ||
(!bStart && pTableFrm->IsAnFollow(pMasterTable)) ) )
{
pRet = pMasterCell;
break;
}
}
}
}
}
ASSERT( pRet, "SwCellFrm::FindStartRowSpanCell: No result" )
return *pRet;
}
// <-- NEW TABLES
const SwRowFrm* SwFrm::IsInSplitTableRow() const
{
ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" )
const SwFrm* pRow = this;
// find most upper row frame
while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
pRow = pRow->GetUpper();
if ( !pRow ) return NULL;
ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" )
const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
// --> OD 2006-06-28 #b6443897#
// 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<const SwRowFrm*>(pRow)->GetTabLine()) ) ||
!pTab->HasFollowFlowLine() ||
!pTab->GetFollow() )
return NULL;
// <--
// skip headline
const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow();
ASSERT( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" )
return pFollowRow;
}
const SwRowFrm* SwFrm::IsInFollowFlowRow() const
{
ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" )
// find most upper row frame
const SwFrm* pRow = this;
while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
pRow = pRow->GetUpper();
if ( !pRow ) return NULL;
ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" )
const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
const SwTabFrm* pMaster = pTab->IsFollow() ? pTab->FindMaster() : 0;
if ( !pMaster || !pMaster->HasFollowFlowLine() )
return NULL;
const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
const bool bIsInFirstLine = ( pTmp == pRow );
if ( !bIsInFirstLine )
return NULL;
const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower());
return pMasterRow;
}
bool SwFrm::IsInBalancedSection() const
{
bool bRet = false;
if ( IsInSct() )
{
const SwSectionFrm* pSectionFrm = FindSctFrm();
if ( pSectionFrm )
bRet = pSectionFrm->IsBalancedSection();
}
return bRet;
}
/*
* SwLayoutFrm::GetLastLower()
*/
const SwFrm* SwLayoutFrm::GetLastLower() const
{
const SwFrm* pRet = Lower();
if ( !pRet )
return 0;
while ( pRet->GetNext() )
pRet = pRet->GetNext();
return pRet;
}