/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/


#ifdef _MSC_VER
#pragma hdrstop
#endif

#include <txtftn.hxx>
#include <fmtftn.hxx>
#include <ftnidx.hxx>
#include <pagefrm.hxx>
#include <colfrm.hxx>
#include <rootfrm.hxx>

#include <horiornt.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 <sectfrm.hxx>
#include <pam.hxx>
namespace binfilter {

/*************************************************************************
|*
|*  lcl_FindFtnPos()        Sucht die Position des Attributes im FtnArray am
|*      Dokument, dort stehen die Fussnoten gluecklicherweise nach ihrem
|*      Index sortiert.
|*
|*************************************************************************/

/*N*/ #define ENDNOTE 0x80000000

/*N*/ ULONG MA_FASTCALL lcl_FindFtnPos( const SwDoc *pDoc, const SwTxtFtn *pAttr )
/*N*/ {
/*N*/   const SwFtnIdxs &rFtnIdxs = pDoc->GetFtnIdxs();
/*N*/
/*N*/   USHORT nRet;
/*N*/   SwTxtFtnPtr pBla = (SwTxtFtn*)pAttr;
/*N*/   if ( rFtnIdxs.Seek_Entry( pBla, &nRet ) )
/*N*/   {
/*N*/       if( pAttr->GetFtn().IsEndNote() )
/*?*/           return ULONG(nRet) + ENDNOTE;
/*N*/       return nRet;
/*N*/   }
/*?*/   OSL_ENSURE( !pDoc, "FtnPos not found." );
/*?*/   return 0;
/*N*/ }


/*************************************************************************
|*
|*  BOOL lcl_NextFtnBoss( SwFtnBossFrm* pBoss, SwPageFrm* pPage)
|*  setzt pBoss auf den naechsten SwFtnBossFrm, das kann entweder eine Spalte
|*  oder eine Seite (ohne Spalten) sein. Wenn die Seite dabei gewechselt wird
|*  enthaelt pPage die neue Seite und die Funktion liefert TRUE.
|*
|*************************************************************************/

/*N*/ BOOL lcl_NextFtnBoss( SwFtnBossFrm* &rpBoss, SwPageFrm* &rpPage,
/*N*/   BOOL bDontLeave )
/*N*/ {
/*N*/   if( rpBoss->IsColumnFrm() )
/*N*/   {
/*?*/       if( rpBoss->GetNext() )
/*?*/       {
/*?*/           rpBoss = (SwFtnBossFrm*)rpBoss->GetNext(); //naechste Spalte
/*?*/           return FALSE;
/*?*/       }
/*?*/       if( rpBoss->IsInSct() )
/*?*/       {
/*?*/           SwSectionFrm* pSct = rpBoss->FindSctFrm()->GetFollow();
/*?*/           if( pSct )
/*?*/           {
/*?*/               OSL_ENSURE( pSct->Lower() && pSct->Lower()->IsColumnFrm(),
/*?*/                       "Where's the column?" );
/*?*/               rpBoss = (SwColumnFrm*)pSct->Lower();
/*?*/               SwPageFrm* pOld = rpPage;
/*?*/               rpPage = pSct->FindPageFrm();
/*?*/               return pOld != rpPage;
/*?*/           }
/*?*/           else if( bDontLeave )
/*?*/           {
/*?*/               rpPage = NULL;
/*?*/               rpBoss = NULL;
/*?*/               return FALSE;
/*?*/           }
/*?*/       }
/*N*/   }
/*N*/   rpPage = (SwPageFrm*)rpPage->GetNext(); // naechste Seite
/*N*/   rpBoss = rpPage;
/*N*/   if( rpPage )
/*N*/   {
/*N*/       SwLayoutFrm* pBody = rpPage->FindBodyCont();
/*N*/       if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
/*?*/           rpBoss = (SwFtnBossFrm*)pBody->Lower(); // erste Spalte
/*N*/   }
/*N*/   return TRUE;
/*N*/ }

/*************************************************************************
|*
|*  USHORT lcl_ColumnNum( SwFrm* pBoss )
|*  liefert die Spaltennummer, wenn pBoss eine Spalte ist,
|*  sonst eine Null (bei Seiten).
|*
|*************************************************************************/

/*N*/ USHORT lcl_ColumnNum( const SwFrm* pBoss )
/*N*/ {
/*N*/   USHORT nRet = 0;
/*N*/   if( !pBoss->IsColumnFrm() )
/*N*/       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;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnContFrm::SwFtnContFrm()
|*
|*************************************************************************/


/*N*/ SwFtnContFrm::SwFtnContFrm( SwFrmFmt *pFmt ):
/*N*/   SwLayoutFrm( pFmt )
/*N*/ {
/*N*/     nType = FRMC_FTNCONT;
/*N*/ }


// lcl_Undersize(..) klappert einen SwFrm und dessen Inneres ab
// und liefert die Summe aller TxtFrm-Vergroesserungswuensche

/*N*/ long lcl_Undersize( const SwFrm* pFrm )
/*N*/ {
/*N*/   long nRet = 0;
/*N*/     SWRECTFN( pFrm )
/*N*/   if( pFrm->IsTxtFrm() )
/*N*/   {
/*N*/       if( ((SwTxtFrm*)pFrm)->IsUndersized() )
/*N*/         {
/*?*/           // Dieser TxtFrm waere gern ein bisschen groesser
/*?*/             nRet = ((SwTxtFrm*)pFrm)->GetParHeight() -
/*?*/                     (pFrm->Prt().*fnRect->fnGetHeight)();
/*?*/             if( nRet < 0 )
/*?*/               nRet = 0;
/*N*/         }
/*N*/   }
/*N*/   else if( pFrm->IsLayoutFrm() )
/*N*/   {
/*N*/       const SwFrm* pNxt = ((SwLayoutFrm*)pFrm)->Lower();
/*N*/       while( pNxt )
/*N*/       {
/*N*/           nRet += lcl_Undersize( pNxt );
/*N*/           pNxt = pNxt->GetNext();
/*N*/       }
/*N*/   }
/*N*/   return nRet;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnContFrm::Format()
|*
|*  Beschreibung:       "Formatiert" den Frame;
|*                      Die Fixsize wird hier nicht eingestellt.
|*
|*************************************************************************/


/*N*/ void SwFtnContFrm::Format( const SwBorderAttrs * )
/*N*/ {
/*N*/   //GesamtBorder ermitteln, es gibt nur einen Abstand nach oben.
/*N*/   const SwPageFrm* pPage = FindPageFrm();
/*N*/   const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo();
/*N*/   const SwTwips nBorder = rInf.GetTopDist() + rInf.GetBottomDist() +
/*N*/                           rInf.GetLineWidth();
/*N*/     SWRECTFN( this )
/*N*/   if ( !bValidPrtArea )
/*N*/   {
/*N*/       bValidPrtArea = TRUE;
/*N*/         (Prt().*fnRect->fnSetTop)( nBorder );
/*N*/         (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
/*N*/         (Prt().*fnRect->fnSetHeight)((Frm().*fnRect->fnGetHeight)() - nBorder );
/*N*/         if( (Prt().*fnRect->fnGetHeight)() < 0 && !pPage->IsFtnPage() )
/*N*/           bValidSize = FALSE;
/*N*/   }
/*N*/
/*N*/   if ( !bValidSize )
/*N*/   {
/*N*/       if ( pPage->IsFtnPage() && !GetFmt()->GetDoc()->IsBrowseMode() )
/*?*/                 Grow( LONG_MAX PHEIGHT, FALSE );
/*N*/       else
/*N*/       {
/*N*/           //Die Groesse in der VarSize wird durch den Inhalt plus den
/*N*/           //Raendern bestimmt.
/*N*/           SwTwips nRemaining = 0;
/*N*/           SwFrm *pFrm = pLower;
/*N*/           while ( pFrm )
/*N*/           {   // lcl_Undersize(..) beruecksichtigt (rekursiv) TxtFrms, die gerne
/*N*/               // groesser waeren. Diese entstehen insbesondere in spaltigen Rahmen,
/*N*/               // wenn diese noch nicht ihre maximale Groesse haben.
/*N*/                 nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)()
/*N*/                               + lcl_Undersize( pFrm );
/*N*/               pFrm = pFrm->GetNext();
/*N*/           }
/*N*/           //Jetzt noch den Rand addieren
/*N*/           nRemaining += nBorder;
/*N*/
/*N*/           SwTwips nDiff;
/*N*/           if( IsInSct() )
/*N*/           {
/*?*/                 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 );
/*?*/               }
/*N*/           }
/*N*/             nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
/*N*/           if ( nDiff > 0 )
/*?*/                 Shrink( nDiff PHEIGHT );
/*N*/           else if ( nDiff < 0 )
/*N*/           {
/*N*/                 Grow( -nDiff PHEIGHT );
/*N*/               //Es kann passieren, dass weniger Platz zur Verfuegung steht,
/*N*/               //als der bereits der Border benoetigt - die Groesse der
/*N*/               //PrtArea wird dann negativ.
/*N*/                 SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
/*N*/                 if( nPrtHeight < 0 )
/*N*/               {
/*?*/                     const SwTwips nDiff1 = Max( (Prt().*fnRect->fnGetTop)(),
/*?*/                                                 -nPrtHeight );
/*?*/                     (Prt().*fnRect->fnSubTop)( nDiff1 );
/*N*/               }
/*N*/           }
/*N*/       }
/*N*/       bValidSize = TRUE;
/*N*/   }
/*N*/ }
/*************************************************************************
|*
|*  SwFtnContFrm::GrowFrm(), ShrinkFrm()
|*
|*************************************************************************/

/*N*/ SwTwips SwFtnContFrm::GrowFrm( SwTwips nDist, BOOL bTst, BOOL /*bInfo*/ )
/*N*/ {
/*N*/   //Keine Pruefung ob FixSize oder nicht, die FtnContainer sind immer bis
/*N*/   //zur Maximalhoehe variabel.
/*N*/   //Wenn die Maximalhoehe LONG_MAX ist, so nehmen wir uns soviel Platz wie eben
/*N*/   //moeglich.
/*N*/   //Wenn die Seite eine spezielle Fussnotenseite ist, so nehmen wir uns auch
/*N*/   //soviel Platz wie eben moeglich.
/*N*/ #ifdef DBG_UTIL
/*N*/   if ( !GetUpper() || !GetUpper()->IsFtnBossFrm() )
/*?*/   {   OSL_ENSURE( !this, "Keine FtnBoss." );
/*?*/       return 0;
/*N*/   }
/*N*/ #endif
/*N*/
/*N*/     SWRECTFN( this )
/*N*/     if( (Frm().*fnRect->fnGetHeight)() > 0 &&
/*N*/          nDist > ( LONG_MAX - (Frm().*fnRect->fnGetHeight)() ) )
/*N*/         nDist = LONG_MAX - (Frm().*fnRect->fnGetHeight)();
/*N*/
/*N*/   SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper();
/*N*/   if( IsInSct() )
/*N*/   {
/*?*/       SwSectionFrm* pSect = FindSctFrm();
/*?*/       OSL_ENSURE( pSect, "GrowFrm: Missing SectFrm" );
/*?*/       // In a section, which has to maximize, a footnotecontainer is allowed
/*?*/       // to grow, when the section can't grow anymore.
/*?*/       if( !bTst && !pSect->IsColLocked() &&
/*?*/           pSect->ToMaximize( FALSE ) && pSect->Growable() )
/*?*/       {
/*?*/           pSect->InvalidateSize();
/*?*/           return 0;
/*?*/       }
/*N*/   }
/*N*/   SwPageFrm *pPage = pBoss->FindPageFrm();
/*N*/   if ( !pPage->IsFtnPage() || GetFmt()->GetDoc()->IsBrowseMode() )
/*N*/   {
/*N*/       if ( pBoss->GetMaxFtnHeight() != LONG_MAX )
/*N*/       {
/*N*/             nDist = Min( nDist, pBoss->GetMaxFtnHeight()
/*N*/                          - (Frm().*fnRect->fnGetHeight)() );
/*N*/           if ( nDist <= 0 )
/*?*/               return 0L;
/*N*/       }
/*N*/       //Der FtnBoss will bezueglich des MaxWerts auch noch mitreden.
/*N*/       if( !IsInSct() )
/*N*/       {
/*N*/           const SwTwips nMax = pBoss->GetVarSpace();
/*N*/           if ( nDist > nMax )
/*N*/               nDist = nMax;
/*N*/           if ( nDist <= 0 )
/*?*/               return 0L;
/*N*/       }
/*N*/   }
/*N*/     else if( nDist > (GetPrev()->Frm().*fnRect->fnGetHeight)() )
/*N*/       //aber mehr als der Body kann koennen und wollen wir nun auch wieder
/*N*/       //nicht herausruecken.
/*?*/         nDist = (GetPrev()->Frm().*fnRect->fnGetHeight)();
/*N*/
/*N*/     long nAvail = 0;
/*N*/   if ( GetFmt()->GetDoc()->IsBrowseMode() )
/*N*/   {
/*?*/         nAvail = GetUpper()->Prt().Height();
/*?*/       const SwFrm *pAvail = GetUpper()->Lower();
/*?*/       do
/*?*/         {   nAvail -= pAvail->Frm().Height();
/*?*/           pAvail = pAvail->GetNext();
/*?*/       } while ( pAvail );
/*?*/       if ( nAvail > nDist )
/*?*/           nAvail = nDist;
/*N*/   }
/*N*/
/*N*/     if ( !bTst )
/*N*/     {
/*N*/         (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() + nDist );
/*N*/         if( IsVertical() && !IsReverse() )
/*?*/             Frm().Pos().X() -= nDist;
/*N*/     }
/*N*/   long nGrow = nDist - nAvail,
/*N*/        nReal = 0;
/*N*/   if ( nGrow > 0 )
/*N*/   {
/*N*/       BYTE nAdjust = pBoss->NeighbourhoodAdjustment( this );
/*N*/       if( NA_ONLY_ADJUST == nAdjust )
/*N*/           nReal = AdjustNeighbourhood( nGrow, bTst );
/*N*/       else
/*N*/       {
/*?*/           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 );
/*N*/       }
/*N*/   }
/*N*/
/*N*/   nReal += nAvail;
/*N*/
/*N*/   if ( !bTst )
/*N*/   {
/*N*/       if ( nReal != nDist )
/*N*/         {
/*?*/             nDist -= nReal;
/*?*/           //Den masslosen Wunsch koennen wir leider nur in Grenzen erfuellen.
/*?*/             Frm().SSize().Height() -= nDist;
/*?*/             if( IsVertical() && !IsReverse() )
/*?*/                 Frm().Pos().X() += nDist;
/*N*/         }
/*N*/
/*N*/       //Nachfolger braucht nicht invalidiert werden, denn wir wachsen
/*N*/       //immer nach oben.
/*N*/       if( nReal )
/*N*/       {
/*N*/           _InvalidateSize();
/*N*/           _InvalidatePos();
/*N*/           InvalidatePage( pPage );
/*N*/       }
/*N*/   }
/*N*/   return nReal;
/*N*/ }


