summaryrefslogtreecommitdiff
path: root/sw/source/core/layout/layouter.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/layout/layouter.cxx')
-rw-r--r--sw/source/core/layout/layouter.cxx565
1 files changed, 565 insertions, 0 deletions
diff --git a/sw/source/core/layout/layouter.cxx b/sw/source/core/layout/layouter.cxx
new file mode 100644
index 000000000000..a02b17401c01
--- /dev/null
+++ b/sw/source/core/layout/layouter.cxx
@@ -0,0 +1,565 @@
+/* -*- 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 "layouter.hxx"
+#include "doc.hxx"
+#include "sectfrm.hxx"
+#include "ftnboss.hxx"
+#include "cntfrm.hxx"
+#include "pagefrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+
+// --> OD 2004-06-23 #i28701#
+#include <movedfwdfrmsbyobjpos.hxx>
+// <--
+// --> OD 2004-10-22 #i35911#
+#include <objstmpconsiderwrapinfl.hxx>
+// <--
+
+#define LOOP_DETECT 250
+
+class SwLooping
+{
+ sal_uInt16 nMinPage;
+ sal_uInt16 nMaxPage;
+ sal_uInt16 nCount;
+ sal_uInt16 mnLoopControlStage;
+public:
+ SwLooping( SwPageFrm* pPage );
+ void Control( SwPageFrm* pPage );
+ void Drastic( SwFrm* pFrm );
+ bool IsLoopingLouieLight() const { return nCount > LOOP_DETECT - 30; };
+};
+
+class SwEndnoter
+{
+ SwLayouter* pMaster;
+ SwSectionFrm* pSect;
+ SvPtrarr* pEndArr;
+public:
+ SwEndnoter( SwLayouter* pLay )
+ : pMaster( pLay ), pSect( NULL ), pEndArr( NULL ) {}
+ ~SwEndnoter() { delete pEndArr; }
+ void CollectEndnotes( SwSectionFrm* pSct );
+ void CollectEndnote( SwFtnFrm* pFtn );
+ const SwSectionFrm* GetSect() const { return pSect; }
+ void InsertEndnotes();
+ sal_Bool HasEndnotes() const { return pEndArr && pEndArr->Count(); }
+};
+
+void SwEndnoter::CollectEndnotes( SwSectionFrm* pSct )
+{
+ OSL_ENSURE( pSct, "CollectEndnotes: Which section?" );
+ if( !pSect )
+ pSect = pSct;
+ else if( pSct != pSect )
+ return;
+ pSect->CollectEndnotes( pMaster );
+}
+
+void SwEndnoter::CollectEndnote( SwFtnFrm* pFtn )
+{
+ if( pEndArr && USHRT_MAX != pEndArr->GetPos( (VoidPtr)pFtn ) )
+ return;
+
+ if( pFtn->GetUpper() )
+ {
+ // pFtn is the master, he incorporates its follows
+ SwFtnFrm *pNxt = pFtn->GetFollow();
+ while ( pNxt )
+ {
+ SwFrm *pCnt = pNxt->ContainsAny();
+ if ( pCnt )
+ {
+ do
+ { SwFrm *pNxtCnt = pCnt->GetNext();
+ pCnt->Cut();
+ pCnt->Paste( pFtn );
+ pCnt = pNxtCnt;
+ } while ( pCnt );
+ }
+ else
+ { OSL_ENSURE( pNxt->Lower() && pNxt->Lower()->IsSctFrm(),
+ "Endnote without content?" );
+ pNxt->Cut();
+ delete pNxt;
+ }
+ pNxt = pFtn->GetFollow();
+ }
+ if( pFtn->GetMaster() )
+ return;
+ pFtn->Cut();
+ }
+ else if( pEndArr )
+ {
+ for ( sal_uInt16 i = 0; i < pEndArr->Count(); ++i )
+ {
+ SwFtnFrm *pEndFtn = (SwFtnFrm*)((*pEndArr)[i]);
+ if( pEndFtn->GetAttr() == pFtn->GetAttr() )
+ {
+ delete pFtn;
+ return;
+ }
+ }
+ }
+ if( !pEndArr )
+ pEndArr = new SvPtrarr( 5, 5 ); // deleted from the SwLayouter
+ pEndArr->Insert( (VoidPtr)pFtn, pEndArr->Count() );
+}
+
+void SwEndnoter::InsertEndnotes()
+{
+ if( !pSect )
+ return;
+ if( !pEndArr || !pEndArr->Count() )
+ {
+ pSect = NULL;
+ return;
+ }
+ OSL_ENSURE( pSect->Lower() && pSect->Lower()->IsFtnBossFrm(),
+ "InsertEndnotes: Where's my column?" );
+ SwFrm* pRef = pSect->FindLastCntnt( FINDMODE_MYLAST );
+ SwFtnBossFrm *pBoss = pRef ? pRef->FindFtnBossFrm()
+ : (SwFtnBossFrm*)pSect->Lower();
+ pBoss->_MoveFtns( *pEndArr );
+ delete pEndArr;
+ pEndArr = NULL;
+ pSect = NULL;
+}
+
+SwLooping::SwLooping( SwPageFrm* pPage )
+{
+ OSL_ENSURE( pPage, "Where's my page?" );
+ nMinPage = pPage->GetPhyPageNum();
+ nMaxPage = nMinPage;
+ nCount = 0;
+ mnLoopControlStage = 0;
+}
+
+void SwLooping::Drastic( SwFrm* pFrm )
+{
+ while( pFrm )
+ {
+ pFrm->ValidateThisAndAllLowers( mnLoopControlStage );
+ pFrm = pFrm->GetNext();
+ }
+}
+
+void SwLooping::Control( SwPageFrm* pPage )
+{
+ if( !pPage )
+ return;
+ sal_uInt16 nNew = pPage->GetPhyPageNum();
+ if( nNew > nMaxPage )
+ nMaxPage = nNew;
+ if( nNew < nMinPage )
+ {
+ nMinPage = nNew;
+ nMaxPage = nNew;
+ nCount = 0;
+ mnLoopControlStage = 0;
+ }
+ else if( nNew > nMinPage + 2 )
+ {
+ nMinPage = nNew - 2;
+ nMaxPage = nNew;
+ nCount = 0;
+ mnLoopControlStage = 0;
+ }
+ else if( ++nCount > LOOP_DETECT )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bNoLouie = sal_False;
+ if( bNoLouie )
+ return;
+
+ // FME 2007-08-30 #i81146# new loop control
+ OSL_ENSURE( 0 != mnLoopControlStage, "Looping Louie: Stage 1!" );
+ OSL_ENSURE( 1 != mnLoopControlStage, "Looping Louie: Stage 2!!" );
+ OSL_ENSURE( 2 > mnLoopControlStage, "Looping Louie: Stage 3!!!" );
+#endif
+
+ Drastic( pPage->Lower() );
+ if( nNew > nMinPage && pPage->GetPrev() )
+ Drastic( ((SwPageFrm*)pPage->GetPrev())->Lower() );
+ if( nNew < nMaxPage && pPage->GetNext() )
+ Drastic( ((SwPageFrm*)pPage->GetNext())->Lower() );
+
+ ++mnLoopControlStage;
+ nCount = 0;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayouter::SwLayouter()
+|*
+|*************************************************************************/
+
+SwLayouter::SwLayouter()
+ : pEndnoter( NULL ),
+ pLooping( NULL ),
+ // --> OD 2004-06-23 #i28701#
+ mpMovedFwdFrms( 0L ),
+ // <--
+ // --> OD 2004-10-22 #i35911#
+ mpObjsTmpConsiderWrapInfl( 0L )
+ // <--
+{
+}
+
+SwLayouter::~SwLayouter()
+{
+ delete pEndnoter;
+ delete pLooping;
+ // --> OD 2004-06-23 #i28701#
+ delete mpMovedFwdFrms;
+ mpMovedFwdFrms = 0L;
+ // <--
+ // --> OD 2004-10-22 #i35911#
+ delete mpObjsTmpConsiderWrapInfl;
+ mpObjsTmpConsiderWrapInfl = 0L;
+ // <--
+}
+
+void SwLayouter::_CollectEndnotes( SwSectionFrm* pSect )
+{
+ if( !pEndnoter )
+ pEndnoter = new SwEndnoter( this );
+ pEndnoter->CollectEndnotes( pSect );
+}
+
+sal_Bool SwLayouter::HasEndnotes() const
+{
+ return pEndnoter->HasEndnotes();
+}
+
+void SwLayouter::CollectEndnote( SwFtnFrm* pFtn )
+{
+ pEndnoter->CollectEndnote( pFtn );
+}
+
+void SwLayouter::InsertEndnotes( SwSectionFrm* pSect )
+{
+ if( !pEndnoter || pEndnoter->GetSect() != pSect )
+ return;
+ pEndnoter->InsertEndnotes();
+}
+
+void SwLayouter::LoopControl( SwPageFrm* pPage, sal_uInt8 )
+{
+ OSL_ENSURE( pLooping, "Looping: Lost control" );
+ pLooping->Control( pPage );
+}
+
+void SwLayouter::LoopingLouieLight( const SwDoc& rDoc, const SwTxtFrm& rFrm )
+{
+ if ( pLooping && pLooping->IsLoopingLouieLight() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "Looping Louie (Light): Fixating fractious frame" );
+#endif
+ SwLayouter::InsertMovedFwdFrm( rDoc, rFrm, rFrm.FindPageFrm()->GetPhyPageNum() );
+ }
+}
+
+sal_Bool SwLayouter::StartLooping( SwPageFrm* pPage )
+{
+ if( pLooping )
+ return sal_False;
+ pLooping = new SwLooping( pPage );
+ return sal_True;
+}
+
+void SwLayouter::EndLoopControl()
+{
+ delete pLooping;
+ pLooping = NULL;
+}
+
+void SwLayouter::CollectEndnotes( SwDoc* pDoc, SwSectionFrm* pSect )
+{
+ OSL_ENSURE( pDoc, "No doc, no fun" );
+ if( !pDoc->GetLayouter() )
+ pDoc->SetLayouter( new SwLayouter() );
+ pDoc->GetLayouter()->_CollectEndnotes( pSect );
+}
+
+sal_Bool SwLayouter::Collecting( SwDoc* pDoc, SwSectionFrm* pSect, SwFtnFrm* pFtn )
+{
+ if( !pDoc->GetLayouter() )
+ return sal_False;
+ SwLayouter *pLayouter = pDoc->GetLayouter();
+ if( pLayouter->pEndnoter && pLayouter->pEndnoter->GetSect() && pSect &&
+ ( pLayouter->pEndnoter->GetSect()->IsAnFollow( pSect ) ||
+ pSect->IsAnFollow( pLayouter->pEndnoter->GetSect() ) ) )
+ {
+ if( pFtn )
+ pLayouter->CollectEndnote( pFtn );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwLayouter::StartLoopControl( SwDoc* pDoc, SwPageFrm *pPage )
+{
+ OSL_ENSURE( pDoc, "No doc, no fun" );
+ if( !pDoc->GetLayouter() )
+ pDoc->SetLayouter( new SwLayouter() );
+ return !pDoc->GetLayouter()->pLooping &&
+ pDoc->GetLayouter()->StartLooping( pPage );
+}
+
+// --> OD 2004-06-23 #i28701#
+// -----------------------------------------------------------------------------
+// methods to manage text frames, which are moved forward by the positioning
+// of its anchored objects
+// -----------------------------------------------------------------------------
+void SwLayouter::ClearMovedFwdFrms( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() &&
+ _rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ _rDoc.GetLayouter()->mpMovedFwdFrms->Clear();
+ }
+}
+
+void SwLayouter::InsertMovedFwdFrm( const SwDoc& _rDoc,
+ const SwTxtFrm& _rMovedFwdFrmByObjPos,
+ const sal_uInt32 _nToPageNum )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->mpMovedFwdFrms =
+ new SwMovedFwdFrmsByObjPos();
+ }
+
+ _rDoc.GetLayouter()->mpMovedFwdFrms->Insert( _rMovedFwdFrmByObjPos,
+ _nToPageNum );
+}
+
+// --> OD 2005-01-12 #i40155#
+void SwLayouter::RemoveMovedFwdFrm( const SwDoc& _rDoc,
+ const SwTxtFrm& _rTxtFrm )
+{
+ sal_uInt32 nDummy;
+ if ( SwLayouter::FrmMovedFwdByObjPos( _rDoc, _rTxtFrm, nDummy ) )
+ {
+ _rDoc.GetLayouter()->mpMovedFwdFrms->Remove( _rTxtFrm );
+ }
+}
+// <--
+
+bool SwLayouter::FrmMovedFwdByObjPos( const SwDoc& _rDoc,
+ const SwTxtFrm& _rTxtFrm,
+ sal_uInt32& _ornToPageNum )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ _ornToPageNum = 0;
+ return false;
+ }
+ else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ _ornToPageNum = 0;
+ return false;
+ }
+ else
+ {
+ return _rDoc.GetLayouter()->mpMovedFwdFrms->
+ FrmMovedFwdByObjPos( _rTxtFrm, _ornToPageNum );
+ }
+}
+// <--
+// --> OD 2004-10-05 #i26945#
+bool SwLayouter::DoesRowContainMovedFwdFrm( const SwDoc& _rDoc,
+ const SwRowFrm& _rRowFrm )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ return false;
+ }
+ else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ return false;
+ }
+ else
+ {
+ return _rDoc.GetLayouter()->
+ mpMovedFwdFrms->DoesRowContainMovedFwdFrm( _rRowFrm );
+ }
+}
+// <--
+
+// --> OD 2004-10-22 #i35911#
+void SwLayouter::ClearObjsTmpConsiderWrapInfluence( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() &&
+ _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
+ {
+ _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Clear();
+ }
+}
+void SwLayouter::InsertObjForTmpConsiderWrapInfluence(
+ const SwDoc& _rDoc,
+ SwAnchoredObject& _rAnchoredObj )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ if ( !_rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->mpObjsTmpConsiderWrapInfl =
+ new SwObjsMarkedAsTmpConsiderWrapInfluence();
+ }
+
+ _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Insert( _rAnchoredObj );
+}
+// <--
+// --> OD 2005-01-12 #i40155#
+void SwLayouter::ClearFrmsNotToWrap( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->maFrmsNotToWrap.clear();
+ }
+}
+
+void SwLayouter::InsertFrmNotToWrap( const SwDoc& _rDoc,
+ const SwFrm& _rFrm )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ if ( !SwLayouter::FrmNotToWrap( _rDoc, _rFrm ) )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->maFrmsNotToWrap.push_back( &_rFrm );
+ }
+}
+
+bool SwLayouter::FrmNotToWrap( const IDocumentLayoutAccess& _rDLA,
+ const SwFrm& _rFrm )
+{
+ const SwLayouter* pLayouter = _rDLA.GetLayouter();
+ if ( !pLayouter )
+ {
+ return false;
+ }
+ else
+ {
+ bool bFrmNotToWrap( false );
+ std::vector< const SwFrm* >::const_iterator aIter =
+ pLayouter->maFrmsNotToWrap.begin();
+ for ( ; aIter != pLayouter->maFrmsNotToWrap.end(); ++aIter )
+ {
+ const SwFrm* pFrm = *(aIter);
+ if ( pFrm == &_rFrm )
+ {
+ bFrmNotToWrap = true;
+ break;
+ }
+ }
+ return bFrmNotToWrap;
+ }
+}
+// <--
+
+void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTxtFrm& rTxtFrm )
+{
+ if ( bCondition )
+ {
+ const SwDoc& rDoc = *rTxtFrm.GetAttrSet()->GetDoc();
+ if ( rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(rDoc).GetLayouter()->LoopingLouieLight( rDoc, rTxtFrm );
+ }
+ }
+}
+
+// --> OD 2006-05-10 #i65250#
+bool SwLayouter::MoveBwdSuppressed( const SwDoc& p_rDoc,
+ const SwFlowFrm& p_rFlowFrm,
+ const SwLayoutFrm& p_rNewUpperFrm )
+{
+ bool bMoveBwdSuppressed( false );
+
+ if ( !p_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(p_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ // create hash map key
+ tMoveBwdLayoutInfoKey aMoveBwdLayoutInfo;
+ aMoveBwdLayoutInfo.mnFrmId = p_rFlowFrm.GetFrm()->GetFrmId();
+ aMoveBwdLayoutInfo.mnNewUpperPosX = p_rNewUpperFrm.Frm().Pos().X();
+ aMoveBwdLayoutInfo.mnNewUpperPosY = p_rNewUpperFrm.Frm().Pos().Y();
+ aMoveBwdLayoutInfo.mnNewUpperWidth = p_rNewUpperFrm.Frm().Width();
+ aMoveBwdLayoutInfo.mnNewUpperHeight = p_rNewUpperFrm.Frm().Height();
+ SWRECTFN( (&p_rNewUpperFrm) )
+ const SwFrm* pLastLower( p_rNewUpperFrm.Lower() );
+ while ( pLastLower && pLastLower->GetNext() )
+ {
+ pLastLower = pLastLower->GetNext();
+ }
+ aMoveBwdLayoutInfo.mnFreeSpaceInNewUpper =
+ pLastLower
+ ? (pLastLower->Frm().*fnRect->fnBottomDist)( (p_rNewUpperFrm.*fnRect->fnGetPrtBottom)() )
+ : (p_rNewUpperFrm.Frm().*fnRect->fnGetHeight)();
+
+ // check for moving backward suppress threshold
+ const sal_uInt16 cMoveBwdCountSuppressThreshold = 20;
+ if ( ++const_cast<SwDoc&>(p_rDoc).GetLayouter()->maMoveBwdLayoutInfo[ aMoveBwdLayoutInfo ] >
+ cMoveBwdCountSuppressThreshold )
+ {
+ bMoveBwdSuppressed = true;
+ }
+
+ return bMoveBwdSuppressed;
+}
+
+void SwLayouter::ClearMoveBwdLayoutInfo( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() )
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->maMoveBwdLayoutInfo.clear();
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */