[Libreoffice-commits] core.git: 2 commits - sw/qa sw/source writerfilter/source

Miklos Vajna vmiklos at collabora.co.uk
Thu Jul 10 01:50:23 PDT 2014


 sw/qa/extras/ooxmlexport/data/sdt-2-run.docx      |binary
 sw/qa/extras/ooxmlexport/ooxmlexport.cxx          |   10 ++++
 sw/source/filter/ww8/docxattributeoutput.cxx      |   49 ++++++++++++++++++----
 sw/source/filter/ww8/docxattributeoutput.hxx      |    8 +++
 writerfilter/source/dmapper/DomainMapper.cxx      |   10 ++++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   10 ++++
 writerfilter/source/dmapper/DomainMapper_Impl.hxx |    6 ++
 writerfilter/source/dmapper/PropertyIds.cxx       |    1 
 writerfilter/source/dmapper/PropertyIds.hxx       |    1 
 9 files changed, 87 insertions(+), 8 deletions(-)

New commits:
commit 0a90643947e3767fd5d76784df54d7ee25e6793d
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Jul 10 10:19:18 2014 +0200

    DOCX export: allow multiple runs in w:sdt tags
    
    Change-Id: Iec053f92ebdfb89ddd311e190609c9dd1a1c64ef

diff --git a/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx b/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx
new file mode 100644
index 0000000..6063ebc
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/sdt-2-run.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index 494b8a8..d534ed9 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -3739,6 +3739,16 @@ DECLARE_OOXMLEXPORT_TEST(test2colHeader, "2col-header.docx")
     CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xPageStyle, "HeaderIsOn"));
 }
 
+DECLARE_OOXMLEXPORT_TEST(testSdt2Run, "sdt-2-run.docx")
+{
+    xmlDocPtr pXmlDoc = parseExport();
+    if (!pXmlDoc)
+        return;
+
+    // The problem was that <w:sdt> was closed after "first", not after "second", so the second assert failed.
+    assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r[1]/w:t", "first");
+    assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r[2]/w:t", "second");
+}
 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 937a337..85c45da 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -508,9 +508,16 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT
         m_nHyperLinkCount = 0;
     }
 
+    if (m_bStartedCharSdt)
+    {
+        // Run-level SDT still open? Close it now.
+        EndSdtBlock();
+        m_bStartedCharSdt = false;
+    }
+
     m_pSerializer->endElementNS( XML_w, XML_p );
     if( !m_bAnchorLinkedToNode )
-        WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs );
+        WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs, /*bPara=*/true );
     else
     {
         //These should be written out to the actual Node and not to the anchor.
@@ -549,7 +556,10 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT
 
 }
 
-void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparser::FastAttributeList* &pSdtPrTokenChildren, ::sax_fastparser::FastAttributeList* &pSdtPrDataBindingAttrs )
+void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken,
+                                         ::sax_fastparser::FastAttributeList*& pSdtPrTokenChildren,
+                                         ::sax_fastparser::FastAttributeList*& pSdtPrDataBindingAttrs,
+                                         bool bPara )
 {
     if( nSdtPrToken > 0 || pSdtPrDataBindingAttrs )
     {
@@ -597,8 +607,11 @@ void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparse
         m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
 
         // write the ending tags after the paragraph
-        m_pSerializer->endElementNS( XML_w, XML_sdtContent );
-        m_pSerializer->endElementNS( XML_w, XML_sdt );
+        if (bPara)
+            EndSdtBlock();
+        else
+            // Support multiple runs inside a run-evel SDT: don't close the SDT block yet.
+            m_bStartedCharSdt = true;
 
         // clear sdt status
         nSdtPrToken = 0;
@@ -611,6 +624,12 @@ void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparse
     }
 }
 
