[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.0' - 2 commits - sw/inc sw/qa sw/source writerfilter/source xmloff/source

Tamás Zolnai (via logerrit) logerrit at kemper.freedesktop.org
Sat Jul 13 22:20:26 UTC 2019


 dev/null                                                           |binary
 sw/inc/IDocumentMarkAccess.hxx                                     |    2 
 sw/inc/IMark.hxx                                                   |   19 
 sw/inc/swabstdlg.hxx                                               |    4 
 sw/qa/extras/globalfilter/data/date_form_field.odt                 |binary
 sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt |binary
 sw/qa/extras/globalfilter/globalfilter.cxx                         |  106 +++
 sw/qa/extras/ooxmlexport/ooxmlexport.cxx                           |   11 
 sw/qa/extras/ooxmlexport/ooxmlexport11.cxx                         |    4 
 sw/qa/extras/uiwriter/uiwriter2.cxx                                |    5 
 sw/source/core/crsr/DateFormFieldButton.cxx                        |   66 --
 sw/source/core/crsr/bookmrk.cxx                                    |  276 +++++++++-
 sw/source/core/doc/docbm.cxx                                       |   33 +
 sw/source/core/inc/MarkManager.hxx                                 |    2 
 sw/source/core/inc/bookmrk.hxx                                     |   31 -
 sw/source/core/text/itrform2.cxx                                   |   96 ---
 sw/source/core/text/porfld.cxx                                     |    9 
 sw/source/core/text/porfld.hxx                                     |    8 
 sw/source/core/unocore/unobkm.cxx                                  |    4 
 sw/source/filter/ww8/docxattributeoutput.cxx                       |   90 +--
 sw/source/filter/ww8/docxattributeoutput.hxx                       |    3 
 sw/source/filter/ww8/docxexport.cxx                                |    3 
 sw/source/filter/ww8/wrtw8nds.cxx                                  |  147 ++---
 sw/source/ui/dialog/swdlgfact.cxx                                  |    2 
 sw/source/ui/dialog/swdlgfact.hxx                                  |    3 
 sw/source/ui/fldui/DateFormFieldDialog.cxx                         |   34 -
 sw/source/uibase/inc/DateFormFieldDialog.hxx                       |    6 
 sw/source/uibase/shells/textfld.cxx                                |   30 -
 sw/source/uibase/shells/textsh1.cxx                                |    3 
 writerfilter/source/dmapper/DomainMapper.cxx                       |   81 +-
 writerfilter/source/dmapper/SdtHelper.cxx                          |   41 +
 writerfilter/source/dmapper/SdtHelper.hxx                          |   18 
 xmloff/source/text/XMLTextMarkImportContext.cxx                    |    5 
 33 files changed, 720 insertions(+), 422 deletions(-)

New commits:
commit fa53a9ec758a31ca890a484fb3399fa63987eef4
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jul 10 18:23:48 2019 +0200
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Sun Jul 14 00:19:55 2019 +0200

    MSForms: Test import / export of character formatting for date field
    
    * With the rework, now the character formatting is fully supported.
    * Remove the other related test, which tested only a interop
    grabbag implementation.
    
    Reviewed-on: https://gerrit.libreoffice.org/75460
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit 01f6c6ad6ba1adce817daa782bf3520fafc512a0)
    
    Change-Id: I598a21691c08a161933a5fef659e7ca21092dd0c
    Reviewed-on: https://gerrit.libreoffice.org/75553
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt b/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt
new file mode 100644
index 000000000000..eb770262056a
Binary files /dev/null and b/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt differ
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index 10dca218b702..fcb40c24e409 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -26,6 +26,7 @@
 #include <IDocumentMarkAccess.hxx>
 #include <IMark.hxx>
 #include <bookmrk.hxx>
+#include <com/sun/star/awt/FontWeight.hpp>
 
 class Test : public SwModelTestBase
 {
@@ -49,6 +50,7 @@ public:
     void testCheckBoxFormField();
     void testDropDownFormField();
     void testDateFormField();
+    void testDateFormFieldCharacterFormatting();
 
     CPPUNIT_TEST_SUITE(Test);
     CPPUNIT_TEST(testSwappedOutImageExport);
@@ -67,6 +69,7 @@ public:
     CPPUNIT_TEST(testCheckBoxFormField);
     CPPUNIT_TEST(testDropDownFormField);
     CPPUNIT_TEST(testDateFormField);
+    CPPUNIT_TEST(testDateFormFieldCharacterFormatting);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -1230,6 +1233,54 @@ void Test::testDateFormField()
     }
 }
 
+void Test::testDateFormFieldCharacterFormatting()
+{
+    const OUString aFilterNames[] = {
+        "writer8",
+        "Office Open XML Text",
+    };
+
+    for (const OUString& rFilterName : aFilterNames)
+    {
+        if (mxComponent.is())
+            mxComponent->dispose();
+        mxComponent = loadFromDesktop(m_directories.getURLFromSrc("/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt"), "com.sun.star.text.TextDocument");
+
+        const OString sFailedMessage = OString("Failed on filter: ") + rFilterName.toUtf8();
+
+        // Export the document and import again for a check
+        uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+        utl::MediaDescriptor aMediaDescriptor;
+        aMediaDescriptor["FilterName"] <<= rFilterName;
+        utl::TempFile aTempFile;
+        aTempFile.EnableKillingFile();
+        xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+        uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
+        xComponent->dispose();
+        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()->get());
+        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(10), 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), 2), "CharWeight"));
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(COL_AUTO), getProperty<sal_Int32>(getRun(getParagraph(1), 2), "CharColor"));
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), awt::FontWeight::NORMAL, getProperty<float>(getRun(getParagraph(1), 3), "CharWeight"));
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(0xff0000), getProperty<sal_Int32>(getRun(getParagraph(1), 3), "CharColor"));
+    }
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/qa/extras/ooxmlexport/data/sdt-date-charformat.docx b/sw/qa/extras/ooxmlexport/data/sdt-date-charformat.docx
deleted file mode 100644
index 22c4d4e1f8c3..000000000000
Binary files a/sw/qa/extras/ooxmlexport/data/sdt-date-charformat.docx and /dev/null differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index 355163fb5927..870c654f855d 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -96,17 +96,6 @@ DECLARE_OOXMLEXPORT_TEST(testSdtAlias, "sdt-alias.docx")
     assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:alias", "val", "Subtitle");
 }
 
-/*DECLARE_OOXMLEXPORT_TEST(testSdtDateCharformat, "sdt-date-charformat.docx")
-{
-    if (xmlDocPtr pXmlDoc = parseExport())
-    {
-        // character formatting (bold) was missing, this was 0
-        assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r/w:rPr/w:b", 1);
-        // alias was also missing.
-        assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:alias", 1);
-    }
-}*/
-
 DECLARE_OOXMLEXPORT_TEST(testFooterBodyDistance, "footer-body-distance.docx")
 {
     if (xmlDocPtr pXmlDoc = parseExport())
commit 6424765accef4fdce2fc23e6310cebafb70f6173
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jul 10 18:22:31 2019 +0200
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Sun Jul 14 00:19:47 2019 +0200

    MSForms: Rework text-based date form field's representation
    
    * Better to represent it similar to text form field with two
    marking characters selecting a text range
    * So the text between the two marks can be anything (not only
    a well formatted date) and also have any character formatting.
    * With this we handle the case when the user needs a placeholder
    text in the date field or when the user needs time values (hour,
    minute, sec) next to the date.
    
    Reviewed-on: https://gerrit.libreoffice.org/75459
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit 68e1be4ccbb90ee9a788962219a88312c4ffbea2)
    
    Change-Id: Id60a50a2028058f8a6a080e265c0730d88b98543
    Reviewed-on: https://gerrit.libreoffice.org/75552
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index ee021ad7c4e4..c26f0ab10461 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -258,7 +258,7 @@ class IDocumentMarkAccess
         virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const=0;
 
         virtual void deleteFieldmarkAt(const SwPosition& rPos) = 0;
-        virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) = 0;
+        virtual ::sw::mark::IFieldmark* changeFormFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) = 0;
 
         virtual void NotifyCursorUpdate(const SwCursorShell& rCursorShell) = 0;
         virtual void ClearFieldActivation() = 0;
diff --git a/sw/inc/IMark.hxx b/sw/inc/IMark.hxx
index ca3b1efa9f44..86ef842b797b 100644
--- a/sw/inc/IMark.hxx
+++ b/sw/inc/IMark.hxx
@@ -153,6 +153,25 @@ namespace sw { namespace mark
         }
     };
 
+    class SW_DLLPUBLIC IDateFieldmark
+        : virtual public IFieldmark
+    {
+        protected:
+            IDateFieldmark() = default;
+
+        public:
+            virtual OUString GetContent() const = 0;
+            virtual void ReplaceContent(const OUString& sNewContent) = 0;
+
+            virtual std::pair<bool, double> GetCurrentDate() const = 0;
+            virtual void SetCurrentDate(double fDate) = 0;
+            virtual OUString GetDateInStandardDateFormat(double fDate) const = 0;
+
+    private:
+            IDateFieldmark(ICheckboxFieldmark const &) = delete;
+            IDateFieldmark &operator =(ICheckboxFieldmark const&) = delete;
+    };
+
     OUString ExpandFieldmark(IFieldmark* pBM);
 
 }}
diff --git a/sw/inc/swabstdlg.hxx b/sw/inc/swabstdlg.hxx
index b1342d55dee8..127c81e5b530 100644
--- a/sw/inc/swabstdlg.hxx
+++ b/sw/inc/swabstdlg.hxx
@@ -93,7 +93,7 @@ namespace com{namespace sun{namespace star{
 }}}
 
 
-namespace sw { namespace mark { class IFieldmark; } }
+namespace sw { namespace mark { class IFieldmark; class IDateFieldmark; } }
 
 typedef   void (*SwLabDlgMethod) (css::uno::Reference< css::frame::XModel> const & xModel, const SwLabItem& rItem);
 
