summaryrefslogtreecommitdiff
path: root/sw/source/filter
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2020-02-26 13:00:23 +0100
committerMichael Stahl <michael.stahl@cib.de>2020-02-27 10:43:10 +0100
commitd55b26a093bdbced08985dbc7113190b52a8bc66 (patch)
treee26b4c8510f50e1c6e91cf1ef93d0b8b31f60546 /sw/source/filter
parent8fc1b60f62c213a0476f3acc9f89cd5eccbf335d (diff)
sw: DOCX export: for SwDropDownField, don't write FORMDROPDOWN
... because Word's funny limitation to 25 listEntry children causes data loss, as seen in commit d9634e3c9bfaf826b3d4d39e9a57d6c2d8d9a3dc "sw: DOCX export: limit FORMDROPDOWN listEntry to Word's abilities". Instead write SDT dropDownList, which appears to be able to store at least 26 listItem children without complaint from Word, so it's an improvement. Funnily domainmapper converts it to a form control on DOCX import. Change-Id: Ic0f24144cb2b5233f82c7b3bc67946a6e56448a8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89541 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@cib.de>
Diffstat (limited to 'sw/source/filter')
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx91
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.hxx3
2 files changed, 69 insertions, 25 deletions
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index b4f137b67f0c..5885e788f6b4 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1321,7 +1321,7 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin() + nFieldsInPrevHyperlink; pIt != m_Fields.end(); )
{
// Add the fields starts for all but hyperlinks and TOCs
- if ( pIt->bOpen && pIt->pField )
+ if (pIt->bOpen && pIt->pField && pIt->eType != ww::eFORMDROPDOWN)
{
StartField_Impl( pNode, nPos, *pIt );
@@ -1386,7 +1386,7 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); )
{
// Add the fields starts for hyperlinks, TOCs and index marks
- if ( pIt->bOpen && !pIt->pField )
+ if (pIt->bOpen && (!pIt->pField || pIt->eType == ww::eFORMDROPDOWN))
{
StartRedline( m_pRedlineData );
StartField_Impl( pNode, nPos, *pIt, true );
@@ -1921,12 +1921,57 @@ void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const OU
m_pSerializer->startElementNS(XML_w, XML_sdtContent);
}
-void DocxAttributeOutput::WriteFormDateEnd()
+void DocxAttributeOutput::WriteSdtEnd()
{
m_pSerializer->endElementNS(XML_w, XML_sdtContent);
m_pSerializer->endElementNS(XML_w, XML_sdt);
}
+void DocxAttributeOutput::WriteSdtDropDownStart(
+ OUString const& rName,
+ OUString const& rSelected,
+ uno::Sequence<OUString> const& rListItems)
+{
+ m_pSerializer->startElementNS(XML_w, XML_sdt);
+ m_pSerializer->startElementNS(XML_w, XML_sdtPr);
+
+ m_pSerializer->singleElementNS(XML_w, XML_alias,
+ FSNS(XML_w, XML_val), OUStringToOString(rName, RTL_TEXTENCODING_UTF8));
+
+ sal_Int32 nId = comphelper::findValue(rListItems, rSelected);
+ if (nId == -1)
+ {
+ nId = 0;
+ }
+
+ m_pSerializer->startElementNS(XML_w, XML_dropDownList,
+ FSNS(XML_w, XML_lastValue), OString::number(nId));
+
+ for (auto const& rItem : rListItems)
+ {
+ auto const item(OUStringToOString(rItem, RTL_TEXTENCODING_UTF8));
+ m_pSerializer->singleElementNS(XML_w, XML_listItem,
+ FSNS(XML_w, XML_value), item,
+ FSNS(XML_w, XML_displayText), item);
+ }
+
+ m_pSerializer->endElementNS(XML_w, XML_dropDownList);
+ m_pSerializer->endElementNS(XML_w, XML_sdtPr);
+
+ m_pSerializer->startElementNS(XML_w, XML_sdtContent);
+
+ // the lastValue only identifies the entry in the list, also export
+ // currently selected item's displayText as run content (if one exists)
+ if (rListItems.size())
+ {
+ m_pSerializer->startElementNS(XML_w, XML_r);
+ m_pSerializer->startElementNS(XML_w, XML_t);
+ m_pSerializer->writeEscaped(rListItems[nId]);
+ m_pSerializer->endElementNS(XML_w, XML_t);
+ m_pSerializer->endElementNS(XML_w, XML_r);
+ }
+}
+
void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun )
{
if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN )
@@ -1962,6 +2007,14 @@ void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nP
WriteFormDateStart( sFullDate, sDateFormat, sLang );
}
+ else if (rInfos.eType == ww::eFORMDROPDOWN && rInfos.pField)
+ {
+ assert(!rInfos.pFieldmark);
+ SwDropDownField const& rField2(*static_cast<SwDropDownField const*>(rInfos.pField.get()));
+ WriteSdtDropDownStart(rField2.GetName(),
+ rField2.GetSelectedItem(),
+ rField2.GetItemSequence());
+ }
else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
{
if ( bWriteRun )
@@ -1969,27 +2022,16 @@ void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nP
if ( rInfos.eType == ww::eFORMDROPDOWN )
{
- m_pSerializer->startElementNS( XML_w, XML_fldChar,
- FSNS( XML_w, XML_fldCharType ), "begin" );
- if ( rInfos.pFieldmark && !rInfos.pField )
- WriteFFData( rInfos );
- if ( rInfos.pField )
- {
- const SwDropDownField& rField2 = *static_cast<const SwDropDownField*>(rInfos.pField.get());
- uno::Sequence<OUString> aItems =
- rField2.GetItemSequence();
- GetExport().DoComboBox(rField2.GetName(),
- rField2.GetHelp(),
- rField2.GetToolTip(),
- rField2.GetSelectedItem(), aItems);
- }
- m_pSerializer->endElementNS( XML_w, XML_fldChar );
+ m_pSerializer->startElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "begin" );
+ assert( rInfos.pFieldmark && !rInfos.pField );
+ WriteFFData(rInfos);
+ m_pSerializer->endElementNS( XML_w, XML_fldChar );
- if ( bWriteRun )
- m_pSerializer->endElementNS( XML_w, XML_r );
+ if ( bWriteRun )
+ m_pSerializer->endElementNS( XML_w, XML_r );
- if ( !rInfos.pField )
- CmdField_Impl( pNode, nPos, rInfos, bWriteRun );
+ CmdField_Impl( pNode, nPos, rInfos, bWriteRun );
}
else
{
@@ -2174,9 +2216,10 @@ void DocxAttributeOutput::DoWriteFieldRunProperties( const SwTextNode * pNode, s
void DocxAttributeOutput::EndField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos& rInfos )
{
- if ( rInfos.eType == ww::eFORMDATE )
+ if (rInfos.eType == ww::eFORMDATE
+ || (rInfos.eType == ww::eFORMDROPDOWN && rInfos.pField))
{
- WriteFormDateEnd();
+ WriteSdtEnd();
return;
}
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index ebcff8966b37..8b7b8ac3c8cf 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -718,7 +718,8 @@ private:
void EndSdtBlock();
void WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang);
- void WriteFormDateEnd();
+ void WriteSdtDropDownStart(OUString const& rName, OUString const& rSelected, uno::Sequence<OUString> const& rListItems);
+ void WriteSdtEnd();
void StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun = false );
void DoWriteCmd( const OUString& rCmd );