sw/qa/extras/globalfilter/globalfilter.cxx        |  276 +++++++++++++++-------
 sw/qa/extras/ooxmlexport/ooxmlexport13.cxx        |   97 ++-----
 sw/qa/extras/ooxmlexport/ooxmlexport8.cxx         |   54 +++-
 sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx     |  136 ++++++++--
 sw/qa/extras/ooxmlimport/ooxmlimport2.cxx         |   42 +--
 sw/source/filter/ww8/docxattributeoutput.cxx      |    2 
 writerfilter/source/dmapper/DomainMapper.cxx      |   35 ++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   50 +++
 writerfilter/source/dmapper/SdtHelper.cxx         |   11 
 writerfilter/source/dmapper/SdtHelper.hxx         |   17 +
 10 files changed, 495 insertions(+), 225 deletions(-)

New commits:
commit 5ee8670f18cb8b1913a23d04590d6a31ac9730de
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon May 30 09:00:25 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon May 30 09:36:51 2022 +0200

    sw content controls, date: add DOCX import
    
    - map
                  <w:date>
                    <w:dateFormat w:val="..."/>
                    <w:lid w:val="..."/>
                  </w:date>
      to the Date, DateFormat and DateLanguage UNO properties of content
      controls instead of fieldmarks, which model content controls poorly
    
    - fix CppunitTest_sw_ooxmlexport8's testN820509: date SDT is now a
      content control
    
    - add current date DOCX import
    
    - fix CppunitTest_sw_ooxmlexport13's testDateControl: date SDT is now a
      content control
    
    - fix CppunitTest_sw_ooxmlexport13's testInvalidDateFormField: date SDT
      is now a content control
    
    - fix CppunitTest_sw_ooxmlexport5's testfdo83048: minimal support for
      nested SDTs in DomainMapper::lcl_attribute()
    
    - fix CppunitTest_sw_ooxmlfieldexport's testDateFieldAtEndOfParagraph:
      date SDT is now a content control
    
    - fix CppunitTest_sw_ooxmlfieldexport's testDateFieldInShape: date SDT
      is now a content control
    
    - fix CppunitTest_sw_ooxmlfieldexport's testSdtDateDuplicate: date SDT
      is now a content control
    
    - fix CppunitTest_sw_ooxmlfieldexport's testSdtDatePicker:
    
      - retain placeholder
    
      - retain data binding
    
      - retain color
    
    - fix CppunitTest_sw_ooxmlimport2's testTdf121203: date SDT is now a
      content control
    
    - fix CppunitTest_sw_globalfilter's
      testDateFormFieldCharacterFormatting: date SDT is now a content control
    
    - fix CppunitTest_sw_globalfilter's testDateFormField: date SDT is now a
      content control
    
    Change-Id: I5a4c34217d23ed6fa0916e4dd6290351456b7232
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135109
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx 
b/sw/qa/extras/globalfilter/globalfilter.cxx
index ae720f503f56..ebe5abb81804 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -1650,92 +1650,170 @@ void Test::testDateFormField()
         mxComponent = loadFromDesktop(aTempFile.GetURL(), 
"com.sun.star.text.TextDocument");
 
         // Check the document after round trip
-        SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
-        CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
-        SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
-        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(5), 
pMarkAccess->getAllMarksCount());
-
-        int nIndex = 0;
-        for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != 
pMarkAccess->getAllMarksEnd(); ++aIter)
+        if (rFilterName == "writer8")
         {
-            ::sw::mark::IDateFieldmark* pFieldmark = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
-            CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
-            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+            SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
+            CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+            SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+            IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
 
-            // Check date form field's parameters.
-            const sw::mark::IFieldmark::parameter_map_t* const pParameters = 
pFieldmark->GetParameters();
-            OUString sDateFormat;
-            auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
-            if (pResult != pParameters->end())
-            {
-                pResult->second >>= sDateFormat;
-            }
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(5), pMarkAccess->getAllMarksCount());
 
-            OUString sLang;
-            pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
-            if (pResult != pParameters->end())
+            int nIndex = 0;
+            for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != 
pMarkAccess->getAllMarksEnd(); ++aIter)
             {
-                pResult->second >>= sLang;
-            }
+                ::sw::mark::IDateFieldmark* pFieldmark = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
+                CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+
+                // Check date form field's parameters.
+                const sw::mark::IFieldmark::parameter_map_t* const pParameters 
= pFieldmark->GetParameters();
+                OUString sDateFormat;
+                auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
+                if (pResult != pParameters->end())
+                {
+                    pResult->second >>= sDateFormat;
+                }
 
-            OUString sCurrentDate = pFieldmark->GetContent();
+                OUString sLang;
+                pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
+                if (pResult != pParameters->end())
+                {
+                    pResult->second >>= sLang;
+                }
 
-            // The first one has the default field content
-            if(nIndex == 0)
-            {
+                OUString sCurrentDate = pFieldmark->GetContent();
 
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("MM/DD/YY"), sDateFormat);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("en-US"), sLang);
-                sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 
8194, 8194, 8194, 8194};
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(vEnSpaces, 5), sCurrentDate);
+                // The first one has the default field content
+                if(nIndex == 0)
+                {
 
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(5), pFieldmark->GetMarkStart().nContent.GetIndex());
-            }
-            else if (nIndex == 1) // The second has the default format
-            {
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("MM/DD/YY"), sDateFormat);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("en-US"), sLang);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("06/12/19"), sCurrentDate);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("MM/DD/YY"), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("en-US"), sLang);
+                    sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = 
{8194, 8194, 8194, 8194, 8194};
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(vEnSpaces, 5), sCurrentDate);
 
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(20), pFieldmark->GetMarkStart().nContent.GetIndex());
-            }
-            else if (nIndex == 2) // The third one has special format
-            {
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("[NatNum12 MMMM=abbreviation]YYYY\". \"MMMM D."), sDateFormat);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("hu-HU"), sLang);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("2019. febr. 12."), sCurrentDate);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(5), pFieldmark->GetMarkStart().nContent.GetIndex());
+                }
+                else if (nIndex == 1) // The second has the default format
+                {
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("MM/DD/YY"), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("en-US"), sLang);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("06/12/19"), sCurrentDate);
+
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(20), pFieldmark->GetMarkStart().nContent.GetIndex());
+                }
+                else if (nIndex == 2) // The third one has special format
+                {
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("[NatNum12 MMMM=abbreviation]YYYY\". \"MMMM D."), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("hu-HU"), sLang);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("2019. febr. 12."), sCurrentDate);
 
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(40), pFieldmark->GetMarkStart().nContent.GetIndex());
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(40), pFieldmark->GetMarkStart().nContent.GetIndex());
 
-            }
-            else if (nIndex == 3) // The fourth one has placeholder text
-            {
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("D, MMM YY"), sDateFormat);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("bm-ML"), sLang);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("[select date]"), sCurrentDate);
+                }
+                else if (nIndex == 3) // The fourth one has placeholder text
+                {
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("D, MMM YY"), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("bm-ML"), sLang);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("[select date]"), sCurrentDate);
+
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(62), pFieldmark->GetMarkStart().nContent.GetIndex());
 
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(62), pFieldmark->GetMarkStart().nContent.GetIndex());
+                }
+                else // The last one is really empty
+                {
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("MM/DD/YY"), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("en-US"), sLang);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(""), sCurrentDate);
 
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(82), pFieldmark->GetMarkStart().nContent.GetIndex());
+
+                }
+                ++nIndex;
             }
-            else // The last one is really empty
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(5), 
nIndex);
+        }
+        else
+        {
+            // Import from DOCX, so the fieldmark is now a content control.
+            uno::Reference<container::XEnumerationAccess> 
xEnumAccess(getParagraph(1), uno::UNO_QUERY);
+            uno::Reference<container::XEnumeration> xTextPortions = 
xEnumAccess->createEnumeration();
+
+            int nIndex = 0;
+            while (xTextPortions->hasMoreElements())
             {
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("MM/DD/YY"), sDateFormat);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("en-US"), sLang);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(""), sCurrentDate);
+                uno::Reference<beans::XPropertySet> 
xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY);
+                OUString aPortionType;
+                xTextPortion->getPropertyValue("TextPortionType") >>= 
aPortionType;
+                if (aPortionType != "ContentControl")
+                {
+                    continue;
+                }
 
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
SwNodeOffset(9), pFieldmark->GetMarkStart().nNode.GetIndex());
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(82), pFieldmark->GetMarkStart().nContent.GetIndex());
+                uno::Reference<text::XTextContent> xContentControl;
+                xTextPortion->getPropertyValue("ContentControl") >>= 
xContentControl;
+                uno::Reference<beans::XPropertySet> 
xContentControlProps(xContentControl, uno::UNO_QUERY);
 
+                bool bDate{};
+                xContentControlProps->getPropertyValue("Date") >>= bDate;
+                CPPUNIT_ASSERT(bDate);
+
+                // Check date form field's parameters.
+                OUString sDateFormat;
+                xContentControlProps->getPropertyValue("DateFormat") >>= 
sDateFormat;
+
+                OUString sLang;
+                xContentControlProps->getPropertyValue("DateLanguage") >>= 
sLang;
+
+                uno::Reference<container::XEnumerationAccess> 
xContentControlEnumAccess(xContentControl,
+                        uno::UNO_QUERY);
+                uno::Reference<container::XEnumeration> xContentControlEnum
+                    = xContentControlEnumAccess->createEnumeration();
+                uno::Reference<text::XTextRange> 
xContentControlTextPortion(xContentControlEnum->nextElement(), uno::UNO_QUERY);
+                OUString sCurrentDate = 
xContentControlTextPortion->getString();
+
+                // The first one has the default field content
+                if(nIndex == 0)
+                {
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("MM/DD/YY"), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("en-US"), sLang);
+                    sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = 
{8194, 8194, 8194, 8194, 8194};
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(vEnSpaces, 5), sCurrentDate);
+                }
+                else if (nIndex == 1) // The second has the default format
+                {
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("MM/DD/YY"), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("en-US"), sLang);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("06/12/19"), sCurrentDate);
+                }
+                else if (nIndex == 2) // The third one has special format
+                {
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("[NatNum12 MMMM=abbreviation]YYYY\". \"MMMM D."), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("hu-HU"), sLang);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("2019. febr. 12."), sCurrentDate);
+                }
+                else if (nIndex == 3) // The fourth one has placeholder text
+                {
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("D, MMM YY"), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("bm-ML"), sLang);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("[select date]"), sCurrentDate);
+                }
+                else // The last one is really empty
+                {
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("MM/DD/YY"), sDateFormat);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString("en-US"), sLang);
+                    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(""), sCurrentDate);
+                }
+                ++nIndex;
             }
-            ++nIndex;
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(5), 
nIndex);
         }
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(5), nIndex);
     }
 }
 
