sw/inc/doc.hxx                                    |    5 
 sw/qa/extras/ooxmlexport/ooxmlexport11.cxx        |   27 +++
 sw/qa/extras/ooxmlexport/ooxmlexport5.cxx         |    2 
 sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx     |    8 -
 sw/source/core/doc/doctxm.cxx                     |   17 +-
 sw/source/core/unocore/unoidx.cxx                 |    6 
 sw/source/filter/ww8/docxexport.cxx               |    5 
 sw/source/filter/ww8/wrtw8nds.cxx                 |   95 +++++++++++++
 sw/source/filter/ww8/wrtww8.hxx                   |    1 
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |  159 ++++++++++++++++++----
 writerfilter/source/dmapper/DomainMapper_Impl.hxx |    5 
 11 files changed, 290 insertions(+), 40 deletions(-)

New commits:
commit 1898bd6d5642ff81a09c2a9b6397ae145c3cfd8c
Author:     Serge Krot <serge.k...@cib.de>
AuthorDate: Thu Nov 22 10:05:47 2018 +0100
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Tue Jan 15 19:02:13 2019 +0100

    tdf#121561: sw: DOCX: add std/stdPr/stdContent around TOC
    
    During export into DOCX from ODT we need to do it
    because in this case the TOC title will be recognized
    inside MS Word as part of the TOC.
    
    Later we could add support of these keywords in LO import
    in order to detect TOC title from DOCX input.
    
    Added unit test for export.
    
    Reviewed-on: https://gerrit.libreoffice.org/63786
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de>
    
    sw: DOCX: recognize TOC title during import
    
    Change-Id: I7135e91dc04d4c0501e6074a046fc473e041f014
    fa4fb59858d61580f76e3d104aa4caa6b5902d1b
    Reviewed-on: https://gerrit.libreoffice.org/64735
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de>
    Reviewed-on: https://gerrit.libreoffice.org/66355
    Reviewed-by: Michael Stahl <michael.st...@cib.de>

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 452a7aa214de..dab81b32309a 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -917,6 +917,11 @@ public:
                                             const SfxItemSet* pSet = nullptr,
                                             bool bExpand = false,
                                     SwRootFrame const* pLayout = nullptr);
+    SwTOXBaseSection* InsertTableOf( const SwPaM& aPam,
+                                            const SwTOXBase& rTOX,
+                                            const SfxItemSet* pSet = nullptr,
+                                            bool bExpand = false,
+                                    SwRootFrame const* pLayout = nullptr );
     void              InsertTableOf( sal_uLong nSttNd, sal_uLong nEndNd,
                                             const SwTOXBase& rTOX,
                                             const SfxItemSet* pSet );
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index d7fd52d87b6d..f460e232b099 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -24,6 +24,7 @@
 #include <com/sun/star/graphic/XGraphic.hpp>
 #include <com/sun/star/text/RubyAdjust.hpp>
 #include <com/sun/star/text/RubyPosition.hpp>
+#include <com/sun/star/text/XDocumentIndex.hpp>
 
 
 #include <sfx2/docfile.hxx>
@@ -131,6 +132,32 @@ DECLARE_OOXMLEXPORT_TEST(testTdf121456_tabsOffset, 
"tdf121456_tabsOffset.odt")
     }
 }
 
