Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  numfmtsh.cxx   Sprache: 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 <tools/color.hxx>

#include <tools/debug.hxx>
#include <unotools/localedatawrapper.hxx>
#include <i18nlangtag/mslangid.hxx>
#include <o3tl/safeint.hxx>
#include <svl/numformat.hxx>
#include <svl/zforlist.hxx>
#include <svl/zformat.hxx>
#include <svl/currencytable.hxx>

#include <svx/numfmtsh.hxx>
#include <svx/flagsdef.hxx>
#include <svx/tbcontrl.hxx>
#include <sfx2/IDocumentModelAccessor.hxx>

#include <limits>

namespace
{
double GetDefaultValNum(const SvNumFormatType nType)
{
    switch (nType)
    {
        case SvNumFormatType::NUMBER:
            return fSvxNumValConst[SvxNumValCategory::Standard];
        case SvNumFormatType::CURRENCY:
            return fSvxNumValConst[SvxNumValCategory::Currency];
        case SvNumFormatType::PERCENT:
            return fSvxNumValConst[SvxNumValCategory::Percent];
        case SvNumFormatType::DATE:
        case SvNumFormatType::DATETIME:
            return fSvxNumValConst[SvxNumValCategory::Date];
        case SvNumFormatType::TIME:
            return fSvxNumValConst[SvxNumValCategory::Time];
        case SvNumFormatType::SCIENTIFIC:
            return fSvxNumValConst[SvxNumValCategory::Scientific];
        case SvNumFormatType::FRACTION:
            return fSvxNumValConst[SvxNumValCategory::Fraction];
        case SvNumFormatType::LOGICAL:
            return fSvxNumValConst[SvxNumValCategory::Boolean];
        default:
            break;
    }
    return fSvxNumValConst[SvxNumValCategory::NoValue];
}
}

SvxNumberFormatShell* SvxNumberFormatShell::Create(SvNumberFormatter* pNumFormatter,
                                                   sal_uInt32 nFormatKey,
                                                   SvxNumberValueType eNumValType,
                                                   const OUString& rNumStr)
{
    return new SvxNumberFormatShell(pNumFormatter, nFormatKey, eNumValType, rNumStr);
}

SvxNumberFormatShell* SvxNumberFormatShell::Create(SvNumberFormatter* pNumFormatter,
                                                   sal_uInt32 nFormatKey,
                                                   SvxNumberValueType eNumValType, double nNumVal,
                                                   const OUString* pNumStr)
{
    return new SvxNumberFormatShell(pNumFormatter, nFormatKey, eNumValType, nNumVal, pNumStr);
}

SvxNumberFormatShell::SvxNumberFormatShell(SvNumberFormatter* pNumFormatter, sal_uInt32 nFormatKey,
                                           SvxNumberValueType eNumValType, const OUString& rNumStr)
    : pFormatter(pNumFormatter)
    , pCurFmtTable(nullptr)
    , eValType(eNumValType)
    , bUndoAddList(true)
    , nCurFormatKey(nFormatKey)
    , nCurCategory(SvNumFormatType::ALL)
    , eCurLanguage(LANGUAGE_NONE)
    , pCurCurrencyEntry(nullptr)
    , bBankingSymbol(false)
    , nCurCurrencyEntryPos(sal_uInt16(SELPOS_NONE))
    , bUseStarFormat(false)
    , bIsDefaultValNum(true)
{
    nValNum = 0;

    switch (eValType)
    {
        case SvxNumberValueType::String:
            aValStr = rNumStr;
            break;
        case SvxNumberValueType::Number:
            if (pFormatter)
            {
                nValNum = GetDefaultValNum(pFormatter->GetType(nCurFormatKey));
            }
            [[fallthrough]];
        case SvxNumberValueType::Undefined:
        default:
            aValStr.clear();
    }
}

SvxNumberFormatShell::SvxNumberFormatShell(SvNumberFormatter* pNumFormatter, sal_uInt32 nFormatKey,
                                           SvxNumberValueType eNumValType, double nNumVal,
                                           const OUString* pNumStr)
    : pFormatter(pNumFormatter)
    , pCurFmtTable(nullptr)
    , eValType(eNumValType)
    , bUndoAddList(true)
    , nCurFormatKey(nFormatKey)
    , nCurCategory(SvNumFormatType::ALL)
    , eCurLanguage(LANGUAGE_NONE)
    , pCurCurrencyEntry(nullptr)
    , bBankingSymbol(false)
    , nCurCurrencyEntryPos(sal_uInt16(SELPOS_NONE))
    , bUseStarFormat(false)
    , bIsDefaultValNum(false)
{
    //  #50441# When used in Writer, the SvxNumberInfoItem contains the
    //  original string in addition to the value

    if (pNumStr)
        aValStr = *pNumStr;

    switch (eValType)
    {
        case SvxNumberValueType::Number:
            nValNum = nNumVal;
            break;
        case SvxNumberValueType::String:
        case SvxNumberValueType::Undefined:
        default:
            nValNum = 0;
            bIsDefaultValNum = true;
    }
}

SvxNumberFormatShell::~SvxNumberFormatShell()
{
    /*
     * At this point, depending on whether the added user-defined were
     * validated (ValidateNewEntries()), the add list is removed from
     * the number formatter again.
     *
     * Deleting formats from the formatter happens for Undo reasons
     * only in the calling instance.
     */


    if (bUndoAddList)
    {
        // Added formats are invalid => remove them

        for (const auto& rItem : aAddList)
            pFormatter->DeleteEntry(rItem);
    }
}

std::vector<sal_uInt32> const& SvxNumberFormatShell::GetUpdateData() const { return aDelList; }

void SvxNumberFormatShell::CategoryChanged(sal_uInt16 nCatLbPos, short& rFmtSelPos,
                                           std::vector<OUString>& rFmtEntries)
{
    SvNumFormatType nOldCategory = nCurCategory;
    PosToCategory_Impl(nCatLbPos, nCurCategory);
    pCurFmtTable = &(pFormatter->GetEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
    // reinitialize currency if category newly entered
    if (nCurCategory == SvNumFormatType::CURRENCY && nOldCategory != nCurCategory)
        pCurCurrencyEntry = nullptr;
    rFmtSelPos = FillEntryList_Impl(rFmtEntries);
}

void SvxNumberFormatShell::LanguageChanged(LanguageType eLangType, short& rFmtSelPos,
                                           std::vector<OUString>& rFmtEntries)
{
    eCurLanguage = eLangType;
    pCurFmtTable = &(pFormatter->ChangeCL(nCurCategory, nCurFormatKey, eCurLanguage));
    rFmtSelPos = FillEntryList_Impl(rFmtEntries);
}

void SvxNumberFormatShell::FormatChanged(sal_uInt16 nFmtLbPos, OUString& rPreviewStr,
                                         const Color*& rpFontColor)
{
    if (static_cast<size_t>(nFmtLbPos) >= aCurEntryList.size())
        return;

    nCurFormatKey = aCurEntryList[nFmtLbPos];

    if (nCurFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND)
    {
        GetPreviewString_Impl(rPreviewStr, rpFontColor);
    }
    else if (nCurCategory == SvNumFormatType::CURRENCY)
    {
        if (static_cast<size_t>(nFmtLbPos) < aCurrencyFormatList.size())
        {
            MakePrevStringFromVal(aCurrencyFormatList[nFmtLbPos], rPreviewStr, rpFontColor,
                                  nValNum);
        }
    }
}

bool SvxNumberFormatShell::AddFormat(OUString& rFormat, sal_Int32& rErrPos,
                                     sal_uInt16& rCatLbSelPos, short& rFmtSelPos,
                                     std::vector<OUString>& rFmtEntries)
{
    bool bInserted = false;
    sal_uInt32 nAddKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);

    if (nAddKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // exists already?
    {
        ::std::vector<sal_uInt32>::iterator nAt = GetRemoved_Impl(nAddKey);
        if (nAt != aDelList.end())
        {
            aDelList.erase(nAt);
            bInserted = true;
        }
        else
        {
            OSL_FAIL("duplicate format!");
        }
    }
    else // new format
    {
        sal_Int32 nPos;
        bInserted = pFormatter->PutEntry(rFormat, nPos, nCurCategory, nAddKey, eCurLanguage);
        rErrPos = (nPos >= 0) ? nPos : -1;

        if (bInserted)
        {
            // May be sorted under a different locale if LCID was parsed.
            const SvNumberformat* pEntry = pFormatter->GetEntry(nAddKey);
            if (pEntry)
            {
                LanguageType nLang = pEntry->GetLanguage();
                if (eCurLanguage != nLang)
                {
                    // Current language's list would not show entry, adapt.
                    eCurLanguage = nLang;
                }
            }
        }
    }

    if (bInserted)
    {
        nCurFormatKey = nAddKey;
        DBG_ASSERT(GetAdded_Impl(nCurFormatKey) == aAddList.end(), "duplicate format!");
        aAddList.push_back(nCurFormatKey);

        // get current table
        pCurFmtTable = &(pFormatter->GetEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));
        nCurCategory = pFormatter->GetType(nAddKey);
        CategoryToPos_Impl(nCurCategory, rCatLbSelPos);
        rFmtSelPos = FillEntryList_Impl(rFmtEntries);
    }
    else if (rErrPos != 0) // syntax error
    {
        ;
    }
    else // insert twice not possible
    {
        OSL_FAIL("duplicate format!");
    }

    return bInserted;
}

void SvxNumberFormatShell::RemoveFormat(std::u16string_view rFormat, sal_uInt16& ;rCatLbSelPos,
                                        short& rFmtSelPos, std::vector<OUString>& rFmtEntries)
{
    sal_uInt32 nDelKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);

    DBG_ASSERT(nDelKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "entry not found!");
    DBG_ASSERT(!IsRemoved_Impl(nDelKey), "entry already removed!");

    if ((nDelKey == NUMBERFORMAT_ENTRY_NOT_FOUND) || IsRemoved_Impl(nDelKey))
        return;

    aDelList.push_back(nDelKey);

    ::std::vector<sal_uInt32>::iterator nAt = GetAdded_Impl(nDelKey);
    if (nAt != aAddList.end())
    {
        aAddList.erase(nAt);
    }

    nCurCategory = pFormatter->GetType(nDelKey);
    pCurFmtTable = &(pFormatter->GetEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));

    nCurFormatKey = pFormatter->GetStandardFormat(nCurCategory, eCurLanguage);

    CategoryToPos_Impl(nCurCategory, rCatLbSelPos);
    rFmtSelPos = FillEntryList_Impl(rFmtEntries);
}

void SvxNumberFormatShell::MakeFormat(OUString& rFormat, bool bThousand, bool bNegRed,
                                      sal_uInt16 nPrecision, sal_uInt16 nLeadingZeroes,
                                      sal_uInt16 nCurrencyPos)
{
    if (aCurrencyFormatList.size() > static_cast<size_t>(nCurrencyPos))
    {
        sal_Int32 rErrPos = 0;
        std::vector<OUString> aFmtEList;

        sal_uInt32 nFound
            = pFormatter->TestNewString(aCurrencyFormatList[nCurrencyPos], eCurLanguage);

        if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
        {
            sal_uInt16 rCatLbSelPos = 0;
            short rFmtSelPos = 0;
            AddFormat(aCurrencyFormatList[nCurrencyPos], rErrPos, rCatLbSelPos, rFmtSelPos,
                      aFmtEList);
        }

        if (rErrPos == 0)
        {
            rFormat = pFormatter->GenerateFormat(nCurFormatKey, eCurLanguage, bThousand, bNegRed,
                                                 nPrecision, nLeadingZeroes);
        }
    }
    else
    {
        rFormat = pFormatter->GenerateFormat(nCurFormatKey, eCurLanguage, bThousand, bNegRed,
                                             nPrecision, nLeadingZeroes);
    }
}

sal_uInt16 SvxNumberFormatShell::GetFormatIntegerDigits(std::u16string_view rFormat) const
{
    sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);

    return pFormatter->GetFormatIntegerDigits(nFmtKey);
}

bool SvxNumberFormatShell::IsNatNum12(std::u16string_view rFormat) const
{
    sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);

    return pFormatter->IsNatNum12(nFmtKey);
}

void SvxNumberFormatShell::GetOptions(const OUString& rFormat, bool& rThousand, bool& rNegRed,
                                      sal_uInt16& rPrecision, sal_uInt16& rLeadingZeroes,
                                      sal_uInt16& rCatLbPos)
{
    sal_uInt32 nFmtKey = pFormatter->GetEntryKey(rFormat, eCurLanguage);

    if (nFmtKey != NUMBERFORMAT_ENTRY_NOT_FOUND)
    {
        pFormatter->GetFormatSpecialInfo(nFmtKey, rThousand, rNegRed, rPrecision, rLeadingZeroes);

        CategoryToPos_Impl(pFormatter->GetType(nFmtKey), rCatLbPos);
    }
    else
    {
        bool bTestBanking = false;
        sal_uInt16 nPos = FindCurrencyTableEntry(rFormat, bTestBanking);

        if (IsInTable(nPos, bTestBanking, rFormat)
            && pFormatter->GetFormatSpecialInfo(rFormat, rThousand, rNegRed, rPrecision,
                                                rLeadingZeroes, eCurLanguage)
                   == 0)
        {
            rCatLbPos = CAT_CURRENCY;
        }
        else
            rCatLbPos = CAT_USERDEFINED;
    }
}

void SvxNumberFormatShell::MakePreviewString(const OUString& rFormatStr, OUString& rPreviewStr,
                                             const Color*& rpFontColor)
{
    rpFontColor = nullptr;

    sal_uInt32 nExistingFormat = pFormatter->GetEntryKey(rFormatStr, eCurLanguage);
    if (nExistingFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
    {
        //  real preview - not implemented in NumberFormatter for text formats
        pFormatter->GetPreviewString(rFormatStr, nValNum, rPreviewStr, &rpFontColor, eCurLanguage,
                                     bUseStarFormat);
    }
    else
    {
        //  format exists

        //  #50441# if a string was set in addition to the value, use it for text formats
        bool bUseText = (eValType == SvxNumberValueType::String
                         || (!aValStr.isEmpty()
                             && (pFormatter->GetType(nExistingFormat) & SvNumFormatType::TEXT)));

        if (bUseText)
        {
            pFormatter->GetOutputString(aValStr, nExistingFormat, rPreviewStr, &rpFontColor);
        }
        else
        {
            if (bIsDefaultValNum)
                nValNum = GetDefaultValNum(pFormatter->GetType(nExistingFormat));
            pFormatter->GetOutputString(nValNum, nExistingFormat, rPreviewStr, &rpFontColor,
                                        bUseStarFormat);
        }
    }
}

bool SvxNumberFormatShell::IsUserDefined(const OUString& rFmtString)
{
    sal_uInt32 nFound = pFormatter->GetEntryKey(rFmtString, eCurLanguage);

    bool bFlag = false;
    if (nFound != NUMBERFORMAT_ENTRY_NOT_FOUND)
    {
        bFlag = pFormatter->IsUserDefined(rFmtString, eCurLanguage);

        if (bFlag)
        {
            const SvNumberformat* pNumEntry = pFormatter->GetEntry(nFound);

            if (pNumEntry != nullptr && pNumEntry->HasNewCurrency())
            {
                bool bTestBanking;
                sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);
                bFlag = !IsInTable(nPos, bTestBanking, rFmtString);
            }
        }
    }
    return bFlag;
}

bool SvxNumberFormatShell::FindEntry(const OUString& rFmtString, sal_uInt32* pAt /* = NULL */)
{
    bool bRes = false;

    sal_uInt32 nFound = NUMBERFORMAT_ENTRY_NOT_FOUND;
    // There may be multiple builtin entries with the same format code, first
    // try if the current key matches.
    const SvNumberformat* pEntry = pFormatter->GetEntry(nCurFormatKey);
    if (pEntry && pEntry->GetLanguage() == eCurLanguage && pEntry->GetFormatstring() == rFmtString)
        nFound = nCurFormatKey;

    if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
        // Find the first matching format code.
        nFound = pFormatter->TestNewString(rFmtString, eCurLanguage);

    if (nFound == NUMBERFORMAT_ENTRY_NOT_FOUND)
    {
        bool bTestBanking = false;
        sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);

        if (IsInTable(nPos, bTestBanking, rFmtString))
        {
            nFound = NUMBERFORMAT_ENTRY_NEW_CURRENCY;
            bRes = true;
        }
    }
    else
    {
        bRes = !IsRemoved_Impl(nFound);
    }

    if (pAt)
        *pAt = nFound;

    return bRes;
}

void SvxNumberFormatShell::GetInitSettings(sal_uInt16& nCatLbPos, LanguageType&&nbsp;rLangType,
                                           sal_uInt16& nFmtLbSelPos,
                                           std::vector<OUString>& rFmtEntries,
                                           OUString& rPrevString, const Color*& rpPrevColor)
{
    // precondition: number formater found
    DBG_ASSERT(pFormatter != nullptr, "Number formatter not found!");

    short nSelPos = SELPOS_NONE;

    // special treatment for undefined number format:
    if ((eValType == SvxNumberValueType::Undefined) && (nCurFormatKey == 0))
        PosToCategory_Impl(CAT_ALL, nCurCategory); // category = all
    else
        nCurCategory = SvNumFormatType::UNDEFINED; // category = undefined

    pCurFmtTable = &(pFormatter->GetFirstEntryTable(nCurCategory, nCurFormatKey, eCurLanguage));

    CategoryToPos_Impl(nCurCategory, nCatLbPos);
    rLangType = eCurLanguage;

    nSelPos = FillEntryList_Impl(rFmtEntries);

    DBG_ASSERT(nSelPos != SELPOS_NONE, "Leere Formatliste!");

    nFmtLbSelPos = (nSelPos != SELPOS_NONE) ? static_cast<sal_uInt16>(nSelPos) : 0;
    GetPreviewString_Impl(rPrevString, rpPrevColor);
}

short SvxNumberFormatShell::FillEntryList_Impl(std::vector<OUString>& rList)
{
    /* Create a current list of format entries. The return value is
     * the list position of the current format. If the list is empty
     * or if there is no current format, SELPOS_NONE is delivered.
     */

    short nSelPos = SELPOS_NONE;

    aCurEntryList.clear();

    if (nCurCategory == SvNumFormatType::ALL)
    {
        FillEListWithStd_Impl(rList, SvNumFormatType::NUMBER, nSelPos);
        nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::NUMBER, nSelPos);

        FillEListWithStd_Impl(rList, SvNumFormatType::PERCENT, nSelPos);
        nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::PERCENT, nSelPos);

        FillEListWithStd_Impl(rList, SvNumFormatType::CURRENCY, nSelPos);
        // No FillEListWithUsD_Impl() here, user defined currency formats
        // were already added.

        FillEListWithStd_Impl(rList, SvNumFormatType::DATE, nSelPos);
        nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATE, nSelPos);

        FillEListWithStd_Impl(rList, SvNumFormatType::TIME, nSelPos);
        nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TIME, nSelPos);

        nSelPos = FillEListWithDateTime_Impl(rList, nSelPos, false);
        nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::DATETIME, nSelPos);

        FillEListWithStd_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);
        nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::SCIENTIFIC, nSelPos);

        FillEListWithStd_Impl(rList, SvNumFormatType::FRACTION, nSelPos);
        nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::FRACTION, nSelPos);

        FillEListWithStd_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);
        nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::LOGICAL, nSelPos);

        FillEListWithStd_Impl(rList, SvNumFormatType::TEXT, nSelPos);
        nSelPos = FillEListWithUsD_Impl(rList, SvNumFormatType::TEXT, nSelPos);
    }
    else
    {
        FillEListWithStd_Impl(rList, nCurCategory, nSelPos, true);
        nSelPos = FillEListWithUsD_Impl(rList, nCurCategory, nSelPos);
        if (nCurCategory == SvNumFormatType::DATE || nCurCategory == SvNumFormatType::TIME)
            nSelPos = FillEListWithDateTime_Impl(rList, nSelPos, true);
    }

    return nSelPos;
}

void SvxNumberFormatShell::FillEListWithStd_Impl(std::vector<OUString>& rList,
                                                 SvNumFormatType eCategory, short& nSelPos,
                                                 bool bSuppressDuplicates)
{
    /* Create a current list of format entries. The return value is
     * the list position of the current format. If the list is empty
     * or if there is no current format, SELPOS_NONE is delivered.
     */


    assert(pCurFmtTable != nullptr);

    aCurrencyFormatList.clear();

    NfIndexTableOffset eOffsetStart;
    NfIndexTableOffset eOffsetEnd;

    switch (eCategory)
    {
        case SvNumFormatType::NUMBER:
            eOffsetStart = NF_NUMBER_START;
            eOffsetEnd = NF_NUMBER_END;
            break;
        case SvNumFormatType::PERCENT:
            eOffsetStart = NF_PERCENT_START;
            eOffsetEnd = NF_PERCENT_END;
            break;
        case SvNumFormatType::CURRENCY:
            // Currency entries are generated and assembled, ignore
            // bSuppressDuplicates.
            nSelPos = FillEListWithCurrency_Impl(rList, nSelPos);
            return;
        case SvNumFormatType::DATE:
            eOffsetStart = NF_DATE_START;
            eOffsetEnd = NF_DATE_END;
            break;
        case SvNumFormatType::TIME:
            eOffsetStart = NF_TIME_START;
            eOffsetEnd = NF_TIME_END;
            break;
        case SvNumFormatType::SCIENTIFIC:
            eOffsetStart = NF_SCIENTIFIC_START;
            eOffsetEnd = NF_SCIENTIFIC_END;
            break;
        case SvNumFormatType::FRACTION:
            eOffsetStart = NF_FRACTION_START;
            eOffsetEnd = NF_FRACTION_END;
            // Fraction formats are internally generated by the number
            // formatter and are not supposed to contain duplicates anyway.
            nSelPos = FillEListWithFormats_Impl(rList, nSelPos, eOffsetStart, eOffsetEnd, false);
            nSelPos
                = FillEListWithFormats_Impl(rList, nSelPos, NF_FRACTION_3D, NF_FRACTION_100, false);
            return;
        case SvNumFormatType::LOGICAL:
            eOffsetStart = NF_BOOLEAN;
            eOffsetEnd = NF_BOOLEAN;
            break;
        case SvNumFormatType::TEXT:
            eOffsetStart = NF_TEXT;
            eOffsetEnd = NF_TEXT;
            break;
        default:
            return;
    }

    nSelPos
        = FillEListWithFormats_Impl(rList, nSelPos, eOffsetStart, eOffsetEnd, bSuppressDuplicates);
}

short SvxNumberFormatShell::FillEListWithFormats_Impl(std::vector<OUString>& rList, short nSelPos,
                                                      NfIndexTableOffset eOffsetStart,
                                                      NfIndexTableOffset eOffsetEnd,
                                                      bool bSuppressDuplicates)
{
    /* Create a current list of format entries. The return value is
     * the list position of the current format. If the list is empty
     * or if there is no current format, SELPOS_NONE is delivered.
     */

    for (tools::Long nIndex = eOffsetStart; nIndex <= eOffsetEnd; ++nIndex)
    {
        FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
                                    static_cast<NfIndexTableOffset>(nIndex), false);
    }

    return nSelPos;
}

short SvxNumberFormatShell::FillEListWithDateTime_Impl(std::vector<OUString>& rList, short nSelPos,
                                                       bool bSuppressDuplicates)
{
    // Append a list of date+time formats.

    // Add first, so a NF_DATETIME_SYSTEM_SHORT_HHMM may be suppressed in
    // locales that do not use 2-digit years there and this here is the
    // default.
    FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates, NF_DATETIME_SYS_DDMMYYYY_HHMM,
                                true);

    for (tools::Long nIndex = NF_DATETIME_START; nIndex <= NF_DATETIME_END; ++nIndex)
    {
        FillEListWithOneFormat_Impl(rList, nSelPos, bSuppressDuplicates,
                                    static_cast<NfIndexTableOffset>(nIndex), true);
    }

    // Always add the internally generated ISO formats.
    nSelPos = FillEListWithFormats_Impl(rList, nSelPos, NF_DATETIME_ISO_YYYYMMDD_HHMMSS,
                                        NF_DATETIME_ISO_YYYYMMDDTHHMMSS000, false);

    return nSelPos;
}

void SvxNumberFormatShell::FillEListWithOneFormat_Impl(std::vector<OUString>& rList, short& nSelPos,
                                                       bool bSuppressDuplicates,
                                                       NfIndexTableOffset nOffset,
                                                       bool bSuppressIsoDateTime)
{
    sal_uInt32 nNFEntry = pFormatter->GetFormatIndex(nOffset, eCurLanguage);

    const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);
    if (pNumEntry == nullptr)
        return;

    SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
    sal_uInt16 nMyType;
    CategoryToPos_Impl(nMyCat, nMyType);
    OUString aNewFormNInfo = pNumEntry->GetFormatstring();

    if (nNFEntry == nCurFormatKey)
    {
        nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
    }

    // Ugly hack to suppress an ISO date+time format that is the default
    // date+time format of the locale and identical to the internally generated
    // one always to be added after/below.
    const bool bSupIso
        = bSuppressIsoDateTime && bSuppressDuplicates
          && (aNewFormNInfo == "YYYY-MM-DD HH:MM:SS" || aNewFormNInfo == "YYYY-MM-DD\"T\"HH:MM:SS");

    if (!bSupIso
        && (!bSuppressDuplicates || IsEssentialFormat_Impl(nMyCat, nNFEntry)
            || std::find(rList.begin(), rList.end(), aNewFormNInfo) == rList.end()))
    {
        rList.push_back(aNewFormNInfo);
        aCurEntryList.push_back(nNFEntry);
    }
}

bool SvxNumberFormatShell::IsEssentialFormat_Impl(SvNumFormatType eType, sal_uInt32 nKey)
{
    if (nKey == nCurFormatKey)
        return true;

    const NfIndexTableOffset nIndex = SvNumberFormatter::GetIndexTableOffset(nKey);
    switch (nIndex)
    {
        // These are preferred or edit formats.
        case NF_DATE_SYS_DDMMYYYY:
        case NF_DATE_ISO_YYYYMMDD:
        case NF_TIME_HH_MMSS:
        case NF_TIME_MMSS00:
        case NF_TIME_HH_MMSS00:
        case NF_DATETIME_SYS_DDMMYYYY_HHMM:
        case NF_DATETIME_SYS_DDMMYYYY_HHMMSS:
        case NF_DATETIME_ISO_YYYYMMDD_HHMMSS:
        case NF_DATETIME_ISO_YYYYMMDD_HHMMSS000:
        case NF_DATETIME_ISO_YYYYMMDDTHHMMSS:
        case NF_DATETIME_ISO_YYYYMMDDTHHMMSS000:
            return true;
        default:
            break;
    }

    return nKey == pFormatter->GetStandardFormat(eType, eCurLanguage);
}

short SvxNumberFormatShell::FillEListWithCurrency_Impl(std::vector<OUString>& rList, short nSelPos)
{
    /* Create a current list of format entries. The return value is
     * the list position of the current format. If the list is empty
     * or if there is no current format, SELPOS_NONE is delivered.
     */

    DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");

    const NfCurrencyEntry* pTmpCurrencyEntry;
    bool bTmpBanking;
    OUString rSymbol;

    bool bFlag = pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
                                                        &bTmpBanking);

    if ((!bFlag && pCurCurrencyEntry == nullptr)
        || (bFlag && pTmpCurrencyEntry == nullptr && rSymbol.isEmpty())
        || (nCurCategory == SvNumFormatType::ALL))
    {
        if (nCurCategory == SvNumFormatType::ALL)
            FillEListWithUserCurrencys(rList, nSelPos);
        nSelPos = FillEListWithSysCurrencys(rList, nSelPos);
    }
    else
    {
        nSelPos = FillEListWithUserCurrencys(rList, nSelPos);
    }

    return nSelPos;
}

