diff options
Diffstat (limited to 'sw/source/core/layout/ftnfrm.cxx')
-rw-r--r-- | sw/source/core/layout/ftnfrm.cxx | 3367 |
1 files changed, 3367 insertions, 0 deletions
diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx new file mode 100644 index 000000000000..3dc03053a23f --- /dev/null +++ b/sw/source/core/layout/ftnfrm.cxx @@ -0,0 +1,3367 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <txtftn.hxx> +#include <fmtftn.hxx> +#include <ftnidx.hxx> +#include <pagefrm.hxx> +#include <colfrm.hxx> +#include <rootfrm.hxx> +#include <cntfrm.hxx> +#include <doc.hxx> +#include <ndtxt.hxx> +#include <frmtool.hxx> +#include <swtable.hxx> +#include <ftnfrm.hxx> +#include <txtfrm.hxx> +#include <tabfrm.hxx> +#include <pagedesc.hxx> +#include <ftninfo.hxx> +#include <ndindex.hxx> +#include <sectfrm.hxx> +#include <pam.hxx> +// --> OD 2005-05-17 #i49383# +#include <objectformatter.hxx> +// <-- + +/************************************************************************* +|* +|* lcl_FindFtnPos() Sucht die Position des Attributes im FtnArray am +|* Dokument, dort stehen die Fussnoten gluecklicherweise nach ihrem +|* Index sortiert. +|* +|* Ersterstellung MA 29. Jun. 93 +|* Letzte Aenderung MA 13. Dec. 93 +|* +|*************************************************************************/ + +#define ENDNOTE 0x80000000 + +ULONG MA_FASTCALL lcl_FindFtnPos( const SwDoc *pDoc, const SwTxtFtn *pAttr ) +{ + const SwFtnIdxs &rFtnIdxs = pDoc->GetFtnIdxs(); + +#ifdef MA_DEBUG + //Wenn das Array nicht stimmt haben wir ein Problem, denn viele + //Ftn-Functions bauen auf dem Array auf. + for ( USHORT k = 0; k+1 < rFtnIdxs.Count(); ++k ) + { + SwIndex aIdx1(&pDoc->GetNodes()); + SwIndex aIdx2(&pDoc->GetNodes()); + rFtnIdxs[k]->pFtn-> GetTxtNode().GetIndex(aIdx1); + rFtnIdxs[k+1]->pFtn->GetTxtNode().GetIndex(aIdx2); + if ( aIdx1.GetIndex() > aIdx2.GetIndex() ) + { + ASSERT( !rFtnIdxs.Count(), "FtnIdxs not up to date" ); + } + else if ( aIdx1.GetIndex() == aIdx2.GetIndex() ) + { + SwTxtFtn *p1 = rFtnIdxs[k]; + SwTxtFtn *p2 = rFtnIdxs[k+1]; + ASSERT( *p1->GetStart() < *p2->GetStart(), + "FtnIdxs not up to date" ); + } + } +#endif + + USHORT nRet; + SwTxtFtnPtr pBla = (SwTxtFtn*)pAttr; + if ( rFtnIdxs.Seek_Entry( pBla, &nRet ) ) + { + if( pAttr->GetFtn().IsEndNote() ) + return ULONG(nRet) + ENDNOTE; + return nRet; + } + ASSERT( !pDoc, "FtnPos not found." ); + return 0; +} + +BOOL SwFtnFrm::operator<( const SwTxtFtn* pTxtFtn ) const +{ + const SwDoc* pDoc = GetFmt()->GetDoc(); + ASSERT( pDoc, "SwFtnFrm: Missing doc!" ); + return lcl_FindFtnPos( pDoc, GetAttr() ) < + lcl_FindFtnPos( pDoc, pTxtFtn ); +} + +/************************************************************************* +|* +|* BOOL lcl_NextFtnBoss( SwFtnBossFrm* pBoss, SwPageFrm* pPage) +|* setzt pBoss auf den naechsten SwFtnBossFrm, das kann entweder eine Spalte +|* oder eine Seite (ohne Spalten) sein. Wenn die Seite dabei gewechselt wird +|* enthaelt pPage die neue Seite und die Funktion liefert TRUE. +|* +|* Ersterstellung AMA 06. Nov. 98 +|* Letzte Aenderung AMA 06. Nov. 98 +|* +|*************************************************************************/ + +BOOL lcl_NextFtnBoss( SwFtnBossFrm* &rpBoss, SwPageFrm* &rpPage, + BOOL bDontLeave ) +{ + if( rpBoss->IsColumnFrm() ) + { + if( rpBoss->GetNext() ) + { + rpBoss = (SwFtnBossFrm*)rpBoss->GetNext(); //naechste Spalte + return FALSE; + } + if( rpBoss->IsInSct() ) + { + SwSectionFrm* pSct = rpBoss->FindSctFrm()->GetFollow(); + if( pSct ) + { + ASSERT( pSct->Lower() && pSct->Lower()->IsColumnFrm(), + "Where's the column?" ); + rpBoss = (SwColumnFrm*)pSct->Lower(); + SwPageFrm* pOld = rpPage; + rpPage = pSct->FindPageFrm(); + return pOld != rpPage; + } + else if( bDontLeave ) + { + rpPage = NULL; + rpBoss = NULL; + return FALSE; + } + } + } + rpPage = (SwPageFrm*)rpPage->GetNext(); // naechste Seite + rpBoss = rpPage; + if( rpPage ) + { + SwLayoutFrm* pBody = rpPage->FindBodyCont(); + if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() ) + rpBoss = (SwFtnBossFrm*)pBody->Lower(); // erste Spalte + } + return TRUE; +} + +/************************************************************************* +|* +|* USHORT lcl_ColumnNum( SwFrm* pBoss ) +|* liefert die Spaltennummer, wenn pBoss eine Spalte ist, +|* sonst eine Null (bei Seiten). +|* +|* Ersterstellung AMA 06. Nov. 98 +|* Letzte Aenderung AMA 06. Nov. 98 +|* +|*************************************************************************/ + +USHORT lcl_ColumnNum( const SwFrm* pBoss ) +{ + USHORT nRet = 0; + if( !pBoss->IsColumnFrm() ) + return 0; + const SwFrm* pCol; + if( pBoss->IsInSct() ) + { + pCol = pBoss->GetUpper()->FindColFrm(); + if( pBoss->GetNext() || pBoss->GetPrev() ) + { + while( pBoss ) + { + ++nRet; // Section columns + pBoss = pBoss->GetPrev(); + } + } + } + else + pCol = pBoss; + while( pCol ) + { + nRet += 256; // Page columns + pCol = pCol->GetPrev(); + } + return nRet; +} + +/************************************************************************* +|* +|* SwFtnContFrm::SwFtnContFrm() +|* +|* Ersterstellung MA 24. Feb. 93 +|* Letzte Aenderung MA 02. Mar. 93 +|* +|*************************************************************************/ + + +SwFtnContFrm::SwFtnContFrm( SwFrmFmt *pFmt ): + SwLayoutFrm( pFmt ) +{ + nType = FRMC_FTNCONT; +} + + +// lcl_Undersize(..) klappert einen SwFrm und dessen Inneres ab +// und liefert die Summe aller TxtFrm-Vergroesserungswuensche + +long lcl_Undersize( const SwFrm* pFrm ) +{ + long nRet = 0; + SWRECTFN( pFrm ) + if( pFrm->IsTxtFrm() ) + { + if( ((SwTxtFrm*)pFrm)->IsUndersized() ) + { + // Dieser TxtFrm waere gern ein bisschen groesser + nRet = ((SwTxtFrm*)pFrm)->GetParHeight() - + (pFrm->Prt().*fnRect->fnGetHeight)(); + if( nRet < 0 ) + nRet = 0; + } + } + else if( pFrm->IsLayoutFrm() ) + { + const SwFrm* pNxt = ((SwLayoutFrm*)pFrm)->Lower(); + while( pNxt ) + { + nRet += lcl_Undersize( pNxt ); + pNxt = pNxt->GetNext(); + } + } + return nRet; +} + +/************************************************************************* +|* +|* SwFtnContFrm::Format() +|* +|* Beschreibung: "Formatiert" den Frame; +|* Die Fixsize wird hier nicht eingestellt. +|* Ersterstellung MA 01. Mar. 93 +|* Letzte Aenderung MA 17. Nov. 98 +|* +|*************************************************************************/ + + +void SwFtnContFrm::Format( const SwBorderAttrs * ) +{ + //GesamtBorder ermitteln, es gibt nur einen Abstand nach oben. + const SwPageFrm* pPage = FindPageFrm(); + const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo(); + const SwTwips nBorder = rInf.GetTopDist() + rInf.GetBottomDist() + + rInf.GetLineWidth(); + SWRECTFN( this ) + if ( !bValidPrtArea ) + { + bValidPrtArea = TRUE; + (Prt().*fnRect->fnSetTop)( nBorder ); + (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() ); + (Prt().*fnRect->fnSetHeight)((Frm().*fnRect->fnGetHeight)() - nBorder ); + if( (Prt().*fnRect->fnGetHeight)() < 0 && !pPage->IsFtnPage() ) + bValidSize = FALSE; + } + + if ( !bValidSize ) + { + if ( pPage->IsFtnPage() && !GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) ) + Grow( LONG_MAX, FALSE ); + else + { + //Die Groesse in der VarSize wird durch den Inhalt plus den + //Raendern bestimmt. + SwTwips nRemaining = 0; + SwFrm *pFrm = pLower; + while ( pFrm ) + { // lcl_Undersize(..) beruecksichtigt (rekursiv) TxtFrms, die gerne + // groesser waeren. Diese entstehen insbesondere in spaltigen Rahmen, + // wenn diese noch nicht ihre maximale Groesse haben. + nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)() + + lcl_Undersize( pFrm ); + pFrm = pFrm->GetNext(); + } + //Jetzt noch den Rand addieren + nRemaining += nBorder; + + SwTwips nDiff; + if( IsInSct() ) + { + nDiff = -(Frm().*fnRect->fnBottomDist)( + (GetUpper()->*fnRect->fnGetPrtBottom)() ); + if( nDiff > 0 ) + { + if( nDiff > (Frm().*fnRect->fnGetHeight)() ) + nDiff = (Frm().*fnRect->fnGetHeight)(); + (Frm().*fnRect->fnAddBottom)( -nDiff ); + (Prt().*fnRect->fnAddHeight)( -nDiff ); + } + } + nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining; + if ( nDiff > 0 ) + Shrink( nDiff ); + else if ( nDiff < 0 ) + { + Grow( -nDiff ); + //Es kann passieren, dass weniger Platz zur Verfuegung steht, + //als der bereits der Border benoetigt - die Groesse der + //PrtArea wird dann negativ. + SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)(); + if( nPrtHeight < 0 ) + { + const SwTwips nTmpDiff = Max( (Prt().*fnRect->fnGetTop)(), + -nPrtHeight ); + (Prt().*fnRect->fnSubTop)( nTmpDiff ); + } + } + } + bValidSize = TRUE; + } +} +/************************************************************************* +|* +|* SwFtnContFrm::GrowFrm(), ShrinkFrm() +|* +|* Ersterstellung MA 24. Feb. 93 +|* Letzte Aenderung AMA 05. Nov. 98 +|* +|*************************************************************************/ + +SwTwips SwFtnContFrm::GrowFrm( SwTwips nDist, BOOL bTst, BOOL ) +{ + //Keine Pruefung ob FixSize oder nicht, die FtnContainer sind immer bis + //zur Maximalhoehe variabel. + //Wenn die Maximalhoehe LONG_MAX ist, so nehmen wir uns soviel Platz wie eben + //moeglich. + //Wenn die Seite eine spezielle Fussnotenseite ist, so nehmen wir uns auch + //soviel Platz wie eben moeglich. +#ifdef DBG_UTIL + if ( !GetUpper() || !GetUpper()->IsFtnBossFrm() ) + { ASSERT( !this, "Keine FtnBoss." ); + return 0; + } +#endif + + SWRECTFN( this ) + if( (Frm().*fnRect->fnGetHeight)() > 0 && + nDist > ( LONG_MAX - (Frm().*fnRect->fnGetHeight)() ) ) + nDist = LONG_MAX - (Frm().*fnRect->fnGetHeight)(); + + SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper(); + if( IsInSct() ) + { + SwSectionFrm* pSect = FindSctFrm(); + ASSERT( pSect, "GrowFrm: Missing SectFrm" ); + // In a section, which has to maximize, a footnotecontainer is allowed + // to grow, when the section can't grow anymore. + if( !bTst && !pSect->IsColLocked() && + pSect->ToMaximize( FALSE ) && pSect->Growable() ) + { + pSect->InvalidateSize(); + return 0; + } + } + const bool bBrowseMode = GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE); + SwPageFrm *pPage = pBoss->FindPageFrm(); + if ( bBrowseMode || !pPage->IsFtnPage() ) + { + if ( pBoss->GetMaxFtnHeight() != LONG_MAX ) + { + nDist = Min( nDist, pBoss->GetMaxFtnHeight() + - (Frm().*fnRect->fnGetHeight)() ); + if ( nDist <= 0 ) + return 0L; + } + //Der FtnBoss will bezueglich des MaxWerts auch noch mitreden. + if( !IsInSct() ) + { + const SwTwips nMax = pBoss->GetVarSpace(); + if ( nDist > nMax ) + nDist = nMax; + if ( nDist <= 0 ) + return 0L; + } + } + else if( nDist > (GetPrev()->Frm().*fnRect->fnGetHeight)() ) + //aber mehr als der Body kann koennen und wollen wir nun auch wieder + //nicht herausruecken. + nDist = (GetPrev()->Frm().*fnRect->fnGetHeight)(); + + long nAvail = 0; + if ( bBrowseMode ) + { + nAvail = GetUpper()->Prt().Height(); + const SwFrm *pAvail = GetUpper()->Lower(); + do + { nAvail -= pAvail->Frm().Height(); + pAvail = pAvail->GetNext(); + } while ( pAvail ); + if ( nAvail > nDist ) + nAvail = nDist; + } + + if ( !bTst ) + { + (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() + nDist ); + if( IsVertical() && !IsReverse() ) + Frm().Pos().X() -= nDist; + } + long nGrow = nDist - nAvail, + nReal = 0; + if ( nGrow > 0 ) + { + BYTE nAdjust = pBoss->NeighbourhoodAdjustment( this ); + if( NA_ONLY_ADJUST == nAdjust ) + nReal = AdjustNeighbourhood( nGrow, bTst ); + else + { + if( NA_GROW_ADJUST == nAdjust ) + { + SwFrm* pFtn = Lower(); + if( pFtn ) + { + while( pFtn->GetNext() ) + pFtn = pFtn->GetNext(); + if( ((SwFtnFrm*)pFtn)->GetAttr()->GetFtn().IsEndNote() ) + { + nReal = AdjustNeighbourhood( nGrow, bTst ); + nAdjust = NA_GROW_SHRINK; // no more AdjustNeighbourhood + } + } + } + nReal += pBoss->Grow( nGrow - nReal, bTst ); + if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust ) + && nReal < nGrow ) + nReal += AdjustNeighbourhood( nGrow - nReal, bTst ); + } + } + + nReal += nAvail; + + if ( !bTst ) + { + if ( nReal != nDist ) + { + nDist -= nReal; + //Den masslosen Wunsch koennen wir leider nur in Grenzen erfuellen. + Frm().SSize().Height() -= nDist; + if( IsVertical() && !IsReverse() ) + Frm().Pos().X() += nDist; + } + + //Nachfolger braucht nicht invalidiert werden, denn wir wachsen + //immer nach oben. + if( nReal ) + { + _InvalidateSize(); + _InvalidatePos(); + InvalidatePage( pPage ); + } + } + return nReal; +} + + +SwTwips SwFtnContFrm::ShrinkFrm( SwTwips nDiff, BOOL bTst, BOOL bInfo ) +{ + SwPageFrm *pPage = FindPageFrm(); + if ( pPage && + ( !pPage->IsFtnPage() || + GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) ) ) + { + SwTwips nRet = SwLayoutFrm::ShrinkFrm( nDiff, bTst, bInfo ); + if( IsInSct() && !bTst ) + FindSctFrm()->InvalidateNextPos(); + if ( !bTst && nRet ) + { + _InvalidatePos(); + InvalidatePage( pPage ); + } + return nRet; + } + return 0; +} + + +/************************************************************************* +|* +|* SwFtnFrm::SwFtnFrm() +|* +|* Ersterstellung MA 24. Feb. 93 +|* Letzte Aenderung MA 11. Oct. 93 +|* +|*************************************************************************/ + + +SwFtnFrm::SwFtnFrm( SwFrmFmt *pFmt, SwCntntFrm *pCnt, SwTxtFtn *pAt ): + SwLayoutFrm( pFmt ), + pFollow( 0 ), + pMaster( 0 ), + pRef( pCnt ), + pAttr( pAt ), + bBackMoveLocked( FALSE ), + // --> OD 2005-08-11 #i49383# + mbUnlockPosOfLowerObjs( true ) + // <-- +{ + nType = FRMC_FTN; +} + +/************************************************************************* +|* +|* SwFtnFrm::InvalidateNxtFtnCnts() +|* +|* Ersterstellung MA 29. Jun. 93 +|* Letzte Aenderung MA 29. Jun. 93 +|* +|*************************************************************************/ + + +void SwFtnFrm::InvalidateNxtFtnCnts( SwPageFrm *pPage ) +{ + if ( GetNext() ) + { + SwFrm *pCnt = ((SwLayoutFrm*)GetNext())->ContainsAny(); + if( pCnt ) + { + pCnt->InvalidatePage( pPage ); + pCnt->_InvalidatePrt(); + do + { pCnt->_InvalidatePos(); + if( pCnt->IsSctFrm() ) + { + SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny(); + if( pTmp ) + pTmp->_InvalidatePos(); + } + pCnt->GetUpper()->_InvalidateSize(); + pCnt = pCnt->FindNext(); + } while ( pCnt && GetUpper()->IsAnLower( pCnt ) ); + } + } +} + +#ifdef DBG_UTIL + +SwTwips SwFtnFrm::GrowFrm( SwTwips nDist, BOOL bTst, BOOL bInfo ) +{ +#if OSL_DEBUG_LEVEL > 1 + static USHORT nNum = USHRT_MAX; + SwTxtFtn* pTxtFtn = GetAttr(); + if ( pTxtFtn->GetFtn().GetNumber() == nNum ) + { + int bla = 5; + (void)bla; + + } +#endif + return SwLayoutFrm::GrowFrm( nDist, bTst, bInfo ); +} + + +SwTwips SwFtnFrm::ShrinkFrm( SwTwips nDist, BOOL bTst, BOOL bInfo ) +{ +#if OSL_DEBUG_LEVEL > 1 + static USHORT nNum = USHRT_MAX; + if( nNum != USHRT_MAX ) + { + SwTxtFtn* pTxtFtn = GetAttr(); + if( &pTxtFtn->GetAttr() && pTxtFtn->GetFtn().GetNumber() == nNum ) + { + int bla = 5; + (void)bla; + } + } +#endif + return SwLayoutFrm::ShrinkFrm( nDist, bTst, bInfo ); +} +#endif + +/************************************************************************* +|* +|* SwFtnFrm::Cut() +|* +|* Ersterstellung MA 23. Feb. 94 +|* Letzte Aenderung MA 24. Jul. 95 +|* +|*************************************************************************/ + + +void SwFtnFrm::Cut() +{ + if ( GetNext() ) + GetNext()->InvalidatePos(); + else if ( GetPrev() ) + GetPrev()->SetRetouche(); + + //Erst removen, dann Upper Shrinken. + SwLayoutFrm *pUp = GetUpper(); + + //Verkettung korrigieren. + SwFtnFrm *pFtn = (SwFtnFrm*)this; + if ( pFtn->GetFollow() ) + pFtn->GetFollow()->SetMaster( pFtn->GetMaster() ); + if ( pFtn->GetMaster() ) + pFtn->GetMaster()->SetFollow( pFtn->GetFollow() ); + pFtn->SetFollow( 0 ); + pFtn->SetMaster( 0 ); + + // Alle Verbindungen kappen. + Remove(); + + if ( pUp ) + { + //Die letzte Fussnote nimmt ihren Container mit. + if ( !pUp->Lower() ) + { + SwPageFrm *pPage = pUp->FindPageFrm(); + if ( pPage ) + { + SwLayoutFrm *pBody = pPage->FindBodyCont(); + if ( !pBody->ContainsCntnt() ) + pPage->FindRootFrm()->SetSuperfluous(); + } + SwSectionFrm* pSect = pUp->FindSctFrm(); + pUp->Cut(); + delete pUp; + // Wenn der letzte Fussnotencontainer aus einem spaltigen Bereich verschwindet, + // so kann dieser, falls er keinen Follow besitzt, zusammenschrumpfen. + if( pSect && !pSect->ToMaximize( FALSE ) && !pSect->IsColLocked() ) + pSect->_InvalidateSize(); + } + else + { if ( Frm().Height() ) + pUp->Shrink( Frm().Height() ); + pUp->SetCompletePaint(); + pUp->InvalidatePage(); + } + } +} + +/************************************************************************* +|* +|* SwFtnFrm::Paste() +|* +|* Ersterstellung MA 23. Feb. 94 +|* Letzte Aenderung MA 23. Feb. 94 +|* +|*************************************************************************/ + + +void SwFtnFrm::Paste( SwFrm* pParent, SwFrm* pSibling ) +{ + ASSERT( pParent, "Kein Parent fuer Paste." ); + ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." ); + ASSERT( pParent != this, "Bin selbst der Parent." ); + ASSERT( pSibling != this, "Bin mein eigener Nachbar." ); + ASSERT( !GetPrev() && !GetNext() && !GetUpper(), + "Bin noch irgendwo angemeldet." ); + + //In den Baum einhaengen. + InsertBefore( (SwLayoutFrm*)pParent, pSibling ); + + SWRECTFN( this ) + if( (Frm().*fnRect->fnGetWidth)()!=(pParent->Prt().*fnRect->fnGetWidth)() ) + _InvalidateSize(); + _InvalidatePos(); + SwPageFrm *pPage = FindPageFrm(); + InvalidatePage( pPage ); + if ( GetNext() ) + GetNext()->_InvalidatePos(); + if( (Frm().*fnRect->fnGetHeight)() ) + pParent->Grow( (Frm().*fnRect->fnGetHeight)() ); + + //Wenn mein Vorgaenger mein Master ist und/oder wenn mein Nachfolger mein + //Follow ist so kann ich deren Inhalt uebernehmen und sie vernichten. + if ( GetPrev() && GetPrev() == GetMaster() ) + { ASSERT( SwFlowFrm::CastFlowFrm( GetPrev()->GetLower() ), + "Fussnote ohne Inhalt?" ); + (SwFlowFrm::CastFlowFrm( GetPrev()->GetLower()))-> + MoveSubTree( this, GetLower() ); + SwFrm *pDel = GetPrev(); + pDel->Cut(); + delete pDel; + } + if ( GetNext() && GetNext() == GetFollow() ) + { ASSERT( SwFlowFrm::CastFlowFrm( GetNext()->GetLower() ), + "Fussnote ohne Inhalt?" ); + (SwFlowFrm::CastFlowFrm( GetNext()->GetLower()))->MoveSubTree( this ); + SwFrm *pDel = GetNext(); + pDel->Cut(); + delete pDel; + } +#ifdef DBG_UTIL + SwDoc *pDoc = GetFmt()->GetDoc(); + if ( GetPrev() ) + { + ASSERT( lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetPrev())->GetAttr() ) <= + lcl_FindFtnPos( pDoc, GetAttr() ), "Prev ist not FtnPrev" ); + } + if ( GetNext() ) + { + ASSERT( lcl_FindFtnPos( pDoc, GetAttr() ) <= + lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetNext())->GetAttr() ), + "Next is not FtnNext" ); + } +#endif + InvalidateNxtFtnCnts( pPage ); +} + +/************************************************************************* +|* +|* SwFrm::GetNextFtnLeaf() +|* +|* Beschreibung Liefert das naechste LayoutBlatt in den das +|* Frame gemoved werden kann. +|* Neue Seiten werden nur dann erzeugt, wenn der Parameter TRUE ist. +|* Ersterstellung MA 16. Nov. 92 +|* Letzte Aenderung AMA 09. Nov. 98 +|* +|*************************************************************************/ + + +SwLayoutFrm *SwFrm::GetNextFtnLeaf( MakePageType eMakePage ) +{ + SwFtnBossFrm *pOldBoss = FindFtnBossFrm(); + SwPageFrm* pOldPage = pOldBoss->FindPageFrm(); + SwPageFrm* pPage; + SwFtnBossFrm *pBoss = pOldBoss->IsColumnFrm() ? + (SwFtnBossFrm*)pOldBoss->GetNext() : 0; // naechste Spalte, wenn vorhanden + if( pBoss ) + pPage = NULL; + else + { + if( pOldBoss->GetUpper()->IsSctFrm() ) + { // Das kann nur in einem spaltigen Bereich sein + SwLayoutFrm* pNxt = pOldBoss->GetNextSctLeaf( eMakePage ); + if( pNxt ) + { + ASSERT( pNxt->IsColBodyFrm(), "GetNextFtnLeaf: Funny Leaf" ); + pBoss = (SwFtnBossFrm*)pNxt->GetUpper(); + pPage = pBoss->FindPageFrm(); + } + else + return 0; + } + else + { + // naechste Seite + pPage = (SwPageFrm*)pOldPage->GetNext(); + // Leerseiten ueberspringen + if( pPage && pPage->IsEmptyPage() ) + pPage = (SwPageFrm*)pPage->GetNext(); + pBoss = pPage; + } + } + // Was haben wir jetzt? + // pBoss != NULL, pPage==NULL => pBoss ist die auf der gleichen Seite folgende Spalte + // pBoss != NULL, pPage!=NULL => pBoss und pPage sind die folgende Seite (Empty uebersprungen) + // pBoss == NULL => pPage == NULL, es gibt keine folgende Seite + + //Wenn die Fussnote bereits einen Follow hat brauchen wir nicht zu suchen. + //Wenn allerdings zwischen Ftn und Follow unerwuenschte Leerseiten/spalten + //herumlungern, so legen wir auf der naechstbesten Seite/Spalte einen weiteren + //Follow an, der Rest wird sich schon finden. + SwFtnFrm *pFtn = FindFtnFrm(); + if ( pFtn && pFtn->GetFollow() ) + { + SwFtnBossFrm* pTmpBoss = pFtn->GetFollow()->FindFtnBossFrm(); + // Folgende Faelle werden hier erkannt und akzeptiert + // 1. Die FtnBosse sind benachbarte Seiten oder benachbarte Spalten + // 2. Der neue ist die erste Spalte der benachbarten Seite + // 3. Der neue ist die erste Spalte in einem Bereich in der naechsten Spalte/Seite + while( pTmpBoss != pBoss && pTmpBoss && !pTmpBoss->GetPrev() ) + pTmpBoss = pTmpBoss->GetUpper()->FindFtnBossFrm(); + if( pTmpBoss == pBoss ) + return pFtn->GetFollow(); + } + + // Wenn wir keinen pBoss gefunden haben oder es sich um eine "falsche" Seite handelt, + // muss eine neue Seite her + if ( !pBoss || ( pPage && pPage->IsEndNotePage() && !pOldPage->IsEndNotePage() ) ) + { + if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) + { + pBoss = InsertPage( pOldPage, pOldPage->IsFtnPage() ); + ((SwPageFrm*)pBoss)->SetEndNotePage( pOldPage->IsEndNotePage() ); + } + else + return 0; + } + if( pBoss->IsPageFrm() ) + { // Wenn wir auf einer spaltigen Seite gelandet sind, + // gehen wir in die erste Spalte + SwLayoutFrm* pLay = pBoss->FindBodyCont(); + if( pLay && pLay->Lower() && pLay->Lower()->IsColumnFrm() ) + pBoss = (SwFtnBossFrm*)pLay->Lower(); + } + //Seite/Spalte gefunden, da schummeln wir uns doch gleich mal 'rein + SwFtnContFrm *pCont = pBoss->FindFtnCont(); + if ( !pCont && pBoss->GetMaxFtnHeight() && + ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) ) + pCont = pBoss->MakeFtnCont(); + return pCont; +} + +/************************************************************************* +|* +|* SwFrm::GetPrevFtnLeaf() +|* +|* Beschreibung Liefert das vorhergehende LayoutBlatt in das der +|* Frame gemoved werden kann. +|* Ersterstellung MA 16. Nov. 92 +|* Letzte Aenderung AMA 06. Nov. 98 +|* +|*************************************************************************/ + + +SwLayoutFrm *SwFrm::GetPrevFtnLeaf( MakePageType eMakeFtn ) +{ + //Der Vorgaenger fuer eine Fussnote ist falls moeglich der Master + //in der Fussnoteneigenen Verkettung. + SwLayoutFrm *pRet = 0; + SwFtnFrm *pFtn = FindFtnFrm(); + pRet = pFtn->GetMaster(); + + SwFtnBossFrm* pOldBoss = FindFtnBossFrm(); + SwPageFrm *pOldPage = pOldBoss->FindPageFrm(); + + if ( !pOldBoss->GetPrev() && !pOldPage->GetPrev() ) + return pRet; // es gibt weder eine Spalte noch eine Seite vor uns + + if ( !pRet ) + { + bool bEndn = pFtn->GetAttr()->GetFtn().IsEndNote(); + SwFrm* pTmpRef = NULL; + if( bEndn && pFtn->IsInSct() ) + { + SwSectionFrm* pSect = pFtn->FindSctFrm(); + if( pSect->IsEndnAtEnd() ) + pTmpRef = pSect->FindLastCntnt( FINDMODE_LASTCNT ); + } + if( !pTmpRef ) + pTmpRef = pFtn->GetRef(); + SwFtnBossFrm* pStop = pTmpRef->FindFtnBossFrm( !bEndn ); + + const USHORT nNum = pStop->GetPhyPageNum(); + + //Wenn die Fussnoten am Dokumentende angezeigt werden, so verlassen wir + //die Entsprechenden Seiten nicht. + //Selbiges gilt analog fuer die Endnotenseiten. + const BOOL bEndNote = pOldPage->IsEndNotePage(); + const BOOL bFtnEndDoc = pOldPage->IsFtnPage(); + SwFtnBossFrm* pNxtBoss = pOldBoss; + SwSectionFrm *pSect = pNxtBoss->GetUpper()->IsSctFrm() ? + (SwSectionFrm*)pNxtBoss->GetUpper() : 0; + + do + { + if( pNxtBoss->IsColumnFrm() && pNxtBoss->GetPrev() ) + pNxtBoss = (SwFtnBossFrm*)pNxtBoss->GetPrev(); // eine Spalte zurueck + else // oder eine Seite zurueck + { + SwLayoutFrm* pBody = 0; + if( pSect ) + { + if( pSect->IsFtnLock() ) + { + if( pNxtBoss == pOldBoss ) + return 0; + pStop = pNxtBoss; + } + else + { + pSect = (SwSectionFrm*)pSect->FindMaster(); + if( !pSect || !pSect->Lower() ) + return 0; + ASSERT( pSect->Lower()->IsColumnFrm(), + "GetPrevFtnLeaf: Where's the column?" ); + pNxtBoss = (SwFtnBossFrm*)pSect->Lower(); + pBody = pSect; + } + } + else + { + SwPageFrm* pPage = (SwPageFrm*)pNxtBoss->FindPageFrm()->GetPrev(); + if( !pPage || pPage->GetPhyPageNum() < nNum || + bEndNote != pPage->IsEndNotePage() || bFtnEndDoc != pPage->IsFtnPage() ) + return NULL; // Keine in Frage kommende Seite mehr gefunden + pNxtBoss = pPage; + pBody = pPage->FindBodyCont(); + } + // Die vorherige Seite haben wir nun, ggf. sollten wir in die letzte Spalte + // der Seite wechseln + if( pBody ) + { + if ( pBody->Lower() && pBody->Lower()->IsColumnFrm() ) + { + pNxtBoss = static_cast<SwFtnBossFrm*>(pBody->GetLastLower()); + } + } + } + SwFtnContFrm *pCont = pNxtBoss->FindFtnCont(); + if ( pCont ) + { + pRet = pCont; + break; + } + if ( pStop == pNxtBoss ) + { //Die Seite/Spalte auf der sich auch die Referenz tummelt, ist erreicht. + //Wir koennen jetzt probehalber mal einen Container erzeugen und + //uns hineinpasten. + if ( eMakeFtn == MAKEPAGE_FTN && pNxtBoss->GetMaxFtnHeight() ) + pRet = pNxtBoss->MakeFtnCont(); + break; + } + } while( !pRet ); + } + if ( pRet ) + { + const SwFtnBossFrm* pNewBoss = pRet->FindFtnBossFrm(); + BOOL bJump = FALSE; + if( pOldBoss->IsColumnFrm() && pOldBoss->GetPrev() ) // es gibt eine vorherige Spalte + bJump = pOldBoss->GetPrev() != (SwFrm*)pNewBoss; // sind wir darin gelandet? + else if( pNewBoss->IsColumnFrm() && pNewBoss->GetNext() ) + bJump = TRUE; // es gibt hinter dem neuen Boss noch eine Spalte, die aber nicht + // der alte Boss sein kann, das haben wir ja bereits geprueft. + else // hier landen wir nur, wenn neuer und alter Boss entweder Seiten oder letzte (neu) + { // bzw. erste (alt) Spalten einer Seite sind. In diesem Fall muss noch geprueft + // werden, ob Seiten ueberspringen wurden. + USHORT nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrm()->GetPhyPageNum(); + if ( nDiff > 2 || + (nDiff > 1 && !((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage()) ) + bJump = TRUE; + } + if( bJump ) + SwFlowFrm::SetMoveBwdJump( TRUE ); + } + return pRet; +} + +/************************************************************************* +|* +|* SwFrm::IsFtnAllowed() +|* +|* Ersterstellung MA 22. Mar. 94 +|* Letzte Aenderung MA 01. Dec. 94 +|* +|*************************************************************************/ + + +BOOL SwFrm::IsFtnAllowed() const +{ + if ( !IsInDocBody() ) + return FALSE; + + if ( IsInTab() ) + { + //Keine Ftns in wiederholten Headlines. + const SwTabFrm *pTab = ((SwFrm*)this)->ImplFindTabFrm(); + if ( pTab->IsFollow() ) + return !pTab->IsInHeadline( *this ); + } + return TRUE; +} + +/************************************************************************* +|* +|* SwRootFrm::UpdateFtnNums() +|* +|* Ersterstellung MA 02. Mar. 93 +|* Letzte Aenderung MA 09. Dec. 97 +|* +|*************************************************************************/ + + +void SwRootFrm::UpdateFtnNums() +{ + //Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist. + if ( GetFmt()->GetDoc()->GetFtnInfo().eNum == FTNNUM_PAGE ) + { + SwPageFrm *pPage = (SwPageFrm*)Lower(); + while ( pPage && !pPage->IsFtnPage() ) + { + pPage->UpdateFtnNum(); + pPage = (SwPageFrm*)pPage->GetNext(); + } + } +} + +/************************************************************************* +|* +|* RemoveFtns() Entfernen aller Fussnoten (nicht etwa die Referenzen) +|* und Entfernen aller Fussnotenseiten. +|* +|* Ersterstellung MA 05. Dec. 97 +|* Letzte Aenderung AMA 06. Nov. 98 +|* +|*************************************************************************/ + +void lcl_RemoveFtns( SwFtnBossFrm* pBoss, BOOL bPageOnly, BOOL bEndNotes ) +{ + do + { + SwFtnContFrm *pCont = pBoss->FindFtnCont(); + if ( pCont ) + { + SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower(); + ASSERT( pFtn, "FtnCont ohne Ftn." ); + if ( bPageOnly ) + while ( pFtn->GetMaster() ) + pFtn = pFtn->GetMaster(); + do + { + SwFtnFrm *pNxt = (SwFtnFrm*)pFtn->GetNext(); + if ( !pFtn->GetAttr()->GetFtn().IsEndNote() || + bEndNotes ) + { + pFtn->GetRef()->Prepare( PREP_FTN, (void*)pFtn->GetAttr() ); + if ( bPageOnly && !pNxt ) + pNxt = pFtn->GetFollow(); + pFtn->Cut(); + delete pFtn; + } + pFtn = pNxt; + + } while ( pFtn ); + } + if( !pBoss->IsInSct() ) + { + // A sectionframe with the Ftn/EndnAtEnd-flags may contain + // foot/endnotes. If the last lower frame of the bodyframe is + // a multicolumned sectionframe, it may contain footnotes, too. + SwLayoutFrm* pBody = pBoss->FindBodyCont(); + if( pBody && pBody->Lower() ) + { + SwFrm* pLow = pBody->Lower(); + while( pLow->GetNext() ) + { + if( pLow->IsSctFrm() && ( !pLow->GetNext() || + ((SwSectionFrm*)pLow)->IsAnyNoteAtEnd() ) && + ((SwSectionFrm*)pLow)->Lower() && + ((SwSectionFrm*)pLow)->Lower()->IsColumnFrm() ) + lcl_RemoveFtns( (SwColumnFrm*)((SwSectionFrm*)pLow)->Lower(), + bPageOnly, bEndNotes ); + pLow = pLow->GetNext(); + } + } + } + // noch 'ne Spalte? + pBoss = pBoss->IsColumnFrm() ? (SwColumnFrm*)pBoss->GetNext() : NULL; + } while( pBoss ); +} + +void SwRootFrm::RemoveFtns( SwPageFrm *pPage, BOOL bPageOnly, BOOL bEndNotes ) +{ + if ( !pPage ) + pPage = (SwPageFrm*)Lower(); + + do + { // Bei spaltigen Seiten muessen wir in allen Spalten aufraeumen + SwFtnBossFrm* pBoss; + SwLayoutFrm* pBody = pPage->FindBodyCont(); + if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() ) + pBoss = (SwFtnBossFrm*)pBody->Lower(); // die erste Spalte + else + pBoss = pPage; // keine Spalten + lcl_RemoveFtns( pBoss, bPageOnly, bEndNotes ); + if ( !bPageOnly ) + { + if ( pPage->IsFtnPage() && + (!pPage->IsEndNotePage() || bEndNotes) ) + { + SwFrm *pDel = pPage; + pPage = (SwPageFrm*)pPage->GetNext(); + pDel->Cut(); + delete pDel; + } + else + pPage = (SwPageFrm*)pPage->GetNext(); + } + else + break; + + } while ( pPage ); +} + +/************************************************************************* +|* +|* SetFtnPageDescs() Seitenvorlagen der Fussnotenseiten aendern +|* +|* Ersterstellung MA 11. Dec. 97 +|* Letzte Aenderung MA 11. Dec. 97 +|* +|*************************************************************************/ + +void SwRootFrm::CheckFtnPageDescs( BOOL bEndNote ) +{ + SwPageFrm *pPage = (SwPageFrm*)Lower(); + while ( pPage && !pPage->IsFtnPage() ) + pPage = (SwPageFrm*)pPage->GetNext(); + while ( pPage && pPage->IsEndNotePage() != bEndNote ) + pPage = (SwPageFrm*)pPage->GetNext(); + if ( pPage ) + SwFrm::CheckPageDescs( pPage, FALSE ); +} + + +/************************************************************************* +|* +|* SwFtnBossFrm::MakeFtnCont() +|* +|* Ersterstellung MA 25. Feb. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +SwFtnContFrm *SwFtnBossFrm::MakeFtnCont() +{ + //Einfuegen eines Fussnotencontainers. Der Fussnotencontainer sitzt + //immer direkt hinter dem Bodytext. + //Sein FrmFmt ist immer das DefaultFrmFmt. + +#ifdef DBG_UTIL + if ( FindFtnCont() ) + { ASSERT( !this, "Fussnotencontainer bereits vorhanden." ); + return 0; + } +#endif + + SwFtnContFrm *pNew = new SwFtnContFrm( GetFmt()->GetDoc()->GetDfltFrmFmt()); + SwLayoutFrm *pLay = FindBodyCont(); + pNew->Paste( this, pLay->GetNext() ); + return pNew; +} + +/************************************************************************* +|* +|* SwFtnBossFrm::FindFtnCont() +|* +|* Ersterstellung MA 25. Feb. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +SwFtnContFrm *SwFtnBossFrm::FindFtnCont() +{ + SwFrm *pFrm = Lower(); + while( pFrm && !pFrm->IsFtnContFrm() ) + pFrm = pFrm->GetNext(); + +#ifdef DBG_UTIL + if ( pFrm ) + { + SwFrm *pFtn = pFrm->GetLower(); + ASSERT( pFtn, "Cont ohne Fussnote." ); + while ( pFtn ) + { + ASSERT( pFtn->IsFtnFrm(), "Nachbar von Fussnote keine Fussnote." ); + pFtn = pFtn->GetNext(); + } + } +#endif + + return (SwFtnContFrm*)pFrm; +} + +/************************************************************************* +|* +|* SwFtnBossFrm::FindNearestFtnCont() Sucht den naechst greifbaren Fussnotencontainer. +|* +|* Ersterstellung MA 02. Aug. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + +SwFtnContFrm *SwFtnBossFrm::FindNearestFtnCont( BOOL bDontLeave ) +{ + SwFtnContFrm *pCont = 0; + if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() ) + { + pCont = FindFtnCont(); + if ( !pCont ) + { + SwPageFrm *pPage = FindPageFrm(); + SwFtnBossFrm* pBoss = this; + BOOL bEndNote = pPage->IsEndNotePage(); + do + { + BOOL bChgPage = lcl_NextFtnBoss( pBoss, pPage, bDontLeave ); + // Haben wir noch einen Boss gefunden? Bei einem Seitenwechsel muss + // zudem noch das EndNotenFlag uebereinstimmen + if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) ) + pCont = pBoss->FindFtnCont(); + } while ( !pCont && pPage ); + } + } + return pCont; +} + + +/************************************************************************* +|* +|* SwFtnBossFrm::FindFirstFtn() +|* +|* Beschreibung Erste Fussnote des Fussnotenbosses suchen. +|* Ersterstellung MA 26. Feb. 93 +|* Letzte Aenderung AMA 29. Oct. 99 +|* +|*************************************************************************/ + + +SwFtnFrm *SwFtnBossFrm::FindFirstFtn() +{ + //Erstmal den naechsten FussnotenContainer suchen. + SwFtnContFrm *pCont = FindNearestFtnCont(); + if ( !pCont ) + return 0; + + //Ab der ersten Fussnote im Container die erste suchen, die + //von der aktuellen Spalte (bzw. einspaltigen Seite) referenziert wird. + + SwFtnFrm *pRet = (SwFtnFrm*)pCont->Lower(); + const USHORT nRefNum = FindPageFrm()->GetPhyPageNum(); + const USHORT nRefCol = lcl_ColumnNum( this ); + USHORT nPgNum, nColNum; //Seitennummer, Spaltennummer + SwFtnBossFrm* pBoss; + SwPageFrm* pPage; + if( pRet ) + { + pBoss = pRet->GetRef()->FindFtnBossFrm(); + ASSERT( pBoss, "FindFirstFtn: No boss found" ); + if( !pBoss ) + return FALSE; // ?There must be a bug, but no GPF + pPage = pBoss->FindPageFrm(); + nPgNum = pPage->GetPhyPageNum(); + if ( nPgNum == nRefNum ) + { + nColNum = lcl_ColumnNum( pBoss ); + if( nColNum == nRefCol ) + return pRet; //hat ihn. + else if( nColNum > nRefCol ) + return NULL; //mind. eine Spalte zu weit. + } + else if ( nPgNum > nRefNum ) + return NULL; //mind. eine Seite zu weit. + } + else + return NULL; + // Ende, wenn Ref auf einer spaeteren Seite oder auf der gleichen Seite in einer + // spaeteren Spalte liegt + + do + { + while ( pRet->GetFollow() ) + pRet = pRet->GetFollow(); + + SwFtnFrm *pNxt = (SwFtnFrm*)pRet->GetNext(); + if ( !pNxt ) + { + pBoss = pRet->FindFtnBossFrm(); + pPage = pBoss->FindPageFrm(); + lcl_NextFtnBoss( pBoss, pPage, FALSE ); // naechster FtnBoss + pCont = pBoss ? pBoss->FindNearestFtnCont() : 0; + if ( pCont ) + pNxt = (SwFtnFrm*)pCont->Lower(); + } + if ( pNxt ) + { + pRet = pNxt; + pBoss = pRet->GetRef()->FindFtnBossFrm(); + pPage = pBoss->FindPageFrm(); + nPgNum = pPage->GetPhyPageNum(); + if ( nPgNum == nRefNum ) + { + nColNum = lcl_ColumnNum( pBoss ); + if( nColNum == nRefCol ) + break; //hat ihn. + else if( nColNum > nRefCol ) + pRet = 0; //mind. eine Spalte zu weit. + } + else if ( nPgNum > nRefNum ) + pRet = 0; //mind. eine Seite zu weit. + } + else + pRet = 0; //Gibt eben keinen. + } while( pRet ); + return pRet; +} + +/************************************************************************* +|* +|* SwFtnBossFrm::FindFirstFtn() +|* +|* Beschreibunt Erste Fussnote zum Cnt suchen. +|* Ersterstellung MA 04. Mar. 93 +|* Letzte Aenderung AMA 28. Oct. 98 +|* +|*************************************************************************/ + + +const SwFtnFrm *SwFtnBossFrm::FindFirstFtn( SwCntntFrm *pCnt ) const +{ + const SwFtnFrm *pRet = ((SwFtnBossFrm*)this)->FindFirstFtn(); + if ( pRet ) + { + const USHORT nColNum = lcl_ColumnNum( this ); //Spaltennummer + const USHORT nPageNum = GetPhyPageNum(); + while ( pRet && (pRet->GetRef() != pCnt) ) + { + while ( pRet->GetFollow() ) + pRet = pRet->GetFollow(); + + if ( pRet->GetNext() ) + pRet = (const SwFtnFrm*)pRet->GetNext(); + else + { SwFtnBossFrm *pBoss = (SwFtnBossFrm*)pRet->FindFtnBossFrm(); + SwPageFrm *pPage = pBoss->FindPageFrm(); + lcl_NextFtnBoss( pBoss, pPage, FALSE ); // naechster FtnBoss + SwFtnContFrm *pCont = pBoss ? pBoss->FindNearestFtnCont() : 0; + pRet = pCont ? (SwFtnFrm*)pCont->Lower() : 0; + } + if ( pRet ) + { + const SwFtnBossFrm* pBoss = pRet->GetRef()->FindFtnBossFrm(); + if( pBoss->GetPhyPageNum() != nPageNum || + nColNum != lcl_ColumnNum( pBoss ) ) + pRet = 0; + } + } + } + return pRet; +} + +/************************************************************************* +|* +|* SwFtnBossFrm::ResetFtn() +|* +|* Ersterstellung MA 11. May. 95 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +void SwFtnBossFrm::ResetFtn( const SwFtnFrm *pCheck ) +{ + //Vernichten der Inkarnationen von Fussnoten zum Attribut, wenn sie nicht + //zu pAssumed gehoeren. + ASSERT( !pCheck->GetMaster(), "Master not an Master." ); + + SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 ); + SwCntntNode *pNd = aIdx.GetNode().GetCntntNode(); + if ( !pNd ) + pNd = pCheck->GetFmt()->GetDoc()-> + GetNodes().GoNextSection( &aIdx, TRUE, FALSE ); + SwClientIter aIter( *pNd ); + SwClient* pLast = aIter.GoStart(); + while( pLast ) + { + if ( pLast->ISA(SwFrm) ) + { + SwFrm *pFrm = (SwFrm*)pLast; + SwFrm *pTmp = pFrm->GetUpper(); + while ( pTmp && !pTmp->IsFtnFrm() ) + pTmp = pTmp->GetUpper(); + + SwFtnFrm *pFtn = (SwFtnFrm*)pTmp; + while ( pFtn && pFtn->GetMaster() ) + pFtn = pFtn->GetMaster(); + if ( pFtn != pCheck ) + { + while ( pFtn ) + { + SwFtnFrm *pNxt = pFtn->GetFollow(); + pFtn->Cut(); + delete pFtn; + pFtn = pNxt; + } + } + } + pLast = ++aIter; + } +} + +/************************************************************************* +|* +|* SwFtnBossFrm::InsertFtn() +|* +|* Ersterstellung MA 26. Feb. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +void SwFtnBossFrm::InsertFtn( SwFtnFrm* pNew ) +{ +#if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL) + static USHORT nStop = 0; + if ( nStop == pNew->GetFrmId() ) + { + int bla = 5; + (void)bla; + } +#endif + //Die Fussnote haben wir, sie muss jetzt nur noch irgendwo + //hin und zwar vor die Fussnote, deren Attribut vor das + //der neuen zeigt (Position wird ueber das Doc ermittelt) + //Gibt es in diesem Fussnotenboss noch keine Fussnoten, so muss eben ein + //Container erzeugt werden. + //Gibt es bereits einen Container aber noch keine Fussnote zu diesem + //Fussnotenboss, so muss die Fussnote hinter die letzte Fussnote der dichtesten + //Vorseite/spalte. + + ResetFtn( pNew ); + SwFtnFrm *pSibling = FindFirstFtn(); + BOOL bDontLeave = FALSE; + + // Ok, a sibling has been found, but is the sibling in an acceptable + // environment? + if( IsInSct() ) + { + SwSectionFrm* pMySect = ImplFindSctFrm(); + bool bEndnt = pNew->GetAttr()->GetFtn().IsEndNote(); + if( bEndnt ) + { + const SwSectionFmt* pEndFmt = pMySect->GetEndSectFmt(); + bDontLeave = 0 != pEndFmt; + if( pSibling ) + { + if( pEndFmt ) + { + if( !pSibling->IsInSct() || + !pSibling->ImplFindSctFrm()->IsDescendantFrom( pEndFmt ) ) + pSibling = NULL; + } + else if( pSibling->IsInSct() ) + pSibling = NULL; + } + } + else + { + bDontLeave = pMySect->IsFtnAtEnd(); + if( pSibling ) + { + if( pMySect->IsFtnAtEnd() ) + { + if( !pSibling->IsInSct() || + !pMySect->IsAnFollow( pSibling->ImplFindSctFrm() ) ) + pSibling = NULL; + } + else if( pSibling->IsInSct() ) + pSibling = NULL; + } + } + } + + if( pSibling && pSibling->FindPageFrm()->IsEndNotePage() != + FindPageFrm()->IsEndNotePage() ) + pSibling = NULL; + + //Damit die Position herausgefunden werden kann. + SwDoc *pDoc = GetFmt()->GetDoc(); + const ULONG nStPos = ::lcl_FindFtnPos( pDoc, pNew->GetAttr() ); + + ULONG nCmpPos = 0; + ULONG nLastPos = 0; + SwFtnContFrm *pParent = 0; + if( pSibling ) + { + nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); + if( nCmpPos > nStPos ) + pSibling = NULL; + } + + if ( !pSibling ) + { pParent = FindFtnCont(); + if ( !pParent ) + { + //Es gibt noch keinen FussnotenContainer, also machen wir einen. + //HAAAAAAAALT! So einfach ist das leider mal wieder nicht: Es kann + //sein, dass irgendeine naechste Fussnote existiert die vor der + //einzufuegenden zu stehen hat, weil z.B. eine Fussnote ueber zig + //Seiten aufgespalten ist usw. + pParent = FindNearestFtnCont( bDontLeave ); + if ( pParent ) + { + SwFtnFrm *pFtn = (SwFtnFrm*)pParent->Lower(); + if ( pFtn ) + { + + nCmpPos = ::lcl_FindFtnPos( pDoc, pFtn->GetAttr() ); + if ( nCmpPos > nStPos ) + pParent = 0; + } + else + pParent = 0; + } + } + if ( !pParent ) + //Jetzt kann aber ein Fussnotencontainer gebaut werden. + pParent = MakeFtnCont(); + else + { + //Ausgehend von der ersten Fussnote unterhalb des Parents wird die + //erste Fussnote gesucht deren Index hinter dem Index der + //einzufuegenden liegt; vor dieser kann der neue dann gepastet + //werden. + pSibling = (SwFtnFrm*)pParent->Lower(); + if ( !pSibling ) + { ASSERT( !this, "Keinen Platz fuer Fussnote gefunden."); + return; + } + nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); + + SwFtnBossFrm *pNxtB = this; //Immer den letzten merken, damit wir nicht + SwFtnFrm *pLastSib = 0; //ueber das Ziel hinausschiessen. + + while ( pSibling && nCmpPos <= nStPos ) + { + pLastSib = pSibling; // der kommt schon mal in Frage + nLastPos = nCmpPos; + + while ( pSibling->GetFollow() ) + pSibling = pSibling->GetFollow(); + + if ( pSibling->GetNext() ) + { + pSibling = (SwFtnFrm*)pSibling->GetNext(); + ASSERT( !pSibling->GetMaster() || ( ENDNOTE > nStPos && + pSibling->GetAttr()->GetFtn().IsEndNote() ), + "InsertFtn: Master expected I" ); + } + else + { + pNxtB = pSibling->FindFtnBossFrm(); + SwPageFrm *pSibPage = pNxtB->FindPageFrm(); + BOOL bEndNote = pSibPage->IsEndNotePage(); + BOOL bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave ); + // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden. + SwFtnContFrm *pCont = pNxtB && ( !bChgPage || + pSibPage->IsEndNotePage() == bEndNote ) + ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0; + if( pCont ) + pSibling = (SwFtnFrm*)pCont->Lower(); + else // kein weiterer FtnContainer, dann werden wir uns wohl hinter + break; // pSibling haengen + } + if ( pSibling ) + { + nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); + ASSERT( nCmpPos > nLastPos, "InsertFtn: Order of FtnFrm's buggy" ); + } + } + // pLastSib ist jetzt die letzte Fussnote vor uns, + // pSibling leer oder die erste nach uns. + if ( pSibling && pLastSib && (pSibling != pLastSib) ) + { //Sind wir vielleicht bereits ueber das Ziel hinausgeschossen? + if ( nCmpPos > nStPos ) + pSibling = pLastSib; + } + else if ( !pSibling ) + { //Eine Chance haben wir noch: wir nehmen einfach die letzte + //Fussnote im Parent. Ein Sonderfall, der z.B. beim + //zurueckfliessen von Absaetzen mit mehreren Fussnoten + //vorkommt. + //Damit wir nicht die Reihenfolge verwuerfeln muessen wir den + //Parent der letzten Fussnote, die wir an der Hand hatten benutzen. + pSibling = pLastSib; + while( pSibling->GetFollow() ) + pSibling = pSibling->GetFollow(); + ASSERT( !pSibling->GetNext(), "InsertFtn: Who's that guy?" ); + } + } + } + else + { //Die erste Fussnote der Spalte/Seite haben wir an der Hand, jetzt ausgehend + //von dieser die erste zur selben Spalte/Seite suchen deren Index hinter + //den uebergebenen zeigt, die letzte, die wir an der Hand hatten, ist + //dann der Vorgaenger. + SwFtnBossFrm* pBoss = pNew->GetRef()->FindFtnBossFrm( + !pNew->GetAttr()->GetFtn().IsEndNote() ); + USHORT nRefNum = pBoss->GetPhyPageNum(); // Die Seiten- und + USHORT nRefCol = lcl_ColumnNum( pBoss ); // Spaltennummer der neuen Fussnote + BOOL bEnd = FALSE; + SwFtnFrm *pLastSib = 0; + while ( pSibling && !bEnd && (nCmpPos <= nStPos) ) + { + pLastSib = pSibling; + nLastPos = nCmpPos; + + while ( pSibling->GetFollow() ) + pSibling = pSibling->GetFollow(); + + SwFtnFrm *pFoll = (SwFtnFrm*)pSibling->GetNext(); + if ( pFoll ) + { + pBoss = pSibling->GetRef()->FindFtnBossFrm( !pSibling-> + GetAttr()->GetFtn().IsEndNote() ); + USHORT nTmpRef; + if( nStPos >= ENDNOTE || + (nTmpRef = pBoss->GetPhyPageNum()) < nRefNum || + ( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol )) + pSibling = pFoll; + else + bEnd = TRUE; + } + else + { + SwFtnBossFrm* pNxtB = pSibling->FindFtnBossFrm(); + SwPageFrm *pSibPage = pNxtB->FindPageFrm(); + BOOL bEndNote = pSibPage->IsEndNotePage(); + BOOL bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave ); + // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden. + SwFtnContFrm *pCont = pNxtB && ( !bChgPage || + pSibPage->IsEndNotePage() == bEndNote ) + ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0; + if ( pCont ) + pSibling = (SwFtnFrm*)pCont->Lower(); + else + bEnd = TRUE; + } + if ( !bEnd && pSibling ) + nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); + if ( pSibling && pLastSib && (pSibling != pLastSib) ) + { //Sind wir vielleicht bereits ueber das Ziel hinausgeschossen? + if ( (nLastPos < nCmpPos) && (nCmpPos > nStPos) ) + { + pSibling = pLastSib; + bEnd = TRUE; + } + } + } + } + if ( pSibling ) + { + nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); + if ( nCmpPos < nStPos ) + { + while ( pSibling->GetFollow() ) + pSibling = pSibling->GetFollow(); + pParent = (SwFtnContFrm*)pSibling->GetUpper(); + pSibling = (SwFtnFrm*)pSibling->GetNext(); + } + else + { + if( pSibling->GetMaster() ) + { + if( ENDNOTE > nCmpPos || nStPos >= ENDNOTE ) + { + ASSERT( FALSE, "InsertFtn: Master expected II" ); + do + pSibling = pSibling->GetMaster(); + while ( pSibling->GetMaster() ); + } + } + pParent = (SwFtnContFrm*)pSibling->GetUpper(); + } + } + ASSERT( pParent, "paste in space?" ); + pNew->Paste( pParent, pSibling ); +} + +/************************************************************************* +|* +|* SwFtnBossFrm::AppendFtn() +|* +|* Ersterstellung MA 25. Feb. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +void SwFtnBossFrm::AppendFtn( SwCntntFrm *pRef, SwTxtFtn *pAttr ) +{ + //Wenn es die Fussnote schon gibt tun wir nix. + if ( FindFtn( pRef, pAttr ) ) + return; + + //Wenn Fussnoten am Dokumentende eingestellt sind, so brauchen wir 'eh erst + //ab der entsprechenden Seite zu suchen. + //Wenn es noch keine gibt, muss eben eine erzeugt werden. + //Wenn es sich um eine Endnote handelt, muss eine Endnotenseite gesucht + //bzw. erzeugt werden. + SwDoc *pDoc = GetFmt()->GetDoc(); + SwFtnBossFrm *pBoss = this; + SwPageFrm *pPage = FindPageFrm(); + SwPageFrm *pMyPage = pPage; + BOOL bChgPage = FALSE; + BOOL bEnd = FALSE; + if ( pAttr->GetFtn().IsEndNote() ) + { + bEnd = TRUE; + if( GetUpper()->IsSctFrm() && + ((SwSectionFrm*)GetUpper())->IsEndnAtEnd() ) + { + SwFrm* pLast = + ((SwSectionFrm*)GetUpper())->FindLastCntnt( FINDMODE_ENDNOTE ); + if( pLast ) + { + pBoss = pLast->FindFtnBossFrm(); + pPage = pBoss->FindPageFrm(); + } + } + else + { + while ( pPage->GetNext() && !pPage->IsEndNotePage() ) + { + pPage = (SwPageFrm*)pPage->GetNext(); + bChgPage = TRUE; + } + if ( !pPage->IsEndNotePage() ) + { + SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc ); + pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(), + !pPage->OnRightPage(), FALSE, TRUE, 0 ); + pPage->SetEndNotePage( TRUE ); + bChgPage = TRUE; + } + else + { + //Wir koennen wenigstens schon mal ungefaehr die richtige Seite + //suchen. Damit stellen wir sicher das wir auch bei hunderten + //Fussnoten noch in endlicher Zeit fertig werden. + SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext(); + const ULONG nStPos = ::lcl_FindFtnPos( pDoc, pAttr ); + while ( pNxt && pNxt->IsEndNotePage() ) + { + SwFtnContFrm *pCont = pNxt->FindFtnCont(); + if ( pCont && pCont->Lower() ) + { + ASSERT( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" ); + if ( nStPos > ::lcl_FindFtnPos( pDoc, + ((SwFtnFrm*)pCont->Lower())->GetAttr())) + { + pPage = pNxt; + pNxt = (SwPageFrm*)pPage->GetNext(); + continue; + } + } + break; + } + } + } + } + else if( FTNPOS_CHAPTER == pDoc->GetFtnInfo().ePos && ( !GetUpper()-> + IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd() ) ) + { + while ( pPage->GetNext() && !pPage->IsFtnPage() && + !((SwPageFrm*)pPage->GetNext())->IsEndNotePage() ) + { + pPage = (SwPageFrm*)pPage->GetNext(); + bChgPage = TRUE; + } + + if ( !pPage->IsFtnPage() ) + { + SwPageDesc *pDesc = pDoc->GetFtnInfo().GetPageDesc( *pDoc ); + pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(), + !pPage->OnRightPage(), FALSE, TRUE, pPage->GetNext() ); + bChgPage = TRUE; + } + else + { + //Wir koennen wenigstens schon mal ungefaehr die richtige Seite + //suchen. Damit stellen wir sicher das wir auch bei hunderten + //Fussnoten noch in endlicher Zeit fertig werden. + SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext(); + const ULONG nStPos = ::lcl_FindFtnPos( pDoc, pAttr ); + while ( pNxt && pNxt->IsFtnPage() && !pNxt->IsEndNotePage() ) + { + SwFtnContFrm *pCont = pNxt->FindFtnCont(); + if ( pCont && pCont->Lower() ) + { + ASSERT( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" ); + if ( nStPos > ::lcl_FindFtnPos( pDoc, + ((SwFtnFrm*)pCont->Lower())->GetAttr())) + { + pPage = pNxt; + pNxt = (SwPageFrm*)pPage->GetNext(); + continue; + } + } + break; + } + } + } + + //Erstmal eine Fussnote und die benoetigten CntntFrms anlegen. + if ( !pAttr->GetStartNode() ) + { ASSERT( !this, "Kein Fussnoteninhalt." ); + return; + } + + // Wenn es auf der Seite/Spalte bereits einen FtnCont gibt, + // kann in einen spaltigen Bereich keiner erzeugt werden. + if( pBoss->IsInSct() && pBoss->IsColumnFrm() && !pPage->IsFtnPage() ) + { + SwSectionFrm* pSct = pBoss->FindSctFrm(); + if( bEnd ? !pSct->IsEndnAtEnd() : !pSct->IsFtnAtEnd() ) + { + SwFtnContFrm* pFtnCont = pSct->FindFtnBossFrm(!bEnd)->FindFtnCont(); + if( pFtnCont ) + { + SwFtnFrm* pTmp = (SwFtnFrm*)pFtnCont->Lower(); + if( bEnd ) + while( pTmp && !pTmp->GetAttr()->GetFtn().IsEndNote() ) + pTmp = (SwFtnFrm*)pTmp->GetNext(); + if( pTmp && *pTmp < pAttr ) + return; + } + } + } + + SwFtnFrm *pNew = new SwFtnFrm( pDoc->GetDfltFrmFmt(), pRef, pAttr ); + { + SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 ); + ::_InsertCnt( pNew, pDoc, aIdx.GetIndex() ); + } + // Wenn die Seite gewechselt (oder gar neu angelegt) wurde, + // muessen wir uns dort in die erste Spalte setzen + if( bChgPage ) + { + SwLayoutFrm* pBody = pPage->FindBodyCont(); + ASSERT( pBody, "AppendFtn: NoPageBody?" ); + if( pBody->Lower() && pBody->Lower()->IsColumnFrm() ) + pBoss = (SwFtnBossFrm*)pBody->Lower(); + else + pBoss = pPage; // bei nichtspaltigen Seiten auf die Seite selbst + } + pBoss->InsertFtn( pNew ); + if ( pNew->GetUpper() ) //Eingesetzt oder nicht? + { + ::RegistFlys( pNew->FindPageFrm(), pNew ); + SwSectionFrm* pSect = FindSctFrm(); + // Der Inhalt des FtnContainers in einem (spaltigen) Bereich + // braucht nur kalkuliert zu werden, + // wenn der Bereich bereits bis zur Unterkante seines Uppers geht. + if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() : + !pSect->IsFtnAtEnd() ) && pSect->Growable() ) + pSect->InvalidateSize(); + else + { + // --> OD 2005-05-18 #i49383# - disable unlock of position of + // lower objects during format of footnote content. + const bool bOldFtnFrmLocked( pNew->IsColLocked() ); + pNew->ColLock(); + pNew->KeepLockPosOfLowerObjs(); + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // no extra notify for footnote frame +// SwLayNotify* pFtnFrmNotitfy = new SwLayNotify( pNew ); + // <-- + SwCntntFrm *pCnt = pNew->ContainsCntnt(); + while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr ) + { + pCnt->Calc(); + // --> OD 2005-05-17 #i49383# - format anchored objects + if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) + { + if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, + *(pCnt->FindPageFrm()) ) ) + { + // restart format with first content + pCnt = pNew->ContainsCntnt(); + continue; + } + } + // <-- + pCnt = (SwCntntFrm*)pCnt->FindNextCnt(); + } + // --> OD 2005-05-18 #i49383# + if ( !bOldFtnFrmLocked ) + { + pNew->ColUnlock(); + } + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // enable lock of lower object position before format of footnote frame. + pNew->UnlockPosOfLowerObjs(); + // <-- + pNew->Calc(); + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // no extra notify for footnote frame +// pNew->UnlockPosOfLowerObjs(); +// delete pFtnFrmNotitfy; + // <-- + if ( !bOldFtnFrmLocked && !pNew->GetLower() && + !pNew->IsColLocked() && !pNew->IsBackMoveLocked() ) + { + pNew->Cut(); + delete pNew; + } + // <-- + } + pMyPage->UpdateFtnNum(); + } + else + delete pNew; +} +/************************************************************************* +|* +|* SwFtnBossFrm::FindFtn() +|* +|* Ersterstellung MA 25. Feb. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +SwFtnFrm *SwFtnBossFrm::FindFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr ) +{ + //Der einfachste und sicherste Weg geht ueber das Attribut. + ASSERT( pAttr->GetStartNode(), "FtnAtr ohne StartNode." ); + SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 ); + SwCntntNode *pNd = aIdx.GetNode().GetCntntNode(); + if ( !pNd ) + pNd = pRef->GetAttrSet()->GetDoc()-> + GetNodes().GoNextSection( &aIdx, TRUE, FALSE ); + if ( !pNd ) + return 0; + SwClientIter aIter( *pNd ); + SwClient *pClient; + if ( 0 != (pClient = aIter.GoStart()) ) + do + { + if ( pClient->IsA( TYPE(SwFrm) ) ) + { + SwFrm *pFrm = ((SwFrm*)pClient)->GetUpper(); + // #i28500#, #i27243# Due to the endnode collector, there are + // SwFtnFrms, which are not in the layout. Therefore the + // bInfFtn flags are not set correctly, and a cell of FindFtnFrm + // would return 0. Therefore we better call ImplFindFtnFrm(). + SwFtnFrm *pFtn = pFrm->ImplFindFtnFrm(); + if ( pFtn && pFtn->GetRef() == pRef ) + { + // The following condition becomes true, if the whole + // footnotecontent is a section. While no frames exist, + // the HiddenFlag of the section is set, this causes + // the GoNextSection-function leaves the footnote. + if( pFtn->GetAttr() != pAttr ) + return 0; + while ( pFtn && pFtn->GetMaster() ) + pFtn = pFtn->GetMaster(); + return pFtn; + } + } + } while ( 0 != (pClient = aIter++) ); + + return 0; +} +/************************************************************************* +|* +|* SwFtnBossFrm::RemoveFtn() +|* +|* Ersterstellung MA 25. Feb. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +void SwFtnBossFrm::RemoveFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr, + BOOL bPrep ) +{ + SwFtnFrm *pFtn = FindFtn( pRef, pAttr ); + if( pFtn ) + { + do + { + SwFtnFrm *pFoll = pFtn->GetFollow(); + pFtn->Cut(); + delete pFtn; + pFtn = pFoll; + } while ( pFtn ); + if( bPrep && pRef->IsFollow() ) + { + ASSERT( pRef->IsTxtFrm(), "NoTxtFrm has Footnote?" ); + SwTxtFrm* pMaster = (SwTxtFrm*)pRef->FindMaster(); + if( !pMaster->IsLocked() ) + pMaster->Prepare( PREP_FTN_GONE ); + } + } + FindPageFrm()->UpdateFtnNum(); +} + +/************************************************************************* +|* +|* SwFtnBossFrm::ChangeFtnRef() +|* +|* Ersterstellung MA 25. Feb. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +void SwFtnBossFrm::ChangeFtnRef( const SwCntntFrm *pOld, const SwTxtFtn *pAttr, + SwCntntFrm *pNew ) +{ + SwFtnFrm *pFtn = FindFtn( pOld, pAttr ); + while ( pFtn ) + { + pFtn->SetRef( pNew ); + pFtn = pFtn->GetFollow(); + } +} + +/************************************************************************* +|* +|* SwFtnBossFrm::CollectFtns() +|* +|* Ersterstellung MA 24. Jul. 95 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +/// OD 03.04.2003 #108446# - add parameter <_bCollectOnlyPreviousFtns> in +/// order to control, if only footnotes, which are positioned before the +/// footnote boss frame <this> have to be collected. +void SwFtnBossFrm::CollectFtns( const SwCntntFrm* _pRef, + SwFtnBossFrm* _pOld, + SvPtrarr& _rFtnArr, + const sal_Bool _bCollectOnlyPreviousFtns ) +{ + SwFtnFrm *pFtn = _pOld->FindFirstFtn(); + while( !pFtn ) + { + if( _pOld->IsColumnFrm() ) + { // Spalten abklappern + while ( !pFtn && _pOld->GetPrev() ) + { + //Wenn wir keine Fussnote gefunden haben, ist noch nicht alles zu + //spaet. Die Schleife wird beim Aufnehmen von Follow-Zeilen durch + //Tabellen benoetigt. Fuer alle anderen Faelle ist sie in der Lage + //'krumme' Verhaeltnisse zu korrigieren. + _pOld = (SwFtnBossFrm*)_pOld->GetPrev(); + pFtn = _pOld->FindFirstFtn(); + } + } + if( !pFtn ) + { + // vorherige Seite + SwPageFrm* pPg; + for ( SwFrm* pTmp = _pOld; + 0 != ( pPg = (SwPageFrm*)pTmp->FindPageFrm()->GetPrev()) + && pPg->IsEmptyPage() ; + ) + { + pTmp = pPg; + } + if( !pPg ) + return; + + SwLayoutFrm* pBody = pPg->FindBodyCont(); + if( pBody->Lower() && pBody->Lower()->IsColumnFrm() ) + { + // mehrspaltige Seite => letzte Spalte suchen + _pOld = static_cast<SwFtnBossFrm*>(pBody->GetLastLower()); + } + else + _pOld = pPg; // einspaltige Seite + pFtn = _pOld->FindFirstFtn(); + } + } + // OD 03.04.2003 #108446# - consider new parameter <_bCollectOnlyPreviousFtns> + SwFtnBossFrm* pRefBossFrm = NULL; + if ( _bCollectOnlyPreviousFtns ) + { + pRefBossFrm = this; + } + _CollectFtns( _pRef, pFtn, _rFtnArr, _bCollectOnlyPreviousFtns, pRefBossFrm ); +} + + +/************************************************************************* +|* +|* SwFtnBossFrm::_CollectFtns() +|* +|* Ersterstellung MA 24. Jul. 95 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ +inline void FtnInArr( SvPtrarr& rFtnArr, SwFtnFrm* pFtn ) +{ + if ( USHRT_MAX == rFtnArr.GetPos( (VoidPtr)pFtn ) ) + rFtnArr.Insert( (VoidPtr)pFtn, rFtnArr.Count() ); +} + +/// OD 03.04.2003 #108446# - add parameters <_bCollectOnlyPreviousFtns> and +/// <_pRefFtnBossFrm> in order to control, if only footnotes, which are positioned +/// before the given reference footnote boss frame have to be collected. +/// Note: if parameter <_bCollectOnlyPreviousFtns> is true, then parameter +/// <_pRefFtnBossFrm> have to be referenced to an object. +/// Adjust parameter names. +void SwFtnBossFrm::_CollectFtns( const SwCntntFrm* _pRef, + SwFtnFrm* _pFtn, + SvPtrarr& _rFtnArr, + sal_Bool _bCollectOnlyPreviousFtns, + const SwFtnBossFrm* _pRefFtnBossFrm) +{ + // OD 03.04.2003 #108446# - assert, that no reference footnote boss frame + // is set, in spite of the order, that only previous footnotes has to be + // collected. + ASSERT( !_bCollectOnlyPreviousFtns || _pRefFtnBossFrm, + "<SwFtnBossFrm::_CollectFtns(..)> - No reference footnote boss frame for collecting only previous footnotes set.\nCrash will be caused!" ); + + //Alle Fussnoten die von pRef referenziert werden nacheinander + //einsammeln (Attribut fuer Attribut), zusammengefuegen + //(der Inhalt zu einem Attribut kann ueber mehrere Seiten verteilt sein) + //und ausschneiden. + + SvPtrarr aNotFtnArr( 20, 20 ); //Zur Robustheit werden hier die nicht + //dazugehoerigen Fussnoten eingetragen. + //Wenn eine Fussnote zweimal angefasst wird + //ists vorbei! So kommt die Funktion auch + //noch mit einem kaputten Layout + //einigermassen (ohne Schleife und Absturz) + //"klar". + + //Hier sollte keiner mit einer Follow-Ftn ankommen, es sei denn er hat + //ernste Absichten (:-)); spricht er kommt mit einer Ftn an die vor der + //ersten der Referenz liegt. + ASSERT( !_pFtn->GetMaster() || _pFtn->GetRef() != _pRef, "FollowFtn moven?" ); + while ( _pFtn->GetMaster() ) + _pFtn = _pFtn->GetMaster(); + + BOOL bFound = FALSE; + + while ( _pFtn ) + { + //Erstmal die naechste Fussnote der Spalte/Seite suchen, damit wir nicht + //nach dem Cut jeder Fussnote von vorn anfangen muessen. + SwFtnFrm *pNxtFtn = _pFtn; + while ( pNxtFtn->GetFollow() ) + pNxtFtn = pNxtFtn->GetFollow(); + pNxtFtn = (SwFtnFrm*)pNxtFtn->GetNext(); + + if ( !pNxtFtn ) + { + SwFtnBossFrm* pBoss = _pFtn->FindFtnBossFrm(); + SwPageFrm* pPage = pBoss->FindPageFrm(); + do + { + lcl_NextFtnBoss( pBoss, pPage, FALSE ); + if( pBoss ) + { + SwLayoutFrm* pCont = pBoss->FindFtnCont(); + if( pCont ) + { + pNxtFtn = (SwFtnFrm*)pCont->Lower(); + if( pNxtFtn ) + { + while( pNxtFtn->GetMaster() ) + pNxtFtn = pNxtFtn->GetMaster(); + if( pNxtFtn == _pFtn ) + pNxtFtn = NULL; + } + } + } + } while( !pNxtFtn && pBoss ); + } + else if( !pNxtFtn->GetAttr()->GetFtn().IsEndNote() ) + { ASSERT( !pNxtFtn->GetMaster(), "_CollectFtn: Master exspected" ); + while ( pNxtFtn->GetMaster() ) + pNxtFtn = pNxtFtn->GetMaster(); + } + if ( pNxtFtn == _pFtn ) + { + ASSERT( FALSE, "_CollectFtn: Devil's circle" ); + pNxtFtn = 0; + } + + // OD 03.04.2003 #108446# - determine, if found footnote has to be collected. + sal_Bool bCollectFoundFtn = sal_False; + if ( _pFtn->GetRef() == _pRef && !_pFtn->GetAttr()->GetFtn().IsEndNote() ) + { + if ( _bCollectOnlyPreviousFtns ) + { + SwFtnBossFrm* pBossOfFoundFtn = _pFtn->FindFtnBossFrm( sal_True ); + ASSERT( pBossOfFoundFtn, + "<SwFtnBossFrm::_CollectFtns(..)> - footnote boss frame of found footnote frame missing.\nWrong layout!" ); + if ( !pBossOfFoundFtn || // don't crash, if no footnote boss is found. + pBossOfFoundFtn->IsBefore( _pRefFtnBossFrm ) + ) + { + bCollectFoundFtn = sal_True; + } + } + else + { + bCollectFoundFtn = sal_True; + } + } + + if ( bCollectFoundFtn ) + { + ASSERT( !_pFtn->GetMaster(), "FollowFtn moven?" ); + SwFtnFrm *pNxt = _pFtn->GetFollow(); + while ( pNxt ) + { + SwFrm *pCnt = pNxt->ContainsAny(); + if ( pCnt ) + { //Unterwegs wird der Follow zerstoert weil er leer wird! + do + { SwFrm *pNxtCnt = pCnt->GetNext(); + pCnt->Cut(); + pCnt->Paste( _pFtn ); + pCnt = pNxtCnt; + } while ( pCnt ); + } + else + { ASSERT( !pNxt, "Fussnote ohne Inhalt?" ); + pNxt->Cut(); + delete pNxt; + } + pNxt = _pFtn->GetFollow(); + } + _pFtn->Cut(); + FtnInArr( _rFtnArr, _pFtn ); + bFound = TRUE; + } + else + { + FtnInArr( aNotFtnArr, _pFtn ); + if( bFound ) + break; + } + if ( pNxtFtn && + USHRT_MAX == _rFtnArr.GetPos( (VoidPtr)pNxtFtn ) && + USHRT_MAX == aNotFtnArr.GetPos( (VoidPtr)pNxtFtn ) ) + _pFtn = pNxtFtn; + else + break; + } +} + +/************************************************************************* +|* +|* SwFtnBossFrm::_MoveFtns() +|* +|* Ersterstellung MA 26. Feb. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +void SwFtnBossFrm::_MoveFtns( SvPtrarr &rFtnArr, BOOL bCalc ) +{ + //Alle Fussnoten die von pRef referenziert werden muessen von der + //aktuellen Position, die sich durch die alte Spalte/Seite ergab, auf eine + //neue Position, bestimmt durch die neue Spalte/Seite, gemoved werden. + const USHORT nMyNum = FindPageFrm()->GetPhyPageNum(); + const USHORT nMyCol = lcl_ColumnNum( this ); + SWRECTFN( this ) + + // --> OD 2004-06-11 #i21478# - keep last inserted footnote in order to + // format the content of the following one. + SwFtnFrm* pLastInsertedFtn = 0L; + for ( USHORT i = 0; i < rFtnArr.Count(); ++i ) + { + SwFtnFrm *pFtn = (SwFtnFrm*)rFtnArr[i]; + + SwFtnBossFrm* pRefBoss = pFtn->GetRef()->FindFtnBossFrm( TRUE ); + if( pRefBoss != this ) + { + const USHORT nRefNum = pRefBoss->FindPageFrm()->GetPhyPageNum(); + const USHORT nRefCol = lcl_ColumnNum( this ); + if( nRefNum < nMyNum || ( nRefNum == nMyNum && nRefCol <= nMyCol ) ) + pRefBoss = this; + } + pRefBoss->InsertFtn( pFtn ); + + if ( pFtn->GetUpper() ) //Robust, z.B. bei doppelten + { + // Damit FtnFrms, die nicht auf die Seite passen, nicht fuer zuviel + // Unruhe sorgen (Loop 66312), wird ihr Inhalt zunaechst zusammengestaucht. + // Damit wird der FtnCont erst gegrowt, wenn der Inhalt formatiert wird + // und feststellt, dass er auf die Seite passt. + SwFrm *pCnt = pFtn->ContainsAny(); + while( pCnt ) + { + if( pCnt->IsLayoutFrm() ) + { + SwFrm* pTmp = ((SwLayoutFrm*)pCnt)->ContainsAny(); + while( pTmp && ((SwLayoutFrm*)pCnt)->IsAnLower( pTmp ) ) + { + pTmp->Prepare( PREP_MOVEFTN ); + (pTmp->Frm().*fnRect->fnSetHeight)(0); + (pTmp->Prt().*fnRect->fnSetHeight)(0); + pTmp = pTmp->FindNext(); + } + } + else + pCnt->Prepare( PREP_MOVEFTN ); + (pCnt->Frm().*fnRect->fnSetHeight)(0); + (pCnt->Prt().*fnRect->fnSetHeight)(0); + pCnt = pCnt->GetNext(); + } + (pFtn->Frm().*fnRect->fnSetHeight)(0); + (pFtn->Prt().*fnRect->fnSetHeight)(0); + pFtn->Calc(); + pFtn->GetUpper()->Calc(); + + if( bCalc ) + { + SwTxtFtn *pAttr = pFtn->GetAttr(); + pCnt = pFtn->ContainsAny(); + BOOL bUnlock = !pFtn->IsBackMoveLocked(); + pFtn->LockBackMove(); + + // --> OD 2005-05-18 #i49383# - disable unlock of position of + // lower objects during format of footnote content. + pFtn->KeepLockPosOfLowerObjs(); + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // no extra notify for footnote frame +// SwLayNotify aFtnFrmNotitfy( pFtn ); + // <-- + + while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr ) + { + pCnt->_InvalidatePos(); + pCnt->Calc(); + // --> OD 2005-05-17 #i49383# - format anchored objects + if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) + { + if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, + *(pCnt->FindPageFrm()) ) ) + { + // restart format with first content + pCnt = pFtn->ContainsAny(); + continue; + } + } + // <-- + if( pCnt->IsSctFrm() ) + { // Wenn es sich um einen nichtleeren Bereich handelt, + // iterieren wir auch ueber seinen Inhalt + SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny(); + if( pTmp ) + pCnt = pTmp; + else + pCnt = pCnt->FindNext(); + } + else + pCnt = pCnt->FindNext(); + } + if( bUnlock ) + { + pFtn->UnlockBackMove(); + if( !pFtn->ContainsAny() && !pFtn->IsColLocked() ) + { + pFtn->Cut(); + delete pFtn; + // --> OD 2004-06-10 #i21478# + pFtn = 0L; + } + } + // --> OD 2005-05-18 #i49383# + if ( pFtn ) + { + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // enable lock of lower object position before format of footnote frame. + pFtn->UnlockPosOfLowerObjs(); + pFtn->Calc(); +// pFtn->UnlockPosOfLowerObjs(); + // <-- + } + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // no extra notify for footnote frame +// else +// { +// aFtnFrmNotitfy.FrmDeleted(); +// } + // <-- + } + } + else + { ASSERT( !pFtn->GetMaster() && !pFtn->GetFollow(), + "DelFtn und Master/Follow?" ); + delete pFtn; + // --> OD 2004-06-10 #i21478# + pFtn = 0L; + } + + // --> OD 2004-06-10 #i21478# + if ( pFtn ) + { + pLastInsertedFtn = pFtn; + } + } + + // --> OD 2004-06-10 #i21478# - format content of footnote following + // the new inserted ones. + if ( bCalc && pLastInsertedFtn ) + { + if ( pLastInsertedFtn->GetNext() ) + { + SwFtnFrm* pNextFtn = static_cast<SwFtnFrm*>(pLastInsertedFtn->GetNext()); + SwTxtFtn* pAttr = pNextFtn->GetAttr(); + SwFrm* pCnt = pNextFtn->ContainsAny(); + + BOOL bUnlock = !pNextFtn->IsBackMoveLocked(); + pNextFtn->LockBackMove(); + // --> OD 2005-05-18 #i49383# - disable unlock of position of + // lower objects during format of footnote content. + pNextFtn->KeepLockPosOfLowerObjs(); + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // no extra notify for footnote frame +// SwLayNotify aFtnFrmNotitfy( pNextFtn ); + // <-- + + while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr ) + { + pCnt->_InvalidatePos(); + pCnt->Calc(); + // --> OD 2005-05-17 #i49383# - format anchored objects + if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) + { + if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, + *(pCnt->FindPageFrm()) ) ) + { + // restart format with first content + pCnt = pNextFtn->ContainsAny(); + continue; + } + } + // <-- + if( pCnt->IsSctFrm() ) + { // Wenn es sich um einen nichtleeren Bereich handelt, + // iterieren wir auch ueber seinen Inhalt + SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny(); + if( pTmp ) + pCnt = pTmp; + else + pCnt = pCnt->FindNext(); + } + else + pCnt = pCnt->FindNext(); + } + if( bUnlock ) + { + pNextFtn->UnlockBackMove(); + } + // --> OD 2005-05-18 #i49383# + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // enable lock of lower object position before format of footnote frame. + pNextFtn->UnlockPosOfLowerObjs(); + pNextFtn->Calc(); +// pNextFtn->UnlockPosOfLowerObjs(); + // <-- + } + } +} + +/************************************************************************* +|* +|* SwFtnBossFrm::MoveFtns() +|* +|* Ersterstellung BP 05. Aug. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +void SwFtnBossFrm::MoveFtns( const SwCntntFrm *pSrc, SwCntntFrm *pDest, + SwTxtFtn *pAttr ) +{ + if( ( GetFmt()->GetDoc()->GetFtnInfo().ePos == FTNPOS_CHAPTER && + (!GetUpper()->IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd())) + || pAttr->GetFtn().IsEndNote() ) + return; + + ASSERT( this == pSrc->FindFtnBossFrm( TRUE ), + "SwPageFrm::MoveFtns: source frame isn't on that FtnBoss" ); + + SwFtnFrm *pFtn = FindFirstFtn(); + if( pFtn ) + { + ChangeFtnRef( pSrc, pAttr, pDest ); + SwFtnBossFrm *pDestBoss = pDest->FindFtnBossFrm( TRUE ); + ASSERT( pDestBoss, "+SwPageFrm::MoveFtns: no destination boss" ); + if( pDestBoss ) // robust + { + SvPtrarr aFtnArr( 5, 5 ); + pDestBoss->_CollectFtns( pDest, pFtn, aFtnArr ); + if ( aFtnArr.Count() ) + { + pDestBoss->_MoveFtns( aFtnArr, TRUE ); + SwPageFrm* pSrcPage = FindPageFrm(); + SwPageFrm* pDestPage = pDestBoss->FindPageFrm(); + // Nur beim Seitenwechsel FtnNum Updaten + if( pSrcPage != pDestPage ) + { + if( pSrcPage->GetPhyPageNum() > pDestPage->GetPhyPageNum() ) + pSrcPage->UpdateFtnNum(); + pDestPage->UpdateFtnNum(); + } + } + } + } +} + +/************************************************************************* +|* +|* SwFtnBossFrm::RearrangeFtns() +|* +|* Ersterstellung MA 20. Jan. 94 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + + +void SwFtnBossFrm::RearrangeFtns( const SwTwips nDeadLine, const BOOL bLock, + const SwTxtFtn *pAttr ) +{ + //Alle Fussnoten der Spalte/Seite dergestalt anformatieren, + //dass sie ggf. die Spalte/Seite wechseln. + + SwSaveFtnHeight aSave( this, nDeadLine ); + SwFtnFrm *pFtn = FindFirstFtn(); + if( pFtn && pFtn->GetPrev() && bLock ) + { + SwFtnFrm* pFirst = (SwFtnFrm*)pFtn->GetUpper()->Lower(); + SwFrm* pCntnt = pFirst->ContainsAny(); + if( pCntnt ) + { + BOOL bUnlock = !pFirst->IsBackMoveLocked(); + pFirst->LockBackMove(); + pFirst->Calc(); + pCntnt->Calc(); + // --> OD 2005-05-17 #i49383# - format anchored objects + if ( pCntnt->IsTxtFrm() && pCntnt->IsValid() ) + { + SwObjectFormatter::FormatObjsAtFrm( *pCntnt, + *(pCntnt->FindPageFrm()) ); + } + // <-- + if( bUnlock ) + pFirst->UnlockBackMove(); + } + pFtn = FindFirstFtn(); + } + SwDoc *pDoc = GetFmt()->GetDoc(); + const ULONG nFtnPos = pAttr ? ::lcl_FindFtnPos( pDoc, pAttr ) : 0; + SwFrm *pCnt = pFtn ? pFtn->ContainsAny() : 0; + if ( pCnt ) + { + BOOL bMore = TRUE; + BOOL bStart = pAttr == 0; // wenn kein Attribut uebergeben wird, alle bearbeiten + // --> OD 2005-05-18 #i49383# - disable unlock of position of + // lower objects during format of footnote and footnote content. + SwFtnFrm* pLastFtnFrm( 0L ); + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // no extra notify for footnote frame +// SwLayNotify* pFtnFrmNotify( 0L ); + // footnote frame needs to be locked, if <bLock> isn't set. + bool bUnlockLastFtnFrm( false ); + // <-- + do + { + if( !bStart ) + bStart = ::lcl_FindFtnPos( pDoc, pCnt->FindFtnFrm()->GetAttr() ) + == nFtnPos; + if( bStart ) + { + pCnt->_InvalidatePos(); + pCnt->_InvalidateSize(); + pCnt->Prepare( PREP_ADJUST_FRM ); + SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm(); + // --> OD 2005-05-18 #i49383# + if ( pFtnFrm != pLastFtnFrm ) + { + if ( pLastFtnFrm ) + { + if ( !bLock && bUnlockLastFtnFrm ) + { + pLastFtnFrm->ColUnlock(); + } + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // enable lock of lower object position before format of footnote frame. + pLastFtnFrm->UnlockPosOfLowerObjs(); + pLastFtnFrm->Calc(); +// pLastFtnFrm->UnlockPosOfLowerObjs(); + // no extra notify for footnote frame +// delete pFtnFrmNotify; + // <-- + if ( !bLock && bUnlockLastFtnFrm && + !pLastFtnFrm->GetLower() && + !pLastFtnFrm->IsColLocked() && + !pLastFtnFrm->IsBackMoveLocked() ) + { + pLastFtnFrm->Cut(); + delete pLastFtnFrm; + pLastFtnFrm = 0L; + } + } + if ( !bLock ) + { + bUnlockLastFtnFrm = !pFtnFrm->IsColLocked(); + pFtnFrm->ColLock(); + } + pFtnFrm->KeepLockPosOfLowerObjs(); + pLastFtnFrm = pFtnFrm; + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // no extra notify for footnote frame +// pFtnFrmNotify = new SwLayNotify( pLastFtnFrm ); + // <-- + } + // <-- + // OD 30.10.2002 #97265# - invalidate position of footnote + // frame, if it's below its footnote container, in order to + // assure its correct position, probably calculating its previous + // footnote frames. + { + SWRECTFN( this ); + SwFrm* aFtnContFrm = pFtnFrm->GetUpper(); + if ( (pFtnFrm->Frm().*fnRect->fnTopDist)((aFtnContFrm->*fnRect->fnGetPrtBottom)()) > 0 ) + { + pFtnFrm->_InvalidatePos(); + } + } + if ( bLock ) + { + BOOL bUnlock = !pFtnFrm->IsBackMoveLocked(); + pFtnFrm->LockBackMove(); + pFtnFrm->Calc(); + pCnt->Calc(); + // --> OD 2005-05-17 #i49383# - format anchored objects + if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) + { + if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, + *(pCnt->FindPageFrm()) ) ) + { + // restart format with first content + pCnt = pFtn->ContainsAny(); + continue; + } + } + // <-- + if( bUnlock ) + { + pFtnFrm->UnlockBackMove(); + if( !pFtnFrm->Lower() && + !pFtnFrm->IsColLocked() ) + { + // --> OD 2005-08-10 #i49383# + ASSERT( pLastFtnFrm == pFtnFrm, + "<SwFtnBossFrm::RearrangeFtns(..)> - <pLastFtnFrm> != <pFtnFrm>" ); + pLastFtnFrm = 0L; + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // no extra notify for footnote frame +// pFtnFrmNotify->FrmDeleted(); +// delete pFtnFrmNotify; + // <-- + pFtnFrm->Cut(); + delete pFtnFrm; + } + } + } + else + { + pFtnFrm->Calc(); + pCnt->Calc(); + // --> OD 2005-05-17 #i49383# - format anchored objects + if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) + { + if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, + *(pCnt->FindPageFrm()) ) ) + { + // restart format with first content + pCnt = pFtn->ContainsAny(); + continue; + } + } + // <-- + } + } + SwSectionFrm *pDel = NULL; + if( pCnt->IsSctFrm() ) + { + SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny(); + if( pTmp ) + { + pCnt = pTmp; + continue; + } + pDel = (SwSectionFrm*)pCnt; + } + if ( pCnt->GetNext() ) + pCnt = pCnt->GetNext(); + else + { + pCnt = pCnt->FindNext(); + if ( pCnt ) + { + SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm(); + if( pFtnFrm->GetRef()->FindFtnBossFrm( + pFtnFrm->GetAttr()->GetFtn().IsEndNote() ) != this ) + bMore = FALSE; + } + else + bMore = FALSE; + } + if( pDel ) + { + pDel->Cut(); + delete pDel; + } + if ( bMore ) + { + //Nicht weiter als bis zur angegebenen Fussnote, falls eine + //angegeben wurde. + if ( pAttr && + (::lcl_FindFtnPos( pDoc, + pCnt->FindFtnFrm()->GetAttr()) > nFtnPos ) ) + bMore = FALSE; + } + } while ( bMore ); + // --> OD 2005-05-18 #i49383# + if ( pLastFtnFrm ) + { + if ( !bLock && bUnlockLastFtnFrm ) + { + pLastFtnFrm->ColUnlock(); + } + // --> OD 2006-02-02 #i57914# - adjust fix #i49383# + // enable lock of lower object position before format of footnote frame. + pLastFtnFrm->UnlockPosOfLowerObjs(); + pLastFtnFrm->Calc(); +// pLastFtnFrm->UnlockPosOfLowerObjs(); + // no extra notify for footnote frame +// delete pFtnFrmNotify; + // <-- + if ( !bLock && bUnlockLastFtnFrm && + !pLastFtnFrm->GetLower() && + !pLastFtnFrm->IsColLocked() && + !pLastFtnFrm->IsBackMoveLocked() ) + { + pLastFtnFrm->Cut(); + delete pLastFtnFrm; + } + } + // <-- + } +} + +/************************************************************************* +|* +|* SwPageFrm::UpdateFtnNum() +|* +|* Ersterstellung MA 02. Mar. 93 +|* Letzte Aenderung AMA 29. Oct. 98 +|* +|*************************************************************************/ + +void SwPageFrm::UpdateFtnNum() +{ + //Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist. + if ( GetFmt()->GetDoc()->GetFtnInfo().eNum != FTNNUM_PAGE ) + return; + + SwLayoutFrm* pBody = FindBodyCont(); + if( !pBody || !pBody->Lower() ) + return; + + SwCntntFrm* pCntnt = pBody->ContainsCntnt(); + USHORT nNum = 0; + + while( pCntnt && pCntnt->FindPageFrm() == this ) + { + if( ((SwTxtFrm*)pCntnt)->HasFtn() ) + { + SwFtnBossFrm* pBoss = pCntnt->FindFtnBossFrm( TRUE ); + if( pBoss->GetUpper()->IsSctFrm() && + ((SwSectionFrm*)pBoss->GetUpper())->IsOwnFtnNum() ) + pCntnt = ((SwSectionFrm*)pBoss->GetUpper())->FindLastCntnt(); + else + { + SwFtnFrm* pFtn = (SwFtnFrm*)pBoss->FindFirstFtn( pCntnt ); + while( pFtn ) + { + SwTxtFtn* pTxtFtn = pFtn->GetAttr(); + if( !pTxtFtn->GetFtn().IsEndNote() && + !pTxtFtn->GetFtn().GetNumStr().Len() && + !pFtn->GetMaster() && + (pTxtFtn->GetFtn().GetNumber() != ++nNum) ) + pTxtFtn->SetNumber( nNum ); + if ( pFtn->GetNext() ) + pFtn = (SwFtnFrm*)pFtn->GetNext(); + else + { + SwFtnBossFrm* pTmpBoss = pFtn->FindFtnBossFrm( TRUE ); + SwPageFrm* pPage = pTmpBoss->FindPageFrm(); + pFtn = NULL; + lcl_NextFtnBoss( pTmpBoss, pPage, FALSE ); + if( pTmpBoss ) + { + SwFtnContFrm *pCont = pTmpBoss->FindNearestFtnCont(); + if ( pCont ) + pFtn = (SwFtnFrm*)pCont->Lower(); + } + } + if( pFtn && pFtn->GetRef() != pCntnt ) + pFtn = NULL; + } + } + } + pCntnt = pCntnt->FindNextCnt(); + } +} + +/************************************************************************* +|* +|* SwFtnBossFrm::SetFtnDeadLine() +|* +|* Ersterstellung MA 02. Aug. 93 +|* Letzte Aenderung MA 16. Nov. 98 +|* +|*************************************************************************/ + +void SwFtnBossFrm::SetFtnDeadLine( const SwTwips nDeadLine ) +{ + SwFrm *pBody = FindBodyCont(); + pBody->Calc(); + + SwFrm *pCont = FindFtnCont(); + const SwTwips nMax = nMaxFtnHeight;//Aktuelle MaxHeight nicht ueberschreiten. + SWRECTFN( this ) + if ( pCont ) + { + pCont->Calc(); + nMaxFtnHeight = -(pCont->Frm().*fnRect->fnBottomDist)( nDeadLine ); + } + else + nMaxFtnHeight = -(pBody->Frm().*fnRect->fnBottomDist)( nDeadLine ); + + if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) ) + nMaxFtnHeight += pBody->Grow( LONG_MAX, TRUE ); + if ( IsInSct() ) + nMaxFtnHeight += FindSctFrm()->Grow( LONG_MAX, TRUE ); + + if ( nMaxFtnHeight < 0 ) + nMaxFtnHeight = 0; + if ( nMax != LONG_MAX && nMaxFtnHeight > nMax ) + nMaxFtnHeight = nMax; +} + +/************************************************************************* +|* +|* SwFtnBossFrm::GetVarSpace() +|* +|* Ersterstellung MA 03. Apr. 95 +|* Letzte Aenderung MA 16. Nov. 98 +|* +|*************************************************************************/ +SwTwips SwFtnBossFrm::GetVarSpace() const +{ + //Fuer Seiten soll ein Wert von 20% der Seitenhoehe nicht unterschritten + //werden (->AMA: was macht MS da?) + //->AMA: Was ist da fuer Bereiche sinnvoll (und kompatibel zu MS ;-)? + //AMA: MS kennt scheinbar kein Begrenzung, die Fussnoten nehmen durchaus + // die ganze Seite/Spalte ein. + + const SwPageFrm* pPg = FindPageFrm(); + ASSERT( pPg || IsInSct(), "Footnote lost page" ); + + const SwFrm *pBody = FindBodyCont(); + SwTwips nRet; + if( pBody ) + { + SWRECTFN( this ) + if( IsInSct() ) + { + nRet = 0; + SwTwips nTmp = (*fnRect->fnYDiff)( (pBody->*fnRect->fnGetPrtTop)(), + (Frm().*fnRect->fnGetTop)() ); + const SwSectionFrm* pSect = FindSctFrm(); + // Endnotes in a ftncontainer causes a deadline: + // the bottom of the last contentfrm + if( pSect->IsEndnAtEnd() ) // endnotes allowed? + { + ASSERT( !Lower() || !Lower()->GetNext() || Lower()->GetNext()-> + IsFtnContFrm(), "FtnContainer exspected" ); + const SwFtnContFrm* pCont = Lower() ? + (SwFtnContFrm*)Lower()->GetNext() : 0; + if( pCont ) + { + SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower(); + while( pFtn) + { + if( pFtn->GetAttr()->GetFtn().IsEndNote() ) + { // endnote found + SwFrm* pFrm = ((SwLayoutFrm*)Lower())->Lower(); + if( pFrm ) + { + while( pFrm->GetNext() ) + pFrm = pFrm->GetNext(); // last cntntfrm + nTmp += (*fnRect->fnYDiff)( + (Frm().*fnRect->fnGetTop)(), + (pFrm->Frm().*fnRect->fnGetBottom)() ); + } + break; + } + pFtn = (SwFtnFrm*)pFtn->GetNext(); + } + } + } + if( nTmp < nRet ) + nRet = nTmp; + } + else + nRet = - (pPg->Prt().*fnRect->fnGetHeight)()/5; + nRet += (pBody->Frm().*fnRect->fnGetHeight)(); + if( nRet < 0 ) + nRet = 0; + } + else + nRet = 0; + if ( IsPageFrm() && + GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) ) + nRet += BROWSE_HEIGHT - Frm().Height(); + return nRet; +} + +/************************************************************************* +|* +|* SwFtnBossFrm::NeighbourhoodAdjustment(SwFrm*) +|* +|* gibt Auskunft, ob die Groessenveraenderung von pFrm von AdjustNeighbourhood(...) +|* oder von Grow/Shrink(..) verarbeitet werden sollte. +|* Bei einem PageFrm oder in Spalten direkt unterhalb der Seite muss AdjustNei.. +|* gerufen werden, in Rahmenspalten Grow/Shrink. +|* Spannend sind die spaltigen Bereiche: Wenn es in der Spalte einen Fussnotencontainer +|* gibt und die Fussnoten nicht vom Bereich eingesammelt werden, ist ein Adjust.., +|* ansonsten ein Grow/Shrink notwendig. +|* +|* Ersterstellung AMA 09. Dec 98 +|* Letzte Aenderung AMA 09. Dec 98 +|* +|*************************************************************************/ + +BYTE SwFtnBossFrm::_NeighbourhoodAdjustment( const SwFrm* ) const +{ + BYTE nRet = NA_ONLY_ADJUST; + if( GetUpper() && !GetUpper()->IsPageBodyFrm() ) + { + // Spaltige Rahmen erfordern Grow/Shrink + if( GetUpper()->IsFlyFrm() ) + nRet = NA_GROW_SHRINK; + else + { + ASSERT( GetUpper()->IsSctFrm(), "NeighbourhoodAdjustment: Unexspected Upper" ); + if( !GetNext() && !GetPrev() ) + nRet = NA_GROW_ADJUST; // section with a single column (FtnAtEnd) + else + { + const SwFrm* pTmp = Lower(); + ASSERT( pTmp, "NeighbourhoodAdjustment: Missing Lower()" ); + if( !pTmp->GetNext() ) + nRet = NA_GROW_SHRINK; + else if( !GetUpper()->IsColLocked() ) + nRet = NA_ADJUST_GROW; + ASSERT( !pTmp->GetNext() || pTmp->GetNext()->IsFtnContFrm(), + "NeighbourhoodAdjustment: Who's that guy?" ); + } + } + } + return nRet; +} + +/************************************************************************* +|* +|* SwPageFrm::SetColMaxFtnHeight() +|* +|* Ersterstellung AMA 29. Oct 98 +|* Letzte Aenderung AMA 29. Oct 98 +|* +|*************************************************************************/ +void SwPageFrm::SetColMaxFtnHeight() +{ + SwLayoutFrm *pBody = FindBodyCont(); + if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() ) + { + SwColumnFrm* pCol = (SwColumnFrm*)pBody->Lower(); + do + { + pCol->SetMaxFtnHeight( GetMaxFtnHeight() ); + pCol = (SwColumnFrm*)pCol->GetNext(); + } while ( pCol ); + } +} + +/************************************************************************* +|* +|* SwLayoutFrm::MoveLowerFtns +|* +|* Ersterstellung MA 01. Sep. 94 +|* Letzte Aenderung MA 05. Sep. 95 +|* +|*************************************************************************/ + + +BOOL SwLayoutFrm::MoveLowerFtns( SwCntntFrm *pStart, SwFtnBossFrm *pOldBoss, + SwFtnBossFrm *pNewBoss, const BOOL bFtnNums ) +{ + SwDoc *pDoc = GetFmt()->GetDoc(); + if ( !pDoc->GetFtnIdxs().Count() ) + return FALSE; + if( pDoc->GetFtnInfo().ePos == FTNPOS_CHAPTER && + ( !IsInSct() || !FindSctFrm()->IsFtnAtEnd() ) ) + return TRUE; + + if ( !pNewBoss ) + pNewBoss = FindFtnBossFrm( TRUE ); + if ( pNewBoss == pOldBoss ) + return FALSE; + + BOOL bMoved = FALSE; + if( !pStart ) + pStart = ContainsCntnt(); + + SvPtrarr aFtnArr( 5, 5 ); + + while ( IsAnLower( pStart ) ) + { + if ( ((SwTxtFrm*)pStart)->HasFtn() ) + { + // OD 03.04.2003 #108446# - To avoid unnecessary moves of footnotes + // use new parameter <_bCollectOnlyPreviousFtn> (4th parameter of + // method <SwFtnBossFrm::CollectFtn(..)>) to control, that only + // footnotes have to be collected, that are positioned before the + // new dedicated footnote boss frame. + pNewBoss->CollectFtns( pStart, pOldBoss, aFtnArr, sal_True ); + } + pStart = pStart->GetNextCntntFrm(); + } + + ASSERT( pOldBoss->IsInSct() == pNewBoss->IsInSct(), + "MoveLowerFtns: Section confusion" ); + SvPtrarr *pFtnArr; + SwLayoutFrm* pNewChief = 0; + SwLayoutFrm* pOldChief = 0; + if( pStart && pOldBoss->IsInSct() && ( pOldChief = pOldBoss->FindSctFrm() ) + != ( pNewChief = pNewBoss->FindSctFrm() ) ) + { + pFtnArr = new SvPtrarr( 5, 5 ); + pOldChief = pOldBoss->FindFtnBossFrm( TRUE ); + pNewChief = pNewBoss->FindFtnBossFrm( TRUE ); + while( pOldChief->IsAnLower( pStart ) ) + { + if ( ((SwTxtFrm*)pStart)->HasFtn() ) + ((SwFtnBossFrm*)pNewChief)->CollectFtns( pStart, + (SwFtnBossFrm*)pOldBoss, *pFtnArr ); + pStart = pStart->GetNextCntntFrm(); + } + if( !pFtnArr->Count() ) + { + delete pFtnArr; + pFtnArr = NULL; + } + } + else + pFtnArr = NULL; + + if ( aFtnArr.Count() || pFtnArr ) + { + if( aFtnArr.Count() ) + pNewBoss->_MoveFtns( aFtnArr, TRUE ); + if( pFtnArr ) + { + ((SwFtnBossFrm*)pNewChief)->_MoveFtns( *pFtnArr, TRUE ); + delete pFtnArr; + } + bMoved = TRUE; + + // Nur bei einem Seitenwechsel muss die FtnNum neu berechnet werden + if ( bFtnNums ) + { + SwPageFrm* pOldPage = pOldBoss->FindPageFrm(); + SwPageFrm* pNewPage =pNewBoss->FindPageFrm(); + if( pOldPage != pNewPage ) + { + pOldPage->UpdateFtnNum(); + pNewPage->UpdateFtnNum(); + } + } + } + return bMoved; +} + +/************************************************************************* +|* +|* SwLayoutFrm::MoveFtnCntFwd() +|* +|* Ersterstellung MA 24. Nov. 94 +|* Letzte Aenderung MA 15. Jun. 95 +|* +|*************************************************************************/ + + +BOOL SwCntntFrm::MoveFtnCntFwd( BOOL bMakePage, SwFtnBossFrm *pOldBoss ) +{ + ASSERT( IsInFtn(), "Keine Ftn." ); + SwLayoutFrm *pFtn = FindFtnFrm(); + + // The first paragraph in the first footnote in the first column in the + // sectionfrm at the top of the page has not to move forward, if the + // columnbody is empty. + if( pOldBoss->IsInSct() && !pOldBoss->GetIndPrev() && !GetIndPrev() && + !pFtn->GetPrev() ) + { + SwLayoutFrm* pBody = pOldBoss->FindBodyCont(); + if( !pBody || !pBody->Lower() ) + return TRUE; + } + + //fix(9538): Wenn die Ftn noch Nachbarn hinter sich hat, so muessen + //diese ersteinmal verschwinden. + SwLayoutFrm *pNxt = (SwLayoutFrm*)pFtn->GetNext(); + SwLayoutFrm *pLst = 0; + while ( pNxt ) + { + while ( pNxt->GetNext() ) + pNxt = (SwLayoutFrm*)pNxt->GetNext(); + if ( pNxt == pLst ) + pNxt = 0; + else + { pLst = pNxt; + SwCntntFrm *pCnt = pNxt->ContainsCntnt(); + if( pCnt ) + pCnt->MoveFtnCntFwd( TRUE, pOldBoss ); + pNxt = (SwLayoutFrm*)pFtn->GetNext(); + } + } + + BOOL bSamePage = TRUE; + SwLayoutFrm *pNewUpper = + GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, TRUE ); + + if ( pNewUpper ) + { + BOOL bSameBoss = TRUE; + SwFtnBossFrm * const pNewBoss = pNewUpper->FindFtnBossFrm(); + //Wechseln wir die Spalte/Seite? + if ( FALSE == ( bSameBoss = pNewBoss == pOldBoss ) ) + { + bSamePage = pOldBoss->FindPageFrm() == pNewBoss->FindPageFrm(); // Seitenwechsel? + pNewUpper->Calc(); + } + + //Das Layoutblatt, dass wir fuer Fussnoten bekommen ist entweder + //ein Fussnotencontainer oder eine Fussnote + //Wenn es eine Fussnote ist, und sie die gleiche Fussnotenreferez + //wie der alte Upper hat, so moven wir uns direkt hinein. + //Ist die Referenz einen andere oder ist es ein Container, so wird + //eine neue Fussnote erzeugt und in den Container gestellt. + // Wenn wir in einem Bereich innerhalb der Fussnote sind, muss + // SectionFrame noch angelegt werden. + SwFtnFrm* pTmpFtn = pNewUpper->IsFtnFrm() ? ((SwFtnFrm*)pNewUpper) : 0; + if( !pTmpFtn ) + { + ASSERT( pNewUpper->IsFtnContFrm(), "Neuer Upper kein FtnCont."); + SwFtnContFrm *pCont = (SwFtnContFrm*)pNewUpper; + + //Fussnote erzeugen. + SwFtnFrm *pOld = FindFtnFrm(); + pTmpFtn = new SwFtnFrm( pOld->GetFmt()->GetDoc()->GetDfltFrmFmt(), + pOld->GetRef(), pOld->GetAttr() ); + //Verkettung der Fussnoten. + if ( pOld->GetFollow() ) + { + pTmpFtn->SetFollow( pOld->GetFollow() ); + pOld->GetFollow()->SetMaster( pTmpFtn ); + } + pOld->SetFollow( pTmpFtn ); + pTmpFtn->SetMaster( pOld ); + SwFrm* pNx = pCont->Lower(); + if( pNx && pTmpFtn->GetAttr()->GetFtn().IsEndNote() ) + while(pNx && !((SwFtnFrm*)pNx)->GetAttr()->GetFtn().IsEndNote()) + pNx = pNx->GetNext(); + pTmpFtn->Paste( pCont, pNx ); + pTmpFtn->Calc(); + } + ASSERT( pTmpFtn->GetAttr() == FindFtnFrm()->GetAttr(), "Wrong Footnote!" ); + // Bereiche in Fussnoten beduerfen besonderer Behandlung + SwLayoutFrm *pNewUp = pTmpFtn; + if( IsInSct() ) + { + SwSectionFrm* pSect = FindSctFrm(); + // Bereich in Fussnote (oder nur Fussnote in Bereich)? + if( pSect->IsInFtn() ) + { + if( pTmpFtn->Lower() && pTmpFtn->Lower()->IsSctFrm() && + pSect->GetFollow() == (SwSectionFrm*)pTmpFtn->Lower() ) + pNewUp = (SwSectionFrm*)pTmpFtn->Lower(); + else + { + pNewUp = new SwSectionFrm( *pSect, FALSE ); + pNewUp->InsertBefore( pTmpFtn, pTmpFtn->Lower() ); + static_cast<SwSectionFrm*>(pNewUp)->Init(); + pNewUp->Frm().Pos() = pTmpFtn->Frm().Pos(); + pNewUp->Frm().Pos().Y() += 1; //wg. Benachrichtigungen. + + // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser + // umgehaengt werden hinter den neuen Follow der Bereichsframes. + SwFrm* pTmp = pSect->GetNext(); + if( pTmp ) + { + SwFlowFrm* pTmpNxt; + if( pTmp->IsCntntFrm() ) + pTmpNxt = (SwCntntFrm*)pTmp; + else if( pTmp->IsSctFrm() ) + pTmpNxt = (SwSectionFrm*)pTmp; + else + { + ASSERT( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" ); + pTmpNxt = (SwTabFrm*)pTmp; + } + pTmpNxt->MoveSubTree( pTmpFtn, pNewUp->GetNext() ); + } + } + } + } + + MoveSubTree( pNewUp, pNewUp->Lower() ); + + if( !bSameBoss ) + Prepare( PREP_BOSS_CHGD ); + } + return bSamePage; +} + +/************************************************************************* +|* +|* class SwSaveFtnHeight +|* +|* Ersterstellung MA 19. Jan. 94 +|* Letzte Aenderung MA 19. Jan. 94 +|* +|*************************************************************************/ + + +SwSaveFtnHeight::SwSaveFtnHeight( SwFtnBossFrm *pBs, const SwTwips nDeadLine ) : + pBoss( pBs ), + nOldHeight( pBs->GetMaxFtnHeight() ) +{ + pBoss->SetFtnDeadLine( nDeadLine ); + nNewHeight = pBoss->GetMaxFtnHeight(); +} + + + +SwSaveFtnHeight::~SwSaveFtnHeight() +{ + //Wenn zwischendurch jemand an der DeadLine gedreht hat, so lassen wir + //ihm seinen Spass! + if ( nNewHeight == pBoss->GetMaxFtnHeight() ) + pBoss->nMaxFtnHeight = nOldHeight; +} + + +#ifdef DBG_UTIL +//JP 15.10.2001: in a non pro version test if the attribute has the same +// meaning which his reference is + +// Normally, the pRef member and the GetRefFromAttr() result has to be +// identically. Sometimes footnote will be moved from a master to its follow, +// but the GetRef() is called first, so we have to ignore a master/follow +// mismatch. + +const SwCntntFrm* SwFtnFrm::GetRef() const +{ + const SwCntntFrm* pRefAttr = GetRefFromAttr(); + ASSERT( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr ) + || pRefAttr->IsAnFollow( pRef ), + "access to deleted Frame? pRef != pAttr->GetRef()" ); + return pRef; +} + +SwCntntFrm* SwFtnFrm::GetRef() +{ + const SwCntntFrm* pRefAttr = GetRefFromAttr(); + ASSERT( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr ) + || pRefAttr->IsAnFollow( pRef ), + "access to deleted Frame? pRef != pAttr->GetRef()" ); + return pRef; +} + +#endif + +const SwCntntFrm* SwFtnFrm::GetRefFromAttr() const +{ + SwFtnFrm* pThis = (SwFtnFrm*)this; + return pThis->GetRefFromAttr(); +} + +SwCntntFrm* SwFtnFrm::GetRefFromAttr() +{ + ASSERT( pAttr, "invalid Attribute" ); + SwTxtNode& rTNd = (SwTxtNode&)pAttr->GetTxtNode(); + SwPosition aPos( rTNd, SwIndex( &rTNd, *pAttr->GetStart() )); + SwCntntFrm* pCFrm = rTNd.GetFrm( 0, &aPos, FALSE ); + return pCFrm; +} + +/** search for last content in the current footnote frame + + OD 2005-12-02 #i27138# + + @author OD +*/ +SwCntntFrm* SwFtnFrm::FindLastCntnt() +{ + SwCntntFrm* pLastCntntFrm( 0L ); + + // find last lower, which is a content frame or contains content. + // hidden text frames, empty sections and empty tables have to be skipped. + SwFrm* pLastLowerOfFtn( GetLower() ); + SwFrm* pTmpLastLower( pLastLowerOfFtn ); + while ( pTmpLastLower && pTmpLastLower->GetNext() ) + { + pTmpLastLower = pTmpLastLower->GetNext(); + if ( ( pTmpLastLower->IsTxtFrm() && + !static_cast<SwTxtFrm*>(pTmpLastLower)->IsHiddenNow() ) || + ( pTmpLastLower->IsSctFrm() && + static_cast<SwSectionFrm*>(pTmpLastLower)->GetSection() && + static_cast<SwSectionFrm*>(pTmpLastLower)->ContainsCntnt() ) || + ( pTmpLastLower->IsTabFrm() && + static_cast<SwTabFrm*>(pTmpLastLower)->ContainsCntnt() ) ) + { + pLastLowerOfFtn = pTmpLastLower; + } + } + + // determine last content frame depending on type of found last lower. + if ( pLastLowerOfFtn && pLastLowerOfFtn->IsTabFrm() ) + { + pLastCntntFrm = static_cast<SwTabFrm*>(pLastLowerOfFtn)->FindLastCntnt(); + } + else if ( pLastLowerOfFtn && pLastLowerOfFtn->IsSctFrm() ) + { + pLastCntntFrm = static_cast<SwSectionFrm*>(pLastLowerOfFtn)->FindLastCntnt(); + } + else + { + pLastCntntFrm = dynamic_cast<SwCntntFrm*>(pLastLowerOfFtn); + } + + return pLastCntntFrm; +} + |