tdf79435 doc/docx: round-trip legacy input formfields

GrabBag the settings which LO doesn't implement
(which is all of them) so that the document
round-trips without losing the config settings.

Change-Id: I00de6c483af68073634430dd74fd445e981573ab
Reviewed-on: https://gerrit.libreoffice.org/62241
Tested-by: Jenkins
Reviewed-by: Justin Luth <justin_luth@sil.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/sw/qa/extras/ooxmlexport/data/tdf79435_legacyInputFields.doc b/sw/qa/extras/ooxmlexport/data/tdf79435_legacyInputFields.doc
new file mode 100644
index 0000000..da7fade
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf79435_legacyInputFields.doc
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
index 8a98742..864d9717 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
@@ -30,6 +30,7 @@
#include <com/sun/star/text/WrapTextMode.hpp>
#include <com/sun/star/text/WritingMode2.hpp>
#include <com/sun/star/text/XBookmarksSupplier.hpp>
#include <com/sun/star/text/XFormField.hpp>
#include <com/sun/star/text/XFootnote.hpp>
#include <com/sun/star/text/XPageCursor.hpp>
#include <com/sun/star/text/XTextColumns.hpp>
@@ -723,6 +724,64 @@
    CPPUNIT_ASSERT_EQUAL(sal_uInt16(21), nIndex);
}

DECLARE_OOXMLEXPORT_TEST(testTdf79435_legacyInputFields, "tdf79435_legacyInputFields.doc")
{
    //using .doc input file to verify cross-format compatability.
    uno::Reference<text::XFormField> xFormField;
    xFormField
        = getProperty<uno::Reference<text::XFormField>>(getRun(getParagraph(5), 3), "Bookmark");
    uno::Reference<container::XNameContainer> xParameters(xFormField->getParameters());

    OUString sTmp;
    xParameters->getByName("EntryMacro") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("test"), sTmp);
    xParameters->getByName("Help") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("F1Help"), sTmp);
    xParameters->getByName("ExitMacro") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("test"), sTmp);
    xParameters->getByName("Hint") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("StatusHelp"), sTmp);
    xParameters->getByName("Content") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("Camelcase"), sTmp);
    xParameters->getByName("Format") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("TITLE CASE"), sTmp);

    sal_uInt16 nMaxLength = 0;
    xParameters->getByName("MaxLength") >>= nMaxLength;
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Max Length", sal_uInt16(10), nMaxLength);

    // too bad this is based on character runs - just found try trial and error.
    xFormField
        = getProperty<uno::Reference<text::XFormField>>(getRun(getParagraph(6), 2), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("calculated"), sTmp);

    xFormField
        = getProperty<uno::Reference<text::XFormField>>(getRun(getParagraph(7), 2), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("currentDate"), sTmp);

    xFormField
        = getProperty<uno::Reference<text::XFormField>>(getRun(getParagraph(7), 6), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("currentTime"), sTmp);

    xFormField
        = getProperty<uno::Reference<text::XFormField>>(getRun(getParagraph(8), 2), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("number"), sTmp);

    xFormField
        = getProperty<uno::Reference<text::XFormField>>(getRun(getParagraph(8), 6), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("date"), sTmp);
}

DECLARE_OOXMLEXPORT_TEST(testTdf120224_textControlCrossRef, "tdf120224_textControlCrossRef.docx")
{
    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
diff --git a/sw/qa/extras/ww8export/data/tdf79435_legacyInputFields.docx b/sw/qa/extras/ww8export/data/tdf79435_legacyInputFields.docx
new file mode 100644
index 0000000..55d1a1f
--- /dev/null
+++ b/sw/qa/extras/ww8export/data/tdf79435_legacyInputFields.docx
Binary files differ
diff --git a/sw/qa/extras/ww8export/ww8export.cxx b/sw/qa/extras/ww8export/ww8export.cxx
index cb73378..bac74e8 100644
--- a/sw/qa/extras/ww8export/ww8export.cxx
+++ b/sw/qa/extras/ww8export/ww8export.cxx
@@ -1116,7 +1116,7 @@
    uno::Reference<text::XFormField> xFormField = getProperty< uno::Reference<text::XFormField> >(getRun(getParagraph(1), 2), "Bookmark");
    uno::Reference<container::XNameContainer> xParameters = xFormField->getParameters();
    // This resulted in a container.NoSuchElementException.
    CPPUNIT_ASSERT_EQUAL(OUString("5"), xParameters->getByName("MaxLength").get<OUString>());
    CPPUNIT_ASSERT_EQUAL(sal_uInt16(5), xParameters->getByName("MaxLength").get<sal_uInt16>());
}


diff --git a/sw/qa/extras/ww8export/ww8export3.cxx b/sw/qa/extras/ww8export/ww8export3.cxx
index d5a888e..901450d 100644
--- a/sw/qa/extras/ww8export/ww8export3.cxx
+++ b/sw/qa/extras/ww8export/ww8export3.cxx
@@ -12,6 +12,7 @@
#include <IDocumentSettingAccess.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/text/XFormField.hpp>
#include <com/sun/star/text/XTextFramesSupplier.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/XTextTablesSupplier.hpp>
@@ -66,6 +67,58 @@
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Section4 is protected", false, getProperty<bool>(xSect, "IsProtected"));
}

DECLARE_WW8EXPORT_TEST(testTdf79435_legacyInputFields, "tdf79435_legacyInputFields.docx")
{
    //using .docx input file to verify cross-format compatability.
    uno::Reference<text::XFormField> xFormField;
    xFormField = getProperty< uno::Reference<text::XFormField> >(getRun(getParagraph(5), 3), "Bookmark");
    uno::Reference<container::XNameContainer> xParameters(xFormField->getParameters());

    OUString sTmp;
    xParameters->getByName("EntryMacro") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("test"), sTmp);
    xParameters->getByName("Help") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("F1Help"), sTmp);
    xParameters->getByName("ExitMacro") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("test"), sTmp);
    xParameters->getByName("Description") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("StatusHelp"), sTmp);
    xParameters->getByName("Content") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("Camelcase"), sTmp);
    xParameters->getByName("Format") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("TITLE CASE"), sTmp);

    sal_uInt16 nMaxLength = 0;
    xParameters->getByName("MaxLength") >>= nMaxLength;
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Max Length", sal_uInt16(10), nMaxLength);

    // too bad this is based on character runs - just found try trial and error.
    xFormField = getProperty< uno::Reference<text::XFormField> >(getRun(getParagraph(6), 2), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("calculated"), sTmp);

    xFormField = getProperty< uno::Reference<text::XFormField> >(getRun(getParagraph(7), 2), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("currentDate"), sTmp);

    xFormField = getProperty< uno::Reference<text::XFormField> >(getRun(getParagraph(7), 6), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("currentTime"), sTmp);

    xFormField = getProperty< uno::Reference<text::XFormField> >(getRun(getParagraph(8), 2), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("number"), sTmp);

    xFormField = getProperty< uno::Reference<text::XFormField> >(getRun(getParagraph(8), 6), "Bookmark");
    xParameters.set(xFormField->getParameters());
    xParameters->getByName("Type") >>= sTmp;
    CPPUNIT_ASSERT_EQUAL(OUString("date"), sTmp);
}

