[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - 15 commits - include/vcl sfx2/source shell/source sw/inc sw/Library_sw.mk sw/qa sw/source sw/uiconfig writerfilter/source

Tamás Zolnai (via logerrit) logerrit at kemper.freedesktop.org
Wed Jun 19 23:01:12 UTC 2019


 include/vcl/window.hxx                                 |    2 
 sfx2/source/control/charwin.cxx                        |    1 
 shell/source/win32/spsupp/COMOpenDocuments.cxx         |   36 +-
 sw/Library_sw.mk                                       |    1 
 sw/inc/IDocumentMarkAccess.hxx                         |    8 
 sw/inc/crsrsh.hxx                                      |    8 
 sw/inc/strings.hrc                                     |    4 
 sw/inc/swundo.hxx                                      |    4 
 sw/inc/view.hxx                                        |    4 
 sw/qa/extras/globalfilter/data/checkbox_form_field.odt |binary
 sw/qa/extras/globalfilter/data/dropdown_form_field.odt |binary
 sw/qa/extras/globalfilter/data/text_form_field.odt     |binary
 sw/qa/extras/globalfilter/globalfilter.cxx             |  217 ++++++++++++++
 sw/qa/extras/uiwriter/uiwriter2.cxx                    |  155 ++++++++++
 sw/source/core/crsr/DropDownFormFieldButton.cxx        |  256 +++++++++++++++++
 sw/source/core/crsr/bookmrk.cxx                        |   74 ++++
 sw/source/core/crsr/crsrsh.cxx                         |    2 
 sw/source/core/doc/docbm.cxx                           |  139 +++++++++
 sw/source/core/inc/DropDownFormFieldButton.hxx         |   54 +++
 sw/source/core/inc/MarkManager.hxx                     |   13 
 sw/source/core/inc/UndoBookmark.hxx                    |   29 +
 sw/source/core/inc/bookmrk.hxx                         |   26 +
 sw/source/core/inc/rolbck.hxx                          |   33 ++
 sw/source/core/inc/unobookmark.hxx                     |    2 
 sw/source/core/text/itrform2.cxx                       |    6 
 sw/source/core/text/porfld.cxx                         |   16 -
 sw/source/core/text/porfld.hxx                         |    8 
 sw/source/core/undo/rolbck.cxx                         |   90 +++++
 sw/source/core/undo/unbkmk.cxx                         |   32 ++
 sw/source/core/undo/undobj.cxx                         |    3 
 sw/source/core/unocore/unobkm.cxx                      |   23 +
 sw/source/ui/config/optcomp.cxx                        |    2 
 sw/source/ui/fldui/DropDownFormFieldDialog.cxx         |   19 -
 sw/source/uibase/docvw/edtwin.cxx                      |   21 -
 sw/source/uibase/shells/textfld.cxx                    |   40 ++
 sw/source/uibase/shells/textsh1.cxx                    |   12 
 sw/source/uibase/uiview/view.cxx                       |    3 
 sw/source/uibase/uiview/viewling.cxx                   |  110 -------
 sw/uiconfig/swriter/ui/optcompatpage.ui                |    2 
 writerfilter/source/dmapper/FormControlHelper.cxx      |   17 -
 40 files changed, 1308 insertions(+), 164 deletions(-)

New commits:
commit bbfb5805d080c108c60b668a1315eb6472114635
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Mar 6 15:48:05 2019 +0100
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:35 2019 +0200

    MSForms: Add some extra comments for the new code.
    
    Reviewed-on: https://gerrit.libreoffice.org/68965
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit d47f037a220636d70297bc098ed08e0bcb763aa9)
    
    Change-Id: I4b70eb2164032623a12f9e703c660eca1d6768ec

diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index 68a97df6c3bc..fd55bc0dc747 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -1225,7 +1225,7 @@ void Test::testDropDownFormField()
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(0), vListEntries.getLength());
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(-1), nSelection);
             }
-            else
+            else // The second one has list and also a selected item
             {
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(4), vListEntries.getLength());
                 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(1), nSelection);
diff --git a/sw/source/core/inc/UndoBookmark.hxx b/sw/source/core/inc/UndoBookmark.hxx
index 7b9dd4fc68e5..3e2017d0721d 100644
--- a/sw/source/core/inc/UndoBookmark.hxx
+++ b/sw/source/core/inc/UndoBookmark.hxx
@@ -98,6 +98,7 @@ private:
     virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
 };
 
+/// Handling undo / redo of checkbox and drop-down form field insertion
 class SwUndoInsNoTextFieldmark : public SwUndo
 {
 private:
@@ -110,6 +111,7 @@ public:
     virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
 };
 
+/// Handling undo / redo of text form field insertion
 class SwUndoInsTextFieldmark : public SwUndo
 {
 private:
diff --git a/sw/source/core/inc/rolbck.hxx b/sw/source/core/inc/rolbck.hxx
index 3fde226b7acf..2feec7e6d973 100644
--- a/sw/source/core/inc/rolbck.hxx
+++ b/sw/source/core/inc/rolbck.hxx
@@ -262,6 +262,8 @@ class SwHistoryBookmark : public SwHistoryHint
         std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndo;
 };
 
+/// History object containing all information used during undo / redo
+/// of checkbox and drop-down form field insertion.
 class SwHistoryNoTextFieldmark : public SwHistoryHint
 {
     public:
@@ -275,6 +277,8 @@ class SwHistoryNoTextFieldmark : public SwHistoryHint
         const sal_Int32 m_nContent;
 };
 
+/// History object containing all information used during undo / redo
+/// of text form field insertion.
 class SwHistoryTextFieldmark : public SwHistoryHint
 {
     public:
commit 2d95079d3c469eddeb88b997ccbef11c844fd582
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jun 19 19:22:06 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:35 2019 +0200

    MSForms: Test insertion of form fields and undo / redo of this insertion.
    
    Reviewed-on: https://gerrit.libreoffice.org/68966
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit 695f6746b555a7b74e84c466469c28030be99e73)
    
    Change-Id: I526faceab8eb1ce2f16d41ab1bed8cfb1bfcca24
    Reviewed-on: https://gerrit.libreoffice.org/69199
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index a88bc96b5c4d..122efa846efe 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -34,6 +34,9 @@
 #include <anchoredobject.hxx>
 #include <swtypes.hxx>
 #include <vcl/scheduler.hxx>
+#include <fmtornt.hxx>
+#include <xmloff/odffields.hxx>
+#include <com/sun/star/frame/DispatchHelper.hpp>
 
 namespace
 {
@@ -66,6 +69,10 @@ public:
     void testUnfloatButton();
     void testUnfloatButtonReadOnlyMode();
     void testUnfloating();
+    void testTextFormFieldInsertion();
+    void testCheckboxFormFieldInsertion();
+    void testDropDownFormFieldInsertion();
+    void testMixedFormFieldInsertion();
 
     CPPUNIT_TEST_SUITE(SwUiWriterTest2);
     CPPUNIT_TEST(testRedlineMoveInsertInDelete);
@@ -89,6 +96,10 @@ public:
     CPPUNIT_TEST(testUnfloatButton);
     CPPUNIT_TEST(testUnfloatButtonReadOnlyMode);
     CPPUNIT_TEST(testUnfloating);
+    CPPUNIT_TEST(testTextFormFieldInsertion);
+    CPPUNIT_TEST(testCheckboxFormFieldInsertion);
+    CPPUNIT_TEST(testDropDownFormFieldInsertion);
+    CPPUNIT_TEST(testMixedFormFieldInsertion);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -949,6 +960,150 @@ void SwUiWriterTest2::testUnfloating()
     }
 }
 
+void SwUiWriterTest2::testTextFormFieldInsertion()
+{
+    SwDoc* pDoc = createDoc();
+    CPPUNIT_ASSERT(pDoc);
+    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+    CPPUNIT_ASSERT(pMarkAccess);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Insert a text form field
+    lcl_dispatchCommand(mxComponent, ".uno:TextFormField", {});
+    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::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+    CPPUNIT_ASSERT(pFieldmark);
+    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMTEXT), pFieldmark->GetFieldname());
+
+    // The text form field has the placholder 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());
+    xPara.set(getParagraph(1));
+    CPPUNIT_ASSERT(xPara->getString().isEmpty());
+
+    // Redo insertion
+    lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    xPara.set(getParagraph(1));
+    CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString());
+}
+
+void SwUiWriterTest2::testCheckboxFormFieldInsertion()
+{
+    SwDoc* pDoc = createDoc();
+    CPPUNIT_ASSERT(pDoc);
+
+    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+    CPPUNIT_ASSERT(pMarkAccess);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Insert a checkbox form field
+    lcl_dispatchCommand(mxComponent, ".uno:CheckBoxFormField", {});
+    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::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+    CPPUNIT_ASSERT(pFieldmark);
+    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname());
+    // The checkbox is not checked by default
+    ::sw::mark::ICheckboxFieldmark* pCheckBox
+        = dynamic_cast<::sw::mark::ICheckboxFieldmark*>(pFieldmark);
+    CPPUNIT_ASSERT(pCheckBox);
+    CPPUNIT_ASSERT(!pCheckBox->IsChecked());
+
+    // Undo insertion
+    lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Redo insertion
+    lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    aIter = pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+    pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+    CPPUNIT_ASSERT(pFieldmark);
+    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname());
+}
+
+void SwUiWriterTest2::testDropDownFormFieldInsertion()
+{
+    SwDoc* pDoc = createDoc();
+    CPPUNIT_ASSERT(pDoc);
+
+    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+    CPPUNIT_ASSERT(pMarkAccess);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Insert a drop-down form field
+    lcl_dispatchCommand(mxComponent, ".uno:DropDownFormField", {});
+    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::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+    CPPUNIT_ASSERT(pFieldmark);
+    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname());
+    // Check drop down field's parameters. By default these params are not set
+    const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
+    auto pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
+    CPPUNIT_ASSERT(bool(pListEntries == pParameters->end()));
+    auto pResult = pParameters->find(ODF_FORMDROPDOWN_RESULT);
+    CPPUNIT_ASSERT(bool(pResult == pParameters->end()));
+
+    // Undo insertion
+    lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Redo insertion
+    lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    aIter = pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
+    pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+    CPPUNIT_ASSERT(pFieldmark);
+    CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname());
+}
+
+void SwUiWriterTest2::testMixedFormFieldInsertion()
+{
+    SwDoc* pDoc = createDoc();
+    CPPUNIT_ASSERT(pDoc);
+
+    IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+    CPPUNIT_ASSERT(pMarkAccess);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Insert fields
+    lcl_dispatchCommand(mxComponent, ".uno:TextFormField", {});
+    lcl_dispatchCommand(mxComponent, ".uno:CheckBoxFormField", {});
+    lcl_dispatchCommand(mxComponent, ".uno:DropDownFormField", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
+
+    // Undo insertion
+    lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+    lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+    lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
+
+    // Redo insertion
+    lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+    lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+    lcl_dispatchCommand(mxComponent, ".uno:Redo", {});
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest2);
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 0c43160596ce978e085a8a94bfd9e6737f8db29f
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jun 19 19:19:07 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:35 2019 +0200

    MSForms: Test legacy form field import / export for the supported formats.
    
    Reviewed-on: https://gerrit.libreoffice.org/68964
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    Tested-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit 2a378bad84c3125c032f0c11f1cbcff23e24c7cb)
    
    Change-Id: Idbb80d097b21386e7d2673290a318d98b92125d5
    Reviewed-on: https://gerrit.libreoffice.org/69198
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/qa/extras/globalfilter/data/checkbox_form_field.odt b/sw/qa/extras/globalfilter/data/checkbox_form_field.odt
new file mode 100644
index 000000000000..14c931ed37da
Binary files /dev/null and b/sw/qa/extras/globalfilter/data/checkbox_form_field.odt differ
diff --git a/sw/qa/extras/globalfilter/data/dropdown_form_field.odt b/sw/qa/extras/globalfilter/data/dropdown_form_field.odt
new file mode 100644
index 000000000000..caaa66acda8f
Binary files /dev/null and b/sw/qa/extras/globalfilter/data/dropdown_form_field.odt differ
diff --git a/sw/qa/extras/globalfilter/data/text_form_field.odt b/sw/qa/extras/globalfilter/data/text_form_field.odt
new file mode 100644
index 000000000000..96af26f7708f
Binary files /dev/null and b/sw/qa/extras/globalfilter/data/text_form_field.odt differ
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index f9a6a60df823..68a97df6c3bc 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -25,6 +25,10 @@
 #include <ndindex.hxx>
 #include <pam.hxx>
 #include <unotools/fltrcfg.hxx>
