summaryrefslogtreecommitdiffstats
path: root/svx/source/items/numfmtsh.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/items/numfmtsh.cxx')
-rw-r--r--svx/source/items/numfmtsh.cxx1593
1 files changed, 1593 insertions, 0 deletions
diff --git a/svx/source/items/numfmtsh.cxx b/svx/source/items/numfmtsh.cxx
new file mode 100644
index 000000000..40811d846
--- /dev/null
+++ b/svx/source/items/numfmtsh.cxx
@@ -0,0 +1,1593 @@
+/* -*- 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 <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 <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);
+}
+
+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& 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);
+ if (nCurCategory != SvNumFormatType::CURRENCY)
+ 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 = pFormatter->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;
+
+ DBG_ASSERT(pCurFmtTable != nullptr, "unknown NumberFormat");
+
+ 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)
+ {
+ 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;
+
+ 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 (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;
+ 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);
+
+ 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();
+
+ 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*& 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,
+ 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())
+ {
+ 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);
+
+ SvxCurrencyToolBoxControl::GetCurrencySymbols(rList, bFlag, aCurCurrencyList);
+
+ 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: */