Makefile.in                                            |    2 
 sw/qa/extras/ooxmlexport/data/test_sdt_datepicker.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx          |   25 ++++++
 sw/source/filter/ww8/docxattributeoutput.cxx           |   62 ++++++++++-------
 sw/source/filter/ww8/docxattributeoutput.hxx           |    3 
 writerfilter/source/dmapper/DomainMapper.cxx           |    9 +-
 writerfilter/source/dmapper/SdtHelper.cxx              |    3 
 writerfilter/source/dmapper/SdtHelper.hxx              |   15 ++++
 8 files changed, 89 insertions(+), 30 deletions(-)

New commits:
commit c3e1c1c5509f6ca9abe786bcc2dabf542a7f0ec1
Author:     Caolán McNamara <[email protected]>
AuthorDate: Thu Dec 2 20:15:23 2021 +0000
Commit:     Caolán McNamara <[email protected]>
CommitDate: Thu Dec 2 21:16:10 2021 +0100

    ofz: Executable_lockfile needs Executable_concat-deps
    
    Change-Id: I4cb2b1aa2b923884f4a2af23d69ff71c66ecef81
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126262
    Tested-by: Caolán McNamara <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/Makefile.in b/Makefile.in
index 6202a5cd5d9f..2d94186644ea 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -491,7 +491,7 @@ $(foreach ide,\
         eclipsecdt,\
 $(eval $(call gb_Top_GbuildToIdeIntegration,$(ide))))
 
-fuzzers: Executable_lockfile StaticLibrary_dtoa StaticLibrary_zlib 
StaticLibrary_libjpeg-turbo Library_sal Library_salhelper Library_reg 
Library_store Library_unoidl codemaker Library_cppu Library_i18nlangtag 
Library_cppuhelper Library_comphelper StaticLibrary_ulingu 
StaticLibrary_findsofficepath Library_tl Library_basegfx Library_canvastools 
Library_cppcanvas Library_dbtools Library_deploymentmisc Library_editeng 
Library_i18nutil Library_localebe1 Library_sax Library_sofficeapp 
Library_ucbhelper Rdb_services udkapi offapi Library_icg Library_reflection 
Library_invocadapt Library_bootstrap Library_introspection Library_stocservices 
Library_xmlreader Library_gcc3_uno instsetoo_native StaticLibrary_boost_locale 
StaticLibrary_fuzzerstubs StaticLibrary_fuzzer_core StaticLibrary_fuzzer_calc 
StaticLibrary_fuzzer_draw StaticLibrary_fuzzer_writer StaticLibrary_fuzzer_math 
Library_forui Library_binaryurp Library_io Library_invocation 
Library_namingservice Library_proxyfac Library_uuresolver 
 Module_ure Library_wpftwriter Library_sb Library_file Executable_pptfuzzer 
Executable_cgmfuzzer Executable_ww2fuzzer Executable_ww6fuzzer 
Executable_ww8fuzzer Executable_qpwfuzzer Executable_slkfuzzer 
Executable_fodtfuzzer Executable_fodsfuzzer Executable_fodpfuzzer 
Executable_xlsfuzzer Executable_scrtffuzzer Executable_wksfuzzer 
Executable_diffuzzer Executable_docxfuzzer Executable_xlsxfuzzer 
Executable_pptxfuzzer Executable_htmlfuzzer Executable_rtffuzzer 
Executable_mmlfuzzer Executable_mtpfuzzer Executable_olefuzzer 
Executable_lwpfuzzer Executable_hwpfuzzer Executable_wmffuzzer 
Executable_dxffuzzer Executable_sftfuzzer Executable_svmfuzzer 
Executable_tiffuzzer Executable_epsfuzzer Executable_jpgfuzzer 
Executable_metfuzzer Executable_bmpfuzzer Executable_giffuzzer 
Executable_pngfuzzer Executable_602fuzzer Executable_tgafuzzer 
Executable_pcxfuzzer Executable_psdfuzzer Executable_ppmfuzzer 
Executable_pcdfuzzer Executable_rasfuzzer Executable_pctfuzzer 
Executable_xpmfuzzer Executable
 _xbmfuzzer Executable_dbffuzzer
+fuzzers: Executable_concat-deps Executable_lockfile StaticLibrary_dtoa 
StaticLibrary_zlib StaticLibrary_libjpeg-turbo Library_sal Library_salhelper 
Library_reg Library_store Library_unoidl codemaker Library_cppu 
Library_i18nlangtag Library_cppuhelper Library_comphelper StaticLibrary_ulingu 
StaticLibrary_findsofficepath Library_tl Library_basegfx Library_canvastools 
Library_cppcanvas Library_dbtools Library_deploymentmisc Library_editeng 
Library_i18nutil Library_localebe1 Library_sax Library_sofficeapp 
Library_ucbhelper Rdb_services udkapi offapi Library_icg Library_reflection 
Library_invocadapt Library_bootstrap Library_introspection Library_stocservices 
Library_xmlreader Library_gcc3_uno instsetoo_native StaticLibrary_boost_locale 
StaticLibrary_fuzzerstubs StaticLibrary_fuzzer_core StaticLibrary_fuzzer_calc 
StaticLibrary_fuzzer_draw StaticLibrary_fuzzer_writer StaticLibrary_fuzzer_math 
Library_forui Library_binaryurp Library_io Library_invocation 
Library_namingservice Library_proxy
 fac Library_uuresolver Module_ure Library_wpftwriter Library_sb Library_file 
Executable_pptfuzzer Executable_cgmfuzzer Executable_ww2fuzzer 
Executable_ww6fuzzer Executable_ww8fuzzer Executable_qpwfuzzer 
Executable_slkfuzzer Executable_fodtfuzzer Executable_fodsfuzzer 
Executable_fodpfuzzer Executable_xlsfuzzer Executable_scrtffuzzer 
Executable_wksfuzzer Executable_diffuzzer Executable_docxfuzzer 
Executable_xlsxfuzzer Executable_pptxfuzzer Executable_htmlfuzzer 
Executable_rtffuzzer Executable_mmlfuzzer Executable_mtpfuzzer 
Executable_olefuzzer Executable_lwpfuzzer Executable_hwpfuzzer 
Executable_wmffuzzer Executable_dxffuzzer Executable_sftfuzzer 
Executable_svmfuzzer Executable_tiffuzzer Executable_epsfuzzer 
Executable_jpgfuzzer Executable_metfuzzer Executable_bmpfuzzer 
Executable_giffuzzer Executable_pngfuzzer Executable_602fuzzer 
Executable_tgafuzzer Executable_pcxfuzzer Executable_psdfuzzer 
Executable_ppmfuzzer Executable_pcdfuzzer Executable_rasfuzzer 
Executable_pctfuzzer Executab
 le_xpmfuzzer Executable_xbmfuzzer Executable_dbffuzzer
 
 endif # MAKE_RESTARTS
 
commit 41a9ff8d9ef6e0dbb4a71b0f923079eb8ffd1851
Author:     Vasily Melenchuk <[email protected]>
AuthorDate: Thu Nov 18 20:06:08 2021 +0300
Commit:     Vasily Melenchuk <[email protected]>
CommitDate: Thu Dec 2 21:16:01 2021 +0100

    sw: support for other sdt attributes roundtrip in datepicker
    
    Word Control Field with datepicker is implemented with LO datepicker,
    but during this conversion we lose some field data, like control
    color, data mapping, etc. This data is already retrieved and stored
    in grab bag, so we need just to keep this grabbag in field and use
    it again on export.
    
    Change-Id: I6af8204fe1a7d2f9081d83372a6786b2f86260d8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125486
    Tested-by: Jenkins
    Reviewed-by: Vasily Melenchuk <[email protected]>

diff --git a/sw/qa/extras/ooxmlexport/data/test_sdt_datepicker.docx 
b/sw/qa/extras/ooxmlexport/data/test_sdt_datepicker.docx
new file mode 100644
index 000000000000..3ff04cb60b89
Binary files /dev/null and 
b/sw/qa/extras/ooxmlexport/data/test_sdt_datepicker.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
index 5c0e0685ecec..610820c40f33 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
@@ -770,6 +770,31 @@ DECLARE_OOXMLEXPORT_TEST(testTdf142464_ampm, 
"tdf142464_ampm.docx")
     }
 }
 
+DECLARE_OOXMLEXPORT_TEST( testSdtDatePicker, "test_sdt_datepicker.docx" )
+{
+    // Check that roundtrip for date picker field does not lose essential data
+    xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
+    if (!pXmlDoc)
+       return; // initial import, no futher checks
+
+    // Placeholder is here
+    OUString sDocPart = getXPath(pXmlDoc, 
"/w:document/w:body/w:p/w:sdt/w:sdtPr/w:placeholder/w:docPart", "val");
+    CPPUNIT_ASSERT_EQUAL(OUString("DefaultPlaceholder_-1854013437"), sDocPart);
+
+    // Ensure that we have data binding stuff
+    OUString sDBprefix = getXPath(pXmlDoc, 
"/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dataBinding", "prefixMappings");
+    
CPPUNIT_ASSERT_EQUAL(OUString("xmlns:ns0='http://schemas.microsoft.com/vsto/samples'
 "), sDBprefix);
+
+    OUString sDBxpath = getXPath(pXmlDoc, 
"/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dataBinding", "xpath");
+    
CPPUNIT_ASSERT_EQUAL(OUString("/ns0:employees[1]/ns0:employee[1]/ns0:hireDate[1]"),
 sDBxpath);
+
+    OUString sDBstoreid = getXPath(pXmlDoc, 
"/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dataBinding", "storeItemID");
+    CPPUNIT_ASSERT_EQUAL(OUString("{241A8A02-7FFD-488D-8827-63FBE74E8BC9}"), 
sDBstoreid);
+
+    OUString sColor = getXPath(pXmlDoc, 
"/w:document/w:body/w:p/w:sdt/w:sdtPr/w15:color", "val");
+    CPPUNIT_ASSERT_EQUAL(OUString("008000"), sColor);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index 71fa753bd44c..51a8ac155cad 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -663,12 +663,36 @@ void 
SdtBlockHelper::WriteSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer, b
         }
     }
 
+    WriteExtraParams(pSerializer);
+
+    pSerializer->endElementNS(XML_w, XML_sdtPr);
+
+    // sdt contents start tag
+    pSerializer->startElementNS(XML_w, XML_sdtContent);
+
+    // prepend the tags since the sdt start mark before the paragraph
+    pSerializer->mergeTopMarks(Tag_WriteSdtBlock, 
sax_fastparser::MergeMarks::PREPEND);
+
+    // write the ending tags after the paragraph
+    m_bStartedSdt = true;
+
+    // clear sdt status
+    m_nSdtPrToken = 0;
+    m_pTokenChildren.clear();
+    m_pDataBindingAttrs.clear();
+    m_pTextAttrs.clear();
+    m_aAlias.clear();
+    m_bHasId = false;
+}
+
+void SdtBlockHelper::WriteExtraParams(::sax_fastparser::FSHelperPtr& 
pSerializer)
+{
     if (m_nSdtPrToken == FSNS(XML_w, XML_id) || m_bHasId)
         //Word won't open a document with an empty id tag, we fill it with a 
random number
         pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val),
             OString::number(comphelper::rng::uniform_int_distribution(0, 
std::numeric_limits<int>::max())));
 
-    if (m_pDataBindingAttrs.is() && !bParagraphHasDrawing)
+    if (m_pDataBindingAttrs.is())
     {
         rtl::Reference<FastAttributeList> xAttrList = 
std::move(m_pDataBindingAttrs);
         pSerializer->singleElementNS(XML_w, XML_dataBinding, xAttrList);
@@ -693,25 +717,6 @@ void 
SdtBlockHelper::WriteSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer, b
 
     if (!m_aAlias.isEmpty())
         pSerializer->singleElementNS(XML_w, XML_alias, FSNS(XML_w, XML_val), 
m_aAlias);
-
-    pSerializer->endElementNS(XML_w, XML_sdtPr);
-
-    // sdt contents start tag
-    pSerializer->startElementNS(XML_w, XML_sdtContent);
-
-    // prepend the tags since the sdt start mark before the paragraph
-    pSerializer->mergeTopMarks(Tag_WriteSdtBlock, 
sax_fastparser::MergeMarks::PREPEND);
-
-    // write the ending tags after the paragraph
-    m_bStartedSdt = true;
-
-    // clear sdt status
-    m_nSdtPrToken = 0;
-    m_pTokenChildren.clear();
-    m_pDataBindingAttrs.clear();
-    m_pTextAttrs.clear();
-    m_aAlias.clear();
-    m_bHasId = false;
 }
 
 void SdtBlockHelper::EndSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer)
@@ -2152,7 +2157,7 @@ void DocxAttributeOutput::WriteFFData(  const FieldInfos& 
rInfos )
     }
 }
 
-void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const 
OUString& sDateFormat, const OUString& sLang)
+void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const 
OUString& sDateFormat, const OUString& sLang, const 
uno::Sequence<beans::PropertyValue>& aGrabBagSdt)
 {
     m_pSerializer->startElementNS(XML_w, XML_sdt);
     m_pSerializer->startElementNS(XML_w, XML_sdtPr);
@@ -2172,8 +2177,16 @@ void DocxAttributeOutput::WriteFormDateStart(const 
OUString& sFullDate, const OU
                                    FSNS(XML_w, XML_val), "dateTime");
     m_pSerializer->singleElementNS(XML_w, XML_calendar,
                                    FSNS(XML_w, XML_val), "gregorian");
-
     m_pSerializer->endElementNS(XML_w, XML_date);
+
+    if (aGrabBagSdt.hasElements())
+    {
+        // There are some extra sdt parameters came from grab bag
+        SdtBlockHelper aSdtBlock;
+        aSdtBlock.GetSdtParamsFromGrabBag(aGrabBagSdt);
+        aSdtBlock.WriteExtraParams(m_pSerializer);
+    }
+
     m_pSerializer->endElementNS(XML_w, XML_sdtPr);
 
     m_pSerializer->startElementNS(XML_w, XML_sdtContent);
@@ -2276,7 +2289,10 @@ void DocxAttributeOutput::StartField_Impl( const 
SwTextNode* pNode, sal_Int32 nP
         OUString sLang;
         params.extractParam( ODF_FORMDATE_DATEFORMAT_LANGUAGE, sLang );
 
-        WriteFormDateStart( sFullDate, sDateFormat, sLang );
+        uno::Sequence<beans::PropertyValue> aSdtParams;
+        params.extractParam("SdtParams", aSdtParams);
+
+        WriteFormDateStart( sFullDate, sDateFormat, sLang, aSdtParams);
     }
     else if (rInfos.eType == ww::eFORMDROPDOWN && rInfos.pField)
     {
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx 
b/sw/source/filter/ww8/docxattributeoutput.hxx
index 595b30e7329b..3897073ffe1f 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -144,6 +144,7 @@ public:
     void DeleteAndResetTheLists();
 
     void WriteSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer, bool 
bRunTextIsOn, bool bParagraphHasDrawing);
+    void WriteExtraParams(::sax_fastparser::FSHelperPtr& pSerializer);
 
     /// Closes a currently open SDT block.
     void EndSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer);
@@ -750,7 +751,7 @@ private:
     void WritePostponedCustomShape();
     void WriteFlyFrame(const ww8::Frame& rFrame);
 
-    void WriteFormDateStart(const OUString& sFullDate, const OUString& 
sDateFormat, const OUString& sLang);
+    void WriteFormDateStart(const OUString& sFullDate, const OUString& 
sDateFormat, const OUString& sLang, const uno::Sequence<beans::PropertyValue>& 
aGrabBagSdt);
     void WriteSdtDropDownStart(std::u16string_view rName, OUString const& 
rSelected, uno::Sequence<OUString> const& rListItems);
     void WriteSdtDropDownEnd(OUString const& rSelected, 
uno::Sequence<OUString> const& rListItems);
     void WriteSdtEnd();
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index ea16e51e0f9f..b247e0156b38 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1132,12 +1132,15 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
         }
         break;
         case NS_ooxml::LN_CT_DataBinding_prefixMappings:
+            m_pImpl->m_pSdtHelper->setDataBindingPrefixMapping(sStringValue);
             m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_DataBinding_prefixMappings", sStringValue);
             break;
         case NS_ooxml::LN_CT_DataBinding_xpath:
+            m_pImpl->m_pSdtHelper->setDataBindingXPath(sStringValue);
             m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_DataBinding_xpath", sStringValue);
             break;
         case NS_ooxml::LN_CT_DataBinding_storeItemID:
+            m_pImpl->m_pSdtHelper->setDataBindingStoreItemID(sStringValue);
             m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_DataBinding_storeItemID", sStringValue);
             break;
         case NS_ooxml::LN_CT_SdtPlaceholder_docPart_val:
@@ -3539,11 +3542,7 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, 
size_t len)
     }
     else if (m_pImpl->m_pSdtHelper->getControlType() == 
SdtControlType::datePicker)
     {
-        if (!m_pImpl->m_pSdtHelper->isInteropGrabBagEmpty())
-        {
-            m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
-        }
-        else if (IsInHeaderFooter() && m_pImpl->IsDiscardHeaderFooter())
+        if (IsInHeaderFooter() && m_pImpl->IsDiscardHeaderFooter())
         {
             m_pImpl->m_pSdtHelper->getDateFormat().truncate();
             m_pImpl->m_pSdtHelper->getLocale().truncate();
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx 
b/writerfilter/source/dmapper/SdtHelper.cxx
index 46f834280404..5466baec8fc1 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -196,6 +196,9 @@ void SdtHelper::createDateContentControl()
     }
 
     setControlType(SdtControlType::unknown);
+
+    // Store all unused sdt parameters from grabbag
+    xNameCont->insertByName("SdtParams", 
uno::makeAny(getInteropGrabBagAndClear()));
 }
 
 void SdtHelper::createControlShape(awt::Size aSize,
diff --git a/writerfilter/source/dmapper/SdtHelper.hxx 
b/writerfilter/source/dmapper/SdtHelper.hxx
index 5a39177c4a56..9d31e1621504 100644
--- a/writerfilter/source/dmapper/SdtHelper.hxx
+++ b/writerfilter/source/dmapper/SdtHelper.hxx
@@ -54,6 +54,14 @@ class SdtHelper final : public virtual SvRefBase
     OUStringBuffer m_sDate;
     /// Date format string as it comes from the ooxml document.
     OUStringBuffer m_sDateFormat;
+
+    /// <w:dataBinding w:prefixMappings="">
+    OUString m_sDataBindingPrefixMapping;
+    /// <w:dataBinding w:xpath="">
+    OUString m_sDataBindingXPath;
+    /// <w:dataBinding w:storeItemID="">
+    OUString m_sDataBindingStoreItemID;
+
     /// Start range of the date field
     css::uno::Reference<css::text::XTextRange> m_xDateFieldStartRange;
     /// Locale string as it comes from the ooxml document.
@@ -81,6 +89,13 @@ public:
 
     OUStringBuffer& getDateFormat() { return m_sDateFormat; }
 
+    void setDataBindingPrefixMapping(const OUString& sValue)
+    {
+        m_sDataBindingPrefixMapping = sValue;
+    }
+    void setDataBindingXPath(const OUString& sValue) { m_sDataBindingXPath = 
sValue; }
+    void setDataBindingStoreItemID(const OUString& sValue) { 
m_sDataBindingStoreItemID = sValue; }
+
     void setDateFieldStartRange(const 
css::uno::Reference<css::text::XTextRange>& xStartRange)
     {
         m_xDateFieldStartRange = xStartRange;

Reply via email to