short SvxNumberFormatShell::FillEListWithSysCurrencys(std::vector<OUString>& rList, short nSelPos)
{
    /* Create a current list of format entries. The return value is
     * the list position of the current format. If the list is empty
     * or if there is no current format, SELPOS_NONE is delivered.
     */

    sal_uInt16 nMyType;

    sal_uInt32 nNFEntry;
    OUString aNewFormNInfo;

    nCurCurrencyEntryPos = 0;

    for (tools::Long nIndex = NF_CURRENCY_START; nIndex <= NF_CURRENCY_END; nIndex++)
    {
        nNFEntry
            = pFormatter->GetFormatIndex(static_cast<NfIndexTableOffset>(nIndex), eCurLanguage);

        if (nCurCategory == SvNumFormatType::ALL && nNFEntry != nCurFormatKey)
            // Deprecated old currency entries, for ALL add only if used as
            // current format key.
            continue;

        const SvNumberformat* pNumEntry = pFormatter->GetEntry(nNFEntry);

        if (pNumEntry == nullptr)
            continue;

        SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
        CategoryToPos_Impl(nMyCat, nMyType);
        aNewFormNInfo = pNumEntry->GetFormatstring();

        if (nNFEntry == nCurFormatKey)
        {
            nSelPos = (!IsRemoved_Impl(nNFEntry)) ? aCurEntryList.size() : SELPOS_NONE;
        }

        rList.push_back(aNewFormNInfo);
        aCurEntryList.push_back(nNFEntry);
    }

    if (nCurCategory != SvNumFormatType::ALL)
    {
        assert(pCurFmtTable != nullptr && "unknown NumberFormat");
        for (const auto& rEntry : *pCurFmtTable)
        {
            sal_uInt32 nKey = rEntry.first;
            const SvNumberformat* pNumEntry = rEntry.second;

            if (!IsRemoved_Impl(nKey))
            {
                bool bUserNewCurrency = false;
                if (pNumEntry->HasNewCurrency())
                {
                    const NfCurrencyEntry* pTmpCurrencyEntry;
                    bool bTmpBanking;
                    OUString rSymbol;

                    pFormatter->GetNewCurrencySymbolString(nKey, rSymbol, &pTmpCurrencyEntry,
                                                           &bTmpBanking);

                    bUserNewCurrency = (pTmpCurrencyEntry != nullptr);
                }

                if (!bUserNewCurrency && (pNumEntry->GetType() & SvNumFormatType::DEFINED))
                {
                    SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
                    CategoryToPos_Impl(nMyCat, nMyType);
                    aNewFormNInfo = pNumEntry->GetFormatstring();

                    if (nKey == nCurFormatKey)
                        nSelPos = aCurEntryList.size();
                    rList.push_back(aNewFormNInfo);
                    aCurEntryList.push_back(nKey);
                }
            }
        }
    }
    return nSelPos;
}

short SvxNumberFormatShell::FillEListWithUserCurrencys(std::vector<OUString>& rList, short nSelPos)
{
    /* Create a current list of format entries. The return value is
     * the list position of the current format. If the list is empty
     * or if there is no current format, SELPOS_NONE is delivered.
     */

    sal_uInt16 nMyType;

    OUString aNewFormNInfo;

    const NfCurrencyEntry* pTmpCurrencyEntry;
    bool bTmpBanking, bAdaptSelPos;
    OUString rSymbol;
    OUString rBankSymbol;

    std::vector<OUString> aList;
    std::vector<sal_uInt32> aKeyList;

    pFormatter->GetNewCurrencySymbolString(nCurFormatKey, rSymbol, &pTmpCurrencyEntry,
                                           &bTmpBanking);

    OUString rShortSymbol;

    if (pCurCurrencyEntry == nullptr)
    {
        // #110398# If no currency format was previously selected (we're not
        // about to add another currency), try to select the initial currency
        // format (nCurFormatKey) that was set in FormatChanged() after
        // matching the format string entered in the dialog.
        bAdaptSelPos = true;
        pCurCurrencyEntry = const_cast<NfCurrencyEntry*>(pTmpCurrencyEntry);
        bBankingSymbol = bTmpBanking;
        nCurCurrencyEntryPos = FindCurrencyFormat(pTmpCurrencyEntry, bTmpBanking);
    }
    else
    {
        if (pTmpCurrencyEntry == pCurCurrencyEntry)
            bAdaptSelPos = true;
        else
        {
            bAdaptSelPos = false;
            pTmpCurrencyEntry = pCurCurrencyEntry;
        }
        bTmpBanking = bBankingSymbol;
    }

    if (pTmpCurrencyEntry != nullptr)
    {
        rSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
        rBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);
        rShortSymbol = pTmpCurrencyEntry->BuildSymbolString(bTmpBanking, true);
    }

    assert(pCurFmtTable != nullptr && "unknown NumberFormat");
    for (const auto& rEntry : *pCurFmtTable)
    {
        sal_uInt32 nKey = rEntry.first;
        const SvNumberformat* pNumEntry = rEntry.second;

        if (!IsRemoved_Impl(nKey))
        {
            if (pNumEntry->GetType() & SvNumFormatType::DEFINED || pNumEntry->IsAdditionalBuiltin())
            {
                SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
                CategoryToPos_Impl(nMyCat, nMyType);
                aNewFormNInfo = pNumEntry->GetFormatstring();

                bool bInsFlag = false;
                if (pNumEntry->HasNewCurrency())
                {
                    bInsFlag = true// merge locale formats into currency selection
                }
                else if ((!bTmpBanking && aNewFormNInfo.indexOf(rSymbol) >= 0)
                         || (bTmpBanking && aNewFormNInfo.indexOf(rBankSymbol) >= 0))
                {
                    bInsFlag = true;
                }
                else if (aNewFormNInfo.indexOf(rShortSymbol) >= 0)
                {
                    OUString rTstSymbol;
                    const NfCurrencyEntry* pTstCurrencyEntry;
                    bool bTstBanking;

                    pFormatter->GetNewCurrencySymbolString(nKey, rTstSymbol, &pTstCurrencyEntry,
                                                           &bTstBanking);

                    if (pTmpCurrencyEntry == pTstCurrencyEntry && bTstBanking == bTmpBanking)
                    {
                        bInsFlag = true;
                    }
                }

                if (bInsFlag)
                {
                    aList.push_back(aNewFormNInfo);
                    aKeyList.push_back(nKey);
                }
            }
        }
    }

    NfWSStringsDtor aWSStringsDtor;
    sal_uInt16 nDefault;
    if (pTmpCurrencyEntry && nCurCategory != SvNumFormatType::ALL)
    {
        nDefault
            = pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, bTmpBanking);
        if (!bTmpBanking)
            pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pTmpCurrencyEntry, true);
    }
    else
        nDefault = 0;
    if (!bTmpBanking && nCurCategory != SvNumFormatType::ALL)
    {
        // append formats for all currencies defined in the current I18N locale
        const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
        sal_uInt16 nCurrCount = rCurrencyTable.size();
        LanguageType eLang = MsLangId::getRealLanguage(eCurLanguage);
        for (sal_uInt16 i = 0; i < nCurrCount; ++i)
        {
            const NfCurrencyEntry* pCurr = &rCurrencyTable[i];
            if (pCurr->GetLanguage() == eLang && pTmpCurrencyEntry != pCurr)
            {
                pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, false);
                pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, *pCurr, true);
            }
        }
    }

    size_t nOldListCount = rList.size();
    for (size_t i = 0, nPos = nOldListCount; i < aWSStringsDtor.size(); ++i)
    {
        bool bFlag = true;
        const OUString& aInsStr(aWSStringsDtor[i]);
        size_t j;
        for (j = 0; j < aList.size(); ++j)
        {
            if (aList[j] == aInsStr)
            {
                bFlag = false;
                break;
            }
        }
        if (bFlag)
        {
            rList.push_back(aInsStr);
            aCurEntryList.insert(aCurEntryList.begin() + (nPos++), NUMBERFORMAT_ENTRY_NOT_FOUND);
        }
        else
        {
            rList.push_back(aList[j]);
            aList.erase(aList.begin() + j);
            aCurEntryList.insert(aCurEntryList.begin() + (nPos++), aKeyList[j]);
            aKeyList.erase(aKeyList.begin() + j);
        }
    }

    for (size_t i = 0; i < aKeyList.size(); ++i)
    {
        if (aKeyList[i] != NUMBERFORMAT_ENTRY_NOT_FOUND)
        {
            rList.push_back(aList[i]);
            aCurEntryList.push_back(aKeyList[i]);
        }
    }

    for (size_t i = nOldListCount; i < rList.size(); ++i)
    {
        aCurrencyFormatList.push_back(rList[i]);

        if (nSelPos == SELPOS_NONE && bAdaptSelPos && aCurEntryList[i] == nCurFormatKey)
            nSelPos = i;
    }

    if (nSelPos == SELPOS_NONE && nCurCategory != SvNumFormatType::ALL)
        nSelPos = nDefault;

    return nSelPos;
}

