summaryrefslogtreecommitdiffstats
path: root/svl/source/numbers/zforscan.hxx
blob: 4e6f7d1454ea10ee1da6a8d8402762177dd567c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/* -*- 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_SOURCE_NUMBERS_ZFORSCAN_HXX
#define INCLUDED_SVL_SOURCE_NUMBERS_ZFORSCAN_HXX

#include <i18nlangtag/lang.h>
#include <rtl/ustring.hxx>
#include <svl/nfkeytab.hxx>
#include <svl/nfsymbol.hxx>
#include <svl/numformat.hxx>
#include <svl/zforlist.hxx>
#include <tools/color.hxx>
#include <tools/date.hxx>
#include <unotools/localedatawrapper.hxx>

class SvNumberFormatter;
struct ImpSvNumberformatInfo;


const size_t NF_MAX_DEFAULT_COLORS   = 10;

// Hack: nThousand==1000 => "Default" occurs in format string
const sal_uInt16 FLAG_STANDARD_IN_FORMAT = 1000;

class ImpSvNumberformatScan
{
public:

    /** Specify what keyword localization is allowed when scanning the format code. */
    enum class KeywordLocalization
    {
        LocaleLegacy,   ///< unfortunately localized in few locales, otherwise English
        EnglishOnly,    ///< only English, no localized keywords
        AllowEnglish    ///< allow English keywords as well as localized keywords
    };

    explicit ImpSvNumberformatScan( SvNumberFormatter* pFormatter );
    ~ImpSvNumberformatScan();
    void ChangeIntl( KeywordLocalization eKeywordLocalization = KeywordLocalization::AllowEnglish ); // Replaces Keywords

    void ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear); // Replaces reference date
    void ChangeStandardPrec(sal_uInt16 nPrec); // Replaces standard precision

    sal_Int32 ScanFormat( OUString& rString ); // Call scan analysis

    void CopyInfo(ImpSvNumberformatInfo* pInfo,
                     sal_uInt16 nCnt); // Copies the FormatInfo
    sal_uInt16 GetResultStringsCnt() const      { return nResultStringsCnt; }

    const CharClass& GetChrCls() const          { return *pFormatter->GetCharClass(); }
    const LocaleDataWrapper& GetLoc() const     { return *pFormatter->GetLocaleData(); }
    CalendarWrapper& GetCal() const             { return *pFormatter->GetCalendar(); }

    const NfKeywordTable & GetKeywords() const
        {
            if ( bKeywordsNeedInit )
            {
                InitKeywords();
            }
            return sKeyword;
        }

    static const NfKeywordTable & GetEnglishKeywords()
        {
            return sEnglishKeyword;
        }

    // Keywords used in output like true and false
    const OUString& GetSpecialKeyword( NfKeywordIndex eIdx ) const
        {
            if ( sKeyword[eIdx].isEmpty() )
            {
                InitSpecialKeyword( eIdx );
            }
            return sKeyword[eIdx];
        }
    const OUString& GetTrueString() const     { return GetSpecialKeyword( NF_KEY_TRUE ); }
    const OUString& GetFalseString() const    { return GetSpecialKeyword( NF_KEY_FALSE ); }
    const OUString& GetRedString() const      { return GetKeywords()[NF_KEY_RED]; }
    const OUString& GetBooleanString() const  { return GetKeywords()[NF_KEY_BOOLEAN]; }
    static const ::std::vector<Color> & GetStandardColors()
        {
            return StandardColor;
        }
    static size_t GetMaxDefaultColors()
        {
            return NF_MAX_DEFAULT_COLORS;
        }

    const Date& GetNullDate() const           { return maNullDate; }
    const OUString& GetStandardName() const
        {
            if ( bKeywordsNeedInit )
            {
                InitKeywords();
            }
            return sNameStandardFormat;
        }
    sal_uInt16 GetStandardPrec() const          { return nStandardPrec; }
    static const Color& GetRedColor()           { return StandardColor[4]; }
    const Color* GetColor(OUString& sStr) const; // Set main colors or defines colors

    // the compatibility currency symbol for old automatic currency formats
    const OUString& GetCurSymbol() const
        {
            if ( bCompatCurNeedInit )
            {
                InitCompatCur();
            }
            return sCurSymbol;
        }

    // the compatibility currency abbreviation for CCC format code
    const OUString& GetCurAbbrev() const
        {
            if ( bCompatCurNeedInit )
            {
                InitCompatCur();
            }
            return sCurAbbrev;
        }

    // the compatibility currency symbol upper case for old automatic currency formats
    const OUString& GetCurString() const
        {
            if ( bCompatCurNeedInit )
            {
                InitCompatCur();
            }
            return sCurString;
        }

    /// Replace Boolean equivalent format codes with proper Boolean format.
    bool ReplaceBooleanEquivalent( OUString& rString );

    void SetConvertMode(LanguageType eTmpLge, LanguageType eNewLge,
            bool bSystemToSystem, bool bConvertDateOrder)
    {
        bConvertMode = true;
        eNewLnge = eNewLge;
        eTmpLnge = eTmpLge;
        bConvertSystemToSystem = bSystemToSystem;
        mbConvertDateOrder = bConvertDateOrder;
    }
    // Only changes the bool variable, in order to temporarily pause the convert mode
    void SetConvertMode(bool bMode) { bConvertMode = bMode; }
    bool GetConvertMode() const     { return bConvertMode; }
    LanguageType GetNewLnge() const { return eNewLnge; } // Read access on ConvertMode and convert country/language
    LanguageType GetTmpLnge() const { return eTmpLnge; } // Read access on StartCountry/Language
    void SetNewLnge( LanguageType e ) { eNewLnge = e; }  // Set new convert country/language

                                                /// get Thai T speciality
    sal_uInt8 GetNatNumModifier() const      { return nNatNumModifier; }
                                                /// set Thai T speciality
    void SetNatNumModifier( sal_uInt8 n )    { nNatNumModifier = n; }

    SvNumberFormatter* GetNumberformatter() { return pFormatter; } // Access to formatter (for zformat.cxx)

    /// Get type scanned (so far).
    SvNumFormatType GetScannedType() const { return eScannedType; }

    static constexpr OUStringLiteral sErrStr = u"#FMT"; // String for error output

