Files
libreoffice/sw/source/core/layout/layouter.cxx

548 lines
15 KiB
C++
Raw Normal View History

2000-09-18 23:08:29 +00:00
/*************************************************************************
*
* $RCSfile: layouter.cxx,v $
*
* $Revision: 1.9 $
2000-09-18 23:08:29 +00:00
*
* last change: $Author: vg $ $Date: 2005-02-22 08:20:05 $
2000-09-18 23:08:29 +00:00
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#pragma hdrstop
#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#
#ifndef _MOVEDFWDFRMSBYOBJPOS_HXX
#include <movedfwdfrmsbyobjpos.hxx>
#endif
// <--
// --> OD 2004-10-22 #i35911#
#ifndef _OBJSTMPCONSIDERWRAPINFL_HXX
#include <objstmpconsiderwrapinfl.hxx>
#endif
// <--
2000-09-18 23:08:29 +00:00
#define LOOP_DETECT 250
2000-09-18 23:08:29 +00:00
class SwLooping
{
USHORT nMinPage;
USHORT nMaxPage;
USHORT nCount;
public:
SwLooping( SwPageFrm* pPage );
void Control( SwPageFrm* pPage );
static void Drastic( SwFrm* pFrm );
bool IsLoopingLouieLight() const { return nCount > LOOP_DETECT - 30; };
2000-09-18 23:08:29 +00:00
};
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() { return pSect; }
void InsertEndnotes();
BOOL HasEndnotes() const { return pEndArr && pEndArr->Count(); }
};
void SwEndnoter::CollectEndnotes( SwSectionFrm* pSct )
{
ASSERT( 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
{ ASSERT( 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 ( USHORT 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;
}
ASSERT( 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 )
{
ASSERT( pPage, "Where's my page?" );
nMinPage = pPage->GetPhyPageNum();
nMaxPage = nMinPage;
nCount = 0;
}
void SwLooping::Drastic( SwFrm* pFrm )
{
while( pFrm )
{
if( pFrm->IsLayoutFrm() )
Drastic( ((SwLayoutFrm*)pFrm)->Lower() );
pFrm->bValidPos = TRUE;
pFrm->bValidSize = TRUE;
pFrm->bValidPrtArea = TRUE;
pFrm = pFrm->GetNext();
}
}
void SwLooping::Control( SwPageFrm* pPage )
{
if( !pPage )
return;
USHORT nNew = pPage->GetPhyPageNum();
if( nNew > nMaxPage )
nMaxPage = nNew;
if( nNew < nMinPage )
{
nMinPage = nNew;
nMaxPage = nNew;
nCount = 0;
}
else if( nNew > nMinPage + 2 )
{
nMinPage = nNew - 2;
nMaxPage = nNew;
nCount = 0;
}
else if( ++nCount > LOOP_DETECT )
{
#ifndef PRODUCT
#if OSL_DEBUG_LEVEL > 1
2000-09-18 23:08:29 +00:00
static BOOL bNoLouie = FALSE;
if( bNoLouie )
return;
#endif
#endif
ASSERT( FALSE, "Looping Louie" );
nCount = 0;
Drastic( pPage->Lower() );
if( nNew > nMinPage && pPage->GetPrev() )
Drastic( ((SwPageFrm*)pPage->GetPrev())->Lower() );
if( nNew < nMaxPage && pPage->GetNext() )
Drastic( ((SwPageFrm*)pPage->GetNext())->Lower() );
}
}
/*************************************************************************
|*
|* SwLayouter::SwLayouter()
|*
|* Ersterstellung AMA 02. Nov. 99
|* Letzte Aenderung AMA 02. Nov. 99
|*
|*************************************************************************/
SwLayouter::SwLayouter()
: pEndnoter( NULL ),
pLooping( NULL ),
// --> OD 2004-06-23 #i28701#
mpMovedFwdFrms( 0L ),
// <--
// --> OD 2004-10-22 #i35911#
mpObjsTmpConsiderWrapInfl( 0L )
// <--
2000-09-18 23:08:29 +00:00
{
}
SwLayouter::~SwLayouter()
{
delete pEndnoter;
delete pLooping;
// --> OD 2004-06-23 #i28701#
delete mpMovedFwdFrms;
// <--
// --> OD 2004-10-22 #i35911#
delete mpObjsTmpConsiderWrapInfl;
// <--
2000-09-18 23:08:29 +00:00
}
void SwLayouter::_CollectEndnotes( SwSectionFrm* pSect )
{
if( !pEndnoter )
pEndnoter = new SwEndnoter( this );
pEndnoter->CollectEndnotes( pSect );
}
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, BYTE nLoop )
{
ASSERT( 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
ASSERT( false, "Looping Louie (Light): Fixating fractious frame" )
#endif
SwLayouter::InsertMovedFwdFrm( rDoc, rFrm, rFrm.FindPageFrm()->GetPhyPageNum() );
}
}
2000-09-18 23:08:29 +00:00
BOOL SwLayouter::StartLooping( SwPageFrm* pPage )
{
if( pLooping )
return FALSE;
pLooping = new SwLooping( pPage );
return TRUE;
}
void SwLayouter::EndLoopControl()
{
delete pLooping;
pLooping = NULL;
}
void SwLayouter::CollectEndnotes( SwDoc* pDoc, SwSectionFrm* pSect )
{
ASSERT( pDoc, "No doc, no fun" );
if( !pDoc->GetLayouter() )
pDoc->SetLayouter( new SwLayouter() );
pDoc->GetLayouter()->_CollectEndnotes( pSect );
}
BOOL SwLayouter::Collecting( SwDoc* pDoc, SwSectionFrm* pSect, SwFtnFrm* pFtn )
{
if( !pDoc->GetLayouter() )
return 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 TRUE;
}
return FALSE;
}
BOOL SwLayouter::StartLoopControl( SwDoc* pDoc, SwPageFrm *pPage )
{
ASSERT( 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 );
}
2000-09-18 23:08:29 +00:00
// --> 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 SwDoc& _rDoc,
const SwFrm& _rFrm )
{
if ( !_rDoc.GetLayouter() )
{
return false;
}
else
{
bool bFrmNotToWrap( false );
std::vector< const SwFrm* >::const_iterator aIter =
_rDoc.GetLayouter()->maFrmsNotToWrap.begin();
for ( ; aIter != _rDoc.GetLayouter()->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 );
}
}
}