LibreOffice Module sw (master)  1
flowfrm.cxx
Go to the documentation of this file.
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 <memory>
21 #include <sal/config.h>
22 #include <sal/log.hxx>
23 #include <osl/diagnose.h>
24 #include <svx/svdobj.hxx>
25 
26 #include <anchoredobject.hxx>
27 #include <bodyfrm.hxx>
28 #include <swtable.hxx>
29 #include <rootfrm.hxx>
30 #include <pagefrm.hxx>
31 #include <viewimp.hxx>
32 #include <viewopt.hxx>
33 #include <frmatr.hxx>
34 #include <frmtool.hxx>
37 #include <editeng/keepitem.hxx>
38 #include <fmtanchr.hxx>
39 #include <fmtsrnd.hxx>
40 #include <fmtpdsc.hxx>
41 #include <editeng/ulspitem.hxx>
42 #include <tgrditem.hxx>
43 #include <txtftn.hxx>
44 #include <fmtftn.hxx>
45 #include <editeng/pgrditem.hxx>
46 #include <paratr.hxx>
47 #include <ftnfrm.hxx>
48 #include <txtfrm.hxx>
49 #include <notxtfrm.hxx>
50 #include <tabfrm.hxx>
51 #include <rowfrm.hxx>
52 #include <pagedesc.hxx>
53 #include <layact.hxx>
54 #include <flyfrm.hxx>
55 #include <sectfrm.hxx>
56 #include <section.hxx>
57 #include <dbg_lay.hxx>
58 #include <lineinfo.hxx>
59 #include <fmtclbl.hxx>
60 #include <sortedobjs.hxx>
61 #include <layouter.hxx>
62 #include <fmtfollowtextflow.hxx>
63 #include <calbck.hxx>
66 #include <pam.hxx>
67 #include <ndtxt.hxx>
68 
69 bool SwFlowFrame::s_bMoveBwdJump = false;
70 
72  m_rThis( rFrame ),
73  m_pFollow( nullptr ),
74  m_pPrecede( nullptr ),
75  m_bLockJoin( false ),
76  m_bUndersized( false ),
77  m_bFlyLock( false )
78 {}
79 
81 {
82  if (m_pFollow)
83  {
84  m_pFollow->m_pPrecede = nullptr;
85  }
86  if (m_pPrecede)
87  {
88  m_pPrecede->m_pFollow = nullptr;
89  }
90 }
91 
92 void SwFlowFrame::SetFollow(SwFlowFrame *const pFollow)
93 {
94  if (m_pFollow)
95  {
96  assert(this == m_pFollow->m_pPrecede);
97  m_pFollow->m_pPrecede = nullptr;
98  }
99  m_pFollow = pFollow;
100  if (m_pFollow != nullptr)
101  {
102  if (m_pFollow->m_pPrecede) // re-chaining pFollow?
103  {
105  m_pFollow->m_pPrecede->m_pFollow = nullptr;
106  }
107  m_pFollow->m_pPrecede = this;
108  }
109 }
110 
113 {
114  const SwFlowFrame* pFrame = GetFollow();
115  while( pFrame )
116  {
117  if( pFrame->IsJoinLocked() )
118  return true;
119  pFrame = pFrame->GetFollow();
120  }
121  return false;
122 }
123 
124 bool SwFlowFrame::IsKeepFwdMoveAllowed( bool bIgnoreMyOwnKeepValue )
125 {
126  // If all the predecessors up to the first of the chain have
127  // the 'keep' attribute set, and the first of the chain's
128  // IsFwdMoveAllowed returns false, then we're not allowed to move.
129  SwFrame *pFrame = &m_rThis;
130  if ( !pFrame->IsInFootnote() ) {
131  if ( bIgnoreMyOwnKeepValue && pFrame->GetIndPrev() )
132  pFrame = pFrame->GetIndPrev();
133  do
134  { if ( pFrame->GetAttrSet()->GetKeep().GetValue() )
135  pFrame = pFrame->GetIndPrev();
136  else
137  return true;
138  } while ( pFrame );
139  }
140  //See IsFwdMoveAllowed()
141  bool bRet = false;
142  if ( pFrame && pFrame->GetIndPrev() )
143  bRet = true;
144  return bRet;
145 }
146 
148 {
149  // Kick off the "last" predecessor with a 'keep' attribute, because
150  // it's possible for the whole troop to move back.
151  SwFrame *pPre = m_rThis.GetIndPrev();
152  assert(pPre);
153  if( pPre->IsSctFrame() )
154  {
155  SwFrame *pLast = static_cast<SwSectionFrame*>(pPre)->FindLastContent();
156  if( pLast && pLast->FindSctFrame() == pPre )
157  pPre = pLast;
158  else
159  return;
160  }
161  SwFrame* pTmp;
162  bool bKeep;
163  while ( (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) &&
164  nullptr != ( pTmp = pPre->GetIndPrev() ) )
165  {
166  if( pTmp->IsSctFrame() )
167  {
168  SwFrame *pLast = static_cast<SwSectionFrame*>(pTmp)->FindLastContent();
169  if( pLast && pLast->FindSctFrame() == pTmp )
170  pTmp = pLast;
171  else
172  break;
173  }
174  pPre = pTmp;
175  }
176  if ( bKeep )
177  pPre->InvalidatePos();
178 }
179 
180 namespace
181 {
186 bool IsNextContentFullPage(const SwFrame& rThis)
187 {
188  const SwFrame* pNext = rThis.FindNextCnt();
189  if (!pNext)
190  {
191  return false;
192  }
193 
194  const SwSortedObjs* pNextDrawObjs = pNext->GetDrawObjs();
195  if (!pNextDrawObjs || !pNextDrawObjs->size())
196  {
197  return false;
198  }
199 
200  for (const auto& pDrawObj : *pNextDrawObjs)
201  {
202  if (!pDrawObj)
203  {
204  continue;
205  }
206 
207  SwTwips nDrawObjHeight = pDrawObj->GetObjRectWithSpaces().Height();
208  const SwPageFrame* pPageFrame = pDrawObj->GetPageFrame();
209  if (!pPageFrame)
210  {
211  continue;
212  }
213 
214  SwTwips nBodyHeight = pPageFrame->GetLower()->getFrameArea().Height();
215  if (nDrawObjHeight < nBodyHeight)
216  {
217  continue;
218  }
219 
220  const SwFormatSurround& rSurround = pDrawObj->GetFrameFormat().GetSurround();
221  if (rSurround.GetSurround() != text::WrapTextMode_NONE)
222  {
223  continue;
224  }
225 
226  // At this point the height of the draw object will use all the vertical available space,
227  // and also no wrapping will be performed, so all horizontal space will be taken as well.
228  return true;
229  }
230 
231  return false;
232 }
233 }
234 
236  SvxFormatBreakItem const& rBreak,
237  bool const bCheckIfLastRowShouldKeep) const
238 {
239  // 1. The keep attribute is ignored inside footnotes
240  // 2. For compatibility reasons, the keep attribute is
241  // ignored for frames inside table cells
242  // 3. If bBreakCheck is set to true, this function only checks
243  // if there are any break after attributes set at rAttrs
244  // or break before attributes set for the next content (or next table)
245  // 4. Keep is ignored if the next frame will require its own page.
246  bool bKeep = bCheckIfLastRowShouldKeep ||
247  ( !m_rThis.IsInFootnote() &&
248  ( !m_rThis.IsInTab() || m_rThis.IsTabFrame() ) &&
249  rKeep.GetValue() && !IsNextContentFullPage(m_rThis));
250 
251  OSL_ENSURE( !bCheckIfLastRowShouldKeep || m_rThis.IsTabFrame(),
252  "IsKeep with bCheckIfLastRowShouldKeep should only be used for tabfrms" );
253 
254  // Ignore keep attribute if there are break situations:
255  if ( bKeep )
256  {
257  switch (rBreak.GetBreak())
258  {
259  case SvxBreak::ColumnAfter:
260  case SvxBreak::ColumnBoth:
261  case SvxBreak::PageAfter:
262  case SvxBreak::PageBoth:
263  {
264  bKeep = false;
265  break;
266  }
267  default: break;
268  }
269  if ( bKeep )
270  {
271  SwFrame *pNxt;
272  if( nullptr != (pNxt = m_rThis.FindNextCnt()) &&
273  (!m_pFollow || pNxt != &m_pFollow->GetFrame()))
274  {
275  // The last row of a table only keeps with the next content
276  // it they are in the same section:
277  if ( bCheckIfLastRowShouldKeep )
278  {
279  const SwSection* pThisSection = nullptr;
280  const SwSection* pNextSection = nullptr;
281  const SwSectionFrame* pThisSectionFrame = m_rThis.FindSctFrame();
282  const SwSectionFrame* pNextSectionFrame = pNxt->FindSctFrame();
283 
284  if ( pThisSectionFrame )
285  pThisSection = pThisSectionFrame->GetSection();
286 
287  if ( pNextSectionFrame )
288  pNextSection = pNextSectionFrame->GetSection();
289 
290  if ( pThisSection != pNextSection )
291  bKeep = false;
292  }
293 
294  if ( bKeep )
295  {
296  SvxFormatBreakItem const* pBreak;
297  SwFormatPageDesc const* pPageDesc;
298  SwTabFrame* pTab = pNxt->IsInTab() ? pNxt->FindTabFrame() : nullptr;
299  if (pTab && (!m_rThis.IsInTab() || m_rThis.FindTabFrame() != pTab))
300  {
301  const SwAttrSet *const pSet = &pTab->GetFormat()->GetAttrSet();
302  pBreak = &pSet->GetBreak();
303  pPageDesc = &pSet->GetPageDesc();
304  }
305  else
306  {
307  pBreak = &pNxt->GetBreakItem();
308  pPageDesc = &pNxt->GetPageDescItem();
309  }
310 
311  if (pPageDesc->GetPageDesc())
312  bKeep = false;
313  else switch (pBreak->GetBreak())
314  {
315  case SvxBreak::ColumnBefore:
316  case SvxBreak::ColumnBoth:
317  case SvxBreak::PageBefore:
318  case SvxBreak::PageBoth:
319  bKeep = false;
320  break;
321  default: break;
322  }
323  }
324  }
325  }
326  }
327  return bKeep;
328 }
329 
331 {
332  // The return value helps deciding whether we need to flow back (3),
333  // or whether we can use the good old WouldFit (0, 1), or if
334  // it's reasonable to relocate and test-format (2).
335 
336  // Bit 1 in this case means that there are objects anchored to myself,
337  // bit 2 means that I have to evade other objects.
338 
339  // If a SurroundObj that desires to be wrapped around overlaps with the
340  // Rect, it's required to flow (because we can't guess the relationships).
341  // However it's possible for a test formatting to happen.
342  // If the SurroundObj is a Fly and I'm a Lower, or the Fly is a Lower of
343  // mine, then it doesn't matter.
344  // If the SurroundObj is anchored in a character bound Fly, and I'm not
345  // a Lower of that character bound Fly myself, then the Fly doesn't matter.
346 
347  // If the object is anchored with me, i can ignore it, because
348  // it's likely that it will follow me with the flow. A test formatting is
349  // not allowed in that case, however!
350  sal_uInt8 nRet = 0;
351  SwFlowFrame *pTmp = this;
352  do
353  { // If there are objects hanging either on me or on a follow, we can't
354  // do a test formatting, because paragraph bound objects wouldn't
355  // be properly considered, and character bound objects shouldn't
356  // be test formatted at all.
357  if( pTmp->GetFrame().GetDrawObjs() )
358  nRet = 1;
359  pTmp = pTmp->GetFollow();
360  } while ( !nRet && pTmp );
361  const SwSortedObjs *pObjs = pPage ? pPage->GetSortedObjs() : nullptr;
362  if (pObjs)
363  {
364 
365  const SwSortedObjs &rObjs = *pObjs;
366  sal_uLong nIndex = ULONG_MAX;
367  for ( size_t i = 0; nRet < 3 && i < rObjs.size(); ++i )
368  {
369 
370  SwAnchoredObject* pObj = rObjs[i];
371  const SwFrameFormat& rFormat = pObj->GetFrameFormat();
372  const SwRect aRect( pObj->GetObjRect() );
373  if ( aRect.IsOver( rRect ) &&
374  rFormat.GetSurround().GetSurround() != css::text::WrapTextMode_THROUGH )
375  {
376  if( m_rThis.IsLayoutFrame() && //Fly Lower of This?
377  Is_Lower_Of( &m_rThis, pObj->GetDrawObj() ) )
378  continue;
379  if( auto pFly = dynamic_cast<const SwFlyFrame*>(pObj) )
380  {
381  if ( pFly->IsAnLower( &m_rThis ) )//This Lower of Fly?
382  continue;
383  }
384 
385  const SwFrame* pAnchor = pObj->GetAnchorFrame();
386  if ( pAnchor == &m_rThis )
387  {
388  nRet |= 1;
389  continue;
390  }
391 
392  // Don't do this if the object is anchored behind me in the text
393  // flow, because then I wouldn't evade it.
394  if ( ::IsFrameInSameContext( pAnchor, &m_rThis ) )
395  {
396  if ( rFormat.GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PARA )
397  {
398  // The index of the other one can be retrieved using the anchor attribute.
399  sal_uLong nTmpIndex = rFormat.GetAnchor().GetContentAnchor()->nNode.GetIndex();
400  // Now we're going to check whether the current paragraph before
401  // the anchor of the displacing object sits in the text. If this
402  // is the case, we don't try to evade it.
403  // The index is being determined via SwFormatAnchor, because it's
404  // getting quite expensive otherwise.
405  if( ULONG_MAX == nIndex )
406  {
407  const SwNode *pNode;
408  if (m_rThis.IsTextFrame())
409  pNode = static_cast<SwTextFrame&>(m_rThis).GetTextNodeFirst();
410  else if (m_rThis.IsNoTextFrame())
411  pNode = static_cast<SwNoTextFrame&>(m_rThis).GetNode();
412  else if( m_rThis.IsSctFrame() )
413  pNode = static_cast<SwSectionFormat*>(static_cast<SwSectionFrame&>(m_rThis).
414  GetFormat())->GetSectionNode();
415  else
416  {
418  OSL_ENSURE( m_rThis.IsTabFrame(), "new FowFrame?" );
419  pNode = static_cast<SwTabFrame&>(m_rThis).GetTable()->
420  GetTabSortBoxes()[0]->GetSttNd()->FindTableNode();
421  }
422  nIndex = pNode->GetIndex();
423  }
424  if (nIndex < nTmpIndex &&
425  (!m_rThis.IsTextFrame() ||
426  !FrameContainsNode(static_cast<SwTextFrame&>(m_rThis), nTmpIndex)))
427  {
428  continue;
429  }
430  }
431  }
432  else
433  continue;
434 
435  nRet |= 2;
436  }
437  }
438  }
439  return nRet;
440 }
441 
445 {
446  // Cut the Start and all the neighbours; they are chained together and
447  // a handle to the first one is returned. Residuals are invalidated
448  // as appropriate.
449 
450  SwLayoutFrame *pLay = pStart->GetUpper();
451  if ( pLay->IsInFootnote() )
452  pLay = pLay->FindFootnoteFrame();
453 
454  // i#58846
455  // <pPrepare( PrepareHint::QuoVadis )> only for frames in footnotes
456  if( pStart->IsInFootnote() )
457  {
458  SwFrame* pTmp = pStart->GetIndPrev();
459  if( pTmp )
461  }
462 
463  // Just cut quickly and take care that we don't cause problems with the
464  // left-behinds. The pointers of the chain being cut can point who-knows where.
465  if ( pStart == pStart->GetUpper()->Lower() )
466  pStart->GetUpper()->m_pLower = nullptr;
467  if ( pStart->GetPrev() )
468  {
469  pStart->GetPrev()->mpNext = nullptr;
470  pStart->mpPrev = nullptr;
471  }
472 
473  if ( pLay->IsFootnoteFrame() )
474  {
475  if ( !pLay->Lower() && !pLay->IsColLocked() &&
476  !static_cast<SwFootnoteFrame*>(pLay)->IsBackMoveLocked() )
477  {
478  // tdf#101821 don't delete it while iterating over it
479  if (!pLay->IsDeleteForbidden())
480  {
481  pLay->Cut();
482  SwFrame::DestroyFrame(pLay);
483  }
484  // else: assume there is code on the stack to clean up empty
485  // footnote frames
486  // (don't go into the else branch below, it produces a disconnected
487  // footnote with null upper that can be returned by
488  // SwFootnoteBossFrame::FindFootnote() causing null pointer deref
489  // in SwTextFrame::ConnectFootnote()
490  }
491  else
492  {
493  bool bUnlock = !static_cast<SwFootnoteFrame*>(pLay)->IsBackMoveLocked();
494  static_cast<SwFootnoteFrame*>(pLay)->LockBackMove();
495  pLay->InvalidateSize();
496  pLay->Calc(pLay->getRootFrame()->GetCurrShell()->GetOut());
497  SwContentFrame *pCnt = pLay->ContainsContent();
498  while ( pCnt && pLay->IsAnLower( pCnt ) )
499  {
500  // It's possible for the ContentFrame to be locked, and we don't want
501  // to end up in an endless page migration, so we're not even
502  // going to call Calc!
503  OSL_ENSURE( pCnt->IsTextFrame(), "The Graphic has landed." );
504  if ( static_cast<SwTextFrame*>(pCnt)->IsLocked() ||
505  static_cast<SwTextFrame*>(pCnt)->GetFollow() == pStart )
506  break;
507  pCnt->Calc(pCnt->getRootFrame()->GetCurrShell()->GetOut());
508  pCnt = pCnt->GetNextContentFrame();
509  }
510  if( bUnlock )
511  static_cast<SwFootnoteFrame*>(pLay)->UnlockBackMove();
512  }
513  pLay = nullptr;
514  }
515  return pLay;
516 }
517 
520 bool SwFlowFrame::PasteTree( SwFrame *pStart, SwLayoutFrame *pParent, SwFrame *pSibling,
521  SwFrame *pOldParent )
522 {
523  // returns true if there's a LayoutFrame in the chain.
524  bool bRet = false;
525 
526  // The chain beginning with pStart is inserted before pSibling
527  // under the parent. We take care to invalidate as required.
528 
529  // I'm receiving a finished chain. We need to update the pointers for
530  // the beginning of the chain, then all the uppers and finally the end.
531  // On the way there, we invalidate as required.
532  if ( pSibling )
533  {
534  pStart->mpPrev = pSibling->GetPrev();
535  if ( nullptr != pStart->mpPrev )
536  pStart->GetPrev()->mpNext = pStart;
537  else
538  pParent->m_pLower = pStart;
539  pSibling->InvalidatePos_();
540  pSibling->InvalidatePrt_();
541  }
542  else
543  {
544  pStart->mpPrev = pParent->Lower();
545  if ( nullptr == pStart->mpPrev )
546  pParent->m_pLower = pStart;
547  else
548  //i#100782
549  //If the pParent has more than 1 child nodes, former design will
550  //ignore them directly without any collection work. It will make some
551  //dangling pointers. This lead the crash...
552  //The new design will find the last child of pParent in loop way, and
553  //add the pStart after the last child.
554  // pParent->Lower()->pNext = pStart;
555  {
556  SwFrame* pTemp = pParent->m_pLower;
557  while (pTemp)
558  {
559  if (pTemp->mpNext)
560  pTemp = pTemp->mpNext;
561  else
562  {
563  pStart->mpPrev = pTemp;
564  pTemp->mpNext = pStart;
565  break;
566  }
567  }
568  }
569 
570 
571  // i#27145
572  if ( pParent->IsSctFrame() )
573  {
574  // We have no sibling because pParent is a section frame and
575  // has just been created to contain some content. The printing
576  // area of the frame behind pParent has to be invalidated, so
577  // that the correct distance between pParent and the next frame
578  // can be calculated.
579  pParent->InvalidateNextPrtArea();
580  }
581  }
582  SwFrame *pFloat = pStart;
583  SwFrame *pLst = nullptr;
584  SwRectFnSet aRectFnSet(pParent);
585  SwTwips nGrowVal = 0;
586  do
587  { pFloat->mpUpper = pParent;
588  pFloat->InvalidateAll_();
589  pFloat->CheckDirChange();
590 
591  // I'm a friend of the TextFrame and thus am allowed to do many things.
592  // The CacheIdx idea seems to be a bit risky!
593  if ( pFloat->IsTextFrame() )
594  {
595  if ( static_cast<SwTextFrame*>(pFloat)->GetCacheIdx() != USHRT_MAX )
596  static_cast<SwTextFrame*>(pFloat)->Init(); // I'm his friend.
597  }
598  else
599  bRet = true;
600 
601  nGrowVal += aRectFnSet.GetHeight(pFloat->getFrameArea());
602  if ( pFloat->GetNext() )
603  pFloat = pFloat->GetNext();
604  else
605  {
606  pLst = pFloat;
607  pFloat = nullptr;
608  }
609  } while ( pFloat );
610 
611  if ( pSibling )
612  {
613  pLst->mpNext = pSibling;
614  pSibling->mpPrev = pLst;
615  if( pSibling->IsInFootnote() )
616  {
617  if( pSibling->IsSctFrame() )
618  pSibling = static_cast<SwSectionFrame*>(pSibling)->ContainsAny();
619  if( pSibling )
620  pSibling->Prepare( PrepareHint::ErgoSum );
621  }
622  }
623  if ( nGrowVal )
624  {
625  if ( pOldParent && pOldParent->IsBodyFrame() ) // For variable page height while browsing
626  pOldParent->Shrink( nGrowVal );
627  pParent->Grow( nGrowVal );
628  }
629 
630  if ( pParent->IsFootnoteFrame() )
631  static_cast<SwFootnoteFrame*>(pParent)->InvalidateNxtFootnoteCnts( pParent->FindPageFrame() );
632  return bRet;
633 }
634 
635 void SwFlowFrame::MoveSubTree( SwLayoutFrame* pParent, SwFrame* pSibling )
636 {
637  OSL_ENSURE( pParent, "No parent given." );
638  OSL_ENSURE( m_rThis.GetUpper(), "Where are we coming from?" );
639 
640  // Be economical with notifications if an action is running.
642  const SwViewShellImp *pImp = pSh ? pSh->Imp() : nullptr;
643  const bool bComplete = pImp && pImp->IsAction() && pImp->GetLayAction().IsComplete();
644 
645  if ( !bComplete )
646  {
647  SwFrame *pPre = m_rThis.GetIndPrev();
648  if ( pPre )
649  {
650  pPre->SetRetouche();
651  // follow-up of i#26250
652  // invalidate printing area of previous frame, if it's in a table
653  if ( pPre->GetUpper()->IsInTab() )
654  {
655  pPre->InvalidatePrt_();
656  }
657  pPre->InvalidatePage();
658  }
659  else
660  {
663  }
664  }
665 
666  SwPageFrame *pOldPage = m_rThis.FindPageFrame();
667 
668  SwLayoutFrame *pOldParent;
669  bool bInvaLay;
670 
671  {
672  //JoinLock pParent for the lifetime of the Cut/Paste call to avoid
673  //SwSectionFrame::MergeNext removing the pParent we're trying to reparent
674  //into
675  FlowFrameJoinLockGuard aJoinGuard(pParent);
676  SwFrameDeleteGuard aDeleteGuard(pParent);
677  pOldParent = CutTree( &m_rThis );
678  bInvaLay = PasteTree( &m_rThis, pParent, pSibling, pOldParent );
679  }
680 
681  // If, by cutting & pasting, an empty SectionFrame came into existence, it should
682  // disappear automatically.
683  SwSectionFrame *pSct;
684 
685  if ( pOldParent && !pOldParent->Lower() &&
686  ( pOldParent->IsInSct() &&
687  !(pSct = pOldParent->FindSctFrame())->ContainsContent() &&
688  !pSct->ContainsAny( true ) ) )
689  {
690  pSct->DelEmpty( false );
691  }
692 
693  // If we're in a column section, we'd rather not call Calc "from below"
694  if( !m_rThis.IsInSct() &&
695  ( !m_rThis.IsInTab() || ( m_rThis.IsTabFrame() && !m_rThis.GetUpper()->IsInTab() ) ) )
697  else if( m_rThis.GetUpper()->IsSctFrame() )
698  {
699  SwSectionFrame* pTmpSct = static_cast<SwSectionFrame*>(m_rThis.GetUpper());
700  bool bOld = pTmpSct->IsContentLocked();
701  pTmpSct->SetContentLock( true );
702  pTmpSct->Calc(m_rThis.getRootFrame()->GetCurrShell()->GetOut());
703  if( !bOld )
704  pTmpSct->SetContentLock( false );
705  }
706  SwPageFrame *pPage = m_rThis.FindPageFrame();
707 
708  if ( pOldPage != pPage )
709  {
710  m_rThis.InvalidatePage( pPage );
711  if ( m_rThis.IsLayoutFrame() )
712  {
713  SwContentFrame *pCnt = static_cast<SwLayoutFrame*>(&m_rThis)->ContainsContent();
714  if ( pCnt )
715  pCnt->InvalidatePage( pPage );
716  }
717  else if ( pSh && pSh->GetDoc()->GetLineNumberInfo().IsRestartEachPage()
718  && pPage->FindFirstBodyContent() == &m_rThis )
719  {
721  }
722  }
723  if ( bInvaLay || (pSibling && pSibling->IsLayoutFrame()) )
724  m_rThis.GetUpper()->InvalidatePage( pPage );
725 }
726 
727 bool SwFlowFrame::IsAnFollow( const SwFlowFrame *pAssumed ) const
728 {
729  const SwFlowFrame *pFoll = this;
730  do
731  { if ( pAssumed == pFoll )
732  return true;
733  pFoll = pFoll->GetFollow();
734  } while ( pFoll );
735  return false;
736 }
737 
739 {
740  OSL_ENSURE( IsFollow(), "SwContentFrame::FindMaster(): !IsFollow" );
741 
742  const SwContentFrame* pPrec = static_cast<const SwContentFrame*>(SwFlowFrame::GetPrecede());
743 
744  if ( pPrec && pPrec->HasFollow() && pPrec->GetFollow() == this )
745  {
746  OSL_ENSURE( pPrec->IsTextFrame(), "NoTextFrame with follow found" );
747  return const_cast<SwTextFrame*>(static_cast< const SwTextFrame* >(pPrec));
748  }
749 
750  OSL_FAIL( "Follow is lost in Space." );
751  return nullptr;
752 }
753 
755 {
756  OSL_ENSURE( IsFollow(), "SwSectionFrame::FindMaster(): !IsFollow" );
757 
758  if (!m_pSection)
759  return nullptr;
760 
762  SwSectionFrame* pSect = aIter.First();
763  while ( pSect )
764  {
765  if (pSect->GetFollow() == this)
766  return pSect;
767  pSect = aIter.Next();
768  }
769 
770  OSL_FAIL( "Follow is lost in Space." );
771  return nullptr;
772 }
773 
774 SwTabFrame* SwTabFrame::FindMaster( bool bFirstMaster ) const
775 {
776  OSL_ENSURE( IsFollow(), "SwTabFrame::FindMaster(): !IsFollow" );
777 
778  SwIterator<SwTabFrame,SwFormat> aIter( *GetTable()->GetFrameFormat() );
779  SwTabFrame* pTab = aIter.First();
780  while ( pTab )
781  {
782  if ( bFirstMaster )
783  {
784  // Optimization. This makes code like this obsolete:
785  // while ( pTab->IsFollow() )
786  // pTab = pTab->FindMaster();
787 
788  if ( !pTab->IsFollow() )
789  {
790  SwTabFrame* pNxt = pTab;
791  while ( pNxt )
792  {
793  if ( pNxt->GetFollow() == this )
794  return pTab;
795  pNxt = pNxt->GetFollow();
796  }
797  }
798  }
799  else
800  {
801  if ( pTab->GetFollow() == this )
802  return pTab;
803  }
804 
805  pTab = aIter.Next();
806  }
807 
808  OSL_FAIL( "Follow is lost in Space." );
809  return nullptr;
810 }
811 
816 const SwLayoutFrame *SwFrame::GetLeaf( MakePageType eMakePage, bool bFwd,
817  const SwFrame *pAnch ) const
818 {
819  // No flow, no joy...
820  if ( !(IsInDocBody() || IsInFootnote() || IsInFly()) )
821  return nullptr;
822 
823  const SwFrame *pLeaf = this;
824  bool bFound = false;
825 
826  do
827  { pLeaf = const_cast<SwFrame*>(pLeaf)->GetLeaf( eMakePage, bFwd );
828 
829  if ( pLeaf &&
830  (!IsLayoutFrame() || !static_cast<const SwLayoutFrame*>(this)->IsAnLower( pLeaf )))
831  {
832  if ( pAnch->IsInDocBody() == pLeaf->IsInDocBody() &&
833  pAnch->IsInFootnote() == pLeaf->IsInFootnote() )
834  {
835  bFound = true;
836  }
837  }
838  } while ( !bFound && pLeaf );
839 
840  return static_cast<const SwLayoutFrame*>(pLeaf);
841 }
842 
844 {
845  if ( IsInFootnote() )
846  return bFwd ? GetNextFootnoteLeaf( eMakePage ) : GetPrevFootnoteLeaf( eMakePage );
847 
848  // i#53323
849  // A frame could be inside a table AND inside a section.
850  // Thus, it has to be determined, which is the first parent.
851  bool bInTab( IsInTab() );
852  bool bInSct( IsInSct() );
853  if ( bInTab && bInSct )
854  {
855  const SwFrame* pUpperFrame( GetUpper() );
856  while ( pUpperFrame )
857  {
858  if ( pUpperFrame->IsTabFrame() )
859  {
860  // the table is the first.
861  bInSct = false;
862  break;
863  }
864  else if ( pUpperFrame->IsSctFrame() )
865  {
866  // the section is the first.
867  bInTab = false;
868  break;
869  }
870 
871  pUpperFrame = pUpperFrame->GetUpper();
872  }
873  }
874 
875  if ( bInTab && ( !IsTabFrame() || GetUpper()->IsCellFrame() ) ) // TABLE IN TABLE
876  return bFwd ? GetNextCellLeaf() : GetPrevCellLeaf();
877 
878  if ( bInSct )
879  return bFwd ? GetNextSctLeaf( eMakePage ) : GetPrevSctLeaf();
880 
881  return bFwd ? GetNextLeaf( eMakePage ) : GetPrevLeaf();
882 }
883 
885 {
886  // Now it's getting a bit complicated:
887 
888  // Maybe I'm bringing a Pagedesc myself; in that case,
889  // the pagedesc of the next page needs to correspond.
890  // Otherwise, I'll have to dig a bit deeper to see where
891  // the following Pagedesc is coming from.
892  // If the following page itself tells me that it's pagedesc
893  // is wrong, I can happily exchange it.
894  // If the page however thinks that it's pagedesc is correct,
895  // this doesn't mean it's useful to me:
896  // If the first BodyContent asks for a PageDesc or a PageBreak,
897  // I'll have to insert a new page - except the desired page is
898  // the correct one.
899  // If I inserted a new page, the problems only get started:
900  // because then it's likely for the next page to have been
901  // wrong and having been swapped because of that.
902  // This in turn means that I have a new (and correct) page,
903  // but the conditions to swap still apply.
904  // Way out of the situation: Try to preliminarily insert a
905  // new page once (empty pages are already inserted by InsertPage()
906  // if required)
907 
908  //My Pagedesc doesn't count if I'm a follow!
909  const SwPageDesc *pDesc = nullptr;
910  std::optional<sal_uInt16> oTmp;
911  SwFlowFrame *pFlow = SwFlowFrame::CastFlowFrame( this );
912  if ( !pFlow || !pFlow->IsFollow() )
913  {
914  const SwFormatPageDesc &rFormatDesc = GetPageDescItem();
915  pDesc = rFormatDesc.GetPageDesc();
916  if( pDesc )
917  {
918  if( !pDesc->GetRightFormat() )
919  oTmp = 2;
920  else if( !pDesc->GetLeftFormat() )
921  oTmp = 1;
922  else if( rFormatDesc.GetNumOffset() )
923  oTmp = rFormatDesc.GetNumOffset();
924  }
925  }
926 
927  // Does the Content bring a Pagedesc or do we need the
928  // virtual page number of the new layout leaf?
929  // PageDesc isn't allowed with Follows
930  const bool isRightPage = oTmp ? sw::IsRightPageByNumber(*mpRoot, *oTmp) : pNew->OnRightPage();
931  if ( !pDesc )
932  pDesc = pNew->FindPageDesc();
933 
934  bool bFirst = pNew->OnFirstPage();
935 
936  const SwFlowFrame *pNewFlow = pNew->FindFirstBodyContent();
937  // Did we find ourselves?
938  if( pNewFlow == pFlow )
939  pNewFlow = nullptr;
940  if ( pNewFlow && pNewFlow->GetFrame().IsInTab() )
941  pNewFlow = pNewFlow->GetFrame().FindTabFrame();
942  const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() )
943  ? pNewFlow->GetFrame().GetPageDescItem().GetPageDesc()
944  : nullptr;
945 
946  SAL_INFO( "sw.pageframe", "WrongPageDesc p: " << pNew << " phys: " << pNew->GetPhyPageNum() );
947  SAL_INFO( "sw.pageframe", "WrongPageDesc " << pNew->GetPageDesc() << " " << pDesc );
948  SAL_INFO( "sw.pageframe", "WrongPageDesc right: " << isRightPage
949  << " first: " << bFirst << " " << pNew->GetFormat() << " == "
950  << (isRightPage ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst)) << " "
951  << (isRightPage ? pDesc->GetLeftFormat(bFirst) : pDesc->GetRightFormat(bFirst)) );
952 
953  return (pNew->GetPageDesc() != pDesc) // own desc ?
954  || (pNew->GetFormat() !=
955  (isRightPage ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst)))
956  || (pNewDesc && pNewDesc == pDesc);
957 }
958 
961 {
962  OSL_ENSURE( !IsInFootnote(), "GetNextLeaf(), don't call me for Footnote." );
963  OSL_ENSURE( !IsInSct(), "GetNextLeaf(), don't call me for Sections." );
964 
965  const bool bBody = IsInDocBody(); // If I'm coming from the DocBody,
966  // I want to end up in the body.
967 
968  // It doesn't make sense to insert pages, as we only want to search the
969  // chain.
970  if( IsInFly() )
971  eMakePage = MAKEPAGE_NONE;
972 
973  // For tables, we just take the big leap. A simple GetNext would
974  // iterate through the first cells and, in turn, all other cells.
975  SwLayoutFrame *pLayLeaf = nullptr;
976  if ( IsTabFrame() )
977  {
978  SwFrame *const pTmp = static_cast<SwTabFrame*>(this)->FindLastContentOrTable();
979  if ( pTmp )
980  pLayLeaf = pTmp->GetUpper();
981  }
982  if ( !pLayLeaf )
983  pLayLeaf = GetNextLayoutLeaf();
984 
985  SwLayoutFrame *pOldLayLeaf = nullptr; // Make sure that we don't have to
986  // start searching from top when we
987  // have a freshly created page.
988  bool bNewPg = false; // Only insert a new page once.
989 
990  while ( true )
991  {
992  if ( pLayLeaf )
993  {
994  // There's yet another LayoutFrame. Let's see if it's ready to host
995  // me as well.
996  // It only needs to be of the same kind like my starting point
997  // (DocBody or Footnote respectively)
998  if ( pLayLeaf->FindPageFrame()->IsFootnotePage() )
999  { // If I ended up at the end note pages, we're done.
1000  pLayLeaf = nullptr;
1001  continue;
1002  }
1003  if ( (bBody && !pLayLeaf->IsInDocBody()) || pLayLeaf->IsInTab()
1004  || pLayLeaf->IsInSct() )
1005  {
1006  // They don't want me! Try again
1007  pOldLayLeaf = pLayLeaf;
1008  pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1009  continue;
1010  }
1011 
1012  // I'm wanted, therefore I'm done. However, it may still be that,
1013  // during a page break, the page type isn't the desired one. In that
1014  // case we have to insert a page of the correct type.
1015 
1016  if( !IsFlowFrame() && ( eMakePage == MAKEPAGE_NONE ||
1017  eMakePage==MAKEPAGE_APPEND || eMakePage==MAKEPAGE_NOSECTION ) )
1018  return pLayLeaf;
1019 
1020  SwPageFrame *pNew = pLayLeaf->FindPageFrame();
1021  const SwViewShell *pSh = getRootFrame()->GetCurrShell();
1022  // The pagedesc check does not make sense for frames in fly frames
1023  if ( pNew != FindPageFrame() && !bNewPg && !IsInFly() &&
1024  // i#46683
1025  // Do not consider page descriptions in browse mode (since
1026  // MoveBwd ignored them)
1027  !(pSh && pSh->GetViewOptions()->getBrowseMode() ) )
1028  {
1029  if( WrongPageDesc( pNew ) )
1030  {
1031  SwFootnoteContFrame *pCont = pNew->FindFootnoteCont();
1032  if( pCont )
1033  {
1034  // If the reference of the first footnote of this page
1035  // lies before the page, we'd rather not insert a new page.
1036 
1037  SwFootnoteFrame *pFootnote = static_cast<SwFootnoteFrame*>(pCont->Lower());
1038  if( pFootnote && pFootnote->GetRef() )
1039  {
1040  const sal_uInt16 nRefNum = pNew->GetPhyPageNum();
1041  if( pFootnote->GetRef()->GetPhyPageNum() < nRefNum )
1042  break;
1043  }
1044  }
1045  //Gotcha! The following page is wrong, therefore we need to
1046  //insert a new one.
1047  if ( eMakePage == MAKEPAGE_INSERT )
1048  {
1049  bNewPg = true;
1050 
1051  SwPageFrame *pPg = pOldLayLeaf ?
1052  pOldLayLeaf->FindPageFrame() : nullptr;
1053  if ( pPg && pPg->IsEmptyPage() )
1054  // Don't insert behind. Insert before the EmptyPage.
1055  pPg = static_cast<SwPageFrame*>(pPg->GetPrev());
1056 
1057  if ( !pPg || pPg == pNew )
1058  pPg = FindPageFrame();
1059 
1060  InsertPage( pPg, false );
1061  pLayLeaf = GetNextLayoutLeaf();
1062  pOldLayLeaf = nullptr;
1063  continue;
1064  }
1065  else
1066  pLayLeaf = nullptr;
1067  }
1068  }
1069  break;
1070  }
1071  else
1072  {
1073  // There's no other matching LayoutFrame, so we have to insert
1074  // a new page.
1075  if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
1076  {
1077  InsertPage(
1078  pOldLayLeaf ? pOldLayLeaf->FindPageFrame() : FindPageFrame(),
1079  false );
1080 
1081  // And again from the start.
1082  pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1083  }
1084  else
1085  break;
1086  }
1087  }
1088  return pLayLeaf;
1089 }
1090 
1093 {
1094  OSL_ENSURE( !IsInFootnote(), "GetPrevLeaf(), don't call me for Footnote." );
1095 
1096  const bool bBody = IsInDocBody(); // If I'm coming from the DocBody,
1097  // I want to end up in the body.
1098  const bool bFly = IsInFly();
1099 
1100  SwLayoutFrame *pLayLeaf = GetPrevLayoutLeaf();
1101  SwLayoutFrame *pPrevLeaf = nullptr;
1102 
1103  while ( pLayLeaf )
1104  {
1105  if ( pLayLeaf->IsInTab() || // Never go into tables.
1106  pLayLeaf->IsInSct() ) // Same goes for sections!
1107  pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1108  else if ( bBody && pLayLeaf->IsInDocBody() )
1109  {
1110  if ( pLayLeaf->Lower() )
1111  break;
1112  pPrevLeaf = pLayLeaf;
1113  pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1114  if ( pLayLeaf )
1116  }
1117  else if ( bFly )
1118  break; //Contents in Flys should accept any layout leaf.
1119  else
1120  pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1121  }
1122  return pLayLeaf ? pLayLeaf : pPrevLeaf;
1123 }
1124 
1126 {
1127  // true: The FlowFrame must respect the a border of the predecessor, also needs
1128  // to insert a break if required.
1129 
1131  const SwViewShell *pSh = m_rThis.getRootFrame()->GetCurrShell();
1132  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
1133  return false;
1134 
1135  SwFrame *pPre = m_rThis.FindPrev();
1136 
1137  if ( pPre && pPre->GetDrawObjs() )
1138  {
1139  OSL_ENSURE( SwFlowFrame::CastFlowFrame( pPre ), "new flowfrm?" );
1140  if( SwFlowFrame::CastFlowFrame( pPre )->IsAnFollow( this ) )
1141  return false;
1142  SwLayoutFrame* pPreUp = pPre->GetUpper();
1143  // If the upper is a SectionFrame, or a column of a SectionFrame, we're
1144  // allowed to protrude out of it. However, we need to respect the
1145  // Upper of the SectionFrame.
1146  if( pPreUp->IsInSct() )
1147  {
1148  if( pPreUp->IsSctFrame() )
1149  pPreUp = pPreUp->GetUpper();
1150  else if( pPreUp->IsColBodyFrame() &&
1151  pPreUp->GetUpper()->GetUpper()->IsSctFrame() )
1152  pPreUp = pPreUp->GetUpper()->GetUpper()->GetUpper();
1153  }
1154  // i#26945 - re-factoring
1155  // use <GetVertPosOrientFrame()> to determine, if object has followed the
1156  // text flow to the next layout frame
1157  for (SwAnchoredObject* pObj : *pPre->GetDrawObjs())
1158  {
1159 
1160  // Do not consider hidden objects
1161  // i#26945 - do not consider object, which
1162  // doesn't follow the text flow.
1163  if ( pObj->GetFrameFormat().GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId(
1164  pObj->GetDrawObj()->GetLayer() ) &&
1165  pObj->GetFrameFormat().GetFollowTextFlow().GetValue() )
1166  {
1167  const SwLayoutFrame* pVertPosOrientFrame = pObj->GetVertPosOrientFrame();
1168  if ( pVertPosOrientFrame &&
1169  pPreUp != pVertPosOrientFrame &&
1170  !pPreUp->IsAnLower( pVertPosOrientFrame ) )
1171  {
1172  return true;
1173  }
1174  }
1175  }
1176  }
1177  return false;
1178 }
1179 
1195 bool SwFlowFrame::IsPageBreak( bool bAct ) const
1196 {
1197  if ( !IsFollow() && m_rThis.IsInDocBody() &&
1198  ( !m_rThis.IsInTab() || ( m_rThis.IsTabFrame() && !m_rThis.GetUpper()->IsInTab() ) ) ) // i66968
1199  {
1200  const SwViewShell *pSh = m_rThis.getRootFrame()->GetCurrShell();
1201  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
1202  return false;
1203 
1204  // Determine predecessor
1205  const SwFrame *pPrev = m_rThis.FindPrev();
1206  while ( pPrev && ( !pPrev->IsInDocBody() ||
1207  ( pPrev->IsTextFrame() && static_cast<const SwTextFrame*>(pPrev)->IsHiddenNow() ) ) )
1208  pPrev = pPrev->FindPrev();
1209 
1210  if ( pPrev )
1211  {
1212  OSL_ENSURE( pPrev->IsInDocBody(), "IsPageBreak: Not in DocBody?" );
1213  if ( bAct )
1214  { if ( m_rThis.FindPageFrame() == pPrev->FindPageFrame() )
1215  return false;
1216  }
1217  else
1218  { if ( m_rThis.FindPageFrame() != pPrev->FindPageFrame() )
1219  return false;
1220  }
1221 
1222  //for compatibility, also break at column break if no columns exist
1224  const bool bTreatSingleColumnBreakAsPageBreak = rIDSA.get(DocumentSettingId::TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK);
1225  const SvxBreak eBreak = m_rThis.GetBreakItem().GetBreak();
1226  if ( eBreak == SvxBreak::PageBefore ||
1227  eBreak == SvxBreak::PageBoth ||
1228  ( bTreatSingleColumnBreakAsPageBreak && eBreak == SvxBreak::ColumnBefore && !m_rThis.FindColFrame() ))
1229  return true;
1230  else
1231  {
1232  const SvxBreak &ePrB = pPrev->GetBreakItem().GetBreak();
1233  if ( ePrB == SvxBreak::PageAfter ||
1234  ePrB == SvxBreak::PageBoth ||
1236  {
1237  return true;
1238  }
1239  }
1240  }
1241  }
1242  return false;
1243 }
1244 
1258 bool SwFlowFrame::IsColBreak( bool bAct ) const
1259 {
1260  if ( !IsFollow() && (m_rThis.IsMoveable() || bAct) )
1261  {
1262  const SwFrame *pCol = m_rThis.FindColFrame();
1263  if ( pCol )
1264  {
1265  // Determine predecessor
1266  const SwFrame *pPrev = m_rThis.FindPrev();
1267  while( pPrev && ( ( !pPrev->IsInDocBody() && !m_rThis.IsInFly() && !m_rThis.FindFooterOrHeader() ) ||
1268  ( pPrev->IsTextFrame() && static_cast<const SwTextFrame*>(pPrev)->IsHiddenNow() ) ) )
1269  pPrev = pPrev->FindPrev();
1270 
1271  if ( pPrev )
1272  {
1273  if ( bAct )
1274  { if ( pCol == pPrev->FindColFrame() )
1275  return false;
1276  }
1277  else
1278  { if ( pCol != pPrev->FindColFrame() )
1279  return false;
1280  }
1281 
1282  const SvxBreak eBreak = m_rThis.GetBreakItem().GetBreak();
1283  if ( eBreak == SvxBreak::ColumnBefore ||
1284  eBreak == SvxBreak::ColumnBoth )
1285  return true;
1286  else
1287  {
1288  const SvxBreak &ePrB = pPrev->GetBreakItem().GetBreak();
1289  if ( ePrB == SvxBreak::ColumnAfter ||
1290  ePrB == SvxBreak::ColumnBoth )
1291  return true;
1292  }
1293  }
1294  }
1295  }
1296  return false;
1297 }
1298 
1299 bool SwFlowFrame::HasParaSpaceAtPages( bool bSct ) const
1300 {
1301  if( m_rThis.IsInSct() )
1302  {
1303  const SwFrame* pTmp = m_rThis.GetUpper();
1304  while( pTmp )
1305  {
1306  if( pTmp->IsCellFrame() || pTmp->IsFlyFrame() ||
1307  pTmp->IsFooterFrame() || pTmp->IsHeaderFrame() ||
1308  ( pTmp->IsFootnoteFrame() && !static_cast<const SwFootnoteFrame*>(pTmp)->GetMaster() ) )
1309  return true;
1310  if( pTmp->IsPageFrame() )
1311  return !pTmp->GetPrev() || IsPageBreak(true);
1312  if( pTmp->IsColumnFrame() && pTmp->GetPrev() )
1313  return IsColBreak( true );
1314  if( pTmp->IsSctFrame() && ( !bSct || pTmp->GetPrev() ) )
1315  return false;
1316  pTmp = pTmp->GetUpper();
1317  }
1318  OSL_FAIL( "HasParaSpaceAtPages: Where's my page?" );
1319  return false;
1320  }
1321  if( !m_rThis.IsInDocBody() || ( m_rThis.IsInTab() && !m_rThis.IsTabFrame()) ||
1322  IsPageBreak( true ) || ( m_rThis.FindColFrame() && IsColBreak( true ) ) )
1323  return true;
1324  const SwFrame* pTmp = m_rThis.FindColFrame();
1325  if( pTmp )
1326  {
1327  if( pTmp->GetPrev() )
1328  return false;
1329  }
1330  else
1331  pTmp = &m_rThis;
1332  pTmp = pTmp->FindPageFrame();
1333  return pTmp && !pTmp->GetPrev();
1334 }
1335 
1341 const SwFrame* SwFlowFrame::GetPrevFrameForUpperSpaceCalc_( const SwFrame* _pProposedPrevFrame ) const
1342 {
1343  const SwFrame* pPrevFrame = _pProposedPrevFrame
1344  ? _pProposedPrevFrame
1345  : m_rThis.GetPrev();
1346 
1347  // Skip hidden paragraphs and empty sections
1348  while ( pPrevFrame &&
1349  ( ( pPrevFrame->IsTextFrame() &&
1350  static_cast<const SwTextFrame*>(pPrevFrame)->IsHiddenNow() ) ||
1351  ( pPrevFrame->IsSctFrame() &&
1352  !static_cast<const SwSectionFrame*>(pPrevFrame)->GetSection() ) ) )
1353  {
1354  pPrevFrame = pPrevFrame->GetPrev();
1355  }
1356 
1357  // Special case: no direct previous frame is found but frame is in footnote
1358  // Search for a previous frame in previous footnote,
1359  // if frame isn't in a section, which is also in the footnote
1360  if ( !pPrevFrame && m_rThis.IsInFootnote() &&
1361  ( m_rThis.IsSctFrame() ||
1363  {
1364  const SwFootnoteFrame* pPrevFootnoteFrame =
1365  static_cast<const SwFootnoteFrame*>(m_rThis.FindFootnoteFrame()->GetPrev());
1366  if ( pPrevFootnoteFrame )
1367  {
1368  pPrevFrame = pPrevFootnoteFrame->GetLastLower();
1369 
1370  // Skip hidden paragraphs and empty sections
1371  while ( pPrevFrame &&
1372  ( ( pPrevFrame->IsTextFrame() &&
1373  static_cast<const SwTextFrame*>(pPrevFrame)->IsHiddenNow() ) ||
1374  ( pPrevFrame->IsSctFrame() &&
1375  !static_cast<const SwSectionFrame*>(pPrevFrame)->GetSection() ) ) )
1376  {
1377  pPrevFrame = pPrevFrame->GetPrev();
1378  }
1379  }
1380  }
1381  // Special case: found previous frame is a section
1382  // Search for the last content in the section
1383  if( pPrevFrame && pPrevFrame->IsSctFrame() )
1384  {
1385  const SwSectionFrame* pPrevSectFrame =
1386  static_cast<const SwSectionFrame*>(pPrevFrame);
1387  pPrevFrame = pPrevSectFrame->FindLastContent();
1388  // If the last content is in a table _inside_ the section,
1389  // take the table herself.
1390  // Correction: Check directly, if table is inside table, instead of indirectly
1391  // by checking, if section isn't inside a table
1392  if ( pPrevFrame && pPrevFrame->IsInTab() )
1393  {
1394  const SwTabFrame* pTableFrame = pPrevFrame->FindTabFrame();
1395  if ( pPrevSectFrame->IsAnLower( pTableFrame ) )
1396  {
1397  pPrevFrame = pTableFrame;
1398  }
1399  }
1400  // Correction: skip hidden text frames
1401  while ( pPrevFrame &&
1402  pPrevFrame->IsTextFrame() &&
1403  static_cast<const SwTextFrame*>(pPrevFrame)->IsHiddenNow() )
1404  {
1405  pPrevFrame = pPrevFrame->GetPrev();
1406  }
1407  }
1408 
1409  return pPrevFrame;
1410 }
1411 
1413 static bool lcl_IdenticalStyles(const SwFrame* pPrevFrame, const SwFrame* pFrame)
1414 {
1415  SwTextFormatColl *pPrevFormatColl = nullptr;
1416  if (pPrevFrame && pPrevFrame->IsTextFrame())
1417  {
1418  const SwTextFrame *pTextFrame = static_cast< const SwTextFrame * >( pPrevFrame );
1419  pPrevFormatColl = dynamic_cast<SwTextFormatColl*>(
1420  pTextFrame->GetTextNodeForParaProps()->GetFormatColl());
1421  }
1422 
1423  bool bIdenticalStyles = false;
1424  if (pFrame && pFrame->IsTextFrame())
1425  {
1426  const SwTextFrame *pTextFrame = static_cast< const SwTextFrame * >( pFrame );
1427  SwTextFormatColl *const pFormatColl = dynamic_cast<SwTextFormatColl*>(
1428  pTextFrame->GetTextNodeForParaProps()->GetFormatColl());
1429  bIdenticalStyles = pPrevFormatColl == pFormatColl;
1430  }
1431  return bIdenticalStyles;
1432 }
1433 
1434 static bool lcl_getContextualSpacing(const SwFrame* pPrevFrame)
1435 {
1436  bool bRet;
1437  auto pAccess = std::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), pPrevFrame);
1438  const SwBorderAttrs *pAttrs = pAccess->Get();
1439 
1440  bRet = pAttrs->GetULSpace().GetContext();
1441 
1442  return bRet;
1443 }
1444 
1445 
1447  const SwFrame* pPr,
1448  const bool _bConsiderGrid ) const
1449 {
1450  const SwFrame* pPrevFrame = GetPrevFrameForUpperSpaceCalc_( pPr );
1451 
1452  std::unique_ptr<SwBorderAttrAccess> pAccess;
1453  SwFrame* pOwn;
1454  if( !pAttrs )
1455  {
1456  if( m_rThis.IsSctFrame() )
1457  {
1458  SwSectionFrame* pFoll = &static_cast<SwSectionFrame&>(m_rThis);
1459  do
1460  pOwn = pFoll->ContainsAny();
1461  while( !pOwn && nullptr != ( pFoll = pFoll->GetFollow() ) );
1462  if( !pOwn )
1463  return 0;
1464  }
1465  else
1466  pOwn = &m_rThis;
1467  pAccess = std::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), pOwn);
1468  pAttrs = pAccess->Get();
1469  }
1470  else
1471  {
1472  pOwn = &m_rThis;
1473  }
1474  SwTwips nUpper = 0;
1475 
1476  {
1478  if( pPrevFrame )
1479  {
1480  const bool bUseFormerLineSpacing = rIDSA.get(DocumentSettingId::OLD_LINE_SPACING);
1481  const bool bContextualSpacingThis = pAttrs->GetULSpace().GetContext();
1482  const bool bContextualSpacingPrev = lcl_getContextualSpacing(pPrevFrame);
1483  bool bIdenticalStyles = lcl_IdenticalStyles(pPrevFrame, &m_rThis);
1484 
1485  const bool bContextualSpacing = bContextualSpacingThis
1486  && bContextualSpacingPrev
1487  && bIdenticalStyles;
1488 
1489  // tdf#125893 always ignore own top margin setting of the actual paragraph
1490  // with contextual spacing, if the previous paragraph is identical
1491  const bool bHalfContextualSpacing = !bContextualSpacing
1492  && bContextualSpacingThis
1493  && !bContextualSpacingPrev
1494  && bIdenticalStyles;
1495 
1496  // tdf#134463 always ignore own bottom margin setting of the previous paragraph
1497  // with contextual spacing, if the actual paragraph is identical
1498  const bool bHalfContextualSpacingPrev = !bContextualSpacing
1499  && !bContextualSpacingThis
1500  && bContextualSpacingPrev
1501  && bIdenticalStyles;
1502 
1503  // i#11860 - use new method to determine needed spacing
1504  // values of found previous frame and use these values.
1505  SwTwips nPrevLowerSpace = 0;
1506  SwTwips nPrevLineSpacing = 0;
1507  // i#102458
1508  bool bPrevLineSpacingProportional = false;
1509  GetSpacingValuesOfFrame( (*pPrevFrame),
1510  nPrevLowerSpace, nPrevLineSpacing,
1511  bPrevLineSpacingProportional,
1512  bIdenticalStyles);
1514  {
1515  // FIXME: apply bHalfContextualSpacing for better portability?
1516  nUpper = bContextualSpacing ? 0 : nPrevLowerSpace + pAttrs->GetULSpace().GetUpper();
1517  SwTwips nAdd = nPrevLineSpacing;
1518  // i#11859 - consideration of the line spacing
1519  // for the upper spacing of a text frame
1520  if ( bUseFormerLineSpacing )
1521  {
1522  // former consideration
1523  if ( pOwn->IsTextFrame() )
1524  {
1525  nAdd = std::max( nAdd, SwTwips(static_cast<SwTextFrame*>(pOwn)->GetLineSpace()) );
1526  }
1527  nUpper += nAdd;
1528  }
1529  else
1530  {
1531  // new consideration:
1532  // Only the proportional line spacing of the previous
1533  // text frame is considered for the upper spacing and
1534  // the line spacing values are add up instead of
1535  // building its maximum.
1536  if ( pOwn->IsTextFrame() )
1537  {
1538  // i#102458
1539  // Correction:
1540  // A proportional line spacing of the previous text frame
1541  // is added up to an own leading line spacing.
1542  // Otherwise, the maximum of the leading line spacing
1543  // of the previous text frame and the own leading line
1544  // spacing is built.
1545  if ( bPrevLineSpacingProportional )
1546  {
1547  nAdd += static_cast<SwTextFrame*>(pOwn)->GetLineSpace( true );
1548  }
1549  else
1550  {
1551  nAdd = std::max( nAdd, SwTwips(static_cast<SwTextFrame*>(pOwn)->GetLineSpace( true )) );
1552  }
1553  }
1554  nUpper += nAdd;
1555  }
1556  }
1557  else
1558  {
1559  nUpper = bContextualSpacing ? 0 : std::max(
1560  bHalfContextualSpacingPrev ? 0 : static_cast<tools::Long>(nPrevLowerSpace),
1561  bHalfContextualSpacing ? 0 : static_cast<tools::Long>(pAttrs->GetULSpace().GetUpper()) );
1562 
1563  // i#11859 - consideration of the line spacing
1564  // for the upper spacing of a text frame
1565  if ( bUseFormerLineSpacing )
1566  {
1567  // former consideration
1568  if ( pOwn->IsTextFrame() )
1569  nUpper = std::max( nUpper, SwTwips(static_cast<SwTextFrame*>(pOwn)->GetLineSpace()) );
1570  if ( nPrevLineSpacing != 0 )
1571  {
1572  nUpper = std::max( nUpper, nPrevLineSpacing );
1573  }
1574  }
1575  else
1576  {
1577  // new consideration:
1578  // Only the proportional line spacing of the previous
1579  // text frame is considered for the upper spacing and
1580  // the line spacing values are add up and added to
1581  // the paragraph spacing instead of building the
1582  // maximum of the line spacings and the paragraph spacing.
1583  SwTwips nAdd = nPrevLineSpacing;
1584  if ( pOwn->IsTextFrame() )
1585  {
1586  // i#102458
1587  // Correction:
1588  // A proportional line spacing of the previous text frame
1589  // is added up to an own leading line spacing.
1590  // Otherwise, the maximum of the leading line spacing
1591  // of the previous text frame and the own leading line
1592  // spacing is built.
1593  if ( bPrevLineSpacingProportional )
1594  {
1595  nAdd += static_cast<SwTextFrame*>(pOwn)->GetLineSpace( true );
1596  }
1597  else
1598  {
1599  nAdd = std::max( nAdd, SwTwips(static_cast<SwTextFrame*>(pOwn)->GetLineSpace( true )) );
1600  }
1601  }
1602  nUpper += nAdd;
1603  }
1604  }
1605  }
1608  {
1609  nUpper = pAttrs->GetULSpace().GetUpper();
1610  }
1611  }
1612 
1613  // i#25029 - pass previous frame <pPrevFrame>
1614  // to method <GetTopLine(..)>, if parameter <pPr> is set.
1615  // Note: parameter <pPr> is set, if method is called from <SwTextFrame::WouldFit(..)>
1616  nUpper += pAttrs->GetTopLine( m_rThis, (pPr ? pPrevFrame : nullptr) );
1617 
1618  // i#11860 - consider value of new parameter <_bConsiderGrid>
1619  // and use new method <GetUpperSpaceAmountConsideredForPageGrid(..)>
1620 
1621  //consider grid in square page mode
1622  if ( _bConsiderGrid && m_rThis.GetUpper()->GetFormat()->GetDoc()->IsSquaredPageMode() )
1623  {
1624  nUpper += GetUpperSpaceAmountConsideredForPageGrid_( nUpper );
1625  }
1626  return nUpper;
1627 }
1628 
1636  const SwTwips _nUpperSpaceWithoutGrid ) const
1637 {
1638  SwTwips nUpperSpaceAmountConsideredForPageGrid = 0;
1639 
1640  if ( m_rThis.IsInDocBody() && m_rThis.GetAttrSet()->GetParaGrid().GetValue() )
1641  {
1642  const SwPageFrame* pPageFrame = m_rThis.FindPageFrame();
1643  SwTextGridItem const*const pGrid(GetGridItem(pPageFrame));
1644  if( pGrid )
1645  {
1646  const SwFrame* pBodyFrame = pPageFrame->FindBodyCont();
1647  if ( pBodyFrame )
1648  {
1649  const tools::Long nGridLineHeight =
1650  pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
1651 
1652  SwRectFnSet aRectFnSet(&m_rThis);
1653  const SwTwips nBodyPrtTop = aRectFnSet.GetPrtTop(*pBodyFrame);
1654  const SwTwips nProposedPrtTop =
1655  aRectFnSet.YInc( aRectFnSet.GetTop(m_rThis.getFrameArea()),
1656  _nUpperSpaceWithoutGrid );
1657 
1658  const SwTwips nSpaceAbovePrtTop =
1659  aRectFnSet.YDiff( nProposedPrtTop, nBodyPrtTop );
1660  const SwTwips nSpaceOfCompleteLinesAbove =
1661  nGridLineHeight * ( nSpaceAbovePrtTop / nGridLineHeight );
1662  SwTwips nNewPrtTop =
1663  aRectFnSet.YInc( nBodyPrtTop, nSpaceOfCompleteLinesAbove );
1664  if ( aRectFnSet.YDiff( nProposedPrtTop, nNewPrtTop ) > 0 )
1665  {
1666  nNewPrtTop = aRectFnSet.YInc( nNewPrtTop, nGridLineHeight );
1667  }
1668 
1669  const SwTwips nNewUpperSpace =
1670  aRectFnSet.YDiff( nNewPrtTop,
1671  aRectFnSet.GetTop(m_rThis.getFrameArea()) );
1672 
1673  nUpperSpaceAmountConsideredForPageGrid =
1674  nNewUpperSpace - _nUpperSpaceWithoutGrid;
1675 
1676  OSL_ENSURE( nUpperSpaceAmountConsideredForPageGrid >= 0,
1677  "<SwFlowFrame::GetUpperSpaceAmountConsideredForPageGrid(..)> - negative space considered for page grid!" );
1678  }
1679  }
1680  }
1681  return nUpperSpaceAmountConsideredForPageGrid;
1682 }
1683 
1690 {
1691  SwTwips nUpperSpaceAmountOfPrevFrame = 0;
1692 
1693  const SwFrame* pPrevFrame = GetPrevFrameForUpperSpaceCalc_();
1694  if ( pPrevFrame )
1695  {
1696  SwTwips nPrevLowerSpace = 0;
1697  SwTwips nPrevLineSpacing = 0;
1698  // i#102458
1699  bool bDummy = false;
1700  GetSpacingValuesOfFrame( (*pPrevFrame), nPrevLowerSpace, nPrevLineSpacing, bDummy, lcl_IdenticalStyles(pPrevFrame, &m_rThis));
1701  if ( nPrevLowerSpace > 0 || nPrevLineSpacing > 0 )
1702  {
1704  if ( rIDSA.get(DocumentSettingId::PARA_SPACE_MAX) ||
1706  {
1707  nUpperSpaceAmountOfPrevFrame = nPrevLowerSpace + nPrevLineSpacing;
1708  }
1709  else
1710  {
1711  nUpperSpaceAmountOfPrevFrame = std::max( nPrevLowerSpace, nPrevLineSpacing );
1712  }
1713  }
1714  }
1715 
1716  return nUpperSpaceAmountOfPrevFrame;
1717 }
1718 
1726 {
1727  SwTwips nUpperSpaceAmountConsideredForPrevFrameAndPageGrid = 0;
1728 
1730  {
1731  nUpperSpaceAmountConsideredForPrevFrameAndPageGrid =
1734  ? GetUpperSpaceAmountConsideredForPageGrid_( CalcUpperSpace( nullptr, nullptr, false ) )
1735  : 0 );
1736  }
1737 
1738  return nUpperSpaceAmountConsideredForPrevFrameAndPageGrid;
1739 }
1740 
1741 // Calculation of lower space
1742 
1744 {
1745  SwTwips nLowerSpace = 0;
1746 
1747  std::unique_ptr<SwBorderAttrAccess> pAttrAccess;
1748  if ( !_pAttrs )
1749  {
1750  pAttrAccess = std::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), &m_rThis);
1751  _pAttrs = pAttrAccess->Get();
1752  }
1753 
1754  bool bCommonBorder = true;
1755  if ( m_rThis.IsInSct() && m_rThis.GetUpper()->IsColBodyFrame() )
1756  {
1757  const SwSectionFrame* pSectFrame = m_rThis.FindSctFrame();
1758  bCommonBorder = pSectFrame->GetFormat()->GetBalancedColumns().GetValue();
1759  }
1760  nLowerSpace = bCommonBorder ?
1761  _pAttrs->GetBottomLine( m_rThis ) :
1762  _pAttrs->CalcBottomLine();
1763 
1764  // i#26250
1765  // - correct consideration of table frames
1766  // - use new method <CalcAddLowerSpaceAsLastInTableCell(..)>
1767  if ( ( ( m_rThis.IsTabFrame() && m_rThis.GetUpper()->IsInTab() ) ||
1768  // No lower spacing, if frame has a follow
1769  ( m_rThis.IsInTab() && !GetFollow() ) ) &&
1770  !m_rThis.GetIndNext() )
1771  {
1772  nLowerSpace += CalcAddLowerSpaceAsLastInTableCell( _pAttrs );
1773  }
1774 
1775  // tdf#128195 Consider para spacing below last paragraph in header
1776  bool bHasSpacingBelowPara = m_rThis.GetUpper()->GetFormat()->getIDocumentSettingAccess().get(
1778  if (bHasSpacingBelowPara && !m_rThis.IsInFly() && m_rThis.FindFooterOrHeader() && !GetFollow()
1779  && !m_rThis.GetIndNext())
1780  nLowerSpace += _pAttrs->GetULSpace().GetLower() + _pAttrs->CalcLineSpacing();
1781 
1782  return nLowerSpace;
1783 }
1784 
1791  const SwBorderAttrs* _pAttrs ) const
1792 {
1793  SwTwips nAdditionalLowerSpace = 0;
1794 
1797  {
1798  const SwFrame* pFrame = &m_rThis;
1799  if ( pFrame->IsSctFrame() )
1800  {
1801  const SwSectionFrame* pSectFrame = static_cast<const SwSectionFrame*>(pFrame);
1802  pFrame = pSectFrame->FindLastContent();
1803  if ( pFrame && pFrame->IsInTab() )
1804  {
1805  const SwTabFrame* pTableFrame = pFrame->FindTabFrame();
1806  if ( pSectFrame->IsAnLower( pTableFrame ) )
1807  {
1808  pFrame = pTableFrame;
1809  }
1810  }
1811  }
1812 
1813  std::unique_ptr<SwBorderAttrAccess> pAttrAccess;
1814  if (pFrame && (!_pAttrs || pFrame != &m_rThis))
1815  {
1816  pAttrAccess = std::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), pFrame);
1817  _pAttrs = pAttrAccess->Get();
1818  }
1819 
1820  if (_pAttrs)
1821  {
1822  nAdditionalLowerSpace += _pAttrs->GetULSpace().GetLower();
1823 
1825  {
1826  nAdditionalLowerSpace += _pAttrs->CalcLineSpacing();
1827  }
1828  }
1829  }
1830 
1831  return nAdditionalLowerSpace;
1832 }
1833 
1835 bool SwFlowFrame::CheckMoveFwd( bool& rbMakePage, bool bKeep, bool bIgnoreMyOwnKeepValue )
1836 {
1837  const SwFrame* pNxt = m_rThis.GetIndNext();
1838 
1839  if ( bKeep &&
1840  ( !pNxt || ( pNxt->IsTextFrame() && static_cast<const SwTextFrame*>(pNxt)->IsEmptyMaster() ) ) &&
1841  ( nullptr != (pNxt = m_rThis.FindNext()) ) && IsKeepFwdMoveAllowed(bIgnoreMyOwnKeepValue) )
1842  {
1843  if( pNxt->IsSctFrame() )
1844  { // Don't get fooled by empty SectionFrames
1845  const SwFrame* pTmp = nullptr;
1846  while( pNxt && pNxt->IsSctFrame() &&
1847  ( !static_cast<const SwSectionFrame*>(pNxt)->GetSection() ||
1848  nullptr == ( pTmp = static_cast<const SwSectionFrame*>(pNxt)->ContainsAny() ) ) )
1849  {
1850  pNxt = pNxt->FindNext();
1851  pTmp = nullptr;
1852  }
1853  if( pTmp )
1854  pNxt = pTmp; // the content of the next notempty sectionfrm
1855  }
1856  if( pNxt && pNxt->isFrameAreaPositionValid() )
1857  {
1858  bool bMove = false;
1859  const SwSectionFrame *pSct = m_rThis.FindSctFrame();
1860  if( pSct && !pSct->isFrameAreaSizeValid() )
1861  {
1862  const SwSectionFrame* pNxtSct = pNxt->FindSctFrame();
1863  if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
1864  bMove = true;
1865  }
1866  else
1867  bMove = true;
1868  if( bMove )
1869  {
1870  //Keep together with the following frame
1871  MoveFwd( rbMakePage, false );
1872  return true;
1873  }
1874  }
1875  }
1876 
1877  bool bMovedFwd = false;
1878 
1879  if ( m_rThis.GetIndPrev() )
1880  {
1881  if ( IsPrevObjMove() ) // Should we care about objects of the Prev?
1882  {
1883  bMovedFwd = true;
1884  if ( !MoveFwd( rbMakePage, false ) )
1885  rbMakePage = false;
1886  }
1887  else
1888  {
1889  if ( IsPageBreak( false ) )
1890  {
1891  while ( MoveFwd( rbMakePage, true ) )
1892  /* do nothing */;
1893  rbMakePage = false;
1894  bMovedFwd = true;
1895  }
1896  else if ( IsColBreak ( false ) )
1897  {
1898  const SwPageFrame *pPage = m_rThis.FindPageFrame();
1899  SwFrame *pCol = m_rThis.FindColFrame();
1900  do
1901  { MoveFwd( rbMakePage, false );
1902  SwFrame *pTmp = m_rThis.FindColFrame();
1903  if( pTmp != pCol )
1904  {
1905  bMovedFwd = true;
1906  pCol = pTmp;
1907  }
1908  else
1909  break;
1910  } while ( IsColBreak( false ) );
1911  if ( pPage != m_rThis.FindPageFrame() )
1912  rbMakePage = false;
1913  }
1914  }
1915  }
1916  return bMovedFwd;
1917 }
1918 
1920 {
1921  return m_rThis.IsTabFrame() || m_rThis.IsInTab();
1922 }
1923 
1927 bool SwFlowFrame::MoveFwd( bool bMakePage, bool bPageBreak, bool bMoveAlways )
1928 {
1931  if (m_rThis.IsInFootnote())
1932  {
1933  assert(!ForbiddenForFootnoteCntFwd()); // prevented by IsMoveable()
1934  if (!m_rThis.IsContentFrame() || !pOldBoss)
1935  {
1936  SAL_WARN("sw.core", "Tables in footnotes are not truly supported");
1937  return false;
1938  }
1939  return static_cast<SwContentFrame&>(m_rThis).MoveFootnoteCntFwd( bMakePage, pOldBoss );
1940  }
1941 
1942  if( !IsFwdMoveAllowed() && !bMoveAlways )
1943  {
1944  bool bNoFwd = true;
1945  if( m_rThis.IsInSct() )
1946  {
1948  bNoFwd = !pBoss->IsInSct() || ( !pBoss->Lower()->GetNext() &&
1949  !pBoss->GetPrev() );
1950  }
1951 
1952  // Allow the MoveFwd even if we do not have an IndPrev in these cases:
1953  if ( m_rThis.IsInTab() &&
1954  ( !m_rThis.IsTabFrame() ||
1955  ( m_rThis.GetUpper()->IsInTab() &&
1957  nullptr != m_rThis.GetNextCellLeaf() )
1958  {
1959  bNoFwd = false;
1960  }
1961 
1962  if( bNoFwd )
1963  {
1964  // It's allowed to move PageBreaks if the Frame isn't the first
1965  // one on the page.
1966  if ( !bPageBreak )
1967  return false;
1968 
1969  const SwFrame *pCol = m_rThis.FindColFrame();
1970  if ( !pCol || !pCol->GetPrev() )
1971  return false;
1972  }
1973  }
1974 
1975  std::unique_ptr<SwFrameDeleteGuard> xDeleteGuard(bMakePage ? new SwFrameDeleteGuard(pOldBoss) : nullptr);
1976 
1977  bool bSamePage = true;
1978  SwLayoutFrame *pNewUpper =
1979  m_rThis.GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, true );
1980 
1981  if ( pNewUpper )
1982  {
1984  SwPageFrame *pOldPage = pOldBoss->FindPageFrame();
1985  // We move ourself and all the direct successors before the
1986  // first ContentFrame below the new Upper.
1987 
1988  // If our NewUpper lies in a SectionFrame, we need to make sure
1989  // that it won't destroy itself in Calc.
1990  SwSectionFrame* pSect = pNewUpper->FindSctFrame();
1991  if( pSect )
1992  {
1993  // If we only switch column within our SectionFrame, we better don't
1994  // call Calc, as this would format the SectionFrame, which in turn would
1995  // call us again, etc.
1996  if( pSect != m_rThis.FindSctFrame() )
1997  {
1998  bool bUnlock = !pSect->IsColLocked();
1999  pSect->ColLock();
2000  pNewUpper->Calc(m_rThis.getRootFrame()->GetCurrShell()->GetOut());
2001  if( bUnlock )
2002  pSect->ColUnlock();
2003  }
2004  }
2005  // Do not calculate split cell frames.
2006  else if ( !pNewUpper->IsCellFrame() || pNewUpper->Lower() )
2007  pNewUpper->Calc(m_rThis.getRootFrame()->GetCurrShell()->GetOut());
2008 
2009  SwFootnoteBossFrame *pNewBoss = pNewUpper->FindFootnoteBossFrame();
2010  bool bBossChg = pNewBoss != pOldBoss;
2011  pNewBoss = pNewBoss->FindFootnoteBossFrame( true );
2012  pOldBoss = pOldBoss->FindFootnoteBossFrame( true );
2013  SwPageFrame* pNewPage = pOldPage;
2014 
2015  xDeleteGuard.reset();
2016 
2017  // First, we move the footnotes.
2018  bool bFootnoteMoved = false;
2019 
2020  // i#26831
2021  // If pSect has just been created, the printing area of pSect has
2022  // been calculated based on the first content of its follow.
2023  // In this case we prefer to call a SimpleFormat for this new
2024  // section after we inserted the contents. Otherwise the section
2025  // frame will invalidate its lowers, if its printing area changes
2026  // in SwSectionFrame::Format, which can cause loops.
2027  const bool bForceSimpleFormat = pSect && pSect->HasFollow() &&
2028  !pSect->ContainsAny();
2029 
2030  if ( pNewBoss != pOldBoss )
2031  {
2032  pNewPage = pNewBoss->FindPageFrame();
2033  bSamePage = pNewPage == pOldPage;
2034  // Set deadline, so the footnotes don't think up
2035  // silly things...
2036  SwRectFnSet aRectFnSet(pOldBoss);
2037  SwSaveFootnoteHeight aHeight( pOldBoss,
2038  aRectFnSet.GetBottom(pOldBoss->getFrameArea()) );
2039  SwContentFrame* pStart = m_rThis.IsContentFrame() ?
2040  static_cast<SwContentFrame*>(&m_rThis) : static_cast<SwLayoutFrame&>(m_rThis).ContainsContent();
2041  OSL_ENSURE( pStart || ( m_rThis.IsTabFrame() && !static_cast<SwTabFrame&>(m_rThis).Lower() ),
2042  "MoveFwd: Missing Content" );
2043  SwLayoutFrame* pBody = pStart ? ( pStart->IsTextFrame() ?
2044  const_cast<SwBodyFrame *>(static_cast<SwTextFrame*>(pStart)->FindBodyFrame()) : nullptr ) : nullptr;
2045  if( pBody )
2046  bFootnoteMoved = pBody->MoveLowerFootnotes( pStart, pOldBoss, pNewBoss,
2047  false);
2048  }
2049  // It's possible when dealing with SectionFrames that we have been moved
2050  // by pNewUpper->Calc(), for instance into the pNewUpper.
2051  // MoveSubTree or PasteTree respectively is not prepared to handle such a
2052  // situation.
2053  if( pNewUpper != m_rThis.GetUpper() )
2054  {
2055  // i#27145
2056  SwSectionFrame* pOldSct = nullptr;
2057  if ( m_rThis.GetUpper()->IsSctFrame() )
2058  {
2059  pOldSct = static_cast<SwSectionFrame*>(m_rThis.GetUpper());
2060  }
2061 
2062  MoveSubTree( pNewUpper, pNewUpper->Lower() );
2063 
2064  // i#27145
2065  if ( pOldSct && pOldSct->GetSection() )
2066  {
2067  // Prevent loops by setting the new height at
2068  // the section frame if footnotes have been moved.
2069  // Otherwise the call of SwLayNotify::~SwLayNotify() for
2070  // the (invalid) section frame will invalidate the first
2071  // lower of its follow, because it grows due to the removed
2072  // footnotes.
2073  // Note: If pOldSct has become empty during MoveSubTree, it
2074  // has already been scheduled for removal. No SimpleFormat
2075  // for these.
2076  pOldSct->SimpleFormat();
2077  }
2078 
2079  // i#26831
2080  if ( bForceSimpleFormat )
2081  {
2082  pSect->SimpleFormat();
2083  }
2084 
2085  if ( bFootnoteMoved && !bSamePage )
2086  {
2087  pOldPage->UpdateFootnoteNum();
2088  pNewPage->UpdateFootnoteNum();
2089  }
2090 
2091  if( bBossChg )
2092  {
2093  m_rThis.Prepare( PrepareHint::BossChanged, nullptr, false );
2094  if( !bSamePage )
2095  {
2097  if ( pSh && !pSh->Imp()->IsUpdateExpFields() )
2098  pSh->GetDoc()->getIDocumentFieldsAccess().SetNewFieldLst(true); // Will be done by CalcLayout() later on!
2099 
2100  pNewPage->InvalidateSpelling();
2101  pNewPage->InvalidateSmartTags();
2102  pNewPage->InvalidateAutoCompleteWords();
2103  pNewPage->InvalidateWordCount();
2104  }
2105  }
2106  }
2107  // No <CheckPageDesc(..)> in online layout
2108  const SwViewShell *pSh = m_rThis.getRootFrame()->GetCurrShell();
2109 
2110  if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
2111  {
2112  // i#106452
2113  // check page description not only in situation with sections.
2114  if ( !bSamePage &&
2116  pOldPage->GetPageDesc()->GetFollow() != pNewPage->GetPageDesc() ) )
2117  {
2118  SwFrame::CheckPageDescs( pNewPage, false );
2119  }
2120  }
2121  }
2122  return bSamePage;
2123 }
2124 
2131 bool SwFlowFrame::MoveBwd( bool &rbReformat )
2132 {
2133  SwFlowFrame::SetMoveBwdJump( false );
2134 
2135  SwFootnoteFrame* pFootnote = m_rThis.FindFootnoteFrame();
2136  if ( pFootnote && pFootnote->IsBackMoveLocked() )
2137  return false;
2138 
2139  // Text frames, which are directly inside
2140  // tables aren't allowed to move backward.
2141  if ( m_rThis.IsTextFrame() && m_rThis.IsInTab() )
2142  {
2143  const SwLayoutFrame* pUpperFrame = m_rThis.GetUpper();
2144  while ( pUpperFrame )
2145  {
2146  if ( pUpperFrame->IsTabFrame() || pUpperFrame->IsRowFrame() )
2147  {
2148  return false;
2149  }
2150  // If the text frame is a follow-section-in-table, that can move
2151  // backward as well.
2152  bool bIsFollowSection = pUpperFrame->IsSctFrame() && static_cast<const SwSectionFrame*>(pUpperFrame)->GetPrecede();
2153 
2154  // If the text frame is a follow-in-table, that can move
2155  // backward as well.
2156  bool bIsFollow = const_cast<SwLayoutFrame*>(pUpperFrame)->GetPrevCellLeaf();
2157 
2158  if ( ( pUpperFrame->IsColumnFrame() && pUpperFrame->IsInSct() ) || bIsFollowSection || bIsFollow )
2159  {
2160  break;
2161  }
2162  pUpperFrame = pUpperFrame->GetUpper();
2163  }
2164  }
2165 
2167  if (!pOldBoss)
2168  return false;
2169 
2170  SwPageFrame * const pOldPage = pOldBoss->FindPageFrame();
2171  SwLayoutFrame *pNewUpper = nullptr;
2172  bool bCheckPageDescs = false;
2173  bool bCheckPageDescOfNextPage = false;
2174 
2175  if ( pFootnote )
2176  {
2177  // If the footnote already sits on the same page/column as the reference,
2178  // we can't flow back. The breaks don't need to be checked for footnotes.
2179 
2180  // i#37084 FindLastContent does not necessarily
2181  // have to have a result != 0
2182  SwFrame* pRef = nullptr;
2183  const bool bEndnote = pFootnote->GetAttr()->GetFootnote().IsEndNote();
2184  const IDocumentSettingAccess& rSettings
2185  = pFootnote->GetAttrSet()->GetDoc()->getIDocumentSettingAccess();
2186  if( bEndnote && pFootnote->IsInSct() )
2187  {
2188  SwSectionFrame* pSect = pFootnote->FindSctFrame();
2189  if( pSect->IsEndnAtEnd() )
2190  // Endnotes at the end of the section.
2191  pRef = pSect->FindLastContent( SwFindMode::LastCnt );
2192  }
2193  else if (bEndnote && rSettings.get(DocumentSettingId::CONTINUOUS_ENDNOTES))
2194  {
2195  // Endnotes at the end of the document.
2197  pRef = pPage->FindLastBodyContent();
2198  }
2199  if( !pRef )
2200  // Endnotes on a separate page.
2201  pRef = pFootnote->GetRef();
2202 
2203  OSL_ENSURE( pRef, "MoveBwd: Endnote for an empty section?" );
2204 
2205  if( !bEndnote )
2206  pOldBoss = pOldBoss->FindFootnoteBossFrame( true );
2207  SwFootnoteBossFrame *pRefBoss = pRef->FindFootnoteBossFrame( !bEndnote );
2208  if ( pOldBoss != pRefBoss &&
2209 
2210  ( !bEndnote ||
2211  pRefBoss->IsBefore( pOldBoss ) )
2212  )
2213  pNewUpper = m_rThis.GetLeaf( MAKEPAGE_FTN, false );
2214  }
2215  else if ( IsPageBreak( true ) ) // Do we have to respect a PageBreak?
2216  {
2217  // If the previous page doesn't have a Frame in the body,
2218  // flowing back makes sense despite the PageBreak (otherwise,
2219  // we'd get an empty page).
2220  // Of course we need to overlook empty pages!
2221  const SwFrame *pFlow = &m_rThis;
2222  do
2223  {
2224  pFlow = pFlow->FindPrev();
2225  } while ( pFlow &&
2226  ( pFlow->FindPageFrame() == pOldPage ||
2227  !pFlow->IsInDocBody() ) );
2228  if ( pFlow )
2229  {
2230  tools::Long nDiff = pOldPage->GetPhyPageNum() - pFlow->GetPhyPageNum();
2231  if ( nDiff > 1 )
2232  {
2233  if ( static_cast<SwPageFrame*>(pOldPage->GetPrev())->IsEmptyPage() )
2234  nDiff -= 1;
2235  if ( nDiff > 1 )
2236  {
2237  pNewUpper = m_rThis.GetLeaf( MAKEPAGE_NONE, false );
2238  // i#53139
2239  // Now <pNewUpper> is a previous layout frame, which contains
2240  // content. But the new upper layout frame has to be the next one.
2241  // Thus, hack for issue i14206 no longer needed, but fix for issue 114442
2242  // Correct fix for i53139
2243  // Check for wrong page description before using next new upper.
2244  // i#66051 - further correction of fix for i53139
2245  // Check for correct type of new next upper layout frame
2246  // Another correction of fix for i53139
2247  // Assumption, that in all cases <pNewUpper> is a previous
2248  // layout frame, which contains content, is wrong.
2249  // Another correction of fix for i53139
2250  // Beside type check, check also, if proposed new next upper
2251  // frame is inside the same frame types.
2252  // i#73194 - and yet another correction
2253  // of fix for i53139:
2254  // Assure that the new next upper layout frame doesn't
2255  // equal the current one.
2256  // E.g.: content is on page 3, on page 2 is only a 'ghost'
2257  // section and on page 1 is normal content. Method <FindPrev(..)>
2258  // will find the last content of page 1, but <GetLeaf(..)>
2259  // returns new upper on page 2.
2260  if (pNewUpper && pNewUpper->Lower())
2261  {
2262  SwLayoutFrame* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, true );
2263  if ( pNewNextUpper &&
2264  pNewNextUpper != m_rThis.GetUpper() &&
2265  pNewNextUpper->GetType() == pNewUpper->GetType() &&
2266  pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2267  pNewNextUpper->IsInFootnote() == pNewUpper->IsInFootnote() &&
2268  pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2269  pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2270  !m_rThis.WrongPageDesc( pNewNextUpper->FindPageFrame() ) )
2271  {
2272  pNewUpper = pNewNextUpper;
2273  bCheckPageDescOfNextPage = true;
2274  }
2275  }
2276 
2277  bCheckPageDescs = true;
2278  }
2279  }
2280  }
2281  }
2282  else if ( IsColBreak( true ) )
2283  {
2284  // If the previous column doesn't contain a ContentFrame, flowing back
2285  // makes sense despite the ColumnBreak, as otherwise we'd get
2286  // an empty column.
2287  if( m_rThis.IsInSct() )
2288  {
2289  pNewUpper = m_rThis.GetLeaf( MAKEPAGE_NONE, false );
2290  if( pNewUpper && !SwFlowFrame::IsMoveBwdJump() &&
2291  ( pNewUpper->ContainsContent() ||
2292  ( ( !pNewUpper->IsColBodyFrame() ||
2293  !pNewUpper->GetUpper()->GetPrev() ) &&
2294  !pNewUpper->FindSctFrame()->GetPrev() ) ) )
2295  {
2296  pNewUpper = nullptr;
2297  }
2298  // i#53139
2299  // i#69409 - check <pNewUpper>
2300  // i#71065 - check <SwFlowFrame::IsMoveBwdJump()>
2301  else if ( pNewUpper && !SwFlowFrame::IsMoveBwdJump() )
2302  {
2303  // Now <pNewUpper> is a previous layout frame, which
2304  // contains content. But the new upper layout frame
2305  // has to be the next one.
2306  // Correct fix for i53139
2307  // Check for wrong page description before using next new upper.
2308  // i#66051 - further correction of fix for i53139
2309  // Check for correct type of new next upper layout frame
2310  // Another correction of fix for i53139
2311  // Beside type check, check also, if proposed new next upper
2312  // frame is inside the same frame types.
2313  SwLayoutFrame* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NOSECTION, true );
2314  if ( pNewNextUpper &&
2315  pNewNextUpper->GetType() == pNewUpper->GetType() &&
2316  pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2317  pNewNextUpper->IsInFootnote() == pNewUpper->IsInFootnote() &&
2318  pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2319  pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2320  !m_rThis.WrongPageDesc( pNewNextUpper->FindPageFrame() ) )
2321  {
2322  pNewUpper = pNewNextUpper;
2323  }
2324  }
2325  }
2326  else
2327  {
2328  const SwFrame *pCol = m_rThis.FindColFrame();
2329  bool bGoOn = true;
2330  bool bJump = false;
2331  do
2332  {
2333  if ( pCol->GetPrev() )
2334  pCol = pCol->GetPrev();
2335  else
2336  {
2337  bGoOn = false;
2338  pCol = m_rThis.GetLeaf( MAKEPAGE_NONE, false );
2339  }
2340  if ( pCol )
2341  {
2342  // ColumnFrames now with BodyFrame
2343  SwLayoutFrame* pColBody = pCol->IsColumnFrame() ?
2344  const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pCol)->Lower())) :
2345  const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pCol));
2346  if ( pColBody->ContainsContent() )
2347  {
2348  bGoOn = false; // We have content here! we accept this
2349  // only if GetLeaf() has set the MoveBwdJump.
2351  {
2352  pNewUpper = pColBody;
2353  // i#53139
2354  // Now <pNewUpper> is a previous layout frame, which
2355  // contains content. But the new upper layout frame
2356  // has to be the next one.
2357  // Correct fix for i53139
2358  // Check for wrong page description before using next new upper.
2359  // i#66051 - further correction of fix for i53139
2360  // Check for correct type of new next upper layout frame
2361  // Another correction of fix for i53139
2362  // Beside type check, check also, if proposed new next upper
2363  // frame is inside the same frame types.
2364  // i#71065
2365  // Check that the proposed new next upper layout
2366  // frame isn't the current one.
2367  SwLayoutFrame* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, true );
2368  if ( pNewNextUpper &&
2369  pNewNextUpper != m_rThis.GetUpper() &&
2370  pNewNextUpper->GetType() == pNewUpper->GetType() &&
2371  pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2372  pNewNextUpper->IsInFootnote() == pNewUpper->IsInFootnote() &&
2373  pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2374  pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2375  !m_rThis.WrongPageDesc( pNewNextUpper->FindPageFrame() ) )
2376  {
2377  pNewUpper = pNewNextUpper;
2378  }
2379  }
2380  }
2381  else
2382  {
2383  if( pNewUpper ) // We already had an empty column, in other
2384  bJump = true; // words we skipped one.
2385  pNewUpper = pColBody; // this empty column could be considered,
2386  // but we continue searching nevertheless.
2387  }
2388  }
2389  } while( bGoOn );
2390  if( bJump )
2392  }
2393  }
2394  else // No breaks - we can flow back.
2395  pNewUpper = m_rThis.GetLeaf( MAKEPAGE_NONE, false );
2396 
2397  // i#27801 - no move backward of 'master' text frame,
2398  // if - due to its object positioning - it isn't allowed to be on the new page frame
2399  // i#44049 - add another condition for not moving backward
2400  // If one of its objects has restarted the layout process, moving backward
2401  // isn't sensible either.
2402  // i#47697 - refine condition made for issue i44049
2403  // - allow move backward as long as the anchored object is only temporarily
2404  // positions considering its wrapping style.
2405  if ( pNewUpper &&
2406  m_rThis.IsTextFrame() && !IsFollow() )
2407  {
2408  sal_uInt32 nToPageNum( 0 );
2409  const bool bMoveFwdByObjPos = SwLayouter::FrameMovedFwdByObjPos(
2410  *(pOldPage->GetFormat()->GetDoc()),
2411  static_cast<SwTextFrame&>(m_rThis),
2412  nToPageNum );
2413  if ( bMoveFwdByObjPos &&
2414  pNewUpper->FindPageFrame()->GetPhyPageNum() < nToPageNum )
2415  {
2416  pNewUpper = nullptr;
2417  }
2418  // i#44049 - check, if one of its anchored objects
2419  // has restarted the layout process.
2420  else if ( m_rThis.GetDrawObjs() )
2421  {
2422  for (SwAnchoredObject* pAnchoredObj : *m_rThis.GetDrawObjs())
2423  {
2424  // i#47697 - refine condition - see above
2425  if ( pAnchoredObj->RestartLayoutProcess() &&
2426  !pAnchoredObj->IsTmpConsiderWrapInfluence() )
2427  {
2428  pNewUpper = nullptr;
2429  break;
2430  }
2431  }
2432  }
2433  }
2434 
2435  // With Follows, it's only allowed to flow back if there's no neighbor
2436  // in the new environment (because that would be the Master).
2437  // (6677) If however we skipped empty pages, we still have to move.
2438  if ( pNewUpper && IsFollow() && pNewUpper->Lower() )
2439  {
2440  // i#79774
2441  // neglect empty sections in proposed new upper frame
2442  bool bProposedNewUpperContainsOnlyEmptySections( true );
2443  {
2444  const SwFrame* pLower( pNewUpper->Lower() );
2445  while ( pLower )
2446  {
2447  if ( pLower->IsSctFrame() &&
2448  !dynamic_cast<const SwSectionFrame&>(*pLower).GetSection() )
2449  {
2450  pLower = pLower->GetNext();
2451  continue;
2452  }
2453  else
2454  {
2455  bProposedNewUpperContainsOnlyEmptySections = false;
2456  break;
2457  }
2458  }
2459  }
2460  if ( !bProposedNewUpperContainsOnlyEmptySections )
2461  {
2463  {
2464  // Don't move after the Master, but into the next empty page.
2465  SwFrame *pFrame = pNewUpper->Lower();
2466  while ( pFrame->GetNext() )
2467  pFrame = pFrame->GetNext();
2468  pNewUpper = pFrame->GetLeaf( MAKEPAGE_INSERT, true );
2469  if( pNewUpper == m_rThis.GetUpper() ) // Did we end up in the same place?
2470  pNewUpper = nullptr; // If so, moving is not needed.
2471  }
2472  else
2473  pNewUpper = nullptr;
2474  }
2475  }
2476  if ( pNewUpper && !ShouldBwdMoved( pNewUpper, rbReformat ) )
2477  {
2478  if( !pNewUpper->Lower() )
2479  {
2480  if( pNewUpper->IsFootnoteContFrame() )
2481  {
2482  pNewUpper->Cut();
2483  SwFrame::DestroyFrame(pNewUpper);
2484  }
2485  else
2486  {
2487  SwSectionFrame* pSectFrame = pNewUpper->FindSctFrame();
2488 
2489  if ( pSectFrame && !pSectFrame->IsColLocked() &&
2490  !pSectFrame->ContainsContent() && !pSectFrame->ContainsAny( true ) )
2491  {
2492  pSectFrame->DelEmpty( true );
2493  SwFrame::DestroyFrame(pSectFrame);
2495  }
2496  }
2497  }
2498  pNewUpper = nullptr;
2499  }
2500 
2501  // i#21478 - don't move backward, if flow frame wants to
2502  // keep with next frame and next frame is locked.
2503  // i#38232 - If next frame is a table, do *not* check,
2504  // if it's locked.
2505  if ( pNewUpper && !IsFollow() &&
2506  m_rThis.GetAttrSet()->GetKeep().GetValue() && m_rThis.GetIndNext() )
2507  {
2508  SwFrame* pIndNext = m_rThis.GetIndNext();
2509  // i#38232
2510  if ( !pIndNext->IsTabFrame() )
2511  {
2512  // get first content of section, while empty sections are skipped
2513  while ( pIndNext && pIndNext->IsSctFrame() )
2514  {
2515  if( static_cast<SwSectionFrame*>(pIndNext)->GetSection() )
2516  {
2517  SwFrame* pTmp = static_cast<SwSectionFrame*>(pIndNext)->ContainsAny();
2518  if ( pTmp )
2519  {
2520  pIndNext = pTmp;
2521  break;
2522  }
2523  }
2524  pIndNext = pIndNext->GetIndNext();
2525  }
2526  OSL_ENSURE( !pIndNext || dynamic_cast<const SwTextFrame*>( pIndNext) != nullptr,
2527  "<SwFlowFrame::MovedBwd(..)> - incorrect next found." );
2528  if ( pIndNext && pIndNext->IsFlowFrame() &&
2530  {
2531  pNewUpper = nullptr;
2532  }
2533  }
2534  }
2535 
2536  // i#65250
2537  // layout loop control for flowing content again and again moving
2538  // backward under the same layout condition.
2539  if ( pNewUpper && !IsFollow() &&
2540  pNewUpper != m_rThis.GetUpper() &&
2541  SwLayouter::MoveBwdSuppressed( *(pOldPage->GetFormat()->GetDoc()),
2542  *this, *pNewUpper ) )
2543  {
2544  SwLayoutFrame* pNextNewUpper = pNewUpper->GetLeaf(
2545  ( !m_rThis.IsSctFrame() && m_rThis.IsInSct() )
2547  : MAKEPAGE_NONE,
2548  true );
2549  // i#73194 - make code robust
2550  OSL_ENSURE( pNextNewUpper, "<SwFlowFrame::MoveBwd(..)> - missing next new upper" );
2551  if ( pNextNewUpper &&
2552  ( pNextNewUpper == m_rThis.GetUpper() ||
2553  pNextNewUpper->GetType() != m_rThis.GetUpper()->GetType() ) )
2554  {
2555  // tdf#107398 do not leave empty footnote container around
2556  if (!pNewUpper->Lower() && pNewUpper->IsFootnoteContFrame())
2557  {
2558  pNewUpper->Cut();
2559  SwFrame::DestroyFrame(pNewUpper);
2560  }
2561  pNewUpper = nullptr;
2562  OSL_FAIL( "<SwFlowFrame::MoveBwd(..)> - layout loop control for layout action <Move Backward> applied!" );
2563  }
2564  }
2565 
2566  OSL_ENSURE( pNewUpper != m_rThis.GetUpper(),
2567  "<SwFlowFrame::MoveBwd(..)> - moving backward to the current upper frame!?" );
2568  if ( pNewUpper )
2569  {
2571  if ( pNewUpper->IsFootnoteContFrame() )
2572  {
2573  // I may have gotten a Container
2575  pNew->Paste( pNewUpper );
2576  pNewUpper = pNew;
2577  }
2578  if( pNewUpper->IsFootnoteFrame() && m_rThis.IsInSct() )
2579  {
2581  // If we're in a section of a footnote, we may need to create
2582  // a SwSectionFrame in the new upper
2583  if( pSct->IsInFootnote() )
2584  {
2585  SwFrame* pTmp = pNewUpper->Lower();
2586  if( pTmp )
2587  {
2588  while( pTmp->GetNext() )
2589  pTmp = pTmp->GetNext();
2590  if( !pTmp->IsSctFrame() ||
2591  static_cast<SwSectionFrame*>(pTmp)->GetFollow() != pSct )
2592  pTmp = nullptr;
2593  }
2594  if( pTmp )
2595  pNewUpper = static_cast<SwSectionFrame*>(pTmp);
2596  else
2597  {
2598  pSct = new SwSectionFrame( *pSct, true );
2599  pSct->Paste( pNewUpper );
2600  pSct->Init();
2601  pNewUpper = pSct;
2602  pSct->SimpleFormat();
2603  }
2604  }
2605  }
2606  bool bUnlock = false;
2607  bool bFollow = false;
2608  // Lock section. Otherwise, it could get destroyed if the only Content
2609  // moves e.g. from the second into the first column.
2610  SwSectionFrame* pSect = pNewUpper->FindSctFrame();
2611  if( pSect )
2612  {
2613  bUnlock = !pSect->IsColLocked();
2614  pSect->ColLock();
2615  bFollow = pSect->HasFollow();
2616  }
2617 
2618  {
2619  auto const pOld = m_rThis.GetUpper();
2620 #if BOOST_VERSION < 105600
2621  std::list<SwFrameDeleteGuard> g;
2622 #else
2623  ::std::optional<SwFrameDeleteGuard> g;
2624 #endif
2625  if (m_rThis.GetUpper()->IsCellFrame())
2626  {
2627  // note: IsFollowFlowRow() is never set for new-style tables
2628  SwTabFrame const*const pTabFrame(m_rThis.FindTabFrame());
2629  if ( pTabFrame->IsFollow()
2630  && static_cast<SwTabFrame const*>(pTabFrame->GetPrecede())->HasFollowFlowLine()
2631  && pTabFrame->GetFirstNonHeadlineRow() == m_rThis.GetUpper()->GetUpper())
2632  {
2633  // lock follow-flow-row (similar to sections above)
2634 #if BOOST_VERSION < 105600
2635  g.emplace_back(m_rThis.GetUpper()->GetUpper());
2636 #else
2637  g.emplace(m_rThis.GetUpper()->GetUpper());
2638 #endif
2640  }
2641  }
2642  pNewUpper->Calc(m_rThis.getRootFrame()->GetCurrShell()->GetOut());
2643  SAL_WARN_IF(pOld != m_rThis.GetUpper(), "sw.core",
2644  "MoveBwd(): pNewUpper->Calc() moved this frame?");
2645  }
2646 
2647  m_rThis.Cut();
2648 
2649  // optimization: format section, if its size is invalidated and if it's
2650  // the new parent of moved backward frame.
2651  bool bFormatSect( false );
2652  if( bUnlock )
2653  {
2654  pSect->ColUnlock();
2655  if( pSect->HasFollow() != bFollow )
2656  {
2657  pSect->InvalidateSize();
2658  // - optimization
2659  if ( pSect == pNewUpper )
2660  bFormatSect = true;
2661  }
2662  }
2663 
2664  m_rThis.Paste( pNewUpper );
2665  // - optimization
2666  if ( bFormatSect )
2667  pSect->Calc(m_rThis.getRootFrame()->GetCurrShell()->GetOut());
2668 
2669  SwPageFrame *pNewPage = m_rThis.FindPageFrame();
2670  if( pNewPage != pOldPage )
2671  {
2672  m_rThis.Prepare( PrepareHint::BossChanged, static_cast<const void*>(pOldPage), false );
2674  if ( pSh && !pSh->Imp()->IsUpdateExpFields() )
2675  pSh->GetDoc()->getIDocumentFieldsAccess().SetNewFieldLst(true); // Will be done by CalcLayout() later on
2676 
2677  pNewPage->InvalidateSpelling();
2678  pNewPage->InvalidateSmartTags();
2679  pNewPage->InvalidateAutoCompleteWords();
2680  pNewPage->InvalidateWordCount();
2681 
2682  // No <CheckPageDesc(..)> in online layout
2683  if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
2684  {
2685  if ( bCheckPageDescs && pNewPage->GetNext() )
2686  {
2687  SwPageFrame* pStartPage = bCheckPageDescOfNextPage ?
2688  pNewPage :
2689  static_cast<SwPageFrame*>(pNewPage->GetNext());
2690  SwFrame::CheckPageDescs( pStartPage, false);
2691  }
2692  else if (m_rThis.GetPageDescItem().GetPageDesc())
2693  {
2694  // First page could get empty for example by disabling
2695  // a section
2696  SwFrame::CheckPageDescs( pNewPage, false);
2697  }
2698  }
2699  }
2700  }
2701  return pNewUpper != nullptr;
2702 }
2703 
2705 {
2706  if ( pFrame->IsContentFrame() )
2707  return static_cast<SwContentFrame*>(pFrame);
2708  if ( pFrame->IsTabFrame() )
2709  return static_cast<SwTabFrame*>(pFrame);
2710  if ( pFrame->IsSctFrame() )
2711  return static_cast<SwSectionFrame*>(pFrame);
2712  return nullptr;
2713 }
2714 
2716 {
2717  if ( pFrame->IsContentFrame() )
2718  return static_cast<const SwContentFrame*>(pFrame);
2719  if ( pFrame->IsTabFrame() )
2720  return static_cast<const SwTabFrame*>(pFrame);
2721  if ( pFrame->IsSctFrame() )
2722  return static_cast<const SwSectionFrame*>(pFrame);
2723  return nullptr;
2724 }
2725 
2726 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsAnLower(const SwFrame *) const
Definition: findfrm.cxx:207
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:338
bool GetValue() const
SwFrame * FindFooterOrHeader()
Definition: findfrm.cxx:548
SwSectionFrame * FindMaster() const
Definition: flowfrm.cxx:754
bool IsKeepFwdMoveAllowed(bool bIgnoreMyOwnKeepValue=false)
Definition: flowfrm.cxx:124
SvxBreak
sal_uInt16 CalcBottomLine() const
Definition: frmtool.hxx:505
Base class of the Writer layout elements.
Definition: frame.hxx:298
Base class that provides the general functionalities for frames that are allowed at page breaks (flow...
Definition: flowfrm.hxx:58
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:157
const ::std::optional< sal_uInt16 > & GetNumOffset() const
Definition: fmtpdsc.hxx:64
virtual SwRect GetObjRect() const =0
sal_uLong GetIndex() const
Definition: node.hxx:291
sal_Int32 nIndex
bool IsFollow() const
Definition: flowfrm.hxx:166
const SwSortedObjs * GetDrawObjs() const
Definition: frame.hxx:548
Represents the style of a paragraph.
Definition: fmtcol.hxx:56
SwFrame * mpNext
Definition: frame.hxx:322
SwFrame * mpPrev
Definition: frame.hxx:323
SwPageDesc * FindPageDesc()
Definition: pagechg.cxx:746
bool IsEndnAtEnd() const
Definition: sectfrm.hxx:146
SwContentFrame * GetNextContentFrame() const
Definition: cntfrm.hxx:98
bool IsInDocBody() const
Definition: frame.hxx:924
bool IsInFly() const
Definition: frame.hxx:942
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
SwTwips Grow(SwTwips, bool bTst=false, bool bInfo=false)
Definition: wsfrm.cxx:1491
sal_uInt16 GetLower() const
bool IsInSct() const
Definition: frame.hxx:948
SwRootFrame * mpRoot
Definition: frame.hxx:320
static void SetMoveBwdJump(bool bNew)
Definition: flowfrm.hxx:155
bool MoveFwd(bool bMakePage, bool bPageBreak, bool bMoveAlways=false)
Return value guarantees that a new page was not created, although false does not NECESSARILY indicate...
Definition: flowfrm.cxx:1927
SwPageDesc * GetPageDesc()
Definition: fmtpdsc.hxx:61
SwViewShellImp * Imp()
Definition: viewsh.hxx:182
void DelEmpty(bool bRemove)
Definition: sectfrm.cxx:186
static void CheckPageDescs(SwPageFrame *pStart, bool bNotifyFields=true, SwPageFrame **ppPrev=nullptr)
Check all pages (starting from the given one) if they use the appropriate frame format.
Definition: pagechg.cxx:1055
void ColLock()
Definition: sectfrm.hxx:84
bool IsColLocked() const
Definition: frame.hxx:867
bool IsBefore(const SwLayoutFrame *_pCheckRefLayFrame) const
method to check relative position of layout frame to a given layout frame.
Definition: findfrm.cxx:234
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr) override
Definition: ftnfrm.cxx:592
bool IsKeep(SvxFormatKeepItem const &rKeep, SvxFormatBreakItem const &rBreak, bool bBreakCheck=false) const
method to determine if a Keep needs to be considered (Breaks!)
Definition: flowfrm.cxx:235
const SwTable * GetTable() const
Definition: tabfrm.hxx:143
SwNodeIndex nNode
Definition: pam.hxx:37
void SetCompletePaint() const
Definition: frame.hxx:975
bool IsInFootnote() const
Definition: frame.hxx:930
virtual bool Prepare(const PrepareHint ePrep=PrepareHint::Clear, const void *pVoid=nullptr, bool bNotify=true)
Definition: wsfrm.cxx:594
sal_uInt16 char char * pDesc
SwLayoutFrame * GetPrevLeaf()
Returns the previous layout leaf where we can move the frame.
Definition: flowfrm.cxx:1092
SwFrameType GetType() const
Definition: frame.hxx:503
SvxBreak GetBreak() const
bool IsPrevObjMove() const
Definition: flowfrm.cxx:1125
sal_uIntPtr sal_uLong
long Long
void InvalidateLineNum_()
Definition: frame.hxx:778
static SwCache & GetCache()
Definition: frame.hxx:505
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
SwFrame * FindPrev()
Definition: frame.hxx:1136
bool IsComplete() const
Definition: layact.hxx:167
TElementType * Next()
Definition: calbck.hxx:333
bool HasFollow() const
Definition: flowfrm.hxx:165
SwTwips GetUpperSpaceAmountConsideredForPageGrid_(const SwTwips _nUpperSpaceWithoutGrid) const
method to determine the upper space amount, which is considered for the page grid ...
Definition: flowfrm.cxx:1635
void UpdateFootnoteNum()
Definition: ftnfrm.cxx:2418
SwTwips CalcLowerSpace(const SwBorderAttrs *_pAttrs=nullptr) const
calculation of lower space
Definition: flowfrm.cxx:1743
void InvalidatePos()
Definition: frame.hxx:1024
bool MoveBwd(bool &rbReformat)
Return value tells whether any changes have been made.
Definition: flowfrm.cxx:2131
SwSectionFormat * GetFormat()
Definition: section.hxx:336
static bool lcl_IdenticalStyles(const SwFrame *pPrevFrame, const SwFrame *pFrame)
Compare styles attached to these text frames.
Definition: flowfrm.cxx:1413
static void DestroyFrame(SwFrame *const pFrame)
this is the only way to delete a SwFrame instance
Definition: ssfrm.cxx:384
bool IsEndNote() const
Definition: fmtftn.hxx:71
SwFrame * FindNext()
Definition: frame.hxx:1122
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1788
bool IsCellFrame() const
Definition: frame.hxx:1207
bool IsFootnotePage() const
Foot note interface.
Definition: pagefrm.hxx:183
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
virtual const SvxFormatBreakItem & GetBreakItem() const
Definition: findfrm.cxx:655
SwContentFrame * FindFirstBodyContent()
Definition: pagefrm.hxx:334
virtual const SwFormatPageDesc & GetPageDescItem() const
Definition: findfrm.cxx:660
const SwFrame * GetPrevFrameForUpperSpaceCalc_(const SwFrame *_pProposedPrevFrame=nullptr) const
helper method to determine previous frame for calculation of the upper space
Definition: flowfrm.cxx:1341
static SwFlowFrame * CastFlowFrame(SwFrame *pFrame)
Definition: flowfrm.cxx:2704
bool IsFootnoteFrame() const
Definition: frame.hxx:1183
SwLayoutFrame * GetPrevSctLeaf()
Returns the preceding layout sheet where the frame can be moved into.
Definition: sectfrm.cxx:1924
void CheckDirChange()
checks the layout direction and invalidates the lower frames recursively, if necessary.
Definition: ssfrm.cxx:192
SwFrame & m_rThis
Definition: flowfrm.hxx:76
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:188
tools::Long GetTop(const SwRect &rRect) const
Definition: frame.hxx:1358
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:357
void SetRetouche() const
Definition: frame.hxx:984
SwTwips CalcUpperSpace(const SwBorderAttrs *pAttrs=nullptr, const SwFrame *pPr=nullptr, const bool _bConsiderGrid=true) const
method to determine the upper space hold by the frame
Definition: flowfrm.cxx:1446
bool IsFlyFrame() const
Definition: frame.hxx:1191
void InvalidateNextPrtArea()
method to invalidate printing area of next frame #i11859#
Definition: findfrm.cxx:1280
wrapper class for the positioning of Writer fly frames and drawing objects
const SvxFormatBreakItem & GetBreak(bool=true) const
Definition: frmatr.hxx:62
SwSection * m_pSection
Definition: sectfrm.hxx:38
void SetContentLock(bool bNew)
Definition: sectfrm.hxx:149
bool IsMoveable(const SwLayoutFrame *_pLayoutFrame=nullptr) const
determine, if frame is moveable in given environment
Definition: findfrm.cxx:1360
const SwFormatNoBalancedColumns & GetBalancedColumns(bool=true) const
Definition: fmtclbl.hxx:42
const SwLayoutFrame * GetPrevLayoutLeaf() const
Definition: frame.hxx:1005
const SwRect & getFrameArea() const
Definition: frame.hxx:178
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
SwFootnoteContFrame * FindFootnoteCont()
Definition: ftnfrm.cxx:1024
bool getBrowseMode() const
Definition: viewopt.hxx:472
SwLayoutFrame * GetNextLeaf(MakePageType eMakePage)
Returns the next layout leaf in which we can move the frame.
Definition: flowfrm.cxx:960
bool IsEmptyPage() const
Definition: pagefrm.hxx:141
SwFlowFrame * m_pFollow
Definition: flowfrm.hxx:117
bool IsInTab() const
Definition: frame.hxx:936
const SwPageFrame * GetLastPage() const
Definition: rootfrm.hxx:361
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
bool IsFrameInSameContext(const SwFrame *pInnerFrame, const SwFrame *pFrame)
Definition: frmtool.cxx:3579
bool IsTextFrame() const
Definition: frame.hxx:1215
bool OnRightPage() const
Definition: frame.hxx:716
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
SwDoc * GetDoc() const
Definition: viewsh.hxx:281
bool IsSctFrame() const
Definition: frame.hxx:1195
bool IsPageBreak(bool bAct) const
|* If there's a hard page break before the Frame AND there's a |* predecessor on the same page...
Definition: flowfrm.cxx:1195
bool IsFlowFrame() const
Definition: frame.hxx:1223
const SvxFormatKeepItem & GetKeep(bool=true) const
Definition: frmatr.hxx:56
SwLayoutFrame * GetNextCellLeaf()
Definition: findfrm.cxx:1523
SwLayoutFrame * GetNextSctLeaf(MakePageType eMakePage)
Returns the next layout sheet where the frame can be moved in.
Definition: sectfrm.cxx:1571
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame, use GetBreakItem()/GetPageDescItem() instead.
Definition: findfrm.cxx:675
static bool MoveBwdSuppressed(const SwDoc &p_rDoc, const SwFlowFrame &p_rFlowFrame, const SwLayoutFrame &p_rNewUpperFrame)
Definition: layouter.cxx:437
const SwFrame & GetFrame() const
Definition: flowfrm.hxx:151
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr)=0
virtual void Cut()=0
bool IsColumnFrame() const
Definition: frame.hxx:1163
SwFootnoteFrame * FindFootnoteFrame()
Definition: frame.hxx:1088
bool FrameContainsNode(SwContentFrame const &rFrame, sal_uLong nNodeIndex)
Definition: txtfrm.cxx:284
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1295
void InvalidateAutoCompleteWords() const
Definition: pagefrm.hxx:377
Style of a layout element.
Definition: frmfmt.hxx:58
SwTabFrame * FindMaster(bool bFirstMaster=false) const
Definition: flowfrm.cxx:774
bool IsContentFrame() const
Definition: frame.hxx:1211
SwFrame * GetIndPrev() const
Definition: frame.hxx:707
const SwContentFrame * GetFollow() const
Definition: cntfrm.hxx:114
const SdrObject * GetDrawObj() const
const SwSortedObjs * GetSortedObjs() const
Definition: pagefrm.hxx:116
void InvalidateSpelling() const
Definition: pagefrm.hxx:368
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
bool HasParaSpaceAtPages(bool bSct) const
Definition: flowfrm.cxx:1299
int i
static bool s_bMoveBwdJump
indicates that a backward move was done over multiple pages
Definition: flowfrm.hxx:88
bool IsFwdMoveAllowed() const
Definition: flowfrm.hxx:240
const SwFrame * GetLastLower() const
Definition: findfrm.cxx:1829
virtual bool ShouldBwdMoved(SwLayoutFrame *pNewUpper, bool &rReformat)=0
SwTwips CalcAddLowerSpaceAsLastInTableCell(const SwBorderAttrs *_pAttrs=nullptr) const
calculation of the additional space to be considered, if flow frame is the last inside a table cell ...
Definition: flowfrm.cxx:1790
sal_uInt16 GetBottomLine(const SwFrame &_rFrame) const
Definition: frmtool.hxx:483
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr) override
Definition: sectfrm.cxx:337
SwFrame * GetIndNext()
Definition: frame.hxx:710
const SwSectionFrame * GetFollow() const
Definition: sectfrm.hxx:158
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
size_t size() const
Definition: sortedobjs.cxx:43
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
SwPageFrame * FindPageFrame()
Definition: frame.hxx:663
virtual bool IsDeleteForbidden() const
Definition: frame.hxx:868
SwFrame * m_pLower
Definition: layfrm.hxx:53
virtual void Cut() override
Definition: wsfrm.cxx:1422
SwFrameFormat * GetLeftFormat(bool const bFirst=false)
Definition: pagedesc.cxx:382
tools::Long YInc(tools::Long n1, tools::Long n2) const
Definition: frame.hxx:1406
const SwFrame * Lower() const
Definition: layfrm.hxx:101
SwContentFrame * FindNextCnt(const bool _bInSameFootnote=false)
Definition: findfrm.cxx:191
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2568
TElementType * First()
Definition: calbck.hxx:325
SwPageDesc * GetPageDesc()
Definition: pagefrm.hxx:127
void InvalidatePage(const SwPageFrame *pPage=nullptr) const
Invalidates the page in which the Frame is currently placed.
Definition: wsfrm.cxx:604
virtual void SetNewFieldLst(bool bFlag)=0
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1363
SwSection * GetSection()
Definition: sectfrm.hxx:82
bool IsJoinLocked() const
Definition: flowfrm.hxx:175
void SetFollow(SwFlowFrame *const pFollow)
Definition: flowfrm.cxx:92
bool IsAction() const
SS for the Lay-/IdleAction and relatives.
Definition: viewimp.hxx:186
SwLayoutFrame * GetUpper()
Definition: frame.hxx:661
static bool PasteTree(SwFrame *, SwLayoutFrame *, SwFrame *, SwFrame *)
A specialized form of Paste(), which relocates a whole chain (this and the following, in particular).
Definition: flowfrm.cxx:520
void InvalidateSmartTags() const
Definition: pagefrm.hxx:373
bool IsRowFrame() const
Definition: frame.hxx:1203
SwTwips GetUpperSpaceAmountConsideredForPrevFrameAndPageGrid() const
method to determine the upper space amount, which is considered for the previous frame and the page g...
Definition: flowfrm.cxx:1725
tools::Long GetPrtTop(const SwFrame &rFrame) const
Definition: frame.hxx:1390
SwFootnoteBossFrame * FindFootnoteBossFrame(bool bFootnotes=false)
Definition: findfrm.cxx:436
Provides access to settings of a document.
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
SwFrame * GetPrev()
Definition: frame.hxx:660
SwLayoutFrame * mpUpper
Definition: frame.hxx:321
bool HasLockedFollow() const
Definition: flowfrm.cxx:112
sal_uInt16 GetTopLine(const SwFrame &_rFrame, const SwFrame *_pPrevFrame=nullptr) const
Definition: frmtool.hxx:474
SwFlowFrame * m_pPrecede
Definition: flowfrm.hxx:118
bool isFrameAreaPositionValid() const
Definition: frame.hxx:165
tools::Long YDiff(tools::Long n1, tools::Long n2) const
Definition: frame.hxx:1404
bool IsUpdateExpFields()
Definition: viewimp.cxx:150
virtual ~SwFlowFrame()
Definition: flowfrm.cxx:80
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:123
const IDocumentSettingAccess & getIDocumentSettingAccess() const
Provides access to the document settings interface.
Definition: format.cxx:717
bool isFrameAreaSizeValid() const
Definition: frame.hxx:166
SwContentFrame * FindLastContent(SwFindMode nMode=SwFindMode::None)
Definition: sectfrm.cxx:908
void InvalidatePos_()
Definition: frame.hxx:770
A page of the document layout.
Definition: pagefrm.hxx:41
const SwFormatFootnote & GetFootnote() const
Definition: txatbase.hxx:204
sal_uInt8 BwdMoveNecessary(const SwPageFrame *pPage, const SwRect &rRect)
method to determine overlapping of an object that requests floating
Definition: flowfrm.cxx:330
tools::Long SwTwips
Definition: swtypes.hxx:49
SwTwips Shrink(SwTwips, bool bTst=false, bool bInfo=false)
Definition: wsfrm.cxx:1536
void InvalidateSize()
Definition: frame.hxx:1010
SwLayoutFrame * GetPrevFootnoteLeaf(MakePageType eMakeFootnote)
Get the preceding layout leaf in that the frame can be moved.
Definition: ftnfrm.cxx:737
bool CheckMoveFwd(bool &rbMakePage, bool bKeep, bool bIgnoreMyOwnKeepValue)
Moves the Frame forward if it seems necessary regarding the current conditions and attributes...
Definition: flowfrm.cxx:1835
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1096
SwLayoutFrame * FindBodyCont()
Searches the first ContentFrame in BodyText below the page.
Definition: findfrm.cxx:43
const SwPageDesc * GetFollow() const
Definition: pagedesc.hxx:268
SwFrame * FindColFrame()
Definition: findfrm.cxx:530
void setFrameAreaPositionValid(bool bNew)
Definition: wsfrm.cxx:83
bool IsLayoutFrame() const
Definition: frame.hxx:1151
const SwFlowFrame * GetPrecede() const
Definition: flowfrm.hxx:172
SwContentFrame * FindLastBodyContent()
Searches the last ContentFrame in BodyText below the page.
Definition: findfrm.cxx:52
SwRowFrame * GetFirstNonHeadlineRow() const
Definition: tabfrm.cxx:5635
void MoveSubTree(SwLayoutFrame *pParent, SwFrame *pSibling=nullptr)
hook tree onto new parent with minimal operations and notifications
Definition: flowfrm.cxx:635
SwLayoutFrame * GetLeaf(MakePageType eMakePage, bool bFwd)
Definition: flowfrm.cxx:843
bool IsSquaredPageMode() const
Definition: docdesc.cxx:951
bool Is_Lower_Of(const SwFrame *pCurrFrame, const SdrObject *pObj)
Definition: frmtool.cxx:3533
MakePageType
Definition: frame.hxx:111
SwLayAction & GetLayAction()
Definition: viewimp.hxx:188
bool IsTabFrame() const
Definition: frame.hxx:1199
bool IsRightPageByNumber(SwRootFrame const &rLayout, sal_uInt16 nPageNum)
Definition: frmtool.cxx:3044
void CheckKeep()
Definition: flowfrm.cxx:147
sal_uInt16 CalcLineSpacing() const
Definition: frmtool.hxx:535
void SimpleFormat()
Definition: sectfrm.cxx:1163
virtual SwFrameFormat & GetFrameFormat()=0
#define SAL_WARN_IF(condition, area, stream)
SwTextFrame * FindMaster() const
Definition: flowfrm.cxx:738
void ColUnlock()
Definition: sectfrm.hxx:85
unsigned char sal_uInt8
sal_uInt16 GetPhyPageNum() const
Definition: trvlfrm.cxx:1695
bool MoveLowerFootnotes(SwContentFrame *pStart, SwFootnoteBossFrame *pOldBoss, SwFootnoteBossFrame *pNewBoss, const bool bFootnoteNums)
Moving the Footnotes of all Lowers - starting from StartContent.
Definition: ftnfrm.cxx:2648
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:423
bool ForbiddenForFootnoteCntFwd() const
Definition: flowfrm.cxx:1919
const SwFrame * ContainsAny(const bool _bInvestigateFootnoteForSections=false) const
Method doesn't investigate content of footnotes by default.
Definition: findfrm.cxx:126
SwTwips GetUpperSpaceAmountConsideredForPrevFrame() const
method to determine the upper space amount, which is considered for the previous frame ...
Definition: flowfrm.cxx:1689
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:254
bool IsBackMoveLocked() const
Definition: ftnfrm.hxx:133
void InvalidateAll_()
Definition: frame.hxx:786
const SvxParaGridItem & GetParaGrid(bool=true) const
Definition: paratr.hxx:221
#define SAL_INFO(area, stream)
const SwFormatPageDesc & GetPageDesc(bool=true) const
Definition: fmtpdsc.hxx:75
SwFrameFormat * GetRightFormat(bool const bFirst=false)
Layout uses the following methods to obtain a format in order to be able to create a page...
Definition: pagedesc.cxx:389
bool IsNoTextFrame() const
Definition: frame.hxx:1219
static SwLayoutFrame * CutTree(SwFrame *)
A specialized form of Cut(), which relocates a whole chain (this and the following, in particular).
Definition: flowfrm.cxx:444
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:176
const SwDoc * GetDoc() const
Definition: swatrset.hxx:204
SwLayoutFrame * GetPrevCellLeaf()
Definition: findfrm.cxx:1533
bool IsColBodyFrame() const
These SwFrame inlines are here, so that frame.hxx does not need to include layfrm.hxx.
Definition: layfrm.hxx:209
void GetSpacingValuesOfFrame(const SwFrame &rFrame, SwTwips &onLowerSpacing, SwTwips &onLineSpacing, bool &obIsLineSpacingProportional, bool bIdenticalStyles)
method to determine the spacing values of a frame
Definition: frmtool.cxx:3865
const SwContentFrame * GetRef() const
Definition: ftnfrm.cxx:2889
SwFrame * GetLower()
Definition: findfrm.cxx:170
bool IsPageFrame() const
Definition: frame.hxx:1159
const SwTextFootnote * GetAttr() const
Definition: ftnfrm.hxx:122
bool IsColBreak(bool bAct) const
|* If there's a hard column break before the Frame AND there is |* a predecessor in the same column...
Definition: flowfrm.cxx:1258
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
bool IsAnFollow(const SwFlowFrame *pFlow) const
Definition: flowfrm.cxx:727
bool OnFirstPage() const
Definition: trvlfrm.cxx:1768
bool IsContentLocked() const
Definition: sectfrm.hxx:150
const SwTabFrame * GetFollow() const
Definition: tabfrm.hxx:242
SwLayoutFrame * GetNextFootnoteLeaf(MakePageType eMakePage)
Return the next layout leaf in that the frame can be moved.
Definition: ftnfrm.cxx:655
SwFlowFrame(SwFrame &rFrame)
Definition: flowfrm.cxx:71
tools::Long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1359
void InvalidatePrt_()
Definition: frame.hxx:762
#define SAL_WARN(area, stream)
SwFormatColl * GetFormatColl() const
Definition: node.hxx:456
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame...
Definition: layfrm.hxx:35
const SwFrame * GetAnchorFrame() const
const SwLayoutFrame * GetNextLayoutLeaf() const
Definition: frame.hxx:1001
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:120
SwPageFrame * InsertPage(SwPageFrame *pSibling, bool bFootnote)
Definition: pagechg.cxx:1350
static bool FrameMovedFwdByObjPos(const SwDoc &_rDoc, const SwTextFrame &_rTextFrame, sal_uInt32 &_ornToPageNum)
Definition: layouter.cxx:342
sal_uInt16 GetBaseHeight() const
Definition: tgrditem.hxx:75
bool IsFootnoteContFrame() const
Definition: frame.hxx:1179
bool WrongPageDesc(SwPageFrame *pNew)
Definition: flowfrm.cxx:884
const SwContentFrame * ContainsContent() const
Checks if the frame contains one or more ContentFrame's anywhere in his subsidiary structure; if so t...
Definition: findfrm.cxx:67
void InvalidateWordCount() const
Definition: pagefrm.hxx:381
const SwFlowFrame * GetFollow() const
Definition: flowfrm.hxx:168
bool IsBodyFrame() const
Definition: frame.hxx:1187
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:208
class for collecting anchored objects
Definition: sortedobjs.hxx:48
void Height(tools::Long nNew)
Definition: swrect.hxx:191
Container of body content (i.e.
Definition: bodyfrm.hxx:28
sal_uInt16 GetRubyHeight() const
Definition: tgrditem.hxx:78
bool IsFooterFrame() const
Definition: frame.hxx:1175
static SwFootnoteFrame * PrependChained(SwFrame *pThis, bool bDefaultFormat)
Definition: ftnfrm.hxx:74
SwRootFrame * getRootFrame()
Definition: frame.hxx:662
bool GetContext() const
sal_uInt16 GetUpper() const
bool IsHeaderFrame() const
Definition: frame.hxx:1171
virtual const SwFrameFormat * GetFormat() const
Definition: ssfrm.cxx:395
#define PROTOCOL_ENTER(pFrame, nFunc, nAct, pPar)
Definition: dbg_lay.hxx:92
const SvxULSpaceItem & GetULSpace() const
Definition: frmtool.hxx:385
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1080
static bool IsMoveBwdJump()
Definition: flowfrm.hxx:154
static bool lcl_getContextualSpacing(const SwFrame *pPrevFrame)
Definition: flowfrm.cxx:1434
SwFrame * GetNext()
Definition: frame.hxx:659
Base class of the Writer document model elements.
Definition: node.hxx:80