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