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