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 <vmiklos@collabora.com>
Tested-by: Jenkins
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index ae720f5..ebe5abb 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())
            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(5), pMarkAccess->getAllMarksCount());

            int nIndex = 0;
            for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
            {
                pResult->second >>= sDateFormat;
                ::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 sLang;
                pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
                if (pResult != pParameters->end())
                {
                    pResult->second >>= sLang;
                }

                OUString sCurrentDate = pFieldmark->GetContent();

                // 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);

                    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());

                }
                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());

                }
                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;
            }

            OUString sLang;
            pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
            if (pResult != pParameters->end())
            {
                pResult->second >>= sLang;
            }

            OUString sCurrentDate = pFieldmark->GetContent();

            // 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);

                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());

            }
            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());

            }
            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;
            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(5), nIndex);
        }
        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())
            {
                uno::Reference<beans::XPropertySet> xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY);
                OUString aPortionType;
                xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
                if (aPortionType != "ContentControl")
                {
                    continue;
                }

                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;
            }
            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();
        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());
            // 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"));
            // 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 0435f42..e3525b5 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)
            continue;

        CPPUNIT_ASSERT(pFieldmark);
        CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());

        // Check date 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())
        uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
        OUString aPortionType;
        xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
        if (aPortionType != "ContentControl")
        {
            pResult->second >>= sDateFormat;
            continue;
        }

        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 content control's parameters.
        OUString 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 b52c25c..62c754a 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());

    ::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())
    if (mbExported)
    {
        pResult->second >>= sDateFormat;
        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);
    }
    CPPUNIT_ASSERT_EQUAL(OUString("M.d.yyyy"), sDateFormat);
    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());

        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;
        }
        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 a630c00..d5fd169 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());

    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());
        ::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());
    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());
        ::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());
    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());
        ::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 4a2c6771..fd148cd 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;
    }
    xContentControlProps->getPropertyValue("DateLanguage") >>= sLang;

    OUString sCurrentDate = pFieldmark->GetContent();
    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 181fbfac..f6f542a 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 cefb05f..5d2549f 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 4e769e1..fd63005 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 9401985..8f5e809e 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 3fab668..c817285 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