/* -*- 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 <i18nlangtag/mslangid.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 <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 ) );
            }
            SAL_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 ( std::vector<sal_uInt32>::const_iterator it(aAddList.begin()); it != aAddList.end(); ++it )
            pFormatter->DeleteEntry( *it );
    }
}
 
 
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,
                                          Color*&     rpFontColor )
{
    if( static_cast<size_t>(nFmtLbPos) < aCurEntryList.size() )
    {
        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( const OUString& 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 ) )
    {
        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( const OUString&  rFormat ) const
{
    sal_uInt32 nFmtKey = pFormatter->GetEntryKey( rFormat, eCurLanguage );
 
    return pFormatter->GetFormatIntegerDigits(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,
                                              Color*&         rpFontColor )
{
    rpFontColor = nullptr;
 
    sal_uIntPtr 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 = 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& rLangType,
                                            sal_uInt16& nFmtLbSelPos,
                                            std::vector<OUString>& rFmtEntries,
                                            OUString& rPrevString,
                                            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=0;
    sal_uInt16 nPrivCat = CAT_CURRENCY;
    nSelPos=SELPOS_NONE;
 
    aCurEntryList.clear();
 
    if(nCurCategory==SvNumFormatType::ALL)
    {
        FillEListWithStd_Impl(rList,CAT_NUMBER,nSelPos);
        FillEListWithStd_Impl(rList,CAT_PERCENT,nSelPos);
        FillEListWithStd_Impl(rList,CAT_CURRENCY,nSelPos);
        FillEListWithStd_Impl(rList,CAT_DATE,nSelPos);
        FillEListWithStd_Impl(rList,CAT_TIME,nSelPos);
        FillEListWithStd_Impl(rList,CAT_SCIENTIFIC,nSelPos);
        FillEListWithStd_Impl(rList,CAT_FRACTION,nSelPos);
        FillEListWithStd_Impl(rList,CAT_BOOLEAN,nSelPos);
        FillEListWithStd_Impl(rList,CAT_TEXT,nSelPos);
    }
    else
    {
        CategoryToPos_Impl(nCurCategory, nPrivCat);
        FillEListWithStd_Impl(rList,nPrivCat,nSelPos);
    }
 
    if( nPrivCat!=CAT_CURRENCY)
        nSelPos=FillEListWithUsD_Impl(rList,nPrivCat,nSelPos);
 
    return nSelPos;
}
 
void SvxNumberFormatShell::FillEListWithStd_Impl( std::vector<OUString>& rList,
                                                  sal_uInt16 nPrivCat,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" );
 
    aCurrencyFormatList.clear();
 
    if(nPrivCat==CAT_CURRENCY)
    {
        nSelPos=FillEListWithCurrency_Impl(rList,nSelPos);
    }
    else
    {
        NfIndexTableOffset eOffsetStart;
        NfIndexTableOffset eOffsetEnd;
 
        switch(nPrivCat)
        {
            case CAT_NUMBER         :eOffsetStart=NF_NUMBER_START;
                                     eOffsetEnd=NF_NUMBER_END;
                                     break;
            case CAT_PERCENT        :eOffsetStart=NF_PERCENT_START;
                                     eOffsetEnd=NF_PERCENT_END;
                                     break;
            case CAT_CURRENCY       :eOffsetStart=NF_CURRENCY_START;
                                     eOffsetEnd=NF_CURRENCY_END;
                                     break;
            case CAT_DATE           :eOffsetStart=NF_DATE_START;
                                     eOffsetEnd=NF_DATE_END;
                                     break;
            case CAT_TIME           :eOffsetStart=NF_TIME_START;
                                     eOffsetEnd=NF_TIME_END;
                                     break;
            case CAT_SCIENTIFIC     :eOffsetStart=NF_SCIENTIFIC_START;
                                     eOffsetEnd=NF_SCIENTIFIC_END;
                                     break;
            case CAT_FRACTION       :eOffsetStart=NF_FRACTION_START;
                                     eOffsetEnd=NF_FRACTION_END;
                                     nSelPos = FillEListWithFormats_Impl( rList, nSelPos, eOffsetStart, eOffsetEnd);
                                     nSelPos = FillEListWithFormats_Impl( rList, nSelPos, NF_FRACTION_3D, NF_FRACTION_100);
                                     return;
            case CAT_BOOLEAN        :eOffsetStart=NF_BOOLEAN;
                                     eOffsetEnd=NF_BOOLEAN;
                                     break;
            case CAT_TEXT           :eOffsetStart=NF_TEXT;
                                     eOffsetEnd=NF_TEXT;
                                     break;
            default                 :return;
        }
 
        nSelPos=FillEListWithFormats_Impl(rList,nSelPos,eOffsetStart,eOffsetEnd);
 
        if(nPrivCat==CAT_DATE || nPrivCat==CAT_TIME)
        {
            nSelPos=FillEListWithDateTime_Impl(rList,nSelPos);
            nSelPos = FillEListWithFormats_Impl( rList, nSelPos,
                    NF_DATETIME_ISO_YYYYMMDD_HHMMSS, NF_DATETIME_ISO_YYYYMMDD_HHMMSS);
        }
    }
}
 
short SvxNumberFormatShell::FillEListWithFormats_Impl( std::vector<OUString>& rList,
                                                       short nSelPos,
                                                       NfIndexTableOffset eOffsetStart,
                                                       NfIndexTableOffset eOffsetEnd)
{
    /* 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;
 
    long nIndex;
 
    for(nIndex=eOffsetStart;nIndex<=eOffsetEnd;nIndex++)
    {
        nNFEntry=pFormatter->GetFormatIndex(static_cast<NfIndexTableOffset>(nIndex),eCurLanguage);
 
        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 );
    }
 
    return nSelPos;
}
 
short SvxNumberFormatShell::FillEListWithDateTime_Impl( std::vector<OUString>& rList,
                                                        short nSelPos)
{
    sal_uInt16  nMyType;
 
    sal_uInt32          nNFEntry;
    OUString            aNewFormNInfo;
 
    for (long nIndex = NF_DATETIME_START; nIndex <= NF_DATETIME_END; ++nIndex)
    {
        nNFEntry=pFormatter->GetFormatIndex(static_cast<NfIndexTableOffset>(nIndex),eCurLanguage);
 
        const SvNumberformat* pNumEntry   = pFormatter->GetEntry(nNFEntry);
        if(pNumEntry!=nullptr)
        {
            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 );
        }
    }
 
    return nSelPos;
}
 
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;
 
    DBG_ASSERT( pCurFmtTable != nullptr, "unknown NumberFormat" );
 
    sal_uInt32          nNFEntry;
    OUString            aNewFormNInfo;
 
    nCurCurrencyEntryPos=0;
 
    for(long nIndex=NF_CURRENCY_START; nIndex<=NF_CURRENCY_END; nIndex++)
    {
        nNFEntry=pFormatter->GetFormatIndex(static_cast<NfIndexTableOffset>(nIndex),eCurLanguage);
 
        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)
    {
        for( SvNumberFormatTable::const_iterator it = pCurFmtTable->begin(), aEnd = pCurFmtTable->end(); it != aEnd; ++it )
        {
            sal_uInt32 nKey = it->first;
            const SvNumberformat* pNumEntry   = it->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;
 
    DBG_ASSERT( pCurFmtTable != nullptr, "unknown NumberFormat" );
 
    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);
    }
 
    for ( SvNumberFormatTable::const_iterator it = pCurFmtTable->begin(), aEnd = pCurFmtTable->end(); it != aEnd; ++it )
    {
        sal_uInt32 nKey = it->first;
        const SvNumberformat* pNumEntry = it->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;
        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,
                                                   sal_uInt16 nPrivCat, 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;
 
    DBG_ASSERT( pCurFmtTable != nullptr, "unknown NumberFormat" );
 
    OUString        aNewFormNInfo;
 
    bool            bAdditional = (nPrivCat != CAT_USERDEFINED &&
                                    nCurCategory != SvNumFormatType::ALL);
 
    for( SvNumberFormatTable::const_iterator it = pCurFmtTable->begin(), aEnd = pCurFmtTable->end(); it != aEnd; ++it )
    {
        sal_uInt32 nKey = it->first;
        const SvNumberformat* pNumEntry = it->second;
 
        if ( !IsRemoved_Impl( nKey ) )
        {
            if( (pNumEntry->GetType() & SvNumFormatType::DEFINED) ||
                    (bAdditional && pNumEntry->IsAdditionalBuiltin()) )
            {
                SvNumFormatType nMyCat=pNumEntry->GetMaskedType();
                CategoryToPos_Impl(nMyCat,nMyType);
                aNewFormNInfo=  pNumEntry->GetFormatstring();
 
                bool bFlag=true;
                if(pNumEntry->HasNewCurrency())
                {
                    bool bTestBanking;
                    sal_uInt16 nPos=FindCurrencyTableEntry(aNewFormNInfo,bTestBanking);
                    bFlag=!IsInTable(nPos,bTestBanking,aNewFormNInfo);
                }
                if(bFlag)
                {
                    if ( nKey == nCurFormatKey ) nSelPos = aCurEntryList.size();
                    rList.push_back( aNewFormNInfo );
                    aCurEntryList.push_back( nKey );
                }
            }
        }
    }
    return nSelPos;
}
 
 
void SvxNumberFormatShell::GetPreviewString_Impl( OUString& rString, Color*& 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
    {
        pFormatter->GetOutputString( nValNum, 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& 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,
        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( static_cast<size_t>(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( static_cast<size_t>(nEntry) < aCurEntryList.size() )
    {
        sal_uInt32  nMyNfEntry=aCurEntryList[nEntry];
 
        if(nMyNfEntry!=NUMBERFORMAT_ENTRY_NOT_FOUND)
        {
            const SvNumberformat *pNumEntry = pFormatter->GetEntry(nMyNfEntry);
            sal_uInt16 nMyType;
            if(pNumEntry!=nullptr)
            {
                SvNumFormatType nMyCat=pNumEntry->GetMaskedType();
                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( static_cast<size_t>(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() )
    {
        if( aCurrencyFormatList.size() > static_cast<size_t>(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)
{
    short nSelP=SELPOS_NONE;
    // Check list size against return type limit.
    if( aCurEntryList.size() <= static_cast<size_t>(::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!" );
    }
    return nSelP;
}
 
short SvxNumberFormatShell::GetListPos4Entry( const OUString& rFmtString )
{
    sal_uInt32 nAt=0;
    short nSelP=SELPOS_NONE;
    if(FindEntry(rFmtString, &nAt))
    {
        if(NUMBERFORMAT_ENTRY_NOT_FOUND!=nAt && NUMBERFORMAT_ENTRY_NEW_CURRENCY!=nAt)
        {
            nSelP=GetListPos4Entry(nAt);
        }
        else
        {
            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);
 
    SvxCurrencyToolBoxControl::GetCurrencySymbols( rList, bFlag, aCurCurrencyList );
 
    if(pPos!=nullptr)
    {
        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())
    {
        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, OUString const& rFmtString)
{
    bool bFlag=false;
 
    if(nPos!=sal_uInt16(-1))
    {
        const NfCurrencyTable& rCurrencyTable=SvNumberFormatter::GetTheCurrencyTable();
        sal_uInt16 nCount=rCurrencyTable.size();
 
        if(nPos<nCount)
        {
            NfWSStringsDtor aWSStringsDtor;
 
            const NfCurrencyEntry* pTmpCurrencyEntry=&rCurrencyTable[nPos];
 
            if ( pTmpCurrencyEntry!=nullptr)
            {
                pFormatter->GetCurrencyFormatStrings( aWSStringsDtor,
                                *pTmpCurrencyEntry, bTmpBanking );
 
                for(const OUString & s : aWSStringsDtor)
                {
                    if (s == rFmtString)
                    {
                        bFlag=true;
                        break;
                    }
                }
            }
        }
    }
 
    return bFlag;
}
 
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.

V547 Expression 'pTmpCurrencyEntry != nullptr' is always true.

V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.