@@ -1766,24 +1844,52 @@ void Test::testDateFormFieldCharacterFormatting()
         mxComponent = loadFromDesktop(aTempFile.GetURL(), 
"com.sun.star.text.TextDocument");
 
         // Check the document after round trip
-        SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
-        CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
-        SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
-        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-
-        // Check that we have the field at the right place
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(1), 
pMarkAccess->getAllMarksCount());
-        ::sw::mark::IDateFieldmark* pFieldmark = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
-        CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(0), 
pFieldmark->GetMarkStart().nContent.GetIndex());
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(11), 
pFieldmark->GetMarkEnd().nContent.GetIndex());
-
-        // We have one date field, first half of the field has bold character 
weight and second part has red character color
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
awt::FontWeight::BOLD, getProperty<float>(getRun(getParagraph(1), 3), 
"CharWeight"));
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_AUTO, 
getProperty<Color>(getRun(getParagraph(1), 3), "CharColor"));
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
awt::FontWeight::NORMAL, getProperty<float>(getRun(getParagraph(1), 4), 
"CharWeight"));
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), Color(0xff0000), 
getProperty<Color>(getRun(getParagraph(1), 4), "CharColor"));
+        if (rFilterName == "writer8")
+        {
+            SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
+            CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+            SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+            IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+            // Check that we have the field at the right place
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(1), pMarkAccess->getAllMarksCount());
+            ::sw::mark::IDateFieldmark* pFieldmark = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
+            CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(0), pFieldmark->GetMarkStart().nContent.GetIndex());
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
sal_Int32(11), pFieldmark->GetMarkEnd().nContent.GetIndex());
+
+            // We have one date field, first half of the field has bold 
character weight and second part has red character color
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
awt::FontWeight::BOLD, getProperty<float>(getRun(getParagraph(1), 3), 
"CharWeight"));
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_AUTO, 
getProperty<Color>(getRun(getParagraph(1), 3), "CharColor"));
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
awt::FontWeight::NORMAL, getProperty<float>(getRun(getParagraph(1), 4), 
"CharWeight"));
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
Color(0xff0000), getProperty<Color>(getRun(getParagraph(1), 4), "CharColor"));
+        }
+        else
+        {
+            uno::Reference<beans::XPropertySet> 
xTextPortion(getRun(getParagraph(1), 1), uno::UNO_QUERY);
+            OUString aPortionType;
+            xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+            CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
+
+            uno::Reference<text::XTextContent> xContentControl;
+            xTextPortion->getPropertyValue("ContentControl") >>= 
xContentControl;
+            uno::Reference<beans::XPropertySet> 
xContentControlProps(xContentControl, uno::UNO_QUERY);
+            bool bDate{};
+            xContentControlProps->getPropertyValue("Date") >>= bDate;
+            CPPUNIT_ASSERT(bDate);
+
+            uno::Reference<container::XEnumerationAccess> 
xContentControlEnumAccess(xContentControl,
+                                                                               
     uno::UNO_QUERY);
+            uno::Reference<container::XEnumeration> xContentControlEnum
+                = xContentControlEnumAccess->createEnumeration();
+            xTextPortion.set(xContentControlEnum->nextElement(), 
uno::UNO_QUERY);
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
awt::FontWeight::BOLD, getProperty<float>(xTextPortion, "CharWeight"));
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_AUTO, 
getProperty<Color>(xTextPortion, "CharColor"));
+            xTextPortion.set(xContentControlEnum->nextElement(), 
uno::UNO_QUERY);
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
awt::FontWeight::NORMAL, getProperty<float>(xTextPortion, "CharWeight"));
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 
Color(0xff0000), getProperty<Color>(xTextPortion, "CharColor"));
+        }
     }
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index 0435f4254f1b..e3525b5991ab 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -528,39 +528,25 @@ CPPUNIT_TEST_FIXTURE(Test, testDateControl)
     // Check that we exported the empty date control correctly
     // Date form field is converted to date content control.
 
-    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
-    CPPUNIT_ASSERT(pTextDoc);
-    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
-    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-
+    uno::Reference<beans::XPropertySet> xTextPortion(getRun(getParagraph(1), 
1), uno::UNO_QUERY);
+    OUString aPortionType;
+    xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+    CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
+    uno::Reference<text::XTextContent> xContentControl;
+    xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
+    uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, 
uno::UNO_QUERY);
+    bool bDate{};
+    xContentControlProps->getPropertyValue("Date") >>= bDate;
+    CPPUNIT_ASSERT(bDate);
 
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
-    ::sw::mark::IFieldmark* pFieldmark = 
dynamic_cast<::sw::mark::IFieldmark*>(*pMarkAccess->getAllMarksBegin());
-
-    CPPUNIT_ASSERT(pFieldmark);
-    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
-
-    const sw::mark::IFieldmark::parameter_map_t* const pParameters = 
pFieldmark->GetParameters();
     OUString sDateFormat;
-    auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
-    if (pResult != pParameters->end())
-    {
-        pResult->second >>= sDateFormat;
-    }
+    xContentControlProps->getPropertyValue("DateFormat") >>= sDateFormat;
 
     OUString sLang;
-    pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
-    if (pResult != pParameters->end())
-    {
-        pResult->second >>= sLang;
-    }
+    xContentControlProps->getPropertyValue("DateLanguage") >>= sLang;
 
     OUString sCurrentDate;
-    pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
-    if (pResult != pParameters->end())
-    {
-        pResult->second >>= sCurrentDate;
-    }
+    xContentControlProps->getPropertyValue("CurrentDate") >>= sCurrentDate;
 
     CPPUNIT_ASSERT_EQUAL(OUString("dd/MM/yyyy"), sDateFormat);
     CPPUNIT_ASSERT_EQUAL(OUString("en-US"), sLang);
@@ -1033,45 +1019,36 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf121663)
 DECLARE_OOXMLEXPORT_TEST(testInvalidDateFormField, 
"invalid_date_form_field.docx")
 {
 
-    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
-    CPPUNIT_ASSERT(pTextDoc);
-    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
-    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pMarkAccess->getAllMarksCount());
+    uno::Reference<container::XEnumerationAccess> xParagraph(getParagraph(1), 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xPortions = 
xParagraph->createEnumeration();
 
     int nIndex = 0;
-    for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != 
pMarkAccess->getAllMarksEnd(); ++aIter)
+    while (xPortions->hasMoreElements())
     {
-        ::sw::mark::IFieldmark* pFieldmark = 
dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
-
-        if(!pFieldmark)
+        uno::Reference<beans::XPropertySet> 
xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
+        OUString aPortionType;
+        xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+        if (aPortionType != "ContentControl")
+        {
             continue;
+        }
 
-        CPPUNIT_ASSERT(pFieldmark);
-        CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), 
pFieldmark->GetFieldname());
+        uno::Reference<text::XTextContent> xContentControl;
+        xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
+        uno::Reference<beans::XPropertySet> 
xContentControlProps(xContentControl, uno::UNO_QUERY);
+        bool bDate{};
+        xContentControlProps->getPropertyValue("Date") >>= bDate;
+        CPPUNIT_ASSERT(bDate);
 
-        // Check date field's parameters.
-        const sw::mark::IFieldmark::parameter_map_t* const pParameters = 
pFieldmark->GetParameters();
+        // Check date content control's parameters.
         OUString sDateFormat;
-        auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
-        if (pResult != pParameters->end())
-        {
-            pResult->second >>= sDateFormat;
-        }
+        xContentControlProps->getPropertyValue("DateFormat") >>= sDateFormat;
 
         OUString sLang;
-        pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
-        if (pResult != pParameters->end())
-        {
-            pResult->second >>= sLang;
-        }
+        xContentControlProps->getPropertyValue("DateLanguage") >>= sLang;
 
         OUString sCurrentDate;
-        pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
-        if (pResult != pParameters->end())
-        {
-            pResult->second >>= sCurrentDate;
-        }
+        xContentControlProps->getPropertyValue("CurrentDate") >>= sCurrentDate;
 
         // The first one has invalid date format (invalid = LO can't parse it)
         if(nIndex == 0)
@@ -1081,26 +1058,20 @@ DECLARE_OOXMLEXPORT_TEST(testInvalidDateFormField, 
"invalid_date_form_field.docx
             CPPUNIT_ASSERT_EQUAL(OUString("en-US"), sLang);
             CPPUNIT_ASSERT_EQUAL(OUString(""), sCurrentDate);
 
-            CPPUNIT_ASSERT_EQUAL(SwNodeOffset(9), 
pFieldmark->GetMarkStart().nNode.GetIndex());
-            CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pFieldmark->GetMarkStart().nContent.GetIndex());
         }
         else if (nIndex == 1) // The second has wrong date
         {
             CPPUNIT_ASSERT_EQUAL(OUString("MM/DD/YY"), sDateFormat);
             CPPUNIT_ASSERT_EQUAL(OUString("en-US"), sLang);
-            CPPUNIT_ASSERT_EQUAL(OUString("2019.06.34"), sCurrentDate);
+            CPPUNIT_ASSERT_EQUAL(OUString("2019.06.34T00:00:00Z"), 
sCurrentDate);
 
-            CPPUNIT_ASSERT_EQUAL(SwNodeOffset(9), 
pFieldmark->GetMarkStart().nNode.GetIndex());
-            CPPUNIT_ASSERT_EQUAL(sal_Int32(15), 
pFieldmark->GetMarkStart().nContent.GetIndex());
         }
         else // The third one has wrong local
         {
             CPPUNIT_ASSERT_EQUAL(OUString("[NatNum12 MMMM=abbreviation]YYYY\". 
\"MMMM D."), sDateFormat);
             CPPUNIT_ASSERT_EQUAL(OUString("xxxx"), sLang);
-            CPPUNIT_ASSERT_EQUAL(OUString("2019.06.11"), sCurrentDate);
+            CPPUNIT_ASSERT_EQUAL(OUString("2019.06.11T00:00:00Z"), 
sCurrentDate);
 
-            CPPUNIT_ASSERT_EQUAL(SwNodeOffset(9), 
pFieldmark->GetMarkStart().nNode.GetIndex());
-            CPPUNIT_ASSERT_EQUAL(sal_Int32(35), 
pFieldmark->GetMarkStart().nContent.GetIndex());
         }
         ++nIndex;
     }
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
index b52c25c01544..62c754af3d0f 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
@@ -999,23 +999,51 @@ DECLARE_OOXMLEXPORT_TEST(testN820509, "n820509.docx")
     // M.d.yyyy date format was unhandled.
     SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
     CPPUNIT_ASSERT(pTextDoc);
-    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
-    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getAllMarksCount());
+    if (mbExported)
+    {
+        uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+        uno::Reference<container::XIndexAccess> 
xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
+        uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), 
uno::UNO_QUERY);
+        uno::Reference<table::XCell> xCell = xTable->getCellByName("A1");
+        uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xCell, 
uno::UNO_QUERY);
+        uno::Reference<container::XEnumeration> xParagraphs = 
xParagraphsAccess->createEnumeration();
+        uno::Reference<container::XEnumerationAccess> 
xParagraph(xParagraphs->nextElement(),
+                                                             uno::UNO_QUERY);
+        uno::Reference<container::XEnumeration> xPortions = 
xParagraph->createEnumeration();
+        uno::Reference<beans::XPropertySet> 
xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
+        OUString aPortionType;
+        xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+        CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
+        uno::Reference<text::XTextContent> xContentControl;
+        xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
+        uno::Reference<beans::XPropertySet> 
xContentControlProps(xContentControl, uno::UNO_QUERY);
+        bool bDate{};
+        xContentControlProps->getPropertyValue("Date") >>= bDate;
+        CPPUNIT_ASSERT(bDate);
+        OUString aDateFormat;
+        xContentControlProps->getPropertyValue("DateFormat") >>= aDateFormat;
+        CPPUNIT_ASSERT_EQUAL(OUString("M.d.yyyy"), aDateFormat);
+    }
+    else
+    {
+        SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getAllMarksCount());
 
-    ::sw::mark::IFieldmark* pFieldmark = 
dynamic_cast<::sw::mark::IFieldmark*>(*pMarkAccess->getAllMarksBegin());
+        ::sw::mark::IFieldmark* pFieldmark = 
dynamic_cast<::sw::mark::IFieldmark*>(*pMarkAccess->getAllMarksBegin());
 
-    CPPUNIT_ASSERT(pFieldmark);
-    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+        CPPUNIT_ASSERT(pFieldmark);
+        CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), 
pFieldmark->GetFieldname());
 
-    const sw::mark::IFieldmark::parameter_map_t* const pParameters = 
pFieldmark->GetParameters();
-    OUString sDateFormat;
-    auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
-    if (pResult != pParameters->end())
-    {
-        pResult->second >>= sDateFormat;
+        const sw::mark::IFieldmark::parameter_map_t* const pParameters = 
pFieldmark->GetParameters();
+        OUString sDateFormat;
+        auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
+        if (pResult != pParameters->end())
+        {
+            pResult->second >>= sDateFormat;
+        }
+        CPPUNIT_ASSERT_EQUAL(OUString("M.d.yyyy"), sDateFormat);
     }
-    CPPUNIT_ASSERT_EQUAL(OUString("M.d.yyyy"), sDateFormat);
 }
 
 DECLARE_OOXMLEXPORT_TEST(testN830205, "n830205.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
index a630c00d1b71..d5fd1691c2a3 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
@@ -11,6 +11,7 @@
 
 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
 #include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/text/XTextTable.hpp>
 
 #include <xmloff/odffields.hxx>
 #include <o3tl/string_view.hxx>
@@ -496,19 +497,44 @@ DECLARE_OOXMLEXPORT_TEST(testSdtDateDuplicate, 
"sdt-date-duplicate.docx")
     {
         // Single <w:sdt> was exported as 2 <w:sdt> elements.
         assertXPath(pXmlDoc, "//w:sdt", 1);
+        uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+        uno::Reference<container::XIndexAccess> 
xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
+        uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), 
uno::UNO_QUERY);
+        uno::Reference<table::XCell> xCell = xTable->getCellByName("A1");
+        uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xCell, 
uno::UNO_QUERY);
+        uno::Reference<container::XEnumeration> xParagraphs = 
xParagraphsAccess->createEnumeration();
+        uno::Reference<container::XEnumerationAccess> 
xParagraph(xParagraphs->nextElement(),
+                                                             uno::UNO_QUERY);
+        uno::Reference<container::XEnumeration> xPortions = 
xParagraph->createEnumeration();
+        uno::Reference<beans::XPropertySet> 
xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
+        OUString aPortionType;
+        xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+        CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
+        uno::Reference<text::XTextContent> xContentControl;
+        xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
+        uno::Reference<beans::XPropertySet> 
xContentControlProps(xContentControl, uno::UNO_QUERY);
+        bool bDate{};
+        xContentControlProps->getPropertyValue("Date") >>= bDate;
+        CPPUNIT_ASSERT(bDate);
+        uno::Reference<container::XEnumerationAccess> 
xContentControlEnumAccess(xContentControl, uno::UNO_QUERY);
+        uno::Reference<container::XEnumeration> xContentControlEnum = 
xContentControlEnumAccess->createEnumeration();
+        uno::Reference<text::XTextRange> 
xTextPortionRange(xContentControlEnum->nextElement(), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(OUString("4/26/2012"), 
xTextPortionRange->getString());
+    }
+    else
+    {
+        SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
+        CPPUNIT_ASSERT(pTextDoc);
+        SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+        ::sw::mark::IDateFieldmark* pFieldmark
+            = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
+        CPPUNIT_ASSERT(pFieldmark);
+        CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), 
pFieldmark->GetFieldname());
+        CPPUNIT_ASSERT_EQUAL(OUString("4/26/2012"), pFieldmark->GetContent());
     }
