Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "layouter.hxx"
22 : #include "doc.hxx"
23 : #include "sectfrm.hxx"
24 : #include "ftnboss.hxx"
25 : #include "cntfrm.hxx"
26 : #include "pagefrm.hxx"
27 : #include "ftnfrm.hxx"
28 : #include "txtfrm.hxx"
29 :
30 : // #i28701#
31 : #include <movedfwdfrmsbyobjpos.hxx>
32 : // #i35911#
33 : #include <objstmpconsiderwrapinfl.hxx>
34 :
35 : #define LOOP_DETECT 250
36 :
37 : class SwLooping
38 : {
39 : sal_uInt16 nMinPage;
40 : sal_uInt16 nMaxPage;
41 : sal_uInt16 nCount;
42 : sal_uInt16 mnLoopControlStage;
43 : public:
44 : SwLooping( SwPageFrm* pPage );
45 : void Control( SwPageFrm* pPage );
46 : void Drastic( SwFrm* pFrm );
47 0 : bool IsLoopingLouieLight() const { return nCount > LOOP_DETECT - 30; };
48 : };
49 :
50 : class SwEndnoter
51 : {
52 : SwLayouter* pMaster;
53 : SwSectionFrm* pSect;
54 : SwFtnFrms* pEndArr;
55 : public:
56 0 : SwEndnoter( SwLayouter* pLay )
57 0 : : pMaster( pLay ), pSect( NULL ), pEndArr( NULL ) {}
58 0 : ~SwEndnoter() { delete pEndArr; }
59 : void CollectEndnotes( SwSectionFrm* pSct );
60 : void CollectEndnote( SwFtnFrm* pFtn );
61 0 : const SwSectionFrm* GetSect() const { return pSect; }
62 : void InsertEndnotes();
63 0 : bool HasEndnotes() const { return pEndArr && !pEndArr->empty(); }
64 : };
65 :
66 0 : void SwEndnoter::CollectEndnotes( SwSectionFrm* pSct )
67 : {
68 : OSL_ENSURE( pSct, "CollectEndnotes: Which section?" );
69 0 : if( !pSect )
70 0 : pSect = pSct;
71 0 : else if( pSct != pSect )
72 0 : return;
73 0 : pSect->CollectEndnotes( pMaster );
74 : }
75 :
76 0 : void SwEndnoter::CollectEndnote( SwFtnFrm* pFtn )
77 : {
78 0 : if( pEndArr && pEndArr->end() != std::find( pEndArr->begin(), pEndArr->end(), pFtn ) )
79 0 : return;
80 :
81 0 : if( pFtn->GetUpper() )
82 : {
83 : // pFtn is the master, he incorporates its follows
84 0 : SwFtnFrm *pNxt = pFtn->GetFollow();
85 0 : while ( pNxt )
86 : {
87 0 : SwFrm *pCnt = pNxt->ContainsAny();
88 0 : if ( pCnt )
89 : {
90 0 : do
91 0 : { SwFrm *pNxtCnt = pCnt->GetNext();
92 0 : pCnt->Cut();
93 0 : pCnt->Paste( pFtn );
94 0 : pCnt = pNxtCnt;
95 : } while ( pCnt );
96 : }
97 : else
98 : { OSL_ENSURE( pNxt->Lower() && pNxt->Lower()->IsSctFrm(),
99 : "Endnote without content?" );
100 0 : pNxt->Cut();
101 0 : delete pNxt;
102 : }
103 0 : pNxt = pFtn->GetFollow();
104 : }
105 0 : if( pFtn->GetMaster() )
106 0 : return;
107 0 : pFtn->Cut();
108 : }
109 0 : else if( pEndArr )
110 : {
111 0 : for ( sal_uInt16 i = 0; i < pEndArr->size(); ++i )
112 : {
113 0 : SwFtnFrm *pEndFtn = (*pEndArr)[i];
114 0 : if( pEndFtn->GetAttr() == pFtn->GetAttr() )
115 : {
116 0 : delete pFtn;
117 0 : return;
118 : }
119 : }
120 : }
121 0 : if( !pEndArr )
122 0 : pEndArr = new SwFtnFrms; // deleted from the SwLayouter
123 0 : pEndArr->push_back( pFtn );
124 : }
125 :
126 0 : void SwEndnoter::InsertEndnotes()
127 : {
128 0 : if( !pSect )
129 0 : return;
130 0 : if( !pEndArr || pEndArr->empty() )
131 : {
132 0 : pSect = NULL;
133 0 : return;
134 : }
135 : OSL_ENSURE( pSect->Lower() && pSect->Lower()->IsFtnBossFrm(),
136 : "InsertEndnotes: Where's my column?" );
137 0 : SwFrm* pRef = pSect->FindLastCntnt( FINDMODE_MYLAST );
138 : SwFtnBossFrm *pBoss = pRef ? pRef->FindFtnBossFrm()
139 0 : : (SwFtnBossFrm*)pSect->Lower();
140 0 : pBoss->_MoveFtns( *pEndArr );
141 0 : delete pEndArr;
142 0 : pEndArr = NULL;
143 0 : pSect = NULL;
144 : }
145 :
146 896 : SwLooping::SwLooping( SwPageFrm* pPage )
147 : {
148 : OSL_ENSURE( pPage, "Where's my page?" );
149 896 : nMinPage = pPage->GetPhyPageNum();
150 896 : nMaxPage = nMinPage;
151 896 : nCount = 0;
152 896 : mnLoopControlStage = 0;
153 896 : }
154 :
155 0 : void SwLooping::Drastic( SwFrm* pFrm )
156 : {
157 0 : while( pFrm )
158 : {
159 0 : pFrm->ValidateThisAndAllLowers( mnLoopControlStage );
160 0 : pFrm = pFrm->GetNext();
161 : }
162 0 : }
163 :
164 922 : void SwLooping::Control( SwPageFrm* pPage )
165 : {
166 922 : if( !pPage )
167 1294 : return;
168 550 : sal_uInt16 nNew = pPage->GetPhyPageNum();
169 550 : if( nNew > nMaxPage )
170 48 : nMaxPage = nNew;
171 550 : if( nNew < nMinPage )
172 : {
173 0 : nMinPage = nNew;
174 0 : nMaxPage = nNew;
175 0 : nCount = 0;
176 0 : mnLoopControlStage = 0;
177 : }
178 550 : else if( nNew > nMinPage + 2 )
179 : {
180 0 : nMinPage = nNew - 2;
181 0 : nMaxPage = nNew;
182 0 : nCount = 0;
183 0 : mnLoopControlStage = 0;
184 : }
185 550 : else if( ++nCount > LOOP_DETECT )
186 : {
187 : #if OSL_DEBUG_LEVEL > 1
188 : static bool bNoLouie = false;
189 : if( bNoLouie )
190 : return;
191 :
192 : // FME 2007-08-30 #i81146# new loop control
193 : OSL_ENSURE( 0 != mnLoopControlStage, "Looping Louie: Stage 1!" );
194 : OSL_ENSURE( 1 != mnLoopControlStage, "Looping Louie: Stage 2!!" );
195 : OSL_ENSURE( 2 > mnLoopControlStage, "Looping Louie: Stage 3!!!" );
196 : #endif
197 :
198 0 : Drastic( pPage->Lower() );
199 0 : if( nNew > nMinPage && pPage->GetPrev() )
200 0 : Drastic( ((SwPageFrm*)pPage->GetPrev())->Lower() );
201 0 : if( nNew < nMaxPage && pPage->GetNext() )
202 0 : Drastic( ((SwPageFrm*)pPage->GetNext())->Lower() );
203 :
204 0 : ++mnLoopControlStage;
205 0 : nCount = 0;
206 : }
207 : }
208 :
209 : /*************************************************************************
210 : |*
211 : |* SwLayouter::SwLayouter()
212 : |*
213 : |*************************************************************************/
214 :
215 478 : SwLayouter::SwLayouter()
216 : : pEndnoter( NULL ),
217 : pLooping( NULL ),
218 : // #i28701#
219 : mpMovedFwdFrms( 0L ),
220 : // #i35911#
221 478 : mpObjsTmpConsiderWrapInfl( 0L )
222 : {
223 478 : }
224 :
225 144 : SwLayouter::~SwLayouter()
226 : {
227 72 : delete pEndnoter;
228 72 : delete pLooping;
229 : // #i28701#
230 72 : delete mpMovedFwdFrms;
231 72 : mpMovedFwdFrms = 0L;
232 : // #i35911#
233 72 : delete mpObjsTmpConsiderWrapInfl;
234 72 : mpObjsTmpConsiderWrapInfl = 0L;
235 72 : }
236 :
237 0 : void SwLayouter::_CollectEndnotes( SwSectionFrm* pSect )
238 : {
239 0 : if( !pEndnoter )
240 0 : pEndnoter = new SwEndnoter( this );
241 0 : pEndnoter->CollectEndnotes( pSect );
242 0 : }
243 :
244 0 : bool SwLayouter::HasEndnotes() const
245 : {
246 0 : return pEndnoter->HasEndnotes();
247 : }
248 :
249 0 : void SwLayouter::CollectEndnote( SwFtnFrm* pFtn )
250 : {
251 0 : pEndnoter->CollectEndnote( pFtn );
252 0 : }
253 :
254 0 : void SwLayouter::InsertEndnotes( SwSectionFrm* pSect )
255 : {
256 0 : if( !pEndnoter || pEndnoter->GetSect() != pSect )
257 0 : return;
258 0 : pEndnoter->InsertEndnotes();
259 : }
260 :
261 922 : void SwLayouter::LoopControl( SwPageFrm* pPage, sal_uInt8 )
262 : {
263 : OSL_ENSURE( pLooping, "Looping: Lost control" );
264 922 : pLooping->Control( pPage );
265 922 : }
266 :
267 0 : void SwLayouter::LoopingLouieLight( const SwDoc& rDoc, const SwTxtFrm& rFrm )
268 : {
269 0 : if ( pLooping && pLooping->IsLoopingLouieLight() )
270 : {
271 : #if OSL_DEBUG_LEVEL > 1
272 : OSL_FAIL( "Looping Louie (Light): Fixating fractious frame" );
273 : #endif
274 0 : SwLayouter::InsertMovedFwdFrm( rDoc, rFrm, rFrm.FindPageFrm()->GetPhyPageNum() );
275 : }
276 0 : }
277 :
278 896 : sal_Bool SwLayouter::StartLooping( SwPageFrm* pPage )
279 : {
280 896 : if( pLooping )
281 0 : return sal_False;
282 896 : pLooping = new SwLooping( pPage );
283 896 : return sal_True;
284 : }
285 :
286 896 : void SwLayouter::EndLoopControl()
287 : {
288 896 : delete pLooping;
289 896 : pLooping = NULL;
290 896 : }
291 :
292 0 : void SwLayouter::CollectEndnotes( SwDoc* pDoc, SwSectionFrm* pSect )
293 : {
294 : OSL_ENSURE( pDoc, "No doc, no fun" );
295 0 : if( !pDoc->GetLayouter() )
296 0 : pDoc->SetLayouter( new SwLayouter() );
297 0 : pDoc->GetLayouter()->_CollectEndnotes( pSect );
298 0 : }
299 :
300 0 : sal_Bool SwLayouter::Collecting( SwDoc* pDoc, SwSectionFrm* pSect, SwFtnFrm* pFtn )
301 : {
302 0 : if( !pDoc->GetLayouter() )
303 0 : return sal_False;
304 0 : SwLayouter *pLayouter = pDoc->GetLayouter();
305 0 : if( pLayouter->pEndnoter && pLayouter->pEndnoter->GetSect() && pSect &&
306 0 : ( pLayouter->pEndnoter->GetSect()->IsAnFollow( pSect ) ||
307 0 : pSect->IsAnFollow( pLayouter->pEndnoter->GetSect() ) ) )
308 : {
309 0 : if( pFtn )
310 0 : pLayouter->CollectEndnote( pFtn );
311 0 : return sal_True;
312 : }
313 0 : return sal_False;
314 : }
315 :
316 896 : sal_Bool SwLayouter::StartLoopControl( SwDoc* pDoc, SwPageFrm *pPage )
317 : {
318 : OSL_ENSURE( pDoc, "No doc, no fun" );
319 896 : if( !pDoc->GetLayouter() )
320 478 : pDoc->SetLayouter( new SwLayouter() );
321 896 : return !pDoc->GetLayouter()->pLooping &&
322 896 : pDoc->GetLayouter()->StartLooping( pPage );
323 : }
324 :
325 : // #i28701#
326 : // -----------------------------------------------------------------------------
327 : // methods to manage text frames, which are moved forward by the positioning
328 : // of its anchored objects
329 : // -----------------------------------------------------------------------------
330 161593 : void SwLayouter::ClearMovedFwdFrms( const SwDoc& _rDoc )
331 : {
332 161831 : if ( _rDoc.GetLayouter() &&
333 238 : _rDoc.GetLayouter()->mpMovedFwdFrms )
334 : {
335 0 : _rDoc.GetLayouter()->mpMovedFwdFrms->Clear();
336 : }
337 161593 : }
338 :
339 0 : void SwLayouter::InsertMovedFwdFrm( const SwDoc& _rDoc,
340 : const SwTxtFrm& _rMovedFwdFrmByObjPos,
341 : const sal_uInt32 _nToPageNum )
342 : {
343 0 : if ( !_rDoc.GetLayouter() )
344 : {
345 0 : const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
346 : }
347 :
348 0 : if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
349 : {
350 0 : const_cast<SwDoc&>(_rDoc).GetLayouter()->mpMovedFwdFrms =
351 0 : new SwMovedFwdFrmsByObjPos();
352 : }
353 :
354 0 : _rDoc.GetLayouter()->mpMovedFwdFrms->Insert( _rMovedFwdFrmByObjPos,
355 0 : _nToPageNum );
356 0 : }
357 :
358 : // #i40155#
359 0 : void SwLayouter::RemoveMovedFwdFrm( const SwDoc& _rDoc,
360 : const SwTxtFrm& _rTxtFrm )
361 : {
362 : sal_uInt32 nDummy;
363 0 : if ( SwLayouter::FrmMovedFwdByObjPos( _rDoc, _rTxtFrm, nDummy ) )
364 : {
365 0 : _rDoc.GetLayouter()->mpMovedFwdFrms->Remove( _rTxtFrm );
366 : }
367 0 : }
368 :
369 2307 : bool SwLayouter::FrmMovedFwdByObjPos( const SwDoc& _rDoc,
370 : const SwTxtFrm& _rTxtFrm,
371 : sal_uInt32& _ornToPageNum )
372 : {
373 2307 : if ( !_rDoc.GetLayouter() )
374 : {
375 464 : _ornToPageNum = 0;
376 464 : return false;
377 : }
378 1843 : else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
379 : {
380 1843 : _ornToPageNum = 0;
381 1843 : return false;
382 : }
383 : else
384 : {
385 0 : return _rDoc.GetLayouter()->mpMovedFwdFrms->
386 0 : FrmMovedFwdByObjPos( _rTxtFrm, _ornToPageNum );
387 : }
388 : }
389 : // #i26945#
390 0 : bool SwLayouter::DoesRowContainMovedFwdFrm( const SwDoc& _rDoc,
391 : const SwRowFrm& _rRowFrm )
392 : {
393 0 : if ( !_rDoc.GetLayouter() )
394 : {
395 0 : return false;
396 : }
397 0 : else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
398 : {
399 0 : return false;
400 : }
401 : else
402 : {
403 0 : return _rDoc.GetLayouter()->
404 0 : mpMovedFwdFrms->DoesRowContainMovedFwdFrm( _rRowFrm );
405 : }
406 : }
407 :
408 : // #i35911#
409 161593 : void SwLayouter::ClearObjsTmpConsiderWrapInfluence( const SwDoc& _rDoc )
410 : {
411 161831 : if ( _rDoc.GetLayouter() &&
412 238 : _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
413 : {
414 0 : _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Clear();
415 : }
416 161593 : }
417 0 : void SwLayouter::InsertObjForTmpConsiderWrapInfluence(
418 : const SwDoc& _rDoc,
419 : SwAnchoredObject& _rAnchoredObj )
420 : {
421 0 : if ( !_rDoc.GetLayouter() )
422 : {
423 0 : const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
424 : }
425 :
426 0 : if ( !_rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
427 : {
428 0 : const_cast<SwDoc&>(_rDoc).GetLayouter()->mpObjsTmpConsiderWrapInfl =
429 0 : new SwObjsMarkedAsTmpConsiderWrapInfluence();
430 : }
431 :
432 0 : _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Insert( _rAnchoredObj );
433 0 : }
434 :
435 2301 : void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTxtFrm& rTxtFrm )
436 : {
437 2301 : if ( bCondition )
438 : {
439 0 : const SwDoc& rDoc = *rTxtFrm.GetAttrSet()->GetDoc();
440 0 : if ( rDoc.GetLayouter() )
441 : {
442 0 : const_cast<SwDoc&>(rDoc).GetLayouter()->LoopingLouieLight( rDoc, rTxtFrm );
443 : }
444 : }
445 2301 : }
446 :
447 : // #i65250#
448 2 : bool SwLayouter::MoveBwdSuppressed( const SwDoc& p_rDoc,
449 : const SwFlowFrm& p_rFlowFrm,
450 : const SwLayoutFrm& p_rNewUpperFrm )
451 : {
452 2 : bool bMoveBwdSuppressed( false );
453 :
454 2 : if ( !p_rDoc.GetLayouter() )
455 : {
456 0 : const_cast<SwDoc&>(p_rDoc).SetLayouter( new SwLayouter() );
457 : }
458 :
459 : // create hash map key
460 : tMoveBwdLayoutInfoKey aMoveBwdLayoutInfo;
461 2 : aMoveBwdLayoutInfo.mnFrmId = p_rFlowFrm.GetFrm()->GetFrmId();
462 2 : aMoveBwdLayoutInfo.mnNewUpperPosX = p_rNewUpperFrm.Frm().Pos().X();
463 2 : aMoveBwdLayoutInfo.mnNewUpperPosY = p_rNewUpperFrm.Frm().Pos().Y();
464 2 : aMoveBwdLayoutInfo.mnNewUpperWidth = p_rNewUpperFrm.Frm().Width();
465 2 : aMoveBwdLayoutInfo.mnNewUpperHeight = p_rNewUpperFrm.Frm().Height();
466 2 : SWRECTFN( (&p_rNewUpperFrm) )
467 2 : const SwFrm* pLastLower( p_rNewUpperFrm.Lower() );
468 53 : while ( pLastLower && pLastLower->GetNext() )
469 : {
470 49 : pLastLower = pLastLower->GetNext();
471 : }
472 : aMoveBwdLayoutInfo.mnFreeSpaceInNewUpper =
473 : pLastLower
474 2 : ? (pLastLower->Frm().*fnRect->fnBottomDist)( (p_rNewUpperFrm.*fnRect->fnGetPrtBottom)() )
475 4 : : (p_rNewUpperFrm.Frm().*fnRect->fnGetHeight)();
476 :
477 : // check for moving backward suppress threshold
478 2 : const sal_uInt16 cMoveBwdCountSuppressThreshold = 20;
479 2 : if ( ++const_cast<SwDoc&>(p_rDoc).GetLayouter()->maMoveBwdLayoutInfo[ aMoveBwdLayoutInfo ] >
480 : cMoveBwdCountSuppressThreshold )
481 : {
482 0 : bMoveBwdSuppressed = true;
483 : }
484 :
485 2 : return bMoveBwdSuppressed;
486 : }
487 :
488 161593 : void SwLayouter::ClearMoveBwdLayoutInfo( const SwDoc& _rDoc )
489 : {
490 161593 : if ( _rDoc.GetLayouter() )
491 238 : const_cast<SwDoc&>(_rDoc).GetLayouter()->maMoveBwdLayoutInfo.clear();
492 161593 : }
493 :
494 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|