private: // Private section
    NfKeywordTable sKeyword;                    // Syntax keywords
    static const NfKeywordTable sEnglishKeyword; // English Syntax keywords
    static const ::std::vector<Color> StandardColor;  // Standard color array
    Date maNullDate;                            // 30Dec1899
    OUString sNameStandardFormat;               // "Standard"
    sal_uInt16 nStandardPrec;                   // Default Precision for Standardformat
    SvNumberFormatter* pFormatter;              // Pointer to the FormatList
    css::uno::Reference< css::i18n::XNumberFormatCode > xNFC;

    OUString sStrArray[NF_MAX_FORMAT_SYMBOLS];  // Array of symbols
    short nTypeArray[NF_MAX_FORMAT_SYMBOLS];    // Array of infos
                                                // External Infos:
    sal_uInt16 nResultStringsCnt;               // Result symbol count
    SvNumFormatType eScannedType;               // Type according to scan
    bool bThousand;                             // With thousands marker
    sal_uInt16 nThousand;                       // Counts ... series
    sal_uInt16 nCntPre;                         // Counts digits of integral part
    sal_uInt16 nCntPost;                        // Counts digits of fractional part
    sal_uInt16 nCntExp;                         // Counts exponent digits AM/PM
                                                // Internal info:
    sal_uInt16 nStringsCnt;                     // Symbol count
    sal_uInt16 nExpPos;                         // Internal position of E
    sal_uInt16 nBlankPos;                       // Internal position of the Blank
    short nDecPos;                              // Internal position of the ,
    bool bExp;                                  // Set when reading E
    bool bFrac;                                 // Set when reading /
    bool bBlank;                                // Set when reading ' ' (Fraction)
    bool bDecSep;                               // Set on first ,
    mutable bool bKeywordsNeedInit;             // Locale dependent keywords need to be initialized
    mutable bool bCompatCurNeedInit;            // Locale dependent compatibility currency need to be initialized
    OUString sCurSymbol;                        // Currency symbol for compatibility format codes
    OUString sCurString;                        // Currency symbol in upper case
    OUString sCurAbbrev;                        // Currency abbreviation
    OUString sBooleanEquivalent1;               // "TRUE";"TRUE";"FALSE"
    OUString sBooleanEquivalent2;               // [>0]"TRUE";[<0]"TRUE";"FALSE"

    bool bConvertMode;                          // Set in the convert mode
    bool mbConvertDateOrder;                    // Set in the convert mode whether to convert date particles order

    LanguageType eNewLnge;                      // Language/country which the scanned string is converted to (for Excel filter)
    LanguageType eTmpLnge;                      // Language/country which the scanned string is converted from (for Excel filter)

    bool bConvertSystemToSystem;                // Whether the conversion is from one system locale to another system locale
                                                // (in this case the automatic currency symbol is converted too).

    sal_Int32 nCurrPos;                         // Position of currency symbol

    sal_uInt8 nNatNumModifier;                  // Thai T speciality

    KeywordLocalization meKeywordLocalization;  ///< which keywords localization to scan

    // Copy assignment is forbidden and not implemented.
    ImpSvNumberformatScan (const ImpSvNumberformatScan &) = delete;
    ImpSvNumberformatScan & operator= (const ImpSvNumberformatScan &) = delete;

    void InitKeywords() const;
    void InitSpecialKeyword( NfKeywordIndex eIdx ) const;
    void InitCompatCur() const;

    void SetDependentKeywords();
                                                // Sets the language dependent keywords
    void SkipStrings(sal_uInt16& i, sal_Int32& nPos) const;// Skips StringSymbols
    sal_uInt16 PreviousKeyword(sal_uInt16 i) const;  // Returns index of the preceding one
                                                // Keyword or 0
    sal_uInt16 NextKeyword(sal_uInt16 i) const; // Returns index of the next one
                                                // Keyword or 0
    sal_Unicode PreviousChar(sal_uInt16 i) const; // Returns last char before index skips EMPTY, STRING, STAR, BLANK
    sal_Unicode NextChar(sal_uInt16 i) const;   // Returns first following char
    short PreviousType( sal_uInt16 i ) const;   // Returns type before position skips EMPTY
    bool IsLastBlankBeforeFrac(sal_uInt16 i) const; // True <=> there won't be a ' ' until the '/'
    void Reset();                               // Reset all variables before starting the analysis

    /** Determine keyword at nPos.
        @param  rbFoundEnglish set if English instead of locale's keyword
                found, never cleared, thus init with false.
        @return 0 if not found, else keyword enumeration.
     */
    short GetKeyWord( const OUString& sSymbol,
                      sal_Int32 nPos,
                      bool& rbFoundEnglish ) const;

    bool IsAmbiguousE( short nKey ) const  // whether nKey is ambiguous E of NF_KEY_E/NF_KEY_EC
        {
            return (nKey == NF_KEY_EC || nKey == NF_KEY_E) &&
                (GetKeywords()[NF_KEY_EC] == GetKeywords()[NF_KEY_E]);
        }

    // if 0 at strArray[i] is of S,00 or SS,00 or SS"any"00 in ScanType() or FinalScan()
    bool Is100SecZero( sal_uInt16 i, bool bHadDecSep ) const;

    short Next_Symbol(const OUString& rStr,
                      sal_Int32& nPos,
                      OUString& sSymbol) const; // Next Symbol
    sal_Int32 Symbol_Division(const OUString& rString);// Initial lexical scan
    sal_Int32 ScanType(); // Analysis of the Format type
    sal_Int32 FinalScan( OUString& rString ); // Final analysis with supplied type

    // -1:= error, return nPos in FinalScan; 0:= no calendar, 1:= calendar found
    int FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i, sal_uInt16& nResultStringsCnt );

    /** Insert symbol into nTypeArray and sStrArray, e.g. grouping separator.
        If at nPos-1 a symbol type NF_SYMBOLTYPE_EMPTY is present, that is
        reused instead of shifting all one up and nPos is decremented! */
    bool InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr );

    /** Whether two key symbols are adjacent separated by date separator.
        This can only be used at the end of FinalScan() after
        NF_SYMBOLTYPE_DATESEP has already been set.
     */
    bool IsDateFragment( size_t nPos1, size_t nPos2 ) const;

    /** Swap nTypeArray and sStrArray elements at positions. */
    void SwapArrayElements( size_t nPos1, size_t nPos2 );

    static bool StringEqualsChar( const OUString& rStr, sal_Unicode ch )
        { return rStr.getLength() == 1 && rStr[0] == ch; }

    // remove "..." and \... quotes from rStr, return how many chars removed
    static sal_Int32 RemoveQuotes( OUString& rStr );
};

#endif // INCLUDED_SVL_SOURCE_NUMBERS_ZFORSCAN_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */