/* -*- 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 <fldbas.hxx>
#include <float.h>
#include <math.h>
#include <libxml/xmlwriter.h>
#include <rtl/math.hxx>
#include <svl/zforlist.hxx>
#include <svl/zformat.hxx>
#include <editeng/unolingu.hxx>
#include <o3tl/enumarray.hxx>
#include <unofldmid.h>
#include <doc.hxx>
#include <editsh.hxx>
#include <frame.hxx>
#include <flddat.hxx>
#include <ndtxt.hxx>
#include <fmtfld.hxx>
#include <txtfld.hxx>
#include <pam.hxx>
#include <docfld.hxx>
#include <swtable.hxx>
#include <docufld.hxx>
#include <expfld.hxx>
#include <shellres.hxx>
#include <calc.hxx>
#include <strings.hrc>
#include <docary.hxx>
#include <authfld.hxx>
#include <calbck.hxx>
using namespace ::com::sun::star;
using namespace nsSwDocInfoSubType;
static LanguageType lcl_GetLanguageOfFormat( LanguageType nLng, sal_uLong nFormat,
const SvNumberFormatter& rFormatter )
{
if( nLng == LANGUAGE_NONE ) // Bug #60010
nLng = LANGUAGE_SYSTEM;
else if( nLng == ::GetAppLanguage() )
switch( rFormatter.GetIndexTableOffset( nFormat ))
{
case NF_NUMBER_SYSTEM:
case NF_DATE_SYSTEM_SHORT:
case NF_DATE_SYSTEM_LONG:
case NF_DATETIME_SYSTEM_SHORT_HHMM:
nLng = LANGUAGE_SYSTEM;
break;
default: break;
}
return nLng;
}
// Globals
/// field names
std::vector<OUString>* SwFieldType::s_pFieldNames = nullptr;
namespace
{
const o3tl::enumarray<SwFieldIds,SwFieldTypesEnum> aTypeTab {
/* SwFieldIds::Database */ TYP_DBFLD,
/* SwFieldIds::User */ TYP_USERFLD,
/* SwFieldIds::Filename */ TYP_FILENAMEFLD,
/* SwFieldIds::DatabaseName */ TYP_DBNAMEFLD,
/* SwFieldIds::Date */ TYP_DATEFLD,
/* SwFieldIds::Time */ TYP_TIMEFLD,
/* SwFieldIds::PageNumber */ TYP_PAGENUMBERFLD, // dynamic
/* SwFieldIds::Author */ TYP_AUTHORFLD,
/* SwFieldIds::Chapter */ TYP_CHAPTERFLD,
/* SwFieldIds::DocStat */ TYP_DOCSTATFLD,
/* SwFieldIds::GetExp */ TYP_GETFLD, // dynamic
/* SwFieldIds::SetExp */ TYP_SETFLD, // dynamic
/* SwFieldIds::GetRef */ TYP_GETREFFLD,
/* SwFieldIds::HiddenText */ TYP_HIDDENTXTFLD,
/* SwFieldIds::Postit */ TYP_POSTITFLD,
/* SwFieldIds::FixDate */ TYP_FIXDATEFLD,
/* SwFieldIds::FixTime */ TYP_FIXTIMEFLD,
/* SwFieldIds::Reg */ TYP_BEGIN, // old (no change since 2000)
/* SwFieldIds::VarReg */ TYP_BEGIN, // old (no change since 2000)
/* SwFieldIds::SetRef */ TYP_SETREFFLD,
/* SwFieldIds::Input */ TYP_INPUTFLD,
/* SwFieldIds::Macro */ TYP_MACROFLD,
/* SwFieldIds::Dde */ TYP_DDEFLD,
/* SwFieldIds::Table */ TYP_FORMELFLD,
/* SwFieldIds::HiddenPara */ TYP_HIDDENPARAFLD,
/* SwFieldIds::DocInfo */ TYP_DOCINFOFLD,
/* SwFieldIds::TemplateName */ TYP_TEMPLNAMEFLD,
/* SwFieldIds::DbNextSet */ TYP_DBNEXTSETFLD,
/* SwFieldIds::DbNumSet */ TYP_DBNUMSETFLD,
/* SwFieldIds::DbSetNumber */ TYP_DBSETNUMBERFLD,
/* SwFieldIds::ExtUser */ TYP_EXTUSERFLD,
/* SwFieldIds::RefPageSet */ TYP_SETREFPAGEFLD,
/* SwFieldIds::RefPageGet */ TYP_GETREFPAGEFLD,
/* SwFieldIds::Internet */ TYP_INTERNETFLD,
/* SwFieldIds::JumpEdit */ TYP_JUMPEDITFLD,
/* SwFieldIds::Script */ TYP_SCRIPTFLD,
/* SwFieldIds::DateTime */ TYP_BEGIN, // dynamic
/* SwFieldIds::TableOfAuthorities*/ TYP_AUTHORITY,
/* SwFieldIds::CombinedChars */ TYP_COMBINED_CHARS,
/* SwFieldIds::Dropdown */ TYP_DROPDOWN,
/* SwFieldIds::ParagraphSignature */ TYP_PARAGRAPHSIGFLD
};
}
OUString SwFieldType::GetTypeStr(sal_uInt16 nTypeId)
{
if (!s_pFieldNames)
GetFieldName_();
if (nTypeId < SwFieldType::s_pFieldNames->size())
return (*SwFieldType::s_pFieldNames)[nTypeId];
return OUString();
}
// each field references a field type that is unique for each document
SwFieldType::SwFieldType( SwFieldIds nWhichId )
: SwModify(nullptr)
, m_nWhich(nWhichId)
{
}
OUString SwFieldType::GetName() const
{
return OUString();
}
void SwFieldType::QueryValue( uno::Any&, sal_uInt16 ) const
{
}
void SwFieldType::PutValue( const uno::Any& , sal_uInt16 )
{
}
void SwFieldType::dumpAsXml(xmlTextWriterPtr pWriter) const
{
SwIterator<SwFormatField, SwFieldType> aIter(*this);
if (!aIter.First())
return;
xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldType"));
for (const SwFormatField* pFormatField = aIter.First(); pFormatField;
pFormatField = aIter.Next())
pFormatField->dumpAsXml(pWriter);
xmlTextWriterEndElement(pWriter);
}
void SwFieldTypes::dumpAsXml(xmlTextWriterPtr pWriter) const
{
xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldTypes"));
sal_uInt16 nCount = size();
for (sal_uInt16 nType = 0; nType < nCount; ++nType)
(*this)[nType]->dumpAsXml(pWriter);
xmlTextWriterEndElement(pWriter);
}
// Base class for all fields.
// A field (multiple can exist) references a field type (can exists only once)
SwField::SwField(
SwFieldType* pType,
sal_uInt32 nFormat,
LanguageType nLang,
bool bUseFieldValueCache)
: m_Cache()
, m_bUseFieldValueCache( bUseFieldValueCache )
, m_nLang( nLang )
, m_bIsAutomaticLanguage( true )
, m_nFormat( nFormat )
, m_pType( pType )
{
assert(m_pType);
}
SwField::~SwField()
{
}
// instead of indirectly via the type
#ifdef DBG_UTIL
SwFieldIds SwField::Which() const
{
assert(m_pType);
return m_pType->Which();
}
#endif
sal_uInt16 SwField::GetTypeId() const
{
sal_uInt16 nRet;
switch (m_pType->Which())
{
case SwFieldIds::DateTime:
if (GetSubType() & FIXEDFLD)
nRet = static_cast<sal_uInt16>(GetSubType() & DATEFLD ? TYP_FIXDATEFLD : TYP_FIXTIMEFLD);
else
nRet = static_cast<sal_uInt16>(GetSubType() & DATEFLD ? TYP_DATEFLD : TYP_TIMEFLD);
break;
case SwFieldIds::GetExp:
nRet = static_cast<sal_uInt16>(nsSwGetSetExpType::GSE_FORMULA & GetSubType() ? TYP_FORMELFLD : TYP_GETFLD);
break;
case SwFieldIds::HiddenText:
nRet = GetSubType();
break;
case SwFieldIds::SetExp:
if( nsSwGetSetExpType::GSE_SEQ & GetSubType() )
nRet = TYP_SEQFLD;
else if( static_cast<const SwSetExpField*>(this)->GetInputFlag() )
nRet = TYP_SETINPFLD;
else
nRet = TYP_SETFLD;
break;
case SwFieldIds::PageNumber:
nRet = GetSubType();
if( PG_NEXT == nRet )
nRet = TYP_NEXTPAGEFLD;
else if( PG_PREV == nRet )
nRet = TYP_PREVPAGEFLD;
else
nRet = TYP_PAGENUMBERFLD;
break;
default:
nRet = aTypeTab[ m_pType->Which() ];
}
return nRet;
}
/// get name or content
OUString SwField::GetFieldName() const
{
sal_uInt16 nTypeId = GetTypeId();
if (SwFieldIds::DateTime == GetTyp()->Which())
{
nTypeId = static_cast<sal_uInt16>(
((GetSubType() & DATEFLD) != 0) ? TYP_DATEFLD : TYP_TIMEFLD);
}
OUString sRet = SwFieldType::GetTypeStr( nTypeId );
if (IsFixed())
{
sRet += " " + SwViewShell::GetShellRes()->aFixedStr;
}
return sRet;
}
OUString SwField::GetPar1() const
{
return OUString();
}
OUString SwField::GetPar2() const
{
return OUString();
}
OUString SwField::GetFormula() const
{
return GetPar2();
}
void SwField::SetPar1(const OUString& )
{}
void SwField::SetPar2(const OUString& )
{}
sal_uInt16 SwField::GetSubType() const
{
return 0;
}
void SwField::SetSubType(sal_uInt16 )
{
}
bool SwField::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
{
switch( nWhichId )
{
case FIELD_PROP_BOOL4:
rVal <<= !m_bIsAutomaticLanguage;
break;
default:
assert(false);
}
return true;
}
bool SwField::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
{
switch( nWhichId )
{
case FIELD_PROP_BOOL4:
{
bool bFixed = false;
if(rVal >>= bFixed)
m_bIsAutomaticLanguage = !bFixed;
}
break;
default:
assert(false);
}
return true;
}
/** Set a new type
*
* This is needed/used for copying between documents.
* Needs to be always of the same type.
* @param pNewType The new type.
* @return The old type.
*/
SwFieldType* SwField::ChgTyp( SwFieldType* pNewType )
{
assert(pNewType && pNewType->Which() == m_pType->Which());
SwFieldType* pOld = m_pType;
m_pType = pNewType;
return pOld;
}
/// Does the field have an action on a ClickHandler? (E.g. INetFields,...)
bool SwField::HasClickHdl() const
{
bool bRet = false;
switch (m_pType->Which())
{
case SwFieldIds::Internet:
case SwFieldIds::JumpEdit:
case SwFieldIds::GetRef:
case SwFieldIds::Macro:
case SwFieldIds::Input:
case SwFieldIds::Dropdown :
bRet = true;
break;
case SwFieldIds::SetExp:
bRet = static_cast<const SwSetExpField*>(this)->GetInputFlag();
break;
default: break;
}
return bRet;
}
void SwField::SetLanguage(LanguageType const nLang)
{
m_nLang = nLang;
}
void SwField::ChangeFormat(sal_uInt32 const nFormat)
{
m_nFormat = nFormat;
}
bool SwField::IsFixed() const
{
bool bRet = false;
switch (m_pType->Which())
{
case SwFieldIds::FixDate:
case SwFieldIds::FixTime:
bRet = true;
break;
case SwFieldIds::DateTime:
bRet = 0 != (GetSubType() & FIXEDFLD);
break;
case SwFieldIds::ExtUser:
case SwFieldIds::Author:
bRet = 0 != (GetFormat() & AF_FIXED);
break;
case SwFieldIds::Filename:
bRet = 0 != (GetFormat() & FF_FIXED);
break;
case SwFieldIds::DocInfo:
bRet = 0 != (GetSubType() & DI_SUB_FIXED);
break;
default: break;
}
return bRet;
}
OUString SwField::ExpandField(bool const bCached) const
{
if ( m_bUseFieldValueCache )
{
if (!bCached) // #i85766# do not expand fields in clipboard documents
{
if (GetTypeId() == TYP_AUTHORITY)
{
const SwAuthorityField* pAuthorityField = static_cast<const SwAuthorityField*>(this);
m_Cache = pAuthorityField->ConditionalExpandAuthIdentifier();
}
else
m_Cache = Expand();
}
return m_Cache;
}
return Expand();
}
std::unique_ptr<SwField> SwField::CopyField() const
{
std::unique_ptr<SwField> pNew = Copy();
// #i85766# cache expansion of source (for clipboard)
// use this->cache, not this->Expand(): only text formatting calls Expand()
pNew->m_Cache = m_Cache;
pNew->m_bUseFieldValueCache = m_bUseFieldValueCache;
return pNew;
}
/// expand numbering
OUString FormatNumber(sal_uInt32 nNum, SvxNumType nFormat, LanguageType nLang)
{
if(SVX_NUM_PAGEDESC == nFormat)
return OUString::number( nNum );
SvxNumberType aNumber;
OSL_ENSURE(nFormat != SVX_NUM_NUMBER_NONE, "wrong number format" );
aNumber.SetNumberingType(nFormat);
if (nLang == LANGUAGE_NONE)
return aNumber.GetNumStr(nNum);
else
return aNumber.GetNumStr(nNum, LanguageTag::convertToLocale(nLang));
}
SwValueFieldType::SwValueFieldType(SwDoc *const pDoc, SwFieldIds const nWhichId)
: SwFieldType(nWhichId)
, m_pDoc(pDoc)
, m_bUseFormat(true)
{
}
SwValueFieldType::SwValueFieldType( const SwValueFieldType& rTyp )
: SwFieldType(rTyp.Which())
, m_pDoc(rTyp.GetDoc())
, m_bUseFormat(rTyp.UseFormat())
{
}
/// return value formatted as string
OUString SwValueFieldType::ExpandValue( const double& rVal,
sal_uInt32 nFormat, LanguageType nLng) const
{
if (rVal >= DBL_MAX) // error string for calculator
return SwViewShell::GetShellRes()->aCalc_Error;
OUString sExpand;
SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
Color* pCol = nullptr;
// Bug #60010
LanguageType nFormatLng = ::lcl_GetLanguageOfFormat( nLng, nFormat, *pFormatter );
if( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && LANGUAGE_SYSTEM != nFormatLng )
{
SvNumFormatType nType = SvNumFormatType::DEFINED;
sal_Int32 nDummy;
const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
if (pEntry && nLng != pEntry->GetLanguage())
{
sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFormat,
nFormatLng);
if (nNewFormat == nFormat)
{
// probably user-defined format
OUString sFormat(pEntry->GetFormatstring());
pFormatter->PutandConvertEntry(sFormat, nDummy, nType, nFormat,
pEntry->GetLanguage(), nFormatLng, false);
}
else
nFormat = nNewFormat;
}
OSL_ENSURE(pEntry, "unknown number format!");
}
if( pFormatter->IsTextFormat( nFormat ) )
{
pFormatter->GetOutputString(DoubleToString(rVal, nFormatLng), nFormat,
sExpand, &pCol);
}
else
{
pFormatter->GetOutputString(rVal, nFormat, sExpand, &pCol);
}
return sExpand;
}
OUString SwValueFieldType::DoubleToString(const double &rVal,
sal_uInt32 nFormat) const
{
SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
if (!pEntry)
return OUString();
return DoubleToString(rVal, pEntry->GetLanguage());
}
OUString SwValueFieldType::DoubleToString( const double &rVal,
LanguageType nLng ) const
{
SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
// Bug #60010
if( nLng == LANGUAGE_NONE )
nLng = LANGUAGE_SYSTEM;
pFormatter->ChangeIntl( nLng ); // get separator in the correct language
return ::rtl::math::doubleToUString( rVal, rtl_math_StringFormat_F, 12,
pFormatter->GetNumDecimalSep()[0], true );
}
SwValueField::SwValueField( SwValueFieldType* pFieldType, sal_uInt32 nFormat,
LanguageType nLng, const double fVal )
: SwField(pFieldType, nFormat, nLng)
, m_fValue(fVal)
{
}
SwValueField::SwValueField( const SwValueField& rField )
: SwField(rField)
, m_fValue(rField.GetValue())
{
}
SwValueField::~SwValueField()
{
}
/** Set a new type
*
* This is needed/used for copying between documents.
* Needs to be always of the same type.
* @param pNewType The new type.
* @return The old type.
*/
SwFieldType* SwValueField::ChgTyp( SwFieldType* pNewType )
{
SwDoc* pNewDoc = static_cast<SwValueFieldType *>(pNewType)->GetDoc();
SwDoc* pDoc = GetDoc();
if( pNewDoc && pDoc && pDoc != pNewDoc)
{
SvNumberFormatter* pFormatter = pNewDoc->GetNumberFormatter();
if( pFormatter && pFormatter->HasMergeFormatTable() &&
static_cast<SwValueFieldType *>(GetTyp())->UseFormat() )
SetFormat(pFormatter->GetMergeFormatIndex( GetFormat() ));
}
return SwField::ChgTyp(pNewType);
}
/// get format in office language
sal_uInt32 SwValueField::GetSystemFormat(SvNumberFormatter* pFormatter, sal_uInt32 nFormat)
{
const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
LanguageType nLng = SvtSysLocale().GetLanguageTag().getLanguageType();
if (pEntry && nLng != pEntry->GetLanguage())
{
sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFormat,
nLng);
if (nNewFormat == nFormat)
{
// probably user-defined format
SvNumFormatType nType = SvNumFormatType::DEFINED;
sal_Int32 nDummy;
OUString sFormat(pEntry->GetFormatstring());
sal_uInt32 nTempFormat = nFormat;
pFormatter->PutandConvertEntry(sFormat, nDummy, nType,
nTempFormat, pEntry->GetLanguage(), nLng, true);
nFormat = nTempFormat;
}
else
nFormat = nNewFormat;
}
return nFormat;
}
void SwValueField::dumpAsXml(xmlTextWriterPtr pWriter) const
{
xmlTextWriterStartElement(pWriter, BAD_CAST("SwValueField"));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_fValue"), BAD_CAST(OString::number(m_fValue).getStr()));
SwField::dumpAsXml(pWriter);
xmlTextWriterEndElement(pWriter);
}
/// set language of the format
void SwValueField::SetLanguage( LanguageType nLng )
{
if( IsAutomaticLanguage() &&
static_cast<SwValueFieldType *>(GetTyp())->UseFormat() &&
GetFormat() != SAL_MAX_UINT32 )
{
// Bug #60010
SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
LanguageType nFormatLng = ::lcl_GetLanguageOfFormat( nLng, GetFormat(),
*pFormatter );
if( (GetFormat() >= SV_COUNTRY_LANGUAGE_OFFSET ||
LANGUAGE_SYSTEM != nFormatLng ) &&
!(Which() == SwFieldIds::User && (GetSubType()&nsSwExtendedSubType::SUB_CMD) ) )
{
const SvNumberformat* pEntry = pFormatter->GetEntry(GetFormat());
if( pEntry && nFormatLng != pEntry->GetLanguage() )
{
sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(
GetFormat(), nFormatLng );
if( nNewFormat == GetFormat() )
{
// probably user-defined format
SvNumFormatType nType = SvNumFormatType::DEFINED;
sal_Int32 nDummy;
OUString sFormat( pEntry->GetFormatstring() );
pFormatter->PutandConvertEntry( sFormat, nDummy, nType,
nNewFormat,
pEntry->GetLanguage(),
nFormatLng, false);
}
SetFormat( nNewFormat );
}
OSL_ENSURE(pEntry, "unknown number format!");
}
}
SwField::SetLanguage(nLng);
}
double SwValueField::GetValue() const
{
return m_fValue;
}
void SwValueField::SetValue( const double& rVal )
{
m_fValue = rVal;
}
SwFormulaField::SwFormulaField( SwValueFieldType* pFieldType, sal_uInt32 nFormat, const double fVal)
: SwValueField(pFieldType, nFormat, LANGUAGE_SYSTEM, fVal)
{
}
SwFormulaField::SwFormulaField( const SwFormulaField& rField )
: SwValueField(static_cast<SwValueFieldType *>(rField.GetTyp()), rField.GetFormat(),
rField.GetLanguage(), rField.GetValue())
{
}
OUString SwFormulaField::GetFormula() const
{
return m_sFormula;
}
void SwFormulaField::SetFormula(const OUString& rStr)
{
m_sFormula = rStr;
sal_uLong nFormat(GetFormat());
if( nFormat && SAL_MAX_UINT32 != nFormat )
{
sal_Int32 nPos = 0;
double fTmpValue;
if( SwCalc::Str2Double( rStr, nPos, fTmpValue, GetDoc() ) )
SwValueField::SetValue( fTmpValue );
}
}
void SwFormulaField::SetExpandedFormula( const OUString& rStr )
{
sal_uInt32 nFormat(GetFormat());
if (nFormat && nFormat != SAL_MAX_UINT32 && static_cast<SwValueFieldType *>(GetTyp())->UseFormat())
{
double fTmpValue;
if (GetDoc()->IsNumberFormat(rStr, nFormat, fTmpValue))
{
SwValueField::SetValue(fTmpValue);
m_sFormula = static_cast<SwValueFieldType *>(GetTyp())->DoubleToString(fTmpValue, nFormat);
return;
}
}
m_sFormula = rStr;
}
OUString SwFormulaField::GetExpandedFormula() const
{
sal_uInt32 nFormat(GetFormat());
if (nFormat && nFormat != SAL_MAX_UINT32 && static_cast<SwValueFieldType *>(GetTyp())->UseFormat())
{
OUString sFormattedValue;
Color* pCol = nullptr;
SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
if (pFormatter->IsTextFormat(nFormat))
{
OUString sTempIn(static_cast<SwValueFieldType *>(GetTyp())->DoubleToString(GetValue(), nFormat));
pFormatter->GetOutputString(sTempIn, nFormat, sFormattedValue, &pCol);
}
else
{
pFormatter->GetOutputString(GetValue(), nFormat, sFormattedValue, &pCol);
}
return sFormattedValue;
}
else
return GetFormula();
}
OUString SwField::GetDescription() const
{
return SwResId(STR_FIELD);
}
bool SwField::IsClickable() const
{
switch (Which())
{
case SwFieldIds::JumpEdit:
case SwFieldIds::Macro:
case SwFieldIds::GetRef:
case SwFieldIds::Input:
case SwFieldIds::SetExp:
case SwFieldIds::Dropdown:
return true;
default: break;
}
return false;
}
void SwField::dumpAsXml(xmlTextWriterPtr pWriter) const
{
xmlTextWriterStartElement(pWriter, BAD_CAST("SwField"));
xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nFormat"), BAD_CAST(OString::number(m_nFormat).getStr()));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nLang"), BAD_CAST(OString::number(m_nLang.get()).getStr()));
xmlTextWriterEndElement(pWriter);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.
↑ V524 It is odd that the body of 'GetPar2' function is fully equivalent to the body of 'GetPar1' function.