/*N*/ SwTwips SwFtnContFrm::ShrinkFrm( SwTwips nDiff, BOOL bTst, BOOL bInfo )
/*N*/ {
/*N*/   SwPageFrm *pPage = FindPageFrm();
/*N*/   if ( pPage && (!pPage->IsFtnPage() || GetFmt()->GetDoc()->IsBrowseMode()) )
/*N*/   {
/*N*/         SwTwips nRet = SwLayoutFrm::ShrinkFrm( nDiff, bTst, bInfo );
/*N*/         if( IsInSct() && !bTst )
/*N*/             FindSctFrm()->InvalidateNextPos();
/*N*/       if ( !bTst && nRet )
/*N*/       {
/*N*/           _InvalidatePos();
/*N*/           InvalidatePage( pPage );
/*N*/       }
/*N*/       return nRet;
/*N*/   }
/*?*/   return 0;
/*N*/ }


/*************************************************************************
|*
|*  SwFtnFrm::SwFtnFrm()
|*
|*************************************************************************/


/*N*/ SwFtnFrm::SwFtnFrm( SwFrmFmt *pFmt, SwCntntFrm *pCnt, SwTxtFtn *pAt ):
/*N*/   SwLayoutFrm( pFmt ),
/*N*/   pFollow( 0 ),
/*N*/   pMaster( 0 ),
/*N*/   pRef( pCnt ),
/*N*/   pAttr( pAt ),
/*N*/   bBackMoveLocked( FALSE )
/*N*/ {
/*N*/     nType = FRMC_FTN;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnFrm::InvalidateNxtFtnCnts()
|*
|*************************************************************************/


/*N*/ void SwFtnFrm::InvalidateNxtFtnCnts( SwPageFrm *pPage )
/*N*/ {
/*N*/   if ( GetNext() )
/*N*/   {
/*N*/       SwFrm *pCnt = ((SwLayoutFrm*)GetNext())->ContainsAny();
/*N*/       if( pCnt )
/*N*/       {
/*?*/           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 ) );
/*N*/       }
/*N*/   }
/*N*/ }

/*N*/ #ifdef DBG_UTIL
/*N*/
/*N*/ SwTwips SwFtnFrm::GrowFrm( SwTwips nDist, BOOL bTst, BOOL bInfo )
/*N*/ {
/*N*/     return SwLayoutFrm::GrowFrm( nDist, bTst, bInfo );
/*N*/ }


/*N*/ SwTwips SwFtnFrm::ShrinkFrm( SwTwips nDist, BOOL bTst, BOOL bInfo )
/*N*/ {
/*N*/     return SwLayoutFrm::ShrinkFrm( nDist, bTst, bInfo );
/*N*/ }
/*N*/ #endif

/*************************************************************************
|*
|*  SwFtnFrm::Cut()
|*
|*************************************************************************/


/*N*/ void SwFtnFrm::Cut()
/*N*/ {
/*N*/   if ( GetNext() )
/*?*/       GetNext()->InvalidatePos();
/*N*/   else if ( GetPrev() )
/*?*/       GetPrev()->SetRetouche();
/*N*/
/*N*/   //Erst removen, dann Upper Shrinken.
/*N*/   SwLayoutFrm *pUp = GetUpper();
/*N*/
/*N*/   //Verkettung korrigieren.
/*N*/   SwFtnFrm *pFtn = (SwFtnFrm*)this;
/*N*/   if ( pFtn->GetFollow() )
/*?*/       pFtn->GetFollow()->SetMaster( pFtn->GetMaster() );
/*N*/   if ( pFtn->GetMaster() )
/*?*/       pFtn->GetMaster()->SetFollow( pFtn->GetFollow() );
/*N*/   pFtn->SetFollow( 0 );
/*N*/   pFtn->SetMaster( 0 );
/*N*/
/*N*/   // Alle Verbindungen kappen.
/*N*/   Remove();
/*N*/
/*N*/   if ( pUp )
/*N*/   {
/*N*/       //Die letzte Fussnote nimmt ihren Container mit.
/*N*/       if ( !pUp->Lower() )
/*N*/       {
/*N*/           SwSectionFrm* pSect = pUp->FindSctFrm();
/*N*/           pUp->Cut();
/*N*/           delete pUp;
/*N*/           // Wenn der letzte Fussnotencontainer aus einem spaltigen Bereich verschwindet,
/*N*/           // so kann dieser, falls er keinen Follow besitzt, zusammenschrumpfen.
/*N*/           if( pSect && !pSect->ToMaximize( FALSE ) && !pSect->IsColLocked() )
/*?*/               pSect->_InvalidateSize();
/*N*/       }
/*N*/       else
/*?*/       {   if ( Frm().Height() )
/*?*/                 pUp->Shrink( Frm().Height() PHEIGHT );
/*?*/           pUp->SetCompletePaint();
/*?*/           pUp->InvalidatePage();
/*N*/       }
/*N*/   }
/*N*/ }

