[Libreoffice-commits] core.git: Branch 'libreoffice-5-3' - sw/inc sw/qa sw/source

Michael Stahl mstahl at redhat.com
Tue May 16 09:56:29 UTC 2017


 sw/inc/swtypes.hxx                 |    6 +
 sw/qa/extras/uiwriter/uiwriter.cxx |  134 +++++++++++++++++++++++++++++++++++++
 sw/source/core/txtnode/thints.cxx  |    8 +-
 sw/source/core/undo/undobj1.cxx    |    2 
 4 files changed, 144 insertions(+), 6 deletions(-)

New commits:
commit 4820c9b981e060a55b3511272824dca7c2eb67d5
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed May 10 17:45:14 2017 +0200

    tdf#107512 sw: fix rollback of text attributes in SwUndoDelete
    
    The problem is that in SwUndoDelete::UndoImpl(), first the formatting
    attributes are restored via TmpRollback(), and then all footnote/fly
    attributes are restored via Rollback(). This means that the SwHistory
    doesn't actually store the original positions of the formatting hints;
    ideally there wouldn't be 2 separate steps here, but that appears
    difficult to change now given the plethora of calls to
    DelContentIndex() ...
    
    So work around the problem by adding a new SetAttrMode::NOHINTEXPAND
    to prevent expanding the existing hints when the CH_TXTATR_BREAKWORD
    are inserted from SwUndoDelLayFormat.
    
    This fixes 2 problematic cases: at the start of the paragraph,
    and if the hint ends at the position before the CH_TXTATR_BREAKWORD.
    
    Let's hope this won't break anything anybody cares about.
    
    (cherry picked from commit 771d85baf18e5b503eb6248e1f41928b00265d8d)
    
    sw: CPPUNIT_ASSERT_EQUAL vs. integer FAIL
    (cherry picked from commit 7f44ca113170a641a1aecc8a48e2b99860e1e2f7)
    
    Change-Id: I557c4c9136f4225ca502019730fb9f0a9c03d23b
    Reviewed-on: https://gerrit.libreoffice.org/37485
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/inc/swtypes.hxx b/sw/inc/swtypes.hxx
index 2c88e9fe99c9..d5114cd033c6 100644
--- a/sw/inc/swtypes.hxx
+++ b/sw/inc/swtypes.hxx
@@ -193,11 +193,13 @@ enum class SetAttrMode
     /// Force hint expand (only matters for hints with CH_TXTATR).
     FORCEHINTEXPAND = 0x0040,
     /// The inserted item is a copy -- intended for use in ndtxt.cxx.
-    IS_COPY         = 0x0080
+    IS_COPY         = 0x0080,
+    /// for Undo, translated to SwInsertFlags::NOHINTEXPAND
+    NOHINTEXPAND    = 0x0100,
 };
 namespace o3tl
 {
-    template<> struct typed_flags<SetAttrMode> : is_typed_flags<SetAttrMode, 0x0ff> {};
+    template<> struct typed_flags<SetAttrMode> : is_typed_flags<SetAttrMode, 0x1ff> {};
 }
 
 #define SW_ISPRINTABLE( c ) ( c >= ' ' && 127 != c )
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 0ba241259e31..d955e769e019 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -176,6 +176,7 @@ public:
     void testTableBackgroundColor();
     void testTdf88899();
     void testTdf90362();
+    void testUndoDelAsCharTdf107512();
     void testUndoCharAttribute();
     void testTdf86639();
     void testTdf90883TableBoxGetCoordinates();
@@ -290,6 +291,7 @@ public:
     CPPUNIT_TEST(testTableBackgroundColor);
     CPPUNIT_TEST(testTdf88899);
     CPPUNIT_TEST(testTdf90362);
+    CPPUNIT_TEST(testUndoDelAsCharTdf107512);
     CPPUNIT_TEST(testUndoCharAttribute);
     CPPUNIT_TEST(testTdf86639);
     CPPUNIT_TEST(testTdf90883TableBoxGetCoordinates);
@@ -3031,6 +3033,138 @@ void SwUiWriterTest::testTdf90362()
     CPPUNIT_ASSERT_EQUAL(false, pWrtShell->HasReadonlySel());
 }
 
