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