diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx
index 44a97ddb9c3f..11cd7c570737 100644
--- a/include/xmloff/xmlimp.hxx
+++ b/include/xmloff/xmlimp.hxx
@@ -553,6 +553,8 @@ public:
static const sal_uInt16 LO_63x = 63 | LO_flag;
static const sal_uInt16 LO_7x = 70 | LO_flag;
static const sal_uInt16 LO_76 = 76 | LO_flag;
+ static const sal_uInt16 LO_242 = 80 | LO_flag;
+ static const sal_uInt16 LO_248 = 81 | LO_flag;
static const sal_uInt16 LO_New = 100 | LO_flag;
static const sal_uInt16 ProductVersionUnknown = SAL_MAX_UINT16;
diff --git a/sw/CppunitTest_sw_ooxmlexport26.mk b/sw/CppunitTest_sw_ooxmlexport26.mk
index 8b57467c2f61..2bb987dd2ce4 100644
--- a/sw/CppunitTest_sw_ooxmlexport26.mk
+++ b/sw/CppunitTest_sw_ooxmlexport26.mk
@@ -11,6 +11,9 @@
$(eval $(call sw_ooxmlexport_test,26))
+# this test requires "de" translations and if missing tests will be skipped
+$(call gb_CppunitTest_get_target,sw_ooxmlexport26) : $(call gb_AllLangMoTarget_get_target,sw)
+
$(call gb_CppunitTest_get_target,sw_ooxmlexport26) : export LO_TEST_LOCALE=de
# vim: set noet sw=4 ts=4:
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 3c26a31db62e..0c9a77bd3cac 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -319,6 +319,7 @@ private:
bool mbInWriting : 1; //< TRUE: Document is in the process of being written.
bool mbInMailMerge : 1; //< TRUE: Document is in the process of being written by mail merge.
bool mbInXMLImport : 1; //< TRUE: During xml import, attribute portion building is not necessary.
+ bool mbInXMLImport242 : 1 = false; //< TRUE: During xml import, apply workaround for style-ref field
bool mbInWriterfilterImport : 1; //< TRUE: writerfilter import (DOCX,RTF)
bool mbUpdateTOX : 1; //< TRUE: After loading document, update TOX.
bool mbInLoadAsynchron : 1; //< TRUE: Document is in the process of being loaded asynchronously.
@@ -989,6 +990,8 @@ public:
bool IsInXMLImport() const { return mbInXMLImport; }
void SetInXMLImport( bool bNew ) { mbInXMLImport = bNew; }
+ bool IsInXMLImport242() const { return mbInXMLImport242; }
+ void SetInXMLImport242(bool const bNew) { mbInXMLImport242 = bNew; }
bool IsInWriterfilterImport() const { return mbInWriterfilterImport; }
void SetInWriterfilterImport(bool const b) { mbInWriterfilterImport = b; }
diff --git a/sw/qa/extras/ooxmlexport/data/tdf166850_24.2.7.2.fodt b/sw/qa/extras/ooxmlexport/data/tdf166850_24.2.7.2.fodt
new file mode 100644
index 000000000000..a2308801c2db
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf166850_24.2.7.2.fodt
@@ -0,0 +1,164 @@
+
+
+ 2025-06-10T15:12:43.320595150LibreOffice/24.2.7.2$Linux_X86_64 LibreOffice_project/ee3885777aa7032db5a9b65deec9457448a91162
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Second heading
+
+
+
+
+
+
+
+
+
+
+
+
+ First heading
+ Second heading
+ Second heading
+
+
+
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index 95a755c3bb29..1e7e8ce727dc 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -739,16 +739,6 @@ DECLARE_OOXMLEXPORT_TEST(testTdf153082_comma, "custom-styles-TOC-comma.docx")
CPPUNIT_ASSERT(tocContent.indexOf("Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.") != -1);
}
-DECLARE_OOXMLEXPORT_TEST(testTdf160402, "StyleRef-DE.docx")
-{
- xmlDocUniquePtr pLayout = parseLayoutDump();
- assertXPath(pLayout, "/root/page[1]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion", "expand", u"Heading 1");
- assertXPath(pLayout, "/root/page[2]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion", "expand", u"Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.");
- assertXPath(pLayout, "/root/page[3]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion", "expand", u"Cras faucibus condimentum odio. Sed ac ligula. Aliquam at eros.");
- assertXPath(pLayout, "/root/page[4]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion", "expand", u"Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.");
- assertXPath(pLayout, "/root/page[5]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion", "expand", u"Aenean nec lorem. In porttitor. Donec laoreet nonummy augue.");
-}
-
DECLARE_OOXMLEXPORT_TEST(testTdf142407, "tdf142407.docx")
{
uno::Reference xPageStyles = getStyles(u"PageStyles"_ustr);
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport26.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport26.cxx
index 2346da8dc504..f40100534939 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport26.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport26.cxx
@@ -9,6 +9,10 @@
#include
+#include
+#include
+#include
+
#include
#include
@@ -23,6 +27,21 @@ public:
}
};
+DECLARE_OOXMLEXPORT_TEST(testTdf160402, "StyleRef-DE.docx")
+{
+ xmlDocUniquePtr pLayout = parseLayoutDump();
+ assertXPath(pLayout, "/root/page[1]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion",
+ "expand", u"Heading 1");
+ assertXPath(pLayout, "/root/page[2]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion",
+ "expand", u"Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.");
+ assertXPath(pLayout, "/root/page[3]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion",
+ "expand", u"Cras faucibus condimentum odio. Sed ac ligula. Aliquam at eros.");
+ assertXPath(pLayout, "/root/page[4]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion",
+ "expand", u"Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.");
+ assertXPath(pLayout, "/root/page[5]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion",
+ "expand", u"Aenean nec lorem. In porttitor. Donec laoreet nonummy augue.");
+}
+
//test requires German user interface otherwise it will not detect the issue
CPPUNIT_TEST_FIXTURE(Test, testTdf166850)
{
@@ -35,6 +54,35 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf166850)
"expand", u"Heading 1");
}
+CPPUNIT_TEST_FIXTURE(Test, testTdf166850_ODT)
+{
+ // test ODT import from version 24.2 where this worked
+ // but only in the same locale that was used to import from DOCX, not in
+ // a different one
+ OUString instdir;
+ osl_getEnvironment(u"INSTDIR"_ustr.pData, &instdir.pData);
+ OUString url;
+ CPPUNIT_ASSERT_EQUAL(::osl::FileBase::E_None,
+ ::osl::FileBase::getFileURLFromSystemPath(instdir, url));
+ url += "/" LIBO_SHARE_RESOURCE_FOLDER "/de/LC_MESSAGES/sw.mo";
+ ::osl::DirectoryItem item;
+ if (::osl::DirectoryItem::get(url, item) == ::osl::FileBase::E_NOENT)
+ {
+ return;
+ }
+ createSwDoc("tdf166850_24.2.7.2.fodt");
+ SwDoc* pDoc = getSwDoc();
+ SwViewShell* pViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
+ pViewShell->UpdateFields();
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page[1]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion",
+ "expand", u"First heading");
+ assertXPath(pXmlDoc, "/root/page[2]/header/txt[1]/SwParaPortion/SwLineLayout/SwFieldPortion",
+ "expand", u"Second heading");
+ assertXPath(pXmlDoc, "/root/page[2]/body/txt[2]/SwParaPortion/SwLineLayout/SwFieldPortion",
+ "expand", u"Second heading");
+}
+
} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/fields/reffld.cxx b/sw/source/core/fields/reffld.cxx
index 20dccd31999e..c7392d889f52 100644
--- a/sw/source/core/fields/reffld.cxx
+++ b/sw/source/core/fields/reffld.cxx
@@ -962,6 +962,17 @@ bool SwGetRefField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
break;
}
}
+ else if (REF_STYLE == m_nSubType)
+ {
+ ProgName name;
+ SwStyleNameMapper::FillProgName(UIName{sTmp}, name, SwGetPoolIdFromName::TxtColl);
+ if (name == sTmp)
+ {
+ SwStyleNameMapper::FillProgName(UIName{sTmp}, name, SwGetPoolIdFromName::ChrFmt);
+ }
+ sTmp = name.toString();
+
+ }
rAny <<= sTmp;
}
break;
@@ -1025,7 +1036,13 @@ bool SwGetRefField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
case ReferenceFieldSource::BOOKMARK : m_nSubType = REF_BOOKMARK ; break;
case ReferenceFieldSource::FOOTNOTE : m_nSubType = REF_FOOTNOTE ; break;
case ReferenceFieldSource::ENDNOTE : m_nSubType = REF_ENDNOTE ; break;
- case ReferenceFieldSource::STYLE : m_nSubType = REF_STYLE ; break;
+ case ReferenceFieldSource::STYLE :
+ if (REF_STYLE != m_nSubType)
+ {
+ m_nSubType = REF_STYLE;
+ ConvertProgrammaticToUIName();
+ }
+ break;
}
}
break;
@@ -1070,6 +1087,29 @@ bool SwGetRefField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
void SwGetRefField::ConvertProgrammaticToUIName()
{
+ if (GetTyp() && REF_STYLE == m_nSubType)
+ {
+ // this is super ugly, but there isn't a sensible way to check in xmloff
+ SwDoc & rDoc{static_cast(GetTyp())->GetDoc()};
+ if (rDoc.IsInXMLImport242())
+ {
+ SAL_INFO("sw.xml", "Potentially accepting erroneously produced UIName for style-ref field");
+ return;
+ }
+ ProgName const par1{GetPar1()};
+ UIName name;
+ SwStyleNameMapper::FillUIName(par1, name, SwGetPoolIdFromName::TxtColl);
+ if (name.toString() == par1.toString())
+ {
+ SwStyleNameMapper::FillUIName(par1, name, SwGetPoolIdFromName::ChrFmt);
+ }
+ if (name.toString() != par1.toString())
+ {
+ SetPar1(name.toString());
+ }
+ return;
+ }
+
if(!(GetTyp() && REF_SEQUENCEFLD == m_nSubType))
return;
diff --git a/sw/source/core/unocore/unofield.cxx b/sw/source/core/unocore/unofield.cxx
index 9fc8a02c6d96..746d21b1509f 100644
--- a/sw/source/core/unocore/unofield.cxx
+++ b/sw/source/core/unocore/unofield.cxx
@@ -1513,6 +1513,9 @@ void SAL_CALL SwXTextField::attach(
case SwServiceType::FieldTypeGetReference:
{
SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::GetRef);
+ // tdf#159549 tdf#166850: if nUSHORT2 is ReferenceFieldSource::STYLE,
+ // sPar1 needs to be converted from ProgName to UIName - this
+ // is done when setting the FIELD_PROP_USHORT2 below
xField.reset(new SwGetRefField(static_cast(pFieldType),
SwMarkName(m_pImpl->m_pProps->sPar1),
m_pImpl->m_pProps->sPar4,
diff --git a/sw/source/filter/basflt/shellio.cxx b/sw/source/filter/basflt/shellio.cxx
index 38440d48eea3..c3d66e8269c8 100644
--- a/sw/source/filter/basflt/shellio.cxx
+++ b/sw/source/filter/basflt/shellio.cxx
@@ -346,6 +346,7 @@ ErrCodeMsg SwReader::Read( const Reader& rOptions )
mxDoc->SetInReading( false );
mxDoc->SetInXMLImport( false );
+ mxDoc->SetInXMLImport242(false);
mxDoc->SetInWriterfilterImport(false);
if (!mbSkipInvalidateNumRules)
diff --git a/sw/source/filter/xml/xmlfmt.cxx b/sw/source/filter/xml/xmlfmt.cxx
index d5b06c6ac502..f4944a282209 100644
--- a/sw/source/filter/xml/xmlfmt.cxx
+++ b/sw/source/filter/xml/xmlfmt.cxx
@@ -995,6 +995,14 @@ void SwXMLMasterStylesContext_Impl::endFastElement(sal_Int32 )
SvXMLImportContext *SwXMLImport::CreateStylesContext(
bool bAuto )
{
+ // tdf#166850 this only worked in 24.2.4..24.2.7 and broke in 24.8.0
+ // anyway but must *not* be applied to fixed 25.2.x or later
+ if (isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_248)
+ && !isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_242))
+ {
+ getDoc()->SetInXMLImport242(true);
+ }
+
SvXMLStylesContext *pContext = new SwXMLStylesContext_Impl( *this, bAuto );
if( bAuto )
SetAutoStyles( pContext );
diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx
index d879abe2f03b..7e6820e3cf66 100644
--- a/sw/source/filter/xml/xmlimp.cxx
+++ b/sw/source/filter/xml/xmlimp.cxx
@@ -668,6 +668,7 @@ void SwXMLImport::endDocument()
assert(pDoc->IsInXMLImport());
pDoc->SetInReading(false);
pDoc->SetInXMLImport(false);
+ pDoc->SetInXMLImport242(false);
}
SwDrawModel* pDrawModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
diff --git a/sw/source/writerfilter/dmapper/StyleSheetTable.cxx b/sw/source/writerfilter/dmapper/StyleSheetTable.cxx
index 6e3259aacc8f..099ae839e7ef 100644
--- a/sw/source/writerfilter/dmapper/StyleSheetTable.cxx
+++ b/sw/source/writerfilter/dmapper/StyleSheetTable.cxx
@@ -1103,22 +1103,19 @@ OUString StyleSheetTable::CloneTOCStyle(FontTablePtr const& rFontTable, StyleShe
// the old converted name is what is applied to paragraphs
m_pImpl->m_ClonedTOCStylesMap.emplace(pStyle->m_sConvertedStyleName, pClone->m_sConvertedStyleName);
std::vector const styles{ pClone };
- std::vector aRetStyleNames = ApplyStyleSheetsImpl(rFontTable, styles);
- pClone->m_sConvertedStyleName = aRetStyleNames[0];
+ ApplyStyleSheetsImpl(rFontTable, styles);
return pClone->m_sConvertedStyleName;
}
void StyleSheetTable::ApplyStyleSheets( const FontTablePtr& rFontTable )
{
- ApplyStyleSheetsImpl(rFontTable, m_pImpl->m_aStyleSheetEntries);
+ return ApplyStyleSheetsImpl(rFontTable, m_pImpl->m_aStyleSheetEntries);
}
-std::vector StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr& rFontTable, std::vector const& rEntries)
+void StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr& rFontTable, std::vector const& rEntries)
{
- std::vector aStyleUINames(rEntries.size());
- std::vector::iterator aStyleUINamesIt = aStyleUINames.begin();
if (!m_pImpl->m_xTextDocument)
- return aStyleUINames;
+ return;
try
{
rtl::Reference< SwXStyleFamilies > xStyleFamilies = m_pImpl->m_xTextDocument->getSwStyleFamilies();
@@ -1134,7 +1131,6 @@ std::vector StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr&
std::vector aTableStylesVec;
for (auto& pEntry : rEntries)
{
- *aStyleUINamesIt = pEntry->m_sStyleName;
if( pEntry->m_nStyleTypeCode == STYLE_TYPE_UNKNOWN && !pEntry->m_sStyleName.isEmpty() )
pEntry->m_nStyleTypeCode = STYLE_TYPE_PARA; // unspecified style types are considered paragraph styles
@@ -1418,7 +1414,7 @@ std::vector StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr&
aMissingParent.emplace_back( sParentStyle, xStyle );
xStyles->insertStyleByName( sConvertedStyleName, static_cast(xStyle.get()) );
- *aStyleUINamesIt = static_cast(xStyle.get())->GetStyleUIName().toString();
+
if (!m_pImpl->m_bIsNewDoc && bParaStyle)
{
// Remember the inserted style, which may or may not be referred during
@@ -1447,7 +1443,6 @@ std::vector StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr&
pEntry->m_pProperties->InsertProps( m_pImpl->m_pDefaultCharProps, /*bOverwrite=*/false );
pEntry->m_pProperties->InsertProps( m_pImpl->m_pDefaultParaProps, /*bOverwrite=*/false );
}
- ++aStyleUINamesIt;
}
// Update the styles that were created before their parents or next-styles
@@ -1497,7 +1492,6 @@ std::vector StyleSheetTable::ApplyStyleSheetsImpl(const FontTablePtr&
{
DBG_UNHANDLED_EXCEPTION("writerfilter", "Styles could not be imported completely");
}
- return aStyleUINames;
}
diff --git a/sw/source/writerfilter/dmapper/StyleSheetTable.hxx b/sw/source/writerfilter/dmapper/StyleSheetTable.hxx
index 3715e1ef6ef7..eaf84387b512 100644
--- a/sw/source/writerfilter/dmapper/StyleSheetTable.hxx
+++ b/sw/source/writerfilter/dmapper/StyleSheetTable.hxx
@@ -128,7 +128,7 @@ private:
void applyDefaults(bool bParaProperties);
- std::vector ApplyStyleSheetsImpl(const FontTablePtr& rFontTable, std::vector const& rEntries);
+ void ApplyStyleSheetsImpl(const FontTablePtr& rFontTable, std::vector const& rEntries);
};
diff --git a/xmloff/qa/unit/uxmloff.cxx b/xmloff/qa/unit/uxmloff.cxx
index 7fb1004bf612..cf888baa93fd 100644
--- a/xmloff/qa/unit/uxmloff.cxx
+++ b/xmloff/qa/unit/uxmloff.cxx
@@ -199,7 +199,9 @@ void Test::testMetaGenerator()
{ "LibreOffice_powered_by_CIBDev/6.4.0.0.0$Linux_X86_64 LibreOffice_project/e29e100174c133d27e953934311d68602c4515b7", ";6.4.0.0.0", SvXMLImport::LO_63x },
{ "LibreOfficeDev/7.0.6.0.0$Linux_X86_64 LibreOffice_project/dfc40e2292c6e19e285c10ed8c8044d9454107d0", ";7.0.6.0.0", SvXMLImport::LO_7x },
{ "CIB_OfficeDev/6.4.0.19$Linux_X86_64 LibreOffice_project/2e04f804b5f82770435f250873f07b3384d95504", ";6.4.0.19", SvXMLImport::LO_63x },
- { "LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/b81e7b6f3c71fb3ade1cb665444ac730dac0a9a9", ";24.2.0.0.", SvXMLImport::LO_New },
+ { "LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/b81e7b6f3c71fb3ade1cb665444ac730dac0a9a9", ";24.2.0.0.", SvXMLImport::LO_242 },
+ { "LibreOfficeDev/24.8.6.2$Linux_X86_64 LibreOffice_project/dc6216c3d2b4ec3bcdba950f1e6ee1d013adb2d6", ";24.8.6.2", SvXMLImport::LO_248 },
+ { "LibreOfficeDev/25.8.0.0.alpha0$Linux_X86_64 LibreOffice_project/308705574842e0c36f7385f73fc47da9a4542367", ";25.8.0.0.", SvXMLImport::LO_New }
};
for (auto const[pGenerator, pBuildId, nResult] : tests)
diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx
index a487b992a142..134259fdb0f5 100644
--- a/xmloff/source/core/xmlimp.cxx
+++ b/xmloff/source/core/xmlimp.cxx
@@ -234,8 +234,16 @@ public:
{
OUString const nMajor(loVersion.subView(0, firstDot));
auto const year(nMajor.toInt32());
- //auto const month(loVersion.copy(firstDot+1).toInt32());
- if (0 < year)
+ auto const month(o3tl::toInt32(loVersion.subView(firstDot+1)));
+ if (24 == year && month == 2)
+ {
+ mnGeneratorVersion = SvXMLImport::LO_242;
+ }
+ else if (24 == year && month == 8)
+ {
+ mnGeneratorVersion = SvXMLImport::LO_248;
+ }
+ else if (0 < year)
{
mnGeneratorVersion = SvXMLImport::LO_New;
}