DECLARE_WW8EXPORT_TEST(testTdf120225_textControlCrossRef, "tdf120225_textControlCrossRef.doc")
{
    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index e2a5ebe..81c1b4f 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -178,7 +178,11 @@
class FFDataWriterHelper
{
    ::sax_fastparser::FSHelperPtr m_pSerializer;
    void writeCommonStart( const OUString& rName )
    void writeCommonStart( const OUString& rName,
                           const OUString& rEntryMacro,
                           const OUString& rExitMacro,
                           const OUString& rHelp,
                           const OUString& rHint )
    {
        m_pSerializer->startElementNS( XML_w, XML_ffData, FSEND );
        m_pSerializer->singleElementNS( XML_w, XML_name,
@@ -188,6 +192,33 @@
        m_pSerializer->singleElementNS( XML_w, XML_calcOnExit,
            FSNS( XML_w, XML_val ),
            "0", FSEND );

        if ( !rEntryMacro.isEmpty() )
            m_pSerializer->singleElementNS( XML_w, XML_entryMacro,
                FSNS(XML_w, XML_val),
                OUStringToOString( rEntryMacro, RTL_TEXTENCODING_UTF8 ).getStr(),
                FSEND );

        if ( !rExitMacro.isEmpty() )
            m_pSerializer->singleElementNS( XML_w, XML_exitMacro,
                FSNS(XML_w, XML_val),
                OUStringToOString( rExitMacro, RTL_TEXTENCODING_UTF8 ).getStr(),
                FSEND );

        if ( !rHelp.isEmpty() )
            m_pSerializer->singleElementNS( XML_w, XML_helpText,
                FSNS(XML_w, XML_type), OString("text"),
                FSNS(XML_w, XML_val),
                OUStringToOString( rHelp, RTL_TEXTENCODING_UTF8 ).getStr(),
                FSEND );

        if ( !rHint.isEmpty() )
            m_pSerializer->singleElementNS( XML_w, XML_statusText,
                FSNS(XML_w, XML_type), OString("text"),
                FSNS(XML_w, XML_val),
                OUStringToOString( rHint, RTL_TEXTENCODING_UTF8 ).getStr(),
                FSEND );

    }
    void writeFinish()
    {
@@ -195,9 +226,14 @@
    }
public:
    explicit FFDataWriterHelper( const ::sax_fastparser::FSHelperPtr& rSerializer ) : m_pSerializer( rSerializer ){}
    void WriteFormCheckbox( const OUString& rName, bool bChecked )
    void WriteFormCheckbox( const OUString& rName,
                            const OUString& rEntryMacro,
                            const OUString& rExitMacro,
                            const OUString& rHelp,
                            const OUString& rHint,
                            bool bChecked )
    {
       writeCommonStart( rName );
       writeCommonStart( rName, rEntryMacro, rExitMacro, rHelp, rHint );
       // Checkbox specific bits
       m_pSerializer->startElementNS( XML_w, XML_checkBox, FSEND );
       // currently hardcoding autosize
@@ -209,9 +245,39 @@
        m_pSerializer->endElementNS( XML_w, XML_checkBox );
       writeFinish();
    }
    void WriteFormText(  const OUString& rName )
    void WriteFormText(  const OUString& rName,
                         const OUString& rEntryMacro,
                         const OUString& rExitMacro,
                         const OUString& rHelp,
                         const OUString& rHint,
                         const OUString& rType,
                         const OUString& rDefaultText,
                         sal_uInt16 nMaxLength,
                         const OUString& rFormat )
    {
       writeCommonStart( rName );
        writeCommonStart( rName, rEntryMacro, rExitMacro, rHelp, rHint );

        m_pSerializer->startElementNS( XML_w, XML_textInput, FSEND );
        if ( !rType.isEmpty() )
            m_pSerializer->singleElementNS( XML_w, XML_type,
                FSNS(XML_w, XML_val),
                OUStringToOString( rType, RTL_TEXTENCODING_UTF8 ).getStr(),
                FSEND );
        if ( !rDefaultText.isEmpty() )
            m_pSerializer->singleElementNS( XML_w, XML_default,
                FSNS(XML_w, XML_val),
                OUStringToOString( rDefaultText, RTL_TEXTENCODING_UTF8 ).getStr(),
                FSEND );
        if ( nMaxLength )
            m_pSerializer->singleElementNS( XML_w, XML_maxLength,
                FSNS(XML_w, XML_val), OString::number(nMaxLength), FSEND );
        if ( !rFormat.isEmpty() )
            m_pSerializer->singleElementNS( XML_w, XML_format,
                FSNS(XML_w, XML_val),
                OUStringToOString( rFormat, RTL_TEXTENCODING_UTF8 ).getStr(),
                FSEND );
        m_pSerializer->endElementNS( XML_w, XML_textInput );

       writeFinish();
    }
};
@@ -1641,12 +1707,24 @@
void DocxAttributeOutput::WriteFFData(  const FieldInfos& rInfos )
{
    const ::sw::mark::IFieldmark& rFieldmark = *rInfos.pFieldmark;
    FieldMarkParamsHelper params( rFieldmark );

    OUString sEntryMacro;
    params.extractParam("EntryMacro", sEntryMacro);
    OUString sExitMacro;
    params.extractParam("ExitMacro", sExitMacro);
    OUString sHelp;
    params.extractParam("Help", sHelp);
    OUString sHint;
    params.extractParam("Hint", sHint); // .docx StatusText
    if ( sHint.isEmpty() )
        params.extractParam("Description", sHint); // .doc StatusText

    if ( rInfos.eType == ww::eFORMDROPDOWN )
    {
        uno::Sequence< OUString> vListEntries;
        OUString sName, sSelected;

        FieldMarkParamsHelper params( rFieldmark );
        params.extractParam( ODF_FORMDROPDOWN_LISTENTRY, vListEntries );
        sName = params.getName();
        sal_Int32 nSelectedIndex = 0;
@@ -1664,7 +1742,6 @@
        OUString sName;
        bool bChecked = false;

        FieldMarkParamsHelper params( rFieldmark );
        params.extractParam( ODF_FORMCHECKBOX_NAME, sName );

        const sw::mark::ICheckboxFieldmark* pCheckboxFm = dynamic_cast<const sw::mark::ICheckboxFieldmark*>(&rFieldmark);
@@ -1672,13 +1749,21 @@
            bChecked = true;

        FFDataWriterHelper ffdataOut( m_pSerializer );
        ffdataOut.WriteFormCheckbox( sName, bChecked );
        ffdataOut.WriteFormCheckbox( sName, sEntryMacro, sExitMacro, sHelp, sHint, bChecked );
    }
    else if ( rInfos.eType == ww::eFORMTEXT )
    {
        FieldMarkParamsHelper params( rFieldmark );
        OUString sType;
        params.extractParam("Type", sType);
        OUString sDefaultText;
        params.extractParam("Content", sDefaultText);
        sal_uInt16 nMaxLength = 0;
        params.extractParam("MaxLength", nMaxLength);
        OUString sFormat;
        params.extractParam("Format", sFormat);
        FFDataWriterHelper ffdataOut( m_pSerializer );
        ffdataOut.WriteFormText( params.getName() );
        ffdataOut.WriteFormText( params.getName(), sEntryMacro, sExitMacro, sHelp, sHint,
                                 sType, sDefaultText, nMaxLength, sFormat );
    }
}

diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index f0ab7e1..1895ae5 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -3831,10 +3831,16 @@
    if ( rFieldmark.GetFieldname() == ODF_FORMDROPDOWN )
        type=2;

    ::sw::mark::IFieldmark::parameter_map_t::const_iterator pNameParameter = rFieldmark.GetParameters()->find("name");
    ::sw::mark::IFieldmark::parameter_map_t::const_iterator pParameter = rFieldmark.GetParameters()->find("name");
    OUString ffname;
    if(pNameParameter != rFieldmark.GetParameters()->end())
        pNameParameter->second >>= ffname;
    if ( pParameter != rFieldmark.GetParameters()->end() )
    {
        OUString aName;
        pParameter->second >>= aName;
        assert( aName.getLength() < 21 && "jluth seeing if following documentation will cause problems." );
        const sal_Int32 nLen = std::min( sal_Int32(20), aName.getLength() );
        ffname = aName.copy(0, nLen);
    }

    sal_uLong nDataStt = pDataStrm->Tell();
    m_pChpPlc->AppendFkpEntry(Strm().Tell());
@@ -3877,15 +3883,107 @@
            ffres = 0;
    }
    aFieldHeader.bits |= ( (ffres<<2) & 0x7C );

    OUString ffdeftext;
    OUString ffformat;
    OUString ffhelptext = rFieldmark.GetFieldHelptext();
    if ( ffhelptext.getLength() > 255 )
        ffhelptext = ffhelptext.copy(0, 255);
    OUString ffstattext;
    OUString ffentrymcr;
    OUString ffexitmcr;
    if (type == 0) // iTypeText
    {
        sw::mark::IFieldmark::parameter_map_t::const_iterator pParameter = rFieldmark.GetParameters()->find("MaxLength");
        if (pParameter != rFieldmark.GetParameters()->end())
        sal_uInt16 nType = 0;
        pParameter = rFieldmark.GetParameters()->find("Type");
        if ( pParameter != rFieldmark.GetParameters()->end() )
        {
            OUString aLength;
            pParameter->second >>= aLength;
            aFieldHeader.cch = aLength.toUInt32();
            OUString aType;
            pParameter->second >>= aType;
            if ( aType == "number" )            nType = 1;
            else if ( aType == "date" )         nType = 2;
            else if ( aType == "currentTime" )  nType = 3;
            else if ( aType == "currentDate" )  nType = 4;
            else if ( aType == "calculated" )   nType = 5;
            aFieldHeader.bits |= nType<<11; // FFDataBits-F  00111000 00000000
        }

        if ( nType < 3 || nType == 5 )  // not currentTime or currentDate
        {
            pParameter = rFieldmark.GetParameters()->find("Content");
            if ( pParameter != rFieldmark.GetParameters()->end() )
            {
                OUString aDefaultText;
                pParameter->second >>= aDefaultText;
                assert( aDefaultText.getLength() < 256 && "jluth seeing if following documentation will cause problems." );
                const sal_Int32 nLen = std::min( sal_Int32(255), aDefaultText.getLength() );
                ffdeftext = aDefaultText.copy (0, nLen);
            }
        }

        pParameter = rFieldmark.GetParameters()->find("MaxLength");
        if ( pParameter != rFieldmark.GetParameters()->end() )
        {
            sal_uInt16 nLength = 0;
            pParameter->second >>= nLength;
            assert( nLength < 32768 && "jluth seeing if following documentation will cause problems." );
            nLength = std::min( sal_uInt16(32767), nLength );
            aFieldHeader.cch = nLength;
        }

        pParameter = rFieldmark.GetParameters()->find("Format");
        if ( pParameter != rFieldmark.GetParameters()->end() )
        {
            OUString aFormat;
            pParameter->second >>= aFormat;
            const sal_Int32 nLen = std::min( sal_Int32(64), aFormat.getLength() );
            assert( nLen < 65 && "jluth seeing if following documentation will cause problems." );
            ffformat = aFormat.copy(0, nLen);
        }
    }

    pParameter = rFieldmark.GetParameters()->find("Help"); //help
    if ( ffhelptext.isEmpty() && pParameter != rFieldmark.GetParameters()->end() )
    {
        OUString aHelpText;
        pParameter->second >>= aHelpText;
        const sal_Int32 nLen = std::min( sal_Int32(255), aHelpText.getLength() );
        ffhelptext = aHelpText.copy (0, nLen);
    }
    if ( !ffhelptext.isEmpty() )
        aFieldHeader.bits |= 0x1<<7;

    pParameter = rFieldmark.GetParameters()->find("Description"); // doc tooltip
    if ( pParameter == rFieldmark.GetParameters()->end() )
        pParameter = rFieldmark.GetParameters()->find("Hint"); //docx tooltip
    if ( pParameter != rFieldmark.GetParameters()->end() )
    {
        OUString aStatusText;
        pParameter->second >>= aStatusText;
        const sal_Int32 nLen = std::min( sal_Int32(138), aStatusText.getLength() );
        ffstattext = aStatusText.copy (0, nLen);
    }
    if ( !ffstattext.isEmpty() )
        aFieldHeader.bits |= 0x1<<8;

    pParameter = rFieldmark.GetParameters()->find("EntryMacro");
    if ( pParameter != rFieldmark.GetParameters()->end() )
    {
        OUString aEntryMacro;
        pParameter->second >>= aEntryMacro;
        assert( aEntryMacro.getLength() < 33 && "jluth seeing if following documentation will cause problems." );
        const sal_Int32 nLen = std::min( sal_Int32(32), aEntryMacro.getLength() );
        ffentrymcr = aEntryMacro.copy (0, nLen);
    }

    pParameter = rFieldmark.GetParameters()->find("ExitMacro");
    if ( pParameter != rFieldmark.GetParameters()->end() )
    {
        OUString aExitMacro;
        pParameter->second >>= aExitMacro;
        assert( aExitMacro.getLength() < 33 && "jluth seeing if following documentation will cause problems." );
        const sal_Int32 nLen = std::min( sal_Int32(32), aExitMacro.getLength() );
        ffexitmcr = aExitMacro.copy (0, nLen);
    }

    std::vector< OUString > aListItems;
@@ -3902,13 +4000,6 @@
        }
    }

    const OUString ffdeftext;
    const OUString ffformat;
    const OUString ffhelptext;
    const OUString ffstattext;
    const OUString ffentrymcr;
    const OUString ffexitmcr;

    const sal_uInt8 aFieldData[] =
    {
        0x44,0,         // the start of "next" data
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index 5cffd97..fc8ab8c 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -652,17 +652,16 @@
public:
    WW8FormulaControl(const OUString& rN, SwWW8ImplReader &rRdr)
        : mrRdr(rRdr), mfUnknown(0), mfDropdownIndex(0),
        mfToolTip(0), mfNoMark(0), mfUseSize(0), mfNumbersOnly(0), mfDateOnly(0),
        mfUnused(0), mhpsCheckBox(20), mnChecked(0), mnMaxLen(0), msName( rN )
        mfToolTip(0), mfNoMark(0), mfType(0),
        mfUnused(0), mhpsCheckBox(20), mnChecked(0), mnMaxLen(0),
        mbHelp(false), msName( rN )
    {
    }
    sal_uInt8 mfUnknown:2;
    sal_uInt8 mfDropdownIndex:6;
    sal_uInt8 mfToolTip:1;
    sal_uInt8 mfNoMark:1;
    sal_uInt8 mfUseSize:1;
    sal_uInt8 mfNumbersOnly:1;
    sal_uInt8 mfDateOnly:1;
    sal_uInt8 mfType:3;
    sal_uInt8 mfUnused:3;

    sal_uInt16 mhpsCheckBox;
@@ -673,8 +672,11 @@
    OUString msTitle;
    OUString msDefault;
    OUString msFormatting;
    bool mbHelp;
    OUString msHelp;
    OUString msToolTip;
    OUString msEntryMcr;
    OUString msExitMcr;
    std::vector<OUString> maListEntries;
    virtual ~WW8FormulaControl() {}
    void FormulaRead(SwWw8ControlType nWhich,SvStream *pD);
diff --git a/sw/source/filter/ww8/ww8par3.cxx b/sw/source/filter/ww8/ww8par3.cxx
index 53d5016..0aec993 100644
--- a/sw/source/filter/ww8/ww8par3.cxx
+++ b/sw/source/filter/ww8/ww8par3.cxx
@@ -159,9 +159,31 @@
            m_aFieldStack.back().SetBookmarkName(aBookmarkName);
            m_aFieldStack.back().SetBookmarkType(ODF_FORMTEXT);
            m_aFieldStack.back().getParameters()["Description"] <<= aFormula.msToolTip;
            if ( aFormula.mbHelp && !aFormula.msHelp.isEmpty() )
                m_aFieldStack.back().getParameters()["Help"] <<= aFormula.msHelp;
            m_aFieldStack.back().getParameters()["Name"] <<= aFormula.msTitle;
            if (aFormula.mnMaxLen)
                m_aFieldStack.back().getParameters()["MaxLength"] <<= OUString::number(aFormula.mnMaxLen);
                m_aFieldStack.back().getParameters()["MaxLength"] <<= aFormula.mnMaxLen;

            if ( aFormula.mfType == 1 )
                m_aFieldStack.back().getParameters()["Type"] <<= OUString("number");
            else if ( aFormula.mfType == 2 )
                m_aFieldStack.back().getParameters()["Type"] <<= OUString("date");
            else if ( aFormula.mfType == 3 )
                m_aFieldStack.back().getParameters()["Type"] <<= OUString("currentTime");
            else if ( aFormula.mfType == 4 )
                m_aFieldStack.back().getParameters()["Type"] <<= OUString("currentDate");
            else if ( aFormula.mfType == 5 )
                m_aFieldStack.back().getParameters()["Type"] <<= OUString("calculated");

            if ( !aFormula.msDefault.isEmpty() )
                m_aFieldStack.back().getParameters()["Content"] <<= aFormula.msDefault;
            if ( !aFormula.msFormatting.isEmpty() )
                m_aFieldStack.back().getParameters()["Format"] <<= aFormula.msFormatting;
            if ( !aFormula.msEntryMcr.isEmpty() )
                m_aFieldStack.back().getParameters()["EntryMacro"] <<= aFormula.msEntryMcr;
            if ( !aFormula.msExitMcr.isEmpty() )
                m_aFieldStack.back().getParameters()["ExitMacro"] <<= aFormula.msExitMcr;
        }
        return eF_ResT::TEXT;
    }
@@ -2186,8 +2208,10 @@
    // xstzStatText
    msToolTip = read_uInt16_BeltAndBracesString(*pDataStream);

    /*String sEntryMacro =*/ read_uInt16_BeltAndBracesString(*pDataStream);
    /*String sExitMcr =*/ read_uInt16_BeltAndBracesString(*pDataStream);
    // xstzEntryMcr
    msEntryMcr = read_uInt16_BeltAndBracesString(*pDataStream);
    //xstzExitMcr
    msExitMcr = read_uInt16_BeltAndBracesString(*pDataStream);

    if (nWhich == WW8_CT_DROPDOWN)
    {
@@ -2227,12 +2251,12 @@
    }
    mfDropdownIndex = iRes;

    mbHelp = bits1 & 0x80;

    nField = bits2;
    mfToolTip = nField & 0x01;
    mfNoMark = (nField & 0x02)>>1;
    mfUseSize = (nField & 0x04)>>2;
    mfNumbersOnly= (nField & 0x08)>>3;
    mfDateOnly = (nField & 0x10)>>4;
    mfType = (nField & 0x38)>>3;
    mfUnused = (nField & 0xE0)>>5;
}

diff --git a/writerfilter/source/dmapper/FFDataHandler.cxx b/writerfilter/source/dmapper/FFDataHandler.cxx
index ebd4e2f..2429a77 100644
--- a/writerfilter/source/dmapper/FFDataHandler.cxx
+++ b/writerfilter/source/dmapper/FFDataHandler.cxx
@@ -32,7 +32,8 @@
m_nCheckboxHeight(0),
m_bCheckboxAutoHeight(false),
m_nCheckboxChecked(-1),
m_nCheckboxDefault(-1)
m_nCheckboxDefault(-1),
m_nTextMaxLength(0)
{
}