@@ -418,7 +418,7 @@ public:
 
     virtual VclPtr<SfxAbstractTabDialog> CreateSwEnvDlg ( vcl::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtSh, Printer* pPrt, bool bInsert ) = 0;
 
-    virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(sw::mark::IFieldmark* pDateField, SwDoc* pDoc) = 0;
+    virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc) = 0;
 
     virtual VclPtr<AbstractSwLabDlg> CreateSwLabDlg(const SfxItemSet& rSet,
                                                      SwDBManager* pDBManager, bool bLabel) = 0;
diff --git a/sw/qa/extras/globalfilter/data/date_form_field.odt b/sw/qa/extras/globalfilter/data/date_form_field.odt
index 8e15793c2d59..2b786a414658 100644
Binary files a/sw/qa/extras/globalfilter/data/date_form_field.odt and b/sw/qa/extras/globalfilter/data/date_form_field.odt differ
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index 67d5a2f53d00..10dca218b702 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -1146,19 +1146,12 @@ void Test::testDateFormField()
         SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
         IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
 
-        if(rFilterName == "Office Open XML Text")
-            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(6), pMarkAccess->getAllMarksCount());
-        else
-            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(3), pMarkAccess->getAllMarksCount());
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(5), pMarkAccess->getAllMarksCount());
 
         int nIndex = 0;
         for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
         {
-            ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
-
-            if(!pFieldmark)
-                continue;
-
+            ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(aIter->get());
             CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
             CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
 
@@ -1178,20 +1171,16 @@ void Test::testDateFormField()
                 pResult->second >>= sLang;
             }
 
-            OUString sCurrentDate;
-            pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
-            if (pResult != pParameters->end())
-            {
-                pResult->second >>= sCurrentDate;
-            }
+            OUString sCurrentDate = pFieldmark->GetContent();
 
-            // The first one is empty
+            // 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);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(""), sCurrentDate);
+                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(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex());
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(5), pFieldmark->GetMarkStart().nContent.GetIndex());
@@ -1200,24 +1189,44 @@ void Test::testDateFormField()
             {
                 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("2019-06-12"), sCurrentDate);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("06/12/19"), sCurrentDate);
 
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex());
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(13), pFieldmark->GetMarkStart().nContent.GetIndex());
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(19), pFieldmark->GetMarkStart().nContent.GetIndex());
             }
-            else // The third one has special format
+            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-06-11"), sCurrentDate);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("2019. febr. 12."), sCurrentDate);
+
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex());
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(38), 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(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex());
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(59), 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(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex());
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(23), pFieldmark->GetMarkStart().nContent.GetIndex());
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(78), pFieldmark->GetMarkStart().nContent.GetIndex());
 
             }
             ++nIndex;
         }
-        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(3), nIndex);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(5), nIndex);
     }
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index dd045978f4b1..5a63694ba4af 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -532,7 +532,7 @@ DECLARE_OOXMLIMPORT_TEST(testInvalidDateFormField, "invalid_date_form_field.docx
             CPPUNIT_ASSERT_EQUAL(OUString("2019.06.34"), sCurrentDate);
 
             CPPUNIT_ASSERT_EQUAL(sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex());
-            CPPUNIT_ASSERT_EQUAL(sal_Int32(13), pFieldmark->GetMarkStart().nContent.GetIndex());
+            CPPUNIT_ASSERT_EQUAL(sal_Int32(14), pFieldmark->GetMarkStart().nContent.GetIndex());
         }
         else // The third one has wrong local
         {
@@ -541,7 +541,7 @@ DECLARE_OOXMLIMPORT_TEST(testInvalidDateFormField, "invalid_date_form_field.docx
             CPPUNIT_ASSERT_EQUAL(OUString("2019.06.11"), sCurrentDate);
 
             CPPUNIT_ASSERT_EQUAL(sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex());
-            CPPUNIT_ASSERT_EQUAL(sal_Int32(23), pFieldmark->GetMarkStart().nContent.GetIndex());
+            CPPUNIT_ASSERT_EQUAL(sal_Int32(33), pFieldmark->GetMarkStart().nContent.GetIndex());
         }
         ++nIndex;
     }
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 833a937f4091..3455692a678f 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -623,6 +623,11 @@ void SwUiWriterTest2::testDateFormFieldInsertion()
     CPPUNIT_ASSERT(pFieldmark);
     CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
 
+    // The date form field has the placeholder text in it
+    uno::Reference<text::XTextRange> xPara = getParagraph(1);
+    sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 };
+    CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString());
+
     // Undo insertion
     lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
     CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
diff --git a/sw/source/core/crsr/DateFormFieldButton.cxx b/sw/source/core/crsr/DateFormFieldButton.cxx
index 52a634e6158f..0fdcf842dc30 100644
--- a/sw/source/core/crsr/DateFormFieldButton.cxx
+++ b/sw/source/core/crsr/DateFormFieldButton.cxx
@@ -28,19 +28,19 @@ class SwDatePickerDialog : public FloatingWindow
 {
 private:
     VclPtr<Calendar> m_pCalendar;
-    sw::mark::IFieldmark* m_pFieldmark;
+    sw::mark::DateFieldmark* m_pFieldmark;
     SvNumberFormatter* m_pNumberFormatter;
 
     DECL_LINK(ImplSelectHdl, Calendar*, void);
 
 public:
-    SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark,
+    SwDatePickerDialog(SwEditWin* parent, sw::mark::DateFieldmark* pFieldmark,
                        SvNumberFormatter* pNumberFormatter);
     virtual ~SwDatePickerDialog() override;
     virtual void dispose() override;
 };
 
-SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark,
+SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::DateFieldmark* pFieldmark,
                                        SvNumberFormatter* pNumberFormatter)
     : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW)
     , m_pCalendar(VclPtr<Calendar>::Create(this, WB_TABSTOP))
@@ -49,33 +49,11 @@ SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark*
 {
     if (m_pFieldmark != nullptr)
     {
-        sw::mark::IFieldmark::parameter_map_t* pParameters = m_pFieldmark->GetParameters();
-
-        auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
-        if (pResult != pParameters->end())
+        std::pair<bool, double> aResult = m_pFieldmark->GetCurrentDate();
+        if (aResult.first)
         {
-            OUString sDateString;
-            pResult->second >>= sDateString;
-
-            sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT,
-                                                                 ODF_FORMDATE_CURRENTDATE_LANGUAGE);
-            if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
-            {
-                sal_Int32 nCheckPos = 0;
-                short nType;
-                OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
-                m_pNumberFormatter->PutEntry(sFormat, nCheckPos, nType, nFormat,
-                                             ODF_FORMDATE_CURRENTDATE_LANGUAGE);
-            }
-
-            if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
-            {
-                double dCurrentDate = 0;
-                m_pNumberFormatter->IsNumberFormat(sDateString, nFormat, dCurrentDate);
-
-                const Date& rNullDate = m_pNumberFormatter->GetNullDate();
-                m_pCalendar->SetCurDate(rNullDate + sal_Int32(dCurrentDate));
-            }
+            const Date& rNullDate = m_pNumberFormatter->GetNullDate();
+            m_pCalendar->SetCurDate(rNullDate + sal_Int32(aResult.second));
         }
     }
     m_pCalendar->SetSelectHdl(LINK(this, SwDatePickerDialog, ImplSelectHdl));
@@ -98,30 +76,9 @@ IMPL_LINK(SwDatePickerDialog, ImplSelectHdl, Calendar*, pCalendar, void)
     {
         if (m_pFieldmark != nullptr)
         {
-            sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT,
-                                                                 ODF_FORMDATE_CURRENTDATE_LANGUAGE);
-            if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
-            {
-                sal_Int32 nCheckPos = 0;
-                short nType;
-                OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
-                m_pNumberFormatter->PutEntry(sFormat, nCheckPos, nType, nFormat,
-                                             ODF_FORMDATE_CURRENTDATE_LANGUAGE);
-            }
-
-            if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
-            {
-                Color* pCol = nullptr;
-                OUString sOutput;
-
-                const Date& rNullDate = m_pNumberFormatter->GetNullDate();
-                double dDate = pCalendar->GetFirstSelectedDate() - rNullDate;
-
-                m_pNumberFormatter->GetOutputString(dDate, nFormat, sOutput, &pCol, false);
-
-                sw::mark::IFieldmark::parameter_map_t* pParameters = m_pFieldmark->GetParameters();
-                (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= sOutput;
-            }
+            const Date& rNullDate = m_pNumberFormatter->GetNullDate();
+            double dDate = pCalendar->GetFirstSelectedDate() - rNullDate;
+            m_pFieldmark->SetCurrentDate(dDate);
         }
         EndPopupMode();
     }
@@ -138,8 +95,9 @@ DateFormFieldButton::~DateFormFieldButton() { disposeOnce(); }
 
 void DateFormFieldButton::InitPopup()
 {
+    sw::mark::DateFieldmark* pDateFieldmark = dynamic_cast<sw::mark::DateFieldmark*>(&m_rFieldmark);
     m_pFieldPopup = VclPtr<SwDatePickerDialog>::Create(static_cast<SwEditWin*>(GetParent()),
-                                                       &m_rFieldmark, m_pNumberFormatter);
+                                                       pDateFieldmark, m_pNumberFormatter);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx
index a0c9afd4f756..09cd5375f2f3 100644
--- a/sw/source/core/crsr/bookmrk.cxx
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -40,6 +40,8 @@
 #include <DateFormFieldButton.hxx>
 #include <DropDownFormFieldButton.hxx>
 #include <svx/numfmtsh.hxx>
+#include <ndtxt.hxx>
+#include <DocumentContentOperationsManager.hxx>
 
 using namespace ::sw::mark;
 using namespace ::com::sun::star;
@@ -499,21 +501,6 @@ namespace sw { namespace mark
         m_pButton.disposeAndClear();
     }
 
-    void FieldmarkWithDropDownButton::SetPortionPaintArea(const SwRect& rPortionPaintArea)
-    {
-        if(m_aPortionPaintArea == rPortionPaintArea &&
-           m_pButton && m_pButton->IsVisible())
-            return;
-
-        m_aPortionPaintArea = rPortionPaintArea;
-        if(m_pButton)
-        {
-            m_pButton->Show();
-            m_pButton->CalcPosAndSize(m_aPortionPaintArea);
-            m_pButton->Invalidate();
-        }
-    }
-
     void FieldmarkWithDropDownButton::HideButton()
     {
         if(m_pButton)
@@ -546,8 +533,25 @@ namespace sw { namespace mark
         }
     }
 
+    void DropDownFieldmark::SetPortionPaintArea(const SwRect& rPortionPaintArea)
+    {
+        if(m_aPortionPaintArea == rPortionPaintArea &&
+           m_pButton && m_pButton->IsVisible())
+            return;
+
+        m_aPortionPaintArea = rPortionPaintArea;
+        if(m_pButton)
+        {
+            m_pButton->Show();
+            m_pButton->CalcPosAndSize(m_aPortionPaintArea);
+            m_pButton->Invalidate();
+        }
+    }
+
     DateFieldmark::DateFieldmark(const SwPaM& rPaM)
         : FieldmarkWithDropDownButton(rPaM)
+        , m_pNumberFormatter(nullptr)
+        , m_pDocumentContentOperationsManager(nullptr)
     {
     }
 
@@ -558,7 +562,20 @@ namespace sw { namespace mark
     void DateFieldmark::InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode)
     {
         m_pNumberFormatter = io_pDoc->GetNumberFormatter();
-        NonTextFieldmark::InitDoc(io_pDoc, eMode);
+        m_pDocumentContentOperationsManager = &io_pDoc->GetDocumentContentOperationsManager();
+        if (eMode == sw::mark::InsertMode::New)
+        {
+            lcl_SetFieldMarks(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
+        }
+        else
+        {
+            lcl_AssertFieldMarksSet(this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
+        }
+    }
+
+    void DateFieldmark::ReleaseDoc(SwDoc* const pDoc)
+    {
+        lcl_RemoveFieldMarks(this, pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
     }
 
     void DateFieldmark::ShowButton(SwEditWin* pEditWin)
@@ -567,10 +584,235 @@ namespace sw { namespace mark
         {
             if(!m_pButton)
                 m_pButton = VclPtr<DateFormFieldButton>::Create(pEditWin, *this, m_pNumberFormatter);
-            m_pButton->CalcPosAndSize(m_aPortionPaintArea);
+            m_pButton->CalcPosAndSize(m_aPaintAreaEnd);
             m_pButton->Show();
         }
     }
+
+    void DateFieldmark::SetPortionPaintAreaStart(const SwRect& rPortionPaintArea)
+    {
+        m_aPaintAreaStart = rPortionPaintArea;
+        InvalidateCurrentDateParam();
+    }
+
+    void DateFieldmark::SetPortionPaintAreaEnd(const SwRect& rPortionPaintArea)
+    {
+        if(m_aPaintAreaEnd == rPortionPaintArea &&
+           m_pButton && m_pButton->IsVisible())
+            return;
+
+        m_aPaintAreaEnd = rPortionPaintArea;
+        if(m_pButton)
+        {
+            m_pButton->Show();
+            SwRect aPaintArea(m_aPaintAreaStart.TopLeft(), m_aPaintAreaEnd.BottomRight());
+            m_pButton->CalcPosAndSize(aPaintArea);
+            m_pButton->Invalidate();
+        }
+        InvalidateCurrentDateParam();
+    }
+
+    OUString DateFieldmark::GetContent() const
+    {
+        const SwTextNode* const pTextNode = GetMarkEnd().nNode.GetNode().GetTextNode();
+        const sal_Int32 nStart(GetMarkStart().nContent.GetIndex());
+        const sal_Int32 nEnd  (GetMarkEnd().nContent.GetIndex());
+
+        OUString sContent;
+        if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() &&
+           nEnd > nStart + 2)
+            sContent = pTextNode->GetText().copy(nStart + 1, nEnd - nStart - 2);
+        return sContent;
+    }
+
+    void DateFieldmark::ReplaceContent(const OUString& sNewContent)
+    {
+        if(!m_pDocumentContentOperationsManager)
+            return;
+
+        const SwTextNode* const pTextNode = GetMarkEnd().nNode.GetNode().GetTextNode();
+        const sal_Int32 nStart(GetMarkStart().nContent.GetIndex());
+        const sal_Int32 nEnd  (GetMarkEnd().nContent.GetIndex());
+
+        if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength())
+        {
+            SwPaM aFieldPam(GetMarkStart().nNode, nStart + 1,
+                            GetMarkStart().nNode, nEnd - 1);
+            m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false);
+        }
+
+    }
+
+    std::pair<bool, double> DateFieldmark::GetCurrentDate() const
+    {
+        // Check current date param first
+        std::pair<bool, double> aResult = ParseCurrentDateParam();
+        if(aResult.first)
+            return aResult;
+
+        const sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
+        bool bFoundValidDate = false;
+        double dCurrentDate = 0;
+        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;
+        }
+
+        // Get current content of the field
+        OUString sContent = GetContent();
+
+        sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType());
+        if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+        {
+            sal_Int32 nCheckPos = 0;
+            short nType;
+            m_pNumberFormatter->PutEntry(sDateFormat,
+                                         nCheckPos,
+                                         nType,
+                                         nFormat,
+                                         LanguageTag(sLang).getLanguageType());
+        }
+
+        if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
+        {
+            bFoundValidDate = m_pNumberFormatter->IsNumberFormat(sContent, nFormat, dCurrentDate);
+        }
+        return std::pair<bool, double>(bFoundValidDate, dCurrentDate);
+    }
+
+    void DateFieldmark::SetCurrentDate(double fDate)
+    {
+        // Replace current content with the selected date
+        ReplaceContent(GetDateInCurrentDateFormat(fDate));
+
+        // Also save the current date in a standard format
+        sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
+        (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= GetDateInStandardDateFormat(fDate);
+    }
+
+    OUString DateFieldmark::GetDateInStandardDateFormat(double fDate) const
+    {
+        OUString sCurrentDate;
+        sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE);
+        if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+        {
+            sal_Int32 nCheckPos = 0;
+            short nType;
+            OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
+            m_pNumberFormatter->PutEntry(sFormat,
+                                         nCheckPos,
+                                         nType,
+                                         nFormat,
+                                         ODF_FORMDATE_CURRENTDATE_LANGUAGE);
+        }
+
+        if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
+        {
+            Color* pCol = nullptr;
+            m_pNumberFormatter->GetOutputString(fDate, nFormat, sCurrentDate, &pCol, false);
+        }
+        return sCurrentDate;
+    }
+
+    std::pair<bool, double> DateFieldmark::ParseCurrentDateParam() const
+    {
+        bool bFoundValidDate = false;
+        double dCurrentDate = 0;
+
+        const sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
+        auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
+        OUString sCurrentDate;
+        if (pResult != pParameters->end())
+        {
+            pResult->second >>= sCurrentDate;
+        }
+        if(!sCurrentDate.isEmpty())
+        {
+            sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE);
+            if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+            {
+                sal_Int32 nCheckPos = 0;
+                short nType;
+                OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
+                m_pNumberFormatter->PutEntry(sFormat,
+                                             nCheckPos,
+                                             nType,
+                                             nFormat,
+                                             ODF_FORMDATE_CURRENTDATE_LANGUAGE);
+            }
+
+            if(nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
+            {
+                bFoundValidDate = m_pNumberFormatter->IsNumberFormat(sCurrentDate, nFormat, dCurrentDate);
+            }
+        }
+        return std::pair<bool, double>(bFoundValidDate, dCurrentDate);
+    }
+
+
+    OUString DateFieldmark::GetDateInCurrentDateFormat(double fDate) const
+    {
+        // Get current date format and language
+        OUString sDateFormat;
+        const sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
+        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;
+        }
+
+        // Fill the content with the specified format
+        OUString sCurrentContent;
+        sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType());
+        if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+        {
+            sal_Int32 nCheckPos = 0;
+            short nType;
+            OUString sFormat = sDateFormat;
+            m_pNumberFormatter->PutEntry(sFormat,
+                                         nCheckPos,
+                                         nType,
+                                         nFormat,
+                                         LanguageTag(sLang).getLanguageType());
+        }
+
+        if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
+        {
+            Color* pCol = nullptr;
+            m_pNumberFormatter->GetOutputString(fDate, nFormat, sCurrentContent, &pCol, false);
+        }
+        return sCurrentContent;
+    }
+
+    void DateFieldmark::InvalidateCurrentDateParam()
+    {
+        std::pair<bool, double> aResult = ParseCurrentDateParam();
+        if(!aResult.first)
+            return;
+
+        // Current date became invalid
+        if(GetDateInCurrentDateFormat(aResult.second) != GetContent())
+        {
+            sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters();
+            (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= OUString();
+        }
+    }
 }}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 985904e27a56..969ab413b0e5 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -509,9 +509,19 @@ namespace sw { namespace mark
         bool bUndoIsEnabled = m_pDoc->GetIDocumentUndoRedo().DoesUndo();
         m_pDoc->GetIDocumentUndoRedo().DoUndo(false);
 
-        sw::mark::IMark* pMark = makeMark( rPaM, rName,
-                IDocumentMarkAccess::MarkType::TEXT_FIELDMARK,
-                sw::mark::InsertMode::New);
+        sw::mark::IMark* pMark = nullptr;
+        if(rType == ODF_FORMDATE)
+        {
+            pMark = makeMark(rPaM, rName,
+                             IDocumentMarkAccess::MarkType::DATE_FIELDMARK,
+                              sw::mark::InsertMode::New);
+        }
+        else
+        {
+            pMark = makeMark(rPaM, rName,
+                             IDocumentMarkAccess::MarkType::TEXT_FIELDMARK,
+                             sw::mark::InsertMode::New);
+        }
         sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
         if (pFieldMark)
             pFieldMark->SetFieldname( rType );
@@ -1121,23 +1131,29 @@ namespace sw { namespace mark
         deleteMark(lcl_FindMark(m_vAllMarks, *pFieldmark));
     }
 
-    ::sw::mark::IFieldmark* MarkManager::changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType)
+    ::sw::mark::IFieldmark* MarkManager::changeFormFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType)
     {
         bool bActualChange = false;
         if(rNewType == ODF_FORMDROPDOWN)
         {
             if (!dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldmark))
                 bActualChange = true;
+            if (!dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark)) // only allowed converting between checkbox <-> dropdown
+                return nullptr;
         }
         else if(rNewType == ODF_FORMCHECKBOX)
         {
             if (!dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark))
                 bActualChange = true;
+            if (!dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldmark)) // only allowed converting between checkbox <-> dropdown
+                return nullptr;
         }
         else if(rNewType == ODF_FORMDATE)
         {
             if (!dynamic_cast<::sw::mark::DateFieldmark*>(pFieldmark))
                 bActualChange = true;
+            if (!dynamic_cast<::sw::mark::TextFieldmark*>(pFieldmark)) // only allowed converting between date field <-> text field
+                return nullptr;
         }
 
         if (!bActualChange)
@@ -1148,13 +1164,20 @@ namespace sw { namespace mark
         SwPaM aPaM(pFieldmark->GetMarkPos());
 
         // Remove the old fieldmark and create a new one with the new type
-        if(aPaM.GetPoint()->nContent > 0)
+        if(aPaM.GetPoint()->nContent > 0 && (rNewType == ODF_FORMDROPDOWN || rNewType == ODF_FORMCHECKBOX))
         {
             --aPaM.GetPoint()->nContent;
             SwPosition aNewPos (aPaM.GetPoint()->nNode, aPaM.GetPoint()->nContent);
             deleteFieldmarkAt(aNewPos);
             return makeNoTextFieldBookmark(aPaM, sName, rNewType);
         }
+        else if(rNewType == ODF_FORMDATE)
+        {
+            SwPosition aPos (aPaM.GetPoint()->nNode, aPaM.GetPoint()->nContent);
+            SwPaM aNewPaM(pFieldmark->GetMarkStart(), pFieldmark->GetMarkEnd());
+            deleteFieldmarkAt(aPos);
+            return makeFieldBookmark(aNewPaM, sName, rNewType);
+        }
         return nullptr;
     }
 
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
index 6e05a171ce34..0bf8f1e97cdc 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -91,7 +91,7 @@ namespace sw {
             virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const override;
 
             virtual void deleteFieldmarkAt(const SwPosition& rPos) override;
-            virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) override;
+            virtual ::sw::mark::IFieldmark* changeFormFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) override;
 
             virtual void NotifyCursorUpdate(const SwCursorShell& rCursorShell) override;
             virtual void ClearFieldActivation() override;
diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx
index 75cd7b1b5c64..34a01ea20995 100644
--- a/sw/source/core/inc/bookmrk.hxx
+++ b/sw/source/core/inc/bookmrk.hxx
@@ -267,15 +267,11 @@ namespace sw {
             FieldmarkWithDropDownButton(const SwPaM& rPaM);
             virtual ~FieldmarkWithDropDownButton() override;
 
-            // This method should be called only by the portion so we can now the portion's painting area
-            void SetPortionPaintArea(const SwRect& rPortionPaintArea);
-
             virtual void ShowButton(SwEditWin* pEditWin) = 0;
             void HideButton();
             void RemoveButton();
 
         protected:
-            SwRect m_aPortionPaintArea;
             VclPtr<FormFieldButton> m_pButton;
         };
 
@@ -288,22 +284,47 @@ namespace sw {
             virtual ~DropDownFieldmark() override;
 
             virtual void ShowButton(SwEditWin* pEditWin) override;
+
+            // This method should be called only by the portion so we can now the portion's painting area
+            void SetPortionPaintArea(const SwRect& rPortionPaintArea);
+
+        private:
+            SwRect m_aPortionPaintArea;
         };
 
         /// Fieldmark representing a date form field.
         class DateFieldmark
-            : public FieldmarkWithDropDownButton
+            : virtual public IDateFieldmark
+            , public FieldmarkWithDropDownButton
         {
         public:
             DateFieldmark(const SwPaM& rPaM);
             virtual ~DateFieldmark() override;
 
             virtual void InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) override;
+            virtual void ReleaseDoc(SwDoc* const pDoc) override;
 
             virtual void ShowButton(SwEditWin* pEditWin) override;
 
+            void SetPortionPaintAreaStart(const SwRect& rPortionPaintArea);
+            void SetPortionPaintAreaEnd(const SwRect& rPortionPaintArea);
+
+            virtual OUString GetContent() const override;
+            virtual void ReplaceContent(const OUString& sNewContent) override;
+
+            virtual std::pair<bool, double> GetCurrentDate() const override;
+            virtual void SetCurrentDate(double fDate) override;
+            virtual OUString GetDateInStandardDateFormat(double fDate) const override;
+
         private:
+            OUString GetDateInCurrentDateFormat(double fDate) const;
+            std::pair<bool, double> ParseCurrentDateParam() const;
+            void InvalidateCurrentDateParam();
+
             SvNumberFormatter* m_pNumberFormatter;
+            sw::DocumentContentOperationsManager* m_pDocumentContentOperationsManager;
+            SwRect m_aPaintAreaStart;
+            SwRect m_aPaintAreaEnd;
         };
     }
 }
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 988a14c18937..9af1839e2bf3 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -863,78 +863,6 @@ namespace sw { namespace mark {
         sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
         return OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH);
     }
-
-    static OUString ExpandDateFieldmark(IFieldmark* pBM, SvNumberFormatter* pFormatter)
-    {
-        OUString sDateFormat;
-        mark::IFieldmark::parameter_map_t* pParameters = pBM->GetParameters();
-        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;
-        }
-
-        double dCurrentDate = 0.0;
-        bool bHasCurrentDate = false;
-        pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
-        if (pResult != pParameters->end())
-        {
-            OUString sFormattedDate;
-            pResult->second >>= sFormattedDate;
-
-            sal_uInt32 nFormat = pFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE);
-            if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
-            {
-                sal_Int32 nCheckPos = 0;
-                short nType;
-                OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
-                pFormatter->PutEntry(sFormat,
-                                     nCheckPos,
-                                     nType,
-                                     nFormat,
-                                     ODF_FORMDATE_CURRENTDATE_LANGUAGE);
-            }
-
-            if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
-            {
-                pFormatter->IsNumberFormat(sFormattedDate, nFormat, dCurrentDate);
-                bHasCurrentDate = true;
-            }
-        }
-
-        if (!sDateFormat.isEmpty() && !sLang.isEmpty() && bHasCurrentDate)
-        {
-            sal_uInt32 nFormat = pFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType());
-            if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
-            {
-                sal_Int32 nCheckPos = 0;
-                short nType;
-                pFormatter->PutEntry(sDateFormat,
-                                     nCheckPos,
-                                     nType,
-                                     nFormat,
-                                     LanguageTag(sLang).getLanguageType());
-            }
-
-            OUString sOutput;
-            if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
-            {
-                Color* pCol = nullptr;
-                pFormatter->GetOutputString(dCurrentDate, nFormat, sOutput, &pCol, false);
-            }
-            return sOutput;
-        }
-
-        sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
-        return OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH);
-    }
 } }
 
 SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const
@@ -961,17 +889,24 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const
             // Only at the End!
             // If pCurr does not have a width, it can however already have content.
             // E.g. for non-displayable characters
-            if (rInf.GetText()[rInf.GetIdx()]==CH_TXT_ATR_FIELDSTART)
+            SwTextNode *pNd = rInf.GetTextFrame()->GetTextNode();
+            const SwDoc *doc = pNd->GetDoc();
+            SwIndex aIndex(pNd, rInf.GetIdx());
+            SwPosition aPosition(*pNd, aIndex);
+            sw::mark::IFieldmark *pBM = doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
+            if(pBM != nullptr && pBM->GetFieldname( ) == ODF_FORMDATE)
+            {
+                if (rInf.GetText()[rInf.GetIdx()] == CH_TXT_ATR_FIELDSTART)
+                    pPor = new SwFieldFormDatePortion(pBM, true);
+                else if (rInf.GetText()[rInf.GetIdx()] == CH_TXT_ATR_FIELDEND)
+                    pPor = new SwFieldFormDatePortion(pBM, false);
+            }
+            else if (rInf.GetText()[rInf.GetIdx()] == CH_TXT_ATR_FIELDSTART)
                 pPor = new SwFieldMarkPortion();
             else if (rInf.GetText()[rInf.GetIdx()]==CH_TXT_ATR_FIELDEND)
                 pPor = new SwFieldMarkPortion();
             else if (rInf.GetText()[rInf.GetIdx()]==CH_TXT_ATR_FORMELEMENT)
             {
-                SwTextNode *pNd = rInf.GetTextFrame()->GetTextNode();
-                const SwDoc *doc = pNd->GetDoc();
-                SwIndex aIndex(pNd, rInf.GetIdx());
-                SwPosition aPosition(*pNd, aIndex);
-                sw::mark::IFieldmark *pBM = doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
                 OSL_ENSURE(pBM != nullptr, "Where is my form field bookmark???");
                 if (pBM != nullptr)
                 {
@@ -983,11 +918,6 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const
                     {
                         pPor = new SwFieldFormDropDownPortion(pBM, sw::mark::ExpandFieldmark(pBM));
                     }
-                    else if (pBM->GetFieldname( ) == ODF_FORMDATE)
-                    {
-                        SvNumberFormatter* pFormatter = const_cast<SvNumberFormatter*>(doc->GetNumberFormatter());
-                        pPor = new SwFieldFormDatePortion(pBM, sw::mark::ExpandDateFieldmark(pBM, pFormatter));
-                    }
                     /* we need to check for ODF_FORMTEXT for scenario having FormFields inside FORMTEXT.
                      * Otherwise file will crash on open.
                      */
diff --git a/sw/source/core/text/porfld.cxx b/sw/source/core/text/porfld.cxx
index af29eaec97fe..c959f0125a6a 100644
--- a/sw/source/core/text/porfld.cxx
+++ b/sw/source/core/text/porfld.cxx
@@ -1332,9 +1332,9 @@ void SwFieldFormDropDownPortion::Paint( const SwTextPaintInfo &rInf ) const
     }
 }
 
-SwFieldPortion *SwFieldFormDatePortion::Clone(const OUString &rExpand) const
+SwFieldPortion *SwFieldFormDatePortion::Clone(const OUString &/*rExpand*/) const
 {
-    return new SwFieldFormDatePortion(m_pFieldMark, rExpand);
+    return new SwFieldFormDatePortion(m_pFieldMark, m_bStart);
 }
 
 void SwFieldFormDatePortion::Paint( const SwTextPaintInfo &rInf ) const
@@ -1346,7 +1346,10 @@ void SwFieldFormDatePortion::Paint( const SwTextPaintInfo &rInf ) const
     {
         SwRect aPaintArea;
         rInf.CalcRect( *this, &aPaintArea );
-        pDateField->SetPortionPaintArea(aPaintArea);
+        if(m_bStart)
+            pDateField->SetPortionPaintAreaStart(aPaintArea);
+        else
+            pDateField->SetPortionPaintAreaEnd(aPaintArea);
     }
 }
 
diff --git a/sw/source/core/text/porfld.hxx b/sw/source/core/text/porfld.hxx
index f16b1b2e7c1c..80bf49347b51 100644
--- a/sw/source/core/text/porfld.hxx
+++ b/sw/source/core/text/porfld.hxx
@@ -243,18 +243,20 @@ private:
 class SwFieldFormDatePortion : public SwFieldPortion
 {
 public:
-    explicit SwFieldFormDatePortion(sw::mark::IFieldmark *pFieldMark, const OUString &rExpand)
-        : SwFieldPortion(rExpand)
+    explicit SwFieldFormDatePortion(sw::mark::IFieldmark *pFieldMark, bool bStart)
+        : SwFieldPortion("")
         , m_pFieldMark(pFieldMark)
+        , m_bStart(bStart)
     {
     }
     // Field cloner for SplitGlue
-    virtual SwFieldPortion *Clone( const OUString &rExpand ) const override;
+    virtual SwFieldPortion *Clone( const OUString &rExpand) const override;
 
     virtual void Paint( const SwTextPaintInfo &rInf ) const override;
 
 private:
     sw::mark::IFieldmark* m_pFieldMark;
+    bool m_bStart;
 };
 
 #endif
diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx
index ed058fb3ccd6..850add3db92a 100644
--- a/sw/source/core/unocore/unobkm.cxx
+++ b/sw/source/core/unocore/unobkm.cxx
@@ -560,7 +560,7 @@ void SwXFieldmark::setFieldType(const OUString & fieldType)
     {
         if(fieldType == ODF_FORMDROPDOWN || fieldType == ODF_FORMCHECKBOX || fieldType == ODF_FORMDATE)
         {
-            ::sw::mark::IFieldmark* pNewFieldmark = GetIDocumentMarkAccess()->changeNonTextFieldmarkType(pBkm, fieldType);
+            ::sw::mark::IFieldmark* pNewFieldmark = GetIDocumentMarkAccess()->changeFormFieldmarkType(pBkm, fieldType);
             if (pNewFieldmark)
             {
                 registerInMark(*this, pNewFieldmark);
@@ -607,7 +607,7 @@ SwXFieldmark::CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark *const pMark,
         else if (dynamic_cast< ::sw::mark::DropDownFieldmark* >(pMark))
             pXBkmk = new SwXFieldmark(true, &rDoc);
         else if (dynamic_cast< ::sw::mark::DateFieldmark* >(pMark))
-            pXBkmk = new SwXFieldmark(true, &rDoc);
+            pXBkmk = new SwXFieldmark(false, &rDoc);
         else
             pXBkmk = new SwXFieldmark(isReplacementObject, &rDoc);
 
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 3c58ae0076c3..91127dcc333a 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1660,21 +1660,18 @@ void DocxAttributeOutput::WriteFFData(  const FieldInfos& rInfos )
     }
 }
 
-void DocxAttributeOutput::WriteFormDate(const OUString& sCurrentDate, const OUString& sDateFormat, const OUString& sLang)
+void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang)
 {
     m_pSerializer->startElementNS(XML_w, XML_sdt, FSEND);
     m_pSerializer->startElementNS(XML_w, XML_sdtPr, FSEND);
 
-    if (!sCurrentDate.isEmpty())
-    {
-        OString sDate = sCurrentDate.toUtf8() + "T00:00:00Z";
-        m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), sDate, FSEND);
-    }
+    if(!sFullDate.isEmpty())
+        m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), sFullDate.toUtf8(), FSEND);
     else
         m_pSerializer->startElementNS(XML_w, XML_date, FSEND);
 
-    OString sUTF8DateFormat = sDateFormat.toUtf8();
     // Replace quotation mark used for marking static strings in date format
+    OString sUTF8DateFormat = sDateFormat.toUtf8();
     sUTF8DateFormat = sUTF8DateFormat.replaceAll("\"", "'");
     m_pSerializer->singleElementNS(XML_w, XML_dateFormat,
                                    FSNS(XML_w, XML_val), sUTF8DateFormat, FSEND);
@@ -1689,58 +1686,11 @@ void DocxAttributeOutput::WriteFormDate(const OUString& sCurrentDate, const OUSt
     m_pSerializer->endElementNS(XML_w, XML_sdtPr);
 
     m_pSerializer->startElementNS(XML_w, XML_sdtContent, FSEND);
-    m_pSerializer->startElementNS(XML_w, XML_r, FSEND);
-
-    // Convert the current date to the right format
-    if (!sCurrentDate.isEmpty())
-    {
-        SvNumberFormatter* pFormatter = m_rExport.m_pDoc->GetNumberFormatter();
-        double dCurrentDate = 0.0;
-        // First get the date internal double representation
-        sal_uInt32 nFormat = pFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE);
-        if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
-        {
-            sal_Int32 nCheckPos = 0;
-            short nType;
-            OUString sFormat = ODF_FORMDATE_CURRENTDATE_FORMAT;
-            pFormatter->PutEntry(sFormat,
-                                 nCheckPos,
-                                 nType,
-                                 nFormat,
-                                 ODF_FORMDATE_CURRENTDATE_LANGUAGE);
-        }
-        if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
-        {
-            pFormatter->IsNumberFormat(sCurrentDate, nFormat, dCurrentDate);
-        }
-
-        // Then convert the date to a fromatter string
-        nFormat = pFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType());
-        if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
-        {
-            sal_Int32 nCheckPos = 0;
-            short nType;
-            OUString sNonConstDateFormat = sDateFormat;
-            pFormatter->PutEntry(sNonConstDateFormat,
-                                 nCheckPos,
-                                 nType,
-                                 nFormat,
-                                 LanguageTag(sLang).getLanguageType());
-        }
-
-        OUString sOutput;
-        if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
-        {
-            Color* pCol = nullptr;
-            pFormatter->GetOutputString(dCurrentDate, nFormat, sOutput, &pCol, false);
-        }
-
-        RunText(sOutput);
-    }
+}
 
-    m_pSerializer->endElementNS(XML_w, XML_r);
+void DocxAttributeOutput::WriteFormDateEnd()
+{
     m_pSerializer->endElementNS(XML_w, XML_sdtContent);
-
     m_pSerializer->endElementNS(XML_w, XML_sdt);
 }
 
@@ -1753,17 +1703,31 @@ void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nP
     }
     else if ( rInfos.eType == ww::eFORMDATE )
     {
-        const ::sw::mark::IFieldmark& rFieldmark = *rInfos.pFieldmark;
-        FieldMarkParamsHelper params( rFieldmark );
+        const sw::mark::IDateFieldmark* const pFieldmark = dynamic_cast<const sw::mark::IDateFieldmark* const>(rInfos.pFieldmark);
+        FieldMarkParamsHelper params( *pFieldmark );
 
+        OUString sFullDate;
         OUString sCurrentDate;
         params.extractParam( ODF_FORMDATE_CURRENTDATE, sCurrentDate );
+        if(!sCurrentDate.isEmpty())
+        {
+            sFullDate = sCurrentDate + "T00:00:00Z";
+        }
+        else
+        {
+            std::pair<bool, double> aResult = pFieldmark->GetCurrentDate();
+            if(aResult.first)
+            {
+                sFullDate = pFieldmark->GetDateInStandardDateFormat(aResult.second) + "T00:00:00Z";
+            }
+        }
+
         OUString sDateFormat;
         params.extractParam( ODF_FORMDATE_DATEFORMAT, sDateFormat );
         OUString sLang;
         params.extractParam( ODF_FORMDATE_DATEFORMAT_LANGUAGE, sLang );
 
-        WriteFormDate( sCurrentDate, sDateFormat, sLang );
+        WriteFormDateStart( sFullDate, sDateFormat, sLang );
     }
     else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
     {
@@ -1995,6 +1959,12 @@ void DocxAttributeOutput::DoWriteFieldRunProperties( const SwTextNode * pNode, s
 
 void DocxAttributeOutput::EndField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos& rInfos )
 {
+    if ( rInfos.eType == ww::eFORMDATE )
+    {
+        WriteFormDateEnd();
+        return;
+    }
+
     // The command has to be written before for the hyperlinks
     if ( rInfos.pField )
     {
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index ad5b94f0b6c6..ed3c79634605 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -715,7 +715,8 @@ private:
     /// Closes a currently open SDT block.
     void EndSdtBlock();
 
-    void WriteFormDate(const OUString& sCurrentDate, const OUString& sDateFormat, const OUString& sLang);
+    void WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang);
+    void WriteFormDateEnd();
 
     void StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun = false );
     void DoWriteCmd( const OUString& rCmd );
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index ccfce360f49c..0ddb40dfd1f3 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -159,6 +159,9 @@ void DocxExport::AppendBookmarks( const SwTextNode& rNode, sal_Int32 nAktPos, sa
             const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
             const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
 
+            if (dynamic_cast<sw::mark::IDateFieldmark*>(pMark))
+                continue;
+
             if ( nStart == nAktPos )
                 aStarts.push_back( pMark->GetName() );
 
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index cdc1da93f6fe..c1c9de724f6d 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2436,49 +2436,64 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                     ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
                     OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
 
-                    if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT
-                         && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
+                    // Date field is exported as content control, not as a simple field
+                    if(pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMDATE)
                     {
-                       AppendBookmark( pFieldmark->GetName() );
+                        if(GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only
+                        {
+                            OutputField( nullptr, lcl_getFieldId( pFieldmark ),
+                                    lcl_getFieldCode( pFieldmark ),
+                                    FieldFlags::Start | FieldFlags::CmdStart );
+                            WriteFormData( *pFieldmark );
+                        }
                     }
-                    ww::eField eFieldId = lcl_getFieldId( pFieldmark );
-                    OUString sCode = lcl_getFieldCode( pFieldmark );
-                    if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
+                    else
                     {
-                        IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
-                        if ( it != pFieldmark->GetParameters()->end() )
+
+                        if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT
+                             && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
                         {
-                            OUString sFieldId;
-                            it->second >>= sFieldId;
-                            eFieldId = (ww::eField)sFieldId.toInt32();
+                            AppendBookmark( pFieldmark->GetName() );
                         }
-
-                        it = pFieldmark->GetParameters()->find( ODF_CODE_PARAM );
-                        if ( it != pFieldmark->GetParameters()->end() )
+                        ww::eField eFieldId = lcl_getFieldId( pFieldmark );
+                        OUString sCode = lcl_getFieldCode( pFieldmark );
+                        if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
                         {
-                            it->second >>= sCode;
+                            IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
+                            if ( it != pFieldmark->GetParameters()->end() )
+                            {
+                                OUString sFieldId;
+                                it->second >>= sFieldId;
+                                eFieldId = static_cast<ww::eField>(sFieldId.toInt32());
+                            }
+
+                            it = pFieldmark->GetParameters()->find( ODF_CODE_PARAM );
+                            if ( it != pFieldmark->GetParameters()->end() )
+                            {
+                                it->second >>= sCode;
+                            }
                         }
-                    }
 
-                    OutputField( nullptr, eFieldId, sCode, FieldFlags::Start | FieldFlags::CmdStart );
+                        OutputField( nullptr, eFieldId, sCode, FieldFlags::Start | FieldFlags::CmdStart );
 
-                    if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMTEXT )
-                        WriteFormData( *pFieldmark );
-                    else if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
-                        WriteHyperlinkData( *pFieldmark );
-                    OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::CmdEnd );
+                        if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMTEXT)
+                            WriteFormData( *pFieldmark );
+                        else if ( pFieldmark && pFieldmark->GetFieldname( ) == ODF_HYPERLINK )
+                            WriteHyperlinkData( *pFieldmark );
+                        OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::CmdEnd );
 
-                    if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
-                    {
-                        // Check for the presence of a linked OLE object
-                        IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_OLE_PARAM );
-                        if ( it != pFieldmark->GetParameters()->end() )
+                        if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
                         {
-                            OUString sOleId;
-                            uno::Any aValue = it->second;
-                            aValue >>= sOleId;
-                            if ( !sOleId.isEmpty() )
-                                OutputLinkedOLE( sOleId );
+                            // Check for the presence of a linked OLE object
+                            IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_OLE_PARAM );
+                            if ( it != pFieldmark->GetParameters()->end() )
+                            {
+                                OUString sOleId;
+                                uno::Any aValue = it->second;
+                                aValue >>= sOleId;
+                                if ( !sOleId.isEmpty() )
+                                    OutputLinkedOLE( sOleId );
+                            }
                         }
                     }
                 }
@@ -2489,24 +2504,34 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
 
                     OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDEND??" );
 
-                    ww::eField eFieldId = lcl_getFieldId( pFieldmark );
-                    if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
+                    if(pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMDATE)
                     {
-                        IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
-                        if ( it != pFieldmark->GetParameters()->end() )
+                        if(GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only
                         {
-                            OUString sFieldId;
-                            it->second >>= sFieldId;
-                            eFieldId = (ww::eField)sFieldId.toInt32();
+                            OutputField( nullptr, ww::eFORMDATE, OUString(), FieldFlags::Close );
                         }
                     }
+                    else
+                    {
+                        ww::eField eFieldId = lcl_getFieldId( pFieldmark );
+                        if ( pFieldmark && pFieldmark->GetFieldname() == ODF_UNHANDLED )
+                        {
+                            IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find( ODF_ID_PARAM );
+                            if ( it != pFieldmark->GetParameters()->end() )
+                            {
+                                OUString sFieldId;
+                                it->second >>= sFieldId;
+                                eFieldId = static_cast<ww::eField>(sFieldId.toInt32());
+                            }
+                        }
 
-                    OutputField( nullptr, eFieldId, OUString(), FieldFlags::Close );
+                        OutputField( nullptr, eFieldId, OUString(), FieldFlags::Close );
 
-                    if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT
-                         && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
-                    {
-                        AppendBookmark( pFieldmark->GetName() );
+                        if ( pFieldmark && pFieldmark->GetFieldname() == ODF_FORMTEXT
+                             && GetExportFormat() != MSWordExportBase::ExportFormat::DOCX )
+                        {
+                            AppendBookmark( pFieldmark->GetName() );
+                        }
                     }
                 }
                 else if ( ch == CH_TXT_ATR_FORMELEMENT )
@@ -2514,30 +2539,18 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                     SwPosition aPosition( rNode, SwIndex( &rNode, nAktPos ) );
                     ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
 
-                    // Date field is exported as content control, not as a simple field
-                    if(pFieldmark && pFieldmark->GetFieldname( ) == ODF_FORMDATE &&
-                       GetExportFormat() == MSWordExportBase::ExportFormat::DOCX) // supported by DOCX only
-                    {
-                        OutputField( nullptr, lcl_getFieldId( pFieldmark ),
-                                lcl_getFieldCode( pFieldmark ),
-                                FieldFlags::Start | FieldFlags::CmdStart );
+                    bool isDropdownOrCheckbox = pFieldmark && (pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN ||
+                                                                pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX );
+                    if ( isDropdownOrCheckbox )
+                        AppendBookmark( pFieldmark->GetName() );
+                    OutputField( nullptr, lcl_getFieldId( pFieldmark ),
+                            lcl_getFieldCode( pFieldmark ),
+                            FieldFlags::Start | FieldFlags::CmdStart );
+                    if ( isDropdownOrCheckbox )
                         WriteFormData( *pFieldmark );
-                    }
-                    else
-                    {
-                        bool isDropdownOrCheckbox = pFieldmark && (pFieldmark->GetFieldname( ) == ODF_FORMDROPDOWN ||
-                                                                    pFieldmark->GetFieldname( ) == ODF_FORMCHECKBOX );
-                        if ( isDropdownOrCheckbox )
-                            AppendBookmark( pFieldmark->GetName() );
-                        OutputField( nullptr, lcl_getFieldId( pFieldmark ),
-                                lcl_getFieldCode( pFieldmark ),
-                                FieldFlags::Start | FieldFlags::CmdStart );
-                        if ( isDropdownOrCheckbox )
-                            WriteFormData( *pFieldmark );
-                        OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::Close );
-                        if ( isDropdownOrCheckbox )
-                            AppendBookmark( pFieldmark->GetName() );
-                    }
+                    OutputField( nullptr, lcl_getFieldId( pFieldmark ), OUString(), FieldFlags::Close );
+                    if ( isDropdownOrCheckbox )
+                        AppendBookmark( pFieldmark->GetName() );
                 }
                 nLen -= ofs;
 
diff --git a/sw/source/ui/dialog/swdlgfact.cxx b/sw/source/ui/dialog/swdlgfact.cxx
index 08221eb9d7e8..367255f80478 100644
--- a/sw/source/ui/dialog/swdlgfact.cxx
+++ b/sw/source/ui/dialog/swdlgfact.cxx
@@ -783,7 +783,7 @@ VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDropDownFormFieldD
     return VclPtr<VclAbstractDialog_Impl>::Create( pDlg );
 }
 
-VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDateFormFieldDialog(sw::mark::IFieldmark* pDateField, SwDoc* pDoc)
+VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDateFormFieldDialog(sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc)
 {
     VclPtr<sw::DateFormFieldDialog> pDlg = VclPtr<sw::DateFormFieldDialog>::Create(nullptr, pDateField, pDoc);
     return VclPtr<VclAbstractDialog_Impl>::Create( pDlg );
diff --git a/sw/source/ui/dialog/swdlgfact.hxx b/sw/source/ui/dialog/swdlgfact.hxx
index f86653e3204d..b2b0bec1d8d1 100644
--- a/sw/source/ui/dialog/swdlgfact.hxx
+++ b/sw/source/ui/dialog/swdlgfact.hxx
@@ -415,8 +415,9 @@ public:
 
     virtual VclPtr<AbstractDropDownFieldDialog> CreateDropDownFieldDialog(SwWrtShell &rSh,
         SwField* pField, bool bPrevButton, bool bNextButton) override;
+
     virtual VclPtr<VclAbstractDialog> CreateDropDownFormFieldDialog(sw::mark::IFieldmark* pDropDownField) override;
-    virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(sw::mark::IFieldmark* pDateField, SwDoc* pDoc) override;
+    virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc) override;
     virtual VclPtr<SfxAbstractTabDialog> CreateSwEnvDlg ( vcl::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtSh, Printer* pPrt, bool bInsert ) override;
     virtual VclPtr<AbstractSwLabDlg> CreateSwLabDlg(const SfxItemSet& rSet,
                                                      SwDBManager* pDBManager, bool bLabel) override;
diff --git a/sw/source/ui/fldui/DateFormFieldDialog.cxx b/sw/source/ui/fldui/DateFormFieldDialog.cxx
index 45c607b0084c..c0c3dbe59199 100644
--- a/sw/source/ui/fldui/DateFormFieldDialog.cxx
+++ b/sw/source/ui/fldui/DateFormFieldDialog.cxx
@@ -18,7 +18,7 @@
 
 namespace sw
 {
-DateFormFieldDialog::DateFormFieldDialog(vcl::Window* pParent, mark::IFieldmark* pDateField,
+DateFormFieldDialog::DateFormFieldDialog(vcl::Window* pParent, mark::IDateFieldmark* pDateField,
                                          SwDoc* pDoc)
     : SvxStandardDialog(pParent, "DateFormFieldDialog", "modules/swriter/ui/dateformfielddialog.ui")
     , m_pDateField(pDateField)
@@ -46,12 +46,28 @@ void DateFormFieldDialog::Apply()
 {
     if (m_pDateField != nullptr)
     {
-        const SvNumberformat* pFormat = m_pNumberFormatter->GetEntry(m_xFormatLB->GetFormat());
+        // Try to find out the current date value and replace the content
+        // with the right formatted date string
         sw::mark::IFieldmark::parameter_map_t* pParameters = m_pDateField->GetParameters();
+        const SvNumberformat* pFormat = m_pNumberFormatter->GetEntry(m_xFormatLB->GetFormat());
+
+        // Get date value first
+        std::pair<bool, double> aResult = m_pDateField->GetCurrentDate();
+
+        // Then set the date format
         (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring();
+        (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE]
+            <<= LanguageTag(pFormat->GetLanguage()).getBcp47();
 
-        LanguageType aLang = pFormat->GetLanguage();
-        (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(aLang).getBcp47();
+        // Update current date
+        if (aResult.first)
+        {
+            m_pDateField->SetCurrentDate(aResult.second);
+        }
+        else
+        {
+            (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= OUString();
+        }
     }
 }
 
@@ -78,16 +94,16 @@ void DateFormFieldDialog::InitControls()
         if (!sFormatString.isEmpty() && !sLang.isEmpty())
         {
             LanguageType aLangType = LanguageTag(sLang).getLanguageType();
-            sal_uInt32 nFormatKey = m_pNumberFormatter->GetEntryKey(sFormatString, aLangType);
-            if (nFormatKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
+            sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(sFormatString, aLangType);
+            if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
             {
                 sal_Int32 nCheckPos = 0;
                 short nType;
-                m_pNumberFormatter->PutEntry(sFormatString, nCheckPos, nType, nFormatKey,
+                m_pNumberFormatter->PutEntry(sFormatString, nCheckPos, nType, nFormat,
                                              LanguageTag(sLang).getLanguageType());
             }
 
-            if (aLangType != LANGUAGE_DONTKNOW && nFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND)
+            if (aLangType != LANGUAGE_DONTKNOW && nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
             {
                 if (m_xFormatLB->GetCurLanguage() == aLangType)
                 {
@@ -102,7 +118,7 @@ void DateFormFieldDialog::InitControls()
                     m_xFormatLB->SetFormatType(css::util::NumberFormat::ALL);
                     m_xFormatLB->SetFormatType(css::util::NumberFormat::DATE);
                 }
-                m_xFormatLB->SetDefFormat(nFormatKey);
+                m_xFormatLB->SetDefFormat(nFormat);
             }
         }
     }
diff --git a/sw/source/uibase/inc/DateFormFieldDialog.hxx b/sw/source/uibase/inc/DateFormFieldDialog.hxx
index b62cb0009865..9e73f6604c97 100644
--- a/sw/source/uibase/inc/DateFormFieldDialog.hxx
+++ b/sw/source/uibase/inc/DateFormFieldDialog.hxx
@@ -21,7 +21,7 @@ namespace sw
 {
 namespace mark
 {
-class IFieldmark;
+class IDateFieldmark;
 }
 } // namespace sw
 
@@ -31,7 +31,7 @@ namespace sw
 class DateFormFieldDialog : public SvxStandardDialog
 {
 private:
-    mark::IFieldmark* m_pDateField;
+    sw::mark::IDateFieldmark* m_pDateField;
     SvNumberFormatter* m_pNumberFormatter;
 
     VclPtr<NumFormatListBox> m_xFormatLB;
@@ -40,7 +40,7 @@ private:
     void InitControls();
 
 public:
-    DateFormFieldDialog(vcl::Window* pParent, mark::IFieldmark* pDateField, SwDoc* pDoc);
+    DateFormFieldDialog(vcl::Window* pParent, sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc);
     virtual ~DateFormFieldDialog() override;
     virtual void dispose() override;
 };
diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx
index be599349a86f..8af1da077698 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -733,17 +733,25 @@ FIELD_INSERT:
             SwPaM* pCursorPos = rSh.GetCursor();
             if(pCursorPos)
             {
-                IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
-                sw::mark::IFieldmark* pFieldBM = pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMDATE);
-
-                // Use a default date format and language
-                sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldBM->GetParameters();
-                SvNumberFormatter* pFormatter = rSh.GetDoc()->GetNumberFormatter();
-                sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(css::util::NumberFormat::DATE);
-                const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat);
-
-                (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring();
-                (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(pFormat->GetLanguage()).getBcp47();
+                // Insert five enspaces into the text field so the field has extent
+                sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
+                bool bSuccess = rSh.GetDoc()->getIDocumentContentOperations().InsertString(*pCursorPos, OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH));
+                if(bSuccess)
+                {
+                    IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
+                    SwPaM aFieldPam(pCursorPos->GetPoint()->nNode, pCursorPos->GetPoint()->nContent.GetIndex()-5,
+                                    pCursorPos->GetPoint()->nNode, pCursorPos->GetPoint()->nContent.GetIndex());
+                    sw::mark::IFieldmark* pFieldBM = pMarksAccess->makeFieldBookmark(aFieldPam, OUString(), ODF_FORMDATE);
+
+                    // Use a default date format and language
+                    sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldBM->GetParameters();
+                    SvNumberFormatter* pFormatter = rSh.GetDoc()->GetNumberFormatter();
+                    sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(css::util::NumberFormat::DATE);
+                    const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat);
+
+                    (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring();
+                    (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(pFormat->GetLanguage()).getBcp47();
+                }
             }
 
             rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx
index 28f59f61e9f7..ce9599b82334 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -1414,7 +1414,8 @@ void SwTextShell::Execute(SfxRequest &rReq)
         else if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDATE )
         {
             SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
-            ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDateFormFieldDialog(pFieldBM, GetView().GetDocShell()->GetDoc()));
+            sw::mark::DateFieldmark* pDateField = dynamic_cast<sw::mark::DateFieldmark*>(pFieldBM);
+            ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDateFormFieldDialog(pDateField, GetView().GetDocShell()->GetDoc()));
             if (pDlg->Execute() == RET_OK)
             {
                 pFieldBM->Invalidate();
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 1c4498d393b5..936523501232 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2568,6 +2568,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
     case NS_ooxml::LN_CT_SdtPr_date:
     {
         resolveSprmProps(*this, rSprm);
+        m_pImpl->m_pSdtHelper->setDateFieldStartRange(GetCurrentTextRange()->getEnd());
     }
     break;
     case NS_ooxml::LN_CT_SdtDate_dateFormat:
@@ -3168,10 +3169,6 @@ void DomainMapper::lcl_startCharacterGroup()
         // call setSdtEndDeferred(false) here, that will happen only in lcl_utext().
         m_pImpl->GetTopContext()->Insert(PROP_SDT_END_BEFORE, uno::makeAny(true), true, CHAR_GRAB_BAG);
     }
-
-    // Remember formatting of the date control as it only supports plain strings natively.
-    if (!m_pImpl->m_pSdtHelper->getDateFormat().isEmpty())
-        enableInteropGrabBag("CharFormat");
 }
 
 void DomainMapper::lcl_endCharacterGroup()
@@ -3340,48 +3337,43 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
             return;
         }
     }
-    else if (m_pImpl->m_pSdtHelper->validateDateFormat())
-    {
-        // Date field will be imported, so we don't need the corresponding date text in most of the cases
-        // however when fullDate is not specified, but we have a date string we need to import it as
-        // simple text (this is the case when user sets date field manually in MSO).
-        if((!m_pImpl->m_pSdtHelper->getDate().toString().isEmpty() || sText.isEmpty()) &&
-           (!IsInHeaderFooter() || !m_pImpl->IsDiscardHeaderFooter())) // discard date control with header / footer
-        {
-            return;
-        }
-        // Remove date field attributes to avoid to import an actual date field
-        m_pImpl->m_pSdtHelper->getDateFormat().truncate();
-        m_pImpl->m_pSdtHelper->getLocale().truncate();
-    }
     else if (!m_pImpl->m_pSdtHelper->isInteropGrabBagEmpty())
     {
-        // there are unsupported SDT properties in the document
-        // save them in the paragraph interop grab bag
-        if (m_pImpl->IsDiscardHeaderFooter())
+         // Ignore grabbag when we have a date field, it can conflict during export
+        if(m_pImpl->m_pSdtHelper->validateDateFormat())
         {
-            // Unless we're supposed to ignore this header/footer.
             m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
-            return;
         }
-        if((m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_checkbox") ||
-                m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_text") ||
-                m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_dataBinding") ||
-                m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_citation") ||
-                (m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_id") &&
-                        m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1)) && !m_pImpl->m_pSdtHelper->isOutsideAParagraph())
+        else
         {
-            PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_CHARACTER);
 
-            if (m_pImpl->IsOpenField())
-                // We have a field, insert the SDT properties to the field's grab-bag, so they won't be lost.
-                pContext = m_pImpl->GetTopFieldContext()->getProperties();
+            // there are unsupported SDT properties in the document
+            // save them in the paragraph interop grab bag
+            if (m_pImpl->IsDiscardHeaderFooter())
+            {
+                // Unless we're supposed to ignore this header/footer.
+                m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
+                return;
+            }
+            if((m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_checkbox") ||
+                    m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_text") ||
+                    m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_dataBinding") ||
+                    m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_citation") ||
+                    (m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_id") &&
+                            m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1)) && !m_pImpl->m_pSdtHelper->isOutsideAParagraph())
+            {
+                PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_CHARACTER);
 
-            pContext->Insert(PROP_SDTPR, uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, CHAR_GRAB_BAG);
+                if (m_pImpl->IsOpenField())
+                    // We have a field, insert the SDT properties to the field's grab-bag, so they won't be lost.
+                    pContext = m_pImpl->GetTopFieldContext()->getProperties();
+
+                pContext->Insert(PROP_SDTPR, uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, CHAR_GRAB_BAG);
+            }
+            else
+                m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)->Insert(PROP_SDTPR,
+                        uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, PARA_GRAB_BAG);
         }
-        else
-            m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)->Insert(PROP_SDTPR,
-                    uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, PARA_GRAB_BAG);
     }
     else if (len == 1 && sText[0] == 0x03)
     {
@@ -3394,6 +3386,21 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
         m_pImpl->m_bIgnoreNextTab = false;
         return;
     }
+    else if (m_pImpl->m_pSdtHelper->validateDateFormat())
+    {
+        if(IsInHeaderFooter() && m_pImpl->IsDiscardHeaderFooter())
+        {
+            m_pImpl->m_pSdtHelper->getDateFormat().truncate();
+            m_pImpl->m_pSdtHelper->getLocale().truncate();
+            return;
+        }
+        if((m_pImpl->hasTableManager() && m_pImpl->getTableManager().isInTable()) ||
+            m_pImpl->m_nTableDepth > 0)
+        {
+            // Inside a table we need to import date field earlier
+            m_pImpl->m_pSdtHelper->createDateContentControl(true);
+        }
+    }
 
     if (!m_pImpl->hasTableManager())
         return;
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx
index 7dd3c2d8a32d..22c3ceafe464 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -91,24 +91,40 @@ bool SdtHelper::validateDateFormat() const
     return !m_sDateFormat.toString().isEmpty() && !m_sLocale.toString().isEmpty();
 }
 
-void SdtHelper::createDateContentControl()
+void SdtHelper::createDateContentControl(bool bInsideTable)
 {
+    if(!m_xDateFieldStartRange.is())
+        return;
+
     uno::Reference<text::XTextCursor> xCrsr;
     if(m_rDM_Impl.HasTopText())
     {
         uno::Reference<text::XTextAppend> xTextAppend = m_rDM_Impl.GetTopTextAppend();
         if (xTextAppend.is())
-            xCrsr = xTextAppend->createTextCursorByRange(xTextAppend->getEnd());
+        {
+            xCrsr = xTextAppend->createTextCursorByRange(xTextAppend);
+        }
     }
     if (xCrsr.is())
     {
+        try
+        {
+            xCrsr->gotoRange(m_xDateFieldStartRange, false);
+            if(bInsideTable)
+                xCrsr->goRight(1, false);
+            xCrsr->gotoEnd(true);
+        }
+        catch (uno::Exception&) {
+            OSL_ENSURE(false, "Cannot get the right text range for date field");
+            return;
+        }
+
         uno::Reference< uno::XInterface > xFieldInterface;
-        xFieldInterface = m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.text.FormFieldmark");
+        xFieldInterface = m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.text.Fieldmark");
         uno::Reference< text::XFormField > xFormField( xFieldInterface, uno::UNO_QUERY );
         uno::Reference< text::XTextContent > xToInsert(xFormField, uno::UNO_QUERY);
         if ( xFormField.is() && xToInsert.is() )
         {
-            xCrsr->gotoEnd(true);
             xToInsert->attach( uno::Reference< text::XTextRange >( xCrsr, uno::UNO_QUERY_THROW ));
             xFormField->setFieldType(ODF_FORMDATE);
             uno::Reference<container::XNameContainer> xNameCont = xFormField->getParameters();
@@ -119,15 +135,14 @@ void SdtHelper::createDateContentControl()
                 sDateFormat = sDateFormat.replaceAll("'", "\"");
                 xNameCont->insertByName(ODF_FORMDATE_DATEFORMAT, uno::makeAny(sDateFormat));
                 xNameCont->insertByName(ODF_FORMDATE_DATEFORMAT_LANGUAGE, uno::makeAny(m_sLocale.makeStringAndClear()));
-                OUString sDate = m_sDate.makeStringAndClear();
-                if(!sDate.isEmpty())
-                {
-                    // Remove time part of the full date
-                    sal_Int32 nTimeSep = sDate.indexOf("T");
-                    if(nTimeSep != -1)
-                        sDate = sDate.copy(0, nTimeSep);
-                    xNameCont->insertByName(ODF_FORMDATE_CURRENTDATE, uno::makeAny(sDate));
-                }
+            }
+            OUString sFullDate = m_sDate.makeStringAndClear();
+            if(!sFullDate.isEmpty())
+            {
+                sal_Int32 nTimeSep = sFullDate.indexOf("T");
+                if(nTimeSep != -1)
+                    sFullDate = sFullDate.copy(0, nTimeSep);
+                xNameCont->insertByName(ODF_FORMDATE_CURRENTDATE, uno::makeAny(sFullDate));
             }
         }
     }
diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx
index 94eb0098230b..0e229ce0fcdf 100644
--- a/writerfilter/source/dmapper/SdtHelper.hxx
+++ b/writerfilter/source/dmapper/SdtHelper.hxx
@@ -13,6 +13,8 @@
 #include <vector>
 
 #include <boost/optional.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
 
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <rtl/ustrbuf.hxx>
@@ -57,6 +59,8 @@ class SdtHelper final
     OUStringBuffer m_sDate;
     /// Date format string as it comes from the ooxml document.
     OUStringBuffer m_sDateFormat;
+    /// Start range of the date field
+    css::uno::Reference<css::text::XTextRange> m_xDateFieldStartRange;
     /// Locale string as it comes from the ooxml document.
     OUStringBuffer m_sLocale;
     /// Grab bag to store unsupported SDTs, aiming to save them back on export.
@@ -80,14 +84,25 @@ public:
     {
         return m_aSdtTexts;
     }
+
     OUStringBuffer& getDate()
     {
         return m_sDate;
     }
+
     OUStringBuffer& getDateFormat()
     {
         return m_sDateFormat;
     }
+
+    void setDateFieldStartRange(const css::uno::Reference<css::text::XTextRange>& xStartRange)
+    {
+        m_xDateFieldStartRange = xStartRange;
+    }
+
+    /// Decides if we have enough information to create a date control.
+    bool validateDateFormat() const;
+
     OUStringBuffer& getLocale()
     {
         return m_sLocale;
@@ -111,9 +126,8 @@ public:
     /// Create drop-down control from w:sdt's w:dropDownList.
     void createDropDownControl();
 
-    bool validateDateFormat() const;
     /// Create date control from w:sdt's w:date.
-    void createDateContentControl();
+    void createDateContentControl(bool bInsideTable = false);
 
     void appendToInteropGrabBag(const css::beans::PropertyValue& rValue);
     css::uno::Sequence<css::beans::PropertyValue> getInteropGrabBagAndClear();
diff --git a/xmloff/source/text/XMLTextMarkImportContext.cxx b/xmloff/source/text/XMLTextMarkImportContext.cxx
index a168788b7c9d..379ecbe6385a 100644
--- a/xmloff/source/text/XMLTextMarkImportContext.cxx
+++ b/xmloff/source/text/XMLTextMarkImportContext.cxx
@@ -135,8 +135,6 @@ static const char *lcl_getFormFieldmarkName(OUString const &name)
     else if (name == ODF_FORMDROPDOWN ||
              name == "ecma.office-open-xml.field.FORMDROPDOWN")
         return ODF_FORMDROPDOWN;
-    else if (name == ODF_FORMDATE)
-        return ODF_FORMDATE;
     else
         return nullptr;
 }
@@ -323,8 +321,7 @@ void XMLTextMarkImportContext::EndElement()
                                 OUString const type(m_rHelper.getCurrentFieldType());
                                 fieldmarkTypeName = lcl_getFieldmarkName(type);
                                 if (fieldmarkTypeName == ODF_FORMCHECKBOX ||
-                                    fieldmarkTypeName == ODF_FORMDROPDOWN ||
-                                    fieldmarkTypeName == ODF_FORMDATE)
+                                    fieldmarkTypeName == ODF_FORMDROPDOWN)
                                 {   // sw can't handle checkbox with start+end
                                     SAL_INFO("xmloff.text", "invalid fieldmark-start/fieldmark-end ignored");
                                     isInvalid = true;


More information about the Libreoffice-commits mailing list