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

Tamás Zolnai (via logerrit) logerrit at kemper.freedesktop.org
Thu Jul 11 18:54:31 UTC 2019


Rebased ref, commits from common ancestor:
commit 6ec98408a30143bab9aba4ff7a602387a333ec93
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Thu Jul 11 17:20:59 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jul 11 20:53:23 2019 +0200

    MSForms: Test date fieldmark's content and current date related methods
    
    These methods are used by the field's properties dialog,
    it's drop-down button and DOCX export.
    
    Change-Id: I2b75e69b452a736cc72785d251516f3b3bf1d1f1

diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 5818597caae4..4b037b3f1678 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -1802,4 +1802,148 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testDateFormFieldInsertion)
     CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testDateFormFieldContentOperations)
+{
+    SwDoc* pDoc = createDoc();
+    CPPUNIT_ASSERT(pDoc);
+    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+    CPPUNIT_ASSERT(pMarkAccess);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Insert a date form field
+    lcl_dispatchCommand(mxComponent, ".uno:DatePickerFormField", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+
+    // Check whether the fieldmark is created
+    auto aIter = pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+    ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
+    CPPUNIT_ASSERT(pFieldmark);
+    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+
+    // Check the default content added by insertion
+    uno::Reference<text::XTextRange> xPara = getParagraph(1);
+    sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 };
+    CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), pFieldmark->GetContent());
+
+    // Set content to empty string
+    pFieldmark->ReplaceContent("");
+    CPPUNIT_ASSERT_EQUAL(OUString(""), pFieldmark->GetContent());
+
+    // Replace empty string with a valid content
+    pFieldmark->ReplaceContent("2019-10-23");
+    CPPUNIT_ASSERT_EQUAL(OUString("2019-10-23"), pFieldmark->GetContent());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testDateFormFieldCurrentDateHandling)
+{
+    SwDoc* pDoc = createDoc();
+    CPPUNIT_ASSERT(pDoc);
+    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+    CPPUNIT_ASSERT(pMarkAccess);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Insert a date form field
+    lcl_dispatchCommand(mxComponent, ".uno:DatePickerFormField", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+
+    // Check whether the fieldmark is created
+    auto aIter = pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+    ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
+    CPPUNIT_ASSERT(pFieldmark);
+    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+
+    // The default content is not a valid date
+    uno::Reference<text::XTextRange> xPara = getParagraph(1);
+    sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 };
+    CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), pFieldmark->GetContent());
+    std::pair<bool, double> aResult = pFieldmark->GetCurrentDate();
+    CPPUNIT_ASSERT(!aResult.first);
+
+    // Check empty string
+    pFieldmark->ReplaceContent("");
+    aResult = pFieldmark->GetCurrentDate();
+    CPPUNIT_ASSERT(!aResult.first);
+
+    // Check valid date
+    // Set date format first
+    sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldmark->GetParameters();
+    (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= OUString("YYYY/MM/DD");
+    (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= OUString("en-US");
+
+    // Set date value and check whether the content is formatted correctly
+    pFieldmark->SetCurrentDate(48000.0);
+    aResult = pFieldmark->GetCurrentDate();
+    CPPUNIT_ASSERT(aResult.first);
+    CPPUNIT_ASSERT_EQUAL(48000.0, aResult.second);
+    CPPUNIT_ASSERT_EQUAL(OUString("2031/06/01"), pFieldmark->GetContent());
+    // Current date param contains date in a "standard format"
+    OUString sCurrentDate;
+    auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
+    if (pResult != pParameters->end())
+    {
+        pResult->second >>= sCurrentDate;
+    }
+    CPPUNIT_ASSERT_EQUAL(OUString("2031-06-01"), sCurrentDate);
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testDateFormFieldCurrentDateInvalidation)
+{
+    SwDoc* pDoc = createDoc();
+    CPPUNIT_ASSERT(pDoc);
+    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+    CPPUNIT_ASSERT(pMarkAccess);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Insert a date form field
+    lcl_dispatchCommand(mxComponent, ".uno:DatePickerFormField", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+
+    // Check whether the fieldmark is created
+    auto aIter = pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+    ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
+    CPPUNIT_ASSERT(pFieldmark);
+    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
+
+    // Set a date first
+    sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldmark->GetParameters();
+    pFieldmark->SetCurrentDate(48000.0);
+    std::pair<bool, double> aResult = pFieldmark->GetCurrentDate();
+    CPPUNIT_ASSERT(aResult.first);
+    CPPUNIT_ASSERT_EQUAL(48000.0, aResult.second);
+
+    // Do the layouting to trigger invalidation
+    // Since we have the current date consistent with the field content
+    // This invalidation won't change anything
+    calcLayout();
+    Scheduler::ProcessEventsToIdle();
+
+    // Current date param contains date in a "standard format"
+    OUString sCurrentDate;
+    auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
+    if (pResult != pParameters->end())
+    {
+        pResult->second >>= sCurrentDate;
+    }
+    // We have the current date parameter set
+    CPPUNIT_ASSERT_EQUAL(OUString("2031-06-01"), sCurrentDate);
+
+    // Now change the content of the field
+    pFieldmark->ReplaceContent("[select date]");
+    // Do the layouting to trigger invalidation
+    calcLayout();
+    Scheduler::ProcessEventsToIdle();
+
+    sCurrentDate.clear();
+    pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
+    if (pResult != pParameters->end())
+    {
+        pResult->second >>= sCurrentDate;
+    }
+    CPPUNIT_ASSERT_EQUAL(OUString(""), sCurrentDate);
+
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 3ca0dd7f4b9700a6eb74d77c3f5e3df9a25b397a
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jul 10 14:37:38 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jul 11 20:53:22 2019 +0200

    MSForms: UITest for date form field's properties dialog
    
    Change-Id: I2fd0661ad41fbc6feb420af5ab2d05d41c6d0838

diff --git a/sw/qa/uitest/writer_tests/data/date_form_field.odt b/sw/qa/uitest/writer_tests/data/date_form_field.odt
new file mode 100644
index 000000000000..8335a1cc11ec
Binary files /dev/null and b/sw/qa/uitest/writer_tests/data/date_form_field.odt differ
diff --git a/sw/qa/uitest/writer_tests/data/date_form_field_custom_format.odt b/sw/qa/uitest/writer_tests/data/date_form_field_custom_format.odt
new file mode 100644
index 000000000000..fadd890eda31
Binary files /dev/null and b/sw/qa/uitest/writer_tests/data/date_form_field_custom_format.odt differ
diff --git a/sw/qa/uitest/writer_tests/data/date_form_field_with_placeholder.odt b/sw/qa/uitest/writer_tests/data/date_form_field_with_placeholder.odt
new file mode 100644
index 000000000000..6f8a63784502
Binary files /dev/null and b/sw/qa/uitest/writer_tests/data/date_form_field_with_placeholder.odt differ
diff --git a/sw/qa/uitest/writer_tests/data/date_form_field_without_current_date.odt b/sw/qa/uitest/writer_tests/data/date_form_field_without_current_date.odt
new file mode 100644
index 000000000000..802dff32dd09
Binary files /dev/null and b/sw/qa/uitest/writer_tests/data/date_form_field_without_current_date.odt differ
diff --git a/sw/qa/uitest/writer_tests5/DateFormFieldPropertiesDialog.py b/sw/qa/uitest/writer_tests5/DateFormFieldPropertiesDialog.py
new file mode 100644
index 000000000000..0a32863d664c
--- /dev/null
+++ b/sw/qa/uitest/writer_tests5/DateFormFieldPropertiesDialog.py
@@ -0,0 +1,164 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+from uitest.framework import UITestCase
+from uitest.uihelper.common import get_state_as_dict
+from libreoffice.uno.propertyvalue import mkPropertyValues
+import org.libreoffice.unotest
+import pathlib
+import time
+
+def get_url_for_data_file(file_name):
+    return pathlib.Path(org.libreoffice.unotest.makeCopyFromTDOC(file_name)).as_uri()
+
+class dateFormFieldDialog(UITestCase):
+
+    def test_setting_date_format(self):
+        # open a file with a date form field
+        writer_doc = self.ui_test.load_file(get_url_for_data_file("date_form_field.odt"))
+        document = self.ui_test.get_component()
+        xWriterDoc = self.xUITest.getTopFocusWindow()
+
+        # open the dialog (cursor is at the field)
+        self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+        xDialog = self.xUITest.getTopFocusWindow()
+
+        itemsList = xDialog.getChild("date_formats_treeview")
+
+        # check whether we have the right format selected
+        self.assertEqual(get_state_as_dict(itemsList)["Children"], "20")
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "12/31/99")
+
+        # select a new format
+        itemsList.getChild("11").executeAction("SELECT", tuple());
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "12-31")
+
+        xOKBtn = xDialog.getChild("ok")
+        self.ui_test.close_dialog_through_button(xOKBtn)
+
+        # open the dialog again
+        self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+        xDialog = self.xUITest.getTopFocusWindow()
+        itemsList = xDialog.getChild("date_formats_treeview")
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "12-31")
+
+        xOKBtn = xDialog.getChild("ok")
+        self.ui_test.close_dialog_through_button(xOKBtn)
+
+        self.ui_test.close_doc()
+
+    def test_date_field_with_custom_format(self):
+        # open a file with a date form field
+        writer_doc = self.ui_test.load_file(get_url_for_data_file("date_form_field_custom_format.odt"))
+        document = self.ui_test.get_component()
+        xWriterDoc = self.xUITest.getTopFocusWindow()
+
+        # open the dialog (cursor is at the field)
+        self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+        xDialog = self.xUITest.getTopFocusWindow()
+
+        itemsList = xDialog.getChild("date_formats_treeview")
+
+        # check whether we have the right format selected
+        self.assertEqual(get_state_as_dict(itemsList)["Children"], "20")
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "1999. december 31., péntek")
+
+        xOKBtn = xDialog.getChild("ok")
+        self.ui_test.close_dialog_through_button(xOKBtn)
+
+        self.ui_test.close_doc()
+
+    def test_date_reformat(self):
+        # open a file with a date form field
+        writer_doc = self.ui_test.load_file(get_url_for_data_file("date_form_field.odt"))
+        document = self.ui_test.get_component()
+        xWriterDoc = self.xUITest.getTopFocusWindow()
+        self.assertEqual(writer_doc.getText().getString(), "07/17/19")
+
+        # open the dialog (cursor is at the field)
+        self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+        xDialog = self.xUITest.getTopFocusWindow()
+
+        itemsList = xDialog.getChild("date_formats_treeview")
+
+        # check whether we have the right format selected
+        self.assertEqual(get_state_as_dict(itemsList)["Children"], "20")
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "12/31/99")
+
+        # select a new format
+        itemsList.getChild("11").executeAction("SELECT", tuple());
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "12-31")
+
+        xOKBtn = xDialog.getChild("ok")
+        self.ui_test.close_dialog_through_button(xOKBtn)
+
+        # after applying the new format, the field content should be updated
+        self.assertEqual(writer_doc.getText().getString(), "07-17")
+
+        self.ui_test.close_doc()
+
+    def test_date_field_with_placeholder(self):
+        # open a file with a date form field
+        writer_doc = self.ui_test.load_file(get_url_for_data_file("date_form_field_with_placeholder.odt"))
+        document = self.ui_test.get_component()
+        xWriterDoc = self.xUITest.getTopFocusWindow()
+        self.assertEqual(writer_doc.getText().getString(), "[select date]")
+
+        # open the dialog (cursor is at the field)
+        self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+        xDialog = self.xUITest.getTopFocusWindow()
+
+        itemsList = xDialog.getChild("date_formats_treeview")
+
+        # check whether we have the right format selected
+        self.assertEqual(get_state_as_dict(itemsList)["Children"], "20")
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "Fri 31/Dec 99")
+
+        # select a new format
+        itemsList.getChild("11").executeAction("SELECT", tuple());
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "12-31")
+
+        xOKBtn = xDialog.getChild("ok")
+        self.ui_test.close_dialog_through_button(xOKBtn)
+
+        # a placeholder text is not changed by format change
+        self.assertEqual(writer_doc.getText().getString(), "[select date]")
+
+        self.ui_test.close_doc()
+
+    def test_date_field_without_current_date(self):
+        # current date means the current date fieldmark parameter which contains the current date in YYYY-MM-DD format
+        # when this parameter is missing LO tries to parse the content string to find out the set date
+
+        # open a file with a date form field
+        writer_doc = self.ui_test.load_file(get_url_for_data_file("date_form_field_without_current_date.odt"))
+        document = self.ui_test.get_component()
+        xWriterDoc = self.xUITest.getTopFocusWindow()
+        self.assertEqual(writer_doc.getText().getString(), "07/17/19")
+
+        # open the dialog (cursor is at the field)
+        self.ui_test.execute_dialog_through_command(".uno:ControlProperties")
+        xDialog = self.xUITest.getTopFocusWindow()
+
+        itemsList = xDialog.getChild("date_formats_treeview")
+
+        # check whether we have the right format selected
+        self.assertEqual(get_state_as_dict(itemsList)["Children"], "20")
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "12/31/99")
+
+        # select a new format
+        itemsList.getChild("3").executeAction("SELECT", tuple());
+        self.assertEqual(get_state_as_dict(itemsList)["SelectEntryText"], "Dec 31, 1999")
+
+        xOKBtn = xDialog.getChild("ok")
+        self.ui_test.close_dialog_through_button(xOKBtn)
+
+        # a placeholder text is not changed by format change
+        self.assertEqual(writer_doc.getText().getString(), "Jul 17, 2019")
+
+        self.ui_test.close_doc()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
commit 1e7771f3ce24ec9250b2de2fc00d1c09ad8606e5
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jul 10 12:07:09 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jul 11 20:53:21 2019 +0200

    MSForms: date field: handle replacing empty content
    
    It occurs when the date field is empty and the user trying to
    set a date with the date picker.
    
    Change-Id: I182930258b05071d861c2b326c139c73e2339af9

diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx
index 61784376509e..85228b5fc195 100644
--- a/sw/source/core/crsr/bookmrk.cxx
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -634,12 +634,18 @@ namespace sw { namespace mark
         const sal_Int32 nStart(GetMarkStart().nContent.GetIndex());
         const sal_Int32 nEnd  (GetMarkEnd().nContent.GetIndex());
 
-        if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength())
+        if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() &&
+           nEnd > nStart + 2)
         {
             SwPaM aFieldPam(GetMarkStart().nNode, nStart + 1,
                             GetMarkStart().nNode, nEnd - 1);
             m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false);
         }
+        else
+        {
+            SwPaM aFieldStartPam(GetMarkStart().nNode, nStart + 1);
+            m_pDocumentContentOperationsManager->InsertString(aFieldStartPam, sNewContent);
+        }
 
     }
 
commit 87c0e26ea3f5fb3e631bd219381d5bd79c5ca3d2
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jul 10 18:23:48 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jul 11 20:53:21 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 b11ead66d7ad..92c64c878a38 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();
 };
 
@@ -1355,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 955204dcc2aadaa4aa97b5099fb87359f2464566
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jul 10 18:22:31 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jul 11 20:53:18 2019 +0200

    MSForms: Rework text-based date form field's representation
    
    * Better to represent it similar to text form field with two
    marking characters selecting a text range
    * So the text between the two marks can be anything (not only
    a well formatted date) and also have any character formatting.
    * With this we handle the case when the user needs a placeholder
    text in the date field or when the user needs time values (hour,
    minute, sec) next to the date.
    
    Change-Id: Id60a50a2028058f8a6a080e265c0730d88b98543

diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index 9670e811f044..cba649ea077e 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -322,7 +322,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 bf48700f6acf..b11ead66d7ad 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -1271,19 +1271,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());
 
@@ -1303,20 +1296,16 @@ void Test::testDateFormField()
                 pResult->second >>= sLang;
             }
 
-            OUString sCurrentDate;
-            pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
-            if (pResult != pParameters->end())
-            {
-                pResult->second >>= sCurrentDate;
-            }
+            OUString sCurrentDate = pFieldmark->GetContent();
 
-            // The first one is empty
+            // The first one has the default field content
             if(nIndex == 0)
             {
 
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("MM/DD/YY"), sDateFormat);
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("en-US"), sLang);
-                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(""), sCurrentDate);
+                sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(vEnSpaces, 5), sCurrentDate);
 
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(9), pFieldmark->GetMarkStart().nNode.GetIndex());
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(5), pFieldmark->GetMarkStart().nContent.GetIndex());
@@ -1325,24 +1314,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 3a0d1924c4c8..0f1226555b04 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -545,7 +545,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
         {
@@ -554,7 +554,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 0cb4cf258dc7..e9f347956bef 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -19,6 +19,9 @@
 #include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
 #include <com/sun/star/embed/Aspects.hpp>
 #include <com/sun/star/text/WritingMode2.hpp>
+#include <xmloff/odffields.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IMark.hxx>
 
 class Test : public SwModelTestBase
 {
@@ -37,16 +40,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 887e59e73b06..5818597caae4 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -1784,6 +1784,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 8f9b4429d805..967602795360 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 + Date(dCurrentDate));
-            }
+            const Date& rNullDate = m_pNumberFormatter->GetNullDate();
+            m_pCalendar->SetCurDate(rNullDate + Date(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 d7eea03eddaf..61784376509e 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 012914060003..d5c802e3ed1c 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -661,9 +661,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 );
@@ -1274,23 +1284,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)
@@ -1301,13 +1317,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 2c30f8e79f75..98f1dc201450 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 0c3acdb84ae5..89af26b39314 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) override;
+
+            // This method should be called only by the portion so we can now the portion's painting area
+            void SetPortionPaintArea(const SwRect& rPortionPaintArea);
+
+        private:
+            SwRect m_aPortionPaintArea;
         };
 
         /// Fieldmark representing a date form field.
         class DateFieldmark
