    /* -*- 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.