summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzymon Kłos <szymon.klos@collabora.com>2021-09-07 12:54:56 +0200
committerSzymon Kłos <szymon.klos@collabora.com>2021-10-06 11:10:04 +0200
commit7df324b4561a6551812bdfa5b72ba1c937148c41 (patch)
tree4e5aab705ccb5b45be04b27cb49ecaa897c0959f
parentd99c7586edf41e1b22f1ef363859a86bf397e35f (diff)
lok: IME: preserve formatting when inserting at the end of paragraph
There was a problem with inserting characters at the end of paragraph in online. When user set text to bolded, inserted few characters, then switched bold off. When trying to put another non-bolded character - the result was still bolded. It is caused by IME mechanics which gathers all elements for composition and at the end deletes these characters and inserts again but using document interface to keep undo records. During that operation formatting has been lost. This change does the same in reversed order so we first put new string correctly formatted at the end. Then we remove old leftovers. In result formatting is correct. Change-Id: Ieb498afdbe42c0080c30ea3db994cedc98e89847 Signed-off-by: Szymon Kłos <szymon.klos@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121774 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122477 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123100 Tested-by: Jenkins
-rw-r--r--sw/qa/extras/tiledrendering/tiledrendering.cxx109
-rw-r--r--sw/source/core/doc/extinput.cxx13
2 files changed, 121 insertions, 1 deletions
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index ed2ba675644f..e1ebae14d421 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -32,6 +32,7 @@
#include <vcl/virdev.hxx>
#include <editeng/editview.hxx>
#include <editeng/outliner.hxx>
+#include <editeng/wghtitem.hxx>
#include <svl/srchitem.hxx>
#include <svl/slstitm.hxx>
#include <svl/stritem.hxx>
@@ -132,6 +133,7 @@ public:
void testTdf115088();
void testRedlineField();
void testIMESupport();
+ void testIMEFormattingAtEndOfParagraph();
void testSplitNodeRedlineCallback();
void testDeleteNodeRedlineCallback();
void testVisCursorInvalidation();
@@ -212,6 +214,7 @@ public:
CPPUNIT_TEST(testTdf115088);
CPPUNIT_TEST(testRedlineField);
CPPUNIT_TEST(testIMESupport);
+ CPPUNIT_TEST(testIMEFormattingAtEndOfParagraph);
CPPUNIT_TEST(testSplitNodeRedlineCallback);
CPPUNIT_TEST(testDeleteNodeRedlineCallback);
CPPUNIT_TEST(testVisCursorInvalidation);
@@ -2219,6 +2222,112 @@ void SwTiledRenderingTest::testIMESupport()
CPPUNIT_ASSERT_EQUAL(OUString(aInputs[aInputs.size() - 1] + "Aaa bbb."), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText());
}
+void SwTiledRenderingTest::testIMEFormattingAtEndOfParagraph()
+{
+ comphelper::LibreOfficeKit::setActive();
+ SwXTextDocument* pXTextDocument = createDoc("dummy.fodt");
+ VclPtr<vcl::Window> pDocWindow = pXTextDocument->getDocWindow();
+
+ SwView* pView = dynamic_cast<SwView*>(SfxViewShell::Current());
+ assert(pView);
+ SwWrtShell* pWrtShell = pView->GetWrtShellPtr();
+
+ // delete all characters
+
+ for (int i = 0; i < 9; i++)
+ {
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DELETE);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DELETE);
+ }
+
+ Scheduler::ProcessEventsToIdle();
+
+ pDocWindow->PostExtTextInputEvent(VclEventId::ExtTextInput, "a");
+ pDocWindow->PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
+
+ // status: "a"
+
+ comphelper::dispatchCommand(".uno:Bold", uno::Sequence<beans::PropertyValue>());
+ Scheduler::ProcessEventsToIdle();
+
+ pDocWindow->PostExtTextInputEvent(VclEventId::ExtTextInput, "b");
+ pDocWindow->PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
+
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_RETURN);
+ Scheduler::ProcessEventsToIdle();
+
+ // status: "a<bold>b</bold>\n"
+
+ pDocWindow->PostExtTextInputEvent(VclEventId::ExtTextInput, "a");
+ pDocWindow->PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
+
+ std::unique_ptr<SfxPoolItem> pItem;
+ pView->GetViewFrame()->GetBindings().QueryState(SID_ATTR_CHAR_WEIGHT, pItem);
+ auto pWeightItem = dynamic_cast<SvxWeightItem*>(pItem.get());
+ CPPUNIT_ASSERT(pWeightItem);
+
+ CPPUNIT_ASSERT_EQUAL(FontWeight::WEIGHT_BOLD, pWeightItem->GetWeight());
+
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN);
+ pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_RETURN);
+ Scheduler::ProcessEventsToIdle();
+
+ // status: "a<bold>b</bold>\n
+ // <bold>a</bold>\n"
+
+ comphelper::dispatchCommand(".uno:Bold", uno::Sequence<beans::PropertyValue>());
+ Scheduler::ProcessEventsToIdle();
+
+ pDocWindow->PostExtTextInputEvent(VclEventId::ExtTextInput, "b");
+ pDocWindow->PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
+
+ pView->GetViewFrame()->GetBindings().QueryState(SID_ATTR_CHAR_WEIGHT, pItem);
+ auto pWeightItem2 = dynamic_cast<SvxWeightItem*>(pItem.get());
+ CPPUNIT_ASSERT(pWeightItem2);
+
+ CPPUNIT_ASSERT_EQUAL(FontWeight::WEIGHT_NORMAL, pWeightItem2->GetWeight());
+
+ // status: "a<bold>b</bold>\n
+ // <bold>a</bold>\n"
+ // b"
+
+ comphelper::dispatchCommand(".uno:Bold", uno::Sequence<beans::PropertyValue>());
+ Scheduler::ProcessEventsToIdle();
+
+ pDocWindow->PostExtTextInputEvent(VclEventId::ExtTextInput, "a");
+ pDocWindow->PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
+
+ pView->GetViewFrame()->GetBindings().QueryState(SID_ATTR_CHAR_WEIGHT, pItem);
+ auto pWeightItem3 = dynamic_cast<SvxWeightItem*>(pItem.get());
+ CPPUNIT_ASSERT(pWeightItem3);
+
+ CPPUNIT_ASSERT_EQUAL(FontWeight::WEIGHT_BOLD, pWeightItem3->GetWeight());
+
+ comphelper::dispatchCommand(".uno:Bold", uno::Sequence<beans::PropertyValue>());
+ Scheduler::ProcessEventsToIdle();
+
+ pDocWindow->PostExtTextInputEvent(VclEventId::ExtTextInput, "b");
+ pDocWindow->PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
+
+ pView->GetViewFrame()->GetBindings().QueryState(SID_ATTR_CHAR_WEIGHT, pItem);
+ auto pWeightItem4 = dynamic_cast<SvxWeightItem*>(pItem.get());
+ CPPUNIT_ASSERT(pWeightItem4);
+
+ CPPUNIT_ASSERT_EQUAL(FontWeight::WEIGHT_NORMAL, pWeightItem4->GetWeight());
+
+ // status: "a<bold>b</bold>\n
+ // <bold>a</bold>\n"
+ // b<bold>a</bold>b"
+
+ // the cursor should be at position 3nd
+ SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), pShellCursor->GetPoint()->nContent.GetIndex());
+
+ // check the content
+ CPPUNIT_ASSERT_EQUAL(OUString("bab"), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText());
+}
+
void SwTiledRenderingTest::testSplitNodeRedlineCallback()
{
// Load a document.
diff --git a/sw/source/core/doc/extinput.cxx b/sw/source/core/doc/extinput.cxx
index 9ddcf0a935b8..5790126b1810 100644
--- a/sw/source/core/doc/extinput.cxx
+++ b/sw/source/core/doc/extinput.cxx
@@ -102,12 +102,23 @@ SwExtTextInput::~SwExtTextInput()
}
else
{
- pTNd->EraseText( rIdx, nEndCnt - nSttCnt );
+ // we need to keep correct formatting
+ // ie. when we erase first, then we will lost information about format
+ // so:
+ // 0. initial status: xxxx | OLD
+ // 1. insert new content using Doc interface at the end so we will use the same formatting
+ // status: xxxx | OLD | NEW
+ // 2. erase old content which is placed at "start" position and before recently inserted text
+ // status: xxxx | NEW
+
+ sal_Int32 nLenghtOfOldString = nEndCnt - nSttCnt;
if( m_bInsText )
{
rDoc.getIDocumentContentOperations().InsertString( *this, sText );
}
+
+ pTNd->EraseText( rIdx, nLenghtOfOldString );
}
rDoc.GetIDocumentUndoRedo().DoGroupUndo(bKeepGroupUndo);
if (m_eInputLanguage == LANGUAGE_DONTKNOW)