sw/qa/core/unocore/unocore.cxx    |    9 ++
 sw/source/core/unocore/unoobj.cxx |  124 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+)

New commits:
commit 08bce8eeb2e18c7cea4108dbfc2519ada56e8b61
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Sep 16 09:12:43 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Sep 16 10:21:41 2022 +0200

    sw content controls: fix getString() and setString() on SwXContentControl
    
    The setter was broken, it inserted the new content at the start, but
    didn't delete the old content. The getter was also broken, it returned
    an empty string, even if the content control had a non-empty content.
    
    This was always a problem since c4268efef25129b162884312b15527f1e5c3bcb0
    (sw content controls: add UNO API to insert this, 2022-03-31) introduced
    SwXContentControl.
    
    Fix the problem by extending SwXTextCursor, so in case m_eType is
    CursorType::ContentControl, then it keeps the cursor's range inside the
    boundaries of the content control.
    
    This also allows changing the data binding code added in
    b5c616d10bff3213840d4893d13b4493de71fa56 (tdf#104823: support for sdt
    plain text fields, 2021-11-24) to use content controls, in a follow-up
    commit.
    
    Change-Id: Ic3ae47a4b26af090539d61035372f1784c8ffe3f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140040
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx
index a8075211d06c..86683e4e9506 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -345,6 +345,15 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlInsert)
         = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
     std::shared_ptr<SwContentControl> pContentControl = 
rFormatContentControl.GetContentControl();
     CPPUNIT_ASSERT(pContentControl->GetShowingPlaceHolder());
+
+    // Also verify that setText() and getText() works:
+    uno::Reference<text::XText> xContentControlText(xContentControl, 
uno::UNO_QUERY);
+    xContentControlText->setString("new");
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: new
+    // - Actual  :
+    // i.e. getString() always returned an empty string.
+    CPPUNIT_ASSERT_EQUAL(OUString("new"), xContentControlText->getString());
 }
 
 CPPUNIT_TEST_FIXTURE(SwModelTestBase, testImageTooltip)
diff --git a/sw/source/core/unocore/unoobj.cxx 
b/sw/source/core/unocore/unoobj.cxx
index 7974a7d3cd1b..c52d7c154785 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -746,6 +746,12 @@ namespace {
 
 enum ForceIntoMetaMode { META_CHECK_BOTH, META_INIT_START, META_INIT_END };
 
+enum ForceIntoContentControlMode
+{
+    CONTENT_CONTROL_CHECK_BOTH,
+    CONTENT_CONTROL_INIT_START,
+    CONTENT_CONTROL_INIT_END
+};
 }
 
 static bool
@@ -792,6 +798,61 @@ lcl_ForceIntoMeta(SwPaM & rCursor,
     return bRet;
 }
 
+namespace
+{
+bool lcl_ForceIntoContentControl(SwPaM& rCursor, const 
uno::Reference<text::XText>& xParentText,
+                                 ForceIntoContentControlMode eMode)
+{
+    bool bRet = true; // means not forced in CONTENT_CONTROL_CHECK_BOTH
+    auto pXContentControl = 
dynamic_cast<SwXContentControl*>(xParentText.get());
+    if (!pXContentControl)
+    {
+        SAL_WARN("sw.core", "lcl_ForceIntoContentControl: no parent text");
+        throw uno::RuntimeException();
+    }
+
+    SwTextNode* pTextNode;
+    sal_Int32 nStart;
+    sal_Int32 nEnd;
+    bool bSuccess = pXContentControl->SetContentRange(pTextNode, nStart, nEnd);
+    if (!bSuccess)
+    {
+        SAL_WARN("sw.core", "lcl_ForceIntoContentControl: SetContentRange() 
failed");
+        throw uno::RuntimeException();
+    }
+
+    // Force the cursor back into the content control if it has moved outside.
+    SwPosition aStart(*pTextNode, nStart);
+    SwPosition aEnd(*pTextNode, nEnd);
+    switch (eMode)
+    {
+        case CONTENT_CONTROL_INIT_START:
+            *rCursor.GetPoint() = aStart;
+            break;
+
+        case CONTENT_CONTROL_INIT_END:
+            *rCursor.GetPoint() = aEnd;
+            break;
+
+        case CONTENT_CONTROL_CHECK_BOTH:
+            if (*rCursor.Start() < aStart)
+            {
+                *rCursor.Start() = aStart;
+                bRet = false;
+            }
+
+            if (*rCursor.End() > aEnd)
+            {
+                *rCursor.End() = aEnd;
+                bRet = false;
+            }
+            break;
+    }
+
+    return bRet;
+}
+}
+
 bool SwXTextCursor::IsAtEndOfMeta() const
 {
     if (CursorType::Meta == m_eType)
@@ -956,6 +1017,11 @@ SwXTextCursor::goLeft(sal_Int16 nCount, sal_Bool Expand)
                     META_CHECK_BOTH)
             && bRet;
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH)
+               && bRet;
+    }
     return bRet;
 }
 