/*************************************************************************
|*
|*  SwFtnFrm::Paste()
|*
|*************************************************************************/


/*N*/ void SwFtnFrm::Paste(  SwFrm* pParent, SwFrm* pSibling )
/*N*/ {
/*N*/   OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
/*N*/   OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
/*N*/   OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
/*N*/   OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
/*N*/   OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
/*N*/           "Bin noch irgendwo angemeldet." );
/*N*/
/*N*/   //In den Baum einhaengen.
/*N*/   InsertBefore( (SwLayoutFrm*)pParent, pSibling );
/*N*/
/*N*/     SWRECTFN( this )
/*N*/     if( (Frm().*fnRect->fnGetWidth)()!=(pParent->Prt().*fnRect->fnGetWidth)() )
/*?*/       _InvalidateSize();
/*N*/   _InvalidatePos();
/*N*/   SwPageFrm *pPage = FindPageFrm();
/*N*/   InvalidatePage( pPage );
/*N*/   if ( GetNext() )
/*?*/       GetNext()->_InvalidatePos();
/*N*/     if( (Frm().*fnRect->fnGetHeight)() )
/*?*/         pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
/*N*/
/*N*/   //Wenn mein Vorgaenger mein Master ist und/oder wenn mein Nachfolger mein
/*N*/   //Follow ist so kann ich deren Inhalt uebernehmen und sie vernichten.
/*N*/   if ( GetPrev() && GetPrev() == GetMaster() )
/*?*/   {   OSL_ENSURE( SwFlowFrm::CastFlowFrm( GetPrev()->GetLower() ),
/*?*/               "Fussnote ohne Inhalt?" );
/*?*/       (SwFlowFrm::CastFlowFrm( GetPrev()->GetLower()))->
/*?*/           MoveSubTree( this, GetLower() );
/*?*/       SwFrm *pDel = GetPrev();
/*?*/       pDel->Cut();
/*?*/       delete pDel;
/*N*/   }
/*N*/   if ( GetNext() && GetNext() == GetFollow() )
/*?*/   {   OSL_ENSURE( SwFlowFrm::CastFlowFrm( GetNext()->GetLower() ),
/*?*/               "Fussnote ohne Inhalt?" );
/*?*/       (SwFlowFrm::CastFlowFrm( GetNext()->GetLower()))->MoveSubTree( this );
/*?*/       SwFrm *pDel = GetNext();
/*?*/       pDel->Cut();
/*?*/       delete pDel;
/*N*/   }
/*N*/ #ifdef DBG_UTIL
/*N*/   SwDoc *pDoc = GetFmt()->GetDoc();
/*N*/   if ( GetPrev() )
/*N*/   {
/*N*/       OSL_ENSURE( lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetPrev())->GetAttr() ) <=
/*?*/               lcl_FindFtnPos( pDoc, GetAttr() ), "Prev ist not FtnPrev" );
/*N*/   }
/*N*/   if ( GetNext() )
/*N*/   {
/*?*/       OSL_ENSURE( lcl_FindFtnPos( pDoc, GetAttr() ) <=
/*?*/               lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetNext())->GetAttr() ),
/*?*/               "Next is not FtnNext" );
/*N*/   }
/*N*/ #endif
/*N*/   InvalidateNxtFtnCnts( pPage );
/*N*/ }


/*************************************************************************
|*
|*  SwFrm::IsFtnAllowed()
|*
|*************************************************************************/


/*N*/ BOOL SwFrm::IsFtnAllowed() const
/*N*/ {
/*N*/   if ( !IsInDocBody() )
/*N*/       return FALSE;
/*N*/
/*N*/   if ( IsInTab() )
/*N*/   {
/*N*/       //Keine Ftns in wiederholten Headlines.
/*N*/       const SwTabFrm *pTab = ((SwFrm*)this)->ImplFindTabFrm();
/*N*/       if ( pTab->GetTable()->IsHeadlineRepeat() && pTab->IsFollow() )
/*N*/           return !((SwLayoutFrm*)pTab->Lower())->IsAnLower( this );
/*N*/   }
/*N*/   return TRUE;
/*N*/ }


/*************************************************************************
|*
|*  RemoveFtns()        Entfernen aller Fussnoten (nicht etwa die Referenzen)
|*                      und Entfernen aller Fussnotenseiten.
|*
|*************************************************************************/

/*N*/ void lcl_RemoveFtns( SwFtnBossFrm* pBoss, BOOL bPageOnly, BOOL bEndNotes )
/*N*/ {
/*N*/   do
/*N*/   {
/*N*/       SwFtnContFrm *pCont = pBoss->FindFtnCont();
/*N*/       if ( pCont )
/*N*/       {
/*?*/           SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
/*?*/           OSL_ENSURE( 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 );
/*N*/       }
/*N*/         if( !pBoss->IsInSct() )
/*N*/       {
/*N*/           // A sectionframe with the Ftn/EndnAtEnd-flags may contain
/*N*/           // foot/endnotes. If the last lower frame of the bodyframe is
/*N*/           // a multicolumned sectionframe, it may contain footnotes, too.
/*N*/           SwLayoutFrm* pBody = pBoss->FindBodyCont();
/*N*/           if( pBody && pBody->Lower() )
/*N*/           {
/*N*/               SwFrm* pLow = pBody->Lower();
/*N*/               while( pLow->GetNext() )
/*N*/               {
/*N*/                   if( pLow->IsSctFrm() && ( !pLow->GetNext() ||
/*N*/                       ((SwSectionFrm*)pLow)->IsAnyNoteAtEnd() ) &&
/*N*/                       ((SwSectionFrm*)pLow)->Lower() &&
/*N*/                       ((SwSectionFrm*)pLow)->Lower()->IsColumnFrm() )
/*?*/                       lcl_RemoveFtns( (SwColumnFrm*)((SwSectionFrm*)pLow)->Lower(),
/*?*/                           bPageOnly, bEndNotes );
/*N*/                   pLow = pLow->GetNext();
/*N*/               }
/*N*/           }
/*N*/       }
/*N*/       // noch 'ne Spalte?
/*N*/       pBoss = pBoss->IsColumnFrm() ? (SwColumnFrm*)pBoss->GetNext() : NULL;
/*N*/   } while( pBoss );
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::MakeFtnCont()
|*
|*************************************************************************/


/*N*/ SwFtnContFrm *SwFtnBossFrm::MakeFtnCont()
/*N*/ {
/*N*/   //Einfuegen eines Fussnotencontainers. Der Fussnotencontainer sitzt
/*N*/   //immer direkt hinter dem Bodytext.
/*N*/   //Sein FrmFmt ist immer das DefaultFrmFmt.
/*N*/
/*N*/ #ifdef DBG_UTIL
/*N*/   if ( FindFtnCont() )
/*?*/   {   OSL_ENSURE( !this, "Fussnotencontainer bereits vorhanden." );
/*?*/       return 0;
/*N*/   }
/*N*/ #endif
/*N*/
/*N*/   SwFtnContFrm *pNew = new SwFtnContFrm( GetFmt()->GetDoc()->GetDfltFrmFmt());
/*N*/   SwLayoutFrm *pLay = FindBodyCont();
/*N*/   pNew->Paste( this, pLay->GetNext() );
/*N*/   return pNew;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::FindFtnCont()
|*
|*************************************************************************/


/*N*/ SwFtnContFrm *SwFtnBossFrm::FindFtnCont()
/*N*/ {
/*N*/   SwFrm *pFrm = Lower();
/*N*/   while( pFrm && !pFrm->IsFtnContFrm() )
/*N*/       pFrm = pFrm->GetNext();
/*N*/
/*N*/ #ifdef DBG_UTIL
/*N*/   if ( pFrm )
/*N*/   {
/*N*/       SwFrm *pFtn = pFrm->GetLower();
/*N*/       OSL_ENSURE( pFtn, "Cont ohne Fussnote." );
/*N*/       while ( pFtn )
/*N*/       {
/*N*/           OSL_ENSURE( pFtn->IsFtnFrm(), "Nachbar von Fussnote keine Fussnote." );
/*N*/           pFtn = pFtn->GetNext();
/*N*/       }
/*N*/   }
/*N*/ #endif
/*N*/
/*N*/   return (SwFtnContFrm*)pFrm;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::FindNearestFtnCont()  Sucht den naechst greifbaren Fussnotencontainer.
|*
|*************************************************************************/

/*N*/ SwFtnContFrm *SwFtnBossFrm::FindNearestFtnCont( BOOL bDontLeave )
/*N*/ {
/*N*/   SwFtnContFrm *pCont = 0;
/*N*/   if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() )
/*N*/   {
/*N*/       pCont = FindFtnCont();
/*N*/       if ( !pCont )
/*N*/       {
/*N*/           SwPageFrm *pPage = FindPageFrm();
/*N*/           SwFtnBossFrm* pBoss = this;
/*N*/           BOOL bEndNote = pPage->IsEndNotePage();
/*N*/           do
/*N*/           {
/*N*/               BOOL bChgPage = lcl_NextFtnBoss( pBoss, pPage, bDontLeave );
/*N*/               // Haben wir noch einen Boss gefunden? Bei einem Seitenwechsel muss
/*N*/               // zudem noch das EndNotenFlag uebereinstimmen
/*N*/               if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) )
/*N*/                   pCont = pBoss->FindFtnCont();
/*N*/           } while ( !pCont && pPage );
/*N*/       }
/*N*/   }
/*N*/   return pCont;
/*N*/ }


/*************************************************************************
|*
|*  SwFtnBossFrm::FindFirstFtn()
|*
|*  Beschreibung        Erste Fussnote des Fussnotenbosses suchen.
|*
|*************************************************************************/


/*N*/ SwFtnFrm *SwFtnBossFrm::FindFirstFtn()
/*N*/ {
/*N*/   //Erstmal den naechsten FussnotenContainer suchen.
/*N*/   SwFtnContFrm *pCont = FindNearestFtnCont();
/*N*/   if ( !pCont )
/*N*/       return 0;
/*N*/
/*N*/   //Ab der ersten Fussnote im Container die erste suchen, die
/*N*/   //von der aktuellen Spalte (bzw. einspaltigen Seite) referenziert wird.
/*N*/
/*N*/   SwFtnFrm *pRet = (SwFtnFrm*)pCont->Lower();
/*N*/   const USHORT nRefNum = FindPageFrm()->GetPhyPageNum();
/*N*/   const USHORT nRefCol = lcl_ColumnNum( this );
/*N*/   USHORT nPgNum, nColNum; //Seitennummer, Spaltennummer
/*N*/   SwFtnBossFrm* pBoss;
/*N*/   SwPageFrm* pPage;
/*N*/   if( pRet )
/*N*/   {
/*N*/       pBoss = pRet->GetRef()->FindFtnBossFrm();
/*N*/       OSL_ENSURE( pBoss, "FindFirstFtn: No boss found" );
/*N*/       if( !pBoss )
/*?*/           return FALSE; // �There must be a bug, but no GPF
/*N*/       pPage = pBoss->FindPageFrm();
/*N*/       nPgNum = pPage->GetPhyPageNum();
/*N*/       if ( nPgNum == nRefNum )
/*N*/       {
/*N*/           nColNum = lcl_ColumnNum( pBoss );
/*N*/           if( nColNum == nRefCol )
/*N*/               return pRet; //hat ihn.
/*?*/           else if( nColNum > nRefCol )
/*?*/               return NULL; //mind. eine Spalte zu weit.
/*?*/       }
/*?*/       else if ( nPgNum > nRefNum )
/*?*/           return NULL;    //mind. eine Seite zu weit.
/*?*/   }
/*?*/   else
/*?*/       return NULL;
/*?*/   // Ende, wenn Ref auf einer spaeteren Seite oder auf der gleichen Seite in einer
/*?*/   // spaeteren Spalte liegt
/*?*/
/*?*/   do
/*?*/   {
/*?*/       while ( pRet->GetFollow() )
/*?*/           pRet = pRet->GetFollow();
/*?*/
/*?*/       SwFtnFrm *pNxt = (SwFtnFrm*)pRet->GetNext();
/*?*/       if ( !pNxt )
/*?*/       {
/*?*/           pBoss = pRet->FindFtnBossFrm();
/*?*/           pPage = pBoss->FindPageFrm();
/*?*/           lcl_NextFtnBoss( pBoss, pPage, FALSE ); // naechster FtnBoss
/*?*/           pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
/*?*/           if ( pCont )
/*?*/               pNxt = (SwFtnFrm*)pCont->Lower();
/*?*/       }
/*?*/       if ( pNxt )
/*?*/       {
/*?*/           pRet = pNxt;
/*?*/           pBoss = pRet->GetRef()->FindFtnBossFrm();
/*?*/           pPage = pBoss->FindPageFrm();
/*?*/           nPgNum = pPage->GetPhyPageNum();
/*?*/           if ( nPgNum == nRefNum )
/*?*/           {
/*?*/               nColNum = lcl_ColumnNum( pBoss );
/*?*/               if( nColNum == nRefCol )
/*?*/                   break; //hat ihn.
/*?*/               else if( nColNum > nRefCol )
/*?*/                   pRet = 0; //mind. eine Spalte zu weit.
/*?*/           }
/*?*/           else if ( nPgNum > nRefNum )
/*?*/               pRet = 0;   //mind. eine Seite zu weit.
/*?*/       }
/*?*/       else
/*?*/           pRet = 0;   //Gibt eben keinen.
/*?*/   } while( pRet );
/*?*/   return pRet;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::FindFirstFtn()
|*
|*  Beschreibunt        Erste Fussnote zum Cnt suchen.
|*
|*************************************************************************/


/*N*/ const SwFtnFrm *SwFtnBossFrm::FindFirstFtn( SwCntntFrm *pCnt ) const
/*N*/ {
/*N*/   const SwFtnFrm *pRet = ((SwFtnBossFrm*)this)->FindFirstFtn();
/*N*/   if ( pRet )
/*N*/   {
/*N*/       const USHORT nColNum = lcl_ColumnNum( this ); //Spaltennummer
/*N*/       const USHORT nPageNum = GetPhyPageNum();
/*N*/       while ( pRet && (pRet->GetRef() != pCnt) )
/*N*/       {
/*?*/           while ( pRet->GetFollow() )
/*?*/               pRet = pRet->GetFollow();
/*?*/
/*?*/           if ( pRet->GetNext() )
/*?*/               pRet = (const SwFtnFrm*)pRet->GetNext();
/*?*/           else
/*?*/           {   SwFtnBossFrm *pBoss = (SwFtnBossFrm*)pRet->FindFtnBossFrm();
/*?*/               SwPageFrm *pPage = pBoss->FindPageFrm();
/*?*/               lcl_NextFtnBoss( pBoss, pPage, FALSE ); // naechster FtnBoss
/*?*/               SwFtnContFrm *pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
/*?*/               pRet = pCont ? (SwFtnFrm*)pCont->Lower() : 0;
/*?*/           }
/*?*/           if ( pRet )
/*?*/           {
/*?*/               const SwFtnBossFrm* pBoss = pRet->GetRef()->FindFtnBossFrm();
/*?*/               if( pBoss->GetPhyPageNum() != nPageNum ||
/*?*/                   nColNum != lcl_ColumnNum( pBoss ) )
/*?*/               pRet = 0;
/*?*/           }
/*N*/       }
/*N*/   }
/*N*/   return pRet;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::ResetFtn()
|*
|*************************************************************************/


/*N*/ void SwFtnBossFrm::ResetFtn( const SwFtnFrm *pCheck )
/*N*/ {
/*N*/   //Vernichten der Inkarnationen von Fussnoten zum Attribut, wenn sie nicht
/*N*/   //zu pAssumed gehoeren.
/*N*/   OSL_ENSURE( !pCheck->GetMaster(), "Master not an Master." );
/*N*/
/*N*/   SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 );
/*N*/   SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
/*N*/   if ( !pNd )
/*?*/       pNd = pCheck->GetFmt()->GetDoc()->
/*?*/             GetNodes().GoNextSection( &aIdx, TRUE, FALSE );
/*N*/   SwClientIter aIter( *pNd );
/*N*/   SwClient* pLast = aIter.GoStart();
/*N*/   while( pLast )
/*N*/   {
/*N*/       if ( pLast->ISA(SwFrm) )
/*N*/       {
/*N*/           SwFrm *pFrm = (SwFrm*)pLast;
/*N*/           SwFrm *pTmp = pFrm->GetUpper();
/*N*/           while ( pTmp && !pTmp->IsFtnFrm() )
/*?*/               pTmp = pTmp->GetUpper();
/*N*/
/*N*/           SwFtnFrm *pFtn = (SwFtnFrm*)pTmp;
/*N*/           while ( pFtn && pFtn->GetMaster() )
/*?*/               pFtn = pFtn->GetMaster();
/*N*/           if ( pFtn != pCheck )
/*N*/           {
/*?*/               while ( pFtn )
/*?*/               {
/*?*/                   SwFtnFrm *pNxt = pFtn->GetFollow();
/*?*/                   pFtn->Cut();
/*?*/                   delete pFtn;
/*?*/                   pFtn = pNxt;
/*?*/               }
/*N*/           }
/*N*/       }
/*N*/       pLast = ++aIter;
/*N*/   }
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::InsertFtn()
|*
|*************************************************************************/


/*N*/ void SwFtnBossFrm::InsertFtn( SwFtnFrm* pNew )
/*N*/ {
/*N*/   //Die Fussnote haben wir, sie muss jetzt nur noch irgendwo
/*N*/   //hin und zwar vor die Fussnote, deren Attribut vor das
/*N*/   //der neuen zeigt (Position wird ueber das Doc ermittelt)
/*N*/   //Gibt es in diesem Fussnotenboss noch keine Fussnoten, so muss eben ein
/*N*/   //Container erzeugt werden.
/*N*/   //Gibt es bereits einen Container aber noch keine Fussnote zu diesem
/*N*/   //Fussnotenboss, so muss die Fussnote hinter die letzte Fussnote der dichtesten
/*N*/   //Vorseite/spalte.
/*N*/
/*N*/   ResetFtn( pNew );
/*N*/   SwFtnFrm *pSibling = FindFirstFtn();
/*N*/   BOOL bDontLeave = FALSE;
/*N*/
/*N*/   // Ok, a sibling has been found, but is the sibling in an acceptable
/*N*/   // environment?
/*N*/   if( IsInSct() )
/*N*/   {
/*?*/       SwSectionFrm* pMySect = ImplFindSctFrm();
/*?*/       BOOL bEndnt = pNew->GetAttr()->GetFtn().IsEndNote();
/*?*/       if( !bEndnt )
/*?*/       {
/*?*/           bDontLeave = pMySect->IsFtnAtEnd();
/*?*/           if( pSibling )
/*?*/           {
/*?*/               if( pMySect->IsFtnAtEnd() )
/*?*/               {
/*?*/                   if( !pSibling->IsInSct() ||
/*?*/                       !pMySect->IsAnFollow( pSibling->ImplFindSctFrm() ) )
/*?*/                       pSibling = NULL;
/*?*/               }
/*?*/               else if( pSibling->IsInSct() )
/*?*/                   pSibling = NULL;
/*?*/           }
/*?*/       }
/*N*/   }
/*N*/
/*N*/   if( pSibling && pSibling->FindPageFrm()->IsEndNotePage() !=
/*N*/       FindPageFrm()->IsEndNotePage() )
/*?*/       pSibling = NULL;
/*N*/
/*N*/   //Damit die Position herausgefunden werden kann.
/*N*/   SwDoc *pDoc = GetFmt()->GetDoc();
/*N*/   const ULONG nStPos = ::binfilter::lcl_FindFtnPos( pDoc, pNew->GetAttr() );
/*N*/
/*N*/   ULONG nCmpPos, nLastPos;
/*N*/   SwFtnContFrm *pParent = 0;
/*N*/   if( pSibling )
/*N*/   {
/*?*/       nCmpPos = ::binfilter::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
/*?*/       if( nCmpPos > nStPos )
/*?*/           pSibling = NULL;
/*N*/   }
/*N*/
/*N*/   if ( !pSibling )
/*N*/   {   pParent = FindFtnCont();
/*N*/       if ( !pParent )
/*N*/       {
/*N*/           //Es gibt noch keinen FussnotenContainer, also machen wir einen.
/*N*/           //HAAAAAAAALT! So einfach ist das leider mal wieder nicht: Es kann
/*N*/           //sein, dass irgendeine naechste Fussnote existiert die vor der
/*N*/           //einzufuegenden zu stehen hat, weil z.B. eine Fussnote ueber zig
/*N*/           //Seiten aufgespalten ist usw.
/*N*/           pParent = FindNearestFtnCont( bDontLeave );
/*N*/           if ( pParent )
/*N*/           {
/*?*/               SwFtnFrm *pFtn = (SwFtnFrm*)pParent->Lower();
/*?*/               if ( pFtn )
/*?*/               {
/*?*/
/*?*/                   nCmpPos = ::binfilter::lcl_FindFtnPos( pDoc, pFtn->GetAttr() );
/*?*/                   if ( nCmpPos > nStPos )
/*?*/                       pParent = 0;
/*?*/               }
/*?*/               else
/*?*/                   pParent = 0;
/*N*/           }
/*N*/       }
/*N*/       if ( !pParent )
/*N*/           //Jetzt kann aber ein Fussnotencontainer gebaut werden.
/*N*/           pParent = MakeFtnCont();
/*N*/       else
/*N*/       {
/*?*/           //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 )
/*?*/           {   OSL_ENSURE( !this, "Keinen Platz fuer Fussnote gefunden.");
/*?*/               return;
/*?*/           }
/*?*/           nCmpPos  = ::binfilter::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();
/*?*/                   OSL_ENSURE( !pSibling->GetMaster() || ( ENDNOTE > nStPos &&
/*?*/                           pSibling->GetAttr()->GetFtn().IsEndNote() ),
/*?*/                           "InsertFtn: Master expected I" );
/*?*/               }
/*?*/               else
/*?*/               {
/*?*/                   pNxtB = pSibling->FindFtnBossFrm();
/*?*/                   SwPageFrm *pSibPage = pNxtB->FindPageFrm();
/*?*/                   BOOL bEndNote = pSibPage->IsEndNotePage();
/*?*/                   BOOL bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
/*?*/                   // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden.
/*?*/                   SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
/*?*/                       pSibPage->IsEndNotePage() == bEndNote )
/*?*/                       ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
/*?*/                   if( pCont )
/*?*/                       pSibling = (SwFtnFrm*)pCont->Lower();
/*?*/                   else // kein weiterer FtnContainer, dann werden  wir uns wohl hinter
/*?*/                       break; // pSibling haengen
/*?*/               }
/*?*/               if ( pSibling )
/*?*/               {
/*?*/                   nCmpPos = ::binfilter::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
/*?*/                   OSL_ENSURE( 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();
/*?*/               OSL_ENSURE( !pSibling->GetNext(), "InsertFtn: Who's that guy?" );
/*?*/           }
/*N*/       }
/*N*/   }
/*N*/   else
/*N*/   {   //Die erste Fussnote der Spalte/Seite haben wir an der Hand, jetzt ausgehend
/*?*/       //von dieser die erste zur selben Spalte/Seite suchen deren Index hinter
/*?*/       //den uebergebenen zeigt, die letzte, die wir an der Hand hatten, ist
/*?*/       //dann der Vorgaenger.
/*?*/       SwFtnBossFrm* pBoss = pNew->GetRef()->FindFtnBossFrm(
/*?*/           !pNew->GetAttr()->GetFtn().IsEndNote() );
/*?*/       USHORT nRefNum = pBoss->GetPhyPageNum();    // Die Seiten- und
/*?*/       USHORT nRefCol = lcl_ColumnNum( pBoss );    // Spaltennummer der neuen Fussnote
/*?*/       BOOL bEnd = FALSE;
/*?*/       SwFtnFrm *pLastSib = 0;
/*?*/       while ( pSibling && !bEnd && (nCmpPos <= nStPos) )
/*?*/       {
/*?*/           pLastSib = pSibling;
/*?*/           nLastPos = nCmpPos;
/*?*/
/*?*/           while ( pSibling->GetFollow() )
/*?*/               pSibling = pSibling->GetFollow();
/*?*/
/*?*/           SwFtnFrm *pFoll = (SwFtnFrm*)pSibling->GetNext();
/*?*/           if ( pFoll )
/*?*/           {
/*?*/               pBoss = pSibling->GetRef()->FindFtnBossFrm( !pSibling->
/*?*/                                           GetAttr()->GetFtn().IsEndNote() );
/*?*/               USHORT nTmpRef;
/*?*/               if( nStPos >= ENDNOTE ||
/*?*/                   (nTmpRef = pBoss->GetPhyPageNum()) < nRefNum ||
/*?*/                   ( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol ))
/*?*/                   pSibling = pFoll;
/*?*/               else
/*?*/                   bEnd = TRUE;
/*?*/           }
/*?*/           else
/*?*/           {
/*?*/               SwFtnBossFrm* pNxtB = pSibling->FindFtnBossFrm();
/*?*/               SwPageFrm *pSibPage = pNxtB->FindPageFrm();
/*?*/               BOOL bEndNote = pSibPage->IsEndNotePage();
/*?*/               BOOL bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
/*?*/               // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden.
/*?*/               SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
/*?*/                   pSibPage->IsEndNotePage() == bEndNote )
/*?*/                   ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
/*?*/               if ( pCont )
/*?*/                   pSibling = (SwFtnFrm*)pCont->Lower();
/*?*/               else
/*?*/                   bEnd = TRUE;
/*?*/           }
/*?*/           if ( !bEnd && pSibling )
/*?*/               nCmpPos = ::binfilter::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
/*?*/           if ( pSibling && pLastSib && (pSibling != pLastSib) )
/*?*/           {   //Sind wir vielleicht bereits ueber das Ziel hinausgeschossen?
/*?*/               if ( (nLastPos < nCmpPos) && (nCmpPos > nStPos) )
/*?*/               {
/*?*/                   pSibling = pLastSib;
/*?*/                   bEnd = TRUE;
/*?*/               }
/*?*/           }
/*?*/       }
/*N*/   }
/*N*/   if ( pSibling )
/*N*/   {
/*?*/       nCmpPos = ::binfilter::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 )
/*?*/               {
/*?*/                   OSL_ENSURE( FALSE, "InsertFtn: Master expected II" );
/*?*/                   do
/*?*/                       pSibling = pSibling->GetMaster();
/*?*/                   while ( pSibling->GetMaster() );
/*?*/               }
/*?*/           }
/*?*/           pParent = (SwFtnContFrm*)pSibling->GetUpper();
/*?*/       }
/*N*/   }
/*N*/   OSL_ENSURE( pParent, "paste in space?" );
/*N*/   pNew->Paste( pParent, pSibling );
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::AppendFtn()
|*
|*************************************************************************/


