[Libreoffice-commits] core.git: Branch 'feature/msforms' - 2 commits - sw/inc sw/qa sw/source writerfilter/source xmloff/source

Tamás Zolnai (via logerrit) logerrit at kemper.freedesktop.org
Wed Jul 10 09:37:09 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                         |  107 +++
 sw/qa/extras/ooxmlexport/ooxmlexport.cxx                           |   11 
 sw/qa/extras/ooxmlexport/ooxmlexport13.cxx                         |    4 
 sw/qa/extras/ooxmlimport/ooxmlimport2.cxx                          |   36 +
 sw/qa/extras/uiwriter/uiwriter2.cxx                                |    5 
 sw/source/core/crsr/DateFormFieldButton.cxx                        |   70 --
 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                                   |   92 ---
 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                       |   91 +--
 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                                  |    2 
 sw/source/ui/fldui/DateFormFieldDialog.cxx                         |   33 -
 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                          |   12 
 xmloff/source/text/XMLTextMarkImportContext.cxx                    |    5 
 34 files changed, 742 insertions(+), 430 deletions(-)

New commits:
commit 25c47dfb1946786f86426adf8b4ddc55c62ed841
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Mon Jul 8 17:49:24 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jul 10 11:08:20 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.
    
    Change-Id: I598a21691c08a161933a5fef659e7ca21092dd0c

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 dac7b79271f3..c9dacb5a591d 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -27,6 +27,7 @@
 #include <xmloff/odffields.hxx>
 #include <IDocumentMarkAccess.hxx>
 #include <IMark.hxx>
+#include <com/sun/star/awt/FontWeight.hpp>
 
 class Test : public SwModelTestBase
 {
@@ -51,6 +52,7 @@ public:
     void testCheckBoxFormField();
     void testDropDownFormField();
     void testDateFormField();
+    void testDateFormFieldCharacterFormatting();
 
     CPPUNIT_TEST_SUITE(Test);
     CPPUNIT_TEST(testEmbeddedGraphicRoundtrip);
@@ -70,6 +72,7 @@ public:
     CPPUNIT_TEST(testCheckBoxFormField);
     CPPUNIT_TEST(testDropDownFormField);
     CPPUNIT_TEST(testDateFormField);
+    CPPUNIT_TEST(testDateFormFieldCharacterFormatting);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -1281,7 +1284,6 @@ void Test::testDateFormField()
             CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
             CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
 
-            // Check drop down field's parameters.
             const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
             OUString sDateFormat;
             auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
@@ -1356,6 +1358,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());
+        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 bd1cf12450af..23a97bfce953 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -71,17 +71,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 a894e09b39a4d9d9551507ef7e859b74cb899611
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Fri Jul 5 13:21:55 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jul 10 11:08:09 2019 +0200

    MSForms: Rework text-based date field representation
    
    * Better to represent it similar to text form field with two
    marking character 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 need a placeholder
    text in the date field or when the user needs time values (hour,
    minute, sec) next to the date.
    
    Change-Id: Id60a50a2028058f8a6a080e265c0730d88b98543

diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index f2cfd2264efb..208ca6440f3e 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -272,7 +272,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 e7275d9f5d56..b8ee6a4a2098 100644
--- a/sw/inc/IMark.hxx
+++ b/sw/inc/IMark.hxx
@@ -121,6 +121,25 @@ namespace sw { namespace mark
             ICheckboxFieldmark &operator =(ICheckboxFieldmark const&) = delete;
     };
 
+    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 c793069b8a41..d696d9388472 100644
--- a/sw/inc/swabstdlg.hxx
+++ b/sw/inc/swabstdlg.hxx
@@ -78,7 +78,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);
 
@@ -392,7 +392,7 @@ public:
         SwField* pField, bool bPrevButton, bool bNextButton) = 0;
     virtual VclPtr<VclAbstractDialog> CreateDropDownFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDropDownField) = 0;
 
-    virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDateField, SwDoc* pDoc) = 0;
+    virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(weld::Widget* pParent, sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc) = 0;
 
     virtual VclPtr<SfxAbstractTabDialog> CreateSwEnvDlg(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtSh, Printer* pPrt, bool bInsert) = 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 b25bbf7ae999..dac7b79271f3 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -1272,19 +1272,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);
-
-            if(!pFieldmark)
-                continue;
-
+            ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
             CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
             CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
 
@@ -1304,20 +1297,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), 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());
@@ -1326,24 +1315,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/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index 64de29ac9175..056c5b0469bf 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -412,7 +412,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
         {
@@ -421,7 +421,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/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index 9bae9e7fab91..94a5685431d8 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -18,6 +18,9 @@
 #include <wrtsh.hxx>
 #include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
 #include <com/sun/star/embed/Aspects.hpp>
+#include <xmloff/odffields.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IMark.hxx>
 
 class Test : public SwModelTestBase
 {
@@ -36,16 +39,37 @@ DECLARE_OOXMLIMPORT_TEST(testTdf108545_embeddedDocxIcon, "tdf108545_embeddedDocx
 
 DECLARE_OOXMLIMPORT_TEST(testTdf121203, "tdf121203.docx")
 {
-    // Make sure that the date SDT's content is imported as plain text, as
-    // the field has no fullDate attribute which we can use to find out the actual date.
-    CPPUNIT_ASSERT_EQUAL(OUString("17-Oct-2018 09:00"), getRun(getParagraph(1), 1)->getString());
-
-    // Make sure we did not import a date field.
+    // We imported the date field
     SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
     CPPUNIT_ASSERT(pTextDoc);
     SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
     IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+
+    // Custom sdt date content is imported correctly
+    ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
+    CPPUNIT_ASSERT(pFieldmark);
+    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+
+    const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
+    OUString sDateFormat;
+    auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
+    if (pResult != pParameters->end())
+    {
+        pResult->second >>= sDateFormat;
+    }
+
+    OUString sLang;
+    pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
+    if (pResult != pParameters->end())
+    {
+        pResult->second >>= sLang;
+    }
+
+    OUString sCurrentDate = pFieldmark->GetContent();
+    CPPUNIT_ASSERT_EQUAL(OUString("dd-MMM-yy"), sDateFormat);
+    CPPUNIT_ASSERT_EQUAL(OUString("en-GB"), sLang);
+    CPPUNIT_ASSERT_EQUAL(OUString("17-Oct-2018 09:00"), sCurrentDate);
 }
 
 DECLARE_OOXMLIMPORT_TEST(testTdf109053, "tdf109053.docx")
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 7a238c94fd81..b57d0fe4b839 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -1343,6 +1343,11 @@ CPPUNIT_TEST_FIXTURE(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 db4275746176..54d34f250ed0 100644
--- a/sw/source/core/crsr/DateFormFieldButton.cxx
+++ b/sw/source/core/crsr/DateFormFieldButton.cxx
@@ -28,18 +28,18 @@ 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, SvNumberFormatter* pNumberFormatter);
+    SwDatePickerDialog(SwEditWin* parent, sw::mark::DateFieldmark* pFieldmark, SvNumberFormatter* pNumberFormatter);
     virtual ~SwDatePickerDialog() override;
     virtual void dispose() override;
 };
 
-SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark, SvNumberFormatter* pNumberFormatter)
+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))
     , m_pFieldmark(pFieldmark)
@@ -47,35 +47,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;
-                SvNumFormatType 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 + dCurrentDate);
-            }
+            const Date& rNullDate = m_pNumberFormatter->GetNullDate();
+            m_pCalendar->SetCurDate(rNullDate + aResult.second);
         }
     }
     m_pCalendar->SetSelectHdl(LINK(this, SwDatePickerDialog, ImplSelectHdl));
@@ -98,32 +74,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;
-                SvNumFormatType 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();
     }
@@ -139,8 +92,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);
+        = VclPtr<SwDatePickerDialog>::Create(static_cast<SwEditWin*>(GetParent()), 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 88e9007aa3bc..682bf5a45446 100644
--- a/sw/source/core/crsr/bookmrk.cxx
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -41,6 +41,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;
+            SvNumFormatType 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;
+            SvNumFormatType 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;
+                SvNumFormatType 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;
+            SvNumFormatType 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 e5b697967e40..8ff3fd4d0969 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -531,9 +531,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 );
@@ -1142,23 +1152,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)
@@ -1169,13 +1185,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 7690fe1ece07..ee24b3ec8d33 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -92,7 +92,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 ee5e9b45c4bd..837345b5e8ba 100644
--- a/sw/source/core/inc/bookmrk.hxx
+++ b/sw/source/core/inc/bookmrk.hxx
@@ -277,15 +277,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;
         };
 
@@ -298,22 +294,47 @@ namespace sw {
             virtual ~DropDownFieldmark() override;
 
             virtual void ShowButton(SwEditWin* pEditWin);
+
+            // 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);
 
+            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 905b427c44e9..f16e195da085 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -865,77 +865,6 @@ namespace sw { namespace mark {
         return OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH);
     }
 
-    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;
-                SvNumFormatType 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;
-                SvNumFormatType 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
@@ -962,16 +891,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
+
             auto const ch(rInf.GetText()[sal_Int32(rInf.GetIdx())]);
-            if (ch == CH_TXT_ATR_FIELDSTART)
+            SwTextFrame const*const pFrame(rInf.GetTextFrame());
+            SwPosition aPosition(pFrame->MapViewToModelPos(rInf.GetIdx()));
+            sw::mark::IFieldmark *pBM = pFrame->GetDoc().getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
+            if(pBM != nullptr && pBM->GetFieldname( ) == ODF_FORMDATE)
+            {
+                if (ch == CH_TXT_ATR_FIELDSTART)
+                    pPor = new SwFieldFormDatePortion(pBM, true);
+                else if (ch == CH_TXT_ATR_FIELDEND)
+                    pPor = new SwFieldFormDatePortion(pBM, false);
+            }
+            else if (ch == CH_TXT_ATR_FIELDSTART)
                 pPor = new SwFieldMarkPortion();
             else if (ch == CH_TXT_ATR_FIELDEND)
                 pPor = new SwFieldMarkPortion();
             else if (ch == CH_TXT_ATR_FORMELEMENT)
             {
-                SwTextFrame const*const pFrame(rInf.GetTextFrame());
-                SwPosition aPosition(pFrame->MapViewToModelPos(rInf.GetIdx()));
-                sw::mark::IFieldmark *pBM = pFrame->GetDoc().getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
                 OSL_ENSURE(pBM != nullptr, "Where is my form field bookmark???");
                 if (pBM != nullptr)
                 {
@@ -983,11 +920,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*>(GetTextFrame()->GetDoc().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 6f16d966abcb..1fcad86ad5f0 100644
--- a/sw/source/core/text/porfld.cxx
+++ b/sw/source/core/text/porfld.cxx
@@ -1329,9 +1329,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
@@ -1343,7 +1343,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 2a76382b9e3f..d0af5e23b488 100644
--- a/sw/source/core/text/porfld.hxx
+++ b/sw/source/core/text/porfld.hxx
@@ -234,18 +234,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 f8ac60385821..7e5e2bce36fa 100644
--- a/sw/source/core/unocore/unobkm.cxx
+++ b/sw/source/core/unocore/unobkm.cxx
@@ -629,7 +629,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);
@@ -676,7 +676,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 eac660544018..8e6c0350d88f 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1871,21 +1871,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);
     m_pSerializer->startElementNS(XML_w, XML_sdtPr);
 
-    if (!sCurrentDate.isEmpty())
-    {
-        OString sDate = sCurrentDate.toUtf8() + "T00:00:00Z";
-        m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), sDate);
-    }
+    if(!sFullDate.isEmpty())
+        m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), sFullDate.toUtf8());
     else
         m_pSerializer->startElementNS(XML_w, XML_date);
 