short SvxNumberFormatShell::FillEListWithUsD_Impl(std::vector<OUString>& rList,
                                                  SvNumFormatType eCategory, short nSelPos)
{
    /* Create a current list of format entries. The return value is
     * the list position of the current format. If the list is empty
     * or if there is no current format, SELPOS_NONE is delivered.
     */


    assert(pCurFmtTable != nullptr);

    OUString aNewFormNInfo;

    const bool bCatDefined = (eCategory == SvNumFormatType::DEFINED);
    const bool bCategoryMatch = (eCategory != SvNumFormatType::ALL && !bCatDefined);
    const bool bNatNumCurrency = (eCategory == SvNumFormatType::CURRENCY);

    for (const auto& rEntry : *pCurFmtTable)
    {
        const SvNumberformat* pNumEntry = rEntry.second;

        if (bCategoryMatch && (pNumEntry->GetMaskedType() & eCategory) != eCategory)
            continue// for; type does not match category if not ALL

        const bool bUserDefined = bool(pNumEntry->GetType() & SvNumFormatType::DEFINED);
        if (!bUserDefined && bCatDefined)
            continue// for; not user defined in DEFINED category

        if (!(bUserDefined || (!bCatDefined && pNumEntry->IsAdditionalBuiltin())))
            continue// for; does not match criteria at all

        const sal_uInt32 nKey = rEntry.first;
        if (!IsRemoved_Impl(nKey))
        {
            aNewFormNInfo = pNumEntry->GetFormatstring();

            if (bNatNumCurrency && (aNewFormNInfo.indexOf("NatNum12") < 0 || bUserDefined))
                continue// for; extra CURRENCY must be not user-defined NatNum12 type

            bool bAdd = true;
            if (pNumEntry->HasNewCurrency())
            {
                bool bTestBanking;
                sal_uInt16 nPos = FindCurrencyTableEntry(aNewFormNInfo, bTestBanking);
                bAdd = !IsInTable(nPos, bTestBanking, aNewFormNInfo);
            }
            if (bAdd)
            {
                if (nKey == nCurFormatKey)
                    nSelPos = aCurEntryList.size();
                rList.push_back(aNewFormNInfo);
                aCurEntryList.push_back(nKey);
            }
        }
    }
    return nSelPos;
}

void SvxNumberFormatShell::GetPreviewString_Impl(OUString& rString, const Color*&&nbsp;rpColor)
{
    rpColor = nullptr;

    //  #50441# if a string was set in addition to the value, use it for text formats
    bool bUseText
        = (eValType == SvxNumberValueType::String
           || (!aValStr.isEmpty() && (pFormatter->GetType(nCurFormatKey) & SvNumFormatType::TEXT)));

    if (bUseText)
    {
        pFormatter->GetOutputString(aValStr, nCurFormatKey, rString, &rpColor);
    }
    else
    {
        double nVal = nValNum;
        const SvNumberformat* pEntry = pFormatter->GetEntry(nCurFormatKey);
        if (nVal == 0.0 && pEntry && pEntry->GetFormatstring().indexOf("NatNum12") >= 0)
        {
            sal_Int32 nEnd;
            rtl_math_ConversionStatus eStatus;
            LocaleDataWrapper aLocale(LanguageTag(pEntry->GetLanguage()));

            nVal = aLocale.stringToDouble(aValStr, true, &eStatus, &nEnd);
            if (rtl_math_ConversionStatus_Ok != eStatus || nEnd == 0)
                nVal = GetDefaultValNum(pFormatter->GetType(nCurFormatKey));
        }

        pFormatter->GetOutputString(nVal, nCurFormatKey, rString, &rpColor, bUseStarFormat);
    }
}

::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetRemoved_Impl(size_t nKey)
{
    return ::std::find(aDelList.begin(), aDelList.end(), nKey);
}

bool SvxNumberFormatShell::IsRemoved_Impl(size_t nKey)
{
    return GetRemoved_Impl(nKey) != aDelList.end();
}

::std::vector<sal_uInt32>::iterator SvxNumberFormatShell::GetAdded_Impl(size_t nKey)
{
    return ::std::find(aAddList.begin(), aAddList.end(), nKey);
}

// Conversion routines:
void SvxNumberFormatShell::PosToCategory_Impl(sal_uInt16 nPos, SvNumFormatType& rCategory)
{
    // map category css::form positions (->resource)
    switch (nPos)
    {
        case CAT_USERDEFINED:
            rCategory = SvNumFormatType::DEFINED;
            break;
        case CAT_NUMBER:
            rCategory = SvNumFormatType::NUMBER;
            break;
        case CAT_PERCENT:
            rCategory = SvNumFormatType::PERCENT;
            break;
        case CAT_CURRENCY:
            rCategory = SvNumFormatType::CURRENCY;
            break;
        case CAT_DATE:
            rCategory = SvNumFormatType::DATE;
            break;
        case CAT_TIME:
            rCategory = SvNumFormatType::TIME;
            break;
        case CAT_SCIENTIFIC:
            rCategory = SvNumFormatType::SCIENTIFIC;
            break;
        case CAT_FRACTION:
            rCategory = SvNumFormatType::FRACTION;
            break;
        case CAT_BOOLEAN:
            rCategory = SvNumFormatType::LOGICAL;
            break;
        case CAT_TEXT:
            rCategory = SvNumFormatType::TEXT;
            break;
        case CAT_ALL:
        default:
            rCategory = SvNumFormatType::ALL;
            break;
    }
}

void SvxNumberFormatShell::CategoryToPos_Impl(SvNumFormatType nCategory, sal_uInt16&&nbsp;rPos)
{
    // map category to css::form positions (->resource)
    switch (nCategory)
    {
        case SvNumFormatType::DEFINED:
            rPos = CAT_USERDEFINED;
            break;
        case SvNumFormatType::NUMBER:
            rPos = CAT_NUMBER;
            break;
        case SvNumFormatType::PERCENT:
            rPos = CAT_PERCENT;
            break;
        case SvNumFormatType::CURRENCY:
            rPos = CAT_CURRENCY;
            break;
        case SvNumFormatType::DATETIME:
        case SvNumFormatType::DATE:
            rPos = CAT_DATE;
            break;
        case SvNumFormatType::TIME:
            rPos = CAT_TIME;
            break;
        case SvNumFormatType::SCIENTIFIC:
            rPos = CAT_SCIENTIFIC;
            break;
        case SvNumFormatType::FRACTION:
            rPos = CAT_FRACTION;
            break;
        case SvNumFormatType::LOGICAL:
            rPos = CAT_BOOLEAN;
            break;
        case SvNumFormatType::TEXT:
            rPos = CAT_TEXT;
            break;
        case SvNumFormatType::ALL:
        default:
            rPos = CAT_ALL;
    }
}

/*
 * Function:   Formats the number nValue dependent on rFormatStr
 *             and stores the result in rPreviewStr.
 * Input:      FormatString, color, number to format
 * Output:     Output string rPreviewStr
 */

void SvxNumberFormatShell::MakePrevStringFromVal(const OUString& rFormatStr, OUString& rPreviewStr,
                                                 const Color*& rpFontColor, double nValue)
{
    rpFontColor = nullptr;
    pFormatter->GetPreviewString(rFormatStr, nValue, rPreviewStr, &rpFontColor, eCurLanguage);
}

/*
 * Function:   Returns the comment for a given entry.
 * Input:      Number of the entry
 * Output:     Comment string
 */

void SvxNumberFormatShell::SetComment4Entry(short nEntry, const OUString& aEntStr)
{
    SvNumberformat* pNumEntry;
    if (nEntry < 0)
        return;
    sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
    pNumEntry = const_cast<SvNumberformat*>(pFormatter->GetEntry(nMyNfEntry));
    if (pNumEntry != nullptr)
        pNumEntry->SetComment(aEntStr);
}

/*
 * Function:   Returns the comment for a given entry.
 * Input:      Number of the entry
 * Output:     Comment string
 */

OUString SvxNumberFormatShell::GetComment4Entry(short nEntry)
{
    if (nEntry < 0)
        return OUString();

    if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
    {
        sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
        const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
        if (pNumEntry != nullptr)
            return pNumEntry->GetComment();
    }

    return OUString();
}

/*
 * Function:   Returns the category number for a given entry.
 * Input:      Number of the entry
 * Output:     Category number
 */

short SvxNumberFormatShell::GetCategory4Entry(short nEntry) const
{
    if (nEntry < 0)
        return 0;
    if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
    {
        sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];

        if (nMyNfEntry != NUMBERFORMAT_ENTRY_NOT_FOUND)
        {
            const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);
            if (pNumEntry != nullptr)
            {
                SvNumFormatType nMyCat = pNumEntry->GetMaskedType();
                sal_uInt16 nMyType;
                CategoryToPos_Impl(nMyCat, nMyType);

                return static_cast<short>(nMyType);
            }
            return 0;
        }
        else if (!aCurrencyFormatList.empty())
        {
            return CAT_CURRENCY;
        }
    }
    return 0;
}

/*
 * Function:   Returns the information about whether an entry is user-specific.
 * Input:      Number of the entry
 * Output:     User-specific?
 */

bool SvxNumberFormatShell::GetUserDefined4Entry(short nEntry)
{
    if (nEntry < 0)
        return false;
    if (o3tl::make_unsigned(nEntry) < aCurEntryList.size())
    {
        sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
        const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);

        if (pNumEntry != nullptr)
        {
            if (pNumEntry->GetType() & SvNumFormatType::DEFINED)
            {
                return true;
            }
        }
    }
    return false;
}

/*
 * Function:   Returns the format string for a given entry.
 * Input:      Number of the entry
 * Output:     Format string
 */

OUString SvxNumberFormatShell::GetFormat4Entry(short nEntry)
{
    if (nEntry < 0)
        return OUString();

    if (!aCurrencyFormatList.empty()
        && (!pFormatter->GetEntry(aCurEntryList[nEntry])
            || pFormatter->GetEntry(aCurEntryList[nEntry])->GetFormatstring().indexOf("NatNum12")
                   < 0))
    {
        if (aCurrencyFormatList.size() > o3tl::make_unsigned(nEntry))
            return aCurrencyFormatList[nEntry];
    }
    else
    {
        sal_uInt32 nMyNfEntry = aCurEntryList[nEntry];
        const SvNumberformat* pNumEntry = pFormatter->GetEntry(nMyNfEntry);

        if (pNumEntry != nullptr)
            return pNumEntry->GetFormatstring();
    }
    return OUString();
}

/*
 * Function:   Returns the list number for a given format index.
 * Input:      Number of the entry
 * Output:     Category number
 */

short SvxNumberFormatShell::GetListPos4Entry(sal_uInt32 nIdx, std::u16string_view rFmtString)
{
    short nSelP = SELPOS_NONE;
    if (nIdx != NUMBERFORMAT_ENTRY_NEW_CURRENCY)
    {
        // Check list size against return type limit.
        if (aCurEntryList.size() <= o3tl::make_unsigned(::std::numeric_limits<short>::max()))
        {
            for (size_t i = 0; i < aCurEntryList.size(); ++i)
            {
                if (aCurEntryList[i] == nIdx)
                {
                    nSelP = i;
                    break;
                }
            }
        }
        else
        {
            OSL_FAIL("svx::SvxNumberFormatShell::GetListPos4Entry(), list got too large!");
        }
    }
    else
    {
        // A second list holds the generated currency formats.
        for (size_t i = 0; i < aCurrencyFormatList.size(); ++i)
        {
            if (rFmtString == aCurrencyFormatList[i])
            {
                nSelP = static_cast<short>(i);
                break;
            }
        }
    }
    return nSelP;
}

OUString SvxNumberFormatShell::GetStandardName() const
{
    return pFormatter->GetStandardName(eCurLanguage);
}

void SvxNumberFormatShell::GetCurrencySymbols(std::vector<OUString>& rList, sal_uInt16* pPos)
{
    const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::MatchSystemCurrency();

    bool bFlag = (pTmpCurrencyEntry == nullptr);

    std::vector<sfx::CurrencyID> aDocumentCurrencyIDs;
    SvxCurrencyToolBoxControl::GetCurrencySymbols(rList, bFlag, aCurCurrencyList,
                                                  aDocumentCurrencyIDs);

    if (pPos == nullptr)
        return;

    const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
    sal_uInt16 nTableCount = rCurrencyTable.size();

    *pPos = 0;
    size_t nCount = aCurCurrencyList.size();

    if (bFlag)
    {
        *pPos = 1;
        nCurCurrencyEntryPos = 1;
    }
    else
    {
        for (size_t i = 1; i < nCount; i++)
        {
            const sal_uInt16 j = aCurCurrencyList[i];
            if (j != sal_uInt16(-1) && j < nTableCount && pTmpCurrencyEntry == &rCurrencyTable[j])
            {
                *pPos = static_cast<sal_uInt16>(i);
                nCurCurrencyEntryPos = static_cast<sal_uInt16>(i);
                break;
            }
        }
    }
}

void SvxNumberFormatShell::SetCurrencySymbol(sal_uInt32 nPos)
{
    const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
    sal_uInt16 nCount = rCurrencyTable.size();

    bBankingSymbol = (nPos >= nCount);

    if (nPos >= aCurCurrencyList.size())
        return;

    sal_uInt16 nCurrencyPos = aCurCurrencyList[nPos];
    if (nCurrencyPos != sal_uInt16(-1))
    {
        pCurCurrencyEntry = const_cast<NfCurrencyEntry*>(&rCurrencyTable[nCurrencyPos]);
        nCurCurrencyEntryPos = nPos;
    }
    else
    {
        pCurCurrencyEntry = nullptr;
        nCurCurrencyEntryPos = 0;
        nCurFormatKey = pFormatter->GetFormatIndex(NF_CURRENCY_1000DEC2_RED, eCurLanguage);
    }
}

void SvxNumberFormatShell::SetCurCurrencyEntry(NfCurrencyEntry* pCEntry)
{
    pCurCurrencyEntry = pCEntry;
}

bool SvxNumberFormatShell::IsTmpCurrencyFormat(const OUString& rFmtString)
{
    sal_uInt32 nFound;
    FindEntry(rFmtString, &nFound);
    return nFound == NUMBERFORMAT_ENTRY_NEW_CURRENCY;
}

sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const OUString& rFmtString)
{
    const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
    sal_uInt16 nCount = rCurrencyTable.size();

    bool bTestBanking = false;

    sal_uInt16 nPos = FindCurrencyTableEntry(rFmtString, bTestBanking);

    if (nPos != sal_uInt16(-1))
    {
        sal_uInt16 nStart = 0;
        if (bTestBanking && aCurCurrencyList.size() > nPos)
        {
            nStart = nCount;
        }
        for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
        {
            if (aCurCurrencyList[j] == nPos)
                return j;
        }
    }
    return sal_uInt16(-1);
}

sal_uInt16 SvxNumberFormatShell::FindCurrencyTableEntry(const OUString& rFmtString,
                                                        bool& bTestBanking)
{
    sal_uInt16 nPos = sal_uInt16(-1);

    const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
    sal_uInt16 nCount = rCurrencyTable.size();

    const SvNumberformat* pFormat;
    OUString aSymbol, aExtension;
    sal_uInt32 nFound = pFormatter->TestNewString(rFmtString, eCurLanguage);
    if (nFound != NUMBERFORMAT_ENTRY_NOT_FOUND
        && ((pFormat = pFormatter->GetEntry(nFound)) != nullptr)
        && pFormat->GetNewCurrencySymbol(aSymbol, aExtension))
    {
        // eventually match with format locale
        const NfCurrencyEntry* pTmpCurrencyEntry = SvNumberFormatter::GetCurrencyEntry(
            bTestBanking, aSymbol, aExtension, pFormat->GetLanguage());
        if (pTmpCurrencyEntry)
        {
            for (sal_uInt16 i = 0; i < nCount; i++)
            {
                if (pTmpCurrencyEntry == &rCurrencyTable[i])
                {
                    nPos = i;
                    break;
                }
            }
        }
    }
    else
    {
        // search symbol string only
        for (sal_uInt16 i = 0; i < nCount; i++)
        {
            const NfCurrencyEntry* pTmpCurrencyEntry = &rCurrencyTable[i];
            OUString _aSymbol = pTmpCurrencyEntry->BuildSymbolString(false);
            OUString aBankSymbol = pTmpCurrencyEntry->BuildSymbolString(true);

            if (rFmtString.indexOf(_aSymbol) != -1)
            {
                bTestBanking = false;
                nPos = i;
                break;
            }
            else if (rFmtString.indexOf(aBankSymbol) != -1)
            {
                bTestBanking = true;
                nPos = i;
                break;
            }
        }
    }

    return nPos;
}

sal_uInt16 SvxNumberFormatShell::FindCurrencyFormat(const NfCurrencyEntry* pTmpCurrencyEntry,
                                                    bool bTmpBanking)
{
    const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
    sal_uInt16 nCount = rCurrencyTable.size();

    sal_uInt16 nPos = 0;
    for (sal_uInt16 i = 0; i < nCount; i++)
    {
        if (pTmpCurrencyEntry == &rCurrencyTable[i])
        {
            nPos = i;
            break;
        }
    }

    sal_uInt16 nStart = 0;
    if (bTmpBanking && aCurCurrencyList.size() > nPos)
    {
        nStart = nCount;
    }
    for (size_t j = nStart; j < aCurCurrencyList.size(); j++)
    {
        if (aCurCurrencyList[j] == nPos)
            return j;
    }
    return sal_uInt16(-1);
}

bool SvxNumberFormatShell::IsInTable(sal_uInt16 const nPos, bool const bTmpBanking,
                                     std::u16string_view rFmtString) const
{
    bool bFlag = false;

    if (nPos != sal_uInt16(-1))
    {
        const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();

        if (nPos < rCurrencyTable.size())
        {
            NfWSStringsDtor aWSStringsDtor;
            pFormatter->GetCurrencyFormatStrings(aWSStringsDtor, rCurrencyTable[nPos], bTmpBanking);

            for (const OUString& s : aWSStringsDtor)
            {
                if (s == rFmtString)
                {
                    bFlag = true;
                    break;
                }
            }
        }
    }

    return bFlag;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=94 H=95 G=94

¤ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge