diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2015-05-14 11:34:33 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2015-05-14 11:39:16 +0200 |
commit | 3c0805e1f4f4d14e92c7e655d59c87de5c207e48 (patch) | |
tree | f83e033781b6724aa77a19537e035d3cfced524e | |
parent | 7e9a4944e53d95f7defb1da384b665e65b2ebc55 (diff) |
tdf#86639 SwEditShell: when setting para style, reset char attrs if needed
The old internal RTF filter used to call SwTxtNode::SetAttr() without
setting SetAttrMode::NOFORMATATTR, so character attributes which cover
the whole node got converted to paragraph attributes. The new UNO
filter goes through SwXText::insertTextPortion(), which sets
SetAttrMode::NOFORMATATTR, so this doesn't happen. The result of this is
that when the UI sets a new paragraph style on the text node, then such
character attributes are no longer removed.
Given that in RTF you can't really have character properties on a
paragraph, going back to the document model produced by the old internal
filter doesn't sound like the good direction -- not to mention that
changing SwXText::insertTextPortion() this way would be an implicit API
change.
Fix the problem by tweaking SwEditShell::SetTxtFmtColl() instead, so
that it removes these full-text-node character attributes, too. The
logic in SwTxtNode::RstTxtAttr() can be extended later if necessary to
delete more attributes, but to be on the safe side, just handle the bare
minimum necessary to fix the problem for now.
Change-Id: I5faa3226fc0f9c18e005da185fe0830d8c393256
-rw-r--r-- | sw/inc/doc.hxx | 2 | ||||
-rw-r--r-- | sw/inc/ndtxt.hxx | 6 | ||||
-rw-r--r-- | sw/qa/extras/uiwriter/data/tdf86639.rtf | 3 | ||||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter.cxx | 14 | ||||
-rw-r--r-- | sw/source/core/doc/DocumentContentOperationsManager.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/doc/docfmt.cxx | 3 | ||||
-rw-r--r-- | sw/source/core/edit/edfcol.cxx | 10 | ||||
-rw-r--r-- | sw/source/core/inc/DocumentContentOperationsManager.hxx | 3 | ||||
-rw-r--r-- | sw/source/core/txtnode/txtedt.cxx | 22 |
9 files changed, 60 insertions, 7 deletions
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx index 546e2dbd80f0..9cc929c1b4f4 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -763,7 +763,7 @@ public: bool bTxtAttr = true, const std::set<sal_uInt16> &rAttrs = std::set<sal_uInt16>(), const bool bSendDataChangedEvents = true ); - void RstTxtAttrs(const SwPaM &rRg, bool bInclRefToxMark = false ); + void RstTxtAttrs(const SwPaM &rRg, bool bInclRefToxMark = false, bool bExactRange = false ); /** Set attribute in given format.1y * If Undo is enabled, the old values is added to the Undo history. */ diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx index e186da7aaedd..87a29ec1bd7d 100644 --- a/sw/inc/ndtxt.hxx +++ b/sw/inc/ndtxt.hxx @@ -266,13 +266,17 @@ public: @param bInclRefToxMark refmarks, toxmarks, and metas will be ignored unless this is true ATTENTION: setting bInclRefToxMark is only allowed from UNDO! + @param bExactRange From the attributes included in the range, delete + only the ones which have exactly same range. Don't delete the ones + which are simply included in the range. */ void RstTxtAttr( const SwIndex &rIdx, const sal_Int32 nLen, const sal_uInt16 nWhich = 0, const SfxItemSet* pSet = 0, - const bool bInclRefToxMark = false ); + const bool bInclRefToxMark = false, + const bool bExactRange = false ); void GCAttr(); // Delete text attribute (needs to be deregistered at Pool!) diff --git a/sw/qa/extras/uiwriter/data/tdf86639.rtf b/sw/qa/extras/uiwriter/data/tdf86639.rtf new file mode 100644 index 000000000000..cdf0be77f956 --- /dev/null +++ b/sw/qa/extras/uiwriter/data/tdf86639.rtf @@ -0,0 +1,3 @@ +{\rtf1\ansi\ansicpg1252\deff0\deflang1035{\fonttbl{\f0\fnil\fcharset0 Calibri;}} +{\*\generator Msftedit 5.41.21.2510;}\viewkind4\uc1\pard\sa200\sl276\slmult1\lang11\f0\fs22 testiiii\par +} diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx index f0a14494b8c5..3a47b8d8fbf1 100644 --- a/sw/qa/extras/uiwriter/uiwriter.cxx +++ b/sw/qa/extras/uiwriter/uiwriter.cxx @@ -28,6 +28,7 @@ #include <swacorr.hxx> #include <swmodule.hxx> #include <modcfg.hxx> +#include <charatr.hxx> #include <editeng/acorrcfg.hxx> #include <unotools/streamwrap.hxx> #include <test/mtfxmldump.hxx> @@ -90,6 +91,7 @@ public: void testSearchWithTransliterate(); void testTdf90362(); void testUndoCharAttribute(); + void testTdf86639(); CPPUNIT_TEST_SUITE(SwUiWriterTest); CPPUNIT_TEST(testReplaceForward); @@ -125,6 +127,7 @@ public: CPPUNIT_TEST(testSearchWithTransliterate); CPPUNIT_TEST(testTdf90362); CPPUNIT_TEST(testUndoCharAttribute); + CPPUNIT_TEST(testTdf86639); CPPUNIT_TEST_SUITE_END(); @@ -948,6 +951,17 @@ void SwUiWriterTest::testUndoCharAttribute() CPPUNIT_ASSERT_EQUAL((*aPoolItem == ampPoolItem), false); } +void SwUiWriterTest::testTdf86639() +{ + SwDoc* pDoc = createDoc("tdf86639.rtf"); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + SwTxtFmtColl* pColl = pDoc->FindTxtFmtCollByName("Heading"); + pWrtShell->SetTxtFmtColl(pColl); + OUString aExpected = pColl->GetAttrSet().GetFont().GetFamilyName(); + // This was Calibri, should be Liberation Sans. + CPPUNIT_ASSERT_EQUAL(aExpected, getProperty<OUString>(getRun(getParagraph(1), 1), "CharFontName")); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index 970d2bc790e1..349e457de7dc 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -3453,13 +3453,13 @@ bool DocumentContentOperationsManager::lcl_RstTxtAttr( const SwNodePtr& rpNd, vo SwRegHistory aRHst( *pTxtNode, pPara->pHistory ); pTxtNode->GetpSwpHints()->Register( &aRHst ); pTxtNode->RstTxtAttr( aSt, nEnd - aSt.GetIndex(), pPara->nWhich, - pPara->pDelSet, pPara->bInclRefToxMark ); + pPara->pDelSet, pPara->bInclRefToxMark, pPara->bExactRange ); if( pTxtNode->GetpSwpHints() ) pTxtNode->GetpSwpHints()->DeRegister(); } else pTxtNode->RstTxtAttr( aSt, nEnd - aSt.GetIndex(), pPara->nWhich, - pPara->pDelSet, pPara->bInclRefToxMark ); + pPara->pDelSet, pPara->bInclRefToxMark, pPara->bExactRange ); } return true; } diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx index 4ba534cb4a0f..c69872bbdb75 100644 --- a/sw/source/core/doc/docfmt.cxx +++ b/sw/source/core/doc/docfmt.cxx @@ -219,7 +219,7 @@ static bool lcl_RstAttr( const SwNodePtr& rpNd, void* pArgs ) return true; } -void SwDoc::RstTxtAttrs(const SwPaM &rRg, bool bInclRefToxMark ) +void SwDoc::RstTxtAttrs(const SwPaM &rRg, bool bInclRefToxMark, bool bExactRange ) { SwHistory* pHst = 0; SwDataChanged aTmp( rRg ); @@ -232,6 +232,7 @@ void SwDoc::RstTxtAttrs(const SwPaM &rRg, bool bInclRefToxMark ) const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End(); sw::DocumentContentOperationsManager::ParaRstFmt aPara( pStt, pEnd, pHst ); aPara.bInclRefToxMark = bInclRefToxMark; + aPara.bExactRange = bExactRange; GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1, sw::DocumentContentOperationsManager::lcl_RstTxtAttr, &aPara ); getIDocumentState().SetModified(); diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index 72b90b38e790..0f1dd3366d47 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -63,7 +63,17 @@ void SwEditShell::SetTxtFmtColl(SwTxtFmtColl *pFmt, if ( !rPaM.HasReadonlySel( GetViewOptions()->IsFormView() ) ) { + // Change the paragraph style to pLocal and remove all direct paragraph formatting. GetDoc()->SetTxtFmtColl( rPaM, pLocal, true, bResetListAttrs ); + + // If there are hints on the nodes which cover the whole node, then remove those, too. + SwPaM aPaM(*rPaM.Start(), *rPaM.End()); + if (SwTxtNode* pEndTxtNode = aPaM.End()->nNode.GetNode().GetTxtNode()) + { + aPaM.Start()->nContent = 0; + aPaM.End()->nContent = pEndTxtNode->GetTxt().getLength(); + } + GetDoc()->RstTxtAttrs(aPaM, /*bInclRefToxMark=*/false, /*bExactRange=*/true); } } diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx index f2ad52b9c1f2..d9122780fad9 100644 --- a/sw/source/core/inc/DocumentContentOperationsManager.hxx +++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx @@ -127,6 +127,8 @@ public: bool bResetListAttrs; // #i62575# bool bResetAll; bool bInclRefToxMark; + /// From the attributes included in the range, delete only the ones which have exactly same range. Don't delete the ones which are simply included in the range. + bool bExactRange; ParaRstFmt(const SwPosition* pStt, const SwPosition* pEnd, SwHistory* pHst, sal_uInt16 nWhch = 0, const SfxItemSet* pSet = 0) @@ -140,6 +142,7 @@ public: , bResetListAttrs(false) , bResetAll(true) , bInclRefToxMark(false) + , bExactRange(false) { } }; diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx index 9c8ea97f932c..06ebf9d4aef1 100644 --- a/sw/source/core/txtnode/txtedt.cxx +++ b/sw/source/core/txtnode/txtedt.cxx @@ -376,7 +376,8 @@ void SwTxtNode::RstTxtAttr( const sal_Int32 nLen, const sal_uInt16 nWhich, const SfxItemSet* pSet, - const bool bInclRefToxMark ) + const bool bInclRefToxMark, + const bool bExactRange ) { if ( !GetpSwpHints() ) return; @@ -421,7 +422,7 @@ void SwTxtNode::RstTxtAttr( SwTxtAttr *pHt = NULL; while ( (i < m_pSwpHints->Count()) && ( ( ( nAttrStart = (*m_pSwpHints)[i]->GetStart()) < nEnd ) - || nLen==0 ) ) + || nLen==0 ) && !bExactRange) { pHt = m_pSwpHints->GetTextHint(i); @@ -599,6 +600,23 @@ void SwTxtNode::RstTxtAttr( ++i; } + if (bExactRange) + { + // Only delete the hints which start at nStt and end at nEnd. + for (i = 0; i < m_pSwpHints->Count(); ++i) + { + SwTxtAttr* pHint = m_pSwpHints->GetTextHint(i); + if (pHint->GetStart() != nStt) + continue; + + const sal_Int32* pHintEnd = pHint->GetEnd(); + if (!pHintEnd || *pHintEnd != nEnd) + continue; + + delAttributes.push_back(pHint); + } + } + if (bChanged && !delAttributes.empty()) { // Delete() calls GetStartOf() - requires sorted hints! m_pSwpHints->Resort(); |