diff --git a/sw/qa/extras/uiwriter/uiwriter7.cxx b/sw/qa/extras/uiwriter/uiwriter7.cxx index b1bd4350d990..8dfdbe3f791f 100644 --- a/sw/qa/extras/uiwriter/uiwriter7.cxx +++ b/sw/qa/extras/uiwriter/uiwriter7.cxx @@ -210,6 +210,46 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testTdf79236) CPPUNIT_ASSERT_EQUAL(SvxAdjust::ParaStart, Adjust5); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testTdf99672SearchReplaceEmptyStringUsingFormat) +{ + // Create a new empty Writer document + createSwDoc(); + SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); + + // Insert and select some text + pWrtShell->Insert("abc"); + pWrtShell->SttPara(/*bSelect=*/true); + SwPaM* pCursor = pWrtShell->GetCursor(); + CPPUNIT_ASSERT_EQUAL(u"abc"_ustr, pCursor->GetText()); + + // Apply bold formatting to the selected text + SwView& rView = pWrtShell->GetView(); + SvxWeightItem aWeightItem(WEIGHT_BOLD, RES_CHRATR_WEIGHT); + SfxItemSetFixed aSet(rView.GetPool()); + aSet.Put(aWeightItem); + pWrtShell->SetAttrSet(aSet); + + // Search for the inserted text using a format without any replacement string + uno::Reference xReplace(mxComponent, uno::UNO_QUERY); + uno::Reference xReplaceDes = xReplace->createReplaceDescriptor(); + + // Search for text with bold formatting + uno::Reference xProp(xReplaceDes, uno::UNO_QUERY); + uno::Sequence aSearchAttr(comphelper::InitPropertySequence( + { { "CharWeight", uno::Any(float(css::awt::FontWeight::BOLD)) } })); + xProp->setSearchAttributes(aSearchAttr); + + xReplaceDes->setSearchString(u"abc"_ustr); + xReplaceDes->setReplaceString(u""_ustr); + xReplace->replaceAll(xReplaceDes); + + // Without the fix in place, this test would have failed with + // - Expected: "" + // - Actual : "abc" + // i.e. bold-formatted text was not replaced when using an empty replacement string + CPPUNIT_ASSERT_EQUAL(u""_ustr, pCursor->GetPointNode().GetTextNode()->GetText()); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testTextSearch) { // Create a new empty Writer document diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx index 507e3a72c60b..09aeb6558d7e 100644 --- a/sw/source/core/crsr/findattr.cxx +++ b/sw/source/core/crsr/findattr.cxx @@ -1274,9 +1274,10 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, const SwPaM & rRegion, bool bInReadOnly, std::unique_ptr& xSearchItem) { - // replace string (only if text given and search is not parameterized)? - bool bReplaceText = pSearchOpt && ( !pSearchOpt->replaceString.isEmpty() || - !pSet->Count() ); + // tdf#99672 - replace text if a search format exists, even when the replace string is empty + const bool bReplaceNoAttr = pReplSet && !pReplSet->Count(); + bool bReplaceText + = pSearchOpt && (!pSearchOpt->replaceString.isEmpty() || !pSet->Count() || bReplaceNoAttr); bool bReplaceAttr = pReplSet && pReplSet->Count(); bool bMoveFirst = !bReplaceAttr; if( bInReadOnly && (bReplaceAttr || bReplaceText )) @@ -1427,9 +1428,8 @@ sal_Int32 SwCursor::FindAttrs( const SfxItemSet& rSet, bool bNoCollections, Link aLnk( rDoc.GetOle2Link() ); rDoc.SetOle2Link( Link() ); - bool bReplace = ( pSearchOpt && ( !pSearchOpt->replaceString.isEmpty() || - !rSet.Count() ) ) || - (pReplSet && pReplSet->Count()); + // tdf#99672 - replace text if a search format exists, even when the replace string is empty + bool bReplace = pReplSet || (pSearchOpt && (!pSearchOpt->replaceString.isEmpty() || !rSet.Count())); bool const bStartUndo = rDoc.GetIDocumentUndoRedo().DoesUndo() && bReplace; if (bStartUndo) { diff --git a/sw/source/uibase/uiview/viewsrch.cxx b/sw/source/uibase/uiview/viewsrch.cxx index 45f963e5a9c9..23d38660d095 100644 --- a/sw/source/uibase/uiview/viewsrch.cxx +++ b/sw/source/uibase/uiview/viewsrch.cxx @@ -789,16 +789,20 @@ sal_Int32 SwView::FUNC_Search(const SwSearchOptions& rOptions) } std::optional xReplSet; - if( bDoReplace && s_xReplaceList && s_xReplaceList->Count() ) + if (bDoReplace) { - xReplSet.emplace( m_pWrtShell->GetAttrPool(), aSearchAttrRange ); - s_xReplaceList->Get( *xReplSet ); + // tdf#99672 - create empty replace set to check for replacements in SwCursor::FindAttrs + xReplSet.emplace(m_pWrtShell->GetAttrPool(), aSearchAttrRange); + if (s_xReplaceList && s_xReplaceList->Count()) + { + s_xReplaceList->Get( *xReplSet ); - // -- Page break with page template - ::SfxToSwPageDescAttr( *m_pWrtShell, *xReplSet ); + // -- Page break with page template + ::SfxToSwPageDescAttr( *m_pWrtShell, *xReplSet ); - if( !xReplSet->Count() ) // too bad, we don't know - xReplSet.reset(); // the attributes + if( !xReplSet->Count() ) // too bad, we don't know + xReplSet.reset(); // the attributes + } } // build SearchOptions to be used