621caf93ce
reduce cost of OUString construction by avoiding initialising a temporary and then overwriting it. 12s to 10s Change-Id: I889152ba71947004ca7d5c96f073182c94d95ed5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175539 Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com> Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
931 lines
28 KiB
C++
931 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 <fldbas.hxx>
|
|
|
|
#include <float.h>
|
|
|
|
#include <libxml/xmlwriter.h>
|
|
|
|
#include <rtl/math.hxx>
|
|
#include <comphelper/string.hxx>
|
|
#include <svl/numformat.hxx>
|
|
#include <svl/zforlist.hxx>
|
|
#include <svl/zformat.hxx>
|
|
#include <o3tl/enumarray.hxx>
|
|
#include <osl/diagnose.h>
|
|
#include <unofldmid.h>
|
|
#include <doc.hxx>
|
|
#include <fmtfld.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>
|
|
#include <viewsh.hxx>
|
|
#include <hints.hxx>
|
|
#include <unofield.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace nsSwDocInfoSubType;
|
|
|
|
static LanguageType lcl_GetLanguageOfFormat(LanguageType nLng, sal_uLong nFormat)
|
|
{
|
|
if( nLng == LANGUAGE_NONE ) // Bug #60010
|
|
nLng = LANGUAGE_SYSTEM;
|
|
else if( nLng == ::GetAppLanguage() )
|
|
switch( SvNumberFormatter::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 */ SwFieldTypesEnum::Database,
|
|
/* SwFieldIds::User */ SwFieldTypesEnum::User,
|
|
/* SwFieldIds::Filename */ SwFieldTypesEnum::Filename,
|
|
/* SwFieldIds::DatabaseName */ SwFieldTypesEnum::DatabaseName,
|
|
/* SwFieldIds::Date */ SwFieldTypesEnum::Date,
|
|
/* SwFieldIds::Time */ SwFieldTypesEnum::Time,
|
|
/* SwFieldIds::PageNumber */ SwFieldTypesEnum::PageNumber, // dynamic
|
|
/* SwFieldIds::Author */ SwFieldTypesEnum::Author,
|
|
/* SwFieldIds::Chapter */ SwFieldTypesEnum::Chapter,
|
|
/* SwFieldIds::DocStat */ SwFieldTypesEnum::DocumentStatistics,
|
|
/* SwFieldIds::GetExp */ SwFieldTypesEnum::Get, // dynamic
|
|
/* SwFieldIds::SetExp */ SwFieldTypesEnum::Set, // dynamic
|
|
/* SwFieldIds::GetRef */ SwFieldTypesEnum::GetRef,
|
|
/* SwFieldIds::HiddenText */ SwFieldTypesEnum::HiddenText,
|
|
/* SwFieldIds::Postit */ SwFieldTypesEnum::Postit,
|
|
/* SwFieldIds::FixDate */ SwFieldTypesEnum::FixedDate,
|
|
/* SwFieldIds::FixTime */ SwFieldTypesEnum::FixedTime,
|
|
/* SwFieldIds::Reg */ SwFieldTypesEnum::Begin, // old (no change since 2000)
|
|
/* SwFieldIds::VarReg */ SwFieldTypesEnum::Begin, // old (no change since 2000)
|
|
/* SwFieldIds::SetRef */ SwFieldTypesEnum::SetRef,
|
|
/* SwFieldIds::Input */ SwFieldTypesEnum::Input,
|
|
/* SwFieldIds::Macro */ SwFieldTypesEnum::Macro,
|
|
/* SwFieldIds::Dde */ SwFieldTypesEnum::DDE,
|
|
/* SwFieldIds::Table */ SwFieldTypesEnum::Formel,
|
|
/* SwFieldIds::HiddenPara */ SwFieldTypesEnum::HiddenParagraph,
|
|
/* SwFieldIds::DocInfo */ SwFieldTypesEnum::DocumentInfo,
|
|
/* SwFieldIds::TemplateName */ SwFieldTypesEnum::TemplateName,
|
|
/* SwFieldIds::DbNextSet */ SwFieldTypesEnum::DatabaseNextSet,
|
|
/* SwFieldIds::DbNumSet */ SwFieldTypesEnum::DatabaseNumberSet,
|
|
/* SwFieldIds::DbSetNumber */ SwFieldTypesEnum::DatabaseSetNumber,
|
|
/* SwFieldIds::ExtUser */ SwFieldTypesEnum::ExtendedUser,
|
|
/* SwFieldIds::RefPageSet */ SwFieldTypesEnum::SetRefPage,
|
|
/* SwFieldIds::RefPageGet */ SwFieldTypesEnum::GetRefPage,
|
|
/* SwFieldIds::Internet */ SwFieldTypesEnum::Internet,
|
|
/* SwFieldIds::JumpEdit */ SwFieldTypesEnum::JumpEdit,
|
|
/* SwFieldIds::Script */ SwFieldTypesEnum::Script,
|
|
/* SwFieldIds::DateTime */ SwFieldTypesEnum::Begin, // dynamic
|
|
/* SwFieldIds::TableOfAuthorities*/ SwFieldTypesEnum::Authority,
|
|
/* SwFieldIds::CombinedChars */ SwFieldTypesEnum::CombinedChars,
|
|
/* SwFieldIds::Dropdown */ SwFieldTypesEnum::Dropdown,
|
|
/* SwFieldIds::ParagraphSignature */ SwFieldTypesEnum::ParagraphSignature
|
|
};
|
|
|
|
}
|
|
|
|
const OUString & SwFieldType::GetTypeStr(SwFieldTypesEnum nTypeId)
|
|
{
|
|
if (!s_pFieldNames)
|
|
GetFieldName_();
|
|
|
|
return (*SwFieldType::s_pFieldNames)[static_cast<int>(nTypeId)];
|
|
}
|
|
|
|
// each field references a field type that is unique for each document
|
|
SwFieldType::SwFieldType( SwFieldIds nWhichId )
|
|
: sw::BroadcastingModify()
|
|
, 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::PrintHiddenPara()
|
|
{
|
|
const SwMsgPoolItem aHint(RES_HIDDENPARA_PRINT);
|
|
SwClientNotify(*this, sw::LegacyModifyHint(&aHint, nullptr));
|
|
}
|
|
|
|
void SwFieldType::dumpAsXml(xmlTextWriterPtr pWriter) const
|
|
{
|
|
std::vector<SwFormatField*> vFields;
|
|
GatherFields(vFields);
|
|
if(!vFields.size())
|
|
return;
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldType"));
|
|
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
|
|
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
|
|
for(const auto pFormatField: vFields)
|
|
{
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatField"));
|
|
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", pFormatField);
|
|
(void)xmlTextWriterEndElement(pWriter);
|
|
}
|
|
(void)xmlTextWriterEndElement(pWriter);
|
|
}
|
|
|
|
SwFormatField* SwFieldType::FindFormatForField(const SwField* pField) const {
|
|
SwFormatField* pFormat = nullptr;
|
|
CallSwClientNotify(sw::FindFormatForFieldHint(pField, pFormat));
|
|
return pFormat;
|
|
}
|
|
|
|
SwFormatField* SwFieldType::FindFormatForPostItId(sal_uInt32 nPostItId) const {
|
|
SwFormatField* pFormat = nullptr;
|
|
CallSwClientNotify(sw::FindFormatForPostItIdHint(nPostItId, pFormat));
|
|
return pFormat;
|
|
}
|
|
|
|
void SwFieldType::CollectPostIts(std::vector<SwFormatField*>& rvFormatFields, IDocumentRedlineAccess const& rIDRA, const bool bHideRedlines)
|
|
{
|
|
CallSwClientNotify(sw::CollectPostItsHint(rvFormatFields, rIDRA, bHideRedlines));
|
|
}
|
|
|
|
bool SwFieldType::HasHiddenInformationNotes() const
|
|
{
|
|
bool bHasHiddenInformationNotes = false;
|
|
CallSwClientNotify(sw::HasHiddenInformationNotesHint(bHasHiddenInformationNotes));
|
|
return bHasHiddenInformationNotes;
|
|
}
|
|
|
|
void SwFieldType::GatherNodeIndex(std::vector<SwNodeOffset>& rvNodeIndex)
|
|
{
|
|
CallSwClientNotify(sw::GatherNodeIndexHint(rvNodeIndex));
|
|
}
|
|
|
|
void SwFieldType::GatherRefFields(std::vector<SwGetRefField*>& rvRFields, const sal_uInt16 nTyp)
|
|
{
|
|
CallSwClientNotify(sw::GatherRefFieldsHint(rvRFields, nTyp));
|
|
}
|
|
|
|
void SwFieldType::GatherFields(std::vector<SwFormatField*>& rvFields, bool bCollectOnlyInDocNodes) const
|
|
{
|
|
CallSwClientNotify(sw::GatherFieldsHint(rvFields, bCollectOnlyInDocNodes));
|
|
}
|
|
|
|
void SwFieldType::GatherDdeTables(std::vector<SwDDETable*>& rvTables) const
|
|
{
|
|
CallSwClientNotify(sw::GatherDdeTablesHint(rvTables));
|
|
}
|
|
|
|
void SwFieldType::UpdateDocPos(const SwTwips nDocPos)
|
|
{
|
|
CallSwClientNotify(sw::DocPosUpdate(nDocPos));
|
|
}
|
|
void SwFieldType::UpdateFields()
|
|
{
|
|
CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
|
|
};
|
|
|
|
void SwFieldType::SetXObject(rtl::Reference<SwXFieldMaster> const& xFieldMaster)
|
|
{
|
|
m_wXFieldMaster = xFieldMaster.get();
|
|
}
|
|
|
|
void SwFieldTypes::dumpAsXml(xmlTextWriterPtr pWriter) const
|
|
{
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldTypes"));
|
|
sal_uInt16 nCount = size();
|
|
for (sal_uInt16 nType = 0; nType < nCount; ++nType)
|
|
(*this)[nType]->dumpAsXml(pWriter);
|
|
(void)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_pType( pType )
|
|
, m_nFormat( nFormat )
|
|
, m_nLang( nLang )
|
|
, m_bUseFieldValueCache( bUseFieldValueCache )
|
|
, m_bIsAutomaticLanguage( true )
|
|
{
|
|
assert(m_pType);
|
|
}
|
|
|
|
SwField::~SwField()
|
|
{
|
|
}
|
|
|
|
SwFieldTypesEnum SwField::GetTypeId() const
|
|
{
|
|
|
|
SwFieldTypesEnum nRet;
|
|
switch (m_pType->Which())
|
|
{
|
|
case SwFieldIds::DateTime:
|
|
if (GetSubType() & FIXEDFLD)
|
|
nRet = GetSubType() & DATEFLD ? SwFieldTypesEnum::FixedDate : SwFieldTypesEnum::FixedTime;
|
|
else
|
|
nRet = GetSubType() & DATEFLD ? SwFieldTypesEnum::Date : SwFieldTypesEnum::Time;
|
|
break;
|
|
case SwFieldIds::GetExp:
|
|
nRet = nsSwGetSetExpType::GSE_FORMULA & GetSubType() ? SwFieldTypesEnum::Formel : SwFieldTypesEnum::Get;
|
|
break;
|
|
|
|
case SwFieldIds::HiddenText:
|
|
nRet = static_cast<SwFieldTypesEnum>(GetSubType());
|
|
break;
|
|
|
|
case SwFieldIds::SetExp:
|
|
if( nsSwGetSetExpType::GSE_SEQ & GetSubType() )
|
|
nRet = SwFieldTypesEnum::Sequence;
|
|
else if( static_cast<const SwSetExpField*>(this)->GetInputFlag() )
|
|
nRet = SwFieldTypesEnum::SetInput;
|
|
else
|
|
nRet = SwFieldTypesEnum::Set;
|
|
break;
|
|
|
|
case SwFieldIds::PageNumber:
|
|
{
|
|
auto nSubType = GetSubType();
|
|
if( PG_NEXT == nSubType )
|
|
nRet = SwFieldTypesEnum::NextPage;
|
|
else if( PG_PREV == nSubType )
|
|
nRet = SwFieldTypesEnum::PreviousPage;
|
|
else
|
|
nRet = SwFieldTypesEnum::PageNumber;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
nRet = aTypeTab[ m_pType->Which() ];
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
/// get name or content
|
|
OUString SwField::GetFieldName() const
|
|
{
|
|
SwFieldTypesEnum nTypeId = GetTypeId();
|
|
if (SwFieldIds::DateTime == GetTyp()->Which())
|
|
{
|
|
nTypeId =
|
|
((GetSubType() & DATEFLD) != 0) ? SwFieldTypesEnum::Date : SwFieldTypesEnum::Time;
|
|
}
|
|
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;
|
|
case FIELD_PROP_TITLE:
|
|
{
|
|
rVal <<= m_aTitle;
|
|
}
|
|
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;
|
|
case FIELD_PROP_TITLE:
|
|
{
|
|
OUString aTitle;
|
|
if (rVal >>= aTitle)
|
|
{
|
|
m_aTitle = aTitle;
|
|
}
|
|
}
|
|
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:
|
|
case SwFieldIds::TableOfAuthorities:
|
|
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, SwRootFrame const*const pLayout) const
|
|
{
|
|
if ( m_bUseFieldValueCache )
|
|
{
|
|
if (!bCached) // #i85766# do not expand fields in clipboard documents
|
|
{
|
|
if (GetTypeId() == SwFieldTypesEnum::Authority)
|
|
{
|
|
const SwAuthorityField* pAuthorityField = static_cast<const SwAuthorityField*>(this);
|
|
m_Cache = pAuthorityField->ConditionalExpandAuthIdentifier(pLayout);
|
|
}
|
|
else
|
|
m_Cache = ExpandImpl(pLayout);
|
|
}
|
|
return m_Cache;
|
|
}
|
|
|
|
return ExpandImpl(pLayout);
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
SwFieldTypesEnum SwFieldTypeFromString(std::u16string_view rString)
|
|
{
|
|
if (rString == u"Date")
|
|
return SwFieldTypesEnum::Date;
|
|
if (rString == u"Time")
|
|
return SwFieldTypesEnum::Time;
|
|
if (rString == u"Filename")
|
|
return SwFieldTypesEnum::Filename;
|
|
if (rString == u"DatabaseName")
|
|
return SwFieldTypesEnum::DatabaseName;
|
|
if (rString == u"Chapter")
|
|
return SwFieldTypesEnum::Chapter;
|
|
if (rString == u"PageNumber")
|
|
return SwFieldTypesEnum::PageNumber;
|
|
if (rString == u"DocumentStatistics")
|
|
return SwFieldTypesEnum::DocumentStatistics;
|
|
if (rString == u"Author")
|
|
return SwFieldTypesEnum::Author;
|
|
if (rString == u"Set")
|
|
return SwFieldTypesEnum::Set;
|
|
if (rString == u"Get")
|
|
return SwFieldTypesEnum::Get;
|
|
if (rString == u"Formel")
|
|
return SwFieldTypesEnum::Formel;
|
|
if (rString == u"HiddenText")
|
|
return SwFieldTypesEnum::HiddenText;
|
|
if (rString == u"SetRef")
|
|
return SwFieldTypesEnum::SetRef;
|
|
return SwFieldTypesEnum::Unknown;
|
|
}
|
|
|
|
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();
|
|
const Color* pCol = nullptr;
|
|
|
|
// Bug #60010
|
|
LanguageType nFormatLng = ::lcl_GetLanguageOfFormat( nLng, nFormat );
|
|
|
|
if( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && LANGUAGE_SYSTEM != nFormatLng )
|
|
{
|
|
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());
|
|
sal_Int32 nDummy;
|
|
SvNumFormatType nType = SvNumFormatType::DEFINED;
|
|
|
|
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 );
|
|
}
|
|
|
|
OUString SwValueFieldType::GetInputOrDateTime( const OUString& rInput, const double& rVal, sal_uInt32 nFormat ) const
|
|
{
|
|
if (nFormat && nFormat != SAL_MAX_UINT32 && UseFormat())
|
|
{
|
|
SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
|
|
const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
|
|
if (pEntry && (pEntry->GetType() & SvNumFormatType::DATETIME))
|
|
return pFormatter->GetInputLineString( rVal, nFormat );
|
|
}
|
|
return rInput;
|
|
}
|
|
|
|
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
|
|
{
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwValueField"));
|
|
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_fValue"), BAD_CAST(OString::number(m_fValue).getStr()));
|
|
SwField::dumpAsXml(pWriter);
|
|
(void)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() );
|
|
|
|
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;
|
|
// Uses the SwCalc document locale.
|
|
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);
|
|
|
|
// Will get reinterpreted by SwCalc when updating fields, so use
|
|
// the proper locale.
|
|
m_sFormula = static_cast<SwValueFieldType *>(GetTyp())->DoubleToString( fTmpValue,
|
|
SwCalc::GetDocAppScriptLang( *GetDoc()));
|
|
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;
|
|
const 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 SwFormulaField::GetInputOrDateTime() const
|
|
{
|
|
// GetFormula() leads to problems with date formats because only the
|
|
// number string without formatting is returned (additionally that may or
|
|
// may not use a localized decimal separator due to the convoluted handling
|
|
// of "formula"). It must be used for expressions though because otherwise
|
|
// with GetPar2() only the value calculated by SwCalc would be displayed
|
|
// (instead of test2 = test + 1).
|
|
// Force a formatted edit value for date+time formats, assuming they are
|
|
// not editable calculated expressions if the formula doesn't contain
|
|
// arithmetic operators or assignment.
|
|
|
|
const OUString aFormula( GetFormula());
|
|
|
|
if (comphelper::string::indexOfAny( aFormula, u"=+-*/", 0) == -1)
|
|
return static_cast<SwValueFieldType*>(GetTyp())->GetInputOrDateTime( aFormula, GetValue(), GetFormat());
|
|
|
|
return aFormula;
|
|
}
|
|
|
|
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:
|
|
case SwFieldIds::TableOfAuthorities:
|
|
return true;
|
|
default: break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void SwField::dumpAsXml(xmlTextWriterPtr pWriter) const
|
|
{
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwField"));
|
|
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
|
|
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
|
|
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nFormat"), BAD_CAST(OString::number(m_nFormat).getStr()));
|
|
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nLang"), BAD_CAST(OString::number(m_nLang.get()).getStr()));
|
|
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_aTitle"), BAD_CAST(m_aTitle.toUtf8().getStr()));
|
|
|
|
(void)xmlTextWriterEndElement(pWriter);
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|