summaryrefslogtreecommitdiffstats
path: root/sw/source/core/txtnode/fmtatr2.cxx
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/txtnode/fmtatr2.cxx
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/txtnode/fmtatr2.cxx')
-rw-r--r--sw/source/core/txtnode/fmtatr2.cxx867
1 files changed, 867 insertions, 0 deletions
diff --git a/sw/source/core/txtnode/fmtatr2.cxx b/sw/source/core/txtnode/fmtatr2.cxx
new file mode 100644
index 0000000000..3e888b660f
--- /dev/null
+++ b/sw/source/core/txtnode/fmtatr2.cxx
@@ -0,0 +1,867 @@
+/* -*- 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 <libxml/xmlwriter.h>
+#include <hintids.hxx>
+#include <poolfmt.hxx>
+#include <unomid.h>
+
+#include <o3tl/any.hxx>
+#include <svl/macitem.hxx>
+#include <svl/stylepool.hxx>
+#include <fmtautofmt.hxx>
+#include <fchrfmt.hxx>
+#include <fmtinfmt.hxx>
+#include <txtatr.hxx>
+#include <fmtruby.hxx>
+#include <charfmt.hxx>
+#include <unoevent.hxx>
+#include <unoport.hxx>
+#include <com/sun/star/text/RubyAdjust.hpp>
+#include <com/sun/star/text/RubyPosition.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <com/sun/star/uno/Any.h>
+#include <SwStyleNameMapper.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <fmtmeta.hxx>
+#include <ndtxt.hxx>
+#include <doc.hxx>
+#include <unometa.hxx>
+#include <unotext.hxx>
+#include <docsh.hxx>
+#include <osl/diagnose.h>
+
+#include <algorithm>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+
+SfxPoolItem* SwFormatINetFormat::CreateDefault() { return new SwFormatINetFormat; }
+
+SwFormatCharFormat::SwFormatCharFormat( SwCharFormat *pFormat )
+ : SfxPoolItem( RES_TXTATR_CHARFMT ),
+ SwClient(pFormat),
+ m_pTextAttribute( nullptr )
+{
+}
+
+SwFormatCharFormat::SwFormatCharFormat( const SwFormatCharFormat& rAttr )
+ : SfxPoolItem( RES_TXTATR_CHARFMT ),
+ SwClient( rAttr.GetCharFormat() ),
+ m_pTextAttribute( nullptr )
+{
+}
+
+SwFormatCharFormat::~SwFormatCharFormat() {}
+
+bool SwFormatCharFormat::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+ return GetCharFormat() == static_cast<const SwFormatCharFormat&>(rAttr).GetCharFormat();
+}
+
+SwFormatCharFormat* SwFormatCharFormat::Clone( SfxItemPool* ) const
+{
+ return new SwFormatCharFormat( *this );
+}
+
+// forward to the TextAttribute
+void SwFormatCharFormat::SwClientNotify(const SwModify&, const SfxHint& rHint)
+{
+ if(rHint.GetId() == SfxHintId::SwAutoFormatUsedHint)
+ {
+ if(m_pTextAttribute)
+ m_pTextAttribute->HandleAutoFormatUsedHint(static_cast<const sw::AutoFormatUsedHint&>(rHint));
+ return;
+ }
+ if (rHint.GetId() != SfxHintId::SwLegacyModify)
+ return;
+ auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
+ if(m_pTextAttribute)
+ m_pTextAttribute->TriggerNodeUpdate(*pLegacy);
+}
+
+bool SwFormatCharFormat::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+ OUString sCharFormatName;
+ if(GetCharFormat())
+ SwStyleNameMapper::FillProgName(GetCharFormat()->GetName(), sCharFormatName, SwGetPoolIdFromName::ChrFmt );
+ rVal <<= sCharFormatName;
+ return true;
+}
+bool SwFormatCharFormat::PutValue( const uno::Any& , sal_uInt8 )
+{
+ OSL_FAIL("format cannot be set with PutValue!");
+ return false;
+}
+
+void SwFormatCharFormat::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatCharFormat"));
+ (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
+ (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("text-attribute"), "%p", m_pTextAttribute);
+ (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("char-format"), "%p", GetCharFormat());
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("char-format-name"),
+ BAD_CAST(GetCharFormat()->GetName().toUtf8().getStr()));
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+SwFormatAutoFormat::SwFormatAutoFormat( sal_uInt16 nInitWhich )
+ : SfxPoolItem( nInitWhich )
+{
+}
+
+bool SwFormatAutoFormat::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+ return mpHandle == static_cast<const SwFormatAutoFormat&>(rAttr).mpHandle;
+}
+
+SwFormatAutoFormat* SwFormatAutoFormat::Clone( SfxItemPool* ) const
+{
+ return new SwFormatAutoFormat( *this );
+}
+
+bool SwFormatAutoFormat::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+ rVal <<= StylePool::nameOf( mpHandle );
+ return true;
+}
+
+bool SwFormatAutoFormat::PutValue( const uno::Any& , sal_uInt8 )
+{
+ //the format is not renameable via API
+ return false;
+}
+
+void SwFormatAutoFormat::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatAutoFormat"));
+ (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
+ if (mpHandle) // pool default doesn't have one
+ {
+ mpHandle->dumpAsXml(pWriter);
+ }
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+SwFormatINetFormat::SwFormatINetFormat()
+ : SfxPoolItem( RES_TXTATR_INETFMT )
+ , msURL()
+ , msTargetFrame()
+ , msINetFormatName()
+ , msVisitedFormatName()
+ , msHyperlinkName()
+ , mpTextAttr( nullptr )
+ , mnINetFormatId( 0 )
+ , mnVisitedFormatId( 0 )
+{}
+
+SwFormatINetFormat::SwFormatINetFormat( OUString aURL, OUString aTarget )
+ : SfxPoolItem( RES_TXTATR_INETFMT )
+ , msURL( std::move(aURL) )
+ , msTargetFrame( std::move(aTarget) )
+ , msINetFormatName()
+ , msVisitedFormatName()
+ , msHyperlinkName()
+ , mpTextAttr( nullptr )
+ , mnINetFormatId( RES_POOLCHR_INET_NORMAL )
+ , mnVisitedFormatId( RES_POOLCHR_INET_VISIT )
+{
+ SwStyleNameMapper::FillUIName( mnINetFormatId, msINetFormatName );
+ SwStyleNameMapper::FillUIName( mnVisitedFormatId, msVisitedFormatName );
+}
+
+SwFormatINetFormat::SwFormatINetFormat( const SwFormatINetFormat& rAttr )
+ : SfxPoolItem( RES_TXTATR_INETFMT )
+ , sw::BroadcasterMixin()
+ , msURL( rAttr.GetValue() )
+ , msTargetFrame( rAttr.msTargetFrame )
+ , msINetFormatName( rAttr.msINetFormatName )
+ , msVisitedFormatName( rAttr.msVisitedFormatName )
+ , msHyperlinkName( rAttr.msHyperlinkName )
+ , mpTextAttr( nullptr )
+ , mnINetFormatId( rAttr.mnINetFormatId )
+ , mnVisitedFormatId( rAttr.mnVisitedFormatId )
+{
+ if ( rAttr.GetMacroTable() )
+ mpMacroTable.reset( new SvxMacroTableDtor( *rAttr.GetMacroTable() ) );
+}
+
+SwFormatINetFormat::~SwFormatINetFormat()
+{
+}
+
+bool SwFormatINetFormat::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+ bool bRet = SfxPoolItem::operator==( rAttr )
+ && msURL == static_cast<const SwFormatINetFormat&>(rAttr).msURL
+ && msHyperlinkName == static_cast<const SwFormatINetFormat&>(rAttr).msHyperlinkName
+ && msTargetFrame == static_cast<const SwFormatINetFormat&>(rAttr).msTargetFrame
+ && msINetFormatName == static_cast<const SwFormatINetFormat&>(rAttr).msINetFormatName
+ && msVisitedFormatName == static_cast<const SwFormatINetFormat&>(rAttr).msVisitedFormatName
+ && mnINetFormatId == static_cast<const SwFormatINetFormat&>(rAttr).mnINetFormatId
+ && mnVisitedFormatId == static_cast<const SwFormatINetFormat&>(rAttr).mnVisitedFormatId;
+
+ if( !bRet )
+ return false;
+
+ const SvxMacroTableDtor* pOther = static_cast<const SwFormatINetFormat&>(rAttr).mpMacroTable.get();
+ if( !mpMacroTable )
+ return ( !pOther || pOther->empty() );
+ if( !pOther )
+ return mpMacroTable->empty();
+
+ const SvxMacroTableDtor& rOwn = *mpMacroTable;
+ const SvxMacroTableDtor& rOther = *pOther;
+
+ return rOwn == rOther;
+}
+
+SwFormatINetFormat* SwFormatINetFormat::Clone( SfxItemPool* ) const
+{
+ return new SwFormatINetFormat( *this );
+}
+
+void SwFormatINetFormat::SetMacroTable( const SvxMacroTableDtor* pNewTable )
+{
+ if( pNewTable )
+ {
+ if( mpMacroTable )
+ *mpMacroTable = *pNewTable;
+ else
+ mpMacroTable.reset( new SvxMacroTableDtor( *pNewTable ) );
+ }
+ else
+ {
+ mpMacroTable.reset();
+ }
+}
+
+void SwFormatINetFormat::SetMacro( SvMacroItemId nEvent, const SvxMacro& rMacro )
+{
+ if( !mpMacroTable )
+ mpMacroTable.reset( new SvxMacroTableDtor );
+
+ mpMacroTable->Insert( nEvent, rMacro );
+}
+
+const SvxMacro* SwFormatINetFormat::GetMacro( SvMacroItemId nEvent ) const
+{
+ const SvxMacro* pRet = nullptr;
+ if( mpMacroTable && mpMacroTable->IsKeyValid( nEvent ) )
+ pRet = mpMacroTable->Get( nEvent );
+ return pRet;
+}
+
+bool SwFormatINetFormat::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ switch(nMemberId)
+ {
+ case MID_URL_URL:
+ rVal <<= msURL;
+ break;
+ case MID_URL_TARGET:
+ rVal <<= msTargetFrame;
+ break;
+ case MID_URL_HYPERLINKNAME:
+ rVal <<= msHyperlinkName;
+ break;
+ case MID_URL_VISITED_FMT:
+ {
+ OUString sVal = msVisitedFormatName;
+ if (sVal.isEmpty() && mnVisitedFormatId != 0)
+ SwStyleNameMapper::FillUIName(mnVisitedFormatId, sVal);
+ if (!sVal.isEmpty())
+ SwStyleNameMapper::FillProgName(sVal, sVal,
+ SwGetPoolIdFromName::ChrFmt);
+ rVal <<= sVal;
+ }
+ break;
+ case MID_URL_UNVISITED_FMT:
+ {
+ OUString sVal = msINetFormatName;
+ if (sVal.isEmpty() && mnINetFormatId != 0)
+ SwStyleNameMapper::FillUIName(mnINetFormatId, sVal);
+ if (!sVal.isEmpty())
+ SwStyleNameMapper::FillProgName(sVal, sVal,
+ SwGetPoolIdFromName::ChrFmt);
+ rVal <<= sVal;
+ }
+ break;
+ case MID_URL_HYPERLINKEVENTS:
+ {
+ // create (and return) event descriptor
+ rtl::Reference<SwHyperlinkEventDescriptor> pEvents =
+ new SwHyperlinkEventDescriptor();
+ pEvents->copyMacrosFromINetFormat(*this);
+
+ // all others return a string; so we just set rVal here and exit
+ rVal <<= uno::Reference<container::XNameReplace>(pEvents);
+ }
+ break;
+ default:
+ rVal <<= OUString();
+ break;
+ }
+ return true;
+}
+bool SwFormatINetFormat::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ nMemberId &= ~CONVERT_TWIPS;
+
+ // all properties except HyperlinkEvents are of type string, hence
+ // we treat HyperlinkEvents specially
+ if (MID_URL_HYPERLINKEVENTS == nMemberId)
+ {
+ uno::Reference<container::XNameReplace> xReplace;
+ rVal >>= xReplace;
+ if (xReplace.is())
+ {
+ // Create hyperlink event descriptor. Then copy events
+ // from argument into descriptor. Then copy events from
+ // the descriptor into the format.
+ rtl::Reference<SwHyperlinkEventDescriptor> pEvents = new SwHyperlinkEventDescriptor();
+ pEvents->copyMacrosFromNameReplace(xReplace);
+ pEvents->copyMacrosIntoINetFormat(*this);
+ }
+ else
+ {
+ // wrong type!
+ bRet = false;
+ }
+ }
+ else
+ {
+ // all string properties:
+ if(rVal.getValueType() != ::cppu::UnoType<OUString>::get())
+ return false;
+
+ switch(nMemberId)
+ {
+ case MID_URL_URL:
+ rVal >>= msURL;
+ break;
+ case MID_URL_TARGET:
+ rVal >>= msTargetFrame;
+ break;
+ case MID_URL_HYPERLINKNAME:
+ rVal >>= msHyperlinkName;
+ break;
+ case MID_URL_VISITED_FMT:
+ {
+ OUString sVal;
+ rVal >>= sVal;
+ OUString aString;
+ SwStyleNameMapper::FillUIName( sVal, aString, SwGetPoolIdFromName::ChrFmt );
+ msVisitedFormatName = aString;
+ mnVisitedFormatId = SwStyleNameMapper::GetPoolIdFromUIName( msVisitedFormatName,
+ SwGetPoolIdFromName::ChrFmt );
+ }
+ break;
+ case MID_URL_UNVISITED_FMT:
+ {
+ OUString sVal;
+ rVal >>= sVal;
+ OUString aString;
+ SwStyleNameMapper::FillUIName( sVal, aString, SwGetPoolIdFromName::ChrFmt );
+ msINetFormatName = aString;
+ mnINetFormatId = SwStyleNameMapper::GetPoolIdFromUIName( msINetFormatName, SwGetPoolIdFromName::ChrFmt );
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ }
+ return bRet;
+}
+
+SwFormatRuby::SwFormatRuby( OUString aRubyText )
+ : SfxPoolItem( RES_TXTATR_CJK_RUBY ),
+ m_sRubyText( std::move(aRubyText) ),
+ m_pTextAttr( nullptr ),
+ m_nCharFormatId( 0 ),
+ m_nPosition( 0 ),
+ m_eAdjustment( css::text::RubyAdjust_LEFT )
+{
+}
+
+SwFormatRuby::SwFormatRuby( const SwFormatRuby& rAttr )
+ : SfxPoolItem( RES_TXTATR_CJK_RUBY ),
+ m_sRubyText( rAttr.m_sRubyText ),
+ m_sCharFormatName( rAttr.m_sCharFormatName ),
+ m_pTextAttr( nullptr ),
+ m_nCharFormatId( rAttr.m_nCharFormatId),
+ m_nPosition( rAttr.m_nPosition ),
+ m_eAdjustment( rAttr.m_eAdjustment )
+{
+}
+
+SwFormatRuby::~SwFormatRuby()
+{
+}
+
+SwFormatRuby& SwFormatRuby::operator=( const SwFormatRuby& rAttr )
+{
+ // SwFormatRuby is not shareable, so ptr compare is OK
+ if (areSfxPoolItemPtrsEqual(this, &rAttr))
+ return *this;
+
+ m_sRubyText = rAttr.m_sRubyText;
+ m_sCharFormatName = rAttr.m_sCharFormatName;
+ m_nCharFormatId = rAttr.m_nCharFormatId;
+ m_nPosition = rAttr.m_nPosition;
+ m_eAdjustment = rAttr.m_eAdjustment;
+ m_pTextAttr = nullptr;
+ return *this;
+}
+
+bool SwFormatRuby::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+ return m_sRubyText == static_cast<const SwFormatRuby&>(rAttr).m_sRubyText &&
+ m_sCharFormatName == static_cast<const SwFormatRuby&>(rAttr).m_sCharFormatName &&
+ m_nCharFormatId == static_cast<const SwFormatRuby&>(rAttr).m_nCharFormatId &&
+ m_nPosition == static_cast<const SwFormatRuby&>(rAttr).m_nPosition &&
+ m_eAdjustment == static_cast<const SwFormatRuby&>(rAttr).m_eAdjustment;
+}
+
+SwFormatRuby* SwFormatRuby::Clone( SfxItemPool* ) const
+{
+ return new SwFormatRuby( *this );
+}
+
+bool SwFormatRuby::QueryValue( uno::Any& rVal,
+ sal_uInt8 nMemberId ) const
+{
+ bool bRet = true;
+ nMemberId &= ~CONVERT_TWIPS;
+ switch( nMemberId )
+ {
+ case MID_RUBY_TEXT: rVal <<= m_sRubyText; break;
+ case MID_RUBY_ADJUST: rVal <<= static_cast<sal_Int16>(m_eAdjustment); break;
+ case MID_RUBY_CHARSTYLE:
+ {
+ OUString aString;
+ SwStyleNameMapper::FillProgName(m_sCharFormatName, aString, SwGetPoolIdFromName::ChrFmt );
+ rVal <<= aString;
+ }
+ break;
+ case MID_RUBY_ABOVE:
+ {
+ rVal <<= static_cast<bool>(!m_nPosition);
+ }
+ break;
+ case MID_RUBY_POSITION:
+ {
+ rVal <<= m_nPosition;
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+bool SwFormatRuby::PutValue( const uno::Any& rVal,
+ sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ nMemberId &= ~CONVERT_TWIPS;
+ switch( nMemberId )
+ {
+ case MID_RUBY_TEXT:
+ bRet = rVal >>= m_sRubyText;
+ break;
+ case MID_RUBY_ADJUST:
+ {
+ sal_Int16 nSet = 0;
+ rVal >>= nSet;
+ if(nSet >= sal_Int16(text::RubyAdjust_LEFT) && nSet <= sal_Int16(text::RubyAdjust_INDENT_BLOCK))
+ m_eAdjustment = static_cast<text::RubyAdjust>(nSet);
+ else
+ bRet = false;
+ }
+ break;
+ case MID_RUBY_ABOVE:
+ {
+ const uno::Type& rType = cppu::UnoType<bool>::get();
+ if(rVal.hasValue() && rVal.getValueType() == rType)
+ {
+ bool bAbove = *o3tl::doAccess<bool>(rVal);
+ m_nPosition = bAbove ? 0 : 1;
+ }
+ }
+ break;
+ case MID_RUBY_POSITION:
+ {
+ sal_Int16 nSet = 0;
+ rVal >>= nSet;
+ if(nSet >= sal_Int16(text::RubyPosition::ABOVE) && nSet <= sal_Int16(text::RubyPosition::INTER_CHARACTER))
+ m_nPosition = nSet;
+ else
+ bRet = false;
+ }
+ break;
+ case MID_RUBY_CHARSTYLE:
+ {
+ OUString sTmp;
+ bRet = rVal >>= sTmp;
+ if(bRet)
+ m_sCharFormatName = SwStyleNameMapper::GetUIName(sTmp, SwGetPoolIdFromName::ChrFmt );
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+SwFormatMeta * SwFormatMeta::CreatePoolDefault(const sal_uInt16 i_nWhich)
+{
+ return new SwFormatMeta(i_nWhich);
+}
+
+SwFormatMeta::SwFormatMeta(const sal_uInt16 i_nWhich)
+ : SfxPoolItem( i_nWhich )
+ , m_pMeta()
+ , m_pTextAttr( nullptr )
+{
+ OSL_ENSURE((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich),
+ "ERROR: SwFormatMeta: invalid which id!");
+}
+
+SwFormatMeta::SwFormatMeta( std::shared_ptr< ::sw::Meta > i_pMeta,
+ const sal_uInt16 i_nWhich )
+ : SfxPoolItem( i_nWhich )
+ , m_pMeta( std::move(i_pMeta) )
+ , m_pTextAttr( nullptr )
+{
+ OSL_ENSURE((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich),
+ "ERROR: SwFormatMeta: invalid which id!");
+ OSL_ENSURE(m_pMeta, "SwFormatMeta: no Meta ?");
+ // DO NOT call m_pMeta->SetFormatMeta(this) here; only from SetTextAttr!
+}
+
+SwFormatMeta::~SwFormatMeta()
+{
+ // SwFormatMeta is not shareable, so ptr compare is OK
+ if (m_pMeta && areSfxPoolItemPtrsEqual(m_pMeta->GetFormatMeta(), this))
+ {
+ NotifyChangeTextNode(nullptr);
+ m_pMeta->SetFormatMeta(nullptr);
+ }
+}
+
+bool SwFormatMeta::operator==( const SfxPoolItem & i_rOther ) const
+{
+ return SfxPoolItem::operator==( i_rOther )
+ && m_pMeta == static_cast<SwFormatMeta const &>( i_rOther ).m_pMeta;
+}
+
+SwFormatMeta* SwFormatMeta::Clone( SfxItemPool * /*pPool*/ ) const
+{
+ // if this is indeed a copy, then DoCopy must be called later!
+ return m_pMeta // #i105148# pool default may be cloned also!
+ ? new SwFormatMeta( m_pMeta, Which() ) : new SwFormatMeta( Which() );
+}
+
+void SwFormatMeta::SetTextAttr(SwTextMeta * const i_pTextAttr)
+{
+ OSL_ENSURE(!(m_pTextAttr && i_pTextAttr),
+ "SwFormatMeta::SetTextAttr: already has text attribute?");
+ OSL_ENSURE( m_pTextAttr || i_pTextAttr ,
+ "SwFormatMeta::SetTextAttr: no attribute to remove?");
+ m_pTextAttr = i_pTextAttr;
+ OSL_ENSURE(m_pMeta, "inserted SwFormatMeta has no sw::Meta?");
+ // the sw::Meta must be able to find the current text attribute!
+ if (m_pMeta)
+ {
+ if (i_pTextAttr)
+ {
+ m_pMeta->SetFormatMeta(this);
+ }
+ // SwFormatMeta is not shareable, so ptr compare is OK
+ else if (areSfxPoolItemPtrsEqual(m_pMeta->GetFormatMeta(), this))
+ { // text attribute gone => de-register from text node!
+ NotifyChangeTextNode(nullptr);
+ m_pMeta->SetFormatMeta(nullptr);
+ }
+ }
+}
+
+void SwFormatMeta::NotifyChangeTextNode(SwTextNode *const pTextNode)
+{
+ // N.B.: do not reset m_pTextAttr here: see call in nodes.cxx,
+ // where the hint is not deleted!
+ OSL_ENSURE(m_pMeta, "SwFormatMeta::NotifyChangeTextNode: no Meta?");
+ // SwFormatMeta is not shareable, so ptr compare is OK
+ if (m_pMeta && areSfxPoolItemPtrsEqual(m_pMeta->GetFormatMeta(), this))
+ { // do not call Modify, that would call SwXMeta::SwClientNotify
+ m_pMeta->NotifyChangeTextNode(pTextNode);
+ }
+}
+
+// this SwFormatMeta has been cloned and points at the same sw::Meta as the source
+// this method copies the sw::Meta
+void SwFormatMeta::DoCopy(::sw::MetaFieldManager & i_rTargetDocManager,
+ SwTextNode & i_rTargetTextNode)
+{
+ OSL_ENSURE(m_pMeta, "DoCopy called for SwFormatMeta with no sw::Meta?");
+ if (!m_pMeta)
+ return;
+
+ const std::shared_ptr< ::sw::Meta> pOriginal( m_pMeta );
+ if (RES_TXTATR_META == Which())
+ {
+ m_pMeta = std::make_shared<::sw::Meta>(this);
+ }
+ else
+ {
+ ::sw::MetaField *const pMetaField(
+ static_cast< ::sw::MetaField* >(pOriginal.get()));
+ m_pMeta = i_rTargetDocManager.makeMetaField( this,
+ pMetaField->m_nNumberFormat, pMetaField->IsFixedLanguage() );
+ }
+ // Meta must have a text node before calling RegisterAsCopyOf
+ m_pMeta->NotifyChangeTextNode(& i_rTargetTextNode);
+ // this cannot be done in Clone: a Clone is not necessarily a copy!
+ m_pMeta->RegisterAsCopyOf(*pOriginal);
+}
+
+namespace sw {
+
+Meta::Meta(SwFormatMeta * const i_pFormat)
+ : ::sfx2::Metadatable()
+ , sw::BroadcastingModify()
+ , m_pFormat(i_pFormat)
+ , m_pTextNode(nullptr)
+{
+}
+
+Meta::~Meta()
+{
+}
+
+SwTextMeta * Meta::GetTextAttr() const
+{
+ return m_pFormat ? m_pFormat->GetTextAttr() : nullptr;
+}
+
+void Meta::SetXMeta(rtl::Reference<SwXMeta> const& xMeta)
+{ m_wXMeta = xMeta.get(); }
+
+void Meta::NotifyChangeTextNode(SwTextNode *const pTextNode)
+{
+ m_pTextNode = pTextNode;
+ if (m_pTextNode && (GetRegisteredIn() != m_pTextNode))
+ {
+ m_pTextNode->Add(this);
+ }
+ else if (!m_pTextNode)
+ {
+ EndListeningAll();
+ }
+ if (!pTextNode) // text node gone? invalidate UNO object!
+ {
+ GetNotifier().Broadcast(SfxHint(SfxHintId::Deinitializing));
+ }
+}
+
+void Meta::SwClientNotify(const SwModify&, const SfxHint& rHint)
+{
+ if (rHint.GetId() != SfxHintId::SwLegacyModify)
+ return;
+ auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
+ CallSwClientNotify(rHint);
+ GetNotifier().Broadcast(SfxHint(SfxHintId::DataChanged));
+ if(RES_REMOVE_UNO_OBJECT == pLegacy->GetWhich())
+ { // invalidate cached uno object
+ SetXMeta(nullptr);
+ GetNotifier().Broadcast(SfxHint(SfxHintId::Deinitializing));
+ }
+}
+
+// sfx2::Metadatable
+::sfx2::IXmlIdRegistry& Meta::GetRegistry()
+{
+ SwTextNode * const pTextNode( GetTextNode() );
+ // GetRegistry may only be called on a meta that is actually in the
+ // document, which means it has a pointer to its text node
+ OSL_ENSURE(pTextNode, "ERROR: GetRegistry: no text node?");
+ if (!pTextNode)
+ throw uno::RuntimeException();
+ return pTextNode->GetRegistry();
+}
+
+bool Meta::IsInClipboard() const
+{
+ const SwTextNode * const pTextNode( GetTextNode() );
+// no text node: in UNDO OSL_ENSURE(pTextNode, "IsInClipboard: no text node?");
+ return pTextNode && pTextNode->IsInClipboard();
+}
+
+bool Meta::IsInUndo() const
+{
+ const SwTextNode * const pTextNode( GetTextNode() );
+// no text node: in UNDO OSL_ENSURE(pTextNode, "IsInUndo: no text node?");
+ return pTextNode == nullptr || pTextNode->IsInUndo();
+}
+
+bool Meta::IsInContent() const
+{
+ const SwTextNode * const pTextNode( GetTextNode() );
+ OSL_ENSURE(pTextNode, "IsInContent: no text node?");
+ return pTextNode == nullptr || pTextNode->IsInContent();
+}
+
+css::uno::Reference< css::rdf::XMetadatable > Meta::MakeUnoObject()
+{
+ return SwXMeta::CreateXMeta(*this, {}, {});
+}
+
+MetaField::MetaField(SwFormatMeta * const i_pFormat,
+ const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage)
+ : Meta(i_pFormat)
+ , m_nNumberFormat( nNumberFormat )
+ , m_bIsFixedLanguage( bIsFixedLanguage )
+{
+}
+
+void MetaField::GetPrefixAndSuffix(
+ OUString *const o_pPrefix, OUString *const o_pSuffix, OUString *const o_pShadowsColor)
+{
+ try
+ {
+ const uno::Reference<rdf::XMetadatable> xMetaField( MakeUnoObject() );
+ assert(dynamic_cast<SwXMetaField*>(xMetaField.get()) && "GetPrefixAndSuffix: no SwXMetaField?");
+ if (xMetaField.is())
+ {
+ SwTextNode * const pTextNode( GetTextNode() );
+ SwDocShell const * const pShell(pTextNode->GetDoc().GetDocShell());
+ const uno::Reference<frame::XModel> xModel(
+ pShell ? pShell->GetModel() : nullptr, uno::UNO_SET_THROW);
+ getPrefixAndSuffix(xModel, xMetaField, o_pPrefix, o_pSuffix, o_pShadowsColor);
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "sw", "");
+ }
+}
+
+sal_uInt32 MetaField::GetNumberFormat(const OUString& aContent) const
+{
+ //TODO: this probably lacks treatment for some special cases
+ sal_uInt32 nNumberFormat( m_nNumberFormat );
+ SwTextNode * const pTextNode( GetTextNode() );
+ if (pTextNode)
+ {
+ double number;
+ (void) pTextNode->GetDoc().IsNumberFormat( aContent, nNumberFormat, number );
+ }
+ return nNumberFormat;
+}
+
+void MetaField::SetNumberFormat(sal_uInt32 nNumberFormat)
+{
+ // effectively, the member is only a default:
+ // GetNumberFormat checks if the text actually conforms
+ m_nNumberFormat = nNumberFormat;
+}
+
+MetaFieldManager::MetaFieldManager()
+{
+}
+
+std::shared_ptr<MetaField>
+MetaFieldManager::makeMetaField(SwFormatMeta * const i_pFormat,
+ const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage)
+{
+ const std::shared_ptr<MetaField> pMetaField(
+ new MetaField(i_pFormat, nNumberFormat, bIsFixedLanguage) );
+ m_MetaFields.push_back(pMetaField);
+ return pMetaField;
+}
+
+namespace {
+
+struct IsInUndo
+{
+ bool operator()(std::weak_ptr<MetaField> const & pMetaField) {
+ return pMetaField.lock()->IsInUndo();
+ }
+};
+
+struct MakeUnoObject
+{
+ uno::Reference<text::XTextField>
+ operator()(std::weak_ptr<MetaField> const & pMetaField) {
+ return uno::Reference<text::XTextField>(
+ pMetaField.lock()->MakeUnoObject(), uno::UNO_QUERY);
+ }
+};
+
+}
+
+std::vector< uno::Reference<text::XTextField> >
+MetaFieldManager::getMetaFields()
+{
+ // erase deleted fields
+ std::erase_if(m_MetaFields, [] (std::weak_ptr<MetaField> const& rField) { return rField.expired(); });
+ // filter out fields in UNDO
+ MetaFieldList_t filtered(m_MetaFields.size());
+ const MetaFieldList_t::iterator iter2(
+ std::remove_copy_if(m_MetaFields.begin(), m_MetaFields.end(),
+ filtered.begin(), IsInUndo()));
+ filtered.erase(iter2, filtered.end());
+ // create uno objects
+ std::vector< uno::Reference<text::XTextField> > ret(filtered.size());
+ std::transform(filtered.begin(), filtered.end(), ret.begin(),
+ MakeUnoObject());
+ return ret;
+}
+
+void MetaFieldManager::copyDocumentProperties(const SwDoc& rSource)
+{
+ const SwDocShell* pDocShell = rSource.GetDocShell();
+ if (!pDocShell)
+ return;
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(pDocShell->GetModel(), uno::UNO_QUERY);
+ uno::Reference<util::XCloneable> xCloneable(xDocumentPropertiesSupplier->getDocumentProperties(), uno::UNO_QUERY);
+ m_xDocumentProperties.set(xCloneable->createClone(), uno::UNO_QUERY);
+}
+
+const uno::Reference<document::XDocumentProperties>& MetaFieldManager::getDocumentProperties() const
+{
+ return m_xDocumentProperties;
+}
+
+} // namespace sw
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */