Line data Source code
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_ZFORMAT_HXX
20 : #define INCLUDED_SVL_ZFORMAT_HXX
21 :
22 : #include <svl/svldllapi.h>
23 : #include <i18nlangtag/mslangid.hxx>
24 : #include <svl/zforlist.hxx>
25 : #include <svl/nfkeytab.hxx>
26 :
27 : namespace utl {
28 : class DigitGroupingIterator;
29 : }
30 :
31 : class Color;
32 :
33 : class ImpSvNumberformatScan; // format code string scanner
34 : class ImpSvNumberInputScan; // input string scanner
35 : class SvNumberFormatter;
36 :
37 : enum SvNumberformatLimitOps
38 : {
39 : NUMBERFORMAT_OP_NO = 0, // Undefined, no OP
40 : NUMBERFORMAT_OP_EQ = 1, // Operator =
41 : NUMBERFORMAT_OP_NE = 2, // Operator <>
42 : NUMBERFORMAT_OP_LT = 3, // Operator <
43 : NUMBERFORMAT_OP_LE = 4, // Operator <=
44 : NUMBERFORMAT_OP_GT = 5, // Operator >
45 : NUMBERFORMAT_OP_GE = 6 // Operator >=
46 : };
47 :
48 : // SYSTEM-german to SYSTEM-xxx and vice versa conversion hack onLoad
49 : enum NfHackConversion
50 : {
51 : NF_CONVERT_NONE,
52 : NF_CONVERT_GERMAN_ENGLISH,
53 : NF_CONVERT_ENGLISH_GERMAN
54 : };
55 :
56 : struct ImpSvNumberformatInfo // Struct for FormatInfo
57 : {
58 : OUString* sStrArray; // Array of symbols
59 : short* nTypeArray; // Array of infos
60 : sal_uInt16 nThousand; // Count of group separator sequences
61 : sal_uInt16 nCntPre; // Count of digits before decimal point
62 : sal_uInt16 nCntPost; // Count of digits after decimal point
63 : sal_uInt16 nCntExp; // Count of exponent digits, or AM/PM
64 : short eScannedType; // Type determined by scan
65 : bool bThousand; // Has group (AKA thousand) separator
66 :
67 : void Copy( const ImpSvNumberformatInfo& rNumFor, sal_uInt16 nAnz );
68 : };
69 :
70 : // NativeNumber, represent numbers using CJK or other digits if nNum>0,
71 : // eLang specifies the Locale to use.
72 : class SvNumberNatNum
73 : {
74 : LanguageType eLang;
75 : sal_uInt8 nNum;
76 : bool bDBNum :1; // DBNum, to be converted to NatNum
77 : bool bDate :1; // Used in date? (needed for DBNum/NatNum mapping)
78 : bool bSet :1; // If set, since NatNum0 is possible
79 :
80 : public:
81 :
82 : static sal_uInt8 MapDBNumToNatNum( sal_uInt8 nDBNum, LanguageType eLang, bool bDate );
83 : #ifdef THE_FUTURE
84 : static sal_uInt8 MapNatNumToDBNum( sal_uInt8 nNatNum, LanguageType eLang, bool bDate );
85 : #endif
86 :
87 1465676 : SvNumberNatNum() : eLang( LANGUAGE_DONTKNOW ), nNum(0),
88 1465676 : bDBNum(false), bDate(false), bSet(false) {}
89 64422 : bool IsComplete() const { return bSet && eLang != LANGUAGE_DONTKNOW; }
90 : sal_uInt8 GetRawNum() const { return nNum; }
91 436773 : sal_uInt8 GetNatNum() const { return bDBNum ? MapDBNumToNatNum( nNum, eLang, bDate ) : nNum; }
92 : #ifdef THE_FUTURE
93 : sal_uInt8 GetDBNum() const { return bDBNum ? nNum : MapNatNumToDBNum( nNum, eLang, bDate ); }
94 : #endif
95 213 : LanguageType GetLang() const { return eLang; }
96 117 : void SetLang( LanguageType e ) { eLang = e; }
97 105 : void SetNum( sal_uInt8 nNumber, bool bDBNumber )
98 : {
99 105 : nNum = nNumber;
100 105 : bDBNum = bDBNumber;
101 105 : bSet = true;
102 105 : }
103 871560 : bool IsSet() const { return bSet; }
104 105 : void SetDate( bool bDateP ) { bDate = bDateP; }
105 : };
106 :
107 : class CharClass;
108 :
109 : class ImpSvNumFor // One of four subformats of the format code string
110 : {
111 : public:
112 : ImpSvNumFor(); // Ctor without filling the Info
113 : ~ImpSvNumFor();
114 :
115 : void Enlarge(sal_uInt16 nAnz); // Init of arrays to the right size
116 :
117 : // if pSc is set, it is used to get the Color pointer
118 : void Copy( const ImpSvNumFor& rNumFor, ImpSvNumberformatScan* pSc );
119 :
120 : // Access to Info; call Enlarge before!
121 912195 : ImpSvNumberformatInfo& Info() { return aI;}
122 61948 : const ImpSvNumberformatInfo& Info() const { return aI; }
123 :
124 : // Get count of substrings (symbols)
125 444249 : sal_uInt16 GetCount() const { return nAnzStrings;}
126 :
127 38830 : Color* GetColor() const { return pColor; }
128 30667 : void SetColor( Color* pCol, OUString& rName )
129 30667 : { pColor = pCol; sColorName = rName; }
130 504 : const OUString& GetColorName() const { return sColorName; }
131 :
132 : // new SYMBOLTYPE_CURRENCY in subformat?
133 : bool HasNewCurrency() const;
134 : bool GetNewCurrencySymbol( OUString& rSymbol, OUString& rExtension ) const;
135 :
136 : // [NatNum1], [NatNum2], ...
137 105 : void SetNatNumNum( sal_uInt8 nNum, bool bDBNum ) { aNatNum.SetNum( nNum, bDBNum ); }
138 117 : void SetNatNumLang( LanguageType eLang ) { aNatNum.SetLang( eLang ); }
139 105 : void SetNatNumDate( bool bDate ) { aNatNum.SetDate( bDate ); }
140 1372966 : const SvNumberNatNum& GetNatNum() const { return aNatNum; }
141 :
142 : private:
143 : ImpSvNumberformatInfo aI; // helper struct for remaining information
144 : OUString sColorName; // color name
145 : Color* pColor; // pointer to color of subformat
146 : sal_uInt16 nAnzStrings; // count of symbols
147 : SvNumberNatNum aNatNum; // DoubleByteNumber
148 :
149 : };
150 :
151 : class SVL_DLLPUBLIC SvNumberformat
152 : {
153 : struct LocaleType
154 : {
155 : sal_uInt8 mnNumeralShape;
156 : sal_uInt8 mnCalendarType;
157 : LanguageType meLanguage;
158 :
159 : OUString generateCode() const;
160 :
161 : LocaleType();
162 : LocaleType(sal_uInt32 nRawCode);
163 : };
164 :
165 : public:
166 : // Normal ctor
167 : SvNumberformat( OUString& rString,
168 : ImpSvNumberformatScan* pSc,
169 : ImpSvNumberInputScan* pISc,
170 : sal_Int32& nCheckPos,
171 : LanguageType& eLan,
172 : bool bStand = false );
173 :
174 : // Copy ctor
175 : SvNumberformat( SvNumberformat& rFormat );
176 :
177 : // Copy ctor with exchange of format code string scanner (used in merge)
178 : SvNumberformat( SvNumberformat& rFormat, ImpSvNumberformatScan& rSc );
179 :
180 : ~SvNumberformat();
181 :
182 : /// Get type of format, may include css::util::NumberFormat::DEFINED bit
183 286185 : short GetType() const { return eType; }
184 :
185 30813 : void SetType(const short eSetType) { eType = eSetType; }
186 : // Standard means the I18N defined standard format of this type
187 43317 : void SetStandard() { bStandard = true; }
188 4844 : bool IsStandard() const { return bStandard; }
189 :
190 : // If this format is an additional built-in format defined by i18n.
191 94765 : void SetAdditionalBuiltin() { bAdditionalBuiltin = true; }
192 0 : bool IsAdditionalBuiltin() const { return bAdditionalBuiltin; }
193 :
194 8003674 : LanguageType GetLanguage() const { return maLocale.meLanguage;}
195 :
196 7624903 : const OUString& GetFormatstring() const { return sFormatstring; }
197 :
198 : // Build a format string of application defined keywords
199 : OUString GetMappedFormatstring( const NfKeywordTable& rKeywords,
200 : const LocaleDataWrapper& rLoc,
201 : bool bDontQuote = false ) const;
202 :
203 : void SetUsed(const bool b) { bIsUsed = b; }
204 : bool GetUsed() const { return bIsUsed; }
205 : bool IsStarFormatSupported() const { return bStarFlag; }
206 22116 : void SetStarFormatSupport( bool b ) { bStarFlag = b; }
207 :
208 : /**
209 : * Get output string from a numeric value that fits the number of
210 : * characters specified.
211 : */
212 : bool GetOutputString( double fNumber, sal_uInt16 nCharCount, OUString& rOutString ) const;
213 :
214 : bool GetOutputString( double fNumber, OUString& OutString, Color** ppColor );
215 : bool GetOutputString( const OUString& sString, OUString& OutString, Color** ppColor );
216 :
217 : // True if type text
218 27241 : bool IsTextFormat() const { return (eType & css::util::NumberFormat::TEXT) != 0; }
219 : // True if 4th subformat present
220 26014 : bool HasTextFormat() const
221 : {
222 51998 : return (NumFor[3].GetCount() > 0) ||
223 51998 : (NumFor[3].Info().eScannedType == css::util::NumberFormat::TEXT);
224 : }
225 :
226 : void GetFormatSpecialInfo(bool& bThousand,
227 : bool& IsRed,
228 : sal_uInt16& nPrecision,
229 : sal_uInt16& nAnzLeading) const;
230 :
231 : /// Count of decimal precision
232 2 : sal_uInt16 GetFormatPrecision() const { return NumFor[0].Info().nCntPost; }
233 :
234 : /// Count of integer digits
235 0 : sal_uInt16 GetFormatIntegerDigits() const { return NumFor[0].Info().nCntPre; }
236 :
237 : //! Read/write access on a special sal_uInt16 component, may only be used on the
238 : //! standard format 0, 5000, ... and only by the number formatter!
239 12186 : sal_uInt16 GetLastInsertKey() const
240 12186 : { return NumFor[0].Info().nThousand; }
241 16999 : void SetLastInsertKey(sal_uInt16 nKey)
242 16999 : { NumFor[0].Info().nThousand = nKey; }
243 :
244 : //! Only onLoad: convert from stored to current system language/country
245 : void ConvertLanguage( SvNumberFormatter& rConverter,
246 : LanguageType eConvertFrom, LanguageType eConvertTo, bool bSystem = false );
247 :
248 : // Substring of a subformat code nNumFor (0..3)
249 : // nPos == 0xFFFF => last substring
250 : // bString==true: first/last SYMBOLTYPE_STRING or SYMBOLTYPE_CURRENCY
251 : const OUString* GetNumForString( sal_uInt16 nNumFor, sal_uInt16 nPos,
252 : bool bString = false ) const;
253 :
254 : // Subtype of a subformat code nNumFor (0..3)
255 : // nPos == 0xFFFF => last substring
256 : // bString==true: first/last SYMBOLTYPE_STRING or SYMBOLTYPE_CURRENCY
257 : short GetNumForType( sal_uInt16 nNumFor, sal_uInt16 nPos, bool bString = false ) const;
258 :
259 : sal_Int32 GetForcedDenominatorForType( sal_uInt16 nNumFor ) const;
260 : /** If the count of string elements (substrings, ignoring [modifiers] and
261 : so on) in a subformat code nNumFor (0..3) is equal to the given number.
262 : Used by ImpSvNumberInputScan::IsNumberFormatMain() to detect a matched
263 : format. */
264 3 : bool IsNumForStringElementCountEqual( sal_uInt16 nNumFor, sal_uInt16 nAllCount,
265 : sal_uInt16 nNumCount ) const
266 : {
267 3 : if ( nNumFor < 4 )
268 : {
269 : // First try a simple approach. Note that this is called only
270 : // if all MidStrings did match so far, to verify that all
271 : // strings of the format were matched and not just the starting
272 : // sequence, so we don't have to check if GetnAnz() includes
273 : // [modifiers] or anything else if both counts are equal.
274 3 : sal_uInt16 nCnt = NumFor[nNumFor].GetCount();
275 3 : if ( nAllCount == nCnt )
276 3 : return true;
277 0 : if ( nAllCount < nCnt ) // check ignoring [modifiers] and so on
278 0 : return ImpGetNumForStringElementCount( nNumFor ) ==
279 0 : (nAllCount - nNumCount);
280 : }
281 0 : return false;
282 : }
283 :
284 : // Whether the second subformat code is really for negative numbers
285 : // or another limit set.
286 95 : bool IsSecondSubformatRealNegative() const
287 : {
288 285 : return fLimit1 == 0.0 && fLimit2 == 0.0 &&
289 190 : ( (eOp1 == NUMBERFORMAT_OP_GE && eOp2 == NUMBERFORMAT_OP_NO) ||
290 176 : (eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_LT) ||
291 271 : (eOp1 == NUMBERFORMAT_OP_NO && eOp2 == NUMBERFORMAT_OP_NO) );
292 : }
293 :
294 : // Whether the first subformat code is really for negative numbers
295 : // or another limit set.
296 986 : bool IsFirstSubformatRealNegative() const
297 : {
298 1972 : return fLimit1 == 0.0 && fLimit2 == 0.0 &&
299 986 : ((eOp1 == NUMBERFORMAT_OP_LT &&
300 0 : (eOp2 == NUMBERFORMAT_OP_GT || eOp2 == NUMBERFORMAT_OP_EQ ||
301 986 : eOp2 == NUMBERFORMAT_OP_GE || eOp2 == NUMBERFORMAT_OP_NO)) ||
302 986 : (eOp1 == NUMBERFORMAT_OP_LE &&
303 986 : (eOp2 == NUMBERFORMAT_OP_NO || eOp2 == NUMBERFORMAT_OP_GT)));
304 : }
305 :
306 : // Whether the negative format is without a sign or not
307 : bool IsNegativeWithoutSign() const;
308 :
309 : bool IsNegativeInBracket() const;
310 :
311 : bool HasPositiveBracketPlaceholder() const;
312 :
313 : // Whether a new SYMBOLTYPE_CURRENCY is contained in the format
314 : bool HasNewCurrency() const;
315 :
316 : // strip [$-yyy] from all [$xxx-yyy] leaving only xxx's,
317 : // if bQuoteSymbol==true the xxx will become "xxx"
318 : static OUString StripNewCurrencyDelimiters( const OUString& rStr,
319 : bool bQuoteSymbol );
320 :
321 : // If a new SYMBOLTYPE_CURRENCY is contained if the format is of type
322 : // css::util::NumberFormat::CURRENCY, and if so the symbol xxx and the extension nnn
323 : // of [$xxx-nnn] are returned
324 : bool GetNewCurrencySymbol( OUString& rSymbol, OUString& rExtension ) const;
325 :
326 : static bool HasStringNegativeSign( const OUString& rStr );
327 :
328 : /**
329 : Whether a character at position nPos is somewhere between two matching
330 : cQuote or not.
331 : If nPos points to a cQuote, a true is returned on an opening cQuote,
332 : a false is returned on a closing cQuote.
333 : A cQuote between quotes may be escaped by a cEscIn, a cQuote outside of
334 : quotes may be escaped by a cEscOut.
335 : The default '\0' results in no escapement possible.
336 : Defaults are set right according to the "unlogic" of the Numberformatter
337 : */
338 : static bool IsInQuote( const OUString& rString, sal_Int32 nPos,
339 : sal_Unicode cQuote = '"',
340 : sal_Unicode cEscIn = '\0', sal_Unicode cEscOut = '\\' );
341 :
342 : /**
343 : Return the position of a matching closing cQuote if the character at
344 : position nPos is between two matching cQuote, otherwise return -1.
345 : If nPos points to an opening cQuote the position of the matching
346 : closing cQuote is returned.
347 : If nPos points to a closing cQuote nPos is returned.
348 : If nPos points into a part which starts with an opening cQuote but has
349 : no closing cQuote, rString.Len() is returned.
350 : Uses <method>IsInQuote</method> internally, so you don't have to call
351 : that prior to a call of this method.
352 : */
353 : static sal_Int32 GetQuoteEnd( const OUString& rString, sal_Int32 nPos,
354 : sal_Unicode cQuote = '"',
355 : sal_Unicode cEscIn = '\0',
356 : sal_Unicode cEscOut = '\\' );
357 :
358 4813 : void SetComment( const OUString& rStr )
359 4813 : { sComment = rStr; }
360 800 : const OUString& GetComment() const { return sComment; }
361 :
362 : /** Insert the number of blanks into the string that is needed to simulate
363 : the width of character c for underscore formats */
364 97 : static sal_Int32 InsertBlanks( OUString& r, sal_Int32 nPos, sal_Unicode c )
365 : {
366 : sal_Int32 result;
367 97 : OUStringBuffer sBuff(r);
368 :
369 97 : result = InsertBlanks(sBuff, nPos, c);
370 97 : r = sBuff.makeStringAndClear();
371 :
372 97 : return result;
373 : }
374 :
375 : /** Insert the number of blanks into the string that is needed to simulate
376 : the width of character c for underscore formats */
377 : static sal_Int32 InsertBlanks( OUStringBuffer& r, sal_Int32 nPos, sal_Unicode c );
378 :
379 : /// One of YMD,DMY,MDY if date format
380 : DateFormat GetDateOrder() const;
381 :
382 : /** A coded value of the exact YMD combination used, if date format.
383 : For example: YYYY-MM-DD => ('Y' << 16) | ('M' << 8) | 'D'
384 : or: MM/YY => ('M' << 8) | 'Y' */
385 : sal_uInt32 GetExactDateOrder() const;
386 :
387 : ImpSvNumberformatScan& ImpGetScan() const { return rScan; }
388 :
389 : // used in XML export
390 : void GetConditions( SvNumberformatLimitOps& rOper1, double& rVal1,
391 : SvNumberformatLimitOps& rOper2, double& rVal2 ) const;
392 : Color* GetColor( sal_uInt16 nNumFor ) const;
393 : void GetNumForInfo( sal_uInt16 nNumFor, short& rScannedType,
394 : bool& bThousand, sal_uInt16& nPrecision, sal_uInt16& nAnzLeading ) const;
395 :
396 : // rAttr.Number not empty if NatNum attributes are to be stored
397 : void GetNatNumXml(
398 : ::com::sun::star::i18n::NativeNumberXmlAttributes& rAttr,
399 : sal_uInt16 nNumFor ) const;
400 :
401 : /** @returns <TRUE/> if E,EE,R,RR,AAA,AAAA in format code of subformat
402 : nNumFor (0..3) and <b>no</b> preceding calendar was specified and the
403 : currently loaded calendar is "gregorian". */
404 : bool IsOtherCalendar( sal_uInt16 nNumFor ) const
405 : {
406 : if ( nNumFor < 4 )
407 : return ImpIsOtherCalendar( NumFor[nNumFor] );
408 : return false;
409 : }
410 :
411 : /** Switches to the first non-"gregorian" calendar, but only if the current
412 : calendar is "gregorian"; original calendar name and date/time returned,
413 : but only if calendar switched and rOrgCalendar was empty. */
414 : void SwitchToOtherCalendar( OUString& rOrgCalendar, double& fOrgDateTime ) const;
415 :
416 : /** Switches to the "gregorian" calendar, but only if the current calendar
417 : is non-"gregorian" and rOrgCalendar is not empty. Thus a preceding
418 : ImpSwitchToOtherCalendar() call should have been placed prior to
419 : calling this method. */
420 : void SwitchToGregorianCalendar( const OUString& rOrgCalendar, double fOrgDateTime ) const;
421 :
422 : #ifdef THE_FUTURE
423 : /** Switches to the first specified calendar, if any, in subformat nNumFor
424 : (0..3). Original calendar name and date/time returned, but only if
425 : calendar switched and rOrgCalendar was empty.
426 :
427 : @return
428 : <TRUE/> if a calendar was specified and switched to,
429 : <FALSE/> else.
430 : */
431 : bool SwitchToSpecifiedCalendar( OUString& rOrgCalendar, double& fOrgDateTime,
432 : sal_uInt16 nNumFor ) const
433 : {
434 : if ( nNumFor < 4 )
435 : return ImpSwitchToSpecifiedCalendar( rOrgCalendar,
436 : fOrgDateTime, NumFor[nNumFor] );
437 : return false;
438 : }
439 : #endif
440 :
441 : /// Whether it's a (YY)YY-M(M)-D(D) format.
442 10 : bool IsIso8601( sal_uInt16 nNumFor )
443 : {
444 10 : if ( nNumFor < 4 )
445 10 : return ImpIsIso8601( NumFor[nNumFor]);
446 0 : return false;
447 : }
448 :
449 : private:
450 : ImpSvNumFor NumFor[4]; // Array for the 4 subformats
451 : OUString sFormatstring; // The format code string
452 : OUString sComment; // Comment, since number formatter version 6
453 : double fLimit1; // Value for first condition
454 : double fLimit2; // Value for second condition
455 : ImpSvNumberformatScan& rScan; // Format code scanner
456 : LocaleType maLocale; // Language/country of the format, numeral shape and calendar type from Excel.
457 : SvNumberformatLimitOps eOp1; // Operator for first condition
458 : SvNumberformatLimitOps eOp2; // Operator for second condition
459 : short eType; // Type of format
460 : bool bAdditionalBuiltin; // If this is an additional built-in format defined by i18n
461 : bool bStarFlag; // Take *n format as ESC n
462 : bool bStandard; // If this is a default standard format
463 : bool bIsUsed; // Flag as used for storing
464 :
465 : SVL_DLLPRIVATE sal_uInt16 ImpGetNumForStringElementCount( sal_uInt16 nNumFor ) const;
466 :
467 : SVL_DLLPRIVATE bool ImpIsOtherCalendar( const ImpSvNumFor& rNumFor ) const;
468 :
469 : #ifdef THE_FUTURE
470 : SVL_DLLPRIVATE bool ImpSwitchToSpecifiedCalendar( OUString& rOrgCalendar,
471 : double& fOrgDateTime,
472 : const ImpSvNumFor& rNumFor ) const;
473 : #endif
474 :
475 : /** Whether to use possessive genitive case month name, or partitive case
476 : month name, instead of nominative name (noun).
477 :
478 : @param io_nState
479 : 0: execute check <br>
480 : set to 1 if nominative case is returned, <br>
481 : set to 2 if genitive case is returned, <br>
482 : set to 3 if partitive case is returned <br>
483 : 1: don't execute check, return nominative case <br>
484 : 2: don't execute check, return genitive case <br>
485 : 3: don't execute check, return partitive case <br>
486 :
487 : @param eCodeType
488 : a NfKeywordIndex, must designate a month type code
489 :
490 : @returns one of com::sun::star::i18n::CalendarDisplayCode values
491 : according to eCodeType and the check executed (or passed).
492 : */
493 : SVL_DLLPRIVATE sal_Int32 ImpUseMonthCase( int & io_nState, const ImpSvNumFor& rNumFor, NfKeywordIndex eCodeType ) const;
494 :
495 : /// Whether it's a (YY)YY-M(M)-D(D) format.
496 : SVL_DLLPRIVATE bool ImpIsIso8601( const ImpSvNumFor& rNumFor );
497 :
498 : const CharClass& rChrCls() const;
499 : const LocaleDataWrapper& rLoc() const;
500 : CalendarWrapper& GetCal() const;
501 : const SvNumberFormatter& GetFormatter() const;
502 :
503 : // divide in substrings and color conditions
504 : SVL_DLLPRIVATE short ImpNextSymbol( OUStringBuffer& rString,
505 : sal_Int32& nPos,
506 : OUString& sSymbol );
507 :
508 : // read string until ']' and strip blanks (after condition)
509 : SVL_DLLPRIVATE static sal_Int32 ImpGetNumber( OUStringBuffer& rString,
510 : sal_Int32& nPos,
511 : OUString& sSymbol );
512 :
513 : /**
514 : * Parse the content of '[$-xxx] or '[$-xxxxxxxx]' and extract the locale
515 : * type from it. Given the string, start parsing at position specified by
516 : * nPos, and store the end position with nPos when the parsing is
517 : * complete. The nPos should point to the '$' before the parsing, and to
518 : * the closing bracket after the parsing. When the content is [$-xxx],
519 : * the xxx part represents the language type (aka LCID) in hex numerals.
520 : * When the content is [$-xxxxxxxx] the last 4 digits represent the LCID
521 : * (again in hex), the next 2 digits represent the calendar type, and the
522 : * 2 highest digits (if exists) is the numeral shape.
523 : *
524 : * @reference
525 : * http://office.microsoft.com/en-us/excel-help/creating-international-number-formats-HA001034635.aspx
526 : *
527 : * @param rString input string
528 : * @param nPos position (see above).
529 : *
530 : * @return struct containing numeral shape, calendar type, and LCID that
531 : * specifies language type. See i18nlangtag/lang.h for a complete
532 : * list of language types. These numbers also correspond with the
533 : * numbers used by Microsoft Office.
534 : */
535 : SVL_DLLPRIVATE static LocaleType ImpGetLocaleType( const OUString& rString, sal_Int32& nPos );
536 :
537 : /** Obtain calendar and numerals from a LocaleType that was parsed from a
538 : LCID with ImpGetLocaleType().
539 :
540 : Inserts a NatNum modifier to rString at nPos if needed as determined
541 : from the numeral code.
542 :
543 : @ATTENTION: may modify <member>maLocale</member> to make it follow
544 : aTmpLocale, in which case also nLang is adapted.
545 :
546 : @returns a string with the calendar if one was determined from the
547 : calendar code, else an empty string. The calendar string needs to be
548 : inserted at a proper position to rString after all bracketed prefixes.
549 : */
550 : SVL_DLLPRIVATE OUString ImpObtainCalendarAndNumerals( OUStringBuffer & rString,
551 : sal_Int32 & nPos,
552 : LanguageType & nLang,
553 : const LocaleType & aTmpLocale );
554 :
555 : // standard number output
556 : SVL_DLLPRIVATE void ImpGetOutputStandard( double& fNumber, OUString& OutString );
557 : SVL_DLLPRIVATE void ImpGetOutputStandard( double& fNumber, OUStringBuffer& OutString );
558 : SVL_DLLPRIVATE void ImpGetOutputStdToPrecision( double& rNumber, OUString& rOutString, sal_uInt16 nPrecision ) const;
559 : // numbers in input line
560 : SVL_DLLPRIVATE void ImpGetOutputInputLine( double fNumber, OUString& OutString );
561 :
562 : // check subcondition
563 : // OP undefined => -1
564 : // else 0 or 1
565 : SVL_DLLPRIVATE short ImpCheckCondition(double& fNumber,
566 : double& fLimit,
567 : SvNumberformatLimitOps eOp);
568 :
569 : SVL_DLLPRIVATE sal_uLong ImpGGT(sal_uLong x, sal_uLong y);
570 : SVL_DLLPRIVATE sal_uLong ImpGGTRound(sal_uLong x, sal_uLong y);
571 :
572 : // Helper function for number strings
573 : // append string symbols, insert leading 0 or ' ', or ...
574 : SVL_DLLPRIVATE bool ImpNumberFill( OUStringBuffer& sStr,
575 : double& rNumber,
576 : sal_Int32& k,
577 : sal_uInt16& j,
578 : sal_uInt16 nIx,
579 : short eSymbolType );
580 :
581 : // Helper function to fill in the integer part and the group (AKA thousand) separators
582 : SVL_DLLPRIVATE bool ImpNumberFillWithThousands( OUStringBuffer& sStr,
583 : double& rNumber,
584 : sal_Int32 k,
585 : sal_uInt16 j,
586 : sal_uInt16 nIx,
587 : sal_Int32 nDigCnt );
588 :
589 : // Helper function to fill in the group (AKA thousand) separators
590 : // or to skip additional digits
591 : SVL_DLLPRIVATE void ImpDigitFill( OUStringBuffer& sStr,
592 : sal_Int32 nStart,
593 : sal_Int32& k,
594 : sal_uInt16 nIx,
595 : sal_Int32 & nDigitCount,
596 : utl::DigitGroupingIterator & );
597 :
598 : SVL_DLLPRIVATE bool ImpDecimalFill( OUStringBuffer& sStr,
599 : double& rNumber,
600 : sal_uInt16 j,
601 : sal_uInt16 nIx,
602 : bool bInteger );
603 :
604 : SVL_DLLPRIVATE bool ImpGetFractionOutput(double fNumber,
605 : sal_uInt16 nIx,
606 : OUStringBuffer& OutString);
607 : SVL_DLLPRIVATE bool ImpGetScientificOutput(double fNumber,
608 : sal_uInt16 nIx,
609 : OUStringBuffer& OutString);
610 :
611 : SVL_DLLPRIVATE bool ImpGetDateOutput( double fNumber,
612 : sal_uInt16 nIx,
613 : OUStringBuffer& OutString );
614 : SVL_DLLPRIVATE bool ImpGetTimeOutput( double fNumber,
615 : sal_uInt16 nIx,
616 : OUStringBuffer& OutString );
617 : SVL_DLLPRIVATE bool ImpGetDateTimeOutput( double fNumber,
618 : sal_uInt16 nIx,
619 : OUStringBuffer& OutString );
620 :
621 : // Switches to the "gregorian" calendar if the current calendar is
622 : // non-"gregorian" and the era is a "Dummy" era of a calendar which doesn't
623 : // know a "before" era (like zh_TW ROC or ja_JP Gengou). If switched and
624 : // rOrgCalendar was "gregorian" the string is emptied. If rOrgCalendar was
625 : // empty the previous calendar name and date/time are returned.
626 : SVL_DLLPRIVATE bool ImpFallBackToGregorianCalendar( OUString& rOrgCalendar, double& fOrgDateTime );
627 :
628 : // Append a "G" short era string of the given calendar. In the case of a
629 : // Gengou calendar this is a one character abbreviation, for other
630 : // calendars the XExtendedCalendar::getDisplayString() method is called.
631 : SVL_DLLPRIVATE static void ImpAppendEraG( OUStringBuffer& OutStringBuffer, const CalendarWrapper& rCal,
632 : sal_Int16 nNatNum );
633 :
634 : SVL_DLLPRIVATE bool ImpGetNumberOutput( double fNumber,
635 : sal_uInt16 nIx,
636 : OUStringBuffer& OutString );
637 :
638 : SVL_DLLPRIVATE void ImpCopyNumberformat( const SvNumberformat& rFormat );
639 :
640 : // normal digits or other digits, depending on ImpSvNumFor.aNatNum,
641 : // [NatNum1], [NatNum2], ...
642 : SVL_DLLPRIVATE OUString ImpGetNatNumString( const SvNumberNatNum& rNum, sal_Int32 nVal,
643 : sal_uInt16 nMinDigits = 0 ) const;
644 :
645 1112 : OUString ImpIntToString( sal_uInt16 nIx, sal_Int32 nVal, sal_uInt16 nMinDigits = 0 ) const
646 : {
647 1112 : const SvNumberNatNum& rNum = NumFor[nIx].GetNatNum();
648 1112 : if ( nMinDigits || rNum.IsComplete() )
649 : {
650 1085 : return ImpGetNatNumString( rNum, nVal, nMinDigits );
651 : }
652 27 : return OUString::number(nVal);
653 : }
654 :
655 : // transliterate according to NativeNumber
656 : SVL_DLLPRIVATE OUString impTransliterateImpl(const OUString& rStr, const SvNumberNatNum& rNum) const;
657 : SVL_DLLPRIVATE void impTransliterateImpl(OUStringBuffer& rStr, const SvNumberNatNum& rNum) const;
658 :
659 59318 : OUString impTransliterate(const OUString& rStr, const SvNumberNatNum& rNum) const
660 : {
661 59318 : return rNum.IsComplete() ? impTransliterateImpl(rStr, rNum) : rStr;
662 : }
663 :
664 5077 : SVL_DLLPRIVATE void impTransliterate(OUStringBuffer& rStr, const SvNumberNatNum& rNum) const
665 : {
666 5077 : if(rNum.IsComplete())
667 : {
668 1 : impTransliterateImpl(rStr, rNum);
669 : }
670 5077 : }
671 : };
672 :
673 : #endif // INCLUDED_SVL_ZFORMAT_HXX
674 :
675 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|