external/boost/UnpackedTarball_boost.mk | 4 external/boost/boost.tuple_basic.Wundef.warnings.patch | 34 + include/sal/log-areas.dox | 1 sw/inc/IDocumentContentOperations.hxx | 2 sw/inc/doc.hxx | 6 sw/inc/docary.hxx | 112 +++++ sw/inc/format.hxx | 4 sw/inc/frmfmt.hxx | 20 + sw/inc/pagedesc.hxx | 94 ++++ sw/inc/textboxhelper.hxx | 36 + sw/qa/extras/mailmerge/data/sections_first_last.odt |binary sw/qa/extras/mailmerge/mailmerge.cxx | 38 + sw/qa/extras/uiwriter/uiwriter.cxx | 19 sw/source/core/doc/DocumentLayoutManager.cxx | 6 sw/source/core/doc/docdesc.cxx | 63 +-- sw/source/core/doc/docedt.cxx | 2 sw/source/core/doc/docfly.cxx | 18 sw/source/core/doc/docfmt.cxx | 139 ++++++- sw/source/core/doc/doclay.cxx | 8 sw/source/core/doc/docnew.cxx | 70 ++- sw/source/core/doc/textboxhelper.cxx | 189 +++------ sw/source/core/docnode/nodes.cxx | 39 + sw/source/core/draw/dcontact.cxx | 2 sw/source/core/draw/dview.cxx | 2 sw/source/core/frmedt/fecopy.cxx | 15 sw/source/core/frmedt/feshview.cxx | 8 sw/source/core/inc/rootfrm.hxx | 8 sw/source/core/layout/atrfrm.cxx | 57 ++ sw/source/core/layout/flowfrm.cxx | 13 sw/source/core/layout/fly.cxx | 5 sw/source/core/layout/frmtool.cxx | 2 sw/source/core/layout/layact.cxx | 5 sw/source/core/layout/pagechg.cxx | 235 +++++++----- sw/source/core/layout/pagedesc.cxx | 75 +++ sw/source/core/objectpositioning/anchoredobjectposition.cxx | 2 sw/source/core/text/porfly.cxx | 2 sw/source/core/undo/unattr.cxx | 8 sw/source/core/undo/undobj1.cxx | 2 sw/source/core/undo/untbl.cxx | 2 sw/source/core/unocore/unocoll.cxx | 4 sw/source/core/unocore/unodraw.cxx | 36 - sw/source/core/unocore/unoframe.cxx | 3 sw/source/core/unocore/unoobj2.cxx | 7 sw/source/core/unocore/unoportenum.cxx | 9 sw/source/filter/basflt/shellio.cxx | 2 sw/source/filter/ww8/docxattributeoutput.cxx | 4 sw/source/filter/ww8/docxsdrexport.cxx | 4 sw/source/filter/ww8/rtfsdrexport.cxx | 7 sw/source/filter/ww8/rtfsdrexport.hxx | 3 sw/source/filter/ww8/wrtw8esh.cxx | 3 sw/source/filter/xml/xmltble.cxx | 3 sw/source/uibase/dbui/dbmgr.cxx | 7 sw/source/uibase/docvw/edtwin.cxx | 11 sw/source/uibase/shells/drawsh.cxx | 4 sw/source/uibase/uiview/viewdraw.cxx | 2 55 files changed, 999 insertions(+), 457 deletions(-)
New commits: commit 412f514365ce6646f6221768ed2c46206dd0c91f Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Thu Aug 11 18:45:21 2016 +0200 MM don't keep undo information Doen't make much sense to store undo information for all merge based progress. Actually it even prevents crahes when undoing a merged ODT document. Change-Id: Ic3a3982f3e5eb4f6de9f027a6a5e376c2833e8a5 diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index d70b4b9..9642b26 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -78,6 +78,7 @@ #include <IDocumentLinksAdministration.hxx> #include <IDocumentContentOperations.hxx> #include <IDocumentFieldsAccess.hxx> +#include <IDocumentUndoRedo.hxx> #include <swwait.hxx> #include <swunohelper.hxx> #include <dbui.hrc> @@ -990,6 +991,7 @@ static SfxObjectShell* lcl_CreateWorkingDocument( pWorkWrtShell->GetViewOptions()->SetIdle( false ); pWorkView->AttrChangedNotify( pWorkWrtShell );// in order for SelectShell to be called SwDoc* pWorkDoc = pWorkWrtShell->GetDoc(); + pWorkDoc->GetIDocumentUndoRedo().DoUndo( false ); pWorkDoc->ReplaceDocumentProperties( *pSourceDoc ); if( aType == WorkingDocType::TARGET ) @@ -1530,6 +1532,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, pTargetShell->CalcLayout(); SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" ); pTargetShell->GetViewOptions()->SetIdle( true ); + pTargetDoc->GetIDocumentUndoRedo().DoUndo( true ); for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() ) { aLayout->FreezeLayout(false); commit d943d4faf92f0b86c25f3cd6fe77ed8a7d4905d1 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Thu Aug 11 18:39:20 2016 +0200 Fix SwDoc::AppendDoc for trailing sections We already treat the StartOfContent node special in the CopyRange function to prevent merging of SwTextNodes. For trailing sections, we have to expand the code to treat EndOfContent special too, because the supplied SwPaM range is handled as [mark, point[, so it previously missed the section end node, which resulted in "unhiding" the last section, if it was the last node in the document. Change-Id: Ie094e2a0182647a49c9ba45d08a7dd2cabe667c6 diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx index 75b4f84..1572e21 100644 --- a/sw/inc/IDocumentContentOperations.hxx +++ b/sw/inc/IDocumentContentOperations.hxx @@ -80,7 +80,7 @@ public: be within the range! \warning The range has to include at least two nodes or has to be a - SwDoc::IsColumnSelection! + SwDoc::IsColumnSelection, because the rPam is treated [mark, point[. Normally this function should work only with content nodes. But there is a special case used by SwDoc::Paste, which starts the SwPaM at the diff --git a/sw/qa/extras/mailmerge/data/sections_first_last.odt b/sw/qa/extras/mailmerge/data/sections_first_last.odt new file mode 100644 index 0000000..5a92adb Binary files /dev/null and b/sw/qa/extras/mailmerge/data/sections_first_last.odt differ diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx index 4b2e8ef..84331cc8 100644 --- a/sw/qa/extras/mailmerge/mailmerge.cxx +++ b/sw/qa/extras/mailmerge/mailmerge.cxx @@ -32,6 +32,7 @@ #include <edtwin.hxx> #include <olmenu.hxx> #include <cmdid.h> +#include <pagefrm.hxx> /** * Maps database URIs to the registered database names for quick lookups @@ -531,5 +532,42 @@ DECLARE_SHELL_MAILMERGE_TEST_SELECTION(testTdf95292, "linked-labels.odt", "10-te CPPUNIT_ASSERT_EQUAL( sal_uInt16( 5 ), pWrtShell->GetPhyPageNum() ); } +DECLARE_SHELL_MAILMERGE_TEST(test_sections_first_last, "sections_first_last.odt", "10-testing-addresses.ods", "testing-addresses") +{ + // A document with a leading, middle and trailing section + // Originally we were losing the trailing section during merge + executeMailMerge(); + + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + + // Get the size of the document in nodes + SwDoc *pDoc = pTextDoc->GetDocShell()->GetDoc(); + sal_uLong nSize = pDoc->GetNodes().GetEndOfContent().GetIndex() - pDoc->GetNodes().GetEndOfExtras().GetIndex(); + nSize -= 2; // The common start and end node + CPPUNIT_ASSERT_EQUAL( sal_uLong(13), nSize ); + + SwXTextDocument* pTextDocMM = dynamic_cast<SwXTextDocument *>(mxMMComponent.get()); + CPPUNIT_ASSERT(pTextDocMM); + + SwDoc *pDocMM = pTextDocMM->GetDocShell()->GetDoc(); + sal_uLong nSizeMM = pDocMM->GetNodes().GetEndOfContent().GetIndex() - pDocMM->GetNodes().GetEndOfExtras().GetIndex(); + nSizeMM -= 2; + CPPUNIT_ASSERT_EQUAL( sal_uLong(10 * nSize), nSizeMM ); + + CPPUNIT_ASSERT_EQUAL( sal_uInt16(19), pDocMM->GetDocShell()->GetWrtShell()->GetPhyPageNum() ); + + // All even pages should be empty, all sub-documents have two pages + const SwRootFrame* pLayout = pDocMM->getIDocumentLayoutAccess().GetCurrentLayout(); + const SwPageFrame* pPageFrm = static_cast<const SwPageFrame*>( pLayout->Lower() ); + while ( pPageFrm ) + { + bool bOdd = (1 == (pPageFrm->GetPhyPageNum() % 2)); + CPPUNIT_ASSERT_EQUAL( !bOdd, pPageFrm->IsEmptyPage() ); + CPPUNIT_ASSERT_EQUAL( sal_uInt16( bOdd ? 1 : 2 ), pPageFrm->GetVirtPageNum() ); + pPageFrm = static_cast<const SwPageFrame*>( pPageFrm->GetNext() ); + } +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx index 8079e8f..aeaf702 100644 --- a/sw/source/core/doc/docnew.cxx +++ b/sw/source/core/doc/docnew.cxx @@ -964,20 +964,13 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu SAL_INFO( "sw.pagefrm", "(SwDoc::AppendDoc in " << bDeletePrevious ); // GetEndOfExtras + 1 = StartOfContent == no content node! - // this ensures, that we have at least two nodes in the SwPaM. - // @see IDocumentContentOperations::CopyRange + // This ensures it won't be merged in the SwTextNode at the position. SwNodeIndex aSourceIdx( rSource.GetNodes().GetEndOfExtras(), 1 ); - SwNodeIndex aSourceEndIdx( rSource.GetNodes().GetEndOfContent(), -1 ); - SwPaM aCpyPam( aSourceIdx ); - - if ( aSourceEndIdx.GetNode().IsTextNode() ) { - aCpyPam.SetMark(); - // moves to the last content node before EOC; for single paragraph - // documents this would result in [n, n], which is considered empty - aCpyPam.Move( fnMoveForward, fnGoDoc ); - } - else - aCpyPam = SwPaM( aSourceIdx, aSourceEndIdx ); + // CopyRange works on the range a [mark, point[ and considers an + // index < point outside the selection. + // @see IDocumentContentOperations::CopyRange + SwNodeIndex aSourceEndIdx( rSource.GetNodes().GetEndOfContent(), 0 ); + SwPaM aCpyPam( aSourceIdx, aSourceEndIdx ); #ifdef DBG_UTIL SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceIdx.GetNode().GetNodeType() @@ -994,10 +987,8 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu SAL_INFO( "sw.docappend", ".." ); SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceEndIdx.GetNode().GetNodeType() << std::dec << " " << aSourceEndIdx.GetNode().GetIndex() ); - aSourceEndIdx++; SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceEndIdx.GetNode().GetNodeType() << std::dec << " " << aSourceEndIdx.GetNode().GetIndex() ); - aSourceEndIdx--; SAL_INFO( "sw.docappend", "Src-Nd: " << CNTNT_DOC( &rSource ) ); SAL_INFO( "sw.docappend", "Nd: " << CNTNT_DOC( this ) ); #endif @@ -1041,9 +1032,23 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu } // Otherwise we have to handle SwPlaceholderNodes as first node - if ( pTargetPageDesc ) { + if ( pTargetPageDesc ) + { + SwNodeIndex aBreakIdx( GetNodes().GetEndOfContent(), -1 ); + SwPosition aBreakPos( aBreakIdx ); + // InsertPageBreak just works on SwTextNode nodes, so make + // sure the last node is one! + bool bIsTextNode = aBreakIdx.GetNode().IsTextNode(); + if ( !bIsTextNode ) + getIDocumentContentOperations().AppendTextNode( aBreakPos ); OUString name = pTargetPageDesc->GetName(); pTargetShell->InsertPageBreak( &name, nStartPageNumber ); + if ( !bIsTextNode ) + { + pTargetShell->SttEndDoc( false ); + --aBreakIdx; + GetNodes().Delete( aBreakIdx, 1 ); + } // There is now a new empty text node on the new page. If it has // any marks, those are from the previous page: move them back @@ -1103,7 +1108,8 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu this->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, nullptr ); this->getIDocumentFieldsAccess().LockExpFields(); - // Position where the appended doc starts. Will be filled in later (uses GetEndOfContent() because SwNodeIndex has no default ctor). + // Position where the appended doc starts. Will be filled in later. + // Initially uses GetEndOfContent() because SwNodeIndex has no default ctor. SwNodeIndex aStartAppendIndex( GetNodes().GetEndOfContent() ); { diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx index 7927af3..4b04d07 100644 --- a/sw/source/core/docnode/nodes.cxx +++ b/sw/source/core/docnode/nodes.cxx @@ -1695,24 +1695,30 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange, !pAktNode->m_pStartOfSection->IsSectionNode() ) ) ++aRg.aStart; - // if aEnd-1 points to no ContentNode, search previous one - --aRg.aEnd; - // #i107142#: if aEnd is start node of a special section, do nothing. - // Otherwise this could lead to crash: going through all previous - // special section nodes and then one before the first. - if (aRg.aEnd.GetNode().StartOfSectionIndex() != 0) + const SwNode *aEndNode = &aRg.aEnd.GetNode(); + int nIsEndOfContent = (aEndNode == &aEndNode->GetNodes().GetEndOfContent()) ? 1 : 0; + + if (0 == nIsEndOfContent) { - while( ((pAktNode = & aRg.aEnd.GetNode())->GetStartNode() && - !pAktNode->IsSectionNode() ) || - ( pAktNode->IsEndNode() && - ND_STARTNODE == pAktNode->m_pStartOfSection->GetNodeType()) ) + // if aEnd-1 points to no ContentNode, search previous one + --aRg.aEnd; + // #i107142#: if aEnd is start node of a special section, do nothing. + // Otherwise this could lead to crash: going through all previous + // special section nodes and then one before the first. + if (aRg.aEnd.GetNode().StartOfSectionIndex() != 0) { - --aRg.aEnd; + while( ((pAktNode = & aRg.aEnd.GetNode())->GetStartNode() && + !pAktNode->IsSectionNode() ) || + ( pAktNode->IsEndNode() && + ND_STARTNODE == pAktNode->m_pStartOfSection->GetNodeType()) ) + { + --aRg.aEnd; + } } + ++aRg.aEnd; } - ++aRg.aEnd; - // if in same array, check insertion position + // is there anything left to copy? if( aRg.aStart >= aRg.aEnd ) return; @@ -1787,7 +1793,7 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange, if (nDistance < nNodeCnt) nNodeCnt -= nDistance; else - nNodeCnt = 1; + nNodeCnt = 1 - nIsEndOfContent; aRg.aStart = pAktNode->EndOfSectionIndex(); @@ -1815,7 +1821,7 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange, if (nDistance < nNodeCnt) nNodeCnt -= nDistance; else - nNodeCnt = 1; + nNodeCnt = 1 - nIsEndOfContent; aRg.aStart = pAktNode->EndOfSectionIndex(); if( bNewFrames && pSectNd && @@ -1840,6 +1846,9 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange, --nLevel; ++aInsPos; // EndNode already exists } + else if( 1 == nNodeCnt && 1 == nIsEndOfContent ) + // we have reached the EndOfContent node - nothing to do! + continue; else if( !pAktNode->m_pStartOfSection->IsSectionNode() ) { // create a section at the original InsertPosition commit 345b7023b80587e1a022ff7d2ce16e8afb23d9c5 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Aug 10 12:42:29 2016 +0200 MM block idle-handling of generated documents We don't need any background idle jobs for the generated documents, like spell checking, statistics etc. This can be done when (or even if) the document is presented to the user as a background task. Change-Id: I4c72ed6e0d2f90d43e7f04cd0ea4418cbffe1206 diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 51cedc2..d70b4b9 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -987,6 +987,7 @@ static SfxObjectShell* lcl_CreateWorkingDocument( SwView* pWorkView = static_cast< SwView* >( pWorkFrame->GetViewShell() ); SwWrtShell* pWorkWrtShell = pWorkView->GetWrtShellPtr(); + pWorkWrtShell->GetViewOptions()->SetIdle( false ); pWorkView->AttrChangedNotify( pWorkWrtShell );// in order for SelectShell to be called SwDoc* pWorkDoc = pWorkWrtShell->GetDoc(); pWorkDoc->ReplaceDocumentProperties( *pSourceDoc ); @@ -1528,6 +1529,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, SAL_INFO( "sw.pageframe", "(MergeMailFiles pTargetShell->CalcLayout in" ); pTargetShell->CalcLayout(); SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" ); + pTargetShell->GetViewOptions()->SetIdle( true ); for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() ) { aLayout->FreezeLayout(false); commit 9031b1aeac7cc9e7eb1ab250a9b523240efae4f6 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Aug 10 11:37:15 2016 +0200 Add SAL_INFOs to dump the SwPageFrame lifecycle Debug area name is "sw.pageframe". Change-Id: I136cc8192137a8c682900a6ce2c557f6b6b3a6cd diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox index ac824a8..29f5227 100644 --- a/include/sal/log-areas.dox +++ b/include/sal/log-areas.dox @@ -471,6 +471,7 @@ certain functionality. @li @c sw.idle @li @c sw.level2 @li @c sw.mailmerge - Writer mail merge +@li @c sw.pageframe - debug lifecycle of SwPageFrame @li @c sw.rtf - .rtf export filter @li @c sw.tiled @li @c sw.ui diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx index 07ac968..8079e8f 100644 --- a/sw/source/core/doc/docnew.cxx +++ b/sw/source/core/doc/docnew.cxx @@ -878,6 +878,7 @@ void SwDoc::ReplaceCompatibilityOptions(const SwDoc& rSource) SfxObjectShell* SwDoc::CreateCopy( bool bCallInitNew, bool bEmpty ) const { + SAL_INFO( "sw.pagefrm", "(SwDoc::CreateCopy in" ); SwDoc* pRet = new SwDoc; // we have to use pointer here, since the callee has to decide whether @@ -916,6 +917,7 @@ SfxObjectShell* SwDoc::CreateCopy( bool bCallInitNew, bool bEmpty ) const (void)pRet->release(); + SAL_INFO( "sw.pagefrm", "SwDoc::CreateCopy out)" ); return pRetShell; } @@ -959,6 +961,8 @@ static void lcl_CopyFollowPageDesc( SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber, bool const bDeletePrevious, int pageOffset, const sal_uLong nDocNo) { + SAL_INFO( "sw.pagefrm", "(SwDoc::AppendDoc in " << bDeletePrevious ); + // GetEndOfExtras + 1 = StartOfContent == no content node! // this ensures, that we have at least two nodes in the SwPaM. // @see IDocumentContentOperations::CopyRange @@ -1070,7 +1074,9 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu // Flush the page break, if we want to keep it if ( !bDeletePrevious ) { + SAL_INFO( "sw.pagefrm", "(Flush pagebreak AKA EndAllAction" ); pTargetShell->EndAllAction(); + SAL_INFO( "sw.pagefrm", "Flush changes AKA EndAllAction)" ); pTargetShell->StartAllAction(); } } @@ -1246,6 +1252,7 @@ else if ( pTargetShell ) pTargetShell->EndAllAction(); + SAL_INFO( "sw.pagefrm", "SwDoc::AppendDoc out)" ); return aStartAppendIndex; } diff --git a/sw/source/core/layout/flowfrm.cxx b/sw/source/core/layout/flowfrm.cxx index a28f36a..3b3cfcd 100644 --- a/sw/source/core/layout/flowfrm.cxx +++ b/sw/source/core/layout/flowfrm.cxx @@ -856,6 +856,13 @@ bool SwFrame::WrongPageDesc( SwPageFrame* pNew ) const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() ) ? pNewFlow->GetFrame().GetAttrSet()->GetPageDesc().GetPageDesc() : nullptr; + SAL_INFO( "sw.pagefrm", "WrongPageDesc p: " << pNew << " phys: " << pNew->GetPhyPageNum() ); + SAL_INFO( "sw.pagefrm", "WrongPageDesc " << pNew->GetPageDesc() << " " << pDesc ); + SAL_INFO( "sw.pagefrm", "WrongPageDesc odd: " << bOdd + << " first: " << bFirst << " " << pNew->GetFormat() << " == " + << (bOdd ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst)) << " " + << (bOdd ? pDesc->GetLeftFormat(bFirst) : pDesc->GetRightFormat(bFirst)) ); + return (pNew->GetPageDesc() != pDesc) // own desc ? || (pNew->GetFormat() != (bOdd ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst))) diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx index 3e36f3f..b69d987 100644 --- a/sw/source/core/layout/frmtool.cxx +++ b/sw/source/core/layout/frmtool.cxx @@ -2663,10 +2663,12 @@ SwPageFrame * InsertNewPage( SwPageDesc &rDesc, SwFrame *pUpper, SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ? static_cast<SwPageFrame*>(pSibling->GetPrev())->GetPageDesc() : &rDesc; pRet = new SwPageFrame( pDoc->GetEmptyPageFormat(), pUpper, pTmpDesc ); + SAL_INFO( "sw.pageframe", "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc ); pRet->Paste( pUpper, pSibling ); pRet->PreparePage( bFootnote ); } pRet = new SwPageFrame( pFormat, pUpper, &rDesc ); + SAL_INFO( "sw.pageframe", "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat ); pRet->Paste( pUpper, pSibling ); pRet->PreparePage( bFootnote ); if ( pRet->GetNext() ) diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx index 28477e9..493c0ec 100644 --- a/sw/source/core/layout/pagechg.cxx +++ b/sw/source/core/layout/pagechg.cxx @@ -966,6 +966,7 @@ void SwPageFrame::PrepareRegisterChg() */ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFrame** ppPrev ) { + SAL_INFO( "sw.pageframe", "(CheckPageDescs in phy: " << pStart->GetPhyPageNum() ); assert(pStart && "no starting page."); SwViewShell *pSh = pStart->getRootFrame()->GetCurrShell(); @@ -974,6 +975,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() ) { pImp->GetLayAction().SetCheckPageNum( pStart->GetPhyPageNum() ); + SAL_INFO( "sw.pageframe", "CheckPageDescs out fast - via SetCheckPageNum: " + << pStart->GetPhyPageNum() << ")" ); return; } @@ -1045,7 +1048,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra pNextFormatWish = bNextWantOdd ? pNextDesc->GetLeftFormat() : pNextDesc->GetRightFormat(); if ( pNextFormatWish && pNextPage->GetFormat() == pNextFormatWish ) { - SAL_INFO( "sw.swpagefrm", "CheckPageDescs phys: " << pPage->GetPhyPageNum() + SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum() << " c: 1+3 - skip next page of p: " << pPage ); if (pPage->GetPageDesc() != pPrevPage->GetPageDesc()) pPage->SetPageDesc( pPrevPage->GetPageDesc(), 0 ); @@ -1059,6 +1062,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra bool bUpdatePrev = false; if (ppPrev && *ppPrev == pPage) bUpdatePrev = true; + SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum() + << " c: 1 - destroy p: " << pPage ); SwFrame::DestroyFrame(pPage); if ( pStart == pPage ) pStart = pNextPage; @@ -1070,6 +1075,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra else if ( bIsEmpty && !pFormatWish && //2. pDesc != pPage->GetPageDesc() ) { + SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum() + << " c: 2 - set desc p: " << pPage << " d: " << pDesc ); pPage->SetPageDesc( pDesc, nullptr ); } else if ( !bIsEmpty && //3. @@ -1082,6 +1089,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra if ( pPrevPage ) pDesc = pPrevPage->GetPageDesc(); SwPageFrame *pTmp = new SwPageFrame( pDoc->GetEmptyPageFormat(), pRoot, pDesc ); + SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum() + << " c: 3 - insert empty p: " << pTmp << " d: " << pDesc ); pTmp->Paste( pRoot, pPage ); pTmp->PreparePage( false ); pPage = pTmp; @@ -1090,6 +1099,9 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra { SwPageDesc *pOld = pPage->GetPageDesc(); pPage->SetPageDesc( pDesc, pFormatWish ); + SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum() + << " c: 4 - set desc + format p: " << pPage + << " d: " << pDesc << " f: " << pFormatWish ); if ( bFootnotes ) { // If specific values of the FootnoteInfo are changed, something has to happen. @@ -1104,13 +1116,19 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra else if ( pFormatWish && pPage->GetFormat() != pFormatWish ) //5. { pPage->SetFrameFormat( pFormatWish ); + SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum() + << " c: 5 - set format p: " << pPage << " f: " << pFormatWish ); } else if ( !pFormatWish ) //6. { // get format with inverted logic pFormatWish = bWantOdd ? pDesc->GetLeftFormat() : pDesc->GetRightFormat(); if ( pFormatWish && pPage->GetFormat() != pFormatWish ) + { pPage->SetFrameFormat( pFormatWish ); + SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum() + << " c: 6 - set format p: " << pPage << " f: " << pFormatWish ); + } } #if OSL_DEBUG_LEVEL > 0 else @@ -1134,6 +1152,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra if (ppPrev && *ppPrev == pPage) bUpdatePrev = true; SwFrame::DestroyFrame(pPage); + SAL_INFO( "sw.pageframe", "CheckPageDescs - handle bIsEmpty - destroy p: " << pPage ); if ( pStart == pPage ) pStart = pTmp; pPage = pTmp; @@ -1175,6 +1194,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra pPg = static_cast<SwPageFrame*>(pPg->GetNext()); } #endif + SAL_INFO( "sw.pageframe", "CheckPageDescs out)" ); } namespace @@ -1193,7 +1213,14 @@ namespace SwPageFrame *pPage = new SwPageFrame(pFormat, pRoot, pDesc); SwPageFrame *pSibling = *pRefSibling; if ( pRefPage ) + { *pRefPage = pPage; + SAL_INFO( "sw.pageframe", "doInsertPage p: " << pPage + << " d: " << pDesc << " f: " << pFormat ); + } + else + SAL_INFO( "sw.pageframe", "doInsertPage - insert empty p: " + << pPage << " d: " << pDesc ); pPage->Paste( pRoot, pSibling ); pPage->PreparePage( bFootnote ); // If the sibling has no body text, destroy it as long as it is no footnote page. @@ -1268,8 +1295,12 @@ SwPageFrame *SwFrame::InsertPage( SwPageFrame *pPrevPage, bool bFootnote ) { const sal_uInt16 nNum = pImp->GetLayAction().GetCheckPageNum(); if ( nNum == pPrevPage->GetPhyPageNum() + 1 ) + { pImp->GetLayAction().SetCheckPageNumDirect( pSibling->GetPhyPageNum() ); + SAL_INFO( "sw.pageframe", "InsertPage - SetCheckPageNumDirect: " + << pSibling->GetPhyPageNum() ); + } return pPage; } } @@ -1406,6 +1437,7 @@ void SwRootFrame::RemoveSuperfluous() if ( pPage ) { + SAL_INFO( "sw.pageframe", "RemoveSuperfluous - DestroyFrm p: " << pPage ); RemovePage( &pPage, SwRemoveResult::Prev ); nDocPos = pPage ? pPage->Frame().Top() : 0; } @@ -1469,11 +1501,27 @@ void SwRootFrame::AssertFlyPages() } } } + +#if OSL_DEBUG_LEVEL > 0 + pPage = static_cast<SwPageFrame*>(Lower()); + while ( pPage && pPage->GetNext() && + !static_cast<SwPageFrame*>(pPage->GetNext())->IsFootnotePage() ) + { + SAL_INFO( "sw.pageframe", "AssertFlyPages p: " << pPage << " d: " << pPage->GetPageDesc() + << " f: " << pPage->GetFormat() << " virt: " << pPage->GetVirtPageNum() + << " phys: " << pPage->GetPhyPageNum() << " empty: " << pPage->IsEmptyPage() ); + pPage = static_cast<SwPageFrame*>(pPage->GetNext()); + } + SAL_INFO( "sw.pageframe", "AssertFlyPages p: " << pPage << " d: " << pPage->GetPageDesc() + << " f: " << pPage->GetFormat() << " virt: " << pPage->GetVirtPageNum() + << " phys: " << pPage->GetPhyPageNum() << " empty: " << pPage->IsEmptyPage() ); +#endif } /// Ensure that after the given page all page-bound objects are located on the correct page void SwRootFrame::AssertPageFlys( SwPageFrame *pPage ) { + SAL_INFO( "sw.pageframe", "(AssertPageFlys in" ); while ( pPage ) { if (pPage->GetSortedObjs()) @@ -1488,6 +1536,7 @@ void SwRootFrame::AssertPageFlys( SwPageFrame *pPage ) if ((rAnch.GetAnchorId() == FLY_AT_PAGE) && nPg != pPage->GetPhyPageNum() ) { + SAL_INFO( "sw.pageframe", nPg << " " << pPage->GetPhyPageNum() ); // If on the wrong page, check if previous page is empty if( nPg && !(pPage->GetPhyPageNum()-1 == nPg && static_cast<SwPageFrame*>(pPage->GetPrev())->IsEmptyPage()) ) @@ -1511,6 +1560,7 @@ void SwRootFrame::AssertPageFlys( SwPageFrame *pPage ) } pPage = static_cast<SwPageFrame*>(pPage->GetNext()); } + SAL_INFO( "sw.pageframe", "AssertPageFlys out)" ); } Size SwRootFrame::ChgSize( const Size& aNewSize ) diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 33d497a..51cedc2 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -1525,7 +1525,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, pTargetDoc->SetAllUniqueFlyNames(); // Unfreeze target document layouts and correct all PageDescs. + SAL_INFO( "sw.pageframe", "(MergeMailFiles pTargetShell->CalcLayout in" ); pTargetShell->CalcLayout(); + SAL_INFO( "sw.pageframe", "MergeMailFiles pTargetShell->CalcLayout out)" ); for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() ) { aLayout->FreezeLayout(false); commit 0599989164b77f6c3368b3a2feedc8861107e37b Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Aug 10 11:29:16 2016 +0200 Don't oscillate empty pages in CheckPageDescs For the first case of dropping "wrong" empty pages,look ahead and pre-validate the next page, if it needs this empty page, to prevent case three for the next page. This prevents destruction and re-insert of the empty page. Change-Id: I475aa98a2693f814afcc41bd4bc73f04e742c105 diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx index 3142e33..28477e9 100644 --- a/sw/source/core/layout/pagechg.cxx +++ b/sw/source/core/layout/pagechg.cxx @@ -1028,6 +1028,33 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra if ( bIsEmpty && ( pFormatWish || //1. ( !bWantOdd && !pPrevPage ) ) ) { + // Check all cases for the next page, so we don't oscillate empty pages + // Skip case 1 and 2, as we require a non-empty next page to save the empty page + // Case 3 is the one we actually want to predict and skip + // We can skip the empty check of case 3, as we just work on an existing next page + bool bNextWantOdd; + SwPageDesc *pNextDesc; + if ( pNextPage && !pNextPage->IsEmptyPage() && //3. + pNextPage->OnRightPage() == (bNextWantOdd = pNextPage->WannaRightPage()) && + pNextPage->GetPageDesc() == (pNextDesc = pNextPage->FindPageDesc()) ) //4. + { + bool bNextFirst = pNextPage->OnFirstPage(); + SwFrameFormat *pNextFormatWish = (bNextWantOdd) ? //5. + pNextDesc->GetRightFormat(bNextFirst) : pNextDesc->GetLeftFormat(bNextFirst); + if ( !pNextFormatWish ) // 6. + pNextFormatWish = bNextWantOdd ? pNextDesc->GetLeftFormat() : pNextDesc->GetRightFormat(); + if ( pNextFormatWish && pNextPage->GetFormat() == pNextFormatWish ) + { + SAL_INFO( "sw.swpagefrm", "CheckPageDescs phys: " << pPage->GetPhyPageNum() + << " c: 1+3 - skip next page of p: " << pPage ); + if (pPage->GetPageDesc() != pPrevPage->GetPageDesc()) + pPage->SetPageDesc( pPrevPage->GetPageDesc(), 0 ); + // We can skip the next page, as all checks were already done! + pPage = static_cast<SwPageFrame*>(pNextPage->GetNext()); + continue; + } + } + pPage->Cut(); bool bUpdatePrev = false; if (ppPrev && *ppPrev == pPage) commit adf4c82b6c4ec9d8892f5c417e4a81cf04808447 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Aug 10 11:23:23 2016 +0200 Flush the page break for correct layouting This is a workaround to create correct SwPageFrm objects for layouting, so the page break is actually visible when copying nodes, so we create the correct SwPageFrm. This is especially problematic for mail merge after the fix in commit 60d34e1c840d2c317bb7d0a5b14f4602c22b3fcc, which - correctly - checks all later SwPageDesc for every fix done by CheckPageDescs(). Change-Id: Ie6ea2e9a0587199be4dbaf3ed63a94c29b318ce2 diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx index 3e162fd..07ac968 100644 --- a/sw/source/core/doc/docnew.cxx +++ b/sw/source/core/doc/docnew.cxx @@ -1066,6 +1066,13 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu for (sw::mark::IMark* pMark : aSeenMarks) pMarkAccess->repositionMark(pMark, aPaM); } + + // Flush the page break, if we want to keep it + if ( !bDeletePrevious ) + { + pTargetShell->EndAllAction(); + pTargetShell->StartAllAction(); + } } } #ifdef DBG_UTIL commit 0b5352f67e9c684e59c4f8653ed7fcdd9ae5aa05 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Aug 10 11:06:33 2016 +0200 Use InsertPage in AssertFlyPages AssertFlyPages used its own code to insert pages. It had two flaws: 1. It used the SwPageDesc of the previous page, unaware of changed page description of a new page, which would later be fixed by CheckPageDescs, eventually requiring re-layout. 2. The Code has an of-by-one error when setting the initial bOdd, which would also insert wrong / inverse left and right pages. So this changes AssertFlyPages to use InsertPage, which has a little more overhead for inserts, but prevents later expensive corrections, especially when CheckPageDescs() inserts or removes "early" pages, which need to evaluate and move all page bound flys. Change-Id: I8806cebb26db60602d8438f117e0416e07228b3b diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx index b679cc6..3142e33 100644 --- a/sw/source/core/layout/pagechg.cxx +++ b/sw/source/core/layout/pagechg.cxx @@ -1422,29 +1422,9 @@ void SwRootFrame::AssertFlyPages() if ( nMaxPg > pPage->GetPhyPageNum() ) { - // Continue pages based on the rules of the PageDesc after the last page. - bool bOdd = (pPage->GetPhyPageNum() % 2) != 0; - SwPageDesc *pDesc = pPage->GetPageDesc(); - SwFrame *pSibling = pPage->GetNext(); - for ( sal_uInt16 i = pPage->GetPhyPageNum(); i < nMaxPg; ++i ) - { - if ( !(bOdd ? pDesc->GetRightFormat() : pDesc->GetLeftFormat()) ) - { - // Insert empty page (but Flys will be stored in the next page) - pPage = new SwPageFrame( pDoc->GetEmptyPageFormat(), this, pDesc ); - pPage->Paste( this, pSibling ); - pPage->PreparePage( false ); - bOdd = !bOdd; - ++i; - } - pPage = new - SwPageFrame( (bOdd ? pDesc->GetRightFormat() : - pDesc->GetLeftFormat()), this, pDesc ); - pPage->Paste( this, pSibling ); - pPage->PreparePage( false ); - bOdd = !bOdd; - pDesc = pDesc->GetFollow(); - } + for ( sal_uInt16 i = pPage->GetPhyPageNum(); i < nMaxPg; ++i ) + pPage = InsertPage( pPage, false ); + // If the endnote pages are now corrupt, destroy them. if ( !pDoc->GetFootnoteIdxs().empty() ) { @@ -1455,7 +1435,7 @@ void SwRootFrame::AssertFlyPages() if ( pPage ) { SwPageDesc *pTmpDesc = pPage->FindPageDesc(); - bOdd = pPage->OnRightPage(); + bool bOdd = pPage->OnRightPage(); if ( pPage->GetFormat() != (bOdd ? pTmpDesc->GetRightFormat() : pTmpDesc->GetLeftFormat()) ) RemoveFootnotes( pPage, false, true ); commit f075c30ed6b7820a7723cf18049c2ec2384c5dab Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Aug 10 10:15:33 2016 +0200 Refactor duplicated code in SwFrame::InsertPage Change-Id: Iff9a78cf2f5e6ded4d1b03a8303529aa324ddad9 diff --git a/sw/source/core/inc/rootfrm.hxx b/sw/source/core/inc/rootfrm.hxx index 66dc0ec..078a838 100644 --- a/sw/source/core/inc/rootfrm.hxx +++ b/sw/source/core/inc/rootfrm.hxx @@ -58,6 +58,12 @@ namespace o3tl template<> struct typed_flags<SwInvalidateFlags> : is_typed_flags<SwInvalidateFlags, 0x7f> {}; }; +enum class SwRemoveResult +{ + Next, + Prev +}; + /// The root element of a Writer document layout. class SwRootFrame: public SwLayoutFrame { @@ -385,6 +391,8 @@ public: bool IsLayoutFreezed() const { return mbLayoutFreezed; } void FreezeLayout( bool freeze ) { mbLayoutFreezed = freeze; } + + void RemovePage( SwPageFrame **pDel, SwRemoveResult eResult ); }; inline long SwRootFrame::GetBrowseWidth() const diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx index 6375f8c..b679cc6 100644 --- a/sw/source/core/layout/pagechg.cxx +++ b/sw/source/core/layout/pagechg.cxx @@ -1158,6 +1158,27 @@ namespace const SwFrame* pBodyContent = pBody ? pBody->Lower() : nullptr; return pBodyContent && pBodyContent->IsDeleteForbidden(); } + + bool doInsertPage( SwRootFrame *pRoot, SwPageFrame **pRefSibling, + SwFrameFormat *pFormat, SwPageDesc *pDesc, + bool bFootnote, SwPageFrame **pRefPage ) + { + SwPageFrame *pPage = new SwPageFrame(pFormat, pRoot, pDesc); + SwPageFrame *pSibling = *pRefSibling; + if ( pRefPage ) + *pRefPage = pPage; + pPage->Paste( pRoot, pSibling ); + pPage->PreparePage( bFootnote ); + // If the sibling has no body text, destroy it as long as it is no footnote page. + if ( pSibling && !pSibling->IsFootnotePage() && + !pSibling->FindFirstBodyContent() && + (!pRefPage || !isDeleteForbidden(pSibling)) ) + { + pRoot->RemovePage( pRefSibling, SwRemoveResult::Next ) ; + return false; + } + return true; + } } SwPageFrame *SwFrame::InsertPage( SwPageFrame *pPrevPage, bool bFootnote ) @@ -1197,44 +1218,16 @@ SwPageFrame *SwFrame::InsertPage( SwPageFrame *pPrevPage, bool bFootnote ) // If there is no FrameFormat for this page, create an empty page. if( bWishedOdd != bNextOdd ) { - SwFrameFormat *const pEmptyFormat = pDoc->GetEmptyPageFormat(); - SwPageDesc *pTmpDesc = pPrevPage->GetPageDesc(); - SwPageFrame *pPage = new SwPageFrame(pEmptyFormat, pRoot, pTmpDesc); - pPage->Paste( pRoot, pSibling ); - pPage->PreparePage( bFootnote ); - // If the sibling has no body text, destroy it as long as it is no footnote page. - if ( pSibling && !pSibling->IsFootnotePage() && - !pSibling->FindFirstBodyContent() ) - { - SwPageFrame *pDel = pSibling; - pSibling = static_cast<SwPageFrame*>(pSibling->GetNext()); - if ( !pDoc->GetFootnoteIdxs().empty() ) - pRoot->RemoveFootnotes( pDel, true ); - pDel->Cut(); - SwFrame::DestroyFrame(pDel); - } - else + if( doInsertPage( pRoot, &pSibling, pDoc->GetEmptyPageFormat(), + pPrevPage->GetPageDesc(), bFootnote, nullptr ) ) bCheckPages = true; } SwFrameFormat *const pFormat( (bWishedOdd) ? pDesc->GetRightFormat(bWishedFirst) : pDesc->GetLeftFormat(bWishedFirst) ); assert(pFormat); - SwPageFrame *pPage = new SwPageFrame( pFormat, pRoot, pDesc ); - pPage->Paste( pRoot, pSibling ); - pPage->PreparePage( bFootnote ); - // If the sibling has no body text, destroy it as long as it is no footnote page. - if ( pSibling && !pSibling->IsFootnotePage() && - !pSibling->FindFirstBodyContent() && !isDeleteForbidden(pSibling) ) - { - SwPageFrame *pDel = pSibling; - pSibling = static_cast<SwPageFrame*>(pSibling->GetNext()); - if ( !pDoc->GetFootnoteIdxs().empty() ) - pRoot->RemoveFootnotes( pDel, true ); - pDel->Cut(); - SwFrame::DestroyFrame(pDel); - } - else + SwPageFrame *pPage = nullptr; + if( doInsertPage( pRoot, &pSibling, pFormat, pDesc, bFootnote, &pPage ) ) bCheckPages = true; if ( pSibling ) @@ -1304,6 +1297,17 @@ SwTwips SwRootFrame::ShrinkFrame( SwTwips nDist, bool bTst, bool ) return nDist; } +void SwRootFrame::RemovePage( SwPageFrame **pDelRef, SwRemoveResult eResult ) +{ + SwPageFrame *pDel = *pDelRef; + (*pDelRef) = static_cast<SwPageFrame*>( + eResult == SwRemoveResult::Next ? pDel->GetNext() : pDel->GetPrev() ); + if ( !GetFormat()->GetDoc()->GetFootnoteIdxs().empty() ) + RemoveFootnotes( pDel, true ); + pDel->Cut(); + SwFrame::DestroyFrame( pDel ); +} + /// remove pages that are not needed at all void SwRootFrame::RemoveSuperfluous() { @@ -1375,12 +1379,7 @@ void SwRootFrame::RemoveSuperfluous() if ( pPage ) { - SwPageFrame *pEmpty = pPage; - pPage = static_cast<SwPageFrame*>(pPage->GetPrev()); - if ( !GetFormat()->GetDoc()->GetFootnoteIdxs().empty() ) - RemoveFootnotes( pEmpty, true ); - pEmpty->Cut(); - SwFrame::DestroyFrame(pEmpty); + RemovePage( &pPage, SwRemoveResult::Prev ); nDocPos = pPage ? pPage->Frame().Top() : 0; } } while ( pPage ); commit 978a54b99d7e2df9c0df61cdc3d4153a005618b0 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Aug 10 10:05:08 2016 +0200 Fix some variable scopes and clarify names Helps understanding the code, especially CheckPageDescs(). Change-Id: I53e7d0ea65d6c6ae3da98acba4d366a47d2c4210 diff --git a/sw/source/core/layout/flowfrm.cxx b/sw/source/core/layout/flowfrm.cxx index f207a89..a28f36a 100644 --- a/sw/source/core/layout/flowfrm.cxx +++ b/sw/source/core/layout/flowfrm.cxx @@ -818,15 +818,15 @@ bool SwFrame::WrongPageDesc( SwPageFrame* pNew ) // Way out of the situation: Try to preliminarily insert a // new page once (empty pages are already inserted by InsertPage() // if required) - const SwFormatPageDesc &rFormatDesc = GetAttrSet()->GetPageDesc(); //My Pagedesc doesn't count if I'm a follow! - SwPageDesc *pDesc = nullptr; + const SwPageDesc *pDesc = nullptr; int nTmp = 0; SwFlowFrame *pFlow = SwFlowFrame::CastFlowFrame( this ); if ( !pFlow || !pFlow->IsFollow() ) { - pDesc = const_cast<SwPageDesc*>(rFormatDesc.GetPageDesc()); + const SwFormatPageDesc &rFormatDesc = GetAttrSet()->GetPageDesc(); + pDesc = rFormatDesc.GetPageDesc(); if( pDesc ) { if( !pDesc->GetRightFormat() ) diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx index 7ea39752..6375f8c 100644 --- a/sw/source/core/layout/pagechg.cxx +++ b/sw/source/core/layout/pagechg.cxx @@ -990,19 +990,21 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra pPage = static_cast<SwPageFrame*>(pPage->GetPrev()); while ( pPage ) { - // obtain PageDesc and FrameFormat + SwPageFrame *pPrevPage = static_cast<SwPageFrame*>(pPage->GetPrev()); + SwPageFrame *pNextPage = static_cast<SwPageFrame*>(pPage->GetNext()); + SwPageDesc *pDesc = pPage->FindPageDesc(); - bool bCheckEmpty = pPage->IsEmptyPage(); - bool bActOdd = pPage->OnRightPage(); - bool bOdd = pPage->WannaRightPage(); + bool bIsEmpty = pPage->IsEmptyPage(); + bool bIsOdd = pPage->OnRightPage(); + bool bWantOdd = pPage->WannaRightPage(); bool bFirst = pPage->OnFirstPage(); - SwFrameFormat *pFormatWish = (bOdd) + SwFrameFormat *pFormatWish = (bWantOdd) ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst); - if ( bActOdd != bOdd || + if ( bIsOdd != bWantOdd || pDesc != pPage->GetPageDesc() || // wrong Desc - ( pFormatWish != pPage->GetFormat() && // wrong format and - ( !pPage->IsEmptyPage() || pFormatWish ) // not blank /empty + ( pFormatWish != pPage->GetFormat() && // wrong format and + ( !bIsEmpty || pFormatWish ) // not blank /empty ) ) { @@ -1012,8 +1014,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra // invalidate the field, starting from here if ( nDocPos == LONG_MAX ) - nDocPos = pPage->GetPrev() ? - pPage->GetPrev()->Frame().Top() : pPage->Frame().Top(); + nDocPos = pPrevPage ? pPrevPage->Frame().Top() : pPage->Frame().Top(); // Cases: // 1. Empty page should be "normal" page -> remove empty page and take next one @@ -1024,38 +1025,36 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra // 5. Normal page should have different format -> change // 6. No "wish" format provided -> take the "other" format (left/right) of the PageDesc - if ( pPage->IsEmptyPage() && ( pFormatWish || //1. - ( !bOdd && !pPage->GetPrev() ) ) ) + if ( bIsEmpty && ( pFormatWish || //1. + ( !bWantOdd && !pPrevPage ) ) ) { - SwPageFrame *pTmp = static_cast<SwPageFrame*>(pPage->GetNext()); pPage->Cut(); bool bUpdatePrev = false; if (ppPrev && *ppPrev == pPage) bUpdatePrev = true; SwFrame::DestroyFrame(pPage); if ( pStart == pPage ) - pStart = pTmp; - pPage = pTmp; + pStart = pNextPage; + pPage = pNextPage; if (bUpdatePrev) - *ppPrev = pTmp; + *ppPrev = pNextPage; continue; } - else if ( pPage->IsEmptyPage() && !pFormatWish && //2. + else if ( bIsEmpty && !pFormatWish && //2. pDesc != pPage->GetPageDesc() ) { pPage->SetPageDesc( pDesc, nullptr ); } - else if ( !pPage->IsEmptyPage() && //3. - bActOdd != bOdd && - ( ( !pPage->GetPrev() && !bOdd ) || - ( pPage->GetPrev() && - !static_cast<SwPageFrame*>(pPage->GetPrev())->IsEmptyPage() ) + else if ( !bIsEmpty && //3. + bIsOdd != bWantOdd && + ( ( !pPrevPage && !bWantOdd ) || + ( pPrevPage && !pPrevPage->IsEmptyPage() ) ) ) { - if ( pPage->GetPrev() ) - pDesc = static_cast<SwPageFrame*>(pPage->GetPrev())->GetPageDesc(); - SwPageFrame *pTmp = new SwPageFrame( pDoc->GetEmptyPageFormat(),pRoot,pDesc); + if ( pPrevPage ) + pDesc = pPrevPage->GetPageDesc(); + SwPageFrame *pTmp = new SwPageFrame( pDoc->GetEmptyPageFormat(), pRoot, pDesc ); pTmp->Paste( pRoot, pPage ); pTmp->PreparePage( false ); pPage = pTmp; @@ -1082,8 +1081,8 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra else if ( !pFormatWish ) //6. { // get format with inverted logic - pFormatWish = bOdd ? pDesc->GetLeftFormat() : pDesc->GetRightFormat(); - if ( pPage->GetFormat() != pFormatWish ) + pFormatWish = bWantOdd ? pDesc->GetLeftFormat() : pDesc->GetRightFormat(); + if ( pFormatWish && pPage->GetFormat() != pFormatWish ) pPage->SetFrameFormat( pFormatWish ); } #if OSL_DEBUG_LEVEL > 0 @@ -1093,7 +1092,7 @@ void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFra } #endif } - if ( bCheckEmpty ) + if ( bIsEmpty ) { // It also might be that an empty page is not needed at all. // However, the algorithm above cannot determine that. It is not needed if the following commit 9eff9e699e17cc5a8a25895bd28dc8e4ceb8071e Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Aug 10 09:47:40 2016 +0200 Don't re-check valid SwPageDescs when layouting nCheckPageNum is set to USHRT_MAX, if all SwPageDesc were checked. Code manipulating SwPageFrm objects checks the pages via CheckPageDescs(). If this is currently forbidden, CheckPageDescs() sets nCheckPageNum to the first page to check. I guess the !pPage check is there to check the pages - at the end, if someone has missed the CheckPageDescs call. And we have to run the check, if the current page is unchecked AKA pPage->GetPhyPageNum() >= nCheckPageNum to do correct layouting. Change-Id: Ib67878115cde04b7161c919a67131a1e1dc67d8d diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx index a8d04af..f416426 100644 --- a/sw/source/core/layout/layact.cxx +++ b/sw/source/core/layout/layact.cxx @@ -454,7 +454,10 @@ void SwLayAction::InternalAction(OutputDevice* pRenderContext) sal_uInt16 nPercentPageNum = 0; while ( (pPage && !IsInterrupt()) || m_nCheckPageNum != USHRT_MAX ) { - if (!pPage || (m_nCheckPageNum != USHRT_MAX && pPage->GetPhyPageNum() >= m_nCheckPageNum)) + // nCheckPageNum is set to USHRT_MAX in this code path after we have + // checked the SwPageDescs and set tos the minimal changed SwPageDesc. + // We don't need to check the SwPageDescs without changes. + if ( (m_nCheckPageNum != USHRT_MAX) && (!pPage || pPage->GetPhyPageNum() >= m_nCheckPageNum) ) { if ( !pPage || pPage->GetPhyPageNum() > m_nCheckPageNum ) { commit 28b4c575703430602c72a442f59bb5f9f6aeb749 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Fri Jul 22 18:00:59 2016 +0200 Remove now unused SwTextBoxHelper functions Change-Id: I39500424c79040b1887ea74081fdf0ea0bc5f009 diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx index 98983ba..32fc216 100644 --- a/sw/inc/textboxhelper.hxx +++ b/sw/inc/textboxhelper.hxx @@ -73,8 +73,6 @@ public: static SwFrameFormat* getOtherTextBoxFormat(const SwFrameFormat* pFormat, sal_uInt16 nType); /// If we have an associated TextFrame, then return that. static SwFrameFormat* getOtherTextBoxFormat(css::uno::Reference<css::drawing::XShape> xShape); - static SwFrameFormat* findTextBox(const SwFrameFormat* pShape); - static SwFrameFormat* findTextBox(const css::uno::Reference<css::drawing::XShape>& xShape); /// Return the textbox rectangle of a draw shape (in twips). static Rectangle getTextRectangle(SwFrameFormat* pShape, bool bAbsolute = true); @@ -91,17 +89,6 @@ public: /// Is pObject a textbox of a drawinglayer shape? static bool isTextBox(const SdrObject* pObject); - /// Look up TextFrames in a document, which are in fact TextBoxes. - static std::set<const SwFrameFormat*> findTextBoxes(const SwDoc* pDoc); - /** - * Look up TextFrames in a document, which are in fact TextBoxes. - * - * If rNode has a matching SwContentFrame, then only TextBoxes of rNode are - * returned. - */ - static std::set<const SwFrameFormat*> findTextBoxes(const SwNode& rNode); - /// Build a textbox -> shape format map. - static std::map<SwFrameFormat*, SwFrameFormat*> findShapes(const SwDoc* pDoc); /// Count number of shapes in the document, excluding TextBoxes. static sal_Int32 getCount(const SwDoc* pDoc); /// Count number of shapes on the page, excluding TextBoxes. diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index 5049f10..8a561bb 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -126,25 +126,6 @@ void SwTextBoxHelper::destroy(SwFrameFormat* pShape) } } -std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc) -{ - std::set<const SwFrameFormat*> aTextBoxes; - - const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats(); - for (const SwFrameFormat* pFormat : rSpzFrameFormats) - { - // A TextBox in the context of this class is a fly frame that has a - // matching (same RES_CNTNT) draw frame. - if (!pFormat->GetAttrSet().HasItem(RES_CNTNT) || !pFormat->GetContent().GetContentIdx()) - continue; - - if (pFormat->Which() == RES_FLYFRMFMT && nullptr != pFormat->GetOtherTextBoxFormat()) - aTextBoxes.insert(pFormat); - } - - return aTextBoxes; -} - bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pShape, sal_uInt16 nType) { assert(nType == RES_FLYFRMFMT || nType == RES_DRAWFRMFMT); @@ -167,49 +148,6 @@ bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pShape, sal_uInt16 nType) return true; } -std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwNode& rNode) -{ - const SwDoc* pDoc = rNode.GetDoc(); - const SwContentNode* pContentNode = nullptr; - const SwContentFrame* pContentFrame = nullptr; - bool bHaveViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell(); - if (bHaveViewShell && (pContentNode = rNode.GetContentNode()) && (pContentFrame = pContentNode->getLayoutFrame(pDoc->getIDocumentLayoutAccess().GetCurrentLayout()))) - { - // We can use the layout information to iterate over only the frames which are anchored to us. - std::set<const SwFrameFormat*> aRet; - const SwSortedObjs* pSortedObjs = pContentFrame->GetDrawObjs(); - if (pSortedObjs) - { - for (SwAnchoredObject* pAnchoredObject : *pSortedObjs) - { - SwFrameFormat* pTextBox = getOtherTextBoxFormat(&pAnchoredObject->GetFrameFormat(), RES_DRAWFRMFMT); - if (pTextBox) - aRet.insert(pTextBox); - } - } - return aRet; - } - else - // If necessary, here we could manually limit the returned set to the - // ones which are anchored to rNode, but currently no need to do so. - return findTextBoxes(pDoc); -} - -std::map<SwFrameFormat*, SwFrameFormat*> SwTextBoxHelper::findShapes(const SwDoc* pDoc) -{ - std::map<SwFrameFormat*, SwFrameFormat*> aRet; - - const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats(); - for (SwFrameFormat* pFormat : rSpzFrameFormats) - { - SwFrameFormat* pTextBox = getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT); - if (pTextBox) - aRet[pTextBox] = pFormat; - } - - return aRet; -} - bool SwTextBoxHelper::isTextBox(const SdrObject* pObject) { const SwVirtFlyDrawObj* pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>(pObject); @@ -310,38 +248,6 @@ SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(uno::Reference<drawing::XS return getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT); } -SwFrameFormat* SwTextBoxHelper::findTextBox(const uno::Reference<drawing::XShape>& xShape) -{ - SwXShape* pShape = dynamic_cast<SwXShape*>(xShape.get()); - if (!pShape) - return nullptr; - - return findTextBox(pShape->GetFrameFormat()); -} - -SwFrameFormat* SwTextBoxHelper::findTextBox(const SwFrameFormat* pShape) -{ - SwFrameFormat* pRet = nullptr; - - // Only draw frames can have TextBoxes. - if (pShape && pShape->Which() == RES_DRAWFRMFMT && pShape->GetAttrSet().HasItem(RES_CNTNT)) - { - const SwFormatContent& rContent = pShape->GetContent(); - const SwFrameFormats& rSpzFrameFormats = *pShape->GetDoc()->GetSpzFrameFormats(); - for (SwFrameFormat* pFormat : rSpzFrameFormats) - { - // Only a fly frame can be a TextBox. - if (pFormat->Which() == RES_FLYFRMFMT && pFormat->GetAttrSet().HasItem(RES_CNTNT) && pFormat->GetContent() == rContent) - { - pRet = pFormat; - break; - } - } - } - - return pRet; -} - template < typename T > void lcl_queryInterface(SwFrameFormat* pShape, uno::Any& rAny) { commit f7f5d27066b696ac4e33246d3794bde8058e8622 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Fri Jul 22 17:59:28 2016 +0200 Add convenience function getOtherTextBoxFormat Since we already have isTextBox to identify a text box, this just adds a call to SwFrameFormat::GetOtherTextBoxFormat() to actually return the corresponding SwFrameFormat. This gets rid off all the remaining occurences of the SwFrameFormat / Textbox sets and maps. Change-Id: Id5f05a1ff71e604658e7d8a0d0825f5671335b3f diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx index eb94bbc..98983ba 100644 --- a/sw/inc/textboxhelper.hxx +++ b/sw/inc/textboxhelper.hxx @@ -62,7 +62,17 @@ public: /// Similar to syncProperty(), but used by the internal API (e.g. for UI purposes). static void syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet& rSet); + /** + * If we have an associated TextFrame, then return that. + * + * @param nType Expected frame format type. + * Valid types are RES_DRAWFRMFMT and RES_FLYFRMFMT. + * + * @see isTextBox + */ + static SwFrameFormat* getOtherTextBoxFormat(const SwFrameFormat* pFormat, sal_uInt16 nType); /// If we have an associated TextFrame, then return that. + static SwFrameFormat* getOtherTextBoxFormat(css::uno::Reference<css::drawing::XShape> xShape); static SwFrameFormat* findTextBox(const SwFrameFormat* pShape); static SwFrameFormat* findTextBox(const css::uno::Reference<css::drawing::XShape>& xShape); /// Return the textbox rectangle of a draw shape (in twips). diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx b/sw/source/core/doc/DocumentLayoutManager.cxx index 5fc0d4c..254a4ee 100644 --- a/sw/source/core/doc/DocumentLayoutManager.cxx +++ b/sw/source/core/doc/DocumentLayoutManager.cxx @@ -494,7 +494,7 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( pDest->MakeFrames(); // If the draw format has a TextBox, then copy its fly format as well. - if (SwFrameFormat* pSourceTextBox = SwTextBoxHelper::findTextBox(&rSource)) + if (SwFrameFormat* pSourceTextBox = SwTextBoxHelper::getOtherTextBoxFormat(&rSource, RES_DRAWFRMFMT)) { SwFormatAnchor boxAnchor(rNewAnchor); if (FLY_AS_CHAR == boxAnchor.GetAnchorId()) diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index b180366..5049f10 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -115,7 +115,7 @@ void SwTextBoxHelper::destroy(SwFrameFormat* pShape) // If a TextBox was enabled previously if (pShape->GetAttrSet().HasItem(RES_CNTNT)) { - SwFrameFormat* pFormat = findTextBox(pShape); + SwFrameFormat* pFormat = pShape->GetOtherTextBoxFormat(); // Unlink the TextBox's text range from the original shape. pShape->ResetFormatAttr(RES_CNTNT); @@ -129,7 +129,6 @@ void SwTextBoxHelper::destroy(SwFrameFormat* pShape) std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc) { std::set<const SwFrameFormat*> aTextBoxes; - std::map<SwNodeIndex, const SwFrameFormat*> aFlyFormats, aDrawFormats; const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats(); for (const SwFrameFormat* pFormat : rSpzFrameFormats) @@ -139,22 +138,8 @@ std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc) if (!pFormat->GetAttrSet().HasItem(RES_CNTNT) || !pFormat->GetContent().GetContentIdx()) continue; - const SwNodeIndex& rIndex = *pFormat->GetContent().GetContentIdx(); - - if (pFormat->Which() == RES_FLYFRMFMT) - { - if (aDrawFormats.find(rIndex) != aDrawFormats.end()) - aTextBoxes.insert(pFormat); - else - aFlyFormats[rIndex] = pFormat; - } - else if (pFormat->Which() == RES_DRAWFRMFMT) - { - if (aFlyFormats.find(rIndex) != aFlyFormats.end()) - aTextBoxes.insert(aFlyFormats[rIndex]); - else - aDrawFormats[rIndex] = pFormat; - } + if (pFormat->Which() == RES_FLYFRMFMT && nullptr != pFormat->GetOtherTextBoxFormat()) + aTextBoxes.insert(pFormat); } return aTextBoxes; @@ -197,7 +182,7 @@ std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwNode& rNod { for (SwAnchoredObject* pAnchoredObject : *pSortedObjs) { - SwFrameFormat* pTextBox = findTextBox(&pAnchoredObject->GetFrameFormat()); + SwFrameFormat* pTextBox = getOtherTextBoxFormat(&pAnchoredObject->GetFrameFormat(), RES_DRAWFRMFMT); if (pTextBox) aRet.insert(pTextBox); } @@ -217,7 +202,7 @@ std::map<SwFrameFormat*, SwFrameFormat*> SwTextBoxHelper::findShapes(const SwDoc const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats(); for (SwFrameFormat* pFormat : rSpzFrameFormats) { - SwFrameFormat* pTextBox = findTextBox(pFormat); + SwFrameFormat* pTextBox = getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT); if (pTextBox) aRet[pTextBox] = pFormat; } @@ -303,11 +288,26 @@ sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject) void SwTextBoxHelper::getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough) { - std::map<SwFrameFormat*, SwFrameFormat*> aMap = findShapes(pTextBox->GetDoc()); - auto it = aMap.find(const_cast<SwFrameFormat*>(pTextBox)); - if (it != aMap.end()) - // pTextBox is indeed a TextBox, it->second is its shape. - rWrapThrough = it->second->GetSurround().GetSurround() == SURROUND_THROUGHT; + SwFrameFormat *pShape = SwTextBoxHelper::getOtherTextBoxFormat(pTextBox, RES_FLYFRMFMT); + if (pShape) + rWrapThrough = pShape->GetSurround().GetSurround() == SURROUND_THROUGHT; +} + +SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(const SwFrameFormat* pFormat, sal_uInt16 nType) +{ + if (!isTextBox(pFormat, nType)) + return nullptr; + return pFormat->GetOtherTextBoxFormat(); +} + +SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(uno::Reference<drawing::XShape> xShape) +{ + SwXShape* pShape = dynamic_cast<SwXShape*>(xShape.get()); + if (!pShape) + return nullptr; + + SwFrameFormat *pFormat = pShape->GetFrameFormat(); + return getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT); } SwFrameFormat* SwTextBoxHelper::findTextBox(const uno::Reference<drawing::XShape>& xShape) @@ -345,7 +345,7 @@ SwFrameFormat* SwTextBoxHelper::findTextBox(const SwFrameFormat* pShape) template < typename T > void lcl_queryInterface(SwFrameFormat* pShape, uno::Any& rAny) { - if (SwFrameFormat* pFormat = SwTextBoxHelper::findTextBox(pShape)) + if (SwFrameFormat* pFormat = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) { uno::Reference<T> const xInterface( SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), @@ -423,7 +423,7 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, const OUString& rPrope syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_POSITION, uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Top())))); } - if (SwFrameFormat* pFormat = findTextBox(pShape)) + if (SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) { comphelper::SequenceAsHashMap aCustomShapeGeometry(rValue); // That would be the btLr text direction which we don't support at a frame level, so do it at a character level. @@ -457,7 +457,7 @@ void SwTextBoxHelper::getProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_uI nMemberId &= ~CONVERT_TWIPS; - if (SwFrameFormat* pFormat = findTextBox(pShape)) + if (SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) { if (nWID == RES_CHAIN) { @@ -487,7 +487,7 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u uno::Any aValue(rValue); nMemberId &= ~CONVERT_TWIPS; - if (SwFrameFormat* pFormat = findTextBox(pShape)) + if (SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) { OUString aPropertyName; bool bAdjustX = false; @@ -628,9 +628,7 @@ void SwTextBoxHelper::saveLinks(const SwFrameFormats& rFormats, std::map<const S for (std::size_t i = 0; i < rFormats.size(); ++i) { const SwFrameFormat* pFormat = rFormats[i]; - if (pFormat->Which() != RES_DRAWFRMFMT) - continue; - if (SwFrameFormat* pTextBox = findTextBox(pFormat)) + if (SwFrameFormat* pTextBox = getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT)) rLinks[pFormat] = pTextBox; } } @@ -667,7 +665,7 @@ void SwTextBoxHelper::restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrame void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet& rSet) { - if (SwFrameFormat* pFormat = findTextBox(&rShape)) + if (SwFrameFormat* pFormat = getOtherTextBoxFormat(&rShape, RES_DRAWFRMFMT)) { SfxItemSet aTextBoxSet(pFormat->GetDoc()->GetAttrPool(), aFrameFormatSetRange); diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx index 13c5f0c..763652f 100644 --- a/sw/source/core/draw/dview.cxx +++ b/sw/source/core/draw/dview.cxx @@ -948,7 +948,7 @@ void SwDrawView::DeleteMarked() SdrObject *pObject = rMarkList.GetMark(i)->GetMarkedSdrObj(); SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(GetUserCall(pObject)); SwFrameFormat* pFormat = pDrawContact->GetFormat(); - if (SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(pFormat)) + if (SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT)) aTextBoxesToDelete.push_back(pTextBox); } diff --git a/sw/source/core/frmedt/feshview.cxx b/sw/source/core/frmedt/feshview.cxx index 7d4b170..66302da 100644 --- a/sw/source/core/frmedt/feshview.cxx +++ b/sw/source/core/frmedt/feshview.cxx @@ -235,15 +235,13 @@ bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 nFlag, SdrObject *pObj ) if (!(nFlag & SW_ALLOW_TEXTBOX)) { // If the fly frame is a textbox of a shape, then select the shape instead. - std::map<SwFrameFormat*, SwFrameFormat*> aTextBoxShapes = SwTextBoxHelper::findShapes(mpDoc); for (size_t i = 0; i < rMrkList.GetMarkCount(); ++i) { SdrObject* pObject = rMrkList.GetMark(i)->GetMarkedSdrObj(); - SwContact* pDrawContact = GetUserCall(pObject); - SwFrameFormat* pFormat = pDrawContact->GetFormat(); - if (aTextBoxShapes.find(pFormat) != aTextBoxShapes.end()) + SwFrameFormat* pFormat = GetUserCall(pObject)->GetFormat(); + if (SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT)) { - SdrObject* pShape = aTextBoxShapes[pFormat]->FindSdrObject(); + SdrObject* pShape = pShapeFormat->FindSdrObject(); pDView->UnmarkAll(); pDView->MarkObj(pShape, Imp()->GetPageView(), bAddSelect, bEnterGroup); break; diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index 0eff50c..310bf43 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -1288,11 +1288,10 @@ void SwFlyFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderA } mbValidSize = true; - std::map<SwFrameFormat*, SwFrameFormat*> aShapes = SwTextBoxHelper::findShapes(GetFormat()->GetDoc()); - if (aShapes.find(GetFormat()) != aShapes.end()) + if (SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT)) { // This fly is a textbox of a draw shape. - SdrObject* pShape = aShapes[GetFormat()]->FindSdrObject(); + SdrObject* pShape = pShapeFormat->FindSdrObject(); if (SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>( pShape) ) { // The shape is a customshape: then inform it about the calculated fly size. diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx index e38e99d..5903566 100644 --- a/sw/source/core/text/porfly.cxx +++ b/sw/source/core/text/porfly.cxx @@ -359,7 +359,7 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase, if (rAnchor.GetAnchorId() == FLY_AS_CHAR) { // This is an inline draw shape, see if it has a textbox. - SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(pShape); + SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT); if (pTextBox) { // It has, so look up its text rectangle, and adjust the position diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index d12977e..ee0ad84 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -5142,7 +5142,7 @@ void DocxAttributeOutput::WriteTextBox(uno::Reference<drawing::XShape> xShape) DocxTableExportContext aTableExportContext; pushToTableExportContext(aTableExportContext); - SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(xShape); + SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(xShape); const SwPosition* pAnchor = pTextBox->GetAnchor().GetContentAnchor(); ww8::Frame aFrame(*pTextBox, *pAnchor); m_rExport.SdrExporter().writeDMLTextFrame(&aFrame, m_anchorId++, /*bTextBoxOnly=*/true); @@ -5155,7 +5155,7 @@ void DocxAttributeOutput::WriteVMLTextBox(uno::Reference<drawing::XShape> xShape DocxTableExportContext aTableExportContext; pushToTableExportContext(aTableExportContext); - SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(xShape); + SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(xShape); const SwPosition* pAnchor = pTextBox->GetAnchor().GetContentAnchor(); ww8::Frame aFrame(*pTextBox, *pAnchor); m_rExport.SdrExporter().writeVMLTextFrame(&aFrame, /*bTextBoxOnly=*/true); diff --git a/sw/source/filter/ww8/rtfsdrexport.cxx b/sw/source/filter/ww8/rtfsdrexport.cxx index d7a0506..ccaf688 100644 --- a/sw/source/filter/ww8/rtfsdrexport.cxx +++ b/sw/source/filter/ww8/rtfsdrexport.cxx @@ -39,8 +39,7 @@ RtfSdrExport::RtfSdrExport(RtfExport& rExport) m_nShapeType(ESCHER_ShpInst_Nil), m_nShapeFlags(0) , m_aShapeStyle(200), - m_pShapeTypeWritten(new bool[ ESCHER_ShpInst_COUNT ]), - m_aTextBoxes(SwTextBoxHelper::findTextBoxes(m_rExport.m_pDoc)) + m_pShapeTypeWritten(new bool[ ESCHER_ShpInst_COUNT ]) { mnGroupLevel = 1; memset(m_pShapeTypeWritten, 0, ESCHER_ShpInst_COUNT * sizeof(bool)); @@ -514,7 +513,7 @@ sal_Int32 RtfSdrExport::StartShape() const SwFrameFormat* pShape = FindFrameFormat(m_pSdrObject); if (pShape) { - if (SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(pShape)) + if (SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) { ww8::Frame* pFrame = nullptr; for (auto& rFrame : m_rExport.m_aFrames) diff --git a/sw/source/filter/ww8/rtfsdrexport.hxx b/sw/source/filter/ww8/rtfsdrexport.hxx index a5b3273..f62d093 100644 --- a/sw/source/filter/ww8/rtfsdrexport.hxx +++ b/sw/source/filter/ww8/rtfsdrexport.hxx @@ -56,9 +56,6 @@ class RtfSdrExport : public EscherEx /// Remember which shape types we had already written. bool* m_pShapeTypeWritten; - /// List of TextBoxes in this document: they are exported as part of their shape, never alone. - std::set<const SwFrameFormat*> m_aTextBoxes; - public: explicit RtfSdrExport(RtfExport& rExport); virtual ~RtfSdrExport(); diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index 37e41b1..4990f5c 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -204,7 +204,7 @@ static bool lcl_goIntoTextBox(SwEditWin& rEditWin, SwWrtShell& rSh) { SdrObject* pSdrObject = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); SwFrameFormat* pObjectFormat = ::FindFrameFormat(pSdrObject); - if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::findTextBox(pObjectFormat)) + if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::getOtherTextBoxFormat(pObjectFormat, RES_DRAWFRMFMT)) { SdrObject* pTextBox = pTextBoxFormat->FindRealSdrObject(); SdrView* pSdrView = rSh.GetDrawView(); @@ -4391,10 +4391,9 @@ void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt) SdrPageView* pPV; if (pSdrView && pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pObj, pPV, SdrSearchOptions::ALSOONMASTER )) { - std::map<SwFrameFormat*, SwFrameFormat*> aTextBoxShapes = SwTextBoxHelper::findShapes(rSh.GetDoc()); - auto pDrawContact = GetUserCall(pObj); - SwFrameFormat* pFormat = pDrawContact->GetFormat(); - if (aTextBoxShapes.find(pFormat) == aTextBoxShapes.end()) + SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat(); + SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT); + if (!pShapeFormat) { pSdrView->UnmarkAllObj(); pSdrView->MarkObj(pObj,pPV); @@ -4402,7 +4401,7 @@ void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt) else { // If the fly frame is a textbox of a shape, then select the shape instead. - SdrObject* pShape = aTextBoxShapes[pFormat]->FindSdrObject(); + SdrObject* pShape = pShapeFormat->FindSdrObject(); pSdrView->UnmarkAllObj(); pSdrView->MarkObj(pShape, pPV); } commit 0bcc5b3daebeb2a7d2b5ba132af4745cc6c78cd0 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Fri Jul 22 17:50:52 2016 +0200 Switch isTextBox to use the format pointers This replaces all possible occurences of the text box format maps, which just want to know, if a SwFrameFormat is part of a text box to use the direct lookup via the isTextBox, which is now a cheap call. Change-Id: I3b4e2301f816aead1b719cd70a8ef118e685ccfc diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx index cce1796..eb94bbc 100644 --- a/sw/inc/textboxhelper.hxx +++ b/sw/inc/textboxhelper.hxx @@ -68,6 +68,19 @@ public: /// Return the textbox rectangle of a draw shape (in twips). static Rectangle getTextRectangle(SwFrameFormat* pShape, bool bAbsolute = true); + /** + * Is the frame format a text box? + * + * A text box consists of a coupled fly and draw format. Most times you + * just want to check for a single type, otherwise you get duplicate results. + * + * @param nType Expected frame format input type. + * Valid types are RES_DRAWFRMFMT and RES_FLYFRMFMT. + */ + static bool isTextBox(const SwFrameFormat* pFormat, sal_uInt16 nType); + /// Is pObject a textbox of a drawinglayer shape? + static bool isTextBox(const SdrObject* pObject); + /// Look up TextFrames in a document, which are in fact TextBoxes. static std::set<const SwFrameFormat*> findTextBoxes(const SwDoc* pDoc); /** @@ -77,16 +90,16 @@ public: * returned. */ static std::set<const SwFrameFormat*> findTextBoxes(const SwNode& rNode); - /// Is pObject a textbox of a drawinglayer shape? - static bool isTextBox(const SdrObject* pObject); /// Build a textbox -> shape format map. static std::map<SwFrameFormat*, SwFrameFormat*> findShapes(const SwDoc* pDoc); /// Count number of shapes in the document, excluding TextBoxes. - static sal_Int32 getCount(SdrPage* pPage, std::set<const SwFrameFormat*>& rTextBoxes); + static sal_Int32 getCount(const SwDoc* pDoc); + /// Count number of shapes on the page, excluding TextBoxes. + static sal_Int32 getCount(SdrPage* pPage); /// Get a shape by index, excluding TextBoxes. - static css::uno::Any getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<const SwFrameFormat*>& rTextBoxes) throw(css::lang::IndexOutOfBoundsException); + static css::uno::Any getByIndex(SdrPage* pPage, sal_Int32 nIndex) throw(css::lang::IndexOutOfBoundsException); /// Get the order of the shape, excluding TextBoxes. - static sal_Int32 getOrdNum(const SdrObject* pObject, std::set<const SwFrameFormat*>& rTextBoxes); + static sal_Int32 getOrdNum(const SdrObject* pObject); /// If pTextBox is a textbox, then set rWrapThrough to the surround of its shape. static void getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough); diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx index e6f851c..6e9341e 100644 --- a/sw/qa/extras/uiwriter/uiwriter.cxx +++ b/sw/qa/extras/uiwriter/uiwriter.cxx @@ -856,9 +856,8 @@ void SwUiWriterTest::testFdo82191() { SwDoc* pDoc = createDoc("fdo82191.odt"); SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); - std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc); // Make sure we have a single draw shape. - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), SwTextBoxHelper::getCount(pPage, aTextBoxes)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), SwTextBoxHelper::getCount(pPage)); SwDoc aClipboard; SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); @@ -868,9 +867,8 @@ void SwUiWriterTest::testFdo82191() pWrtShell->Copy(&aClipboard); pWrtShell->Paste(&aClipboard); - aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc); // This was one: the textbox of the shape wasn't copied. - CPPUNIT_ASSERT_EQUAL(size_t(2), aTextBoxes.size()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), SwTextBoxHelper::getCount(pDoc)); } void SwUiWriterTest::testCommentedWord() @@ -3446,15 +3444,20 @@ void SwUiWriterTest::testTdf92648() { SwDoc* pDoc = createDoc("tdf92648.docx"); SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); - std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc); // Make sure we have ten draw shapes. - CPPUNIT_ASSERT_EQUAL(sal_Int32(10), SwTextBoxHelper::getCount(pPage, aTextBoxes)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(10), SwTextBoxHelper::getCount(pPage)); // and the text boxes haven't got zero height - for (std::set<const SwFrameFormat*>::iterator it=aTextBoxes.begin(); it!=aTextBoxes.end(); ++it) + sal_Int32 nCount = 0; + for (const SwFrameFormat* pFormat : *pDoc->GetSpzFrameFormats()) { - SwFormatFrameSize aSize((*it)->GetFrameSize()); + if (!SwTextBoxHelper::isTextBox(pFormat, RES_FLYFRMFMT)) + continue; + SwFormatFrameSize aSize(pFormat->GetFrameSize()); CPPUNIT_ASSERT(aSize.GetHeight() != 0); + ++nCount; } + // and we have had five of them. + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), nCount); } void SwUiWriterTest::testTdf96515() diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx index e1291b6..98ffdae 100644 --- a/sw/source/core/doc/docfly.cxx +++ b/sw/source/core/doc/docfly.cxx @@ -79,15 +79,11 @@ size_t SwDoc::GetFlyCount( FlyCntType eType, bool bIgnoreTextBoxes ) const size_t nCount = 0; const SwNodeIndex* pIdx; - std::set<const SwFrameFormat*> aTextBoxes; - if (bIgnoreTextBoxes) - aTextBoxes = SwTextBoxHelper::findTextBoxes(this); - for ( size_t i = 0; i < nSize; ++i) { const SwFrameFormat* pFlyFormat = rFormats[ i ]; - if (bIgnoreTextBoxes && aTextBoxes.find(pFlyFormat) != aTextBoxes.end()) + if (bIgnoreTextBoxes && SwTextBoxHelper::isTextBox(pFlyFormat, RES_FLYFRMFMT)) continue; if( RES_FLYFRMFMT == pFlyFormat->Which() @@ -131,15 +127,11 @@ SwFrameFormat* SwDoc::GetFlyNum( size_t nIdx, FlyCntType eType, bool bIgnoreText const SwNodeIndex* pIdx; size_t nCount = 0; - std::set<const SwFrameFormat*> aTextBoxes; - if (bIgnoreTextBoxes) - aTextBoxes = SwTextBoxHelper::findTextBoxes(this); - for( size_t i = 0; !pRetFormat && i < nSize; ++i ) { SwFrameFormat* pFlyFormat = rFormats[ i ]; - if (bIgnoreTextBoxes && aTextBoxes.find(pFlyFormat) != aTextBoxes.end()) + if (bIgnoreTextBoxes && SwTextBoxHelper::isTextBox(pFlyFormat, RES_FLYFRMFMT)) continue; if( RES_FLYFRMFMT == pFlyFormat->Which() @@ -177,10 +169,6 @@ std::vector<SwFrameFormat const*> SwDoc::GetFlyFrameFormats( SwFrameFormats& rFormats = *GetSpzFrameFormats(); const size_t nSize = rFormats.size(); - std::set<const SwFrameFormat*> aTextBoxes; - if (bIgnoreTextBoxes) - aTextBoxes = SwTextBoxHelper::findTextBoxes(this); - std::vector<SwFrameFormat const*> ret; ret.reserve(nSize); @@ -188,7 +176,7 @@ std::vector<SwFrameFormat const*> SwDoc::GetFlyFrameFormats( { SwFrameFormat const*const pFlyFormat = rFormats[ i ]; - if (bIgnoreTextBoxes && aTextBoxes.find(pFlyFormat) != aTextBoxes.end()) + if (bIgnoreTextBoxes && SwTextBoxHelper::isTextBox(pFlyFormat, RES_FLYFRMFMT)) { continue; } diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index ce18cd0..b180366 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -160,6 +160,28 @@ std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc) return aTextBoxes; } +bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pShape, sal_uInt16 nType) +{ + assert(nType == RES_FLYFRMFMT || nType == RES_DRAWFRMFMT); + if (!pShape || pShape->Which() != nType || !pShape->GetAttrSet().HasItem(RES_CNTNT)) + return false; + + sal_uInt16 nOtherType = (pShape->Which() == RES_FLYFRMFMT) ? RES_DRAWFRMFMT : RES_FLYFRMFMT; + SwFrameFormat* pFormat = pShape->GetOtherTextBoxFormat(); + if (!pFormat) + return false; + + assert(pFormat->Which() == nOtherType); + if (pFormat->Which() != nOtherType) + return false; + + const SwFormatContent& rContent = pShape->GetContent(); + if (!pFormat->GetAttrSet().HasItem(RES_CNTNT) || pFormat->GetContent() != rContent) + return false; + + return true; +} + std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwNode& rNode) { const SwDoc* pDoc = rNode.GetDoc(); @@ -203,35 +225,39 @@ std::map<SwFrameFormat*, SwFrameFormat*> SwTextBoxHelper::findShapes(const SwDoc return aRet; } -/// If the passed SdrObject is in fact a TextFrame, that is used as a TextBox. -bool lcl_isTextBox(SdrObject* pSdrObject, std::set<const SwFrameFormat*>& rTextBoxes) -{ - SwVirtFlyDrawObj* pObject = dynamic_cast<SwVirtFlyDrawObj*>(pSdrObject); - return pObject && rTextBoxes.find(pObject->GetFormat()) != rTextBoxes.end(); -} - bool SwTextBoxHelper::isTextBox(const SdrObject* pObject) { const SwVirtFlyDrawObj* pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>(pObject); if (!pVirtFlyDrawObj) return false; - std::set<const SwFrameFormat*> aTextBoxes = findTextBoxes(pVirtFlyDrawObj->GetFormat()->GetDoc()); - return aTextBoxes.find(pVirtFlyDrawObj->GetFormat()) != aTextBoxes.end(); + return isTextBox(pVirtFlyDrawObj->GetFormat(), RES_FLYFRMFMT); } -sal_Int32 SwTextBoxHelper::getCount(SdrPage* pPage, std::set<const SwFrameFormat*>& rTextBoxes) +sal_Int32 SwTextBoxHelper::getCount(SdrPage* pPage) { sal_Int32 nRet = 0; for (std::size_t i = 0; i < pPage->GetObjCount(); ++i) { - if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes)) + if (isTextBox(pPage->GetObj(i))) continue; ++nRet; } return nRet; } -uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<const SwFrameFormat*>& rTextBoxes) throw(lang::IndexOutOfBoundsException) +sal_Int32 SwTextBoxHelper::getCount(const SwDoc* pDoc) +{ + sal_Int32 nRet = 0; + const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats(); + for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it) + { + if (isTextBox(*it, RES_FLYFRMFMT)) + ++nRet; + } + return nRet; +} + +uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex) throw(lang::IndexOutOfBoundsException) { if (nIndex < 0) throw lang::IndexOutOfBoundsException(); @@ -240,7 +266,7 @@ uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set< sal_Int32 nCount = 0; // Current logical index. for (std::size_t i = 0; i < pPage->GetObjCount(); ++i) { - if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes)) + if (isTextBox(pPage->GetObj(i))) continue; if (nCount == nIndex) { @@ -256,14 +282,14 @@ uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set< return uno::makeAny(uno::Reference<drawing::XShape>(pRet->getUnoShape(), uno::UNO_QUERY)); } -sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject, std::set<const SwFrameFormat*>& rTextBoxes) +sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject) { if (const SdrPage* pPage = pObject->GetPage()) { sal_Int32 nOrder = 0; // Current logical order. for (std::size_t i = 0; i < pPage->GetObjCount(); ++i) { - if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes)) + if (isTextBox(pPage->GetObj(i))) continue; if (pPage->GetObj(i) == pObject) return nOrder; diff --git a/sw/source/core/draw/dcontact.cxx b/sw/source/core/draw/dcontact.cxx index 7001945..6c60a8b 100644 --- a/sw/source/core/draw/dcontact.cxx +++ b/sw/source/core/draw/dcontact.cxx @@ -1151,7 +1151,7 @@ class NestedUserCallHdl /// Notify the format's textbox that it should reconsider its position / size. void lcl_textBoxSizeNotify(SwFrameFormat* pFormat) { - if (SwTextBoxHelper::findTextBox(pFormat)) + if (SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT)) { // Just notify the textbox that the size has changed, the actual object size is not interesting. SfxItemSet aResizeSet(pFormat->GetDoc()->GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE, 0); diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx index 277a0b6..0c65476 100644 --- a/sw/source/core/frmedt/fecopy.cxx +++ b/sw/source/core/frmedt/fecopy.cxx @@ -902,7 +902,6 @@ bool SwFEShell::Paste( SwDoc* pClpDoc ) if( !Imp()->GetDrawView() ) MakeDrawView(); - std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pClpDoc); for ( auto pCpyFormat : *pClpDoc->GetSpzFrameFormats() ) { bool bInsWithFormat = true; @@ -972,7 +971,7 @@ bool SwFEShell::Paste( SwDoc* pClpDoc ) } // Ignore TextBoxes, they are already handled in sw::DocumentLayoutManager::CopyLayoutFormat(). - if (aTextBoxes.find(pCpyFormat) != aTextBoxes.end()) + if (SwTextBoxHelper::isTextBox(pCpyFormat, RES_FLYFRMFMT)) continue; aAnchor.SetAnchor( pPos ); diff --git a/sw/source/core/objectpositioning/anchoredobjectposition.cxx b/sw/source/core/objectpositioning/anchoredobjectposition.cxx index 1cf2c0f..9488a4b 100644 --- a/sw/source/core/objectpositioning/anchoredobjectposition.cxx +++ b/sw/source/core/objectpositioning/anchoredobjectposition.cxx @@ -501,7 +501,7 @@ SwTwips SwAnchoredObjectPosition::ImplAdjustVertRelPos( const SwTwips nTopOfAnch pFrameFormat->SetFormatAttr(aSize); } nAdjustedRelPosY = nProposedRelPosY; - } else if ( SwTextBoxHelper::findTextBox(pFormat) ) + } else if ( SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT) ) // when the shape has a textbox, use only the proposed vertical position nAdjustedRelPosY = nProposedRelPosY; } diff --git a/sw/source/core/unocore/unocoll.cxx b/sw/source/core/unocore/unocoll.cxx index 44e7b63..79d3859 100644 --- a/sw/source/core/unocore/unocoll.cxx +++ b/sw/source/core/unocore/unocoll.cxx @@ -1088,13 +1088,11 @@ SwXFrameEnumeration<T>::SwXFrameEnumeration(const SwDoc* const pDoc) // #i104937# SwFrameFormat* pFormat( nullptr ); - std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc); - for( size_t i = 0; i < nSize; ++i ) { // #i104937# pFormat = (*pFormats)[i]; - if(pFormat->Which() != RES_FLYFRMFMT || aTextBoxes.find(pFormat) != aTextBoxes.end()) + if(pFormat->Which() != RES_FLYFRMFMT || SwTextBoxHelper::isTextBox(pFormat, RES_FLYFRMFMT)) continue; const SwNodeIndex* pIdx = pFormat->GetContent().GetContentIdx(); if(!pIdx || !pIdx->GetNodes().IsDocNodes()) diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx index f3d7cf5..846fe42 100644 --- a/sw/source/core/unocore/unodraw.cxx +++ b/sw/source/core/unocore/unodraw.cxx @@ -397,10 +397,9 @@ SwXShapesEnumeration::SwXShapesEnumeration(SwXDrawPage* const pDrawPage) SolarMutexGuard aGuard; std::insert_iterator<shapescontainer_t> pInserter = std::insert_iterator<shapescontainer_t>(m_aShapes, m_aShapes.begin()); sal_Int32 nCount = pDrawPage->getCount(); - std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDrawPage->GetDoc()); for(sal_Int32 nIdx = 0; nIdx < nCount; nIdx++) { - uno::Reference<drawing::XShape> xShape(pDrawPage->getByIndex(nIdx, &aTextBoxes), uno::UNO_QUERY); + uno::Reference<drawing::XShape> xShape(pDrawPage->getByIndex(nIdx), uno::UNO_QUERY); *pInserter++ = uno::makeAny(xShape); } } @@ -523,13 +522,7 @@ sal_Int32 SwXDrawPage::getCount() throw( uno::RuntimeException, std::exception ) else { GetSvxPage(); - - std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc); - - if (aTextBoxes.empty()) - return pDrawPage->getCount(); - else - return SwTextBoxHelper::getCount(pDrawPage->GetSdrPage(), aTextBoxes); + return SwTextBoxHelper::getCount(pDrawPage->GetSdrPage()); } } @@ -537,12 +530,6 @@ uno::Any SwXDrawPage::getByIndex(sal_Int32 nIndex) throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException, std::exception ) { - return getByIndex(nIndex, nullptr); -} - -uno::Any SwXDrawPage::getByIndex(sal_Int32 nIndex, std::set<const SwFrameFormat*>* pTextBoxes) - throw(lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException, std::exception) -{ SolarMutexGuard aGuard; if(!pDoc) throw uno::RuntimeException(); @@ -550,17 +537,7 @@ uno::Any SwXDrawPage::getByIndex(sal_Int32 nIndex, std::set<const SwFrameFormat* throw lang::IndexOutOfBoundsException(); GetSvxPage(); - std::set<const SwFrameFormat*> aTextBoxes; - if (!pTextBoxes) - { - // We got no set, so let's generate one. - aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc); - pTextBoxes = &aTextBoxes; - } - if (pTextBoxes->empty()) - return pDrawPage->getByIndex( nIndex ); - else - return SwTextBoxHelper::getByIndex(pDrawPage->GetSdrPage(), nIndex, *pTextBoxes); + return SwTextBoxHelper::getByIndex(pDrawPage->GetSdrPage(), nIndex); } uno::Type SwXDrawPage::getElementType() throw( uno::RuntimeException, std::exception ) @@ -1554,7 +1531,7 @@ uno::Any SwXShape::getPropertyValue(const OUString& rPropertyName) } else if (pEntry->nWID == FN_TEXT_BOX) { - bool bValue = SwTextBoxHelper::findTextBox(pFormat); + bool bValue = SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT); aRet <<= bValue; } else if (pEntry->nWID == RES_CHAIN) @@ -1759,8 +1736,7 @@ uno::Any SwXShape::getPropertyValue(const OUString& rPropertyName) bConvert = false; if (bConvert) { - std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pFormat->GetDoc()); - aRet <<= SwTextBoxHelper::getOrdNum(pObj, aTextBoxes); + aRet <<= SwTextBoxHelper::getOrdNum(pObj); } } } @@ -1840,7 +1816,7 @@ uno::Sequence< beans::PropertyState > SwXShape::getPropertyStates( else if (pEntry->nWID == FN_TEXT_BOX) { // The TextBox property is set, if we can find a textbox for this shape. - if (pFormat && SwTextBoxHelper::findTextBox(pFormat)) + if (pFormat && SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT)) pRet[nProperty] = beans::PropertyState_DIRECT_VALUE; else pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE; diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx index cca3207..656d868 100644 --- a/sw/source/core/unocore/unoframe.cxx +++ b/sw/source/core/unocore/unoframe.cxx @@ -1751,8 +1751,7 @@ void SwXFrame::setPropertyValue(const OUString& rPropertyName, const ::uno::Any& aValue >>= nZOrder; // Don't set an explicit ZOrder on TextBoxes. - std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc); - if( nZOrder >= 0 && aTextBoxes.find(pFormat) == aTextBoxes.end()) + if( nZOrder >= 0 && !SwTextBoxHelper::isTextBox(pFormat, RES_FLYFRMFMT) ) { SdrObject* pObject = GetOrCreateSdrObject( static_cast<SwFlyFrameFormat&>(*pFormat) ); diff --git a/sw/source/core/unocore/unoobj2.cxx b/sw/source/core/unocore/unoobj2.cxx index 8c43ba7..ee4e4e9 100644 --- a/sw/source/core/unocore/unoobj2.cxx +++ b/sw/source/core/unocore/unoobj2.cxx @@ -165,19 +165,18 @@ struct FrameClientSortListLess namespace { - void lcl_CollectFrameAtNodeWithLayout(SwDoc* pDoc, const SwContentFrame* pCFrame, + void lcl_CollectFrameAtNodeWithLayout(const SwContentFrame* pCFrame, FrameClientSortList_t& rFrames, const sal_uInt16 nAnchorType) { auto pObjs = pCFrame->GetDrawObjs(); if(!pObjs) return; - const auto aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc); for(const auto pAnchoredObj : *pObjs) { SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat(); // Filter out textboxes, which are not interesting at an UNO level. - if(aTextBoxes.find(&rFormat) != aTextBoxes.end()) + if(SwTextBoxHelper::isTextBox(&rFormat, RES_FLYFRMFMT)) continue; if(rFormat.GetAnchor().GetAnchorId() == nAnchorType) { @@ -211,7 +210,7 @@ void CollectFrameAtNode( const SwNodeIndex& rIdx, nullptr != (pCNd = rIdx.GetNode().GetContentNode()) && nullptr != (pCFrame = pCNd->getLayoutFrame( pDoc->getIDocumentLayoutAccess().GetCurrentLayout())) ) { - lcl_CollectFrameAtNodeWithLayout(pDoc, pCFrame, rFrames, nChkType); + lcl_CollectFrameAtNodeWithLayout(pCFrame, rFrames, nChkType); } else { diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx index 07fe139..eac6691 100644 --- a/sw/source/core/unocore/unoportenum.cxx +++ b/sw/source/core/unocore/unoportenum.cxx @@ -716,8 +716,7 @@ lcl_ExportHints( const sal_Int32 nCurrentIndex, const bool bRightMoveForbidden, bool & o_rbCursorMoved, - sal_Int32 & o_rNextAttrPosition, - std::set<const SwFrameFormat*>& rTextBoxes) + sal_Int32 & o_rNextAttrPosition) { // if the attribute has a dummy character, then xRef is set (except META) // otherwise, the portion for the attribute is inserted into rPortions! @@ -887,7 +886,7 @@ lcl_ExportHints( break; // Robust #i81708 content in covered cells // Do not expose inline anchored textboxes. - if (rTextBoxes.find(pAttr->GetFlyCnt().GetFrameFormat()) != rTextBoxes.end()) + if (SwTextBoxHelper::isTextBox(pAttr->GetFlyCnt().GetFrameFormat(), RES_FLYFRMFMT)) break; pUnoCursor->Exchange(); @@ -1272,8 +1271,6 @@ static void lcl_CreatePortions( PortionStack_t PortionStack; PortionStack.push( PortionList_t(&i_rPortions, nullptr) ); - std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pUnoCursor->GetNode()); - bool bAtEnd( false ); while (!bAtEnd) // every iteration consumes at least current character! { @@ -1324,7 +1321,7 @@ static void lcl_CreatePortions( // N.B.: side-effects nNextAttrIndex, bCursorMoved; may move cursor xRef = lcl_ExportHints(PortionStack, i_xParentText, pUnoCursor, pHints, i_nStartPos, i_nEndPos, nCurrentIndex, bAtEnd, ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits