From e83fe075468915aaa481bcf73a06ccec485517db Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Tue, 13 Nov 2018 18:53:50 +0100 Subject: sw_redlinehide_3: add second result to SwAuthorityField ... and SwAuthorityFieldType, which needs 2 lists of the fields because each citation may occur multiple times, so their order might change on deletions. This is for when there is a bibliography in the document, and it is set to IsSequence(), i.e., insert Bibliography -> Number entries -> Sort by document position... Change-Id: Iba2c31267aeebacb779713567eeb0aa6659afefb --- sw/inc/IDocumentFieldsAccess.hxx | 6 ++ sw/inc/authfld.hxx | 17 +++++- sw/source/core/doc/DocumentFieldsManager.cxx | 23 ++++--- sw/source/core/fields/authfld.cxx | 89 ++++++++++++++++++---------- sw/source/core/fields/fldbas.cxx | 2 +- sw/source/filter/ww8/docxattributeoutput.cxx | 2 +- sw/source/filter/ww8/ww8atr.cxx | 2 +- 7 files changed, 98 insertions(+), 43 deletions(-) diff --git a/sw/inc/IDocumentFieldsAccess.hxx b/sw/inc/IDocumentFieldsAccess.hxx index 617ea990614c..00ceff6fcc2a 100644 --- a/sw/inc/IDocumentFieldsAccess.hxx +++ b/sw/inc/IDocumentFieldsAccess.hxx @@ -39,6 +39,7 @@ enum class SwFieldIds : sal_uInt16; template class SwHashTable; struct HashStr; class SwRootFrame; +class IDocumentRedlineAccess; namespace rtl { class OUString; } using rtl::OUString; @@ -139,6 +140,11 @@ protected: virtual ~IDocumentFieldsAccess() {}; }; +namespace sw { +bool IsFieldDeletedInModel(IDocumentRedlineAccess const& rIDRA, + SwTextField const& rTextField); +} + #endif // INCLUDED_SW_INC_IDOCUMENTFIELDSACCESS_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/inc/authfld.hxx b/sw/inc/authfld.hxx index c6bab5ccf91c..72837f765c65 100644 --- a/sw/inc/authfld.hxx +++ b/sw/inc/authfld.hxx @@ -62,6 +62,7 @@ class SW_DLLPUBLIC SwAuthorityFieldType : public SwFieldType SwDoc* m_pDoc; SwAuthDataArr m_DataArr; std::vector m_SequArr; + std::vector m_SequArrRLHidden; ///< hidden redlines SortKeyArr m_SortKeyArr; sal_Unicode m_cPrefix; sal_Unicode m_cSuffix; @@ -90,6 +91,7 @@ public: void DelSequenceArray() { m_SequArr.clear(); + m_SequArrRLHidden.clear(); } const SwAuthEntry* GetEntryByHandle(sal_IntPtr nHandle) const; @@ -102,7 +104,7 @@ public: sal_uInt16 AppendField(const SwAuthEntry& rInsert); sal_IntPtr GetHandle(sal_uInt16 nPos); - sal_uInt16 GetSequencePos(sal_IntPtr nHandle); + sal_uInt16 GetSequencePos(sal_IntPtr nHandle, SwRootFrame const* pLayout); bool IsSequence() const {return m_bIsSequence;} void SetSequence(bool bSet) @@ -142,20 +144,29 @@ public: }; +/** invariant for SwAuthorityField is that it is always registered at its + SwAuthorityFieldType via AddField()/RemoveField() & therefore has m_nHandle + set - but it's possible that multiple SwAuthorityField have the same + m_nHandle & so the number of instances is an upper bound on + SwAuthorityField::m_DataArr.size() - it's not clear to me if more than one + one of the instances with the same m_nHandle is actually in the document, + they're all cloned via CopyField()... + */ class SwAuthorityField : public SwField { sal_IntPtr m_nHandle; mutable sal_IntPtr m_nTempSequencePos; + mutable sal_IntPtr m_nTempSequencePosRLHidden; ///< hidden redlines virtual OUString ExpandImpl(SwRootFrame const* pLayout) const override; virtual std::unique_ptr Copy() const override; public: /// For internal use only, in general continue using ExpandField() instead. - OUString ConditionalExpandAuthIdentifier() const; + OUString ConditionalExpandAuthIdentifier(SwRootFrame const* pLayout) const; //To handle Citation - SW_DLLPUBLIC OUString ExpandCitation(ToxAuthorityField eField) const; + SW_DLLPUBLIC OUString ExpandCitation(ToxAuthorityField eField, SwRootFrame const* pLayout) const; SwAuthorityField(SwAuthorityFieldType* pType, const OUString& rFieldContents); SwAuthorityField(SwAuthorityFieldType* pType, sal_IntPtr nHandle); diff --git a/sw/source/core/doc/DocumentFieldsManager.cxx b/sw/source/core/doc/DocumentFieldsManager.cxx index e089f88ec7fb..efe6c60357ff 100644 --- a/sw/source/core/doc/DocumentFieldsManager.cxx +++ b/sw/source/core/doc/DocumentFieldsManager.cxx @@ -59,6 +59,21 @@ using namespace ::com::sun::star::uno; +namespace sw +{ + bool IsFieldDeletedInModel(IDocumentRedlineAccess const& rIDRA, + SwTextField const& rTextField) + { + SwRedlineTable::size_type tmp; + SwPosition const pos(rTextField.GetTextNode(), + rTextField.GetStart()); + SwRangeRedline const*const pRedline(rIDRA.GetRedline(pos, &tmp)); + return (pRedline + && pRedline->GetType() == nsRedlineType_t::REDLINE_DELETE + && *pRedline->GetPoint() != *pRedline->GetMark()); + } +} + namespace { #if HAVE_FEATURE_DBCONNECTIVITY @@ -94,13 +109,7 @@ namespace // for *any* layout... return true; } - SwRedlineTable::size_type tmp; - SwPosition const pos(const_cast(rTextField.GetTextNode()), - rTextField.GetStart()); - SwRangeRedline const*const pRedline(rIDRA.GetRedline(pos, &tmp)); - return (pRedline - && pRedline->GetType() == nsRedlineType_t::REDLINE_DELETE - && *pRedline->GetPoint() != *pRedline->GetMark()); + return sw::IsFieldDeletedInModel(rIDRA, rTextField); } void lcl_CalcField( SwDoc& rDoc, SwCalc& rCalc, const SetGetExpField& rSGEField, diff --git a/sw/source/core/fields/authfld.cxx b/sw/source/core/fields/authfld.cxx index 034a221e72e5..1e9c1ab6ed74 100644 --- a/sw/source/core/fields/authfld.cxx +++ b/sw/source/core/fields/authfld.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -231,7 +232,8 @@ sal_IntPtr SwAuthorityFieldType::GetHandle(sal_uInt16 nPos) return 0; } -sal_uInt16 SwAuthorityFieldType::GetSequencePos(sal_IntPtr nHandle) +sal_uInt16 SwAuthorityFieldType::GetSequencePos(sal_IntPtr nHandle, + SwRootFrame const*const pLayout) { //find the field in a sorted array of handles, #if OSL_DEBUG_LEVEL > 0 @@ -241,7 +243,11 @@ sal_uInt16 SwAuthorityFieldType::GetSequencePos(sal_IntPtr nHandle) DelSequenceArray(); if(m_SequArr.empty()) { + IDocumentRedlineAccess const& rIDRA(m_pDoc->getIDocumentRedlineAccess()); + // sw_redlinehide: need 2 arrays because the sorting may be different, + // if multiple fields refer to the same entry and first one is deleted std::vector> aSortArr; + std::vector> aSortArrRLHidden; SwIterator aIter( *this ); SwTOXInternational aIntl(m_eLanguage, SwTOIOptions::NONE, m_sSortAlgorithm); @@ -268,16 +274,21 @@ sal_uInt16 SwAuthorityFieldType::GetSequencePos(sal_IntPtr nHandle) //body the directly available text node will be used if(!pTextNode) pTextNode = &rFieldTextNode; - if (!pTextNode->GetText().isEmpty() && - pTextNode->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ) && - pTextNode->GetNodes().IsDocNodes() ) + if (pTextNode->GetText().isEmpty() + || !pTextNode->getLayoutFrame(rDoc.getIDocumentLayoutAccess().GetCurrentLayout()) + || !pTextNode->GetNodes().IsDocNodes()) + { + continue; + } + auto const InsertImpl = [&aIntl, pTextNode, pFormatField] + (std::vector> & rSortArr) { std::unique_ptr pNew( new SwTOXAuthority(*pTextNode, *pFormatField, aIntl)); - for(size_t i = 0; i < aSortArr.size(); ++i) + for (size_t i = 0; i < rSortArr.size(); ++i) { - SwTOXSortTabBase* pOld = aSortArr[i].get(); + SwTOXSortTabBase* pOld = rSortArr[i].get(); if(*pOld == *pNew) { //only the first occurrence in the document @@ -285,7 +296,7 @@ sal_uInt16 SwAuthorityFieldType::GetSequencePos(sal_IntPtr nHandle) if(*pOld < *pNew) pNew.reset(); else // remove the old content - aSortArr.erase(aSortArr.begin() + i); + rSortArr.erase(rSortArr.begin() + i); break; } } @@ -294,31 +305,41 @@ sal_uInt16 SwAuthorityFieldType::GetSequencePos(sal_IntPtr nHandle) { size_t j {0}; - while(j < aSortArr.size()) + while (j < rSortArr.size()) { - SwTOXSortTabBase* pOld = aSortArr[j].get(); + SwTOXSortTabBase* pOld = rSortArr[j].get(); if(*pNew < *pOld) break; ++j; } - aSortArr.insert(aSortArr.begin() + j, std::move(pNew)); + rSortArr.insert(rSortArr.begin() + j, std::move(pNew)); } + }; + InsertImpl(aSortArr); + if (!sw::IsFieldDeletedInModel(rIDRA, *pTextField)) + { + InsertImpl(aSortArrRLHidden); } } for(auto & pBase : aSortArr) { - SwTOXSortTabBase& rBase = *pBase; - SwFormatField& rFormatField = static_cast(rBase).GetFieldFormat(); + SwFormatField& rFormatField = static_cast(*pBase).GetFieldFormat(); SwAuthorityField* pAField = static_cast(rFormatField.GetField()); m_SequArr.push_back(pAField->GetHandle()); } - aSortArr.clear(); + for (auto & pBase : aSortArrRLHidden) + { + SwFormatField& rFormatField = static_cast(*pBase).GetFieldFormat(); + SwAuthorityField* pAField = static_cast(rFormatField.GetField()); + m_SequArrRLHidden.push_back(pAField->GetHandle()); + } } //find nHandle - for(std::vector::size_type i = 0; i < m_SequArr.size(); ++i) + auto const& rSequArr(pLayout && pLayout->IsHideRedlines() ? m_SequArrRLHidden : m_SequArr); + for (std::vector::size_type i = 0; i < rSequArr.size(); ++i) { - if(m_SequArr[i] == nHandle) + if (rSequArr[i] == nHandle) { return i + 1; } @@ -491,17 +512,19 @@ void SwAuthorityFieldType::SetSortKeys(sal_uInt16 nKeyCount, SwTOXSortKey const SwAuthorityField::SwAuthorityField( SwAuthorityFieldType* pInitType, const OUString& rFieldContents ) - : SwField(pInitType), - m_nTempSequencePos( -1 ) + : SwField(pInitType) + , m_nTempSequencePos( -1 ) + , m_nTempSequencePosRLHidden( -1 ) { m_nHandle = pInitType->AddField( rFieldContents ); } SwAuthorityField::SwAuthorityField( SwAuthorityFieldType* pInitType, sal_IntPtr nSetHandle ) - : SwField( pInitType ), - m_nHandle( nSetHandle ), - m_nTempSequencePos( -1 ) + : SwField( pInitType ) + , m_nHandle( nSetHandle ) + , m_nTempSequencePos( -1 ) + , m_nTempSequencePosRLHidden( -1 ) { pInitType->AddField( m_nHandle ); } @@ -511,12 +534,13 @@ SwAuthorityField::~SwAuthorityField() static_cast(GetTyp())->RemoveField(m_nHandle); } -OUString SwAuthorityField::ExpandImpl(SwRootFrame const*const) const +OUString SwAuthorityField::ExpandImpl(SwRootFrame const*const pLayout) const { - return ConditionalExpandAuthIdentifier(); + return ConditionalExpandAuthIdentifier(pLayout); } -OUString SwAuthorityField::ConditionalExpandAuthIdentifier() const +OUString SwAuthorityField::ConditionalExpandAuthIdentifier( + SwRootFrame const*const pLayout) const { SwAuthorityFieldType* pAuthType = static_cast(GetTyp()); OUString sRet; @@ -525,10 +549,12 @@ OUString SwAuthorityField::ConditionalExpandAuthIdentifier() const if( pAuthType->IsSequence() ) { + sal_IntPtr & rnTempSequencePos(pLayout && pLayout->IsHideRedlines() + ? m_nTempSequencePosRLHidden : m_nTempSequencePos); if(!pAuthType->GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked()) - m_nTempSequencePos = pAuthType->GetSequencePos( m_nHandle ); - if( m_nTempSequencePos >= 0 ) - sRet += OUString::number( m_nTempSequencePos ); + rnTempSequencePos = pAuthType->GetSequencePos(m_nHandle, pLayout); + if (0 <= rnTempSequencePos) + sRet += OUString::number(rnTempSequencePos); } else { @@ -542,17 +568,20 @@ OUString SwAuthorityField::ConditionalExpandAuthIdentifier() const return sRet; } -OUString SwAuthorityField::ExpandCitation(ToxAuthorityField eField) const +OUString SwAuthorityField::ExpandCitation(ToxAuthorityField eField, + SwRootFrame const*const pLayout) const { SwAuthorityFieldType* pAuthType = static_cast(GetTyp()); OUString sRet; if( pAuthType->IsSequence() ) { + sal_IntPtr & rnTempSequencePos(pLayout && pLayout->IsHideRedlines() + ? m_nTempSequencePosRLHidden : m_nTempSequencePos); if(!pAuthType->GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked()) - m_nTempSequencePos = pAuthType->GetSequencePos( m_nHandle ); - if( m_nTempSequencePos >= 0 ) - sRet += OUString::number( m_nTempSequencePos ); + rnTempSequencePos = pAuthType->GetSequencePos(m_nHandle, pLayout); + if (0 <= rnTempSequencePos) + sRet += OUString::number(rnTempSequencePos); } else { diff --git a/sw/source/core/fields/fldbas.cxx b/sw/source/core/fields/fldbas.cxx index 7be1be2d0f11..a5008b4c4e3a 100644 --- a/sw/source/core/fields/fldbas.cxx +++ b/sw/source/core/fields/fldbas.cxx @@ -418,7 +418,7 @@ SwField::ExpandField(bool const bCached, SwRootFrame const*const pLayout) const if (GetTypeId() == TYP_AUTHORITY) { const SwAuthorityField* pAuthorityField = static_cast(this); - m_Cache = pAuthorityField->ConditionalExpandAuthIdentifier(); + m_Cache = pAuthorityField->ConditionalExpandAuthIdentifier(pLayout); } else m_Cache = ExpandImpl(pLayout); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 796c6e621f8e..756cf145443a 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -1940,7 +1940,7 @@ void DocxAttributeOutput::EndField_Impl( const SwTextNode* pNode, sal_Int32 nPos if(rInfos.eType == ww::eCITATION) { sExpand = static_cast(rInfos.pField.get()) - ->ExpandCitation(AUTH_FIELD_TITLE); + ->ExpandCitation(AUTH_FIELD_TITLE, nullptr); } else { diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx index cbe0fa6ac810..3deb8c137891 100644 --- a/sw/source/filter/ww8/ww8atr.cxx +++ b/sw/source/filter/ww8/ww8atr.cxx @@ -2993,7 +2993,7 @@ void AttributeOutputBase::TextField( const SwFormatField& rField ) case SwFieldIds::TableOfAuthorities: { OUString sRet(static_cast(pField) - ->ExpandCitation(AUTH_FIELD_IDENTIFIER)); + ->ExpandCitation(AUTH_FIELD_IDENTIFIER, nullptr)); // FIXME: DomainMapper_Impl::CloseFieldCommand() stuffs fully formed // field instructions in here, but if the field doesn't originate // from those filters it won't have that -- cgit v1.2.3