basic/CppunitTest_basic_macros.mk              |    1 
 basic/qa/basic_coverage/test_string_replace.vb |    9 ++++-
 basic/source/runtime/methods.cxx               |   44 ++++++++++++++-----------
 3 files changed, 34 insertions(+), 20 deletions(-)

New commits:
commit 15e4d775f7c2edbafca04ade1d293ce71045e9e7
Author:     Andreas Heinisch <andreas.heini...@yahoo.de>
AuthorDate: Sun Jul 11 21:06:23 2021 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Tue Jul 13 12:45:08 2021 +0200

    tdf#142487 - use utl::TextSearch in order to implement the replace algorithm
    
    In the old algorithm, some special unicode characters lead to a
    malfunction of basic's replace function. For instance, replacing a
    German ß to uppercase in the insensitive case will lead to SS, breaking
    the replace positions.
    
    Change-Id: I4e6f6e5fba3d560b8cfd0786fa2439ed5174a928
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118760
    Tested-by: Jenkins
    Reviewed-by: Andreas Heinisch <andreas.heini...@yahoo.de>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118818

diff --git a/basic/CppunitTest_basic_macros.mk 
b/basic/CppunitTest_basic_macros.mk
index c2c1eb5b7a04..c70bfff42c68 100644
--- a/basic/CppunitTest_basic_macros.mk
+++ b/basic/CppunitTest_basic_macros.mk
@@ -61,6 +61,7 @@ $(eval $(call gb_CppunitTest_use_vcl,basic_macros))
 
 $(eval $(call gb_CppunitTest_use_components,basic_macros,\
        configmgr/source/configmgr \
+       i18npool/source/search/i18nsearch \
        i18npool/util/i18npool \
        ucb/source/core/ucb1 \
        ucb/source/ucp/file/ucpfile1 \
diff --git a/basic/qa/basic_coverage/test_string_replace.vb 
b/basic/qa/basic_coverage/test_string_replace.vb
index 8404aaf4961e..21485daa508a 100644
--- a/basic/qa/basic_coverage/test_string_replace.vb
+++ b/basic/qa/basic_coverage/test_string_replace.vb
@@ -31,7 +31,14 @@ Function verify_stringReplace() As String
 
     ' tdf#143081 - Without the fix in place, this test would have crashed here
     retStr = Replace("""Straße""", """", "&quot;")
-    TestLog_ASSERT retStr, "&quot;Straße""&quot;", "replace doesn't crash: " & 
retStr
+    TestLog_ASSERT retStr, "&quot;Straße&quot;", "replace doesn't crash: " & 
retStr
+
+    ' tdf#142487 - replace of special unicode characters.
+    ' Without the fix in place, this test would have failed with:
+    ' - Expected: Straßen
+    ' - Actual  : Straßeen
+    retStr = Replace("Straße", "e", "en")
+    TestLog_ASSERT retStr, "Straßen", "special unicode character: " & retStr
 
     result = result & Chr$(10) & "Tests passed: " & passCount & Chr$(10) & 
"Tests failed: " & failCount & Chr$(10)
     verify_stringReplace = result
diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx
index 7cd9b4716141..ab77fc895b6e 100644
--- a/basic/source/runtime/methods.cxx
+++ b/basic/source/runtime/methods.cxx
@@ -67,6 +67,14 @@
 #include <string_view>
 #include <o3tl/char16_t2wchar_t.hxx>
 
+// include search util
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/util/SearchAlgorithms2.hpp>
+#include <i18nutil/searchopt.hxx>
+#include <unotools/textsearch.hxx>
+
+
+
 using namespace comphelper;
 using namespace osl;
 using namespace com::sun::star;
@@ -1283,34 +1291,32 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool)
     }
 
     const OUString aExpStr = rPar.Get(1)->GetOUString();
-    OUString aFindStr = rPar.Get(2)->GetOUString();
+    const OUString aFindStr = rPar.Get(2)->GetOUString();
     const OUString aReplaceStr = rPar.Get(3)->GetOUString();
+    const sal_Int32 nExpStrLen = aExpStr.getLength();
+    const sal_Int32 nFindStrLen = aFindStr.getLength();
 
-    OUString aSrcStr(aExpStr);
+    // tdf#142487 - use utl::TextSearch in order to implement the replace 
algorithm
+    i18nutil::SearchOptions2 aSearchOptions;
+    aSearchOptions.searchString = aFindStr;
+    aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
     if (bCaseInsensitive)
-    {
-        // tdf#132389 - case-insensitive operation for non-ASCII characters
-        const css::lang::Locale& rLocale = 
Application::GetSettings().GetLanguageTag().getLocale();
-        css::uno::Reference<i18n::XCharacterClassification> xCharClass
-            = vcl::unohelper::CreateCharacterClassification();
-        aSrcStr = xCharClass->toUpper(aSrcStr, 0, aSrcStr.getLength(), 
rLocale);
-        aFindStr = xCharClass->toUpper(aFindStr, 0, aFindStr.getLength(), 
rLocale);
-    }
-    const sal_Int32 nSrcStrLen = aSrcStr.getLength();
-    const sal_Int32 nFindStrLen = aFindStr.getLength();
+        aSearchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
+    utl::TextSearch textSearch(aSearchOptions);
 
     // Note: the result starts from lStartPos, removing everything to the 
left. See i#94895.
-    sal_Int32 nPrevPos = std::min(lStartPos - 1, nSrcStrLen);
-    OUStringBuffer sResult(nSrcStrLen - nPrevPos);
+    sal_Int32 nPrevPos = std::min(lStartPos - 1, nExpStrLen);
+    OUStringBuffer sResult(nExpStrLen - nPrevPos);
     sal_Int32 nCounts = 0;
     while (lCount == -1 || lCount > nCounts)
     {
-        sal_Int32 nPos = aSrcStr.indexOf(aFindStr, nPrevPos);
-        if (nPos >= 0)
+        sal_Int32 nStartPos = nPrevPos;
+        sal_Int32 aEndPos = aExpStr.getLength();
+        if (textSearch.SearchForward(aExpStr, &nStartPos, &aEndPos))
         {
-            sResult.append(aExpStr.getStr() + nPrevPos, nPos - nPrevPos);
+            sResult.append(aExpStr.getStr() + nPrevPos, nStartPos - nPrevPos);
             sResult.append(aReplaceStr);
-            nPrevPos = nPos + nFindStrLen;
+            nPrevPos = nStartPos + nFindStrLen;
             nCounts++;
         }
         else
@@ -1318,7 +1324,7 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool)
             break;
         }
     }
-    sResult.append(aExpStr.getStr() + nPrevPos, nSrcStrLen - nPrevPos);
+    sResult.append(aExpStr.getStr() + nPrevPos, nExpStrLen - nPrevPos);
     rPar.Get(0)->PutString(sResult.makeStringAndClear());
 }
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to