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