1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: layouter.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
36 #include "layouter.hxx"
38 #include "sectfrm.hxx"
39 #include "ftnboss.hxx"
41 #include "pagefrm.hxx"
45 // --> OD 2004-06-23 #i28701#
46 #include <movedfwdfrmsbyobjpos.hxx>
48 // --> OD 2004-10-22 #i35911#
49 #include <objstmpconsiderwrapinfl.hxx>
52 #define LOOP_DETECT 250
59 USHORT mnLoopControlStage
;
61 SwLooping( SwPageFrm
* pPage
);
62 void Control( SwPageFrm
* pPage
);
63 void Drastic( SwFrm
* pFrm
);
64 bool IsLoopingLouieLight() const { return nCount
> LOOP_DETECT
- 30; };
73 SwEndnoter( SwLayouter
* pLay
)
74 : pMaster( pLay
), pSect( NULL
), pEndArr( NULL
) {}
75 ~SwEndnoter() { delete pEndArr
; }
76 void CollectEndnotes( SwSectionFrm
* pSct
);
77 void CollectEndnote( SwFtnFrm
* pFtn
);
78 const SwSectionFrm
* GetSect() { return pSect
; }
79 void InsertEndnotes();
80 BOOL
HasEndnotes() const { return pEndArr
&& pEndArr
->Count(); }
83 void SwEndnoter::CollectEndnotes( SwSectionFrm
* pSct
)
85 ASSERT( pSct
, "CollectEndnotes: Which section?" );
88 else if( pSct
!= pSect
)
90 pSect
->CollectEndnotes( pMaster
);
93 void SwEndnoter::CollectEndnote( SwFtnFrm
* pFtn
)
95 if( pEndArr
&& USHRT_MAX
!= pEndArr
->GetPos( (VoidPtr
)pFtn
) )
98 if( pFtn
->GetUpper() )
100 // pFtn is the master, he incorporates its follows
101 SwFtnFrm
*pNxt
= pFtn
->GetFollow();
104 SwFrm
*pCnt
= pNxt
->ContainsAny();
108 { SwFrm
*pNxtCnt
= pCnt
->GetNext();
115 { ASSERT( pNxt
->Lower() && pNxt
->Lower()->IsSctFrm(),
116 "Endnote without content?" );
120 pNxt
= pFtn
->GetFollow();
122 if( pFtn
->GetMaster() )
128 for ( USHORT i
= 0; i
< pEndArr
->Count(); ++i
)
130 SwFtnFrm
*pEndFtn
= (SwFtnFrm
*)((*pEndArr
)[i
]);
131 if( pEndFtn
->GetAttr() == pFtn
->GetAttr() )
139 pEndArr
= new SvPtrarr( 5, 5 ); // deleted from the SwLayouter
140 pEndArr
->Insert( (VoidPtr
)pFtn
, pEndArr
->Count() );
143 void SwEndnoter::InsertEndnotes()
147 if( !pEndArr
|| !pEndArr
->Count() )
152 ASSERT( pSect
->Lower() && pSect
->Lower()->IsFtnBossFrm(),
153 "InsertEndnotes: Where's my column?" );
154 SwFrm
* pRef
= pSect
->FindLastCntnt( FINDMODE_MYLAST
);
155 SwFtnBossFrm
*pBoss
= pRef
? pRef
->FindFtnBossFrm()
156 : (SwFtnBossFrm
*)pSect
->Lower();
157 pBoss
->_MoveFtns( *pEndArr
);
163 SwLooping::SwLooping( SwPageFrm
* pPage
)
165 ASSERT( pPage
, "Where's my page?" );
166 nMinPage
= pPage
->GetPhyPageNum();
169 mnLoopControlStage
= 0;
172 void SwLooping::Drastic( SwFrm
* pFrm
)
176 pFrm
->ValidateThisAndAllLowers( mnLoopControlStage
);
177 pFrm
= pFrm
->GetNext();
181 void SwLooping::Control( SwPageFrm
* pPage
)
185 USHORT nNew
= pPage
->GetPhyPageNum();
186 if( nNew
> nMaxPage
)
188 if( nNew
< nMinPage
)
193 mnLoopControlStage
= 0;
195 else if( nNew
> nMinPage
+ 2 )
200 mnLoopControlStage
= 0;
202 else if( ++nCount
> LOOP_DETECT
)
205 #if OSL_DEBUG_LEVEL > 1
206 static BOOL bNoLouie
= FALSE
;
212 // FME 2007-08-30 #i81146# new loop control
213 #if OSL_DEBUG_LEVEL > 1
214 ASSERT( 0 != mnLoopControlStage
, "Looping Louie: Stage 1!" );
215 ASSERT( 1 != mnLoopControlStage
, "Looping Louie: Stage 2!!" );
216 ASSERT( 2 > mnLoopControlStage
, "Looping Louie: Stage 3!!!" );
219 Drastic( pPage
->Lower() );
220 if( nNew
> nMinPage
&& pPage
->GetPrev() )
221 Drastic( ((SwPageFrm
*)pPage
->GetPrev())->Lower() );
222 if( nNew
< nMaxPage
&& pPage
->GetNext() )
223 Drastic( ((SwPageFrm
*)pPage
->GetNext())->Lower() );
225 ++mnLoopControlStage
;
230 /*************************************************************************
232 |* SwLayouter::SwLayouter()
234 |* Ersterstellung AMA 02. Nov. 99
235 |* Letzte Aenderung AMA 02. Nov. 99
237 |*************************************************************************/
239 SwLayouter::SwLayouter()
242 // --> OD 2004-06-23 #i28701#
243 mpMovedFwdFrms( 0L ),
245 // --> OD 2004-10-22 #i35911#
246 mpObjsTmpConsiderWrapInfl( 0L )
251 SwLayouter::~SwLayouter()
255 // --> OD 2004-06-23 #i28701#
256 delete mpMovedFwdFrms
;
259 // --> OD 2004-10-22 #i35911#
260 delete mpObjsTmpConsiderWrapInfl
;
261 mpObjsTmpConsiderWrapInfl
= 0L;
265 void SwLayouter::_CollectEndnotes( SwSectionFrm
* pSect
)
268 pEndnoter
= new SwEndnoter( this );
269 pEndnoter
->CollectEndnotes( pSect
);
272 BOOL
SwLayouter::HasEndnotes() const
274 return pEndnoter
->HasEndnotes();
277 void SwLayouter::CollectEndnote( SwFtnFrm
* pFtn
)
279 pEndnoter
->CollectEndnote( pFtn
);
282 void SwLayouter::InsertEndnotes( SwSectionFrm
* pSect
)
284 if( !pEndnoter
|| pEndnoter
->GetSect() != pSect
)
286 pEndnoter
->InsertEndnotes();
289 void SwLayouter::LoopControl( SwPageFrm
* pPage
, BYTE
)
291 ASSERT( pLooping
, "Looping: Lost control" );
292 pLooping
->Control( pPage
);
295 void SwLayouter::LoopingLouieLight( const SwDoc
& rDoc
, const SwTxtFrm
& rFrm
)
297 if ( pLooping
&& pLooping
->IsLoopingLouieLight() )
299 #if OSL_DEBUG_LEVEL > 1
300 ASSERT( false, "Looping Louie (Light): Fixating fractious frame" )
302 SwLayouter::InsertMovedFwdFrm( rDoc
, rFrm
, rFrm
.FindPageFrm()->GetPhyPageNum() );
306 BOOL
SwLayouter::StartLooping( SwPageFrm
* pPage
)
310 pLooping
= new SwLooping( pPage
);
314 void SwLayouter::EndLoopControl()
320 void SwLayouter::CollectEndnotes( SwDoc
* pDoc
, SwSectionFrm
* pSect
)
322 ASSERT( pDoc
, "No doc, no fun" );
323 if( !pDoc
->GetLayouter() )
324 pDoc
->SetLayouter( new SwLayouter() );
325 pDoc
->GetLayouter()->_CollectEndnotes( pSect
);
328 BOOL
SwLayouter::Collecting( SwDoc
* pDoc
, SwSectionFrm
* pSect
, SwFtnFrm
* pFtn
)
330 if( !pDoc
->GetLayouter() )
332 SwLayouter
*pLayouter
= pDoc
->GetLayouter();
333 if( pLayouter
->pEndnoter
&& pLayouter
->pEndnoter
->GetSect() && pSect
&&
334 ( pLayouter
->pEndnoter
->GetSect()->IsAnFollow( pSect
) ||
335 pSect
->IsAnFollow( pLayouter
->pEndnoter
->GetSect() ) ) )
338 pLayouter
->CollectEndnote( pFtn
);
344 BOOL
SwLayouter::StartLoopControl( SwDoc
* pDoc
, SwPageFrm
*pPage
)
346 ASSERT( pDoc
, "No doc, no fun" );
347 if( !pDoc
->GetLayouter() )
348 pDoc
->SetLayouter( new SwLayouter() );
349 return !pDoc
->GetLayouter()->pLooping
&&
350 pDoc
->GetLayouter()->StartLooping( pPage
);
353 // --> OD 2004-06-23 #i28701#
354 // -----------------------------------------------------------------------------
355 // methods to manage text frames, which are moved forward by the positioning
356 // of its anchored objects
357 // -----------------------------------------------------------------------------
358 void SwLayouter::ClearMovedFwdFrms( const SwDoc
& _rDoc
)
360 if ( _rDoc
.GetLayouter() &&
361 _rDoc
.GetLayouter()->mpMovedFwdFrms
)
363 _rDoc
.GetLayouter()->mpMovedFwdFrms
->Clear();
367 void SwLayouter::InsertMovedFwdFrm( const SwDoc
& _rDoc
,
368 const SwTxtFrm
& _rMovedFwdFrmByObjPos
,
369 const sal_uInt32 _nToPageNum
)
371 if ( !_rDoc
.GetLayouter() )
373 const_cast<SwDoc
&>(_rDoc
).SetLayouter( new SwLayouter() );
376 if ( !_rDoc
.GetLayouter()->mpMovedFwdFrms
)
378 const_cast<SwDoc
&>(_rDoc
).GetLayouter()->mpMovedFwdFrms
=
379 new SwMovedFwdFrmsByObjPos();
382 _rDoc
.GetLayouter()->mpMovedFwdFrms
->Insert( _rMovedFwdFrmByObjPos
,
386 // --> OD 2005-01-12 #i40155#
387 void SwLayouter::RemoveMovedFwdFrm( const SwDoc
& _rDoc
,
388 const SwTxtFrm
& _rTxtFrm
)
391 if ( SwLayouter::FrmMovedFwdByObjPos( _rDoc
, _rTxtFrm
, nDummy
) )
393 _rDoc
.GetLayouter()->mpMovedFwdFrms
->Remove( _rTxtFrm
);
398 bool SwLayouter::FrmMovedFwdByObjPos( const SwDoc
& _rDoc
,
399 const SwTxtFrm
& _rTxtFrm
,
400 sal_uInt32
& _ornToPageNum
)
402 if ( !_rDoc
.GetLayouter() )
407 else if ( !_rDoc
.GetLayouter()->mpMovedFwdFrms
)
414 return _rDoc
.GetLayouter()->mpMovedFwdFrms
->
415 FrmMovedFwdByObjPos( _rTxtFrm
, _ornToPageNum
);
419 // --> OD 2004-10-05 #i26945#
420 bool SwLayouter::DoesRowContainMovedFwdFrm( const SwDoc
& _rDoc
,
421 const SwRowFrm
& _rRowFrm
)
423 if ( !_rDoc
.GetLayouter() )
427 else if ( !_rDoc
.GetLayouter()->mpMovedFwdFrms
)
433 return _rDoc
.GetLayouter()->
434 mpMovedFwdFrms
->DoesRowContainMovedFwdFrm( _rRowFrm
);
439 // --> OD 2004-10-22 #i35911#
440 void SwLayouter::ClearObjsTmpConsiderWrapInfluence( const SwDoc
& _rDoc
)
442 if ( _rDoc
.GetLayouter() &&
443 _rDoc
.GetLayouter()->mpObjsTmpConsiderWrapInfl
)
445 _rDoc
.GetLayouter()->mpObjsTmpConsiderWrapInfl
->Clear();
448 void SwLayouter::InsertObjForTmpConsiderWrapInfluence(
450 SwAnchoredObject
& _rAnchoredObj
)
452 if ( !_rDoc
.GetLayouter() )
454 const_cast<SwDoc
&>(_rDoc
).SetLayouter( new SwLayouter() );
457 if ( !_rDoc
.GetLayouter()->mpObjsTmpConsiderWrapInfl
)
459 const_cast<SwDoc
&>(_rDoc
).GetLayouter()->mpObjsTmpConsiderWrapInfl
=
460 new SwObjsMarkedAsTmpConsiderWrapInfluence();
463 _rDoc
.GetLayouter()->mpObjsTmpConsiderWrapInfl
->Insert( _rAnchoredObj
);
466 // --> OD 2005-01-12 #i40155#
467 void SwLayouter::ClearFrmsNotToWrap( const SwDoc
& _rDoc
)
469 if ( _rDoc
.GetLayouter() )
471 const_cast<SwDoc
&>(_rDoc
).GetLayouter()->maFrmsNotToWrap
.clear();
475 void SwLayouter::InsertFrmNotToWrap( const SwDoc
& _rDoc
,
478 if ( !_rDoc
.GetLayouter() )
480 const_cast<SwDoc
&>(_rDoc
).SetLayouter( new SwLayouter() );
483 if ( !SwLayouter::FrmNotToWrap( _rDoc
, _rFrm
) )
485 const_cast<SwDoc
&>(_rDoc
).GetLayouter()->maFrmsNotToWrap
.push_back( &_rFrm
);
489 bool SwLayouter::FrmNotToWrap( const IDocumentLayoutAccess
& _rDLA
,
492 const SwLayouter
* pLayouter
= _rDLA
.GetLayouter();
499 bool bFrmNotToWrap( false );
500 std::vector
< const SwFrm
* >::const_iterator aIter
=
501 pLayouter
->maFrmsNotToWrap
.begin();
502 for ( ; aIter
!= pLayouter
->maFrmsNotToWrap
.end(); ++aIter
)
504 const SwFrm
* pFrm
= *(aIter
);
505 if ( pFrm
== &_rFrm
)
507 bFrmNotToWrap
= true;
511 return bFrmNotToWrap
;
516 void LOOPING_LOUIE_LIGHT( bool bCondition
, const SwTxtFrm
& rTxtFrm
)
520 const SwDoc
& rDoc
= *rTxtFrm
.GetAttrSet()->GetDoc();
521 if ( rDoc
.GetLayouter() )
523 const_cast<SwDoc
&>(rDoc
).GetLayouter()->LoopingLouieLight( rDoc
, rTxtFrm
);
528 // --> OD 2006-05-10 #i65250#
529 bool SwLayouter::MoveBwdSuppressed( const SwDoc
& p_rDoc
,
530 const SwFlowFrm
& p_rFlowFrm
,
531 const SwLayoutFrm
& p_rNewUpperFrm
)
533 bool bMoveBwdSuppressed( false );
535 if ( !p_rDoc
.GetLayouter() )
537 const_cast<SwDoc
&>(p_rDoc
).SetLayouter( new SwLayouter() );
540 // create hash map key
541 tMoveBwdLayoutInfoKey aMoveBwdLayoutInfo
;
542 aMoveBwdLayoutInfo
.mnFrmId
= p_rFlowFrm
.GetFrm()->GetFrmId();
543 aMoveBwdLayoutInfo
.mnNewUpperPosX
= p_rNewUpperFrm
.Frm().Pos().X();
544 aMoveBwdLayoutInfo
.mnNewUpperPosY
= p_rNewUpperFrm
.Frm().Pos().Y();
545 aMoveBwdLayoutInfo
.mnNewUpperWidth
= p_rNewUpperFrm
.Frm().Width();
546 aMoveBwdLayoutInfo
.mnNewUpperHeight
= p_rNewUpperFrm
.Frm().Height();
547 SWRECTFN( (&p_rNewUpperFrm
) )
548 const SwFrm
* pLastLower( p_rNewUpperFrm
.Lower() );
549 while ( pLastLower
&& pLastLower
->GetNext() )
551 pLastLower
= pLastLower
->GetNext();
553 aMoveBwdLayoutInfo
.mnFreeSpaceInNewUpper
=
555 ? (pLastLower
->Frm().*fnRect
->fnBottomDist
)( (p_rNewUpperFrm
.*fnRect
->fnGetPrtBottom
)() )
556 : (p_rNewUpperFrm
.Frm().*fnRect
->fnGetHeight
)();
558 // check for moving backward suppress threshold
559 const sal_uInt16 cMoveBwdCountSuppressThreshold
= 20;
560 if ( ++const_cast<SwDoc
&>(p_rDoc
).GetLayouter()->maMoveBwdLayoutInfo
[ aMoveBwdLayoutInfo
] >
561 cMoveBwdCountSuppressThreshold
)
563 bMoveBwdSuppressed
= true;
566 return bMoveBwdSuppressed
;
569 void SwLayouter::ClearMoveBwdLayoutInfo( const SwDoc
& _rDoc
)
571 if ( _rDoc
.GetLayouter() )
572 const_cast<SwDoc
&>(_rDoc
).GetLayouter()->maMoveBwdLayoutInfo
.clear();