1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #ifndef INCLUDED_SVL_SOURCE_NUMBERS_ZFORSCAN_HXX
20 #define INCLUDED_SVL_SOURCE_NUMBERS_ZFORSCAN_HXX
21 
22 #include <i18nlangtag/lang.h>
23 #include <rtl/ustring.hxx>
24 #include <svl/nfkeytab.hxx>
25 #include <svl/nfsymbol.hxx>
26 #include <tools/color.hxx>
27 #include <tools/date.hxx>
28 
29 class SvNumberFormatter;
30 struct ImpSvNumberformatInfo;
31 
32 
33 const size_t NF_MAX_DEFAULT_COLORS   = 10;
34 
35 // Hack: nThousand==1000 => "Default" occurs in format string
36 const sal_uInt16 FLAG_STANDARD_IN_FORMAT = 1000;
37 
38 class ImpSvNumberformatScan
39 {
40 public:
41 
42     /** Specify what keyword localization is allowed when scanning the format code. */
43     enum class KeywordLocalization
44     {
45         LocaleLegacy,   ///< unfortunately localized in few locales, otherwise English
46         EnglishOnly,    ///< only English, no localized keywords
47         AllowEnglish    ///< allow English keywords as well as localized keywords
48     };
49 
50     explicit ImpSvNumberformatScan( SvNumberFormatter* pFormatter );
51     ~ImpSvNumberformatScan();
52     void ChangeIntl( KeywordLocalization eKeywordLocalization = KeywordLocalization::AllowEnglish ); // Replaces Keywords
53 
54     void ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear); // Replaces reference date
55     void ChangeStandardPrec(sal_uInt16 nPrec); // Replaces standard precision
56 
57     sal_Int32 ScanFormat( OUString& rString ); // Call scan analysis
58 
59     void CopyInfo(ImpSvNumberformatInfo* pInfo,
60                      sal_uInt16 nCnt); // Copies the FormatInfo
GetResultStringsCnt() const61     sal_uInt16 GetResultStringsCnt() const      { return nResultStringsCnt; }
62 
GetChrCls() const63     const CharClass& GetChrCls() const          { return *pFormatter->GetCharClass(); }
GetLoc() const64     const LocaleDataWrapper& GetLoc() const     { return *pFormatter->GetLocaleData(); }
GetCal() const65     CalendarWrapper& GetCal() const             { return *pFormatter->GetCalendar(); }
66 
GetKeywords() const67     const NfKeywordTable & GetKeywords() const
68         {
69             if ( bKeywordsNeedInit )
70             {
71                 InitKeywords();
72             }
73             return sKeyword;
74         }
75 
GetEnglishKeywords()76     static const NfKeywordTable & GetEnglishKeywords()
77         {
78             return sEnglishKeyword;
79         }
80 
81     // Keywords used in output like true and false
GetSpecialKeyword(NfKeywordIndex eIdx) const82     const OUString& GetSpecialKeyword( NfKeywordIndex eIdx ) const
83         {
84             if ( sKeyword[eIdx].isEmpty() )
85             {
86                 InitSpecialKeyword( eIdx );
87             }
88             return sKeyword[eIdx];
89         }
GetTrueString() const90     const OUString& GetTrueString() const     { return GetSpecialKeyword( NF_KEY_TRUE ); }
GetFalseString() const91     const OUString& GetFalseString() const    { return GetSpecialKeyword( NF_KEY_FALSE ); }
GetRedString() const92     const OUString& GetRedString() const      { return GetKeywords()[NF_KEY_RED]; }
GetBooleanString() const93     const OUString& GetBooleanString() const  { return GetKeywords()[NF_KEY_BOOLEAN]; }
GetErrorString()94     static const OUString& GetErrorString()   { return sErrStr; }
GetStandardColors()95     static const ::std::vector<Color> & GetStandardColors()
96         {
97             return StandardColor;
98         }
GetMaxDefaultColors()99     static size_t GetMaxDefaultColors()
100         {
101             return NF_MAX_DEFAULT_COLORS;
102         }
103 
GetNullDate() const104     const Date& GetNullDate() const           { return maNullDate; }
GetStandardName() const105     const OUString& GetStandardName() const
106         {
107             if ( bKeywordsNeedInit )
108             {
109                 InitKeywords();
110             }
111             return sNameStandardFormat;
112         }
GetStandardPrec() const113     sal_uInt16 GetStandardPrec() const          { return nStandardPrec; }
GetRedColor()114     static const Color& GetRedColor()           { return StandardColor[4]; }
115     Color* GetColor(OUString& sStr); // Set main colors or defines colors
116 
117     // the compatibility currency symbol for old automatic currency formats
GetCurSymbol() const118     const OUString& GetCurSymbol() const
119         {
120             if ( bCompatCurNeedInit )
121             {
122                 InitCompatCur();
123             }
124             return sCurSymbol;
125         }
126 
127     // the compatibility currency abbreviation for CCC format code
GetCurAbbrev() const128     const OUString& GetCurAbbrev() const
129         {
130             if ( bCompatCurNeedInit )
131             {
132                 InitCompatCur();
133             }
134             return sCurAbbrev;
135         }
136 
137     // the compatibility currency symbol upper case for old automatic currency formats
GetCurString() const138     const OUString& GetCurString() const
139         {
140             if ( bCompatCurNeedInit )
141             {
142                 InitCompatCur();
143             }
144             return sCurString;
145         }
146 
147     /// Replace Boolean equivalent format codes with proper Boolean format.
148     void ReplaceBooleanEquivalent( OUString& rString );
149 
SetConvertMode(LanguageType eTmpLge,LanguageType eNewLge,bool bSystemToSystem,bool bConvertDateOrder)150     void SetConvertMode(LanguageType eTmpLge, LanguageType eNewLge,
151             bool bSystemToSystem, bool bConvertDateOrder)
152     {
153         bConvertMode = true;
154         eNewLnge = eNewLge;
155         eTmpLnge = eTmpLge;
156         bConvertSystemToSystem = bSystemToSystem;
157         mbConvertDateOrder = bConvertDateOrder;
158     }
159     // Only changes the bool variable, in order to temporarily pause the convert mode
SetConvertMode(bool bMode)160     void SetConvertMode(bool bMode) { bConvertMode = bMode; }
GetConvertMode() const161     bool GetConvertMode() const     { return bConvertMode; }
GetNewLnge() const162     LanguageType GetNewLnge() const { return eNewLnge; } // Read access on ConvertMode and convert country/language
GetTmpLnge() const163     LanguageType GetTmpLnge() const { return eTmpLnge; } // Read access on StartCountry/Language
SetNewLnge(LanguageType e)164     void SetNewLnge( LanguageType e ) { eNewLnge = e; }  // Set new convert country/language
165 
166                                                 /// get Thai T speciality
GetNatNumModifier() const167     sal_uInt8 GetNatNumModifier() const      { return nNatNumModifier; }
168                                                 /// set Thai T speciality
SetNatNumModifier(sal_uInt8 n)169     void SetNatNumModifier( sal_uInt8 n )    { nNatNumModifier = n; }
170 
GetNumberformatter()171     SvNumberFormatter* GetNumberformatter() { return pFormatter; } // Access to formatter (for zformat.cxx)
172 
173     /// Get type scanned (so far).
GetScannedType() const174     SvNumFormatType GetScannedType() const { return eScannedType; }
175 
176 private: // Private section
177     NfKeywordTable sKeyword;                    // Syntax keywords
178     static const NfKeywordTable sEnglishKeyword; // English Syntax keywords
179     static ::std::vector<Color> StandardColor;  // Standard color array
180     static bool bStandardColorNeedInitialization; // initialize Standard color array
181     static ::std::vector<OUString> sGermanColorNames;   // German color names array
182     Date maNullDate;                            // 30Dec1899
183     OUString sNameStandardFormat;               // "Standard"
184     sal_uInt16 nStandardPrec;                   // Default Precision for Standardformat
185     SvNumberFormatter* pFormatter;              // Pointer to the FormatList
186     css::uno::Reference< css::i18n::XNumberFormatCode > xNFC;
187 
188     OUString sStrArray[NF_MAX_FORMAT_SYMBOLS];  // Array of symbols
189     short nTypeArray[NF_MAX_FORMAT_SYMBOLS];    // Array of infos
190                                                 // External Infos:
191     sal_uInt16 nResultStringsCnt;               // Result symbol count
192     SvNumFormatType eScannedType;               // Type according to scan
193     bool bThousand;                             // With thousands marker
194     sal_uInt16 nThousand;                       // Counts ... series
195     sal_uInt16 nCntPre;                         // Counts digits of integral part
196     sal_uInt16 nCntPost;                        // Counts digits of fractional part
197     sal_uInt16 nCntExp;                         // Counts exponent digits AM/PM
198                                                 // Internal info:
199     sal_uInt16 nStringsCnt;                     // Symbol count
200     sal_uInt16 nExpPos;                         // Internal position of E
201     sal_uInt16 nBlankPos;                       // Internal position of the Blank
202     short nDecPos;                              // Internal position of the ,
203     bool bExp;                                  // Set when reading E
204     bool bFrac;                                 // Set when reading /
205     bool bBlank;                                // Set when reading ' ' (Fraction)
206     bool bDecSep;                               // Set on first ,
207     mutable bool bKeywordsNeedInit;             // Locale dependent keywords need to be initialized
208     mutable bool bCompatCurNeedInit;            // Locale dependent compatibility currency need to be initialized
209     OUString sCurSymbol;                        // Currency symbol for compatibility format codes
210     OUString sCurString;                        // Currency symbol in upper case
211     OUString sCurAbbrev;                        // Currency abbreviation
212     OUString sBooleanEquivalent1;               // "TRUE";"TRUE";"FALSE"
213     OUString sBooleanEquivalent2;               // [>0]"TRUE";[<0]"TRUE";"FALSE"
214     static const OUString sErrStr;              // String for error output
215 
216     bool bConvertMode;                          // Set in the convert mode
217     bool mbConvertDateOrder;                    // Set in the convert mode whether to convert date particles order
218 
219     LanguageType eNewLnge;                      // Language/country which the scanned string is converted to (for Excel filter)
220     LanguageType eTmpLnge;                      // Language/country which the scanned string is converted from (for Excel filter)
221 
222     bool bConvertSystemToSystem;                // Whether the conversion is from one system locale to another system locale
223                                                 // (in this case the automatic currency symbol is converted too).
224 
225     sal_Int32 nCurrPos;                         // Position of currency symbol
226 
227     sal_uInt8 nNatNumModifier;                  // Thai T speciality
228 
229     KeywordLocalization meKeywordLocalization;  ///< which keywords localization to scan
230 
231     // Copy assignment is forbidden and not implemented.
232     ImpSvNumberformatScan (const ImpSvNumberformatScan &) = delete;
233     ImpSvNumberformatScan & operator= (const ImpSvNumberformatScan &) = delete;
234 
235     void InitKeywords() const;
236     void InitSpecialKeyword( NfKeywordIndex eIdx ) const;
237     void InitCompatCur() const;
238 
239     void SetDependentKeywords();
240                                                 // Sets the language dependent keywords
241     void SkipStrings(sal_uInt16& i, sal_Int32& nPos) const;// Skips StringSymbols
242     sal_uInt16 PreviousKeyword(sal_uInt16 i) const;  // Returns index of the preceding one
243                                                 // Keyword or 0
244     sal_uInt16 NextKeyword(sal_uInt16 i) const; // Returns index of the next one
245                                                 // Keyword or 0
246     sal_Unicode PreviousChar(sal_uInt16 i) const; // Returns last char before index skips EMPTY, STRING, STAR, BLANK
247     sal_Unicode NextChar(sal_uInt16 i) const;   // Returns first following char
248     short PreviousType( sal_uInt16 i ) const;   // Returns type before position skips EMPTY
249     bool IsLastBlankBeforeFrac(sal_uInt16 i) const; // True <=> there won't be a ' ' until the '/'
250     void Reset();                               // Reset all variables before starting the analysis
251 
252     /** Determine keyword at nPos.
253         @param  rbFoundEnglish set if English instead of locale's keyword
254                 found, never cleared, thus init with false.
255         @return 0 if not found, else keyword enumeration.
256      */
257     short GetKeyWord( const OUString& sSymbol,
258                       sal_Int32 nPos,
259                       bool& rbFoundEnglish ) const;
260 
IsAmbiguousE(short nKey) const261     bool IsAmbiguousE( short nKey ) const  // whether nKey is ambiguous E of NF_KEY_E/NF_KEY_EC
262         {
263             return (nKey == NF_KEY_EC || nKey == NF_KEY_E) &&
264                 (GetKeywords()[NF_KEY_EC] == GetKeywords()[NF_KEY_E]);
265         }
266 
267     // if 0 at strArray[i] is of S,00 or SS,00 or SS"any"00 in ScanType() or FinalScan()
268     bool Is100SecZero( sal_uInt16 i, bool bHadDecSep ) const;
269 
270     short Next_Symbol(const OUString& rStr,
271                       sal_Int32& nPos,
272                       OUString& sSymbol) const; // Next Symbol
273     sal_Int32 Symbol_Division(const OUString& rString);// Initial lexical scan
274     sal_Int32 ScanType(); // Analysis of the Format type
275     sal_Int32 FinalScan( OUString& rString ); // Final analysis with supplied type
276 
277     // -1:= error, return nPos in FinalScan; 0:= no calendar, 1:= calendar found
278     int FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i, sal_uInt16& nResultStringsCnt );
279 
280     /** Insert symbol into nTypeArray and sStrArray, e.g. grouping separator.
281         If at nPos-1 a symbol type NF_SYMBOLTYPE_EMPTY is present, that is
282         reused instead of shifting all one up and nPos is decremented! */
283     bool InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr );
284 
285     /** Whether two key symbols are adjacent separated by date separator.
286         This can only be used at the end of FinalScan() after
287         NF_SYMBOLTYPE_DATESEP has already been set.
288      */
289     bool IsDateFragment( size_t nPos1, size_t nPos2 ) const;
290 
291     /** Swap nTypeArray and sStrArray elements at positions. */
292     void SwapArrayElements( size_t nPos1, size_t nPos2 );
293 
StringEqualsChar(const OUString & rStr,sal_Unicode ch)294     static bool StringEqualsChar( const OUString& rStr, sal_Unicode ch )
295         { return rStr.getLength() == 1 && rStr[0] == ch; }
296 
297     // remove "..." and \... quotes from rStr, return how many chars removed
298     static sal_Int32 RemoveQuotes( OUString& rStr );
299 };
300 
301 #endif // INCLUDED_SVL_SOURCE_NUMBERS_ZFORSCAN_HXX
302 
303 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
304