779 lines
36 KiB
C++
779 lines
36 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
#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 SvNFLanguageData;
|
|
|
|
class ImpSvNumberformatScan; // format code string scanner
|
|
class ImpSvNumberInputScan; // input string scanner
|
|
class NativeNumberWrapper;
|
|
class SvNFFormatData;
|
|
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,
|
|
const NativeNumberWrapper& rNatNum,
|
|
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;
|
|
|
|
/**
|
|
* Get output string from a numeric value that fits the number of
|
|
* characters specified.
|
|
*/
|
|
bool GetOutputString( double fNumber, sal_uInt16 nCharCount, OUString& rOutString, const NativeNumberWrapper& rNatNum ) const;
|
|
|
|
// bStarFlag: Take *n format as ESC n
|
|
bool GetOutputString( double fNumber, OUString& OutString, const Color** ppColor, const NativeNumberWrapper& rNatNum, const SvNFLanguageData& rCurrentLang, bool bStarFlag = false) const;
|
|
void GetOutputString( std::u16string_view sString, OUString& OutString, const Color** ppColor, bool bStarFlag = false) const;
|
|
|
|
// 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; friend SvNFFormatData; 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 NativeNumberWrapper& rNatNum ) 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, CalendarWrapper& rCal ) 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, CalendarWrapper& rCal ) 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 bStandard; // If this is a default standard format
|
|
bool bIsUsed; // Flag as used for storing
|
|
|
|
SVL_DLLPRIVATE sal_uInt16 ImpGetNumForStringElementCount( sal_uInt16 nNumFor ) 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;
|
|
const SvNFLanguageData& GetCurrentLanguageData() 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 NativeNumberWrapper& rNatNum) const;
|
|
SVL_DLLPRIVATE void ImpGetOutputStandard(double& fNumber, OUStringBuffer& OutString,
|
|
const NativeNumberWrapper& rNatNum) const;
|
|
SVL_DLLPRIVATE void ImpGetOutputStdToPrecision(double& rNumber, OUString& rOutString, sal_uInt16 nPrecision,
|
|
const NativeNumberWrapper& rNatNum) 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(
|
|
const NativeNumberWrapper& rNatNum,
|
|
OUStringBuffer& sStr,
|
|
double& rNumber,
|
|
sal_Int32& k,
|
|
sal_uInt16& j,
|
|
sal_uInt16 nIx,
|
|
short eSymbolType,
|
|
bool bStarFlag,
|
|
bool bInsertRightBlank = false ) const;
|
|
|
|
// Helper function to fill in the integer part and the group (AKA thousand) separators
|
|
SVL_DLLPRIVATE bool ImpNumberFillWithThousands(
|
|
const NativeNumberWrapper& rNatNum,
|
|
OUStringBuffer& sStr,
|
|
double& rNumber,
|
|
sal_Int32 k,
|
|
sal_uInt16 j,
|
|
sal_uInt16 nIx,
|
|
sal_Int32 nDigCnt,
|
|
bool bStarFlag,
|
|
bool bAddDecSep = true ) const;
|
|
|
|
// 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 & ) const;
|
|
|
|
SVL_DLLPRIVATE bool ImpDecimalFill(const NativeNumberWrapper& rNatNum,
|
|
OUStringBuffer& sStr,
|
|
double& rNumber,
|
|
sal_Int32 nDecPos,
|
|
sal_uInt16 j,
|
|
sal_uInt16 nIx,
|
|
bool bInteger,
|
|
bool bStarFlag) const;
|
|
|
|
/** 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,
|
|
bool bStarFlag,
|
|
const NativeNumberWrapper& rNatNum,
|
|
OUStringBuffer& OutString) const;
|
|
SVL_DLLPRIVATE bool ImpGetScientificOutput(double fNumber,
|
|
sal_uInt16 nIx,
|
|
bool bStarFlag,
|
|
const NativeNumberWrapper& rNatNum,
|
|
OUStringBuffer& OutString) const;
|
|
|
|
SVL_DLLPRIVATE bool ImpGetDateOutput( double fNumber,
|
|
sal_uInt16 nIx,
|
|
bool bStarFlag,
|
|
const NativeNumberWrapper& rNatNum,
|
|
const SvNFLanguageData& rCurrentLang,
|
|
OUStringBuffer& OutString ) const;
|
|
SVL_DLLPRIVATE bool ImpGetTimeOutput( double fNumber,
|
|
sal_uInt16 nIx,
|
|
bool bStarFlag,
|
|
const NativeNumberWrapper& rNatNum,
|
|
const SvNFLanguageData& rCurrentLang,
|
|
OUStringBuffer& OutString ) const;
|
|
SVL_DLLPRIVATE bool ImpGetDateTimeOutput( double fNumber,
|
|
sal_uInt16 nIx,
|
|
bool bStarFlag,
|
|
const NativeNumberWrapper& rNatNum,
|
|
const SvNFLanguageData& rCurrentLang,
|
|
OUStringBuffer& OutString ) const;
|
|
|
|
// 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,
|
|
CalendarWrapper& rCal) const;
|
|
|
|
// 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,
|
|
const NativeNumberWrapper& rNatNum,
|
|
OUStringBuffer& OutString) const;
|
|
|
|
SVL_DLLPRIVATE bool ImpGetNumberOutput( double fNumber,
|
|
sal_uInt16 nIx,
|
|
bool bStarFlag,
|
|
const NativeNumberWrapper& rNatNum,
|
|
OUStringBuffer& OutString) const;
|
|
|
|
SVL_DLLPRIVATE void ImpCopyNumberformat( const SvNumberformat& rFormat );
|
|
|
|
// normal digits or other digits, depending on ImpSvNumFor.aNatNum,
|
|
// [NatNum1], [NatNum2], ...
|
|
SVL_DLLPRIVATE static OUString ImpGetNatNumString(const SvNumberNatNum& rNum, sal_Int64 nVal,
|
|
sal_uInt16 nMinDigits, const NativeNumberWrapper& rNatNum);
|
|
|
|
OUString ImpIntToString(const NativeNumberWrapper& rNatNum, 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, rNatNum );
|
|
}
|
|
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,
|
|
const NativeNumberWrapper& rNatNum) const;
|
|
|
|
// transliterate according to NativeNumber
|
|
SVL_DLLPRIVATE OUString impTransliterateImpl(const OUString& rStr, const SvNumberNatNum& rNum, sal_uInt16 nDateKey, const NativeNumberWrapper& rNatNum) const;
|
|
|
|
OUString impTransliterate(const OUString& rStr, const SvNumberNatNum& rNum, sal_uInt16 nDateKey, const NativeNumberWrapper& rNatNum) const
|
|
{
|
|
return rNum.IsComplete() ? impTransliterateImpl(rStr, rNum, nDateKey, rNatNum) : rStr;
|
|
}
|
|
|
|
};
|
|
|
|
#endif // INCLUDED_SVL_ZFORMAT_HXX
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|