svx: prefix members of SvxClipboardFormatItem
[LibreOffice.git] / sw / source / core / layout / layouter.cxx
blob29c333ef5fb81f663189aa1a96be95628ba9d623
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <memory>
21 #include <layouter.hxx>
22 #include <doc.hxx>
23 #include <sectfrm.hxx>
24 #include <pagefrm.hxx>
25 #include <ftnfrm.hxx>
26 #include <txtfrm.hxx>
27 #include <IDocumentLayoutAccess.hxx>
29 #include <movedfwdfrmsbyobjpos.hxx>
30 #include "objstmpconsiderwrapinfl.hxx"
31 #include <osl/diagnose.h>
33 #define LOOP_DETECT 250
35 class SwLooping
37 sal_uInt16 mnMinPage;
38 sal_uInt16 mnMaxPage;
39 sal_uInt16 mnCount;
40 sal_uInt16 mnLoopControlStage;
41 public:
42 explicit SwLooping( SwPageFrame const * pPage );
43 void Control( SwPageFrame* pPage );
44 void Drastic( SwFrame* pFrame );
45 bool IsLoopingLouieLight() const { return mnCount > LOOP_DETECT - 30; };
48 class SwEndnoter
50 SwLayouter* m_pMaster;
51 SwSectionFrame* m_pSect;
52 std::unique_ptr<SwFootnoteFrames> m_pEndArr;
53 public:
54 explicit SwEndnoter( SwLayouter* pLay )
55 : m_pMaster( pLay ), m_pSect( nullptr ) {}
56 void CollectEndnotes( SwSectionFrame* pSct );
57 void CollectEndnote( SwFootnoteFrame* pFootnote );
58 const SwSectionFrame* GetSect() const { return m_pSect; }
59 void InsertEndnotes();
60 bool HasEndnotes() const { return m_pEndArr && !m_pEndArr->empty(); }
63 void SwEndnoter::CollectEndnotes( SwSectionFrame* pSct )
65 OSL_ENSURE( pSct, "CollectEndnotes: Which section?" );
66 if( !m_pSect )
67 m_pSect = pSct;
68 else if( pSct != m_pSect )
69 return;
70 m_pSect->CollectEndnotes( m_pMaster );
73 void SwEndnoter::CollectEndnote( SwFootnoteFrame* pFootnote )
75 if( m_pEndArr && m_pEndArr->end() != std::find( m_pEndArr->begin(), m_pEndArr->end(), pFootnote ) )
76 return;
78 if( pFootnote->GetUpper() )
80 // pFootnote is the master, he incorporates its follows
81 SwFootnoteFrame *pNxt = pFootnote->GetFollow();
82 while ( pNxt )
84 SwFrame *pCnt = pNxt->ContainsAny();
85 if ( pCnt )
88 { SwFrame *pNxtCnt = pCnt->GetNext();
89 pCnt->Cut();
90 pCnt->Paste( pFootnote );
91 pCnt = pNxtCnt;
92 } while ( pCnt );
94 else
96 #ifdef DBG_UTIL
97 SwFrame* pLower = pNxt->Lower();
98 OSL_ENSURE( pLower && pLower->IsSctFrame(),
99 "Endnote without content?" );
100 #endif
101 pNxt->Cut();
102 SwFrame::DestroyFrame(pNxt);
104 pNxt = pFootnote->GetFollow();
106 if( pFootnote->GetMaster() )
107 return;
108 pFootnote->Cut();
110 else if( m_pEndArr )
112 for (SwFootnoteFrame* pEndFootnote : *m_pEndArr)
114 if( pEndFootnote->GetAttr() == pFootnote->GetAttr() )
116 SwFrame::DestroyFrame(pFootnote);
117 return;
121 if( !m_pEndArr )
122 m_pEndArr.reset( new SwFootnoteFrames ); // deleted from the SwLayouter
123 m_pEndArr->push_back( pFootnote );
126 void SwEndnoter::InsertEndnotes()
128 if( !m_pSect )
129 return;
130 if( !m_pEndArr || m_pEndArr->empty() )
132 m_pSect = nullptr;
133 return;
135 SwFrame* pLower = m_pSect->Lower();
136 OSL_ENSURE( pLower && pLower->IsFootnoteBossFrame(),
137 "InsertEndnotes: Where's my column?" );
138 SwFrame* pRef = m_pSect->FindLastContent( SwFindMode::MyLast );
139 SwFootnoteBossFrame *pBoss = pRef ? pRef->FindFootnoteBossFrame()
140 : static_cast<SwFootnoteBossFrame*>(pLower);
141 pBoss->MoveFootnotes_( *m_pEndArr );
142 m_pEndArr.reset();
143 m_pSect = nullptr;
146 SwLooping::SwLooping( SwPageFrame const * pPage )
148 assert(pPage);
149 mnMinPage = pPage->GetPhyPageNum();
150 mnMaxPage = mnMinPage;
151 mnCount = 0;
152 mnLoopControlStage = 0;
155 void SwLooping::Drastic( SwFrame* pFrame )
157 while( pFrame )
159 pFrame->ValidateThisAndAllLowers( mnLoopControlStage );
160 pFrame = pFrame->GetNext();
164 void SwLooping::Control( SwPageFrame* pPage )
166 if( !pPage )
167 return;
168 const sal_uInt16 nNew = pPage->GetPhyPageNum();
169 if (nNew > mnMaxPage)
170 mnMaxPage = nNew;
171 if (nNew < mnMinPage)
173 mnMinPage = nNew;
174 mnMaxPage = nNew;
175 mnCount = 0;
176 mnLoopControlStage = 0;
178 else if (nNew > mnMinPage + 2)
180 mnMinPage = nNew - 2;
181 mnMaxPage = nNew;
182 mnCount = 0;
183 mnLoopControlStage = 0;
185 else if (++mnCount > LOOP_DETECT)
187 #if OSL_DEBUG_LEVEL > 1
188 static bool bNoLouie = false;
189 if( bNoLouie )
190 return;
191 #endif
193 // FME 2007-08-30 #i81146# new loop control
194 SAL_WARN("sw.layout", "Looping Louie: Stage " << (mnLoopControlStage + 1) << "!");
196 Drastic( pPage->Lower() );
197 if (nNew > mnMinPage && pPage->GetPrev())
198 Drastic( static_cast<SwPageFrame*>(pPage->GetPrev())->Lower() );
199 if (nNew < mnMaxPage && pPage->GetNext())
200 Drastic( static_cast<SwPageFrame*>(pPage->GetNext())->Lower() );
202 ++mnLoopControlStage;
203 mnCount = 0;
207 SwLayouter::SwLayouter()
211 SwLayouter::~SwLayouter()
215 void SwLayouter::CollectEndnotes_( SwSectionFrame* pSect )
217 if( !mpEndnoter )
218 mpEndnoter.reset(new SwEndnoter( this ));
219 mpEndnoter->CollectEndnotes( pSect );
222 bool SwLayouter::HasEndnotes() const
224 return mpEndnoter->HasEndnotes();
227 void SwLayouter::CollectEndnote( SwFootnoteFrame* pFootnote )
229 mpEndnoter->CollectEndnote( pFootnote );
232 void SwLayouter::InsertEndnotes( SwSectionFrame const * pSect )
234 if( !mpEndnoter || mpEndnoter->GetSect() != pSect )
235 return;
236 mpEndnoter->InsertEndnotes();
239 void SwLayouter::LoopControl( SwPageFrame* pPage )
241 assert(mpLooping);
242 mpLooping->Control( pPage );
245 void SwLayouter::LoopingLouieLight( const SwDoc& rDoc, const SwTextFrame& rFrame )
247 if ( mpLooping && mpLooping->IsLoopingLouieLight() )
249 SAL_WARN("sw.layout", "Looping Louie (Light): Fixating fractious frame");
250 SwLayouter::InsertMovedFwdFrame( rDoc, rFrame, rFrame.FindPageFrame()->GetPhyPageNum() );
254 bool SwLayouter::StartLooping( SwPageFrame const * pPage )
256 if( mpLooping )
257 return false;
258 mpLooping.reset(new SwLooping( pPage ));
259 return true;
262 void SwLayouter::EndLoopControl()
264 mpLooping.reset();
267 void SwLayouter::CollectEndnotes( SwDoc* pDoc, SwSectionFrame* pSect )
269 assert(pDoc && "No doc, no fun");
270 if( !pDoc->getIDocumentLayoutAccess().GetLayouter() )
271 pDoc->getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
272 pDoc->getIDocumentLayoutAccess().GetLayouter()->CollectEndnotes_( pSect );
275 bool SwLayouter::Collecting( SwDoc* pDoc, SwSectionFrame const * pSect, SwFootnoteFrame* pFootnote )
277 if( !pDoc->getIDocumentLayoutAccess().GetLayouter() )
278 return false;
279 SwLayouter *pLayouter = pDoc->getIDocumentLayoutAccess().GetLayouter();
280 if( pLayouter->mpEndnoter && pLayouter->mpEndnoter->GetSect() && pSect &&
281 ( pLayouter->mpEndnoter->GetSect()->IsAnFollow( pSect ) ||
282 pSect->IsAnFollow( pLayouter->mpEndnoter->GetSect() ) ) )
284 if( pFootnote )
285 pLayouter->CollectEndnote( pFootnote );
286 return true;
288 return false;
291 bool SwLayouter::StartLoopControl( SwDoc* pDoc, SwPageFrame const *pPage )
293 assert(pDoc);
294 if( !pDoc->getIDocumentLayoutAccess().GetLayouter() )
295 pDoc->getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
296 return !pDoc->getIDocumentLayoutAccess().GetLayouter()->mpLooping &&
297 pDoc->getIDocumentLayoutAccess().GetLayouter()->StartLooping( pPage );
300 // #i28701#
301 // methods to manage text frames, which are moved forward by the positioning
302 // of its anchored objects
303 void SwLayouter::ClearMovedFwdFrames( const SwDoc& _rDoc )
305 if ( _rDoc.getIDocumentLayoutAccess().GetLayouter() &&
306 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames )
308 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames->Clear();
312 void SwLayouter::InsertMovedFwdFrame( const SwDoc& _rDoc,
313 const SwTextFrame& _rMovedFwdFrameByObjPos,
314 const sal_uInt32 _nToPageNum )
316 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
318 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
321 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames )
323 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames.reset(
324 new SwMovedFwdFramesByObjPos());
327 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames->Insert( _rMovedFwdFrameByObjPos,
328 _nToPageNum );
331 // #i40155#
332 void SwLayouter::RemoveMovedFwdFrame( const SwDoc& _rDoc,
333 const SwTextFrame& _rTextFrame )
335 sal_uInt32 nDummy;
336 if ( SwLayouter::FrameMovedFwdByObjPos( _rDoc, _rTextFrame, nDummy ) )
338 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames->Remove( _rTextFrame );
342 bool SwLayouter::FrameMovedFwdByObjPos( const SwDoc& _rDoc,
343 const SwTextFrame& _rTextFrame,
344 sal_uInt32& _ornToPageNum )
346 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
348 _ornToPageNum = 0;
349 return false;
351 else if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames )
353 _ornToPageNum = 0;
354 return false;
356 else
358 return _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames->
359 FrameMovedFwdByObjPos( _rTextFrame, _ornToPageNum );
363 // #i26945#
364 bool SwLayouter::DoesRowContainMovedFwdFrame( const SwDoc& _rDoc,
365 const SwRowFrame& _rRowFrame )
367 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
369 return false;
371 else if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter()->mpMovedFwdFrames )
373 return false;
375 else
377 return _rDoc.getIDocumentLayoutAccess().GetLayouter()->
378 mpMovedFwdFrames->DoesRowContainMovedFwdFrame( _rRowFrame );
382 // #i35911#
383 void SwLayouter::ClearObjsTmpConsiderWrapInfluence( const SwDoc& _rDoc )
385 if ( _rDoc.getIDocumentLayoutAccess().GetLayouter() &&
386 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl )
388 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl->Clear();
392 void SwLayouter::InsertObjForTmpConsiderWrapInfluence(
393 const SwDoc& _rDoc,
394 SwAnchoredObject& _rAnchoredObj )
396 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
398 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
401 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl )
403 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl.reset(
404 new SwObjsMarkedAsTmpConsiderWrapInfluence());
407 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl->Insert( _rAnchoredObj );
410 void SwLayouter::RemoveObjForTmpConsiderWrapInfluence(
411 const SwDoc& _rDoc,
412 SwAnchoredObject& _rAnchoredObj )
414 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter() )
415 return;
417 if ( !_rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl )
418 return;
420 _rDoc.getIDocumentLayoutAccess().GetLayouter()->mpObjsTmpConsiderWrapInfl->Remove( _rAnchoredObj );
424 void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTextFrame& rTextFrame )
426 if ( bCondition )
428 const SwDoc& rDoc = *rTextFrame.GetAttrSet()->GetDoc();
429 if ( rDoc.getIDocumentLayoutAccess().GetLayouter() )
431 const_cast<SwDoc&>(rDoc).getIDocumentLayoutAccess().GetLayouter()->LoopingLouieLight( rDoc, rTextFrame );
436 // #i65250#
437 bool SwLayouter::MoveBwdSuppressed( const SwDoc& p_rDoc,
438 const SwFlowFrame& p_rFlowFrame,
439 const SwLayoutFrame& p_rNewUpperFrame )
441 bool bMoveBwdSuppressed( false );
443 if ( !p_rDoc.getIDocumentLayoutAccess().GetLayouter() )
445 const_cast<SwDoc&>(p_rDoc).getIDocumentLayoutAccess().SetLayouter( new SwLayouter() );
448 // create hash map key
449 tMoveBwdLayoutInfoKey aMoveBwdLayoutInfo;
450 aMoveBwdLayoutInfo.mnFrameId = p_rFlowFrame.GetFrame().GetFrameId();
451 aMoveBwdLayoutInfo.mnNewUpperPosX = p_rNewUpperFrame.getFrameArea().Pos().X();
452 aMoveBwdLayoutInfo.mnNewUpperPosY = p_rNewUpperFrame.getFrameArea().Pos().Y();
453 aMoveBwdLayoutInfo.mnNewUpperWidth = p_rNewUpperFrame.getFrameArea().Width();
454 aMoveBwdLayoutInfo.mnNewUpperHeight = p_rNewUpperFrame.getFrameArea().Height();
455 SwRectFnSet aRectFnSet(&p_rNewUpperFrame);
456 const SwFrame* pLastLower( p_rNewUpperFrame.Lower() );
457 while ( pLastLower && pLastLower->GetNext() )
459 pLastLower = pLastLower->GetNext();
461 aMoveBwdLayoutInfo.mnFreeSpaceInNewUpper =
462 pLastLower
463 ? aRectFnSet.BottomDist( pLastLower->getFrameArea(), aRectFnSet.GetPrtBottom(p_rNewUpperFrame) )
464 : aRectFnSet.GetHeight(p_rNewUpperFrame.getFrameArea());
466 // check for moving backward suppress threshold
467 const sal_uInt16 cMoveBwdCountSuppressThreshold = 20;
468 if ( ++const_cast<SwDoc&>(p_rDoc).getIDocumentLayoutAccess().GetLayouter()->maMoveBwdLayoutInfo[ aMoveBwdLayoutInfo ] >
469 cMoveBwdCountSuppressThreshold )
471 bMoveBwdSuppressed = true;
474 return bMoveBwdSuppressed;
477 void SwLayouter::ClearMoveBwdLayoutInfo( const SwDoc& _rDoc )
479 if ( _rDoc.getIDocumentLayoutAccess().GetLayouter() )
480 const_cast<SwDoc&>(_rDoc).getIDocumentLayoutAccess().GetLayouter()->maMoveBwdLayoutInfo.clear();
483 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */