i18npool/source/breakiterator/breakiteratorImpl.cxx     |    4 +--
 i18npool/source/breakiterator/breakiterator_unicode.cxx |   15 +++++++-----
 sw/qa/core/crsr/crsr.cxx                                |   19 ++++++++++++++++
 3 files changed, 30 insertions(+), 8 deletions(-)

New commits:
commit 70c99eef1643a17b2c1f0dba38b55a58cdb9aafc
Author:     Andreas Heinisch <andreas.heini...@yahoo.de>
AuthorDate: Fri Jul 29 09:29:33 2022 +0200
Commit:     Andreas Heinisch <andreas.heini...@yahoo.de>
CommitDate: Sun Aug 21 14:12:43 2022 +0200

    tdf#135451 - Change the skipSpace implementation of the break iterator
    
    Change the ICU whitespace function of the break iterator from 
u_isWhitespace to u_isUWhiteSpace to include no-break spaces.
    
    u_isWhitespace includes Java isWhitespace; Z + whitespace ISO controls but 
excludes no-break spaces
    u_isUWhiteSpace includes all code points with the Unicode White_Space 
property; most of general categories "Z" (separators) + most whitespace ISO 
controls (including no-break spaces, but excluding IS1..IS4)
    
    See https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/uchar_8h.html 
for further details.
    
    Change-Id: I21fddefaf2149096824908f644310a59d6e2f38d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137582
    Tested-by: Jenkins
    Reviewed-by: Andreas Heinisch <andreas.heini...@yahoo.de>

diff --git a/i18npool/source/breakiterator/breakiteratorImpl.cxx 
b/i18npool/source/breakiterator/breakiteratorImpl.cxx
index 71f371a7eddc..71d794e2c9d4 100644
--- a/i18npool/source/breakiterator/breakiteratorImpl.cxx
+++ b/i18npool/source/breakiterator/breakiteratorImpl.cxx
@@ -82,7 +82,7 @@ static sal_Int32 skipSpace(const OUString& Text, sal_Int32 
nPos, sal_Int32 len,
                 while (nPos < len)
                 {
                     ch = Text.iterateCodePoints(&pos);
-                    if (!u_isWhitespace(ch) && !isZWSP(ch))
+                    if (!u_isUWhiteSpace(ch) && !isZWSP(ch))
                         break;
                     nPos = pos;
                 }
@@ -90,7 +90,7 @@ static sal_Int32 skipSpace(const OUString& Text, sal_Int32 
nPos, sal_Int32 len,
                 while (nPos > 0)
                 {
                     ch = Text.iterateCodePoints(&pos, -1);
-                    if (!u_isWhitespace(ch) && !isZWSP(ch))
+                    if (!u_isUWhiteSpace(ch) && !isZWSP(ch))
                         break;
                     nPos = pos;
                 }
diff --git a/i18npool/source/breakiterator/breakiterator_unicode.cxx 
b/i18npool/source/breakiterator/breakiterator_unicode.cxx
index a4a00c46a1ad..cfac4ddea89d 100644
--- a/i18npool/source/breakiterator/breakiterator_unicode.cxx
+++ b/i18npool/source/breakiterator/breakiterator_unicode.cxx
@@ -379,9 +379,10 @@ Boundary SAL_CALL BreakIterator_Unicode::nextWord( const 
OUString& Text, sal_Int
     if( rv.startPos >= Text.getLength() || rv.startPos == 
icu::BreakIterator::DONE )
         rv.endPos = result.startPos;
     else {
-        if ( (rWordType == WordType::ANYWORD_IGNOREWHITESPACES ||
-                    rWordType == WordType::DICTIONARY_WORD ) &&
-                u_isWhitespace(Text.iterateCodePoints(&rv.startPos, 0)) )
+        if ((rWordType == WordType::ANYWORD_IGNOREWHITESPACES
+             && u_isUWhiteSpace(Text.iterateCodePoints(&rv.startPos, 0)))
+            || (rWordType == WordType::DICTIONARY_WORD
+                && u_isWhitespace(Text.iterateCodePoints(&rv.startPos, 0))))
             rv.startPos = 
icuBI->mpValue->mpBreakIterator->following(rv.startPos);
 
         rv.endPos = icuBI->mpValue->mpBreakIterator->following(rv.startPos);
@@ -402,9 +403,11 @@ Boundary SAL_CALL 
BreakIterator_Unicode::previousWord(const OUString& Text, sal_
     if( rv.startPos < 0)
         rv.endPos = rv.startPos;
     else {
-        if ( (rWordType == WordType::ANYWORD_IGNOREWHITESPACES ||
-                    rWordType == WordType::DICTIONARY_WORD) &&
-                u_isWhitespace(Text.iterateCodePoints(&rv.startPos, 0)) )
+
+        if ((rWordType == WordType::ANYWORD_IGNOREWHITESPACES
+             && u_isUWhiteSpace(Text.iterateCodePoints(&rv.startPos, 0)))
+            || (rWordType == WordType::DICTIONARY_WORD
+                && u_isWhitespace(Text.iterateCodePoints(&rv.startPos, 0))))
             rv.startPos = 
icuBI->mpValue->mpBreakIterator->preceding(rv.startPos);
 
         rv.endPos = icuBI->mpValue->mpBreakIterator->following(rv.startPos);
diff --git a/sw/qa/core/crsr/crsr.cxx b/sw/qa/core/crsr/crsr.cxx
index c0713389bec3..759b236d16ac 100644
--- a/sw/qa/core/crsr/crsr.cxx
+++ b/sw/qa/core/crsr/crsr.cxx
@@ -164,6 +164,25 @@ CPPUNIT_TEST_FIXTURE(SwCoreCrsrTest, 
testContentControlReadOnly)
     CPPUNIT_ASSERT(pWrtShell->HasReadonlySel());
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreCrsrTest, testTdf135451)
+{
+    SwDoc* pDoc = createSwDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+    // Insert narrow no-break space and move the cursor right before it
+    pWrtShell->Insert(u"a" + OUStringChar(CHAR_NNBSP) + "b");
+    pWrtShell->EndPara(/*bSelect=*/false);
+    pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    pWrtShell->GoPrevWord();
+    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, 
/*bBasicCall=*/false);
+
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: a
+    // - Actual  : CHAR_NNBSP
+    // i.e., the cursor did not move over the narrow no-break space 
(CHAR_NNBSP)
+    CPPUNIT_ASSERT_EQUAL(OUString("a"), pWrtShell->GetSelText());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to