sw/qa/extras/tiledrendering/tiledrendering.cxx |  109 +++++++++++++++++++++++++
 sw/source/core/doc/extinput.cxx                |   13 ++
 2 files changed, 121 insertions(+), 1 deletion(-)

New commits:
commit bf96d1f23e5c12f9263643dfdab94fd1361bb098
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Tue Sep 7 12:54:56 2021 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Sep 15 08:45:39 2021 +0200

    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.k...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121774
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx 
b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index 3a79210430b0..4994797328b8 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -26,6 +26,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>
@@ -118,6 +119,7 @@ public:
     void testTdf115088();
     void testRedlineField();
     void testIMESupport();
+    void testIMEFormattingAtEndOfParagraph();
     void testSplitNodeRedlineCallback();
     void testDeleteNodeRedlineCallback();
     void testVisCursorInvalidation();
@@ -193,6 +195,7 @@ public:
     CPPUNIT_TEST(testTdf115088);
     CPPUNIT_TEST(testRedlineField);
     CPPUNIT_TEST(testIMESupport);
+    CPPUNIT_TEST(testIMEFormattingAtEndOfParagraph);
     CPPUNIT_TEST(testSplitNodeRedlineCallback);
     CPPUNIT_TEST(testDeleteNodeRedlineCallback);
     CPPUNIT_TEST(testVisCursorInvalidation);
@@ -2245,6 +2248,112 @@ void SwTiledRenderingTest::testIMESupport()
     CPPUNIT_ASSERT_EQUAL(aInputs[aInputs.size() - 1].concat("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 e9076064a745..4795862e9e1a 100644
--- a/sw/source/core/doc/extinput.cxx
+++ b/sw/source/core/doc/extinput.cxx
@@ -100,12 +100,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( bInsText )
                 {
                     pDoc->getIDocumentContentOperations().InsertString( *this, 
sText );
                 }
+
+                pTNd->EraseText( rIdx, nLenghtOfOldString );
             }
             pDoc->GetIDocumentUndoRedo().DoGroupUndo(bKeepGroupUndo);
             if (eInputLanguage != LANGUAGE_DONTKNOW)

Reply via email to