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.heinisch@yahoo.de>
This commit is contained in:
@@ -82,7 +82,7 @@ static sal_Int32 skipSpace(const OUString& Text, sal_Int32 nPos, sal_Int32 len,
|
|||||||
while (nPos < len)
|
while (nPos < len)
|
||||||
{
|
{
|
||||||
ch = Text.iterateCodePoints(&pos);
|
ch = Text.iterateCodePoints(&pos);
|
||||||
if (!u_isWhitespace(ch) && !isZWSP(ch))
|
if (!u_isUWhiteSpace(ch) && !isZWSP(ch))
|
||||||
break;
|
break;
|
||||||
nPos = pos;
|
nPos = pos;
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ static sal_Int32 skipSpace(const OUString& Text, sal_Int32 nPos, sal_Int32 len,
|
|||||||
while (nPos > 0)
|
while (nPos > 0)
|
||||||
{
|
{
|
||||||
ch = Text.iterateCodePoints(&pos, -1);
|
ch = Text.iterateCodePoints(&pos, -1);
|
||||||
if (!u_isWhitespace(ch) && !isZWSP(ch))
|
if (!u_isUWhiteSpace(ch) && !isZWSP(ch))
|
||||||
break;
|
break;
|
||||||
nPos = pos;
|
nPos = pos;
|
||||||
}
|
}
|
||||||
|
@@ -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 )
|
if( rv.startPos >= Text.getLength() || rv.startPos == icu::BreakIterator::DONE )
|
||||||
rv.endPos = result.startPos;
|
rv.endPos = result.startPos;
|
||||||
else {
|
else {
|
||||||
if ( (rWordType == WordType::ANYWORD_IGNOREWHITESPACES ||
|
if ((rWordType == WordType::ANYWORD_IGNOREWHITESPACES
|
||||||
rWordType == WordType::DICTIONARY_WORD ) &&
|
&& u_isUWhiteSpace(Text.iterateCodePoints(&rv.startPos, 0)))
|
||||||
u_isWhitespace(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.startPos = icuBI->mpValue->mpBreakIterator->following(rv.startPos);
|
||||||
|
|
||||||
rv.endPos = 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)
|
if( rv.startPos < 0)
|
||||||
rv.endPos = rv.startPos;
|
rv.endPos = rv.startPos;
|
||||||
else {
|
else {
|
||||||
if ( (rWordType == WordType::ANYWORD_IGNOREWHITESPACES ||
|
|
||||||
rWordType == WordType::DICTIONARY_WORD) &&
|
if ((rWordType == WordType::ANYWORD_IGNOREWHITESPACES
|
||||||
u_isWhitespace(Text.iterateCodePoints(&rv.startPos, 0)) )
|
&& 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.startPos = icuBI->mpValue->mpBreakIterator->preceding(rv.startPos);
|
||||||
|
|
||||||
rv.endPos = icuBI->mpValue->mpBreakIterator->following(rv.startPos);
|
rv.endPos = icuBI->mpValue->mpBreakIterator->following(rv.startPos);
|
||||||
|
@@ -164,6 +164,25 @@ CPPUNIT_TEST_FIXTURE(SwCoreCrsrTest, testContentControlReadOnly)
|
|||||||
CPPUNIT_ASSERT(pWrtShell->HasReadonlySel());
|
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();
|
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||||
|
|
||||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||||
|
Reference in New Issue
Block a user