summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xmloff/txtimp.hxx3
-rw-r--r--sw/inc/IDocumentMarkAccess.hxx2
-rw-r--r--sw/qa/extras/odfexport/odfexport.cxx4
-rw-r--r--sw/source/core/doc/docbm.cxx6
-rw-r--r--sw/source/core/inc/MarkManager.hxx2
-rw-r--r--sw/source/core/unocore/unobkm.cxx9
-rw-r--r--xmloff/source/core/xmlimp.cxx2
-rw-r--r--xmloff/source/text/XMLTextMarkImportContext.cxx46
-rw-r--r--xmloff/source/text/XMLTextMarkImportContext.hxx6
-rw-r--r--xmloff/source/text/txtimp.cxx60
-rw-r--r--xmloff/source/text/txtparai.cxx40
11 files changed, 152 insertions, 28 deletions
diff --git a/include/xmloff/txtimp.hxx b/include/xmloff/txtimp.hxx
index ca0ce7ab7e5a..291998bae489 100644
--- a/include/xmloff/txtimp.hxx
+++ b/include/xmloff/txtimp.hxx
@@ -733,6 +733,9 @@ public:
void SetCellParaStyleDefault(OUString const& rNewValue);
OUString const& GetCellParaStyleDefault();
+
+ void AddCrossRefHeadingMapping(OUString const& rFrom, OUString const& rTo);
+ void MapCrossRefHeadingFieldsHorribly();
};
#endif
diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index befbaeb707c8..78e73f7c3140 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -77,7 +77,7 @@ class IDocumentMarkAccess
*/
virtual ::sw::mark::IMark* makeMark(const SwPaM& rPaM,
const OUString& rProposedName,
- MarkType eMark, bool = false) = 0;
+ MarkType eMark) = 0;
virtual sw::mark::IFieldmark* makeFieldBookmark( const SwPaM& rPaM,
const OUString& rName,
diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx
index bc7d768c3ae4..0e106facbbf2 100644
--- a/sw/qa/extras/odfexport/odfexport.cxx
+++ b/sw/qa/extras/odfexport/odfexport.cxx
@@ -385,9 +385,7 @@ DECLARE_ODFEXPORT_TEST(testDuplicateCrossRefHeadingBookmark, "CrossRefHeadingBoo
uno::Reference<text::XTextContent> xBookmark1(
xBookmarks->getByName("__RefHeading__8284_1826734303"), uno::UNO_QUERY);
CPPUNIT_ASSERT(xBookmark1.is());
- uno::Reference<text::XTextContent> xBookmark2(
- xBookmarks->getByName("__RefHeading__1673_25705824"), uno::UNO_QUERY);
- CPPUNIT_ASSERT(xBookmark2.is());
+ CPPUNIT_ASSERT_THROW(xBookmarks->getByName("__RefHeading__1673_25705824"), container::NoSuchElementException);
uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<util::XRefreshable>(xTextFieldsSupplier->getTextFields(), uno::UNO_QUERY)->refresh();
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 4680744ccba6..9b93a37ee1a4 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -352,8 +352,7 @@ namespace sw { namespace mark
::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM,
const OUString& rName,
- const IDocumentMarkAccess::MarkType eType,
- bool const isHorribleHackIgnoreDuplicates)
+ const IDocumentMarkAccess::MarkType eType)
{
#if 0
{
@@ -376,8 +375,7 @@ namespace sw { namespace mark
" - more than USHRT_MAX marks are not supported correctly");
// There should only be one CrossRefBookmark per Textnode per Type
if ((eType == MarkType::CROSSREF_NUMITEM_BOOKMARK || eType == MarkType::CROSSREF_HEADING_BOOKMARK)
- && (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.Start(), eType) != m_vBookmarks.end())
- && !isHorribleHackIgnoreDuplicates)
+ && (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.Start(), eType) != m_vBookmarks.end()))
{ // this can happen via UNO API
SAL_WARN("sw.core", "MarkManager::makeMark(..)"
" - refusing to create duplicate CrossRefBookmark");
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
index 05e3cec3f657..b797764c623b 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -36,7 +36,7 @@ namespace sw {
public:
MarkManager(/*[in/out]*/ SwDoc& rDoc);
// IDocumentMarkAccess
- virtual ::sw::mark::IMark* makeMark(const SwPaM& rPaM, const OUString& rName, IDocumentMarkAccess::MarkType eMark, bool = false) SAL_OVERRIDE;
+ virtual ::sw::mark::IMark* makeMark(const SwPaM& rPaM, const OUString& rName, IDocumentMarkAccess::MarkType eMark) SAL_OVERRIDE;
virtual sw::mark::IFieldmark* makeFieldBookmark( const SwPaM& rPaM,
const OUString& rName,
diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx
index fd85f3fa7718..e6bc9af235e6 100644
--- a/sw/source/core/unocore/unobkm.cxx
+++ b/sw/source/core/unocore/unobkm.cxx
@@ -226,7 +226,6 @@ throw (lang::IllegalArgumentException, uno::RuntimeException)
SwUnoInternalPaM aPam(*m_pImpl->m_pDoc);
::sw::XTextRangeToSwPaM(aPam, xTextRange);
UnoActionContext aCont(m_pImpl->m_pDoc);
- bool isHorribleHackIgnoreDuplicates(false);
if (m_pImpl->m_sMarkName.isEmpty())
{
m_pImpl->m_sMarkName = "Bookmark";
@@ -241,16 +240,10 @@ throw (lang::IllegalArgumentException, uno::RuntimeException)
IDocumentMarkAccess::IsLegalPaMForCrossRefHeadingBookmark( aPam ) )
{
eType = IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK;
- // tdf#94804 LO 4.2-5.0 create invalid duplicates that must be preserved
- // note: do not check meta:generator, may be preserved by other versions
- if (m_pImpl->m_pDoc->IsInXMLImport())
- {
- isHorribleHackIgnoreDuplicates = true;
- }
}
m_pImpl->registerInMark(*this,
m_pImpl->m_pDoc->getIDocumentMarkAccess()->makeMark(
- aPam, m_pImpl->m_sMarkName, eType, isHorribleHackIgnoreDuplicates));
+ aPam, m_pImpl->m_sMarkName, eType));
// #i81002#
// Check, if bookmark has been created.
// E.g., the creation of a cross-reference bookmark is suppress,
diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx
index 46fdae84d368..6491db6c49e3 100644
--- a/xmloff/source/core/xmlimp.cxx
+++ b/xmloff/source/core/xmlimp.cxx
@@ -547,6 +547,8 @@ void SAL_CALL SvXMLImport::endDocument()
// #i9518# All the stuff that accesses the document has to be done here, not in the dtor,
// because the SvXMLImport dtor might not be called until after the document has been closed.
+ GetTextImport()->MapCrossRefHeadingFieldsHorribly();
+
if (mpImpl->mpRDFaHelper.get())
{
const uno::Reference<rdf::XRepositorySupplier> xRS(mxModel,
diff --git a/xmloff/source/text/XMLTextMarkImportContext.cxx b/xmloff/source/text/XMLTextMarkImportContext.cxx
index f0d34582f180..f344cde5053b 100644
--- a/xmloff/source/text/XMLTextMarkImportContext.cxx
+++ b/xmloff/source/text/XMLTextMarkImportContext.cxx
@@ -100,10 +100,12 @@ TYPEINIT1( XMLTextMarkImportContext, SvXMLImportContext);
XMLTextMarkImportContext::XMLTextMarkImportContext(
SvXMLImport& rImport,
XMLTextImportHelper& rHlp,
+ uno::Reference<uno::XInterface> & io_rxCrossRefHeadingBookmark,
sal_uInt16 nPrefix,
const OUString& rLocalName )
: SvXMLImportContext(rImport, nPrefix, rLocalName)
, m_rHelper(rHlp)
+ , m_rxCrossRefHeadingBookmark(io_rxCrossRefHeadingBookmark)
, m_bHaveAbout(false)
{
}
@@ -203,9 +205,23 @@ void XMLTextMarkImportContext::EndElement()
OUString());
break;
- case TypeFieldmark:
case TypeBookmark:
{
+ // tdf#94804: detect duplicate heading cross reference bookmarks
+ if (m_sBookmarkName.startsWith("__RefHeading__"))
+ {
+ if (m_rxCrossRefHeadingBookmark.is())
+ {
+ uno::Reference<container::XNamed> const xNamed(
+ m_rxCrossRefHeadingBookmark, uno::UNO_QUERY);
+ m_rHelper.AddCrossRefHeadingMapping(
+ m_sBookmarkName, xNamed->getName());
+ break; // don't insert
+ }
+ }
+ } // fall through
+ case TypeFieldmark:
+ {
const char *formFieldmarkName=lcl_getFormFieldmarkName(m_sFieldName);
bool bImportAsField=((lcl_MarkType)nTmp==TypeFieldmark && formFieldmarkName!=NULL); //@TODO handle abbreviation cases..
// export point bookmark
@@ -226,6 +242,12 @@ void XMLTextMarkImportContext::EndElement()
}
m_rHelper.popFieldCtx();
}
+ if (TypeBookmark == nTmp
+ && m_sBookmarkName.startsWith("__RefHeading__"))
+ {
+ assert(xContent.is());
+ m_rxCrossRefHeadingBookmark = xContent;
+ }
}
break;
@@ -250,8 +272,22 @@ void XMLTextMarkImportContext::EndElement()
}
break;
- case TypeFieldmarkEnd:
case TypeBookmarkEnd:
+ {
+ // tdf#94804: detect duplicate heading cross reference bookmarks
+ if (m_sBookmarkName.startsWith("__RefHeading__"))
+ {
+ if (m_rxCrossRefHeadingBookmark.is())
+ {
+ uno::Reference<container::XNamed> const xNamed(
+ m_rxCrossRefHeadingBookmark, uno::UNO_QUERY);
+ m_rHelper.AddCrossRefHeadingMapping(
+ m_sBookmarkName, xNamed->getName());
+ break; // don't insert
+ }
+ }
+ } // fall through
+ case TypeFieldmarkEnd:
{
// get old range, and construct
Reference<XTextRange> xStartRange;
@@ -334,6 +370,12 @@ void XMLTextMarkImportContext::EndElement()
}
m_rHelper.popFieldCtx();
}
+ if (TypeBookmarkEnd == nTmp
+ && m_sBookmarkName.startsWith("__RefHeading__"))
+ {
+ assert(xContent.is());
+ m_rxCrossRefHeadingBookmark = xContent;
+ }
}
// else: beginning/end in different XText -> ignore!
}
diff --git a/xmloff/source/text/XMLTextMarkImportContext.hxx b/xmloff/source/text/XMLTextMarkImportContext.hxx
index ae01b79b2a6b..2f449ca30a31 100644
--- a/xmloff/source/text/XMLTextMarkImportContext.hxx
+++ b/xmloff/source/text/XMLTextMarkImportContext.hxx
@@ -61,8 +61,11 @@ public:
*/
class XMLTextMarkImportContext : public SvXMLImportContext
{
-
+private:
XMLTextImportHelper & m_rHelper;
+
+ css::uno::Reference<css::uno::XInterface> & m_rxCrossRefHeadingBookmark;
+
OUString m_sBookmarkName;
OUString m_sFieldName;
OUString m_sXmlId;
@@ -80,6 +83,7 @@ public:
XMLTextMarkImportContext(
SvXMLImport& rImport,
XMLTextImportHelper& rHlp,
+ css::uno::Reference<css::uno::XInterface> & io_rxCrossRefHeadingBookmark,
sal_uInt16 nPrfx,
const OUString& rLocalName );
diff --git a/xmloff/source/text/txtimp.cxx b/xmloff/source/text/txtimp.cxx
index 652f2b9735eb..eb87ec39cdc8 100644
--- a/xmloff/source/text/txtimp.cxx
+++ b/xmloff/source/text/txtimp.cxx
@@ -25,7 +25,9 @@
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/text/ReferenceFieldSource.hpp>
#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
#include <com/sun/star/text/XTextFramesSupplier.hpp>
#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
@@ -576,6 +578,8 @@ struct XMLTextImportHelper::Impl
OUString m_sCellParaStyleDefault;
+ std::unique_ptr<std::map<OUString, OUString>> m_pCrossRefHeadingBookmarkMap;
+
Impl( uno::Reference<frame::XModel> const& rModel,
SvXMLImport & rImport,
bool const bInsertMode, bool const bStylesOnlyMode,
@@ -2801,4 +2805,60 @@ OUString const& XMLTextImportHelper::GetCellParaStyleDefault()
return m_xImpl->m_sCellParaStyleDefault;
}
+void XMLTextImportHelper::AddCrossRefHeadingMapping(OUString const& rFrom, OUString const& rTo)
+{
+ if (!m_xImpl->m_pCrossRefHeadingBookmarkMap)
+ {
+ m_xImpl->m_pCrossRefHeadingBookmarkMap.reset(new std::map<OUString, OUString>);
+ }
+ m_xImpl->m_pCrossRefHeadingBookmarkMap->insert(std::make_pair(rFrom, rTo));
+}
+
+// tdf#94804: hack to map cross reference fiels that reference duplicate marks
+// note that we can't really check meta:generator for this since the file might
+// be round-tripped by different versions preserving duplicates => always map
+void XMLTextImportHelper::MapCrossRefHeadingFieldsHorribly()
+{
+ if (!m_xImpl->m_pCrossRefHeadingBookmarkMap)
+ {
+ return;
+ }
+
+ uno::Reference<text::XTextFieldsSupplier> const xFieldsSupplier(
+ m_xImpl->m_rSvXMLImport.GetModel(), uno::UNO_QUERY);
+ if (!xFieldsSupplier.is())
+ {
+ return;
+ }
+ uno::Reference<container::XEnumerationAccess> const xFieldsEA(
+ xFieldsSupplier->getTextFields());
+ uno::Reference<container::XEnumeration> const xFields(
+ xFieldsEA->createEnumeration());
+ while (xFields->hasMoreElements())
+ {
+ uno::Reference<lang::XServiceInfo> const xFieldInfo(
+ xFields->nextElement(), uno::UNO_QUERY);
+ if (!xFieldInfo->supportsService("com.sun.star.text.textfield.GetReference"))
+ {
+ continue;
+ }
+ uno::Reference<beans::XPropertySet> const xField(
+ xFieldInfo, uno::UNO_QUERY);
+ sal_uInt16 nType(0);
+ xField->getPropertyValue("ReferenceFieldSource") >>= nType;
+ if (text::ReferenceFieldSource::BOOKMARK != nType)
+ {
+ continue;
+ }
+ OUString name;
+ xField->getPropertyValue("SourceName") >>= name;
+ auto const iter(m_xImpl->m_pCrossRefHeadingBookmarkMap->find(name));
+ if (iter == m_xImpl->m_pCrossRefHeadingBookmarkMap->end())
+ {
+ continue;
+ }
+ xField->setPropertyValue("SourceName", uno::makeAny(iter->second));
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtparai.cxx b/xmloff/source/text/txtparai.cxx
index 6a324b71a7ee..24853beadaab 100644
--- a/xmloff/source/text/txtparai.cxx
+++ b/xmloff/source/text/txtparai.cxx
@@ -53,7 +53,6 @@
#include "txtlists.hxx"
#include <txtparaimphint.hxx>
-class XMLHints_Impl : public boost::ptr_vector<XMLHint_Impl> {};
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
@@ -66,6 +65,29 @@ using ::com::sun::star::container::XEnumeration;
TYPEINIT1( XMLCharContext, SvXMLImportContext );
+class XMLHints_Impl
+{
+private:
+ boost::ptr_vector<XMLHint_Impl> m_Hints;
+ uno::Reference<uno::XInterface> m_xCrossRefHeadingBookmark;
+
+public:
+ void push_back(XMLHint_Impl * pHint)
+ {
+ m_Hints.push_back(pHint);
+ }
+
+ boost::ptr_vector<XMLHint_Impl> & GetHints()
+ {
+ return m_Hints;
+ }
+
+ uno::Reference<uno::XInterface> & GetCrossRefHeadingBookmark()
+ {
+ return m_xCrossRefHeadingBookmark;
+ }
+};
+
XMLCharContext::XMLCharContext(
SvXMLImport& rImport,
sal_uInt16 nPrfx,
@@ -252,10 +274,10 @@ XMLEndReferenceContext_Impl::XMLEndReferenceContext_Impl(
if (XMLStartReferenceContext_Impl::FindName(GetImport(), xAttrList, sName))
{
// search for reference start
- sal_uInt16 nCount = rHints.size();
+ sal_uInt16 nCount = rHints.GetHints().size();
for(sal_uInt16 nPos = 0; nPos < nCount; nPos++)
{
- XMLHint_Impl *pHint = &rHints[nPos];
+ XMLHint_Impl *pHint = &rHints.GetHints()[nPos];
if ( pHint->IsReference() &&
sName.equals( static_cast<XMLReferenceHint_Impl *>(pHint)->GetRefName()) )
{
@@ -1120,10 +1142,10 @@ void XMLIndexMarkImportContext_Impl::StartElement(
if (!sID.isEmpty())
{
// if we have an ID, find the hint and set the end position
- sal_uInt16 nCount = rHints.size();
+ sal_uInt16 nCount = rHints.GetHints().size();
for(sal_uInt16 nPos = 0; nPos < nCount; nPos++)
{
- XMLHint_Impl *pHint = &rHints[nPos];
+ XMLHint_Impl *pHint = &rHints.GetHints()[nPos];
if ( pHint->IsIndexMark() &&
sID.equals(
static_cast<XMLIndexMarkHint_Impl *>(pHint)->GetID()) )
@@ -1655,6 +1677,7 @@ SvXMLImportContext *XMLImpSpanContext_Impl::CreateChildContext(
case XML_TOK_TEXT_BOOKMARK_END:
pContext = new XMLTextMarkImportContext( rImport,
*rImport.GetTextImport().get(),
+ rHints.GetCrossRefHeadingBookmark(),
nPrefix, rLocalName );
break;
@@ -1663,6 +1686,7 @@ SvXMLImportContext *XMLImpSpanContext_Impl::CreateChildContext(
case XML_TOK_TEXT_FIELDMARK_END:
pContext = new XMLTextMarkImportContext( rImport,
*rImport.GetTextImport().get(),
+ rHints.GetCrossRefHeadingBookmark(),
nPrefix, rLocalName );
break;
@@ -2072,11 +2096,11 @@ XMLParaContext::~XMLParaContext()
}
}
- if( pHints && !pHints->empty() )
+ if (pHints && !pHints->GetHints().empty())
{
- for( sal_uInt16 i=0; i<pHints->size(); i++ )
+ for( sal_uInt16 i=0; i < pHints->GetHints().size(); i++ )
{
- XMLHint_Impl *pHint = &(*pHints)[i];
+ XMLHint_Impl *pHint = &pHints->GetHints()[i];
xAttrCursor->gotoRange( pHint->GetStart(), sal_False );
xAttrCursor->gotoRange( pHint->GetEnd(), sal_True );
switch( pHint->GetType() )