-            : public FieldmarkWithDropDownButton
+            : virtual public IDateFieldmark
+            , public FieldmarkWithDropDownButton
         {
         public:
             DateFieldmark(const SwPaM& rPaM);
             virtual ~DateFieldmark() override;
 
             virtual void InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) override;
+            virtual void ReleaseDoc(SwDoc* const pDoc) override;
 
             virtual void ShowButton(SwEditWin* pEditWin) override;
 
+            void SetPortionPaintAreaStart(const SwRect& rPortionPaintArea);
+            void SetPortionPaintAreaEnd(const SwRect& rPortionPaintArea);
+
+            virtual OUString GetContent() const override;
+            virtual void ReplaceContent(const OUString& sNewContent) override;
+
+            virtual std::pair<bool, double> GetCurrentDate() const override;
+            virtual void SetCurrentDate(double fDate) override;
+            virtual OUString GetDateInStandardDateFormat(double fDate) const override;
+
         private:
+            OUString GetDateInCurrentDateFormat(double fDate) const;
+            std::pair<bool, double> ParseCurrentDateParam() const;
+            void InvalidateCurrentDateParam();
+
             SvNumberFormatter* m_pNumberFormatter;
+            sw::DocumentContentOperationsManager* m_pDocumentContentOperationsManager;
+            SwRect m_aPaintAreaStart;
+            SwRect m_aPaintAreaEnd;
         };
     }
 }
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 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 09ace4f82c84..428dc0bfa5e6 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 0363e9d6ab6f..225f686f8eb7 100644
--- a/sw/source/core/text/porfld.hxx
+++ b/sw/source/core/text/porfld.hxx
@@ -235,18 +235,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 482185361409..85596ca25611 100644
--- a/sw/source/core/unocore/unobkm.cxx
+++ b/sw/source/core/unocore/unobkm.cxx
@@ -624,7 +624,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);
@@ -671,7 +671,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 024e29182209..7d7620990ada 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1878,21 +1878,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 marking static strings in date format
+    OString sUTF8DateFormat = sDateFormat.toUtf8();
     sUTF8DateFormat = sUTF8DateFormat.replaceAll("\"", "'");
     m_pSerializer->singleElementNS(XML_w, XML_dateFormat,
                                    FSNS(XML_w, XML_val), sUTF8DateFormat);