+void DocxAttributeOutput::EndSdtBlock()
+{
+    m_pSerializer->endElementNS( XML_w, XML_sdtContent );
+    m_pSerializer->endElementNS( XML_w, XML_sdt );
+}
+
 void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph )
 {
     if ( pInner.get() )
@@ -945,6 +964,14 @@ void DocxAttributeOutput::EndRun()
     // before "postponed run start")
     m_pSerializer->mark(); // let's call it "actual run start"
 
+    if (m_bEndCharSdt)
+    {
+        // This is the common case: "close sdt before the current run" was requrested by the next run.
+        EndSdtBlock();
+        m_bEndCharSdt = false;
+        m_bStartedCharSdt = false;
+    }
+
     if ( m_closeHyperlinkInPreviousRun )
     {
         if ( m_startedHyperlink )
@@ -1052,9 +1079,10 @@ void DocxAttributeOutput::EndRun()
     // if there is some redlining in the document, output it
     EndRedline( m_pRedlineData );
 
-    // enclose in a sdt block, if necessary
-    if ( !m_bAnchorLinkedToNode )
-        WriteSdtBlock( m_nRunSdtPrToken, m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs );
+    // enclose in a sdt block, if necessary: if one is already started, then don't do it for now
+    // (so on export sdt blocks are never nested ATM)
+    if ( !m_bAnchorLinkedToNode && !m_bStartedCharSdt )
+        WriteSdtBlock( m_nRunSdtPrToken, m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs, /*bPara=*/false );
     else
     {
         //These should be written out to the actual Node and not to the anchor.
@@ -7693,6 +7721,11 @@ void DocxAttributeOutput::CharGrabBag( const SfxGrabBagItem& rItem )
             m_aTextEffectsGrabBag.realloc(m_aTextEffectsGrabBag.getLength() + 1);
             m_aTextEffectsGrabBag[aLength] = aPropertyValue;
         }
+        else if (i->first == "SdtEndBefore")
+        {
+            if (m_bStartedCharSdt)
+                m_bEndCharSdt = true;
+        }
         else if (i->first == "SdtPr")
         {
             uno::Sequence<beans::PropertyValue> aGrabBagSdt =
@@ -7766,6 +7799,8 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri
       m_pSectionSpacingAttrList( NULL ),
       m_pParagraphSpacingAttrList( NULL ),
       m_pHyperlinkAttrList( NULL ),
+      m_bEndCharSdt(false),
+      m_bStartedCharSdt(false),
       m_pColorAttrList( NULL ),
       m_pBackgroundAttrList( NULL ),
       m_endPageRef( false ),
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 17bc31c..34362f3 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -691,7 +691,9 @@ private:
     void WritePostponedDMLDrawing();
     void WritePostponedCustomShape();
 
-    void WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparser::FastAttributeList* &pSdtPrTokenChildren, ::sax_fastparser::FastAttributeList* &pSdtPrDataBindingAttrs );
+    void WriteSdtBlock( sal_Int32& nSdtPrToken, ::sax_fastparser::FastAttributeList* &pSdtPrTokenChildren, ::sax_fastparser::FastAttributeList* &pSdtPrDataBindingAttrs, bool bPara );
+    /// Closes a currently open SDT block.
+    void EndSdtBlock();
 
     void StartField_Impl( FieldInfos& rInfos, bool bWriteRun = false );
     void DoWriteCmd( const OUString& rCmd );
@@ -706,6 +708,10 @@ private:
     ::sax_fastparser::FastAttributeList *m_pSectionSpacingAttrList;
     ::sax_fastparser::FastAttributeList *m_pParagraphSpacingAttrList;
     ::sax_fastparser::FastAttributeList *m_pHyperlinkAttrList;
+    /// If the current SDT around runs should be ended before the current run.
+    bool m_bEndCharSdt;
+    /// If an SDT around runs is currently open.
+    bool m_bStartedCharSdt;
     /// Attributes of the run color
     ::sax_fastparser::FastAttributeList *m_pColorAttrList;
     /// Attributes of the paragraph background
commit 7ab5fcfbda1898f862d599e4351db2da92027867
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Jul 10 09:53:44 2014 +0200

    DOCX import: handle exact end of w:sdt tags
    
    Change-Id: I5b6158281782fc07ffe0eef73ab94345563498f9

diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 98e14d7..f6a91fb 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -902,6 +902,11 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
         break;
         case NS_ooxml::LN_CT_SdtBlock_sdtEndContent:
             m_pImpl->SetSdt(false);
+
+            // It's not possible to insert the relevant property to the character context here:
+            // the previous, already sent character context may be still active, so the property would be lost.
+            m_pImpl->setSdtEndDeferred(true);
+
             if (!m_pImpl->m_pSdtHelper->getDropDownItems().empty())
                 m_pImpl->m_pSdtHelper->createDropDownControl();
         break;
@@ -2653,6 +2658,11 @@ void DomainMapper::lcl_startCharacterGroup()
     if (m_pImpl->m_bFrameBtLr)
         // No support for this in core, work around by char rotation, as we do so for table cells already.
         m_pImpl->GetTopContext()->Insert(PROP_CHAR_ROTATION, uno::makeAny(sal_Int16(900)));
+    if (m_pImpl->isSdtEndDeferred())
+    {
+        m_pImpl->GetTopContext()->Insert(PROP_SDT_END_BEFORE, uno::makeAny(true), true, CHAR_GRAB_BAG);
+        m_pImpl->setSdtEndDeferred(false);
+    }
 }
 
 void DomainMapper::lcl_endCharacterGroup()
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 9457568..edd30e5 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -160,6 +160,7 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bIsFirstSection( true ),
         m_bIsColumnBreakDeferred( false ),
         m_bIsPageBreakDeferred( false ),
+        m_bSdtEndDeferred(false),
         m_bStartTOC(false),
         m_bStartTOCHeaderFooter(false),
         m_bStartedTOC(false),
@@ -706,6 +707,15 @@ void DomainMapper_Impl::clearDeferredBreaks()
     m_bIsPageBreakDeferred = false;
 }
 
+void DomainMapper_Impl::setSdtEndDeferred(bool bSdtEndDeferred)
+{
+    m_bSdtEndDeferred = bSdtEndDeferred;
+}
+
+bool DomainMapper_Impl::isSdtEndDeferred()
+{
+    return m_bSdtEndDeferred;
+}
 
 void lcl_MoveBorderPropertiesToFrame(comphelper::SequenceAsHashMap& rFrameProperties,
     uno::Reference<text::XTextRange> xStartTextRange,
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 778d7b0..43bedc8 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -319,6 +319,8 @@ private:
     bool                                                                            m_bIsFirstSection;
     bool                                                                            m_bIsColumnBreakDeferred;
     bool                                                                            m_bIsPageBreakDeferred;
+    /// If we want to set "sdt end" on the next character contet.
+    bool                                                                            m_bSdtEndDeferred;
     bool                                                                            m_bStartTOC;
     bool                                                                            m_bStartTOCHeaderFooter;
     /// If we got any text that is the pre-rendered result of the TOC field.
@@ -489,6 +491,10 @@ public:
     bool isBreakDeferred( BreakType deferredBreakType );
     void clearDeferredBreaks();
     void clearDeferredBreak(BreakType deferredBreakType);
+
+    void setSdtEndDeferred(bool bSdtEndDeferred);
+    bool isSdtEndDeferred();
+
     void finishParagraph( PropertyMapPtr pPropertyMap );
     void appendTextPortion( const OUString& rString, PropertyMapPtr pPropertyMap );
     void appendTextContent( const ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextContent >,
diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx
index e5b9918..8c1e42b 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -393,6 +393,7 @@ OUString PropertyNameSupplier::GetName( PropertyIds eId ) const
             case PROP_TABLE_INTEROP_GRAB_BAG         :   sName = "TableInteropGrabBag"; break;
             case PROP_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING : sName = "ApplyParagraphMarkFormatToNumbering"; break;
             case PROP_CELL_DIRECTION: sName = "CellDirection"; break;
+            case PROP_SDT_END_BEFORE: sName = "SdtEndBefore"; break;
         }
         ::std::pair<PropertyNameMap_t::iterator,bool> aInsertIt =
                 m_pImpl->aNameMap.insert( PropertyNameMap_t::value_type( eId, sName ));
diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx
index f1543be..635df35 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -365,6 +365,7 @@ enum PropertyIds
         ,PROP_INDEX_ENTRY_TYPE
         ,PROP_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING
         ,PROP_CELL_DIRECTION
+        ,PROP_SDT_END_BEFORE
     };
 struct PropertyNameSupplier_Impl;
 class PropertyNameSupplier


More information about the Libreoffice-commits mailing list