+// tdf#121561: make sure w:sdt/w:sdtContent around TOC is written during 
ODT->DOCX conversion
+DECLARE_OOXMLEXPORT_TEST(testTdf121561_tocTitle, "tdf121456_tabsOffset.odt")
+{
+    xmlDocPtr pXmlDoc = parseExport();
+    if (!pXmlDoc)
+        return;
+
+    assertXPathContent(pXmlDoc, 
"/w:document/w:body/w:sdt/w:sdtContent/w:p/w:r/w:t", "Inhaltsverzeichnis");
+    assertXPathContent(pXmlDoc, 
"/w:document/w:body/w:sdt/w:sdtContent/w:p/w:r/w:instrText", " TOC \\f \\o 
\"1-9\" \\h");
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:sdt/w:sdtPr/w:docPartObj/w:docPartGallery", "val", "Table 
of Contents");
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:sdt/w:sdtPr/w:docPartObj/w:docPartUnique", 1);
+}
+
+DECLARE_OOXMLEXPORT_TEST(testTdf121561_tocTitleDocx, 
"tdf121456_tabsOffset.odt")
+{
+    xmlDocPtr pXmlDoc = parseExport();
+    if (!pXmlDoc)
+        return;
+
+    uno::Reference<text::XDocumentIndexesSupplier> xIndexSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xIndexes(xIndexSupplier->getDocumentIndexes( ), uno::UNO_QUERY);
+    uno::Reference<text::XDocumentIndex> xTOCIndex(xIndexes->getByIndex(0), 
uno::UNO_QUERY);
+
+    CPPUNIT_ASSERT_EQUAL(OUString("Inhaltsverzeichnis"), 
getProperty<OUString>(xTOCIndex, "Title"));
+}
+
 DECLARE_OOXMLEXPORT_TEST(testTdf106174_rtlParaAlign, 
"tdf106174_rtlParaAlign.docx")
 {
     CPPUNIT_ASSERT_EQUAL(sal_Int16(style::ParagraphAdjust_CENTER), 
getProperty<sal_Int16>(getParagraph(1), "ParaAdjust"));
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
index 268805695c08..8a98934dd484 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
@@ -695,7 +695,7 @@ DECLARE_OOXMLEXPORT_TEST(testFdo77129, "fdo77129.docx")
        return;
 
     // Data was lost from this paragraph.
-    assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[5]/w:r[1]/w:t", 
"Abstract");
+    assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[4]/w:r[1]/w:t", 
"Abstract");
 }
 
 DECLARE_OOXMLEXPORT_TEST(testfdo79969_xlsm, "fdo79969_xlsm.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
index 277f8b71ce22..84b38fc0a26a 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
@@ -143,7 +143,7 @@ DECLARE_OOXMLEXPORT_TEST(testFieldFlagO,"TOC_field_f.docx")
 
     // FIXME "p[2]" will have to be "p[1]", once the TOC import code is fixed
     // not to insert an empty paragraph before TOC.
-    assertXPathContent(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:instrText", " TOC \\z \\f \\o \"1-3\" \\u 
\\h");
+    assertXPathContent(pXmlDoc, 
"/w:document/w:body/w:sdt/w:sdtContent/w:p[1]/w:r[2]/w:instrText", " TOC \\z 
\\f \\o \"1-3\" \\u \\h");
 }
 
 DECLARE_OOXMLEXPORT_TEST(testTOCFlag_f, "toc_doc.docx")
@@ -160,7 +160,7 @@ DECLARE_OOXMLEXPORT_TEST(testTOCFlag_f, "toc_doc.docx")
 
     // FIXME "p[2]" will have to be "p[1]", once the TOC import code is fixed
     // not to insert an empty paragraph before TOC.
-    assertXPathContent(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:instrText", " TOC \\z \\o \"1-3\" \\u \\h");
+    assertXPathContent(pXmlDoc, 
"/w:document/w:body/w:sdt/w:sdtContent/w:p[1]/w:r[2]/w:instrText", " TOC \\z 
\\o \"1-3\" \\u \\h");
 }
 
 DECLARE_OOXMLEXPORT_TEST(testPreserveZfield,"preserve_Z_field_TOC.docx")
@@ -190,7 +190,7 @@ DECLARE_OOXMLEXPORT_TEST(testFieldFlagB,"TOC_field_b.docx")
 
     // FIXME "p[2]" will have to be "p[1]", once the TOC import code is fixed
     // not to insert an empty paragraph before TOC.
-    assertXPathContent(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:instrText", " TOC \\b \"bookmark111\" \\o 
\"1-9\" \\h");
+    assertXPathContent(pXmlDoc, 
"/w:document/w:body/w:sdt/w:sdtContent/w:p[1]/w:r[2]/w:instrText", " TOC \\b 
\"bookmark111\" \\o \"1-9\" \\h");
 }
 
 DECLARE_OOXMLEXPORT_TEST(testPreserveXfieldTOC, "PreserveXfieldTOC.docx")
@@ -448,7 +448,7 @@ DECLARE_OOXMLEXPORT_TEST(testFDO78654 , "fdo78654.docx")
         return;
     // In case of two "Hyperlink" tags in one paragraph and one of them
     // contains "PAGEREF" field then field end tag was missing from hyperlink.
-    assertXPath ( pXmlDoc, 
"/w:document/w:body/w:sdt/w:sdtContent/w:p[2]/w:hyperlink[3]/w:r[5]/w:fldChar", 
"fldCharType", "end" );
+    assertXPath ( pXmlDoc, 
"/w:document/w:body/w:p[2]/w:hyperlink[3]/w:r[5]/w:fldChar", "fldCharType", 
"end" );
 }
 
 
diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx
index b6248adf84db..05eb2de9295d 100644
--- a/sw/source/core/doc/doctxm.cxx
+++ b/sw/source/core/doc/doctxm.cxx
@@ -347,15 +347,24 @@ const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& 
rCurTOXMark,
 }
 
 SwTOXBaseSection* SwDoc::InsertTableOf( const SwPosition& rPos,
-                                                const SwTOXBase& rTOX,
-                                                const SfxItemSet* pSet,
-                                                bool bExpand,
+                                        const SwTOXBase& rTOX,
+                                        const SfxItemSet* pSet,
+                                        bool bExpand,
                                         SwRootFrame const*const pLayout)
 {
+    SwPaM aPam( rPos );
+    return InsertTableOf( aPam, rTOX, pSet, bExpand, pLayout );
+}
+
+SwTOXBaseSection* SwDoc::InsertTableOf( const SwPaM& aPam,
+                                        const SwTOXBase& rTOX,
+                                        const SfxItemSet* pSet,
+                                        bool bExpand,
+                                        SwRootFrame const*const pLayout )
+{
     GetIDocumentUndoRedo().StartUndo( SwUndoId::INSTOX, nullptr );
 
     OUString sSectNm = GetUniqueTOXBaseName( *rTOX.GetTOXType(), 
rTOX.GetTOXName() );
-    SwPaM aPam( rPos );
     SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
     SwTOXBaseSection *const pNewSection = dynamic_cast<SwTOXBaseSection *>(
         InsertSwSection( aPam, aSectionData, & rTOX, pSet, false ));
diff --git a/sw/source/core/unocore/unoidx.cxx 
b/sw/source/core/unocore/unoidx.cxx
index 59b51520dd1a..35deb15018b4 100644
--- a/sw/source/core/unocore/unoidx.cxx
+++ b/sw/source/core/unocore/unoidx.cxx
@@ -1339,10 +1339,6 @@ SwXDocumentIndex::attach(const uno::Reference< 
text::XTextRange > & xTextRange)
     }
 
     UnoActionContext aAction(pDoc);
-    if (aPam.HasMark())
-    {
-        pDoc->getIDocumentContentOperations().DeleteAndJoin(aPam);
-    }
 
     SwTOXBase & rTOXBase = m_pImpl->m_pProps->GetTOXBase();
     SwTOXType const*const pTOXType = rTOXBase.GetTOXType();
@@ -1353,7 +1349,7 @@ SwXDocumentIndex::attach(const uno::Reference< 
text::XTextRange > & xTextRange)
     }
     //TODO: apply Section attributes (columns and background)
     SwTOXBaseSection *const pTOX =
-        pDoc->InsertTableOf( *aPam.GetPoint(), rTOXBase, nullptr, false,
+        pDoc->InsertTableOf( aPam, rTOXBase, nullptr, false,
                 
m_pImpl->m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
 
     pDoc->SetTOXBaseName(*pTOX, m_pImpl->m_pProps->GetTOXBase().GetTOXName());
diff --git a/sw/source/filter/ww8/docxexport.cxx 
b/sw/source/filter/ww8/docxexport.cxx
index 91e485eaa980..9e4cd6c9fc6b 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -1431,6 +1431,11 @@ void DocxExport::WriteMainText()
     // setup the namespaces
     m_pDocumentFS->startElementNS( XML_w, XML_document, MainXmlNamespaces());
 
+    if ( getenv("SW_DEBUG_DOM") )
+    {
+        m_pDoc->dumpAsXml();
+    }
+
     // reset the incrementing linked-textboxes chain ID before re-saving.
     m_nLinkedTextboxesChainId=0;
     m_aLinkedTextboxesHelper.clear();
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx 
b/sw/source/filter/ww8/wrtw8nds.cxx
index bc64e2a4362c..6f87279690f0 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -92,6 +92,7 @@
 #include <oox/export/vmlexport.hxx>
 #include <sfx2/docfile.hxx>
 #include <sal/log.hxx>
+#include <comphelper/propertysequence.hxx>
 
 #include "sprmids.hxx"
 
@@ -3055,7 +3056,101 @@ void MSWordExportBase::OutputSectionNode( const 
SwSectionNode& rSectionNode )
         }
     }
     if ( TOX_CONTENT_SECTION == rSection.GetType() )
+    {
         m_bStartTOX = true;
+        UpdateTocSectionNodeProperties(rSectionNode);
+    }
+}
+
+// tdf#121561: During export of the ODT file with TOC inside into DOCX format,
+// the TOC title is being exported as regular paragraph. We should surround it
+// with <w:sdt><w:sdtPr><w:sdtContent> to make it (TOC title) recognizable
+// by MS Word as part of the TOC.
+void MSWordExportBase::UpdateTocSectionNodeProperties(const SwSectionNode& 
rSectionNode)
+{
+    // check section type
+    {
+        const SwSection& rSection = rSectionNode.GetSection();
+        if (TOX_CONTENT_SECTION != rSection.GetType())
+            return;
+
+        const SwTOXBase* pTOX = rSection.GetTOXBase();
+        if (pTOX)
+        {
+            TOXTypes type = pTOX->GetType();
+            if (type != TOXTypes::TOX_CONTENT)
+                return;
+        }
+    }
+
+    // get section node, skip toc-header node
+    const SwSectionNode* pSectNd = &rSectionNode;
+    {
+        SwNodeIndex aIdxNext( *pSectNd, 1 );
+        const SwNode& rNdNext = aIdxNext.GetNode();
+
+        if (rNdNext.IsSectionNode())
+        {
+            const SwSectionNode* pSectNdNext = static_cast<const 
SwSectionNode*>(&rNdNext);
+            if (TOX_HEADER_SECTION == pSectNdNext->GetSection().GetType() &&
+                pSectNdNext->StartOfSectionNode()->IsSectionNode())
+            {
+                pSectNd = pSectNdNext;
+            }
+        }
+    }
+
+    // get node of the first paragraph inside TOC
+    SwNodeIndex aIdxNext( *pSectNd, 1 );
+    const SwNode& rNdTocPara = aIdxNext.GetNode();
+    const SwContentNode* pNode = rNdTocPara.GetContentNode();
+    if (!pNode)
+        return;
+
+    // put required flags into grab bag of the first node in TOC
+    {
+        uno::Sequence<beans::PropertyValue> 
aDocPropertyValues(comphelper::InitPropertySequence(
+        {
+            {"ooxml:CT_SdtDocPart_docPartGallery", 
uno::makeAny(OUString("Table of Contents"))},
+            {"ooxml:CT_SdtDocPart_docPartUnique",  
uno::makeAny(OUString("true"))},
+        }));
+
+        uno::Sequence<beans::PropertyValue> 
aSdtPrPropertyValues(comphelper::InitPropertySequence(
+        {
+            {"ooxml:CT_SdtPr_docPartObj", uno::makeAny(aDocPropertyValues)},
+        }));
+
+        SfxGrabBagItem aGrabBag(RES_PARATR_GRABBAG);
+        aGrabBag.GetGrabBag()["SdtPr"] <<= aSdtPrPropertyValues;
+
+        // create temp attr set
+        SwAttrSet aSet(pNode->GetSwAttrSet());
+        aSet.Put(aGrabBag);
+
+        // set new attr to node
+        const_cast<SwContentNode*>(pNode)->SetAttr(aSet);
+    }
+
+    // set flag for the next node after TOC
+    // in order to indicate that std area has been finished
+    // see, DomainMapper::lcl_startParagraphGroup() for the same functionality 
during load
+    {
+        SwNodeIndex aEndTocNext( *rSectionNode.EndOfSectionNode(), 1 );
+        const SwNode& rEndTocNextNode = aEndTocNext.GetNode();
+        const SwContentNode* pNodeAfterToc = rEndTocNextNode.GetContentNode();
+        if (pNodeAfterToc)
+        {
+            SfxGrabBagItem aGrabBag(RES_PARATR_GRABBAG);
+            aGrabBag.GetGrabBag()["ParaSdtEndBefore"] <<= true;
+
+            // create temp attr set
+            SwAttrSet aSet(pNodeAfterToc->GetSwAttrSet());
+            aSet.Put(aGrabBag);
+
+            // set new attr to node
+            const_cast<SwContentNode*>(pNodeAfterToc)->SetAttr(aSet);
+        }
+    }
 }
 
 void WW8Export::AppendSection( const SwPageDesc *pPageDesc, const 
SwSectionFormat* pFormat, sal_uLong nLnNum )
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 0766d4df2c39..064055fd06c7 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -843,6 +843,7 @@ protected:
 
     /// Output SwSectionNode
     void OutputSectionNode( const SwSectionNode& );
+    static void UpdateTocSectionNodeProperties(const SwSectionNode& 
rSectionNode);
 
     virtual void AppendSection( const SwPageDesc *pPageDesc, const 
SwSectionFormat* pFormat, sal_uLong nLnNum ) = 0;
 
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index ae045d57e200..326fb0df9a89 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -514,6 +514,15 @@ void DomainMapper_Impl::SetParaSectpr(bool bParaSectpr)
 void DomainMapper_Impl::SetSdt(bool bSdt)
 {
     m_bSdt = bSdt;
+
+    if (m_bSdt)
+    {
+        m_xStdEntryStart = GetTopTextAppend()->getEnd();
+    }
+    else
+    {
+        m_xStdEntryStart = uno::Reference< text::XTextRange >();
+    }
 }
 
 
@@ -3663,6 +3672,42 @@ static uno::Sequence< beans::PropertyValues > 
lcl_createTOXLevelHyperlinks( bool
     return aNewLevel;
 }
 
+/// Returns title of the TOC placed in paragraph(s) before TOC field inside 
STD-frame
+OUString DomainMapper_Impl::extractTocTitle()
+{
+    if (!m_xStdEntryStart.is())
+        return OUString();
+
+    uno::Reference< text::XTextAppend > xTextAppend = 
m_aTextAppendStack.top().xTextAppend;
+    if(!xTextAppend.is())
+        return OUString();
+
+    // try-catch was added in the same way as inside appendTextSectionAfter()
+    try
+    {
+        uno::Reference< text::XParagraphCursor > xCursor( 
xTextAppend->createTextCursorByRange( m_xStdEntryStart ), uno::UNO_QUERY_THROW);
+        if (!xCursor.is())
+            return OUString();
+
+        //the cursor has been moved to the end of the paragraph because of the 
appendTextPortion() calls
+        xCursor->gotoStartOfParagraph( false );
+        if (m_aTextAppendStack.top().xInsertPosition.is())
+            xCursor->gotoRange( m_aTextAppendStack.top().xInsertPosition, true 
);
+        else
+            xCursor->gotoEnd( true );
+
+        //the paragraph after this new section is already inserted
+        xCursor->goLeft(1, true);
+
+        return xCursor->getString();
+    }
+    catch(const uno::Exception&)
+    {
+    }
+
+    return OUString();
+}
+
 void DomainMapper_Impl::handleToc
     (const FieldContextPtr& pContext,
     const OUString & sTOCServiceName)
@@ -3782,16 +3827,57 @@ void DomainMapper_Impl::handleToc
     if( !bFromOutline && !bFromEntries && sTemplate.isEmpty()  )
         bFromOutline = true;
 
+    const OUString aTocTitle = extractTocTitle();
+
+    if (m_xTextFactory.is() && ! m_aTextAppendStack.empty())
+    {
+        if (aTocTitle.isEmpty() || bTableOfFigures)
+        {
+            xTOC.set(
+                    m_xTextFactory->createInstance
+                    ( bTableOfFigures ?
+                      "com.sun.star.text.IllustrationsIndex"
+                      : sTOCServiceName),
+                    uno::UNO_QUERY_THROW);
+
+            OUString const sMarker("Y");
+            //insert index
+            uno::Reference< text::XTextContent > xToInsert( xTOC, 
uno::UNO_QUERY );
+            uno::Reference< text::XTextAppend >  xTextAppend = 
m_aTextAppendStack.top().xTextAppend;
+            if (xTextAppend.is())
+            {
+                uno::Reference< text::XTextCursor > xCrsr = 
xTextAppend->getText()->createTextCursor();
+                uno::Reference< text::XText > xText = xTextAppend->getText();
+                if(xCrsr.is() && xText.is())
+                {
+                    xCrsr->gotoEnd(false);
+                    xText->insertString(xCrsr, sMarker, false);
+                    xText->insertTextContent(uno::Reference< text::XTextRange 
>( xCrsr, uno::UNO_QUERY_THROW ), xToInsert, false);
+                    xTOCMarkerCursor = xCrsr;
+                }
+            }
+        }
+        else
+        {
+            // create TOC section
+            css::uno::Reference<css::text::XTextRange> 
xTextRangeEndOfTocHeader = GetTopTextAppend()->getEnd();
+            xTOC = createSectionForRange(m_xStdEntryStart, 
xTextRangeEndOfTocHeader, sTOCServiceName, false);
+
+            // init [xTOCMarkerCursor]
+            uno::Reference< text::XTextAppend >  xTextAppend = 
m_aTextAppendStack.top().xTextAppend;
+            uno::Reference< text::XText > xText = xTextAppend->getText();
+            uno::Reference< text::XTextCursor > xCrsr = 
xText->createTextCursor();
+            xTOCMarkerCursor = xCrsr;
+
+            // create header of the TOC with the TOC title inside
+            const OUString aObjectType("com.sun.star.text.IndexHeaderSection");
+            uno::Reference<beans::XPropertySet> xIfc = 
createSectionForRange(m_xStdEntryStart, xTextRangeEndOfTocHeader, aObjectType, 
true);
+        }
+    }
 
-    if (m_xTextFactory.is())
-        xTOC.set(
-                m_xTextFactory->createInstance
-                ( bTableOfFigures ?
-                  "com.sun.star.text.IllustrationsIndex"
-                  : sTOCServiceName),
-                uno::UNO_QUERY_THROW);
     if (xTOC.is())
-        xTOC->setPropertyValue(getPropertyName( PROP_TITLE ), 
uno::makeAny(OUString()));
+        xTOC->setPropertyValue(getPropertyName( PROP_TITLE ), 
uno::makeAny(aTocTitle));
+
     if (!aBookmarkName.isEmpty())
         xTOC->setPropertyValue(getPropertyName(PROP_TOC_BOOKMARK), 
uno::makeAny(aBookmarkName));
     if( !bTableOfFigures && xTOC.is() )
@@ -3881,27 +3967,45 @@ void DomainMapper_Impl::handleToc
     }
     pContext->SetTOC( xTOC );
     m_bParaHadField = false;
+}
 
-    if (m_aTextAppendStack.empty())
-        return;
+uno::Reference<beans::XPropertySet> DomainMapper_Impl::createSectionForRange(
+    uno::Reference< css::text::XTextRange > xStart,
+    uno::Reference< css::text::XTextRange > xEnd,
+    const OUString & sObjectType,
+    bool stepLeft)
+{
+    if (!xStart.is())
+        return uno::Reference<beans::XPropertySet>();
+    if (!xEnd.is())
+        return uno::Reference<beans::XPropertySet>();
 
-    OUString const sMarker("Y");
-    //insert index
-    uno::Reference< text::XTextContent > xToInsert( xTOC, uno::UNO_QUERY );
+    uno::Reference< beans::XPropertySet > xRet;
+    if (m_aTextAppendStack.empty())
+        return xRet;
     uno::Reference< text::XTextAppend >  xTextAppend = 
m_aTextAppendStack.top().xTextAppend;
-    if (xTextAppend.is())
+    if(xTextAppend.is())
     {
-        uno::Reference< text::XTextCursor > xCrsr = 
xTextAppend->getText()->createTextCursor();
-
-        uno::Reference< text::XText > xText = xTextAppend->getText();
-        if(xCrsr.is() && xText.is())
+        try
+        {
+            uno::Reference< text::XParagraphCursor > xCursor(
+                xTextAppend->createTextCursorByRange( xStart ), 
uno::UNO_QUERY_THROW);
+            //the cursor has been moved to the end of the paragraph because of 
the appendTextPortion() calls
+            xCursor->gotoStartOfParagraph( false );
+            xCursor->gotoRange( xEnd, true );
+            //the paragraph after this new section is already inserted
+            if (stepLeft)
+                xCursor->goLeft(1, true);
+            uno::Reference< text::XTextContent > xSection( 
m_xTextFactory->createInstance(sObjectType), uno::UNO_QUERY_THROW );
+            xSection->attach( uno::Reference< text::XTextRange >( xCursor, 
uno::UNO_QUERY_THROW) );
+            xRet.set(xSection, uno::UNO_QUERY );
+        }
+        catch(const uno::Exception&)
         {
-            xCrsr->gotoEnd(false);
-            xText->insertString(xCrsr, sMarker, false);
-            xText->insertTextContent(uno::Reference< text::XTextRange >( 
xCrsr, uno::UNO_QUERY_THROW ), xToInsert, false);
-            xTOCMarkerCursor = xCrsr;
         }
     }
+
+    return xRet;
 }
 
 void DomainMapper_Impl::handleBibliography
@@ -4988,10 +5092,13 @@ void DomainMapper_Impl::PopFieldContext()
                         }
                         else
                         {
-                            xTOCMarkerCursor->goLeft(1,true);
-                            xTOCMarkerCursor->setString(OUString());
-                            xTOCMarkerCursor->goLeft(1,true);
-                            xTOCMarkerCursor->setString(OUString());
+                            if (!m_xStdEntryStart.is())
+                            {
+                                xTOCMarkerCursor->goLeft(1,true);
+                                xTOCMarkerCursor->setString(OUString());
+                                xTOCMarkerCursor->goLeft(1,true);
+                                xTOCMarkerCursor->setString(OUString());
+                            }
                         }
                     }
                     if (m_bStartedTOC || m_bStartIndex || m_bStartBibliography)
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 89deb65f1b56..02f029a4732c 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -542,6 +542,7 @@ private:
     SmartTagHandler m_aSmartTagHandler;
 
     css::uno::Reference<css::text::XTextRange> m_xGlossaryEntryStart;
+    css::uno::Reference<css::text::XTextRange> m_xStdEntryStart;
 
 public:
     css::uno::Reference<css::text::XTextRange> m_xInsertTextRange;
@@ -792,6 +793,10 @@ public:
     /// The end of field is reached (cFieldEnd appeared) - the command might 
still be open.
     void PopFieldContext();
 
+    /// Returns title of the TOC placed in paragraph(s) before TOC field 
inside STD-frame
+    OUString extractTocTitle();
+    css::uno::Reference<css::beans::XPropertySet> 
createSectionForRange(css::uno::Reference< css::text::XTextRange > xStart, 
css::uno::Reference< css::text::XTextRange > xEnd, const OUString & 
sObjectType, bool stepLeft);
+
     void SetBookmarkName( const OUString& rBookmarkName );
     void StartOrEndBookmark( const OUString& rId );
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to