@@ -974,6 +1040,11 @@ SwXTextCursor::goRight(sal_Int16 nCount, sal_Bool Expand)
                     META_CHECK_BOTH)
             && bRet;
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH)
+               && bRet;
+    }
     return bRet;
 }
 
@@ -1023,6 +1094,10 @@ SwXTextCursor::gotoStart(sal_Bool Expand)
     {
         lcl_ForceIntoMeta(rUnoCursor, m_xParentText, META_INIT_START);
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_INIT_START);
+    }
 }
 
 void SAL_CALL
@@ -1051,6 +1126,10 @@ SwXTextCursor::gotoEnd(sal_Bool Expand)
     {
         lcl_ForceIntoMeta(rUnoCursor, m_xParentText, META_INIT_END);
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_INIT_END);
+    }
 }
 
 void SAL_CALL
@@ -1158,6 +1237,15 @@ SwXTextCursor::gotoRange(
                 static_cast<text::XWordCursor*>(this));
         }
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        SwPaM aPaM(*pPam->GetMark(), *pPam->GetPoint());
+        if (!lcl_ForceIntoContentControl(aPaM, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH))
+        {
+            throw uno::RuntimeException("gotoRange: xRange is out of bounds of 
the content control",
+                                        static_cast<text::XWordCursor*>(this));
+        }
+    }
 
     // selection has to be expanded here
     if(bExpand)
@@ -1261,6 +1349,10 @@ SwXTextCursor::gotoNextWord(sal_Bool Expand)
         bRet = lcl_ForceIntoMeta(rUnoCursor, m_xParentText,
                     META_CHECK_BOTH);
     }
+    else if (bRet && m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH);
+    }
 
     return bRet;
 }
@@ -1301,6 +1393,10 @@ SwXTextCursor::gotoPreviousWord(sal_Bool Expand)
         bRet = lcl_ForceIntoMeta(rUnoCursor, m_xParentText,
                     META_CHECK_BOTH);
     }
+    else if (bRet && m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH);
+    }
 
     return bRet;
 }
@@ -1336,6 +1432,10 @@ SwXTextCursor::gotoEndOfWord(sal_Bool Expand)
         bRet = lcl_ForceIntoMeta(rUnoCursor, m_xParentText,
                     META_CHECK_BOTH);
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH);
+    }
 
     return bRet;
 }
@@ -1371,6 +1471,10 @@ SwXTextCursor::gotoStartOfWord(sal_Bool Expand)
         bRet = lcl_ForceIntoMeta(rUnoCursor, m_xParentText,
                     META_CHECK_BOTH);
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH);
+    }
 
     return bRet;
 }
@@ -1454,6 +1558,11 @@ SwXTextCursor::gotoNextSentence(sal_Bool Expand)
                     META_CHECK_BOTH)
             && bRet;
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH)
+               && bRet;
+    }
     return bRet;
 }
 
@@ -1482,6 +1591,11 @@ SwXTextCursor::gotoPreviousSentence(sal_Bool Expand)
                     META_CHECK_BOTH)
             && bRet;
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH)
+               && bRet;
+    }
     return bRet;
 }
 
@@ -1505,6 +1619,11 @@ SwXTextCursor::gotoStartOfSentence(sal_Bool Expand)
                     META_CHECK_BOTH)
             && bRet;
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH)
+               && bRet;
+    }
     return bRet;
 }
 
@@ -1529,6 +1648,11 @@ SwXTextCursor::gotoEndOfSentence(sal_Bool Expand)
                     META_CHECK_BOTH)
             && bRet;
     }
+    else if (m_eType == CursorType::ContentControl)
+    {
+        bRet = lcl_ForceIntoContentControl(rUnoCursor, m_xParentText, 
CONTENT_CONTROL_CHECK_BOTH)
+               && bRet;
+    }
     return bRet;
 }
 

Reply via email to