@@ -1907,59 +1904,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);
 }
 
@@ -1972,17 +1921,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
     {
@@ -2215,6 +2178,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 b4c8204052af..899c99f45a04 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -707,7 +707,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 39105ace49f8..813839e4b84a 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -162,6 +162,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 a322da5f9ed3..2c273be6449d 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2333,49 +2333,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 );
+                            }
                         }
                     }
                 }
@@ -2386,24 +2401,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 )
@@ -2411,30 +2436,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 8df610df64d7..04a2c0f5e7f9 100644
--- a/sw/source/ui/dialog/swdlgfact.cxx
+++ b/sw/source/ui/dialog/swdlgfact.cxx
@@ -878,7 +878,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 cf2e973b4d34..0de317f9eefc 100644
--- a/sw/source/ui/fldui/DateFormFieldDialog.cxx
+++ b/sw/source/ui/fldui/DateFormFieldDialog.cxx
@@ -18,7 +18,7 @@
 
 namespace sw
 {
-DateFormFieldDialog::DateFormFieldDialog(weld::Widget* pParent, mark::IFieldmark* pDateField)
+DateFormFieldDialog::DateFormFieldDialog(weld::Widget* pParent, sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc)
     : GenericDialogController(pParent, "modules/swriter/ui/dateformfielddialog.ui",
                               "DateFormFieldDialog")
     , m_pDateField(pDateField)
@@ -43,12 +43,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();
+        }
     }
 }
 
@@ -75,19 +90,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)
                 {
@@ -102,7 +117,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 8bb0d638a837..a09227c9af69 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 81d0687ed03f..f16f6cea2749 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -730,17 +730,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);

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list