@@ -72,6 +73,16 @@
            resolveSprm(r_Sprm);
        }
        break;
    case NS_ooxml::LN_CT_FFData_entryMacro:
        {
            m_sEntryMacro = r_Sprm.getValue()->getString();
        }
        break;
    case NS_ooxml::LN_CT_FFData_exitMacro:
        {
            m_sExitMacro = r_Sprm.getValue()->getString();
        }
        break;
    case NS_ooxml::LN_CT_FFCheckBox_size:
        {
            m_nCheckboxHeight = r_Sprm.getValue()->getInt();
@@ -112,11 +123,26 @@
            resolveSprm(r_Sprm);
        }
        break;
    case NS_ooxml::LN_CT_FFTextInput_type:
        {
            m_sTextType = r_Sprm.getValue()->getString();
        }
        break;
    case NS_ooxml::LN_CT_FFTextInput_default:
        {
            m_sTextDefault = r_Sprm.getValue()->getString();
        }
        break;
    case NS_ooxml::LN_CT_FFTextInput_maxLength:
        {
            m_nTextMaxLength = r_Sprm.getValue()->getInt();
        }
        break;
    case NS_ooxml::LN_CT_FFTextInput_format:
        {
            m_sTextFormat = r_Sprm.getValue()->getString();
        }
        break;
    case NS_ooxml::LN_CT_FFData_textInput:
        {
            resolveSprm(r_Sprm);
diff --git a/writerfilter/source/dmapper/FFDataHandler.hxx b/writerfilter/source/dmapper/FFDataHandler.hxx
index 7289d6f..84ac070e 100644
--- a/writerfilter/source/dmapper/FFDataHandler.hxx
+++ b/writerfilter/source/dmapper/FFDataHandler.hxx
@@ -44,6 +44,9 @@
    // member: statusText
    const OUString & getStatusText() const { return m_sStatusText;}

    const OUString & getEntryMacro() const { return m_sEntryMacro;}
    const OUString & getExitMacro() const { return m_sExitMacro;}

    // member: checkboxHeight
    sal_uInt32 getCheckboxHeight() const { return m_nCheckboxHeight;}

@@ -62,6 +65,10 @@
    // member: textDefault
    const OUString & getTextDefault() const { return m_sTextDefault;}

    const OUString & getTextType() const { return m_sTextType; }
    const OUString & getTextFormat() const { return m_sTextFormat; }
    sal_uInt16 getTextMaxLength() const { return m_nTextMaxLength; }

    // sprm
    void resolveSprm(Sprm & r_sprm);

@@ -69,6 +76,8 @@
    OUString m_sName;
    OUString m_sHelpText;
    OUString m_sStatusText;
    OUString m_sEntryMacro;
    OUString m_sExitMacro;
    sal_uInt32 m_nCheckboxHeight;
    bool m_bCheckboxAutoHeight;
    int m_nCheckboxChecked;
@@ -76,6 +85,9 @@
    OUString m_sDropDownResult;
    DropDownEntries_t m_DropDownEntries;
    OUString m_sTextDefault;
    OUString m_sTextType;
    OUString m_sTextFormat;
    sal_uInt16 m_nTextMaxLength;

    // sprm
    void lcl_sprm(Sprm & r_sprm) override;
diff --git a/writerfilter/source/dmapper/FormControlHelper.cxx b/writerfilter/source/dmapper/FormControlHelper.cxx
index 3877763..3088a4a 100644
--- a/writerfilter/source/dmapper/FormControlHelper.cxx
+++ b/writerfilter/source/dmapper/FormControlHelper.cxx
@@ -37,6 +37,7 @@
#include "FormControlHelper.hxx"
#include <xmloff/odffields.hxx>
#include <comphelper/sequence.hxx>
#include <tools/diagnose_ex.h>

namespace writerfilter {
namespace dmapper {
@@ -205,14 +206,52 @@
    uno::Reference<container::XNamed> xNamed( xFormField, uno::UNO_QUERY );
    if ( m_pFFData && xNamed.is() && xNameCont.is() )
    {
        OUString sTmp = m_pFFData->getEntryMacro();
        if ( !sTmp.isEmpty() )
            xNameCont->insertByName( "EntryMacro", uno::makeAny(sTmp) );
        sTmp = m_pFFData->getExitMacro();
        if ( !sTmp.isEmpty() )
            xNameCont->insertByName( "ExitMacro", uno::makeAny(sTmp) );

        sTmp = m_pFFData->getHelpText();
        if ( !sTmp.isEmpty() )
            xNameCont->insertByName( "Help", uno::makeAny(sTmp) );

        sTmp = m_pFFData->getStatusText();
        if ( !sTmp.isEmpty() )
            xNameCont->insertByName( "Hint", uno::makeAny(sTmp) );

        if (m_pImpl->m_eFieldId == FIELD_FORMTEXT )
        {
            xFormField->setFieldType(ODF_FORMTEXT);
            if (  !m_pFFData->getName().isEmpty() )
            sTmp = m_pFFData->getName();
            try
            {
                xNamed->setName( m_pFFData->getName() );
                if ( !sTmp.isEmpty() )
                    xNamed->setName( sTmp );
            }
            catch ( uno::Exception& )
            {
                DBG_UNHANDLED_EXCEPTION("writerfilter","Set Formfield name failed");
            }

            sTmp = m_pFFData->getTextType();
            if ( !sTmp.isEmpty() )
                xNameCont->insertByName( "Type", uno::makeAny(sTmp) );

            const sal_uInt16 nMaxLength = m_pFFData->getTextMaxLength();
            if ( nMaxLength )
            {
                xNameCont->insertByName( "MaxLength", uno::makeAny(nMaxLength) );
            }

            sTmp = m_pFFData->getTextDefault();
            if ( !sTmp.isEmpty() )
                xNameCont->insertByName( "Content", uno::makeAny(sTmp) );

            sTmp = m_pFFData->getTextFormat();
            if ( !sTmp.isEmpty() )
                xNameCont->insertByName( "Format", uno::makeAny(sTmp) );
        }
        else if (m_pImpl->m_eFieldId == FIELD_FORMCHECKBOX )
        {