summaryrefslogtreecommitdiffstats
path: root/sw/source/core/attr
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/core/attr
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/core/attr')
-rw-r--r--sw/source/core/attr/BorderCacheOwner.cxx48
-rw-r--r--sw/source/core/attr/calbck.cxx337
-rw-r--r--sw/source/core/attr/cellatr.cxx182
-rw-r--r--sw/source/core/attr/fmtfollowtextflow.cxx27
-rw-r--r--sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx174
-rw-r--r--sw/source/core/attr/format.cxx792
-rw-r--r--sw/source/core/attr/formatflysplit.cxx62
-rw-r--r--sw/source/core/attr/formatwraptextatflystart.cxx46
-rw-r--r--sw/source/core/attr/hints.cxx266
-rw-r--r--sw/source/core/attr/swatrset.cxx583
10 files changed, 2517 insertions, 0 deletions
diff --git a/sw/source/core/attr/BorderCacheOwner.cxx b/sw/source/core/attr/BorderCacheOwner.cxx
new file mode 100644
index 0000000000..dd71b69493
--- /dev/null
+++ b/sw/source/core/attr/BorderCacheOwner.cxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <BorderCacheOwner.hxx>
+
+#include <hintids.hxx>
+#include <frame.hxx>
+#include <swcache.hxx>
+
+using namespace sw;
+
+BorderCacheOwner::~BorderCacheOwner()
+{
+ if (m_bInCache)
+ SwFrame::GetCache().Delete(this);
+}
+
+void BorderCacheOwner::InvalidateInSwCache(const sal_uInt16 nWhich)
+{
+ switch (nWhich)
+ {
+ case RES_OBJECTDYING:
+ case RES_FMT_CHG:
+ case RES_ATTRSET_CHG:
+ case RES_UL_SPACE:
+ case RES_MARGIN_FIRSTLINE:
+ case RES_MARGIN_TEXTLEFT:
+ case RES_MARGIN_RIGHT:
+ case RES_LR_SPACE:
+ case RES_BOX:
+ case RES_SHADOW:
+ case RES_FRM_SIZE:
+ case RES_KEEP:
+ case RES_BREAK:
+ if (m_bInCache)
+ {
+ SwFrame::GetCache().Delete(this);
+ m_bInCache = false;
+ }
+ }
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/calbck.cxx b/sw/source/core/attr/calbck.cxx
new file mode 100644
index 0000000000..871dff4347
--- /dev/null
+++ b/sw/source/core/attr/calbck.cxx
@@ -0,0 +1,337 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <algorithm>
+#include <format.hxx>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <tools/debug.hxx>
+
+#ifdef DBG_UTIL
+#include <sal/backtrace.hxx>
+#endif
+
+namespace sw
+{
+ bool ListenerEntry::GetInfo(SfxPoolItem& rInfo) const
+ { return m_pToTell == nullptr || m_pToTell->GetInfo( rInfo ); }
+ void ListenerEntry::SwClientNotify(const SwModify& rModify, const SfxHint& rHint)
+ {
+ if (rHint.GetId() == SfxHintId::SwLegacyModify)
+ {
+ auto pLegacyHint = static_cast<const sw::LegacyModifyHint*>(&rHint);
+ if (pLegacyHint->m_pNew && pLegacyHint->m_pNew->Which() == RES_OBJECTDYING)
+ {
+ auto pModifyChanged = CheckRegistration(pLegacyHint->m_pOld);
+ if (pModifyChanged)
+ m_pToTell->SwClientNotify(rModify, *pModifyChanged);
+ }
+ else if (m_pToTell)
+ m_pToTell->SwClientNotify(rModify, rHint);
+ }
+ else if (m_pToTell)
+ m_pToTell->SwClientNotify(rModify, rHint);
+ }
+}
+
+sw::LegacyModifyHint::~LegacyModifyHint() {}
+
+SwClient::SwClient(SwClient&& o) noexcept
+ : m_pRegisteredIn(nullptr)
+{
+ if(o.m_pRegisteredIn)
+ {
+ o.m_pRegisteredIn->Add(this);
+ o.EndListeningAll();
+ }
+}
+
+SwClient::~SwClient()
+{
+ if(GetRegisteredIn())
+ DBG_TESTSOLARMUTEX();
+ OSL_ENSURE( !m_pRegisteredIn || m_pRegisteredIn->HasWriterListeners(), "SwModify still known, but Client already disconnected!" );
+ if( m_pRegisteredIn && m_pRegisteredIn->HasWriterListeners() )
+ m_pRegisteredIn->Remove( this );
+}
+
+std::optional<sw::ModifyChangedHint> SwClient::CheckRegistration( const SfxPoolItem* pOld )
+{
+ DBG_TESTSOLARMUTEX();
+ // this method only handles notification about dying SwModify objects
+ if( !pOld || pOld->Which() != RES_OBJECTDYING )
+ return {};
+
+ assert(dynamic_cast<const SwPtrMsgPoolItem*>(pOld));
+ const SwPtrMsgPoolItem* pDead = static_cast<const SwPtrMsgPoolItem*>(pOld);
+ if(pDead->pObject != m_pRegisteredIn)
+ {
+ // we should only care received death notes from objects we are following
+ return {};
+ }
+ // I've got a notification from the object I know
+ SwModify* pAbove = m_pRegisteredIn->GetRegisteredIn();
+ if(pAbove)
+ {
+ // if the dying object itself was listening at an SwModify, I take over
+ // adding myself to pAbove will automatically remove me from my current pRegisteredIn
+ pAbove->Add(this);
+ }
+ else
+ {
+ // destroy connection
+ EndListeningAll();
+ }
+ return sw::ModifyChangedHint(pAbove);
+}
+
+void SwClient::CheckRegistrationFormat(SwFormat& rOld)
+{
+ assert(GetRegisteredIn() == &rOld);
+ auto pNew = rOld.DerivedFrom();
+ SAL_INFO("sw.core", "reparenting " << typeid(*this).name() << " at " << this << " from " << typeid(rOld).name() << " at " << &rOld << " to " << typeid(*pNew).name() << " at " << pNew);
+ assert(pNew);
+ pNew->Add(this);
+ const SwFormatChg aOldFormat(&rOld);
+ const SwFormatChg aNewFormat(pNew);
+ const sw::LegacyModifyHint aHint(&aOldFormat, &aNewFormat);
+ SwClientNotify(rOld, aHint);
+}
+
+void SwClient::SwClientNotify(const SwModify&, const SfxHint& rHint)
+{
+ if (rHint.GetId() != SfxHintId::SwLegacyModify)
+ return;
+ auto pLegacyHint = static_cast<const sw::LegacyModifyHint*>(&rHint);
+ CheckRegistration(pLegacyHint->m_pOld);
+};
+
+void SwClient::StartListeningToSameModifyAs(const SwClient& other)
+{
+ if(other.m_pRegisteredIn)
+ other.m_pRegisteredIn->Add(this);
+ else
+ EndListeningAll();
+}
+
+void SwClient::EndListeningAll()
+{
+ if(m_pRegisteredIn)
+ m_pRegisteredIn->Remove(this);
+}
+
+SwModify::~SwModify()
+{
+ DBG_TESTSOLARMUTEX();
+ OSL_ENSURE( !IsModifyLocked(), "Modify destroyed but locked." );
+
+ // notify all clients that they shall remove themselves
+ SwPtrMsgPoolItem aDyObject( RES_OBJECTDYING, this );
+ SwModify::SwClientNotify(*this, sw::LegacyModifyHint(&aDyObject, &aDyObject));
+
+ const bool hasListenersOnDeath = m_pWriterListeners;
+ (void)hasListenersOnDeath;
+ while(m_pWriterListeners)
+ {
+ SAL_WARN("sw.core", "lost a client of type: " << typeid(*m_pWriterListeners).name() << " at " << m_pWriterListeners << " still registered on type: " << typeid(*this).name() << " at " << this << ".");
+ static_cast<SwClient*>(m_pWriterListeners)->CheckRegistration(&aDyObject);
+ }
+ assert(!hasListenersOnDeath);
+}
+
+bool SwModify::GetInfo( SfxPoolItem& rInfo ) const
+{
+ if(!m_pWriterListeners)
+ return true;
+ SwIterator<SwClient,SwModify> aIter(*this);
+ for(SwClient* pClient = aIter.First(); pClient; pClient = aIter.Next())
+ if(!pClient->GetInfo( rInfo ))
+ return false;
+ return true;
+}
+
+void SwModify::Add( SwClient* pDepend )
+{
+ DBG_TESTSOLARMUTEX();
+#ifdef DBG_UTIL
+ // You should not EVER use SwModify directly in new code:
+ // - Preexisting SwModifys should only ever be used via sw::BroadcastingModify.
+ // This includes sw::BroadcastMixin, which is the long-term target (without
+ // SwModify).
+ // - New classes should use sw::BroadcastMixin alone.
+ if(!dynamic_cast<sw::BroadcastingModify*>(this))
+ {
+ auto pBT = sal::backtrace_get(20);
+ SAL_WARN("sw.core", "Modify that is not broadcasting used!\n" << sal::backtrace_to_string(pBT.get()));
+ }
+#endif
+
+ if(pDepend->m_pRegisteredIn == this)
+ return;
+
+#if OSL_DEBUG_LEVEL > 0
+ if(sw::ClientIteratorBase::s_pClientIters)
+ {
+ for(auto& rIter : sw::ClientIteratorBase::s_pClientIters->GetRingContainer())
+ {
+ SAL_WARN_IF(&rIter.m_rRoot == m_pWriterListeners, "sw.core", "a " << typeid(*pDepend).name() << " client added as listener to a " << typeid(*this).name() << " during client iteration.");
+ }
+ }
+#endif
+ // deregister new client in case it is already registered elsewhere
+ if( pDepend->m_pRegisteredIn != nullptr )
+ pDepend->m_pRegisteredIn->Remove( pDepend );
+
+ if( !m_pWriterListeners )
+ {
+ // first client added
+ m_pWriterListeners = pDepend;
+ m_pWriterListeners->m_pLeft = nullptr;
+ m_pWriterListeners->m_pRight = nullptr;
+ }
+ else
+ {
+ // append client
+ pDepend->m_pRight = m_pWriterListeners->m_pRight;
+ m_pWriterListeners->m_pRight = pDepend;
+ pDepend->m_pLeft = m_pWriterListeners;
+ if( pDepend->m_pRight )
+ pDepend->m_pRight->m_pLeft = pDepend;
+ }
+
+ // connect client to me
+ pDepend->m_pRegisteredIn = this;
+}
+
+SwClient* SwModify::Remove( SwClient* pDepend )
+{
+ DBG_TESTSOLARMUTEX();
+ assert(pDepend->m_pRegisteredIn == this);
+
+ // SwClient is my listener
+ // remove it from my list
+ ::sw::WriterListener* pR = pDepend->m_pRight;
+ ::sw::WriterListener* pL = pDepend->m_pLeft;
+ if( m_pWriterListeners == pDepend )
+ m_pWriterListeners = pL ? pL : pR;
+
+ if( pL )
+ pL->m_pRight = pR;
+ if( pR )
+ pR->m_pLeft = pL;
+
+ // update ClientIterators
+ if(sw::ClientIteratorBase::s_pClientIters)
+ {
+ for(auto& rIter : sw::ClientIteratorBase::s_pClientIters->GetRingContainer())
+ {
+ if (&rIter.m_rRoot == this &&
+ (rIter.m_pCurrent == pDepend || rIter.m_pPosition == pDepend))
+ {
+ // if object being removed is the current or next object in an
+ // iterator, advance this iterator
+ rIter.m_pPosition = pR;
+ }
+ }
+ }
+ pDepend->m_pLeft = nullptr;
+ pDepend->m_pRight = nullptr;
+ pDepend->m_pRegisteredIn = nullptr;
+ return pDepend;
+}
+
+sw::WriterMultiListener::WriterMultiListener(SwClient& rToTell)
+ : m_rToTell(rToTell)
+{}
+
+sw::WriterMultiListener::~WriterMultiListener()
+{}
+
+void sw::WriterMultiListener::StartListening(SwModify* pDepend)
+{
+ EndListening(nullptr);
+ m_vDepends.emplace_back(&m_rToTell, pDepend);
+}
+
+
+bool sw::WriterMultiListener::IsListeningTo(const SwModify* const pBroadcaster) const
+{
+ return std::any_of(m_vDepends.begin(), m_vDepends.end(),
+ [&pBroadcaster](const ListenerEntry& aListener)
+ {
+ return aListener.GetRegisteredIn() == pBroadcaster;
+ });
+}
+
+void sw::WriterMultiListener::EndListening(SwModify* pBroadcaster)
+{
+ std::erase_if(
+ m_vDepends,
+ [&pBroadcaster](const ListenerEntry& aListener)
+ {
+ return aListener.GetRegisteredIn() == nullptr || aListener.GetRegisteredIn() == pBroadcaster;
+ });
+}
+
+void sw::WriterMultiListener::EndListeningAll()
+{
+ m_vDepends.clear();
+}
+
+sw::ClientIteratorBase* sw::ClientIteratorBase::s_pClientIters = nullptr;
+
+void SwModify::SwClientNotify(const SwModify&, const SfxHint& rHint)
+{
+ if (rHint.GetId() != SfxHintId::SwLegacyModify)
+ return;
+
+ DBG_TESTSOLARMUTEX();
+ if(IsModifyLocked())
+ return;
+
+ LockModify();
+ CallSwClientNotify(rHint);
+ UnlockModify();
+}
+
+void SwModify::CallSwClientNotify( const SfxHint& rHint ) const
+{
+ DBG_TESTSOLARMUTEX();
+ SwIterator<SwClient,SwModify> aIter(*this);
+ for(SwClient* pClient = aIter.First(); pClient; pClient = aIter.Next())
+ pClient->SwClientNotify( *this, rHint );
+}
+
+void sw::BroadcastingModify::CallSwClientNotify(const SfxHint& rHint) const
+{
+ SwModify::CallSwClientNotify(rHint);
+ const_cast<BroadcastingModify*>(this)->GetNotifier().Broadcast(rHint);
+}
+
+void sw::ClientNotifyAttrChg(SwModify& rModify, const SwAttrSet& aSet, SwAttrSet& aOld, SwAttrSet& aNew)
+{
+ const SwAttrSetChg aChgOld(aSet, aOld);
+ const SwAttrSetChg aChgNew(aSet, aNew);
+ const sw::LegacyModifyHint aHint(&aChgOld, &aChgNew);
+ rModify.SwClientNotify(rModify, aHint);
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/cellatr.cxx b/sw/source/core/attr/cellatr.cxx
new file mode 100644
index 0000000000..69eb6b1dd3
--- /dev/null
+++ b/sw/source/core/attr/cellatr.cxx
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <calc.hxx>
+#include <cellatr.hxx>
+#include <doc.hxx>
+#include <float.h>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <node.hxx>
+#include <rolbck.hxx>
+#include <rtl/ustring.hxx>
+#include <calbck.hxx>
+#include <swtable.hxx>
+
+// The % SV_COUNTRY_LANGUAGE_OFFSET result checks if nFormat is a mere built-in
+// @ Text format of *any* locale and if so uses the default text format. Text
+// is text, the locale doesn't matter for Writer's number formatting purposes.
+// The advantage is that this is the pool's default item value and some places
+// benefit from this special treatment in that they don't have to handle/store
+// attribute specifics, especially when writing a document.
+SwTableBoxNumFormat::SwTableBoxNumFormat( sal_uInt32 nFormat )
+ : SfxUInt32Item( RES_BOXATR_FORMAT,
+ (((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == getSwDefaultTextFormat()) ?
+ getSwDefaultTextFormat() : nFormat))
+{
+}
+
+bool SwTableBoxNumFormat::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+ return GetValue() == static_cast<const SwTableBoxNumFormat&>(rAttr).GetValue();
+}
+
+SwTableBoxNumFormat* SwTableBoxNumFormat::Clone( SfxItemPool* ) const
+{
+ return new SwTableBoxNumFormat( GetValue() );
+}
+
+SwTableBoxFormula::SwTableBoxFormula( const OUString& rFormula )
+ : SfxPoolItem( RES_BOXATR_FORMULA ),
+ SwTableFormula( rFormula ),
+ m_pDefinedIn( nullptr )
+{
+}
+
+bool SwTableBoxFormula::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+ return GetFormula() == static_cast<const SwTableBoxFormula&>(rAttr).GetFormula() &&
+ m_pDefinedIn == static_cast<const SwTableBoxFormula&>(rAttr).m_pDefinedIn;
+}
+
+SwTableBoxFormula* SwTableBoxFormula::Clone( SfxItemPool* ) const
+{
+ // switch to external rendering
+ SwTableBoxFormula* pNew = new SwTableBoxFormula( GetFormula() );
+ pNew->SwTableFormula::operator=( *this );
+ return pNew;
+}
+
+/** Get node type of the node containing this formula
+
+ E.g. TextField -> TextNode, or
+ BoxAttribute -> BoxStartNode
+
+ Caution: Must override when inheriting.
+*/
+const SwNode* SwTableBoxFormula::GetNodeOfFormula() const
+{
+ auto pTableBox = GetTableBox();
+ return pTableBox ? pTableBox->GetSttNd() : nullptr;
+}
+
+SwTableBox* SwTableBoxFormula::GetTableBox()
+{
+ assert(!m_pDefinedIn || dynamic_cast<SwTableBoxFormat*>(m_pDefinedIn));
+ return m_pDefinedIn ? static_cast<SwTableBoxFormat*>(m_pDefinedIn)->GetTableBox() : nullptr;
+}
+
+void SwTableBoxFormula::TryBoxNmToPtr()
+{
+ const SwNode* pNd = GetNodeOfFormula();
+ if (!pNd || &pNd->GetNodes() != &pNd->GetDoc().GetNodes())
+ return;
+ if(const SwTableNode* pTableNd = pNd->FindTableNode())
+ {
+ BoxNmToPtr(&pTableNd->GetTable());
+ }
+}
+
+void SwTableBoxFormula::TryRelBoxNm()
+{
+ const SwNode* pNd = GetNodeOfFormula();
+ if (!pNd || &pNd->GetNodes() != &pNd->GetDoc().GetNodes())
+ return;
+ if(const SwTableNode* pTableNd = pNd->FindTableNode())
+ {
+ ToRelBoxNm(&pTableNd->GetTable());
+ }
+}
+
+void SwTableBoxFormula::ToSplitMergeBoxNmWithHistory(SwTableFormulaUpdate& rUpdate, SwHistory* pHistory)
+{
+ if(!pHistory)
+ {
+ ToSplitMergeBoxNm(rUpdate);
+ return;
+ }
+ auto pNd = GetNodeOfFormula();
+ // for a history record the unchanged formula is needed
+ SwTableBoxFormula aCopy(*this);
+ rUpdate.m_bModified = false;
+ ToSplitMergeBoxNm(rUpdate);
+ if(rUpdate.m_bModified)
+ {
+ // external rendering
+ aCopy.PtrToBoxNm(&pNd->FindTableNode()->GetTable());
+ pHistory->AddPoolItem(
+ &aCopy,
+ &aCopy,
+ pNd->FindTableBoxStartNode()->GetIndex());
+ }
+}
+
+void SwTableBoxFormula::Calc( SwTableCalcPara& rCalcPara, double& rValue )
+{
+ if( !rCalcPara.m_rCalc.IsCalcError() )
+ {
+ // create pointers from box names
+ BoxNmToPtr( rCalcPara.m_pTable );
+ const OUString sFormula( MakeFormula( rCalcPara ));
+ if( !rCalcPara.m_rCalc.IsCalcError() )
+ rValue = rCalcPara.m_rCalc.Calculate( sFormula ).GetDouble();
+ else
+ rValue = DBL_MAX;
+ ChgValid( !rCalcPara.IsStackOverflow() ); // value is now valid again
+ }
+}
+
+SwTableBoxValue::SwTableBoxValue()
+ : SfxPoolItem( RES_BOXATR_VALUE ), m_nValue( 0 )
+{
+}
+
+SwTableBoxValue::SwTableBoxValue( const double nVal )
+ : SfxPoolItem( RES_BOXATR_VALUE ), m_nValue( nVal )
+{
+}
+
+bool SwTableBoxValue::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+ SwTableBoxValue const& rOther( static_cast<SwTableBoxValue const&>(rAttr) );
+ // items with NaN should be equal to enable pooling
+ return std::isnan( m_nValue )
+ ? std::isnan( rOther.m_nValue )
+ : ( m_nValue == rOther.m_nValue );
+}
+
+SwTableBoxValue* SwTableBoxValue::Clone( SfxItemPool* ) const
+{
+ return new SwTableBoxValue( m_nValue );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/fmtfollowtextflow.cxx b/sw/source/core/attr/fmtfollowtextflow.cxx
new file mode 100644
index 0000000000..5b42405373
--- /dev/null
+++ b/sw/source/core/attr/fmtfollowtextflow.cxx
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <fmtfollowtextflow.hxx>
+
+SwFormatFollowTextFlow* SwFormatFollowTextFlow::Clone(SfxItemPool*) const
+{
+ return new SwFormatFollowTextFlow(*this);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx b/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx
new file mode 100644
index 0000000000..8f9abd96c7
--- /dev/null
+++ b/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <fmtwrapinfluenceonobjpos.hxx>
+#include <unomid.h>
+#include <osl/diagnose.h>
+#include <libxml/xmlwriter.h>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+SwFormatWrapInfluenceOnObjPos::SwFormatWrapInfluenceOnObjPos( sal_Int16 _nWrapInfluenceOnPosition )
+ : SfxPoolItem( RES_WRAP_INFLUENCE_ON_OBJPOS ),
+ mnWrapInfluenceOnPosition( _nWrapInfluenceOnPosition )
+{
+}
+
+SwFormatWrapInfluenceOnObjPos::~SwFormatWrapInfluenceOnObjPos()
+{
+}
+
+bool SwFormatWrapInfluenceOnObjPos::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+ const SwFormatWrapInfluenceOnObjPos& rAttribute
+ = static_cast<const SwFormatWrapInfluenceOnObjPos&>(rAttr);
+ return (mnWrapInfluenceOnPosition == rAttribute.GetWrapInfluenceOnObjPos()
+ && mbAllowOverlap == rAttribute.mbAllowOverlap
+ && mnOverlapVertOffset == rAttribute.mnOverlapVertOffset);
+}
+
+SwFormatWrapInfluenceOnObjPos* SwFormatWrapInfluenceOnObjPos::Clone( SfxItemPool * ) const
+{
+ return new SwFormatWrapInfluenceOnObjPos(*this);
+}
+
+bool SwFormatWrapInfluenceOnObjPos::QueryValue( Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ if( nMemberId == MID_WRAP_INFLUENCE )
+ {
+ rVal <<= GetWrapInfluenceOnObjPos();
+ }
+ else if( nMemberId == MID_ALLOW_OVERLAP )
+ {
+ rVal <<= GetAllowOverlap();
+ }
+ else
+ {
+ OSL_FAIL( "<SwFormatWrapInfluenceOnObjPos::QueryValue()> - unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFormatWrapInfluenceOnObjPos::PutValue( const Any& rVal, sal_uInt8 nMemberId )
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = false;
+
+ if( nMemberId == MID_WRAP_INFLUENCE )
+ {
+ sal_Int16 nNewWrapInfluence = 0;
+ rVal >>= nNewWrapInfluence;
+ // #i35017# - constant names have changed and <ITERATIVE> has been added
+ if ( nNewWrapInfluence == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ||
+ nNewWrapInfluence == text::WrapInfluenceOnPosition::ONCE_CONCURRENT ||
+ nNewWrapInfluence == text::WrapInfluenceOnPosition::ITERATIVE )
+ {
+ SetWrapInfluenceOnObjPos( nNewWrapInfluence );
+ bRet = true;
+ }
+ else
+ {
+ OSL_FAIL( "<SwFormatWrapInfluenceOnObjPos::PutValue(..)> - invalid attribute value" );
+ }
+ }
+ else if( nMemberId == MID_ALLOW_OVERLAP )
+ {
+ bool bAllowOverlap = true;
+ if (rVal >>= bAllowOverlap)
+ {
+ SetAllowOverlap(bAllowOverlap);
+ bRet = true;
+ }
+ else
+ {
+ SAL_WARN("sw.core", "SwFormatWrapInfluenceOnObjPos::PutValue: invalid AllowOverlap type");
+ }
+ }
+ else
+ {
+ OSL_FAIL( "<SwFormatWrapInfluenceOnObjPos::PutValue(..)> - unknown MemberId" );
+ }
+ return bRet;
+}
+
+void SwFormatWrapInfluenceOnObjPos::SetWrapInfluenceOnObjPos( sal_Int16 _nWrapInfluenceOnPosition )
+{
+ // #i35017# - constant names have changed and consider new value <ITERATIVE>
+ if ( _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ||
+ _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_CONCURRENT ||
+ _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ITERATIVE )
+ {
+ mnWrapInfluenceOnPosition = _nWrapInfluenceOnPosition;
+ }
+ else
+ {
+ OSL_FAIL( "<SwFormatWrapInfluenceOnObjPos::SetWrapInfluenceOnObjPos(..)> - invalid attribute value" );
+ }
+}
+
+// #i35017# - add parameter <_bIterativeAsOnceConcurrent> to control, if
+// value <ITERATIVE> has to be treated as <ONCE_CONCURRENT>
+sal_Int16 SwFormatWrapInfluenceOnObjPos::GetWrapInfluenceOnObjPos(
+ const bool _bIterativeAsOnceConcurrent ) const
+{
+ sal_Int16 nWrapInfluenceOnPosition( mnWrapInfluenceOnPosition );
+
+ if ( _bIterativeAsOnceConcurrent &&
+ nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ITERATIVE )
+ {
+ nWrapInfluenceOnPosition = text::WrapInfluenceOnPosition::ONCE_CONCURRENT;
+ }
+
+ return nWrapInfluenceOnPosition;
+}
+
+void SwFormatWrapInfluenceOnObjPos::SetAllowOverlap(bool bAllowOverlap)
+{
+ mbAllowOverlap = bAllowOverlap;
+}
+
+bool SwFormatWrapInfluenceOnObjPos::GetAllowOverlap() const
+{
+ return mbAllowOverlap;
+}
+
+void SwFormatWrapInfluenceOnObjPos::SetOverlapVertOffset(SwTwips nOverlapVertOffset)
+{
+ mnOverlapVertOffset = nOverlapVertOffset;
+}
+
+SwTwips SwFormatWrapInfluenceOnObjPos::GetOverlapVertOffset() const { return mnOverlapVertOffset; }
+
+void SwFormatWrapInfluenceOnObjPos::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatWrapInfluenceOnObjPos"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nWrapInfluenceOnPosition"), BAD_CAST(OString::number(mnWrapInfluenceOnPosition).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("mbAllowOverlap"), BAD_CAST(OString::boolean(mbAllowOverlap).getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/format.cxx b/sw/source/core/attr/format.cxx
new file mode 100644
index 0000000000..6f2f076881
--- /dev/null
+++ b/sw/source/core/attr/format.cxx
@@ -0,0 +1,792 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DocumentSettingManager.hxx> //For SwFmt::getIDocumentSettingAccess()
+#include <IDocumentTimerAccess.hxx>
+#include <doc.hxx>
+#include <fmtcolfunc.hxx>
+#include <format.hxx>
+#include <frmatr.hxx>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <o3tl/unit_conversion.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <svl/grabbagitem.hxx>
+#include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
+#include <svx/unobrushitemhelper.hxx>
+#include <svx/xdef.hxx>
+#include <utility>
+
+using namespace com::sun::star;
+
+SwFormat::SwFormat( SwAttrPool& rPool, const char* pFormatNm,
+ const WhichRangesContainer& pWhichRanges, SwFormat *pDrvdFrame,
+ sal_uInt16 nFormatWhich ) :
+ m_aFormatName( OUString::createFromAscii(pFormatNm) ),
+ m_aSet( rPool, pWhichRanges ),
+ m_nWhichId( nFormatWhich ),
+ m_nPoolFormatId( USHRT_MAX ),
+ m_nPoolHelpId( USHRT_MAX ),
+ m_nPoolHlpFileId( UCHAR_MAX )
+{
+ m_bAutoUpdateOnDirectFormat = false; // LAYER_IMPL
+ m_bAutoFormat = true;
+ m_bFormatInDTOR = m_bHidden = false;
+
+ if( pDrvdFrame )
+ {
+ pDrvdFrame->Add(this);
+ m_aSet.SetParent( &pDrvdFrame->m_aSet );
+ }
+}
+
+SwFormat::SwFormat( SwAttrPool& rPool, OUString aFormatNm,
+ const WhichRangesContainer& pWhichRanges, SwFormat* pDrvdFrame,
+ sal_uInt16 nFormatWhich ) :
+ m_aFormatName( std::move(aFormatNm) ),
+ m_aSet( rPool, pWhichRanges ),
+ m_nWhichId( nFormatWhich ),
+ m_nPoolFormatId( USHRT_MAX ),
+ m_nPoolHelpId( USHRT_MAX ),
+ m_nPoolHlpFileId( UCHAR_MAX )
+{
+ m_bAutoUpdateOnDirectFormat = false; // LAYER_IMPL
+ m_bAutoFormat = true;
+ m_bFormatInDTOR = m_bHidden = false;
+
+ if( pDrvdFrame )
+ {
+ pDrvdFrame->Add(this);
+ m_aSet.SetParent( &pDrvdFrame->m_aSet );
+ }
+}
+
+SwFormat::SwFormat( const SwFormat& rFormat ) :
+ sw::BorderCacheOwner(),
+ m_aFormatName( rFormat.m_aFormatName ),
+ m_aSet( rFormat.m_aSet ),
+ m_nWhichId( rFormat.m_nWhichId ),
+ m_nPoolFormatId( rFormat.GetPoolFormatId() ),
+ m_nPoolHelpId( rFormat.GetPoolHelpId() ),
+ m_nPoolHlpFileId( rFormat.GetPoolHlpFileId() )
+{
+ m_bFormatInDTOR = false; // LAYER_IMPL
+ m_bAutoFormat = rFormat.m_bAutoFormat;
+ m_bHidden = rFormat.m_bHidden;
+ m_bAutoUpdateOnDirectFormat = rFormat.m_bAutoUpdateOnDirectFormat;
+
+ if( auto pDerived = rFormat.DerivedFrom() )
+ {
+ pDerived->Add(this);
+ m_aSet.SetParent( &pDerived->m_aSet );
+ }
+ // a few special treatments for attributes
+ m_aSet.SetModifyAtAttr( this );
+}
+
+SwFormat &SwFormat::operator=(const SwFormat& rFormat)
+{
+ if(this == &rFormat)
+ return *this;
+
+ m_nWhichId = rFormat.m_nWhichId;
+ m_nPoolFormatId = rFormat.GetPoolFormatId();
+ m_nPoolHelpId = rFormat.GetPoolHelpId();
+ m_nPoolHlpFileId = rFormat.GetPoolHlpFileId();
+
+ InvalidateInSwCache(RES_OBJECTDYING);
+
+ // copy only array with attributes delta
+ SwAttrSet aOld( *m_aSet.GetPool(), m_aSet.GetRanges() ),
+ aNew( *m_aSet.GetPool(), m_aSet.GetRanges() );
+ m_aSet.Intersect_BC( rFormat.m_aSet, &aOld, &aNew );
+ (void)m_aSet.Put_BC( rFormat.m_aSet, &aOld, &aNew );
+
+ // a few special treatments for attributes
+ m_aSet.SetModifyAtAttr( this );
+
+ // create PoolItem attribute for Modify
+ if( aOld.Count() )
+ {
+ sw::ClientNotifyAttrChg(*this, m_aSet, aOld, aNew);
+ }
+
+ if(GetRegisteredIn() != rFormat.GetRegisteredIn())
+ {
+ StartListeningToSameModifyAs(rFormat);
+ m_aSet.SetParent( GetRegisteredIn()
+ ? &rFormat.m_aSet
+ : nullptr);
+ }
+
+ m_bAutoFormat = rFormat.m_bAutoFormat;
+ m_bHidden = rFormat.m_bHidden;
+ m_bAutoUpdateOnDirectFormat = rFormat.m_bAutoUpdateOnDirectFormat;
+ return *this;
+}
+
+void SwFormat::SetFormatName( const OUString& rNewName, bool bBroadcast )
+{
+ OSL_ENSURE( !IsDefault(), "SetName: Defaultformat" );
+ if( bBroadcast )
+ {
+ m_aFormatName = rNewName;
+ const sw::NameChanged aHint(m_aFormatName, rNewName);
+ SwClientNotify(*this, aHint);
+ }
+ else
+ {
+ m_aFormatName = rNewName;
+ }
+}
+
+/** Copy attributes
+
+ This function is called in every Copy-Ctor for copying the attributes.
+ The latter can be only copied as soon as the derived class exists since
+ for setting them the Which() function is called and that has the default
+ value of 0 in the base class and is then overridden by the derived class.
+
+ If we copy over multiple documents then the new document has to be provided
+ in which <this> is defined. Currently this is important for DropCaps
+ because that contains data that needs to be copied deeply.
+*/
+void SwFormat::CopyAttrs( const SwFormat& rFormat )
+{
+ // copy only array with attributes delta
+ InvalidateInSwCache(RES_ATTRSET_CHG);
+ InvalidateInSwFntCache(RES_ATTRSET_CHG);
+
+ // special treatments for some attributes
+ SwAttrSet* pChgSet = const_cast<SwAttrSet*>(&rFormat.m_aSet);
+
+ // copy only array with attributes delta
+ if( pChgSet->GetPool() != m_aSet.GetPool() )
+ pChgSet->CopyToModify( *this );
+ else
+ {
+ SwAttrSet aOld( *m_aSet.GetPool(), m_aSet.GetRanges() ),
+ aNew( *m_aSet.GetPool(), m_aSet.GetRanges() );
+
+ if ( m_aSet.Put_BC( *pChgSet, &aOld, &aNew ) )
+ {
+ // a few special treatments for attributes
+ m_aSet.SetModifyAtAttr( this );
+
+ SwAttrSetChg aChgOld( m_aSet, aOld );
+ SwAttrSetChg aChgNew( m_aSet, aNew );
+ SwClientNotify(*this, sw::LegacyModifyHint(&aChgOld, &aChgNew)); // send all modified ones
+ }
+ }
+
+ if( pChgSet != &rFormat.m_aSet ) // was a Set created?
+ delete pChgSet;
+}
+
+SwFormat::~SwFormat()
+{
+ // This happens at an ObjectDying message. Thus put all dependent
+ // ones on DerivedFrom.
+ if(!HasWriterListeners())
+ return;
+
+ m_bFormatInDTOR = true;
+
+ if(!DerivedFrom())
+ {
+ SwFormat::ResetFormatAttr(RES_PAGEDESC);
+ SAL_WARN("sw.core", "~SwFormat: format still has clients on death, but parent format is missing: " << GetName());
+ return;
+ }
+ SwIterator<SwClient,SwFormat> aIter(*this);
+ for(SwClient* pClient = aIter.First(); pClient; pClient = aIter.Next())
+ pClient->CheckRegistrationFormat(*this);
+ assert(!HasWriterListeners());
+}
+
+void SwFormat::SwClientNotify(const SwModify&, const SfxHint& rHint)
+{
+ if (rHint.GetId() != SfxHintId::SwLegacyModify)
+ return;
+ auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
+
+ std::optional<SwAttrSetChg> oOldClientChg, oNewClientChg;
+ std::optional<sw::LegacyModifyHint> oDependsHint(std::in_place, pLegacy->m_pOld, pLegacy->m_pNew);
+ const sal_uInt16 nWhich = pLegacy->GetWhich();
+ InvalidateInSwCache(nWhich);
+ switch(nWhich)
+ {
+ case 0:
+ break;
+ case RES_OBJECTDYING:
+ {
+ // NB: this still notifies depends even if pLegacy->m_pNew is nullptr, which seems non-obvious
+ if(!pLegacy->m_pNew)
+ break;
+ // If the dying object is the parent format of this format so
+ // attach this to the parent of the parent
+ SwFormat* pFormat = static_cast<SwFormat*>(pLegacy->m_pNew->StaticWhichCast(RES_OBJECTDYING).pObject);
+
+ // do not move if this is the topmost format
+ if(GetRegisteredIn() && GetRegisteredIn() == pFormat)
+ {
+ if(pFormat->GetRegisteredIn())
+ {
+ // if parent so register in new parent
+ pFormat->DerivedFrom()->Add(this);
+ m_aSet.SetParent(&DerivedFrom()->m_aSet);
+ }
+ else
+ {
+ // otherwise de-register at least from dying one
+ EndListeningAll();
+ m_aSet.SetParent(nullptr);
+ }
+ }
+ break;
+ }
+ case RES_ATTRSET_CHG:
+ {
+ // NB: this still notifies depends even if this condition is not met, which seems non-obvious
+ auto pOldAttrSetChg = static_cast<const SwAttrSetChg*>(pLegacy->m_pOld);
+ auto pNewAttrSetChg = static_cast<const SwAttrSetChg*>(pLegacy->m_pNew);
+ if (pOldAttrSetChg && pNewAttrSetChg && pOldAttrSetChg->GetTheChgdSet() != &m_aSet)
+ {
+ // pass only those that are not set...
+ oNewClientChg.emplace(*pNewAttrSetChg);
+ oNewClientChg->GetChgSet()->Differentiate(m_aSet);
+ if(oNewClientChg->Count()) // ... if any
+ {
+ oOldClientChg.emplace(*pOldAttrSetChg);
+ oOldClientChg->GetChgSet()->Differentiate(m_aSet);
+ oDependsHint.emplace(&*oOldClientChg, &*oNewClientChg);
+ }
+ else
+ oDependsHint.reset();
+ }
+ break;
+ }
+ case RES_FMT_CHG:
+ {
+ // if the format parent will be moved so register my attribute set at
+ // the new one
+
+ // skip my own Modify
+ // NB: this still notifies depends even if this condition is not met, which seems non-obvious
+ auto pOldFormatChg = static_cast<const SwFormatChg*>(pLegacy->m_pOld);
+ auto pNewFormatChg = static_cast<const SwFormatChg*>(pLegacy->m_pNew);
+ if(pOldFormatChg && pNewFormatChg && pOldFormatChg->pChangedFormat != this && pNewFormatChg->pChangedFormat == GetRegisteredIn())
+ {
+ // attach Set to new parent
+ m_aSet.SetParent(DerivedFrom() ? &DerivedFrom()->m_aSet : nullptr);
+ }
+ break;
+ }
+ default:
+ // attribute is defined in this format
+ if(SfxItemState::SET == m_aSet.GetItemState(nWhich, false))
+ {
+ // DropCaps might come into this block
+ SAL_WARN_IF(RES_PARATR_DROP != nWhich, "sw.core", "Hint was sent without sender");
+ oDependsHint.reset();
+ }
+ }
+ if(oDependsHint)
+ {
+ InvalidateInSwFntCache(oDependsHint->GetWhich());
+ SwModify::SwClientNotify(*this, *oDependsHint);
+ }
+}
+
+bool SwFormat::SetDerivedFrom(SwFormat *pDerFrom)
+{
+ if ( pDerFrom )
+ {
+ const SwFormat* pFormat = pDerFrom;
+ while ( pFormat != nullptr )
+ {
+ if ( pFormat == this )
+ return false;
+
+ pFormat=pFormat->DerivedFrom();
+ }
+ }
+ else
+ {
+ // nothing provided, search for Dflt format
+ pDerFrom = this;
+ while ( pDerFrom->DerivedFrom() )
+ pDerFrom = pDerFrom->DerivedFrom();
+ }
+ if ( (pDerFrom == DerivedFrom()) || (pDerFrom == this) )
+ return false;
+
+ assert( Which()==pDerFrom->Which()
+ || (Which()==RES_CONDTXTFMTCOLL && pDerFrom->Which()==RES_TXTFMTCOLL)
+ || (Which()==RES_TXTFMTCOLL && pDerFrom->Which()==RES_CONDTXTFMTCOLL)
+ || (Which()==RES_FLYFRMFMT && pDerFrom->Which()==RES_FRMFMT)
+ );
+
+ InvalidateInSwCache(RES_ATTRSET_CHG);
+ InvalidateInSwFntCache(RES_ATTRSET_CHG);
+
+ pDerFrom->Add( this );
+ m_aSet.SetParent( &pDerFrom->m_aSet );
+
+ SwFormatChg aOldFormat( this );
+ SwFormatChg aNewFormat( this );
+ const sw::LegacyModifyHint aHint(&aOldFormat, &aNewFormat);
+ SwClientNotify(*this, aHint);
+
+ return true;
+}
+
+bool SwFormat::supportsFullDrawingLayerFillAttributeSet() const
+{
+ return false;
+}
+
+const SfxPoolItem& SwFormat::GetFormatAttr( sal_uInt16 nWhich, bool bInParents ) const
+{
+ if (RES_BACKGROUND == nWhich && supportsFullDrawingLayerFillAttributeSet())
+ {
+ // FALLBACKBREAKHERE should not be used; instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST]
+ SAL_INFO("sw.core", "Do no longer use SvxBrushItem, instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST] FillAttributes or makeBackgroundBrushItem (simple fallback is in place and used)");
+ static std::unique_ptr<SvxBrushItem> aSvxBrushItem; //(std::make_shared<SvxBrushItem>(RES_BACKGROUND));
+
+ // fill the local static SvxBrushItem from the current ItemSet so that
+ // the fill attributes [XATTR_FILL_FIRST .. XATTR_FILL_LAST] are used
+ // as good as possible to create a fallback representation and return that
+ aSvxBrushItem = getSvxBrushItemFromSourceSet(m_aSet, RES_BACKGROUND, bInParents);
+
+ return *aSvxBrushItem;
+ }
+
+ return m_aSet.Get( nWhich, bInParents );
+}
+
+SfxItemState SwFormat::GetItemState( sal_uInt16 nWhich, bool bSrchInParent, const SfxPoolItem **ppItem ) const
+{
+ if (RES_BACKGROUND == nWhich && supportsFullDrawingLayerFillAttributeSet())
+ {
+ // FALLBACKBREAKHERE should not be used; instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST]
+ SAL_INFO("sw.core", "Do no longer use SvxBrushItem, instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST] FillAttributes or SwFormat::GetBackgroundStat (simple fallback is in place and used)");
+ const drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFill = getSdrAllFillAttributesHelper();
+
+ // check if the new fill attributes are used
+ if(aFill && aFill->isUsed())
+ {
+ // if yes, fill the local SvxBrushItem using the new fill attributes
+ // as good as possible to have an instance for the pointer to point
+ // to and return as state that it is set
+ static std::unique_ptr<SvxBrushItem> aSvxBrushItem; //(RES_BACKGROUND);
+
+ aSvxBrushItem = getSvxBrushItemFromSourceSet(m_aSet, RES_BACKGROUND, bSrchInParent);
+ if( ppItem )
+ *ppItem = aSvxBrushItem.get();
+
+ return SfxItemState::SET;
+ }
+
+ // if not, reset pointer and return SfxItemState::DEFAULT to signal that
+ // the item is not set
+ if( ppItem )
+ *ppItem = nullptr;
+
+ return SfxItemState::DEFAULT;
+ }
+
+ return m_aSet.GetItemState( nWhich, bSrchInParent, ppItem );
+}
+
+SfxItemState SwFormat::GetBackgroundState(std::unique_ptr<SvxBrushItem>& rItem) const
+{
+ if (supportsFullDrawingLayerFillAttributeSet())
+ {
+ // FALLBACKBREAKHERE should not be used; instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST]
+ const drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFill = getSdrAllFillAttributesHelper();
+
+ // check if the new fill attributes are used
+ if(aFill && aFill->isUsed())
+ {
+ // if yes, fill the local SvxBrushItem using the new fill attributes
+ // as good as possible to have an instance for the pointer to point
+ // to and return as state that it is set
+ rItem = getSvxBrushItemFromSourceSet(m_aSet, RES_BACKGROUND);
+ return SfxItemState::SET;
+ }
+
+ // if not return SfxItemState::DEFAULT to signal that the item is not set
+ return SfxItemState::DEFAULT;
+ }
+
+ const SvxBrushItem* pItem = nullptr;
+ SfxItemState eRet = m_aSet.GetItemState(RES_BACKGROUND, true, &pItem);
+ if (pItem)
+ rItem.reset(pItem->Clone());
+ return eRet;
+}
+
+bool SwFormat::SetFormatAttr( const SfxPoolItem& rAttr )
+{
+ const sal_uInt16 nWhich = rAttr.Which();
+ InvalidateInSwFntCache( nWhich );
+ InvalidateInSwCache( nWhich );
+
+ bool bRet = false;
+
+ if (RES_BACKGROUND == rAttr.Which() && supportsFullDrawingLayerFillAttributeSet())
+ {
+ // FALLBACKBREAKHERE should not be used; instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST]
+ SAL_INFO("sw.core", "Do no longer use SvxBrushItem, instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST] FillAttributes (simple fallback is in place and used)");
+ SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aTempSet(*m_aSet.GetPool());
+ const SvxBrushItem& rSource = rAttr.StaticWhichCast(RES_BACKGROUND);
+
+ // fill a local ItemSet with the attributes corresponding as good as possible
+ // to the new fill properties [XATTR_FILL_FIRST .. XATTR_FILL_LAST] and set these
+ // as ItemSet
+ setSvxBrushItemAsFillAttributesToTargetSet(rSource, aTempSet);
+
+ if(IsModifyLocked())
+ {
+ bRet = m_aSet.Put( aTempSet );
+ if( bRet )
+ {
+ m_aSet.SetModifyAtAttr( this );
+ }
+ }
+ else
+ {
+ SwAttrSet aOld(*m_aSet.GetPool(), m_aSet.GetRanges()), aNew(*m_aSet.GetPool(), m_aSet.GetRanges());
+
+ bRet = m_aSet.Put_BC(aTempSet, &aOld, &aNew);
+
+ if(bRet)
+ {
+ m_aSet.SetModifyAtAttr(this);
+ sw::ClientNotifyAttrChg(*this, m_aSet, aOld, aNew);
+ }
+ }
+
+ return bRet;
+ }
+
+ // if Modify is locked then no modifications will be sent;
+ // but call Modify always for FrameFormats
+ const sal_uInt16 nFormatWhich = Which();
+ if( IsModifyLocked() ||
+ ( !HasWriterListeners() &&
+ (RES_GRFFMTCOLL == nFormatWhich ||
+ RES_TXTFMTCOLL == nFormatWhich ) ) )
+ {
+ bRet = nullptr != m_aSet.Put( rAttr );
+ if( bRet )
+ m_aSet.SetModifyAtAttr( this );
+ // #i71574#
+ if ( nFormatWhich == RES_TXTFMTCOLL && rAttr.Which() == RES_PARATR_NUMRULE )
+ {
+ TextFormatCollFunc::CheckTextFormatCollForDeletionOfAssignmentToOutlineStyle( this );
+ }
+ }
+ else
+ {
+ // copy only array with attributes delta
+ SwAttrSet aOld( *m_aSet.GetPool(), m_aSet.GetRanges() ),
+ aNew( *m_aSet.GetPool(), m_aSet.GetRanges() );
+
+ bRet = m_aSet.Put_BC( rAttr, &aOld, &aNew );
+ if( bRet )
+ {
+ // some special treatments for attributes
+ m_aSet.SetModifyAtAttr( this );
+
+ sw::ClientNotifyAttrChg(*this, m_aSet, aOld, aNew);
+ }
+ }
+ return bRet;
+}
+
+bool SwFormat::SetFormatAttr( const SfxItemSet& rSet )
+{
+ if( !rSet.Count() )
+ return false;
+
+ InvalidateInSwCache(RES_ATTRSET_CHG);
+ InvalidateInSwFntCache(RES_ATTRSET_CHG);
+
+ bool bRet = false;
+
+ // Use local copy to be able to apply needed changes, e.g. call
+ // CheckForUniqueItemForLineFillNameOrIndex which is needed for NameOrIndex stuff
+ SfxItemSet aTempSet(rSet);
+
+ // Need to check for unique item for DrawingLayer items of type NameOrIndex
+ // and evtl. correct that item to ensure unique names for that type. This call may
+ // modify/correct entries inside of the given SfxItemSet
+ if(GetDoc())
+ {
+ GetDoc()->CheckForUniqueItemForLineFillNameOrIndex(aTempSet);
+ }
+
+ if (supportsFullDrawingLayerFillAttributeSet())
+ {
+ if(const SvxBrushItem* pSource = aTempSet.GetItemIfSet(RES_BACKGROUND, false))
+ {
+ // FALLBACKBREAKHERE should not be used; instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST]
+ SAL_INFO("sw.core", "Do no longer use SvxBrushItem, instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST] FillAttributes (simple fallback is in place and used)");
+
+ // copy all items to be set anyways to a local ItemSet with is also prepared for the new
+ // fill attribute ranges [XATTR_FILL_FIRST .. XATTR_FILL_LAST]. Add the attributes
+ // corresponding as good as possible to the new fill properties and set the whole ItemSet
+ setSvxBrushItemAsFillAttributesToTargetSet(*pSource, aTempSet);
+
+ if(IsModifyLocked())
+ {
+ bRet = m_aSet.Put( aTempSet );
+ if( bRet )
+ {
+ m_aSet.SetModifyAtAttr( this );
+ }
+ }
+ else
+ {
+ SwAttrSet aOld(*m_aSet.GetPool(), m_aSet.GetRanges()), aNew(*m_aSet.GetPool(), m_aSet.GetRanges());
+
+ bRet = m_aSet.Put_BC(aTempSet, &aOld, &aNew);
+
+ if(bRet)
+ {
+ m_aSet.SetModifyAtAttr(this);
+ sw::ClientNotifyAttrChg(*this, m_aSet, aOld, aNew);
+ }
+ }
+
+ return bRet;
+ }
+ }
+
+ // if Modify is locked then no modifications will be sent;
+ // but call Modify always for FrameFormats
+ const sal_uInt16 nFormatWhich = Which();
+ if ( IsModifyLocked() ||
+ ( !HasWriterListeners() &&
+ ( RES_GRFFMTCOLL == nFormatWhich ||
+ RES_TXTFMTCOLL == nFormatWhich ) ) )
+ {
+ bRet = m_aSet.Put( aTempSet );
+ if( bRet )
+ m_aSet.SetModifyAtAttr( this );
+ // #i71574#
+ if ( nFormatWhich == RES_TXTFMTCOLL )
+ {
+ TextFormatCollFunc::CheckTextFormatCollForDeletionOfAssignmentToOutlineStyle( this );
+ }
+ }
+ else
+ {
+ SwAttrSet aOld( *m_aSet.GetPool(), m_aSet.GetRanges() ),
+ aNew( *m_aSet.GetPool(), m_aSet.GetRanges() );
+ bRet = m_aSet.Put_BC( aTempSet, &aOld, &aNew );
+ if( bRet )
+ {
+ // some special treatments for attributes
+ m_aSet.SetModifyAtAttr( this );
+ sw::ClientNotifyAttrChg(*this, m_aSet, aOld, aNew);
+ }
+ }
+ return bRet;
+}
+
+// remove Hint using nWhich from array with delta
+bool SwFormat::ResetFormatAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
+{
+ if( !m_aSet.Count() )
+ return false;
+
+ if( !nWhich2 || nWhich2 < nWhich1 )
+ nWhich2 = nWhich1; // then set to 1st ID, only this item
+
+ for( sal_uInt16 n = nWhich1; n < nWhich2; ++n )
+ InvalidateInSwFntCache( n );
+ for( sal_uInt16 n = nWhich1; n < nWhich2 && IsInCache(); ++n )
+ InvalidateInSwCache( n );
+
+ // if Modify is locked then no modifications will be sent
+ if( IsModifyLocked() )
+ return 0 != (( nWhich2 == nWhich1 )
+ ? m_aSet.ClearItem( nWhich1 )
+ : m_aSet.ClearItem_BC( nWhich1, nWhich2 ));
+
+ SwAttrSet aOld( *m_aSet.GetPool(), m_aSet.GetRanges() ),
+ aNew( *m_aSet.GetPool(), m_aSet.GetRanges() );
+ bool bRet = 0 != m_aSet.ClearItem_BC( nWhich1, nWhich2, &aOld, &aNew );
+ if( bRet )
+ sw::ClientNotifyAttrChg(*this, m_aSet, aOld, aNew);
+ return bRet;
+}
+
+// #i73790#
+sal_uInt16 SwFormat::ResetAllFormatAttr()
+{
+ if( !m_aSet.Count() )
+ return 0;
+
+ InvalidateInSwCache(RES_ATTRSET_CHG);
+ InvalidateInSwFntCache(RES_ATTRSET_CHG);
+
+ // if Modify is locked then no modifications will be sent
+ if( IsModifyLocked() )
+ return m_aSet.ClearItem();
+
+ SwAttrSet aOld( *m_aSet.GetPool(), m_aSet.GetRanges() ),
+ aNew( *m_aSet.GetPool(), m_aSet.GetRanges() );
+ bool bRet = 0 != m_aSet.ClearItem_BC( 0, &aOld, &aNew );
+ if( bRet )
+ sw::ClientNotifyAttrChg(*this, m_aSet, aOld, aNew);
+ return aNew.Count();
+}
+
+void SwFormat::DelDiffs( const SfxItemSet& rSet )
+{
+ if( !m_aSet.Count() )
+ return;
+
+ InvalidateInSwCache(RES_ATTRSET_CHG);
+ InvalidateInSwFntCache(RES_ATTRSET_CHG);
+
+ // if Modify is locked then no modifications will be sent
+ if( IsModifyLocked() )
+ {
+ m_aSet.Intersect( rSet );
+ return;
+ }
+
+ SwAttrSet aOld( *m_aSet.GetPool(), m_aSet.GetRanges() ),
+ aNew( *m_aSet.GetPool(), m_aSet.GetRanges() );
+ bool bRet = 0 != m_aSet.Intersect_BC( rSet, &aOld, &aNew );
+ if( bRet )
+ sw::ClientNotifyAttrChg(*this, m_aSet, aOld, aNew);
+}
+
+void SwFormat::SetPageFormatToDefault()
+{
+ const sal_Int32 nSize = o3tl::convert(2, o3tl::Length::cm, o3tl::Length::twip);
+ SetFormatAttr(SvxLRSpaceItem(nSize, nSize, 0, RES_LR_SPACE));
+ SetFormatAttr(SvxULSpaceItem(nSize, nSize, RES_UL_SPACE));
+}
+
+/** SwFormat::IsBackgroundTransparent
+
+ Virtual method to determine, if background of format is transparent.
+ Default implementation returns false. Thus, subclasses have to override
+ method, if the specific subclass can have a transparent background.
+
+ @return false, default implementation
+*/
+bool SwFormat::IsBackgroundTransparent() const
+{
+ return false;
+}
+
+/*
+ * Document Interface Access
+ */
+const IDocumentSettingAccess& SwFormat::getIDocumentSettingAccess() const { return GetDoc()->GetDocumentSettingManager(); }
+const IDocumentDrawModelAccess& SwFormat::getIDocumentDrawModelAccess() const { return GetDoc()->getIDocumentDrawModelAccess(); }
+IDocumentDrawModelAccess& SwFormat::getIDocumentDrawModelAccess() { return GetDoc()->getIDocumentDrawModelAccess(); }
+const IDocumentLayoutAccess& SwFormat::getIDocumentLayoutAccess() const { return GetDoc()->getIDocumentLayoutAccess(); }
+IDocumentLayoutAccess& SwFormat::getIDocumentLayoutAccess() { return GetDoc()->getIDocumentLayoutAccess(); }
+IDocumentTimerAccess& SwFormat::getIDocumentTimerAccess() { return GetDoc()->getIDocumentTimerAccess(); }
+IDocumentFieldsAccess& SwFormat::getIDocumentFieldsAccess() { return GetDoc()->getIDocumentFieldsAccess(); }
+IDocumentChartDataProviderAccess& SwFormat::getIDocumentChartDataProviderAccess() { return GetDoc()->getIDocumentChartDataProviderAccess(); }
+
+void SwFormat::GetGrabBagItem(uno::Any& rVal) const
+{
+ if (m_pGrabBagItem)
+ m_pGrabBagItem->QueryValue(rVal);
+ else
+ rVal <<= uno::Sequence<beans::PropertyValue>();
+}
+
+void SwFormat::SetGrabBagItem(const uno::Any& rVal)
+{
+ if (!m_pGrabBagItem)
+ m_pGrabBagItem = std::make_shared<SfxGrabBagItem>();
+
+ m_pGrabBagItem->PutValue(rVal, 0);
+}
+
+std::unique_ptr<SvxBrushItem> SwFormat::makeBackgroundBrushItem(bool bInP) const
+{
+ if (supportsFullDrawingLayerFillAttributeSet())
+ {
+ // FALLBACKBREAKHERE should not be used; instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST]
+ SAL_INFO("sw.core", "Do no longer use SvxBrushItem, instead use [XATTR_FILL_FIRST .. XATTR_FILL_LAST] FillAttributes (simple fallback is in place and used)");
+
+ // fill the local static SvxBrushItem from the current ItemSet so that
+ // the fill attributes [XATTR_FILL_FIRST .. XATTR_FILL_LAST] are used
+ // as good as possible to create a fallback representation and return that
+ return getSvxBrushItemFromSourceSet(m_aSet, RES_BACKGROUND, bInP);
+ }
+
+ return std::unique_ptr<SvxBrushItem>(m_aSet.GetBackground(bInP).Clone());
+}
+
+drawinglayer::attribute::SdrAllFillAttributesHelperPtr SwFormat::getSdrAllFillAttributesHelper() const
+{
+ return drawinglayer::attribute::SdrAllFillAttributesHelperPtr();
+}
+
+void SwFormat::RemoveAllUnos()
+{
+ SwPtrMsgPoolItem aMsgHint(RES_REMOVE_UNO_OBJECT, this);
+ SwClientNotify(*this, sw::LegacyModifyHint(&aMsgHint, &aMsgHint));
+}
+
+bool SwFormat::IsUsed() const
+{
+ auto pDoc = GetDoc();
+ if(!pDoc)
+ return false;
+ bool isUsed = false;
+ sw::AutoFormatUsedHint aHint(isUsed, pDoc->GetNodes());
+ CallSwClientNotify(aHint);
+ return isUsed;
+}
+
+SwFormatsBase::~SwFormatsBase()
+{}
+
+SwFormat* SwFormatsBase::FindFormatByName( const OUString& rName ) const
+{
+ SwFormat* pFnd = nullptr;
+ for( size_t n = 0; n < GetFormatCount(); ++n )
+ {
+ // Does the Doc already contain the template?
+ if( GetFormat(n)->HasName( rName ) )
+ {
+ pFnd = GetFormat(n);
+ break;
+ }
+ }
+ return pFnd;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/formatflysplit.cxx b/sw/source/core/attr/formatflysplit.cxx
new file mode 100644
index 0000000000..6bcfd74390
--- /dev/null
+++ b/sw/source/core/attr/formatflysplit.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <formatflysplit.hxx>
+
+#include <libxml/xmlwriter.h>
+
+SwFormatFlySplit::SwFormatFlySplit(bool bSplit)
+ : SfxBoolItem(RES_FLY_SPLIT, bSplit)
+{
+ // Once this pool item is true, a floating table (text frame + table inside it) is meant to
+ // split across multiple pages.
+ //
+ // The layout representation is the following:
+ //
+ // - We assume that the anchor type is at-para for such fly frames.
+ //
+ // - We also assume that AutoSize is true for such fly frames.
+ //
+ // - SwFlyAtContentFrame derives from SwFlowFrame to be able to split in general.
+ //
+ // - Both the master fly and the follow flys need an anchor. At the same time, we want all text
+ // of the anchor frame to be wrapped around the last follow fly frame, for Word compatibility.
+ // These are solved by splitting the anchor frame as many times as needed, always at
+ // TextFrameIndex 0.
+ //
+ // - The vertical offset is only considered on the master fly, all the follow flys ignore it, so
+ // they start at the top of a next page.
+}
+
+SwFormatFlySplit* SwFormatFlySplit::Clone(SfxItemPool*) const
+{
+ return new SwFormatFlySplit(*this);
+}
+
+void SwFormatFlySplit::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatFlySplit"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"),
+ BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
+ BAD_CAST(OString::boolean(GetValue()).getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/formatwraptextatflystart.cxx b/sw/source/core/attr/formatwraptextatflystart.cxx
new file mode 100644
index 0000000000..88a17d5ade
--- /dev/null
+++ b/sw/source/core/attr/formatwraptextatflystart.cxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <formatwraptextatflystart.hxx>
+
+#include <libxml/xmlwriter.h>
+
+SwFormatWrapTextAtFlyStart::SwFormatWrapTextAtFlyStart(bool bAtStart)
+ : SfxBoolItem(RES_WRAP_TEXT_AT_FLY_START, bAtStart)
+{
+ // Once this pool item is true, the text from the anchor text of the fly wraps an all pages, not
+ // only on the last page of the fly chain.
+}
+
+SwFormatWrapTextAtFlyStart* SwFormatWrapTextAtFlyStart::Clone(SfxItemPool*) const
+{
+ return new SwFormatWrapTextAtFlyStart(*this);
+}
+
+void SwFormatWrapTextAtFlyStart::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatWrapTextAtFlyStart"));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"),
+ BAD_CAST(OString::number(Which()).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
+ BAD_CAST(OString::boolean(GetValue()).getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/hints.cxx b/sw/source/core/attr/hints.cxx
new file mode 100644
index 0000000000..641d738031
--- /dev/null
+++ b/sw/source/core/attr/hints.cxx
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <ndtxt.hxx>
+#include <swtypes.hxx>
+#include <svl/languageoptions.hxx>
+#include <utility>
+#include <vcl/outdev.hxx>
+#include <osl/diagnose.h>
+
+SwFormatChg::SwFormatChg( SwFormat* pFormat )
+ : SwMsgPoolItem( RES_FMT_CHG ), pChangedFormat( pFormat )
+{
+}
+
+
+
+namespace sw {
+
+MoveText::MoveText(SwTextNode *const pD, sal_Int32 const nD, sal_Int32 const nS, sal_Int32 const nL)
+ : pDestNode(pD), nDestStart(nD), nSourceStart(nS), nLen(nL)
+{
+}
+
+InsertText::InsertText(const sal_Int32 nP, const sal_Int32 nL, const bool isInFMCommand, const bool isInFMResult)
+ : SfxHint( SfxHintId::SwInsertText )
+ , nPos( nP ), nLen( nL )
+ , isInsideFieldmarkCommand(isInFMCommand)
+ , isInsideFieldmarkResult(isInFMResult)
+{
+}
+
+DeleteText::DeleteText( const sal_Int32 nS, const sal_Int32 nL )
+ : SfxHint( SfxHintId::SwDeleteText ), nStart( nS ), nLen( nL )
+{
+}
+
+DeleteChar::DeleteChar( const sal_Int32 nPos )
+ : SfxHint( SfxHintId::SwDeleteChar ), m_nPos( nPos )
+{
+}
+
+RedlineDelText::RedlineDelText(sal_Int32 const nS, sal_Int32 const nL)
+ : nStart(nS), nLen(nL)
+{
+}
+
+RedlineUnDelText::RedlineUnDelText(sal_Int32 const nS, sal_Int32 const nL)
+ : nStart(nS), nLen(nL)
+{
+}
+
+VirtPageNumHint::VirtPageNumHint(const SwPageFrame* pPg):
+ SfxHint(SfxHintId::SwVirtPageNumHint),
+ m_pPage(nullptr),
+ m_pOrigPage(pPg),
+ m_pFrame(nullptr),
+ m_bFound(false)
+{
+}
+
+void AutoFormatUsedHint::CheckNode(const SwNode* pNode) const
+{
+ if(pNode && &pNode->GetNodes() == &m_rNodes)
+ SetUsed();
+}
+} // namespace sw
+
+SwUpdateAttr::SwUpdateAttr( sal_Int32 nS, sal_Int32 nE, sal_uInt16 nW )
+ : SwMsgPoolItem( RES_UPDATE_ATTR ), m_nStart( nS ), m_nEnd( nE ), m_nWhichAttr( nW )
+{
+}
+
+SwUpdateAttr::SwUpdateAttr( sal_Int32 nS, sal_Int32 nE, sal_uInt16 nW, std::vector<sal_uInt16> aW )
+ : SwMsgPoolItem( RES_UPDATE_ATTR ), m_nStart( nS ), m_nEnd( nE ), m_nWhichAttr( nW ), m_aWhichFmtAttrs(std::move( aW ))
+{
+}
+
+SwTableFormulaUpdate::SwTableFormulaUpdate(const SwTable* pNewTable)
+ : m_pTable(pNewTable)
+ , m_nSplitLine(USHRT_MAX)
+ , m_eFlags(TBL_CALC)
+{
+ m_aData.pDelTable = nullptr;
+ m_bModified = m_bBehindSplitLine = false;
+ OSL_ENSURE( m_pTable, "No Table pointer" );
+}
+
+SwAttrSetChg::SwAttrSetChg( const SwAttrSet& rTheSet, SwAttrSet& rSet )
+ : SwMsgPoolItem( RES_ATTRSET_CHG ),
+ m_bDelSet( false ),
+ m_pChgSet( &rSet ),
+ m_pTheChgdSet( &rTheSet )
+{
+}
+
+SwAttrSetChg::SwAttrSetChg( const SwAttrSetChg& rChgSet )
+ : SwMsgPoolItem( RES_ATTRSET_CHG ),
+ m_bDelSet( true ),
+ m_pTheChgdSet( rChgSet.m_pTheChgdSet )
+{
+ m_pChgSet = new SwAttrSet( *rChgSet.m_pChgSet );
+}
+
+SwAttrSetChg::~SwAttrSetChg()
+{
+ if( m_bDelSet )
+ delete m_pChgSet;
+}
+
+#ifdef DBG_UTIL
+void SwAttrSetChg::ClearItem( sal_uInt16 nWhch )
+{
+ OSL_ENSURE( m_bDelSet, "The Set may not be changed!" );
+ m_pChgSet->ClearItem( nWhch );
+}
+#endif
+
+SwMsgPoolItem::SwMsgPoolItem( sal_uInt16 nWhch )
+ : SfxPoolItem( nWhch )
+{
+}
+
+bool SwMsgPoolItem::operator==( const SfxPoolItem& rItem ) const
+{
+ assert( SfxPoolItem::operator==(rItem)); (void)rItem;
+ // SwMsgPoolItem now knows operator== due to evtl. deeper
+ // ItemCompares using SfxPoolItem::areSame. No members,
+ // so always equal
+ return true;
+}
+
+SwMsgPoolItem* SwMsgPoolItem::Clone( SfxItemPool* ) const
+{
+ OSL_FAIL( "SwMsgPoolItem knows no Clone" );
+ return nullptr;
+}
+
+#if OSL_DEBUG_LEVEL > 0
+const SfxPoolItem* GetDfltAttr( sal_uInt16 nWhich )
+{
+ OSL_ASSERT( nWhich < POOLATTR_END && nWhich >= POOLATTR_BEGIN );
+
+ SfxPoolItem *pHt = aAttrTab[ nWhich - POOLATTR_BEGIN ];
+ OSL_ENSURE( pHt, "GetDfltFormatAttr(): Dflt == 0" );
+ return pHt;
+}
+#else
+const SfxPoolItem* GetDfltAttr( sal_uInt16 nWhich )
+{
+ return aAttrTab[ nWhich - POOLATTR_BEGIN ];
+}
+#endif
+
+SwFindNearestNode::SwFindNearestNode( const SwNode& rNd )
+ : SwMsgPoolItem( RES_FINDNEARESTNODE ), m_pNode( &rNd ), m_pFound( nullptr )
+{
+}
+
+void SwFindNearestNode::CheckNode( const SwNode& rNd )
+{
+ if( &m_pNode->GetNodes() == &rNd.GetNodes() )
+ {
+ SwNodeOffset nIdx = rNd.GetIndex();
+ if( nIdx < m_pNode->GetIndex() &&
+ ( !m_pFound || nIdx > m_pFound->GetIndex() ) &&
+ nIdx > rNd.GetNodes().GetEndOfExtras().GetIndex() )
+ m_pFound = &rNd;
+ }
+}
+
+sal_uInt16 GetWhichOfScript( sal_uInt16 nWhich, sal_uInt16 nScript )
+{
+ static const sal_uInt16 aLangMap[3] =
+ { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE };
+ static const sal_uInt16 aFontMap[3] =
+ { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_FONT};
+ static const sal_uInt16 aFontSizeMap[3] =
+ { RES_CHRATR_FONTSIZE, RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CTL_FONTSIZE };
+ static const sal_uInt16 aWeightMap[3] =
+ { RES_CHRATR_WEIGHT, RES_CHRATR_CJK_WEIGHT, RES_CHRATR_CTL_WEIGHT};
+ static const sal_uInt16 aPostureMap[3] =
+ { RES_CHRATR_POSTURE, RES_CHRATR_CJK_POSTURE, RES_CHRATR_CTL_POSTURE};
+
+ const sal_uInt16* pM;
+ switch( nWhich )
+ {
+ case RES_CHRATR_LANGUAGE:
+ case RES_CHRATR_CJK_LANGUAGE:
+ case RES_CHRATR_CTL_LANGUAGE:
+ pM = aLangMap;
+ break;
+
+ case RES_CHRATR_FONT:
+ case RES_CHRATR_CJK_FONT:
+ case RES_CHRATR_CTL_FONT:
+ pM = aFontMap;
+ break;
+
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_CJK_FONTSIZE:
+ case RES_CHRATR_CTL_FONTSIZE:
+ pM = aFontSizeMap;
+ break;
+
+ case RES_CHRATR_WEIGHT:
+ case RES_CHRATR_CJK_WEIGHT:
+ case RES_CHRATR_CTL_WEIGHT:
+ pM = aWeightMap;
+ break;
+
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CTL_POSTURE:
+ pM = aPostureMap;
+ break;
+
+ default:
+ pM = nullptr;
+ }
+
+ sal_uInt16 nRet;
+ if( pM )
+ {
+ using namespace ::com::sun::star;
+ {
+ if( i18n::ScriptType::WEAK == nScript )
+ nScript = SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() );
+ switch( nScript)
+ {
+ case i18n::ScriptType::COMPLEX:
+ ++pM;
+ [[fallthrough]];
+ case i18n::ScriptType::ASIAN:
+ ++pM;
+ [[fallthrough]];
+ default:
+ nRet = *pM;
+ }
+ }
+ }
+ else
+ nRet = nWhich;
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/swatrset.cxx b/sw/source/core/attr/swatrset.cxx
new file mode 100644
index 0000000000..fc4612757d
--- /dev/null
+++ b/sw/source/core/attr/swatrset.cxx
@@ -0,0 +1,583 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+
+#include <cellatr.hxx>
+#include <charfmt.hxx>
+#include <fchrfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentListsAccess.hxx>
+#include <editeng/editeng.hxx>
+#include <fmtanchr.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtautofmt.hxx>
+#include <hintids.hxx>
+#include <list.hxx>
+#include <node.hxx>
+#include <numrule.hxx>
+#include <pagedesc.hxx>
+#include <paratr.hxx>
+#include <o3tl/unit_conversion.hxx>
+#include <osl/diagnose.h>
+#include <svl/whiter.hxx>
+
+#include <svx/svdpool.hxx>
+#include <svx/sxenditm.hxx>
+#include <svx/sdsxyitm.hxx>
+
+SwAttrPool::SwAttrPool( SwDoc* pD )
+ : SfxItemPool( "SWG",
+ POOLATTR_BEGIN, POOLATTR_END-1,
+ aSlotTab, &aAttrTab ),
+ m_pDoc( pD )
+{
+ // create SfxItemPool and EditEngine pool and add these in a chain. These
+ // belong us and will be removed/destroyed in removeAndDeleteSecondaryPools() used from
+ // the destructor
+ rtl::Reference<SfxItemPool> pSdrPool = new SdrItemPool(this);
+
+ // #75371# change DefaultItems for the SdrEdgeObj distance items
+ // to TWIPS.
+ constexpr tools::Long nDefEdgeDist
+ = o3tl::convert(500, o3tl::Length::mm100, o3tl::Length::twip);
+
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode1HorzDistItem(nDefEdgeDist));
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode1VertDistItem(nDefEdgeDist));
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode2HorzDistItem(nDefEdgeDist));
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode2VertDistItem(nDefEdgeDist));
+
+ // #i33700# // Set shadow distance defaults as PoolDefaultItems
+ constexpr tools::Long nDefShadowDist
+ = o3tl::convert(300, o3tl::Length::mm100, o3tl::Length::twip);
+ pSdrPool->SetPoolDefaultItem(makeSdrShadowXDistItem(nDefShadowDist));
+ pSdrPool->SetPoolDefaultItem(makeSdrShadowYDistItem(nDefShadowDist));
+
+ rtl::Reference<SfxItemPool> pEEgPool = EditEngine::CreatePool();
+
+ pSdrPool->SetSecondaryPool(pEEgPool.get());
+
+ if(GetFrozenIdRanges().empty())
+ {
+ FreezeIdRanges();
+ }
+ else
+ {
+ pSdrPool->FreezeIdRanges();
+ }
+}
+
+SwAttrPool::~SwAttrPool()
+{
+ // cleanup secondary pools
+ SfxItemPool *pSdrPool = GetSecondaryPool();
+ // first delete the items, then break the linking
+ pSdrPool->Delete();
+ SetSecondaryPool(nullptr);
+}
+
+/// Notification callback
+void SwAttrSet::changeCallback(const SfxPoolItem* pOld, const SfxPoolItem* pNew) const
+{
+ // will have no effect, return
+ if (nullptr == m_pOldSet && nullptr == m_pNewSet)
+ return;
+
+ // at least one SfxPoolItem has to be provided, else this is an error
+ assert(nullptr != pOld || nullptr != pNew);
+ sal_uInt16 nWhich(0);
+
+ if (nullptr != pOld)
+ {
+ // do not handle if an invalid item is involved
+ if (IsInvalidItem(pOld))
+ return;
+
+ // get WhichID from pOld
+ nWhich = pOld->Which();
+ }
+
+ if (nullptr != pNew)
+ {
+ // do not handle if an invalid item is involved
+ if (IsInvalidItem(pNew))
+ return;
+
+ if (0 == nWhich)
+ {
+ // get WhichID from pNew
+ nWhich = pNew->Which();
+ }
+ }
+
+ // all given items are valid. If we got no WhichID != 0 then
+ // pOld == pNew == nullptr or SfxVoidItem(0) and we have no
+ // valid input. Also not needed if !IsWhich (aka > SFX_WHICH_MAX)
+ if (0 == nWhich || !SfxItemPool::IsWhich(nWhich))
+ return;
+
+ if(m_pOldSet)
+ {
+ // old state shall be saved
+ if (nullptr == pOld)
+ {
+ // no old value given, generate default from WhichID
+ const SfxItemSet* pParent(GetParent());
+ m_pOldSet->PutImpl(nullptr != pParent
+ ? pParent->Get(nWhich)
+ : GetPool()->GetDefaultItem(nWhich), nWhich, false);
+ }
+ else if (!IsInvalidItem(pOld))
+ {
+ // set/remember old value
+ m_pOldSet->PutImpl(*pOld, nWhich, false);
+ }
+ }
+
+ if(m_pNewSet)
+ {
+ // old state shall be saved
+ if (nullptr == pNew)
+ {
+ // no new value given, generate default from WhichID
+ const SfxItemSet* pParent(GetParent());
+ m_pNewSet->PutImpl(nullptr != pParent
+ ? pParent->Get(nWhich)
+ : GetPool()->GetDefaultItem(nWhich), nWhich, false);
+ }
+ else if (!IsInvalidItem(pNew))
+ {
+ // set/remember new value
+ m_pNewSet->PutImpl(*pNew, nWhich, false);
+ }
+ }
+}
+
+SwAttrSet::SwAttrSet( SwAttrPool& rPool, sal_uInt16 nWh1, sal_uInt16 nWh2 )
+ : SfxItemSet( rPool, nWh1, nWh2 )
+ , m_pOldSet( nullptr )
+ , m_pNewSet( nullptr )
+ , m_aCallbackHolder(this)
+{
+}
+
+SwAttrSet::SwAttrSet( SwAttrPool& rPool, const WhichRangesContainer& nWhichPairTable )
+ : SfxItemSet( rPool, nWhichPairTable )
+ , m_pOldSet( nullptr )
+ , m_pNewSet( nullptr )
+ , m_aCallbackHolder(this)
+{
+}
+
+SwAttrSet::SwAttrSet( const SwAttrSet& rSet )
+ : SfxItemSet( rSet )
+ , m_pOldSet( nullptr )
+ , m_pNewSet( nullptr )
+ , m_aCallbackHolder(this)
+{
+}
+
+std::unique_ptr<SfxItemSet> SwAttrSet::Clone( bool bItems, SfxItemPool *pToPool ) const
+{
+ if ( pToPool && pToPool != GetPool() )
+ {
+ SwAttrPool* pAttrPool = dynamic_cast< SwAttrPool* >(pToPool);
+ std::unique_ptr<SfxItemSet> pTmpSet;
+ if ( !pAttrPool )
+ pTmpSet = SfxItemSet::Clone( bItems, pToPool );
+ else
+ {
+ pTmpSet.reset(new SwAttrSet( *pAttrPool, GetRanges() ));
+ if ( bItems )
+ {
+ SfxWhichIter aIter(*pTmpSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ const SfxPoolItem* pItem;
+ if ( SfxItemState::SET == GetItemState( nWhich, false, &pItem ) )
+ pTmpSet->Put( *pItem );
+ nWhich = aIter.NextWhich();
+ }
+ }
+ }
+ return pTmpSet;
+ }
+ else
+ return std::unique_ptr<SfxItemSet>(
+ bItems
+ ? new SwAttrSet( *this )
+ : new SwAttrSet( *GetPool(), GetRanges() ));
+}
+
+SwAttrSet SwAttrSet::CloneAsValue( bool bItems ) const
+{
+ if (bItems)
+ return *this;
+ else
+ return SwAttrSet( *GetPool(), GetRanges() );
+}
+
+bool SwAttrSet::Put_BC( const SfxPoolItem& rAttr,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ // direct call when neither pOld nor pNew is set, no need for callback
+ if (nullptr == pOld && nullptr == pNew)
+ return nullptr != SfxItemSet::Put( rAttr );
+
+ m_pNewSet = pNew;
+ m_pOldSet = pOld;
+ setCallback(m_aCallbackHolder);
+ bool bRet = nullptr != SfxItemSet::Put( rAttr );
+ clearCallback();
+ m_pOldSet = m_pNewSet = nullptr;
+ return bRet;
+}
+
+bool SwAttrSet::Put_BC( const SfxItemSet& rSet,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ // direct call when neither pOld nor pNew is set, no need for callback
+ if (nullptr == pOld && nullptr == pNew)
+ return SfxItemSet::Put( rSet );
+
+ m_pNewSet = pNew;
+ m_pOldSet = pOld;
+ setCallback(m_aCallbackHolder);
+ bool bRet = SfxItemSet::Put( rSet );
+ clearCallback();
+ m_pOldSet = m_pNewSet = nullptr;
+ return bRet;
+}
+
+sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ // direct call when neither pOld nor pNew is set, no need for callback
+ if (nullptr == pOld && nullptr == pNew)
+ return SfxItemSet::ClearItem( nWhich );
+
+ m_pNewSet = pNew;
+ m_pOldSet = pOld;
+ setCallback(m_aCallbackHolder);
+ sal_uInt16 nRet = SfxItemSet::ClearItem( nWhich );
+ clearCallback();
+ m_pOldSet = m_pNewSet = nullptr;
+ return nRet;
+}
+
+sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich1, sal_uInt16 nWhich2,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ OSL_ENSURE( nWhich1 <= nWhich2, "no valid range" );
+ sal_uInt16 nRet = 0;
+
+ // direct call when neither pOld nor pNew is set, no need for callback
+ if (nullptr == pOld && nullptr == pNew)
+ {
+ for( ; nWhich1 <= nWhich2; ++nWhich1 )
+ nRet = nRet + SfxItemSet::ClearItem( nWhich1 );
+ return nRet;
+ }
+
+ m_pNewSet = pNew;
+ m_pOldSet = pOld;
+ setCallback(m_aCallbackHolder);
+ for( ; nWhich1 <= nWhich2; ++nWhich1 )
+ nRet = nRet + SfxItemSet::ClearItem( nWhich1 );
+ clearCallback();
+ m_pOldSet = m_pNewSet = nullptr;
+ return nRet;
+}
+
+int SwAttrSet::Intersect_BC( const SfxItemSet& rSet,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ // direct call when neither pOld nor pNew is set, no need for callback
+ if (nullptr == pOld && nullptr == pNew)
+ {
+ SfxItemSet::Intersect( rSet );
+ return 0; // as below when neither pOld nor pNew is set
+ }
+
+ m_pNewSet = pNew;
+ m_pOldSet = pOld;
+ setCallback(m_aCallbackHolder);
+ SfxItemSet::Intersect( rSet );
+ clearCallback();
+ m_pOldSet = m_pNewSet = nullptr;
+ return pNew ? pNew->Count() : pOld->Count();
+}
+
+/** special treatment for some attributes
+
+ Set the Modify pointer (old pDefinedIn) for the following attributes:
+ - SwFormatDropCaps
+ - SwFormatPageDesc
+
+ (Is called at inserts into formats/nodes)
+*/
+bool SwAttrSet::SetModifyAtAttr( const sw::BroadcastingModify* pModify )
+{
+ bool bSet = false;
+
+ const SwFormatPageDesc* pPageDescItem = GetItemIfSet( RES_PAGEDESC, false );
+ if( pPageDescItem &&
+ pPageDescItem->GetDefinedIn() != pModify )
+ {
+ const_cast<SwFormatPageDesc&>(*pPageDescItem).ChgDefinedIn( pModify );
+ bSet = true;
+ }
+
+ if(SwFormatDrop* pFormatDrop = const_cast<SwFormatDrop*>(GetItemIfSet( RES_PARATR_DROP, false )))
+ {
+ auto pDropDefiner = dynamic_cast<const sw::FormatDropDefiner*>(pModify);
+ // If CharFormat is set and it is set in different attribute pools then
+ // the CharFormat has to be copied.
+ SwCharFormat* pCharFormat = pFormatDrop->GetCharFormat();
+ if(pCharFormat && GetPool() != pCharFormat->GetAttrSet().GetPool())
+ {
+ pCharFormat = GetDoc()->CopyCharFormat(*pCharFormat);
+ pFormatDrop->SetCharFormat(pCharFormat);
+ }
+ pFormatDrop->ChgDefinedIn(pDropDefiner);
+ bSet = true;
+ }
+
+ const SwTableBoxFormula* pBoxFormula = GetItemIfSet( RES_BOXATR_FORMULA, false );
+ if( pBoxFormula && pBoxFormula->GetDefinedIn() != pModify )
+ {
+ const_cast<SwTableBoxFormula&>(*pBoxFormula).ChgDefinedIn( pModify );
+ bSet = true;
+ }
+
+ return bSet;
+}
+
+void SwAttrSet::CopyToModify( sw::BroadcastingModify& rMod ) const
+{
+ // copy attributes across multiple documents if needed
+ SwContentNode* pCNd = dynamic_cast<SwContentNode*>( &rMod );
+ SwFormat* pFormat = dynamic_cast<SwFormat*>( &rMod );
+
+ if( pCNd || pFormat )
+ {
+ if( Count() )
+ {
+ // #i92811#
+ std::unique_ptr<SfxStringItem> pNewListIdItem;
+
+ const SwDoc *pSrcDoc = GetDoc();
+ SwDoc *pDstDoc = pCNd ? &pCNd->GetDoc() : pFormat->GetDoc();
+
+ // Does the NumRule has to be copied?
+ const SwNumRuleItem* pNumRuleItem;
+ if( pSrcDoc != pDstDoc &&
+ (pNumRuleItem = GetItemIfSet( RES_PARATR_NUMRULE, false )) )
+ {
+ const OUString& rNm = pNumRuleItem->GetValue();
+ if( !rNm.isEmpty() )
+ {
+ SwNumRule* pDestRule = pDstDoc->FindNumRulePtr( rNm );
+ if( pDestRule )
+ pDestRule->SetInvalidRule( true );
+ else
+ pDstDoc->MakeNumRule( rNm, pSrcDoc->FindNumRulePtr( rNm ) );
+ }
+ }
+
+ // copy list and if needed also the corresponding list style
+ // for text nodes
+ const SfxStringItem* pStrItem;
+ if ( pSrcDoc != pDstDoc &&
+ pCNd && pCNd->IsTextNode() &&
+ (pStrItem = GetItemIfSet( RES_PARATR_LIST_ID, false )) )
+ {
+ const OUString& sListId = pStrItem->GetValue();
+ if ( !sListId.isEmpty() &&
+ !pDstDoc->getIDocumentListsAccess().getListByName( sListId ) )
+ {
+ const SwList* pList = pSrcDoc->getIDocumentListsAccess().getListByName( sListId );
+ // copy list style, if needed
+ const OUString& sDefaultListStyleName =
+ pList->GetDefaultListStyleName();
+ // #i92811#
+ const SwNumRule* pDstDocNumRule =
+ pDstDoc->FindNumRulePtr( sDefaultListStyleName );
+ if ( !pDstDocNumRule )
+ {
+ pDstDoc->MakeNumRule( sDefaultListStyleName,
+ pSrcDoc->FindNumRulePtr( sDefaultListStyleName ) );
+ }
+ else
+ {
+ const SwNumRule* pSrcDocNumRule =
+ pSrcDoc->FindNumRulePtr( sDefaultListStyleName );
+ // If list id of text node equals the list style's
+ // default list id in the source document, the same
+ // should be hold in the destination document.
+ // Thus, create new list id item.
+ if (pSrcDocNumRule && sListId == pSrcDocNumRule->GetDefaultListId())
+ {
+ pNewListIdItem.reset(new SfxStringItem (
+ RES_PARATR_LIST_ID,
+ pDstDocNumRule->GetDefaultListId() ));
+ }
+ }
+ // check again, if list exist, because <SwDoc::MakeNumRule(..)>
+ // could have also created it.
+ if ( pNewListIdItem == nullptr &&
+ !pDstDoc->getIDocumentListsAccess().getListByName( sListId ) )
+ {
+ // copy list
+ pDstDoc->getIDocumentListsAccess().createList( sListId, sDefaultListStyleName );
+ }
+ }
+ }
+
+ std::optional< SfxItemSet > tmpSet;
+ const SwFormatPageDesc* pPageDescItem;
+ if( pSrcDoc != pDstDoc && (pPageDescItem = GetItemIfSet(
+ RES_PAGEDESC, false )))
+ {
+ const SwPageDesc* pPgDesc = pPageDescItem->GetPageDesc();
+ if( pPgDesc )
+ {
+ tmpSet.emplace(*this);
+
+ SwPageDesc* pDstPgDesc = pDstDoc->FindPageDesc(pPgDesc->GetName());
+ if( !pDstPgDesc )
+ {
+ pDstPgDesc = pDstDoc->MakePageDesc(pPgDesc->GetName());
+ pDstDoc->CopyPageDesc( *pPgDesc, *pDstPgDesc );
+ }
+ SwFormatPageDesc aDesc( pDstPgDesc );
+ aDesc.SetNumOffset( pPageDescItem->GetNumOffset() );
+ tmpSet->Put( aDesc );
+ }
+ }
+
+ const SwFormatAnchor* pAnchorItem;
+ if( pSrcDoc != pDstDoc && (pAnchorItem = GetItemIfSet( RES_ANCHOR, false ))
+ && pAnchorItem->GetAnchorNode() != nullptr )
+ {
+ if( !tmpSet )
+ tmpSet.emplace( *this );
+ // Anchors at any node position cannot be copied to another document, because the SwPosition
+ // would still point to the old document. It needs to be fixed up explicitly.
+ tmpSet->ClearItem( RES_ANCHOR );
+ }
+
+ const SwFormatAutoFormat* pAutoFormatItem;
+ if (pSrcDoc != pDstDoc &&
+ (pAutoFormatItem = GetItemIfSet(RES_PARATR_LIST_AUTOFMT, false)) &&
+ pAutoFormatItem->GetStyleHandle())
+ {
+ SfxItemSet const& rAutoStyle(*pAutoFormatItem->GetStyleHandle());
+ std::shared_ptr<SfxItemSet> const pNewSet(
+ rAutoStyle.SfxItemSet::Clone(true, &pDstDoc->GetAttrPool()));
+
+ // fix up character style, it contains pointers to pSrcDoc
+ if (const SwFormatCharFormat* pCharFormatItem = pNewSet->GetItemIfSet(RES_TXTATR_CHARFMT, false))
+ {
+ SwCharFormat *const pCopy(pDstDoc->CopyCharFormat(*pCharFormatItem->GetCharFormat()));
+ const_cast<SwFormatCharFormat&>(*pCharFormatItem).SetCharFormat(pCopy);
+ }
+
+ SwFormatAutoFormat item(RES_PARATR_LIST_AUTOFMT);
+ // TODO: for ODF export we'd need to add it to the autostyle pool
+ item.SetStyleHandle(pNewSet);
+ if (!tmpSet)
+ {
+ tmpSet.emplace(*this);
+ }
+ tmpSet->Put(item);
+ }
+
+ if( tmpSet )
+ {
+ if( pCNd )
+ {
+ // #i92811#
+ if ( pNewListIdItem != nullptr )
+ {
+ tmpSet->Put( std::move(pNewListIdItem) );
+ }
+ pCNd->SetAttr( *tmpSet );
+ }
+ else
+ {
+ pFormat->SetFormatAttr( *tmpSet );
+ }
+ }
+ else if( pCNd )
+ {
+ // #i92811#
+ if ( pNewListIdItem != nullptr )
+ {
+ SfxItemSet aTmpSet( *this );
+ aTmpSet.Put( std::move(pNewListIdItem) );
+ pCNd->SetAttr( aTmpSet );
+ }
+ else
+ {
+ pCNd->SetAttr( *this );
+ }
+ }
+ else
+ {
+ pFormat->SetFormatAttr( *this );
+ }
+ }
+ if (pCNd && pCNd->HasSwAttrSet())
+ {
+ SfxWhichIter it(*this);
+ std::vector<sal_uInt16> toClear;
+ for (sal_uInt16 nWhich = it.FirstWhich(); nWhich != 0; nWhich = it.NextWhich())
+ {
+ if (GetItemState(nWhich, false) != SfxItemState::SET
+ && pCNd->GetSwAttrSet().GetItemState(nWhich, false) == SfxItemState::SET)
+ {
+ toClear.emplace_back(nWhich);
+ }
+ }
+ if (!toClear.empty())
+ {
+ pCNd->ResetAttr(toClear);
+ }
+ }
+ }
+#if OSL_DEBUG_LEVEL > 0
+ else
+ OSL_FAIL("neither Format nor ContentNode - no Attributes copied");
+#endif
+}
+
+/// check if ID is in range of attribute set IDs
+bool IsInRange( const WhichRangesContainer& pRange, const sal_uInt16 nId )
+{
+ for(const auto& rPair : pRange)
+ {
+ if( rPair.first <= nId && nId <= rPair.second )
+ return true;
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */