diff options
author | Jean-Sebastien Bevilacqua <realitix@gmail.com> | 2017-02-16 10:16:50 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-03-28 07:05:30 +0000 |
commit | 4d5ce76d894d2335b551f8c2b29437e2049894f0 (patch) | |
tree | 152ac7f5dabfc7f7cb1df385dac8ed63a3afa1d1 | |
parent | b3549aacabffad3c4c66d901938d59e4789eef22 (diff) |
tdf#105975 Add Set field parsing (docx) in LibreOffice Writer
Introduction
------------
In MSWord, you can create a variable with `SET` field and then
reference it later in a formula. When you save your file as `docx`,
this `SET` field is registered in you file. In its current state,
LibreOffice can't parse the `SET` field in `docx` file.
Context of this fix
-------------------
This fix is entirely located in the `DomainMapper_Impl.cxx` file
because it's where the parsing is done.
How this fix works
------------------
First, we add `SET` support by adding it to the `aFields[]` variable.
Next, to handle the `SET` constant, we add a condition (swith case) in
`DomainMapper_Impl::CloseFieldCommand()` to call `handleFieldSet`.
Finally, `handleFieldSet` works like `handleFieldAsk` with small
differences.
Note
----
I have renamed `lcl_ExctractAskVariableAndHint` to
`lcl_ExctractVariableAndHint` because this function is used for both `ASK` and
`SET` fields.
Change-Id: I2bf948e26e8506ac151d1d0bc8556721bbe0392b
Reviewed-on: https://gerrit.libreoffice.org/34333
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 2 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlimport/data/105975.docx | bin | 0 -> 12783 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 8 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 46 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 4 |
5 files changed, 55 insertions, 5 deletions
diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index ec8b13621001..d473a13f73e2 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -432,7 +432,7 @@ DECLARE_OOXMLEXPORT_TEST(testFDO76163 , "fdo76163.docx") if (!pXmlDoc) return; //docx file after RT is getting corrupted. - assertXPath ( pXmlDoc, "/w:document/w:body/w:p[2]/w:hyperlink/w:r[11]/w:fldChar", "fldCharType", "end" ); + assertXPath ( pXmlDoc, "/w:document/w:body/w:p[2]/w:hyperlink/w:r[10]/w:fldChar", "fldCharType", "end" ); } DECLARE_OOXMLEXPORT_TEST(testFDO78659, "fdo78659.docx") diff --git a/sw/qa/extras/ooxmlimport/data/105975.docx b/sw/qa/extras/ooxmlimport/data/105975.docx Binary files differnew file mode 100644 index 000000000000..b902aa168a9a --- /dev/null +++ b/sw/qa/extras/ooxmlimport/data/105975.docx diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx index 77880b935b96..87c71b8afb6b 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -699,6 +699,14 @@ DECLARE_OOXMLIMPORT_TEST(testTdf105143, "tdf105143.docx") CPPUNIT_ASSERT_EQUAL(OUString("6674"), aTop); } +DECLARE_OOXMLIMPORT_TEST(testTdf105975, "105975.docx") +{ + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xMasters(xTextFieldsSupplier->getTextFieldMasters()); + // Make sure we have a variable named TEST_VAR. + CPPUNIT_ASSERT(xMasters->hasByName("com.sun.star.text.FieldMaster.SetExpression.TEST_VAR")); +} + DECLARE_OOXMLIMPORT_TEST(testfdo76583, "fdo76583.docx") { // The problem was that the floating table was imported as a non-floating one. diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index c64d9de17889..6189f9f139ab 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -2367,7 +2367,7 @@ std::tuple<OUString, std::vector<OUString>, std::vector<OUString> > splitFieldCo return std::make_tuple(sType, arguments, switches); } -OUString lcl_ExctractAskVariableAndHint( const OUString& rCommand, OUString& rHint ) +OUString lcl_ExctractVariableAndHint( const OUString& rCommand, OUString& rHint ) { // the first word after "ASK " is the variable // the text after the variable and before a '\' is the hint @@ -2862,7 +2862,7 @@ if(!bFilled) // {OUString("SECTION"), "", FIELD_SECTION }, // {OUString("SECTIONPAGES"), "", FIELD_SECTIONPAGES }, {OUString("SEQ"), "SetExpression", FIELD_SEQ }, -// {OUString("SET"), FIELD_SET }, + {OUString("SET"), "SetExpression", FIELD_SET }, // {OUString("SKIPIF"),"", FIELD_SKIPIF }, // {OUString("STYLEREF"),"", FIELD_STYLEREF }, {OUString("SUBJECT"), "DocInfo.Subject", FIELD_SUBJECT }, @@ -2928,6 +2928,42 @@ const FieldConversionMap_t & lcl_GetEnhancedFieldConversion() return aEnhancedFieldConversionMap; } +void DomainMapper_Impl::handleFieldSet + (const FieldContextPtr& pContext, + uno::Reference< uno::XInterface > & xFieldInterface, + uno::Reference< beans::XPropertySet > const& xFieldProperties) +{ + OUString sVariable, sHint; + + sVariable = lcl_ExctractVariableAndHint(pContext->GetCommand(), sHint); + + // remove surrounding "" if exists + if( sHint.getLength() >= 2 && sHint.startsWith("\"") ) + { + sHint = sHint.trim().copy(1, sHint.getLength() - 2); + } + + // determine field master name + uno::Reference< beans::XPropertySet > xMaster = + FindOrCreateFieldMaster + ("com.sun.star.text.FieldMaster.SetExpression", sVariable ); + + // a set field is a string + xMaster->setPropertyValue(getPropertyName(PROP_SUB_TYPE), uno::makeAny(text::SetVariableType::STRING)); + + // attach the master to the field + uno::Reference< text::XDependentTextField > xDependentField + ( xFieldInterface, uno::UNO_QUERY_THROW ); + xDependentField->attachTextFieldMaster( xMaster ); + + xFieldProperties->setPropertyValue(getPropertyName(PROP_HINT), uno::makeAny( sHint )); + xFieldProperties->setPropertyValue(getPropertyName(PROP_CONTENT), uno::makeAny( sHint )); + xFieldProperties->setPropertyValue(getPropertyName(PROP_SUB_TYPE), uno::makeAny(text::SetVariableType::STRING)); + + // Mimic MS Word behavior (hide the SET) + xFieldProperties->setPropertyValue(getPropertyName(PROP_IS_VISIBLE), uno::makeAny(false)); +} + void DomainMapper_Impl::handleFieldAsk (const FieldContextPtr& pContext, uno::Reference< uno::XInterface > & xFieldInterface, @@ -2936,7 +2972,7 @@ void DomainMapper_Impl::handleFieldAsk //doesn the command contain a variable name? OUString sVariable, sHint; - sVariable = lcl_ExctractAskVariableAndHint( pContext->GetCommand(), + sVariable = lcl_ExctractVariableAndHint( pContext->GetCommand(), sHint ); if(!sVariable.isEmpty()) { @@ -4099,7 +4135,9 @@ void DomainMapper_Impl::CloseFieldCommand() uno::makeAny(nNumberingType)); } break; - case FIELD_SET : break; + case FIELD_SET : + handleFieldSet(pContext, xFieldInterface, xFieldProperties); + break; case FIELD_SKIPIF : break; case FIELD_STYLEREF : break; case FIELD_SUBJECT : diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index e3071b9abe78..f8924f1e75f4 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -651,6 +651,10 @@ public: //collect the pieces of the command void AppendFieldCommand(OUString& rPartOfCommand); void handleRubyEQField( const FieldContextPtr& pContext); + void handleFieldSet + (const FieldContextPtr& pContext, + css::uno::Reference< css::uno::XInterface > & xFieldInterface, + css::uno::Reference< css::beans::XPropertySet > const& xFieldProperties); void handleFieldAsk (const FieldContextPtr& pContext, css::uno::Reference< css::uno::XInterface > & xFieldInterface, |