diff options
-rw-r--r-- | sw/qa/extras/uiwriter/data/tdf113481-IVS.odt | bin | 0 -> 9571 bytes | |||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter.cxx | 33 | ||||
-rw-r--r-- | sw/source/uibase/wrtsh/delete.cxx | 42 |
3 files changed, 75 insertions, 0 deletions
diff --git a/sw/qa/extras/uiwriter/data/tdf113481-IVS.odt b/sw/qa/extras/uiwriter/data/tdf113481-IVS.odt Binary files differnew file mode 100644 index 000000000000..1d4a13929d37 --- /dev/null +++ b/sw/qa/extras/uiwriter/data/tdf113481-IVS.odt diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx index e8bc2ea51aae..7319c80a6835 100644 --- a/sw/qa/extras/uiwriter/uiwriter.cxx +++ b/sw/qa/extras/uiwriter/uiwriter.cxx @@ -292,6 +292,7 @@ public: void testTdf113790(); void testTdf108048(); void testTdf114306(); + void testTdf113481(); CPPUNIT_TEST_SUITE(SwUiWriterTest); CPPUNIT_TEST(testReplaceForward); @@ -464,6 +465,7 @@ public: CPPUNIT_TEST(testTdf113790); CPPUNIT_TEST(testTdf108048); CPPUNIT_TEST(testTdf114306); + CPPUNIT_TEST(testTdf113481); CPPUNIT_TEST_SUITE_END(); private: @@ -5668,6 +5670,37 @@ void SwUiWriterTest::testTdf108048() CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), nPageNumber); } +void SwUiWriterTest::testTdf113481() +{ + SwDoc* pDoc = createDoc("tdf113481-IVS.odt"); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + + // One backspace should completely remove the CJK ideograph varation sequence + pWrtShell->EndPara(); + // Before: U+8FBA U+E0102. After: empty + pWrtShell->DelLeft(); + const uno::Reference< text::XTextRange > xPara1 = getParagraph(1); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xPara1->getString().getLength()); + + // In case that weak script is treated as CJK script, remove one character. + pWrtShell->Down(false); + pWrtShell->EndPara(); + // Before: U+4E2D U+2205 U+FE00. After: U+4E2D U+2205 + pWrtShell->DelLeft(); + const uno::Reference< text::XTextRange > xPara2 = getParagraph(2); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xPara2->getString().getLength()); + CPPUNIT_ASSERT_EQUAL(u'\x2205', xPara2->getString()[1]); + + // Characters of other scripts, remove one character. + pWrtShell->Down(false); + pWrtShell->EndPara(); + // Before: U+1820 U+180B. After: U+1820 + pWrtShell->DelLeft(); + const uno::Reference< text::XTextRange > xPara3 = getParagraph(3); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xPara3->getString().getLength()); + CPPUNIT_ASSERT_EQUAL(u'\x1820', xPara3->getString()[0]); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/uibase/wrtsh/delete.cxx b/sw/source/uibase/wrtsh/delete.cxx index 6c2a7d04d272..2f0be3984c85 100644 --- a/sw/source/uibase/wrtsh/delete.cxx +++ b/sw/source/uibase/wrtsh/delete.cxx @@ -42,6 +42,25 @@ inline void SwWrtShell::CloseMark( bool bOkFlag ) EndAllAction(); } +namespace { + +inline bool isUnicodeVariationSequenceSelector( sal_uInt32 nCode ) +{ + return ( nCode >= 0xFE00 && nCode <= 0xFE0F ) // Variation Selectors block + || ( nCode >= 0xE0100 && nCode <= 0xE01EF );// Variation Selectors Supplement block +} + +// Return if the chracter might be a base character of a CJK ideographic varaiation sequence +inline bool isCJKIVSCharacters( sal_uInt32 nCode ) +{ + return ( nCode >= 0x4E00 && nCode <= 0x9FFF ) // CJK Unified Ideographs + || ( nCode >= 0x3400 && nCode <= 0x4DBF ) // CJK Unified Ideographs Extension A + || ( nCode >= 0x20000 && nCode <= 0x2A6DF ); // CJK Unified Ideographs Extension B +} + +} + + // #i23725# bool SwWrtShell::TryRemoveIndent() { @@ -222,6 +241,29 @@ long SwWrtShell::DelLeft() OpenMark(); SwCursorShell::Left(1, CRSR_SKIP_CHARS); + if (SvtScriptType::ASIAN == GetScriptType()) + { + sal_uInt32 nCode = GetChar(false); + if ( rtl::isSurrogate( nCode ) ) + { + OUString sStr = GetSelText(); + sal_Int32 nIndex = 0; + nCode = sStr.iterateCodePoints( &nIndex ); + } + + if ( isUnicodeVariationSequenceSelector( nCode ) ) + { + SwCursorShell::Push(); + SwCursorShell::Left(1, CRSR_SKIP_CHARS); + OUString sStr = GetSelText(); + sal_Int32 nIndex = 0; + nCode = sStr.iterateCodePoints( &nIndex ); + if ( isCJKIVSCharacters( nCode ) ) + SwCursorShell::Pop( SwCursorShell::PopMode::DeleteStack ); + else + SwCursorShell::Pop( SwCursorShell::PopMode::DeleteCurrent ); // For the weak script. + } + } } long nRet = Delete(); if( !nRet && bSwap ) |