diff options
author | Michael Stahl <Michael.Stahl@cib.de> | 2019-05-22 17:03:09 +0200 |
---|---|---|
committer | Michael Stahl <Michael.Stahl@cib.de> | 2019-05-23 10:38:30 +0200 |
commit | e14056e6e88d9b8d988b7b88b2776a8fc952031b (patch) | |
tree | f5ce2b6fe8e278600f360f26b4820be1a77d2c8d | |
parent | e3015d7021e689c71c2ed8e5dd01a74d832c84f0 (diff) |
tdf#119109 sw: fix iteration in SwFrame::PrepareMake()
The problem is that with the change in SwFlowFrame::MoveBwd(), a
SwTextFrame in a table may move backwards during MakeAll(); if the next
frame of the moved frame, and the "this" frame in PrepareMake(), is a
SwTabFrame, then the pFrame->FindNext() will return not this SwTabFrame,
but the first SwTextFrame *inside* the SwTabFrame - hence the iteration
will never meet the "pFrame == this" termination condition and the
SwTabFrame remains unformatted; this warning is printed:
warn:legacy.osl:6874:6874:sw/source/core/layout/calcmove.cxx:296: :-( Layout unstable (this not found).
(regression from 18765b9fa739337d2d891513f6e2fb7c3ce23b50)
Change-Id: I68207ba9cf68cd5abe51d647cb757176261eda40
Reviewed-on: https://gerrit.libreoffice.org/72797
Tested-by: Jenkins
Reviewed-by: Michael Stahl <Michael.Stahl@cib.de>
-rw-r--r-- | sw/source/core/layout/calcmove.cxx | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx index 6e64c2903da6..f4817f2d8cd5 100644 --- a/sw/source/core/layout/calcmove.cxx +++ b/sw/source/core/layout/calcmove.cxx @@ -308,12 +308,29 @@ void SwFrame::PrepareMake(vcl::RenderContext* pRenderContext) SwFlowFrame::CastFlowFrame(pFrame)->IsAnFollow( pThis ) ) break; + bool const isLast(pFrame->GetNext() == this); + // note: this seems obvious but does *not* hold, a MakeAll() + // could move more than 1 frame backwards! + // that's why FindNext() is used below + // assert(pFrame->GetUpper() == GetUpper()); pFrame->MakeAll(pRenderContext); if( IsSctFrame() && !static_cast<SwSectionFrame*>(this)->GetSection() ) break; + if (isLast && pFrame->GetUpper() != GetUpper()) + { + assert(GetUpper()->Lower() == this + // tab frame/section frame may split multiple times + || ( SwFlowFrame::CastFlowFrame(pFrame) + && SwFlowFrame::CastFlowFrame(GetUpper()->Lower()) + && SwFlowFrame::CastFlowFrame(pFrame)->IsAnFollow( + SwFlowFrame::CastFlowFrame(GetUpper()->Lower())) + && GetUpper()->Lower()->GetNext() == this)); + break; // tdf#119109 frame was moved backward, prevent + // FindNext() returning a frame inside this if + } // this is a table! } // With ContentFrames, the chain may be broken while walking through - // it. Therefore we have to figure out the follower in a bit more + // it. Therefore we have to figure out the next frame in a bit more // complicated way. However, I'll HAVE to get back to myself // sometime again. pFrame = pFrame->FindNext(); @@ -422,7 +439,7 @@ void SwFrame::PrepareCursor() pFrame->MakeAll(getRootFrame()->GetCurrShell()->GetOut()); } // With ContentFrames, the chain may be broken while walking through - // it. Therefore we have to figure out the follower in a bit more + // it. Therefore we have to figure out the next frame in a bit more // complicated way. However, I'll HAVE to get back to myself // sometime again. pFrame = pFrame->FindNext(); |