LibreOffice Module sw (master)  1
calcmove.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 <rootfrm.hxx>
22 #include <pagefrm.hxx>
23 #include <viewopt.hxx>
24 #include <frmatr.hxx>
25 #include <frmtool.hxx>
26 #include <txtftn.hxx>
27 #include <fmtftn.hxx>
28 #include <ndtxt.hxx>
29 #include <editeng/ulspitem.hxx>
30 #include <editeng/keepitem.hxx>
31 #include <osl/diagnose.h>
32 #include <svx/sdtaitm.hxx>
33 
34 #include <fmtfsize.hxx>
35 #include <fmtanchr.hxx>
36 #include <fmtclbl.hxx>
37 
38 #include <tabfrm.hxx>
39 #include <ftnfrm.hxx>
40 #include <txtfrm.hxx>
41 #include <sectfrm.hxx>
42 #include <dbg_lay.hxx>
43 
44 #include <sortedobjs.hxx>
45 #include <layouter.hxx>
46 #include <flyfrms.hxx>
47 
50 
51 // Move methods
52 
55 {
57  {
58  // Floating back a frm uses a bit of time unfortunately.
59  // The most common case is the following: The Frame wants to float to
60  // somewhere where the FixSize is the same that the Frame itself has already.
61  // In that case it's pretty easy to check if the Frame has enough space
62  // for its VarSize. If this is NOT the case, we already know that
63  // we don't need to move.
64  // The Frame checks itself whether it has enough space - respecting the fact
65  // that it could possibly split itself if needed.
66  // If, however, the FixSize differs from the Frame or Flys are involved
67  // (either in the old or the new position), checking is pointless,
68  // and we have to move the Frame just to see what happens - if there's
69  // some space available to do it, that is.
70 
71  // The FixSize of the containers of Contents is always the width.
72 
73  // If we moved more than one sheet back (for example jumping over empty
74  // pages), we have to move either way. Otherwise, if the Frame doesn't fit
75  // into the page, empty pages wouldn't be respected anymore.
76  sal_uInt8 nMoveAnyway = 0;
77  SwPageFrame * const pNewPage = pNewUpper->FindPageFrame();
78  SwPageFrame *pOldPage = FindPageFrame();
79 
81  return true;
82 
83  if( IsInFootnote() && IsInSct() )
84  {
85  SwFootnoteFrame* pFootnote = FindFootnoteFrame();
86  SwSectionFrame* pMySect = pFootnote->FindSctFrame();
87  if( pMySect && pMySect->IsFootnoteLock() )
88  {
89  SwSectionFrame *pSect = pNewUpper->FindSctFrame();
90  while( pSect && pSect->IsInFootnote() )
91  pSect = pSect->GetUpper()->FindSctFrame();
92  OSL_ENSURE( pSect, "Escaping footnote" );
93  if( pSect != pMySect )
94  return false;
95  }
96  }
97  SwRectFnSet aRectFnSet(this);
98  SwRectFnSet fnRectX(pNewUpper);
99  if( std::abs( fnRectX.GetWidth(pNewUpper->getFramePrintArea()) -
100  aRectFnSet.GetWidth(GetUpper()->getFramePrintArea()) ) > 1 ) {
101  // In this case, only a WouldFit_ with test move is possible
102  nMoveAnyway = 2;
103  }
104 
105  // Do *not* move backward, if <nMoveAnyway> equals 3 and no space is left in new upper.
106  nMoveAnyway |= BwdMoveNecessary( pOldPage, getFrameArea() );
107  {
108  const IDocumentSettingAccess& rIDSA = pNewPage->GetFormat()->getIDocumentSettingAccess();
109  SwTwips nSpace = 0;
110  SwRect aRect( pNewUpper->getFramePrintArea() );
111  aRect.Pos() += pNewUpper->getFrameArea().Pos();
112  const SwFrame *pPrevFrame = pNewUpper->Lower();
113  while ( pPrevFrame )
114  {
115  SwTwips nNewTop = fnRectX.GetBottom(pPrevFrame->getFrameArea());
116  // Consider lower spacing of last frame in a table cell
117  {
118  // Check if last frame is inside table and if it includes its lower spacing.
119  if ( !pPrevFrame->GetNext() && pPrevFrame->IsInTab() &&
121  {
122  const SwFrame* pLastFrame = pPrevFrame;
123  // if last frame is a section, take its last content
124  if ( pPrevFrame->IsSctFrame() )
125  {
126  pLastFrame = static_cast<const SwSectionFrame*>(pPrevFrame)->FindLastContent();
127  if ( pLastFrame &&
128  pLastFrame->FindTabFrame() != pPrevFrame->FindTabFrame() )
129  {
130  pLastFrame = pLastFrame->FindTabFrame();
131  }
132  }
133 
134  if ( pLastFrame )
135  {
136  SwBorderAttrAccess aAccess( SwFrame::GetCache(), pLastFrame );
137  const SwBorderAttrs& rAttrs = *aAccess.Get();
138  nNewTop -= rAttrs.GetULSpace().GetLower();
140  {
141  nNewTop -= rAttrs.CalcLineSpacing();
142  }
143  }
144  }
145  }
146  fnRectX.SetTop( aRect, nNewTop );
147 
148  pPrevFrame = pPrevFrame->GetNext();
149  }
150 
151  nMoveAnyway |= BwdMoveNecessary( pNewPage, aRect);
152 
153  //determine space left in new upper frame
154  nSpace = fnRectX.GetHeight(aRect);
155  const SwViewShell *pSh = pNewUpper->getRootFrame()->GetCurrShell();
156  if ( IsInFootnote() ||
157  (pSh && pSh->GetViewOptions()->getBrowseMode()) ||
158  pNewUpper->IsCellFrame() ||
159  ( pNewUpper->IsInSct() && ( pNewUpper->IsSctFrame() ||
160  ( pNewUpper->IsColBodyFrame() &&
161  !pNewUpper->GetUpper()->GetPrev() &&
162  !pNewUpper->GetUpper()->GetNext() ) ) ) )
163  nSpace += pNewUpper->Grow( LONG_MAX, true );
164 
165  if ( nMoveAnyway < 3 )
166  {
167  if ( nSpace )
168  {
169  // Do not notify footnotes which are stuck to the paragraph:
170  // This would require extremely confusing code, taking into
171  // account the widths
172  // and Flys, that in turn influence the footnotes, ...
173 
174  // WouldFit_ can only be used if the width is the same and
175  // ONLY self-anchored Flys are present.
176 
177  // WouldFit_ can also be used if ONLY Flys anchored
178  // somewhere else are present.
179  // In this case, the width doesn't even matter,
180  // because we're running a TestFormat in the new upper.
181  const sal_uInt8 nBwdMoveNecessaryResult =
182  BwdMoveNecessary( pNewPage, aRect);
183  const bool bObjsInNewUpper( nBwdMoveNecessaryResult == 2 ||
184  nBwdMoveNecessaryResult == 3 );
185 
186  return WouldFit_( nSpace, pNewUpper, nMoveAnyway == 2,
187  bObjsInNewUpper );
188  }
189  // It's impossible for WouldFit_ to return a usable result if
190  // we have a fresh multi-column section - so we really have to
191  // float back unless there is no space.
192  return pNewUpper->IsInSct() && pNewUpper->IsColBodyFrame() &&
193  !fnRectX.GetWidth(pNewUpper->getFramePrintArea()) &&
194  ( pNewUpper->GetUpper()->GetPrev() ||
195  pNewUpper->GetUpper()->GetNext() );
196  }
197 
198  // Check for space left in new upper
199  return nSpace != 0;
200  }
201  }
202  return false;
203 }
204 
205 // Calc methods
206 
207 // Two little friendships form a secret society
208 inline void PrepareLock( SwFlowFrame *pTab )
209 {
210  pTab->LockJoin();
211 }
212 inline void PrepareUnlock( SwFlowFrame *pTab )
213 {
214  pTab->UnlockJoin();
215 
216 }
217 
218 // hopefully, one day this function simply will return 'false'
219 static bool lcl_IsCalcUpperAllowed( const SwFrame& rFrame )
220 {
221  return !rFrame.GetUpper()->IsSctFrame() &&
222  !rFrame.GetUpper()->IsFooterFrame() &&
223  // No format of upper Writer fly frame
224  !rFrame.GetUpper()->IsFlyFrame() &&
225  !( rFrame.GetUpper()->IsTabFrame() && rFrame.GetUpper()->GetUpper()->IsInTab() ) &&
226  !( rFrame.IsTabFrame() && rFrame.GetUpper()->IsInTab() );
227 }
228 
247 {
248  StackHack aHack;
249  if ( GetUpper() )
250  {
251  SwFrameDeleteGuard aDeleteGuard(this);
252  if ( lcl_IsCalcUpperAllowed( *this ) )
253  GetUpper()->Calc(pRenderContext);
254  OSL_ENSURE( GetUpper(), ":-( Layout unstable (Upper gone)." );
255  if ( !GetUpper() )
256  return;
257 
258  const bool bCnt = IsContentFrame();
259  const bool bTab = IsTabFrame();
260  bool bNoSect = IsInSct();
261  bool bOldTabLock = false, bFoll = false;
262  SwFlowFrame* pThis = bCnt ? static_cast<SwContentFrame*>(this) : nullptr;
263 
264  if ( bTab )
265  {
266  pThis = static_cast<SwTabFrame*>(this);
267  bOldTabLock = static_cast<SwTabFrame*>(this)->IsJoinLocked();
268  ::PrepareLock( static_cast<SwTabFrame*>(this) );
269  bFoll = pThis->IsFollow();
270  }
271  else if( IsSctFrame() )
272  {
273  pThis = static_cast<SwSectionFrame*>(this);
274  bFoll = pThis->IsFollow();
275  bNoSect = false;
276  }
277  else if ( bCnt )
278  {
279  bFoll = pThis->IsFollow();
280  if ( bFoll && GetPrev() )
281  {
282  // Do not follow the chain when we need only one instance
283  const SwTextFrame* pMaster = static_cast<SwContentFrame*>(this)->FindMaster();
284  if ( pMaster && pMaster->IsLocked() )
285  {
286  MakeAll(pRenderContext);
287  return;
288  }
289  }
290  }
291 
292  // There is no format of previous frame, if current frame is a table
293  // frame and its previous frame wants to keep with it.
294  const bool bFormatPrev = !bTab ||
295  !GetPrev() ||
296  !GetPrev()->GetAttrSet()->GetKeep().GetValue();
297  if ( bFormatPrev )
298  {
299  SwFrame *pFrame = GetUpper()->Lower();
300  while ( pFrame != this )
301  {
302  OSL_ENSURE( pFrame, ":-( Layout unstable (this not found)." );
303  if ( !pFrame )
304  return; //Oioioioi ...
305 
306  if ( !pFrame->isFrameAreaDefinitionValid() )
307  {
308  // A small interference that hopefully improves on the stability:
309  // If I'm Follow AND neighbor of a Frame before me, it would delete
310  // me when formatting. This as you can see could easily become a
311  // confusing situation that we want to avoid.
312  if ( bFoll && pFrame->IsFlowFrame() &&
313  SwFlowFrame::CastFlowFrame(pFrame)->IsAnFollow( pThis ) )
314  break;
315 
316  bool const isLast(pFrame->GetNext() == this);
317  // note: this seems obvious but does *not* hold, a MakeAll()
318  // could move more than 1 frame backwards!
319  // that's why FindNext() is used below
320  // assert(pFrame->GetUpper() == GetUpper());
321  pFrame->MakeAll(pRenderContext);
322  if( IsSctFrame() && !static_cast<SwSectionFrame*>(this)->GetSection() )
323  break;
324  if (isLast && pFrame->GetUpper() != GetUpper())
325  {
326  assert(GetUpper()->Lower() == this
327  // empty section frames are created all the time...
328  || GetUpper()->Lower()->IsSctFrame()
329  // tab frame/section frame may split multiple times
330  || ( SwFlowFrame::CastFlowFrame(pFrame)
332  && SwFlowFrame::CastFlowFrame(pFrame)->IsAnFollow(
334  && (GetUpper()->Lower()->GetNext() == this
335  // if it's more than 10 pages long...
336  || (SwFlowFrame::CastFlowFrame(GetUpper()->Lower())->GetFollow()
338  && GetUpper()->Lower()->GetNext()->GetNext() == this)
339  // pre-existing empty section frames may end up between them...
340  || GetUpper()->Lower()->GetNext()->IsSctFrame())));
341  break; // tdf#119109 frame was moved backward, prevent
342  // FindNext() returning a frame inside this if
343  } // this is a table!
344  }
345  // With ContentFrames, the chain may be broken while walking through
346  // it. Therefore we have to figure out the next frame in a bit more
347  // complicated way. However, I'll HAVE to get back to myself
348  // sometime again.
349  pFrame = pFrame->FindNext();
350 
351  // If we started out in a SectionFrame, it might have happened that
352  // we landed in a Section Follow via the MakeAll calls.
353  // FindNext only gives us the SectionFrame, not it's content - we
354  // won't find ourselves anymore!
355  if( bNoSect && pFrame && pFrame->IsSctFrame() )
356  {
357  SwFrame* pCnt = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
358  if( pCnt )
359  pFrame = pCnt;
360  }
361  }
362  OSL_ENSURE( GetUpper(), "Layout unstable (Upper gone II)." );
363  if ( !GetUpper() )
364  return;
365 
366  if ( lcl_IsCalcUpperAllowed( *this ) )
367  GetUpper()->Calc(pRenderContext);
368 
369  OSL_ENSURE( GetUpper(), "Layout unstable (Upper gone III)." );
370  }
371 
372  if ( bTab && !bOldTabLock )
373  ::PrepareUnlock( static_cast<SwTabFrame*>(this) );
374  }
375  MakeAll(pRenderContext);
376 }
377 
379 {
380  // #i23129#, #i36347# - no format of upper Writer fly frame
381  if ( GetUpper() && !GetUpper()->IsFooterFrame() &&
382  !GetUpper()->IsFlyFrame() )
383  {
384  {
385  SwFrameDeleteGuard aDeleteGuard(this);
386  GetUpper()->Calc(getRootFrame()->GetCurrShell() ? getRootFrame()->GetCurrShell()->GetOut() : nullptr);
387  }
388  OSL_ENSURE( GetUpper(), ":-( Layout unstable (Upper gone)." );
389  if ( !GetUpper() )
390  return;
391  }
392  if ( GetPrev() && !GetPrev()->isFrameAreaDefinitionValid() )
393  {
394  PrepareMake(getRootFrame()->GetCurrShell() ? getRootFrame()->GetCurrShell()->GetOut() : nullptr);
395  }
396  else
397  {
398  StackHack aHack;
399  MakeAll(IsRootFrame() ? nullptr : getRootFrame()->GetCurrShell()->GetOut());
400  }
401 }
402 
404 {
405  StackHack aHack;
406  if( GetUpper() && !GetUpper()->IsSctFrame() )
407  {
408  const bool bCnt = IsContentFrame();
409  const bool bTab = IsTabFrame();
410  bool bNoSect = IsInSct();
411 
412 #if BOOST_VERSION < 105600
413  std::list<FlowFrameJoinLockGuard> tabGuard;
414  std::list<SwFrameDeleteGuard> rowGuard;
415 #else
416  std::optional<FlowFrameJoinLockGuard> tabGuard;
417  std::optional<SwFrameDeleteGuard> rowGuard;
418 #endif
419  SwFlowFrame* pThis = bCnt ? static_cast<SwContentFrame*>(this) : nullptr;
420 
421  if ( bTab )
422  {
423 #if BOOST_VERSION < 105600
424  tabGuard.emplace_back(static_cast<SwTabFrame*>(this)); // tdf#125741
425 #else
426  tabGuard.emplace(static_cast<SwTabFrame*>(this)); // tdf#125741
427 #endif
428  pThis = static_cast<SwTabFrame*>(this);
429  }
430  else if (IsRowFrame())
431  {
432 #if BOOST_VERSION < 105600
433  rowGuard.emplace_back(this); // tdf#125741 keep this alive
434 #else
435  rowGuard.emplace(this); // tdf#125741 keep this alive
436 #endif
437  }
438  else if( IsSctFrame() )
439  {
440  pThis = static_cast<SwSectionFrame*>(this);
441  bNoSect = false;
442  }
443 
444  GetUpper()->PrepareCursor();
445  GetUpper()->Calc(getRootFrame()->GetCurrShell() ? getRootFrame()->GetCurrShell()->GetOut() : nullptr);
446 
447  OSL_ENSURE( GetUpper(), ":-( Layout unstable (Upper gone)." );
448  if ( !GetUpper() )
449  return;
450 
451  bool const bFoll = pThis && pThis->IsFollow();
452 
453  SwFrame *pFrame = GetUpper()->Lower();
454  while ( pFrame != this )
455  {
456  OSL_ENSURE( pFrame, ":-( Layout unstable (this not found)." );
457  if ( !pFrame )
458  return; //Oioioioi ...
459 
460  if ( !pFrame->isFrameAreaDefinitionValid() )
461  {
462  // A small interference that hopefully improves on the stability:
463  // If I'm Follow AND neighbor of a Frame before me, it would delete
464  // me when formatting. This as you can see could easily become a
465  // confusing situation that we want to avoid.
466  if ( bFoll && pFrame->IsFlowFrame() &&
467  SwFlowFrame::CastFlowFrame(pFrame)->IsAnFollow( pThis ) )
468  break;
469 
470  bool const isLast(pFrame->GetNext() == this);
471  pFrame->MakeAll(getRootFrame()->GetCurrShell()->GetOut());
472  if (isLast && pFrame->GetUpper() != GetUpper())
473  {
474  assert(GetUpper()->Lower() == this
475  // empty section frames are created all the time...
476  || GetUpper()->Lower()->IsSctFrame()
477  // tab frame/section frame may split multiple times
478  || ( SwFlowFrame::CastFlowFrame(pFrame)
480  && SwFlowFrame::CastFlowFrame(pFrame)->IsAnFollow(
482  && (GetUpper()->Lower()->GetNext() == this
483  // if it's more than 10 pages long...
484  || (SwFlowFrame::CastFlowFrame(GetUpper()->Lower())->GetFollow()
486  && GetUpper()->Lower()->GetNext()->GetNext() == this)
487  // pre-existing empty section frames may end up between them...
488  || GetUpper()->Lower()->GetNext()->IsSctFrame())));
489  break; // tdf#119109 frame was moved backward, prevent
490  // FindNext() returning a frame inside this if
491  } // this is a table!
492  }
493  // With ContentFrames, the chain may be broken while walking through
494  // it. Therefore we have to figure out the next frame in a bit more
495  // complicated way. However, I'll HAVE to get back to myself
496  // sometime again.
497  pFrame = pFrame->FindNext();
498  if( bNoSect && pFrame && pFrame->IsSctFrame() )
499  {
500  SwFrame* pCnt = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
501  if( pCnt )
502  pFrame = pCnt;
503  }
504  }
505  OSL_ENSURE( GetUpper(), "Layout unstable (Upper gone II)." );
506  if ( !GetUpper() )
507  return;
508 
509  GetUpper()->Calc(getRootFrame()->GetCurrShell()->GetOut());
510 
511  OSL_ENSURE( GetUpper(), "Layout unstable (Upper gone III)." );
512  }
513  Calc(getRootFrame()->GetCurrShell() ? getRootFrame()->GetCurrShell()->GetOut() : nullptr);
514 }
515 
516 // Here we return GetPrev(); however we will ignore empty SectionFrames
517 static SwFrame* lcl_Prev( SwFrame* pFrame, bool bSectPrv = true )
518 {
519  SwFrame* pRet = pFrame->GetPrev();
520  if( !pRet && pFrame->GetUpper() && pFrame->GetUpper()->IsSctFrame() &&
521  bSectPrv && !pFrame->IsColumnFrame() )
522  pRet = pFrame->GetUpper()->GetPrev();
523  while( pRet && pRet->IsSctFrame() &&
524  !static_cast<SwSectionFrame*>(pRet)->GetSection() )
525  pRet = pRet->GetPrev();
526  return pRet;
527 }
528 
530 {
531  SwFrame *pRet = pFrame;
532  do
533  {
534  pRet = lcl_Prev( pRet );
535  } while ( pRet && pRet->IsTextFrame() && static_cast<SwTextFrame*>(pRet)->IsHiddenNow() );
536  return pRet;
537 }
538 
540 {
541  if ( isFrameAreaPositionValid() )
542  return;
543 
545  bool bUseUpper = false;
546  SwFrame* pPrv = lcl_Prev( this );
547  if ( pPrv &&
548  ( !pPrv->IsContentFrame() ||
549  ( static_cast<SwContentFrame*>(pPrv)->GetFollow() != this ) )
550  )
551  {
552  if ( !StackHack::IsLocked() &&
553  ( !IsInSct() || IsSctFrame() ) &&
554  !pPrv->IsSctFrame() &&
555  !pPrv->GetAttrSet()->GetKeep().GetValue()
556  )
557  {
558  pPrv->Calc(getRootFrame()->GetCurrShell() ? getRootFrame()->GetCurrShell()->GetOut() : nullptr); // This may cause Prev to vanish!
559  }
560  else if ( pPrv->getFrameArea().Top() == 0 )
561  {
562  bUseUpper = true;
563  }
564  }
565 
566  pPrv = lcl_Prev( this, false );
567  const SwFrameType nMyType = GetType();
568  SwRectFnSet aRectFnSet((IsCellFrame() && GetUpper() ? GetUpper() : this));
569  if ( !bUseUpper && pPrv )
570  {
572  aFrm.Pos( pPrv->getFrameArea().Pos() );
573 
574  if( FRM_NEIGHBOUR & nMyType )
575  {
576  const bool bR2L = IsRightToLeft();
577 
578  if( bR2L )
579  {
580  aRectFnSet.SetPosX( aFrm, aRectFnSet.GetLeft(aFrm) - aRectFnSet.GetWidth(aFrm) );
581  }
582  else
583  {
584  aRectFnSet.SetPosX( aFrm, aRectFnSet.GetLeft(aFrm) + aRectFnSet.GetWidth(pPrv->getFrameArea()) );
585  }
586 
587  // cells may now leave their uppers
588  if( aRectFnSet.IsVert() && SwFrameType::Cell & nMyType )
589  {
590  aFrm.Pos().setX(aFrm.Pos().getX() - aFrm.Width() + pPrv->getFrameArea().Width());
591  }
592  }
593  else if( aRectFnSet.IsVert() && FRM_NOTE_VERT & nMyType )
594  {
595  if ( aRectFnSet.IsVertL2R() )
596  {
597  aFrm.Pos().setX(aFrm.Pos().getX() + pPrv->getFrameArea().Width());
598  }
599  else
600  {
601  aFrm.Pos().setX(aFrm.Pos().getX() - aFrm.Width());
602  }
603  }
604  else
605  {
606  aFrm.Pos().setY(aFrm.Pos().getY() + pPrv->getFrameArea().Height());
607  }
608  }
609  else if ( GetUpper() )
610  {
611  // If parent frame is a footer frame and its <ColLocked()>, then
612  // do *not* calculate it.
613  // NOTE: Footer frame is <ColLocked()> during its
614  // <FormatSize(..)>, which is called from <Format(..)>, which
615  // is called from <MakeAll()>, which is called from <Calc()>.
616  // #i56850#
617  // - no format of upper Writer fly frame, which is anchored
618  // at-paragraph or at-character.
619  if ( !GetUpper()->IsTabFrame() &&
620  !( IsTabFrame() && GetUpper()->IsInTab() ) &&
621  !GetUpper()->IsSctFrame() &&
622  !dynamic_cast<SwFlyAtContentFrame*>(GetUpper()) &&
623  !( GetUpper()->IsFooterFrame() &&
624  GetUpper()->IsColLocked() )
625  )
626  {
627  GetUpper()->Calc(getRootFrame()->GetCurrShell()->GetOut());
628  }
629  pPrv = lcl_Prev( this, false );
630  if ( !bUseUpper && pPrv )
631  {
633  aFrm.Pos( pPrv->getFrameArea().Pos() );
634 
635  if( FRM_NEIGHBOUR & nMyType )
636  {
637  const bool bR2L = IsRightToLeft();
638 
639  if( bR2L )
640  {
641  aRectFnSet.SetPosX( aFrm, aRectFnSet.GetLeft(aFrm) - aRectFnSet.GetWidth(aFrm) );
642  }
643  else
644  {
645  aRectFnSet.SetPosX( aFrm, aRectFnSet.GetLeft(aFrm) + aRectFnSet.GetWidth(pPrv->getFrameArea()) );
646  }
647 
648  // cells may now leave their uppers
649  if( aRectFnSet.IsVert() && SwFrameType::Cell & nMyType )
650  {
651  aFrm.Pos().setX(aFrm.Pos().getX() - aFrm.Width() + pPrv->getFrameArea().Width());
652  }
653  }
654  else if( aRectFnSet.IsVert() && FRM_NOTE_VERT & nMyType )
655  {
656  aFrm.Pos().setX(aFrm.Pos().getX() - aFrm.Width());
657  }
658  else
659  {
660  aFrm.Pos().setY(aFrm.Pos().getY() + pPrv->getFrameArea().Height());
661  }
662  }
663  else
664  {
666  aFrm.Pos( GetUpper()->getFrameArea().Pos() );
667 
668  if( GetUpper()->IsFlyFrame() )
669  {
670  aFrm.Pos() += static_cast<SwFlyFrame*>(GetUpper())->ContentPos();
671  }
672  else
673  {
674  aFrm.Pos() += GetUpper()->getFramePrintArea().Pos();
675  }
676 
677  if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() )
678  {
679  if( aRectFnSet.IsVert() )
680  {
681  aFrm.Pos().setY(aFrm.Pos().getY() + GetUpper()->getFramePrintArea().Height() - aFrm.Height());
682  }
683  else
684  {
685  aFrm.Pos().setX(aFrm.Pos().getX() + GetUpper()->getFramePrintArea().Width() - aFrm.Width());
686  }
687  }
688  else if( aRectFnSet.IsVert() && !aRectFnSet.IsVertL2R() && FRM_NOTE_VERT & nMyType )
689  {
690  aFrm.Pos().setX(aFrm.Pos().getX() - aFrm.Width() + GetUpper()->getFramePrintArea().Width());
691  }
692  }
693  }
694  else
695  {
697  aFrm.Pos().setX(0);
698  aFrm.Pos().setY(0);
699  }
700 
701  if( IsBodyFrame() && aRectFnSet.IsVert() && !aRectFnSet.IsVertL2R() && GetUpper() )
702  {
704  aFrm.Pos().setX(aFrm.Pos().getX() + GetUpper()->getFramePrintArea().Width() - aFrm.Width());
705  }
706 
708 }
709 
710 // #i28701# - new type <SwSortedObjs>
711 static void lcl_CheckObjects(SwSortedObjs& rSortedObjs, const SwFrame* pFrame, tools::Long& rBot)
712 {
713  // And then there can be paragraph anchored frames that sit below their paragraph.
714  tools::Long nMax = 0;
715  for (SwAnchoredObject* pObj : rSortedObjs)
716  {
717  // #i28701# - consider changed type of <SwSortedObjs>
718  // entries.
719  tools::Long nTmp = 0;
720  if ( auto pFly = pObj->DynCastFlyFrame() )
721  {
722  if( pFly->getFrameArea().Top() != FAR_AWAY &&
723  ( pFrame->IsPageFrame() ? pFly->IsFlyLayFrame() :
724  ( pFly->IsFlyAtContentFrame() &&
725  ( pFrame->IsBodyFrame() ? pFly->GetAnchorFrame()->IsInDocBody() :
726  pFly->GetAnchorFrame()->IsInFootnote() ) ) ) )
727  {
728  nTmp = pFly->getFrameArea().Bottom();
729  }
730  }
731  else
732  nTmp = pObj->GetObjRect().Bottom();
733  nMax = std::max( nTmp, nMax );
734  }
735  ++nMax; // Lower edge vs. height!
736  rBot = std::max( rBot, nMax );
737 }
738 
739 size_t SwPageFrame::GetContentHeight(const tools::Long nTop, const tools::Long nBottom) const
740 {
741  OSL_ENSURE(!(FindBodyCont() && FindBodyCont()->Lower() && FindBodyCont()->Lower()->IsColumnFrame()),
742  "SwPageFrame::GetContentHeight(): No support for columns.");
743 
744  // In pages without columns, the content defines the size.
745  tools::Long nBot = getFrameArea().Top() + nTop;
746  const SwFrame *pFrame = Lower();
747  while (pFrame)
748  {
749  tools::Long nTmp = 0;
750  const SwFrame *pCnt = static_cast<const SwLayoutFrame*>(pFrame)->ContainsAny();
751  while (pCnt && (pCnt->GetUpper() == pFrame ||
752  static_cast<const SwLayoutFrame*>(pFrame)->IsAnLower(pCnt)))
753  {
754  nTmp += pCnt->getFrameArea().Height();
755  if (pCnt->IsTextFrame() &&
756  static_cast<const SwTextFrame*>(pCnt)->IsUndersized())
757  {
758  // This TextFrame would like to be a bit bigger.
759  nTmp += static_cast<const SwTextFrame*>(pCnt)->GetParHeight()
760  - pCnt->getFramePrintArea().Height();
761  }
762  else if (pCnt->IsSctFrame())
763  {
764  // Grow if undersized, but don't shrink if oversized.
765  const auto delta = static_cast<const SwSectionFrame*>(pCnt)->CalcUndersize();
766  if (delta > 0)
767  nTmp += delta;
768  }
769 
770  pCnt = pCnt->FindNext();
771  }
772  // Consider invalid body frame properties
773  if (pFrame->IsBodyFrame() &&
774  (!pFrame->isFrameAreaSizeValid() ||
775  !pFrame->isFramePrintAreaValid()) &&
776  (pFrame->getFrameArea().Height() < pFrame->getFramePrintArea().Height())
777  )
778  {
779  nTmp = std::min(nTmp, pFrame->getFrameArea().Height());
780  }
781  else
782  {
783  // Assert invalid lower property
784  OSL_ENSURE(!(pFrame->getFrameArea().Height() < pFrame->getFramePrintArea().Height()),
785  "SwPageFrame::GetContentHeight(): Lower with frame height < printing height");
786  nTmp += pFrame->getFrameArea().Height() - pFrame->getFramePrintArea().Height();
787  }
788  if (!pFrame->IsBodyFrame())
789  nTmp = std::min(nTmp, pFrame->getFrameArea().Height());
790  nBot += nTmp;
791  // Here we check whether paragraph anchored objects
792  // protrude outside the Body/FootnoteCont.
793  if (m_pSortedObjs && !pFrame->IsHeaderFrame() &&
794  !pFrame->IsFooterFrame())
795  lcl_CheckObjects(*m_pSortedObjs, pFrame, nBot);
796  pFrame = pFrame->GetNext();
797  }
798  nBot += nBottom;
799  // And the page anchored ones
800  if (m_pSortedObjs)
801  lcl_CheckObjects(*m_pSortedObjs, this, nBot);
802  nBot -= getFrameArea().Top();
803 
804  return nBot;
805 }
806 
808 {
809  PROTOCOL_ENTER( this, PROT::MakeAll, DbgAction::NONE, nullptr )
810 
811  const SwRect aOldRect( getFrameArea() ); // Adjust root size
812  const SwLayNotify aNotify( this ); // takes care of the notification in the dtor
813  std::optional<SwBorderAttrAccess> oAccess;
814  const SwBorderAttrs*pAttrs = nullptr;
815 
817  {
818  if ( !isFrameAreaPositionValid() )
819  {
820  setFrameAreaPositionValid(true); // positioning of the pages is taken care of by the root frame
821  }
822 
824  {
825  if ( IsEmptyPage() )
826  {
828  aFrm.Width( 0 );
829  aFrm.Height( 0 );
830 
832  aPrt.Width( 0 );
833  aPrt.Height( 0 );
834  aPrt.Left( 0 );
835  aPrt.Top( 0 );
836 
837  setFrameAreaSizeValid(true);
839  }
840  else
841  {
842  if (!oAccess)
843  {
844  oAccess.emplace(SwFrame::GetCache(), this);
845  pAttrs = oAccess->Get();
846  }
847  assert(pAttrs);
848 
849  SwRootFrame* pRootFrame = getRootFrame();
850  SwViewShell* pSh = pRootFrame->GetCurrShell();
851  if (pSh && pSh->GetViewOptions()->getBrowseMode())
852  {
853  // In BrowseView, we use fixed settings
854  const Size aBorder = pRenderContext->PixelToLogic( pSh->GetBrowseBorder() );
855  const tools::Long nTop = pAttrs->CalcTopLine() + aBorder.Height();
856  const tools::Long nBottom = pAttrs->CalcBottomLine()+ aBorder.Height();
857 
858  tools::Long nWidth = GetUpper() ? static_cast<SwRootFrame*>(GetUpper())->GetBrowseWidth() : 0;
859  const auto nDefWidth = pSh->GetBrowseWidth();
860  if (nWidth < nDefWidth)
861  nWidth = nDefWidth;
862  nWidth += + 2 * aBorder.Width();
863 
864  constexpr tools::Long constTwips_2cm = o3tl::toTwips(2, o3tl::Length::cm);
865  nWidth = std::max(nWidth, 2L * aBorder.Width() + constTwips_2cm);
866 
867  {
869  aFrm.Width( nWidth );
870 
871  SwLayoutFrame *pBody = FindBodyCont();
872  if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame() )
873  {
874  // Columns have a fixed height
875  aFrm.Height( pAttrs->GetSize().Height() );
876  }
877  else
878  {
879  // In pages without columns, the content defines the size.
880  tools::Long nBot = GetContentHeight(nTop, nBottom);
881 
882  // #i35143# - If second page frame
883  // exists, the first page doesn't have to fulfill the
884  // visible area.
885  if ( !GetPrev() && !GetNext() )
886  {
887  nBot = std::max( nBot, pSh->VisArea().Height() );
888  }
889  // #i35143# - Assure, that the page
890  // doesn't exceed the defined browse height.
891  aFrm.Height( std::min( nBot, BROWSE_HEIGHT ) );
892  }
893  }
894 
895  {
897  aPrt.Left ( pAttrs->CalcLeftLine() + aBorder.Width() );
898  aPrt.Top ( nTop );
899  aPrt.Width( getFrameArea().Width() - ( aPrt.Left() + pAttrs->CalcRightLine() + aBorder.Width() ) );
900  aPrt.Height( getFrameArea().Height() - (nTop + nBottom) );
901  }
902 
903  setFrameAreaSizeValid(true);
905  continue;
906  }
907  else if (pSh && pSh->GetViewOptions()->IsWhitespaceHidden() && pRootFrame->GetLastPage() != this)
908  {
909  tools::Long height = 0;
910  SwLayoutFrame *pBody = FindBodyCont();
911  if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame() )
912  {
913  // Columns have a fixed height
914  height = pAttrs->GetSize().Height();
915  }
916  else
917  {
918  // No need for borders.
919  height = GetContentHeight(0, 0);
920  }
921 
922  if (height > 0)
923  {
924  ChgSize(Size(getFrameArea().Width(), height));
926  aPrt.Top(0);
927  aPrt.Height(height);
928  setFrameAreaSizeValid(true);
930  continue;
931  }
932 
933  // Fallback to default formatting. Especially relevant
934  // when loading a doc when Hide Whitespace is enabled.
935  // Heights are zero initially.
936  }
937 
938  // Set FixSize. For pages, this is not done from Upper, but from
939  // the attribute.
940  //FIXME: This resets the size when (isFrameAreaSizeValid() && !isFramePrintAreaValid()).
941  {
943  aFrm.SSize( pAttrs->GetSize() );
944  }
945  Format( pRenderContext, pAttrs );
946  }
947  }
948  } //while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() )
949 
950  if ( getFrameArea() != aOldRect && GetUpper() )
951  static_cast<SwRootFrame*>(GetUpper())->CheckViewLayout( nullptr, nullptr );
952 
953  OSL_ENSURE( !GetUpper() || GetUpper()->getFramePrintArea().Width() >= getFrameArea().Width(),
954  "Upper (Root) must be wide enough to contain the widest page");
955 }
956 
958 {
959  PROTOCOL_ENTER( this, PROT::MakeAll, DbgAction::NONE, nullptr )
960 
961  // takes care of the notification in the dtor
962  const SwLayNotify aNotify( this );
963  bool bVert = IsVertical();
964 
966 
967  std::optional<SwBorderAttrAccess> oAccess;
968  const SwBorderAttrs*pAttrs = nullptr;
969 
971  {
972  if ( !isFrameAreaPositionValid() )
973  MakePos();
974 
975  if ( GetUpper() )
976  {
977  // NEW TABLES
978  if ( IsLeaveUpperAllowed() )
979  {
980  if ( !isFrameAreaSizeValid() )
981  {
982  setFramePrintAreaValid(false);
983  }
984  }
985  else
986  {
987  if ( !isFrameAreaSizeValid() )
988  {
989  // Set FixSize; VarSize is set by Format() after calculating the PrtArea
990  setFramePrintAreaValid(false);
991 
992  SwTwips nPrtWidth = (GetUpper()->getFramePrintArea().*fnRect->fnGetWidth)();
993  if( bVert && ( IsBodyFrame() || IsFootnoteContFrame() ) )
994  {
995  SwFrame* pNxt = GetPrev();
996  while( pNxt && !pNxt->IsHeaderFrame() )
997  pNxt = pNxt->GetPrev();
998  if( pNxt )
999  nPrtWidth -= pNxt->getFrameArea().Height();
1000  pNxt = GetNext();
1001  while( pNxt && !pNxt->IsFooterFrame() )
1002  pNxt = pNxt->GetNext();
1003  if( pNxt )
1004  nPrtWidth -= pNxt->getFrameArea().Height();
1005  }
1006 
1007  const tools::Long nDiff = nPrtWidth - (getFrameArea().*fnRect->fnGetWidth)();
1009 
1010  if( IsNeighbourFrame() && IsRightToLeft() )
1011  {
1012  (aFrm.*fnRect->fnSubLeft)( nDiff );
1013  }
1014  else
1015  {
1016  (aFrm.*fnRect->fnAddRight)( nDiff );
1017  }
1018  }
1019  else
1020  {
1021  // Don't leave your upper
1022  const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1023  if( (getFrameArea().*fnRect->fnOverStep)( nDeadLine ) )
1024  {
1025  setFrameAreaSizeValid(false);
1026  }
1027  }
1028  }
1029  }
1030 
1032  {
1033  if ( !oAccess )
1034  {
1035  oAccess.emplace(SwFrame::GetCache(), this);
1036  pAttrs = oAccess->Get();
1037  }
1038  Format( getRootFrame()->GetCurrShell()->GetOut(), pAttrs );
1039  }
1040  } //while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() )
1041 }
1042 
1044 {
1045  if (GetDoc().GetDocumentSettingManager().get( DocumentSettingId::COLLAPSE_EMPTY_CELL_PARA )
1046  && GetText().isEmpty())
1047  {
1048  SwNodeOffset nIdx=GetIndex();
1049  const SwEndNode *pNdBefore=GetNodes()[nIdx-1]->GetEndNode();
1050  const SwEndNode *pNdAfter=GetNodes()[nIdx+1]->GetEndNode();
1051 
1052  // The paragraph is collapsed only if the NdAfter is the end of a cell
1053  bool bInTable = FindTableNode( ) != nullptr;
1054 
1055  SwSortedObjs* pObjs = getLayoutFrame( GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() )->GetDrawObjs( );
1056  const size_t nObjs = ( pObjs != nullptr ) ? pObjs->size( ) : 0;
1057 
1058  return pNdBefore!=nullptr && pNdAfter!=nullptr && nObjs == 0 && bInTable;
1059  }
1060 
1061  return false;
1062 }
1063 
1065 {
1066  if (!IsTextFrame())
1067  return false;
1068 
1069  const SwTextFrame *pTextFrame = static_cast<const SwTextFrame*>(this);
1070  const SwTextNode *pTextNode = pTextFrame->GetTextNodeForParaProps();
1071  // TODO this SwTextNode function is pointless and should be merged in here
1072  return pTextFrame->GetText().isEmpty() && pTextNode && pTextNode->IsCollapse();
1073 }
1074 
1076 {
1077  if ( isFramePrintAreaValid() )
1078  return;
1079 
1080  setFramePrintAreaValid(true);
1081  SwRectFnSet aRectFnSet(this);
1082  const bool bTextFrame = IsTextFrame();
1083  SwTwips nUpper = 0;
1084  if ( bTextFrame && static_cast<SwTextFrame*>(this)->IsHiddenNow() )
1085  {
1086  if ( static_cast<SwTextFrame*>(this)->HasFollow() )
1087  static_cast<SwTextFrame*>(this)->JoinFrame();
1088 
1089  if( aRectFnSet.GetHeight(getFramePrintArea()) )
1090  {
1091  static_cast<SwTextFrame*>(this)->HideHidden();
1092  }
1093 
1094  {
1096  aPrt.Pos().setX(0);
1097  aPrt.Pos().setY(0);
1098  aRectFnSet.SetWidth( aPrt, aRectFnSet.GetWidth(getFrameArea()) );
1099  aRectFnSet.SetHeight( aPrt, 0 );
1100  }
1101 
1102  nUpper = -( aRectFnSet.GetHeight(getFrameArea()) );
1103  }
1104  else
1105  {
1106  // Simplification: ContentFrames are always variable in height!
1107 
1108  // At the FixSize, the surrounding Frame enforces the size;
1109  // the borders are simply subtracted.
1110  const tools::Long nLeft = rAttrs.CalcLeft( this );
1111  const tools::Long nRight = rAttrs.CalcRight( this );
1112  aRectFnSet.SetXMargins( *this, nLeft, nRight );
1113 
1115  SwTwips nWidthArea;
1116  if( pSh && 0!=(nWidthArea=aRectFnSet.GetWidth(pSh->VisArea())) &&
1117  GetUpper()->IsPageBodyFrame() && // but not for BodyFrames in Columns
1118  pSh->GetViewOptions()->getBrowseMode() )
1119  {
1120  // Do not protrude the edge of the visible area. The page may be
1121  // wider, because there may be objects with excess width
1122  // (RootFrame::ImplCalcBrowseWidth())
1123  tools::Long nMinWidth = 0;
1124 
1125  for (size_t i = 0; GetDrawObjs() && i < GetDrawObjs()->size(); ++i)
1126  {
1127  // #i28701# - consider changed type of
1128  // <SwSortedObjs> entries
1129  SwAnchoredObject* pObj = (*GetDrawObjs())[i];
1130  const SwFrameFormat& rFormat = pObj->GetFrameFormat();
1131  const bool bFly = pObj->DynCastFlyFrame() != nullptr;
1132  if ((bFly && (FAR_AWAY == pObj->GetObjRect().Width()))
1133  || rFormat.GetFrameSize().GetWidthPercent())
1134  {
1135  continue;
1136  }
1137 
1138  if ( RndStdIds::FLY_AS_CHAR == rFormat.GetAnchor().GetAnchorId() )
1139  {
1140  nMinWidth = std::max( nMinWidth,
1141  bFly ? rFormat.GetFrameSize().GetWidth()
1142  : pObj->GetObjRect().Width() );
1143  }
1144  }
1145 
1146  const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
1147  tools::Long nWidth = nWidthArea - 2 * ( IsVertical() ? aBorder.Height() : aBorder.Width() );
1148  nWidth -= aRectFnSet.GetLeft(getFramePrintArea());
1149  nWidth -= rAttrs.CalcRightLine();
1150  nWidth = std::max( nMinWidth, nWidth );
1151 
1153  aRectFnSet.SetWidth( aPrt, std::min( nWidth, aRectFnSet.GetWidth(aPrt) ) );
1154  }
1155 
1156  if ( aRectFnSet.GetWidth(getFramePrintArea()) <= MINLAY )
1157  {
1158  // The PrtArea should already be at least MINLAY wide, matching the
1159  // minimal values of the UI
1161  aRectFnSet.SetWidth( aPrt, std::min( tools::Long(MINLAY), aRectFnSet.GetWidth(getFrameArea()) ) );
1162  SwTwips nTmp = aRectFnSet.GetWidth(getFrameArea()) - aRectFnSet.GetWidth(aPrt);
1163 
1164  if( aRectFnSet.GetLeft(aPrt) > nTmp )
1165  {
1166  aRectFnSet.SetLeft( aPrt, nTmp );
1167  }
1168  }
1169 
1170  // The following rules apply for VarSize:
1171  // 1. The first entry of a chain has no top border
1172  // 2. There is never a bottom border
1173  // 3. The top border is the maximum of the distance
1174  // of Prev downwards and our own distance upwards
1175  // Those three rules apply when calculating spacings
1176  // that are given by UL- and LRSpace. There might be a spacing
1177  // in all directions however; this may be caused by borders
1178  // and / or shadows.
1179  // 4. The spacing for TextFrames corresponds to the interline lead,
1180  // at a minimum.
1181 
1182  nUpper = CalcUpperSpace( &rAttrs );
1183 
1184  SwTwips nLower = CalcLowerSpace( &rAttrs );
1185  if (IsCollapse()) {
1186  nUpper=0;
1187  nLower=0;
1188  }
1189 
1190  {
1192  aRectFnSet.SetPosY( aPrt, !aRectFnSet.IsVert() ? nUpper : nLower);
1193  }
1194 
1195  nUpper += nLower;
1196  nUpper -= aRectFnSet.GetHeight(getFrameArea()) - aRectFnSet.GetHeight(getFramePrintArea());
1197  }
1198  // If there's a difference between old and new size, call Grow() or
1199  // Shrink() respectively.
1200  if ( nUpper )
1201  {
1202  if ( nUpper > 0 )
1203  GrowFrame( nUpper );
1204  else
1205  ShrinkFrame( -nUpper );
1206  }
1207 }
1208 
1209 #define STOP_FLY_FORMAT 10
1210 // - loop prevention
1211 const int cnStopFormat = 15;
1212 
1213 inline void ValidateSz( SwFrame *pFrame )
1214 {
1215  if ( pFrame )
1216  {
1217  pFrame->setFrameAreaSizeValid(true);
1218  pFrame->setFramePrintAreaValid(true);
1219  }
1220 }
1221 
1223 {
1224  OSL_ENSURE( GetUpper(), "no Upper?" );
1225  OSL_ENSURE( IsTextFrame(), "MakeAll(), NoText" );
1226 
1227  if ( !IsFollow() && StackHack::IsLocked() )
1228  return;
1229 
1230  if ( IsJoinLocked() )
1231  return;
1232 
1233  OSL_ENSURE( !static_cast<SwTextFrame*>(this)->IsSwapped(), "Calculation of a swapped frame" );
1234 
1235  StackHack aHack;
1236 
1237  if ( static_cast<SwTextFrame*>(this)->IsLocked() )
1238  {
1239  OSL_FAIL( "Format for locked TextFrame." );
1240  return;
1241  }
1242 
1243  std::optional<SwFrameDeleteGuard> oDeleteGuard(std::in_place, this);
1244  LockJoin();
1245  tools::Long nFormatCount = 0;
1246  // - loop prevention
1247  int nConsecutiveFormatsWithoutChange = 0;
1248  PROTOCOL_ENTER( this, PROT::MakeAll, DbgAction::NONE, nullptr )
1249 
1250  // takes care of the notification in the dtor
1251  std::optional<SwContentNotify> oNotify( std::in_place, this );
1252 
1253  // as long as bMakePage is true, a new page can be created (exactly once)
1254  bool bMakePage = true;
1255  // bMovedBwd gets set to true when the frame flows backwards
1256  bool bMovedBwd = false;
1257  // as long as bMovedFwd is false, the Frame may flow backwards (until
1258  // it has been moved forward once)
1259  bool bMovedFwd = false;
1260  sal_Bool bFormatted = false; // For the widow/orphan rules, we encourage the
1261  // last ContentFrame of a chain to format. This only
1262  // needs to happen once. Every time the Frame is
1263  // moved, the flag will have to be reset.
1264  bool bMustFit = false; // Once the emergency brake is pulled,
1265  // no other prepares will be triggered
1266  bool bFitPromise = false; // If a paragraph didn't fit, but promises
1267  // with WouldFit that it would adjust accordingly,
1268  // this flag is set. If it turns out that it
1269  // didn't keep it's promise, we can act in a
1270  // controlled fashion.
1271  const bool bFly = IsInFly();
1272  const bool bTab = IsInTab();
1273  const bool bFootnote = IsInFootnote();
1274  const bool bSct = IsInSct();
1275  Point aOldFramePos; // This is so we can compare with the last pos
1276  Point aOldPrtPos; // and determine whether it makes sense to Prepare
1277 
1278  SwBorderAttrAccess aAccess( SwFrame::GetCache(), this );
1279  const SwBorderAttrs &rAttrs = *aAccess.Get();
1280 
1281  if ( !IsFollow() && rAttrs.JoinedWithPrev( *(this) ) )
1282  {
1283  oNotify->SetBordersJoinedWithPrev();
1284  }
1285 
1286  const bool bKeep = IsKeep(rAttrs.GetAttrSet().GetKeep(), GetBreakItem());
1287 
1288  std::unique_ptr<SwSaveFootnoteHeight> pSaveFootnote;
1289  if ( bFootnote )
1290  {
1291  SwFootnoteFrame *pFootnote = FindFootnoteFrame();
1292  SwSectionFrame* pSct = pFootnote->FindSctFrame();
1293  if ( !static_cast<SwTextFrame*>(pFootnote->GetRef())->IsLocked() )
1294  {
1295  SwFootnoteBossFrame* pBoss = pFootnote->GetRef()->FindFootnoteBossFrame(
1296  pFootnote->GetAttr()->GetFootnote().IsEndNote() );
1297  if( !pSct || pSct->IsColLocked() || !pSct->Growable() )
1298  pSaveFootnote.reset( new SwSaveFootnoteHeight( pBoss,
1299  static_cast<SwTextFrame*>(pFootnote->GetRef())->GetFootnoteLine( pFootnote->GetAttr() ) ) );
1300  }
1301  }
1302 
1303  if ( GetUpper()->IsSctFrame() &&
1304  HasFollow() && !GetFollow()->IsDeleteForbidden() &&
1305  &GetFollow()->GetFrame() == GetNext() )
1306  {
1307  static_cast<SwTextFrame&>(*this).JoinFrame();
1308  }
1309 
1310  // #i28701# - move master forward, if it has to move,
1311  // because of its object positioning.
1312  if ( !static_cast<SwTextFrame*>(this)->IsFollow() )
1313  {
1314  sal_uInt32 nToPageNum = 0;
1315  const bool bMoveFwdByObjPos = SwLayouter::FrameMovedFwdByObjPos(
1316  *(GetAttrSet()->GetDoc()),
1317  *static_cast<SwTextFrame*>(this),
1318  nToPageNum );
1319  // #i58182#
1320  // Also move a paragraph forward, which is the first one inside a table cell.
1321  if ( bMoveFwdByObjPos &&
1322  FindPageFrame()->GetPhyPageNum() < nToPageNum &&
1323  ( lcl_Prev( this ) ||
1324  GetUpper()->IsCellFrame() ||
1325  ( GetUpper()->IsSctFrame() &&
1326  GetUpper()->GetUpper()->IsCellFrame() ) ) &&
1327  IsMoveable() )
1328  {
1329  bMovedFwd = true;
1330  MoveFwd( bMakePage, false );
1331  }
1332  }
1333 
1334  // If a Follow sits next to its Master and doesn't fit, we know it can
1335  // be moved right now.
1336  if ( lcl_Prev( this ) && static_cast<SwTextFrame*>(this)->IsFollow() && IsMoveable() )
1337  {
1338  bMovedFwd = true;
1339  // If follow frame is in table, its master will be the last in the
1340  // current table cell. Thus, invalidate the printing area of the master.
1341  if ( IsInTab() )
1342  {
1343  lcl_Prev( this )->InvalidatePrt();
1344  }
1345  MoveFwd( bMakePage, false );
1346  }
1347 
1348  // Check footnote content for forward move.
1349  // If a content of a footnote is on a prior page/column as its invalid
1350  // reference, it can be moved forward.
1351  if ( bFootnote && !isFrameAreaPositionValid() )
1352  {
1353  SwFootnoteFrame* pFootnote = FindFootnoteFrame();
1354  SwContentFrame* pRefCnt = pFootnote ? pFootnote->GetRef() : nullptr;
1355 
1356  if ( pRefCnt && !pRefCnt->isFrameAreaDefinitionValid() )
1357  {
1358  SwFootnoteBossFrame* pFootnoteBossOfFootnote = pFootnote->FindFootnoteBossFrame();
1359  SwFootnoteBossFrame* pFootnoteBossOfRef = pRefCnt->FindFootnoteBossFrame();
1360  //<loop of movefwd until condition held or no move>
1361  if ( pFootnoteBossOfFootnote && pFootnoteBossOfRef &&
1362  pFootnoteBossOfFootnote != pFootnoteBossOfRef &&
1363  pFootnoteBossOfFootnote->IsBefore( pFootnoteBossOfRef ) )
1364  {
1365  bMovedFwd = true;
1366  MoveFwd( bMakePage, false );
1367  }
1368  }
1369  }
1370 
1371  SwRectFnSet aRectFnSet(this);
1372 
1373  SwFrame const* pMoveBwdPre(nullptr);
1374  bool isMoveBwdPreValid(false);
1375 
1376  SwRect aOldFrame_StopFormat, aOldFrame_StopFormat2;
1377  SwRect aOldPrt_StopFormat, aOldPrt_StopFormat2;
1378 
1380  {
1381  // - loop prevention
1382  aOldFrame_StopFormat2 = aOldFrame_StopFormat;
1383  aOldPrt_StopFormat2 = aOldPrt_StopFormat;
1384  aOldFrame_StopFormat = getFrameArea();
1385  aOldPrt_StopFormat = getFramePrintArea();
1386 
1387  bool bMoveable = IsMoveable();
1388  if (bMoveable)
1389  {
1390  SwFrame *pPre = GetIndPrev();
1391  if ( CheckMoveFwd( bMakePage, bKeep, bMovedBwd ) )
1392  {
1393  aRectFnSet.Refresh(this);
1394  bMovedFwd = true;
1395  if ( bMovedBwd )
1396  {
1397  // While flowing back, the Upper was encouraged to
1398  // completely re-paint itself. We can skip this now after
1399  // flowing back and forth.
1401  // The predecessor was invalidated, so this is obsolete as well now.
1402  assert(pPre);
1403  if ((pPre == pMoveBwdPre && isMoveBwdPreValid) && !pPre->IsSctFrame())
1404  ::ValidateSz( pPre );
1405  }
1406  bMoveable = IsMoveable();
1407  }
1408  }
1409 
1410  aOldFramePos = aRectFnSet.GetPos(getFrameArea());
1411  aOldPrtPos = aRectFnSet.GetPos(getFramePrintArea());
1412 
1413  if ( !isFrameAreaPositionValid() )
1414  MakePos();
1415 
1416  //Set FixSize. VarSize is being adjusted by Format().
1417  if ( !isFrameAreaSizeValid() )
1418  {
1419  // invalidate printing area flag, if the following conditions are hold:
1420  // - current frame width is 0.
1421  // - current printing area width is 0.
1422  // - frame width is adjusted to a value greater than 0.
1423  // - printing area flag is true.
1424  // Thus, it's assured that the printing area is adjusted, if the
1425  // frame area width changes its width from 0 to something greater
1426  // than 0.
1427  // Note: A text frame can be in such a situation, if the format is
1428  // triggered by method call <SwCursorShell::SetCursor()> after
1429  // loading the document.
1430  const SwTwips nNewFrameWidth = aRectFnSet.GetWidth(GetUpper()->getFramePrintArea());
1431 
1432  if ( isFramePrintAreaValid() &&
1433  nNewFrameWidth > 0 &&
1434  aRectFnSet.GetWidth(getFrameArea()) == 0 &&
1435  aRectFnSet.GetWidth(getFramePrintArea()) == 0 )
1436  {
1437  setFramePrintAreaValid(false);
1438  }
1439 
1440  {
1442  aRectFnSet.SetWidth( aFrm, nNewFrameWidth );
1443  }
1444 
1445  // When a lower of a vertically aligned fly frame changes its size we need to recalculate content pos.
1446  if( GetUpper() && GetUpper()->IsFlyFrame() &&
1447  GetUpper()->GetFormat()->GetTextVertAdjust().GetValue() != SDRTEXTVERTADJUST_TOP )
1448  {
1449  static_cast<SwFlyFrame*>(GetUpper())->InvalidateContentPos();
1451  }
1452  }
1453  if ( !isFramePrintAreaValid() )
1454  {
1455  const tools::Long nOldW = aRectFnSet.GetWidth(getFramePrintArea());
1456  // #i34730# - keep current frame height
1457  const SwTwips nOldH = aRectFnSet.GetHeight(getFrameArea());
1458  MakePrtArea( rAttrs );
1459  if ( nOldW != aRectFnSet.GetWidth(getFramePrintArea()) )
1461  // #i34730# - check, if frame height has changed.
1462  // If yes, send a PrepareHint::AdjustSizeWithoutFormatting and invalidate the size flag to
1463  // force a format. The format will check in its method
1464  // <SwTextFrame::CalcPreps()>, if the already formatted lines still
1465  // fit and if not, performs necessary actions.
1466  // #i40150# - no check, if frame is undersized.
1467  if ( isFrameAreaSizeValid() && !IsUndersized() && nOldH != aRectFnSet.GetHeight(getFrameArea()) )
1468  {
1469  // #115759# - no PrepareHint::AdjustSizeWithoutFormatting and size
1470  // invalidation, if height decreases only by the additional
1471  // lower space as last content of a table cell and an existing
1472  // follow containing one line exists.
1473  const SwTwips nHDiff = nOldH - aRectFnSet.GetHeight(getFrameArea());
1474  const bool bNoPrepAdjustFrame =
1475  nHDiff > 0 && IsInTab() && GetFollow() &&
1476  (1 == static_cast<SwTextFrame*>(GetFollow())->GetLineCount(TextFrameIndex(COMPLETE_STRING))
1477  || aRectFnSet.GetWidth(static_cast<SwTextFrame*>(GetFollow())->getFrameArea()) < 0) &&
1479  if ( !bNoPrepAdjustFrame )
1480  {
1482  setFrameAreaSizeValid(false);
1483  }
1484  }
1485  }
1486 
1487  // To make the widow and orphan rules work, we need to notify the ContentFrame.
1488  // Criteria:
1489  // - It needs to be movable (otherwise, splitting doesn't make sense)
1490  // - It needs to overlap with the lower edge of the PrtArea of the Upper
1491  if ( !bMustFit )
1492  {
1493  bool bWidow = true;
1494  const SwTwips nDeadLine = aRectFnSet.GetPrtBottom(*GetUpper());
1495  if( bMoveable && !bFormatted &&
1496  ( GetFollow() || aRectFnSet.OverStep( getFrameArea(), nDeadLine ) ) )
1497  {
1498  Prepare( PrepareHint::WidowsOrphans, nullptr, false );
1499  setFrameAreaSizeValid(false);
1500  bWidow = false;
1501  }
1502  if( aRectFnSet.GetPos(getFrameArea()) != aOldFramePos ||
1503  aRectFnSet.GetPos(getFramePrintArea()) != aOldPrtPos )
1504  {
1505  // In this Prepare, an InvalidateSize_() might happen.
1506  // isFrameAreaSizeValid() becomes false and Format() gets called.
1507  Prepare( PrepareHint::FramePositionChanged, static_cast<const void*>(&bFormatted), false );
1508  if ( bWidow && GetFollow() )
1509  {
1510  Prepare( PrepareHint::WidowsOrphans, nullptr, false );
1511  setFrameAreaSizeValid(false);
1512  }
1513  }
1514  }
1515  if ( !isFrameAreaSizeValid() )
1516  {
1517  setFrameAreaSizeValid(true);
1518  bFormatted = true;
1519  ++nFormatCount;
1520  if( nFormatCount > STOP_FLY_FORMAT )
1521  SetFlyLock( true );
1522  // - loop prevention
1523  // No format any longer, if <cnStopFormat> consecutive formats
1524  // without change occur.
1525  if ( nConsecutiveFormatsWithoutChange <= cnStopFormat )
1526  {
1527  Format(getRootFrame()->GetCurrShell()->GetOut());
1528  }
1529 #if OSL_DEBUG_LEVEL > 0
1530  else
1531  {
1532  OSL_FAIL( "debug assertion: <SwContentFrame::MakeAll()> - format of text frame suppressed by fix b6448963" );
1533  }
1534 #endif
1535  }
1536 
1537  // If this is the first one in a chain, check if this can flow
1538  // backwards (if this is movable at all).
1539  // To prevent oscillations/loops, check that this has not just
1540  // flowed forwards.
1541  bool bDummy;
1542  auto const pTemp(GetIndPrev());
1543  auto const bTemp(pTemp && pTemp->isFrameAreaSizeValid()
1544  && pTemp->isFramePrintAreaValid());
1545  if ( !lcl_Prev( this ) &&
1546  !bMovedFwd &&
1547  ( bMoveable || ( bFly && !bTab ) ) &&
1548  ( !bFootnote || !GetUpper()->FindFootnoteFrame()->GetPrev() )
1549  && MoveBwd( bDummy ) )
1550  {
1551  aRectFnSet.Refresh(this);
1552  pMoveBwdPre = pTemp;
1553  isMoveBwdPreValid = bTemp;
1554  bMovedBwd = true;
1555  bFormatted = false;
1556  if ( bKeep && bMoveable )
1557  {
1558  if( CheckMoveFwd( bMakePage, false, bMovedBwd ) )
1559  {
1560  bMovedFwd = true;
1561  bMoveable = IsMoveable();
1562  aRectFnSet.Refresh(this);
1563  }
1564  Point aOldPos = aRectFnSet.GetPos(getFrameArea());
1565  MakePos();
1566  if( aOldPos != aRectFnSet.GetPos(getFrameArea()) )
1567  {
1568  Prepare( PrepareHint::FramePositionChanged, static_cast<const void*>(&bFormatted), false );
1569  if ( !isFrameAreaSizeValid() )
1570  {
1571  {
1573  aRectFnSet.SetWidth( aFrm, aRectFnSet.GetWidth(GetUpper()->getFramePrintArea()) );
1574  }
1575 
1576  if ( !isFramePrintAreaValid() )
1577  {
1578  const tools::Long nOldW = aRectFnSet.GetWidth(getFramePrintArea());
1579  MakePrtArea( rAttrs );
1580  if( nOldW != aRectFnSet.GetWidth(getFramePrintArea()) )
1581  Prepare( PrepareHint::FixSizeChanged, nullptr, false );
1582  }
1583  if( GetFollow() )
1584  {
1585  Prepare( PrepareHint::WidowsOrphans, nullptr, false );
1586  }
1587 
1588  setFrameAreaSizeValid(true);
1589  bFormatted = true;
1590  Format(getRootFrame()->GetCurrShell()->GetOut());
1591  }
1592  }
1593  SwFrame *pNxt = HasFollow() ? nullptr : FindNext();
1594  while( pNxt && pNxt->IsSctFrame() )
1595  { // Leave empty sections out, go into the other ones.
1596  if( static_cast<SwSectionFrame*>(pNxt)->GetSection() )
1597  {
1598  SwFrame* pTmp = static_cast<SwSectionFrame*>(pNxt)->ContainsAny();
1599  if( pTmp )
1600  {
1601  pNxt = pTmp;
1602  break;
1603  }
1604  }
1605  pNxt = pNxt->FindNext();
1606  }
1607  if ( pNxt )
1608  {
1609  pNxt->Calc(getRootFrame()->GetCurrShell()->GetOut());
1610  if( isFrameAreaPositionValid() && !GetIndNext() )
1611  {
1612  SwSectionFrame *pSct = FindSctFrame();
1613  if( pSct && !pSct->isFrameAreaSizeValid() )
1614  {
1615  SwSectionFrame* pNxtSct = pNxt->FindSctFrame();
1616  if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
1617  {
1619  }
1620  }
1621  else
1622  {
1624  }
1625  }
1626  }
1627  }
1628  }
1629 
1630  // In footnotes, the TextFrame may validate itself, which can lead to the
1631  // situation that it's position is wrong despite being "valid".
1632  if ( isFrameAreaPositionValid() )
1633  {
1634  // #i59341#
1635  // Workaround for inadequate layout algorithm:
1636  // suppress invalidation and calculation of position, if paragraph
1637  // has formatted itself at least STOP_FLY_FORMAT times and
1638  // has anchored objects.
1639  // Thus, the anchored objects get the possibility to format itself
1640  // and this probably solve the layout loop.
1641  if ( bFootnote &&
1642  nFormatCount <= STOP_FLY_FORMAT &&
1643  !GetDrawObjs() )
1644  {
1646  MakePos();
1647  aOldFramePos = aRectFnSet.GetPos(getFrameArea());
1648  aOldPrtPos = aRectFnSet.GetPos(getFramePrintArea());
1649  }
1650  }
1651 
1652  // - loop prevention
1653  {
1654  if ( (aOldFrame_StopFormat == getFrameArea() || aOldFrame_StopFormat2 == getFrameArea() ) &&
1655  (aOldPrt_StopFormat == getFramePrintArea() || aOldPrt_StopFormat2 == getFramePrintArea()))
1656  {
1657  ++nConsecutiveFormatsWithoutChange;
1658  }
1659  else
1660  {
1661  nConsecutiveFormatsWithoutChange = 0;
1662  }
1663  }
1664 
1665  // Yet again an invalid value? Repeat from the start...
1667  continue;
1668 
1669  // Done?
1670  // Attention: because height == 0, it's better to use Top()+Height() instead of
1671  // Bottom(). This might happen with undersized TextFrames on the lower edge of a
1672  // multi-column section
1673  const tools::Long nPrtBottom = aRectFnSet.GetPrtBottom(*GetUpper());
1674  tools::Long nBottomDist = aRectFnSet.BottomDist(getFrameArea(), nPrtBottom);
1675 
1676  // Hide whitespace may require not to insert a new page.
1677  SwPageFrame* pPageFrame = FindPageFrame();
1678  const bool bHeightValid = pPageFrame->CheckPageHeightValidForHideWhitespace(nBottomDist);
1679  if (!bHeightValid)
1680  {
1681  pPageFrame->InvalidateSize();
1682  nBottomDist = 0;
1683  }
1684 
1685  if( nBottomDist >= 0 )
1686  {
1687  if ( bKeep && bMoveable )
1688  {
1689  // We make sure the successor will be formatted the same.
1690  // This way, we keep control until (almost) everything is stable,
1691  // allowing us to avoid endless loops caused by ever repeating
1692  // retries.
1693 
1694  // bMoveFwdInvalid is required for #38407#. This was originally solved
1695  // in flowfrm.cxx rev 1.38, but broke the above schema and
1696  // preferred to play towers of hanoi (#43669#).
1697  SwFrame *pNxt = HasFollow() ? nullptr : FindNext();
1698  // For sections we prefer the content, because it can change
1699  // the page if required.
1700  while( pNxt && pNxt->IsSctFrame() )
1701  {
1702  if( static_cast<SwSectionFrame*>(pNxt)->GetSection() )
1703  {
1704  pNxt = static_cast<SwSectionFrame*>(pNxt)->ContainsAny();
1705  break;
1706  }
1707  pNxt = pNxt->FindNext();
1708  }
1709  if ( pNxt )
1710  {
1711  const bool bMoveFwdInvalid = nullptr != GetIndNext();
1712  const bool bNxtNew =
1713  ( 0 == aRectFnSet.GetHeight(pNxt->getFramePrintArea()) ) &&
1714  (!pNxt->IsTextFrame() ||!static_cast<SwTextFrame*>(pNxt)->IsHiddenNow());
1715 
1716  pNxt->Calc(getRootFrame()->GetCurrShell()->GetOut());
1717 
1718  if ( !bMovedBwd &&
1719  ((bMoveFwdInvalid && !GetIndNext()) ||
1720  bNxtNew) )
1721  {
1722  if( bMovedFwd )
1723  oNotify->SetInvaKeep();
1724  bMovedFwd = false;
1725  }
1726  }
1727  }
1728  continue;
1729  }
1730 
1731  // I don't fit into my parents, so it's time to make changes
1732  // as constructively as possible.
1733 
1734  //If I'm NOT allowed to leave the parent Frame, I've got a problem.
1735  // Following Arthur Dent, we do the only thing that you can do with
1736  // an unsolvable problem: We ignore it with all our power.
1737  if ( !bMoveable || IsUndersized() )
1738  {
1739  if( !bMoveable && IsInTab() )
1740  {
1741  tools::Long nDiff = -aRectFnSet.BottomDist( getFrameArea(), aRectFnSet.GetPrtBottom(*GetUpper()) );
1742  tools::Long nReal = GetUpper()->Grow( nDiff );
1743  if( nReal )
1744  continue;
1745  }
1746  break;
1747  }
1748 
1749  // If there's no way I can make myself fit into my Upper, the situation
1750  // could still probably be mitigated by splitting up.
1751  // This situation arises with freshly created Follows that had been moved
1752  // to the next page but is still too big for it - ie. needs to be split
1753  // as well.
1754 
1755  // If I'm unable to split (WouldFit()) and can't be fitted, I'm going
1756  // to tell my TextFrame part that, if possible, we still need to split despite
1757  // the "don't split" attribute.
1758  bool bMoveOrFit = false;
1759  bool bDontMoveMe = !GetIndPrev();
1760  if( bDontMoveMe && IsInSct() )
1761  {
1763  bDontMoveMe = !pBoss->IsInSct() ||
1764  ( !pBoss->Lower()->GetNext() && !pBoss->GetPrev() );
1765  }
1766 
1767  // Finally, we are able to split table rows. Therefore, bDontMoveMe
1768  // can be set to false:
1769  if( bDontMoveMe && IsInTab() &&
1770  nullptr != GetNextCellLeaf() )
1771  bDontMoveMe = false;
1772 
1773  assert(bMoveable);
1774 
1775  if ( bDontMoveMe && aRectFnSet.GetHeight(getFrameArea()) >
1776  aRectFnSet.GetHeight(GetUpper()->getFramePrintArea()) )
1777  {
1778  if ( !bFitPromise )
1779  {
1780  SwTwips nTmp = aRectFnSet.GetHeight(GetUpper()->getFramePrintArea()) -
1781  aRectFnSet.GetTop(getFramePrintArea());
1782  bool bSplit = !IsFwdMoveAllowed();
1783  if ( nTmp > 0 && WouldFit( nTmp, bSplit, false ) )
1784  {
1785  Prepare( PrepareHint::WidowsOrphans, nullptr, false );
1786  setFrameAreaSizeValid(false);
1787  bFitPromise = true;
1788  continue;
1789  }
1790  /*
1791  * In earlier days, we never tried to fit TextFrames in
1792  * frames and sections using bMoveOrFit by ignoring
1793  * its attributes (Widows, Keep).
1794  * This should have been done at least for column frames;
1795  * as it must be tried anyway with linked frames and sections.
1796  * Exception: If we sit in FormatWidthCols, we must not ignore
1797  * the attributes.
1798  */
1799  else if ( !bFootnote &&
1800  ( !bFly || !FindFlyFrame()->IsColLocked() ) &&
1801  ( !bSct || !FindSctFrame()->IsColLocked() ) )
1802  bMoveOrFit = true;
1803  }
1804 #if OSL_DEBUG_LEVEL > 0
1805  else
1806  {
1807  OSL_FAIL( "+TextFrame didn't respect WouldFit promise." );
1808  }
1809 #endif
1810  }
1811 
1812  // Let's see if I can find some space somewhere...
1813  // footnotes in the neighbourhood are moved into _MoveFootnoteCntFwd
1814  SwFrame *pPre = GetIndPrev();
1815  SwFrame *pOldUp = GetUpper();
1816 
1817 /* MA 13. Oct. 98: What is this supposed to be!?
1818  * AMA 14. Dec 98: If a column section can't find any space for its first ContentFrame, it should be
1819  * moved not only to the next column, but probably even to the next page, creating
1820  * a section-follow there.
1821  */
1822  if( IsInSct() && bMovedFwd && bMakePage && pOldUp->IsColBodyFrame() &&
1823  pOldUp->GetUpper()->GetUpper()->IsSctFrame() &&
1824  ( pPre || pOldUp->GetUpper()->GetPrev() ) &&
1825  static_cast<SwSectionFrame*>(pOldUp->GetUpper()->GetUpper())->MoveAllowed(this) )
1826  {
1827  bMovedFwd = false;
1828  }
1829 
1830  const bool bCheckForGrownBody = pOldUp->IsBodyFrame();
1831  const tools::Long nOldBodyHeight = aRectFnSet.GetHeight(pOldUp->getFrameArea());
1832 
1833  if ( !bMovedFwd && !MoveFwd( bMakePage, false ) )
1834  bMakePage = false;
1835  aRectFnSet.Refresh(this);
1836  if (!bMovedFwd && bFootnote && GetIndPrev() != pPre)
1837  { // SwFlowFrame::CutTree() could have formatted and deleted pPre
1838  auto const pPrevFootnoteFrame(static_cast<SwFootnoteFrame const*>(
1839  FindFootnoteFrame())->GetMaster());
1840  bool bReset = true;
1841  if (pPrevFootnoteFrame)
1842  { // use GetIndNext() in case there are sections
1843  for (auto p = pPrevFootnoteFrame->Lower(); p; p = p->GetIndNext())
1844  {
1845  if (p == pPre)
1846  {
1847  bReset = false;
1848  break;
1849  }
1850  }
1851  }
1852  if (bReset)
1853  {
1854  pPre = nullptr;
1855  }
1856  }
1857 
1858  // If MoveFwd moves the paragraph to the next page, a following
1859  // paragraph, which contains footnotes can cause the old upper
1860  // frame to grow. In this case we explicitly allow a new check
1861  // for MoveBwd. Robust: We also check the bMovedBwd flag again.
1862  // If pOldUp was a footnote frame, it has been deleted inside MoveFwd.
1863  // Therefore we only check for growing body frames.
1864  bMovedFwd = !bCheckForGrownBody || bMovedBwd || pOldUp == GetUpper() ||
1865  aRectFnSet.GetHeight(pOldUp->getFrameArea()) <= nOldBodyHeight;
1866 
1867  bFormatted = false;
1868  if ( bMoveOrFit && GetUpper() == pOldUp )
1869  {
1870  // FME 2007-08-30 #i81146# new loop control
1871  if ( nConsecutiveFormatsWithoutChange <= cnStopFormat )
1872  {
1873  Prepare( PrepareHint::MustFit, nullptr, false );
1874  setFrameAreaSizeValid(false);
1875  bMustFit = true;
1876  continue;
1877  }
1878 
1879 #if OSL_DEBUG_LEVEL > 0
1880  OSL_FAIL( "LoopControl in SwContentFrame::MakeAll" );
1881 #endif
1882  }
1883  if ( bMovedBwd && GetUpper() )
1884  { // Retire invalidations that have become useless.
1886  if( pPre && !pPre->IsSctFrame() )
1887  ::ValidateSz( pPre );
1888  }
1889 
1890  } //while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() )
1891 
1892  // NEW: Looping Louie (Light). Should not be applied in balanced sections.
1893  // Should only be applied if there is no better solution!
1894  LOOPING_LOUIE_LIGHT( bMovedFwd && bMovedBwd && !IsInBalancedSection() &&
1895  (
1896 
1897  ( bFootnote && !FindFootnoteFrame()->GetRef()->IsInSct() ) ||
1898 
1899  // #i33887#
1900  ( IsInSct() && bKeep )
1901 
1902  // ... add your conditions here ...
1903 
1904  ),
1905  static_cast<SwTextFrame&>(*this) );
1906 
1907  pSaveFootnote.reset();
1908 
1909  UnlockJoin();
1910  oDeleteGuard.reset();
1911  if ( bMovedFwd || bMovedBwd )
1912  oNotify->SetInvaKeep();
1913  if ( bMovedFwd )
1914  {
1915  oNotify->SetInvalidatePrevPrtArea();
1916  }
1917  oNotify.reset();
1918  SetFlyLock( false );
1919 }
1920 
1921 void MakeNxt( SwFrame *pFrame, SwFrame *pNxt )
1922 {
1923  // fix(25455): Validate, otherwise this leads to a recursion.
1924  // The first try, cancelling with pFrame = 0 if !Valid, leads to a problem, as
1925  // the Keep may not be considered properly anymore (27417).
1926  const bool bOldPos = pFrame->isFrameAreaPositionValid();
1927  const bool bOldSz = pFrame->isFrameAreaSizeValid();
1928  const bool bOldPrt = pFrame->isFramePrintAreaValid();
1929  pFrame->setFrameAreaPositionValid(true);
1930  pFrame->setFrameAreaSizeValid(true);
1931  pFrame->setFramePrintAreaValid(true);
1932 
1933  // fix(29272): Don't call MakeAll - there, pFrame might be invalidated again, and
1934  // we recursively end up in here again.
1935  if ( pNxt->IsContentFrame() )
1936  {
1937  SwContentNotify aNotify( static_cast<SwContentFrame*>(pNxt) );
1938  SwBorderAttrAccess aAccess( SwFrame::GetCache(), pNxt );
1939  const SwBorderAttrs &rAttrs = *aAccess.Get();
1940  if ( !pNxt->isFrameAreaSizeValid() )
1941  {
1943 
1944  if( pNxt->IsVertical() )
1945  {
1946  aFrm.Height( pNxt->GetUpper()->getFramePrintArea().Height() );
1947  }
1948  else
1949  {
1950  aFrm.Width( pNxt->GetUpper()->getFramePrintArea().Width() );
1951  }
1952  }
1953  static_cast<SwContentFrame*>(pNxt)->MakePrtArea( rAttrs );
1954  pNxt->Format( pNxt->getRootFrame()->GetCurrShell()->GetOut(), &rAttrs );
1955  }
1956  else
1957  {
1958  SwLayNotify aNotify( static_cast<SwLayoutFrame*>(pNxt) );
1959  SwBorderAttrAccess aAccess( SwFrame::GetCache(), pNxt );
1960  const SwBorderAttrs &rAttrs = *aAccess.Get();
1961  if ( !pNxt->isFrameAreaSizeValid() )
1962  {
1964 
1965  if( pNxt->IsVertical() )
1966  {
1967  aFrm.Height( pNxt->GetUpper()->getFramePrintArea().Height() );
1968  }
1969  else
1970  {
1971  aFrm.Width( pNxt->GetUpper()->getFramePrintArea().Width() );
1972  }
1973  }
1974  pNxt->Format( pNxt->getRootFrame()->GetCurrShell()->GetOut(), &rAttrs );
1975  }
1976 
1977  pFrame->setFrameAreaPositionValid(bOldPos);
1978  pFrame->setFrameAreaSizeValid(bOldSz);
1979  pFrame->setFramePrintAreaValid(bOldPrt);
1980 }
1981 
1984 static bool lcl_IsNextFootnoteBoss( const SwFrame *pFrame, const SwFrame* pNxt )
1985 {
1986  assert(pFrame && pNxt && "lcl_IsNextFootnoteBoss: No Frames?");
1987  pFrame = pFrame->FindFootnoteBossFrame();
1988  pNxt = pNxt->FindFootnoteBossFrame();
1989  // If pFrame is a last column, we use the page instead.
1990  while( pFrame && pFrame->IsColumnFrame() && !pFrame->GetNext() )
1991  pFrame = pFrame->GetUpper()->FindFootnoteBossFrame();
1992  // If pNxt is a first column, we use the page instead.
1993  while( pNxt && pNxt->IsColumnFrame() && !pNxt->GetPrev() )
1994  pNxt = pNxt->GetUpper()->FindFootnoteBossFrame();
1995  // So... now pFrame and pNxt are either two adjacent pages or columns.
1996  return pFrame && pNxt && pFrame->GetNext() == pNxt;
1997 }
1998 
2000  SwLayoutFrame *pNewUpper,
2001  bool bTstMove,
2002  const bool bObjsInNewUpper )
2003 {
2004  // To have the footnote select its place carefully, it needs
2005  // to be moved in any case if there is at least one page/column
2006  // between the footnote and the new Upper.
2007  SwFootnoteFrame* pFootnoteFrame = nullptr;
2008  if ( IsInFootnote() )
2009  {
2010  if( !lcl_IsNextFootnoteBoss( pNewUpper, this ) )
2011  return true;
2012  pFootnoteFrame = FindFootnoteFrame();
2013  }
2014 
2015  bool bRet;
2016  bool bSplit = !pNewUpper->Lower();
2017  SwContentFrame *pFrame = this;
2018  const SwFrame *pTmpPrev = pNewUpper->Lower();
2019  if( pTmpPrev && pTmpPrev->IsFootnoteFrame() )
2020  pTmpPrev = static_cast<const SwFootnoteFrame*>(pTmpPrev)->Lower();
2021  while ( pTmpPrev && pTmpPrev->GetNext() )
2022  pTmpPrev = pTmpPrev->GetNext();
2023  do
2024  {
2025  // #i46181#
2026  SwTwips nSecondCheck = 0;
2027  SwTwips nOldSpace = nSpace;
2028  bool bOldSplit = bSplit;
2029 
2030  if ( bTstMove || IsInFly() || ( IsInSct() &&
2031  ( pFrame->GetUpper()->IsColBodyFrame() || ( pFootnoteFrame &&
2032  pFootnoteFrame->GetUpper()->GetUpper()->IsColumnFrame() ) ) ) )
2033  {
2034  // This is going to get a bit insidious now. If you're faint of heart,
2035  // you'd better look away here. If a Fly contains columns, then the Contents
2036  // are movable, except ones in the last column (see SwFrame::IsMoveable()).
2037  // Of course they're allowed to float back. WouldFit() only returns a usable
2038  // value if the Frame is movable. To fool WouldFit() into believing there's
2039  // a movable Frame, I'm just going to hang it somewhere else for the time.
2040  // The same procedure applies for column sections to make SwSectionFrame::Growable()
2041  // return the proper value.
2042  // Within footnotes, we may even need to put the SwFootnoteFrame somewhere else, if
2043  // there's no SwFootnoteFrame there.
2044  SwFrame* pTmpFrame = pFrame->IsInFootnote() && !pNewUpper->FindFootnoteFrame() ?
2045  static_cast<SwFrame*>(pFrame->FindFootnoteFrame()) : pFrame;
2046  SwLayoutFrame *pUp = pTmpFrame->GetUpper();
2047  SwFrame *pOldNext = pTmpFrame->GetNext();
2048  pTmpFrame->RemoveFromLayout();
2049  pTmpFrame->InsertBefore( pNewUpper, nullptr );
2050  // tdf#107126 for a section in a footnote, we have only inserted
2051  // the SwTextFrame but no SwSectionFrame - reset mbInfSct flag
2052  // to avoid crashing (but perhaps we should create a temp
2053  // SwSectionFrame here because WidowsAndOrphans checks for that?)
2054  pTmpFrame->InvalidateInfFlags();
2055  if ( pFrame->IsTextFrame() &&
2056  ( bTstMove ||
2057  static_cast<SwTextFrame*>(pFrame)->HasFollow() ||
2058  ( !static_cast<SwTextFrame*>(pFrame)->HasPara() &&
2059  !static_cast<SwTextFrame*>(pFrame)->IsEmpty()
2060  )
2061  )
2062  )
2063  {
2064  bTstMove = true;
2065  bRet = static_cast<SwTextFrame*>(pFrame)->TestFormat( pTmpPrev, nSpace, bSplit );
2066  }
2067  else
2068  bRet = pFrame->WouldFit( nSpace, bSplit, false );
2069 
2070  pTmpFrame->RemoveFromLayout();
2071  pTmpFrame->InsertBefore( pUp, pOldNext );
2072  pTmpFrame->InvalidateInfFlags(); // restore flags
2073  }
2074  else
2075  {
2076  bRet = pFrame->WouldFit( nSpace, bSplit, false );
2077  nSecondCheck = !bSplit ? 1 : 0;
2078  }
2079 
2080  SwBorderAttrAccess aAccess( SwFrame::GetCache(), pFrame );
2081  const SwBorderAttrs &rAttrs = *aAccess.Get();
2082 
2083  // Sad but true: We need to consider the spacing in our calculation.
2084  // This already happened in TestFormat.
2085  if ( bRet && !bTstMove )
2086  {
2087  SwTwips nUpper;
2088 
2089  if ( pTmpPrev )
2090  {
2091  nUpper = CalcUpperSpace( nullptr, pTmpPrev );
2092 
2093  // in balanced columned section frames we do not want the
2094  // common border
2095  bool bCommonBorder = true;
2096  if ( pFrame->IsInSct() && pFrame->GetUpper()->IsColBodyFrame() )
2097  {
2098  const SwSectionFrame* pSct = pFrame->FindSctFrame();
2099  bCommonBorder = pSct->GetFormat()->GetBalancedColumns().GetValue();
2100  }
2101 
2102  // #i46181#
2103  nSecondCheck = ( 1 == nSecondCheck &&
2104  pFrame == this &&
2105  IsTextFrame() &&
2106  bCommonBorder &&
2107  !static_cast<const SwTextFrame*>(this)->IsEmpty() ) ?
2108  nUpper :
2109  0;
2110 
2111  nUpper += bCommonBorder ?
2112  rAttrs.GetBottomLine( *pFrame ) :
2113  rAttrs.CalcBottomLine();
2114 
2115  }
2116  else
2117  {
2118  // #i46181#
2119  nSecondCheck = 0;
2120 
2121  if( pFrame->IsVertical() )
2122  nUpper = pFrame->getFrameArea().Width() - pFrame->getFramePrintArea().Width();
2123  else
2124  nUpper = pFrame->getFrameArea().Height() - pFrame->getFramePrintArea().Height();
2125  }
2126 
2127  nSpace -= nUpper;
2128 
2129  if ( nSpace < 0 )
2130  {
2131  bRet = false;
2132 
2133  // #i46181#
2134  if ( nSecondCheck > 0 )
2135  {
2136  // The following code is intended to solve a (rare) problem
2137  // causing some frames not to move backward:
2138  // SwTextFrame::WouldFit() claims that the whole paragraph
2139  // fits into the given space and subtracts the height of
2140  // all lines from nSpace. nSpace - nUpper is not a valid
2141  // indicator if the frame should be allowed to move backward.
2142  // We do a second check with the original remaining space
2143  // reduced by the required upper space:
2144  nOldSpace -= nSecondCheck;
2145  const bool bSecondRet = nOldSpace >= 0 && pFrame->WouldFit( nOldSpace, bOldSplit, false );
2146  if ( bSecondRet && bOldSplit && nOldSpace >= 0 )
2147  {
2148  bRet = true;
2149  bSplit = true;
2150  }
2151  }
2152  }
2153  }
2154 
2155  // Also consider lower spacing in table cells
2156  IDocumentSettingAccess const& rIDSA(pNewUpper->GetFormat()->getIDocumentSettingAccess());
2157  if ( bRet && IsInTab() &&
2159  {
2160  nSpace -= rAttrs.GetULSpace().GetLower();
2161 
2163  {
2164  nSpace -= rAttrs.CalcLineSpacing();
2165  }
2166  if ( nSpace < 0 )
2167  {
2168  bRet = false;
2169  }
2170  }
2171 
2172  if (bRet && !bSplit && pFrame->IsKeep(rAttrs.GetAttrSet().GetKeep(), GetBreakItem()))
2173  {
2174  if( bTstMove )
2175  {
2176  while( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->HasFollow() )
2177  {
2178  pFrame = static_cast<SwTextFrame*>(pFrame)->GetFollow();
2179  }
2180  // If last follow frame of <this> text frame isn't valid,
2181  // a formatting of the next content frame doesn't makes sense.
2182  // Thus, return true.
2183  if ( IsAnFollow( pFrame ) && !pFrame->isFrameAreaDefinitionValid() )
2184  {
2185  OSL_FAIL( "Only a warning for task 108824:/n<SwContentFrame::WouldFit_(..) - follow not valid!" );
2186  return true;
2187  }
2188  }
2189  SwFrame *pNxt;
2190  if( nullptr != (pNxt = pFrame->FindNext()) && pNxt->IsContentFrame() &&
2191  ( !pFootnoteFrame || ( pNxt->IsInFootnote() &&
2192  pNxt->FindFootnoteFrame()->GetAttr() == pFootnoteFrame->GetAttr() ) ) )
2193  {
2194  // TestFormat(?) does not like paragraph- or character anchored objects.
2195 
2196  // current solution for the test formatting doesn't work, if
2197  // objects are present in the remaining area of the new upper
2198  if ( bTstMove &&
2199  ( pNxt->GetDrawObjs() || bObjsInNewUpper ) )
2200  {
2201  return true;
2202  }
2203 
2204  if ( !pNxt->isFrameAreaDefinitionValid() )
2205  {
2206  MakeNxt( pFrame, pNxt );
2207  }
2208 
2209  // Little trick: if the next has a predecessor, then the paragraph
2210  // spacing has been calculated already, and we don't need to re-calculate
2211  // it in an expensive way.
2212  if( lcl_NotHiddenPrev( pNxt ) )
2213  pTmpPrev = nullptr;
2214  else
2215  {
2216  if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsHiddenNow() )
2217  pTmpPrev = lcl_NotHiddenPrev( pFrame );
2218  else
2219  pTmpPrev = pFrame;
2220  }
2221  pFrame = static_cast<SwContentFrame*>(pNxt);
2222  }
2223  else
2224  pFrame = nullptr;
2225  }
2226  else
2227  pFrame = nullptr;
2228 
2229  } while ( bRet && pFrame );
2230 
2231  return bRet;
2232 }
2233 
2234 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void InsertBefore(SwLayoutFrame *pParent, SwFrame *pBehind)
Insert SwFrame into existing structure.
Definition: wsfrm.cxx:830
bool IsAnLower(const SwFrame *) const
Definition: findfrm.cxx:207
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:339
bool GetValue() const
#define FRM_NEIGHBOUR
Definition: frame.hxx:107
void SetTop(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1387
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:33
sal_uInt16 CalcBottomLine() const
Definition: frmtool.hxx:509
Base class of the Writer layout elements.
Definition: frame.hxx:315
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:159
tools::Long GetWidth() const
void PrepareLock(SwFlowFrame *pTab)
Definition: calcmove.cxx:208
virtual SwRect GetObjRect() const =0
void InvalidateInfFlags()
Definition: frame.hxx:609
SwFrameGet fnGetPrtBottom
Definition: frame.hxx:1325
SDRTEXTVERTADJUST_TOP
bool IsFollow() const
Definition: flowfrm.hxx:166
Point GetPos(const SwRect &rRect) const
Definition: frame.hxx:1384
const SwSortedObjs * GetDrawObjs() const
Definition: frame.hxx:565
SwRectMax fnOverStep
Definition: frame.hxx:1333
void MakePrtArea(const SwBorderAttrs &)
Definition: calcmove.cxx:1075
virtual void MakeAll(vcl::RenderContext *pRenderContext) override
Definition: calcmove.cxx:1222
virtual void MakeAll(vcl::RenderContext *pRenderContext)=0
bool IsInFly() const
Definition: frame.hxx:962
bool IsRootFrame() const
Definition: frame.hxx:1175
SwTwips Grow(SwTwips, bool bTst=false, bool bInfo=false)
Definition: wsfrm.cxx:1503
void SetPosY(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1402
sal_uInt16 GetLower() const
bool IsInSct() const
Definition: frame.hxx:968
virtual void Format(vcl::RenderContext *pRenderContext, const SwBorderAttrs *pAttrs=nullptr) override
"Formats" the Frame; Frame and PrtArea.
Definition: wsfrm.cxx:3411
constexpr auto toTwips(N number, Length from)
bool MoveFwd(bool bMakePage, bool bPageBreak, bool bMoveAlways=false)
Return value guarantees that a new page was not created, although false does not NECESSARILY indicate...
Definition: flowfrm.cxx:1927
tools::Long BottomDist(const SwRect &rRect, tools::Long nPos) const
Definition: frame.hxx:1415
const OUString & GetText() const
Definition: ndtxt.hxx:218
void LOOPING_LOUIE_LIGHT(bool bCondition, const SwTextFrame &rTextFrame)
Definition: layouter.cxx:424
std::string GetValue
bool IsColLocked() const
Definition: frame.hxx:887
bool IsBefore(const SwLayoutFrame *_pCheckRefLayFrame) const
method to check relative position of layout frame to a given layout frame.
Definition: findfrm.cxx:234
friend void ValidateSz(SwFrame *pFrame)
Definition: calcmove.cxx:1213
bool IsKeep(SvxFormatKeepItem const &rKeep, SvxFormatBreakItem const &rBreak, bool bBreakCheck=false) const
method to determine if a Keep needs to be considered (Breaks!)
Definition: flowfrm.cxx:235
void Left(const tools::Long nLeft)
Definition: swrect.hxx:197
void Refresh(const SwFrame *pFrame)
Definition: frame.hxx:1360
void SetCompletePaint() const
Definition: frame.hxx:995
bool IsInFootnote() const
Definition: frame.hxx:950
virtual bool Prepare(const PrepareHint ePrep=PrepareHint::Clear, const void *pVoid=nullptr, bool bNotify=true)
Definition: wsfrm.cxx:597
SwFrameType GetType() const
Definition: frame.hxx:520
bool IsPrevObjMove() const
Definition: flowfrm.cxx:1125
void SetFlyLock(bool bNew)
Definition: flowfrm.hxx:229
static SwFrame * lcl_Prev(SwFrame *pFrame, bool bSectPrv=true)
Definition: calcmove.cxx:517
long Long
const SwRect & getFramePrintArea() const
Definition: frame.hxx:181
#define MINLAY
Definition: swtypes.hxx:63
static SwCache & GetCache()
Definition: frame.hxx:522
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:46
tools::Long CalcRight(const SwFrame *pCaller) const
Definition: frmtool.cxx:2277
bool JoinedWithPrev(const SwFrame &_rFrame, const SwFrame *_pPrevFrame=nullptr) const
Definition: frmtool.cxx:2557
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1213
bool HasFollow() const
Definition: flowfrm.hxx:165
SwTwips CalcLowerSpace(const SwBorderAttrs *_pAttrs=nullptr) const
calculation of lower space
Definition: flowfrm.cxx:1743
bool MoveBwd(bool &rbReformat)
Return value tells whether any changes have been made.
Definition: flowfrm.cxx:2132
sal_uInt16 CalcTopLine() const
Definition: frmtool.hxx:503
bool IsVert() const
Definition: frame.hxx:1368
SwRectGet fnGetWidth
Definition: frame.hxx:1296
void Pos(const Point &rNew)
Definition: swrect.hxx:171
bool IsEndNote() const
Definition: fmtftn.hxx:71
SwFrame * FindNext()
Definition: frame.hxx:1142
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1788
bool IsCellFrame() const
Definition: frame.hxx:1227
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
virtual const SvxFormatBreakItem & GetBreakItem() const
Definition: findfrm.cxx:657
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1294
tools::Long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1382
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:32
bool WouldFit_(SwTwips nSpace, SwLayoutFrame *pNewUpper, bool bTstMove, const bool bObjsInNewUpper)
Definition: calcmove.cxx:1999
static SwFlowFrame * CastFlowFrame(SwFrame *pFrame)
Definition: flowfrm.cxx:2705
SwRectSet fnSubLeft
Definition: frame.hxx:1310
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
void PrepareUnlock(SwFlowFrame *pTab)
Definition: calcmove.cxx:212
bool IsFootnoteFrame() const
Definition: frame.hxx:1203
void SetXMargins(SwFrame &rFrame, tools::Long nLeft, tools::Long nRight) const
Definition: frame.hxx:1408
sal_Int32 GetBrowseWidth() const
Definition: viewsh.cxx:2051
virtual void MakeAll(vcl::RenderContext *pRenderContext) override
Definition: calcmove.cxx:807
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:172
static bool bFootnote
Definition: insfnote.cxx:33
void ValidateSz(SwFrame *pFrame)
Definition: calcmove.cxx:1213
SwRectSet fnAddRight
Definition: frame.hxx:1311
bool IsVertLRBT() const
Definition: frame.hxx:984
void PrepareMake(vcl::RenderContext *pRenderContext)
Prepares the Frame for "formatting" (MakeAll()).
Definition: calcmove.cxx:246
tools::Long GetTop(const SwRect &rRect) const
Definition: frame.hxx:1378
constexpr tools::Long Width() const
SwTwips CalcUpperSpace(const SwBorderAttrs *pAttrs=nullptr, const SwFrame *pPr=nullptr, const bool _bConsiderGrid=true) const
method to determine the upper space hold by the frame
Definition: flowfrm.cxx:1446
void PrepareCursor()
Definition: calcmove.cxx:403
bool IsFlyFrame() const
Definition: frame.hxx:1211
sal_uInt16 CalcLeftLine() const
Definition: frmtool.hxx:515
wrapper class for the positioning of Writer fly frames and drawing objects
bool IsMoveable(const SwLayoutFrame *_pLayoutFrame=nullptr) const
determine, if frame is moveable in given environment
Definition: findfrm.cxx:1362
const SwFormatNoBalancedColumns & GetBalancedColumns(bool=true) const
Definition: fmtclbl.hxx:42
virtual bool IsLeaveUpperAllowed() const
Definition: tabfrm.cxx:6072
const SwRect & getFrameArea() const
Definition: frame.hxx:180
bool getBrowseMode() const
Definition: viewopt.hxx:472
virtual Size ChgSize(const Size &aNewSize)
Definition: wsfrm.cxx:731
bool IsEmptyPage() const
Definition: pagefrm.hxx:157
bool IsInTab() const
Definition: frame.hxx:956
const SwPageFrame * GetLastPage() const
Definition: rootfrm.hxx:363
bool IsTextFrame() const
Definition: frame.hxx:1235
SwRectFn fnRectVertL2R
Definition: newfrm.cxx:288
void Width(tools::Long nNew)
Definition: swrect.hxx:189
void setFramePrintAreaValid(bool bNew)
Definition: wsfrm.cxx:99
bool IsPageBodyFrame() const
Definition: layfrm.hxx:214
bool IsSctFrame() const
Definition: frame.hxx:1215
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1112
tools::Long GetLeft(const SwRect &rRect) const
Definition: frame.hxx:1380
bool IsFlowFrame() const
Definition: frame.hxx:1243
SwRectFn fnRectHori
Definition: newfrm.cxx:286
const SvxFormatKeepItem & GetKeep(bool=true) const
Definition: frmatr.hxx:56
SwLayoutFrame * GetNextCellLeaf()
Definition: findfrm.cxx:1525
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame, use GetBreakItem()/GetPageDescItem() instead.
Definition: findfrm.cxx:677
const SwFrame & GetFrame() const
Definition: flowfrm.hxx:151
bool IsFootnoteLock() const
Definition: sectfrm.hxx:166
virtual SwTwips GrowFrame(SwTwips, bool bTst=false, bool bInfo=false) override
Definition: wsfrm.cxx:2098
bool IsColumnFrame() const
Definition: frame.hxx:1183
SwRectFn fnRectVertL2RB2T
Definition: newfrm.cxx:289
SwFootnoteFrame * FindFootnoteFrame()
Definition: frame.hxx:1108
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1304
friend void MakeNxt(SwFrame *pFrame, SwFrame *pNxt)
Definition: calcmove.cxx:1921
Style of a layout element.
Definition: frmfmt.hxx:59
bool IsContentFrame() const
Definition: frame.hxx:1231
bool CheckPageHeightValidForHideWhitespace(SwTwips nDiff)
Is bottom-of-page-frame - bottom-of-text-frame difference valid in case whitespace is hidden...
Definition: pagechg.cxx:2520
SwFrame * GetIndPrev() const
Definition: frame.hxx:725
const SwContentFrame * GetFollow() const
Definition: cntfrm.hxx:131
void InvalidatePrt()
Definition: frame.hxx:1037
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
int i
tools::Long GetPrtBottom(const SwFrame &rFrame) const
Definition: frame.hxx:1411
bool IsFwdMoveAllowed() const
Definition: flowfrm.hxx:240
const SwRect & VisArea() const
Definition: viewsh.cxx:623
size_t GetContentHeight(const tools::Long nTop, const tools::Long nBottom) const
Calculate the content height of a page (without columns).
Definition: calcmove.cxx:739
SwTwips CalcAddLowerSpaceAsLastInTableCell(const SwBorderAttrs *_pAttrs=nullptr) const
calculation of the additional space to be considered, if flow frame is the last inside a table cell ...
Definition: flowfrm.cxx:1790
SwDoc & GetDoc()
Definition: node.hxx:213
sal_uInt16 GetBottomLine(const SwFrame &_rFrame) const
Definition: frmtool.hxx:487
SwFrameType
Definition: frame.hxx:75
SwFrame * GetIndNext()
Definition: frame.hxx:728
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
bool IsCollapse() const
Definition: calcmove.cxx:1064
size_t size() const
Definition: sortedobjs.cxx:43
const int cnStopFormat
Definition: calcmove.cxx:1211
tools::Long CalcLeft(const SwFrame *pCaller) const
Definition: frmtool.cxx:2339
static bool lcl_IsCalcUpperAllowed(const SwFrame &rFrame)
Definition: calcmove.cxx:219
SwPageFrame * FindPageFrame()
Definition: frame.hxx:681
virtual bool IsDeleteForbidden() const
Definition: frame.hxx:888
const SwFrame * Lower() const
Definition: layfrm.hxx:101
SwNodeOffset GetIndex() const
Definition: node.hxx:292
bool IsInBalancedSection() const
Definition: findfrm.cxx:1818
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1383
bool IsJoinLocked() const
Definition: flowfrm.hxx:175
virtual const SwFlyFrame * DynCastFlyFrame() const
SwLayoutFrame * GetUpper()
Definition: frame.hxx:679
bool isFramePrintAreaValid() const
Definition: frame.hxx:169
unsigned char sal_Bool
bool IsUndersized() const
Definition: flowfrm.hxx:158
void LockJoin()
Definition: flowfrm.hxx:139
bool IsRowFrame() const
Definition: frame.hxx:1223
SwFootnoteBossFrame * FindFootnoteBossFrame(bool bFootnotes=false)
Definition: findfrm.cxx:436
constexpr tools::Long BROWSE_HEIGHT
Definition: frmtool.hxx:54
Provides access to settings of a document.
SwFrame * GetPrev()
Definition: frame.hxx:678
const SwAttrSet & GetAttrSet() const
Definition: frmtool.hxx:388
virtual void Format(vcl::RenderContext *pRenderContext, const SwBorderAttrs *pAttrs=nullptr)
Definition: unusedf.cxx:25
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:695
bool isFrameAreaPositionValid() const
Definition: frame.hxx:167
sal_uInt8 GetWidthPercent() const
Definition: fmtfsize.hxx:91
const IDocumentSettingAccess & getIDocumentSettingAccess() const
Provides access to the document settings interface.
Definition: format.cxx:717
void SSize(const Size &rNew)
Definition: swrect.hxx:180
bool IsLocked() const
Definition: txtfrm.hxx:518
bool isFrameAreaSizeValid() const
Definition: frame.hxx:168
A page of the document layout.
Definition: pagefrm.hxx:57
const SwFormatFootnote & GetFootnote() const
Definition: txatbase.hxx:204
sal_uInt8 BwdMoveNecessary(const SwPageFrame *pPage, const SwRect &rRect)
method to determine overlapping of an object that requests floating
Definition: flowfrm.cxx:330
tools::Long SwTwips
Definition: swtypes.hxx:52
const long LONG_MAX
SwBorderAttrs * Get()
Definition: frmtool.cxx:2649
void InvalidateSize()
Definition: frame.hxx:1030
void ResetCompletePaint() const
Definition: frame.hxx:999
bool CheckMoveFwd(bool &rbMakePage, bool bKeep, bool bIgnoreMyOwnKeepValue)
Moves the Frame forward if it seems necessary regarding the current conditions and attributes...
Definition: flowfrm.cxx:1835
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1116
SwLayoutFrame * FindBodyCont()
Searches the first ContentFrame in BodyText below the page.
Definition: findfrm.cxx:43
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
const IDocumentLayoutAccess & getIDocumentLayoutAccess() const
Provides access to the document layout interface.
Definition: node.cxx:2098
void setFrameAreaPositionValid(bool bNew)
Definition: wsfrm.cxx:83
static SwFrame * lcl_NotHiddenPrev(SwFrame *pFrame)
Definition: calcmove.cxx:529
void SetPosX(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1401
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
bool OverStep(const SwRect &rRect, tools::Long nPos) const
Definition: frame.hxx:1419
bool Growable() const
checks whether the SectionFrame is still able to grow, as case may be the environment has to be asked...
Definition: sectfrm.cxx:2144
void MakeNxt(SwFrame *pFrame, SwFrame *pNxt)
Definition: calcmove.cxx:1921
void SetWidth(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1391
bool IsVertLR() const
Definition: frame.hxx:980
bool IsTabFrame() const
Definition: frame.hxx:1219
static void lcl_CheckObjects(SwSortedObjs &rSortedObjs, const SwFrame *pFrame, tools::Long &rBot)
Definition: calcmove.cxx:711
general base class for all free-flowing frames
Definition: flyfrm.hxx:78
virtual bool ShouldBwdMoved(SwLayoutFrame *pNewUpper, bool &) override
Return value tells whether the Frame should be moved.
Definition: calcmove.cxx:54
void UnlockJoin()
Definition: flowfrm.hxx:140
sal_uInt16 CalcLineSpacing() const
Definition: frmtool.hxx:539
void OptPrepareMake()
Definition: calcmove.cxx:378
virtual SwFrameFormat & GetFrameFormat()=0
constexpr tools::Long Height() const
unsigned char sal_uInt8
sal_uInt16 GetPhyPageNum() const
Definition: trvlfrm.cxx:1695
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:424
const SwFrame * ContainsAny(const bool _bInvestigateFootnoteForSections=false) const
Method doesn't investigate content of footnotes by default.
Definition: findfrm.cxx:126
void SetHeight(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1392
void RemoveFromLayout()
Definition: wsfrm.cxx:1007
bool IsRightToLeft() const
Definition: frame.hxx:988
void Top(const tools::Long nTop)
Definition: swrect.hxx:206
bool IsColBodyFrame() const
These SwFrame inlines are here, so that frame.hxx does not need to include layfrm.hxx.
Definition: layfrm.hxx:209
virtual bool WouldFit(SwTwips &nMaxHeight, bool &bSplit, bool bTst)
Definition: unusedf.cxx:35
void setFrameAreaSizeValid(bool bNew)
Definition: wsfrm.cxx:91
bool IsVertL2R() const
Definition: frame.hxx:1369
const SwContentFrame * GetRef() const
Definition: ftnfrm.cxx:2891
bool IsPageFrame() const
Definition: frame.hxx:1179
void * p
const SwTextFootnote * GetAttr() const
Definition: ftnfrm.hxx:122
const Size & GetBrowseBorder() const
Definition: viewsh.cxx:2046
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
static bool lcl_IsNextFootnoteBoss(const SwFrame *pFrame, const SwFrame *pNxt)
This routine checks whether there are no other FootnoteBosses between the pFrame's FootnoteBoss and t...
Definition: calcmove.cxx:1984
bool IsAnFollow(const SwFlowFrame *pFlow) const
Definition: flowfrm.cxx:727
virtual SwTwips ShrinkFrame(SwTwips, bool bTst=false, bool bInfo=false) override
Definition: wsfrm.cxx:2219
#define FAR_AWAY
Definition: frmtool.hxx:53
static bool IsLocked()
Definition: frmtool.hxx:471
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
const Size & GetSize() const
Definition: frmtool.hxx:405
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:357
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:58
#define FRM_NOTE_VERT
Definition: frame.hxx:108
bool IsVertical() const
Definition: frame.hxx:974
tools::Long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1379
void SetLeft(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1389
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame...
Definition: layfrm.hxx:35
Ends a section of nodes in the document model.
Definition: node.hxx:343
SwRectFn fnRectVert
Definition: newfrm.cxx:287
#define STOP_FLY_FORMAT
Definition: calcmove.cxx:1209
virtual void MakePos()
Definition: calcmove.cxx:539
static bool FrameMovedFwdByObjPos(const SwDoc &_rDoc, const SwTextFrame &_rTextFrame, sal_uInt32 &_ornToPageNum)
Definition: layouter.cxx:342
bool IsFootnoteContFrame() const
Definition: frame.hxx:1199
bool IsWhitespaceHidden() const
Definition: viewopt.hxx:488
bool IsNeighbourFrame() const
Definition: frame.hxx:913
bool IsBodyFrame() const
Definition: frame.hxx:1207
virtual void MakeAll(vcl::RenderContext *pRenderContext) override
Definition: calcmove.cxx:957
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:207
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
class for collecting anchored objects
Definition: sortedobjs.hxx:48
void Height(tools::Long nNew)
Definition: swrect.hxx:193
SwContentFrame * JoinFrame()
Definition: frmform.cxx:613
bool IsFooterFrame() const
Definition: frame.hxx:1195
SwRootFrame * getRootFrame()
Definition: frame.hxx:680
std::unique_ptr< SwSortedObjs > m_pSortedObjs
Definition: pagefrm.hxx:61
bool IsCollapse() const
Definition: calcmove.cxx:1043
bool IsHeaderFrame() const
Definition: frame.hxx:1191
virtual const SwFrameFormat * GetFormat() const
Definition: ssfrm.cxx:395
#define PROTOCOL_ENTER(pFrame, nFunc, nAct, pPar)
Definition: dbg_lay.hxx:92
const SvxULSpaceItem & GetULSpace() const
Definition: frmtool.hxx:389
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1100
sal_uInt16 CalcRightLine() const
Definition: frmtool.hxx:521
static bool IsMoveBwdJump()
Definition: flowfrm.hxx:154
SwFrame * GetNext()
Definition: frame.hxx:677