diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /include/svl/zformat.hxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/svl/zformat.hxx')
-rw-r--r-- | include/svl/zformat.hxx | 763 |
1 files changed, 763 insertions, 0 deletions
diff --git a/include/svl/zformat.hxx b/include/svl/zformat.hxx new file mode 100644 index 0000000000..1fa52c3384 --- /dev/null +++ b/include/svl/zformat.hxx @@ -0,0 +1,763 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_SVL_ZFORMAT_HXX +#define INCLUDED_SVL_ZFORMAT_HXX + +#include <svl/svldllapi.h> +#include <svl/zforlist.hxx> +#include <svl/nfkeytab.hxx> +#include <vector> + +namespace utl { + class DigitGroupingIterator; +} + +namespace com::sun::star::i18n { struct NativeNumberXmlAttributes2; } + +class Color; + +class ImpSvNumberformatScan; // format code string scanner +class ImpSvNumberInputScan; // input string scanner +class SvNumberFormatter; + +enum SvNumberformatLimitOps +{ + NUMBERFORMAT_OP_NO = 0, // Undefined, no OP + NUMBERFORMAT_OP_EQ = 1, // Operator = + NUMBERFORMAT_OP_NE = 2, // Operator <> + NUMBERFORMAT_OP_LT = 3, // Operator < + NUMBERFORMAT_OP_LE = 4, // Operator <= + NUMBERFORMAT_OP_GT = 5, // Operator > + NUMBERFORMAT_OP_GE = 6 // Operator >= +}; + +struct ImpSvNumberformatInfo // Struct for FormatInfo +{ + std::vector<OUString> sStrArray; // Array of symbols + std::vector<short> nTypeArray; // Array of infos + sal_uInt16 nThousand; // Count of group separator sequences + sal_uInt16 nCntPre; // Count of digits before decimal point + sal_uInt16 nCntPost; // Count of digits after decimal point + sal_uInt16 nCntExp; // Count of exponent digits, or AM/PM + SvNumFormatType eScannedType; // Type determined by scan + bool bThousand; // Has group (AKA thousand) separator + + void Copy( const ImpSvNumberformatInfo& rNumFor, sal_uInt16 nCount ); +}; + +// NativeNumber, represent numbers using CJK or other digits if nNum>0, +// eLang specifies the Locale to use. +class SvNumberNatNum +{ + OUString sParams; // For [NatNum12 ordinal-number]-like syntax + LanguageType eLang; + sal_uInt8 nNum; + bool bDBNum :1; // DBNum, to be converted to NatNum + bool bDate :1; // Used in date? (needed for DBNum/NatNum mapping) + bool bSet :1; // If set, since NatNum0 is possible + +public: + + static sal_uInt8 MapDBNumToNatNum( sal_uInt8 nDBNum, LanguageType eLang, bool bDate ); + static sal_uInt8 MapNatNumToDBNum( sal_uInt8 nNatNum, LanguageType eLang, bool bDate ); + + SvNumberNatNum() : eLang( LANGUAGE_DONTKNOW ), nNum(0), + bDBNum(false), bDate(false), bSet(false) {} + bool IsComplete() const { return bSet && eLang != LANGUAGE_DONTKNOW; } + sal_uInt8 GetNatNum() const { return bDBNum ? MapDBNumToNatNum( nNum, eLang, bDate ) : nNum; } + sal_uInt8 GetDBNum() const { return bDBNum ? nNum : MapNatNumToDBNum( nNum, eLang, bDate ); } + LanguageType GetLang() const { return eLang; } + void SetLang( LanguageType e ) { eLang = e; } + void SetNum( sal_uInt8 nNumber, bool bDBNumber ) + { + nNum = nNumber; + bDBNum = bDBNumber; + bSet = true; + } + bool IsSet() const { return bSet; } + void SetDate( bool bDateP ) { bDate = bDateP; } + void SetParams(const OUString& s) { sParams = s; } + OUString const & GetParams() const { return sParams; } +}; + +class CharClass; + +class ImpSvNumFor // One of four subformats of the format code string +{ +public: + ImpSvNumFor(); // Ctor without filling the Info + ~ImpSvNumFor(); + + void Enlarge(sal_uInt16 nCount); // Init of arrays to the right size + + // if pSc is set, it is used to get the Color pointer + void Copy( const ImpSvNumFor& rNumFor, const ImpSvNumberformatScan* pSc ); + + // Access to Info; call Enlarge before! + ImpSvNumberformatInfo& Info() { return aI;} + const ImpSvNumberformatInfo& Info() const { return aI; } + + // Get count of substrings (symbols) + sal_uInt16 GetCount() const { return nStringsCnt;} + + const Color* GetColor() const { return pColor; } + void SetColor(const Color* pCol, OUString const& rName) + { pColor = pCol; sColorName = rName; } + const OUString& GetColorName() const { return sColorName; } + + // new SYMBOLTYPE_CURRENCY in subformat? + bool HasNewCurrency() const; + bool GetNewCurrencySymbol( OUString& rSymbol, OUString& rExtension ) const; + + // [NatNum1], [NatNum2], ... + void SetNatNumNum( sal_uInt8 nNum, bool bDBNum ) { aNatNum.SetNum( nNum, bDBNum ); } + void SetNatNumLang( LanguageType eLang ) { aNatNum.SetLang( eLang ); } + void SetNatNumDate( bool bDate ) { aNatNum.SetDate( bDate ); } + void SetNatNumParams(const OUString& sParams) { aNatNum.SetParams(sParams); } + const SvNumberNatNum& GetNatNum() const { return aNatNum; } + +private: + ImpSvNumberformatInfo aI; // helper struct for remaining information + OUString sColorName; // color name + const Color* pColor; // pointer to color of subformat + sal_uInt16 nStringsCnt; // count of symbols + SvNumberNatNum aNatNum; // DoubleByteNumber + +}; + +class SVL_DLLPUBLIC SvNumberformat +{ + struct SAL_DLLPRIVATE LocaleType + { + enum class Substitute : sal_uInt8 + { + NONE, + TIME, + LONGDATE + }; + + LanguageType meLanguage; + LanguageType meLanguageWithoutLocaleData; + Substitute meSubstitute; + sal_uInt8 mnNumeralShape; + sal_uInt8 mnCalendarType; + + OUString generateCode() const; + + LocaleType(); + LocaleType(sal_uInt32 nRawCode); + + bool isPlainLocale() const; + }; + +public: + // Normal ctor + SvNumberformat( OUString& rString, + ImpSvNumberformatScan* pSc, + ImpSvNumberInputScan* pISc, + sal_Int32& nCheckPos, + LanguageType& eLan, + bool bReplaceBooleanEquivalent = true ); + + // Copy ctor + SvNumberformat( SvNumberformat const & rFormat ); + + // Copy ctor with exchange of format code string scanner (used in merge) + SvNumberformat( SvNumberformat const & rFormat, ImpSvNumberformatScan& rSc ); + + ~SvNumberformat(); + + /// Get type of format, may include css::util::NumberFormat::DEFINED bit + SvNumFormatType GetType() const { return eType; } + + /// Get type of format, does not include css::util::NumberFormat::DEFINED + SvNumFormatType GetMaskedType() const { return eType & ~SvNumFormatType::DEFINED; } + + void SetType(SvNumFormatType eSetType) { eType = eSetType; } + // Standard means the I18N defined standard format of this type + void SetStandard() { bStandard = true; } + bool IsStandard() const { return bStandard; } + + // If this format is an additional built-in format defined by i18n. + void SetAdditionalBuiltin() { bAdditionalBuiltin = true; } + bool IsAdditionalBuiltin() const { return bAdditionalBuiltin; } + + LanguageType GetLanguage() const { return maLocale.meLanguage;} + + /** If the format is a placeholder and needs to be substituted. */ + bool IsSubstituted() const + { + return maLocale.meSubstitute != LocaleType::Substitute::NONE; + } + + /** If the format is a placeholder for the system time format and needs to + be substituted during formatting time. + */ + bool IsSystemTimeFormat() const + { + return maLocale.meSubstitute == LocaleType::Substitute::TIME && maLocale.meLanguage == LANGUAGE_SYSTEM; + } + + /** If the format is a placeholder for the system long date format and needs + to be substituted during formatting time. + */ + bool IsSystemLongDateFormat() const + { + return maLocale.meSubstitute == LocaleType::Substitute::LONGDATE && maLocale.meLanguage == LANGUAGE_SYSTEM; + } + + /** If the format is a MM:SS or [MM]:SS format, or MM:[SS] (sic!) or even + MM:SS.00 or [MM]:SS.00 or MM:[SS].00 + */ + bool IsMinuteSecondFormat() const; + + const OUString& GetFormatstring() const { return sFormatstring; } + + // Build a format string of application defined keywords + OUString GetMappedFormatstring( const NfKeywordTable& rKeywords, + const LocaleDataWrapper& rLoc, + LanguageType nOriginalLang = LANGUAGE_DONTKNOW, + bool bSystemLanguage = false ) const; + + void SetStarFormatSupport( bool b ) { bStarFlag = b; } + + /** + * Get output string from a numeric value that fits the number of + * characters specified. + */ + bool GetOutputString( double fNumber, sal_uInt16 nCharCount, OUString& rOutString ) const; + + bool GetOutputString( double fNumber, OUString& OutString, const Color** ppColor ); + void GetOutputString( std::u16string_view sString, OUString& OutString, const Color** ppColor ); + + // True if type text + bool IsTextFormat() const { return bool(eType & SvNumFormatType::TEXT); } + // True if 4th subformat present + bool HasTextFormat() const + { + return (NumFor[3].GetCount() > 0) || + (NumFor[3].Info().eScannedType == SvNumFormatType::TEXT); + } + + void GetFormatSpecialInfo(bool& bThousand, + bool& IsRed, + sal_uInt16& nPrecision, + sal_uInt16& nLeadingCnt) const; + + /// Get index of subformat (0..3) according to conditions and fNumber value + sal_uInt16 GetSubformatIndex( double fNumber ) const; + + /// Count of decimal precision + sal_uInt16 GetFormatPrecision( sal_uInt16 nIx = 0 ) const + { return NumFor[nIx].Info().nCntPost; } + + /// Count of integer digits + sal_uInt16 GetFormatIntegerDigits( sal_uInt16 nIx = 0 ) const + { return NumFor[nIx].Info().nCntPre; } + + /** Count of hidden integer digits with thousands divisor: + formats like "0," to show only thousands. + + Works only with SvNumFormatType::NUMBER and SvNumFormatType::CURRENCY, + returns 0 otherwise. + + Returns SvNumberFormatter::UNLIMITED_PRECISION for formats that contain + the General keyword. + */ + sal_uInt16 GetThousandDivisorPrecision( sal_uInt16 nIx = 0 ) const; + + //! Read/write access on a special sal_uInt16 component, may only be used on the + //! standard format 0, 10000, ... and only by the number formatter! + struct FormatterPrivateAccess { friend SvNumberFormatter; private: FormatterPrivateAccess() {} }; + sal_uInt16 GetLastInsertKey( const FormatterPrivateAccess& ) const + { return NumFor[0].Info().nThousand; } + void SetLastInsertKey( sal_uInt16 nKey, const FormatterPrivateAccess& ) + { NumFor[0].Info().nThousand = nKey; } + + //! Only onLoad: convert from stored to current system language/country + void ConvertLanguage( SvNumberFormatter& rConverter, + LanguageType eConvertFrom, LanguageType eConvertTo ); + + // Substring of a subformat code nNumFor (0..3) + // nPos == 0xFFFF => last substring + // bString==true: first/last SYMBOLTYPE_STRING or SYMBOLTYPE_CURRENCY + const OUString* GetNumForString( sal_uInt16 nNumFor, sal_uInt16 nPos, + bool bString = false ) const; + + // Subtype of a subformat code nNumFor (0..3) + // nPos == 0xFFFF => last substring + short GetNumForType( sal_uInt16 nNumFor, sal_uInt16 nPos ) const; + + OUString GetPercentString( sal_uInt16 nNumFor = 0 ) const; + + OUString GetDenominatorString( sal_uInt16 nNumFor ) const; + OUString GetNumeratorString( sal_uInt16 nNumFor ) const; + OUString GetIntegerFractionDelimiterString( sal_uInt16 nNumFor ) const; + /// Round fNumber to its fraction representation + double GetRoundFractionValue ( double fNumber ) const; + + /// Create a format string for time with a new precision + OUString GetFormatStringForTimePrecision( int nPrecision ) const; + + + /** If the count of string elements (substrings, ignoring [modifiers] and + so on) in a subformat code nNumFor (0..3) is equal to the given number. + Used by ImpSvNumberInputScan::IsNumberFormatMain() to detect a matched + format. */ + bool IsNumForStringElementCountEqual( sal_uInt16 nNumFor, sal_uInt16 nAllCount, + sal_uInt16 nNumCount ) const + { + if ( nNumFor < 4 ) + { + // First try a simple approach. Note that this is called only + // if all MidStrings did match so far, to verify that all + // strings of the format were matched and not just the starting + // sequence, so we don't have to check if GetCount() includes + // [modifiers] or anything else if both counts are equal. + sal_uInt16 nCnt = NumFor[nNumFor].GetCount(); + if ( nAllCount == nCnt ) + return true; + if ( nAllCount < nCnt ) // check ignoring [modifiers] and so on + return ImpGetNumForStringElementCount( nNumFor ) == + (nAllCount - nNumCount); + } + return false; + } + /** Get the count of numbers among string elements **/ + sal_uInt16 GetNumForNumberElementCount( sal_uInt16 nNumFor ) const; + + /** Get the scanned type of the specified subformat. */ + SvNumFormatType GetNumForInfoScannedType( sal_uInt16 nNumFor ) const + { + return (nNumFor < 4) ? NumFor[nNumFor].Info().eScannedType : SvNumFormatType::UNDEFINED; + } + + // Whether the second subformat code is really for negative numbers + // or another limit set. + bool IsSecondSubformatRealNegative() const + { + return fLimit1 == 0.0 && fLimit2 == 0.0 && + ( (eOp1 == NUMBERFORMAT_OP_GE && eOp2 == NUMBERFORMAT_OP_NO) || + (eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_LT) || + (eOp1 == NUMBERFORMAT_OP_NO && eOp2 == NUMBERFORMAT_OP_NO) ); + } + + // Whether the first subformat code is really for negative numbers + // or another limit set. + bool IsFirstSubformatRealNegative() const + { + return fLimit1 == 0.0 && fLimit2 == 0.0 && + ((eOp1 == NUMBERFORMAT_OP_LT && + (eOp2 == NUMBERFORMAT_OP_GT || eOp2 == NUMBERFORMAT_OP_EQ || + eOp2 == NUMBERFORMAT_OP_GE || eOp2 == NUMBERFORMAT_OP_NO)) || + (eOp1 == NUMBERFORMAT_OP_LE && + (eOp2 == NUMBERFORMAT_OP_NO || eOp2 == NUMBERFORMAT_OP_GT))); + } + + // Whether the negative format is without a sign or not + bool IsNegativeWithoutSign() const; + + bool IsNegativeInBracket() const; + + bool HasPositiveBracketPlaceholder() const; + + // Whether a new SYMBOLTYPE_CURRENCY is contained in the format + bool HasNewCurrency() const; + + // strip [$-yyy] from all [$xxx-yyy] leaving only xxx's, + static OUString StripNewCurrencyDelimiters( const OUString& rStr ); + + // If a new SYMBOLTYPE_CURRENCY is contained if the format is of type + // css::util::NumberFormat::CURRENCY, and if so the symbol xxx and the extension nnn + // of [$xxx-nnn] are returned + bool GetNewCurrencySymbol( OUString& rSymbol, OUString& rExtension ) const; + + static bool HasStringNegativeSign( const OUString& rStr ); + + /** + Whether a character at position nPos is somewhere between two matching + cQuote or not. + If nPos points to a cQuote, a true is returned on an opening cQuote, + a false is returned on a closing cQuote. + A cQuote between quotes may be escaped by a cEscIn, a cQuote outside of + quotes may be escaped by a cEscOut. + The default '\0' results in no escapement possible. + Defaults are set right according to the "unlogic" of the Numberformatter + */ + static bool IsInQuote( const OUString& rString, sal_Int32 nPos, + sal_Unicode cQuote = '"', + sal_Unicode cEscIn = '\0', sal_Unicode cEscOut = '\\' ); + + /** + Return the position of a matching closing cQuote if the character at + position nPos is between two matching cQuote, otherwise return -1. + If nPos points to an opening cQuote the position of the matching + closing cQuote is returned. + If nPos points to a closing cQuote nPos is returned. + If nPos points into a part which starts with an opening cQuote but has + no closing cQuote, rString.Len() is returned. + Uses <method>IsInQuote</method> internally, so you don't have to call + that prior to a call of this method. + */ + static sal_Int32 GetQuoteEnd( const OUString& rString, sal_Int32 nPos, + sal_Unicode cQuote = '"', + sal_Unicode cEscIn = '\0' ); + + void SetComment( const OUString& rStr ) + { sComment = rStr; } + const OUString& GetComment() const { return sComment; } + + /** Insert the number of blanks into the string that is needed to simulate + the width of character c for underscore formats */ + static sal_Int32 InsertBlanks( OUString& r, sal_Int32 nPos, sal_Unicode c ) + { + sal_Int32 result; + OUStringBuffer sBuff(r); + + result = InsertBlanks(sBuff, nPos, c); + r = sBuff.makeStringAndClear(); + + return result; + } + + /** Insert the number of blanks into the string that is needed to simulate + the width of character c for underscore formats */ + static sal_Int32 InsertBlanks( OUStringBuffer& r, sal_Int32 nPos, sal_Unicode c ); + + /// One of YMD,DMY,MDY if date format + DateOrder GetDateOrder() const; + + /** A coded value of the exact YMD combination used, if date format. + For example: YYYY-MM-DD => ('Y' << 16) | ('M' << 8) | 'D' + or: MM/YY => ('M' << 8) | 'Y' */ + sal_uInt32 GetExactDateOrder() const; + + // used in XML export + void GetConditions( SvNumberformatLimitOps& rOper1, double& rVal1, + SvNumberformatLimitOps& rOper2, double& rVal2 ) const; + const Color* GetColor( sal_uInt16 nNumFor ) const; + void GetNumForInfo( sal_uInt16 nNumFor, SvNumFormatType& rScannedType, + bool& bThousand, sal_uInt16& nPrecision, sal_uInt16& nLeadingCnt ) const; + + // rAttr.Number not empty if NatNum attributes are to be stored + void GetNatNumXml( + css::i18n::NativeNumberXmlAttributes2& rAttr, + sal_uInt16 nNumFor ) const; + /** Return empty string if no NatNum modifier or invalid nNumFor + otherwise return "[NatNum1]" or "[NatNum12 ...]" */ + OUString GetNatNumModifierString( sal_uInt16 nNumFor = 0 ) const; + + /** Switches to the first non-"gregorian" calendar, but only if the current + calendar is "gregorian"; original calendar name and date/time returned, + but only if calendar switched and rOrgCalendar was empty. */ + void SwitchToOtherCalendar( OUString& rOrgCalendar, double& fOrgDateTime ) const; + + /** Switches to the "gregorian" calendar, but only if the current calendar + is non-"gregorian" and rOrgCalendar is not empty. Thus a preceding + ImpSwitchToOtherCalendar() call should have been placed prior to + calling this method. */ + void SwitchToGregorianCalendar( std::u16string_view rOrgCalendar, double fOrgDateTime ) const; + +#ifdef THE_FUTURE + /** Switches to the first specified calendar, if any, in subformat nNumFor + (0..3). Original calendar name and date/time returned, but only if + calendar switched and rOrgCalendar was empty. + + @return + <TRUE/> if a calendar was specified and switched to, + <FALSE/> else. + */ + bool SwitchToSpecifiedCalendar( OUString& rOrgCalendar, double& fOrgDateTime, + sal_uInt16 nNumFor ) const + { + if ( nNumFor < 4 ) + return ImpSwitchToSpecifiedCalendar( rOrgCalendar, + fOrgDateTime, NumFor[nNumFor] ); + return false; + } +#endif + + /// Whether it's a (YY)YY-M(M)-D(D) format. + bool IsIso8601( sal_uInt16 nNumFor ) const + { + if ( nNumFor < 4 ) + return ImpIsIso8601( NumFor[nNumFor]); + return false; + } + +private: + ImpSvNumFor NumFor[4]; // Array for the 4 subformats + OUString sFormatstring; // The format code string + OUString sComment; // Comment, since number formatter version 6 + double fLimit1; // Value for first condition + double fLimit2; // Value for second condition + ImpSvNumberformatScan& rScan; // Format code scanner + LocaleType maLocale; // Language/country of the format, numeral shape and calendar type from Excel. + SvNumberformatLimitOps eOp1; // Operator for first condition + SvNumberformatLimitOps eOp2; // Operator for second condition + SvNumFormatType eType; // Type of format + bool bAdditionalBuiltin; // If this is an additional built-in format defined by i18n + bool bStarFlag; // Take *n format as ESC n + bool bStandard; // If this is a default standard format + bool bIsUsed; // Flag as used for storing + + SVL_DLLPRIVATE sal_uInt16 ImpGetNumForStringElementCount( sal_uInt16 nNumFor ) const; + + SVL_DLLPRIVATE bool ImpIsOtherCalendar( const ImpSvNumFor& rNumFor ) const; + +#ifdef THE_FUTURE + SVL_DLLPRIVATE bool ImpSwitchToSpecifiedCalendar( OUString& rOrgCalendar, + double& fOrgDateTime, + const ImpSvNumFor& rNumFor ) const; +#endif + + /** Whether to use possessive genitive case month name, or partitive case + month name, instead of nominative name (noun). + + @param io_nState + 0: execute check <br> + set to 1 if nominative case is returned, <br> + set to 2 if genitive case is returned, <br> + set to 3 if partitive case is returned <br> + 1: don't execute check, return nominative case <br> + 2: don't execute check, return genitive case <br> + 3: don't execute check, return partitive case <br> + + @param eCodeType + a NfKeywordIndex, must designate a month type code + + @returns one of css::i18n::CalendarDisplayCode values + according to eCodeType and the check executed (or passed). + */ + SVL_DLLPRIVATE static sal_Int32 ImpUseMonthCase( int & io_nState, const ImpSvNumFor& rNumFor, NfKeywordIndex eCodeType ); + + /// Whether it's a (YY)YY-M(M)-D(D) format. + SVL_DLLPRIVATE bool ImpIsIso8601( const ImpSvNumFor& rNumFor ) const; + + const CharClass& rChrCls() const; + const LocaleDataWrapper& rLoc() const; + CalendarWrapper& GetCal() const; + const SvNumberFormatter& GetFormatter() const; + + // divide in substrings and color conditions + SVL_DLLPRIVATE short ImpNextSymbol( OUStringBuffer& rString, + sal_Int32& nPos, + OUString& sSymbol ) const; + + // read string until ']' and strip blanks (after condition) + SVL_DLLPRIVATE static sal_Int32 ImpGetNumber( OUStringBuffer& rString, + sal_Int32& nPos, + OUString& sSymbol ); + + /** + * Parse the content of '[$-xxx] or '[$-xxxxxxxx]' and extract the locale + * type from it. Given the string, start parsing at position specified by + * nPos, and store the end position with nPos when the parsing is + * complete. The nPos should point to the '$' before the parsing, and to + * the closing bracket after the parsing. When the content is [$-xxx], + * the xxx part represents the language type (aka LCID) in hex numerals. + * When the content is [$-xxxxxxxx] the last 4 digits represent the LCID + * (again in hex), the next 2 digits represent the calendar type, and the + * 2 highest digits (if exists) is the numeral shape. + * + * @reference + * http://office.microsoft.com/en-us/excel-help/creating-international-number-formats-HA001034635.aspx + * + * @param rString input string + * @param nPos position (see above). + * + * @return struct containing numeral shape, calendar type, and LCID that + * specifies language type. See i18nlangtag/lang.h for a complete + * list of language types. These numbers also correspond with the + * numbers used by Microsoft Office. + */ + SVL_DLLPRIVATE static LocaleType ImpGetLocaleType( std::u16string_view rString, sal_Int32& nPos ); + + /** Obtain calendar and numerals from a LocaleType that was parsed from a + LCID with ImpGetLocaleType(). + + Inserts a NatNum modifier to rString at nPos if needed as determined + from the numeral code. + + @ATTENTION: may modify <member>maLocale</member> to make it follow + aTmpLocale, in which case also nLang is adapted. + + @returns a string with the calendar if one was determined from the + calendar code, else an empty string. The calendar string needs to be + inserted at a proper position to rString after all bracketed prefixes. + */ + SVL_DLLPRIVATE OUString ImpObtainCalendarAndNumerals( OUStringBuffer & rString, + sal_Int32 nPos, + LanguageType & nLang, + const LocaleType & aTmpLocale ); + + // standard number output + SVL_DLLPRIVATE void ImpGetOutputStandard( double& fNumber, OUString& OutString ) const; + SVL_DLLPRIVATE void ImpGetOutputStandard( double& fNumber, OUStringBuffer& OutString ) const; + SVL_DLLPRIVATE void ImpGetOutputStdToPrecision( double& rNumber, OUString& rOutString, sal_uInt16 nPrecision ) const; + // numbers in input line + SVL_DLLPRIVATE void ImpGetOutputInputLine( double fNumber, OUString& OutString ) const; + + // check subcondition + // OP undefined => -1 + // else 0 or 1 + SVL_DLLPRIVATE static short ImpCheckCondition(double fNumber, + double fLimit, + SvNumberformatLimitOps eOp); + + // Helper function for number strings + // append string symbols, insert leading 0 or ' ', or ... + SVL_DLLPRIVATE bool ImpNumberFill( OUStringBuffer& sStr, + double& rNumber, + sal_Int32& k, + sal_uInt16& j, + sal_uInt16 nIx, + short eSymbolType, + bool bInsertRightBlank = false ); + + // Helper function to fill in the integer part and the group (AKA thousand) separators + SVL_DLLPRIVATE bool ImpNumberFillWithThousands( OUStringBuffer& sStr, + double& rNumber, + sal_Int32 k, + sal_uInt16 j, + sal_uInt16 nIx, + sal_Int32 nDigCnt, + bool bAddDecSep = true ); + + // Helper function to fill in the group (AKA thousand) separators + // or to skip additional digits + SVL_DLLPRIVATE void ImpDigitFill( OUStringBuffer& sStr, + sal_Int32 nStart, + sal_Int32& k, + sal_uInt16 nIx, + sal_Int32 & nDigitCount, + utl::DigitGroupingIterator & ); + + SVL_DLLPRIVATE bool ImpDecimalFill( OUStringBuffer& sStr, + double& rNumber, + sal_Int32 nDecPos, + sal_uInt16 j, + sal_uInt16 nIx, + bool bInteger ); + + /** Calculate each element of fraction: + * integer part, numerator part, denominator part + * @param fNumber value to be represented as fraction. Will contain absolute fractional part + * @param nIx subformat number 0..3 + * @param fIntPart integral part of fraction + * @param nFrac numerator of fraction + * @param nDic denominator of fraction + */ + SVL_DLLPRIVATE void ImpGetFractionElements( double& fNumber, + sal_uInt16 nIx, + double& fIntPart, + sal_Int64& nFrac, + sal_Int64& nDiv ) const; + SVL_DLLPRIVATE bool ImpGetFractionOutput(double fNumber, + sal_uInt16 nIx, + OUStringBuffer& OutString); + SVL_DLLPRIVATE bool ImpGetScientificOutput(double fNumber, + sal_uInt16 nIx, + OUStringBuffer& OutString); + + SVL_DLLPRIVATE bool ImpGetDateOutput( double fNumber, + sal_uInt16 nIx, + OUStringBuffer& OutString ); + SVL_DLLPRIVATE bool ImpGetTimeOutput( double fNumber, + sal_uInt16 nIx, + OUStringBuffer& OutString ); + SVL_DLLPRIVATE bool ImpGetDateTimeOutput( double fNumber, + sal_uInt16 nIx, + OUStringBuffer& OutString ); + + // Switches to the "gregorian" calendar if the current calendar is + // non-"gregorian" and the era is a "Dummy" era of a calendar which doesn't + // know a "before" era (like zh_TW ROC or ja_JP Gengou). If switched and + // rOrgCalendar was "gregorian" the string is emptied. If rOrgCalendar was + // empty the previous calendar name and date/time are returned. + SVL_DLLPRIVATE bool ImpFallBackToGregorianCalendar( OUString& rOrgCalendar, double& fOrgDateTime ); + + // Append a "G" short era string of the given calendar. In the case of a + // Gengou calendar this is a one character abbreviation, for other + // calendars the XExtendedCalendar::getDisplayString() method is called. + SVL_DLLPRIVATE static void ImpAppendEraG( OUStringBuffer& OutStringBuffer, const CalendarWrapper& rCal, + sal_Int16 nNatNum ); + + SVL_DLLPRIVATE bool ImpGetLogicalOutput( double fNumber, + sal_uInt16 nIx, + OUStringBuffer& OutString ); + + SVL_DLLPRIVATE bool ImpGetNumberOutput( double fNumber, + sal_uInt16 nIx, + OUStringBuffer& OutString ); + + SVL_DLLPRIVATE void ImpCopyNumberformat( const SvNumberformat& rFormat ); + + // normal digits or other digits, depending on ImpSvNumFor.aNatNum, + // [NatNum1], [NatNum2], ... + SVL_DLLPRIVATE OUString ImpGetNatNumString( const SvNumberNatNum& rNum, sal_Int64 nVal, + sal_uInt16 nMinDigits ) const; + + OUString ImpIntToString( sal_uInt16 nIx, sal_Int64 nVal, sal_uInt16 nMinDigits = 0 ) const + { + const SvNumberNatNum& rNum = NumFor[nIx].GetNatNum(); + if ( nMinDigits || rNum.IsComplete() ) + { + return ImpGetNatNumString( rNum, nVal, nMinDigits ); + } + return OUString::number(nVal); + } + + // Obtain the string of the fraction of second, without leading "0.", + // rounded to nFractionDecimals (or nFractionDecimals+1 if + // bAddOneRoundingDecimal==true but then truncated at nFractionDecimals, + // for use with the result of tools::Time::GetClock()) with the length of + // nFractionDecimals, unless nMinimumInputLineDecimals>0 is given for input + // line string where extra trailing "0" are discarded. + SVL_DLLPRIVATE sal_uInt16 ImpGetFractionOfSecondString( OUStringBuffer& rBuf, double fFractionOfSecond, + int nFractionDecimals, bool bAddOneRoundingDecimal, sal_uInt16 nIx, sal_uInt16 nMinimumInputLineDecimals ); + + // transliterate according to NativeNumber + SVL_DLLPRIVATE OUString impTransliterateImpl(const OUString& rStr, const SvNumberNatNum& rNum) const; + SVL_DLLPRIVATE void impTransliterateImpl(OUStringBuffer& rStr, const SvNumberNatNum& rNum) const; + SVL_DLLPRIVATE OUString impTransliterateImpl(const OUString& rStr, const SvNumberNatNum& rNum, sal_uInt16 nDateKey) const; + + OUString impTransliterate(const OUString& rStr, const SvNumberNatNum& rNum) const + { + return rNum.IsComplete() ? impTransliterateImpl(rStr, rNum) : rStr; + } + + SVL_DLLPRIVATE void impTransliterate(OUStringBuffer& rStr, const SvNumberNatNum& rNum) const + { + if(rNum.IsComplete()) + { + impTransliterateImpl(rStr, rNum); + } + } + + OUString impTransliterate(const OUString& rStr, const SvNumberNatNum& rNum, sal_uInt16 nDateKey) const + { + return rNum.IsComplete() ? impTransliterateImpl(rStr, rNum, nDateKey) : rStr; + } + +}; + +#endif // INCLUDED_SVL_ZFORMAT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |