sw/source/core/layout/pagechg.cxx | 116 ++++++++++++++++++++++++++++++++++---- 1 file changed, 106 insertions(+), 10 deletions(-)
New commits: commit 0b53f794ffb2550288610b9488f11fd21ab85aae Author: Armin Le Grand <armin.le.gr...@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 <c...@libreoffice.org> Reviewed-by: Armin Le Grand <armin.le.gr...@cib.de> diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx index 68dfd632b5ec..79abcfdf6f56 100644 --- a/sw/source/core/layout/pagechg.cxx +++ b/sw/source/core/layout/pagechg.cxx @@ -216,12 +216,14 @@ SwPageFrame::SwPageFrame( SwFrameFormat *pFormat, SwFrame* pSib, SwPageDesc *pPg } // create and insert body area if it is not a blank page - SwDoc *pDoc = pFormat->GetDoc(); - m_bEmptyPage = pFormat == pDoc->GetEmptyPageFormat(); - if ( m_bEmptyPage ) + SwDoc* pDoc(pFormat->GetDoc()); + m_bEmptyPage = (pFormat == pDoc->GetEmptyPageFormat()); + + if(m_bEmptyPage) + { return; + } - m_bEmptyPage = false; Calc(pRenderContext); // so that the PrtArea is correct SwBodyFrame *pBodyFrame = new SwBodyFrame( pDoc->GetDfltFrameFormat(), this ); pBodyFrame->ChgSize( getFramePrintArea().SSize() ); @@ -571,6 +573,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(getFramePrintArea().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 @@ -1486,19 +1510,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()); } @@ -1525,6 +1611,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); + } + #if OSL_DEBUG_LEVEL > 0 pPage = static_cast<SwPageFrame*>(Lower()); while ( pPage && pPage->GetNext() && _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits