sw/qa/extras/rtfexport/data/FORMDROPDOWN.rtf | 33 ++++++++++++ sw/qa/extras/rtfexport/rtfexport4.cxx | 21 +++++++ sw/source/filter/ww8/rtfexport.cxx | 58 +++++++++++++++++++++- writerfilter/source/dmapper/FormControlHelper.cxx | 5 + writerfilter/source/rtftok/rtfdocumentimpl.cxx | 4 + 5 files changed, 117 insertions(+), 4 deletions(-)
New commits: commit 47b08551a77918e4d35a98197ac99c1c3d5dec73 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Aug 5 12:57:57 2022 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Mon Aug 8 15:50:08 2022 +0200 tdf#148518 writerfilter,sw: RTF import/export of FORMDROPDOWN field On import, the values overwrote each other; export of the form data was missing completely. Change-Id: I918b3cfced39dc2602c6de03cdaf5848a9825dd2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137861 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/qa/extras/rtfexport/data/FORMDROPDOWN.rtf b/sw/qa/extras/rtfexport/data/FORMDROPDOWN.rtf new file mode 100644 index 000000000000..ef1d3af744db --- /dev/null +++ b/sw/qa/extras/rtfexport/data/FORMDROPDOWN.rtf @@ -0,0 +1,33 @@ +{\rtf1\adeflang1025\ansi\ansicpg1250\uc1\adeff0\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1038\deflangfe1038\themelang1031\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0; +\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128; +\red192\green192\blue192;}{\*\defchp \fs22 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3079\langfe3079\cgrid\langnp3079\langfenp3079 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive +\ssemihidden Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv +\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1038\langfe1038\cgrid\langnp1038\langfenp1038 \snext11 \ssemihidden \sunhideused +Normal Table;}{\*\ts15\tsrowd\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv +\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20\alang1025 \ltrch\fcs0 \fs20\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 \sbasedon11 \snext15 \styrsid6366418 Table Grid;}{ +\s16\ql \li0\ri0\widctlpar\tqc\tx4513\tqr\tx9026\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3079\langfe3079\cgrid\langnp3079\langfenp3079 +\sbasedon0 \snext16 \slink17 \styrsid14450383 header;}{\*\cs17 \additive \rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs24\lang3079\langfe3079\langnp3079\langfenp3079 \sbasedon10 \slink16 \slocked \styrsid14450383 Header Char;}{\s18\ql \li0\ri0\widctlpar +\tqc\tx4513\tqr\tx9026\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3079\langfe3079\cgrid\langnp3079\langfenp3079 \sbasedon0 \snext18 \slink19 \styrsid14450383 footer;}{\*\cs19 +\additive \rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs24\lang3079\langfe3079\langnp3079\langfenp3079 \sbasedon10 \slink18 \slocked \styrsid14450383 Footer Char;}}{\*\rsidtbl \rsid1922796\rsid2437734\rsid4346699\rsid4392934\rsid5467240\rsid5720824\rsid6366418 +\rsid6843717\rsid7742502\rsid7807608\rsid7872863\rsid7957046\rsid8722154\rsid8811273\rsid9708480\rsid9904672\rsid10167906\rsid11299441\rsid12799272\rsid13922319\rsid14183170\rsid14450383\rsid14632381\rsid14900426\rsid15207980\rsid15864162\rsid16002556 +\rsid16275940}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\creatim\yr2022\mo4\dy6\hr15\min54}{\revtim\yr2022\mo4\dy6\hr15\min59}{\version1}{\edmins0}{\nofpages1} +{\nofwords7}{\nofchars56}{\nofcharsws62}{\vern57453}} +\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1134\gutter0\ltrsect +\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0 +\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1417\dgvorigin1417\dghshow1\dgvshow1 +\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\rempersonalinfo\allowfieldendsel +\wrppunct\asianbrkrule\rsidroot13922319\newtblstyruls\nogrowautofit\remdttm \fet0{\*\wgrffmtfilter 013f}\ilfomacatclnup0 +\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj +\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6366418 +\rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3079\langfe3079\cgrid\langnp3079\langfenp3079 \sectd \ltrsect +\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj +{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid10167906 +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid7872863 {\*\bkmkstart Dropdown1}Dropdown list}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid10167906 : }{\field\fldpriv{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid10167906 FORMDROPDOWN }{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid10167906 {\*\datafield 66800000000000000944726f70646f776e31000000000000000000000000000c000300030000000a00060008000a00017801760164}{\*\formfield{\fftype2\ffres1\fftypetxt0\ffhaslistbox{\*\ffname Dropdown1}\ffdefres0{\*\ffl x}{\*\ffl v}{\*\ffl d}}} +}}{\fldrslt }}\sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid10167906 {\*\bkmkend Dropdown1} +\par +\par } +} diff --git a/sw/qa/extras/rtfexport/rtfexport4.cxx b/sw/qa/extras/rtfexport/rtfexport4.cxx index 367b75ac34d8..f730afd93c25 100644 --- a/sw/qa/extras/rtfexport/rtfexport4.cxx +++ b/sw/qa/extras/rtfexport/rtfexport4.cxx @@ -19,6 +19,8 @@ #include <com/sun/star/text/XTextTable.hpp> #include <o3tl/cppunittraitshelper.hxx> +#include <xmloff/odffields.hxx> + #include <docsh.hxx> #include <unotxdoc.hxx> #include <pam.hxx> @@ -96,6 +98,25 @@ DECLARE_RTFEXPORT_TEST(testCjklist31, "cjklist31.rtf") CPPUNIT_ASSERT_EQUAL(style::NumberingType::DI_ZI_ZH, numFormat); } +DECLARE_RTFEXPORT_TEST(test148518, "FORMDROPDOWN.rtf") +{ + SwXTextDocument* const pTextDoc(dynamic_cast<SwXTextDocument*>(mxComponent.get())); + CPPUNIT_ASSERT(pTextDoc); + SwDoc* const pDoc(pTextDoc->GetDocShell()->GetDoc()); + + CPPUNIT_ASSERT(pDoc->getIDocumentMarkAccess()->getFieldmarksBegin() + != pDoc->getIDocumentMarkAccess()->getFieldmarksEnd()); + ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>( + *pDoc->getIDocumentMarkAccess()->getFieldmarksBegin()); + uno::Sequence<OUString> entries; + (*pFieldmark->GetParameters())[ODF_FORMDROPDOWN_LISTENTRY] >>= entries; + uno::Sequence<OUString> const expected{ OUString("x"), OUString("v"), OUString("d") }; + CPPUNIT_ASSERT_EQUAL(expected, entries); + sal_Int32 result(-1); + (*pFieldmark->GetParameters())[ODF_FORMDROPDOWN_RESULT] >>= result; + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), result); +} + DECLARE_RTFEXPORT_TEST(testAnchoredAtSamePosition, "anchor.fodt") { SwXTextDocument* const pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx index f51ea6f62182..7a0dee9c743b 100644 --- a/sw/source/filter/ww8/rtfexport.cxx +++ b/sw/source/filter/ww8/rtfexport.cxx @@ -55,6 +55,7 @@ #include <svtools/rtfkeywd.hxx> #include <filter/msfilter/rtfutil.hxx> #include <unotools/docinfohelper.hxx> +#include <xmloff/odffields.hxx> #include <o3tl/string_view.hxx> #include <osl/diagnose.h> #include <rtl/tencinfo.h> @@ -318,9 +319,62 @@ void RtfExport::OutputField(const SwField* pField, ww::eField eFieldType, const m_pAttrOutput->WriteField_Impl(pField, eFieldType, rFieldCmd, nMode); } -void RtfExport::WriteFormData(const ::sw::mark::IFieldmark& /*rFieldmark*/) +void RtfExport::WriteFormData(const ::sw::mark::IFieldmark& rFieldmark) { - SAL_INFO("sw.rtf", "TODO: " << __func__); + sal_Int32 nType; + if (rFieldmark.GetFieldname() == ODF_FORMDROPDOWN) + { + nType = 2; + } + /* TODO + else if (rFieldmark.GetFieldname() == ODF_FORMCHECKBOX) + { + nType = 1; + } + else if (rFieldmark.GetFieldname() == ODF_FORMTEXT) + { + nType = 0; + } +*/ + else + { + SAL_INFO("sw.rtf", "unknown field type"); + return; + } + m_pAttrOutput->RunText().append( + "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD + "{" OOO_STRING_SVTOOLS_RTF_FFTYPE); + m_pAttrOutput->RunText().append(nType); + if (rFieldmark.GetFieldname() == ODF_FORMDROPDOWN) + { + m_pAttrOutput->RunText().append(OOO_STRING_SVTOOLS_RTF_FFHASLISTBOX "1"); + uno::Sequence<OUString> entries; + if (auto const it = rFieldmark.GetParameters()->find(ODF_FORMDROPDOWN_LISTENTRY); + it != rFieldmark.GetParameters()->end()) + { + it->second >>= entries; + } + if (auto const it = rFieldmark.GetParameters()->find(ODF_FORMDROPDOWN_RESULT); + it != rFieldmark.GetParameters()->end()) + { + sal_Int32 result(-1); + it->second >>= result; + if (0 <= result && result < entries.getLength()) + { + m_pAttrOutput->RunText().append(OOO_STRING_SVTOOLS_RTF_FFRES); + m_pAttrOutput->RunText().append(result); + } + } + for (OUString const& rEntry : entries) + { + m_pAttrOutput->RunText().append( + "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFL " "); + m_pAttrOutput->RunText().append( + msfilter::rtfutil::OutString(rEntry, m_eDefaultEncoding)); + m_pAttrOutput->RunText().append("}"); + } + } + m_pAttrOutput->RunText().append("}}"); // close FORMFIELD destination } void RtfExport::WriteHyperlinkData(const ::sw::mark::IFieldmark& /*rFieldmark*/) diff --git a/writerfilter/source/dmapper/FormControlHelper.cxx b/writerfilter/source/dmapper/FormControlHelper.cxx index 4e2cd3ecd50a..6e51543abad2 100644 --- a/writerfilter/source/dmapper/FormControlHelper.cxx +++ b/writerfilter/source/dmapper/FormControlHelper.cxx @@ -34,6 +34,8 @@ #include <com/sun/star/text/VertOrientation.hpp> #include <com/sun/star/uno/Any.hxx> +#include <o3tl/safeint.hxx> + #include "FormControlHelper.hxx" #include <utility> #include <xmloff/odffields.hxx> @@ -286,7 +288,8 @@ void FormControlHelper::processField(uno::Reference<text::XFormField> const& xFo xNameCont->insertByName(ODF_FORMDROPDOWN_LISTENTRY, uno::Any(comphelper::containerToSequence(rEntries))); sal_Int32 nResult = m_pFFData->getDropDownResult().toInt32(); - if ( nResult ) + // 0 is valid, but also how toInt32 reports parse error, but it's a sensible default... + if (0 <= nResult && o3tl::make_unsigned(nResult) < rEntries.size()) { if ( xNameCont->hasByName(ODF_FORMDROPDOWN_RESULT) ) xNameCont->replaceByName(ODF_FORMDROPDOWN_RESULT, uno::Any( nResult ) ); diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index 71e25f4571f8..840a6bb5bdef 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -2545,7 +2545,9 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState) break; // not for nested group auto pValue = new RTFValue(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); - m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_listEntry, pValue); + // OOXML puts these into a LN_CT_FFData_ddList but FFDataHandler should handle this too + m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_listEntry, pValue, + RTFOverwrite::NO_APPEND); } break; case Destination::DATAFIELD: