diff --git a/include/xmloff/txtparae.hxx b/include/xmloff/txtparae.hxx
index c003909795dd..c8772907045b 100644
--- a/include/xmloff/txtparae.hxx
+++ b/include/xmloff/txtparae.hxx
@@ -114,6 +114,8 @@ class XMLOFF_DLLPUBLIC XMLTextParagraphExport : public XMLStyleExport
struct DocumentListNodes;
std::unique_ptr mpDocumentListNodes;
+ std::vector maDocumentNodeOrder;
+ bool bInDocumentNodeOrderCollection = false;
o3tl::sorted_vector> maFrameRecurseGuard;
o3tl::sorted_vector> maShapeRecurseGuard;
@@ -472,9 +474,7 @@ public:
exportText( rText, rBaseSection, true, bIsProgress, true/*bExportParagraph*/ );
}
- // It the model implements the xAutoStylesSupplier interface, the automatic
- // styles can exported without iterating over the text portions
- void collectTextAutoStylesOptimized( bool bIsProgress );
+ void collectTextAutoStylesAndNodeExportOrder(bool bIsProgress);
// This method exports all automatic styles that have been collected.
void exportTextAutoStyles();
@@ -540,6 +540,7 @@ public:
void PopTextListsHelper();
private:
+ void RecordNodeIndex(const css::uno::Reference& xTextContent);
bool ShouldSkipListId(const css::uno::Reference& xTextContent);
bool ExportListId() const;
diff --git a/sw/qa/extras/htmlexport/xhtmlexport.cxx b/sw/qa/extras/htmlexport/xhtmlexport.cxx
index 8527e66e024c..70fa1738d290 100644
--- a/sw/qa/extras/htmlexport/xhtmlexport.cxx
+++ b/sw/qa/extras/htmlexport/xhtmlexport.cxx
@@ -178,9 +178,9 @@ CPPUNIT_TEST_FIXTURE(XHtmlExportTest, testTdf66305)
sal_uInt64 nLength = pStream->TellEnd();
OString aStream(read_uInt8s_ToOString(*pStream, nLength));
CPPUNIT_ASSERT(
- aStream.indexOf("Introduction
")
+ "class=\"paragraph-P6\">
")
!= -1);
}
diff --git a/sw/qa/extras/odfexport/data/tdf160253_ordinary_numbering.fodt b/sw/qa/extras/odfexport/data/tdf160253_ordinary_numbering.fodt
new file mode 100644
index 000000000000..ca5c1128d1c0
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/tdf160253_ordinary_numbering.fodt
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a
+
+
+ b
+
+
+ ci
+
+
+ xyz
+
+
+
+
+ d
+
+
+
+
+
\ No newline at end of file
diff --git a/sw/qa/extras/odfexport/data/tdf160253_outline_numbering.fodt b/sw/qa/extras/odfexport/data/tdf160253_outline_numbering.fodt
new file mode 100644
index 000000000000..2eddd6dd4593
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/tdf160253_outline_numbering.fodt
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ foo
+ xyzi
+ abc
+ bar
+
+
+
\ No newline at end of file
diff --git a/sw/qa/extras/odfexport/odfexport2.cxx b/sw/qa/extras/odfexport/odfexport2.cxx
index 4523e0551e18..4432d9eb1623 100644
--- a/sw/qa/extras/odfexport/odfexport2.cxx
+++ b/sw/qa/extras/odfexport/odfexport2.cxx
@@ -115,10 +115,14 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf106733)
CPPUNIT_ASSERT_EQUAL(1, getPages());
xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
+ OUString autostyle = getXPath(pXmlDoc, "//office:body/office:text/text:p[2]/text:span"_ostr,
+ "style-name"_ostr);
+ OString autostyle_span_xpath = "//style:style[@style:name='" + autostyle.toUtf8() + "']";
+
// keep fo:hyphenate="false" in direct formatting
assertXPath(
pXmlDoc,
- "//style:style[@style:name='T3']/style:text-properties"_ostr,
+ autostyle_span_xpath + "/style:text-properties",
"hyphenate"_ostr, "false");
// keep fo:hyphenate="false" in character style
@@ -1250,9 +1254,13 @@ CPPUNIT_TEST_FIXTURE(Test, testParagraphMarkerMarkupRoundtrip)
loadAndReload("ParagraphMarkerMarkup.fodt");
// Test that the markup stays at save-and-reload
xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
- assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p"_ostr, "marker-style-name"_ostr, "T2");
- assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name='T2']/style:text-properties"_ostr, "font-size"_ostr, "9pt");
- assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name='T2']/style:text-properties"_ostr, "color"_ostr, "#ff0000");
+ OUString autostyle
+ = getXPath(pXmlDoc, "//office:body/office:text/text:p"_ostr, "marker-style-name"_ostr);
+ OString style_text_properties
+ = "/office:document-content/office:automatic-styles/style:style[@style:name='"
+ + autostyle.toUtf8() + "']/style:text-properties";
+ assertXPath(pXmlDoc, style_text_properties, "font-size"_ostr, "9pt");
+ assertXPath(pXmlDoc, style_text_properties, "color"_ostr, "#ff0000");
}
CPPUNIT_TEST_FIXTURE(Test, testCommentStyles)
@@ -1529,6 +1537,46 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf160700)
assertXPath(pXmlDoc, "//office:text/text:list/text:list-item/text:p/text:bookmark"_ostr);
}
+CPPUNIT_TEST_FIXTURE(Test, testTdf160253_ordinary_numbering)
+{
+ // Given a document with a list, and an out-of-the-list paragraph in the middle, having an
+ // endnote, which has a paragraph in another list.
+ // Before the fix, this already failed with
+ // Error: "list2916587379" is referenced by an IDREF, but not defined.
+ loadAndReload("tdf160253_ordinary_numbering.fodt");
+
+ // Make sure that the fourth paragraph has correct number - it was "1." before the fix
+ CPPUNIT_ASSERT_EQUAL(u"3."_ustr,
+ getProperty(getParagraph(4), u"ListLabelString"_ustr));
+
+ // Make sure that we emit an identifier for the first list, and refer to it in the continuation
+ xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
+ // This failed before the fix, because 'xml:id' attribute wasn't emitted
+ OUString firstListId
+ = getXPath(pXmlDoc, "//office:body/office:text/text:list[1]"_ostr, "id"_ostr);
+ CPPUNIT_ASSERT(!firstListId.isEmpty());
+ assertXPath(pXmlDoc, "//office:body/office:text/text:list[2]"_ostr, "continue-list"_ostr,
+ firstListId);
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testTdf160253_outline_numbering)
+{
+ // Given a document with an outline (chapter) numbering, and a paragraph in the middle, having
+ // an endnote, which has a paragraph in a list.
+ // Before the fix, this already failed with
+ // Error: "list2916587379" is referenced by an IDREF, but not defined.
+ loadAndReload("tdf160253_outline_numbering.fodt");
+
+ // Make sure that the third paragraph has correct number - it was "1" before the fix
+ CPPUNIT_ASSERT_EQUAL(u"2"_ustr,
+ getProperty(getParagraph(3), u"ListLabelString"_ustr));
+
+ // The difference with the ordinary numbering is that for outline numbering, the list element
+ // isn't really necessary. It is a TODO to fix the output, and not export the list.
+ // xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
+ // assertXPath(pXmlDoc, "//office:body/office:text/text:list"_ostr, 0);
+}
+
} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/text/txtfld.cxx b/sw/source/core/text/txtfld.cxx
index 55e439096f3d..e522f4e08929 100644
--- a/sw/source/core/text/txtfld.cxx
+++ b/sw/source/core/text/txtfld.cxx
@@ -657,28 +657,6 @@ SwNumberPortion *SwTextFormatter::NewNumberPortion( SwTextFormatInfo &rInf ) con
// Build a new numbering font basing on the current paragraph font:
std::unique_ptr pNumFnt(new SwFont( &rInf.GetCharAttr(), pIDSA ));
- const SwTextNode& rTextNode = *rInf.GetTextFrame()->GetTextNodeForParaProps();
- if (const SwpHints* pHints = rTextNode.GetpSwpHints())
- {
- // Also look for an empty character hint that sits at the paragraph end:
- for (size_t i = 0; i < pHints->Count(); ++i)
- {
- const SwTextAttr* pHint = pHints->GetSortedByEnd(i);
- if (pHint->Which() == RES_TXTATR_AUTOFMT && pHint->GetEnd()
- && pHint->GetStart() == *pHint->GetEnd()
- && pHint->GetStart() == rTextNode.GetText().getLength())
- {
- std::shared_ptr pSet
- = pHint->GetAutoFormat().GetStyleHandle();
- if (pSet)
- {
- pNumFnt->SetDiffFnt(pSet.get(), pIDSA);
- break;
- }
- }
- }
- }
-
// #i53199#
if ( !pIDSA->get(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) )
{
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index a329b73ca7fb..bbdc70048c01 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -2477,7 +2477,7 @@ void wwSectionManager::SetHdFt(wwSection const &rSection, int nSect,
}
-void SwWW8ImplReader::AppendTextNode(SwPosition& rPos)
+void SwWW8ImplReader::FinalizeTextNode(SwPosition& rPos, bool bAddNew)
{
SwTextNode* pText = m_pPaM->GetPointNode().GetTextNode();
@@ -2564,7 +2564,8 @@ void SwWW8ImplReader::AppendTextNode(SwPosition& rPos)
m_bFirstPara = false;
- m_rDoc.getIDocumentContentOperations().AppendTextNode(rPos);
+ if (bAddNew)
+ m_rDoc.getIDocumentContentOperations().AppendTextNode(rPos);
// We can flush all anchored graphics at the end of a paragraph.
m_xAnchorStck->Flush();
@@ -3480,13 +3481,13 @@ void SwWW8ImplReader::simpleAddTextToParagraph(std::u16string_view aAddString)
else
{
m_rDoc.getIDocumentContentOperations().InsertString(*m_pPaM, addString.copy(0, nCharsLeft));
- AppendTextNode(*m_pPaM->GetPoint());
+ FinalizeTextNode(*m_pPaM->GetPoint());
m_rDoc.getIDocumentContentOperations().InsertString(*m_pPaM, addString.copy(nCharsLeft));
}
}
else
{
- AppendTextNode(*m_pPaM->GetPoint());
+ FinalizeTextNode(*m_pPaM->GetPoint());
m_rDoc.getIDocumentContentOperations().InsertString(*m_pPaM, addString);
}
@@ -3557,7 +3558,7 @@ bool SwWW8ImplReader::HandlePageBreakChar()
&& (m_bFirstPara || m_bFirstParaOfPage))
{
IsTemp = false;
- AppendTextNode(*m_pPaM->GetPoint());
+ FinalizeTextNode(*m_pPaM->GetPoint());
pTemp->SetAttr(*GetDfltAttr(RES_PARATR_NUMRULE));
}
@@ -3636,7 +3637,7 @@ bool SwWW8ImplReader::ReadChar(tools::Long nPosCp, tools::Long nCpOfs)
// Always insert a txtnode for a column break, e.g. ##
SwContentNode *pCntNd=m_pPaM->GetPointContentNode();
if (pCntNd!=nullptr && pCntNd->Len()>0) // if par is empty not break is needed
- AppendTextNode(*m_pPaM->GetPoint());
+ FinalizeTextNode(*m_pPaM->GetPoint());
m_rDoc.getIDocumentContentOperations().InsertPoolItem(*m_pPaM, SvxFormatBreakItem(SvxBreak::ColumnBefore, RES_BREAK));
}
break;
@@ -4105,7 +4106,7 @@ bool SwWW8ImplReader::ReadText(WW8_CP nStartCp, WW8_CP nTextLen, ManTypes nType)
}
if (bSplit)
{
- AppendTextNode(*m_pPaM->GetPoint());
+ FinalizeTextNode(*m_pPaM->GetPoint());
}
}
@@ -4220,7 +4221,7 @@ bool SwWW8ImplReader::ReadText(WW8_CP nStartCp, WW8_CP nTextLen, ManTypes nType)
// to insert a text node.
if (!bStartLine && !m_xAnchorStck->empty())
{
- AppendTextNode(*m_pPaM->GetPoint());
+ FinalizeTextNode(*m_pPaM->GetPoint());
}
m_rDoc.getIDocumentContentOperations().InsertPoolItem(*m_pPaM,
SvxFormatBreakItem(SvxBreak::PageBefore, RES_BREAK));
@@ -4233,7 +4234,7 @@ bool SwWW8ImplReader::ReadText(WW8_CP nStartCp, WW8_CP nTextLen, ManTypes nType)
m_xPreviousNode.reset();
if (m_pPaM->GetPoint()->GetContentIndex())
- AppendTextNode(*m_pPaM->GetPoint());
+ FinalizeTextNode(*m_pPaM->GetPoint());
if (!m_bInHyperlink)
bJoined = JoinNode(*m_pPaM);
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index caaafc2b122a..6f0c260f1966 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -1421,7 +1421,7 @@ private:
bool StyleExists(unsigned int nColl) const { return (nColl < m_vColl.size()); }
SwWW8StyInf *GetStyle(sal_uInt16 nColl) const;
- void AppendTextNode(SwPosition& rPos);
+ void FinalizeTextNode(SwPosition& rPos, bool bAddNew = true);
void Read_HdFt(int nSect, const SwPageDesc *pPrev,
const wwSection &rSection);
diff --git a/sw/source/filter/ww8/ww8par2.cxx b/sw/source/filter/ww8/ww8par2.cxx
index 061144045b12..c1e80efd2d38 100644
--- a/sw/source/filter/ww8/ww8par2.cxx
+++ b/sw/source/filter/ww8/ww8par2.cxx
@@ -2402,7 +2402,7 @@ void WW8TabDesc::CreateSwTable()
}
if (bInsNode)
- m_pIo->AppendTextNode(*pPoint);
+ m_pIo->FinalizeTextNode(*pPoint);
m_xTmpPos = m_pIo->m_rDoc.CreateUnoCursor(*m_pIo->m_pPaM->GetPoint());
@@ -3497,6 +3497,8 @@ bool SwWW8ImplReader::StartTable(WW8_CP nStartCp)
void SwWW8ImplReader::TabCellEnd()
{
+ FinalizeTextNode(*m_pPaM->GetPoint(), false);
+
if (m_nInTable && m_xTableDesc)
m_xTableDesc->TableCellEnd();
diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index 47cb7e788223..f34f5996caa9 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -3477,7 +3477,7 @@ eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr )
}
if (m_pPaM->GetPoint()->GetContentIndex())
- AppendTextNode(*m_pPaM->GetPoint());
+ FinalizeTextNode(*m_pPaM->GetPoint());
const SwPosition* pPos = m_pPaM->GetPoint();
diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index 6b33ac0d5bd6..bc89199c4904 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -881,7 +881,7 @@ void wwSectionManager::CreateSep(const tools::Long nTextPos)
if( txtNode->Len() == 0 )
insert = false;
if( insert )
- mrReader.AppendTextNode(*mrReader.m_pPaM->GetPoint());
+ mrReader.FinalizeTextNode(*mrReader.m_pPaM->GetPoint());
}
ww::WordVersion eVer = mrReader.GetFib().GetFIBVersion();
@@ -2528,7 +2528,7 @@ bool SwWW8ImplReader::StartApo(const ApoTestResults &rApo, const WW8_TablePos *p
{
// The two fly frames would have the same anchor position, leading to
// potentially overlapping text, prevent that.
- AppendTextNode(*pPoint);
+ FinalizeTextNode(*pPoint);
}
}
}
diff --git a/sw/source/filter/xml/xmlfmte.cxx b/sw/source/filter/xml/xmlfmte.cxx
index fc8932e8bb2f..d64810724cf8 100644
--- a/sw/source/filter/xml/xmlfmte.cxx
+++ b/sw/source/filter/xml/xmlfmte.cxx
@@ -247,7 +247,7 @@ void SwXMLExport::collectAutoStyles()
GetFormExport()->examineForms(xPage);
}
- GetTextParagraphExport()->collectTextAutoStylesOptimized( m_bShowProgress );
+ GetTextParagraphExport()->collectTextAutoStylesAndNodeExportOrder(m_bShowProgress);
}
mbAutoStylesCollected = true;
diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx
index 6153fb09d7a8..786539812341 100644
--- a/xmloff/source/text/txtparae.cxx
+++ b/xmloff/source/text/txtparae.cxx
@@ -39,6 +39,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -1331,12 +1332,14 @@ struct XMLTextParagraphExport::DocumentListNodes
{
struct NodeData
{
+ std::ptrdiff_t order;
sal_Int32 index; // see SwNode::GetIndex and SwNodeOffset
sal_uInt64 style_id; // actually a pointer to NumRule
OUString list_id;
};
std::vector docListNodes;
- DocumentListNodes(const css::uno::Reference& xModel)
+ DocumentListNodes(const css::uno::Reference& xModel,
+ const std::vector& aDocumentNodeOrder)
{
// Sequence of nodes, each of them represented by three-element sequence,
// corresponding to NodeData members
@@ -1358,13 +1361,18 @@ struct XMLTextParagraphExport::DocumentListNodes
for (const auto& node : nodes)
{
assert(node.getLength() == 3);
- docListNodes.push_back({ .index = node[0].get(),
+ sal_Int32 nodeIndex = node[0].get();
+ auto nodeOrder = std::distance(
+ aDocumentNodeOrder.begin(),
+ std::find(aDocumentNodeOrder.begin(), aDocumentNodeOrder.end(), nodeIndex));
+ docListNodes.push_back({ .order = nodeOrder,
+ .index = nodeIndex,
.style_id = node[1].get(),
.list_id = node[2].get() });
}
std::sort(docListNodes.begin(), docListNodes.end(),
- [](const NodeData& lhs, const NodeData& rhs) { return lhs.index < rhs.index; });
+ [](const NodeData& lhs, const NodeData& rhs) { return lhs.order < rhs.order; });
}
bool ShouldSkipListId(const Reference& xTextContent) const
{
@@ -1385,10 +1393,9 @@ struct XMLTextParagraphExport::DocumentListNodes
return false;
}
- auto it = std::lower_bound(docListNodes.begin(), docListNodes.end(), index,
- [](const NodeData& lhs, sal_Int32 rhs)
- { return lhs.index < rhs; });
- if (it == docListNodes.end() || it->index != index)
+ auto it = std::find_if(docListNodes.begin(), docListNodes.end(),
+ [index](const NodeData& el) { return el.index == index; });
+ if (it == docListNodes.end())
return false;
// We need to write the id, when there will be continuation of the list either with
@@ -1616,9 +1623,7 @@ const enum XMLTokenEnum lcl_XmlReferenceElements[] = {
const enum XMLTokenEnum lcl_XmlBookmarkElements[] = {
XML_BOOKMARK, XML_BOOKMARK_START, XML_BOOKMARK_END };
-// This function replaces the text portion iteration during auto style
-// collection.
-void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress )
+void XMLTextParagraphExport::collectTextAutoStylesAndNodeExportOrder(bool bIsProgress)
{
GetExport().GetShapeExport(); // make sure the graphics styles family is added
@@ -1628,60 +1633,11 @@ void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress )
const bool bAutoStyles = true;
const bool bExportContent = false;
- // Export AutoStyles:
- Reference< XAutoStylesSupplier > xAutoStylesSupp( GetExport().GetModel(), UNO_QUERY );
- if ( xAutoStylesSupp.is() )
+ if (auto xTextDocument = GetExport().GetModel().query())
{
- Reference< XAutoStyles > xAutoStyleFamilies = xAutoStylesSupp->getAutoStyles();
- const auto collectFamily = [this, &xAutoStyleFamilies](const OUString& sName,
- XmlStyleFamily nFamily) {
- Any aAny = xAutoStyleFamilies->getByName( sName );
- Reference< XAutoStyleFamily > xAutoStyles = *o3tl::doAccess>(aAny);
- Reference < XEnumeration > xAutoStylesEnum( xAutoStyles->createEnumeration() );
-
- while ( xAutoStylesEnum->hasMoreElements() )
- {
- aAny = xAutoStylesEnum->nextElement();
- Reference< XAutoStyle > xAutoStyle = *o3tl::doAccess>(aAny);
- Reference < XPropertySet > xPSet( xAutoStyle, uno::UNO_QUERY );
- Add( nFamily, xPSet, {}, true );
- }
- };
- collectFamily("CharacterStyles", XmlStyleFamily::TEXT_TEXT);
- collectFamily("RubyStyles", XmlStyleFamily::TEXT_RUBY);
- collectFamily("ParagraphStyles", XmlStyleFamily::TEXT_PARAGRAPH);
- }
-
- // Export Field AutoStyles:
- Reference< XTextFieldsSupplier > xTextFieldsSupp( GetExport().GetModel(), UNO_QUERY );
- if ( xTextFieldsSupp.is() )
- {
- Reference< XEnumerationAccess > xTextFields = xTextFieldsSupp->getTextFields();
- Reference < XEnumeration > xTextFieldsEnum( xTextFields->createEnumeration() );
-
- while ( xTextFieldsEnum->hasMoreElements() )
- {
- Any aAny = xTextFieldsEnum->nextElement();
- Reference< XTextField > xTextField = *o3tl::doAccess>(aAny);
- exportTextField( xTextField, bAutoStyles, bIsProgress,
- !xAutoStylesSupp.is(), nullptr );
- try
- {
- Reference < XPropertySet > xSet( xTextField, UNO_QUERY );
- Reference < XText > xText;
- Any a = xSet->getPropertyValue("TextRange");
- a >>= xText;
- if ( xText.is() )
- {
- exportText( xText, true, bIsProgress, bExportContent );
- GetExport().GetTextParagraphExport()
- ->collectTextAutoStyles( xText );
- }
- }
- catch (Exception&)
- {
- }
- }
+ bInDocumentNodeOrderCollection = true;
+ collectTextAutoStyles(xTextDocument->getText(), bIsProgress);
+ bInDocumentNodeOrderCollection = false;
}
// Export text frames:
@@ -1728,47 +1684,11 @@ void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress )
}
}
- sal_Int32 nCount;
- // AutoStyles for sections
- Reference< XTextSectionsSupplier > xSectionsSupp( GetExport().GetModel(), UNO_QUERY );
- if ( xSectionsSupp.is() )
- {
- Reference< XIndexAccess > xSections( xSectionsSupp->getTextSections(), UNO_QUERY );
- if ( xSections.is() )
- {
- nCount = xSections->getCount();
- for( sal_Int32 i = 0; i < nCount; ++i )
- {
- Any aAny = xSections->getByIndex( i );
- Reference< XTextSection > xSection = *o3tl::doAccess>(aAny);
- Reference < XPropertySet > xPSet( xSection, uno::UNO_QUERY );
- Add( XmlStyleFamily::TEXT_SECTION, xPSet );
- }
- }
- }
-
- // AutoStyles for tables (Note: suppress autostyle collection for paragraphs in exportTable)
- Reference< XTextTablesSupplier > xTablesSupp( GetExport().GetModel(), UNO_QUERY );
- if ( xTablesSupp.is() )
- {
- Reference< XIndexAccess > xTables( xTablesSupp->getTextTables(), UNO_QUERY );
- if ( xTables.is() )
- {
- nCount = xTables->getCount();
- for( sal_Int32 i = 0; i < nCount; ++i )
- {
- Any aAny = xTables->getByIndex( i );
- Reference< XTextTable > xTable = *o3tl::doAccess>(aAny);
- exportTable( xTable, true, true );
- }
- }
- }
-
Reference< XNumberingRulesSupplier > xNumberingRulesSupp( GetExport().GetModel(), UNO_QUERY );
if ( xNumberingRulesSupp.is() )
{
Reference< XIndexAccess > xNumberingRules = xNumberingRulesSupp->getNumberingRules();
- nCount = xNumberingRules->getCount();
+ sal_Int32 nCount = xNumberingRules->getCount();
// Custom outline assignment lost after re-importing sxw (#i73361#)
for( sal_Int32 i = 0; i < nCount; ++i )
{
@@ -1894,14 +1814,36 @@ bool XMLTextParagraphExport::ExportListId() const
&& GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012;
}
+void XMLTextParagraphExport::RecordNodeIndex(const css::uno::Reference& xTextContent)
+{
+ if (!bInDocumentNodeOrderCollection)
+ return;
+ if (auto xPropSet = xTextContent.query())
+ {
+ try
+ {
+ sal_Int32 index = 0;
+ // See SwXParagraph::Impl::GetPropertyValues_Impl
+ xPropSet->getPropertyValue("ODFExport_NodeIndex") >>= index;
+ assert(std::find(maDocumentNodeOrder.begin(), maDocumentNodeOrder.end(), index)
+ == maDocumentNodeOrder.end());
+ maDocumentNodeOrder.push_back(index);
+ }
+ catch (css::beans::UnknownPropertyException&)
+ {
+ // That's absolutely fine!
+ }
+ }
+}
+
bool XMLTextParagraphExport::ShouldSkipListId(const Reference& xTextContent)
{
if (!mpDocumentListNodes)
{
if (ExportListId())
- mpDocumentListNodes.reset(new DocumentListNodes(GetExport().GetModel()));
+ mpDocumentListNodes.reset(new DocumentListNodes(GetExport().GetModel(), maDocumentNodeOrder));
else
- mpDocumentListNodes.reset(new DocumentListNodes({}));
+ mpDocumentListNodes.reset(new DocumentListNodes({}, {}));
}
return mpDocumentListNodes->ShouldSkipListId(xTextContent);
@@ -1952,6 +1894,7 @@ void XMLTextParagraphExport::exportTextContentEnumeration(
{
if( bAutoStyles )
{
+ RecordNodeIndex(xTxtCntnt);
exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
aPrevNumInfo, aNextNumInfo,
bAutoStyles );
@@ -2323,7 +2266,6 @@ void XMLTextParagraphExport::exportParagraph(
Reference < XEnumerationAccess > xEA( rTextContent, UNO_QUERY );
Reference < XEnumeration > xTextEnum = xEA->createEnumeration();
- const bool bHasPortions = xTextEnum.is();
Reference < XEnumeration> xContentEnum;
Reference < XContentEnumerationAccess > xCEA( rTextContent, UNO_QUERY );
@@ -2357,22 +2299,10 @@ void XMLTextParagraphExport::exportParagraph(
bool bPrevCharIsSpace(true); // true because whitespace at start is ignored
- if( bAutoStyles )
- {
- if( bHasContentEnum )
- exportTextContentEnumeration(
- xContentEnum, bAutoStyles, xSection,
- bIsProgress );
- if ( bHasPortions )
- {
- exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
- }
- }
- else
{
enum XMLTokenEnum eElem =
0 < nOutlineLevel ? XML_H : XML_P;
- SvXMLElementExport aElem( GetExport(), eExtensionNS == TextPNS::EXTENSION ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_TEXT, eElem,
+ SvXMLElementExport aElem( GetExport(), !bAutoStyles, eExtensionNS == TextPNS::EXTENSION ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_TEXT, eElem,
true, false );
if( bHasContentEnum )
{
diff --git a/xmloff/source/text/txtparai.cxx b/xmloff/source/text/txtparai.cxx
index 94cef85739ef..f2124bf068ed 100644
--- a/xmloff/source/text/txtparai.cxx
+++ b/xmloff/source/text/txtparai.cxx
@@ -1789,6 +1789,46 @@ void XMLParaContext::endFastElement(sal_Int32 )
true,
mbOutlineContentVisible);
+ bool bEmptyHints = false;
+ XMLHint_Impl* pMarkerStyleHint = nullptr;
+ if (m_xHints)
+ {
+ uno::Reference xCompare(xTxtImport->GetText(), uno::UNO_QUERY);
+ if (xCompare.is())
+ {
+ try
+ {
+ for (const auto& pHint : m_xHints->GetHints())
+ {
+ if (xCompare->compareRegionStarts(pHint->GetStart(), pHint->GetEnd()) == 0)
+ {
+ bEmptyHints = true;
+
+ // Is this the trailing empty span, defining the paragraph mark properties?
+ // Convert it to the marker style, for backward compatibility with documents
+ // created between commits 6249858a8972aef077e0249bd93cfe8f01bce4d6 and
+ // 1a88efa8e02a6d765dab13c7110443bb9e6acecf, where the trailing empty spans
+ // were used to store the marker formatting
+ if (!m_aMarkerStyleName.hasValue()
+ && xCompare->compareRegionStarts(pHint->GetStart(), xEnd) == 0)
+ {
+ if (auto pStyle = GetImport().GetTextImport()->FindAutoCharStyle(
+ static_cast(pHint.get())->GetStyleName()))
+ {
+ m_aMarkerStyleName = pStyle->GetAutoName();
+ pMarkerStyleHint = pHint.get();
+ }
+ }
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("xmloff.text", "");
+ }
+ }
+ }
+
if (m_aMarkerStyleName.hasValue())
{
if (auto xPropSet = xStart.query())
@@ -1850,26 +1890,7 @@ void XMLParaContext::endFastElement(sal_Int32 )
{
bool bSetNoFormatAttr = false;
uno::Reference xCursorProps(xAttrCursor, uno::UNO_QUERY);
- int nEmptyHints = 0;
- uno::Reference xCompare(xTxtImport->GetText(), uno::UNO_QUERY);
- if (xCompare.is())
- {
- try
- {
- for (const auto& pHint : m_xHints->GetHints())
- {
- if (xCompare->compareRegionStarts(pHint->GetStart(), pHint->GetEnd()) == 0)
- {
- ++nEmptyHints;
- }
- }
- }
- catch (const uno::Exception&)
- {
- TOOLS_WARN_EXCEPTION("xmloff.text", "");
- }
- }
- if (nEmptyHints > 0 || m_aMarkerStyleName.hasValue())
+ if (bEmptyHints || m_aMarkerStyleName.hasValue())
{
// We have at least one empty hint, then make try to ask the cursor to not upgrade our character
// attributes to paragraph-level formatting, which would lead to incorrect rendering.
@@ -1888,6 +1909,7 @@ void XMLParaContext::endFastElement(sal_Int32 )
switch( pHint->GetType() )
{
case XMLHintType::XML_HINT_STYLE:
+ if (pHint != pMarkerStyleHint) // already processed above
{
const OUString& rStyleName =
static_cast(pHint)->GetStyleName();