merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / layout / layouter.cxx
blobea3d8bfd91653f52bb871acdda50d55fa22dd928
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: layouter.cxx,v $
10 * $Revision: 1.17 $
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"
37 #include "doc.hxx"
38 #include "sectfrm.hxx"
39 #include "ftnboss.hxx"
40 #include "cntfrm.hxx"
41 #include "pagefrm.hxx"
42 #include "ftnfrm.hxx"
43 #include "txtfrm.hxx"
45 // --> OD 2004-06-23 #i28701#
46 #include <movedfwdfrmsbyobjpos.hxx>
47 // <--
48 // --> OD 2004-10-22 #i35911#
49 #include <objstmpconsiderwrapinfl.hxx>
50 // <--
52 #define LOOP_DETECT 250
54 class SwLooping
56 USHORT nMinPage;
57 USHORT nMaxPage;
58 USHORT nCount;
59 USHORT mnLoopControlStage;
60 public:
61 SwLooping( SwPageFrm* pPage );
62 void Control( SwPageFrm* pPage );
63 void Drastic( SwFrm* pFrm );
64 bool IsLoopingLouieLight() const { return nCount > LOOP_DETECT - 30; };
67 class SwEndnoter
69 SwLayouter* pMaster;
70 SwSectionFrm* pSect;
71 SvPtrarr* pEndArr;
72 public:
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?" );
86 if( !pSect )
87 pSect = pSct;
88 else if( pSct != pSect )
89 return;
90 pSect->CollectEndnotes( pMaster );
93 void SwEndnoter::CollectEndnote( SwFtnFrm* pFtn )
95 if( pEndArr && USHRT_MAX != pEndArr->GetPos( (VoidPtr)pFtn ) )
96 return;
98 if( pFtn->GetUpper() )
100 // pFtn is the master, he incorporates its follows
101 SwFtnFrm *pNxt = pFtn->GetFollow();
102 while ( pNxt )
104 SwFrm *pCnt = pNxt->ContainsAny();
105 if ( pCnt )
108 { SwFrm *pNxtCnt = pCnt->GetNext();
109 pCnt->Cut();
110 pCnt->Paste( pFtn );
111 pCnt = pNxtCnt;
112 } while ( pCnt );
114 else
115 { ASSERT( pNxt->Lower() && pNxt->Lower()->IsSctFrm(),
116 "Endnote without content?" );
117 pNxt->Cut();
118 delete pNxt;
120 pNxt = pFtn->GetFollow();
122 if( pFtn->GetMaster() )
123 return;
124 pFtn->Cut();
126 else if( pEndArr )
128 for ( USHORT i = 0; i < pEndArr->Count(); ++i )
130 SwFtnFrm *pEndFtn = (SwFtnFrm*)((*pEndArr)[i]);
131 if( pEndFtn->GetAttr() == pFtn->GetAttr() )
133 delete pFtn;
134 return;
138 if( !pEndArr )
139 pEndArr = new SvPtrarr( 5, 5 ); // deleted from the SwLayouter
140 pEndArr->Insert( (VoidPtr)pFtn, pEndArr->Count() );
143 void SwEndnoter::InsertEndnotes()
145 if( !pSect )
146 return;
147 if( !pEndArr || !pEndArr->Count() )
149 pSect = NULL;
150 return;
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 );
158 delete pEndArr;
159 pEndArr = NULL;
160 pSect = NULL;
163 SwLooping::SwLooping( SwPageFrm* pPage )
165 ASSERT( pPage, "Where's my page?" );
166 nMinPage = pPage->GetPhyPageNum();
167 nMaxPage = nMinPage;
168 nCount = 0;
169 mnLoopControlStage = 0;
172 void SwLooping::Drastic( SwFrm* pFrm )
174 while( pFrm )
176 pFrm->ValidateThisAndAllLowers( mnLoopControlStage );
177 pFrm = pFrm->GetNext();
181 void SwLooping::Control( SwPageFrm* pPage )
183 if( !pPage )
184 return;
185 USHORT nNew = pPage->GetPhyPageNum();
186 if( nNew > nMaxPage )
187 nMaxPage = nNew;
188 if( nNew < nMinPage )
190 nMinPage = nNew;
191 nMaxPage = nNew;
192 nCount = 0;
193 mnLoopControlStage = 0;
195 else if( nNew > nMinPage + 2 )
197 nMinPage = nNew - 2;
198 nMaxPage = nNew;
199 nCount = 0;
200 mnLoopControlStage = 0;
202 else if( ++nCount > LOOP_DETECT )
204 #ifndef PRODUCT
205 #if OSL_DEBUG_LEVEL > 1
206 static BOOL bNoLouie = FALSE;
207 if( bNoLouie )
208 return;
209 #endif
210 #endif
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!!!" );
217 #endif
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;
226 nCount = 0;
230 /*************************************************************************
232 |* SwLayouter::SwLayouter()
234 |* Ersterstellung AMA 02. Nov. 99
235 |* Letzte Aenderung AMA 02. Nov. 99
237 |*************************************************************************/
239 SwLayouter::SwLayouter()
240 : pEndnoter( NULL ),
241 pLooping( NULL ),
242 // --> OD 2004-06-23 #i28701#
243 mpMovedFwdFrms( 0L ),
244 // <--
245 // --> OD 2004-10-22 #i35911#
246 mpObjsTmpConsiderWrapInfl( 0L )
247 // <--
251 SwLayouter::~SwLayouter()
253 delete pEndnoter;
254 delete pLooping;
255 // --> OD 2004-06-23 #i28701#
256 delete mpMovedFwdFrms;
257 mpMovedFwdFrms = 0L;
258 // <--
259 // --> OD 2004-10-22 #i35911#
260 delete mpObjsTmpConsiderWrapInfl;
261 mpObjsTmpConsiderWrapInfl = 0L;
262 // <--
265 void SwLayouter::_CollectEndnotes( SwSectionFrm* pSect )
267 if( !pEndnoter )
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 )
285 return;
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" )
301 #endif
302 SwLayouter::InsertMovedFwdFrm( rDoc, rFrm, rFrm.FindPageFrm()->GetPhyPageNum() );
306 BOOL SwLayouter::StartLooping( SwPageFrm* pPage )
308 if( pLooping )
309 return FALSE;
310 pLooping = new SwLooping( pPage );
311 return TRUE;
314 void SwLayouter::EndLoopControl()
316 delete pLooping;
317 pLooping = NULL;
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() )
331 return FALSE;
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() ) ) )
337 if( pFtn )
338 pLayouter->CollectEndnote( pFtn );
339 return TRUE;
341 return FALSE;
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,
383 _nToPageNum );
386 // --> OD 2005-01-12 #i40155#
387 void SwLayouter::RemoveMovedFwdFrm( const SwDoc& _rDoc,
388 const SwTxtFrm& _rTxtFrm )
390 sal_uInt32 nDummy;
391 if ( SwLayouter::FrmMovedFwdByObjPos( _rDoc, _rTxtFrm, nDummy ) )
393 _rDoc.GetLayouter()->mpMovedFwdFrms->Remove( _rTxtFrm );
396 // <--
398 bool SwLayouter::FrmMovedFwdByObjPos( const SwDoc& _rDoc,
399 const SwTxtFrm& _rTxtFrm,
400 sal_uInt32& _ornToPageNum )
402 if ( !_rDoc.GetLayouter() )
404 _ornToPageNum = 0;
405 return false;
407 else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
409 _ornToPageNum = 0;
410 return false;
412 else
414 return _rDoc.GetLayouter()->mpMovedFwdFrms->
415 FrmMovedFwdByObjPos( _rTxtFrm, _ornToPageNum );
418 // <--
419 // --> OD 2004-10-05 #i26945#
420 bool SwLayouter::DoesRowContainMovedFwdFrm( const SwDoc& _rDoc,
421 const SwRowFrm& _rRowFrm )
423 if ( !_rDoc.GetLayouter() )
425 return false;
427 else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
429 return false;
431 else
433 return _rDoc.GetLayouter()->
434 mpMovedFwdFrms->DoesRowContainMovedFwdFrm( _rRowFrm );
437 // <--
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(
449 const SwDoc& _rDoc,
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 );
465 // <--
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,
476 const SwFrm& _rFrm )
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,
490 const SwFrm& _rFrm )
492 const SwLayouter* pLayouter = _rDLA.GetLayouter();
493 if ( !pLayouter )
495 return false;
497 else
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;
508 break;
511 return bFrmNotToWrap;
514 // <--
516 void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTxtFrm& rTxtFrm )
518 if ( bCondition )
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 =
554 pLastLower
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();
574 // <--