1
0
Fork 0
libreoffice/sw/source/core/txtnode/fmtatr2.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

900 lines
28 KiB
C++

/* -*- 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 )
{
setNonShareable();
}
SwFormatCharFormat::SwFormatCharFormat( const SwFormatCharFormat& rAttr )
: SfxPoolItem( RES_TXTATR_CHARFMT ),
SwClient( rAttr.GetCharFormat() ),
m_pTextAttribute( nullptr )
{
setNonShareable();
}
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));
}
else if (rHint.GetId() == SfxHintId::SwFormatChange)
{
auto pChangeHint = static_cast<const SwFormatChangeHint*>(&rHint);
if(m_pTextAttribute)
m_pTextAttribute->TriggerNodeUpdate(*pChangeHint);
}
else if (rHint.GetId() == SfxHintId::SwLegacyModify)
{
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 )
{
setNonShareable();
}
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 )
{
setNonShareable();
}
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 )
{
setNonShareable();
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 )
{
setNonShareable();
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 )
{
setNonShareable();
}
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 )
{
setNonShareable();
}
SwFormatRuby::~SwFormatRuby()
{
}
void SwFormatRuby::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatRuby"));
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("m_pTextAttr"), "%p", m_pTextAttr);
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("ruby-text"),
BAD_CAST(m_sRubyText.toUtf8().getStr()));
SfxPoolItem::dumpAsXml(pWriter);
(void)xmlTextWriterEndElement(pWriter);
}
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 )
{
setNonShareable();
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 )
{
setNonShareable();
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(SfxHintId::SwRemoveUnoObject == rHint.GetId())
{
CallSwClientNotify(rHint);
GetNotifier().Broadcast(SfxHint(SfxHintId::DataChanged));
// invalidate cached uno object
SetXMeta(nullptr);
GetNotifier().Broadcast(SfxHint(SfxHintId::Deinitializing));
}
else if (rHint.GetId() == SfxHintId::SwLegacyModify || rHint.GetId() == SfxHintId::SwFormatChange)
{
CallSwClientNotify(rHint);
GetNotifier().Broadcast(SfxHint(SfxHintId::DataChanged));
}
}
// 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: */