tdf#162657: re-check the result of combining surrogates

They may constitute a combining mark, and require more characters
to the left to be processed.

Change-Id: Ie626badf66edaf44c56e0ba2d294304f139d2bca
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172533
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
Mike Kaganski
2024-08-28 20:52:04 +02:00
parent 5f1579c6fe
commit ac0117713e
3 changed files with 24 additions and 12 deletions
+14 -6
View File
@@ -1068,7 +1068,7 @@ OUString unicode::formatPercent(double dNumber,
return aRet;
}
bool ToggleUnicodeCodepoint::AllowMoreInput(sal_Unicode uChar)
bool ToggleUnicodeCodepoint::AllowMoreInput(sal_uInt32 uChar)
{
//arbitrarily chosen maximum length allowed - normal max usage would be around 30.
if( maInput.getLength() > 255 )
@@ -1092,12 +1092,20 @@ bool ToggleUnicodeCodepoint::AllowMoreInput(sal_Unicode uChar)
if( rtl::isLowSurrogate(uChar) && maUtf16.isEmpty() && maInput.isEmpty() )
{
maUtf16.append(uChar);
maUtf16.append(sal_Unicode(uChar));
return true;
}
if( rtl::isHighSurrogate(uChar) && maInput.isEmpty() )
maUtf16.insert(0, uChar );
//end of hex strings, or unexpected order of high/low, so don't accept more
maUtf16.insert(0, sal_Unicode(uChar));
if (maUtf16.getLength() == 2)
{
assert(rtl::isHighSurrogate(maUtf16[0]) && rtl::isLowSurrogate(maUtf16[1]));
// The resulting codepoint may itself be combining, so may allow more
sal_uInt32 nUCS4 = rtl::combineSurrogates(maUtf16[0], maUtf16[1]);
maUtf16.setLength(0);
return AllowMoreInput(nUCS4);
}
// unexpected order of high/low, so don't accept more
if( !maUtf16.isEmpty() )
maInput.append(maUtf16);
if( !maCombining.isEmpty() )
@@ -1122,7 +1130,7 @@ bool ToggleUnicodeCodepoint::AllowMoreInput(sal_Unicode uChar)
mbAllowMoreChars = false;
return false;
}
maCombining.insert(0, uChar);
maCombining.insertUtf32(0, uChar);
break;
default:
@@ -1138,7 +1146,7 @@ bool ToggleUnicodeCodepoint::AllowMoreInput(sal_Unicode uChar)
if( !maCombining.isEmpty() )
{
maCombining.insert(0, uChar);
maCombining.insertUtf32(0, uChar);
maInput = maCombining;
mbAllowMoreChars = false;
return false;
+2 -2
View File
@@ -102,11 +102,11 @@ private:
public:
/**
Build an input string of valid UTF16 units to toggle.
Build an input string of valid UTF16/UCS4 units to toggle.
-do not call the other functions until the input process is complete
-build string from Right to Left. (Start from the character to the left of the cursor: move left.)
*/
bool AllowMoreInput(sal_Unicode uChar);
bool AllowMoreInput(sal_uInt32 uChar);
/**
Validates (and potentially modifies) the input string.
+8 -4
View File
@@ -2405,8 +2405,8 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testUnicodeNotationToggle)
sDocString = pWrtShell->GetCursor()->GetPointNode().GetTextNode()->GetText();
CPPUNIT_ASSERT_EQUAL(sOriginalDocString, sDocString);
constexpr OUString sWithCombiningSMPName = u"xyzU+e0101"_ustr;
constexpr OUString sWithCombiningSMP = u"xyz\U000e0101"_ustr;
constexpr OUString sWithCombiningSMPName = u"xyzU+4faeU+e0101"_ustr;
constexpr OUString sWithCombiningSMP = u"xyz\U00004fae\U000e0101"_ustr;
pWrtShell->SplitNode();
pWrtShell->Insert2(sWithCombiningSMPName);
dispatchCommand(mxComponent, u".uno:UnicodeNotationToggle"_ustr, aPropertyValues);
@@ -2416,9 +2416,13 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testUnicodeNotationToggle)
dispatchCommand(mxComponent, u".uno:UnicodeNotationToggle"_ustr, aPropertyValues);
sDocString = pWrtShell->GetCursor()->GetPointNode().GetTextNode()->GetText();
// Before tdf#162656 fix, this failed with
// - Expected: xyzU+e0101
// - Actual : xyU+e0101
// - Expected: xyzU+4faeU+e0101
// - Actual : xyxU+e0101
// i.e., one codepoint to the left of the combining codepoint was removed
// Before tdf#162657 fix, this failed with
// - Expected: xyzU+4faeU+e0101
// - Actual : xyz侮U+e0101
// i.e., one codepoint to the left of the combining codepoint was not converted
CPPUNIT_ASSERT_EQUAL(sWithCombiningSMPName, sDocString);
}