tdf#99672 - Allow replace with empty string when a search format is set

Change-Id: I89d4886db414a802a74f48ca5285f33e3d3ad3e2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201713
Reviewed-by: Andreas Heinisch <andreas.heinisch@yahoo.de>
Tested-by: Jenkins
This commit is contained in:
Andreas Heinisch
2026-03-18 18:35:39 +01:00
parent 3906bb7bed
commit 73b7ac240e
3 changed files with 57 additions and 13 deletions
+40
View File
@@ -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<RES_CHRATR_BEGIN, RES_CHRATR_END> aSet(rView.GetPool());
aSet.Put(aWeightItem);
pWrtShell->SetAttrSet(aSet);
// Search for the inserted text using a format without any replacement string
uno::Reference<util::XReplaceable> xReplace(mxComponent, uno::UNO_QUERY);
uno::Reference<util::XReplaceDescriptor> xReplaceDes = xReplace->createReplaceDescriptor();
// Search for text with bold formatting
uno::Reference<util::XPropertyReplace> xProp(xReplaceDes, uno::UNO_QUERY);
uno::Sequence<beans::PropertyValue> 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
+6 -6
View File
@@ -1274,9 +1274,10 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
const SwPaM & rRegion, bool bInReadOnly,
std::unique_ptr<SvxSearchItem>& 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<bool,void> aLnk( rDoc.GetOle2Link() );
rDoc.SetOle2Link( Link<bool,void>() );
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)
{
+11 -7
View File
@@ -789,16 +789,20 @@ sal_Int32 SwView::FUNC_Search(const SwSearchOptions& rOptions)
}
std::optional<SfxItemSet> 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