-    OString sUTF8DateFormat = sDateFormat.toUtf8();
     // Replace quotation mark used for mark 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);
@@ -1900,59 +1897,11 @@ void DocxAttributeOutput::WriteFormDate(const OUString& sCurrentDate, const OUSt
     m_pSerializer->endElementNS(XML_w, XML_sdtPr);
 
     m_pSerializer->startElementNS(XML_w, XML_sdtContent);
-    m_pSerializer->startElementNS(XML_w, XML_r);
-
-    // 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;
-            SvNumFormatType 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;
-            SvNumFormatType 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);
 }
 
@@ -1965,17 +1914,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
     {
@@ -2202,6 +2165,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 189a2400d8d6..7bbb2554a96d 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -706,7 +706,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 f0db6407c55d..a16226978bbe 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -160,6 +160,9 @@ void DocxExport::AppendBookmarks( const SwTextNode& rNode, sal_Int32 nCurrentPos
             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 == nCurrentPos )
                 aStarts.push_back( pMark->GetName() );
 
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 293da7625a8e..5246233a7505 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2307,49 +2307,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 = static_cast<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 );
+                            }
                         }
                     }
                 }
@@ -2360,24 +2375,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 = static_cast<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 )
@@ -2385,30 +2410,18 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                     SwPosition aPosition( rNode, SwIndex( &rNode, nCurrentPos ) );
                     ::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 2a954af248c7..5eaa8d220d41 100644
--- a/sw/source/ui/dialog/swdlgfact.cxx
+++ b/sw/source/ui/dialog/swdlgfact.cxx
@@ -875,7 +875,7 @@ VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDropDownFormFieldD
     return VclPtr<AbstractDropDownFormFieldDialog_Impl>::Create(std::make_unique<sw::DropDownFormFieldDialog>(pParent, pDropDownField));
 }
 
-VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDateFormFieldDialog(weld::Widget *pParent, sw::mark::IFieldmark* pDateField, SwDoc* pDoc)
+VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDateFormFieldDialog(weld::Widget *pParent, sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc)
 {
     return VclPtr<AbstractDateFormFieldDialog_Impl>::Create(std::make_unique<sw::DateFormFieldDialog>(pParent, pDateField, pDoc));
 }
diff --git a/sw/source/ui/dialog/swdlgfact.hxx b/sw/source/ui/dialog/swdlgfact.hxx
index 7638f7d150fd..9d07b650c989 100644
--- a/sw/source/ui/dialog/swdlgfact.hxx
+++ b/sw/source/ui/dialog/swdlgfact.hxx
@@ -652,7 +652,7 @@ public:
     virtual VclPtr<AbstractDropDownFieldDialog> CreateDropDownFieldDialog(weld::Widget* pParent, SwWrtShell &rSh,
         SwField* pField, bool bPrevButton, bool bNextButton) override;
     virtual VclPtr<VclAbstractDialog> CreateDropDownFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDropDownField) override;
-    virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDateField, SwDoc* pDoc) override;
+    virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(weld::Widget* pParent, sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc) override;
 
     virtual VclPtr<SfxAbstractTabDialog> CreateSwEnvDlg(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtSh, Printer* pPrt, bool bInsert) override;
     virtual VclPtr<AbstractSwLabDlg> CreateSwLabDlg(weld::Window* pParent, const SfxItemSet& rSet,
diff --git a/sw/source/ui/fldui/DateFormFieldDialog.cxx b/sw/source/ui/fldui/DateFormFieldDialog.cxx
index 30b97178f44e..2080271d3661 100644
--- a/sw/source/ui/fldui/DateFormFieldDialog.cxx
+++ b/sw/source/ui/fldui/DateFormFieldDialog.cxx
@@ -19,7 +19,7 @@
 namespace sw
 {
 DateFormFieldDialog::DateFormFieldDialog(weld::Widget* pParent,
-                                         mark::IFieldmark* pDateField, SwDoc* pDoc)
+                                         mark::IDateFieldmark* pDateField, SwDoc* pDoc)
     : GenericDialogController(pParent, "modules/swriter/ui/dateformfielddialog.ui",
                               "DateFormFieldDialog")
     , m_pDateField(pDateField)
@@ -44,12 +44,27 @@ void DateFormFieldDialog::Apply()
 {
     if (m_pDateField != nullptr)
     {
+        // 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());
-        sw::mark::IFieldmark::parameter_map_t* pParameters = m_pDateField->GetParameters();
+
+        // 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();
+        }
     }
 }
 
@@ -76,19 +91,19 @@ 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;
                 SvNumFormatType nType;
                 m_pNumberFormatter->PutEntry(sFormatString,
                                              nCheckPos,
                                              nType,
-                                             nFormatKey,
+                                             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)
                 {
@@ -103,7 +118,7 @@ void DateFormFieldDialog::InitControls()
                     m_xFormatLB->SetFormatType(SvNumFormatType::ALL);
                     m_xFormatLB->SetFormatType(SvNumFormatType::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 3d7d8b75d79d..a090cdbcd30c 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 weld::GenericDialogController
 {
 private:
-    mark::IFieldmark* m_pDateField;
+    sw::mark::IDateFieldmark* m_pDateField;
     SvNumberFormatter* m_pNumberFormatter;
 
     std::unique_ptr<SwNumFormatTreeView> m_xFormatLB;
@@ -40,7 +40,7 @@ private:
     void InitControls();
 
 public:
-    DateFormFieldDialog(weld::Widget* pParent, mark::IFieldmark* pDateField, SwDoc* pDoc);
+    DateFormFieldDialog(weld::Widget* pParent, sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc);
     virtual ~DateFormFieldDialog() override;
 
     virtual short run() override
diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx
index e7fb07417aa5..8865d2aa2151 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -792,17 +792,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(SvNumFormatType::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(SvNumFormatType::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 50445cff3d99..093926a6d976 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -1377,7 +1377,8 @@ void SwTextShell::Execute(SfxRequest &rReq)
         else if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDATE )
         {
             SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
-            ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDateFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pFieldBM, GetView().GetDocShell()->GetDoc()));
+            sw::mark::DateFieldmark* pDateField = dynamic_cast<sw::mark::DateFieldmark*>(pFieldBM);
+            ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDateFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), 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 5647b6ef115d..b12ed0bf8111 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2423,6 +2423,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:
@@ -3031,10 +3032,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()
@@ -3203,48 +3200,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)
     {
@@ -3270,6 +3262,21 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
             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 1c7c04563f09..fa249deb0e60 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -99,24 +99,40 @@ bool SdtHelper::validateDateFormat()
     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();
@@ -127,15 +143,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 01abd4117adb..5efb397edd8a 100644
--- a/writerfilter/source/dmapper/SdtHelper.hxx
+++ b/writerfilter/source/dmapper/SdtHelper.hxx
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
 
 #include <rtl/ustrbuf.hxx>
 #include <tools/ref.hxx>
@@ -56,6 +57,8 @@ class SdtHelper final : public virtual SvRefBase
     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.
@@ -79,15 +82,22 @@ 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();
 
@@ -114,7 +124,7 @@ public:
     /// Create drop-down control from w:sdt's w:dropDownList.
     void createDropDownControl();
     /// 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 aff9a18c38d1..62e58c8a84c1 100644
--- a/xmloff/source/text/XMLTextMarkImportContext.cxx
+++ b/xmloff/source/text/XMLTextMarkImportContext.cxx
@@ -137,8 +137,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;
 }
@@ -332,8 +330,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