[Libreoffice-commits] core.git: Branch 'private/swe/libreoffice-5-2+backports' - sw/source

Armin Le Grand Armin.Le.Grand at cib.de
Thu Dec 21 15:02:21 UTC 2017


 sw/source/core/layout/pagechg.cxx |  113 ++++++++++++++++++++++++++++++++++----
 1 file changed, 104 insertions(+), 9 deletions(-)

New commits:
commit d0f51d571c2e24c647eea7f68085531d251ce812
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Dec 20 09:51:52 2017 +0100

    Make used Pages alive in AssertFlyPages
    
    There is a case where docs are created/exist that have an empty
    2nd page with a single, page-anchored Frame (e.g. graphic), not
    using a PageBreak. Persistence works in this case due to method
    AssertFlyPages adding the missing page at end, but when multiple of
    these docs get serialized (e.g. MailMerge) the problem exists for
    in-between pages, too, and needs to be corrected. Also need to
    correct the Pages for the Frames when Pages in that situation were
    corrected.
    
    Change-Id: I7c8bbbf0668438af98bc615e5b7c472ea6eee906
    Reviewed-on: https://gerrit.libreoffice.org/46855
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>
    Reviewed-on: https://gerrit.libreoffice.org/46891
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx
index f081ad6c6f3a..aac2ab98461d 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -191,10 +191,11 @@ SwPageFrame::SwPageFrame( SwFrameFormat *pFormat, SwFrame* pSib, SwPageDesc *pPg
         Frame().SSize( pFormat->GetFrameSize().GetSize() );
 
     // create and insert body area if it is not a blank page
-    SwDoc *pDoc = pFormat->GetDoc();
-    if ( !(m_bEmptyPage = (pFormat == pDoc->GetEmptyPageFormat())) )
+    SwDoc* pDoc(pFormat->GetDoc());
+    m_bEmptyPage = (pFormat == pDoc->GetEmptyPageFormat());
+
+    if(!m_bEmptyPage)
     {
-        m_bEmptyPage = false;
         Calc(pRenderContext); // so that the PrtArea is correct
         SwBodyFrame *pBodyFrame = new SwBodyFrame( pDoc->GetDfltFrameFormat(), this );
         pBodyFrame->ChgSize( Prt().SSize() );
@@ -544,6 +545,28 @@ void SwPageFrame::UpdateAttr_( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
     {
         case RES_FMT_CHG:
         {
+            // state of m_bEmptyPage needs to be determined newly
+            const bool bNewState(GetFormat() == GetFormat()->GetDoc()->GetEmptyPageFormat());
+
+            if(m_bEmptyPage != bNewState)
+            {
+                // copy new state
+                m_bEmptyPage = bNewState;
+
+                if(nullptr == GetLower())
+                {
+                    // if we were an empty page before there is not yet a BodyArea in the
+                    // form of a SwBodyFrame, see constructor
+                    SwViewShell* pSh(getRootFrame()->GetCurrShell());
+                    vcl::RenderContext* pRenderContext(pSh ? pSh->GetOut() : nullptr);
+                    Calc(pRenderContext); // so that the PrtArea is correct
+                    SwBodyFrame* pBodyFrame = new SwBodyFrame(GetFormat(), this);
+                    pBodyFrame->ChgSize( Prt().SSize() );
+                    pBodyFrame->Paste(this);
+                    pBodyFrame->InvalidatePos();
+                }
+            }
+
             // If the frame format is changed, several things might also change:
             // 1. columns:
             assert(pOld && pNew); //FMT_CHG Missing Format
@@ -1389,19 +1412,81 @@ void SwRootFrame::AssertFlyPages()
     const SwFrameFormats *pTable = pDoc->GetSpzFrameFormats();
 
     // what page targets the "last" Fly?
-    sal_uInt16 nMaxPg = 0;
+    // note the needed pages in a set
+    sal_uInt16 nMaxPg(0);
+    std::set< sal_uInt16 > neededPages;
 
     for ( size_t i = 0; i < pTable->size(); ++i )
     {
         const SwFormatAnchor &rAnch = (*pTable)[i]->GetAnchor();
-        if ( !rAnch.GetContentAnchor() && nMaxPg < rAnch.GetPageNum() )
-            nMaxPg = rAnch.GetPageNum();
+        if(!rAnch.GetContentAnchor())
+        {
+            const sal_uInt16 nPageNum(rAnch.GetPageNum());
+
+            // calc MaxPage (as before)
+            nMaxPg = std::max(nMaxPg, nPageNum);
+
+            // note as needed page
+            neededPages.insert(nPageNum);
+        }
     }
+
     // How many pages exist at the moment?
-    SwPageFrame *pPage = static_cast<SwPageFrame*>(Lower());
-    while ( pPage && pPage->GetNext() &&
-            !static_cast<SwPageFrame*>(pPage->GetNext())->IsFootnotePage() )
+    // And are there EmptyPages that are needed?
+    SwPageFrame* pPage(static_cast<SwPageFrame*>(Lower()));
+    SwPageFrame* pPrevPage(nullptr);
+    SwPageFrame* pFirstRevivedEmptyPage(nullptr);
+
+    while(pPage) // moved two while-conditions to break-statements (see below)
     {
+        const sal_uInt16 nPageNum(pPage->GetPhyPageNum());
+
+        if(pPage->IsEmptyPage() &&
+            nullptr != pPrevPage &&
+            neededPages.find(nPageNum) != neededPages.end())
+        {
+            // This is an empty page, but it *is* needed since a SwFrame
+            // is anchored at it directly. Initially these SwFrames are
+            // not fully initialized. Need to change the format of this SwFrame
+            // and let the ::Notify mechanism newly evaluate
+            // m_bEmptyPage (see SwPageFrame::UpdateAttr_). Code is taken and
+            // adapted from ::InsertPage (used below), this needs previous page
+            bool bWishedOdd(!pPrevPage->OnRightPage());
+            SwPageDesc* pDesc(pPrevPage->GetPageDesc()->GetFollow());
+            assert(pDesc && "Missing PageDesc");
+
+            if(!(bWishedOdd ? pDesc->GetRightFormat() : pDesc->GetLeftFormat()))
+            {
+                bWishedOdd = !bWishedOdd;
+            }
+
+            bool const bWishedFirst(pDesc != pPrevPage->GetPageDesc());
+            SwFrameFormat* pFormat(bWishedOdd ? pDesc->GetRightFormat(bWishedFirst) : pDesc->GetLeftFormat(bWishedFirst));
+
+            // set SwFrameFormat, this will trigger SwPageFrame::UpdateAttr_ and re-evaluate
+            // m_bEmptyPage, too
+            pPage->SetFrameFormat(pFormat);
+
+            if(nullptr == pFirstRevivedEmptyPage)
+            {
+                // remember first (lowest) SwPageFrame which needed correction
+                pFirstRevivedEmptyPage = pPage;
+            }
+        }
+
+        // original while-condition II
+        if(nullptr == pPage->GetNext())
+        {
+            break;
+        }
+
+        // original while-condition III
+        if(static_cast< SwPageFrame* >(pPage->GetNext())->IsFootnotePage())
+        {
+            break;
+        }
+
+        pPrevPage = pPage;
         pPage = static_cast<SwPageFrame*>(pPage->GetNext());
     }
 
@@ -1447,6 +1532,16 @@ void SwRootFrame::AssertFlyPages()
             }
         }
     }
+
+    // if we corrected SwFrameFormat and changed one (or more) m_bEmptyPage
+    // flags, we need to correct evtl. currently wrong positioned SwFrame(s)
+    // which did think until now that these Page(s) are empty.
+    // After trying to correct myself I found SwRootFrame::AssertPageFlys
+    // directly below that already does that, so use it.
+    if(nullptr != pFirstRevivedEmptyPage)
+    {
+        AssertPageFlys(pFirstRevivedEmptyPage);
+    }
 }
 
 /// Ensure that after the given page all page-bound objects are located on the correct page


More information about the Libreoffice-commits mailing list