| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| |
| #include <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> |
| #include <objectformatter.hxx> |
| #include "viewopt.hxx" |
| #include "viewsh.hxx" |
| #include <switerator.hxx> |
| |
| /************************************************************************* |
| |* |
| |* lcl_FindFtnPos() Sucht die Position des Attributes im FtnArray am |
| |* Dokument, dort stehen die Fussnoten gluecklicherweise nach ihrem |
| |* Index sortiert. |
| |* |
| |*************************************************************************/ |
| |
| #define ENDNOTE 0x80000000 |
| |
| sal_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 ( sal_uInt16 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 |
| |
| sal_uInt16 nRet; |
| SwTxtFtnPtr pBla = (SwTxtFtn*)pAttr; |
| if ( rFtnIdxs.Seek_Entry( pBla, &nRet ) ) |
| { |
| if( pAttr->GetFtn().IsEndNote() ) |
| return sal_uLong(nRet) + ENDNOTE; |
| return nRet; |
| } |
| ASSERT( !pDoc, "FtnPos not found." ); |
| return 0; |
| } |
| |
| sal_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 ); |
| } |
| |
| /************************************************************************* |
| |* |
| |* sal_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 sal_True. |
| |* |
| |*************************************************************************/ |
| |
| sal_Bool lcl_NextFtnBoss( SwFtnBossFrm* &rpBoss, SwPageFrm* &rpPage, |
| sal_Bool bDontLeave ) |
| { |
| if( rpBoss->IsColumnFrm() ) |
| { |
| if( rpBoss->GetNext() ) |
| { |
| rpBoss = (SwFtnBossFrm*)rpBoss->GetNext(); //naechste Spalte |
| return sal_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 sal_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 sal_True; |
| } |
| |
| /************************************************************************* |
| |* |
| |* sal_uInt16 lcl_ColumnNum( SwFrm* pBoss ) |
| |* liefert die Spaltennummer, wenn pBoss eine Spalte ist, |
| |* sonst eine Null (bei Seiten). |
| |* |
| |*************************************************************************/ |
| |
| sal_uInt16 lcl_ColumnNum( const SwFrm* pBoss ) |
| { |
| sal_uInt16 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() |
| |* |
| |*************************************************************************/ |
| |
| |
| SwFtnContFrm::SwFtnContFrm( SwFrmFmt *pFmt, SwFrm* pSib ): |
| SwLayoutFrm( pFmt, pSib ) |
| { |
| 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. |
| |* |
| |*************************************************************************/ |
| |
| |
| 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 = sal_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 = sal_False; |
| } |
| |
| if ( !bValidSize ) |
| { |
| bool bGrow = pPage->IsFtnPage(); |
| if( bGrow ) |
| { |
| const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; |
| if( pSh && pSh->GetViewOptions()->getBrowseMode() ) |
| bGrow = false; |
| } |
| if( bGrow ) |
| Grow( LONG_MAX, sal_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 = sal_True; |
| } |
| } |
| /************************************************************************* |
| |* |
| |* SwFtnContFrm::GrowFrm(), ShrinkFrm() |
| |* |
| |*************************************************************************/ |
| |
| SwTwips SwFtnContFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_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( sal_False ) && pSect->Growable() ) |
| { |
| pSect->InvalidateSize(); |
| return 0; |
| } |
| } |
| const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; |
| const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode(); |
| 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 ); |
| //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin |
| if( IsVertical() && !IsVertLR() && !IsReverse() ) |
| Frm().Pos().X() -= nDist; |
| } |
| long nGrow = nDist - nAvail, |
| nReal = 0; |
| if ( nGrow > 0 ) |
| { |
| sal_uInt8 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; |
| //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin |
| if( IsVertical() && !IsVertLR() && !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, sal_Bool bTst, sal_Bool bInfo ) |
| { |
| SwPageFrm *pPage = FindPageFrm(); |
| bool bShrink = false; |
| if ( pPage ) |
| { |
| if( !pPage->IsFtnPage() ) |
| bShrink = true; |
| else |
| { |
| const ViewShell *pSh = getRootFrm()->GetCurrShell(); |
| if( pSh && pSh->GetViewOptions()->getBrowseMode() ) |
| bShrink = true; |
| } |
| } |
| if( bShrink ) |
| { |
| SwTwips nRet = SwLayoutFrm::ShrinkFrm( nDiff, bTst, bInfo ); |
| if( IsInSct() && !bTst ) |
| FindSctFrm()->InvalidateNextPos(); |
| if ( !bTst && nRet ) |
| { |
| _InvalidatePos(); |
| InvalidatePage( pPage ); |
| } |
| return nRet; |
| } |
| return 0; |
| } |
| |
| |
| /************************************************************************* |
| |* |
| |* SwFtnFrm::SwFtnFrm() |
| |* |
| |*************************************************************************/ |
| |
| |
| SwFtnFrm::SwFtnFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwCntntFrm *pCnt, SwTxtFtn *pAt ): |
| SwLayoutFrm( pFmt, pSib ), |
| pFollow( 0 ), |
| pMaster( 0 ), |
| pRef( pCnt ), |
| pAttr( pAt ), |
| bBackMoveLocked( sal_False ), |
| // --> OD 2005-08-11 #i49383# |
| mbUnlockPosOfLowerObjs( true ) |
| // <-- |
| { |
| nType = FRMC_FTN; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFtnFrm::InvalidateNxtFtnCnts() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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, sal_Bool bTst, sal_Bool bInfo ) |
| { |
| #if OSL_DEBUG_LEVEL > 1 |
| static sal_uInt16 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, sal_Bool bTst, sal_Bool bInfo ) |
| { |
| #if OSL_DEBUG_LEVEL > 1 |
| static sal_uInt16 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() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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 && !pBody->ContainsCntnt() ) |
| pPage->getRootFrm()->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( sal_False ) && !pSect->IsColLocked() ) |
| pSect->_InvalidateSize(); |
| } |
| else |
| { if ( Frm().Height() ) |
| pUp->Shrink( Frm().Height() ); |
| pUp->SetCompletePaint(); |
| pUp->InvalidatePage(); |
| } |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFtnFrm::Paste() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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 sal_True ist. |
| |* |
| |*************************************************************************/ |
| |
| |
| 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. |
| |* |
| |*************************************************************************/ |
| |
| |
| 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 sal_uInt16 nNum = pStop->GetPhyPageNum(); |
| |
| //Wenn die Fussnoten am Dokumentende angezeigt werden, so verlassen wir |
| //die Entsprechenden Seiten nicht. |
| //Selbiges gilt analog fuer die Endnotenseiten. |
| const sal_Bool bEndNote = pOldPage->IsEndNotePage(); |
| const sal_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(); |
| sal_Bool bJump = sal_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 = sal_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. |
| sal_uInt16 nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrm()->GetPhyPageNum(); |
| if ( nDiff > 2 || |
| (nDiff > 1 && !((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage()) ) |
| bJump = sal_True; |
| } |
| if( bJump ) |
| SwFlowFrm::SetMoveBwdJump( sal_True ); |
| } |
| return pRet; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFrm::IsFtnAllowed() |
| |* |
| |*************************************************************************/ |
| |
| |
| sal_Bool SwFrm::IsFtnAllowed() const |
| { |
| if ( !IsInDocBody() ) |
| return sal_False; |
| |
| if ( IsInTab() ) |
| { |
| //Keine Ftns in wiederholten Headlines. |
| const SwTabFrm *pTab = ((SwFrm*)this)->ImplFindTabFrm(); |
| if ( pTab->IsFollow() ) |
| return !pTab->IsInHeadline( *this ); |
| } |
| return sal_True; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwRootFrm::UpdateFtnNums() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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. |
| |* |
| |*************************************************************************/ |
| |
| void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_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, sal_Bool bPageOnly, sal_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 |
| |* |
| |*************************************************************************/ |
| |
| void SwRootFrm::CheckFtnPageDescs( sal_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, sal_False ); |
| } |
| |
| |
| /************************************************************************* |
| |* |
| |* SwFtnBossFrm::MakeFtnCont() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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(), this ); |
| SwLayoutFrm *pLay = FindBodyCont(); |
| pNew->Paste( this, pLay->GetNext() ); |
| return pNew; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFtnBossFrm::FindFtnCont() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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. |
| |* |
| |*************************************************************************/ |
| |
| SwFtnContFrm *SwFtnBossFrm::FindNearestFtnCont( sal_Bool bDontLeave ) |
| { |
| SwFtnContFrm *pCont = 0; |
| if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() ) |
| { |
| pCont = FindFtnCont(); |
| if ( !pCont ) |
| { |
| SwPageFrm *pPage = FindPageFrm(); |
| SwFtnBossFrm* pBoss = this; |
| sal_Bool bEndNote = pPage->IsEndNotePage(); |
| do |
| { |
| sal_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. |
| |* |
| |*************************************************************************/ |
| |
| |
| 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 sal_uInt16 nRefNum = FindPageFrm()->GetPhyPageNum(); |
| const sal_uInt16 nRefCol = lcl_ColumnNum( this ); |
| sal_uInt16 nPgNum, nColNum; //Seitennummer, Spaltennummer |
| SwFtnBossFrm* pBoss; |
| SwPageFrm* pPage; |
| if( pRet ) |
| { |
| pBoss = pRet->GetRef()->FindFtnBossFrm(); |
| ASSERT( pBoss, "FindFirstFtn: No boss found" ); |
| if( !pBoss ) |
| return NULL; // ?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, sal_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. |
| |* |
| |*************************************************************************/ |
| |
| |
| const SwFtnFrm *SwFtnBossFrm::FindFirstFtn( SwCntntFrm *pCnt ) const |
| { |
| const SwFtnFrm *pRet = ((SwFtnBossFrm*)this)->FindFirstFtn(); |
| if ( pRet ) |
| { |
| const sal_uInt16 nColNum = lcl_ColumnNum( this ); //Spaltennummer |
| const sal_uInt16 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, sal_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() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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, sal_True, sal_False ); |
| SwIterator<SwFrm,SwCntntNode> aIter( *pNd ); |
| SwFrm* pFrm = aIter.First(); |
| while( pFrm ) |
| { |
| if( pFrm->getRootFrm() == pCheck->getRootFrm() ) |
| { |
| 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; |
| } |
| } |
| } |
| |
| pFrm = aIter.Next(); |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFtnBossFrm::InsertFtn() |
| |* |
| |*************************************************************************/ |
| |
| |
| void SwFtnBossFrm::InsertFtn( SwFtnFrm* pNew ) |
| { |
| #if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL) |
| static sal_uInt16 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(); |
| sal_Bool bDontLeave = sal_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 sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pNew->GetAttr() ); |
| |
| sal_uLong nCmpPos = 0; |
| sal_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(); |
| sal_Bool bEndNote = pSibPage->IsEndNotePage(); |
| sal_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() ); |
| sal_uInt16 nRefNum = pBoss->GetPhyPageNum(); // Die Seiten- und |
| sal_uInt16 nRefCol = lcl_ColumnNum( pBoss ); // Spaltennummer der neuen Fussnote |
| sal_Bool bEnd = sal_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() ); |
| sal_uInt16 nTmpRef; |
| if( nStPos >= ENDNOTE || |
| (nTmpRef = pBoss->GetPhyPageNum()) < nRefNum || |
| ( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol )) |
| pSibling = pFoll; |
| else |
| bEnd = sal_True; |
| } |
| else |
| { |
| SwFtnBossFrm* pNxtB = pSibling->FindFtnBossFrm(); |
| SwPageFrm *pSibPage = pNxtB->FindPageFrm(); |
| sal_Bool bEndNote = pSibPage->IsEndNotePage(); |
| sal_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 = sal_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 = sal_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( sal_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() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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; |
| sal_Bool bChgPage = sal_False; |
| sal_Bool bEnd = sal_False; |
| if ( pAttr->GetFtn().IsEndNote() ) |
| { |
| bEnd = sal_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 = sal_True; |
| } |
| if ( !pPage->IsEndNotePage() ) |
| { |
| SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc ); |
| pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(), |
| !pPage->OnRightPage(), sal_False, sal_True, 0 ); |
| pPage->SetEndNotePage( sal_True ); |
| bChgPage = sal_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 sal_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 = sal_True; |
| } |
| |
| if ( !pPage->IsFtnPage() ) |
| { |
| SwPageDesc *pDesc = pDoc->GetFtnInfo().GetPageDesc( *pDoc ); |
| pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(), |
| !pPage->OnRightPage(), sal_False, sal_True, pPage->GetNext() ); |
| bChgPage = sal_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 sal_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(), this, 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() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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, sal_True, sal_False ); |
| if ( !pNd ) |
| return 0; |
| SwIterator<SwFrm,SwCntntNode> aIter( *pNd ); |
| SwFrm* pFrm = aIter.First(); |
| if( pFrm ) |
| do |
| { |
| pFrm = pFrm->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 != (pFrm = aIter.Next()) ); |
| |
| return 0; |
| } |
| /************************************************************************* |
| |* |
| |* SwFtnBossFrm::RemoveFtn() |
| |* |
| |*************************************************************************/ |
| |
| |
| void SwFtnBossFrm::RemoveFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr, |
| sal_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() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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() |
| |* |
| |*************************************************************************/ |
| |
| |
| /// 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() |
| |* |
| |*************************************************************************/ |
| 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(); |
| |
| sal_Bool bFound = sal_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, sal_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( sal_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 = sal_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() |
| |* |
| |*************************************************************************/ |
| |
| |
| void SwFtnBossFrm::_MoveFtns( SvPtrarr &rFtnArr, sal_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 sal_uInt16 nMyNum = FindPageFrm()->GetPhyPageNum(); |
| const sal_uInt16 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 ( sal_uInt16 i = 0; i < rFtnArr.Count(); ++i ) |
| { |
| SwFtnFrm *pFtn = (SwFtnFrm*)rFtnArr[i]; |
| |
| SwFtnBossFrm* pRefBoss = pFtn->GetRef()->FindFtnBossFrm( sal_True ); |
| if( pRefBoss != this ) |
| { |
| const sal_uInt16 nRefNum = pRefBoss->FindPageFrm()->GetPhyPageNum(); |
| const sal_uInt16 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(); |
| sal_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(); |
| |
| sal_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() |
| |* |
| |*************************************************************************/ |
| |
| |
| 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( sal_True ), |
| "SwPageFrm::MoveFtns: source frame isn't on that FtnBoss" ); |
| |
| SwFtnFrm *pFtn = FindFirstFtn(); |
| if( pFtn ) |
| { |
| ChangeFtnRef( pSrc, pAttr, pDest ); |
| SwFtnBossFrm *pDestBoss = pDest->FindFtnBossFrm( sal_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, sal_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() |
| |* |
| |*************************************************************************/ |
| |
| |
| void SwFtnBossFrm::RearrangeFtns( const SwTwips nDeadLine, const sal_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 ) |
| { |
| sal_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 sal_uLong nFtnPos = pAttr ? ::lcl_FindFtnPos( pDoc, pAttr ) : 0; |
| SwFrm *pCnt = pFtn ? pFtn->ContainsAny() : 0; |
| if ( pCnt ) |
| { |
| sal_Bool bMore = sal_True; |
| sal_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 ) |
| { |
| sal_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 = sal_False; |
| } |
| else |
| bMore = sal_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 = sal_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() |
| |* |
| |*************************************************************************/ |
| |
| 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(); |
| sal_uInt16 nNum = 0; |
| |
| while( pCntnt && pCntnt->FindPageFrm() == this ) |
| { |
| if( ((SwTxtFrm*)pCntnt)->HasFtn() ) |
| { |
| SwFtnBossFrm* pBoss = pCntnt->FindFtnBossFrm( sal_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( sal_True ); |
| SwPageFrm* pPage = pTmpBoss->FindPageFrm(); |
| pFtn = NULL; |
| lcl_NextFtnBoss( pTmpBoss, pPage, sal_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() |
| |* |
| |*************************************************************************/ |
| |
| 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 ); |
| |
| const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; |
| if( pSh && pSh->GetViewOptions()->getBrowseMode() ) |
| nMaxFtnHeight += pBody->Grow( LONG_MAX, sal_True ); |
| if ( IsInSct() ) |
| nMaxFtnHeight += FindSctFrm()->Grow( LONG_MAX, sal_True ); |
| |
| if ( nMaxFtnHeight < 0 ) |
| nMaxFtnHeight = 0; |
| if ( nMax != LONG_MAX && nMaxFtnHeight > nMax ) |
| nMaxFtnHeight = nMax; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFtnBossFrm::GetVarSpace() |
| |* |
| |*************************************************************************/ |
| 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() ) |
| { |
| const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; |
| if( pSh && pSh->GetViewOptions()->getBrowseMode() ) |
| 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. |
| |* |
| |*************************************************************************/ |
| |
| sal_uInt8 SwFtnBossFrm::_NeighbourhoodAdjustment( const SwFrm* ) const |
| { |
| sal_uInt8 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() |
| |* |
| |*************************************************************************/ |
| 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 |
| |* |
| |*************************************************************************/ |
| |
| |
| sal_Bool SwLayoutFrm::MoveLowerFtns( SwCntntFrm *pStart, SwFtnBossFrm *pOldBoss, |
| SwFtnBossFrm *pNewBoss, const sal_Bool bFtnNums ) |
| { |
| SwDoc *pDoc = GetFmt()->GetDoc(); |
| if ( !pDoc->GetFtnIdxs().Count() ) |
| return sal_False; |
| if( pDoc->GetFtnInfo().ePos == FTNPOS_CHAPTER && |
| ( !IsInSct() || !FindSctFrm()->IsFtnAtEnd() ) ) |
| return sal_True; |
| |
| if ( !pNewBoss ) |
| pNewBoss = FindFtnBossFrm( sal_True ); |
| if ( pNewBoss == pOldBoss ) |
| return sal_False; |
| |
| sal_Bool bMoved = sal_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( sal_True ); |
| pNewChief = pNewBoss->FindFtnBossFrm( sal_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, sal_True ); |
| if( pFtnArr ) |
| { |
| ((SwFtnBossFrm*)pNewChief)->_MoveFtns( *pFtnArr, sal_True ); |
| delete pFtnArr; |
| } |
| bMoved = sal_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() |
| |* |
| |*************************************************************************/ |
| |
| |
| sal_Bool SwCntntFrm::MoveFtnCntFwd( sal_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 sal_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( sal_True, pOldBoss ); |
| pNxt = (SwLayoutFrm*)pFtn->GetNext(); |
| } |
| } |
| |
| sal_Bool bSamePage = sal_True; |
| SwLayoutFrm *pNewUpper = |
| GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True ); |
| |
| if ( pNewUpper ) |
| { |
| sal_Bool bSameBoss = sal_True; |
| SwFtnBossFrm * const pNewBoss = pNewUpper->FindFtnBossFrm(); |
| //Wechseln wir die Spalte/Seite? |
| if ( sal_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, 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, sal_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 |
| |* |
| |*************************************************************************/ |
| |
| |
| 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.getLayoutFrm( getRootFrm(), 0, &aPos, sal_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; |
| } |
| |