summaryrefslogtreecommitdiff
path: root/sw/source/core/layout/calcmove.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/layout/calcmove.cxx')
-rw-r--r--sw/source/core/layout/calcmove.cxx2116
1 files changed, 2116 insertions, 0 deletions
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx
new file mode 100644
index 000000000000..e3bcf56ee9c4
--- /dev/null
+++ b/sw/source/core/layout/calcmove.cxx
@@ -0,0 +1,2116 @@
+/* -*- 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "cntfrm.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "swtypes.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "txtftn.hxx"
+#include "fmtftn.hxx"
+#include <editeng/ulspitem.hxx>
+#include <editeng/keepitem.hxx>
+
+#include <vcl/outdev.hxx>
+#include <fmtfsize.hxx>
+#include <fmtanchr.hxx>
+#include <fmtclbl.hxx>
+
+#include "tabfrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+#include "pagedesc.hxx"
+#include "ftninfo.hxx"
+#include "sectfrm.hxx"
+#include "dbg_lay.hxx"
+
+// --> OD 2004-06-23 #i28701#
+#include <sortedobjs.hxx>
+#include <layouter.hxx>
+// --> OD 2004-11-01 #i36347#
+#include <flyfrms.hxx>
+// <--
+
+#include <ndtxt.hxx>
+
+//------------------------------------------------------------------------
+// Move-Methoden
+//------------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* SwCntntFrm::ShouldBwdMoved()
+|*
+|* Beschreibung Returnwert sagt, ob der Frm verschoben werden sollte.
+|*
+|*************************************************************************/
+
+
+sal_Bool SwCntntFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool & )
+{
+ if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()))
+ {
+ //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
+ //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
+ //moechte die FixSize die gleiche ist, die der Frm selbst hat.
+ //In diesem Fall kann einfach geprueft werden, ob der Frm genug
+ //Platz fuer seine VarSize findet, ist dies nicht der Fall kann
+ //gleich auf das Verschieben verzichtet werden.
+ //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
+ //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
+ //aufspalten kann.
+ //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
+ //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
+ //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
+ //etwas Platz zur Verfuegung steht).
+
+ //Die FixSize der Umgebungen in denen Cntnts herumlungern ist immer
+ //Die Breite.
+
+ //Wenn mehr als ein Blatt zurueckgegangen wurde (z.B. ueberspringen
+ //von Leerseiten), so muss in jedemfall gemoved werden - sonst wuerde,
+ //falls der Frm nicht in das Blatt passt, nicht mehr auf die
+ //dazwischenliegenden Blaetter geachtet werden.
+ sal_uInt8 nMoveAnyway = 0;
+ SwPageFrm * const pNewPage = pNewUpper->FindPageFrm();
+ SwPageFrm *pOldPage = FindPageFrm();
+
+ if ( SwFlowFrm::IsMoveBwdJump() )
+ return sal_True;
+
+ if( IsInFtn() && IsInSct() )
+ {
+ SwFtnFrm* pFtn = FindFtnFrm();
+ SwSectionFrm* pMySect = pFtn->FindSctFrm();
+ if( pMySect && pMySect->IsFtnLock() )
+ {
+ SwSectionFrm *pSect = pNewUpper->FindSctFrm();
+ while( pSect && pSect->IsInFtn() )
+ pSect = pSect->GetUpper()->FindSctFrm();
+ OSL_ENSURE( pSect, "Escaping footnote" );
+ if( pSect != pMySect )
+ return sal_False;
+ }
+ }
+ SWRECTFN( this )
+ SWRECTFNX( pNewUpper )
+ if( Abs( (pNewUpper->Prt().*fnRectX->fnGetWidth)() -
+ (GetUpper()->Prt().*fnRect->fnGetWidth)() ) > 1 )
+ nMoveAnyway = 2; // Damit kommt nur noch ein _WouldFit mit Umhaengen in Frage
+
+ // OD 2004-05-26 #i25904# - do *not* move backward,
+ // if <nMoveAnyway> equals 3 and no space is left in new upper.
+ nMoveAnyway |= BwdMoveNecessary( pOldPage, Frm() );
+ {
+ const IDocumentSettingAccess* pIDSA = pNewPage->GetFmt()->getIDocumentSettingAccess();
+ SwTwips nSpace = 0;
+ SwRect aRect( pNewUpper->Prt() );
+ aRect.Pos() += pNewUpper->Frm().Pos();
+ const SwFrm *pPrevFrm = pNewUpper->Lower();
+ while ( pPrevFrm )
+ {
+ SwTwips nNewTop = (pPrevFrm->Frm().*fnRectX->fnGetBottom)();
+ // OD 2004-03-01 #106629#:
+ // consider lower spacing of last frame in a table cell
+ {
+ // check, if last frame is inside table and if it includes
+ // its lower spacing.
+ if ( !pPrevFrm->GetNext() && pPrevFrm->IsInTab() &&
+ pIDSA->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
+ {
+ const SwFrm* pLastFrm = pPrevFrm;
+ // if last frame is a section, take its last content
+ if ( pPrevFrm->IsSctFrm() )
+ {
+ pLastFrm = static_cast<const SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
+ if ( pLastFrm &&
+ pLastFrm->FindTabFrm() != pPrevFrm->FindTabFrm() )
+ {
+ pLastFrm = pLastFrm->FindTabFrm();
+ }
+ }
+
+ if ( pLastFrm )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pLastFrm );
+ const SwBorderAttrs& rAttrs = *aAccess.Get();
+ nNewTop -= rAttrs.GetULSpace().GetLower();
+ }
+ }
+ }
+ (aRect.*fnRectX->fnSetTop)( nNewTop );
+
+ pPrevFrm = pPrevFrm->GetNext();
+ }
+
+ nMoveAnyway |= BwdMoveNecessary( pNewPage, aRect);
+
+ //determine space left in new upper frame
+ nSpace = (aRect.*fnRectX->fnGetHeight)();
+ const ViewShell *pSh = pNewUpper->getRootFrm()->GetCurrShell();
+ if ( IsInFtn() ||
+ (pSh && pSh->GetViewOptions()->getBrowseMode()) ||
+ pNewUpper->IsCellFrm() ||
+ ( pNewUpper->IsInSct() && ( pNewUpper->IsSctFrm() ||
+ ( pNewUpper->IsColBodyFrm() &&
+ !pNewUpper->GetUpper()->GetPrev() &&
+ !pNewUpper->GetUpper()->GetNext() ) ) ) )
+ nSpace += pNewUpper->Grow( LONG_MAX, sal_True );
+
+ if ( nMoveAnyway < 3 )
+ {
+ if ( nSpace )
+ {
+ //Keine Beruecksichtigung der Fussnoten die an dem Absatz
+ //kleben, denn dies wuerde extrem unuebersichtlichen Code
+ //beduerfen (wg. Beruecksichtung der Breiten und vor allem
+ //der Flys, die ja wieder Einfluss auf die Fussnoten nehmen...).
+
+ // _WouldFit kann bei gleicher Breite und _nur_ selbst verankerten Flys
+ // befragt werden.
+ // _WouldFit kann auch gefragt werden, wenn _nur_ fremdverankerte Flys vorliegen,
+ // dabei ist sogar die Breite egal, da ein TestFormat in der neuen Umgebung
+ // vorgenommen wird.
+ // --> OD 2007-11-26 #b6614158#
+ const sal_uInt8 nBwdMoveNecessaryResult =
+ BwdMoveNecessary( pNewPage, aRect);
+ const bool bObjsInNewUpper( nBwdMoveNecessaryResult == 2 ||
+ nBwdMoveNecessaryResult == 3 );
+
+ return _WouldFit( nSpace, pNewUpper, nMoveAnyway == 2,
+ bObjsInNewUpper );
+ // <--
+ }
+ //Bei einem spaltigen Bereichsfrischling kann _WouldFit kein
+ //brauchbares Ergebnis liefern, also muessen wir wirklich
+ //zurueckfliessen
+ else if( pNewUpper->IsInSct() && pNewUpper->IsColBodyFrm() &&
+ !(pNewUpper->Prt().*fnRectX->fnGetWidth)() &&
+ ( pNewUpper->GetUpper()->GetPrev() ||
+ pNewUpper->GetUpper()->GetNext() ) )
+ return sal_True;
+ else
+ return sal_False; // Kein Platz, dann ist es sinnlos, zurueckzufliessen
+ }
+ else
+ {
+ // OD 2004-05-26 #i25904# - check for space left in new upper
+ if ( nSpace )
+ return sal_True;
+ else
+ return sal_False;
+ }
+ }
+ }
+ return sal_False;
+}
+
+//------------------------------------------------------------------------
+// Calc-Methoden
+//------------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* SwFrm::Prepare()
+|*
+|* Beschreibung Bereitet den Frm auf die 'Formatierung' (MakeAll())
+|* vor. Diese Methode dient dazu auf dem Stack Platz einzusparen,
+|* denn zur Positionsberechnung des Frm muss sichergestellt sein, dass
+|* die Position von Upper und Prev gueltig sind, mithin also ein
+|* rekursiver Aufruf (Schleife waere relativ teuer, da selten notwendig).
+|* Jeder Aufruf von MakeAll verbraucht aber ca. 500Byte Stack -
+|* das Ende ist leicht abzusehen. _Prepare benoetigt nur wenig Stack,
+|* deshalb solle der Rekursive Aufruf hier kein Problem sein.
+|* Ein weiterer Vorteil ist, das eines schoenen Tages das _Prepare und
+|* damit die Formatierung von Vorgaengern umgangen werden kann.
+|* So kann evtl. mal 'schnell' an's Dokumentende gesprungen werden.
+|*
+|*************************************************************************/
+//Zwei kleine Freundschaften werden hier zu einem Geheimbund.
+inline void PrepareLock( SwFlowFrm *pTab )
+{
+ pTab->LockJoin();
+}
+inline void PrepareUnlock( SwFlowFrm *pTab )
+{
+ pTab->UnlockJoin();
+
+}
+
+// hopefully, one day this function simply will return 'false'
+bool lcl_IsCalcUpperAllowed( const SwFrm& rFrm )
+{
+ return !rFrm.GetUpper()->IsSctFrm() &&
+ !rFrm.GetUpper()->IsFooterFrm() &&
+ // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
+ !rFrm.GetUpper()->IsFlyFrm() &&
+ // <--
+ !( rFrm.GetUpper()->IsTabFrm() && rFrm.GetUpper()->GetUpper()->IsInTab() ) &&
+ !( rFrm.IsTabFrm() && rFrm.GetUpper()->IsInTab() );
+}
+
+void SwFrm::PrepareMake()
+{
+ StackHack aHack;
+ if ( GetUpper() )
+ {
+ if ( lcl_IsCalcUpperAllowed( *this ) )
+ GetUpper()->Calc();
+ OSL_ENSURE( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
+ if ( !GetUpper() )
+ return;
+
+ const sal_Bool bCnt = IsCntntFrm();
+ const sal_Bool bTab = IsTabFrm();
+ sal_Bool bNoSect = IsInSct();
+ sal_Bool bOldTabLock = sal_False, bFoll = sal_False;
+ SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
+
+ if ( bTab )
+ {
+ pThis = (SwTabFrm*)this;
+ bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
+ ::PrepareLock( (SwTabFrm*)this );
+ bFoll = pThis->IsFollow();
+ }
+ else if( IsSctFrm() )
+ {
+ pThis = (SwSectionFrm*)this;
+ bFoll = pThis->IsFollow();
+ bNoSect = sal_False;
+ }
+ else if ( bCnt && sal_True == (bFoll = pThis->IsFollow()) &&
+ GetPrev() )
+ {
+ //Wenn der Master gereade ein CalcFollow ruft braucht die Kette
+ //nicht durchlaufen werden. Das spart Zeit und vermeidet Probleme.
+ if ( ((SwTxtFrm*)((SwTxtFrm*)this)->FindMaster())->IsLocked() )
+ {
+ MakeAll();
+ return;
+ }
+ }
+
+ // --> OD 2005-03-04 #i44049# - no format of previous frame, if current
+ // frame is a table frame and its previous frame wants to keep with it.
+ const bool bFormatPrev = !bTab ||
+ !GetPrev() ||
+ !GetPrev()->GetAttrSet()->GetKeep().GetValue();
+ if ( bFormatPrev )
+ {
+ SwFrm *pFrm = GetUpper()->Lower();
+ while ( pFrm != this )
+ {
+ OSL_ENSURE( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
+ if ( !pFrm )
+ return; //Oioioioi ...
+
+ if ( !pFrm->IsValid() )
+ {
+ //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
+ //der Stabilitaet beitraegt:
+ //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
+ //so wuerde dieser mich beim Formatieren deleten; wie jeder
+ //leicht sehen kann waere dies eine etwas unuebersichtliche
+ //Situation die es zu vermeiden gilt.
+ if ( bFoll && pFrm->IsFlowFrm() &&
+ (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
+ break;
+
+ //MA: 24. Mar. 94, Calc wuerde doch nur wieder in ein _Prepare laufen und so
+ //die ganze Kette nocheinmal abhuenern.
+ // pFrm->Calc();
+ pFrm->MakeAll();
+ if( IsSctFrm() && !((SwSectionFrm*)this)->GetSection() )
+ break;
+ }
+ //Die Kette kann bei CntntFrms waehrend des durchlaufens
+ //aufgebrochen werden, deshalb muss der Nachfolger etwas
+ //umstaendlich ermittelt werden. However, irgendwann _muss_
+ //ich wieder bei mir selbst ankommen.
+ pFrm = pFrm->FindNext();
+
+ //Wenn wir in einem SectionFrm gestartet sind, koennen wir durch die
+ //MakeAll-Aufrufe in einen Section-Follow gewandert sein.
+ //FindNext liefert allerdings den SectionFrm, nicht seinen Inhalt.
+ // => wir finden uns selbst nicht mehr!
+ if( bNoSect && pFrm && pFrm->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pCnt )
+ pFrm = pCnt;
+ }
+ }
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
+ if ( !GetUpper() )
+ return;
+
+ if ( lcl_IsCalcUpperAllowed( *this ) )
+ GetUpper()->Calc();
+
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
+ }
+
+ if ( bTab && !bOldTabLock )
+ ::PrepareUnlock( (SwTabFrm*)this );
+ }
+ MakeAll();
+}
+
+void SwFrm::OptPrepareMake()
+{
+ // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
+ if ( GetUpper() && !GetUpper()->IsFooterFrm() &&
+ !GetUpper()->IsFlyFrm() )
+ // <--
+ {
+ GetUpper()->Calc();
+ OSL_ENSURE( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
+ if ( !GetUpper() )
+ return;
+ }
+ if ( GetPrev() && !GetPrev()->IsValid() )
+ PrepareMake();
+ else
+ {
+ StackHack aHack;
+ MakeAll();
+ }
+}
+
+
+
+void SwFrm::PrepareCrsr()
+{
+ StackHack aHack;
+ if( GetUpper() && !GetUpper()->IsSctFrm() )
+ {
+ GetUpper()->PrepareCrsr();
+ GetUpper()->Calc();
+
+ OSL_ENSURE( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
+ if ( !GetUpper() )
+ return;
+
+ const sal_Bool bCnt = IsCntntFrm();
+ const sal_Bool bTab = IsTabFrm();
+ sal_Bool bNoSect = IsInSct();
+
+ sal_Bool bOldTabLock = sal_False, bFoll;
+ SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
+
+ if ( bTab )
+ {
+ bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
+ ::PrepareLock( (SwTabFrm*)this );
+ pThis = (SwTabFrm*)this;
+ }
+ else if( IsSctFrm() )
+ {
+ pThis = (SwSectionFrm*)this;
+ bNoSect = sal_False;
+ }
+ bFoll = pThis && pThis->IsFollow();
+
+ SwFrm *pFrm = GetUpper()->Lower();
+ while ( pFrm != this )
+ {
+ OSL_ENSURE( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
+ if ( !pFrm )
+ return; //Oioioioi ...
+
+ if ( !pFrm->IsValid() )
+ {
+ //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
+ //der Stabilitaet beitraegt:
+ //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
+ //so wuerde dieser mich beim Formatieren deleten; wie jeder
+ //leicht sehen kann waere dies eine etwas unuebersichtliche
+ //Situation die es zu vermeiden gilt.
+ if ( bFoll && pFrm->IsFlowFrm() &&
+ (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
+ break;
+
+ pFrm->MakeAll();
+ }
+ //Die Kette kann bei CntntFrms waehrend des durchlaufens
+ //aufgebrochen werden, deshalb muss der Nachfolger etwas
+ //umstaendlich ermittelt werden. However, irgendwann _muss_
+ //ich wieder bei mir selbst ankommen.
+ pFrm = pFrm->FindNext();
+ if( bNoSect && pFrm && pFrm->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pCnt )
+ pFrm = pCnt;
+ }
+ }
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
+ if ( !GetUpper() )
+ return;
+
+ GetUpper()->Calc();
+
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
+
+ if ( bTab && !bOldTabLock )
+ ::PrepareUnlock( (SwTabFrm*)this );
+ }
+ Calc();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::MakePos()
+|*
+|*************************************************************************/
+
+// Hier wird GetPrev() zurueckgegeben, allerdings werden
+// dabei leere SectionFrms ueberlesen
+SwFrm* lcl_Prev( SwFrm* pFrm, sal_Bool bSectPrv = sal_True )
+{
+ SwFrm* pRet = pFrm->GetPrev();
+ if( !pRet && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm() &&
+ bSectPrv && !pFrm->IsColumnFrm() )
+ pRet = pFrm->GetUpper()->GetPrev();
+ while( pRet && pRet->IsSctFrm() &&
+ !((SwSectionFrm*)pRet)->GetSection() )
+ pRet = pRet->GetPrev();
+ return pRet;
+}
+
+SwFrm* lcl_NotHiddenPrev( SwFrm* pFrm )
+{
+ SwFrm *pRet = pFrm;
+ do
+ {
+ pRet = lcl_Prev( pRet );
+ } while ( pRet && pRet->IsTxtFrm() && ((SwTxtFrm*)pRet)->IsHiddenNow() );
+ return pRet;
+}
+
+void SwFrm::MakePos()
+{
+ if ( !bValidPos )
+ {
+ bValidPos = sal_True;
+ sal_Bool bUseUpper = sal_False;
+ SwFrm* pPrv = lcl_Prev( this );
+ if ( pPrv &&
+ ( !pPrv->IsCntntFrm() ||
+ ( ((SwCntntFrm*)pPrv)->GetFollow() != this ) )
+ )
+ {
+ if ( !StackHack::IsLocked() &&
+ ( !IsInSct() || IsSctFrm() ) &&
+ !pPrv->IsSctFrm() &&
+ !pPrv->GetAttrSet()->GetKeep().GetValue()
+ )
+ {
+ pPrv->Calc(); //hierbei kann der Prev verschwinden!
+ }
+ else if ( pPrv->Frm().Top() == 0 )
+ {
+ bUseUpper = sal_True;
+ }
+ }
+
+ pPrv = lcl_Prev( this, sal_False );
+ sal_uInt16 nMyType = GetType();
+ SWRECTFN( ( IsCellFrm() && GetUpper() ? GetUpper() : this ) )
+ if ( !bUseUpper && pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ if( FRM_NEIGHBOUR & nMyType )
+ {
+ sal_Bool bR2L = IsRightToLeft();
+ if( bR2L )
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
+ (aFrm.*fnRect->fnGetWidth)() );
+ else
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() +
+ (pPrv->Frm().*fnRect->fnGetWidth)() );
+
+ // cells may now leave their uppers
+ if( bVert && FRM_CELL & nMyType && !bReverse )
+ aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
+ }
+ else if( bVert && FRM_NOTE_VERT & nMyType )
+ {
+ if( bReverse )
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ else
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ else
+ aFrm.Pos().X() -= aFrm.Width();
+ }
+ }
+ else
+ aFrm.Pos().Y() += pPrv->Frm().Height();
+ }
+ else if ( GetUpper() )
+ {
+ // OD 15.10.2002 #103517# - add safeguard for <SwFooterFrm::Calc()>
+ // If parent frame is a footer frame and its <ColLocked()>, then
+ // do *not* calculate it.
+ // NOTE: Footer frame is <ColLocked()> during its
+ // <FormatSize(..)>, which is called from <Format(..)>, which
+ // is called from <MakeAll()>, which is called from <Calc()>.
+ // --> OD 2005-11-17 #i56850#
+ // - no format of upper Writer fly frame, which is anchored
+ // at-paragraph or at-character.
+ if ( !GetUpper()->IsTabFrm() &&
+ !( IsTabFrm() && GetUpper()->IsInTab() ) &&
+ !GetUpper()->IsSctFrm() &&
+ !dynamic_cast<SwFlyAtCntFrm*>(GetUpper()) &&
+ !( GetUpper()->IsFooterFrm() &&
+ GetUpper()->IsColLocked() )
+ )
+ {
+ GetUpper()->Calc();
+ }
+ // <--
+ pPrv = lcl_Prev( this, sal_False );
+ if ( !bUseUpper && pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ if( FRM_NEIGHBOUR & nMyType )
+ {
+ sal_Bool bR2L = IsRightToLeft();
+ if( bR2L )
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
+ (aFrm.*fnRect->fnGetWidth)() );
+ else
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() +
+ (pPrv->Frm().*fnRect->fnGetWidth)() );
+
+ // cells may now leave their uppers
+ if( bVert && FRM_CELL & nMyType && !bReverse )
+ aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
+ }
+ else if( bVert && FRM_NOTE_VERT & nMyType )
+ {
+ if( bReverse )
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ else
+ aFrm.Pos().X() -= aFrm.Width();
+ }
+ else
+ aFrm.Pos().Y() += pPrv->Frm().Height();
+ }
+ else
+ {
+ aFrm.Pos( GetUpper()->Frm().Pos() );
+ aFrm.Pos() += GetUpper()->Prt().Pos();
+ if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() )
+ {
+ if( bVert )
+ aFrm.Pos().Y() += GetUpper()->Prt().Height()
+ - aFrm.Height();
+ else
+ aFrm.Pos().X() += GetUpper()->Prt().Width()
+ - aFrm.Width();
+ }
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ else if( bVert && !bVertL2R && FRM_NOTE_VERT & nMyType && !bReverse )
+ aFrm.Pos().X() -= aFrm.Width() - GetUpper()->Prt().Width();
+ }
+ }
+ else
+ aFrm.Pos().X() = aFrm.Pos().Y() = 0;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsBodyFrm() && bVert && !bVertL2R && !bReverse && GetUpper() )
+ aFrm.Pos().X() += GetUpper()->Prt().Width() - aFrm.Width();
+ bValidPos = sal_True;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::MakeAll()
+|*
+|*************************************************************************/
+// --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
+void lcl_CheckObjects( SwSortedObjs* pSortedObjs, SwFrm* pFrm, long& rBot )
+{
+ //Und dann kann es natuerlich noch Absatzgebundene
+ //Rahmen geben, die unterhalb ihres Absatzes stehen.
+ long nMax = 0;
+ for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of <SwSortedObjs>
+ // entries.
+ SwAnchoredObject* pObj = (*pSortedObjs)[i];
+ long nTmp = 0;
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
+ if( pFly->Frm().Top() != WEIT_WECH &&
+ ( pFrm->IsPageFrm() ? pFly->IsFlyLayFrm() :
+ ( pFly->IsFlyAtCntFrm() &&
+ ( pFrm->IsBodyFrm() ? pFly->GetAnchorFrm()->IsInDocBody() :
+ pFly->GetAnchorFrm()->IsInFtn() ) ) ) )
+ {
+ nTmp = pFly->Frm().Bottom();
+ }
+ }
+ else
+ nTmp = pObj->GetObjRect().Bottom();
+ nMax = Max( nTmp, nMax );
+ // <--
+ }
+ ++nMax; //Unterkante vs. Hoehe!
+ rBot = Max( rBot, nMax );
+}
+
+void SwPageFrm::MakeAll()
+{
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+ const SwRect aOldRect( Frm() ); //Anpassung der Root-Groesse
+ const SwLayNotify aNotify( this ); //uebernimmt im DTor die Benachrichtigung
+ SwBorderAttrAccess *pAccess = 0;
+ const SwBorderAttrs*pAttrs = 0;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ if ( !bValidPos )
+ {
+ // PAGES01
+ bValidPos = sal_True; // positioning of the pages is taken care of by the root frame
+ }
+
+ if ( !bValidSize || !bValidPrtArea )
+ {
+ if ( IsEmptyPage() )
+ {
+ Frm().Width( 0 ); Prt().Width( 0 );
+ Frm().Height( 0 ); Prt().Height( 0 );
+ Prt().Left( 0 ); Prt().Top( 0 );
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else
+ {
+ if ( !pAccess )
+ {
+ pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+ //Bei der BrowseView gelten feste Einstellungen.
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
+ const long nTop = pAttrs->CalcTopLine() + aBorder.Height();
+ const long nBottom = pAttrs->CalcBottomLine()+ aBorder.Height();
+
+ long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() : 0;
+ if ( nWidth < pSh->GetBrowseWidth() )
+ nWidth = pSh->GetBrowseWidth();
+ nWidth += + 2 * aBorder.Width();
+/*
+ long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() + 2 * aBorder.Width() : 0;
+ if ( nWidth < pSh->VisArea().Width() )
+ nWidth = pSh->VisArea().Width(); */
+
+ nWidth = Max( nWidth, 2L * aBorder.Width() + 4L*MM50 );
+ Frm().Width( nWidth );
+
+ SwLayoutFrm *pBody = FindBodyCont();
+ if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ {
+ //Fuer Spalten gilt eine feste Hoehe
+ Frm().Height( pAttrs->GetSize().Height() );
+ }
+ else
+ {
+ //Fuer Seiten ohne Spalten bestimmt der Inhalt die
+ //Groesse.
+ long nBot = Frm().Top() + nTop;
+ SwFrm *pFrm = Lower();
+ while ( pFrm )
+ {
+ long nTmp = 0;
+ SwFrm *pCnt = ((SwLayoutFrm*)pFrm)->ContainsAny();
+ while ( pCnt && (pCnt->GetUpper() == pFrm ||
+ ((SwLayoutFrm*)pFrm)->IsAnLower( pCnt )))
+ {
+ nTmp += pCnt->Frm().Height();
+ if( pCnt->IsTxtFrm() &&
+ ((SwTxtFrm*)pCnt)->IsUndersized() )
+ nTmp += ((SwTxtFrm*)pCnt)->GetParHeight()
+ - pCnt->Prt().Height();
+ else if( pCnt->IsSctFrm() &&
+ ((SwSectionFrm*)pCnt)->IsUndersized() )
+ nTmp += ((SwSectionFrm*)pCnt)->Undersize();
+ pCnt = pCnt->FindNext();
+ }
+ // OD 29.10.2002 #97265# - consider invalid body frame properties
+ if ( pFrm->IsBodyFrm() &&
+ ( !pFrm->GetValidSizeFlag() ||
+ !pFrm->GetValidPrtAreaFlag() ) &&
+ ( pFrm->Frm().Height() < pFrm->Prt().Height() )
+ )
+ {
+ nTmp = Min( nTmp, pFrm->Frm().Height() );
+ }
+ else
+ {
+ // OD 30.10.2002 #97265# - assert invalid lower property
+ OSL_ENSURE( !(pFrm->Frm().Height() < pFrm->Prt().Height()),
+ "SwPageFrm::MakeAll(): Lower with frame height < printing height" );
+ nTmp += pFrm->Frm().Height() - pFrm->Prt().Height();
+ }
+ if ( !pFrm->IsBodyFrm() )
+ nTmp = Min( nTmp, pFrm->Frm().Height() );
+ nBot += nTmp;
+ // Hier werden die absatzgebundenen Objekte ueberprueft,
+ // ob sie ueber den Body/FtnCont hinausragen.
+ if( pSortedObjs && !pFrm->IsHeaderFrm() &&
+ !pFrm->IsFooterFrm() )
+ lcl_CheckObjects( pSortedObjs, pFrm, nBot );
+ pFrm = pFrm->GetNext();
+ }
+ nBot += nBottom;
+ //Und die Seitengebundenen
+ if ( pSortedObjs )
+ lcl_CheckObjects( pSortedObjs, this, nBot );
+ nBot -= Frm().Top();
+ // --> OD 2004-11-10 #i35143# - If second page frame
+ // exists, the first page doesn't have to fulfill the
+ // visible area.
+ if ( !GetPrev() && !GetNext() )
+ // <--
+ {
+ nBot = Max( nBot, pSh->VisArea().Height() );
+ }
+ // --> OD 2004-11-10 #i35143# - Assure, that the page
+ // doesn't exceed the defined browse height.
+ Frm().Height( Min( nBot, BROWSE_HEIGHT ) );
+ // <--
+ }
+ Prt().Left ( pAttrs->CalcLeftLine() + aBorder.Width() );
+ Prt().Top ( nTop );
+ Prt().Width( Frm().Width() - ( Prt().Left()
+ + pAttrs->CalcRightLine() + aBorder.Width() ) );
+ Prt().Height( Frm().Height() - (nTop + nBottom) );
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else
+ { //FixSize einstellen, bei Seiten nicht vom Upper sondern vom
+ //Attribut vorgegeben.
+ Frm().SSize( pAttrs->GetSize() );
+ Format( pAttrs );
+ }
+ }
+ }
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ delete pAccess;
+
+ // PAGES01
+ if ( Frm() != aOldRect && GetUpper() )
+ static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
+
+#if OSL_DEBUG_LEVEL > 1
+ //Der Upper (Root) muss mindestens so breit
+ //sein, dass er die breiteste Seite aufnehmen kann.
+ if ( GetUpper() )
+ {
+ OSL_ENSURE( GetUpper()->Prt().Width() >= aFrm.Width(), "Rootsize" );
+ }
+#endif
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::MakeAll()
+|*
+|*************************************************************************/
+
+
+void SwLayoutFrm::MakeAll()
+{
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+ //uebernimmt im DTor die Benachrichtigung
+ const SwLayNotify aNotify( this );
+ sal_Bool bVert = IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = ( IsNeighbourFrm() == bVert )? fnRectHori : ( IsVertLR() ? fnRectVertL2R : fnRectVert );
+
+ SwBorderAttrAccess *pAccess = 0;
+ const SwBorderAttrs*pAttrs = 0;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ if ( !bValidPos )
+ MakePos();
+
+ if ( GetUpper() )
+ {
+ // NEW TABLES
+ if ( IsLeaveUpperAllowed() )
+ {
+ if ( !bValidSize )
+ bValidPrtArea = sal_False;
+ }
+ else
+ {
+ if ( !bValidSize )
+ {
+ //FixSize einstellen, die VarSize wird von Format() nach
+ //Berechnung der PrtArea eingestellt.
+ bValidPrtArea = sal_False;
+
+ SwTwips nPrtWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ if( bVert && ( IsBodyFrm() || IsFtnContFrm() ) )
+ {
+ SwFrm* pNxt = GetPrev();
+ while( pNxt && !pNxt->IsHeaderFrm() )
+ pNxt = pNxt->GetPrev();
+ if( pNxt )
+ nPrtWidth -= pNxt->Frm().Height();
+ pNxt = GetNext();
+ while( pNxt && !pNxt->IsFooterFrm() )
+ pNxt = pNxt->GetNext();
+ if( pNxt )
+ nPrtWidth -= pNxt->Frm().Height();
+ }
+
+ const long nDiff = nPrtWidth - (Frm().*fnRect->fnGetWidth)();
+
+ if( IsNeighbourFrm() && IsRightToLeft() )
+ (Frm().*fnRect->fnSubLeft)( nDiff );
+ else
+ (Frm().*fnRect->fnAddRight)( nDiff );
+ }
+ else
+ {
+ // Don't leave your upper
+ const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( (Frm().*fnRect->fnOverStep)( nDeadLine ) )
+ bValidSize = sal_False;
+ }
+ }
+ }
+ if ( !bValidSize || !bValidPrtArea )
+ {
+ if ( !pAccess )
+ {
+ pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+ Format( pAttrs );
+ }
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ if ( pAccess )
+ delete pAccess;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::MakePrtArea()
+|*
+|*************************************************************************/
+bool SwTxtNode::IsCollapse() const
+{
+ if ( GetDoc()->get( IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA ) && GetTxt().Len()==0 ) {
+ sal_uLong nIdx=GetIndex();
+ const SwEndNode *pNdBefore=GetNodes()[nIdx-1]->GetEndNode();
+ const SwEndNode *pNdAfter=GetNodes()[nIdx+1]->GetEndNode();
+
+ // The paragraph is collapsed only if the NdAfter is the end of a cell
+ bool bInTable = this->FindTableNode( ) != NULL;
+
+ SwSortedObjs* pObjs = this->getLayoutFrm( GetDoc()->GetCurrentLayout() )->GetDrawObjs( );
+ sal_uInt32 nObjs = ( pObjs != NULL ) ? pObjs->Count( ) : 0;
+
+ if ( pNdBefore!=NULL && pNdAfter!=NULL && nObjs == 0 && bInTable ) {
+ return true;
+ } else {
+ return false;
+ }
+ } else
+ return false;
+}
+
+bool SwFrm::IsCollapse() const
+{
+ if (IsTxtFrm()) {
+ const SwTxtFrm *pTxtFrm=(SwTxtFrm*)this;
+ const SwTxtNode *pTxtNode=pTxtFrm->GetTxtNode();
+ if (pTxtNode && pTxtNode->IsCollapse()) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+}
+
+sal_Bool SwCntntFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
+{
+ sal_Bool bSizeChgd = sal_False;
+
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+
+ SWRECTFN( this )
+ const sal_Bool bTxtFrm = IsTxtFrm();
+ SwTwips nUpper = 0;
+ if ( bTxtFrm && ((SwTxtFrm*)this)->IsHiddenNow() )
+ {
+ if ( ((SwTxtFrm*)this)->HasFollow() )
+ ((SwTxtFrm*)this)->JoinFrm();
+
+ if( (Prt().*fnRect->fnGetHeight)() )
+ ((SwTxtFrm*)this)->HideHidden();
+ Prt().Pos().X() = Prt().Pos().Y() = 0;
+ (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
+ (Prt().*fnRect->fnSetHeight)( 0 );
+ nUpper = -( (Frm().*fnRect->fnGetHeight)() );
+ }
+ else
+ {
+ //Vereinfachung: CntntFrms sind immer in der Hoehe Variabel!
+
+ //An der FixSize gibt der umgebende Frame die Groesse vor, die
+ //Raender werden einfach abgezogen.
+ const long nLeft = rAttrs.CalcLeft( this );
+ const long nRight = ((SwBorderAttrs&)rAttrs).CalcRight( this );
+ (this->*fnRect->fnSetXMargins)( nLeft, nRight );
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwTwips nWidthArea;
+ if( pSh && 0!=(nWidthArea=(pSh->VisArea().*fnRect->fnGetWidth)()) &&
+ GetUpper()->IsPageBodyFrm() && // nicht dagegen bei BodyFrms in Columns
+ pSh->GetViewOptions()->getBrowseMode() )
+ {
+ //Nicht ueber die Kante des sichbaren Bereiches hinausragen.
+ //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
+ //geben kann (RootFrm::ImplCalcBrowseWidth())
+ long nMinWidth = 0;
+
+ for (sal_uInt16 i = 0; GetDrawObjs() && i < GetDrawObjs()->Count();++i)
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of
+ // <SwSortedObjs> entries
+ SwAnchoredObject* pObj = (*GetDrawObjs())[i];
+ const SwFrmFmt& rFmt = pObj->GetFrmFmt();
+ const sal_Bool bFly = pObj->ISA(SwFlyFrm);
+ if ((bFly && (WEIT_WECH == pObj->GetObjRect().Width()))
+ || rFmt.GetFrmSize().GetWidthPercent())
+ {
+ continue;
+ }
+
+ if ( FLY_AS_CHAR == rFmt.GetAnchor().GetAnchorId() )
+ {
+ nMinWidth = Max( nMinWidth,
+ bFly ? rFmt.GetFrmSize().GetWidth()
+ : pObj->GetObjRect().Width() );
+ }
+ // <--
+ }
+
+ const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
+ long nWidth = nWidthArea - 2 * ( IsVertical() ? aBorder.Height() : aBorder.Width() );
+ nWidth -= (Prt().*fnRect->fnGetLeft)();
+ nWidth -= rAttrs.CalcRightLine();
+ nWidth = Max( nMinWidth, nWidth );
+ (Prt().*fnRect->fnSetWidth)( Min( nWidth,
+ (Prt().*fnRect->fnGetWidth)() ) );
+ }
+
+ if ( (Prt().*fnRect->fnGetWidth)() <= MINLAY )
+ {
+ //Die PrtArea sollte schon wenigstens MINLAY breit sein, passend
+ //zu den Minimalwerten des UI
+ (Prt().*fnRect->fnSetWidth)( Min( long(MINLAY),
+ (Frm().*fnRect->fnGetWidth)() ) );
+ SwTwips nTmp = (Frm().*fnRect->fnGetWidth)() -
+ (Prt().*fnRect->fnGetWidth)();
+ if( (Prt().*fnRect->fnGetLeft)() > nTmp )
+ (Prt().*fnRect->fnSetLeft)( nTmp );
+ }
+
+ //Fuer die VarSize gelten folgende Regeln:
+ //1. Der erste einer Kette hat keinen Rand nach oben
+ //2. Nach unten gibt es nie einen Rand
+ //3. Der Rand nach oben ist das Maximum aus dem Abstand des
+ // Prev nach unten und dem eigenen Abstand nach oben.
+ //Die drei Regeln werden auf die Berechnung der Freiraeume, die von
+ //UL- bzw. LRSpace vorgegeben werden, angewand. Es gibt in alle
+ //Richtungen jedoch ggf. trotzdem einen Abstand; dieser wird durch
+ //Umrandung und/oder Schatten vorgegeben.
+ //4. Der Abstand fuer TextFrms entspricht mindestens dem Durchschuss
+
+ nUpper = CalcUpperSpace( &rAttrs, NULL );
+
+ SwTwips nLower = CalcLowerSpace( &rAttrs );
+ if (IsCollapse()) {
+ nUpper=0;
+ nLower=0;
+ }
+// // in balanced columned section frames we do not want the
+// // common border
+// sal_Bool bCommonBorder = sal_True;
+// if ( IsInSct() && GetUpper()->IsColBodyFrm() )
+// {
+// const SwSectionFrm* pSct = FindSctFrm();
+// bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
+// }
+// SwTwips nLower = bCommonBorder ?
+// rAttrs.GetBottomLine( this ) :
+// rAttrs.CalcBottomLine();
+
+ (Prt().*fnRect->fnSetPosY)( (!bVert || bReverse) ? nUpper : nLower);
+ nUpper += nLower;
+ nUpper -= (Frm().*fnRect->fnGetHeight)() -
+ (Prt().*fnRect->fnGetHeight)();
+ }
+ //Wenn Unterschiede zwischen Alter und neuer Groesse,
+ //Grow() oder Shrink() rufen
+ if ( nUpper )
+ {
+ if ( nUpper > 0 )
+ GrowFrm( nUpper );
+ else
+ ShrinkFrm( -nUpper );
+ bSizeChgd = sal_True;
+ }
+ }
+ return bSizeChgd;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::MakeAll()
+|*
+|*************************************************************************/
+
+#define STOP_FLY_FORMAT 10
+// --> OD 2006-09-25 #b6448963# - loop prevention
+const int cnStopFormat = 15;
+// <--
+
+inline void ValidateSz( SwFrm *pFrm )
+{
+ if ( pFrm )
+ {
+ pFrm->bValidSize = sal_True;
+ pFrm->bValidPrtArea = sal_True;
+ }
+}
+
+void SwCntntFrm::MakeAll()
+{
+ OSL_ENSURE( GetUpper(), "keinen Upper?" );
+ OSL_ENSURE( IsTxtFrm(), "MakeAll(), NoTxt" );
+
+ if ( !IsFollow() && StackHack::IsLocked() )
+ return;
+
+ if ( IsJoinLocked() )
+ return;
+
+ OSL_ENSURE( !((SwTxtFrm*)this)->IsSwapped(), "Calculation of a swapped frame" );
+
+ StackHack aHack;
+
+ if ( ((SwTxtFrm*)this)->IsLocked() )
+ {
+ OSL_FAIL( "Format fuer gelockten TxtFrm." );
+ return;
+ }
+
+ LockJoin();
+ long nFormatCount = 0;
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ int nConsequetiveFormatsWithoutChange = 0;
+ // <--
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+#if OSL_DEBUG_LEVEL > 1
+ const SwDoc *pDoc = GetAttrSet()->GetDoc();
+ if( pDoc )
+ {
+ static sal_Bool bWarn = sal_False;
+ if( pDoc->InXMLExport() )
+ {
+ OSL_ENSURE( bWarn, "Formatting during XML-export!" );
+ bWarn = sal_True;
+ }
+ else
+ bWarn = sal_False;
+ }
+#endif
+
+ //uebernimmt im DTor die Benachrichtigung
+ SwCntntNotify *pNotify = new SwCntntNotify( this );
+
+ sal_Bool bMakePage = sal_True; //solange sal_True kann eine neue Seite
+ //angelegt werden (genau einmal)
+ sal_Bool bMovedBwd = sal_False; //Wird sal_True wenn der Frame zurueckfliesst
+ sal_Bool bMovedFwd = sal_False; //solange sal_False kann der Frm zurueck-
+ //fliessen (solange, bis er einmal
+ //vorwaerts ge'moved wurde).
+ sal_Bool bFormatted = sal_False; //Fuer die Witwen und Waisen Regelung
+ //wird der letzte CntntFrm einer Kette
+ //u.U. zum Formatieren angeregt, dies
+ //braucht nur einmal zu passieren.
+ //Immer wenn der Frm gemoved wird muss
+ //das Flag zurueckgesetzt werden.
+ sal_Bool bMustFit = sal_False; //Wenn einmal die Notbremse gezogen wurde,
+ //werden keine anderen Prepares mehr
+ //abgesetzt.
+ sal_Bool bFitPromise = sal_False; //Wenn ein Absatz nicht passte, mit WouldFit
+ //aber verspricht, dass er sich passend
+ //einstellt wird dieses Flag gesetzt.
+ //Wenn er dann sein Versprechen nicht haelt,
+ //kann kontrolliert verfahren werden.
+ sal_Bool bMoveable;
+ const sal_Bool bFly = IsInFly();
+ const sal_Bool bTab = IsInTab();
+ const sal_Bool bFtn = IsInFtn();
+ const sal_Bool bSct = IsInSct();
+ Point aOldFrmPos; //Damit bei Turnarounds jew. mit der
+ Point aOldPrtPos; //letzten Pos verglichen und geprueft
+ //werden kann, ob ein Prepare sinnvoll ist.
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ // OD 2004-02-26 #i25029#
+ if ( !IsFollow() && rAttrs.JoinedWithPrev( *(this) ) )
+ {
+ pNotify->SetBordersJoinedWithPrev();
+ }
+
+ const sal_Bool bKeep = IsKeep( rAttrs.GetAttrSet() );
+
+ SwSaveFtnHeight *pSaveFtn = 0;
+ if ( bFtn )
+ {
+ SwFtnFrm *pFtn = FindFtnFrm();
+ SwSectionFrm* pSct = pFtn->FindSctFrm();
+ if ( !((SwTxtFrm*)pFtn->GetRef())->IsLocked() )
+ {
+ SwFtnBossFrm* pBoss = pFtn->GetRef()->FindFtnBossFrm(
+ pFtn->GetAttr()->GetFtn().IsEndNote() );
+ if( !pSct || pSct->IsColLocked() || !pSct->Growable() )
+ pSaveFtn = new SwSaveFtnHeight( pBoss,
+ ((SwTxtFrm*)pFtn->GetRef())->GetFtnLine( pFtn->GetAttr() ) );
+ }
+ }
+
+ // --> OD 2008-08-12 #b6732519#
+ if ( GetUpper()->IsSctFrm() &&
+ HasFollow() &&
+ GetFollow()->GetFrm() == GetNext() )
+ {
+ dynamic_cast<SwTxtFrm*>(this)->JoinFrm();
+ }
+ // <--
+
+ // --> OD 2004-06-23 #i28701# - move master forward, if it has to move,
+ // because of its object positioning.
+ if ( !static_cast<SwTxtFrm*>(this)->IsFollow() )
+ {
+ sal_uInt32 nToPageNum = 0L;
+ const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
+ *(GetAttrSet()->GetDoc()),
+ *(static_cast<SwTxtFrm*>(this)),
+ nToPageNum );
+ // --> OD 2006-01-27 #i58182#
+ // Also move a paragraph forward, which is the first one inside a table cell.
+ if ( bMoveFwdByObjPos &&
+ FindPageFrm()->GetPhyPageNum() < nToPageNum &&
+ ( lcl_Prev( this ) ||
+ GetUpper()->IsCellFrm() ||
+ ( GetUpper()->IsSctFrm() &&
+ GetUpper()->GetUpper()->IsCellFrm() ) ) &&
+ IsMoveable() )
+ {
+ bMovedFwd = sal_True;
+ MoveFwd( bMakePage, sal_False );
+ }
+ // <--
+ }
+ // <--
+
+ //Wenn ein Follow neben seinem Master steht und nicht passt, kann er
+ //gleich verschoben werden.
+ if ( lcl_Prev( this ) && ((SwTxtFrm*)this)->IsFollow() && IsMoveable() )
+ {
+ bMovedFwd = sal_True;
+ // OD 2004-03-02 #106629# - If follow frame is in table, it's master
+ // will be the last in the current table cell. Thus, invalidate the
+ // printing area of the master,
+ if ( IsInTab() )
+ {
+ lcl_Prev( this )->InvalidatePrt();
+ }
+ MoveFwd( bMakePage, sal_False );
+ }
+
+ // OD 08.11.2002 #104840# - check footnote content for forward move.
+ // If a content of a footnote is on a prior page/column as its invalid
+ // reference, it can be moved forward.
+ if ( bFtn && !bValidPos )
+ {
+ SwFtnFrm* pFtn = FindFtnFrm();
+ SwCntntFrm* pRefCnt = pFtn ? pFtn->GetRef() : 0;
+ if ( pRefCnt && !pRefCnt->IsValid() )
+ {
+ SwFtnBossFrm* pFtnBossOfFtn = pFtn->FindFtnBossFrm();
+ SwFtnBossFrm* pFtnBossOfRef = pRefCnt->FindFtnBossFrm();
+ //<loop of movefwd until condition held or no move>
+ if ( pFtnBossOfFtn && pFtnBossOfRef &&
+ pFtnBossOfFtn != pFtnBossOfRef &&
+ pFtnBossOfFtn->IsBefore( pFtnBossOfRef ) )
+ {
+ bMovedFwd = sal_True;
+ MoveFwd( bMakePage, sal_False );
+ }
+ }
+ }
+
+ SWRECTFN( this )
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ SwRect aOldFrm_StopFormat( Frm() );
+ SwRect aOldPrt_StopFormat( Prt() );
+ // <--
+ if ( sal_True == (bMoveable = IsMoveable()) )
+ {
+ SwFrm *pPre = GetIndPrev();
+ if ( CheckMoveFwd( bMakePage, bKeep, bMovedBwd ) )
+ {
+ SWREFRESHFN( this )
+ bMovedFwd = sal_True;
+ if ( bMovedBwd )
+ {
+ //Beim zurueckfliessen wurde der Upper angeregt sich
+ //vollstaendig zu Painten, dass koennen wir uns jetzt
+ //nach dem hin und her fliessen sparen.
+ GetUpper()->ResetCompletePaint();
+ //Der Vorgaenger wurde Invalidiert, das ist jetzt auch obsolete.
+ OSL_ENSURE( pPre, "missing old Prev" );
+ if( !pPre->IsSctFrm() )
+ ::ValidateSz( pPre );
+ }
+ bMoveable = IsMoveable();
+ }
+ }
+
+ aOldFrmPos = (Frm().*fnRect->fnGetPos)();
+ aOldPrtPos = (Prt().*fnRect->fnGetPos)();
+
+ if ( !bValidPos )
+ MakePos();
+
+ //FixSize einstellen, die VarSize wird von Format() justiert.
+ if ( !bValidSize )
+ {
+ // --> OD 2006-01-03 #125452#
+ // invalidate printing area flag, if the following conditions are hold:
+ // - current frame width is 0.
+ // - current printing area width is 0.
+ // - frame width is adjusted to a value greater than 0.
+ // - printing area flag is sal_True.
+ // Thus, it's assured that the printing area is adjusted, if the
+ // frame area width changes its width from 0 to something greater
+ // than 0.
+ // Note: A text frame can be in such a situation, if the format is
+ // triggered by method call <SwCrsrShell::SetCrsr()> after
+ // loading the document.
+ const SwTwips nNewFrmWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ if ( bValidPrtArea && nNewFrmWidth > 0 &&
+ (Frm().*fnRect->fnGetWidth)() == 0 &&
+ (Prt().*fnRect->fnGetWidth)() == 0 )
+ {
+ bValidPrtArea = sal_False;
+ }
+
+ (Frm().*fnRect->fnSetWidth)( nNewFrmWidth );
+ // <--
+ }
+ if ( !bValidPrtArea )
+ {
+ const long nOldW = (Prt().*fnRect->fnGetWidth)();
+ // --> OD 2004-09-28 #i34730# - keep current frame height
+ const SwTwips nOldH = (Frm().*fnRect->fnGetHeight)();
+ // <--
+ MakePrtArea( rAttrs );
+ if ( nOldW != (Prt().*fnRect->fnGetWidth)() )
+ Prepare( PREP_FIXSIZE_CHG );
+ // --> OD 2004-09-28 #i34730# - check, if frame height has changed.
+ // If yes, send a PREP_ADJUST_FRM and invalidate the size flag to
+ // force a format. The format will check in its method
+ // <SwTxtFrm::CalcPreps()>, if the already formatted lines still
+ // fit and if not, performs necessary actions.
+ // --> OD 2005-01-10 #i40150# - no check, if frame is undersized.
+ if ( bValidSize && !IsUndersized() &&
+ nOldH != (Frm().*fnRect->fnGetHeight)() )
+ {
+ // --> OD 2004-11-25 #115759# - no PREP_ADJUST_FRM and size
+ // invalidation, if height decreases only by the additional
+ // lower space as last content of a table cell and an existing
+ // follow containing one line exists.
+ const SwTwips nHDiff = nOldH - (Frm().*fnRect->fnGetHeight)();
+ const bool bNoPrepAdjustFrm =
+ nHDiff > 0 && IsInTab() && GetFollow() &&
+ ( 1 == static_cast<SwTxtFrm*>(GetFollow())->GetLineCount( STRING_LEN ) || (static_cast<SwTxtFrm*>(GetFollow())->Frm().*fnRect->fnGetWidth)() < 0 ) &&
+ GetFollow()->CalcAddLowerSpaceAsLastInTableCell() == nHDiff;
+ if ( !bNoPrepAdjustFrm )
+ {
+ Prepare( PREP_ADJUST_FRM );
+ bValidSize = sal_False;
+ }
+ // <--
+ }
+ // <--
+ }
+
+ //Damit die Witwen- und Waisen-Regelung eine Change bekommt muss der
+ //CntntFrm benachrichtigt werden.
+ //Kriterium:
+ //- Er muss Moveable sein (sonst mach das Spalten keinen Sinn.)
+ //- Er muss mit der Unterkante der PrtArea des Upper ueberlappen.
+ if ( !bMustFit )
+ {
+ sal_Bool bWidow = sal_True;
+ const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if ( bMoveable && !bFormatted && ( GetFollow() ||
+ ( (Frm().*fnRect->fnOverStep)( nDeadLine ) ) ) )
+ {
+ Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = bWidow = sal_False;
+ }
+ if( (Frm().*fnRect->fnGetPos)() != aOldFrmPos ||
+ (Prt().*fnRect->fnGetPos)() != aOldPrtPos )
+ {
+ // In diesem Prepare erfolgt ggf. ein _InvalidateSize().
+ // bValidSize wird sal_False und das Format() wird gerufen.
+ Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
+ if ( bWidow && GetFollow() )
+ { Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = sal_False;
+ }
+ }
+ }
+ if ( !bValidSize )
+ {
+ bValidSize = bFormatted = sal_True;
+ ++nFormatCount;
+ if( nFormatCount > STOP_FLY_FORMAT )
+ SetFlyLock( sal_True );
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ // No format any longer, if <cnStopFormat> consequetive formats
+ // without change occur.
+ if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
+ {
+ Format();
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "debug assertion: <SwCntntFrm::MakeAll()> - format of text frame suppressed by fix b6448963" );
+ }
+#endif
+ // <--
+ }
+
+ //Wenn ich der erste einer Kette bin koennte ich mal sehen ob
+ //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
+ //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
+ //geflossen sein.
+ sal_Bool bDummy;
+ if ( !lcl_Prev( this ) &&
+ !bMovedFwd &&
+ ( bMoveable || ( bFly && !bTab ) ) &&
+ ( !bFtn || !GetUpper()->FindFtnFrm()->GetPrev() )
+ && MoveBwd( bDummy ) )
+ {
+ SWREFRESHFN( this )
+ bMovedBwd = sal_True;
+ bFormatted = sal_False;
+ if ( bKeep && bMoveable )
+ {
+ if( CheckMoveFwd( bMakePage, sal_False, bMovedBwd ) )
+ {
+ bMovedFwd = sal_True;
+ bMoveable = IsMoveable();
+ SWREFRESHFN( this )
+ }
+ Point aOldPos = (Frm().*fnRect->fnGetPos)();
+ MakePos();
+ if( aOldPos != (Frm().*fnRect->fnGetPos)() )
+ {
+ Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
+ if ( !bValidSize )
+ {
+ (Frm().*fnRect->fnSetWidth)( (GetUpper()->
+ Prt().*fnRect->fnGetWidth)() );
+ if ( !bValidPrtArea )
+ {
+ const long nOldW = (Prt().*fnRect->fnGetWidth)();
+ MakePrtArea( rAttrs );
+ if( nOldW != (Prt().*fnRect->fnGetWidth)() )
+ Prepare( PREP_FIXSIZE_CHG, 0, sal_False );
+ }
+ if( GetFollow() )
+ Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = bFormatted = sal_True;
+ Format();
+ }
+ }
+ SwFrm *pNxt = HasFollow() ? NULL : FindNext();
+ while( pNxt && pNxt->IsSctFrm() )
+ { // Leere Bereiche auslassen, in die anderen hinein
+ if( ((SwSectionFrm*)pNxt)->GetSection() )
+ {
+ SwFrm* pTmp = ((SwSectionFrm*)pNxt)->ContainsAny();
+ if( pTmp )
+ {
+ pNxt = pTmp;
+ break;
+ }
+ }
+ pNxt = pNxt->FindNext();
+ }
+ if ( pNxt )
+ {
+ pNxt->Calc();
+ if( bValidPos && !GetIndNext() )
+ {
+ SwSectionFrm *pSct = FindSctFrm();
+ if( pSct && !pSct->GetValidSizeFlag() )
+ {
+ SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
+ if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
+ bValidPos = sal_False;
+ }
+ else
+ bValidPos = sal_False;
+ }
+ }
+ }
+ }
+
+ //Der TxtFrm Validiert sich bei Fussnoten ggf. selbst, dass kann leicht
+ //dazu fuehren, dass seine Position obwohl unrichtig valide ist.
+ if ( bValidPos )
+ {
+ // --> OD 2006-01-23 #i59341#
+ // Workaround for inadequate layout algorithm:
+ // suppress invalidation and calculation of position, if paragraph
+ // has formatted itself at least STOP_FLY_FORMAT times and
+ // has anchored objects.
+ // Thus, the anchored objects get the possibility to format itself
+ // and this probably solve the layout loop.
+ if ( bFtn &&
+ nFormatCount <= STOP_FLY_FORMAT &&
+ !GetDrawObjs() )
+ // <--
+ {
+ bValidPos = sal_False;
+ MakePos();
+ aOldFrmPos = (Frm().*fnRect->fnGetPos)();
+ aOldPrtPos = (Prt().*fnRect->fnGetPos)();
+ }
+ }
+
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ {
+ if ( aOldFrm_StopFormat == Frm() &&
+ aOldPrt_StopFormat == Prt() )
+ {
+ ++nConsequetiveFormatsWithoutChange;
+ }
+ else
+ {
+ nConsequetiveFormatsWithoutChange = 0;
+ }
+ }
+ // <--
+
+ //Wieder ein Wert ungueltig? - dann nochmal das ganze...
+ if ( !bValidPos || !bValidSize || !bValidPrtArea )
+ continue;
+
+ //Fertig?
+ // Achtung, wg. Hoehe==0, ist es besser statt Bottom() Top()+Height() zu nehmen
+ // (kommt bei Undersized TxtFrms an der Unterkante eines spaltigen Bereichs vor)
+ const long nPrtBottom = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ const long nBottomDist = (Frm().*fnRect->fnBottomDist)( nPrtBottom );
+ if( nBottomDist >= 0 )
+ {
+ if ( bKeep && bMoveable )
+ {
+ //Wir sorgen dafuer, dass der Nachfolger gleich mit formatiert
+ //wird. Dadurch halten wir das Heft in der Hand, bis wirklich
+ //(fast) alles stabil ist. So vermeiden wir Endlosschleifen,
+ //die durch staendig wiederholte Versuche entstehen.
+ //Das bMoveFwdInvalid ist fuer #38407# notwendig. War urspruenglich
+ //in flowfrm.cxx rev 1.38 behoben, das unterbrach aber obiges
+ //Schema und spielte lieber Tuerme von Hanoi (#43669#).
+ SwFrm *pNxt = HasFollow() ? NULL : FindNext();
+ // Bei Bereichen nehmen wir lieber den Inhalt, denn nur
+ // dieser kann ggf. die Seite wechseln
+ while( pNxt && pNxt->IsSctFrm() )
+ {
+ if( ((SwSectionFrm*)pNxt)->GetSection() )
+ {
+ pNxt = ((SwSectionFrm*)pNxt)->ContainsAny();
+ break;
+ }
+ pNxt = pNxt->FindNext();
+ }
+ if ( pNxt )
+ {
+ const sal_Bool bMoveFwdInvalid = 0 != GetIndNext();
+ const sal_Bool bNxtNew =
+ ( 0 == (pNxt->Prt().*fnRect->fnGetHeight)() ) &&
+ (!pNxt->IsTxtFrm() ||!((SwTxtFrm*)pNxt)->IsHiddenNow());
+
+ pNxt->Calc();
+
+ if ( !bMovedBwd &&
+ ((bMoveFwdInvalid && !GetIndNext()) ||
+ bNxtNew) )
+ {
+ if( bMovedFwd )
+ pNotify->SetInvaKeep();
+ bMovedFwd = sal_False;
+ }
+ }
+ }
+ continue;
+ }
+
+ //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
+ //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
+
+ //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
+ //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
+ //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
+ //zwar mit aller Kraft.
+ if ( !bMoveable || IsUndersized() )
+ {
+ if( !bMoveable && IsInTab() )
+ {
+ long nDiff = -(Frm().*fnRect->fnBottomDist)(
+ (GetUpper()->*fnRect->fnGetPrtBottom)() );
+ long nReal = GetUpper()->Grow( nDiff );
+ if( nReal )
+ continue;
+ }
+ break;
+ }
+
+ //Wenn ich nun ueberhaupt ganz und garnicht in meinen Upper passe
+ //so kann die Situation vielleicht doch noch durch Aufbrechen
+ //aufgeklart werden. Diese Situation tritt bei einem frisch
+ //erzeugten Follow auf, der zwar auf die Folgeseite geschoben wurde
+ //aber selbst noch zu gross fuer diese ist; also wiederum
+ //aufgespalten werden muss.
+ //Wenn ich nicht passe und nicht Spaltbar (WouldFit()) bin, so schicke
+ //ich meinem TxtFrmanteil die Nachricht, dass eben falls moeglich
+ //trotz des Attributes 'nicht aufspalten' aufgespalten werden muss.
+ sal_Bool bMoveOrFit = sal_False;
+ sal_Bool bDontMoveMe = !GetIndPrev();
+ if( bDontMoveMe && IsInSct() )
+ {
+ SwFtnBossFrm* pBoss = FindFtnBossFrm();
+ bDontMoveMe = !pBoss->IsInSct() ||
+ ( !pBoss->Lower()->GetNext() && !pBoss->GetPrev() );
+ }
+
+ // Finally, we are able to split table rows. Therefore, bDontMoveMe
+ // can be set to sal_False:
+ if( bDontMoveMe && IsInTab() &&
+ 0 != const_cast<SwCntntFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) )
+ bDontMoveMe = sal_False;
+
+ if ( bDontMoveMe && (Frm().*fnRect->fnGetHeight)() >
+ (GetUpper()->Prt().*fnRect->fnGetHeight)() )
+ {
+ if ( !bFitPromise )
+ {
+ SwTwips nTmp = (GetUpper()->Prt().*fnRect->fnGetHeight)() -
+ (Prt().*fnRect->fnGetTop)();
+ sal_Bool bSplit = !IsFwdMoveAllowed();
+ if ( nTmp > 0 && WouldFit( nTmp, bSplit, sal_False ) )
+ {
+ Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = sal_False;
+ bFitPromise = sal_True;
+ continue;
+ }
+ /* --------------------------------------------------
+ * Frueher wurde in Rahmen und Bereichen niemals versucht,
+ * durch bMoveOrFit den TxtFrm unter Verzicht auf seine
+ * Attribute (Widows,Keep) doch noch passend zu bekommen.
+ * Dies haette zumindest bei spaltigen Rahmen versucht
+ * werden muessen, spaetestens bei verketteten Rahmen und
+ * in Bereichen muss es versucht werden.
+ * Ausnahme: Wenn wir im FormatWidthCols stehen, duerfen die
+ * Attribute nicht ausser Acht gelassen werden.
+ * --------------------------------------------------*/
+ else if ( !bFtn && bMoveable &&
+ ( !bFly || !FindFlyFrm()->IsColLocked() ) &&
+ ( !bSct || !FindSctFrm()->IsColLocked() ) )
+ bMoveOrFit = sal_True;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "+TxtFrm hat WouldFit-Versprechen nicht eingehalten." );
+ }
+#endif
+ }
+
+ //Mal sehen ob ich irgenwo Platz finde...
+ //Benachbarte Fussnoten werden in _MoveFtnCntFwd 'vorgeschoben'
+ SwFrm *pPre = GetIndPrev();
+ SwFrm *pOldUp = GetUpper();
+
+/* MA 13. Oct. 98: Was soll das denn sein!?
+ * AMA 14. Dec 98: Wenn ein spaltiger Bereich keinen Platz mehr fuer seinen ersten ContentFrm
+ * bietet, so soll dieser nicht nur in die naechste Spalte, sondern ggf. bis zur naechsten
+ * Seite wandern und dort einen Section-Follow erzeugen.
+ */
+ if( IsInSct() && bMovedFwd && bMakePage && pOldUp->IsColBodyFrm() &&
+ pOldUp->GetUpper()->GetUpper()->IsSctFrm() &&
+ ( pPre || pOldUp->GetUpper()->GetPrev() ) &&
+ ((SwSectionFrm*)pOldUp->GetUpper()->GetUpper())->MoveAllowed(this) )
+ bMovedFwd = sal_False;
+
+ const sal_Bool bCheckForGrownBody = pOldUp->IsBodyFrm();
+ const long nOldBodyHeight = (pOldUp->Frm().*fnRect->fnGetHeight)();
+
+ if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
+ bMakePage = sal_False;
+ SWREFRESHFN( this )
+
+ // If MoveFwd moves the paragraph to the next page, a following
+ // paragraph, which contains footnotes can can cause the old upper
+ // frame to grow. In this case we explicitely allow a new check
+ // for MoveBwd. Robust: We also check the bMovedBwd flag again.
+ // If pOldUp was a footnote frame, it has been deleted inside MoveFwd.
+ // Therefore we only check for growing body frames.
+ if ( bCheckForGrownBody && ! bMovedBwd && pOldUp != GetUpper() &&
+ (pOldUp->Frm().*fnRect->fnGetHeight)() > nOldBodyHeight )
+ bMovedFwd = sal_False;
+ else
+ bMovedFwd = sal_True;
+
+ bFormatted = sal_False;
+ if ( bMoveOrFit && GetUpper() == pOldUp )
+ {
+ // FME 2007-08-30 #i81146# new loop control
+ if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
+ {
+ Prepare( PREP_MUST_FIT, 0, sal_False );
+ bValidSize = sal_False;
+ bMustFit = sal_True;
+ continue;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl in SwCntntFrm::MakeAll" );
+#endif
+ }
+ if ( bMovedBwd && GetUpper() )
+ { //Unuetz gewordene Invalidierungen zuruecknehmen.
+ GetUpper()->ResetCompletePaint();
+ if( pPre && !pPre->IsSctFrm() )
+ ::ValidateSz( pPre );
+ }
+
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+
+
+ // NEW: Looping Louie (Light). Should not be applied in balanced sections.
+ // Should only be applied if there is no better solution!
+ LOOPING_LOUIE_LIGHT( bMovedFwd && bMovedBwd && !IsInBalancedSection() &&
+ (
+
+ // --> FME 2005-01-26 #118572#
+ ( bFtn && !FindFtnFrm()->GetRef()->IsInSct() ) ||
+ // <--
+
+ // --> FME 2005-01-27 #i33887#
+ ( IsInSct() && bKeep )
+ // <--
+
+ // ... add your conditions here ...
+
+ ),
+ static_cast<SwTxtFrm&>(*this) );
+
+
+ if ( pSaveFtn )
+ delete pSaveFtn;
+
+ UnlockJoin();
+ if ( bMovedFwd || bMovedBwd )
+ pNotify->SetInvaKeep();
+ // OD 2004-02-26 #i25029#
+ if ( bMovedFwd )
+ {
+ pNotify->SetInvalidatePrevPrtArea();
+ }
+ delete pNotify;
+ SetFlyLock( sal_False );
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::_WouldFit()
+|*
+|*************************************************************************/
+
+
+
+
+void MakeNxt( SwFrm *pFrm, SwFrm *pNxt )
+{
+ //fix(25455): Validieren, sonst kommt es zu einer Rekursion.
+ //Der erste Versuch, der Abbruch mit pFrm = 0 wenn !Valid,
+ //fuehrt leider zu dem Problem, dass das Keep dann u.U. nicht mehr
+ //korrekt beachtet wird (27417)
+ const sal_Bool bOldPos = pFrm->GetValidPosFlag();
+ const sal_Bool bOldSz = pFrm->GetValidSizeFlag();
+ const sal_Bool bOldPrt = pFrm->GetValidPrtAreaFlag();
+ pFrm->bValidPos = pFrm->bValidPrtArea = pFrm->bValidSize = sal_True;
+
+ //fix(29272): Nicht MakeAll rufen, dort wird evtl. pFrm wieder invalidert
+ //und kommt rekursiv wieder herein.
+ if ( pNxt->IsCntntFrm() )
+ {
+ SwCntntNotify aNotify( (SwCntntFrm*)pNxt );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ if ( !pNxt->GetValidSizeFlag() )
+ {
+ if( pNxt->IsVertical() )
+ pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
+ else
+ pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
+ }
+ ((SwCntntFrm*)pNxt)->MakePrtArea( rAttrs );
+ pNxt->Format( &rAttrs );
+ }
+ else
+ {
+ SwLayNotify aNotify( (SwLayoutFrm*)pNxt );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ if ( !pNxt->GetValidSizeFlag() )
+ {
+ if( pNxt->IsVertical() )
+ pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
+ else
+ pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
+ }
+ pNxt->Format( &rAttrs );
+ }
+
+ pFrm->bValidPos = bOldPos;
+ pFrm->bValidSize = bOldSz;
+ pFrm->bValidPrtArea = bOldPrt;
+}
+
+// Diese Routine ueberprueft, ob zwischen dem FtnBoss von pFrm und dem
+// von pNxt keine anderen FtnBosse liegen
+
+sal_Bool lcl_IsNextFtnBoss( const SwFrm *pFrm, const SwFrm* pNxt )
+{
+ OSL_ENSURE( pFrm && pNxt, "lcl_IsNextFtnBoss: No Frames?" );
+ pFrm = pFrm->FindFtnBossFrm();
+ pNxt = pNxt->FindFtnBossFrm();
+ // Falls pFrm eine letzte Spalte ist, wird stattdessen die Seite genommen
+ while( pFrm && pFrm->IsColumnFrm() && !pFrm->GetNext() )
+ pFrm = pFrm->GetUpper()->FindFtnBossFrm();
+ // Falls pNxt eine erste Spalte ist, wird stattdessen die Seite genommen
+ while( pNxt && pNxt->IsColumnFrm() && !pNxt->GetPrev() )
+ pNxt = pNxt->GetUpper()->FindFtnBossFrm();
+ // So, jetzt muessen pFrm und pNxt entweder zwei benachbarte Seiten oder Spalten sein.
+ return ( pFrm && pNxt && pFrm->GetNext() == pNxt );
+}
+
+// --> OD 2007-11-26 #b6614158#
+sal_Bool SwCntntFrm::_WouldFit( SwTwips nSpace,
+ SwLayoutFrm *pNewUpper,
+ sal_Bool bTstMove,
+ const bool bObjsInNewUpper )
+// <--
+{
+ //Damit die Fussnote sich ihren Platz sorgsam waehlt, muss
+ //sie in jedem Fall gemoved werden, wenn zwischen dem
+ //neuen Upper und ihrer aktuellen Seite/Spalte mindestens eine
+ //Seite/Spalte liegt.
+ SwFtnFrm* pFtnFrm = 0;
+ if ( IsInFtn() )
+ {
+ if( !lcl_IsNextFtnBoss( pNewUpper, this ) )
+ return sal_True;
+ pFtnFrm = FindFtnFrm();
+ }
+
+ sal_Bool bRet;
+ sal_Bool bSplit = !pNewUpper->Lower();
+ SwCntntFrm *pFrm = this;
+ const SwFrm *pTmpPrev = pNewUpper->Lower();
+ if( pTmpPrev && pTmpPrev->IsFtnFrm() )
+ pTmpPrev = ((SwFtnFrm*)pTmpPrev)->Lower();
+ while ( pTmpPrev && pTmpPrev->GetNext() )
+ pTmpPrev = pTmpPrev->GetNext();
+ do
+ {
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ SwTwips nSecondCheck = 0;
+ SwTwips nOldSpace = nSpace;
+ sal_Bool bOldSplit = bSplit;
+ // <--
+
+ if ( bTstMove || IsInFly() || ( IsInSct() &&
+ ( pFrm->GetUpper()->IsColBodyFrm() || ( pFtnFrm &&
+ pFtnFrm->GetUpper()->GetUpper()->IsColumnFrm() ) ) ) )
+ {
+ //Jetzt wirds ein bischen hinterlistig; empfindliche Gemueter sollten
+ //lieber wegsehen. Wenn ein Flys Spalten enthaelt so sind die Cntnts
+ //moveable, mit Ausnahme der in der letzten Spalte (siehe
+ //SwFrm::IsMoveable()). Zurueckfliessen duerfen sie aber natuerlich.
+ //Das WouldFit() liefert leider nur dann einen vernueftigen Wert, wenn
+ //der Frm moveable ist. Um dem WouldFit() einen Moveable Frm
+ //vorzugaukeln haenge ich ihn einfach solange um.
+ // Auch bei spaltigen Bereichen muss umgehaengt werden, damit
+ // SwSectionFrm::Growable() den richtigen Wert liefert.
+ // Innerhalb von Fussnoten muss ggf. sogar der SwFtnFrm umgehaengt werden,
+ // falls es dort keinen SwFtnFrm gibt.
+ SwFrm* pTmpFrm = pFrm->IsInFtn() && !pNewUpper->FindFtnFrm() ?
+ (SwFrm*)pFrm->FindFtnFrm() : pFrm;
+ SwLayoutFrm *pUp = pTmpFrm->GetUpper();
+ SwFrm *pOldNext = pTmpFrm->GetNext();
+ pTmpFrm->Remove();
+ pTmpFrm->InsertBefore( pNewUpper, 0 );
+ if ( pFrm->IsTxtFrm() &&
+ ( bTstMove ||
+ ((SwTxtFrm*)pFrm)->HasFollow() ||
+ ( !((SwTxtFrm*)pFrm)->HasPara() &&
+ !((SwTxtFrm*)pFrm)->IsEmpty()
+ )
+ )
+ )
+ {
+ bTstMove = sal_True;
+ bRet = ((SwTxtFrm*)pFrm)->TestFormat( pTmpPrev, nSpace, bSplit );
+ }
+ else
+ bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
+
+ pTmpFrm->Remove();
+ pTmpFrm->InsertBefore( pUp, pOldNext );
+ }
+ else
+ {
+ bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
+ nSecondCheck = !bSplit ? 1 : 0;
+ }
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ //Bitter aber wahr: Der Abstand muss auch noch mit einkalkuliert werden.
+ //Bei TestFormatierung ist dies bereits geschehen.
+ if ( bRet && !bTstMove )
+ {
+ SwTwips nUpper;
+
+ if ( pTmpPrev )
+ {
+ nUpper = CalcUpperSpace( NULL, pTmpPrev );
+
+ // in balanced columned section frames we do not want the
+ // common border
+ sal_Bool bCommonBorder = sal_True;
+ if ( pFrm->IsInSct() && pFrm->GetUpper()->IsColBodyFrm() )
+ {
+ const SwSectionFrm* pSct = pFrm->FindSctFrm();
+ bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
+ }
+
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ nSecondCheck = ( 1 == nSecondCheck &&
+ pFrm == this &&
+ IsTxtFrm() &&
+ bCommonBorder &&
+ !static_cast<const SwTxtFrm*>(this)->IsEmpty() ) ?
+ nUpper :
+ 0;
+ // <--
+
+ nUpper += bCommonBorder ?
+ rAttrs.GetBottomLine( *(pFrm) ) :
+ rAttrs.CalcBottomLine();
+
+ }
+ else
+ {
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ nSecondCheck = 0;
+ // <--
+
+ if( pFrm->IsVertical() )
+ nUpper = pFrm->Frm().Width() - pFrm->Prt().Width();
+ else
+ nUpper = pFrm->Frm().Height() - pFrm->Prt().Height();
+ }
+
+ nSpace -= nUpper;
+
+ if ( nSpace < 0 )
+ {
+ bRet = sal_False;
+
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ if ( nSecondCheck > 0 )
+ {
+ // The following code is indented to solve a (rare) problem
+ // causing some frames not to move backward:
+ // SwTxtFrm::WouldFit() claims that the whole paragraph
+ // fits into the given space and subtracts the height of
+ // all lines from nSpace. nSpace - nUpper is not a valid
+ // indicator if the frame should be allowed to move backward.
+ // We do a second check with the original remaining space
+ // reduced by the required upper space:
+ nOldSpace -= nSecondCheck;
+ const bool bSecondRet = nOldSpace >= 0 && pFrm->WouldFit( nOldSpace, bOldSplit, sal_False );
+ if ( bSecondRet && bOldSplit && nOldSpace >= 0 )
+ {
+ bRet = sal_True;
+ bSplit = sal_True;
+ }
+ }
+ // <--
+ }
+ }
+
+ // OD 2004-03-01 #106629# - also consider lower spacing in table cells
+ if ( bRet && IsInTab() &&
+ pNewUpper->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
+ {
+ nSpace -= rAttrs.GetULSpace().GetLower();
+ if ( nSpace < 0 )
+ {
+ bRet = sal_False;
+ }
+ }
+
+ if ( bRet && !bSplit && pFrm->IsKeep( rAttrs.GetAttrSet() ) )
+ {
+ if( bTstMove )
+ {
+ while( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
+ {
+ pFrm = ((SwTxtFrm*)pFrm)->GetFollow();
+ }
+ // OD 11.04.2003 #108824# - If last follow frame of <this> text
+ // frame isn't valid, a formatting of the next content frame
+ // doesn't makes sense. Thus, return sal_True.
+ if ( IsAnFollow( pFrm ) && !pFrm->IsValid() )
+ {
+ OSL_FAIL( "Only a warning for task 108824:/n<SwCntntFrm::_WouldFit(..) - follow not valid!" );
+ return sal_True;
+ }
+ }
+ SwFrm *pNxt;
+ if( 0 != (pNxt = pFrm->FindNext()) && pNxt->IsCntntFrm() &&
+ ( !pFtnFrm || ( pNxt->IsInFtn() &&
+ pNxt->FindFtnFrm()->GetAttr() == pFtnFrm->GetAttr() ) ) )
+ {
+ // ProbeFormatierung vertraegt keine absatz- oder gar zeichengebundene Objekte
+ // --> OD 2007-11-26 #b6614158#
+ // current solution for the test formatting doesn't work, if
+ // objects are present in the remaining area of the new upper
+ if ( bTstMove &&
+ ( pNxt->GetDrawObjs() || bObjsInNewUpper ) )
+ {
+ return sal_True;
+ }
+ // <--
+
+ if ( !pNxt->IsValid() )
+ MakeNxt( pFrm, pNxt );
+
+ //Kleiner Trick: Wenn der naechste einen Vorgaenger hat, so hat
+ //er den Absatzabstand bereits berechnet. Er braucht dann nicht
+ //teuer kalkuliert werden.
+ if( lcl_NotHiddenPrev( pNxt ) )
+ pTmpPrev = 0;
+ else
+ {
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow() )
+ pTmpPrev = lcl_NotHiddenPrev( pFrm );
+ else
+ pTmpPrev = pFrm;
+ }
+ pFrm = (SwCntntFrm*)pNxt;
+ }
+ else
+ pFrm = 0;
+ }
+ else
+ pFrm = 0;
+
+ } while ( bRet && pFrm );
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */