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 :
20 :
21 : #include <stdlib.h>
22 : #include <comphelper/string.hxx>
23 : #include <tools/debug.hxx>
24 : #include <i18nlangtag/mslangid.hxx>
25 : #include <unotools/charclass.hxx>
26 : #include <unotools/localedatawrapper.hxx>
27 : #include <unotools/numberformatcodewrapper.hxx>
28 : #include <rtl/instance.hxx>
29 :
30 : #include <svl/zforlist.hxx>
31 : #include <svl/zformat.hxx>
32 : #include <unotools/digitgroupingiterator.hxx>
33 :
34 : #include "zforscan.hxx"
35 :
36 : #include <svl/nfsymbol.hxx>
37 : using namespace svt;
38 :
39 : const sal_Unicode cNoBreakSpace = 0xA0;
40 : const sal_Unicode cNarrowNoBreakSpace = 0x202F;
41 :
42 : namespace
43 : {
44 : struct ImplEnglishColors
45 : {
46 9 : const OUString* operator()()
47 : {
48 : static const OUString aEnglishColors[NF_MAX_DEFAULT_COLORS] =
49 : {
50 : OUString( "BLACK" ),
51 : OUString( "BLUE" ),
52 : OUString( "GREEN" ),
53 : OUString( "CYAN" ),
54 : OUString( "RED" ),
55 : OUString( "MAGENTA" ),
56 : OUString( "BROWN" ),
57 : OUString( "GREY" ),
58 : OUString( "YELLOW" ),
59 : OUString( "WHITE" )
60 18 : };
61 9 : return &aEnglishColors[0];
62 : }
63 : };
64 :
65 : struct theEnglishColors
66 : : public rtl::StaticAggregate< const OUString, ImplEnglishColors> {};
67 :
68 : }
69 :
70 2758 : ImpSvNumberformatScan::ImpSvNumberformatScan( SvNumberFormatter* pFormatterP )
71 : : eNewLnge(LANGUAGE_DONTKNOW)
72 : , eTmpLnge(LANGUAGE_DONTKNOW)
73 2758 : , nCurrPos(-1)
74 : {
75 2758 : pFormatter = pFormatterP;
76 2758 : bConvertMode = false;
77 2758 : bConvertSystemToSystem = false;
78 : //! All keywords MUST be UPPERCASE!
79 2758 : sKeyword[NF_KEY_E] = "E"; // Exponent
80 2758 : sKeyword[NF_KEY_AMPM] = "AM/PM"; // AM/PM
81 2758 : sKeyword[NF_KEY_AP] = "A/P"; // AM/PM short
82 2758 : sKeyword[NF_KEY_MI] = "M"; // Minute
83 2758 : sKeyword[NF_KEY_MMI] = "MM"; // Minute 02
84 2758 : sKeyword[NF_KEY_S] = "S"; // Second
85 2758 : sKeyword[NF_KEY_SS] = "SS"; // Second 02
86 2758 : sKeyword[NF_KEY_Q] = "Q"; // Quarter short 'Q'
87 2758 : sKeyword[NF_KEY_QQ] = "QQ"; // Quarter long
88 2758 : sKeyword[NF_KEY_NN] = "NN"; // Day of week short
89 2758 : sKeyword[NF_KEY_NNN] = "NNN"; // Day of week long
90 2758 : sKeyword[NF_KEY_NNNN] = "NNNN"; // Day of week long incl. separator
91 2758 : sKeyword[NF_KEY_WW] = "WW"; // Week of year
92 2758 : sKeyword[NF_KEY_CCC] = "CCC"; // Currency abbreviation
93 2758 : bKeywordsNeedInit = true; // locale dependent keywords
94 2758 : bCompatCurNeedInit = true; // locale dependent compatibility currency strings
95 :
96 2758 : StandardColor[0] = Color(COL_BLACK);
97 2758 : StandardColor[1] = Color(COL_LIGHTBLUE);
98 2758 : StandardColor[2] = Color(COL_LIGHTGREEN);
99 2758 : StandardColor[3] = Color(COL_LIGHTCYAN);
100 2758 : StandardColor[4] = Color(COL_LIGHTRED);
101 2758 : StandardColor[5] = Color(COL_LIGHTMAGENTA);
102 2758 : StandardColor[6] = Color(COL_BROWN);
103 2758 : StandardColor[7] = Color(COL_GRAY);
104 2758 : StandardColor[8] = Color(COL_YELLOW);
105 2758 : StandardColor[9] = Color(COL_WHITE);
106 :
107 2758 : pNullDate = new Date(30,12,1899);
108 2758 : nStandardPrec = 2;
109 :
110 2758 : sErrStr = "###";
111 2758 : Reset();
112 2758 : }
113 :
114 5068 : ImpSvNumberformatScan::~ImpSvNumberformatScan()
115 : {
116 2534 : delete pNullDate;
117 2534 : Reset();
118 2534 : }
119 :
120 13941 : void ImpSvNumberformatScan::ChangeIntl()
121 : {
122 13941 : bKeywordsNeedInit = true;
123 13941 : bCompatCurNeedInit = true;
124 : // may be initialized by InitSpecialKeyword()
125 13941 : sKeyword[NF_KEY_TRUE] = "";
126 13941 : sKeyword[NF_KEY_FALSE] = "";
127 13941 : }
128 :
129 29378 : void ImpSvNumberformatScan::InitSpecialKeyword( NfKeywordIndex eIdx ) const
130 : {
131 29378 : switch ( eIdx )
132 : {
133 : case NF_KEY_TRUE :
134 29382 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] =
135 29382 : pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getTrueWord() );
136 14691 : if ( sKeyword[NF_KEY_TRUE].isEmpty() )
137 : {
138 : SAL_WARN( "svl.numbers", "InitSpecialKeyword: TRUE_WORD?" );
139 0 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] = "TRUE";
140 : }
141 14691 : break;
142 : case NF_KEY_FALSE :
143 29374 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] =
144 29374 : pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getFalseWord() );
145 14687 : if ( sKeyword[NF_KEY_FALSE].isEmpty() )
146 : {
147 : SAL_WARN( "svl.numbers", "InitSpecialKeyword: FALSE_WORD?" );
148 0 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] = "FALSE";
149 : }
150 14687 : break;
151 : default:
152 : SAL_WARN( "svl.numbers", "InitSpecialKeyword: unknown request" );
153 : }
154 29378 : }
155 :
156 12927 : void ImpSvNumberformatScan::InitCompatCur() const
157 : {
158 12927 : ImpSvNumberformatScan* pThis = (ImpSvNumberformatScan*)this;
159 : // currency symbol for old style ("automatic") compatibility format codes
160 12927 : pFormatter->GetCompatibilityCurrency( pThis->sCurSymbol, pThis->sCurAbbrev );
161 : // currency symbol upper case
162 12927 : pThis->sCurString = pFormatter->GetCharClass()->uppercase( sCurSymbol );
163 12927 : bCompatCurNeedInit = false;
164 12927 : }
165 :
166 16781 : void ImpSvNumberformatScan::InitKeywords() const
167 : {
168 16781 : if ( !bKeywordsNeedInit )
169 20635 : return ;
170 12927 : ((ImpSvNumberformatScan*)this)->SetDependentKeywords();
171 12927 : bKeywordsNeedInit = false;
172 : }
173 :
174 : /** Extract the name of General, Standard, Whatever, ignoring leading modifiers
175 : such as [NatNum1]. */
176 12927 : static OUString lcl_extractStandardGeneralName( const OUString & rCode )
177 : {
178 12927 : OUString aStr;
179 12927 : const sal_Unicode* p = rCode.getStr();
180 12927 : const sal_Unicode* const pStop = p + rCode.getLength();
181 12927 : const sal_Unicode* pBeg = p; // name begins here
182 12927 : bool bMod = false;
183 12927 : bool bDone = false;
184 116374 : while (p < pStop && !bDone)
185 : {
186 90520 : switch (*p)
187 : {
188 : case '[':
189 0 : bMod = true;
190 0 : break;
191 : case ']':
192 0 : if (bMod)
193 : {
194 0 : bMod = false;
195 0 : pBeg = p+1;
196 : }
197 : // else: would be a locale data error, easily to be spotted in
198 : // UI dialog
199 0 : break;
200 : case ';':
201 0 : if (!bMod)
202 : {
203 0 : bDone = true;
204 0 : --p; // put back, increment by one follows
205 : }
206 0 : break;
207 : }
208 90520 : ++p;
209 90520 : if (bMod)
210 : {
211 0 : pBeg = p;
212 : }
213 : }
214 12927 : if (pBeg < p)
215 : {
216 12927 : aStr = rCode.copy( pBeg - rCode.getStr(), p - pBeg);
217 : }
218 12927 : return aStr;
219 : }
220 :
221 12927 : void ImpSvNumberformatScan::SetDependentKeywords()
222 : {
223 : using namespace ::com::sun::star;
224 : using namespace ::com::sun::star::uno;
225 :
226 12927 : const CharClass* pCharClass = pFormatter->GetCharClass();
227 12927 : const LocaleDataWrapper* pLocaleData = pFormatter->GetLocaleData();
228 : // #80023# be sure to generate keywords for the loaded Locale, not for the
229 : // requested Locale, otherwise number format codes might not match
230 12927 : const LanguageTag& rLoadedLocale = pLocaleData->getLoadedLanguageTag();
231 12927 : LanguageType eLang = rLoadedLocale.getLanguageType( false);
232 : NumberFormatCodeWrapper aNumberFormatCode( pFormatter->GetComponentContext(),
233 25854 : rLoadedLocale.getLocale() );
234 :
235 25854 : i18n::NumberFormatCode aFormat = aNumberFormatCode.getFormatCode( NF_NUMBER_STANDARD );
236 12927 : sNameStandardFormat = lcl_extractStandardGeneralName( aFormat.Code);
237 12927 : sKeyword[NF_KEY_GENERAL] = pCharClass->uppercase( sNameStandardFormat );
238 :
239 : // preset new calendar keywords
240 12927 : sKeyword[NF_KEY_AAA] = "AAA";
241 12927 : sKeyword[NF_KEY_AAAA] = "AAAA";
242 12927 : sKeyword[NF_KEY_EC] = "E";
243 12927 : sKeyword[NF_KEY_EEC] = "EE";
244 12927 : sKeyword[NF_KEY_G] = "G";
245 12927 : sKeyword[NF_KEY_GG] = "GG";
246 12927 : sKeyword[NF_KEY_GGG] = "GGG";
247 12927 : sKeyword[NF_KEY_R] = "R";
248 12927 : sKeyword[NF_KEY_RR] = "RR";
249 :
250 : // Thai T NatNum special. Other locale's small letter 't' results in upper
251 : // case comparison not matching but length does in conversion mode. Ugly.
252 12927 : if (eLang == LANGUAGE_THAI)
253 : {
254 3 : sKeyword[NF_KEY_THAI_T] = "T";
255 : }
256 : else
257 : {
258 12924 : sKeyword[NF_KEY_THAI_T] = "t";
259 : }
260 12927 : switch ( eLang )
261 : {
262 : case LANGUAGE_GERMAN:
263 : case LANGUAGE_GERMAN_SWISS:
264 : case LANGUAGE_GERMAN_AUSTRIAN:
265 : case LANGUAGE_GERMAN_LUXEMBOURG:
266 : case LANGUAGE_GERMAN_LIECHTENSTEIN:
267 : //! all capital letters
268 19 : sKeyword[NF_KEY_M] = "M"; // month 1
269 19 : sKeyword[NF_KEY_MM] = "MM"; // month 01
270 19 : sKeyword[NF_KEY_MMM] = "MMM"; // month Jan
271 19 : sKeyword[NF_KEY_MMMM] = "MMMM"; // month Januar
272 19 : sKeyword[NF_KEY_MMMMM] = "MMMMM"; // month J
273 19 : sKeyword[NF_KEY_H] = "H"; // hour 2
274 19 : sKeyword[NF_KEY_HH] = "HH"; // hour 02
275 19 : sKeyword[NF_KEY_D] = "T";
276 19 : sKeyword[NF_KEY_DD] = "TT";
277 19 : sKeyword[NF_KEY_DDD] = "TTT";
278 19 : sKeyword[NF_KEY_DDDD] = "TTTT";
279 19 : sKeyword[NF_KEY_YY] = "JJ";
280 19 : sKeyword[NF_KEY_YYYY] = "JJJJ";
281 19 : sKeyword[NF_KEY_BOOLEAN] = "LOGISCH";
282 19 : sKeyword[NF_KEY_COLOR] = "FARBE";
283 19 : sKeyword[NF_KEY_BLACK] = "SCHWARZ";
284 19 : sKeyword[NF_KEY_BLUE] = "BLAU";
285 19 : sKeyword[NF_KEY_GREEN] = OUString( "GR" "\xDC" "N", 4, RTL_TEXTENCODING_ISO_8859_1 );
286 19 : sKeyword[NF_KEY_CYAN] = "CYAN";
287 19 : sKeyword[NF_KEY_RED] = "ROT";
288 19 : sKeyword[NF_KEY_MAGENTA] = "MAGENTA";
289 19 : sKeyword[NF_KEY_BROWN] = "BRAUN";
290 19 : sKeyword[NF_KEY_GREY] = "GRAU";
291 19 : sKeyword[NF_KEY_YELLOW] = "GELB";
292 19 : sKeyword[NF_KEY_WHITE] = "WEISS";
293 19 : break;
294 : default:
295 : // day
296 12908 : switch ( eLang )
297 : {
298 : case LANGUAGE_ITALIAN:
299 : case LANGUAGE_ITALIAN_SWISS:
300 0 : sKeyword[NF_KEY_D] = "G";
301 0 : sKeyword[NF_KEY_DD] = "GG";
302 0 : sKeyword[NF_KEY_DDD] = "GGG";
303 0 : sKeyword[NF_KEY_DDDD] = "GGGG";
304 : // must exchange the era code, same as Xcl
305 0 : sKeyword[NF_KEY_G] = "X";
306 0 : sKeyword[NF_KEY_GG] = "XX";
307 0 : sKeyword[NF_KEY_GGG] = "XXX";
308 0 : break;
309 : case LANGUAGE_FRENCH:
310 : case LANGUAGE_FRENCH_BELGIAN:
311 : case LANGUAGE_FRENCH_CANADIAN:
312 : case LANGUAGE_FRENCH_SWISS:
313 : case LANGUAGE_FRENCH_LUXEMBOURG:
314 : case LANGUAGE_FRENCH_MONACO:
315 5 : sKeyword[NF_KEY_D] = "J";
316 5 : sKeyword[NF_KEY_DD] = "JJ";
317 5 : sKeyword[NF_KEY_DDD] = "JJJ";
318 5 : sKeyword[NF_KEY_DDDD] = "JJJJ";
319 5 : break;
320 : case LANGUAGE_FINNISH:
321 0 : sKeyword[NF_KEY_D] = "P";
322 0 : sKeyword[NF_KEY_DD] = "PP";
323 0 : sKeyword[NF_KEY_DDD] = "PPP";
324 0 : sKeyword[NF_KEY_DDDD] = "PPPP";
325 0 : break;
326 : default:
327 12903 : sKeyword[NF_KEY_D] = "D";
328 12903 : sKeyword[NF_KEY_DD] = "DD";
329 12903 : sKeyword[NF_KEY_DDD] = "DDD";
330 12903 : sKeyword[NF_KEY_DDDD] = "DDDD";
331 : }
332 : // month
333 12908 : switch ( eLang )
334 : {
335 : case LANGUAGE_FINNISH:
336 0 : sKeyword[NF_KEY_M] = "K";
337 0 : sKeyword[NF_KEY_MM] = "KK";
338 0 : sKeyword[NF_KEY_MMM] = "KKK";
339 0 : sKeyword[NF_KEY_MMMM] = "KKKK";
340 0 : sKeyword[NF_KEY_MMMMM] = "KKKKK";
341 0 : break;
342 : default:
343 12908 : sKeyword[NF_KEY_M] = "M";
344 12908 : sKeyword[NF_KEY_MM] = "MM";
345 12908 : sKeyword[NF_KEY_MMM] = "MMM";
346 12908 : sKeyword[NF_KEY_MMMM] = "MMMM";
347 12908 : sKeyword[NF_KEY_MMMMM] = "MMMMM";
348 : }
349 : // year
350 12908 : switch ( eLang )
351 : {
352 : case LANGUAGE_ITALIAN:
353 : case LANGUAGE_ITALIAN_SWISS:
354 : case LANGUAGE_FRENCH:
355 : case LANGUAGE_FRENCH_BELGIAN:
356 : case LANGUAGE_FRENCH_CANADIAN:
357 : case LANGUAGE_FRENCH_SWISS:
358 : case LANGUAGE_FRENCH_LUXEMBOURG:
359 : case LANGUAGE_FRENCH_MONACO:
360 : case LANGUAGE_PORTUGUESE:
361 : case LANGUAGE_PORTUGUESE_BRAZILIAN:
362 : case LANGUAGE_SPANISH_MODERN:
363 : case LANGUAGE_SPANISH_DATED:
364 : case LANGUAGE_SPANISH_MEXICAN:
365 : case LANGUAGE_SPANISH_GUATEMALA:
366 : case LANGUAGE_SPANISH_COSTARICA:
367 : case LANGUAGE_SPANISH_PANAMA:
368 : case LANGUAGE_SPANISH_DOMINICAN_REPUBLIC:
369 : case LANGUAGE_SPANISH_VENEZUELA:
370 : case LANGUAGE_SPANISH_COLOMBIA:
371 : case LANGUAGE_SPANISH_PERU:
372 : case LANGUAGE_SPANISH_ARGENTINA:
373 : case LANGUAGE_SPANISH_ECUADOR:
374 : case LANGUAGE_SPANISH_CHILE:
375 : case LANGUAGE_SPANISH_URUGUAY:
376 : case LANGUAGE_SPANISH_PARAGUAY:
377 : case LANGUAGE_SPANISH_BOLIVIA:
378 : case LANGUAGE_SPANISH_EL_SALVADOR:
379 : case LANGUAGE_SPANISH_HONDURAS:
380 : case LANGUAGE_SPANISH_NICARAGUA:
381 : case LANGUAGE_SPANISH_PUERTO_RICO:
382 5 : sKeyword[NF_KEY_YY] = "AA";
383 5 : sKeyword[NF_KEY_YYYY] = "AAAA";
384 : // must exchange the day of week name code, same as Xcl
385 5 : sKeyword[NF_KEY_AAA] = "OOO";
386 5 : sKeyword[NF_KEY_AAAA] = "OOOO";
387 5 : break;
388 : case LANGUAGE_DUTCH:
389 : case LANGUAGE_DUTCH_BELGIAN:
390 0 : sKeyword[NF_KEY_YY] = "JJ";
391 0 : sKeyword[NF_KEY_YYYY] = "JJJJ";
392 0 : break;
393 : case LANGUAGE_FINNISH:
394 0 : sKeyword[NF_KEY_YY] = "VV";
395 0 : sKeyword[NF_KEY_YYYY] = "VVVV";
396 0 : break;
397 : default:
398 12903 : sKeyword[NF_KEY_YY] = "YY";
399 12903 : sKeyword[NF_KEY_YYYY] = "YYYY";
400 : }
401 : // hour
402 12908 : switch ( eLang )
403 : {
404 : case LANGUAGE_DUTCH:
405 : case LANGUAGE_DUTCH_BELGIAN:
406 0 : sKeyword[NF_KEY_H] = "U";
407 0 : sKeyword[NF_KEY_HH] = "UU";
408 0 : break;
409 : case LANGUAGE_FINNISH:
410 : case LANGUAGE_SWEDISH:
411 : case LANGUAGE_SWEDISH_FINLAND:
412 : case LANGUAGE_DANISH:
413 : case LANGUAGE_NORWEGIAN:
414 : case LANGUAGE_NORWEGIAN_BOKMAL:
415 : case LANGUAGE_NORWEGIAN_NYNORSK:
416 4 : sKeyword[NF_KEY_H] = "T";
417 4 : sKeyword[NF_KEY_HH] = "TT";
418 4 : break;
419 : default:
420 12904 : sKeyword[NF_KEY_H] = "H";
421 12904 : sKeyword[NF_KEY_HH] = "HH";
422 : }
423 : // boolean
424 12908 : sKeyword[NF_KEY_BOOLEAN] = "BOOLEAN";
425 : // colours
426 12908 : sKeyword[NF_KEY_COLOR] = "COLOR";
427 12908 : sKeyword[NF_KEY_BLACK] = "BLACK";
428 12908 : sKeyword[NF_KEY_BLUE] = "BLUE";
429 12908 : sKeyword[NF_KEY_GREEN] = "GREEN";
430 12908 : sKeyword[NF_KEY_CYAN] = "CYAN";
431 12908 : sKeyword[NF_KEY_RED] = "RED";
432 12908 : sKeyword[NF_KEY_MAGENTA] = "MAGENTA";
433 12908 : sKeyword[NF_KEY_BROWN] = "BROWN";
434 12908 : sKeyword[NF_KEY_GREY] = "GREY";
435 12908 : sKeyword[NF_KEY_YELLOW] = "YELLOW";
436 12908 : sKeyword[NF_KEY_WHITE] = "WHITE";
437 12908 : break;
438 : }
439 :
440 : // boolean keyords
441 12927 : InitSpecialKeyword( NF_KEY_TRUE );
442 12927 : InitSpecialKeyword( NF_KEY_FALSE );
443 :
444 : // compatibility currency strings
445 25854 : InitCompatCur();
446 12927 : }
447 :
448 1918 : void ImpSvNumberformatScan::ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear)
449 : {
450 1918 : if ( pNullDate )
451 1918 : *pNullDate = Date(nDay, nMonth, nYear);
452 : else
453 0 : pNullDate = new Date(nDay, nMonth, nYear);
454 1918 : }
455 :
456 2818 : void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec)
457 : {
458 2818 : nStandardPrec = nPrec;
459 2818 : }
460 :
461 21029 : Color* ImpSvNumberformatScan::GetColor(OUString& sStr)
462 : {
463 21029 : OUString sString = pFormatter->GetCharClass()->uppercase(sStr);
464 21029 : const NfKeywordTable & rKeyword = GetKeywords();
465 21029 : size_t i = 0;
466 135486 : while (i < NF_MAX_DEFAULT_COLORS && sString != rKeyword[NF_KEY_FIRSTCOLOR+i] )
467 : {
468 93428 : i++;
469 : }
470 21029 : if ( i >= NF_MAX_DEFAULT_COLORS )
471 : {
472 1552 : const OUString* pEnglishColors = theEnglishColors::get();
473 1552 : size_t j = 0;
474 18624 : while ( j < NF_MAX_DEFAULT_COLORS && sString != pEnglishColors[j] )
475 : {
476 15520 : ++j;
477 : }
478 1552 : if ( j < NF_MAX_DEFAULT_COLORS )
479 : {
480 0 : i = j;
481 : }
482 : }
483 :
484 21029 : Color* pResult = NULL;
485 21029 : if (i >= NF_MAX_DEFAULT_COLORS)
486 : {
487 1552 : const OUString& rColorWord = rKeyword[NF_KEY_COLOR];
488 1552 : if (sString.startsWith(rColorWord))
489 : {
490 0 : sal_Int32 nPos = rColorWord.getLength();
491 0 : sStr = sStr.copy(nPos);
492 0 : sStr = comphelper::string::strip(sStr, ' ');
493 0 : if (bConvertMode)
494 : {
495 0 : pFormatter->ChangeIntl(eNewLnge);
496 0 : sStr = GetKeywords()[NF_KEY_COLOR] + sStr; // Color -> FARBE
497 0 : pFormatter->ChangeIntl(eTmpLnge);
498 : }
499 : else
500 : {
501 0 : sStr = rColorWord + sStr;
502 : }
503 0 : sString = sString.copy(nPos);
504 0 : sString = comphelper::string::strip(sString, ' ');
505 :
506 0 : if ( CharClass::isAsciiNumeric( sString ) )
507 : {
508 0 : long nIndex = sString.toInt32();
509 0 : if (nIndex > 0 && nIndex <= 64)
510 : {
511 0 : pResult = pFormatter->GetUserDefColor((sal_uInt16)nIndex-1);
512 : }
513 : }
514 : }
515 : }
516 : else
517 : {
518 19477 : sStr = "";
519 19477 : if (bConvertMode)
520 : {
521 563 : pFormatter->ChangeIntl(eNewLnge);
522 563 : sStr = GetKeywords()[NF_KEY_FIRSTCOLOR+i]; // red -> rot
523 563 : pFormatter->ChangeIntl(eTmpLnge);
524 : }
525 : else
526 : {
527 18914 : sStr = rKeyword[NF_KEY_FIRSTCOLOR+i];
528 : }
529 19477 : pResult = &(StandardColor[i]);
530 : }
531 21029 : return pResult;
532 : }
533 :
534 674354 : short ImpSvNumberformatScan::GetKeyWord( const OUString& sSymbol, sal_Int32 nPos )
535 : {
536 674354 : OUString sString = pFormatter->GetCharClass()->uppercase( sSymbol, nPos, sSymbol.getLength() - nPos );
537 674354 : const NfKeywordTable & rKeyword = GetKeywords();
538 : // #77026# for the Xcl perverts: the GENERAL keyword is recognized anywhere
539 674354 : if ( sString.startsWith( rKeyword[NF_KEY_GENERAL] ))
540 : {
541 3185 : return NF_KEY_GENERAL;
542 : }
543 : //! MUST be a reverse search to find longer strings first
544 671169 : short i = NF_KEYWORD_ENTRIES_COUNT-1;
545 671169 : bool bFound = false;
546 7156482 : for ( ; i > NF_KEY_LASTKEYWORD_SO5; --i )
547 : {
548 6560696 : bFound = sString.startsWith(rKeyword[i]);
549 6560696 : if ( bFound )
550 : {
551 75383 : break;
552 : }
553 : }
554 : // new keywords take precedence over old keywords
555 671169 : if ( !bFound )
556 : {
557 : // skip the gap of colors et al between new and old keywords and search on
558 595786 : i = NF_KEY_LASTKEYWORD;
559 11300880 : while ( i > 0 && sString.indexOf(rKeyword[i]) != 0 )
560 : {
561 10109308 : i--;
562 : }
563 595786 : if ( i > NF_KEY_LASTOLDKEYWORD && sString != rKeyword[i] )
564 : {
565 : // found something, but maybe it's something else?
566 : // e.g. new NNN is found in NNNN, for NNNN we must search on
567 12323 : short j = i - 1;
568 49292 : while ( j > 0 && sString.indexOf(rKeyword[j]) != 0 )
569 : {
570 24646 : j--;
571 : }
572 12323 : if ( j && rKeyword[j].getLength() > rKeyword[i].getLength() )
573 : {
574 12323 : return j;
575 : }
576 : }
577 : }
578 : // The Thai T NatNum modifier during Xcl import.
579 779605 : if (i == 0 && bConvertMode &&
580 4455 : sString[0] == 'T' &&
581 658846 : eTmpLnge == LANGUAGE_ENGLISH_US &&
582 0 : MsLangId::getRealLanguage( eNewLnge) == LANGUAGE_THAI)
583 : {
584 0 : i = NF_KEY_THAI_T;
585 : }
586 658846 : return i; // 0 => not found
587 : }
588 :
589 : /**
590 : * Next_Symbol
591 : *
592 : * Splits up the input for further processing (by the Turing machine).
593 : *
594 : * Starting state = SsStar
595 : *
596 : * ---------------+-------------------+---------------------------+---------------
597 : * Old state | Character read | Event | New state
598 : * ---------------+-------------------+---------------------------+---------------
599 : * SsStart | Character | Symbol = Character | SsGetWord
600 : * | " | Type = String | SsGetString
601 : * | \ | Type = String | SsGetChar
602 : * | * | Type = Star | SsGetStar
603 : * | _ | Type = Blank | SsGetBlank
604 : * | @ # 0 ? / . , % [ | Symbol = Character; |
605 : * | ] ' Blank | Type = Control character | SsStop
606 : * | $ - + ( ) : | Type = String; |
607 : * | Else | Symbol = Character | SsStop
608 : * ---------------|-------------------+---------------------------+---------------
609 : * SsGetChar | Else | Symbol = Character | SsStop
610 : * ---------------+-------------------+---------------------------+---------------
611 : * GetString | " | | SsStop
612 : * | Else | Symbol += Character | GetString
613 : * ---------------+-------------------+---------------------------+---------------
614 : * SsGetWord | Character | Symbol += Character |
615 : * | + - (E+ E-)| Symbol += Character | SsStop
616 : * | / (AM/PM)| Symbol += Character |
617 : * | Else | Pos--, if Key Type = Word | SsStop
618 : * ---------------+-------------------+---------------------------+---------------
619 : * SsGetStar | Else | Symbol += Character | SsStop
620 : * | | Mark special case * |
621 : * ---------------+-------------------+---------------------------+---------------
622 : * SsGetBlank | Else | Symbol + =Character | SsStop
623 : * | | Mark special case _ |
624 : * ---------------------------------------------------------------+--------------
625 : *
626 : * If we recognize a keyword in the state SsGetWord (even as the symbol's start text)
627 : * we write back the rest of the characters!
628 : */
629 :
630 : enum ScanState
631 : {
632 : SsStop = 0,
633 : SsStart = 1,
634 : SsGetChar = 2,
635 : SsGetString = 3,
636 : SsGetWord = 4,
637 : SsGetStar = 5,
638 : SsGetBlank = 6
639 : };
640 :
641 2298273 : short ImpSvNumberformatScan::Next_Symbol( const OUString& rStr,
642 : sal_Int32& nPos,
643 : OUString& sSymbol )
644 : {
645 2298273 : if ( bKeywordsNeedInit )
646 : {
647 0 : InitKeywords();
648 : }
649 2298273 : const CharClass* pChrCls = pFormatter->GetCharClass();
650 2298273 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
651 2298273 : const sal_Int32 nStart = nPos;
652 2298273 : short eType = 0;
653 2298273 : ScanState eState = SsStart;
654 2298273 : sSymbol = "";
655 7034263 : while ( nPos < rStr.getLength() && eState != SsStop )
656 : {
657 2438057 : sal_Unicode cToken = rStr[nPos++];
658 2438057 : switch (eState)
659 : {
660 : case SsStart:
661 : // Fetch any currency longer than one character and don't get
662 : // confused later on by "E/" or other combinations of letters
663 : // and meaningful symbols. Necessary for old automatic currency.
664 : // #96158# But don't do it if we're starting a "[...]" section,
665 : // for example a "[$...]" new currency symbol to not parse away
666 : // "$U" (symbol) of "[$UYU]" (abbreviation).
667 5550662 : if ( nCurrPos >= 0 && sCurString.getLength() > 1 &&
668 2310659 : nPos-1 + sCurString.getLength() <= rStr.getLength() &&
669 7884 : !(nPos > 1 && rStr[nPos-2] == '[') )
670 : {
671 3942 : OUString aTest = pChrCls->uppercase( rStr.copy( nPos-1, sCurString.getLength() ) );
672 3942 : if ( aTest == sCurString )
673 : {
674 340 : sSymbol = rStr.copy( --nPos, sCurString.getLength() );
675 340 : nPos = nPos + sSymbol.getLength();
676 340 : eState = SsStop;
677 340 : eType = NF_SYMBOLTYPE_STRING;
678 340 : return eType;
679 3602 : }
680 : }
681 2297933 : switch (cToken)
682 : {
683 : case '#':
684 : case '0':
685 : case '?':
686 : case '%':
687 : case '@':
688 : case '[':
689 : case ']':
690 : case ',':
691 : case '.':
692 : case '/':
693 : case '\'':
694 : case ' ':
695 : case ':':
696 : case '-':
697 1450053 : eType = NF_SYMBOLTYPE_DEL;
698 1450053 : sSymbol += OUString(cToken);
699 1450053 : eState = SsStop;
700 1450053 : break;
701 : case '*':
702 13956 : eType = NF_SYMBOLTYPE_STAR;
703 13956 : sSymbol += OUString(cToken);
704 13956 : eState = SsGetStar;
705 13956 : break;
706 : case '_':
707 10483 : eType = NF_SYMBOLTYPE_BLANK;
708 10483 : sSymbol += OUString(cToken);
709 10483 : eState = SsGetBlank;
710 10483 : break;
711 : case '"':
712 2205 : eType = NF_SYMBOLTYPE_STRING;
713 2205 : eState = SsGetString;
714 2205 : sSymbol += OUString(cToken);
715 2205 : break;
716 : case '\\':
717 1481 : eType = NF_SYMBOLTYPE_STRING;
718 1481 : eState = SsGetChar;
719 1481 : sSymbol += OUString(cToken);
720 1481 : break;
721 : case '$':
722 : case '+':
723 : case '(':
724 : case ')':
725 132779 : eType = NF_SYMBOLTYPE_STRING;
726 132779 : eState = SsStop;
727 132779 : sSymbol += OUString(cToken);
728 132779 : break;
729 : default :
730 2060928 : if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cToken) ||
731 1373952 : StringEqualsChar( pFormatter->GetNumThousandSep(), cToken) ||
732 1373940 : StringEqualsChar( pFormatter->GetDateSep(), cToken) ||
733 2060904 : StringEqualsChar( pLoc->getTimeSep(), cToken) ||
734 686964 : StringEqualsChar( pLoc->getTime100SecSep(), cToken))
735 : {
736 : // Another separator than pre-known ASCII
737 12 : eType = NF_SYMBOLTYPE_DEL;
738 12 : sSymbol += OUString(cToken);
739 12 : eState = SsStop;
740 : }
741 686964 : else if ( pChrCls->isLetter( rStr, nPos-1 ) )
742 : {
743 561586 : short nTmpType = GetKeyWord( rStr, nPos-1 );
744 561586 : if ( nTmpType )
745 : {
746 493108 : bool bCurrency = false;
747 : // "Automatic" currency may start with keyword,
748 : // like "R" (Rand) and 'R' (era)
749 986760 : if ( nCurrPos >= 0 &&
750 493652 : nPos-1 + sCurString.getLength() <= rStr.getLength() &&
751 544 : sCurString.startsWith( sKeyword[nTmpType] ) )
752 : {
753 0 : OUString aTest = pChrCls->uppercase( rStr.copy( nPos-1, sCurString.getLength() ) );
754 0 : if ( aTest == sCurString )
755 : {
756 0 : bCurrency = true;
757 0 : }
758 : }
759 493108 : if ( bCurrency )
760 : {
761 0 : eState = SsGetWord;
762 0 : sSymbol += OUString(cToken);
763 : }
764 : else
765 : {
766 493108 : eType = nTmpType;
767 493108 : sal_Int32 nLen = sKeyword[eType].getLength();
768 493108 : sSymbol = rStr.copy( nPos-1, nLen );
769 493108 : if ((eType == NF_KEY_E || IsAmbiguousE(eType)) && nPos < rStr.getLength())
770 : {
771 40538 : sal_Unicode cNext = rStr[nPos];
772 40538 : switch ( cNext )
773 : {
774 : case '+' :
775 : case '-' : // E+ E- combine to one symbol
776 6326 : sSymbol += OUString(cNext);
777 6326 : eType = NF_KEY_E;
778 6326 : nPos++;
779 6326 : break;
780 : case '0' :
781 : case '#' : // scientific E without sign
782 0 : eType = NF_KEY_E;
783 0 : break;
784 : }
785 : }
786 493108 : nPos--;
787 493108 : nPos = nPos + nLen;
788 493108 : eState = SsStop;
789 : }
790 : }
791 : else
792 : {
793 68478 : eState = SsGetWord;
794 68478 : sSymbol += OUString(cToken);
795 : }
796 : }
797 : else
798 : {
799 125378 : eType = NF_SYMBOLTYPE_STRING;
800 125378 : eState = SsStop;
801 125378 : sSymbol += OUString(cToken);
802 : }
803 686976 : break;
804 : }
805 2297933 : break;
806 : case SsGetChar:
807 1481 : sSymbol += OUString(cToken);
808 1481 : eState = SsStop;
809 1481 : break;
810 : case SsGetString:
811 5135 : if (cToken == '"')
812 : {
813 2205 : eState = SsStop;
814 : }
815 5135 : sSymbol += OUString(cToken);
816 5135 : break;
817 : case SsGetWord:
818 108729 : if ( pChrCls->isLetter( rStr, nPos-1 ) )
819 : {
820 108313 : short nTmpType = GetKeyWord( rStr, nPos-1 );
821 108313 : if ( nTmpType )
822 : {
823 : // beginning of keyword, stop scan and put back
824 64942 : eType = NF_SYMBOLTYPE_STRING;
825 64942 : eState = SsStop;
826 64942 : nPos--;
827 : }
828 : else
829 : {
830 43371 : sSymbol += OUString(cToken);
831 : }
832 : }
833 : else
834 : {
835 416 : bool bDontStop = false;
836 : sal_Unicode cNext;
837 416 : switch (cToken)
838 : {
839 : case '/': // AM/PM, A/P
840 0 : cNext = rStr[nPos];
841 0 : if ( cNext == 'P' || cNext == 'p' )
842 : {
843 0 : sal_Int32 nLen = sSymbol.getLength();
844 0 : if ( 1 <= nLen &&
845 0 : (sSymbol[0] == 'A' || sSymbol[0] == 'a') &&
846 0 : (nLen == 1 ||
847 0 : (nLen == 2 && (sSymbol[1] == 'M' || sSymbol[1] == 'm')
848 0 : && (rStr[nPos + 1] == 'M' || rStr[nPos + 1] == 'm'))))
849 : {
850 0 : sSymbol += OUString(cToken);
851 0 : bDontStop = true;
852 : }
853 : }
854 0 : break;
855 : }
856 : // anything not recognized will stop the scan
857 416 : if ( eState != SsStop && !bDontStop )
858 : {
859 416 : eState = SsStop;
860 416 : nPos--;
861 416 : eType = NF_SYMBOLTYPE_STRING;
862 : }
863 : }
864 108729 : break;
865 : case SsGetStar:
866 13956 : eState = SsStop;
867 13956 : sSymbol += OUString(cToken);
868 13956 : nRepPos = (nPos - nStart) - 1; // everytime > 0!!
869 13956 : break;
870 : case SsGetBlank:
871 10483 : eState = SsStop;
872 10483 : sSymbol += OUString(cToken);
873 10483 : break;
874 : default:
875 0 : break;
876 : } // of switch
877 : } // of while
878 2297933 : if (eState == SsGetWord)
879 : {
880 3120 : eType = NF_SYMBOLTYPE_STRING;
881 : }
882 2297933 : return eType;
883 : }
884 :
885 273386 : sal_Int32 ImpSvNumberformatScan::Symbol_Division(const OUString& rString)
886 : {
887 273386 : nCurrPos = -1;
888 : // Do we have some sort of currency?
889 273386 : OUString sString = pFormatter->GetCharClass()->uppercase(rString);
890 273386 : sal_Int32 nCPos = 0;
891 820611 : while (nCPos >= 0)
892 : {
893 273839 : nCPos = sString.indexOf(GetCurString(),nCPos);
894 273839 : if (nCPos >= 0)
895 : {
896 : // In Quotes?
897 76449 : sal_Int32 nQ = SvNumberformat::GetQuoteEnd( sString, nCPos );
898 76449 : if ( nQ < 0 )
899 : {
900 : sal_Unicode c;
901 212284 : if ( nCPos == 0 ||
902 60228 : ((c = sString[nCPos-1]) != '"'
903 60228 : && c != '\\') ) // dm can be protected by "dm \d
904 : {
905 75996 : nCurrPos = nCPos;
906 75996 : nCPos = -1;
907 : }
908 : else
909 : {
910 64 : nCPos++; // Continue search
911 : }
912 : }
913 : else
914 : {
915 389 : nCPos = nQ + 1; // Continue search
916 : }
917 : }
918 : }
919 273386 : nAnzStrings = 0;
920 273386 : bool bStar = false; // Is set on detecting '*'
921 273386 : Reset();
922 :
923 273386 : sal_Int32 nPos = 0;
924 273386 : const sal_Int32 nLen = rString.getLength();
925 2845045 : while (nPos < nLen && nAnzStrings < NF_MAX_FORMAT_SYMBOLS)
926 : {
927 2298273 : nTypeArray[nAnzStrings] = Next_Symbol(rString, nPos, sStrArray[nAnzStrings]);
928 2298273 : if (nTypeArray[nAnzStrings] == NF_SYMBOLTYPE_STAR)
929 : { // Monitoring the '*'
930 13956 : if (bStar)
931 : {
932 0 : return nPos; // Error: double '*'
933 : }
934 : else
935 : {
936 13956 : bStar = true;
937 : }
938 : }
939 2298273 : nAnzStrings++;
940 : }
941 :
942 273386 : return 0; // 0 => ok
943 : }
944 :
945 1961314 : void ImpSvNumberformatScan::SkipStrings(sal_uInt16& i, sal_Int32& nPos)
946 : {
947 4008811 : while (i < nAnzStrings && ( nTypeArray[i] == NF_SYMBOLTYPE_STRING
948 1712367 : || nTypeArray[i] == NF_SYMBOLTYPE_BLANK
949 1701884 : || nTypeArray[i] == NF_SYMBOLTYPE_STAR) )
950 : {
951 86183 : nPos = nPos + sStrArray[i].getLength();
952 86183 : i++;
953 : }
954 1961314 : }
955 :
956 78122 : sal_uInt16 ImpSvNumberformatScan::PreviousKeyword(sal_uInt16 i)
957 : {
958 78122 : short res = 0;
959 78122 : if (i > 0 && i < nAnzStrings)
960 : {
961 51671 : i--;
962 167677 : while (i > 0 && nTypeArray[i] <= 0)
963 : {
964 64335 : i--;
965 : }
966 51671 : if (nTypeArray[i] > 0)
967 : {
968 51668 : res = nTypeArray[i];
969 : }
970 : }
971 78122 : return res;
972 : }
973 :
974 65481 : sal_uInt16 ImpSvNumberformatScan::NextKeyword(sal_uInt16 i)
975 : {
976 65481 : short res = 0;
977 65481 : if (i < nAnzStrings-1)
978 : {
979 62023 : i++;
980 179621 : while (i < nAnzStrings-1 && nTypeArray[i] <= 0)
981 : {
982 55575 : i++;
983 : }
984 62023 : if (nTypeArray[i] > 0)
985 : {
986 62005 : res = nTypeArray[i];
987 : }
988 : }
989 65481 : return res;
990 : }
991 :
992 51 : short ImpSvNumberformatScan::PreviousType( sal_uInt16 i )
993 : {
994 51 : if ( i > 0 && i < nAnzStrings )
995 : {
996 51 : do
997 : {
998 51 : i--;
999 : }
1000 51 : while ( i > 0 && nTypeArray[i] == NF_SYMBOLTYPE_EMPTY );
1001 51 : return nTypeArray[i];
1002 : }
1003 0 : return 0;
1004 : }
1005 :
1006 162438 : sal_Unicode ImpSvNumberformatScan::PreviousChar(sal_uInt16 i)
1007 : {
1008 162438 : sal_Unicode res = ' ';
1009 162438 : if (i > 0 && i < nAnzStrings)
1010 : {
1011 135987 : i--;
1012 388597 : while (i > 0 &&
1013 233098 : ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
1014 233030 : nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
1015 232974 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1016 116487 : nTypeArray[i] == NF_SYMBOLTYPE_BLANK ))
1017 : {
1018 68 : i--;
1019 : }
1020 135987 : if (sStrArray[i].getLength() > 0)
1021 : {
1022 135987 : res = sStrArray[i][sStrArray[i].getLength()-1];
1023 : }
1024 : }
1025 162438 : return res;
1026 : }
1027 :
1028 109856 : sal_Unicode ImpSvNumberformatScan::NextChar(sal_uInt16 i)
1029 : {
1030 109856 : sal_Unicode res = ' ';
1031 109856 : if (i < nAnzStrings-1)
1032 : {
1033 109856 : i++;
1034 329514 : while (i < nAnzStrings-1 &&
1035 219604 : ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
1036 219604 : nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
1037 219604 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1038 109802 : nTypeArray[i] == NF_SYMBOLTYPE_BLANK))
1039 : {
1040 0 : i++;
1041 : }
1042 109856 : if (sStrArray[i].getLength() > 0)
1043 : {
1044 109856 : res = sStrArray[i][0];
1045 : }
1046 : }
1047 109856 : return res;
1048 : }
1049 :
1050 12 : bool ImpSvNumberformatScan::IsLastBlankBeforeFrac(sal_uInt16 i)
1051 : {
1052 12 : bool res = true;
1053 12 : if (i < nAnzStrings-1)
1054 : {
1055 12 : bool bStop = false;
1056 12 : i++;
1057 42 : while (i < nAnzStrings-1 && !bStop)
1058 : {
1059 18 : i++;
1060 36 : if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
1061 18 : sStrArray[i][0] == '/')
1062 : {
1063 12 : bStop = true;
1064 : }
1065 12 : else if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
1066 6 : sStrArray[i][0] == ' ')
1067 : {
1068 0 : res = false;
1069 : }
1070 : }
1071 12 : if (!bStop) // no '/'{
1072 : {
1073 0 : res = false;
1074 : }
1075 : }
1076 : else
1077 : {
1078 0 : res = false; // no '/' any more
1079 : }
1080 12 : return res;
1081 : }
1082 :
1083 278678 : void ImpSvNumberformatScan::Reset()
1084 : {
1085 278678 : nAnzStrings = 0;
1086 278678 : nAnzResStrings = 0;
1087 278678 : eScannedType = NUMBERFORMAT_UNDEFINED;
1088 278678 : nRepPos = 0;
1089 278678 : bExp = false;
1090 278678 : bThousand = false;
1091 278678 : nThousand = 0;
1092 278678 : bDecSep = false;
1093 278678 : nDecPos = (sal_uInt16)-1;
1094 278678 : nExpPos = (sal_uInt16)-1;
1095 278678 : nBlankPos = (sal_uInt16)-1;
1096 278678 : nCntPre = 0;
1097 278678 : nCntPost = 0;
1098 278678 : nCntExp = 0;
1099 278678 : bFrac = false;
1100 278678 : bBlank = false;
1101 278678 : nNatNumModifier = 0;
1102 278678 : }
1103 :
1104 19071 : bool ImpSvNumberformatScan::Is100SecZero( sal_uInt16 i, bool bHadDecSep )
1105 : {
1106 19071 : sal_uInt16 nIndexPre = PreviousKeyword( i );
1107 38142 : return (nIndexPre == NF_KEY_S || nIndexPre == NF_KEY_SS) &&
1108 6 : (bHadDecSep ||
1109 19077 : ( i > 0 && nTypeArray[i-1] == NF_SYMBOLTYPE_STRING));
1110 : // SS"any"00 take "any" as a valid decimal separator
1111 : }
1112 :
1113 273386 : sal_Int32 ImpSvNumberformatScan::ScanType()
1114 : {
1115 273386 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1116 :
1117 273386 : sal_Int32 nPos = 0;
1118 273386 : sal_uInt16 i = 0;
1119 : short eNewType;
1120 273386 : bool bMatchBracket = false;
1121 273386 : bool bHaveGeneral = false; // if General/Standard encountered
1122 :
1123 273386 : SkipStrings(i, nPos);
1124 2234700 : while (i < nAnzStrings)
1125 : {
1126 1687928 : if (nTypeArray[i] > 0)
1127 : { // keyword
1128 : sal_uInt16 nIndexPre;
1129 : sal_uInt16 nIndexNex;
1130 : sal_Unicode cChar;
1131 :
1132 400460 : switch (nTypeArray[i])
1133 : {
1134 : case NF_KEY_E: // E
1135 6326 : eNewType = NUMBERFORMAT_SCIENTIFIC;
1136 6326 : break;
1137 : case NF_KEY_AMPM: // AM,A,PM,P
1138 : case NF_KEY_AP:
1139 : case NF_KEY_H: // H
1140 : case NF_KEY_HH: // HH
1141 : case NF_KEY_S: // S
1142 : case NF_KEY_SS: // SS
1143 55233 : eNewType = NUMBERFORMAT_TIME;
1144 55233 : break;
1145 : case NF_KEY_M: // M
1146 : case NF_KEY_MM: // MM
1147 : // minute or month
1148 59051 : nIndexPre = PreviousKeyword(i);
1149 59051 : nIndexNex = NextKeyword(i);
1150 59051 : cChar = PreviousChar(i);
1151 59051 : if (nIndexPre == NF_KEY_H || // H
1152 33083 : nIndexPre == NF_KEY_HH || // HH
1153 33083 : nIndexNex == NF_KEY_S || // S
1154 29539 : nIndexNex == NF_KEY_SS || // SS
1155 : cChar == '[' ) // [M
1156 : {
1157 29512 : eNewType = NUMBERFORMAT_TIME;
1158 29512 : nTypeArray[i] -= 2; // 6 -> 4, 7 -> 5
1159 : }
1160 : else
1161 : {
1162 29539 : eNewType = NUMBERFORMAT_DATE;
1163 : }
1164 59051 : break;
1165 : case NF_KEY_MMM: // MMM
1166 : case NF_KEY_MMMM: // MMMM
1167 : case NF_KEY_MMMMM: // MMMMM
1168 : case NF_KEY_Q: // Q
1169 : case NF_KEY_QQ: // QQ
1170 : case NF_KEY_D: // D
1171 : case NF_KEY_DD: // DD
1172 : case NF_KEY_DDD: // DDD
1173 : case NF_KEY_DDDD: // DDDD
1174 : case NF_KEY_YY: // YY
1175 : case NF_KEY_YYYY: // YYYY
1176 : case NF_KEY_NN: // NN
1177 : case NF_KEY_NNN: // NNN
1178 : case NF_KEY_NNNN: // NNNN
1179 : case NF_KEY_WW : // WW
1180 : case NF_KEY_AAA : // AAA
1181 : case NF_KEY_AAAA : // AAAA
1182 : case NF_KEY_EC : // E
1183 : case NF_KEY_EEC : // EE
1184 : case NF_KEY_G : // G
1185 : case NF_KEY_GG : // GG
1186 : case NF_KEY_GGG : // GGG
1187 : case NF_KEY_R : // R
1188 : case NF_KEY_RR : // RR
1189 273561 : eNewType = NUMBERFORMAT_DATE;
1190 273561 : break;
1191 : case NF_KEY_CCC: // CCC
1192 3104 : eNewType = NUMBERFORMAT_CURRENCY;
1193 3104 : break;
1194 : case NF_KEY_GENERAL: // Standard
1195 3185 : eNewType = NUMBERFORMAT_NUMBER;
1196 3185 : bHaveGeneral = true;
1197 3185 : break;
1198 : default:
1199 0 : eNewType = NUMBERFORMAT_UNDEFINED;
1200 0 : break;
1201 : }
1202 : }
1203 : else
1204 : { // control character
1205 1287468 : switch ( sStrArray[i][0] )
1206 : {
1207 : case '#':
1208 : case '?':
1209 354238 : eNewType = NUMBERFORMAT_NUMBER;
1210 354238 : break;
1211 : case '0':
1212 278346 : if ( (eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME )
1213 : {
1214 12641 : if ( Is100SecZero( i, bDecSep ) )
1215 : {
1216 12641 : bDecSep = true; // subsequent 0's
1217 12641 : eNewType = NUMBERFORMAT_TIME;
1218 : }
1219 : else
1220 : {
1221 0 : return nPos; // Error
1222 : }
1223 : }
1224 : else
1225 : {
1226 265705 : eNewType = NUMBERFORMAT_NUMBER;
1227 : }
1228 278346 : break;
1229 : case '%':
1230 6239 : eNewType = NUMBERFORMAT_PERCENT;
1231 6239 : break;
1232 : case '/':
1233 52507 : eNewType = NUMBERFORMAT_FRACTION;
1234 52507 : break;
1235 : case '[':
1236 243960 : if ( i < nAnzStrings-1 &&
1237 156210 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1238 74890 : sStrArray[i+1][0] == '$' )
1239 : { // as of SV_NUMBERFORMATTER_VERSION_NEW_CURR
1240 44233 : eNewType = NUMBERFORMAT_CURRENCY;
1241 44233 : bMatchBracket = true;
1242 : }
1243 111261 : else if ( i < nAnzStrings-1 &&
1244 67744 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1245 30657 : sStrArray[i+1][0] == '~' )
1246 : { // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1247 30657 : eNewType = NUMBERFORMAT_DATE;
1248 30657 : bMatchBracket = true;
1249 : }
1250 : else
1251 : {
1252 6430 : sal_uInt16 nIndexNex = NextKeyword(i);
1253 6430 : if (nIndexNex == NF_KEY_H || // H
1254 0 : nIndexNex == NF_KEY_HH || // HH
1255 0 : nIndexNex == NF_KEY_M || // M
1256 0 : nIndexNex == NF_KEY_MM || // MM
1257 0 : nIndexNex == NF_KEY_S || // S
1258 : nIndexNex == NF_KEY_SS ) // SS
1259 6430 : eNewType = NUMBERFORMAT_TIME;
1260 : else
1261 : {
1262 0 : return nPos; // Error
1263 : }
1264 : }
1265 81320 : break;
1266 : case '@':
1267 3654 : eNewType = NUMBERFORMAT_TEXT;
1268 3654 : break;
1269 : default:
1270 511164 : if (pLoc->getTime100SecSep().equals(sStrArray[i]))
1271 : {
1272 89960 : bDecSep = true; // for SS,0
1273 : }
1274 511164 : eNewType = NUMBERFORMAT_UNDEFINED;
1275 511164 : break;
1276 : }
1277 : }
1278 1687928 : if (eScannedType == NUMBERFORMAT_UNDEFINED)
1279 : {
1280 310872 : eScannedType = eNewType;
1281 : }
1282 1377056 : else if (eScannedType == NUMBERFORMAT_TEXT || eNewType == NUMBERFORMAT_TEXT)
1283 : {
1284 43 : eScannedType = NUMBERFORMAT_TEXT; // Text always remains text
1285 : }
1286 1377013 : else if (eNewType == NUMBERFORMAT_UNDEFINED)
1287 : { // Remains as is
1288 : }
1289 903748 : else if (eScannedType != eNewType)
1290 : {
1291 331552 : switch (eScannedType)
1292 : {
1293 : case NUMBERFORMAT_DATE:
1294 46477 : switch (eNewType)
1295 : {
1296 : case NUMBERFORMAT_TIME:
1297 6392 : eScannedType = NUMBERFORMAT_DATETIME;
1298 6392 : break;
1299 : case NUMBERFORMAT_FRACTION: // DD/MM
1300 40085 : break;
1301 : default:
1302 0 : if (nCurrPos >= 0)
1303 : {
1304 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1305 : }
1306 0 : else if ( sStrArray[i] != OUString(pFormatter->GetDateSep()) )
1307 : {
1308 0 : return nPos;
1309 : }
1310 : }
1311 46477 : break;
1312 : case NUMBERFORMAT_TIME:
1313 0 : switch (eNewType)
1314 : {
1315 : case NUMBERFORMAT_DATE:
1316 0 : eScannedType = NUMBERFORMAT_DATETIME;
1317 0 : break;
1318 : case NUMBERFORMAT_FRACTION: // MM/SS
1319 0 : break;
1320 : default:
1321 0 : if (nCurrPos >= 0)
1322 : {
1323 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1324 : }
1325 0 : else if (!pLoc->getTimeSep().equals(sStrArray[i]))
1326 : {
1327 0 : return nPos;
1328 : }
1329 0 : break;
1330 : }
1331 0 : break;
1332 : case NUMBERFORMAT_DATETIME:
1333 12564 : switch (eNewType)
1334 : {
1335 : case NUMBERFORMAT_TIME:
1336 : case NUMBERFORMAT_DATE:
1337 12564 : break;
1338 : case NUMBERFORMAT_FRACTION: // DD/MM
1339 0 : break;
1340 : default:
1341 0 : if (nCurrPos >= 0)
1342 : {
1343 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1344 : }
1345 0 : else if ( OUString(pFormatter->GetDateSep()) != sStrArray[i] &&
1346 0 : !pLoc->getTimeSep().equals(sStrArray[i]) )
1347 : {
1348 0 : return nPos;
1349 : }
1350 : }
1351 12564 : break;
1352 : case NUMBERFORMAT_PERCENT:
1353 0 : switch (eNewType)
1354 : {
1355 : case NUMBERFORMAT_NUMBER: // Only number to percent
1356 0 : break;
1357 : default:
1358 0 : return nPos;
1359 : }
1360 0 : break;
1361 : case NUMBERFORMAT_SCIENTIFIC:
1362 15643 : switch (eNewType)
1363 : {
1364 : case NUMBERFORMAT_NUMBER: // Only number to E
1365 15643 : break;
1366 : default:
1367 0 : return nPos;
1368 : }
1369 15643 : break;
1370 : case NUMBERFORMAT_NUMBER:
1371 28599 : switch (eNewType)
1372 : {
1373 : case NUMBERFORMAT_SCIENTIFIC:
1374 : case NUMBERFORMAT_PERCENT:
1375 : case NUMBERFORMAT_FRACTION:
1376 : case NUMBERFORMAT_CURRENCY:
1377 28599 : eScannedType = eNewType;
1378 28599 : break;
1379 : default:
1380 0 : if (nCurrPos >= 0)
1381 : {
1382 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1383 : }
1384 : else
1385 : {
1386 0 : return nPos;
1387 : }
1388 : }
1389 28599 : break;
1390 : case NUMBERFORMAT_FRACTION:
1391 15523 : switch (eNewType)
1392 : {
1393 : case NUMBERFORMAT_NUMBER: // Only number to fraction
1394 15523 : break;
1395 : default:
1396 0 : return nPos;
1397 : }
1398 15523 : break;
1399 : default:
1400 212746 : break;
1401 : }
1402 : }
1403 1687928 : nPos = nPos + sStrArray[i].getLength(); // Position of correction
1404 1687928 : i++;
1405 1687928 : if ( bMatchBracket )
1406 : { // no type detection inside of matching brackets if [$...], [~...]
1407 673942 : while ( bMatchBracket && i < nAnzStrings )
1408 : {
1409 1048324 : if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL
1410 524162 : && sStrArray[i][0] == ']' )
1411 : {
1412 74890 : bMatchBracket = false;
1413 : }
1414 : else
1415 : {
1416 449272 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1417 : }
1418 524162 : nPos = nPos + sStrArray[i].getLength();
1419 524162 : i++;
1420 : }
1421 74890 : if ( bMatchBracket )
1422 : {
1423 0 : return nPos; // missing closing bracket at end of code
1424 : }
1425 : }
1426 1687928 : SkipStrings(i, nPos);
1427 : }
1428 :
1429 480555 : if ((eScannedType == NUMBERFORMAT_NUMBER ||
1430 273759 : eScannedType == NUMBERFORMAT_UNDEFINED) &&
1431 98401 : nCurrPos >= 0 && !bHaveGeneral)
1432 : {
1433 31811 : eScannedType = NUMBERFORMAT_CURRENCY; // old "automatic" currency
1434 : }
1435 273386 : if (eScannedType == NUMBERFORMAT_UNDEFINED)
1436 : {
1437 359 : eScannedType = NUMBERFORMAT_DEFINED;
1438 : }
1439 273386 : return 0; // All is fine
1440 : }
1441 :
1442 103324 : bool ImpSvNumberformatScan::InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr )
1443 : {
1444 103324 : if (nAnzStrings >= NF_MAX_FORMAT_SYMBOLS || nPos > nAnzStrings)
1445 : {
1446 0 : return false;
1447 : }
1448 103324 : if (nPos > 0 && nTypeArray[nPos-1] == NF_SYMBOLTYPE_EMPTY)
1449 : {
1450 103324 : --nPos; // reuse position
1451 : }
1452 : else
1453 : {
1454 0 : if ((size_t) (nAnzStrings + 1) >= NF_MAX_FORMAT_SYMBOLS)
1455 : {
1456 0 : return false;
1457 : }
1458 0 : ++nAnzStrings;
1459 0 : for (size_t i = nAnzStrings; i > nPos; --i)
1460 : {
1461 0 : nTypeArray[i] = nTypeArray[i-1];
1462 0 : sStrArray[i] = sStrArray[i-1];
1463 : }
1464 : }
1465 103324 : ++nAnzResStrings;
1466 103324 : nTypeArray[nPos] = static_cast<short>(eType);
1467 103324 : sStrArray[nPos] = rStr;
1468 103324 : return true;
1469 : }
1470 :
1471 241778 : int ImpSvNumberformatScan::FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i,
1472 : sal_uInt16& rAnzResStrings )
1473 : {
1474 725334 : if ( i < nAnzStrings-1 &&
1475 272435 : sStrArray[i][0] == '[' &&
1476 303092 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1477 30657 : sStrArray[i+1][0] == '~' )
1478 : {
1479 : // [~calendarID]
1480 : // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1481 30657 : nPos = nPos + sStrArray[i].getLength(); // [
1482 30657 : nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
1483 30657 : nPos = nPos + sStrArray[++i].getLength(); // ~
1484 30657 : sStrArray[i-1] += sStrArray[i]; // [~
1485 30657 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1486 30657 : rAnzResStrings--;
1487 30657 : if ( ++i >= nAnzStrings )
1488 : {
1489 0 : return -1; // error
1490 : }
1491 30657 : nPos = nPos + sStrArray[i].getLength(); // calendarID
1492 30657 : OUString& rStr = sStrArray[i];
1493 30657 : nTypeArray[i] = NF_SYMBOLTYPE_CALENDAR; // convert
1494 30657 : i++;
1495 184029 : while ( i < nAnzStrings && sStrArray[i][0] != ']' )
1496 : {
1497 122715 : nPos = nPos + sStrArray[i].getLength();
1498 122715 : rStr += sStrArray[i];
1499 122715 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1500 122715 : rAnzResStrings--;
1501 122715 : i++;
1502 : }
1503 61314 : if ( rStr.getLength() && i < nAnzStrings &&
1504 30657 : sStrArray[i][0] == ']' )
1505 : {
1506 30657 : nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
1507 30657 : nPos = nPos + sStrArray[i].getLength();
1508 30657 : i++;
1509 : }
1510 : else
1511 : {
1512 0 : return -1; // error
1513 : }
1514 30657 : return 1;
1515 : }
1516 211121 : return 0;
1517 : }
1518 :
1519 273386 : sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
1520 : {
1521 273386 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1522 :
1523 : // save values for convert mode
1524 273386 : OUString sOldDecSep = pFormatter->GetNumDecimalSep();
1525 546772 : OUString sOldThousandSep = pFormatter->GetNumThousandSep();
1526 546772 : OUString sOldDateSep = pFormatter->GetDateSep();
1527 546772 : OUString sOldTimeSep = pLoc->getTimeSep();
1528 546772 : OUString sOldTime100SecSep= pLoc->getTime100SecSep();
1529 546772 : OUString sOldCurSymbol = GetCurSymbol();
1530 546772 : OUString sOldCurString = GetCurString();
1531 273386 : sal_Unicode cOldKeyH = sKeyword[NF_KEY_H][0];
1532 273386 : sal_Unicode cOldKeyMI = sKeyword[NF_KEY_MI][0];
1533 273386 : sal_Unicode cOldKeyS = sKeyword[NF_KEY_S][0];
1534 :
1535 : // If the group separator is a No-Break Space (French) continue with a
1536 : // normal space instead so queries on space work correctly.
1537 : // The same for Narrow No-Break Space just in case some locale uses it.
1538 : // The format string is adjusted to allow both.
1539 : // For output of the format code string the LocaleData characters are used.
1540 273613 : if ( (sOldThousandSep[0] == cNoBreakSpace || sOldThousandSep[0] == cNarrowNoBreakSpace) &&
1541 227 : sOldThousandSep.getLength() == 1 )
1542 : {
1543 227 : sOldThousandSep = " ";
1544 : }
1545 : // change locale data et al
1546 273386 : if (bConvertMode)
1547 : {
1548 8399 : pFormatter->ChangeIntl(eNewLnge);
1549 : //! pointer may have changed
1550 8399 : pLoc = pFormatter->GetLocaleData();
1551 : //! init new keywords
1552 8399 : InitKeywords();
1553 : }
1554 273386 : const CharClass* pChrCls = pFormatter->GetCharClass();
1555 :
1556 273386 : sal_Int32 nPos = 0; // error correction position
1557 273386 : sal_uInt16 i = 0; // symbol loop counter
1558 273386 : sal_uInt16 nCounter = 0; // counts digits
1559 273386 : nAnzResStrings = nAnzStrings; // counts remaining symbols
1560 273386 : bDecSep = false; // reset in case already used in TypeCheck
1561 273386 : bool bThaiT = false; // Thai T NatNum modifier present
1562 273386 : bool bTimePart = false;
1563 :
1564 273386 : switch (eScannedType)
1565 : {
1566 : case NUMBERFORMAT_TEXT:
1567 : case NUMBERFORMAT_DEFINED:
1568 13980 : while (i < nAnzStrings)
1569 : {
1570 5954 : switch (nTypeArray[i])
1571 : {
1572 : case NF_SYMBOLTYPE_BLANK:
1573 : case NF_SYMBOLTYPE_STAR:
1574 1740 : break;
1575 : case NF_KEY_GENERAL : // #77026# "General" is the same as "@"
1576 0 : break;
1577 : default:
1578 7951 : if ( nTypeArray[i] != NF_SYMBOLTYPE_DEL ||
1579 3737 : sStrArray[i][0] != '@' )
1580 : {
1581 560 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1582 : }
1583 4214 : break;
1584 : }
1585 5954 : nPos = nPos + sStrArray[i].getLength();
1586 5954 : i++;
1587 : } // of while
1588 4013 : break;
1589 :
1590 : case NUMBERFORMAT_NUMBER:
1591 : case NUMBERFORMAT_PERCENT:
1592 : case NUMBERFORMAT_CURRENCY:
1593 : case NUMBERFORMAT_SCIENTIFIC:
1594 : case NUMBERFORMAT_FRACTION:
1595 1012340 : while (i < nAnzStrings)
1596 : {
1597 : // TODO: rechecking eScannedType is unnecessary.
1598 : // This switch-case is for eScannedType == NUMBERFORMAT_FRACTION anyway
1599 1544971 : if (eScannedType == NUMBERFORMAT_FRACTION && // special case
1600 130382 : nTypeArray[i] == NF_SYMBOLTYPE_DEL && // # ### #/#
1601 55937 : StringEqualsChar( sOldThousandSep, ' ' ) && // e.g. France or Sweden
1602 66 : StringEqualsChar( sStrArray[i], ' ' ) &&
1603 735260 : !bFrac &&
1604 12 : IsLastBlankBeforeFrac(i) )
1605 : {
1606 12 : nTypeArray[i] = NF_SYMBOLTYPE_STRING; // del->string
1607 : } // No thousands marker
1608 :
1609 1461471 : if (nTypeArray[i] == NF_SYMBOLTYPE_BLANK ||
1610 1438772 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1611 1421970 : nTypeArray[i] == NF_KEY_CCC || // CCC
1612 709433 : nTypeArray[i] == NF_KEY_GENERAL ) // Standard
1613 : {
1614 28988 : if (nTypeArray[i] == NF_KEY_GENERAL)
1615 : {
1616 3185 : nThousand = FLAG_STANDARD_IN_FORMAT;
1617 3185 : if ( bConvertMode )
1618 : {
1619 77 : sStrArray[i] = sNameStandardFormat;
1620 : }
1621 : }
1622 28988 : nPos = nPos + sStrArray[i].getLength();
1623 28988 : i++;
1624 : }
1625 1345338 : else if (nTypeArray[i] == NF_SYMBOLTYPE_STRING || // No Strings or
1626 639090 : nTypeArray[i] > 0) // Keywords
1627 : {
1628 79810 : if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
1629 6326 : nTypeArray[i] == NF_KEY_E) // E+
1630 : {
1631 6326 : if (bExp) // Double
1632 : {
1633 0 : return nPos;
1634 : }
1635 6326 : bExp = true;
1636 6326 : nExpPos = i;
1637 6326 : if (bDecSep)
1638 : {
1639 6325 : nCntPost = nCounter;
1640 : }
1641 : else
1642 : {
1643 1 : nCntPre = nCounter;
1644 : }
1645 6326 : nCounter = 0;
1646 6326 : nTypeArray[i] = NF_SYMBOLTYPE_EXP;
1647 : }
1648 85786 : else if (eScannedType == NUMBERFORMAT_FRACTION &&
1649 18628 : sStrArray[i][0] == ' ')
1650 : {
1651 12416 : if (!bBlank && !bFrac) // Not double or after a /
1652 : {
1653 12 : if (bDecSep && nCounter > 0) // Decimal places
1654 : {
1655 0 : return nPos; // Error
1656 : }
1657 12 : bBlank = true;
1658 12 : nBlankPos = i;
1659 12 : nCntPre = nCounter;
1660 12 : nCounter = 0;
1661 : }
1662 12416 : nTypeArray[i] = NF_SYMBOLTYPE_FRACBLANK;
1663 : }
1664 54742 : else if (nTypeArray[i] == NF_KEY_THAI_T)
1665 : {
1666 0 : bThaiT = true;
1667 0 : sStrArray[i] = sKeyword[nTypeArray[i]];
1668 : }
1669 62818 : else if (sStrArray[i][0] >= '0' &&
1670 8076 : sStrArray[i][0] <= '9')
1671 : {
1672 6209 : OUString sDiv;
1673 6209 : sal_uInt16 j = i;
1674 24836 : while(j < nAnzStrings)
1675 : {
1676 12418 : sDiv += sStrArray[j++];
1677 : }
1678 6209 : if (OUString::number(sDiv.toInt32()) == sDiv)
1679 : {
1680 : // Found a Divisor
1681 24836 : while (i < j)
1682 : {
1683 12418 : nTypeArray[i++] = NF_SYMBOLTYPE_FRAC_FDIV;
1684 : }
1685 6209 : i = j - 1; // Stop the loop
1686 6209 : if (nCntPost)
1687 : {
1688 6209 : nCounter = nCntPost;
1689 : }
1690 0 : else if (nCntPre)
1691 : {
1692 0 : nCounter = nCntPre;
1693 : }
1694 : // don't artificially increment nCntPre for forced denominator
1695 6209 : if ( ( eScannedType != NUMBERFORMAT_FRACTION ) && (!nCntPre) )
1696 : {
1697 0 : nCntPre++;
1698 : }
1699 6209 : }
1700 : }
1701 : else
1702 : {
1703 48533 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1704 : }
1705 73484 : nPos = nPos + sStrArray[i].getLength();
1706 73484 : i++;
1707 : }
1708 632764 : else if (nTypeArray[i] == NF_SYMBOLTYPE_DEL)
1709 : {
1710 632764 : sal_Unicode cHere = sStrArray[i][0];
1711 632764 : sal_Unicode cSaved = cHere;
1712 : // Handle not pre-known separators in switch.
1713 : sal_Unicode cSimplified;
1714 632764 : if (StringEqualsChar( pFormatter->GetNumThousandSep(), cHere))
1715 : {
1716 103232 : cSimplified = ',';
1717 : }
1718 529532 : else if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cHere))
1719 : {
1720 74251 : cSimplified = '.';
1721 : }
1722 : else
1723 : {
1724 455281 : cSimplified = cHere;
1725 : }
1726 :
1727 632764 : OUString& rStr = sStrArray[i];
1728 :
1729 632764 : switch ( cSimplified )
1730 : {
1731 : case '#':
1732 : case '0':
1733 : case '?':
1734 325467 : if (nThousand > 0) // #... #
1735 : {
1736 0 : return nPos; // Error
1737 : }
1738 325467 : else if (bFrac && cHere == '0')
1739 : {
1740 0 : return nPos; // Denominator is 0
1741 : }
1742 325467 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1743 325467 : nPos = nPos + rStr.getLength();
1744 325467 : i++;
1745 325467 : nCounter++;
1746 1749969 : while (i < nAnzStrings &&
1747 938422 : (sStrArray[i][0] == '#' ||
1748 659715 : sStrArray[i][0] == '0' ||
1749 243792 : sStrArray[i][0] == '?'))
1750 : {
1751 288268 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1752 288268 : nPos = nPos + sStrArray[i].getLength();
1753 288268 : nCounter++;
1754 288268 : i++;
1755 : }
1756 325467 : break;
1757 : case '-':
1758 75112 : if ( bDecSep && nDecPos+1 == i &&
1759 12416 : nTypeArray[nDecPos] == NF_SYMBOLTYPE_DECSEP )
1760 : {
1761 : // "0.--"
1762 12416 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1763 12416 : nPos = nPos + rStr.getLength();
1764 12416 : i++;
1765 12416 : nCounter++;
1766 49732 : while (i < nAnzStrings &&
1767 12484 : (sStrArray[i][0] == '-') )
1768 : {
1769 : // If more than two dashes are present in
1770 : // currency formats the last dash will be
1771 : // interpreted literally as a minus sign.
1772 : // Has to be this ugly. Period.
1773 24832 : if ( eScannedType == NUMBERFORMAT_CURRENCY
1774 12416 : && rStr.getLength() >= 2 &&
1775 0 : (i == nAnzStrings-1 ||
1776 0 : sStrArray[i+1][0] != '-') )
1777 : {
1778 0 : break;
1779 : }
1780 12416 : rStr += sStrArray[i];
1781 12416 : nPos = nPos + sStrArray[i].getLength();
1782 12416 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1783 12416 : nAnzResStrings--;
1784 12416 : nCounter++;
1785 12416 : i++;
1786 : }
1787 : }
1788 : else
1789 : {
1790 37864 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1791 37864 : nPos = nPos + sStrArray[i].getLength();
1792 37864 : i++;
1793 : }
1794 50280 : break;
1795 : case '.':
1796 : case ',':
1797 : case '\'':
1798 : case ' ':
1799 194126 : if ( StringEqualsChar( sOldThousandSep, cSaved ) )
1800 : {
1801 : // previous char with skip empty
1802 103387 : sal_Unicode cPre = PreviousChar(i);
1803 : sal_Unicode cNext;
1804 103387 : if (bExp || bBlank || bFrac)
1805 : {
1806 : // after E, / or ' '
1807 0 : if ( !StringEqualsChar( sOldThousandSep, ' ' ) )
1808 : {
1809 0 : nPos = nPos + sStrArray[i].getLength();
1810 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1811 0 : nAnzResStrings--;
1812 0 : i++; // eat it
1813 : }
1814 : else
1815 : {
1816 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1817 : }
1818 : }
1819 310161 : else if (i > 0 && i < nAnzStrings-1 &&
1820 310149 : (cPre == '#' || cPre == '0') &&
1821 103426 : ((cNext = NextChar(i)) == '#' || cNext == '0')) // #,#
1822 : {
1823 103324 : nPos = nPos + sStrArray[i].getLength();
1824 103324 : if (!bThousand) // only once
1825 : {
1826 103324 : bThousand = true;
1827 : }
1828 : // Eat it, will be reinserted at proper grouping positions further down.
1829 103324 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1830 103324 : nAnzResStrings--;
1831 103324 : i++;
1832 : }
1833 189 : else if (i > 0 && (cPre == '#' || cPre == '0')
1834 51 : && PreviousType(i) == NF_SYMBOLTYPE_DIGIT
1835 114 : && nThousand < FLAG_STANDARD_IN_FORMAT )
1836 : { // #,,,,
1837 51 : if ( StringEqualsChar( sOldThousandSep, ' ' ) )
1838 : {
1839 : // strange, those French..
1840 51 : bool bFirst = true;
1841 : // set a hard No-Break Space or ConvertMode
1842 51 : const OUString& rSepF = pFormatter->GetNumThousandSep();
1843 204 : while ( i < nAnzStrings &&
1844 102 : sStrArray[i] == sOldThousandSep &&
1845 51 : StringEqualsChar( sOldThousandSep, NextChar(i) ) )
1846 : { // last was a space or another space
1847 : // is following => separator
1848 0 : nPos = nPos + sStrArray[i].getLength();
1849 0 : if ( bFirst )
1850 : {
1851 0 : bFirst = false;
1852 0 : rStr = rSepF;
1853 0 : nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
1854 : }
1855 : else
1856 : {
1857 0 : rStr += rSepF;
1858 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1859 0 : nAnzResStrings--;
1860 : }
1861 0 : nThousand++;
1862 0 : i++;
1863 : }
1864 102 : if ( i < nAnzStrings-1 &&
1865 51 : sStrArray[i] == sOldThousandSep )
1866 : {
1867 : // something following last space
1868 : // => space if currency contained,
1869 : // else separator
1870 51 : nPos = nPos + sStrArray[i].getLength();
1871 150 : if ( (nPos <= nCurrPos &&
1872 75 : nCurrPos < nPos + sStrArray[i+1].getLength()) ||
1873 153 : nTypeArray[i+1] == NF_KEY_CCC ||
1874 48 : (i < nAnzStrings-2 &&
1875 48 : sStrArray[i+1][0] == '[' &&
1876 24 : sStrArray[i+2][0] == '$') )
1877 : {
1878 51 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1879 : }
1880 : else
1881 : {
1882 0 : if ( bFirst )
1883 : {
1884 0 : bFirst = false;
1885 0 : rStr = rSepF;
1886 0 : nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
1887 : }
1888 : else
1889 : {
1890 0 : rStr += rSepF;
1891 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1892 0 : nAnzResStrings--;
1893 : }
1894 0 : nThousand++;
1895 : }
1896 51 : i++;
1897 : }
1898 : }
1899 : else
1900 : {
1901 0 : do
1902 : {
1903 0 : nThousand++;
1904 0 : nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
1905 0 : nPos = nPos + sStrArray[i].getLength();
1906 0 : sStrArray[i] = pFormatter->GetNumThousandSep();
1907 0 : i++;
1908 : }
1909 0 : while (i < nAnzStrings && sStrArray[i] == sOldThousandSep);
1910 : }
1911 : }
1912 : else // any grsep
1913 : {
1914 12 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1915 12 : nPos = nPos + rStr.getLength();
1916 12 : i++;
1917 24 : while ( i < nAnzStrings && sStrArray[i] == sOldThousandSep )
1918 : {
1919 0 : rStr += sStrArray[i];
1920 0 : nPos = nPos + sStrArray[i].getLength();
1921 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1922 0 : nAnzResStrings--;
1923 0 : i++;
1924 : }
1925 : }
1926 : }
1927 90739 : else if ( StringEqualsChar( sOldDecSep, cSaved ) )
1928 : {
1929 74251 : if (bBlank || bFrac) // . behind / or ' '
1930 : {
1931 0 : return nPos; // error
1932 : }
1933 74251 : else if (bExp) // behind E
1934 : {
1935 0 : nPos = nPos + sStrArray[i].getLength();
1936 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1937 0 : nAnzResStrings--;
1938 0 : i++; // eat it
1939 : }
1940 74251 : else if (bDecSep) // any .
1941 : {
1942 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1943 0 : nPos = nPos + rStr.getLength();
1944 0 : i++;
1945 0 : while ( i < nAnzStrings && sStrArray[i] == sOldDecSep )
1946 : {
1947 0 : rStr += sStrArray[i];
1948 0 : nPos = nPos + sStrArray[i].getLength();
1949 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1950 0 : nAnzResStrings--;
1951 0 : i++;
1952 : }
1953 : }
1954 : else
1955 : {
1956 74251 : nPos = nPos + sStrArray[i].getLength();
1957 74251 : nTypeArray[i] = NF_SYMBOLTYPE_DECSEP;
1958 74251 : sStrArray[i] = pFormatter->GetNumDecimalSep();
1959 74251 : bDecSep = true;
1960 74251 : nDecPos = i;
1961 74251 : nCntPre = nCounter;
1962 74251 : nCounter = 0;
1963 :
1964 74251 : i++;
1965 : }
1966 : } // of else = DecSep
1967 : else // . without meaning
1968 : {
1969 32976 : if (cSaved == ' ' &&
1970 28892 : eScannedType == NUMBERFORMAT_FRACTION &&
1971 12404 : StringEqualsChar( sStrArray[i], ' ' ) )
1972 : {
1973 12404 : if (!bBlank && !bFrac) // no dups
1974 : { // or behind /
1975 12404 : if (bDecSep && nCounter > 0) // dec.
1976 : {
1977 0 : return nPos; // error
1978 : }
1979 12404 : bBlank = true;
1980 12404 : nBlankPos = i;
1981 12404 : nCntPre = nCounter;
1982 12404 : nCounter = 0;
1983 : }
1984 12404 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1985 12404 : nPos = nPos + sStrArray[i].getLength();
1986 : }
1987 : else
1988 : {
1989 4084 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1990 4084 : nPos = nPos + rStr.getLength();
1991 4084 : i++;
1992 8168 : while (i < nAnzStrings && StringEqualsChar( sStrArray[i], cSaved ) )
1993 : {
1994 0 : rStr += sStrArray[i];
1995 0 : nPos = nPos + sStrArray[i].getLength();
1996 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1997 0 : nAnzResStrings--;
1998 0 : i++;
1999 : }
2000 : }
2001 : }
2002 194126 : break;
2003 : case '/':
2004 12419 : if (eScannedType == NUMBERFORMAT_FRACTION)
2005 : {
2006 24838 : if ( i == 0 ||
2007 12419 : (nTypeArray[i-1] != NF_SYMBOLTYPE_DIGIT &&
2008 0 : nTypeArray[i-1] != NF_SYMBOLTYPE_EMPTY) )
2009 : {
2010 0 : return nPos ? nPos : 1; // /? not allowed
2011 : }
2012 12419 : else if (!bFrac || (bDecSep && nCounter > 0))
2013 : {
2014 12419 : bFrac = true;
2015 12419 : nCntPost = nCounter;
2016 12419 : nCounter = 0;
2017 12419 : nTypeArray[i] = NF_SYMBOLTYPE_FRAC;
2018 12419 : nPos = nPos + sStrArray[i].getLength();
2019 12419 : i++;
2020 : }
2021 : else // / double or in , in the denominator
2022 : {
2023 0 : return nPos; // Error
2024 : }
2025 : }
2026 : else
2027 : {
2028 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2029 0 : nPos = nPos + sStrArray[i].getLength();
2030 0 : i++;
2031 : }
2032 12419 : break;
2033 : case '[' :
2034 132699 : if ( eScannedType == NUMBERFORMAT_CURRENCY &&
2035 88466 : i < nAnzStrings-1 &&
2036 132699 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
2037 44233 : sStrArray[i+1][0] == '$' )
2038 : {
2039 : // [$DM-xxx]
2040 : // As of SV_NUMBERFORMATTER_VERSION_NEW_CURR
2041 44233 : nPos = nPos + sStrArray[i].getLength(); // [
2042 44233 : nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
2043 44233 : nPos = nPos + sStrArray[++i].getLength(); // $
2044 44233 : sStrArray[i-1] += sStrArray[i]; // [$
2045 44233 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2046 44233 : nAnzResStrings--;
2047 44233 : if ( ++i >= nAnzStrings )
2048 : {
2049 0 : return nPos; // Error
2050 : }
2051 44233 : nPos = nPos + sStrArray[i].getLength(); // DM
2052 44233 : OUString* pStr = &sStrArray[i];
2053 44233 : nTypeArray[i] = NF_SYMBOLTYPE_CURRENCY; // convert
2054 44233 : bool bHadDash = false;
2055 44233 : i++;
2056 265243 : while ( i < nAnzStrings && sStrArray[i][0] != ']' )
2057 : {
2058 176777 : nPos = nPos + sStrArray[i].getLength();
2059 176777 : if ( bHadDash )
2060 : {
2061 131689 : *pStr += sStrArray[i];
2062 131689 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2063 131689 : nAnzResStrings--;
2064 : }
2065 : else
2066 : {
2067 45088 : if ( sStrArray[i][0] == '-' )
2068 : {
2069 43880 : bHadDash = true;
2070 43880 : pStr = &sStrArray[i];
2071 43880 : nTypeArray[i] = NF_SYMBOLTYPE_CURREXT;
2072 : }
2073 : else
2074 : {
2075 1208 : *pStr += sStrArray[i];
2076 1208 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2077 1208 : nAnzResStrings--;
2078 : }
2079 : }
2080 176777 : i++;
2081 : }
2082 44233 : if ( rStr.getLength() && i < nAnzStrings && sStrArray[i][0] == ']' )
2083 : {
2084 44233 : nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
2085 44233 : nPos = nPos + sStrArray[i].getLength();
2086 44233 : i++;
2087 : }
2088 : else
2089 : {
2090 0 : return nPos; // Error
2091 : }
2092 : }
2093 : else
2094 : {
2095 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2096 0 : nPos = nPos + sStrArray[i].getLength();
2097 0 : i++;
2098 : }
2099 44233 : break;
2100 : default: // Other Dels
2101 6239 : if (eScannedType == NUMBERFORMAT_PERCENT && cHere == '%')
2102 : {
2103 6239 : nTypeArray[i] = NF_SYMBOLTYPE_PERCENT;
2104 : }
2105 : else
2106 : {
2107 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2108 : }
2109 6239 : nPos = nPos + sStrArray[i].getLength();
2110 6239 : i++;
2111 6239 : break;
2112 : } // of switch (Del)
2113 : } // of else Del
2114 : else
2115 : {
2116 : SAL_WARN( "svl.numbers", "unknown NF_SYMBOLTYPE_..." );
2117 0 : nPos = nPos + sStrArray[i].getLength();
2118 0 : i++;
2119 : }
2120 : } // of while
2121 138552 : if (eScannedType == NUMBERFORMAT_FRACTION)
2122 : {
2123 12419 : if (bFrac)
2124 : {
2125 12419 : nCntExp = nCounter;
2126 : }
2127 0 : else if (bBlank)
2128 : {
2129 0 : nCntPost = nCounter;
2130 : }
2131 : else
2132 : {
2133 0 : nCntPre = nCounter;
2134 : }
2135 : }
2136 : else
2137 : {
2138 126133 : if (bExp)
2139 : {
2140 6326 : nCntExp = nCounter;
2141 : }
2142 119807 : else if (bDecSep)
2143 : {
2144 67926 : nCntPost = nCounter;
2145 : }
2146 : else
2147 : {
2148 51881 : nCntPre = nCounter;
2149 : }
2150 : }
2151 138552 : if (bThousand) // Expansion of grouping separators
2152 : {
2153 : sal_uInt16 nMaxPos;
2154 103324 : if (bFrac)
2155 : {
2156 0 : if (bBlank)
2157 : {
2158 0 : nMaxPos = nBlankPos;
2159 : }
2160 : else
2161 : {
2162 0 : nMaxPos = 0; // no grouping
2163 : }
2164 : }
2165 103324 : else if (bDecSep) // decimal separator present
2166 : {
2167 61248 : nMaxPos = nDecPos;
2168 : }
2169 42076 : else if (bExp) // 'E' exponent present
2170 : {
2171 0 : nMaxPos = nExpPos;
2172 : }
2173 : else // up to end
2174 : {
2175 42076 : nMaxPos = i;
2176 : }
2177 : // Insert separators at proper positions.
2178 103324 : sal_Int32 nCount = 0;
2179 103324 : utl::DigitGroupingIterator aGrouping( pLoc->getDigitGrouping());
2180 103324 : size_t nFirstDigitSymbol = nMaxPos;
2181 103324 : size_t nFirstGroupingSymbol = nMaxPos;
2182 103324 : i = nMaxPos;
2183 1069599 : while (i-- > 0)
2184 : {
2185 862951 : if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2186 : {
2187 413296 : nFirstDigitSymbol = i;
2188 413296 : nCount = nCount + sStrArray[i].getLength(); // MSC converts += to int and then warns, so ...
2189 : // Insert separator only if not leftmost symbol.
2190 413296 : if (i > 0 && nCount >= aGrouping.getPos())
2191 : {
2192 : DBG_ASSERT( sStrArray[i].getLength() == 1,
2193 : "ImpSvNumberformatScan::FinalScan: combined digits in group separator insertion");
2194 103324 : if (!InsertSymbol( i, NF_SYMBOLTYPE_THSEP, pFormatter->GetNumThousandSep()))
2195 : {
2196 : // nPos isn't correct here, but signals error
2197 0 : return nPos;
2198 : }
2199 : // i may have been decremented by 1
2200 103324 : nFirstDigitSymbol = i + 1;
2201 103324 : nFirstGroupingSymbol = i;
2202 103324 : aGrouping.advance();
2203 : }
2204 : }
2205 : }
2206 : // Generated something like "string",000; remove separator again.
2207 103324 : if (nFirstGroupingSymbol < nFirstDigitSymbol)
2208 : {
2209 0 : nTypeArray[nFirstGroupingSymbol] = NF_SYMBOLTYPE_EMPTY;
2210 0 : nAnzResStrings--;
2211 103324 : }
2212 : }
2213 : // Combine digits into groups to save memory (Info will be copied
2214 : // later, taking only non-empty symbols).
2215 942838 : for (i = 0; i < nAnzStrings; ++i)
2216 : {
2217 804286 : if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2218 : {
2219 337883 : OUString& rStr = sStrArray[i];
2220 964034 : while (++i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2221 : {
2222 288268 : rStr += sStrArray[i];
2223 288268 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2224 288268 : nAnzResStrings--;
2225 : }
2226 : }
2227 : }
2228 138552 : break; // of NUMBERFORMAT_NUMBER
2229 : case NUMBERFORMAT_DATE:
2230 730780 : while (i < nAnzStrings)
2231 : {
2232 : int nCalRet;
2233 528190 : switch (nTypeArray[i])
2234 : {
2235 : case NF_SYMBOLTYPE_BLANK:
2236 : case NF_SYMBOLTYPE_STAR:
2237 : case NF_SYMBOLTYPE_STRING:
2238 6404 : nPos = nPos + sStrArray[i].getLength();
2239 6404 : i++;
2240 6404 : break;
2241 : case NF_SYMBOLTYPE_DEL:
2242 237836 : if (sStrArray[i] == sOldDateSep)
2243 : {
2244 27725 : nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
2245 27725 : nPos = nPos + sStrArray[i].getLength();
2246 27725 : if (bConvertMode)
2247 : {
2248 2527 : sStrArray[i] = pFormatter->GetDateSep();
2249 : }
2250 27725 : i++;
2251 : }
2252 210111 : else if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
2253 : {
2254 30645 : if ( nCalRet < 0 )
2255 : {
2256 0 : return nPos; // error
2257 : }
2258 : }
2259 : else
2260 : {
2261 179466 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2262 179466 : nPos = nPos + sStrArray[i].getLength();
2263 179466 : i++;
2264 : }
2265 237836 : break;
2266 : case NF_KEY_THAI_T :
2267 0 : bThaiT = true;
2268 : // fall thru
2269 : case NF_KEY_M: // M
2270 : case NF_KEY_MM: // MM
2271 : case NF_KEY_MMM: // MMM
2272 : case NF_KEY_MMMM: // MMMM
2273 : case NF_KEY_MMMMM: // MMMMM
2274 : case NF_KEY_Q: // Q
2275 : case NF_KEY_QQ: // QQ
2276 : case NF_KEY_D: // D
2277 : case NF_KEY_DD: // DD
2278 : case NF_KEY_DDD: // DDD
2279 : case NF_KEY_DDDD: // DDDD
2280 : case NF_KEY_YY: // YY
2281 : case NF_KEY_YYYY: // YYYY
2282 : case NF_KEY_NN: // NN
2283 : case NF_KEY_NNN: // NNN
2284 : case NF_KEY_NNNN: // NNNN
2285 : case NF_KEY_WW : // WW
2286 : case NF_KEY_AAA : // AAA
2287 : case NF_KEY_AAAA : // AAAA
2288 : case NF_KEY_EC : // E
2289 : case NF_KEY_EEC : // EE
2290 : case NF_KEY_G : // G
2291 : case NF_KEY_GG : // GG
2292 : case NF_KEY_GGG : // GGG
2293 : case NF_KEY_R : // R
2294 : case NF_KEY_RR : // RR
2295 283950 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2296 283950 : nPos = nPos + sStrArray[i].getLength();
2297 283950 : i++;
2298 283950 : break;
2299 : default: // Other keywords
2300 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2301 0 : nPos = nPos + sStrArray[i].getLength();
2302 0 : i++;
2303 0 : break;
2304 : }
2305 : } // of while
2306 101295 : break; // of NUMBERFORMAT_DATE
2307 : case NUMBERFORMAT_TIME:
2308 180443 : while (i < nAnzStrings)
2309 : {
2310 : sal_Unicode cChar;
2311 :
2312 134175 : switch (nTypeArray[i])
2313 : {
2314 : case NF_SYMBOLTYPE_BLANK:
2315 : case NF_SYMBOLTYPE_STAR:
2316 0 : nPos = nPos + sStrArray[i].getLength();
2317 0 : i++;
2318 0 : break;
2319 : case NF_SYMBOLTYPE_DEL:
2320 68349 : switch( sStrArray[i][0] )
2321 : {
2322 : case '0':
2323 6430 : if ( Is100SecZero( i, bDecSep ) )
2324 : {
2325 6430 : bDecSep = true;
2326 6430 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
2327 6430 : OUString& rStr = sStrArray[i];
2328 6430 : i++;
2329 6430 : nPos = nPos + sStrArray[i].getLength();
2330 6430 : nCounter++;
2331 25282 : while (i < nAnzStrings &&
2332 6211 : sStrArray[i][0] == '0')
2333 : {
2334 6211 : rStr += sStrArray[i];
2335 6211 : nPos = nPos + sStrArray[i].getLength();
2336 6211 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2337 6211 : nAnzResStrings--;
2338 6211 : nCounter++;
2339 6211 : i++;
2340 : }
2341 : }
2342 : else
2343 : {
2344 0 : return nPos;
2345 : }
2346 6430 : break;
2347 : case '#':
2348 : case '?':
2349 0 : return nPos;
2350 : case '[':
2351 6430 : if (bThousand) // Double
2352 : {
2353 0 : return nPos;
2354 : }
2355 6430 : bThousand = true; // Empty for Time
2356 6430 : cChar = pChrCls->uppercase(OUString(NextChar(i)))[0];
2357 6430 : if ( cChar == cOldKeyH )
2358 : {
2359 6430 : nThousand = 1; // H
2360 : }
2361 0 : else if ( cChar == cOldKeyMI )
2362 : {
2363 0 : nThousand = 2; // M
2364 : }
2365 0 : else if ( cChar == cOldKeyS )
2366 : {
2367 0 : nThousand = 3; // S
2368 : }
2369 : else
2370 : {
2371 0 : return nPos;
2372 : }
2373 6430 : nPos = nPos + sStrArray[i].getLength();
2374 6430 : i++;
2375 6430 : break;
2376 : case ']':
2377 6430 : if (!bThousand) // No preceding [
2378 : {
2379 0 : return nPos;
2380 : }
2381 6430 : nPos = nPos + sStrArray[i].getLength();
2382 6430 : i++;
2383 6430 : break;
2384 : default:
2385 49059 : nPos = nPos + sStrArray[i].getLength();
2386 49059 : if ( sStrArray[i] == sOldTimeSep )
2387 : {
2388 36263 : nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
2389 36263 : if ( bConvertMode )
2390 : {
2391 2033 : sStrArray[i] = pLoc->getTimeSep();
2392 : }
2393 : }
2394 12796 : else if ( sStrArray[i] == sOldTime100SecSep )
2395 : {
2396 6427 : bDecSep = true;
2397 6427 : nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
2398 6427 : if ( bConvertMode )
2399 : {
2400 211 : sStrArray[i] = pLoc->getTime100SecSep();
2401 : }
2402 : }
2403 : else
2404 : {
2405 6369 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2406 : }
2407 49059 : i++;
2408 49059 : break;
2409 : }
2410 68349 : break;
2411 : case NF_SYMBOLTYPE_STRING:
2412 37 : nPos = nPos + sStrArray[i].getLength();
2413 37 : i++;
2414 37 : break;
2415 : case NF_KEY_AMPM: // AM/PM
2416 : case NF_KEY_AP: // A/P
2417 6372 : bExp = true; // Abuse for A/P
2418 6372 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2419 6372 : nPos = nPos + sStrArray[i].getLength();
2420 6372 : i++;
2421 6372 : break;
2422 : case NF_KEY_THAI_T :
2423 0 : bThaiT = true;
2424 : // fall thru
2425 : case NF_KEY_MI: // M
2426 : case NF_KEY_MMI: // MM
2427 : case NF_KEY_H: // H
2428 : case NF_KEY_HH: // HH
2429 : case NF_KEY_S: // S
2430 : case NF_KEY_SS: // SS
2431 59417 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2432 59417 : nPos = nPos + sStrArray[i].getLength();
2433 59417 : i++;
2434 59417 : break;
2435 : default: // Other keywords
2436 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2437 0 : nPos = nPos + sStrArray[i].getLength();
2438 0 : i++;
2439 0 : break;
2440 : }
2441 : } // of while
2442 23134 : nCntPost = nCounter; // Zero counter
2443 23134 : if (bExp)
2444 : {
2445 6372 : nCntExp = 1; // Remembers AM/PM
2446 : }
2447 23134 : break; // of NUMBERFORMAT_TIME
2448 : case NUMBERFORMAT_DATETIME:
2449 82640 : while (i < nAnzStrings)
2450 : {
2451 : int nCalRet;
2452 69856 : switch (nTypeArray[i])
2453 : {
2454 : case NF_SYMBOLTYPE_BLANK:
2455 : case NF_SYMBOLTYPE_STAR:
2456 : case NF_SYMBOLTYPE_STRING:
2457 83 : nPos = nPos + sStrArray[i].getLength();
2458 83 : i++;
2459 83 : break;
2460 : case NF_SYMBOLTYPE_DEL:
2461 31667 : if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
2462 : {
2463 12 : if ( nCalRet < 0 )
2464 : {
2465 0 : return nPos; // Error
2466 : }
2467 : }
2468 : else
2469 : {
2470 31655 : switch( sStrArray[i][0] )
2471 : {
2472 : case '0':
2473 0 : if ( bTimePart && Is100SecZero( i, bDecSep ) )
2474 : {
2475 0 : bDecSep = true;
2476 0 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
2477 0 : OUString& rStr = sStrArray[i];
2478 0 : i++;
2479 0 : nPos = nPos + sStrArray[i].getLength();
2480 0 : nCounter++;
2481 0 : while (i < nAnzStrings &&
2482 0 : sStrArray[i][0] == '0')
2483 : {
2484 0 : rStr += sStrArray[i];
2485 0 : nPos = nPos + sStrArray[i].getLength();
2486 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2487 0 : nAnzResStrings--;
2488 0 : nCounter++;
2489 0 : i++;
2490 : }
2491 : }
2492 : else
2493 : {
2494 0 : return nPos;
2495 : }
2496 0 : break;
2497 : case '#':
2498 : case '?':
2499 0 : return nPos;
2500 : default:
2501 31655 : nPos = nPos + sStrArray[i].getLength();
2502 31655 : if (bTimePart)
2503 : {
2504 12541 : if ( sStrArray[i] == sOldTimeSep )
2505 : {
2506 9483 : nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
2507 9483 : if ( bConvertMode )
2508 : {
2509 143 : sStrArray[i] = pLoc->getTimeSep();
2510 : }
2511 : }
2512 3058 : else if ( sStrArray[i] == sOldTime100SecSep )
2513 : {
2514 0 : bDecSep = true;
2515 0 : nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
2516 0 : if ( bConvertMode )
2517 : {
2518 0 : sStrArray[i] = pLoc->getTime100SecSep();
2519 : }
2520 : }
2521 : else
2522 : {
2523 3058 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2524 : }
2525 : }
2526 : else
2527 : {
2528 19114 : if ( sStrArray[i] == sOldDateSep )
2529 : {
2530 12740 : nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
2531 12740 : if (bConvertMode)
2532 284 : sStrArray[i] = pFormatter->GetDateSep();
2533 : }
2534 : else
2535 : {
2536 6374 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2537 : }
2538 : }
2539 31655 : i++;
2540 31655 : break;
2541 : }
2542 : }
2543 31667 : break;
2544 : case NF_KEY_AMPM: // AM/PM
2545 : case NF_KEY_AP: // A/P
2546 3058 : bTimePart = true;
2547 3058 : bExp = true; // Abuse for A/P
2548 3058 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2549 3058 : nPos = nPos + sStrArray[i].getLength();
2550 3058 : i++;
2551 3058 : break;
2552 : case NF_KEY_MI: // M
2553 : case NF_KEY_MMI: // MM
2554 : case NF_KEY_H: // H
2555 : case NF_KEY_HH: // HH
2556 : case NF_KEY_S: // S
2557 : case NF_KEY_SS: // SS
2558 15898 : bTimePart = true;
2559 15898 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2560 15898 : nPos = nPos + sStrArray[i].getLength();
2561 15898 : i++;
2562 15898 : break;
2563 : case NF_KEY_M: // M
2564 : case NF_KEY_MM: // MM
2565 : case NF_KEY_MMM: // MMM
2566 : case NF_KEY_MMMM: // MMMM
2567 : case NF_KEY_MMMMM: // MMMMM
2568 : case NF_KEY_Q: // Q
2569 : case NF_KEY_QQ: // QQ
2570 : case NF_KEY_D: // D
2571 : case NF_KEY_DD: // DD
2572 : case NF_KEY_DDD: // DDD
2573 : case NF_KEY_DDDD: // DDDD
2574 : case NF_KEY_YY: // YY
2575 : case NF_KEY_YYYY: // YYYY
2576 : case NF_KEY_NN: // NN
2577 : case NF_KEY_NNN: // NNN
2578 : case NF_KEY_NNNN: // NNNN
2579 : case NF_KEY_WW : // WW
2580 : case NF_KEY_AAA : // AAA
2581 : case NF_KEY_AAAA : // AAAA
2582 : case NF_KEY_EC : // E
2583 : case NF_KEY_EEC : // EE
2584 : case NF_KEY_G : // G
2585 : case NF_KEY_GG : // GG
2586 : case NF_KEY_GGG : // GGG
2587 : case NF_KEY_R : // R
2588 : case NF_KEY_RR : // RR
2589 19150 : bTimePart = false;
2590 19150 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2591 19150 : nPos = nPos + sStrArray[i].getLength();
2592 19150 : i++;
2593 19150 : break;
2594 : case NF_KEY_THAI_T :
2595 0 : bThaiT = true;
2596 0 : sStrArray[i] = sKeyword[nTypeArray[i]];
2597 0 : nPos = nPos + sStrArray[i].getLength();
2598 0 : i++;
2599 0 : break;
2600 : default: // Other keywords
2601 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2602 0 : nPos = nPos + sStrArray[i].getLength();
2603 0 : i++;
2604 0 : break;
2605 : }
2606 : } // of while
2607 6392 : nCntPost = nCounter; // decimals (100th seconds)
2608 6392 : if (bExp)
2609 : {
2610 3058 : nCntExp = 1; // Remembers AM/PM
2611 : }
2612 6392 : break; // of NUMBERFORMAT_DATETIME
2613 : default:
2614 0 : break;
2615 : }
2616 279712 : if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
2617 12652 : (nCntPre + nCntPost == 0 || nCntExp == 0))
2618 : {
2619 0 : return nPos;
2620 : }
2621 273386 : else if (eScannedType == NUMBERFORMAT_FRACTION && (nCntExp > 8 || nCntExp == 0))
2622 : {
2623 0 : return nPos;
2624 : }
2625 273386 : if (bThaiT && !GetNatNumModifier())
2626 : {
2627 0 : SetNatNumModifier(1);
2628 : }
2629 273386 : if ( bConvertMode )
2630 : {
2631 : // strings containing keywords of the target locale must be quoted, so
2632 : // the user sees the difference and is able to edit the format string
2633 59511 : for ( i=0; i < nAnzStrings; i++ )
2634 : {
2635 57329 : if ( nTypeArray[i] == NF_SYMBOLTYPE_STRING &&
2636 6217 : sStrArray[i][0] != '\"' )
2637 : {
2638 4455 : if ( bConvertSystemToSystem && eScannedType == NUMBERFORMAT_CURRENCY )
2639 : {
2640 : // don't stringize automatic currency, will be converted
2641 0 : if ( sStrArray[i] == sOldCurSymbol )
2642 : {
2643 0 : continue; // for
2644 : }
2645 : // DM might be splitted into D and M
2646 0 : if ( sStrArray[i].getLength() < sOldCurSymbol.getLength() &&
2647 0 : pChrCls->uppercase( sStrArray[i], 0, 1 )[0] ==
2648 0 : sOldCurString[0] )
2649 : {
2650 0 : OUString aTmp( sStrArray[i] );
2651 0 : sal_uInt16 j = i + 1;
2652 0 : while ( aTmp.getLength() < sOldCurSymbol.getLength() &&
2653 0 : j < nAnzStrings &&
2654 0 : nTypeArray[j] == NF_SYMBOLTYPE_STRING )
2655 : {
2656 0 : aTmp += sStrArray[j++];
2657 : }
2658 0 : if ( pChrCls->uppercase( aTmp ) == sOldCurString )
2659 : {
2660 0 : sStrArray[i++] = aTmp;
2661 0 : for ( ; i<j; i++ )
2662 : {
2663 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2664 0 : nAnzResStrings--;
2665 : }
2666 0 : i = j - 1;
2667 0 : continue; // for
2668 0 : }
2669 : }
2670 : }
2671 4455 : OUString& rStr = sStrArray[i];
2672 4455 : sal_Int32 nLen = rStr.getLength();
2673 10320 : for ( sal_Int32 j = 0; j < nLen; j++ )
2674 : {
2675 5865 : if ( (j == 0 || rStr[j - 1] != '\\') && GetKeyWord( rStr, j ) )
2676 : {
2677 0 : rStr = "\"" + rStr + "\"";
2678 0 : break; // for
2679 : }
2680 : }
2681 : }
2682 : }
2683 : }
2684 : // Concatenate strings, remove quotes for output, and rebuild the format string
2685 273386 : rString = "";
2686 273386 : i = 0;
2687 2791353 : while (i < nAnzStrings)
2688 : {
2689 : sal_Int32 nStringPos;
2690 2244581 : sal_Int32 nArrPos = 0;
2691 2244581 : sal_uInt16 iPos = i;
2692 2244581 : switch ( nTypeArray[i] )
2693 : {
2694 : case NF_SYMBOLTYPE_STRING :
2695 239203 : nStringPos = rString.getLength();
2696 292895 : do
2697 : {
2698 297644 : if (sStrArray[i].getLength() == 2 &&
2699 4749 : sStrArray[i][0] == '\\')
2700 : {
2701 : // Unescape some simple forms of symbols even in the UI
2702 : // visible string to prevent duplicates that differ
2703 : // only in notation, originating from import.
2704 : // e.g. YYYY-MM-DD and YYYY\-MM\-DD are identical,
2705 : // but 0\ 000 0 and 0 000 0 in a French locale are not.
2706 :
2707 1481 : sal_Unicode c = sStrArray[i][1];
2708 :
2709 1481 : switch (c)
2710 : {
2711 : case '+':
2712 : case '-':
2713 479 : rString += OUString(c);
2714 479 : break;
2715 : case ' ':
2716 : case '.':
2717 : case '/':
2718 784 : if (((eScannedType & NUMBERFORMAT_DATE) == 0) &&
2719 764 : (StringEqualsChar( pFormatter->GetNumThousandSep(), c) ||
2720 764 : StringEqualsChar( pFormatter->GetNumDecimalSep(), c) ||
2721 382 : (c == ' ' &&
2722 764 : (StringEqualsChar( pFormatter->GetNumThousandSep(), cNoBreakSpace) ||
2723 382 : StringEqualsChar( pFormatter->GetNumThousandSep(), cNarrowNoBreakSpace)))))
2724 : {
2725 0 : rString += sStrArray[i];
2726 : }
2727 422 : else if ((eScannedType & NUMBERFORMAT_DATE) &&
2728 20 : StringEqualsChar( pFormatter->GetDateSep(), c))
2729 : {
2730 2 : rString += sStrArray[i];
2731 : }
2732 406 : else if ((eScannedType & NUMBERFORMAT_TIME) &&
2733 12 : (StringEqualsChar( pLoc->getTimeSep(), c) ||
2734 6 : StringEqualsChar( pLoc->getTime100SecSep(), c)))
2735 : {
2736 0 : rString += sStrArray[i];
2737 : }
2738 400 : else if (eScannedType & NUMBERFORMAT_FRACTION)
2739 : {
2740 3 : rString += sStrArray[i];
2741 : }
2742 : else
2743 : {
2744 397 : rString += OUString(c);
2745 : }
2746 402 : break;
2747 : default:
2748 600 : rString += sStrArray[i];
2749 : }
2750 : }
2751 : else
2752 : {
2753 291414 : rString += sStrArray[i];
2754 : }
2755 292895 : if ( RemoveQuotes( sStrArray[i] ) > 0 )
2756 : {
2757 : // update currency up to quoted string
2758 3686 : if ( eScannedType == NUMBERFORMAT_CURRENCY )
2759 : {
2760 : // dM -> DM or DM -> $ in old automatic
2761 : // currency formats, oh my ..., why did we ever introduce them?
2762 44 : OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
2763 88 : sStrArray[iPos].getLength()-nArrPos ) );
2764 44 : sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
2765 44 : if ( nCPos >= 0 )
2766 : {
2767 0 : const OUString& rCur = bConvertMode && bConvertSystemToSystem ?
2768 0 : GetCurSymbol() : sOldCurSymbol;
2769 0 : sStrArray[iPos] = sStrArray[iPos].replaceAt( nArrPos + nCPos,
2770 : sOldCurString.getLength(),
2771 0 : rCur );
2772 0 : rString = rString.replaceAt( nStringPos + nCPos,
2773 : sOldCurString.getLength(),
2774 0 : rCur );
2775 : }
2776 44 : nStringPos = rString.getLength();
2777 44 : if ( iPos == i )
2778 : {
2779 41 : nArrPos = sStrArray[iPos].getLength();
2780 : }
2781 : else
2782 : {
2783 3 : nArrPos = sStrArray[iPos].getLength() + sStrArray[i].getLength();
2784 44 : }
2785 : }
2786 : }
2787 292895 : if ( iPos != i )
2788 : {
2789 53692 : sStrArray[iPos] += sStrArray[i];
2790 53692 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2791 53692 : nAnzResStrings--;
2792 : }
2793 292895 : i++;
2794 : }
2795 574764 : while ( i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_STRING );
2796 :
2797 239203 : if ( i < nAnzStrings )
2798 : {
2799 228177 : i--; // enter switch on next symbol again
2800 : }
2801 239203 : if ( eScannedType == NUMBERFORMAT_CURRENCY && nStringPos < rString.getLength() )
2802 : {
2803 : // same as above, since last RemoveQuotes
2804 58029 : OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
2805 116058 : sStrArray[iPos].getLength()-nArrPos ) );
2806 58029 : sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
2807 58029 : if ( nCPos >= 0 )
2808 : {
2809 665 : const OUString& rCur = bConvertMode && bConvertSystemToSystem ?
2810 31811 : GetCurSymbol() : sOldCurSymbol;
2811 63622 : sStrArray[iPos] = sStrArray[iPos].replaceAt( nArrPos + nCPos,
2812 : sOldCurString.getLength(),
2813 31811 : rCur );
2814 63622 : rString = rString.replaceAt( nStringPos + nCPos,
2815 31811 : sOldCurString.getLength(), rCur );
2816 58029 : }
2817 : }
2818 239203 : break;
2819 : case NF_SYMBOLTYPE_CURRENCY :
2820 44233 : rString += sStrArray[i];
2821 44233 : RemoveQuotes( sStrArray[i] );
2822 44233 : break;
2823 : case NF_KEY_THAI_T:
2824 0 : if (bThaiT && GetNatNumModifier() == 1)
2825 : {
2826 : // Remove T from format code, will be replaced with a [NatNum1] prefix.
2827 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2828 0 : nAnzResStrings--;
2829 : }
2830 : else
2831 : {
2832 0 : rString += sStrArray[i];
2833 : }
2834 0 : break;
2835 : case NF_SYMBOLTYPE_EMPTY :
2836 : // nothing
2837 637397 : break;
2838 : default:
2839 1323748 : rString += sStrArray[i];
2840 : }
2841 2244581 : i++;
2842 : }
2843 546772 : return 0;
2844 : }
2845 :
2846 337128 : sal_Int32 ImpSvNumberformatScan::RemoveQuotes( OUString& rStr )
2847 : {
2848 337128 : if ( rStr.getLength() > 1 )
2849 : {
2850 10517 : sal_Unicode c = rStr[0];
2851 10517 : sal_Int32 n = rStr.getLength() - 1;
2852 10517 : if ( c == '"' && rStr[n] == '"' )
2853 : {
2854 2205 : rStr = rStr.copy( 1, n-1);
2855 2205 : return 2;
2856 : }
2857 8312 : else if ( c == '\\' )
2858 : {
2859 1481 : rStr = rStr.copy(1);
2860 1481 : return 1;
2861 : }
2862 : }
2863 333442 : return 0;
2864 : }
2865 :
2866 273386 : sal_Int32 ImpSvNumberformatScan::ScanFormat( OUString& rString )
2867 : {
2868 273386 : sal_Int32 res = Symbol_Division(rString); // Lexical analysis
2869 273386 : if (!res)
2870 : {
2871 273386 : res = ScanType(); // Recognizing the Format type
2872 : }
2873 273386 : if (!res)
2874 : {
2875 273386 : res = FinalScan( rString ); // Type dependent final analysis
2876 : }
2877 273386 : return res; // res = control position; res = 0 => Format ok
2878 : }
2879 :
2880 273386 : void ImpSvNumberformatScan::CopyInfo(ImpSvNumberformatInfo* pInfo, sal_uInt16 nAnz)
2881 : {
2882 : size_t i,j;
2883 273386 : j = 0;
2884 273386 : i = 0;
2885 2703262 : while (i < nAnz && j < NF_MAX_FORMAT_SYMBOLS)
2886 : {
2887 2156490 : if (nTypeArray[j] != NF_SYMBOLTYPE_EMPTY)
2888 : {
2889 1607184 : pInfo->sStrArray[i] = sStrArray[j];
2890 1607184 : pInfo->nTypeArray[i] = nTypeArray[j];
2891 1607184 : i++;
2892 : }
2893 2156490 : j++;
2894 : }
2895 273386 : pInfo->eScannedType = eScannedType;
2896 273386 : pInfo->bThousand = bThousand;
2897 273386 : pInfo->nThousand = nThousand;
2898 273386 : pInfo->nCntPre = nCntPre;
2899 273386 : pInfo->nCntPost = nCntPost;
2900 273386 : pInfo->nCntExp = nCntExp;
2901 273386 : }
2902 :
2903 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|