+#include <xmloff/odffields.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IMark.hxx>
+#include <bookmrk.hxx>
 
 class Test : public SwModelTestBase
 {
@@ -45,6 +49,9 @@ public:
 #endif
     void testRedlineFlags();
     void testBulletAsImage();
+    void testTextFormField();
+    void testCheckBoxFormField();
+    void testDropDownFormField();
 
     CPPUNIT_TEST_SUITE(Test);
     CPPUNIT_TEST(testEmbeddedGraphicRoundtrip);
@@ -60,6 +67,9 @@ public:
 #endif
     CPPUNIT_TEST(testRedlineFlags);
     CPPUNIT_TEST(testBulletAsImage);
+    CPPUNIT_TEST(testTextFormField);
+    CPPUNIT_TEST(testCheckBoxFormField);
+    CPPUNIT_TEST(testDropDownFormField);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -1023,6 +1033,213 @@ void Test::testBulletAsImage()
     }
 }
 
+void Test::testTextFormField()
+{
+    const OUString aFilterNames[] = {
+        "writer8",
+        "MS Word 97",
+        "Office Open XML Text",
+    };
+
+    for (const OUString& rFilterName : aFilterNames)
+    {
+        if (mxComponent.is())
+            mxComponent->dispose();
+        mxComponent = loadFromDesktop(m_directories.getURLFromSrc("/sw/qa/extras/globalfilter/data/text_form_field.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();
+
+        // We have two text form fields
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+        // Check whether all fieldmarks are text form fields
+        for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+        {
+            ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+            CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMTEXT), pFieldmark->GetFieldname());
+        }
+
+        // In the first paragraph we have an empty text form field with the placeholder spaces
+        const uno::Reference< text::XTextRange > xPara = getParagraph(1);
+        sal_Unicode vEnSpaces[5] = {8194, 8194, 8194, 8194, 8194};
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(vEnSpaces, 5), xPara->getString());
+
+        // In the second paragraph we have a set text
+        const uno::Reference< text::XTextRange > xPara2 = getParagraph(2);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("xxxxx"), xPara2->getString());
+    }
+}
+
+void Test::testCheckBoxFormField()
+{
+    const OUString aFilterNames[] = {
+        "writer8",
+        "MS Word 97",
+        "Office Open XML Text",
+    };
+
+    for (const OUString& rFilterName : aFilterNames)
+    {
+        if (mxComponent.is())
+            mxComponent->dispose();
+        mxComponent = loadFromDesktop(m_directories.getURLFromSrc("/sw/qa/extras/globalfilter/data/checkbox_form_field.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();
+
+        // We have two check box form fields
+        if(rFilterName == "Office Open XML Text")
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(4), pMarkAccess->getAllMarksCount());
+        else
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+        int nIndex = 0;
+        for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+        {
+            ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+
+            if(rFilterName == "Office Open XML Text") // OOXML import also generates bookmarks
+            {
+                if(!pFieldmark)
+                    continue;
+            }
+
+            CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname());
+            ::sw::mark::ICheckboxFieldmark* pCheckBox = dynamic_cast< ::sw::mark::ICheckboxFieldmark* >(pFieldmark);
+            CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pCheckBox);
+
+            // The first one is unchecked, the other one is checked
+            if(nIndex == 0)
+                CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), !pCheckBox->IsChecked());
+            else
+                CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pCheckBox->IsChecked());
+            ++nIndex;
+        }
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(2), nIndex);
+    }
+}
+
+void Test::testDropDownFormField()
+{
+    const OUString aFilterNames[] = {
+        "writer8",
+        "MS Word 97",
+        "Office Open XML Text",
+    };
+
+    for (const OUString& rFilterName : aFilterNames)
+    {
+        if (mxComponent.is())
+            mxComponent->dispose();
+        mxComponent = loadFromDesktop(m_directories.getURLFromSrc("/sw/qa/extras/globalfilter/data/dropdown_form_field.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();
+
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+        int nIndex = 0;
+        for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+        {
+            ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(aIter->get());
+
+            if(!pFieldmark)
+                continue;
+
+            CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname());
+
+            // Check drop down field's parameters.
+            const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
+            css::uno::Sequence<OUString> vListEntries;
+            sal_Int32 nSelection = -1;
+            auto pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
+            if (pListEntries != pParameters->end())
+            {
+                pListEntries->second >>= vListEntries;
+
+                if(vListEntries.getLength())
+                {
+                    auto pResult = pParameters->find(ODF_FORMDROPDOWN_RESULT);
+                    if (pResult != pParameters->end())
+                    {
+                        pResult->second >>= nSelection;
+                    }
+                }
+            }
+
+            // The first one is empty
+            if(nIndex == 0)
+            {
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(0), vListEntries.getLength());
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(-1), nSelection);
+            }
+            else
+            {
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(4), vListEntries.getLength());
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(1), nSelection);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("1000"), vListEntries[0]);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("2000"), vListEntries[1]);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("3000"), vListEntries[2]);
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("4000"), vListEntries[3]);
+            }
+            ++nIndex;
+        }
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(2), nIndex);
+    }
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit e69e2851105287a1529ed366a902428aad93db2a
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Sun Mar 10 09:45:56 2019 +0100
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:35 2019 +0200

    MSForms: Fix handling of drop-down form field after DOC import
    
    In the properties dialog, code expected that the ODF_FORMDROPDOWN_RESULT
    is not set in case of an empty list. This caused a crash.
    The field popup window code expected that the list is not specified
    when it is empty, but DOC import code sets ODF_FORMDROPDOWN_LISTENTRY
    even if the list is empty.
    
    Change-Id: If4c86fc5a08cdc578150afaa42ad7e86bdba9150
    Reviewed-on: https://gerrit.libreoffice.org/68963
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    Tested-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit aa3b3ee8c2aad6af69f0710c7531ef2cf9fb1fc1)

diff --git a/sw/source/core/crsr/DropDownFormFieldButton.cxx b/sw/source/core/crsr/DropDownFormFieldButton.cxx
index a4614da8932e..bef4c873dace 100644
--- a/sw/source/core/crsr/DropDownFormFieldButton.cxx
+++ b/sw/source/core/crsr/DropDownFormFieldButton.cxx
@@ -53,14 +53,15 @@ SwFieldDialog::SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM, l
         OUString sListKey = ODF_FORMDROPDOWN_LISTENTRY;
         sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries
             = pParameters->find(sListKey);
+        css::uno::Sequence<OUString> vListEntries;
         if (pListEntries != pParameters->end())
         {
-            css::uno::Sequence<OUString> vListEntries;
             pListEntries->second >>= vListEntries;
             for (OUString const& i : vListEntries)
                 aListBox->InsertEntry(i);
         }
-        else
+
+        if (vListEntries.getLength() == 0)
         {
             aListBox->InsertEntry(SwResId(STR_DROP_DOWN_EMPTY_LIST));
         }
diff --git a/sw/source/ui/fldui/DropDownFormFieldDialog.cxx b/sw/source/ui/fldui/DropDownFormFieldDialog.cxx
index e52907fd6c74..dd187704aa7a 100644
--- a/sw/source/ui/fldui/DropDownFormFieldDialog.cxx
+++ b/sw/source/ui/fldui/DropDownFormFieldDialog.cxx
@@ -119,7 +119,8 @@ void DropDownFormFieldDialog::InitControls()
             {
                 sal_Int32 nSelection = -1;
                 pResult->second >>= nSelection;
-                m_xListItemsTreeView->select_text(vListEntries[nSelection]);
+                if (vListEntries.getLength() > nSelection)
+                    m_xListItemsTreeView->select_text(vListEntries[nSelection]);
             }
         }
     }
commit 324e54de0a00f90c2d868c714d69120a83d7765d
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Sat Mar 2 10:22:54 2019 +0100
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:35 2019 +0200

    MSForms: Open Control Properties dialog by double click for drop-down field
    
    Change-Id: I66c0a7bad63d929ae346afe9d328d87dfa2c24ae
    Reviewed-on: https://gerrit.libreoffice.org/68962
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/69196
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index 3d2e52058ce7..cb6b59b8736d 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -3348,6 +3348,21 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt)
                                 // table.
                                 rSh.SelTableBox();
                         }
+
+                        SwContentAtPos aContentAtPos(IsAttrAtPos::FormControl);
+                        if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
+                                aContentAtPos.aFnd.pFieldmark != nullptr)
+                        {
+                            IFieldmark *pFieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
+                            if ( pFieldBM->GetFieldname( ) == ODF_FORMDROPDOWN )
+                            {
+                                RstMBDownFlags();
+                                rSh.getIDocumentMarkAccess()->ClearFieldActivation();
+                                GetView().GetViewFrame()->GetBindings().Execute(SID_FM_CTL_PROPERTIES);
+                                return;
+                            }
+                        }
+
                         g_bHoldSelection = true;
                         return;
                     }
commit e87c8b4ce567492c71affdfdaf49426faa69d2a5
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jun 19 19:13:37 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:35 2019 +0200

    MSForms: Add a drop-down button for drop-down form field
    
    * Introduce a editing frame with a button for drop-down form field.
    ** The frame is mouse transparent.
    ** Pushing the button opens the popup window with the items of the field.
    * The button is visible when the cursor is inside the field.
    
    Reviewed-on: https://gerrit.libreoffice.org/68961
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit 10be5b6ce972dff517f3ceed41cab04d3e051f57)
    
    Change-Id: I5c7db138d14380899fee046c95a5afe14cfea213

diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index 6557c45434d1..9d2dbe51e0a4 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -628,7 +628,7 @@ protected:
 
     SAL_DLLPRIVATE void                 ImplInvalidate( const vcl::Region* rRegion, InvalidateFlags nFlags );
 
-    SAL_DLLPRIVATE WindowHitTest        ImplHitTest( const Point& rFramePos );
+    virtual WindowHitTest               ImplHitTest( const Point& rFramePos );
 
     SAL_DLLPRIVATE void                 ImplSetMouseTransparent( bool bTransparent );
 
diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index 2751a24a4b00..b70451c18df9 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -150,6 +150,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
     sw/source/core/crsr/crsrsh \
     sw/source/core/crsr/crstrvl \
     sw/source/core/crsr/crstrvl1 \
+    sw/source/core/crsr/DropDownFormFieldButton \
     sw/source/core/crsr/findattr \
     sw/source/core/crsr/findcoll \
     sw/source/core/crsr/findfmt \
diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index cbd523c012b1..d7111112612f 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -27,6 +27,7 @@
 class SwPaM;
 struct SwPosition;
 class SwTextNode;
+class SwCursorShell;
 
 namespace sw { namespace mark {
     class SaveBookmark; // FIXME: Ugly: SaveBookmark is a core-internal class, and should not be used in the interface
@@ -258,6 +259,9 @@ class IDocumentMarkAccess
         virtual void deleteFieldmarkAt(const SwPosition& rPos) = 0;
         virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) = 0;
 
+        virtual void NotifyCursorUpdate(const SwCursorShell& rCursorShell) = 0;
+        virtual void ClearFieldActivation() = 0;
+
         // Annotation Marks
         virtual const_iterator_t getAnnotationMarksBegin() const = 0;
         virtual const_iterator_t getAnnotationMarksEnd() const = 0;
diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index da13d2fb16e6..b16f0051d182 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -1332,6 +1332,9 @@
 #define STR_MENU_UP                             NC_("STR_MENU_UP", "~Upwards")
 #define STR_MENU_DOWN                           NC_("STR_MENU_DOWN", "Do~wnwards")
 
+
+#define STR_DROP_DOWN_EMPTY_LIST                NC_("STR_DROP_DOWN_EMPTY_LIST", "No Item specified")
+
 /*--------------------------------------------------------------------
     Description: Classification strings
  --------------------------------------------------------------------*/
diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx
index fe33f94e6dd9..94e2cc86e81e 100644
--- a/sw/inc/view.hxx
+++ b/sw/inc/view.hxx
@@ -208,7 +208,6 @@ class SW_DLLPUBLIC SwView: public SfxViewShell
     std::unique_ptr<SwPostItMgr> m_pPostItMgr;
 
     SelectionType       m_nSelectionType;
-    VclPtr<FloatingWindow> m_pFieldPopup;
     sal_uInt16          m_nPageCnt;
 
     // current draw mode
@@ -265,8 +264,6 @@ class SW_DLLPUBLIC SwView: public SfxViewShell
 
     DECL_DLLPRIVATE_LINK( TimeoutHdl, Timer*, void );
 
-    DECL_DLLPRIVATE_LINK( FieldPopupModeEndHdl, FloatingWindow*, void );
-
     inline long                  GetXScroll() const;
     inline long                  GetYScroll() const;
     SAL_DLLPRIVATE Point         AlignToPixel(const Point& rPt) const;
@@ -423,7 +420,6 @@ public:
 
     void            SpellError(LanguageType eLang);
     bool            ExecSpellPopup( const Point& rPt );
-    void                ExecFieldPopup( const Point& rPt, sw::mark::IFieldmark *fieldBM );
     void            ExecSmartTagPopup( const Point& rPt );
 
     DECL_LINK( OnlineSpellCallback, SpellCallbackInfo&, void );
diff --git a/sw/source/core/crsr/DropDownFormFieldButton.cxx b/sw/source/core/crsr/DropDownFormFieldButton.cxx
new file mode 100644
index 000000000000..a4614da8932e
--- /dev/null
+++ b/sw/source/core/crsr/DropDownFormFieldButton.cxx
@@ -0,0 +1,255 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * 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/.
+ */
+
+#include <DropDownFormFieldButton.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <edtwin.hxx>
+#include <basegfx/color/bcolortools.hxx>
+#include <viewopt.hxx>
+#include <bookmrk.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/event.hxx>
+#include <vcl/lstbox.hxx>
+#include <xmloff/odffields.hxx>
+#include <IMark.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <strings.hrc>
+
+/**
+ * Popup dialog for drop-down form field showing the list items of the field.
+ * The user can select the item using this popup while filling in a form.
+ */
+class SwFieldDialog : public FloatingWindow
+{
+private:
+    VclPtr<ListBox> aListBox;
+    sw::mark::IFieldmark* pFieldmark;
+
+    DECL_LINK(MyListBoxHandler, ListBox&, void);
+
+public:
+    SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM, long nMinListWidth);
+    virtual ~SwFieldDialog() override;
+    virtual void dispose() override;
+};
+
+SwFieldDialog::SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM, long nMinListWidth)
+    : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW)
+    , aListBox(VclPtr<ListBox>::Create(this))
+    , pFieldmark(fieldBM)
+{
+    if (fieldBM != nullptr)
+    {
+        const sw::mark::IFieldmark::parameter_map_t* const pParameters = fieldBM->GetParameters();
+
+        OUString sListKey = ODF_FORMDROPDOWN_LISTENTRY;
+        sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries
+            = pParameters->find(sListKey);
+        if (pListEntries != pParameters->end())
+        {
+            css::uno::Sequence<OUString> vListEntries;
+            pListEntries->second >>= vListEntries;
+            for (OUString const& i : vListEntries)
+                aListBox->InsertEntry(i);
+        }
+        else
+        {
+            aListBox->InsertEntry(SwResId(STR_DROP_DOWN_EMPTY_LIST));
+        }
+
+        // Select the current one
+        OUString sResultKey = ODF_FORMDROPDOWN_RESULT;
+        sw::mark::IFieldmark::parameter_map_t::const_iterator pResult
+            = pParameters->find(sResultKey);
+        if (pResult != pParameters->end())
+        {
+            sal_Int32 nSelection = -1;
+            pResult->second >>= nSelection;
+            aListBox->SelectEntryPos(nSelection);
+        }
+    }
+
+    Size lbSize(aListBox->GetOptimalSize());
+    lbSize.AdjustWidth(50);
+    lbSize.AdjustHeight(20);
+    lbSize.setWidth(std::max(lbSize.Width(), nMinListWidth));
+    aListBox->SetSizePixel(lbSize);
+    aListBox->SetSelectHdl(LINK(this, SwFieldDialog, MyListBoxHandler));
+    aListBox->Show();
+
+    SetSizePixel(lbSize);
+}
+
+SwFieldDialog::~SwFieldDialog() { disposeOnce(); }
+
+void SwFieldDialog::dispose()
+{
+    aListBox.disposeAndClear();
+    FloatingWindow::dispose();
+}
+
+IMPL_LINK(SwFieldDialog, MyListBoxHandler, ListBox&, rBox, void)
+{
+    if (!rBox.IsTravelSelect())
+    {
+        OUString sSelection = rBox.GetSelectedEntry();
+        if (sSelection == SwResId(STR_DROP_DOWN_EMPTY_LIST))
+        {
+            EndPopupMode();
+            return;
+        }
+
+        sal_Int32 nSelection = rBox.GetSelectedEntryPos();
+        if (nSelection >= 0)
+        {
+            OUString sKey = ODF_FORMDROPDOWN_RESULT;
+            (*pFieldmark->GetParameters())[sKey] <<= nSelection;
+            pFieldmark->Invalidate();
+            SwView& rView = static_cast<SwEditWin*>(GetParent())->GetView();
+            rView.GetDocShell()->SetModified();
+        }
+
+        EndPopupMode();
+    }
+}
+
+DropDownFormFieldButton::DropDownFormFieldButton(SwEditWin* pEditWin,
+                                                 sw::mark::DropDownFieldmark& rFieldmark)
+    : MenuButton(pEditWin, WB_DIALOGCONTROL)
+    , m_rFieldmark(rFieldmark)
+{
+    assert(GetParent());
+    assert(dynamic_cast<SwEditWin*>(GetParent()));
+}
+
+DropDownFormFieldButton::~DropDownFormFieldButton() { disposeOnce(); }
+
+void DropDownFormFieldButton::dispose()
+{
+    m_pFieldPopup.disposeAndClear();
+    MenuButton::dispose();
+}
+
+void DropDownFormFieldButton::CalcPosAndSize(const SwRect& rPortionPaintArea)
+{
+    assert(GetParent());
+
+    Point aBoxPos = GetParent()->LogicToPixel(rPortionPaintArea.Pos());
+    Size aBoxSize = GetParent()->LogicToPixel(rPortionPaintArea.SSize());
+
+    // First calculate the size of the frame around the field
+    int nPadding = aBoxSize.Height() / 4;
+    aBoxPos.AdjustX(-nPadding);
+    aBoxPos.AdjustY(-nPadding);
+    aBoxSize.AdjustWidth(2 * nPadding);
+    aBoxSize.AdjustHeight(2 * nPadding);
+
+    m_aFieldFramePixel = tools::Rectangle(aBoxPos, aBoxSize);
+
+    // Then extend the size with the button area
+    aBoxSize.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height());
+
+    SetPosSizePixel(aBoxPos, aBoxSize);
+}
+
+void DropDownFormFieldButton::MouseButtonUp(const MouseEvent&)
+{
+    assert(GetParent());
+
+    Point aPixPos = GetPosPixel();
+    aPixPos.AdjustY(GetSizePixel().Height());
+
+    m_pFieldPopup = VclPtr<SwFieldDialog>::Create(static_cast<SwEditWin*>(GetParent()),
+                                                  &m_rFieldmark, GetSizePixel().Width());
+    m_pFieldPopup->SetPopupModeEndHdl(LINK(this, DropDownFormFieldButton, FieldPopupModeEndHdl));
+
+    tools::Rectangle aRect(GetParent()->OutputToScreenPixel(aPixPos), Size(0, 0));
+    m_pFieldPopup->StartPopupMode(aRect, FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus);
+    Invalidate();
+}
+
+IMPL_LINK_NOARG(DropDownFormFieldButton, FieldPopupModeEndHdl, FloatingWindow*, void)
+{
+    m_pFieldPopup.disposeAndClear();
+    m_rFieldmark.Invalidate();
+    // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen
+    Show(false);
+    Invalidate();
+}
+
+static basegfx::BColor lcl_GetFillColor(const basegfx::BColor& rLineColor, double aLuminance)
+{
+    basegfx::BColor aHslLine = basegfx::utils::rgb2hsl(rLineColor);
+    aHslLine.setZ(aLuminance);
+    return basegfx::utils::hsl2rgb(aHslLine);
+}
+
+void DropDownFormFieldButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
+{
+    SetMapMode(MapMode(MapUnit::MapPixel));
+
+    //const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
+    Color aLineColor = COL_BLACK;
+    Color aFillColor
+        = Color(lcl_GetFillColor(aLineColor.getBColor(), (m_pFieldPopup ? 0.5 : 0.75)));
+
+    // Draw the frame around the field
+    // GTK3 backend cuts down the frame's top and left border, to avoid that add a padding around the frame
+    int nPadding = 1;
+    Point aPos(nPadding, nPadding);
+    Size aSize(m_aFieldFramePixel.GetSize().Width() - nPadding,
+               m_aFieldFramePixel.GetSize().Height() - 2 * nPadding);
+    const tools::Rectangle aFrameRect(tools::Rectangle(aPos, aSize));
+    rRenderContext.SetLineColor(aLineColor);
+    rRenderContext.SetFillColor(COL_TRANSPARENT);
+    rRenderContext.DrawRect(aFrameRect);
+
+    // Draw the button next to the frame
+    Point aButtonPos(aFrameRect.TopLeft());
+    aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - 1);
+    Size aButtonSize(aFrameRect.GetSize());
+    aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getWidth() - nPadding);
+    const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize));
+
+    // Background & border
+    rRenderContext.SetLineColor(aLineColor);
+    rRenderContext.SetFillColor(aFillColor);
+    rRenderContext.DrawRect(aButtonRect);
+
+    // the arrowhead
+    rRenderContext.SetLineColor(aLineColor);
+    rRenderContext.SetFillColor(aLineColor);
+
+    Point aCenter(aButtonPos.X() + (aButtonSize.Width() / 2),
+                  aButtonPos.Y() + (aButtonSize.Height() / 2));
+    Size aArrowSize(aButtonSize.Width() / 4, aButtonSize.Height() / 10);
+
+    tools::Polygon aPoly(3);
+    aPoly.SetPoint(Point(aCenter.X() - aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 0);
+    aPoly.SetPoint(Point(aCenter.X() + aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 1);
+    aPoly.SetPoint(Point(aCenter.X(), aCenter.Y() + aArrowSize.Height()), 2);
+    rRenderContext.DrawPolygon(aPoly);
+}
+
+WindowHitTest DropDownFormFieldButton::ImplHitTest(const Point& rFramePos)
+{
+    // We need to check whether the position hits the button (the frame should be mouse transparent)
+    WindowHitTest aResult = MenuButton::ImplHitTest(rFramePos);
+    if (aResult != WindowHitTest::Inside)
+        return aResult;
+    else
+    {
+        return rFramePos.X() >= m_aFieldFramePixel.Right() ? WindowHitTest::Inside
+                                                           : WindowHitTest::Transparent;
+    }
+}
+
+/* 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 259168f49440..f3cd8ddf9d91 100644
--- a/sw/source/core/crsr/bookmrk.cxx
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -37,6 +37,7 @@
 #include <comphelper/random.hxx>
 #include <comphelper/anytostring.hxx>
 #include <sal/log.hxx>
+#include <edtwin.hxx>
 
 using namespace ::sw::mark;
 using namespace ::com::sun::star;
@@ -482,11 +483,13 @@ namespace sw { namespace mark
 
     DropDownFieldmark::DropDownFieldmark(const SwPaM& rPaM)
         : Fieldmark(rPaM)
+        , m_pButton(nullptr)
     {
     }
 
     DropDownFieldmark::~DropDownFieldmark()
     {
+        m_pButton.disposeAndClear();
     }
 
     void DropDownFieldmark::InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode const eMode)
@@ -512,6 +515,44 @@ namespace sw { namespace mark
         lcl_RemoveFieldMarks(this, pDoc,
                 CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
     }
+
+    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();
+        }
+    }
+
+    void DropDownFieldmark::ShowButton(SwEditWin* pEditWin)
+    {
+        if(pEditWin)
+        {
+            if(!m_pButton)
+                m_pButton = VclPtr<DropDownFormFieldButton>::Create(pEditWin, *this);
+            m_pButton->CalcPosAndSize(m_aPortionPaintArea);
+            m_pButton->Show();
+        }
+    }
+
+    void DropDownFieldmark::HideButton()
+    {
+        if(m_pButton)
+            m_pButton->Show(false);
+    }
+
+    void DropDownFieldmark::RemoveButton()
+    {
+        if(m_pButton)
+            m_pButton.disposeAndClear();
+    }
 }}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 607c6f42ca92..696eb41c73c8 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2007,6 +2007,8 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
 
     if( m_bSVCursorVis )
         m_pVisibleCursor->Show(); // show again
+
+    getIDocumentMarkAccess()->NotifyCursorUpdate(*this);
 }
 
 void SwCursorShell::RefreshBlockCursor()
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 222eeb846e8c..7068e81b5c91 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -55,6 +55,7 @@
 #include <viscrs.hxx>
 #include <edimp.hxx>
 #include <tools/datetimeutils.hxx>
+#include <view.hxx>
 
 using namespace ::sw::mark;
 
@@ -373,6 +374,7 @@ namespace sw { namespace mark
         , m_vFieldmarks()
         , m_vAnnotationMarks()
         , m_pDoc(&rDoc)
+        , m_pLastActiveFieldmark(nullptr)
     { }
 
     ::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM,
@@ -960,6 +962,9 @@ namespace sw { namespace mark
                     IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark);
                     if ( ppFieldmark != m_vFieldmarks.end() )
                     {
+                        if(m_pLastActiveFieldmark == ppFieldmark->get())
+                            ClearFieldActivation();
+
                         m_vFieldmarks.erase(ppFieldmark);
                         ret.reset(new LazyFieldmarkDeleter(*ppMark, m_pDoc));
                     }
@@ -1036,6 +1041,7 @@ namespace sw { namespace mark
 
     void MarkManager::clearAllMarks()
     {
+        ClearFieldActivation();
         m_vFieldmarks.clear();
         m_vBookmarks.clear();
         m_aMarkNamesSet.clear();
@@ -1123,10 +1129,61 @@ namespace sw { namespace mark
         SwPaM aPaM(pFieldmark->GetMarkPos());
 
         // Remove the old fieldmark and create a new one with the new type
-        deleteFieldmarkAt(*aPaM.GetPoint());
-        return makeNoTextFieldBookmark(aPaM, sName, rNewType);
+        if(aPaM.GetPoint()->nContent > 0)
+        {
+            --aPaM.GetPoint()->nContent;
+            SwPosition aNewPos (aPaM.GetPoint()->nNode, aPaM.GetPoint()->nContent);
+            deleteFieldmarkAt(aNewPos);
+            return makeNoTextFieldBookmark(aPaM, sName, rNewType);
+        }
+        return nullptr;
+    }
+
+    void MarkManager::NotifyCursorUpdate(const SwCursorShell& rCursorShell)
+    {
+        SwView* pSwView = dynamic_cast<SwView *>(rCursorShell.GetSfxViewShell());
+        if(!pSwView)
+            return;
+
+        SwEditWin& rEditWin = pSwView->GetEditWin();
+        SwPosition aPos(*rCursorShell.GetCursor()->GetPoint());
+        IFieldmark* pFieldBM = getFieldmarkFor(aPos);
+        DropDownFieldmark* pNewActiveFieldmark = nullptr;
+        if ((!pFieldBM || pFieldBM->GetFieldname() != ODF_FORMDROPDOWN)
+            && aPos.nContent.GetIndex() > 0 )
+        {
+            --aPos.nContent;
+            pFieldBM = getFieldmarkFor(aPos);
+        }
+
+        if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN )
+        {
+            if (m_pLastActiveFieldmark != pFieldBM)
+            {
+                DropDownFieldmark* pDropDownFm = dynamic_cast<DropDownFieldmark*>(pFieldBM);
+                pDropDownFm->ShowButton(&rEditWin);
+                pNewActiveFieldmark = pDropDownFm;
+            }
+            else
+            {
+                pNewActiveFieldmark = m_pLastActiveFieldmark;
+            }
+        }
+
+        if(pNewActiveFieldmark != m_pLastActiveFieldmark)
+        {
+            ClearFieldActivation();
+            m_pLastActiveFieldmark = pNewActiveFieldmark;
+        }
     }
 
+    void MarkManager::ClearFieldActivation()
+    {
+        if(m_pLastActiveFieldmark)
+            m_pLastActiveFieldmark->RemoveButton();
+
+        m_pLastActiveFieldmark = nullptr;
+    }
 
     IFieldmark* MarkManager::getDropDownFor(const SwPosition& rPos) const
     {
diff --git a/sw/source/core/inc/DropDownFormFieldButton.hxx b/sw/source/core/inc/DropDownFormFieldButton.hxx
new file mode 100644
index 000000000000..e8b9153cb1a6
--- /dev/null
+++ b/sw/source/core/inc/DropDownFormFieldButton.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * 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/.
+ */
+
+#ifndef INCLUDED_SW_SOURCE_CORE_TEXT_DROPDOWNFORMEFIELDBUTTO_HXX
+#define INCLUDED_SW_SOURCE_CORE_TEXT_DROPDOWNFORMEFIELDBUTTO_HXX
+
+#include <vcl/menubtn.hxx>
+#include <swrect.hxx>
+
+class SwFieldFormDropDownPortion;
+class SwEditWin;
+class FloatingWindow;
+namespace sw
+{
+namespace mark
+{
+class DropDownFieldmark;
+}
+}
+
+/**
+ * This button is shown when the cursor is in a drop-down form field.
+ * The user can select an item of the field using this button while filling in a form.
+ */
+class DropDownFormFieldButton : public MenuButton
+{
+public:
+    DropDownFormFieldButton(SwEditWin* pEditWin, sw::mark::DropDownFieldmark& rFieldMark);
+    virtual ~DropDownFormFieldButton() override;
+    virtual void dispose() override;
+
+    void CalcPosAndSize(const SwRect& rPortionPaintArea);
+
+    virtual void MouseButtonUp(const MouseEvent& rMEvt) override;
+    DECL_LINK(FieldPopupModeEndHdl, FloatingWindow*, void);
+
+    virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+    virtual WindowHitTest ImplHitTest(const Point& rFramePos) override;
+
+private:
+    tools::Rectangle m_aFieldFramePixel;
+    sw::mark::DropDownFieldmark& m_rFieldmark;
+    VclPtr<FloatingWindow> m_pFieldPopup;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
index 4544bae57b85..6ca604a29976 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -24,11 +24,16 @@
 #include <IDocumentMarkAccess.hxx>
 #include <unordered_set>
 #include <unordered_map>
+#include <memory>
+
+class SwCursorShell;
 
 namespace sw {
     namespace mark {
     typedef std::unordered_map<OUString, sal_Int32> MarkBasenameMapUniqueOffset_t;
 
+    class DropDownFieldmark;
+
     class MarkManager
         : virtual public IDocumentMarkAccess
     {
@@ -88,6 +93,9 @@ namespace sw {
             virtual void deleteFieldmarkAt(const SwPosition& rPos) override;
             virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) override;
 
+            virtual void NotifyCursorUpdate(const SwCursorShell& rCursorShell) override;
+            virtual void ClearFieldActivation() override;
+
             void dumpAsXml(struct _xmlTextWriter* pWriter) const;
 
             // Annotation Marks
@@ -126,6 +134,8 @@ namespace sw {
             container_t m_vAnnotationMarks;
 
             SwDoc * const m_pDoc;
+
+            sw::mark::DropDownFieldmark* m_pLastActiveFieldmark;
     };
     } // namespace mark
 }
diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx
index 362f0aeb3156..142fbf7fe4a0 100644
--- a/sw/source/core/inc/bookmrk.hxx
+++ b/sw/source/core/inc/bookmrk.hxx
@@ -29,6 +29,8 @@
 #include <osl/diagnose.h>
 #include <IMark.hxx>
 #include <swserv.hxx>
+#include <swrect.hxx>
+#include "DropDownFormFieldButton.hxx"
 
 namespace com {
     namespace sun {
@@ -42,6 +44,7 @@ namespace com {
 
 struct SwPosition;  // fwd Decl. wg. UI
 class SwDoc;
+class SwEditWin;
 
 namespace sw {
     namespace mark {
@@ -267,6 +270,17 @@ namespace sw {
             virtual ~DropDownFieldmark() override;
             virtual void InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) override;
             virtual void ReleaseDoc(SwDoc* const pDoc) override;
+
+            // This method should be called only by the portion so we can now the portion's painting area
+            void SetPortionPaintArea(const SwRect& rPortionPaintArea);
+
+            void ShowButton(SwEditWin* pEditWin);
+            void HideButton();
+            void RemoveButton();
+
+        private:
+            SwRect m_aPortionPaintArea;
+            VclPtr<DropDownFormFieldButton> m_pButton;
         };
     }
 }
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index a864f281c70d..44acc4e194b5 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -908,7 +908,7 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const
                     }
                     else if (pBM->GetFieldname( ) == ODF_FORMDROPDOWN)
                     {
-                        pPor = new SwFieldFormDropDownPortion(sw::mark::ExpandFieldmark(pBM));
+                        pPor = new SwFieldFormDropDownPortion(pBM, sw::mark::ExpandFieldmark(pBM));
                     }
                     /* 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 bb563e63875a..b03d28942e3d 100644
--- a/sw/source/core/text/porfld.cxx
+++ b/sw/source/core/text/porfld.cxx
@@ -44,6 +44,7 @@
 #include <accessibilityoptions.hxx>
 #include <editeng/lrspitem.hxx>
 #include <unicode/ubidi.h>
+#include <bookmrk.hxx>
 
 using namespace ::com::sun::star;
 
@@ -1311,7 +1312,20 @@ sal_uInt16 SwCombinedPortion::GetViewWidth( const SwTextSizeInfo &rInf ) const
 
 SwFieldPortion *SwFieldFormDropDownPortion::Clone(const OUString &rExpand) const
 {
-    return new SwFieldFormDropDownPortion(rExpand);
+    return new SwFieldFormDropDownPortion(m_pFieldMark, rExpand);
+}
+
+void SwFieldFormDropDownPortion::Paint( const SwTextPaintInfo &rInf ) const
+{
+    SwFieldPortion::Paint( rInf );
+
+    ::sw::mark::DropDownFieldmark* pDropDownField = dynamic_cast< ::sw::mark::DropDownFieldmark* >(m_pFieldMark);
+    if(pDropDownField)
+    {
+        SwRect aPaintArea;
+        rInf.CalcRect( *this, &aPaintArea );
+        pDropDownField->SetPortionPaintArea(aPaintArea);
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porfld.hxx b/sw/source/core/text/porfld.hxx
index 1490d9399c60..2d1498d9b3ac 100644
--- a/sw/source/core/text/porfld.hxx
+++ b/sw/source/core/text/porfld.hxx
@@ -218,12 +218,18 @@ namespace sw { namespace mark {
 class SwFieldFormDropDownPortion : public SwFieldPortion
 {
 public:
-    explicit SwFieldFormDropDownPortion(const OUString &rExpand)
+    explicit SwFieldFormDropDownPortion(sw::mark::IFieldmark *pFieldMark, const OUString &rExpand)
         : SwFieldPortion(rExpand)
+        , m_pFieldMark(pFieldMark)
     {
     }
     // Field cloner for SplitGlue
     virtual SwFieldPortion *Clone( const OUString &rExpand ) const override;
+
+    virtual void Paint( const SwTextPaintInfo &rInf ) const override;
+
+private:
+    sw::mark::IFieldmark* m_pFieldMark;
 };
 
 #endif
diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index 0f4a669bcf05..3d2e52058ce7 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -4613,12 +4613,6 @@ void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt)
                                         rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
                                         rCheckboxFm.Invalidate();
                                         rSh.InvalidateWindows( m_rView.GetVisArea() );
-                                    } else if ( fieldBM->GetFieldname() == ODF_FORMDROPDOWN ) {
-                                        m_rView.ExecFieldPopup( aDocPt, fieldBM );
-                                        fieldBM->Invalidate();
-                                        rSh.InvalidateWindows( m_rView.GetVisArea() );
-                                    } else {
-                                        // unknown type..
                                     }
                                 }
                             }
diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx
index bef8fe50dfb1..b95e5b9fcc76 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -121,6 +121,7 @@
 #include <memory>
 #include <xmloff/odffields.hxx>
 #include <swabstdlg.hxx>
+#include <bookmrk.hxx>
 
 using namespace ::com::sun::star;
 using namespace com::sun::star::beans;
@@ -1354,10 +1355,14 @@ void SwTextShell::Execute(SfxRequest &rReq)
         {
             SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
             ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDropDownFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pFieldBM));
-            pDlg->Execute();
-            pFieldBM->Invalidate();
-            rWrtSh.InvalidateWindows( rWrtSh.GetView().GetVisArea() );
-            rWrtSh.UpdateCursor(); // cursor position might be invalid
+            if (pDlg->Execute() == RET_OK)
+            {
+                pFieldBM->Invalidate();
+                rWrtSh.InvalidateWindows( rWrtSh.GetView().GetVisArea() );
+                rWrtSh.UpdateCursor(); // cursor position might be invalid
+                // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen
+                dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldBM)->HideButton();
+            }
         }
         else
         {
diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx
index c3a6711e6d50..039977ff6827 100644
--- a/sw/source/uibase/uiview/view.cxx
+++ b/sw/source/uibase/uiview/view.cxx
@@ -1065,6 +1065,9 @@ SwView::~SwView()
     SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", "");
     SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
 
+    // Need to remove activated field's button before disposing EditWin.
+    GetWrtShell().getIDocumentMarkAccess()->ClearFieldActivation();
+
     GetViewFrame()->GetWindow().RemoveChildEventListener( LINK( this, SwView, WindowChildEventListener ) );
     m_pPostItMgr.reset();
 
diff --git a/sw/source/uibase/uiview/viewling.cxx b/sw/source/uibase/uiview/viewling.cxx
index c29c1637ab87..6aed16bc533f 100644
--- a/sw/source/uibase/uiview/viewling.cxx
+++ b/sw/source/uibase/uiview/viewling.cxx
@@ -822,114 +822,4 @@ void SwView::ExecSmartTagPopup( const Point& rPt )
     m_pWrtShell->LockView( bOldViewLock );
 }
 
-class SwFieldDialog : public FloatingWindow
-{
-private:
-    VclPtr<ListBox> aListBox;
-    IFieldmark *pFieldmark;
-
-    DECL_LINK( MyListBoxHandler, ListBox&, void );
-
-public:
-    SwFieldDialog( SwEditWin* parent, IFieldmark *fieldBM );
-    virtual ~SwFieldDialog() override;
-    virtual void dispose() override;
-};
-
-SwFieldDialog::SwFieldDialog( SwEditWin* parent, IFieldmark *fieldBM ) :
-    FloatingWindow( parent, WB_BORDER | WB_SYSTEMWINDOW ),
-    aListBox(VclPtr<ListBox>::Create(this)),
-    pFieldmark( fieldBM )
-{
-    if ( fieldBM != nullptr )
-    {
-        const IFieldmark::parameter_map_t* const pParameters = fieldBM->GetParameters();
-
-        OUString sListKey = ODF_FORMDROPDOWN_LISTENTRY;
-        IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find( sListKey );
-        if(pListEntries != pParameters->end())
-        {
-            Sequence< OUString > vListEntries;
-            pListEntries->second >>= vListEntries;
-            for( OUString const & i : vListEntries)
-                aListBox->InsertEntry(i);
-        }
-
-        // Select the current one
-        OUString sResultKey = ODF_FORMDROPDOWN_RESULT;
-        IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find( sResultKey );
-        if ( pResult != pParameters->end() )
-        {
-            sal_Int32 nSelection = -1;
-            pResult->second >>= nSelection;
-            aListBox->SelectEntryPos( nSelection );
-        }
-    }
-
-    Size lbSize(aListBox->GetOptimalSize());
-    lbSize.AdjustWidth(50 );
-    lbSize.AdjustHeight(20 );
-    aListBox->SetSizePixel(lbSize);
-    aListBox->SetSelectHdl( LINK( this, SwFieldDialog, MyListBoxHandler ) );
-    aListBox->Show();
-
-    SetSizePixel( lbSize );
-}
-
-SwFieldDialog::~SwFieldDialog()
-{
-    disposeOnce();
-}
-
-void SwFieldDialog::dispose()
-{
-    aListBox.disposeAndClear();
-    FloatingWindow::dispose();
-}
-
-IMPL_LINK( SwFieldDialog, MyListBoxHandler, ListBox&, rBox, void )
-{
-    if ( !rBox.IsTravelSelect() )
-    {
-        sal_Int32 selection = rBox.GetSelectedEntryPos();
-        if ( selection >= 0 )
-        {
-            OUString sKey = ODF_FORMDROPDOWN_RESULT;
-            (*pFieldmark->GetParameters())[ sKey ] <<= selection;
-            pFieldmark->Invalidate();
-            SwView& rView = static_cast<SwEditWin*>( GetParent() )->GetView();
-            rView.GetDocShell()->SetModified();
-        }
-
-        EndPopupMode();
-    }
-}
-
-IMPL_LINK_NOARG(SwView, FieldPopupModeEndHdl, FloatingWindow*, void)
-{
-    m_pFieldPopup.disposeAndClear();
-}
-
-void SwView::ExecFieldPopup( const Point& rPt, IFieldmark *fieldBM )
-{
-    // Don't show popup if there is no list item
-    auto pListEntries = fieldBM->GetParameters()->find( ODF_FORMDROPDOWN_LISTENTRY );
-    Sequence< OUString > vListEntries;
-    if(pListEntries != fieldBM->GetParameters()->end())
-    {
-        pListEntries->second >>= vListEntries;
-    }
-
-    if(vListEntries.getLength() == 0)
-        return;
-
-    const Point aPixPos = GetEditWin().LogicToPixel( rPt );
-
-    m_pFieldPopup = VclPtr<SwFieldDialog>::Create( m_pEditWin, fieldBM );
-    m_pFieldPopup->SetPopupModeEndHdl( LINK( this, SwView, FieldPopupModeEndHdl ) );
-
-    tools::Rectangle aRect( m_pEditWin->OutputToScreenPixel( aPixPos ), Size( 0, 0 ) );
-    m_pFieldPopup->StartPopupMode( aRect, FloatWinPopupFlags::Down|FloatWinPopupFlags::GrabFocus );
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit c34f0b2d0695d69196e90820e479ce541c5973f5
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jun 19 16:39:27 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:35 2019 +0200

    MSForms: Introduce a new IFieldMark for drop-down form field
    
    * It was weird anyway that a drop-down form field was represented
    as an CheckboxFieldmark.
    * It will be useful for later commits, to have a separate field type
    for drop-down field.
    * Needed to fix-up the API a bit because it was designed to specify
    the field type after initialization. I solved it in a way to not break
    the API behavior. Hopefully it's not very slow.
    
    Reviewed-on: https://gerrit.libreoffice.org/68960
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit f66a83c95c21b4311918a64bb85016857b49f4d4)
    
    Change-Id: I3103e6b1c36289b27b62ab9ca7dfeebc14901c8a
    Reviewed-on: https://gerrit.libreoffice.org/69194
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index 823326e2b8ac..cbd523c012b1 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -47,6 +47,7 @@ class IDocumentMarkAccess
             ANNOTATIONMARK,
             TEXT_FIELDMARK,
             CHECKBOX_FIELDMARK,
+            DROPDOWN_FIELDMARK,
             NAVIGATOR_REMINDER
         };
 
@@ -255,6 +256,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;
 
         // Annotation Marks
         virtual const_iterator_t getAnnotationMarksBegin() const = 0;
diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx
index 1fa3e307aca5..259168f49440 100644
--- a/sw/source/core/crsr/bookmrk.cxx
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -479,6 +479,39 @@ namespace sw { namespace mark
             pResult->second >>= bResult;
         return bResult;
     }
+
+    DropDownFieldmark::DropDownFieldmark(const SwPaM& rPaM)
+        : Fieldmark(rPaM)
+    {
+    }
+
+    DropDownFieldmark::~DropDownFieldmark()
+    {
+    }
+
+    void DropDownFieldmark::InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode const eMode)
+    {
+        if (eMode == sw::mark::InsertMode::New)
+        {
+            lcl_SetFieldMarks(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
+
+            // For some reason the end mark is moved from 1 by the Insert:
+            // we don't want this for checkboxes
+            SwPosition aNewEndPos = GetMarkEnd();
+            aNewEndPos.nContent--;
+            SetMarkEndPos( aNewEndPos );
+        }
+        else
+        {
+            lcl_AssertFieldMarksSet(this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
+        }
+    }
+
+    void DropDownFieldmark::ReleaseDoc(SwDoc* const pDoc)
+    {
+        lcl_RemoveFieldMarks(this, pDoc,
+                CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
+    }
 }}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 97b29bdb21c6..222eeb846e8c 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -339,6 +339,8 @@ IDocumentMarkAccess::MarkType IDocumentMarkAccess::GetType(const IMark& rBkmk)
         return MarkType::TEXT_FIELDMARK;
     else if(*pMarkTypeInfo == typeid(CheckboxFieldmark))
         return MarkType::CHECKBOX_FIELDMARK;
+    else if(*pMarkTypeInfo == typeid(DropDownFieldmark))
+        return MarkType::DROPDOWN_FIELDMARK;
     else if(*pMarkTypeInfo == typeid(NavigatorReminder))
         return MarkType::NAVIGATOR_REMINDER;
     else
@@ -415,6 +417,9 @@ namespace sw { namespace mark
             case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK:
                 pMark = std::shared_ptr<IMark>(new CheckboxFieldmark(rPaM));
                 break;
+            case IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK:
+                pMark = std::shared_ptr<IMark>(new DropDownFieldmark(rPaM));
+                break;
             case IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER:
                 pMark = std::shared_ptr<IMark>(new NavigatorReminder(rPaM));
                 break;
@@ -464,6 +469,7 @@ namespace sw { namespace mark
                 break;
             case IDocumentMarkAccess::MarkType::TEXT_FIELDMARK:
             case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK:
+            case IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK:
                 lcl_InsertMarkSorted(m_vFieldmarks, pMark);
                 break;
             case IDocumentMarkAccess::MarkType::ANNOTATIONMARK:
@@ -524,9 +530,20 @@ namespace sw { namespace mark
         bool bEnableSetModified = m_pDoc->getIDocumentState().IsEnableSetModified();
         m_pDoc->getIDocumentState().SetEnableSetModified(false);
 
-        sw::mark::IMark* pMark = makeMark( rPaM, rName,
-                IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK,
-                sw::mark::InsertMode::New);
+        sw::mark::IMark* pMark = nullptr;
+        if(rType == ODF_FORMCHECKBOX)
+        {
+            pMark = makeMark( rPaM, rName,
+                    IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK,
+                    sw::mark::InsertMode::New);
+        }
+        else if(rType == ODF_FORMDROPDOWN)
+        {
+            pMark = makeMark( rPaM, rName,
+                    IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK,
+                    sw::mark::InsertMode::New);
+        }
+
         sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
         if (pFieldMark)
             pFieldMark->SetFieldname( rType );
@@ -938,6 +955,7 @@ namespace sw { namespace mark
 
             case IDocumentMarkAccess::MarkType::TEXT_FIELDMARK:
             case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK:
+            case IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK:
                 {
                     IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark);
                     if ( ppFieldmark != m_vFieldmarks.end() )
@@ -1083,6 +1101,32 @@ namespace sw { namespace mark
         deleteMark(lcl_FindMark(m_vAllMarks, *pFieldmark));
     }
 
+    ::sw::mark::IFieldmark* MarkManager::changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType)
+    {
+        bool bActualChange = false;
+        if(rNewType == ODF_FORMDROPDOWN)
+        {
+            if (dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark))
+                bActualChange = true;
+        }
+        else if(rNewType == ODF_FORMCHECKBOX)
+        {
+            if (dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldmark))
+                bActualChange = true;
+        }
+
+        if (!bActualChange)
+            return nullptr;
+
+        // Store attributes needed to create the new fieldmark
+        OUString sName = pFieldmark->GetName();
+        SwPaM aPaM(pFieldmark->GetMarkPos());
+
+        // Remove the old fieldmark and create a new one with the new type
+        deleteFieldmarkAt(*aPaM.GetPoint());
+        return makeNoTextFieldBookmark(aPaM, sName, rNewType);
+    }
+
 
     IFieldmark* MarkManager::getDropDownFor(const SwPosition& rPos) const
     {
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
index 7a3612bb6131..4544bae57b85 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -86,6 +86,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;
 
             void dumpAsXml(struct _xmlTextWriter* pWriter) const;
 
diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx
index d5f0495ef09e..362f0aeb3156 100644
--- a/sw/source/core/inc/bookmrk.hxx
+++ b/sw/source/core/inc/bookmrk.hxx
@@ -245,6 +245,7 @@ namespace sw {
             virtual void ReleaseDoc(SwDoc* const pDoc) override;
         };
 
+        /// Fieldmark representing a checkbox form field.
         class CheckboxFieldmark
             : virtual public ICheckboxFieldmark
             , public Fieldmark
@@ -256,6 +257,17 @@ namespace sw {
             bool IsChecked() const override;
             void SetChecked(bool checked) override;
         };
+
+        /// Fieldmark representing a drop-down form field.
+        class DropDownFieldmark
+            : public Fieldmark
+        {
+        public:
+            DropDownFieldmark(const SwPaM& rPaM);
+            virtual ~DropDownFieldmark() override;
+            virtual void InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) override;
+            virtual void ReleaseDoc(SwDoc* const pDoc) override;
+        };
     }
 }
 #endif
diff --git a/sw/source/core/inc/unobookmark.hxx b/sw/source/core/inc/unobookmark.hxx
index 39a9e973502f..a11f42c4d855 100644
--- a/sw/source/core/inc/unobookmark.hxx
+++ b/sw/source/core/inc/unobookmark.hxx
@@ -67,6 +67,8 @@ protected:
 
     const ::sw::mark::IMark* GetBookmark() const;
 
+    IDocumentMarkAccess* GetIDocumentMarkAccess();
+
     void registerInMark( SwXBookmark& rXMark, ::sw::mark::IMark* const pMarkBase );
 
     virtual ~SwXBookmark() override;
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 3517812be531..a864f281c70d 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -917,10 +917,6 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const
                     {
                         pPor = new SwFieldMarkPortion();
                     }
-                    else
-                    {
-                        assert( false );        // unknown type...
-                    }
                 }
             }
             if( !pPor )
diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx
index a66247f33fe1..abd18ac53499 100644
--- a/sw/source/core/unocore/unobkm.cxx
+++ b/sw/source/core/unocore/unobkm.cxx
@@ -134,6 +134,11 @@ const ::sw::mark::IMark* SwXBookmark::GetBookmark() const
     return m_pImpl->m_pRegisteredBookmark;
 }
 
+IDocumentMarkAccess* SwXBookmark::GetIDocumentMarkAccess()
+{
+    return m_pImpl->m_pDoc->getIDocumentMarkAccess();
+}
+
 SwXBookmark::SwXBookmark(SwDoc *const pDoc)
     : m_pImpl( new SwXBookmark::Impl(pDoc) )
 {
@@ -620,7 +625,21 @@ void SwXFieldmark::setFieldType(const OUString & fieldType)
         dynamic_cast<const IFieldmark*>(GetBookmark()));
     if(!pBkm)
         throw uno::RuntimeException();
-    pBkm->SetFieldname(fieldType);
+    if(fieldType != getFieldType())
+    {
+        if(fieldType == ODF_FORMDROPDOWN || fieldType == ODF_FORMCHECKBOX)
+        {
+            ::sw::mark::IFieldmark* pNewFieldmark = GetIDocumentMarkAccess()->changeNonTextFieldmarkType(pBkm, fieldType);
+            if (pNewFieldmark)
+            {
+                registerInMark(*this, pNewFieldmark);
+                return;
+            }
+        }
+
+        // We did not generate a new fieldmark, so set the type ID
+        pBkm->SetFieldname(fieldType);
+    }
 }
 
 uno::Reference<container::XNameContainer> SwXFieldmark::getParameters()
@@ -654,6 +673,8 @@ SwXFieldmark::CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark *const pMark,
             pXBkmk = new SwXFieldmark(false, &rDoc);
         else if (dynamic_cast< ::sw::mark::CheckboxFieldmark* >(pMark))
             pXBkmk = new SwXFieldmark(true, &rDoc);
+        else if (dynamic_cast< ::sw::mark::DropDownFieldmark* >(pMark))
+            pXBkmk = new SwXFieldmark(true, &rDoc);
         else
             pXBkmk = new SwXFieldmark(isReplacementObject, &rDoc);
 
diff --git a/writerfilter/source/dmapper/FormControlHelper.cxx b/writerfilter/source/dmapper/FormControlHelper.cxx
index 3088a4a27361..98e7bb0ba319 100644
--- a/writerfilter/source/dmapper/FormControlHelper.cxx
+++ b/writerfilter/source/dmapper/FormControlHelper.cxx
@@ -202,6 +202,20 @@ bool FormControlHelper::createCheckbox(uno::Reference<text::XTextRange> const& x
 
 void FormControlHelper::processField(uno::Reference<text::XFormField> const& xFormField)
 {
+    // Set field type first before adding parameters.
+    if (m_pImpl->m_eFieldId == FIELD_FORMTEXT )
+    {
+        xFormField->setFieldType(ODF_FORMTEXT);
+    }
+    else if (m_pImpl->m_eFieldId == FIELD_FORMCHECKBOX )
+    {
+        xFormField->setFieldType(ODF_FORMCHECKBOX);
+    }
+    else if (m_pImpl->m_eFieldId == FIELD_FORMDROPDOWN )
+    {
+        xFormField->setFieldType(ODF_FORMDROPDOWN);
+    }
+
     uno::Reference<container::XNameContainer> xNameCont = xFormField->getParameters();
     uno::Reference<container::XNamed> xNamed( xFormField, uno::UNO_QUERY );
     if ( m_pFFData && xNamed.is() && xNameCont.is() )
@@ -223,7 +237,6 @@ void FormControlHelper::processField(uno::Reference<text::XFormField> const& xFo
 
         if (m_pImpl->m_eFieldId == FIELD_FORMTEXT )
         {
-            xFormField->setFieldType(ODF_FORMTEXT);
             sTmp = m_pFFData->getName();
             try
             {
@@ -255,7 +268,6 @@ void FormControlHelper::processField(uno::Reference<text::XFormField> const& xFo
         }
         else if (m_pImpl->m_eFieldId == FIELD_FORMCHECKBOX )
         {
-            xFormField->setFieldType(ODF_FORMCHECKBOX);
             uno::Reference<beans::XPropertySet> xPropSet(xFormField, uno::UNO_QUERY);
             uno::Any aAny;
             aAny <<= m_pFFData->getCheckboxChecked();
@@ -264,7 +276,6 @@ void FormControlHelper::processField(uno::Reference<text::XFormField> const& xFo
         }
         else if (m_pImpl->m_eFieldId == FIELD_FORMDROPDOWN )
         {
-            xFormField->setFieldType(ODF_FORMDROPDOWN);
             const FFDataHandler::DropDownEntries_t& rEntries = m_pFFData->getDropDownEntries();
             if (!rEntries.empty())
             {
commit 356959529c4891093c435c40ddc93b57b625d40a
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Feb 20 12:45:44 2019 +0100
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:35 2019 +0200

    MSForms: Update cursor position after the drop down form field was changed
    
    Change-Id: I0e9e8a0e9212cdf539caa163f9071bc2f21e4c9f
    Reviewed-on: https://gerrit.libreoffice.org/68959
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit 499501e8cf1d511eb95a7b72b755c2dc69985719)
    Reviewed-on: https://gerrit.libreoffice.org/69193
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index a5c8e1acc4d2..c76be980179d 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -162,6 +162,10 @@ public:
         READONLY    = (1 << 3)      ///< make visible in spite of Readonly
     };
 
+    SAL_DLLPRIVATE void UpdateCursor(
+        sal_uInt16 eFlags = SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE,
+        bool bIdleEnd = false );
+
 private:
 
     SwRect  m_aCharRect;          ///< Char-SRectangle on which the cursor is located
@@ -232,10 +236,6 @@ private:
 
     SwFrame* m_oldColFrame;
 
-    SAL_DLLPRIVATE void UpdateCursor(
-        sal_uInt16 eFlags = SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE,
-        bool bIdleEnd = false );
-
     SAL_DLLPRIVATE void MoveCursorToNum();
 
     SAL_DLLPRIVATE void ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing );
diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx
index ae9db9357140..bef8fe50dfb1 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -1357,6 +1357,7 @@ void SwTextShell::Execute(SfxRequest &rReq)
             pDlg->Execute();
             pFieldBM->Invalidate();
             rWrtSh.InvalidateWindows( rWrtSh.GetView().GetVisArea() );
+            rWrtSh.UpdateCursor(); // cursor position might be invalid
         }
         else
         {
commit c6f4b7397e55d061daaa9cb024151f33a9ec755a
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Thu Feb 21 13:39:27 2019 +0100
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:34 2019 +0200

    MSForms: Disable legacy field menu slots if the cursor is inside a text field
    
    Insertion of fields inside fields is not an allowed operation.
    
    Change-Id: Icfdbc1add9c828227201b70cd545a83b6dcbc3e6
    Reviewed-on: https://gerrit.libreoffice.org/68957
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit c138047c75dcd0d6c572a58870edf2a7761ae35e)
    Reviewed-on: https://gerrit.libreoffice.org/69192
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx
index 55d19a48eee8..6b1915e095b3 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -924,6 +924,12 @@ void SwTextShell::StateField( SfxItemSet &rSet )
         case FN_INSERT_FLD_TITLE:
         case FN_INSERT_FLD_TOPIC:
         case FN_INSERT_DBFIELD:
+            if ( rSh.CursorInsideInputField() )
+            {
+                rSet.DisableItem(nWhich);
+            }
+            break;
+
         case FN_INSERT_TEXT_FORMFIELD:
         case FN_INSERT_CHECKBOX_FORMFIELD:
         case FN_INSERT_DROPDOWN_FORMFIELD:
@@ -931,6 +937,24 @@ void SwTextShell::StateField( SfxItemSet &rSet )
             {
                 rSet.DisableItem(nWhich);
             }
+            else
+            {
+                // Check whether we are in a text form field
+                SwPosition aCursorPos(*rSh.GetCursor()->GetPoint());
+                sw::mark::IFieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getFieldmarkFor(aCursorPos);
+                if ((!pFieldBM || pFieldBM->GetFieldname() != ODF_FORMTEXT)
+                    && aCursorPos.nContent.GetIndex() > 0)
+                {
+                    SwPosition aPos(aCursorPos);
+                    --aPos.nContent;
+                    pFieldBM = GetShell().getIDocumentMarkAccess()->getFieldmarkFor(aPos);
+                }
+                if (pFieldBM && pFieldBM->GetFieldname() == ODF_FORMTEXT &&
+                    (aCursorPos > pFieldBM->GetMarkStart() && aCursorPos < pFieldBM->GetMarkEnd() ))
+                {
+                    rSet.DisableItem(nWhich);
+                }
+            }
             break;
 
         }
commit a138e5a5910d782068cf9bb76dab48f873be18cf
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Thu Feb 21 13:40:14 2019 +0100
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:34 2019 +0200

    Fix typo
    
    Change-Id: I2b09bf30c3769f6b987409cabf24735647d3c31d
    Reviewed-on: https://gerrit.libreoffice.org/68958
    Reviewed-by: Julien Nabet <serval2412 at yahoo.fr>
    Tested-by: Jenkins
    (cherry picked from commit ba296f8e413f0cb1cd4095a342495b511df2aea4)
    Reviewed-on: https://gerrit.libreoffice.org/69191
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/source/ui/config/optcomp.cxx b/sw/source/ui/config/optcomp.cxx
index 524e8642276b..1a74d382a7ca 100644
--- a/sw/source/ui/config/optcomp.cxx
+++ b/sw/source/ui/config/optcomp.cxx
@@ -60,7 +60,7 @@ SwCompatibilityOptPage::SwCompatibilityOptPage(vcl::Window* pParent, const SfxIt
     get(m_pFormattingLB, "format");
     get(m_pGlobalOptionsLB, "globaloptions");
     get(m_pOptionsLB, "options");
-    get(m_pGlobalOptionsCLB, "globaloptioncheckboxs");
+    get(m_pGlobalOptionsCLB, "globaloptioncheckbox");
     get(m_pDefaultPB, "default");
 
     for ( int i = (static_cast<int>(SvtCompatibilityEntry::Index::Module) + 1); i < static_cast<int>(SvtCompatibilityEntry::Index::INVALID); ++i )
diff --git a/sw/uiconfig/swriter/ui/optcompatpage.ui b/sw/uiconfig/swriter/ui/optcompatpage.ui
index 8f4a5342c75d..3965324f43bb 100644
--- a/sw/uiconfig/swriter/ui/optcompatpage.ui
+++ b/sw/uiconfig/swriter/ui/optcompatpage.ui
@@ -140,7 +140,7 @@
                 <property name="can_focus">False</property>
                 <property name="row_spacing">5</property>
                 <child>
-                  <object class="svxcorelo-SvxCheckListBox" id="globaloptioncheckboxs:border">
+                  <object class="svxcorelo-SvxCheckListBox" id="globaloptioncheckbox:border">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="hexpand">True</property>
commit e87a61e4147140972716a653c8bfe10968031ef2
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Jun 19 16:07:23 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Wed Jun 19 22:21:34 2019 +0200

    MSForms: Implement undo / redo for insertion of legacy form fields
    
    Need to handle undo / redo explicitely for form fields, because
    there is no a general working undo / redo mechanism for fieldmarks.
    During the insertion of the fieldmark, text insertion also happens which
    generates an interfering undo action, so we need to disable undoing
    temporary.
    Also need to invalidta SID_UNDO slot to make the undo toolbar item updated
    after we insert a form field.
    
    Reviewed-on: https://gerrit.libreoffice.org/68956
    Tested-by: Jenkins
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    (cherry picked from commit 55d6be75732d1bb0067bba9496c74ef30be9a3ec)
    
    Change-Id: I358c2704cb30212a38f8a998888a36f72fa404e5

diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index 3fb7090e5067..823326e2b8ac 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -254,6 +254,8 @@ class IDocumentMarkAccess
         virtual ::sw::mark::IFieldmark* getDropDownFor(const SwPosition& pos) const=0;
         virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const=0;
 
+        virtual void deleteFieldmarkAt(const SwPosition& rPos) = 0;
+
         // Annotation Marks
         virtual const_iterator_t getAnnotationMarksBegin() const = 0;
         virtual const_iterator_t getAnnotationMarksEnd() const = 0;
diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index 1b3153dab176..da13d2fb16e6 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -539,6 +539,7 @@
 #define STR_UNDO_TBLSTYLE_DELETE                NC_("STR_UNDO_TBLSTYLE_DELETE", "Delete table style: $1")
 #define STR_UNDO_TBLSTYLE_UPDATE                NC_("STR_UNDO_TBLSTYLE_UPDATE", "Update table style: $1")
 #define STR_UNDO_TABLE_DELETE                   NC_("STR_UNDO_TABLE_DELETE", "Delete table")
+#define STR_UNDO_INSERT_FORM_FIELD              NC_("STR_UNDO_INSERT_FORM_FIELD", "Insert form field")
 
 #define STR_ACCESS_DOC_NAME                     NC_("STR_ACCESS_DOC_NAME", "Document view")
 #define STR_ACCESS_DOC_DESC                     NC_("STR_ACCESS_DOC_DESC", "Document view")
diff --git a/sw/inc/swundo.hxx b/sw/inc/swundo.hxx
index c393554f0614..90fa6c51d055 100644
--- a/sw/inc/swundo.hxx
+++ b/sw/inc/swundo.hxx
@@ -162,7 +162,9 @@ enum class SwUndoId
     UI_DELETE_PAGE_BREAK,              // 131
     UI_TEXT_CORRECTION,                // 132
     UI_TABLE_DELETE,                   // 133
-    CONFLICT                           // 134
+    CONFLICT,                          // 134
+
+    INSERT_FORM_FIELD                  // 135
 };
 
 OUString GetUndoComment(SwUndoId eId);
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index f48e3c626cc2..97b29bdb21c6 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -492,6 +492,10 @@ namespace sw { namespace mark
         const OUString& rName,
         const OUString& rType )
     {
+        // Disable undo, because we handle it using SwUndoInsTextFieldmark
+        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);
@@ -499,6 +503,12 @@ namespace sw { namespace mark
         if (pFieldMark)
             pFieldMark->SetFieldname( rType );
 
+        if (bUndoIsEnabled)
+        {
+            m_pDoc->GetIDocumentUndoRedo().DoUndo(bUndoIsEnabled);
+            m_pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsTextFieldmark>(*pFieldMark));
+        }
+
         return pFieldMark;
     }
 
@@ -507,6 +517,10 @@ namespace sw { namespace mark
         const OUString& rName,
         const OUString& rType)
     {
+        // Disable undo, because we handle it using SwUndoInsNoTextFieldmark
+        bool bUndoIsEnabled = m_pDoc->GetIDocumentUndoRedo().DoesUndo();
+        m_pDoc->GetIDocumentUndoRedo().DoUndo(false);
+
         bool bEnableSetModified = m_pDoc->getIDocumentState().IsEnableSetModified();
         m_pDoc->getIDocumentState().SetEnableSetModified(false);
 
@@ -517,6 +531,12 @@ namespace sw { namespace mark
         if (pFieldMark)
             pFieldMark->SetFieldname( rType );
 
+        if (bUndoIsEnabled)
+        {
+            m_pDoc->GetIDocumentUndoRedo().DoUndo(bUndoIsEnabled);
+            m_pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsNoTextFieldmark>(*pFieldMark));
+        }
+
         m_pDoc->getIDocumentState().SetEnableSetModified(bEnableSetModified);
         m_pDoc->getIDocumentState().SetModified();
 
@@ -1052,6 +1072,18 @@ namespace sw { namespace mark
         return dynamic_cast<IFieldmark*>(pFieldmark->get());
     }
 
+    void MarkManager::deleteFieldmarkAt(const SwPosition& rPos)
+    {
+        const_iterator_t pFieldmark = find_if(
+            m_vFieldmarks.begin(),
+            m_vFieldmarks.end(),
+            [&rPos] (pMark_t const& rpMark) { return rpMark->IsCoveringPosition(rPos); } );
+        if(pFieldmark == m_vFieldmarks.end()) return;
+
+        deleteMark(lcl_FindMark(m_vAllMarks, *pFieldmark));
+    }
+
+
     IFieldmark* MarkManager::getDropDownFor(const SwPosition& rPos) const
     {
         IFieldmark *pMark = getFieldmarkFor(rPos);
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
index a12657ef2469..7a3612bb6131 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -85,6 +85,8 @@ namespace sw {
             virtual ::sw::mark::IFieldmark* getDropDownFor(const SwPosition &rPos) const override;
             virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const override;
 
+            virtual void deleteFieldmarkAt(const SwPosition& rPos) override;
+
             void dumpAsXml(struct _xmlTextWriter* pWriter) const;
 
             // Annotation Marks
diff --git a/sw/source/core/inc/UndoBookmark.hxx b/sw/source/core/inc/UndoBookmark.hxx
index eb32662c92d8..7b9dd4fc68e5 100644
--- a/sw/source/core/inc/UndoBookmark.hxx
+++ b/sw/source/core/inc/UndoBookmark.hxx
@@ -24,10 +24,13 @@
 #include <undobj.hxx>
 
 class SwHistoryBookmark;
+class SwHistoryNoTextFieldmark;
+class SwHistoryTextFieldmark;
 
 namespace sw {
     namespace mark {
         class IMark;
+        class IFieldmark;
     }
 }
 
@@ -95,6 +98,30 @@ private:
     virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
 };
 
+class SwUndoInsNoTextFieldmark : public SwUndo
+{
+private:
+    const std::unique_ptr<SwHistoryNoTextFieldmark> m_pHistoryNoTextFieldmark;
+
+public:
+    SwUndoInsNoTextFieldmark(const ::sw::mark::IFieldmark& rFieldmark);
+
+    virtual void UndoImpl( ::sw::UndoRedoContext & ) override;
+    virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
+};
+
+class SwUndoInsTextFieldmark : public SwUndo
+{
+private:
+    const std::unique_ptr<SwHistoryTextFieldmark> m_pHistoryTextFieldmark;
+
+public:
+    SwUndoInsTextFieldmark(const ::sw::mark::IFieldmark& rFieldmark);
+
+    virtual void UndoImpl( ::sw::UndoRedoContext & ) override;
+    virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
+};
+
 #endif // INCLUDED_SW_SOURCE_CORE_INC_UNDOBOOKMARK_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/rolbck.hxx b/sw/source/core/inc/rolbck.hxx
index 945ed1948388..3fde226b7acf 100644
--- a/sw/source/core/inc/rolbck.hxx
+++ b/sw/source/core/inc/rolbck.hxx
@@ -72,6 +72,8 @@ enum HISTORY_HINT {
     HSTRY_CHGFLYANCHOR,
     HSTRY_CHGFLYCHAIN,
     HSTRY_CHGCHARFMT,
+    HSTRY_NOTEXTFIELDMARK,
+    HSTRY_TEXTFIELDMARK,
 };
 
 class SwHistoryHint
@@ -260,6 +262,33 @@ class SwHistoryBookmark : public SwHistoryHint
         std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndo;
 };
 
+class SwHistoryNoTextFieldmark : public SwHistoryHint
+{
+    public:
+        SwHistoryNoTextFieldmark(const ::sw::mark::IFieldmark& rFieldMark);
+        virtual void SetInDoc(SwDoc* pDoc, bool) override;
+        void ResetInDoc(SwDoc* pDoc);
+
+    private:
+        const OUString m_sType;
+        const sal_uLong m_nNode;
+        const sal_Int32 m_nContent;
+};
+
+class SwHistoryTextFieldmark : public SwHistoryHint
+{
+    public:
+        SwHistoryTextFieldmark(const ::sw::mark::IFieldmark& rFieldMark);
+        virtual void SetInDoc(SwDoc* pDoc, bool) override;
+        void ResetInDoc(SwDoc* pDoc);
+
+    private:
+        const OUString m_sName;
+        const OUString m_sType;
+        const sal_uLong m_nNode;
+        const sal_Int32 m_nContent;
+};
+
 class SwHistorySetAttrSet : public SwHistoryHint
 {
     SfxItemSet m_OldSet;
diff --git a/sw/source/core/undo/rolbck.cxx b/sw/source/core/undo/rolbck.cxx
index b8048539f459..495ce724032d 100644
--- a/sw/source/core/undo/rolbck.cxx
+++ b/sw/source/core/undo/rolbck.cxx
@@ -674,6 +674,96 @@ bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark& rBkmk)
         && m_aName == rBkmk.GetName();
 }
 
+SwHistoryNoTextFieldmark::SwHistoryNoTextFieldmark(const ::sw::mark::IFieldmark& rFieldMark)
+    : SwHistoryHint(HSTRY_NOTEXTFIELDMARK)
+    , m_sType(rFieldMark.GetFieldname())
+    , m_nNode(rFieldMark.GetMarkPos().nNode.GetIndex())
+    , m_nContent(rFieldMark.GetMarkPos().nContent.GetIndex())
+{
+}
+
+void SwHistoryNoTextFieldmark::SetInDoc(SwDoc* pDoc, bool)
+{
+    ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+    SwNodes& rNds = pDoc->GetNodes();
+    std::unique_ptr<SwPaM> pPam;
+
+    const SwContentNode* pContentNd = rNds[m_nNode]->GetContentNode();
+    if(pContentNd)
+        pPam.reset(new SwPaM(*pContentNd, m_nContent));
+
+    if (pPam)
+    {
+        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+        pMarkAccess->makeNoTextFieldBookmark(*pPam, OUString(), m_sType);
+    }
+}
+
+void SwHistoryNoTextFieldmark::ResetInDoc(SwDoc* pDoc)
+{
+    ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+    SwNodes& rNds = pDoc->GetNodes();
+    std::unique_ptr<SwPaM> pPam;
+
+    const SwContentNode* pContentNd = rNds[m_nNode]->GetContentNode();
+    if(pContentNd)
+        pPam.reset(new SwPaM(*pContentNd, m_nContent-1));
+
+    if (pPam)
+    {
+        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+        pMarkAccess->deleteFieldmarkAt(*pPam->GetPoint());
+    }
+}
+
+SwHistoryTextFieldmark::SwHistoryTextFieldmark(const ::sw::mark::IFieldmark& rFieldMark)
+    : SwHistoryHint(HSTRY_TEXTFIELDMARK)
+    , m_sName(rFieldMark.GetName())
+    , m_sType(rFieldMark.GetFieldname())
+    , m_nNode(rFieldMark.GetMarkPos().nNode.GetIndex())
+    , m_nContent(rFieldMark.GetMarkPos().nContent.GetIndex())
+{
+}
+
+void SwHistoryTextFieldmark::SetInDoc(SwDoc* pDoc, bool)
+{
+    ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+    SwNodes& rNds = pDoc->GetNodes();
+    std::unique_ptr<SwPaM> pPam;
+
+    const SwContentNode* pContentNd = rNds[m_nNode]->GetContentNode();
+    if(pContentNd)
+        pPam.reset(new SwPaM(*pContentNd, m_nContent));
+
+    if (pPam)
+    {
+        IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess();
+        SwPaM aFieldPam(pPam->GetPoint()->nNode, pPam->GetPoint()->nContent.GetIndex(),
+                        pPam->GetPoint()->nNode, pPam->GetPoint()->nContent.GetIndex() + 5);
+        pMarksAccess->makeFieldBookmark(aFieldPam, m_sName, m_sType);
+    }
+}
+
+void SwHistoryTextFieldmark::ResetInDoc(SwDoc* pDoc)
+{
+    ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+    SwNodes& rNds = pDoc->GetNodes();
+    std::unique_ptr<SwPaM> pPam;
+
+    const SwContentNode* pContentNd = rNds[m_nNode]->GetContentNode();
+    if(pContentNd)
+        pPam.reset(new SwPaM(*pContentNd, m_nContent));
+
+    if (pPam)
+    {
+        IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+        pMarkAccess->deleteFieldmarkAt(*pPam->GetPoint());
+    }
+}
 
 SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet& rSet,
                         sal_uLong nNodePos, const std::set<sal_uInt16> &rSetArr )
diff --git a/sw/source/core/undo/unbkmk.cxx b/sw/source/core/undo/unbkmk.cxx
index fc465aad21b2..c4d77b6e2f71 100644
--- a/sw/source/core/undo/unbkmk.cxx
+++ b/sw/source/core/undo/unbkmk.cxx
@@ -148,4 +148,36 @@ void SwUndoRenameBookmark::RedoImpl(::sw::UndoRedoContext & rContext)
     Rename(rContext, m_sOldName, m_sNewName);
 }
 
+SwUndoInsNoTextFieldmark::SwUndoInsNoTextFieldmark(const ::sw::mark::IFieldmark& rFieldmark)
+    : SwUndo(SwUndoId::INSERT, rFieldmark.GetMarkPos().GetDoc())
+    , m_pHistoryNoTextFieldmark(new SwHistoryNoTextFieldmark(rFieldmark))
+{
+}
+
+void SwUndoInsNoTextFieldmark::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+    m_pHistoryNoTextFieldmark->ResetInDoc(&rContext.GetDoc());
+}
+
+void SwUndoInsNoTextFieldmark::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+    m_pHistoryNoTextFieldmark->SetInDoc(&rContext.GetDoc(), false);
+}
+
+SwUndoInsTextFieldmark::SwUndoInsTextFieldmark(const ::sw::mark::IFieldmark& rFieldmark)
+    : SwUndo(SwUndoId::INSERT, rFieldmark.GetMarkPos().GetDoc())
+    , m_pHistoryTextFieldmark(new SwHistoryTextFieldmark(rFieldmark))
+{
+}
+
+void SwUndoInsTextFieldmark::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+    m_pHistoryTextFieldmark->ResetInDoc(&rContext.GetDoc());
+}
+
+void SwUndoInsTextFieldmark::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+    m_pHistoryTextFieldmark->SetInDoc(&rContext.GetDoc(), false);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
index 63a8bd949bcc..844a29be2073 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -642,6 +642,9 @@ OUString GetUndoComment(SwUndoId eId)
         case SwUndoId::PARA_SIGN_ADD:
             pId = STR_PARAGRAPH_SIGN_UNDO;
             break;
+        case SwUndoId::INSERT_FORM_FIELD:
+            pId = STR_UNDO_INSERT_FORM_FIELD;
+            break;
     };
 
     assert(pId);
diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx
index 095d89bc1182..55d19a48eee8 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -74,6 +74,7 @@
 #include <MarkManager.hxx>
 #include <xmloff/odffields.hxx>
 #include <IDocumentContentOperations.hxx>
+#include <IDocumentUndoRedo.hxx>
 
 using namespace nsSwDocInfoSubType;
 
@@ -722,6 +723,8 @@ FIELD_INSERT:
 
             case FN_INSERT_TEXT_FORMFIELD:
             {
+                rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+
                 SwPaM* pCursorPos = rSh.GetCursor();
                 if(pCursorPos)
                 {
@@ -736,26 +739,39 @@ FIELD_INSERT:

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list