-
-    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
-    CPPUNIT_ASSERT(pTextDoc);
-    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
-    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getAllMarksCount());
-
-    ::sw::mark::IDateFieldmark* pFieldmark
-          = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
-    CPPUNIT_ASSERT(pFieldmark);
-    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
-    CPPUNIT_ASSERT_EQUAL(OUString("4/26/2012"), pFieldmark->GetContent());
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testFdo81492)
@@ -670,33 +696,75 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf66401)
 DECLARE_OOXMLEXPORT_TEST( testDateFieldInShape, "date_field_in_shape.docx" )
 {
     // This was crashed on export.
-    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
-    CPPUNIT_ASSERT(pTextDoc);
-    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
-    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getAllMarksCount());
-
-    ::sw::mark::IDateFieldmark* pFieldmark
-          = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
-    CPPUNIT_ASSERT(pFieldmark);
-    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
-    CPPUNIT_ASSERT_EQUAL(OUString("Click here to enter a date."), 
pFieldmark->GetContent());
+    if (mbExported)
+    {
+        uno::Reference<text::XTextRange> xShape(getShape(1), uno::UNO_QUERY);
+        uno::Reference<text::XText> xShapeText = xShape->getText();
+        uno::Reference<beans::XPropertySet> 
xTextPortion(getRun(getParagraphOfText(1, xShapeText), 1), uno::UNO_QUERY);
+        OUString aPortionType;
+        xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+        CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
+        uno::Reference<text::XTextContent> xContentControl;
+        xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
+        uno::Reference<beans::XPropertySet> 
xContentControlProps(xContentControl, uno::UNO_QUERY);
+        bool bDate{};
+        xContentControlProps->getPropertyValue("Date") >>= bDate;
+        CPPUNIT_ASSERT(bDate);
+        uno::Reference<container::XEnumerationAccess> 
xContentControlEnumAccess(xContentControl, uno::UNO_QUERY);
+        uno::Reference<container::XEnumeration> xContentControlEnum = 
xContentControlEnumAccess->createEnumeration();
+        uno::Reference<text::XTextRange> 
xTextPortionRange(xContentControlEnum->nextElement(), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(OUString("Click here to enter a date."), 
xTextPortionRange->getString());
+    }
+    else
+    {
+        SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
+        CPPUNIT_ASSERT(pTextDoc);
+        SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+        ::sw::mark::IDateFieldmark* pFieldmark
+            = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
+        CPPUNIT_ASSERT(pFieldmark);
+        CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), 
pFieldmark->GetFieldname());
+        CPPUNIT_ASSERT_EQUAL(OUString("Click here to enter a date."), 
pFieldmark->GetContent());
+    }
 }
 
 DECLARE_OOXMLEXPORT_TEST( testDateFieldAtEndOfParagraph, 
"date_field_at_end_of_paragraph.docx" )
 {
     // Additional line end was added by import and it was crashed on export
-    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
-    CPPUNIT_ASSERT(pTextDoc);
-    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
-    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getAllMarksCount());
-
-    ::sw::mark::IDateFieldmark* pFieldmark
-          = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
-    CPPUNIT_ASSERT(pFieldmark);
-    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
-    CPPUNIT_ASSERT_EQUAL(OUString("Click here to enter a date."), 
pFieldmark->GetContent());
+    if (mbExported)
+    {
+        uno::Reference<beans::XPropertySet> 
xTextPortion(getRun(getParagraph(2), 1), uno::UNO_QUERY);
+        OUString aPortionType;
+        xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+        CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
+        uno::Reference<text::XTextContent> xContentControl;
+        xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
+        uno::Reference<beans::XPropertySet> 
xContentControlProps(xContentControl, uno::UNO_QUERY);
+        bool bDate{};
+        xContentControlProps->getPropertyValue("Date") >>= bDate;
+        CPPUNIT_ASSERT(bDate);
+        uno::Reference<container::XEnumerationAccess> 
xContentControlEnumAccess(xContentControl, uno::UNO_QUERY);
+        uno::Reference<container::XEnumeration> xContentControlEnum = 
xContentControlEnumAccess->createEnumeration();
+        uno::Reference<text::XTextRange> 
xTextPortionRange(xContentControlEnum->nextElement(), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(OUString("Click here to enter a date."), 
xTextPortionRange->getString());
+    }
+    else
+    {
+        SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
+        CPPUNIT_ASSERT(pTextDoc);
+        SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+        ::sw::mark::IDateFieldmark* pFieldmark
+            = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
+        CPPUNIT_ASSERT(pFieldmark);
+        CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), 
pFieldmark->GetFieldname());
+        CPPUNIT_ASSERT_EQUAL(OUString("Click here to enter a date."), 
pFieldmark->GetContent());
+    }
 }
 
 DECLARE_OOXMLEXPORT_TEST(testDropDownFieldEntryLimit, "tdf126792.odt" )
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx 
b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index 4a2c6771674d..fd148cd8db49 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -172,34 +172,32 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf121203)
 {
     load(mpTestDocumentPath, "tdf121203.docx");
     // We imported the date field
-    SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
-    CPPUNIT_ASSERT(pTextDoc);
-    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
-    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    uno::Reference<beans::XPropertySet> xTextPortion(getRun(getParagraph(1), 
1), uno::UNO_QUERY);
+    OUString aPortionType;
+    xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+    CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
 
     // Custom sdt date content is imported correctly
-    ::sw::mark::IDateFieldmark* pFieldmark
-        = 
dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
-    CPPUNIT_ASSERT(pFieldmark);
-    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+    uno::Reference<text::XTextContent> xContentControl;
+    xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
+    uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, 
uno::UNO_QUERY);
+    bool bDate{};
+    xContentControlProps->getPropertyValue("Date") >>= bDate;
+    CPPUNIT_ASSERT(bDate);
 
-    const sw::mark::IFieldmark::parameter_map_t* const pParameters = 
pFieldmark->GetParameters();
     OUString sDateFormat;
-    auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
-    if (pResult != pParameters->end())
-    {
-        pResult->second >>= sDateFormat;
-    }
+    xContentControlProps->getPropertyValue("DateFormat") >>= sDateFormat;
 
     OUString sLang;
-    pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
-    if (pResult != pParameters->end())
-    {
-        pResult->second >>= sLang;
-    }
-
-    OUString sCurrentDate = pFieldmark->GetContent();
+    xContentControlProps->getPropertyValue("DateLanguage") >>= sLang;
+
+    uno::Reference<container::XEnumerationAccess> 
xContentControlEnumAccess(xContentControl,
+                                                                            
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xContentControlEnum
+        = xContentControlEnumAccess->createEnumeration();
+    uno::Reference<text::XTextRange> 
xTextPortionRange(xContentControlEnum->nextElement(),
+                                                       uno::UNO_QUERY);
+    OUString sCurrentDate = xTextPortionRange->getString();
     CPPUNIT_ASSERT_EQUAL(OUString("dd-MMM-yy"), sDateFormat);
     CPPUNIT_ASSERT_EQUAL(OUString("en-GB"), sLang);
     CPPUNIT_ASSERT_EQUAL(OUString("17-Oct-2018 09:00"), sCurrentDate);
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index 181fbfac0508..f6f542ad4b39 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -2405,7 +2405,7 @@ void DocxAttributeOutput::WriteContentControlStart()
         {
             m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, 
XML_fullDate), aCurrentDate);
         }
-        OUString aDateFormat = m_pContentControl->GetDateFormat();
+        OUString aDateFormat = 
m_pContentControl->GetDateFormat().replaceAll("\"", "'");
         if (!aDateFormat.isEmpty())
         {
             m_pSerializer->singleElementNS(XML_w, XML_dateFormat, FSNS(XML_w, 
XML_val),
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index cefb05fd5292..5d2549f6a9c8 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1074,12 +1074,12 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
             {
                 // Still not determined content type? and it is even not 
unsupported? Then it is plain text field
                 
m_pImpl->m_pSdtHelper->setControlType(SdtControlType::plainText);
-                if (nName == NS_ooxml::LN_CT_SdtRun_sdtContent)
-                {
-                    
m_pImpl->m_pSdtHelper->setControlType(SdtControlType::richText);
-                    m_pImpl->PushSdt();
-                    break;
-                }
+            }
+            if (nName == NS_ooxml::LN_CT_SdtRun_sdtContent)
+            {
+                
m_pImpl->m_pSdtHelper->setControlType(SdtControlType::richText);
+                m_pImpl->PushSdt();
+                break;
             }
             m_pImpl->SetSdt(true);
         break;
@@ -1094,6 +1094,7 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
                     case SdtControlType::checkBox:
                     case SdtControlType::dropDown:
                     case SdtControlType::picture:
+                    case SdtControlType::datePicker:
                         m_pImpl->PopSdt();
                         break;
                     default:
@@ -1180,9 +1181,11 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
             break;
         case NS_ooxml::LN_CT_SdtPlaceholder_docPart_val:
             m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_SdtPlaceholder_docPart_val", sStringValue);
+            m_pImpl->m_pSdtHelper->SetPlaceholderDocPart(sStringValue);
             break;
         case NS_ooxml::LN_CT_SdtColor_val:
             m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_SdtColor_val", sStringValue);
+            m_pImpl->m_pSdtHelper->SetColor(sStringValue);
             break;
         case NS_ooxml::LN_CT_SdtText_multiLine:
             m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_SdtText_multiLine", sStringValue);
@@ -2766,6 +2769,16 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
     {
         if (!m_pImpl->GetSdtStarts().empty())
         {
+            if (nSprmId == NS_ooxml::LN_CT_SdtPr_color)
+            {
+                writerfilter::Reference<Properties>::Pointer_t pProperties = 
rSprm.getProps();
+                if (pProperties)
+                {
+                    pProperties->resolve(*this);
+                }
+                break;
+            }
+
             if (nSprmId == NS_ooxml::LN_CT_SdtPr_checkbox)
             {
                 
m_pImpl->m_pSdtHelper->setControlType(SdtControlType::checkBox);
@@ -2786,6 +2799,16 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
                 }
                 break;
             }
+            else if (nSprmId == NS_ooxml::LN_CT_SdtPr_date)
+            {
+                
m_pImpl->m_pSdtHelper->setControlType(SdtControlType::datePicker);
+                writerfilter::Reference<Properties>::Pointer_t pProperties = 
rSprm.getProps();
+                if (pProperties)
+                {
+                    pProperties->resolve(*this);
+                }
+                break;
+            }
         }
 
         // this is an unsupported SDT property, create a grab bag for it
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 4e769e15b0cf..fd6300504de5 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -875,7 +875,15 @@ void DomainMapper_Impl::PopSdt()
 
     if (aPosition.m_bIsStartOfText)
     {
-        xCursor->gotoStart(/*bExpand=*/false);
+        // Go to the start of the end's paragraph. This helps in case
+        // DomainMapper_Impl::AddDummyParaForTableInSection() would make our 
range multi-paragraph,
+        // while the intention is to keep start/end inside the same paragraph 
for run SDTs.
+        uno::Reference<text::XParagraphCursor> xParagraphCursor(xCursor, 
uno::UNO_QUERY);
+        if (xParagraphCursor.is())
+        {
+            xCursor->gotoRange(xEnd, /*bExpand=*/false);
+            xParagraphCursor->gotoStartOfParagraph(/*bExpand=*/false);
+        }
     }
     else
     {
@@ -892,6 +900,34 @@ void DomainMapper_Impl::PopSdt()
                                                
uno::Any(m_pSdtHelper->GetShowingPlcHdr()));
     }
 
+    if (!m_pSdtHelper->GetPlaceholderDocPart().isEmpty())
+    {
+        xContentControlProps->setPropertyValue("PlaceholderDocPart",
+                                               
uno::Any(m_pSdtHelper->GetPlaceholderDocPart()));
+    }
+
+    if (!m_pSdtHelper->GetDataBindingPrefixMapping().isEmpty())
+    {
+        xContentControlProps->setPropertyValue("DataBindingPrefixMappings",
+                                               
uno::Any(m_pSdtHelper->GetDataBindingPrefixMapping()));
+    }
+    if (!m_pSdtHelper->GetDataBindingXPath().isEmpty())
+    {
+        xContentControlProps->setPropertyValue("DataBindingXpath",
+                                               
uno::Any(m_pSdtHelper->GetDataBindingXPath()));
+    }
+    if (!m_pSdtHelper->GetDataBindingStoreItemID().isEmpty())
+    {
+        xContentControlProps->setPropertyValue("DataBindingStoreItemID",
+                                               
uno::Any(m_pSdtHelper->GetDataBindingStoreItemID()));
+    }
+
+    if (!m_pSdtHelper->GetColor().isEmpty())
+    {
+        xContentControlProps->setPropertyValue("Color",
+                                               
uno::Any(m_pSdtHelper->GetColor()));
+    }
+
     if (m_pSdtHelper->getControlType() == SdtControlType::checkBox)
     {
         xContentControlProps->setPropertyValue("Checkbox", uno::Any(true));
@@ -930,6 +966,18 @@ void DomainMapper_Impl::PopSdt()
         xContentControlProps->setPropertyValue("Picture", uno::Any(true));
     }
 
+    if (m_pSdtHelper->getControlType() == SdtControlType::datePicker)
+    {
+        xContentControlProps->setPropertyValue("Date", uno::Any(true));
+        OUString aDateFormat = 
m_pSdtHelper->getDateFormat().makeStringAndClear();
+        xContentControlProps->setPropertyValue("DateFormat",
+                                               
uno::Any(aDateFormat.replaceAll("'", "\"")));
+        xContentControlProps->setPropertyValue("DateLanguage",
+                                               
uno::Any(m_pSdtHelper->getLocale().makeStringAndClear()));
+        xContentControlProps->setPropertyValue("CurrentDate",
+                                               
uno::Any(m_pSdtHelper->getDate().makeStringAndClear()));
+    }
+
     xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
 
     m_pSdtHelper->clear();
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx 
b/writerfilter/source/dmapper/SdtHelper.cxx
index 94019850f7dc..8f5e809efdec 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -453,6 +453,17 @@ void SdtHelper::clear()
     m_aUncheckedState.clear();
 }
 
+void SdtHelper::SetPlaceholderDocPart(const OUString& rPlaceholderDocPart)
+{
+    m_aPlaceholderDocPart = rPlaceholderDocPart;
+}
+
+OUString SdtHelper::GetPlaceholderDocPart() const { return 
m_aPlaceholderDocPart; }
+
+void SdtHelper::SetColor(const OUString& rColor) { m_aColor = rColor; }
+
+OUString SdtHelper::GetColor() const { return m_aColor; }
+
 } // namespace writerfilter::dmapper
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/SdtHelper.hxx 
b/writerfilter/source/dmapper/SdtHelper.hxx
index 3fab668c1f19..c817285095e7 100644
--- a/writerfilter/source/dmapper/SdtHelper.hxx
+++ b/writerfilter/source/dmapper/SdtHelper.hxx
@@ -119,6 +119,12 @@ class SdtHelper final : public virtual SvRefBase
 
     void loadPropertiesXMLs();
 
+    /// <w:placeholder>'s <w:docPart w:val="...">.
+    OUString m_aPlaceholderDocPart;
+
+    /// <w:sdtPr>'s <w15:color w:val="...">.
+    OUString m_aColor;
+
 public:
     explicit SdtHelper(DomainMapper_Impl& rDM_Impl,
                        css::uno::Reference<css::uno::XComponentContext> const& 
xContext);
@@ -136,8 +142,13 @@ public:
     {
         m_sDataBindingPrefixMapping = sValue;
     }
+    OUString GetDataBindingPrefixMapping() const { return 
m_sDataBindingPrefixMapping; }
+
     void setDataBindingXPath(const OUString& sValue) { m_sDataBindingXPath = 
sValue; }
+    OUString GetDataBindingXPath() const { return m_sDataBindingXPath; }
+
     void setDataBindingStoreItemID(const OUString& sValue) { 
m_sDataBindingStoreItemID = sValue; }
+    OUString GetDataBindingStoreItemID() const { return 
m_sDataBindingStoreItemID; }
 
     void setDateFieldStartRange(const 
css::uno::Reference<css::text::XTextRange>& xStartRange)
     {
@@ -183,6 +194,12 @@ public:
 
     /// Clear all collected attributes for further reuse
     void clear();
+
+    void SetPlaceholderDocPart(const OUString& rPlaceholderDocPart);
+    OUString GetPlaceholderDocPart() const;
+
+    void SetColor(const OUString& rColor);
+    OUString GetColor() const;
 };
 
 } // namespace writerfilter::dmapper

Reply via email to