/*N*/ void SwFtnBossFrm::AppendFtn( SwCntntFrm *pRef, SwTxtFtn *pAttr )
/*N*/ {
/*N*/   //Wenn es die Fussnote schon gibt tun wir nix.
/*N*/   if ( FindFtn( pRef, pAttr ) )
/*?*/       return;
/*N*/
/*N*/   //Wenn Fussnoten am Dokumentende eingestellt sind, so brauchen wir 'eh erst
/*N*/   //ab der entsprechenden Seite zu suchen.
/*N*/   //Wenn es noch keine gibt, muss eben eine erzeugt werden.
/*N*/   //Wenn es sich um eine Endnote handelt, muss eine Endnotenseite gesucht
/*N*/   //bzw. erzeugt werden.
/*N*/   SwDoc *pDoc = GetFmt()->GetDoc();
/*N*/   SwFtnBossFrm *pBoss = this;
/*N*/   SwPageFrm *pPage = FindPageFrm();
/*N*/   SwPageFrm *pMyPage = pPage;
/*N*/   BOOL bChgPage = FALSE;
/*N*/   BOOL bEnd = FALSE;
/*N*/   if ( pAttr->GetFtn().IsEndNote() )
/*N*/   {
/*?*/       bEnd = TRUE;
/*?*/       if( GetUpper()->IsSctFrm() &&
/*?*/           ((SwSectionFrm*)GetUpper())->IsEndnAtEnd() )
/*?*/       {
/*?*/           SwFrm* pLast =
/*?*/               ((SwSectionFrm*)GetUpper())->FindLastCntnt( FINDMODE_ENDNOTE );
/*?*/           if( pLast )
/*?*/           {
/*?*/               pBoss = pLast->FindFtnBossFrm();
/*?*/               pPage = pBoss->FindPageFrm();
/*?*/           }
/*?*/       }
/*?*/       else
/*?*/       {
/*?*/           while ( pPage->GetNext() && !pPage->IsEndNotePage() )
/*?*/           {
/*?*/               pPage = (SwPageFrm*)pPage->GetNext();
/*?*/               bChgPage = TRUE;
/*?*/           }
/*?*/           if ( !pPage->IsEndNotePage() )
/*?*/           {
/*?*/               SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
/*?*/               pPage = ::binfilter::InsertNewPage( *pDesc, pPage->GetUpper(),
/*?*/                       !pPage->OnRightPage(), FALSE, TRUE, 0 );
/*?*/               pPage->SetEndNotePage( TRUE );
/*?*/               bChgPage = TRUE;
/*?*/           }
/*?*/           else
/*?*/           {
/*?*/               //Wir koennen wenigstens schon mal ungefaehr die richtige Seite
/*?*/               //suchen. Damit stellen wir sicher das wir auch bei hunderten
/*?*/               //Fussnoten noch in endlicher Zeit fertig werden.
/*?*/               SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
/*?*/               const ULONG nStPos = ::binfilter::lcl_FindFtnPos( pDoc, pAttr );
/*?*/               while ( pNxt && pNxt->IsEndNotePage() )
/*?*/               {
/*?*/                   SwFtnContFrm *pCont = pNxt->FindFtnCont();
/*?*/                   if ( pCont && pCont->Lower() )
/*?*/                   {
/*?*/                       OSL_ENSURE( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" );
/*?*/                       if ( nStPos > ::binfilter::lcl_FindFtnPos( pDoc,
/*?*/                                       ((SwFtnFrm*)pCont->Lower())->GetAttr()))
/*?*/                       {
/*?*/                           pPage = pNxt;
/*?*/                           pNxt = (SwPageFrm*)pPage->GetNext();
/*?*/                           continue;
/*?*/                       }
/*?*/                   }
/*?*/                   break;
/*?*/               }
/*?*/           }
/*?*/       }
/*N*/   }
/*N*/   else if( FTNPOS_CHAPTER == pDoc->GetFtnInfo().ePos && ( !GetUpper()->
/*N*/            IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd() ) )
/*N*/   {
/*?*/       while ( pPage->GetNext() && !pPage->IsFtnPage() &&
/*?*/               !((SwPageFrm*)pPage->GetNext())->IsEndNotePage() )
/*?*/       {
/*?*/           pPage = (SwPageFrm*)pPage->GetNext();
/*?*/           bChgPage = TRUE;
/*?*/       }
/*?*/
/*?*/       if ( !pPage->IsFtnPage() )
/*?*/       {
/*?*/           SwPageDesc *pDesc = pDoc->GetFtnInfo().GetPageDesc( *pDoc );
/*?*/           pPage = ::binfilter::InsertNewPage( *pDesc, pPage->GetUpper(),
/*?*/               !pPage->OnRightPage(), FALSE, TRUE, pPage->GetNext() );
/*?*/           bChgPage = TRUE;
/*?*/       }
/*?*/       else
/*?*/       {
/*?*/           //Wir koennen wenigstens schon mal ungefaehr die richtige Seite
/*?*/           //suchen. Damit stellen wir sicher das wir auch bei hunderten
/*?*/           //Fussnoten noch in endlicher Zeit fertig werden.
/*?*/           SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
/*?*/           const ULONG nStPos = ::binfilter::lcl_FindFtnPos( pDoc, pAttr );
/*?*/           while ( pNxt && pNxt->IsFtnPage() && !pNxt->IsEndNotePage() )
/*?*/           {
/*?*/               SwFtnContFrm *pCont = pNxt->FindFtnCont();
/*?*/               if ( pCont && pCont->Lower() )
/*?*/               {
/*?*/                   OSL_ENSURE( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" );
/*?*/                   if ( nStPos > ::binfilter::lcl_FindFtnPos( pDoc,
/*?*/                                       ((SwFtnFrm*)pCont->Lower())->GetAttr()))
/*?*/                   {
/*?*/                       pPage = pNxt;
/*?*/                       pNxt = (SwPageFrm*)pPage->GetNext();
/*?*/                       continue;
/*?*/                   }
/*?*/               }
/*?*/               break;
/*?*/           }
/*?*/       }
/*N*/   }
/*N*/
/*N*/   //Erstmal eine Fussnote und die benoetigten CntntFrms anlegen.
/*N*/   if ( !pAttr->GetStartNode() )
/*?*/   {   OSL_ENSURE( !this, "Kein Fussnoteninhalt." );
/*?*/       return;
/*N*/   }
/*N*/
/*N*/   SwFtnFrm *pNew = new SwFtnFrm( pDoc->GetDfltFrmFmt(), pRef, pAttr );
/*N*/   {
/*N*/       SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
/*N*/       ::binfilter::_InsertCnt( pNew, pDoc, aIdx.GetIndex() );
/*N*/   }
/*N*/   // Wenn die Seite gewechselt (oder gar neu angelegt) wurde,
/*N*/   // muessen wir uns dort in die erste Spalte setzen
/*N*/   if( bChgPage )
/*N*/   {
/*?*/       SwLayoutFrm* pBody = pPage->FindBodyCont();
/*?*/       OSL_ENSURE( pBody, "AppendFtn: NoPageBody?" );
/*?*/       if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
/*?*/           pBoss = (SwFtnBossFrm*)pBody->Lower();
/*?*/       else
/*?*/           pBoss = pPage; // bei nichtspaltigen Seiten auf die Seite selbst
/*N*/   }
/*N*/   pBoss->InsertFtn( pNew );
/*N*/   if ( pNew->GetUpper() )         //Eingesetzt oder nicht?
/*N*/   {
/*N*/       ::binfilter::RegistFlys( pNew->FindPageFrm(), pNew );
/*N*/       SwSectionFrm* pSect = FindSctFrm();
/*N*/       // Der Inhalt des FtnContainers in einem (spaltigen) Bereich
/*N*/       // braucht nur kalkuliert zu werden,
/*N*/       // wenn der Bereich bereits bis zur Unterkante seines Uppers geht.
/*N*/       if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() :
/*N*/           !pSect->IsFtnAtEnd() ) && pSect->Growable() )
/*?*/           pSect->InvalidateSize();
/*N*/       else
/*N*/       {
/*N*/           SwCntntFrm *pCnt = pNew->ContainsCntnt();
/*N*/           while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
/*N*/           {
/*N*/               pCnt->Calc();
/*N*/               pCnt = (SwCntntFrm*)pCnt->FindNextCnt();
/*N*/           }
/*N*/       }
/*N*/       pMyPage->UpdateFtnNum();
/*N*/   }
/*N*/   else
/*?*/       delete pNew;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::FindFtn()
|*
|*************************************************************************/


/*N*/ SwFtnFrm *SwFtnBossFrm::FindFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr )
/*N*/ {
/*N*/   //Der einfachste und sicherste Weg geht ueber das Attribut.
/*N*/   OSL_ENSURE( pAttr->GetStartNode(), "FtnAtr ohne StartNode." );
/*N*/   SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
/*N*/   SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
/*N*/   if ( !pNd )
/*N*/       pNd = pRef->GetAttrSet()->GetDoc()->
/*?*/             GetNodes().GoNextSection( &aIdx, TRUE, FALSE );
/*N*/   if ( !pNd )
/*?*/       return 0;
/*N*/   SwClientIter aIter( *pNd );
/*N*/   SwClient *pClient;
/*N*/   if ( 0 != (pClient = aIter.GoStart()) )
/*N*/       do
/*N*/       {
/*N*/           if ( pClient->IsA( TYPE(SwFrm) ) )
/*N*/           {
/*N*/               SwFrm *pFrm = ((SwFrm*)pClient)->GetUpper();
/*N*/               SwFtnFrm *pFtn = pFrm->FindFtnFrm();
/*N*/               if ( pFtn && pFtn->GetRef() == pRef )
/*N*/               {
/*N*/                   // The following condition becomes true, if the whole
/*N*/                   // footnotecontent is a section. While no frames exist,
/*N*/                   // the HiddenFlag of the section is set, this causes
/*N*/                   // the GoNextSection-function leaves the footnote.
/*N*/                   if( pFtn->GetAttr() != pAttr )
/*?*/                       return 0;
/*N*/                   while ( pFtn && pFtn->GetMaster() )
/*?*/                       pFtn = pFtn->GetMaster();
/*N*/                   return pFtn;
/*N*/               }
/*N*/           }
/*?*/       } while ( 0 != (pClient = aIter++) );
/*N*/
/*N*/   return 0;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::RemoveFtn()
|*
|*************************************************************************/


/*N*/ void SwFtnBossFrm::RemoveFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr,
/*N*/                             BOOL bPrep )
/*N*/ {
/*N*/   SwFtnFrm *pFtn = FindFtn( pRef, pAttr );
/*N*/   if( pFtn )
/*N*/   {
/*N*/       do
/*N*/       {
/*N*/           SwFtnFrm *pFoll = pFtn->GetFollow();
/*N*/           pFtn->Cut();
/*N*/           delete pFtn;
/*N*/           pFtn = pFoll;
/*N*/       } while ( pFtn );
/*N*/       if( bPrep && pRef->IsFollow() )
/*N*/       {
/*?*/           OSL_ENSURE( pRef->IsTxtFrm(), "NoTxtFrm has Footnote?" );
/*?*/           SwTxtFrm* pMaster = (SwTxtFrm*)pRef->FindMaster();
/*?*/           if( !pMaster->IsLocked() )
/*?*/               pMaster->Prepare( PREP_FTN_GONE );
/*N*/       }
/*N*/   }
/*N*/   FindPageFrm()->UpdateFtnNum();
/*N*/ }