+void SwUiWriterTest::testUndoDelAsCharTdf107512()
+{
+    SwDoc * pDoc(createDoc());
+    sw::UndoManager & rUndoManager(pDoc->GetUndoManager());
+    IDocumentContentOperations & rIDCO(pDoc->getIDocumentContentOperations());
+    SwCursorShell * pShell(pDoc->GetEditShell());
+    SfxItemSet frameSet(pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1);
+    SfxItemSet grfSet(pDoc->GetAttrPool(), RES_GRFATR_BEGIN, RES_GRFATR_END-1);
+    rIDCO.InsertString(*pShell->GetCursor(), "foo");
+    pShell->ClearMark();
+    SwFormatAnchor anchor(RndStdIds::FLY_AS_CHAR);
+    frameSet.Put(anchor);
+    GraphicObject grf;
+    pShell->SttEndDoc(true);
+    CPPUNIT_ASSERT(rIDCO.Insert(*pShell->GetCursor(), grf, &frameSet, &grfSet, nullptr));
+    pShell->SttEndDoc(false);
+    CPPUNIT_ASSERT(rIDCO.Insert(*pShell->GetCursor(), grf, &frameSet, &grfSet, nullptr));
+    CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+    SvxCharHiddenItem hidden(true, RES_CHRATR_HIDDEN);
+    pShell->SelectText(1, 4);
+    rIDCO.InsertPoolItem(*pShell->GetCursor(), hidden);
+    // now we have "\1foo\1" with the "foo" hidden
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT_EQUAL(OUString(OUStringLiteral1(CH_TXTATR_BREAKWORD) + "foo" + OUStringLiteral1(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+    SfxPoolItem const* pItem;
+    SfxItemSet query(pDoc->GetAttrPool(), RES_CHRATR_HIDDEN, RES_CHRATR_HIDDEN);
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 1, 4);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::SET == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+    query.ClearItem(RES_CHRATR_HIDDEN);
+
+    // delete from the start
+    pShell->SelectText(0, 4);
+    rIDCO.DeleteAndJoin(*pShell->GetCursor());
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 0, 1);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::DEFAULT == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    rUndoManager.Undo();
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+    CPPUNIT_ASSERT_EQUAL(OUString(OUStringLiteral1(CH_TXTATR_BREAKWORD) + "foo" + OUStringLiteral1(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 0, 1);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::DEFAULT == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 1, 4);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::SET == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    rUndoManager.Redo();
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 0, 1);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::DEFAULT == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    rUndoManager.Undo();
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+    CPPUNIT_ASSERT_EQUAL(OUString(OUStringLiteral1(CH_TXTATR_BREAKWORD) + "foo" + OUStringLiteral1(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 0, 1);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::DEFAULT == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 1, 4);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::SET == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+    query.ClearItem(RES_CHRATR_HIDDEN);
+
+    // delete from the end
+    pShell->SelectText(1, 5);
+    rIDCO.DeleteAndJoin(*pShell->GetCursor());
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 4, 5);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::DEFAULT == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    rUndoManager.Undo();
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+    CPPUNIT_ASSERT_EQUAL(OUString(OUStringLiteral1(CH_TXTATR_BREAKWORD) + "foo" + OUStringLiteral1(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 4, 5);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::DEFAULT == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 1, 4);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::SET == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    rUndoManager.Redo();
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 4, 5);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::DEFAULT == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    rUndoManager.Undo();
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(0, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT(pShell->GetCursor()->GetNode().GetTextNode()->GetTextAttrForCharAt(4, RES_TXTATR_FLYCNT));
+    CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pShell->GetCursor()->GetNode().GetTextNode()->Len());
+    CPPUNIT_ASSERT_EQUAL(OUString(OUStringLiteral1(CH_TXTATR_BREAKWORD) + "foo" + OUStringLiteral1(CH_TXTATR_BREAKWORD)), pShell->GetCursor()->GetNode().GetTextNode()->GetText());
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 4, 5);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::DEFAULT == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    query.ClearItem(RES_CHRATR_HIDDEN);
+    pShell->GetCursor()->GetNode().GetTextNode()->GetAttr(query, 1, 4);
+//    CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(SfxItemState::SET == query.GetItemState(RES_CHRATR_HIDDEN, false, &pItem));
+    CPPUNIT_ASSERT(static_cast<SvxCharHiddenItem const*>(pItem)->GetValue());
+    query.ClearItem(RES_CHRATR_HIDDEN);
+}
+
 void SwUiWriterTest::testUndoCharAttribute()
 {
     // Create a new empty Writer document
diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx
index b091b6fe920c..0e6f73fd5939 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -1251,9 +1251,11 @@ bool SwTextNode::InsertHint( SwTextAttr * const pAttr, const SetAttrMode nMode )
 
     // translate from SetAttrMode to InsertMode (for hints with CH_TXTATR)
     const SwInsertFlags nInsertFlags =
-        (nMode & SetAttrMode::FORCEHINTEXPAND)
-        ? (SwInsertFlags::FORCEHINTEXPAND | SwInsertFlags::EMPTYEXPAND)
-        : SwInsertFlags::EMPTYEXPAND;
+        (nMode & SetAttrMode::NOHINTEXPAND)
+        ? SwInsertFlags::NOHINTEXPAND
+        : (nMode & SetAttrMode::FORCEHINTEXPAND)
+            ? (SwInsertFlags::FORCEHINTEXPAND | SwInsertFlags::EMPTYEXPAND)
+            : SwInsertFlags::EMPTYEXPAND;
 
     // need this after TryInsertHint, when pAttr may be deleted
     const sal_Int32 nStart( pAttr->GetStart() );
diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx
index 2fcc24efc98e..ed97d013c904 100644
--- a/sw/source/core/undo/undobj1.cxx
+++ b/sw/source/core/undo/undobj1.cxx
@@ -114,7 +114,7 @@ void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrame)
         SwContentNode* pCNd = aAnchor.GetContentAnchor()->nNode.GetNode().GetContentNode();
         OSL_ENSURE( pCNd->IsTextNode(), "no Text Node at position." );
         SwFormatFlyCnt aFormat( pFrameFormat );
-        pCNd->GetTextNode()->InsertItem( aFormat, nCntPos, nCntPos );
+        pCNd->GetTextNode()->InsertItem(aFormat, nCntPos, nCntPos, SetAttrMode::NOHINTEXPAND);
     }
 
     pFrameFormat->MakeFrames();


More information about the Libreoffice-commits mailing list