/* -*- 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/style/CaseMap.hpp>
#include <com/sun/star/awt/FontDescriptor.hpp>
#include <com/sun/star/frame/status/FontHeight.hpp>
#include <math.h>
#include <sal/log.hxx>
#include <o3tl/safeint.hxx>
#include <osl/diagnose.h>
#include <comphelper/configuration.hxx>
#include <unotools/fontdefs.hxx>
#include <unotools/intlwrapper.hxx>
#include <unotools/syslocale.hxx>
#include <utility>
#include <vcl/outdev.hxx>
#include <vcl/unohelp.hxx>
#include <svtools/unitconv.hxx>
#include <editeng/editids.hrc>
#include <editeng/editrids.hrc>
#include <tools/bigint.hxx>
#include <tools/mapunit.hxx>
#include <tools/UnitConversion.hxx>
#include <rtl/math.hxx>
#include <rtl/ustring.hxx>
#include <i18nlangtag/languagetag.hxx>
#include <svl/itemset.hxx>
#include <svtools/langtab.hxx>
#include <svl/itempool.hxx>
#include <svtools/ctrltool.hxx>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/text/FontEmphasis.hpp>
#include <editeng/rsiditem.hxx>
#include <editeng/memberids.h>
#include <editeng/flstitem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/postitem.hxx>
#include <editeng/wghtitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/crossedoutitem.hxx>
#include <editeng/shdditem.hxx>
#include <editeng/autokernitem.hxx>
#include <editeng/wrlmitem.hxx>
#include <editeng/contouritem.hxx>
#include <editeng/colritem.hxx>
#include <editeng/kernitem.hxx>
#include <editeng/cmapitem.hxx>
#include <editeng/escapementitem.hxx>
#include <editeng/langitem.hxx>
#include <editeng/nhypitem.hxx>
#include <editeng/blinkitem.hxx>
#include <editeng/emphasismarkitem.hxx>
#include <editeng/twolinesitem.hxx>
#include <editeng/scriptsetitem.hxx>
#include <editeng/charrotateitem.hxx>
#include <editeng/charscaleitem.hxx>
#include <editeng/charreliefitem.hxx>
#include <editeng/rubyitem.hxx>
#include <editeng/itemtype.hxx>
#include <editeng/scripthintitem.hxx>
#include <editeng/eerdll.hxx>
#include <docmodel/color/ComplexColorJSON.hxx>
#include <docmodel/uno/UnoComplexColor.hxx>
#include <docmodel/color/ComplexColor.hxx>
#include <libxml/xmlwriter.h>
#include <unordered_map>
using namespace ::com::sun::star;
using namespace ::com::sun::star::text;
SfxPoolItem* SvxFontItem::CreateDefault() {
return new SvxFontItem(0);}
SfxPoolItem* SvxPostureItem::CreateDefault() {
return new SvxPostureItem(ITALIC_NONE,
0);}
SfxPoolItem* SvxWeightItem::CreateDefault() {return new SvxWeightItem(WEIGHT_NORMAL, 0);}
SfxPoolItem* SvxScriptHintItem::CreateDefault() {return new SvxScriptHintItem(0);}
SfxPoolItem* SvxFontHeightItem::CreateDefault() {return new SvxFontHeightItem(240, 100, 0);}
SfxPoolItem* SvxUnderlineItem::CreateDefault() {return new SvxUnderlineItem(LINESTYLE_NONE, 0);}
SfxPoolItem* SvxOverlineItem::CreateDefault() {return new SvxOverlineItem(LINESTYLE_NONE, 0);}
SfxPoolItem* SvxCrossedOutItem::CreateDefault() {return new SvxCrossedOutItem(STRIKEOUT_NONE, 0);}
SfxPoolItem* SvxShadowedItem::CreateDefault() {return new SvxShadowedItem(false , 0);}
SfxPoolItem* SvxAutoKernItem::CreateDefault() {return new SvxAutoKernItem(false , 0);}
SfxPoolItem* SvxWordLineModeItem::CreateDefault() {return new SvxWordLineModeItem(false , 0);}
SfxPoolItem* SvxContourItem::CreateDefault() {return new SvxContourItem(false , 0);}
SfxPoolItem* SvxColorItem::CreateDefault() {return new SvxColorItem(0);}
SfxPoolItem* SvxKerningItem::CreateDefault() {return new SvxKerningItem(0, 0);}
SfxPoolItem* SvxCaseMapItem::CreateDefault() {return new SvxCaseMapItem(SvxCaseMap::NotMapped, 0);}
SfxPoolItem* SvxEscapementItem::CreateDefault() {return new SvxEscapementItem(0);}
SfxPoolItem* SvxLanguageItem::CreateDefault() {return new SvxLanguageItem(LANGUAGE_GERMAN, 0);}
SfxPoolItem* SvxEmphasisMarkItem::CreateDefault() {return new SvxEmphasisMarkItem(FontEmphasisMark::NONE, TypedWhichId<SvxEmphasisMarkItem>(0));}
SfxPoolItem* SvxCharRotateItem::CreateDefault() {return new SvxCharRotateItem(0_deg10, false , TypedWhichId<SvxCharRotateItem>(0));}
SfxPoolItem* SvxCharScaleWidthItem::CreateDefault() {return new SvxCharScaleWidthItem(100, TypedWhichId<SvxCharScaleWidthItem>(0));}
SfxPoolItem* SvxCharReliefItem::CreateDefault() {return new SvxCharReliefItem(FontRelief::NONE, 0);}
// class SvxFontListItem -------------------------------------------------
SvxFontListItem::SvxFontListItem( const FontList* pFontLst,
const sal_uInt16 nId ) :
SfxPoolItem( nId ),
pFontList( pFontLst )
{
if ( pFontList )
{
sal_Int32 nCount = pFontList->GetFontNameCount();
aFontNameSeq.realloc( nCount );
auto pFontNameSeq = aFontNameSeq.getArray();
for ( sal_Int32 i = 0; i < nCount; i++ )
pFontNameSeq[i] = pFontList->GetFontName(i).GetFamilyName();
}
}
SvxFontListItem* SvxFontListItem::Clone( SfxItemPool* ) const
{
return new SvxFontListItem( *this );
}
bool SvxFontListItem::operator ==( const SfxPoolItem& rAttr ) const
{
assert(SfxPoolItem::operator ==(rAttr));
return ( pFontList == static_cast <const SvxFontListItem&>(rAttr).pFontList );
}
bool SvxFontListItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
{
rVal <<= aFontNameSeq;
return true ;
}
bool SvxFontListItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
rText.clear();
return false ;
}
// class SvxFontItem -----------------------------------------------------
ItemInstanceManager* SvxFontItem::getItemInstanceManager() const
{
static HashedItemInstanceManager aInstanceManager(ItemType());
return &aInstanceManager;
}
size_t SvxFontItem::hashCode() const
{
std::size_t seed(0);
o3tl::hash_combine(seed, Which());
o3tl::hash_combine(seed, GetFamilyName().hashCode());
o3tl::hash_combine(seed, GetStyleName().hashCode());
o3tl::hash_combine(seed, GetFamily());
o3tl::hash_combine(seed, GetPitch());
o3tl::hash_combine(seed, GetCharSet());
return seed;
}
SvxFontItem::SvxFontItem(
const sal_uInt16 nId)
: SfxPoolItem( nId )
, aFamilyName()
, aStyleName()
, eFamily(FAMILY_SWISS)
, ePitch(PITCH_VARIABLE)
, eTextEncoding(RTL_TEXTENCODING_DONTKNOW)
{
}
SvxFontItem::SvxFontItem(
const FontFamily eFam,
OUString aName,
OUString aStName,
const FontPitch eFontPitch,
const rtl_TextEncoding eFontTextEncoding,
const sal_uInt16 nId)
: SfxPoolItem( nId )
, aFamilyName(std::move(aName))
, aStyleName(std::move(aStName))
, eFamily(eFam)
, ePitch(eFontPitch)
, eTextEncoding(eFontTextEncoding)
{
}
bool SvxFontItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case 0:
{
css::awt::FontDescriptor aFontDescriptor;
aFontDescriptor.Name = aFamilyName;
aFontDescriptor.StyleName = aStyleName;
aFontDescriptor.Family = static_cast <sal_Int16>(eFamily);
aFontDescriptor.CharSet = static_cast <sal_Int16>(eTextEncoding);
aFontDescriptor.Pitch = static_cast <sal_Int16>(ePitch);
rVal <<= aFontDescriptor;
}
break ;
case MID_FONT_FAMILY_NAME:
rVal <<= aFamilyName;
break ;
case MID_FONT_STYLE_NAME:
rVal <<= aStyleName;
break ;
case MID_FONT_FAMILY : rVal <<= static_cast <sal_Int16>(eFamily); break ;
case MID_FONT_CHAR_SET : rVal <<= static_cast <sal_Int16>(eTextEncoding); break ;
case MID_FONT_PITCH : rVal <<= static_cast <sal_Int16>(ePitch); break ;
}
return true ;
}
bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId)
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case 0:
{
css::awt::FontDescriptor aFontDescriptor;
if ( !( rVal >>= aFontDescriptor ))
return false ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
aFamilyName = aFontDescriptor.Name;
aStyleName = aFontDescriptor.StyleName;
eFamily = static_cast <FontFamily>(aFontDescriptor.Family);
eTextEncoding = static_cast <rtl_TextEncoding>(aFontDescriptor.CharSet);
ePitch = static_cast <FontPitch>(aFontDescriptor.Pitch);
}
break ;
case MID_FONT_FAMILY_NAME :
{
OUString aStr;
if (!(rVal >>= aStr))
return false ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
aFamilyName = aStr;
}
break ;
case MID_FONT_STYLE_NAME:
{
OUString aStr;
if (!(rVal >>= aStr))
return false ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
aStyleName = aStr;
}
break ;
case MID_FONT_FAMILY :
{
sal_Int16 nFamily = sal_Int16();
if (!(rVal >>= nFamily))
return false ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
eFamily = static_cast <FontFamily>(nFamily);
}
break ;
case MID_FONT_CHAR_SET :
{
sal_Int16 nSet = sal_Int16();
if (!(rVal >>= nSet))
return false ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
eTextEncoding = static_cast <rtl_TextEncoding>(nSet);
}
break ;
case MID_FONT_PITCH :
{
sal_Int16 nPitch = sal_Int16();
if (!(rVal >>= nPitch))
return false ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
ePitch = static_cast <FontPitch>(nPitch);
}
break ;
}
return true ;
}
void SvxFontItem::SetFamilyName(const OUString& rFamilyName)
{
if (aFamilyName == rFamilyName)
return ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
aFamilyName = rFamilyName;
}
void SvxFontItem::SetStyleName(const OUString &rStyleName)
{
if (aStyleName == rStyleName)
return ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
aStyleName = rStyleName;
}
void SvxFontItem::SetFamily(FontFamily _eFamily)
{
if (eFamily == _eFamily)
return ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
eFamily = _eFamily;
}
void SvxFontItem::SetPitch(FontPitch _ePitch)
{
if (ePitch == _ePitch)
return ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
ePitch = _ePitch;
}
void SvxFontItem::SetCharSet(rtl_TextEncoding _eEncoding)
{
if (eTextEncoding == _eEncoding)
return ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
eTextEncoding = _eEncoding;
}
bool SvxFontItem::operator ==( const SfxPoolItem& rAttr ) const
{
if (this == &rAttr)
return true ;
assert(SfxPoolItem::operator ==(rAttr));
const SvxFontItem& rItem(static_cast <const SvxFontItem&>(rAttr));
bool bRet = ( eFamily == rItem.eFamily &&
aFamilyName == rItem.aFamilyName &&
aStyleName == rItem.aStyleName );
if ( bRet )
{
if ( ePitch != rItem.ePitch || eTextEncoding != rItem.eTextEncoding )
{
bRet = false ;
SAL_INFO( "editeng.items" , "FontItem::operator==(): only pitch or rtl_TextEncoding different " );
}
}
return bRet;
}
SvxFontItem* SvxFontItem::Clone( SfxItemPool * ) const
{
return new SvxFontItem( *this );
}
bool SvxFontItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
rText = aFamilyName;
return true ;
}
void SvxFontItem::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("SvxFontItem" ));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId" ), BAD_CAST(OString::number(Which()).getStr()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("familyName" ), BAD_CAST(aFamilyName.toUtf8().getStr()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("styleName" ), BAD_CAST(aStyleName.toUtf8().getStr()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("family" ), BAD_CAST(OString::number(eFamily).getStr()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("pitch" ), BAD_CAST(OString::number(ePitch).getStr()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("textEncoding" ), BAD_CAST(OString::number(eTextEncoding).getStr()));
(void )xmlTextWriterEndElement(pWriter);
}
// class SvxPostureItem --------------------------------------------------
ItemInstanceManager* SvxPostureItem::getItemInstanceManager() const
{
static HashedItemInstanceManager aInstanceManager(ItemType());
return &aInstanceManager;
}
SvxPostureItem::SvxPostureItem( const FontItalic ePosture, const sal_uInt16 nId ) :
SfxEnumItem( nId, ePosture )
{
}
SvxPostureItem* SvxPostureItem::Clone( SfxItemPool * ) const
{
return new SvxPostureItem( *this );
}
bool SvxPostureItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
rText = GetValueTextByPos( GetValue() );
return true ;
}
OUString SvxPostureItem::GetValueTextByPos( sal_uInt16 nPos )
{
DBG_ASSERT( nPos <= sal_uInt16(ITALIC_NORMAL), "enum overflow!" );
FontItalic eItalic = static_cast <FontItalic>(nPos);
TranslateId pId;
switch ( eItalic )
{
case ITALIC_NONE: pId = RID_SVXITEMS_ITALIC_NONE; break ;
case ITALIC_OBLIQUE: pId = RID_SVXITEMS_ITALIC_OBLIQUE; break ;
case ITALIC_NORMAL: pId = RID_SVXITEMS_ITALIC_NORMAL; break ;
default : ;//prevent warning
}
return pId ? EditResId(pId) : OUString();
}
bool SvxPostureItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
nMemberId &= ~CONVERT_TWIPS;
switch ( nMemberId )
{
case MID_ITALIC:
rVal <<= GetBoolValue();
break ;
case MID_POSTURE:
rVal <<= vcl::unohelper::ConvertFontSlant(GetValue());
break ;
}
return true ;
}
bool SvxPostureItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
nMemberId &= ~CONVERT_TWIPS;
switch ( nMemberId )
{
case MID_ITALIC:
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetBoolValue(Any2Bool(rVal));
break ;
case MID_POSTURE:
{
awt::FontSlant eSlant;
if (!(rVal >>= eSlant))
{
sal_Int32 nValue = 0;
if (!(rVal >>= nValue))
return false ;
eSlant = static_cast <awt::FontSlant>(nValue);
}
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue(vcl::unohelper::ConvertFontSlant(eSlant));
}
}
return true ;
}
bool SvxPostureItem::HasBoolValue() const
{
return true ;
}
bool SvxPostureItem::GetBoolValue() const
{
return ( GetValue() >= ITALIC_OBLIQUE );
}
void SvxPostureItem::SetBoolValue( bool bVal )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( bVal ? ITALIC_NORMAL : ITALIC_NONE );
}
void SvxPostureItem::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("SvxPostureItem" ));
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("whichId" ), "%d" , Which());
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("value" ), "%d" , GetValue());
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation" ), BAD_CAST(GetValueTextByPos(GetValue()).toUtf8().getStr()));
(void )xmlTextWriterEndElement(pWriter);
}
// class SvxWeightItem ---------------------------------------------------
ItemInstanceManager* SvxWeightItem::getItemInstanceManager() const
{
static DefaultItemInstanceManager aInstanceManager(ItemType());
return &aInstanceManager;
}
SvxWeightItem::SvxWeightItem( const FontWeight eWght, const sal_uInt16 nId ) :
SfxEnumItem( nId, eWght )
{
}
bool SvxWeightItem::HasBoolValue() const
{
return true ;
}
bool SvxWeightItem::GetBoolValue() const
{
return GetValue() >= WEIGHT_BOLD;
}
void SvxWeightItem::SetBoolValue( bool bVal )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( bVal ? WEIGHT_BOLD : WEIGHT_NORMAL );
}
SvxWeightItem* SvxWeightItem::Clone( SfxItemPool * ) const
{
return new SvxWeightItem( *this );
}
bool SvxWeightItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
rText = GetValueTextByPos( GetValue() );
return true ;
}
OUString SvxWeightItem::GetValueTextByPos( sal_uInt16 nPos )
{
static TranslateId RID_SVXITEMS_WEIGHTS[] =
{
RID_SVXITEMS_WEIGHT_DONTKNOW,
RID_SVXITEMS_WEIGHT_THIN,
RID_SVXITEMS_WEIGHT_ULTRALIGHT,
RID_SVXITEMS_WEIGHT_LIGHT,
RID_SVXITEMS_WEIGHT_SEMILIGHT,
RID_SVXITEMS_WEIGHT_NORMAL,
RID_SVXITEMS_WEIGHT_MEDIUM,
RID_SVXITEMS_WEIGHT_SEMIBOLD,
RID_SVXITEMS_WEIGHT_BOLD,
RID_SVXITEMS_WEIGHT_ULTRABOLD,
RID_SVXITEMS_WEIGHT_BLACK
};
static_assert(std::size(RID_SVXITEMS_WEIGHTS) - 1 == WEIGHT_BLACK, "must match" );
assert(nPos <= sal_uInt16(WEIGHT_BLACK) && "enum overflow!" );
return EditResId(RID_SVXITEMS_WEIGHTS[nPos]);
}
bool SvxWeightItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
nMemberId &= ~CONVERT_TWIPS;
switch ( nMemberId )
{
case MID_BOLD :
rVal <<= GetBoolValue();
break ;
case MID_WEIGHT:
{
rVal <<= vcl::unohelper::ConvertFontWeight( GetValue() );
}
break ;
}
return true ;
}
bool SvxWeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
nMemberId &= ~CONVERT_TWIPS;
switch ( nMemberId )
{
case MID_BOLD :
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetBoolValue(Any2Bool(rVal));
break ;
case MID_WEIGHT:
{
double fValue = 0;
if (!(rVal >>= fValue))
{
sal_Int32 nValue = 0;
if (!(rVal >>= nValue))
return false ;
fValue = static_cast <float >(nValue);
}
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( vcl::unohelper::ConvertFontWeight(static_cast <float >(fValue)) );
}
break ;
}
return true ;
}
void SvxWeightItem::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("SvxWeightItem" ));
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("whichId" ), "%d" , Which());
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("value" ), "%d" , GetValue());
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation" ), BAD_CAST(GetValueTextByPos(GetValue()).toUtf8().getStr()));
(void )xmlTextWriterEndElement(pWriter);
}
// class SvxScriptHintItem ---------------------------------------------------
ItemInstanceManager* SvxScriptHintItem::getItemInstanceManager() const
{
static DefaultItemInstanceManager aInstanceManager(ItemType());
return &aInstanceManager;
}
SvxScriptHintItem::SvxScriptHintItem(const sal_uInt16 nId)
: SfxEnumItem(nId, i18nutil::ScriptHintType::Automatic)
{
}
SvxScriptHintItem::SvxScriptHintItem(i18nutil::ScriptHintType eType, const sal_uInt16 nId)
: SfxEnumItem(nId, eType)
{
}
SvxScriptHintItem* SvxScriptHintItem::Clone(SfxItemPool*) const
{
return new SvxScriptHintItem(*this );
}
bool SvxScriptHintItem::GetPresentation(SfxItemPresentation /*ePres*/, MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/, OUString& rText,
const IntlWrapper& /*rIntl*/) const
{
rText = GetValueText(GetValue());
return true ;
}
OUString SvxScriptHintItem::GetValueText(i18nutil::ScriptHintType eValue)
{
static const std::array<TranslateId, 5> RID_SVXITEMS_TYPES{
{ RID_SVXITEMS_SCRIPTHINTVAL_AUTO, RID_SVXITEMS_SCRIPTHINTVAL_IGNORE,
RID_SVXITEMS_SCRIPTHINTVAL_LATIN, RID_SVXITEMS_SCRIPTHINTVAL_ASIAN,
RID_SVXITEMS_SCRIPTHINTVAL_COMPLEX }
};
return EditResId(RID_SVXITEMS_TYPES.at(static_cast <size_t>(eValue)));
}
bool SvxScriptHintItem::QueryValue(uno::Any& rVal, sal_uInt8 nMemberId) const
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_SCRIPTHINT:
rVal <<= static_cast <sal_uInt16>(GetValue());
break ;
}
return true ;
}
bool SvxScriptHintItem::PutValue(const uno::Any& rVal, sal_uInt8 nMemberId)
{
sal_uInt16 nValue = 0;
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_SCRIPTHINT:
if (!(rVal >>= nValue))
{
return false ;
}
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue(i18nutil::ScriptHintType{ nValue });
break ;
}
return true ;
}
void SvxScriptHintItem::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("SvxScriptHintItem" ));
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("whichId" ), "%d" , Which());
(void )xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("value" ), "%d" ,
static_cast <int >(GetValue()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation" ),
BAD_CAST(GetValueText(GetValue()).toUtf8().getStr()));
(void )xmlTextWriterEndElement(pWriter);
}
// class SvxFontHeightItem -----------------------------------------------
ItemInstanceManager* SvxFontHeightItem::getItemInstanceManager() const
{
static HashedItemInstanceManager aInstanceManager(ItemType());
return &aInstanceManager;
}
size_t SvxFontHeightItem::hashCode() const
{
std::size_t seed(0);
o3tl::hash_combine(seed, Which());
o3tl::hash_combine(seed, GetHeight());
o3tl::hash_combine(seed, GetProp());
o3tl::hash_combine(seed, GetPropUnit());
return seed;
}
SvxFontHeightItem::SvxFontHeightItem( const sal_uInt32 nSz,
const sal_uInt16 nPrp,
const sal_uInt16 nId ) :
SfxPoolItem( nId )
{
SetHeight( nSz,nPrp ); // calculate in percentage
}
SvxFontHeightItem* SvxFontHeightItem::Clone( SfxItemPool * ) const
{
return new SvxFontHeightItem( *this );
}
bool SvxFontHeightItem::operator ==( const SfxPoolItem& rItem ) const
{
assert(SfxPoolItem::operator ==(rItem));
return GetHeight() == static_cast <const SvxFontHeightItem&>(rItem).GetHeight() &&
GetProp() == static_cast <const SvxFontHeightItem&>(rItem).GetProp() &&
GetPropUnit() == static_cast <const SvxFontHeightItem&>(rItem).GetPropUnit();
}
bool SvxFontHeightItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
// In StarOne is the uno::Any always 1/100mm. Through the MemberId it is
// controlled if the value in the Item should be 1/100mm or Twips.
bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
nMemberId &= ~CONVERT_TWIPS;
switch ( nMemberId )
{
case 0:
{
css::frame::status::FontHeight aFontHeight;
// Point (i.e. Twips) is asked for, thus re-calculate if
// CONVERT_TWIPS is not set.
if ( bConvert )
{
aFontHeight.Height = o3tl::convert<double >(nHeight, o3tl::Length::twip, o3tl::Length::pt);
}
else
{
double fPoints = o3tl::convert<double >(nHeight, o3tl::Length::mm100, o3tl::Length::pt);
aFontHeight.Height = rtl::math::round(fPoints, 1);
}
aFontHeight.Prop = MapUnit::MapRelative == ePropUnit ? nProp : 100;
float fRet = nProp;
switch ( ePropUnit )
{
case MapUnit::MapRelative:
fRet = 0.;
break ;
case MapUnit::Map100thMM:
fRet = o3tl::convert(fRet, o3tl::Length::mm100, o3tl::Length::pt);
break ;
case MapUnit::MapPoint:
break ;
case MapUnit::MapTwip:
fRet = o3tl::convert(fRet, o3tl::Length::twip, o3tl::Length::pt);
break ;
default : ;//prevent warning
}
aFontHeight.Diff = fRet;
rVal <<= aFontHeight;
}
break ;
case MID_FONTHEIGHT:
{
// Point (i.e. Twips) is asked for, thus re-calculate if
// CONVERT_TWIPS is not set.
if ( bConvert )
{
rVal <<= static_cast <float >(o3tl::convert<double >(nHeight, o3tl::Length::twip, o3tl::Length::pt));
}
else
{
double fPoints = o3tl::convert<double >(nHeight, o3tl::Length::mm100, o3tl::Length::pt);
rVal <<= static_cast <float >(::rtl::math::round(fPoints, 1));
}
}
break ;
case MID_FONTHEIGHT_PROP:
rVal <<= static_cast <sal_Int16>(MapUnit::MapRelative == ePropUnit ? nProp : 100);
break ;
case MID_FONTHEIGHT_DIFF:
{
float fRet = nProp;
switch ( ePropUnit )
{
case MapUnit::MapRelative:
fRet = 0.;
break ;
case MapUnit::Map100thMM:
fRet = o3tl::convert(fRet, o3tl::Length::mm100, o3tl::Length::pt);
break ;
case MapUnit::MapPoint:
break ;
case MapUnit::MapTwip:
fRet = o3tl::convert(fRet, o3tl::Length::twip, o3tl::Length::pt);
break ;
default : ;//prevent warning
}
rVal <<= fRet;
}
break ;
}
return true ;
}
// Try to reconstruct the original height input value from the modified height
// and the prop data; this seems somewhat futile given the various ways how the
// modified height is calculated (with and without conversion between twips and
// 100th mm; with an additional eCoreMetric input in one of the SetHeight
// overloads), and indeed known to occasionally produce nRet values that would
// be negative, so just guard against negative results here and throw the hands
// up in despair:
static sal_uInt32 lcl_GetRealHeight_Impl(sal_uInt32 nHeight, sal_uInt16 nProp, MapUnit eProp, bool bCoreInTwip)
{
sal_uInt32 nRet = nHeight;
short nDiff = 0;
switch ( eProp )
{
case MapUnit::MapRelative:
if (nProp)
{
nRet *= 100;
nRet /= nProp;
}
break ;
case MapUnit::MapPoint:
{
short nTemp = static_cast <short >(nProp);
nDiff = nTemp * 20;
if (!bCoreInTwip)
nDiff = static_cast <short >(convertTwipToMm100(nDiff));
break ;
}
case MapUnit::Map100thMM:
case MapUnit::MapTwip:
// In both cases, the units match core
nDiff = static_cast <short >(nProp);
break ;
default :
break ;
}
nRet = (nDiff < 0 || nRet >= o3tl::make_unsigned(nDiff))
? nRet - nDiff : 0;
//TODO: overflow in case nDiff < 0 and nRet - nDiff > SAL_MAX_UINT32
return nRet;
}
bool SvxFontHeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
nMemberId &= ~CONVERT_TWIPS;
switch ( nMemberId )
{
case 0:
{
css::frame::status::FontHeight aFontHeight;
if ( rVal >>= aFontHeight )
{
// Height
ePropUnit = MapUnit::MapRelative;
nProp = 100;
double fPoint = aFontHeight.Height;
if ( fPoint < 0. || fPoint > 10000. )
return false ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
nHeight = static_cast <tools::Long >( fPoint * 20.0 + 0.5 ); // Twips
if (!bConvert)
nHeight = convertTwipToMm100(nHeight); // Convert, if the item contains 1/100mm
nProp = aFontHeight.Prop;
}
else
return false ;
}
break ;
case MID_FONTHEIGHT:
{
ePropUnit = MapUnit::MapRelative;
nProp = 100;
double fPoint = 0;
if (!(rVal >>= fPoint))
{
sal_Int32 nValue = 0;
if (!(rVal >>= nValue))
return false ;
fPoint = static_cast <float >(nValue);
}
if (fPoint < 0. || fPoint > 10000.)
return false ;
static bool bFuzzing = comphelper::IsFuzzing();
if (bFuzzing && fPoint > 120)
{
SAL_WARN("editeng.items" , "SvxFontHeightItem ignoring font size of " << fPoint << " for performance" );
return false ;
}
ASSERT_CHANGE_REFCOUNTED_ITEM;
nHeight = static_cast <tools::Long >( fPoint * 20.0 + 0.5 ); // Twips
if (!bConvert)
nHeight = convertTwipToMm100(nHeight); // Convert, if the item contains 1/100mm
}
break ;
case MID_FONTHEIGHT_PROP:
{
sal_Int16 nNew = sal_Int16();
if (!(rVal >>= nNew))
return true ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
nHeight = lcl_GetRealHeight_Impl(nHeight, nProp, ePropUnit, bConvert);
nHeight *= nNew;
nHeight /= 100;
nProp = nNew;
ePropUnit = MapUnit::MapRelative;
}
break ;
case MID_FONTHEIGHT_DIFF:
{
nHeight = lcl_GetRealHeight_Impl(nHeight, nProp, ePropUnit, bConvert);
float fValue = 0;
if (!(rVal >>= fValue))
{
sal_Int32 nValue = 0;
if (!(rVal >>= nValue))
return false ;
fValue = static_cast <float >(nValue);
}
ASSERT_CHANGE_REFCOUNTED_ITEM;
sal_Int16 nCoreDiffValue = static_cast <sal_Int16>(fValue * 20.);
nHeight += bConvert ? nCoreDiffValue : convertTwipToMm100(nCoreDiffValue);
nProp = static_cast <sal_uInt16>(static_cast <sal_Int16>(fValue));
ePropUnit = MapUnit::MapPoint;
}
break ;
}
return true ;
}
bool SvxFontHeightItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit eCoreUnit,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& rIntl
) const
{
if ( MapUnit::MapRelative != ePropUnit )
{
rText = OUString::number( static_cast <short >(nProp) ) +
" " + EditResId( GetMetricId( ePropUnit ) );
if ( 0 <= static_cast <short >(nProp) )
rText = "+" + rText;
}
else if ( 100 == nProp )
{
rText = GetMetricText( static_cast <tools::Long >(nHeight),
eCoreUnit, MapUnit::MapPoint, &rIntl ) +
" " + EditResId(GetMetricId(MapUnit::MapPoint));
}
else
rText = OUString::number( nProp ) + "%" ;
return true ;
}
void SvxFontHeightItem::ScaleMetrics( tools::Long nMult, tools::Long nDiv )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
nHeight = static_cast <sal_uInt32>(BigInt::Scale( nHeight, nMult, nDiv ));
}
bool SvxFontHeightItem::HasMetrics() const
{
return true ;
}
void SvxFontHeightItem::SetHeight( sal_uInt32 nNewHeight, const sal_uInt16 nNewProp,
MapUnit eUnit )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
if ( MapUnit::MapRelative != eUnit )
nHeight = nNewHeight + ::ItemToControl( short (nNewProp), eUnit,
FieldUnit::TWIP );
else if ( 100 != nNewProp )
nHeight = sal_uInt32(( nNewHeight * nNewProp ) / 100 );
else
nHeight = nNewHeight;
nProp = nNewProp;
ePropUnit = eUnit;
}
void SvxFontHeightItem::SetHeight( sal_uInt32 nNewHeight, sal_uInt16 nNewProp,
MapUnit eMetric, MapUnit eCoreMetric )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
if ( MapUnit::MapRelative != eMetric )
nHeight = nNewHeight +
::ControlToItem( ::ItemToControl(static_cast <short >(nNewProp), eMetric,
FieldUnit::TWIP ), FieldUnit::TWIP,
eCoreMetric );
else if ( 100 != nNewProp )
nHeight = sal_uInt32(( nNewHeight * nNewProp ) / 100 );
else
nHeight = nNewHeight;
nProp = nNewProp;
ePropUnit = eMetric;
}
void SvxFontHeightItem::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("SvxFontHeightItem" ));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId" ), BAD_CAST(OString::number(Which()).getStr()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("height" ), BAD_CAST(OString::number(nHeight).getStr()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("prop" ), BAD_CAST(OString::number(nProp).getStr()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("propUnit" ), BAD_CAST(OString::number(static_cast <int >(ePropUnit)).getStr()));
(void )xmlTextWriterEndElement(pWriter);
}
// class SvxTextLineItem ------------------------------------------------
SvxTextLineItem::SvxTextLineItem( const FontLineStyle eSt, const sal_uInt16 nId )
: SfxEnumItem(nId, eSt)
, maColor(COL_TRANSPARENT)
{
}
bool SvxTextLineItem::HasBoolValue() const
{
return true ;
}
bool SvxTextLineItem::GetBoolValue() const
{
return GetValue() != LINESTYLE_NONE;
}
void SvxTextLineItem::SetBoolValue( bool bVal )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( bVal ? LINESTYLE_SINGLE : LINESTYLE_NONE );
}
SvxTextLineItem* SvxTextLineItem::Clone( SfxItemPool * ) const
{
return new SvxTextLineItem( *this );
}
bool SvxTextLineItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
rText = GetValueTextByPos( GetValue() );
if ( !maColor.IsTransparent() )
rText += cpDelim + ::GetColorString(maColor);
return true ;
}
OUString SvxTextLineItem::GetValueTextByPos( sal_uInt16 /*nPos*/ ) const
{
OSL_FAIL("SvxTextLineItem::GetValueTextByPos: Pure virtual method" );
return OUString();
}
bool SvxTextLineItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_TEXTLINED:
rVal <<= GetBoolValue();
break ;
case MID_TL_STYLE:
rVal <<= static_cast <sal_Int16>(GetValue());
break ;
case MID_TL_COLOR:
rVal <<= maColor;
break ;
case MID_TL_COMPLEX_COLOR:
{
auto xComplexColor = model::color::createXComplexColor(maComplexColor);
rVal <<= xComplexColor;
break ;
}
case MID_TL_HASCOLOR:
rVal <<= maColor.GetAlpha() == 255;
break ;
}
return true ;
}
bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
nMemberId &= ~CONVERT_TWIPS;
bool bRet = true ;
switch (nMemberId)
{
case MID_TEXTLINED:
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetBoolValue(Any2Bool(rVal));
break ;
case MID_TL_STYLE:
{
sal_Int32 nValue = 0;
if (!(rVal >>= nValue))
bRet = false ;
else
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue(static_cast <FontLineStyle>(nValue));
}
}
break ;
case MID_TL_COLOR:
{
Color nCol;
if ( !( rVal >>= nCol ) )
bRet = false ;
else
{
// Keep transparence, because it contains the information
// whether the font color or the stored color should be used
ASSERT_CHANGE_REFCOUNTED_ITEM;
sal_uInt8 nAlpha = maColor.GetAlpha();
maColor = nCol;
maColor.SetAlpha( nAlpha );
}
}
break ;
case MID_TL_COMPLEX_COLOR:
{
css::uno::Reference<css::util::XComplexColor> xComplexColor;
if (!(rVal >>= xComplexColor))
return false ;
if (xComplexColor.is())
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
maComplexColor = model::color::getFromXComplexColor(xComplexColor);
}
}
break ;
case MID_TL_HASCOLOR:
ASSERT_CHANGE_REFCOUNTED_ITEM;
maColor.SetAlpha( Any2Bool( rVal ) ? 255 : 0 );
break ;
}
return bRet;
}
bool SvxTextLineItem::operator ==( const SfxPoolItem& rItem ) const
{
return SfxEnumItem::operator ==( rItem ) &&
maColor == static_cast <const SvxTextLineItem&>(rItem).maColor &&
maComplexColor == static_cast <const SvxTextLineItem&>(rItem).maComplexColor;
}
// class SvxUnderlineItem ------------------------------------------------
ItemInstanceManager* SvxUnderlineItem::getItemInstanceManager() const
{
static DefaultItemInstanceManager aInstanceManager(ItemType());
return &aInstanceManager;
}
SvxUnderlineItem::SvxUnderlineItem( const FontLineStyle eSt, const sal_uInt16 nId )
: SvxTextLineItem( eSt, nId )
{
}
SvxUnderlineItem* SvxUnderlineItem::Clone( SfxItemPool * ) const
{
return new SvxUnderlineItem( *this );
}
OUString SvxUnderlineItem::GetValueTextByPos( sal_uInt16 nPos ) const
{
static TranslateId RID_SVXITEMS_UL[] =
{
RID_SVXITEMS_UL_NONE,
RID_SVXITEMS_UL_SINGLE,
RID_SVXITEMS_UL_DOUBLE,
RID_SVXITEMS_UL_DOTTED,
RID_SVXITEMS_UL_DONTKNOW,
RID_SVXITEMS_UL_DASH,
RID_SVXITEMS_UL_LONGDASH,
RID_SVXITEMS_UL_DASHDOT,
RID_SVXITEMS_UL_DASHDOTDOT,
RID_SVXITEMS_UL_SMALLWAVE,
RID_SVXITEMS_UL_WAVE,
RID_SVXITEMS_UL_DOUBLEWAVE,
RID_SVXITEMS_UL_BOLD,
RID_SVXITEMS_UL_BOLDDOTTED,
RID_SVXITEMS_UL_BOLDDASH,
RID_SVXITEMS_UL_BOLDLONGDASH,
RID_SVXITEMS_UL_BOLDDASHDOT,
RID_SVXITEMS_UL_BOLDDASHDOTDOT,
RID_SVXITEMS_UL_BOLDWAVE
};
static_assert(std::size(RID_SVXITEMS_UL) - 1 == LINESTYLE_BOLDWAVE, "must match" );
assert(nPos <= sal_uInt16(LINESTYLE_BOLDWAVE) && "enum overflow!" );
return EditResId(RID_SVXITEMS_UL[nPos]);
}
// class SvxOverlineItem ------------------------------------------------
ItemInstanceManager* SvxOverlineItem::getItemInstanceManager() const
{
static DefaultItemInstanceManager aInstanceManager(ItemType());
return &aInstanceManager;
}
SvxOverlineItem::SvxOverlineItem( const FontLineStyle eSt, const sal_uInt16 nId )
: SvxTextLineItem( eSt, nId )
{
}
SvxOverlineItem* SvxOverlineItem::Clone( SfxItemPool * ) const
{
return new SvxOverlineItem( *this );
}
OUString SvxOverlineItem::GetValueTextByPos( sal_uInt16 nPos ) const
{
static TranslateId RID_SVXITEMS_OL[] =
{
RID_SVXITEMS_OL_NONE,
RID_SVXITEMS_OL_SINGLE,
RID_SVXITEMS_OL_DOUBLE,
RID_SVXITEMS_OL_DOTTED,
RID_SVXITEMS_OL_DONTKNOW,
RID_SVXITEMS_OL_DASH,
RID_SVXITEMS_OL_LONGDASH,
RID_SVXITEMS_OL_DASHDOT,
RID_SVXITEMS_OL_DASHDOTDOT,
RID_SVXITEMS_OL_SMALLWAVE,
RID_SVXITEMS_OL_WAVE,
RID_SVXITEMS_OL_DOUBLEWAVE,
RID_SVXITEMS_OL_BOLD,
RID_SVXITEMS_OL_BOLDDOTTED,
RID_SVXITEMS_OL_BOLDDASH,
RID_SVXITEMS_OL_BOLDLONGDASH,
RID_SVXITEMS_OL_BOLDDASHDOT,
RID_SVXITEMS_OL_BOLDDASHDOTDOT,
RID_SVXITEMS_OL_BOLDWAVE
};
static_assert(std::size(RID_SVXITEMS_OL) - 1 == LINESTYLE_BOLDWAVE, "must match" );
assert(nPos <= sal_uInt16(LINESTYLE_BOLDWAVE) && "enum overflow!" );
return EditResId(RID_SVXITEMS_OL[nPos]);
}
// class SvxCrossedOutItem -----------------------------------------------
ItemInstanceManager* SvxCrossedOutItem::getItemInstanceManager() const
{
static DefaultItemInstanceManager aInstanceManager(ItemType());
return &aInstanceManager;
}
SvxCrossedOutItem::SvxCrossedOutItem( const FontStrikeout eSt, const sal_uInt16 nId )
: SfxEnumItem( nId, eSt )
{
}
bool SvxCrossedOutItem::HasBoolValue() const
{
return true ;
}
bool SvxCrossedOutItem::GetBoolValue() const
{
return GetValue() != STRIKEOUT_NONE;
}
void SvxCrossedOutItem::SetBoolValue( bool bVal )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( bVal ? STRIKEOUT_SINGLE : STRIKEOUT_NONE );
}
SvxCrossedOutItem* SvxCrossedOutItem::Clone( SfxItemPool * ) const
{
return new SvxCrossedOutItem( *this );
}
bool SvxCrossedOutItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
rText = GetValueTextByPos( GetValue() );
return true ;
}
OUString SvxCrossedOutItem::GetValueTextByPos( sal_uInt16 nPos )
{
static TranslateId RID_SVXITEMS_STRIKEOUT[] =
{
RID_SVXITEMS_STRIKEOUT_NONE,
RID_SVXITEMS_STRIKEOUT_SINGLE,
RID_SVXITEMS_STRIKEOUT_DOUBLE,
RID_SVXITEMS_STRIKEOUT_DONTKNOW,
RID_SVXITEMS_STRIKEOUT_BOLD,
RID_SVXITEMS_STRIKEOUT_SLASH,
RID_SVXITEMS_STRIKEOUT_X
};
static_assert(std::size(RID_SVXITEMS_STRIKEOUT) - 1 == STRIKEOUT_X, "must match" );
assert(nPos <= sal_uInt16(STRIKEOUT_X) && "enum overflow!" );
return EditResId(RID_SVXITEMS_STRIKEOUT[nPos]);
}
bool SvxCrossedOutItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_CROSSED_OUT:
rVal <<= GetBoolValue();
break ;
case MID_CROSS_OUT:
rVal <<= static_cast <sal_Int16>(GetValue());
break ;
}
return true ;
}
bool SvxCrossedOutItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_CROSSED_OUT:
SetBoolValue(Any2Bool(rVal));
break ;
case MID_CROSS_OUT:
{
sal_Int32 nValue = 0;
if (!(rVal >>= nValue))
return false ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue(static_cast <FontStrikeout>(nValue));
}
break ;
}
return true ;
}
// class SvxShadowedItem -------------------------------------------------
SvxShadowedItem::SvxShadowedItem( const bool bShadowed, const sal_uInt16 nId ) :
SfxBoolItem( nId, bShadowed )
{
}
SvxShadowedItem* SvxShadowedItem::Clone( SfxItemPool * ) const
{
return new SvxShadowedItem( *this );
}
bool SvxShadowedItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
TranslateId pId = RID_SVXITEMS_SHADOWED_FALSE;
if ( GetValue() )
pId = RID_SVXITEMS_SHADOWED_TRUE;
rText = EditResId(pId);
return true ;
}
// class SvxAutoKernItem -------------------------------------------------
SvxAutoKernItem::SvxAutoKernItem( const bool bAutoKern, const sal_uInt16 nId ) :
SfxBoolItem( nId, bAutoKern )
{
}
SvxAutoKernItem* SvxAutoKernItem::Clone( SfxItemPool * ) const
{
return new SvxAutoKernItem( *this );
}
bool SvxAutoKernItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
TranslateId pId = RID_SVXITEMS_AUTOKERN_FALSE;
if ( GetValue() )
pId = RID_SVXITEMS_AUTOKERN_TRUE;
rText = EditResId(pId);
return true ;
}
// class SvxWordLineModeItem ---------------------------------------------
SvxWordLineModeItem::SvxWordLineModeItem( const bool bWordLineMode,
const sal_uInt16 nId ) :
SfxBoolItem( nId, bWordLineMode )
{
}
SvxWordLineModeItem* SvxWordLineModeItem::Clone( SfxItemPool * ) const
{
return new SvxWordLineModeItem( *this );
}
bool SvxWordLineModeItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
TranslateId pId = RID_SVXITEMS_WORDLINE_FALSE;
if ( GetValue() )
pId = RID_SVXITEMS_WORDLINE_TRUE;
rText = EditResId(pId);
return true ;
}
// class SvxContourItem --------------------------------------------------
SvxContourItem::SvxContourItem( const bool bContoured, const sal_uInt16 nId ) :
SfxBoolItem( nId, bContoured )
{
}
SvxContourItem* SvxContourItem::Clone( SfxItemPool * ) const
{
return new SvxContourItem( *this );
}
bool SvxContourItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
TranslateId pId = RID_SVXITEMS_CONTOUR_FALSE;
if ( GetValue() )
pId = RID_SVXITEMS_CONTOUR_TRUE;
rText = EditResId(pId);
return true ;
}
// class SvxColorItem ----------------------------------------------------
SvxColorItem::SvxColorItem( const sal_uInt16 nId ) :
SfxPoolItem(nId),
mColor( COL_BLACK )
{
}
SvxColorItem::SvxColorItem( const Color& rCol, const sal_uInt16 nId ) :
SfxPoolItem( nId ),
mColor( rCol )
{
}
SvxColorItem::SvxColorItem(Color const & rColor, model::ComplexColor const & rComplexColor, const sal_uInt16 nId)
: SfxPoolItem(nId)
, mColor(rColor)
, maComplexColor(rComplexColor)
{
}
SvxColorItem::~SvxColorItem()
{
}
bool SvxColorItem::operator ==( const SfxPoolItem& rAttr ) const
{
assert(SfxPoolItem::operator ==(rAttr));
const SvxColorItem& rColorItem = static_cast <const SvxColorItem&>(rAttr);
return mColor == rColorItem.mColor &&
maComplexColor == rColorItem.maComplexColor;
}
size_t SvxColorItem::hashCode() const
{
std::size_t seed(0);
o3tl::hash_combine(seed, static_cast <sal_Int32>(mColor));
o3tl::hash_combine(seed, maComplexColor);
return seed;
}
bool SvxColorItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_COLOR_ALPHA:
{
auto fTransparency = static_cast <double >(255 - mColor.GetAlpha()) * 100 / 255;
rVal <<= static_cast <sal_Int16>(basegfx::fround(fTransparency));
break ;
}
case MID_GRAPHIC_TRANSPARENT:
{
rVal <<= mColor.GetAlpha() == 0;
break ;
}
case MID_COLOR_THEME_INDEX:
{
rVal <<= sal_Int16(maComplexColor.getThemeColorType());
break ;
}
case MID_COLOR_TINT_OR_SHADE:
{
sal_Int16 nValue = 0;
for (auto const & rTransform : maComplexColor.getTransformations())
{
if (rTransform.meType == model::TransformationType::Tint)
nValue = rTransform.mnValue;
else if (rTransform.meType == model::TransformationType::Shade)
nValue = -rTransform.mnValue;
}
rVal <<= nValue;
break ;
}
case MID_COLOR_LUM_MOD:
{
sal_Int16 nValue = 10000;
for (auto const & rTransform : maComplexColor.getTransformations())
{
if (rTransform.meType == model::TransformationType::LumMod)
nValue = rTransform.mnValue;
}
rVal <<= nValue;
break ;
}
case MID_COLOR_LUM_OFF:
{
sal_Int16 nValue = 0;
for (auto const & rTransform : maComplexColor.getTransformations())
{
if (rTransform.meType == model::TransformationType::LumOff)
nValue = rTransform.mnValue;
}
rVal <<= nValue;
break ;
}
case MID_COMPLEX_COLOR_JSON:
{
rVal <<= OStringToOUString(model::color::convertToJSON(maComplexColor), RTL_TEXTENCODING_UTF8);
break ;
}
case MID_COMPLEX_COLOR:
{
auto xComplexColor = model::color::createXComplexColor(maComplexColor);
rVal <<= xComplexColor;
break ;
}
case MID_COLOR_RGB:
default :
{
rVal <<= mColor;
break ;
}
}
return true ;
}
bool SvxColorItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_COLOR_ALPHA:
{
sal_Int16 nTransparency = 0;
bool bRet = rVal >>= nTransparency;
if (bRet)
{
auto fTransparency = static_cast <double >(nTransparency) * 255 / 100;
mColor.SetAlpha(255 - static_cast <sal_uInt8>(basegfx::fround(fTransparency)));
}
return bRet;
}
case MID_GRAPHIC_TRANSPARENT:
{
mColor.SetAlpha( Any2Bool( rVal ) ? 0 : 255 );
return true ;
}
case MID_COLOR_THEME_INDEX:
{
sal_Int16 nIndex = -1;
if (!(rVal >>= nIndex))
return false ;
maComplexColor.setThemeColor(model::convertToThemeColorType(nIndex));
}
break ;
case MID_COLOR_TINT_OR_SHADE:
{
sal_Int16 nTintShade = 0;
if (!(rVal >>= nTintShade))
return false ;
maComplexColor.removeTransformations(model::TransformationType::Tint);
maComplexColor.removeTransformations(model::TransformationType::Shade);
if (nTintShade > 0)
maComplexColor.addTransformation({model::TransformationType::Tint, nTintShade});
else if (nTintShade < 0)
{
sal_Int16 nShade = o3tl::narrowing<sal_Int16>(-nTintShade);
maComplexColor.addTransformation({model::TransformationType::Shade, nShade});
}
}
break ;
case MID_COLOR_LUM_MOD:
{
sal_Int16 nLumMod = 10000;
if (!(rVal >>= nLumMod))
return false ;
maComplexColor.removeTransformations(model::TransformationType::LumMod);
maComplexColor.addTransformation({model::TransformationType::LumMod, nLumMod});
}
break ;
case MID_COLOR_LUM_OFF:
{
sal_Int16 nLumOff = 0;
if (!(rVal >>= nLumOff))
return false ;
maComplexColor.removeTransformations(model::TransformationType::LumOff);
maComplexColor.addTransformation({model::TransformationType::LumOff, nLumOff});
}
break ;
case MID_COMPLEX_COLOR_JSON:
{
OUString sComplexColorJson;
if (!(rVal >>= sComplexColorJson))
return false ;
if (sComplexColorJson.isEmpty())
return false ;
OString aJSON = OUStringToOString(sComplexColorJson, RTL_TEXTENCODING_ASCII_US);
if (!model::color::convertFromJSON(aJSON, maComplexColor))
return false ;
}
break ;
case MID_COMPLEX_COLOR:
{
css::uno::Reference<css::util::XComplexColor> xComplexColor;
if (!(rVal >>= xComplexColor))
return false ;
if (xComplexColor.is())
maComplexColor = model::color::getFromXComplexColor(xComplexColor);
}
break ;
case MID_COLOR_RGB:
default :
{
if (!(rVal >>= mColor))
return false ;
}
break ;
}
return true ;
}
SvxColorItem* SvxColorItem::Clone( SfxItemPool * ) const
{
return new SvxColorItem( *this );
}
bool SvxColorItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
rText = ::GetColorString( mColor );
return true ;
}
void SvxColorItem::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("SvxColorItem" ));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId" ), BAD_CAST(OString::number(Which()).getStr()));
std::stringstream ss;
ss << mColor;
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value" ), BAD_CAST(ss.str().c_str()));
OUString aStr;
IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
GetPresentation( SfxItemPresentation::Complete, MapUnit::Map100thMM, MapUnit::Map100thMM, aStr, aIntlWrapper);
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation" ), BAD_CAST(OUStringToOString(aStr, RTL_TEXTENCODING_UTF8).getStr()));
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("complex-color" ));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("type" ),
BAD_CAST(OString::number(sal_Int16(maComplexColor.getType())).getStr()));
for (auto const & rTransform : maComplexColor.getTransformations())
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("transformation" ));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("type" ),
BAD_CAST(OString::number(sal_Int16(rTransform.meType)).getStr()));
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value" ),
BAD_CAST(OString::number(rTransform.mnValue).getStr()));
(void )xmlTextWriterEndElement(pWriter);
}
(void )xmlTextWriterEndElement(pWriter);
(void )xmlTextWriterEndElement(pWriter);
}
// class SvxKerningItem --------------------------------------------------
SvxKerningItem::SvxKerningItem( const short nKern, const sal_uInt16 nId ) :
SfxInt16Item( nId, nKern )
{
}
SvxKerningItem* SvxKerningItem::Clone( SfxItemPool * ) const
{
return new SvxKerningItem( *this );
}
void SvxKerningItem::ScaleMetrics( tools::Long nMult, tools::Long nDiv )
{
SetValue( static_cast <sal_Int16>(BigInt::Scale( GetValue(), nMult, nDiv )) );
}
bool SvxKerningItem::HasMetrics() const
{
return true ;
}
bool SvxKerningItem::GetPresentation
(
SfxItemPresentation ePres,
MapUnit eCoreUnit,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& rIntl
) const
{
switch ( ePres )
{
case SfxItemPresentation::Nameless:
rText = GetMetricText( static_cast <tools::Long >(GetValue()), eCoreUnit, MapUnit::MapPoint, &rIntl ) +
" " + EditResId(GetMetricId(MapUnit::MapPoint));
return true ;
case SfxItemPresentation::Complete:
{
rText = EditResId(RID_SVXITEMS_KERNING_COMPLETE);
TranslateId pId;
if ( GetValue() > 0 )
pId = RID_SVXITEMS_KERNING_EXPANDED;
else if ( GetValue() < 0 )
pId = RID_SVXITEMS_KERNING_CONDENSED;
if (pId)
rText += EditResId(pId);
rText += GetMetricText( static_cast <tools::Long >(GetValue()), eCoreUnit, MapUnit::MapPoint, &rIntl ) +
" " + EditResId(GetMetricId(MapUnit::MapPoint));
return true ;
}
default : ; //prevent warning
}
return false ;
}
bool SvxKerningItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
sal_Int16 nVal = GetValue();
if (nMemberId & CONVERT_TWIPS)
nVal = static_cast <sal_Int16>(convertTwipToMm100(nVal));
rVal <<= nVal;
return true ;
}
bool SvxKerningItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId)
{
sal_Int16 nVal = sal_Int16();
if (!(rVal >>= nVal))
return false ;
if (nMemberId & CONVERT_TWIPS)
nVal = o3tl::toTwips(nVal, o3tl::Length::mm100);
SetValue(nVal);
return true ;
}
// class SvxCaseMapItem --------------------------------------------------
SvxCaseMapItem::SvxCaseMapItem( const SvxCaseMap eMap, const sal_uInt16 nId ) :
SfxEnumItem( nId, eMap )
{
}
SvxCaseMapItem* SvxCaseMapItem::Clone( SfxItemPool * ) const
{
return new SvxCaseMapItem( *this );
}
bool SvxCaseMapItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
rText = GetValueTextByPos( static_cast <sal_uInt16>(GetValue()) );
return true ;
}
OUString SvxCaseMapItem::GetValueTextByPos( sal_uInt16 nPos )
{
static TranslateId RID_SVXITEMS_CASEMAP[] =
{
RID_SVXITEMS_CASEMAP_NONE,
RID_SVXITEMS_CASEMAP_UPPERCASE,
RID_SVXITEMS_CASEMAP_LOWERCASE,
RID_SVXITEMS_CASEMAP_TITLE,
RID_SVXITEMS_CASEMAP_SMALLCAPS
};
static_assert(std::size(RID_SVXITEMS_CASEMAP) == size_t(SvxCaseMap::End), "must match" );
assert(nPos < sal_uInt16(SvxCaseMap::End) && "enum overflow!" );
return EditResId(RID_SVXITEMS_CASEMAP[nPos]);
}
bool SvxCaseMapItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
{
sal_Int16 nRet = style::CaseMap::NONE;
switch ( GetValue() )
{
case SvxCaseMap::Uppercase : nRet = style::CaseMap::UPPERCASE; break ;
case SvxCaseMap::Lowercase : nRet = style::CaseMap::LOWERCASE; break ;
case SvxCaseMap::Capitalize : nRet = style::CaseMap::TITLE ; break ;
case SvxCaseMap::SmallCaps: nRet = style::CaseMap::SMALLCAPS; break ;
default : break ;
}
rVal <<= nRet;
return true ;
}
bool SvxCaseMapItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
{
sal_uInt16 nVal = sal_uInt16();
if (!(rVal >>= nVal))
return false ;
SvxCaseMap eVal;
switch ( nVal )
{
case style::CaseMap::NONE : eVal = SvxCaseMap::NotMapped; break ;
case style::CaseMap::UPPERCASE: eVal = SvxCaseMap::Uppercase; break ;
case style::CaseMap::LOWERCASE: eVal = SvxCaseMap::Lowercase; break ;
case style::CaseMap::TITLE : eVal = SvxCaseMap::Capitalize; break ;
case style::CaseMap::SMALLCAPS: eVal = SvxCaseMap::SmallCaps; break ;
default : return false ;
}
SetValue(eVal);
return true ;
}
// class SvxEscapementItem -----------------------------------------------
SvxEscapementItem::SvxEscapementItem( const sal_uInt16 nId ) :
SfxPoolItem( nId ),
nEsc ( 0 ),
nProp ( 100 )
{
}
SvxEscapementItem::SvxEscapementItem( const SvxEscapement eEscape,
const sal_uInt16 nId ) :
SfxPoolItem( nId ),
nProp( 100 )
{
SetEscapement( eEscape );
if ( nEsc )
nProp = DFLT_ESC_PROP;
}
SvxEscapementItem::SvxEscapementItem( const short _nEsc,
const sal_uInt8 _nProp,
const sal_uInt16 nId ) :
SfxPoolItem( nId ),
nEsc ( _nEsc ),
nProp ( _nProp )
{
}
bool SvxEscapementItem::operator ==( const SfxPoolItem& rAttr ) const
{
assert(SfxPoolItem::operator ==(rAttr));
return ( nEsc == static_cast <const SvxEscapementItem&>(rAttr).nEsc &&
nProp == static_cast <const SvxEscapementItem&>(rAttr).nProp );
}
SvxEscapementItem* SvxEscapementItem::Clone( SfxItemPool * ) const
{
return new SvxEscapementItem( *this );
}
bool SvxEscapementItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
static constexpr TranslateId RID_SVXITEMS_ESCAPEMENT[] =
{
RID_SVXITEMS_ESCAPEMENT_OFF,
RID_SVXITEMS_ESCAPEMENT_SUPER,
RID_SVXITEMS_ESCAPEMENT_SUB
};
SvxEscapement pos = GetEscapement();
static_assert(std::size(RID_SVXITEMS_ESCAPEMENT) == size_t(SvxEscapement::End), "must match" );
assert(pos < SvxEscapement::End && "enum overflow!" );
rText = EditResId(RID_SVXITEMS_ESCAPEMENT[static_cast <size_t>(pos)]);
if ( nEsc != 0 )
{
if ( DFLT_ESC_AUTO_SUPER == nEsc || DFLT_ESC_AUTO_SUB == nEsc )
rText += EditResId(RID_SVXITEMS_ESCAPEMENT_AUTO);
else
rText += OUString::number( nEsc ) + "%" ;
}
return true ;
}
SvxEscapement SvxEscapementItem::GetEscapement() const
{
if ( nEsc < 0 )
return SvxEscapement::Subscript;
else if ( nEsc > 0 )
return SvxEscapement::Superscript;
return SvxEscapement::Off;
}
bool SvxEscapementItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_ESC:
rVal <<= static_cast <sal_Int16>(nEsc);
break ;
case MID_ESC_HEIGHT:
rVal <<= static_cast <sal_Int8>(nProp);
break ;
case MID_AUTO_ESC:
rVal <<= (DFLT_ESC_AUTO_SUB == nEsc || DFLT_ESC_AUTO_SUPER == nEsc);
break ;
}
return true ;
}
bool SvxEscapementItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_ESC:
{
sal_Int16 nVal = sal_Int16();
if ( (rVal >>= nVal) && (std::abs(nVal) <= MAX_ESC_POS+1))
nEsc = nVal;
else
return false ;
}
break ;
case MID_ESC_HEIGHT:
{
sal_Int8 nVal = sal_Int8();
if ( (rVal >>= nVal) && (nVal <= 100))
nProp = nVal;
else
return false ;
}
break ;
case MID_AUTO_ESC:
{
bool bVal = Any2Bool(rVal);
if (bVal)
{
if (nEsc < 0)
nEsc = DFLT_ESC_AUTO_SUB;
else
nEsc = DFLT_ESC_AUTO_SUPER;
}
else
if (DFLT_ESC_AUTO_SUPER == nEsc )
--nEsc;
else if (DFLT_ESC_AUTO_SUB == nEsc)
++nEsc;
}
break ;
}
return true ;
}
// class SvxLanguageItem -------------------------------------------------
ItemInstanceManager* SvxLanguageItem::getItemInstanceManager() const
{
static DefaultItemInstanceManager aInstanceManager(ItemType());
return &aInstanceManager;
}
SvxLanguageItem::SvxLanguageItem( const LanguageType eLang, const sal_uInt16 nId )
: SvxLanguageItem_Base( nId , eLang )
{
}
SvxLanguageItem* SvxLanguageItem::Clone( SfxItemPool * ) const
{
return new SvxLanguageItem( *this );
}
bool SvxLanguageItem::GetPresentation
(
SfxItemPresentation /*ePres*/,
MapUnit /*eCoreUnit*/,
MapUnit /*ePresUnit*/,
OUString& rText, const IntlWrapper& /*rIntl*/
) const
{
rText = SvtLanguageTable::GetLanguageString( GetValue() );
return true ;
}
bool SvxLanguageItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_LANG_INT: // for basic conversions!
rVal <<= static_cast <sal_Int16>(static_cast <sal_uInt16>(GetValue()));
break ;
case MID_LANG_LOCALE:
lang::Locale aRet( LanguageTag::convertToLocale( GetValue(), false ));
rVal <<= aRet;
break ;
}
return true ;
}
bool SvxLanguageItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
nMemberId &= ~CONVERT_TWIPS;
switch (nMemberId)
{
case MID_LANG_INT: // for basic conversions!
{
sal_Int32 nValue = 0;
if (!(rVal >>= nValue))
return false ;
ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue(LanguageType(nValue));
}
break ;
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=95 H=99 G=96
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland