diff options
-rw-r--r-- | oox/source/export/vmlexport.cxx | 5 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport17.cxx | 25 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport5.cxx | 2 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 6 | ||||
-rw-r--r-- | sw/source/filter/ww8/attributeoutputbase.hxx | 2 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 16 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 2 | ||||
-rw-r--r-- | sw/source/filter/ww8/wrtw8nds.cxx | 2 | ||||
-rw-r--r-- | writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx | 30 | ||||
-rw-r--r-- | writerfilter/qa/cppunittests/dmapper/data/sdt-run-plain-text.docx | bin | 0 -> 4179 bytes | |||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 20 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 5 | ||||
-rw-r--r-- | writerfilter/source/dmapper/SdtHelper.cxx | 1 | ||||
-rw-r--r-- | writerfilter/source/dmapper/SdtHelper.hxx | 4 |
14 files changed, 100 insertions, 20 deletions
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx index 47a196908a4d..1bfc59ee13db 100644 --- a/oox/source/export/vmlexport.cxx +++ b/oox/source/export/vmlexport.cxx @@ -1008,12 +1008,9 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle& default: #if OSL_DEBUG_LEVEL > 0 const size_t opt_nProp_size(opt.nProp.size()); - const sal_uInt8 opt_nProp_empty(0); SAL_WARN( "oox.vml", "TODO VMLExport::Commit(), unimplemented id: " << nId << ", value: " << opt.nPropValue - << ", data: [" << opt_nProp_size << ", " - << (0 == opt_nProp_size ? &opt_nProp_empty : opt.nProp.data()) - << "]"); + << ", data: [" << opt_nProp_size << "]"); if ( opt.nProp.size() ) { const sal_uInt8 *pIt = opt.nProp.data(); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx index f139837b822a..ee5b0dd19b14 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx @@ -676,15 +676,26 @@ DECLARE_OOXMLEXPORT_TEST(testTdf123642_BookmarkAtDocEnd, "tdf123642.docx") DECLARE_OOXMLEXPORT_TEST(testTdf148361, "tdf148361.docx") { - // Refresh fields and ensure cross-reference to numbered para is okay - uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); + if (mbExported) + { + // Block SDT is turned into run SDT on export, so the next import will have this as content + // control, not as a field. + OUString aActual = getParagraph(1)->getString(); + // This was "itadmin". + CPPUNIT_ASSERT_EQUAL(OUString("itadmin"), aActual); + } + else + { + // Refresh fields and ensure cross-reference to numbered para is okay + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); - uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); - CPPUNIT_ASSERT(xFields->hasMoreElements()); + uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); + CPPUNIT_ASSERT(xFields->hasMoreElements()); - uno::Reference<text::XTextField> xTextField1(xFields->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(OUString("itadmin"), xTextField1->getPresentation(false)); + uno::Reference<text::XTextField> xTextField1(xFields->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("itadmin"), xTextField1->getPresentation(false)); + } OUString aActual = getParagraph(2)->getString(); // This was "itadmin". diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index cd405b196cba..d34e5ce957f0 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -1095,7 +1095,7 @@ CPPUNIT_TEST_FIXTURE(Test, testSdt2Run) xmlDocUniquePtr pXmlDoc = parseExport(); // The problem was that <w:sdt> was closed after "first", not after "second", so the second assert failed. - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r", 1); + assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r/w:t", "firstsecond"); // Make sure the third portion is still outside <w:sdt>. assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/w:t", "third"); } diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index d5fd1691c2a3..43a7c2a67ce4 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -587,7 +587,8 @@ CPPUNIT_TEST_FIXTURE(Test, testfdo82123) xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); // make sure there is only one run inside first SDT after RT as in the Original file. - assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr/w:tc[2]/w:p/w:sdt[1]/w:sdtContent/w:r",1); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr/w:tc[2]/w:p/w:sdt[1]/w:sdtContent/w:r/w:t", 1); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr/w:tc[2]/w:p/w:r/w:drawing", 1); } CPPUNIT_TEST_FIXTURE(Test, testSdtBeforeField) @@ -612,7 +613,8 @@ CPPUNIT_TEST_FIXTURE(Test, testfdo82492) xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); // make sure there is only one run inside first SDT after RT as in the Original file. - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt[1]/w:sdtContent/w:r",1); + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt[1]/w:sdtContent/w:r/w:t", 1); + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/mc:AlternateContent", 1); } CPPUNIT_TEST_FIXTURE(Test, testSdtHeader) diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx index a9331c9b628b..35ac50057786 100644 --- a/sw/source/filter/ww8/attributeoutputbase.hxx +++ b/sw/source/filter/ww8/attributeoutputbase.hxx @@ -373,7 +373,7 @@ public: virtual void StartContentControl(const SwFormatContentControl& /*rFormatContentControl*/) {} /// Output content control end. - virtual void EndContentControl() {} + virtual void EndContentControl( const SwTextNode& /*rNode*/, sal_Int32 /*nPos*/ ) {} protected: diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index f525aadf460f..9bf73a95ff9a 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -368,9 +368,16 @@ void DocxAttributeOutput::StartContentControl(const SwFormatContentControl& rFor m_pContentControl = rFormatContentControl.GetContentControl(); } -void DocxAttributeOutput::EndContentControl() +void DocxAttributeOutput::EndContentControl(const SwTextNode& rNode, sal_Int32 nPos) { - ++m_nCloseContentControlInThisRun; + if (rNode.GetTextAttrForCharAt(nPos, RES_TXTATR_FLYCNT) || rNode.GetTextAttrForCharAt(nPos, RES_TXTATR_CONTENTCONTROL)) + { + ++m_nCloseContentControlInPreviousRun; + } + else + { + ++m_nCloseContentControlInThisRun; + } } static void checkAndWriteFloatingTables(DocxAttributeOutput& rDocxAttributeOutput) @@ -2331,6 +2338,11 @@ void DocxAttributeOutput::WriteContentControlStart() return; } + if (m_bAnchorLinkedToNode) + { + return; + } + m_pSerializer->startElementNS(XML_w, XML_sdt); m_pSerializer->startElementNS(XML_w, XML_sdtPr); if (!m_pContentControl->GetPlaceholderDocPart().isEmpty()) diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 877e8ded562a..c25c4ad1225a 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -408,7 +408,7 @@ public: void StartContentControl(const SwFormatContentControl& rFormatContentControl) override; /// See AttributeOutputBase::EndContentControl(). - void EndContentControl() override; + void EndContentControl( const SwTextNode& rNode, sal_Int32 nPos ) override; private: /// Initialize the structures where we are going to collect some of the paragraph properties. diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx index 7bd841d727b5..4b42fc63e2e3 100644 --- a/sw/source/filter/ww8/wrtw8nds.cxx +++ b/sw/source/filter/ww8/wrtw8nds.cxx @@ -1407,7 +1407,7 @@ int SwWW8AttrIter::OutAttrWithRange(const SwTextNode& rNode, sal_Int32 nPos) pEnd = pHt->End(); if (nPos == *pEnd && nPos != pHt->GetStart()) { - m_rExport.AttrOutput().EndContentControl(); + m_rExport.AttrOutput().EndContentControl(rNode, nPos); --nRet; } break; diff --git a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx index b2e7f1058f88..6b568619785e 100644 --- a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx +++ b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx @@ -88,6 +88,36 @@ CPPUNIT_TEST_FIXTURE(Test, testSdtRunRichText) CPPUNIT_ASSERT_EQUAL(24.f, fCharheight); } +CPPUNIT_TEST_FIXTURE(Test, testSdtRunPlainText) +{ + // Given a document with a plain text inline/run SDT: + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "sdt-run-plain-text.docx"; + + // When loading the document: + getComponent() = loadFromDesktop(aURL); + + // Then make sure that the text inside the SDT is not rich: + uno::Reference<text::XTextDocument> xTextDocument(getComponent(), uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + uno::Reference<container::XEnumerationAccess> xPara(xParaEnum->nextElement(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xPortionEnum = xPara->createEnumeration(); + uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY); + OUString aTextPortionType; + xPortion->getPropertyValue("TextPortionType") >>= aTextPortionType; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: ContentControl + // - Actual : TextField + // i.e. the SDT was imported as a text field, not as a content control. + CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aTextPortionType); + uno::Reference<beans::XPropertySet> xContentControl; + xPortion->getPropertyValue("ContentControl") >>= xContentControl; + bool bPlainText{}; + xContentControl->getPropertyValue("PlainText") >>= bPlainText; + CPPUNIT_ASSERT(bPlainText); +} + CPPUNIT_TEST_FIXTURE(Test, testSdtRunCheckbox) { // Given a document with a checkbox inline/run SDT: diff --git a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-plain-text.docx b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-plain-text.docx Binary files differnew file mode 100644 index 000000000000..127d81fd966b --- /dev/null +++ b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-plain-text.docx diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index c3742cdbaa47..826404d640be 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -1067,6 +1067,7 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) break; case NS_ooxml::LN_CT_SdtBlock_sdtContent: case NS_ooxml::LN_CT_SdtRun_sdtContent: + m_pImpl->m_pSdtHelper->SetSdtType(nName); if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::unknown) { // Still not determined content type? and it is even not unsupported? Then it is plain text field @@ -1107,6 +1108,15 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) default: break; } + + if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText) + { + // The plain text && data binding case needs more work before it can be enabled. + if (m_pImpl->m_pSdtHelper->GetDataBindingPrefixMapping().isEmpty()) + { + m_pImpl->PopSdt(); + } + } } m_pImpl->SetSdt(false); @@ -2754,6 +2764,14 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) case NS_ooxml::LN_CT_SdtPr_text: { m_pImpl->m_pSdtHelper->setControlType(SdtControlType::plainText); + if (m_pImpl->m_pSdtHelper->GetSdtType() == NS_ooxml::LN_CT_SdtRun_sdtContent) + { + if (m_pImpl->m_pSdtHelper->GetDataBindingPrefixMapping().isEmpty()) + { + m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear(); + break; + } + } enableInteropGrabBag("ooxml:CT_SdtPr_text"); writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); if (pProperties) @@ -3753,7 +3771,7 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len) return; } } - else if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText) + else if ((m_pImpl->m_pSdtHelper->GetSdtType() != NS_ooxml::LN_CT_SdtRun_sdtContent || !m_pImpl->m_pSdtHelper->GetDataBindingPrefixMapping().isEmpty()) && m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText) { m_pImpl->m_pSdtHelper->getSdtTexts().append(sText); if (bNewLine) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index f37e7c2d9032..ba66d5c340f7 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -978,6 +978,11 @@ void DomainMapper_Impl::PopSdt() uno::Any(m_pSdtHelper->getDate().makeStringAndClear())); } + if (m_pSdtHelper->getControlType() == SdtControlType::plainText) + { + xContentControlProps->setPropertyValue("PlainText", uno::Any(true)); + } + xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); m_pSdtHelper->clear(); diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx index 8f5e809efdec..0301264bbaef 100644 --- a/writerfilter/source/dmapper/SdtHelper.cxx +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -443,6 +443,7 @@ void SdtHelper::clear() m_aDropDownItems.clear(); m_aDropDownDisplayTexts.clear(); setControlType(SdtControlType::unknown); + m_nSdtType = 0; m_sDataBindingPrefixMapping.clear(); m_sDataBindingXPath.clear(); m_sDataBindingStoreItemID.clear(); diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx index c817285095e7..441fa927b045 100644 --- a/writerfilter/source/dmapper/SdtHelper.hxx +++ b/writerfilter/source/dmapper/SdtHelper.hxx @@ -66,6 +66,7 @@ class SdtHelper final : public virtual SvRefBase std::vector<OUString> m_aDropDownDisplayTexts; /// Type of sdt control SdtControlType m_aControlType; + sal_uInt32 m_nSdtType = 0; /// Pieces of the default text -- currently used only by the dropdown control. OUStringBuffer m_aSdtTexts; /// Date ISO string contained in the w:date element, used by the date control. @@ -169,6 +170,9 @@ public: SdtControlType getControlType() { return m_aControlType; } void setControlType(SdtControlType aType) { m_aControlType = aType; } + void SetSdtType(sal_uInt32 nSdtType) { m_nSdtType = nSdtType; } + sal_uInt32 GetSdtType() const { return m_nSdtType; } + /// Create drop-down control from w:sdt's w:dropDownList. void createDropDownControl(); /// Create date control from w:sdt's w:date. |