/*************************************************************************
|*
|*  SwFtnBossFrm::RearrangeFtns()
|*
|*************************************************************************/


/*N*/ void SwFtnBossFrm::RearrangeFtns( const SwTwips nDeadLine, const BOOL bLock,
/*N*/                                 const SwTxtFtn *pAttr )
/*N*/ {
/*N*/   //Alle Fussnoten der Spalte/Seite dergestalt anformatieren,
/*N*/   //dass sie ggf. die Spalte/Seite wechseln.
/*N*/
/*N*/   SwSaveFtnHeight aSave( this, nDeadLine );
/*N*/   SwFtnFrm *pFtn = FindFirstFtn();
/*N*/   if( pFtn && pFtn->GetPrev() && bLock )
/*N*/   {
/*?*/       SwFtnFrm* pFirst = (SwFtnFrm*)pFtn->GetUpper()->Lower();
/*?*/       SwFrm* pCntnt = pFirst->ContainsAny();
/*?*/       if( pCntnt )
/*?*/       {
/*?*/             BOOL bUnlock = !pFirst->IsBackMoveLocked();
/*?*/           pFirst->LockBackMove();
/*?*/           pFirst->Calc();
/*?*/           pCntnt->Calc();
/*?*/             if( bUnlock )
/*?*/                 pFirst->UnlockBackMove();
/*?*/       }
/*?*/       pFtn = FindFirstFtn();
/*N*/   }
/*N*/   SwDoc *pDoc = GetFmt()->GetDoc();
/*N*/   const ULONG nFtnPos = pAttr ? ::binfilter::lcl_FindFtnPos( pDoc, pAttr ) : 0;
/*N*/   SwFrm *pCnt = pFtn ? pFtn->ContainsAny() : 0;
/*N*/   if ( pCnt )
/*N*/   {
/*N*/       BOOL bMore = TRUE;
/*N*/       BOOL bStart = pAttr == 0; // wenn kein Attribut uebergeben wird, alle bearbeiten
/*N*/       do
/*N*/       {
/*N*/           if( !bStart )
/*N*/               bStart = ::binfilter::lcl_FindFtnPos( pDoc, pCnt->FindFtnFrm()->GetAttr() )
/*N*/                        == nFtnPos;
/*N*/           if( bStart )
/*N*/             {
/*N*/                 pCnt->_InvalidatePos();
/*N*/               pCnt->_InvalidateSize();
/*N*/               pCnt->Prepare( PREP_ADJUST_FRM );
/*N*/                 SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm();
/*N*/                 // invalidate position of footnote frame, if it's below
/*N*/                 // its footnote container, in order to assure its correct
/*N*/                 // position, probably calculating its previous
/*N*/                 // footnote frames.
/*N*/                 {
/*N*/                     SWRECTFN( this );
/*N*/                     SwFrm* aFtnContFrm = pFtnFrm->GetUpper();
/*N*/                     if ( (pFtnFrm->Frm().*fnRect->fnTopDist)((aFtnContFrm->*fnRect->fnGetPrtBottom)()) > 0 )
/*N*/                     {
/*N*/                         pFtnFrm->_InvalidatePos();
/*N*/                     }
/*N*/                 }
/*N*/                 if ( bLock )
/*N*/               {
/*N*/                     BOOL bUnlock = !pFtnFrm->IsBackMoveLocked();
/*N*/                     pFtnFrm->LockBackMove();
/*N*/                     pFtnFrm->Calc();
/*N*/                   pCnt->Calc();
/*N*/                     if( bUnlock )
/*N*/                     {
/*N*/                         pFtnFrm->UnlockBackMove();
/*N*/                         if( !pFtnFrm->Lower() &&
/*N*/                             !pFtnFrm->IsColLocked() )
/*N*/                         {
/*N*/                             pFtnFrm->Cut();
/*N*/                             delete pFtnFrm;
/*N*/                         }
/*N*/                     }
/*N*/               }
/*N*/               else
/*N*/               {
/*N*/                     pFtnFrm->Calc();
/*N*/                   pCnt->Calc();
/*N*/               }
/*N*/           }
/*N*/           SwSectionFrm *pDel = NULL;
/*N*/           if( pCnt->IsSctFrm() )
/*N*/           {
/*N*/               SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
/*N*/               if( pTmp )
/*N*/               {
/*N*/                   pCnt = pTmp;
/*N*/                   continue;
/*N*/               }
/*N*/               pDel = (SwSectionFrm*)pCnt;
/*N*/           }
/*N*/           if ( pCnt->GetNext() )
/*N*/               pCnt = pCnt->GetNext();
/*N*/           else
/*N*/           {
/*N*/               pCnt = pCnt->FindNext();
/*N*/               if ( pCnt )
/*N*/               {
/*N*/                   SwFtnFrm* pFtn1 = pCnt->FindFtnFrm();
/*N*/                   if( pFtn1->GetRef()->FindFtnBossFrm(
/*N*/                       pFtn1->GetAttr()->GetFtn().IsEndNote() ) != this )
/*N*/                       bMore = FALSE;
/*N*/               }
/*N*/               else
/*N*/                   bMore = FALSE;
/*N*/           }
/*N*/           if( pDel )
/*N*/           {
/*N*/               pDel->Cut();
/*N*/               delete pDel;
/*N*/           }
/*N*/           if ( bMore )
/*N*/           {
/*N*/               //Nicht weiter als bis zur angegebenen Fussnote, falls eine
/*N*/               //angegeben wurde.
/*N*/               if ( pAttr &&
/*N*/                    (::binfilter::lcl_FindFtnPos( pDoc,
/*N*/                                   pCnt->FindFtnFrm()->GetAttr()) > nFtnPos ) )
/*N*/                   bMore = FALSE;
/*N*/           }
/*N*/       } while ( bMore );
/*N*/   }
/*N*/ }

/*************************************************************************
|*
|*  SwPageFrm::UpdateFtnNum()
|*
|*************************************************************************/

/*N*/ void SwPageFrm::UpdateFtnNum()
/*N*/ {
/*N*/   //Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist.
/*N*/   if ( GetFmt()->GetDoc()->GetFtnInfo().eNum != FTNNUM_PAGE )
/*N*/       return;
/*?*/
/*?*/   SwLayoutFrm* pBody = FindBodyCont();
/*?*/   if( !pBody || !pBody->Lower() )
/*?*/       return;
/*?*/
/*?*/   SwCntntFrm* pCntnt = pBody->ContainsCntnt();
/*?*/   USHORT nNum = 0;
/*?*/
/*?*/   while( pCntnt && pCntnt->FindPageFrm() == this )
/*?*/   {
/*?*/       if( ((SwTxtFrm*)pCntnt)->HasFtn() )
/*?*/       {
/*?*/           SwFtnBossFrm* pBoss = pCntnt->FindFtnBossFrm( TRUE );
/*?*/           if( pBoss->GetUpper()->IsSctFrm() &&
/*?*/               ((SwSectionFrm*)pBoss->GetUpper())->IsOwnFtnNum() )
/*?*/               pCntnt = ((SwSectionFrm*)pBoss->GetUpper())->FindLastCntnt();
/*?*/           else
/*?*/           {
/*?*/               SwFtnFrm* pFtn = (SwFtnFrm*)pBoss->FindFirstFtn( pCntnt );
/*?*/               while( pFtn )
/*?*/               {
/*?*/                   SwTxtFtn* pTxtFtn = pFtn->GetAttr();
/*?*/                   if( !pTxtFtn->GetFtn().IsEndNote() &&
/*?*/                       !pTxtFtn->GetFtn().GetNumStr().Len() &&
/*?*/                       !pFtn->GetMaster() &&
/*?*/                       (pTxtFtn->GetFtn().GetNumber() != ++nNum) )
/*?*/                       pTxtFtn->SetNumber( nNum );
/*?*/                   if ( pFtn->GetNext() )
/*?*/                       pFtn = (SwFtnFrm*)pFtn->GetNext();
/*?*/                   else
/*?*/                   {
/*?*/                       SwFtnBossFrm* pBoss1 = pFtn->FindFtnBossFrm( TRUE );
/*?*/                       SwPageFrm* pPage = pBoss1->FindPageFrm();
/*?*/                       pFtn = NULL;
/*?*/                       lcl_NextFtnBoss( pBoss1, pPage, FALSE );
/*?*/                       if( pBoss1 )
/*?*/                       {
/*?*/                           SwFtnContFrm *pCont = pBoss1->FindNearestFtnCont();
/*?*/                           if ( pCont )
/*?*/                               pFtn = (SwFtnFrm*)pCont->Lower();
/*?*/                       }
/*?*/                   }
/*?*/                   if( pFtn && pFtn->GetRef() != pCntnt )
/*?*/                       pFtn = NULL;
/*?*/               }
/*?*/           }
/*?*/       }
/*?*/       pCntnt = pCntnt->FindNextCnt();
/*?*/   }
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::SetFtnDeadLine()
|*
|*************************************************************************/

/*N*/ void SwFtnBossFrm::SetFtnDeadLine( const SwTwips nDeadLine )
/*N*/ {
/*N*/   SwFrm *pBody = FindBodyCont();
/*N*/   pBody->Calc();
/*N*/
/*N*/   SwFrm *pCont = FindFtnCont();
/*N*/   const SwTwips nMax = nMaxFtnHeight;//Aktuelle MaxHeight nicht ueberschreiten.
/*N*/     SWRECTFN( this )
/*N*/   if ( pCont )
/*N*/   {
/*N*/       pCont->Calc();
/*N*/         nMaxFtnHeight = -(pCont->Frm().*fnRect->fnBottomDist)( nDeadLine );
/*N*/   }
/*N*/   else
/*N*/         nMaxFtnHeight = -(pBody->Frm().*fnRect->fnBottomDist)( nDeadLine );
/*N*/
/*N*/   if ( GetFmt()->GetDoc()->IsBrowseMode() )
/*?*/         nMaxFtnHeight += pBody->Grow( LONG_MAX PHEIGHT, TRUE );
/*N*/   if ( IsInSct() )
/*?*/         nMaxFtnHeight += FindSctFrm()->Grow( LONG_MAX PHEIGHT, TRUE );
/*N*/
/*N*/   if ( nMaxFtnHeight < 0 )
/*N*/       nMaxFtnHeight = 0;
/*N*/   if ( nMax != LONG_MAX && nMaxFtnHeight > nMax )
/*N*/       nMaxFtnHeight = nMax;
/*N*/ }

/*************************************************************************
|*
|*  SwFtnBossFrm::GetVarSpace()
|*
|*************************************************************************/
/*N*/ SwTwips SwFtnBossFrm::GetVarSpace() const
/*N*/ {
/*N*/   //Fuer Seiten soll ein Wert von 20% der Seitenhoehe nicht unterschritten
/*N*/   //werden (->AMA: was macht MS da?)
/*N*/   //->AMA: Was ist da fuer Bereiche sinnvoll (und kompatibel zu MS ;-)?
/*N*/   //AMA: MS kennt scheinbar kein Begrenzung, die Fussnoten nehmen durchaus
/*N*/   // die ganze Seite/Spalte ein.
/*N*/
/*N*/   const SwPageFrm* pPg = FindPageFrm();
/*N*/   OSL_ENSURE( pPg, "Footnote lost page" );
/*N*/
/*N*/   const SwFrm *pBody = FindBodyCont();
/*N*/   SwTwips nRet;
/*N*/   if( pBody )
/*N*/   {
/*N*/         SWRECTFN( this )
/*N*/       if( IsInSct() )
/*N*/       {
/*?*/           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?
/*?*/           {
/*?*/               OSL_ENSURE( !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;
/*?*/       }
/*N*/       else
/*N*/             nRet = - (pPg->Prt().*fnRect->fnGetHeight)()/5;
/*N*/         nRet += (pBody->Frm().*fnRect->fnGetHeight)();
/*N*/       if( nRet < 0 )
/*?*/           nRet = 0;
/*N*/   }
/*N*/   else
/*?*/       nRet = 0;
/*N*/   if ( IsPageFrm() && GetFmt()->GetDoc()->IsBrowseMode() )
/*?*/       nRet += BROWSE_HEIGHT - Frm().Height();
/*N*/   return nRet;
/*N*/ }

/*************************************************************************
|*
|*  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.
|*
|*************************************************************************/

/*N*/ BYTE SwFtnBossFrm::_NeighbourhoodAdjustment( const SwFrm* /*pFrm*/ ) const
/*N*/ {
/*N*/   BYTE nRet = NA_ONLY_ADJUST;
/*N*/   if( GetUpper() && !GetUpper()->IsPageBodyFrm() )
/*N*/   {
/*N*/       // Spaltige Rahmen erfordern Grow/Shrink
/*N*/       if( GetUpper()->IsFlyFrm() )
/*N*/           nRet = NA_GROW_SHRINK;
/*N*/       else
/*N*/       {
/*?*/           OSL_ENSURE( GetUpper()->IsSctFrm(), "NeighbourhoodAdjustment: Unexspected Upper" );
/*?*/           if( !GetNext() && !GetPrev() )
/*?*/               nRet = NA_GROW_ADJUST; // section with a single column (FtnAtEnd)
/*?*/           else
/*?*/           {
/*?*/               const SwFrm* pTmp = Lower();
/*?*/               OSL_ENSURE( pTmp, "NeighbourhoodAdjustment: Missing Lower()" );
/*?*/               if( !pTmp->GetNext() )
/*?*/                   nRet = NA_GROW_SHRINK;
/*?*/               else if( !GetUpper()->IsColLocked() )
/*?*/                   nRet = NA_ADJUST_GROW;
/*?*/               OSL_ENSURE( !pTmp->GetNext() || pTmp->GetNext()->IsFtnContFrm(),
/*?*/                       "NeighbourhoodAdjustment: Who's that guy?" );
/*?*/           }
/*N*/       }
/*N*/   }
/*N*/   return nRet;
/*N*/ }

/*************************************************************************
|*
|*  SwLayoutFrm::MoveLowerFtns
|*
|*************************************************************************/


/*N*/ BOOL SwLayoutFrm::MoveLowerFtns( SwCntntFrm* /*pStart*/, SwFtnBossFrm *pOldBoss,
/*N*/                                SwFtnBossFrm *pNewBoss, const BOOL /*bFtnNums*/ )
/*N*/ {
/*N*/   SwDoc *pDoc = GetFmt()->GetDoc();
/*N*/   if ( !pDoc->GetFtnIdxs().Count() )
/*N*/       return FALSE;
/*?*/   if( pDoc->GetFtnInfo().ePos == FTNPOS_CHAPTER &&
/*?*/       ( !IsInSct() || !FindSctFrm()->IsFtnAtEnd() ) )
/*?*/       return TRUE;
/*?*/
/*?*/   if ( !pNewBoss )
/*?*/       pNewBoss = FindFtnBossFrm( TRUE );
/*?*/   if ( pNewBoss == pOldBoss )
/*?*/       return FALSE;
/*?*/
/*?*/   return FALSE;
/*N*/ }


/*************************************************************************
|*
|*  class SwSaveFtnHeight
|*
|*************************************************************************/


/*N*/ SwSaveFtnHeight::SwSaveFtnHeight( SwFtnBossFrm *pBs, const SwTwips nDeadLine ) :
/*N*/   pBoss( pBs ),
/*N*/   nOldHeight( pBs->GetMaxFtnHeight() )
/*N*/ {
/*N*/   pBoss->SetFtnDeadLine( nDeadLine );
/*N*/   nNewHeight = pBoss->GetMaxFtnHeight();
/*N*/ }



/*N*/ SwSaveFtnHeight::~SwSaveFtnHeight()
/*N*/ {
/*N*/   //Wenn zwischendurch jemand an der DeadLine gedreht hat, so lassen wir
/*N*/   //ihm seinen Spass!
/*N*/   if ( nNewHeight == pBoss->GetMaxFtnHeight() )
/*N*/       pBoss->nMaxFtnHeight = nOldHeight;
/*N*/ }


/*N*/ #ifdef DBG_UTIL
// 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.

/*N*/ const SwCntntFrm* SwFtnFrm::GetRef() const
/*N*/ {
/*N*/     const SwCntntFrm* pRefAttr = GetRefFromAttr();
/*N*/     OSL_ENSURE( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr )
/*N*/             || pRefAttr->IsAnFollow( pRef ),
/*N*/             "access to deleted Frame? pRef != pAttr->GetRef()" );
/*N*/   return pRef;
/*N*/ }

/*N*/ SwCntntFrm* SwFtnFrm::GetRef()
/*N*/ {
/*N*/     const SwCntntFrm* pRefAttr = GetRefFromAttr();
/*N*/     OSL_ENSURE( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr )
/*N*/             || pRefAttr->IsAnFollow( pRef ),
/*N*/             "access to deleted Frame? pRef != pAttr->GetRef()" );
/*N*/   return pRef;
/*N*/ }

/*N*/ #endif

/*N*/ const SwCntntFrm* SwFtnFrm::GetRefFromAttr()  const
/*N*/ {
/*N*/   SwFtnFrm* pThis = (SwFtnFrm*)this;
/*N*/   return pThis->GetRefFromAttr();
/*N*/ }

/*N*/ SwCntntFrm* SwFtnFrm::GetRefFromAttr()
/*N*/ {
/*N*/   OSL_ENSURE( pAttr, "invalid Attribute" );
/*N*/   SwTxtNode& rTNd = (SwTxtNode&)pAttr->GetTxtNode();
/*N*/   SwPosition aPos( rTNd, SwIndex( &rTNd, *pAttr->GetStart() ));
/*N*/   SwCntntFrm* pCFrm = rTNd.GetFrm( 0, &aPos, FALSE );
/*N*/   return pCFrm;
/*N*/ }

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
