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 24 : 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 48 : };
61 24 : return &aEnglishColors[0];
62 : }
63 : };
64 :
65 : struct theEnglishColors
66 : : public rtl::StaticAggregate< const OUString, ImplEnglishColors> {};
67 :
68 : }
69 :
70 7047 : ImpSvNumberformatScan::ImpSvNumberformatScan( SvNumberFormatter* pFormatterP )
71 : : eNewLnge(LANGUAGE_DONTKNOW)
72 : , eTmpLnge(LANGUAGE_DONTKNOW)
73 7047 : , nCurrPos(-1)
74 : {
75 7047 : pFormatter = pFormatterP;
76 7047 : bConvertMode = false;
77 7047 : bConvertSystemToSystem = false;
78 : //! All keywords MUST be UPPERCASE!
79 7047 : sKeyword[NF_KEY_E] = "E"; // Exponent
80 7047 : sKeyword[NF_KEY_AMPM] = "AM/PM"; // AM/PM
81 7047 : sKeyword[NF_KEY_AP] = "A/P"; // AM/PM short
82 7047 : sKeyword[NF_KEY_MI] = "M"; // Minute
83 7047 : sKeyword[NF_KEY_MMI] = "MM"; // Minute 02
84 7047 : sKeyword[NF_KEY_S] = "S"; // Second
85 7047 : sKeyword[NF_KEY_SS] = "SS"; // Second 02
86 7047 : sKeyword[NF_KEY_Q] = "Q"; // Quarter short 'Q'
87 7047 : sKeyword[NF_KEY_QQ] = "QQ"; // Quarter long
88 7047 : sKeyword[NF_KEY_NN] = "NN"; // Day of week short
89 7047 : sKeyword[NF_KEY_NNN] = "NNN"; // Day of week long
90 7047 : sKeyword[NF_KEY_NNNN] = "NNNN"; // Day of week long incl. separator
91 7047 : sKeyword[NF_KEY_WW] = "WW"; // Week of year
92 7047 : sKeyword[NF_KEY_CCC] = "CCC"; // Currency abbreviation
93 7047 : bKeywordsNeedInit = true; // locale dependent keywords
94 7047 : bCompatCurNeedInit = true; // locale dependent compatibility currency strings
95 :
96 7047 : StandardColor[0] = Color(COL_BLACK);
97 7047 : StandardColor[1] = Color(COL_LIGHTBLUE);
98 7047 : StandardColor[2] = Color(COL_LIGHTGREEN);
99 7047 : StandardColor[3] = Color(COL_LIGHTCYAN);
100 7047 : StandardColor[4] = Color(COL_LIGHTRED);
101 7047 : StandardColor[5] = Color(COL_LIGHTMAGENTA);
102 7047 : StandardColor[6] = Color(COL_BROWN);
103 7047 : StandardColor[7] = Color(COL_GRAY);
104 7047 : StandardColor[8] = Color(COL_YELLOW);
105 7047 : StandardColor[9] = Color(COL_WHITE);
106 :
107 7047 : pNullDate = new Date(30,12,1899);
108 7047 : nStandardPrec = 2;
109 :
110 7047 : sErrStr = "###";
111 7047 : Reset();
112 7047 : }
113 :
114 14006 : ImpSvNumberformatScan::~ImpSvNumberformatScan()
115 : {
116 7003 : delete pNullDate;
117 7003 : Reset();
118 7003 : }
119 :
120 30507 : void ImpSvNumberformatScan::ChangeIntl()
121 : {
122 30507 : bKeywordsNeedInit = true;
123 30507 : bCompatCurNeedInit = true;
124 : // may be initialized by InitSpecialKeyword()
125 30507 : sKeyword[NF_KEY_TRUE] = "";
126 30507 : sKeyword[NF_KEY_FALSE] = "";
127 30507 : }
128 :
129 68650 : void ImpSvNumberformatScan::InitSpecialKeyword( NfKeywordIndex eIdx ) const
130 : {
131 68650 : switch ( eIdx )
132 : {
133 : case NF_KEY_TRUE :
134 68656 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] =
135 68656 : pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getTrueWord() );
136 34328 : 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 34328 : break;
142 : case NF_KEY_FALSE :
143 68644 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] =
144 68644 : pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getFalseWord() );
145 34322 : 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 34322 : break;
151 : default:
152 : SAL_WARN( "svl.numbers", "InitSpecialKeyword: unknown request" );
153 : }
154 68650 : }
155 :
156 30804 : void ImpSvNumberformatScan::InitCompatCur() const
157 : {
158 30804 : ImpSvNumberformatScan* pThis = (ImpSvNumberformatScan*)this;
159 : // currency symbol for old style ("automatic") compatibility format codes
160 30804 : pFormatter->GetCompatibilityCurrency( pThis->sCurSymbol, pThis->sCurAbbrev );
161 : // currency symbol upper case
162 30804 : pThis->sCurString = pFormatter->GetCharClass()->uppercase( sCurSymbol );
163 30804 : bCompatCurNeedInit = false;
164 30804 : }
165 :
166 40642 : void ImpSvNumberformatScan::InitKeywords() const
167 : {
168 40642 : if ( !bKeywordsNeedInit )
169 50480 : return ;
170 30804 : ((ImpSvNumberformatScan*)this)->SetDependentKeywords();
171 30804 : bKeywordsNeedInit = false;
172 : }
173 :
174 : /** Extract the name of General, Standard, Whatever, ignoring leading modifiers
175 : such as [NatNum1]. */
176 30804 : static OUString lcl_extractStandardGeneralName( const OUString & rCode )
177 : {
178 30804 : OUString aStr;
179 30804 : const sal_Unicode* p = rCode.getStr();
180 30804 : const sal_Unicode* const pStop = p + rCode.getLength();
181 30804 : const sal_Unicode* pBeg = p; // name begins here
182 30804 : bool bMod = false;
183 30804 : bool bDone = false;
184 277334 : while (p < pStop && !bDone)
185 : {
186 215726 : 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 215726 : ++p;
209 215726 : if (bMod)
210 : {
211 0 : pBeg = p;
212 : }
213 : }
214 30804 : if (pBeg < p)
215 : {
216 30804 : aStr = rCode.copy( pBeg - rCode.getStr(), p - pBeg);
217 : }
218 30804 : return aStr;
219 : }
220 :
221 30804 : void ImpSvNumberformatScan::SetDependentKeywords()
222 : {
223 : using namespace ::com::sun::star;
224 : using namespace ::com::sun::star::uno;
225 :
226 30804 : const CharClass* pCharClass = pFormatter->GetCharClass();
227 30804 : 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 30804 : const LanguageTag& rLoadedLocale = pLocaleData->getLoadedLanguageTag();
231 30804 : LanguageType eLang = rLoadedLocale.getLanguageType( false);
232 : NumberFormatCodeWrapper aNumberFormatCode( pFormatter->GetComponentContext(),
233 61608 : rLoadedLocale.getLocale() );
234 :
235 61608 : i18n::NumberFormatCode aFormat = aNumberFormatCode.getFormatCode( NF_NUMBER_STANDARD );
236 30804 : sNameStandardFormat = lcl_extractStandardGeneralName( aFormat.Code);
237 30804 : sKeyword[NF_KEY_GENERAL] = pCharClass->uppercase( sNameStandardFormat );
238 :
239 : // preset new calendar keywords
240 30804 : sKeyword[NF_KEY_AAA] = "AAA";
241 30804 : sKeyword[NF_KEY_AAAA] = "AAAA";
242 30804 : sKeyword[NF_KEY_EC] = "E";
243 30804 : sKeyword[NF_KEY_EEC] = "EE";
244 30804 : sKeyword[NF_KEY_G] = "G";
245 30804 : sKeyword[NF_KEY_GG] = "GG";
246 30804 : sKeyword[NF_KEY_GGG] = "GGG";
247 30804 : sKeyword[NF_KEY_R] = "R";
248 30804 : 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 30804 : if (eLang == LANGUAGE_THAI)
253 : {
254 6 : sKeyword[NF_KEY_THAI_T] = "T";
255 : }
256 : else
257 : {
258 30798 : sKeyword[NF_KEY_THAI_T] = "t";
259 : }
260 30804 : 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 62 : sKeyword[NF_KEY_M] = "M"; // month 1
269 62 : sKeyword[NF_KEY_MM] = "MM"; // month 01
270 62 : sKeyword[NF_KEY_MMM] = "MMM"; // month Jan
271 62 : sKeyword[NF_KEY_MMMM] = "MMMM"; // month Januar
272 62 : sKeyword[NF_KEY_MMMMM] = "MMMMM"; // month J
273 62 : sKeyword[NF_KEY_H] = "H"; // hour 2
274 62 : sKeyword[NF_KEY_HH] = "HH"; // hour 02
275 62 : sKeyword[NF_KEY_D] = "T";
276 62 : sKeyword[NF_KEY_DD] = "TT";
277 62 : sKeyword[NF_KEY_DDD] = "TTT";
278 62 : sKeyword[NF_KEY_DDDD] = "TTTT";
279 62 : sKeyword[NF_KEY_YY] = "JJ";
280 62 : sKeyword[NF_KEY_YYYY] = "JJJJ";
281 62 : sKeyword[NF_KEY_BOOLEAN] = "LOGISCH";
282 62 : sKeyword[NF_KEY_COLOR] = "FARBE";
283 62 : sKeyword[NF_KEY_BLACK] = "SCHWARZ";
284 62 : sKeyword[NF_KEY_BLUE] = "BLAU";
285 62 : sKeyword[NF_KEY_GREEN] = OUString( "GR" "\xDC" "N", 4, RTL_TEXTENCODING_ISO_8859_1 );
286 62 : sKeyword[NF_KEY_CYAN] = "CYAN";
287 62 : sKeyword[NF_KEY_RED] = "ROT";
288 62 : sKeyword[NF_KEY_MAGENTA] = "MAGENTA";
289 62 : sKeyword[NF_KEY_BROWN] = "BRAUN";
290 62 : sKeyword[NF_KEY_GREY] = "GRAU";
291 62 : sKeyword[NF_KEY_YELLOW] = "GELB";
292 62 : sKeyword[NF_KEY_WHITE] = "WEISS";
293 62 : break;
294 : default:
295 : // day
296 30742 : 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 18 : sKeyword[NF_KEY_D] = "J";
316 18 : sKeyword[NF_KEY_DD] = "JJ";
317 18 : sKeyword[NF_KEY_DDD] = "JJJ";
318 18 : sKeyword[NF_KEY_DDDD] = "JJJJ";
319 18 : 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 30724 : sKeyword[NF_KEY_D] = "D";
328 30724 : sKeyword[NF_KEY_DD] = "DD";
329 30724 : sKeyword[NF_KEY_DDD] = "DDD";
330 30724 : sKeyword[NF_KEY_DDDD] = "DDDD";
331 : }
332 : // month
333 30742 : 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 30742 : sKeyword[NF_KEY_M] = "M";
344 30742 : sKeyword[NF_KEY_MM] = "MM";
345 30742 : sKeyword[NF_KEY_MMM] = "MMM";
346 30742 : sKeyword[NF_KEY_MMMM] = "MMMM";
347 30742 : sKeyword[NF_KEY_MMMMM] = "MMMMM";
348 : }
349 : // year
350 30742 : 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 18 : sKeyword[NF_KEY_YY] = "AA";
383 18 : sKeyword[NF_KEY_YYYY] = "AAAA";
384 : // must exchange the day of week name code, same as Xcl
385 18 : sKeyword[NF_KEY_AAA] = "OOO";
386 18 : sKeyword[NF_KEY_AAAA] = "OOOO";
387 18 : 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 30724 : sKeyword[NF_KEY_YY] = "YY";
399 30724 : sKeyword[NF_KEY_YYYY] = "YYYY";
400 : }
401 : // hour
402 30742 : 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 8 : sKeyword[NF_KEY_H] = "T";
417 8 : sKeyword[NF_KEY_HH] = "TT";
418 8 : break;
419 : default:
420 30734 : sKeyword[NF_KEY_H] = "H";
421 30734 : sKeyword[NF_KEY_HH] = "HH";
422 : }
423 : // boolean
424 30742 : sKeyword[NF_KEY_BOOLEAN] = "BOOLEAN";
425 : // colours
426 30742 : sKeyword[NF_KEY_COLOR] = "COLOR";
427 30742 : sKeyword[NF_KEY_BLACK] = "BLACK";
428 30742 : sKeyword[NF_KEY_BLUE] = "BLUE";
429 30742 : sKeyword[NF_KEY_GREEN] = "GREEN";
430 30742 : sKeyword[NF_KEY_CYAN] = "CYAN";
431 30742 : sKeyword[NF_KEY_RED] = "RED";
432 30742 : sKeyword[NF_KEY_MAGENTA] = "MAGENTA";
433 30742 : sKeyword[NF_KEY_BROWN] = "BROWN";
434 30742 : sKeyword[NF_KEY_GREY] = "GREY";
435 30742 : sKeyword[NF_KEY_YELLOW] = "YELLOW";
436 30742 : sKeyword[NF_KEY_WHITE] = "WHITE";
437 30742 : break;
438 : }
439 :
440 : // boolean keyords
441 30804 : InitSpecialKeyword( NF_KEY_TRUE );
442 30804 : InitSpecialKeyword( NF_KEY_FALSE );
443 :
444 : // compatibility currency strings
445 61608 : InitCompatCur();
446 30804 : }
447 :
448 10452 : void ImpSvNumberformatScan::ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear)
449 : {
450 10452 : if ( pNullDate )
451 10452 : *pNullDate = Date(nDay, nMonth, nYear);
452 : else
453 0 : pNullDate = new Date(nDay, nMonth, nYear);
454 10452 : }
455 :
456 6582 : void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec)
457 : {
458 6582 : nStandardPrec = nPrec;
459 6582 : }
460 :
461 58792 : Color* ImpSvNumberformatScan::GetColor(OUString& sStr)
462 : {
463 58792 : OUString sString = pFormatter->GetCharClass()->uppercase(sStr);
464 58792 : const NfKeywordTable & rKeyword = GetKeywords();
465 58792 : size_t i = 0;
466 409244 : while (i < NF_MAX_DEFAULT_COLORS && sString != rKeyword[NF_KEY_FIRSTCOLOR+i] )
467 : {
468 291660 : i++;
469 : }
470 58792 : if ( i >= NF_MAX_DEFAULT_COLORS )
471 : {
472 9434 : const OUString* pEnglishColors = theEnglishColors::get();
473 9434 : size_t j = 0;
474 113208 : while ( j < NF_MAX_DEFAULT_COLORS && sString != pEnglishColors[j] )
475 : {
476 94340 : ++j;
477 : }
478 9434 : if ( j < NF_MAX_DEFAULT_COLORS )
479 : {
480 0 : i = j;
481 : }
482 : }
483 :
484 58792 : Color* pResult = NULL;
485 58792 : if (i >= NF_MAX_DEFAULT_COLORS)
486 : {
487 9434 : const OUString& rColorWord = rKeyword[NF_KEY_COLOR];
488 9434 : 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 49358 : sStr = "";
519 49358 : if (bConvertMode)
520 : {
521 1366 : pFormatter->ChangeIntl(eNewLnge);
522 1366 : sStr = GetKeywords()[NF_KEY_FIRSTCOLOR+i]; // red -> rot
523 1366 : pFormatter->ChangeIntl(eTmpLnge);
524 : }
525 : else
526 : {
527 47992 : sStr = rKeyword[NF_KEY_FIRSTCOLOR+i];
528 : }
529 49358 : pResult = &(StandardColor[i]);
530 : }
531 58792 : return pResult;
532 : }
533 :
534 1697594 : short ImpSvNumberformatScan::GetKeyWord( const OUString& sSymbol, sal_Int32 nPos )
535 : {
536 1697594 : OUString sString = pFormatter->GetCharClass()->uppercase( sSymbol, nPos, sSymbol.getLength() - nPos );
537 1697594 : const NfKeywordTable & rKeyword = GetKeywords();
538 : // #77026# for the Xcl perverts: the GENERAL keyword is recognized anywhere
539 1697594 : if ( sString.startsWith( rKeyword[NF_KEY_GENERAL] ))
540 : {
541 8046 : return NF_KEY_GENERAL;
542 : }
543 : //! MUST be a reverse search to find longer strings first
544 1689548 : short i = NF_KEYWORD_ENTRIES_COUNT-1;
545 1689548 : bool bFound = false;
546 18017028 : for ( ; i > NF_KEY_LASTKEYWORD_SO5; --i )
547 : {
548 16516598 : bFound = sString.startsWith(rKeyword[i]);
549 16516598 : if ( bFound )
550 : {
551 189118 : break;
552 : }
553 : }
554 : // new keywords take precedence over old keywords
555 1689548 : if ( !bFound )
556 : {
557 : // skip the gap of colors et al between new and old keywords and search on
558 1500430 : i = NF_KEY_LASTKEYWORD;
559 28451412 : while ( i > 0 && sString.indexOf(rKeyword[i]) != 0 )
560 : {
561 25450552 : i--;
562 : }
563 1500430 : 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 31048 : short j = i - 1;
568 124192 : while ( j > 0 && sString.indexOf(rKeyword[j]) != 0 )
569 : {
570 62096 : j--;
571 : }
572 31048 : if ( j && rKeyword[j].getLength() > rKeyword[i].getLength() )
573 : {
574 31048 : return j;
575 : }
576 : }
577 : }
578 : // The Thai T NatNum modifier during Xcl import.
579 1961682 : if (i == 0 && bConvertMode &&
580 10970 : sString[0] == 'T' &&
581 1658500 : eTmpLnge == LANGUAGE_ENGLISH_US &&
582 0 : MsLangId::getRealLanguage( eNewLnge) == LANGUAGE_THAI)
583 : {
584 0 : i = NF_KEY_THAI_T;
585 : }
586 1658500 : 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 5789419 : short ImpSvNumberformatScan::Next_Symbol( const OUString& rStr,
642 : sal_Int32& nPos,
643 : OUString& sSymbol )
644 : {
645 5789419 : if ( bKeywordsNeedInit )
646 : {
647 0 : InitKeywords();
648 : }
649 5789419 : const CharClass* pChrCls = pFormatter->GetCharClass();
650 5789419 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
651 5789419 : const sal_Int32 nStart = nPos;
652 5789419 : short eType = 0;
653 5789419 : ScanState eState = SsStart;
654 5789419 : sSymbol = "";
655 17718601 : while ( nPos < rStr.getLength() && eState != SsStop )
656 : {
657 6140883 : sal_Unicode cToken = rStr[nPos++];
658 6140883 : 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 13985741 : if ( nCurrPos >= 0 && sCurString.getLength() > 1 &&
668 5830287 : nPos-1 + sCurString.getLength() <= rStr.getLength() &&
669 25992 : !(nPos > 1 && rStr[nPos-2] == '[') )
670 : {
671 12996 : OUString aTest = pChrCls->uppercase( rStr.copy( nPos-1, sCurString.getLength() ) );
672 12996 : if ( aTest == sCurString )
673 : {
674 1120 : sSymbol = rStr.copy( --nPos, sCurString.getLength() );
675 1120 : nPos = nPos + sSymbol.getLength();
676 1120 : eState = SsStop;
677 1120 : eType = NF_SYMBOLTYPE_STRING;
678 1120 : return eType;
679 11876 : }
680 : }
681 5788299 : 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 3654332 : eType = NF_SYMBOLTYPE_DEL;
698 3654332 : sSymbol += OUString(cToken);
699 3654332 : eState = SsStop;
700 3654332 : break;
701 : case '*':
702 34938 : eType = NF_SYMBOLTYPE_STAR;
703 34938 : sSymbol += OUString(cToken);
704 34938 : eState = SsGetStar;
705 34938 : break;
706 : case '_':
707 26052 : eType = NF_SYMBOLTYPE_BLANK;
708 26052 : sSymbol += OUString(cToken);
709 26052 : eState = SsGetBlank;
710 26052 : break;
711 : case '"':
712 5504 : eType = NF_SYMBOLTYPE_STRING;
713 5504 : eState = SsGetString;
714 5504 : sSymbol += OUString(cToken);
715 5504 : break;
716 : case '\\':
717 3194 : eType = NF_SYMBOLTYPE_STRING;
718 3194 : eState = SsGetChar;
719 3194 : sSymbol += OUString(cToken);
720 3194 : break;
721 : case '$':
722 : case '+':
723 : case '(':
724 : case ')':
725 334324 : eType = NF_SYMBOLTYPE_STRING;
726 334324 : eState = SsStop;
727 334324 : sSymbol += OUString(cToken);
728 334324 : break;
729 : default :
730 5189865 : if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cToken) ||
731 3459910 : StringEqualsChar( pFormatter->GetNumThousandSep(), cToken) ||
732 3459910 : StringEqualsChar( pFormatter->GetDateSep(), cToken) ||
733 5189865 : StringEqualsChar( pLoc->getTimeSep(), cToken) ||
734 1729955 : StringEqualsChar( pLoc->getTime100SecSep(), cToken))
735 : {
736 : // Another separator than pre-known ASCII
737 0 : eType = NF_SYMBOLTYPE_DEL;
738 0 : sSymbol += OUString(cToken);
739 0 : eState = SsStop;
740 : }
741 1729955 : else if ( pChrCls->isLetter( rStr, nPos-1 ) )
742 : {
743 1414229 : short nTmpType = GetKeyWord( rStr, nPos-1 );
744 1414229 : if ( nTmpType )
745 : {
746 1242029 : bool bCurrency = false;
747 : // "Automatic" currency may start with keyword,
748 : // like "R" (Rand) and 'R' (era)
749 2485153 : if ( nCurrPos >= 0 &&
750 1243124 : nPos-1 + sCurString.getLength() <= rStr.getLength() &&
751 1095 : 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 1242029 : if ( bCurrency )
760 : {
761 0 : eState = SsGetWord;
762 0 : sSymbol += OUString(cToken);
763 : }
764 : else
765 : {
766 1242029 : eType = nTmpType;
767 1242029 : sal_Int32 nLen = sKeyword[eType].getLength();
768 1242029 : sSymbol = rStr.copy( nPos-1, nLen );
769 1242029 : if ((eType == NF_KEY_E || IsAmbiguousE(eType)) && nPos < rStr.getLength())
770 : {
771 101867 : sal_Unicode cNext = rStr[nPos];
772 101867 : switch ( cNext )
773 : {
774 : case '+' :
775 : case '-' : // E+ E- combine to one symbol
776 15954 : sSymbol += OUString(cNext);
777 15954 : eType = NF_KEY_E;
778 15954 : nPos++;
779 15954 : break;
780 : case '0' :
781 : case '#' : // scientific E without sign
782 0 : eType = NF_KEY_E;
783 0 : break;
784 : }
785 : }
786 1242029 : nPos--;
787 1242029 : nPos = nPos + nLen;
788 1242029 : eState = SsStop;
789 : }
790 : }
791 : else
792 : {
793 172200 : eState = SsGetWord;
794 172200 : sSymbol += OUString(cToken);
795 : }
796 : }
797 : else
798 : {
799 315726 : eType = NF_SYMBOLTYPE_STRING;
800 315726 : eState = SsStop;
801 315726 : sSymbol += OUString(cToken);
802 : }
803 1729955 : break;
804 : }
805 5788299 : break;
806 : case SsGetChar:
807 3194 : sSymbol += OUString(cToken);
808 3194 : eState = SsStop;
809 3194 : break;
810 : case SsGetString:
811 13910 : if (cToken == '"')
812 : {
813 5504 : eState = SsStop;
814 : }
815 13910 : sSymbol += OUString(cToken);
816 13910 : break;
817 : case SsGetWord:
818 273370 : if ( pChrCls->isLetter( rStr, nPos-1 ) )
819 : {
820 272395 : short nTmpType = GetKeyWord( rStr, nPos-1 );
821 272395 : if ( nTmpType )
822 : {
823 : // beginning of keyword, stop scan and put back
824 163353 : eType = NF_SYMBOLTYPE_STRING;
825 163353 : eState = SsStop;
826 163353 : nPos--;
827 : }
828 : else
829 : {
830 109042 : sSymbol += OUString(cToken);
831 : }
832 : }
833 : else
834 : {
835 975 : bool bDontStop = false;
836 : sal_Unicode cNext;
837 975 : 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 975 : if ( eState != SsStop && !bDontStop )
858 : {
859 975 : eState = SsStop;
860 975 : nPos--;
861 975 : eType = NF_SYMBOLTYPE_STRING;
862 : }
863 : }
864 273370 : break;
865 : case SsGetStar:
866 34938 : eState = SsStop;
867 34938 : sSymbol += OUString(cToken);
868 34938 : nRepPos = (nPos - nStart) - 1; // everytime > 0!!
869 34938 : break;
870 : case SsGetBlank:
871 26052 : eState = SsStop;
872 26052 : sSymbol += OUString(cToken);
873 26052 : break;
874 : default:
875 0 : break;
876 : } // of switch
877 : } // of while
878 5788299 : if (eState == SsGetWord)
879 : {
880 7872 : eType = NF_SYMBOLTYPE_STRING;
881 : }
882 5788299 : return eType;
883 : }
884 :
885 688667 : sal_Int32 ImpSvNumberformatScan::Symbol_Division(const OUString& rString)
886 : {
887 688667 : nCurrPos = -1;
888 : // Do we have some sort of currency?
889 688667 : OUString sString = pFormatter->GetCharClass()->uppercase(rString);
890 688667 : sal_Int32 nCPos = 0;
891 2067129 : while (nCPos >= 0)
892 : {
893 689795 : nCPos = sString.indexOf(GetCurString(),nCPos);
894 689795 : if (nCPos >= 0)
895 : {
896 : // In Quotes?
897 192583 : sal_Int32 nQ = SvNumberformat::GetQuoteEnd( sString, nCPos );
898 192583 : if ( nQ < 0 )
899 : {
900 : sal_Unicode c;
901 534785 : if ( nCPos == 0 ||
902 151747 : ((c = sString[nCPos-1]) != '"'
903 151747 : && c != '\\') ) // dm can be protected by "dm \d
904 : {
905 191455 : nCurrPos = nCPos;
906 191455 : nCPos = -1;
907 : }
908 : else
909 : {
910 128 : nCPos++; // Continue search
911 : }
912 : }
913 : else
914 : {
915 1000 : nCPos = nQ + 1; // Continue search
916 : }
917 : }
918 : }
919 688667 : nAnzStrings = 0;
920 688667 : bool bStar = false; // Is set on detecting '*'
921 688667 : Reset();
922 :
923 688667 : sal_Int32 nPos = 0;
924 688667 : const sal_Int32 nLen = rString.getLength();
925 7166753 : while (nPos < nLen && nAnzStrings < NF_MAX_FORMAT_SYMBOLS)
926 : {
927 5789419 : nTypeArray[nAnzStrings] = Next_Symbol(rString, nPos, sStrArray[nAnzStrings]);
928 5789419 : if (nTypeArray[nAnzStrings] == NF_SYMBOLTYPE_STAR)
929 : { // Monitoring the '*'
930 34938 : if (bStar)
931 : {
932 0 : return nPos; // Error: double '*'
933 : }
934 : else
935 : {
936 : // Valid only if there is a character following, else we are
937 : // at the end of a code that does not have a fill character
938 : // (yet?).
939 34938 : if (sStrArray[nAnzStrings].getLength() < 2)
940 0 : return nPos;
941 34938 : bStar = true;
942 : }
943 : }
944 5789419 : nAnzStrings++;
945 : }
946 :
947 688667 : return 0; // 0 => ok
948 : }
949 :
950 4942474 : void ImpSvNumberformatScan::SkipStrings(sal_uInt16& i, sal_Int32& nPos)
951 : {
952 10101142 : while (i < nAnzStrings && ( nTypeArray[i] == NF_SYMBOLTYPE_STRING
953 4314797 : || nTypeArray[i] == NF_SYMBOLTYPE_BLANK
954 4288745 : || nTypeArray[i] == NF_SYMBOLTYPE_STAR) )
955 : {
956 216194 : nPos = nPos + sStrArray[i].getLength();
957 216194 : i++;
958 : }
959 4942474 : }
960 :
961 196962 : sal_uInt16 ImpSvNumberformatScan::PreviousKeyword(sal_uInt16 i)
962 : {
963 196962 : short res = 0;
964 196962 : if (i > 0 && i < nAnzStrings)
965 : {
966 130306 : i--;
967 422834 : while (i > 0 && nTypeArray[i] <= 0)
968 : {
969 162222 : i--;
970 : }
971 130306 : if (nTypeArray[i] > 0)
972 : {
973 130300 : res = nTypeArray[i];
974 : }
975 : }
976 196962 : return res;
977 : }
978 :
979 165092 : sal_uInt16 ImpSvNumberformatScan::NextKeyword(sal_uInt16 i)
980 : {
981 165092 : short res = 0;
982 165092 : if (i < nAnzStrings-1)
983 : {
984 156374 : i++;
985 452878 : while (i < nAnzStrings-1 && nTypeArray[i] <= 0)
986 : {
987 140130 : i++;
988 : }
989 156374 : if (nTypeArray[i] > 0)
990 : {
991 156334 : res = nTypeArray[i];
992 : }
993 : }
994 165092 : return res;
995 : }
996 :
997 180 : short ImpSvNumberformatScan::PreviousType( sal_uInt16 i )
998 : {
999 180 : if ( i > 0 && i < nAnzStrings )
1000 : {
1001 180 : do
1002 : {
1003 180 : i--;
1004 : }
1005 180 : while ( i > 0 && nTypeArray[i] == NF_SYMBOLTYPE_EMPTY );
1006 180 : return nTypeArray[i];
1007 : }
1008 0 : return 0;
1009 : }
1010 :
1011 409494 : sal_Unicode ImpSvNumberformatScan::PreviousChar(sal_uInt16 i)
1012 : {
1013 409494 : sal_Unicode res = ' ';
1014 409494 : if (i > 0 && i < nAnzStrings)
1015 : {
1016 342838 : i--;
1017 979431 : while (i > 0 &&
1018 587130 : ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
1019 586956 : nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
1020 586814 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1021 293407 : nTypeArray[i] == NF_SYMBOLTYPE_BLANK ))
1022 : {
1023 174 : i--;
1024 : }
1025 342838 : if (sStrArray[i].getLength() > 0)
1026 : {
1027 342838 : res = sStrArray[i][sStrArray[i].getLength()-1];
1028 : }
1029 : }
1030 409494 : return res;
1031 : }
1032 :
1033 276900 : sal_Unicode ImpSvNumberformatScan::NextChar(sal_uInt16 i)
1034 : {
1035 276900 : sal_Unicode res = ' ';
1036 276900 : if (i < nAnzStrings-1)
1037 : {
1038 276900 : i++;
1039 830550 : while (i < nAnzStrings-1 &&
1040 553500 : ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
1041 553500 : nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
1042 553500 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1043 276750 : nTypeArray[i] == NF_SYMBOLTYPE_BLANK))
1044 : {
1045 0 : i++;
1046 : }
1047 276900 : if (sStrArray[i].getLength() > 0)
1048 : {
1049 276900 : res = sStrArray[i][0];
1050 : }
1051 : }
1052 276900 : return res;
1053 : }
1054 :
1055 32 : bool ImpSvNumberformatScan::IsLastBlankBeforeFrac(sal_uInt16 i)
1056 : {
1057 32 : bool res = true;
1058 32 : if (i < nAnzStrings-1)
1059 : {
1060 32 : bool bStop = false;
1061 32 : i++;
1062 112 : while (i < nAnzStrings-1 && !bStop)
1063 : {
1064 48 : i++;
1065 96 : if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
1066 48 : sStrArray[i][0] == '/')
1067 : {
1068 32 : bStop = true;
1069 : }
1070 32 : else if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
1071 16 : sStrArray[i][0] == ' ')
1072 : {
1073 0 : res = false;
1074 : }
1075 : }
1076 32 : if (!bStop) // no '/'{
1077 : {
1078 0 : res = false;
1079 : }
1080 : }
1081 : else
1082 : {
1083 0 : res = false; // no '/' any more
1084 : }
1085 32 : return res;
1086 : }
1087 :
1088 702717 : void ImpSvNumberformatScan::Reset()
1089 : {
1090 702717 : nAnzStrings = 0;
1091 702717 : nAnzResStrings = 0;
1092 702717 : eScannedType = NUMBERFORMAT_UNDEFINED;
1093 702717 : nRepPos = 0;
1094 702717 : bExp = false;
1095 702717 : bThousand = false;
1096 702717 : nThousand = 0;
1097 702717 : bDecSep = false;
1098 702717 : nDecPos = (sal_uInt16)-1;
1099 702717 : nExpPos = (sal_uInt16)-1;
1100 702717 : nBlankPos = (sal_uInt16)-1;
1101 702717 : nCntPre = 0;
1102 702717 : nCntPost = 0;
1103 702717 : nCntExp = 0;
1104 702717 : bFrac = false;
1105 702717 : bBlank = false;
1106 702717 : nNatNumModifier = 0;
1107 702717 : }
1108 :
1109 48086 : bool ImpSvNumberformatScan::Is100SecZero( sal_uInt16 i, bool bHadDecSep )
1110 : {
1111 48086 : sal_uInt16 nIndexPre = PreviousKeyword( i );
1112 96172 : return (nIndexPre == NF_KEY_S || nIndexPre == NF_KEY_SS) &&
1113 12 : (bHadDecSep ||
1114 48098 : ( i > 0 && nTypeArray[i-1] == NF_SYMBOLTYPE_STRING));
1115 : // SS"any"00 take "any" as a valid decimal separator
1116 : }
1117 :
1118 688667 : sal_Int32 ImpSvNumberformatScan::ScanType()
1119 : {
1120 688667 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1121 :
1122 688667 : sal_Int32 nPos = 0;
1123 688667 : sal_uInt16 i = 0;
1124 : short eNewType;
1125 688667 : bool bMatchBracket = false;
1126 688667 : bool bHaveGeneral = false; // if General/Standard encountered
1127 :
1128 688667 : SkipStrings(i, nPos);
1129 5631141 : while (i < nAnzStrings)
1130 : {
1131 4253807 : if (nTypeArray[i] > 0)
1132 : { // keyword
1133 : sal_uInt16 nIndexPre;
1134 : sal_uInt16 nIndexNex;
1135 : sal_Unicode cChar;
1136 :
1137 1009074 : switch (nTypeArray[i])
1138 : {
1139 : case NF_KEY_E: // E
1140 15954 : eNewType = NUMBERFORMAT_SCIENTIFIC;
1141 15954 : break;
1142 : case NF_KEY_AMPM: // AM,A,PM,P
1143 : case NF_KEY_AP:
1144 : case NF_KEY_H: // H
1145 : case NF_KEY_HH: // HH
1146 : case NF_KEY_S: // S
1147 : case NF_KEY_SS: // SS
1148 139262 : eNewType = NUMBERFORMAT_TIME;
1149 139262 : break;
1150 : case NF_KEY_M: // M
1151 : case NF_KEY_MM: // MM
1152 : // minute or month
1153 148876 : nIndexPre = PreviousKeyword(i);
1154 148876 : nIndexNex = NextKeyword(i);
1155 148876 : cChar = PreviousChar(i);
1156 148876 : if (nIndexPre == NF_KEY_H || // H
1157 83428 : nIndexPre == NF_KEY_HH || // HH
1158 83428 : nIndexNex == NF_KEY_S || // S
1159 74476 : nIndexNex == NF_KEY_SS || // SS
1160 : cChar == '[' ) // [M
1161 : {
1162 74400 : eNewType = NUMBERFORMAT_TIME;
1163 74400 : nTypeArray[i] -= 2; // 6 -> 4, 7 -> 5
1164 : }
1165 : else
1166 : {
1167 74476 : eNewType = NUMBERFORMAT_DATE;
1168 : }
1169 148876 : break;
1170 : case NF_KEY_MMM: // MMM
1171 : case NF_KEY_MMMM: // MMMM
1172 : case NF_KEY_MMMMM: // MMMMM
1173 : case NF_KEY_Q: // Q
1174 : case NF_KEY_QQ: // QQ
1175 : case NF_KEY_D: // D
1176 : case NF_KEY_DD: // DD
1177 : case NF_KEY_DDD: // DDD
1178 : case NF_KEY_DDDD: // DDDD
1179 : case NF_KEY_YY: // YY
1180 : case NF_KEY_YYYY: // YYYY
1181 : case NF_KEY_NN: // NN
1182 : case NF_KEY_NNN: // NNN
1183 : case NF_KEY_NNNN: // NNNN
1184 : case NF_KEY_WW : // WW
1185 : case NF_KEY_AAA : // AAA
1186 : case NF_KEY_AAAA : // AAAA
1187 : case NF_KEY_EC : // E
1188 : case NF_KEY_EEC : // EE
1189 : case NF_KEY_G : // G
1190 : case NF_KEY_GG : // GG
1191 : case NF_KEY_GGG : // GGG
1192 : case NF_KEY_R : // R
1193 : case NF_KEY_RR : // RR
1194 689112 : eNewType = NUMBERFORMAT_DATE;
1195 689112 : break;
1196 : case NF_KEY_CCC: // CCC
1197 7824 : eNewType = NUMBERFORMAT_CURRENCY;
1198 7824 : break;
1199 : case NF_KEY_GENERAL: // Standard
1200 8046 : eNewType = NUMBERFORMAT_NUMBER;
1201 8046 : bHaveGeneral = true;
1202 8046 : break;
1203 : default:
1204 0 : eNewType = NUMBERFORMAT_UNDEFINED;
1205 0 : break;
1206 : }
1207 : }
1208 : else
1209 : { // control character
1210 3244733 : switch ( sStrArray[i][0] )
1211 : {
1212 : case '#':
1213 : case '?':
1214 892844 : eNewType = NUMBERFORMAT_NUMBER;
1215 892844 : break;
1216 : case '0':
1217 701206 : if ( (eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME )
1218 : {
1219 31870 : if ( Is100SecZero( i, bDecSep ) )
1220 : {
1221 31870 : bDecSep = true; // subsequent 0's
1222 31870 : eNewType = NUMBERFORMAT_TIME;
1223 : }
1224 : else
1225 : {
1226 0 : return nPos; // Error
1227 : }
1228 : }
1229 : else
1230 : {
1231 669336 : eNewType = NUMBERFORMAT_NUMBER;
1232 : }
1233 701206 : break;
1234 : case '%':
1235 15736 : eNewType = NUMBERFORMAT_PERCENT;
1236 15736 : break;
1237 : case '/':
1238 132206 : eNewType = NUMBERFORMAT_FRACTION;
1239 132206 : break;
1240 : case '[':
1241 614163 : if ( i < nAnzStrings-1 &&
1242 393226 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1243 188505 : sStrArray[i+1][0] == '$' )
1244 : { // as of SV_NUMBERFORMATTER_VERSION_NEW_CURR
1245 111307 : eNewType = NUMBERFORMAT_CURRENCY;
1246 111307 : bMatchBracket = true;
1247 : }
1248 280242 : else if ( i < nAnzStrings-1 &&
1249 170612 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1250 77198 : sStrArray[i+1][0] == '~' )
1251 : { // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1252 77198 : eNewType = NUMBERFORMAT_DATE;
1253 77198 : bMatchBracket = true;
1254 : }
1255 : else
1256 : {
1257 16216 : sal_uInt16 nIndexNex = NextKeyword(i);
1258 16216 : if (nIndexNex == NF_KEY_H || // H
1259 0 : nIndexNex == NF_KEY_HH || // HH
1260 0 : nIndexNex == NF_KEY_M || // M
1261 0 : nIndexNex == NF_KEY_MM || // MM
1262 0 : nIndexNex == NF_KEY_S || // S
1263 : nIndexNex == NF_KEY_SS ) // SS
1264 16216 : eNewType = NUMBERFORMAT_TIME;
1265 : else
1266 : {
1267 0 : return nPos; // Error
1268 : }
1269 : }
1270 204721 : break;
1271 : case '@':
1272 9180 : eNewType = NUMBERFORMAT_TEXT;
1273 9180 : break;
1274 : default:
1275 1288840 : if (pLoc->getTime100SecSep().equals(sStrArray[i]))
1276 : {
1277 226663 : bDecSep = true; // for SS,0
1278 : }
1279 1288840 : eNewType = NUMBERFORMAT_UNDEFINED;
1280 1288840 : break;
1281 : }
1282 : }
1283 4253807 : if (eScannedType == NUMBERFORMAT_UNDEFINED)
1284 : {
1285 783327 : eScannedType = eNewType;
1286 : }
1287 3470480 : else if (eScannedType == NUMBERFORMAT_TEXT || eNewType == NUMBERFORMAT_TEXT)
1288 : {
1289 124 : eScannedType = NUMBERFORMAT_TEXT; // Text always remains text
1290 : }
1291 3470356 : else if (eNewType == NUMBERFORMAT_UNDEFINED)
1292 : { // Remains as is
1293 : }
1294 2277266 : else if (eScannedType != eNewType)
1295 : {
1296 834549 : switch (eScannedType)
1297 : {
1298 : case NUMBERFORMAT_DATE:
1299 117014 : switch (eNewType)
1300 : {
1301 : case NUMBERFORMAT_TIME:
1302 16116 : eScannedType = NUMBERFORMAT_DATETIME;
1303 16116 : break;
1304 : case NUMBERFORMAT_FRACTION: // DD/MM
1305 100898 : break;
1306 : default:
1307 0 : if (nCurrPos >= 0)
1308 : {
1309 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1310 : }
1311 0 : else if ( sStrArray[i] != OUString(pFormatter->GetDateSep()) )
1312 : {
1313 0 : return nPos;
1314 : }
1315 : }
1316 117014 : break;
1317 : case NUMBERFORMAT_TIME:
1318 0 : switch (eNewType)
1319 : {
1320 : case NUMBERFORMAT_DATE:
1321 0 : eScannedType = NUMBERFORMAT_DATETIME;
1322 0 : break;
1323 : case NUMBERFORMAT_FRACTION: // MM/SS
1324 0 : break;
1325 : default:
1326 0 : if (nCurrPos >= 0)
1327 : {
1328 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1329 : }
1330 0 : else if (!pLoc->getTimeSep().equals(sStrArray[i]))
1331 : {
1332 0 : return nPos;
1333 : }
1334 0 : break;
1335 : }
1336 0 : break;
1337 : case NUMBERFORMAT_DATETIME:
1338 31664 : switch (eNewType)
1339 : {
1340 : case NUMBERFORMAT_TIME:
1341 : case NUMBERFORMAT_DATE:
1342 31664 : break;
1343 : case NUMBERFORMAT_FRACTION: // DD/MM
1344 0 : break;
1345 : default:
1346 0 : if (nCurrPos >= 0)
1347 : {
1348 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1349 : }
1350 0 : else if ( OUString(pFormatter->GetDateSep()) != sStrArray[i] &&
1351 0 : !pLoc->getTimeSep().equals(sStrArray[i]) )
1352 : {
1353 0 : return nPos;
1354 : }
1355 : }
1356 31664 : break;
1357 : case NUMBERFORMAT_PERCENT:
1358 0 : switch (eNewType)
1359 : {
1360 : case NUMBERFORMAT_NUMBER: // Only number to percent
1361 0 : break;
1362 : default:
1363 0 : return nPos;
1364 : }
1365 0 : break;
1366 : case NUMBERFORMAT_SCIENTIFIC:
1367 39440 : switch (eNewType)
1368 : {
1369 : case NUMBERFORMAT_NUMBER: // Only number to E
1370 39440 : break;
1371 : default:
1372 0 : return nPos;
1373 : }
1374 39440 : break;
1375 : case NUMBERFORMAT_NUMBER:
1376 72127 : switch (eNewType)
1377 : {
1378 : case NUMBERFORMAT_SCIENTIFIC:
1379 : case NUMBERFORMAT_PERCENT:
1380 : case NUMBERFORMAT_FRACTION:
1381 : case NUMBERFORMAT_CURRENCY:
1382 72127 : eScannedType = eNewType;
1383 72127 : break;
1384 : default:
1385 0 : if (nCurrPos >= 0)
1386 : {
1387 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1388 : }
1389 : else
1390 : {
1391 0 : return nPos;
1392 : }
1393 : }
1394 72127 : break;
1395 : case NUMBERFORMAT_FRACTION:
1396 39126 : switch (eNewType)
1397 : {
1398 : case NUMBERFORMAT_NUMBER: // Only number to fraction
1399 39126 : break;
1400 : default:
1401 0 : return nPos;
1402 : }
1403 39126 : break;
1404 : default:
1405 535178 : break;
1406 : }
1407 : }
1408 4253807 : nPos = nPos + sStrArray[i].getLength(); // Position of correction
1409 4253807 : i++;
1410 4253807 : if ( bMatchBracket )
1411 : { // no type detection inside of matching brackets if [$...], [~...]
1412 1696428 : while ( bMatchBracket && i < nAnzStrings )
1413 : {
1414 2638836 : if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL
1415 1319418 : && sStrArray[i][0] == ']' )
1416 : {
1417 188505 : bMatchBracket = false;
1418 : }
1419 : else
1420 : {
1421 1130913 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1422 : }
1423 1319418 : nPos = nPos + sStrArray[i].getLength();
1424 1319418 : i++;
1425 : }
1426 188505 : if ( bMatchBracket )
1427 : {
1428 0 : return nPos; // missing closing bracket at end of code
1429 : }
1430 : }
1431 4253807 : SkipStrings(i, nPos);
1432 : }
1433 :
1434 1210386 : if ((eScannedType == NUMBERFORMAT_NUMBER ||
1435 689639 : eScannedType == NUMBERFORMAT_UNDEFINED) &&
1436 248170 : nCurrPos >= 0 && !bHaveGeneral)
1437 : {
1438 80250 : eScannedType = NUMBERFORMAT_CURRENCY; // old "automatic" currency
1439 : }
1440 688667 : if (eScannedType == NUMBERFORMAT_UNDEFINED)
1441 : {
1442 930 : eScannedType = NUMBERFORMAT_DEFINED;
1443 : }
1444 688667 : return 0; // All is fine
1445 : }
1446 :
1447 260406 : bool ImpSvNumberformatScan::InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr )
1448 : {
1449 260406 : if (nAnzStrings >= NF_MAX_FORMAT_SYMBOLS || nPos > nAnzStrings)
1450 : {
1451 0 : return false;
1452 : }
1453 260406 : if (nPos > 0 && nTypeArray[nPos-1] == NF_SYMBOLTYPE_EMPTY)
1454 : {
1455 260406 : --nPos; // reuse position
1456 : }
1457 : else
1458 : {
1459 0 : if ((size_t) (nAnzStrings + 1) >= NF_MAX_FORMAT_SYMBOLS)
1460 : {
1461 0 : return false;
1462 : }
1463 0 : ++nAnzStrings;
1464 0 : for (size_t i = nAnzStrings; i > nPos; --i)
1465 : {
1466 0 : nTypeArray[i] = nTypeArray[i-1];
1467 0 : sStrArray[i] = sStrArray[i-1];
1468 : }
1469 : }
1470 260406 : ++nAnzResStrings;
1471 260406 : nTypeArray[nPos] = static_cast<short>(eType);
1472 260406 : sStrArray[nPos] = rStr;
1473 260406 : return true;
1474 : }
1475 :
1476 609172 : int ImpSvNumberformatScan::FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i,
1477 : sal_uInt16& rAnzResStrings )
1478 : {
1479 1827508 : if ( i < nAnzStrings-1 &&
1480 686362 : sStrArray[i][0] == '[' &&
1481 763568 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1482 77198 : sStrArray[i+1][0] == '~' )
1483 : {
1484 : // [~calendarID]
1485 : // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1486 77198 : nPos = nPos + sStrArray[i].getLength(); // [
1487 77198 : nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
1488 77198 : nPos = nPos + sStrArray[++i].getLength(); // ~
1489 77198 : sStrArray[i-1] += sStrArray[i]; // [~
1490 77198 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1491 77198 : rAnzResStrings--;
1492 77198 : if ( ++i >= nAnzStrings )
1493 : {
1494 0 : return -1; // error
1495 : }
1496 77198 : nPos = nPos + sStrArray[i].getLength(); // calendarID
1497 77198 : OUString& rStr = sStrArray[i];
1498 77198 : nTypeArray[i] = NF_SYMBOLTYPE_CALENDAR; // convert
1499 77198 : i++;
1500 463362 : while ( i < nAnzStrings && sStrArray[i][0] != ']' )
1501 : {
1502 308966 : nPos = nPos + sStrArray[i].getLength();
1503 308966 : rStr += sStrArray[i];
1504 308966 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1505 308966 : rAnzResStrings--;
1506 308966 : i++;
1507 : }
1508 154396 : if ( rStr.getLength() && i < nAnzStrings &&
1509 77198 : sStrArray[i][0] == ']' )
1510 : {
1511 77198 : nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
1512 77198 : nPos = nPos + sStrArray[i].getLength();
1513 77198 : i++;
1514 : }
1515 : else
1516 : {
1517 0 : return -1; // error
1518 : }
1519 77198 : return 1;
1520 : }
1521 531974 : return 0;
1522 : }
1523 :
1524 688667 : sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
1525 : {
1526 688667 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1527 :
1528 : // save values for convert mode
1529 688667 : OUString sOldDecSep = pFormatter->GetNumDecimalSep();
1530 1377334 : OUString sOldThousandSep = pFormatter->GetNumThousandSep();
1531 1377334 : OUString sOldDateSep = pFormatter->GetDateSep();
1532 1377334 : OUString sOldTimeSep = pLoc->getTimeSep();
1533 1377334 : OUString sOldTime100SecSep= pLoc->getTime100SecSep();
1534 1377334 : OUString sOldCurSymbol = GetCurSymbol();
1535 1377334 : OUString sOldCurString = GetCurString();
1536 688667 : sal_Unicode cOldKeyH = sKeyword[NF_KEY_H][0];
1537 688667 : sal_Unicode cOldKeyMI = sKeyword[NF_KEY_MI][0];
1538 688667 : sal_Unicode cOldKeyS = sKeyword[NF_KEY_S][0];
1539 :
1540 : // If the group separator is a No-Break Space (French) continue with a
1541 : // normal space instead so queries on space work correctly.
1542 : // The same for Narrow No-Break Space just in case some locale uses it.
1543 : // The format string is adjusted to allow both.
1544 : // For output of the format code string the LocaleData characters are used.
1545 689387 : if ( (sOldThousandSep[0] == cNoBreakSpace || sOldThousandSep[0] == cNarrowNoBreakSpace) &&
1546 720 : sOldThousandSep.getLength() == 1 )
1547 : {
1548 720 : sOldThousandSep = " ";
1549 : }
1550 : // change locale data et al
1551 688667 : if (bConvertMode)
1552 : {
1553 20442 : pFormatter->ChangeIntl(eNewLnge);
1554 : //! pointer may have changed
1555 20442 : pLoc = pFormatter->GetLocaleData();
1556 : //! init new keywords
1557 20442 : InitKeywords();
1558 : }
1559 688667 : const CharClass* pChrCls = pFormatter->GetCharClass();
1560 :
1561 688667 : sal_Int32 nPos = 0; // error correction position
1562 688667 : sal_uInt16 i = 0; // symbol loop counter
1563 688667 : sal_uInt16 nCounter = 0; // counts digits
1564 688667 : nAnzResStrings = nAnzStrings; // counts remaining symbols
1565 688667 : bDecSep = false; // reset in case already used in TypeCheck
1566 688667 : bool bThaiT = false; // Thai T NatNum modifier present
1567 688667 : bool bTimePart = false;
1568 :
1569 688667 : switch (eScannedType)
1570 : {
1571 : case NUMBERFORMAT_TEXT:
1572 : case NUMBERFORMAT_DEFINED:
1573 34980 : while (i < nAnzStrings)
1574 : {
1575 14760 : switch (nTypeArray[i])
1576 : {
1577 : case NF_SYMBOLTYPE_BLANK:
1578 : case NF_SYMBOLTYPE_STAR:
1579 4188 : break;
1580 : case NF_KEY_GENERAL : // #77026# "General" is the same as "@"
1581 0 : break;
1582 : default:
1583 19968 : if ( nTypeArray[i] != NF_SYMBOLTYPE_DEL ||
1584 9396 : sStrArray[i][0] != '@' )
1585 : {
1586 1392 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1587 : }
1588 10572 : break;
1589 : }
1590 14760 : nPos = nPos + sStrArray[i].getLength();
1591 14760 : i++;
1592 : } // of while
1593 10110 : break;
1594 :
1595 : case NUMBERFORMAT_NUMBER:
1596 : case NUMBERFORMAT_PERCENT:
1597 : case NUMBERFORMAT_CURRENCY:
1598 : case NUMBERFORMAT_SCIENTIFIC:
1599 : case NUMBERFORMAT_FRACTION:
1600 2550377 : while (i < nAnzStrings)
1601 : {
1602 : // TODO: rechecking eScannedType is unnecessary.
1603 : // This switch-case is for eScannedType == NUMBERFORMAT_FRACTION anyway
1604 3892084 : if (eScannedType == NUMBERFORMAT_FRACTION && // special case
1605 328628 : nTypeArray[i] == NF_SYMBOLTYPE_DEL && // # ### #/#
1606 140998 : StringEqualsChar( sOldThousandSep, ' ' ) && // e.g. France or Sweden
1607 176 : StringEqualsChar( sStrArray[i], ' ' ) &&
1608 1852219 : !bFrac &&
1609 32 : IsLastBlankBeforeFrac(i) )
1610 : {
1611 32 : nTypeArray[i] = NF_SYMBOLTYPE_STRING; // del->string
1612 : } // No thousands marker
1613 :
1614 3681840 : if (nTypeArray[i] == NF_SYMBOLTYPE_BLANK ||
1615 3625038 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1616 3582882 : nTypeArray[i] == NF_KEY_CCC || // CCC
1617 1787529 : nTypeArray[i] == NF_KEY_GENERAL ) // Standard
1618 : {
1619 72672 : if (nTypeArray[i] == NF_KEY_GENERAL)
1620 : {
1621 8046 : nThousand = FLAG_STANDARD_IN_FORMAT;
1622 8046 : if ( bConvertMode )
1623 : {
1624 198 : sStrArray[i] = sNameStandardFormat;
1625 : }
1626 : }
1627 72672 : nPos = nPos + sStrArray[i].getLength();
1628 72672 : i++;
1629 : }
1630 3390070 : else if (nTypeArray[i] == NF_SYMBOLTYPE_STRING || // No Strings or
1631 1610587 : nTypeArray[i] > 0) // Keywords
1632 : {
1633 200804 : if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
1634 15954 : nTypeArray[i] == NF_KEY_E) // E+
1635 : {
1636 15954 : if (bExp) // Double
1637 : {
1638 0 : return nPos;
1639 : }
1640 15954 : bExp = true;
1641 15954 : nExpPos = i;
1642 15954 : if (bDecSep)
1643 : {
1644 15948 : nCntPost = nCounter;
1645 : }
1646 : else
1647 : {
1648 6 : nCntPre = nCounter;
1649 : }
1650 15954 : nCounter = 0;
1651 15954 : nTypeArray[i] = NF_SYMBOLTYPE_EXP;
1652 : }
1653 215848 : else if (eScannedType == NUMBERFORMAT_FRACTION &&
1654 46952 : sStrArray[i][0] == ' ')
1655 : {
1656 31296 : if (!bBlank && !bFrac) // Not double or after a /
1657 : {
1658 32 : if (bDecSep && nCounter > 0) // Decimal places
1659 : {
1660 0 : return nPos; // Error
1661 : }
1662 32 : bBlank = true;
1663 32 : nBlankPos = i;
1664 32 : nCntPre = nCounter;
1665 32 : nCounter = 0;
1666 : }
1667 31296 : nTypeArray[i] = NF_SYMBOLTYPE_FRACBLANK;
1668 : }
1669 137600 : else if (nTypeArray[i] == NF_KEY_THAI_T)
1670 : {
1671 0 : bThaiT = true;
1672 0 : sStrArray[i] = sKeyword[nTypeArray[i]];
1673 : }
1674 157492 : else if (sStrArray[i][0] >= '0' &&
1675 19892 : sStrArray[i][0] <= '9')
1676 : {
1677 15650 : OUString sDiv;
1678 15650 : sal_uInt16 j = i;
1679 62600 : while(j < nAnzStrings)
1680 : {
1681 31300 : sDiv += sStrArray[j++];
1682 : }
1683 15650 : if (OUString::number(sDiv.toInt32()) == sDiv)
1684 : {
1685 : // Found a Divisor
1686 62600 : while (i < j)
1687 : {
1688 31300 : nTypeArray[i++] = NF_SYMBOLTYPE_FRAC_FDIV;
1689 : }
1690 15650 : i = j - 1; // Stop the loop
1691 15650 : if (nCntPost)
1692 : {
1693 15650 : nCounter = nCntPost;
1694 : }
1695 0 : else if (nCntPre)
1696 : {
1697 0 : nCounter = nCntPre;
1698 : }
1699 : // don't artificially increment nCntPre for forced denominator
1700 15650 : if ( ( eScannedType != NUMBERFORMAT_FRACTION ) && (!nCntPre) )
1701 : {
1702 0 : nCntPre++;
1703 : }
1704 15650 : }
1705 : }
1706 : else
1707 : {
1708 121950 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1709 : }
1710 184850 : nPos = nPos + sStrArray[i].getLength();
1711 184850 : i++;
1712 : }
1713 1594633 : else if (nTypeArray[i] == NF_SYMBOLTYPE_DEL)
1714 : {
1715 1594633 : sal_Unicode cHere = sStrArray[i][0];
1716 1594633 : sal_Unicode cSaved = cHere;
1717 : // Handle not pre-known separators in switch.
1718 : sal_Unicode cSimplified;
1719 1594633 : if (StringEqualsChar( pFormatter->GetNumThousandSep(), cHere))
1720 : {
1721 260132 : cSimplified = ',';
1722 : }
1723 1334501 : else if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cHere))
1724 : {
1725 187027 : cSimplified = '.';
1726 : }
1727 : else
1728 : {
1729 1147474 : cSimplified = cHere;
1730 : }
1731 :
1732 1594633 : OUString& rStr = sStrArray[i];
1733 :
1734 1594633 : switch ( cSimplified )
1735 : {
1736 : case '#':
1737 : case '0':
1738 : case '?':
1739 820064 : if (nThousand > 0) // #... #
1740 : {
1741 4 : return nPos; // Error
1742 : }
1743 820060 : else if (bFrac && cHere == '0')
1744 : {
1745 0 : return nPos; // Denominator is 0
1746 : }
1747 820060 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1748 820060 : nPos = nPos + rStr.getLength();
1749 820060 : i++;
1750 820060 : nCounter++;
1751 4410004 : while (i < nAnzStrings &&
1752 2365288 : (sStrArray[i][0] == '#' ||
1753 1662908 : sStrArray[i][0] == '0' ||
1754 614576 : sStrArray[i][0] == '?'))
1755 : {
1756 726464 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1757 726464 : nPos = nPos + sStrArray[i].getLength();
1758 726464 : nCounter++;
1759 726464 : i++;
1760 : }
1761 820060 : break;
1762 : case '-':
1763 189528 : if ( bDecSep && nDecPos+1 == i &&
1764 31302 : nTypeArray[nDecPos] == NF_SYMBOLTYPE_DECSEP )
1765 : {
1766 : // "0.--"
1767 31302 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1768 31302 : nPos = nPos + rStr.getLength();
1769 31302 : i++;
1770 31302 : nCounter++;
1771 125432 : while (i < nAnzStrings &&
1772 31526 : (sStrArray[i][0] == '-') )
1773 : {
1774 : // If more than two dashes are present in
1775 : // currency formats the last dash will be
1776 : // interpreted literally as a minus sign.
1777 : // Has to be this ugly. Period.
1778 62604 : if ( eScannedType == NUMBERFORMAT_CURRENCY
1779 31302 : && rStr.getLength() >= 2 &&
1780 0 : (i == nAnzStrings-1 ||
1781 0 : sStrArray[i+1][0] != '-') )
1782 : {
1783 0 : break;
1784 : }
1785 31302 : rStr += sStrArray[i];
1786 31302 : nPos = nPos + sStrArray[i].getLength();
1787 31302 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1788 31302 : nAnzResStrings--;
1789 31302 : nCounter++;
1790 31302 : i++;
1791 : }
1792 : }
1793 : else
1794 : {
1795 95622 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1796 95622 : nPos = nPos + sStrArray[i].getLength();
1797 95622 : i++;
1798 : }
1799 126924 : break;
1800 : case '.':
1801 : case ',':
1802 : case '\'':
1803 : case ' ':
1804 489300 : if ( StringEqualsChar( sOldThousandSep, cSaved ) )
1805 : {
1806 : // previous char with skip empty
1807 260618 : sal_Unicode cPre = PreviousChar(i);
1808 : sal_Unicode cNext;
1809 260618 : if (bExp || bBlank || bFrac)
1810 : {
1811 : // after E, / or ' '
1812 0 : if ( !StringEqualsChar( sOldThousandSep, ' ' ) )
1813 : {
1814 0 : nPos = nPos + sStrArray[i].getLength();
1815 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1816 0 : nAnzResStrings--;
1817 0 : i++; // eat it
1818 : }
1819 : else
1820 : {
1821 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1822 : }
1823 : }
1824 781854 : else if (i > 0 && i < nAnzStrings-1 &&
1825 781746 : (cPre == '#' || cPre == '0') &&
1826 260690 : ((cNext = NextChar(i)) == '#' || cNext == '0')) // #,#
1827 : {
1828 260406 : nPos = nPos + sStrArray[i].getLength();
1829 260406 : if (!bThousand) // only once
1830 : {
1831 260406 : bThousand = true;
1832 : }
1833 : // Eat it, will be reinserted at proper grouping positions further down.
1834 260406 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1835 260406 : nAnzResStrings--;
1836 260406 : i++;
1837 : }
1838 636 : else if (i > 0 && (cPre == '#' || cPre == '0')
1839 180 : && PreviousType(i) == NF_SYMBOLTYPE_DIGIT
1840 392 : && nThousand < FLAG_STANDARD_IN_FORMAT )
1841 : { // #,,,,
1842 180 : if ( StringEqualsChar( sOldThousandSep, ' ' ) )
1843 : {
1844 : // strange, those French..
1845 136 : bool bFirst = true;
1846 : // set a hard No-Break Space or ConvertMode
1847 136 : const OUString& rSepF = pFormatter->GetNumThousandSep();
1848 544 : while ( i < nAnzStrings &&
1849 272 : sStrArray[i] == sOldThousandSep &&
1850 136 : StringEqualsChar( sOldThousandSep, NextChar(i) ) )
1851 : { // last was a space or another space
1852 : // is following => separator
1853 0 : nPos = nPos + sStrArray[i].getLength();
1854 0 : if ( bFirst )
1855 : {
1856 0 : bFirst = false;
1857 0 : rStr = rSepF;
1858 0 : nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
1859 : }
1860 : else
1861 : {
1862 0 : rStr += rSepF;
1863 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1864 0 : nAnzResStrings--;
1865 : }
1866 0 : nThousand++;
1867 0 : i++;
1868 : }
1869 272 : if ( i < nAnzStrings-1 &&
1870 136 : sStrArray[i] == sOldThousandSep )
1871 : {
1872 : // something following last space
1873 : // => space if currency contained,
1874 : // else separator
1875 136 : nPos = nPos + sStrArray[i].getLength();
1876 400 : if ( (nPos <= nCurrPos &&
1877 200 : nCurrPos < nPos + sStrArray[i+1].getLength()) ||
1878 408 : nTypeArray[i+1] == NF_KEY_CCC ||
1879 128 : (i < nAnzStrings-2 &&
1880 128 : sStrArray[i+1][0] == '[' &&
1881 64 : sStrArray[i+2][0] == '$') )
1882 : {
1883 136 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1884 : }
1885 : else
1886 : {
1887 0 : if ( bFirst )
1888 : {
1889 0 : bFirst = false;
1890 0 : rStr = rSepF;
1891 0 : nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
1892 : }
1893 : else
1894 : {
1895 0 : rStr += rSepF;
1896 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1897 0 : nAnzResStrings--;
1898 : }
1899 0 : nThousand++;
1900 : }
1901 136 : i++;
1902 : }
1903 : }
1904 : else
1905 : {
1906 44 : do
1907 : {
1908 44 : nThousand++;
1909 44 : nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
1910 44 : nPos = nPos + sStrArray[i].getLength();
1911 44 : sStrArray[i] = pFormatter->GetNumThousandSep();
1912 44 : i++;
1913 : }
1914 44 : while (i < nAnzStrings && sStrArray[i] == sOldThousandSep);
1915 : }
1916 : }
1917 : else // any grsep
1918 : {
1919 32 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1920 32 : nPos = nPos + rStr.getLength();
1921 32 : i++;
1922 64 : while ( i < nAnzStrings && sStrArray[i] == sOldThousandSep )
1923 : {
1924 0 : rStr += sStrArray[i];
1925 0 : nPos = nPos + sStrArray[i].getLength();
1926 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1927 0 : nAnzResStrings--;
1928 0 : i++;
1929 : }
1930 : }
1931 : }
1932 228682 : else if ( StringEqualsChar( sOldDecSep, cSaved ) )
1933 : {
1934 187027 : if (bBlank || bFrac) // . behind / or ' '
1935 : {
1936 0 : return nPos; // error
1937 : }
1938 187027 : else if (bExp) // behind E
1939 : {
1940 0 : nPos = nPos + sStrArray[i].getLength();
1941 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1942 0 : nAnzResStrings--;
1943 0 : i++; // eat it
1944 : }
1945 187027 : else if (bDecSep) // any .
1946 : {
1947 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1948 0 : nPos = nPos + rStr.getLength();
1949 0 : i++;
1950 0 : while ( i < nAnzStrings && sStrArray[i] == sOldDecSep )
1951 : {
1952 0 : rStr += sStrArray[i];
1953 0 : nPos = nPos + sStrArray[i].getLength();
1954 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1955 0 : nAnzResStrings--;
1956 0 : i++;
1957 : }
1958 : }
1959 : else
1960 : {
1961 187027 : nPos = nPos + sStrArray[i].getLength();
1962 187027 : nTypeArray[i] = NF_SYMBOLTYPE_DECSEP;
1963 187027 : sStrArray[i] = pFormatter->GetNumDecimalSep();
1964 187027 : bDecSep = true;
1965 187027 : nDecPos = i;
1966 187027 : nCntPre = nCounter;
1967 187027 : nCounter = 0;
1968 :
1969 187027 : i++;
1970 : }
1971 : } // of else = DecSep
1972 : else // . without meaning
1973 : {
1974 83310 : if (cSaved == ' ' &&
1975 72919 : eScannedType == NUMBERFORMAT_FRACTION &&
1976 31264 : StringEqualsChar( sStrArray[i], ' ' ) )
1977 : {
1978 31264 : if (!bBlank && !bFrac) // no dups
1979 : { // or behind /
1980 31264 : if (bDecSep && nCounter > 0) // dec.
1981 : {
1982 0 : return nPos; // error
1983 : }
1984 31264 : bBlank = true;
1985 31264 : nBlankPos = i;
1986 31264 : nCntPre = nCounter;
1987 31264 : nCounter = 0;
1988 : }
1989 31264 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1990 31264 : nPos = nPos + sStrArray[i].getLength();
1991 : }
1992 : else
1993 : {
1994 10391 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1995 10391 : nPos = nPos + rStr.getLength();
1996 10391 : i++;
1997 20782 : while (i < nAnzStrings && StringEqualsChar( sStrArray[i], cSaved ) )
1998 : {
1999 0 : rStr += sStrArray[i];
2000 0 : nPos = nPos + sStrArray[i].getLength();
2001 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2002 0 : nAnzResStrings--;
2003 0 : i++;
2004 : }
2005 : }
2006 : }
2007 489300 : break;
2008 : case '/':
2009 31302 : if (eScannedType == NUMBERFORMAT_FRACTION)
2010 : {
2011 62604 : if ( i == 0 ||
2012 31302 : (nTypeArray[i-1] != NF_SYMBOLTYPE_DIGIT &&
2013 0 : nTypeArray[i-1] != NF_SYMBOLTYPE_EMPTY) )
2014 : {
2015 0 : return nPos ? nPos : 1; // /? not allowed
2016 : }
2017 31302 : else if (!bFrac || (bDecSep && nCounter > 0))
2018 : {
2019 31302 : bFrac = true;
2020 31302 : nCntPost = nCounter;
2021 31302 : nCounter = 0;
2022 31302 : nTypeArray[i] = NF_SYMBOLTYPE_FRAC;
2023 31302 : nPos = nPos + sStrArray[i].getLength();
2024 31302 : i++;
2025 : }
2026 : else // / double or in , in the denominator
2027 : {
2028 0 : return nPos; // Error
2029 : }
2030 : }
2031 : else
2032 : {
2033 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2034 0 : nPos = nPos + sStrArray[i].getLength();
2035 0 : i++;
2036 : }
2037 31302 : break;
2038 : case '[' :
2039 333921 : if ( eScannedType == NUMBERFORMAT_CURRENCY &&
2040 222614 : i < nAnzStrings-1 &&
2041 333921 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
2042 111307 : sStrArray[i+1][0] == '$' )
2043 : {
2044 : // [$DM-xxx]
2045 : // As of SV_NUMBERFORMATTER_VERSION_NEW_CURR
2046 111307 : nPos = nPos + sStrArray[i].getLength(); // [
2047 111307 : nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
2048 111307 : nPos = nPos + sStrArray[++i].getLength(); // $
2049 111307 : sStrArray[i-1] += sStrArray[i]; // [$
2050 111307 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2051 111307 : nAnzResStrings--;
2052 111307 : if ( ++i >= nAnzStrings )
2053 : {
2054 0 : return nPos; // Error
2055 : }
2056 111307 : nPos = nPos + sStrArray[i].getLength(); // DM
2057 111307 : OUString* pStr = &sStrArray[i];
2058 111307 : nTypeArray[i] = NF_SYMBOLTYPE_CURRENCY; // convert
2059 111307 : bool bHadDash = false;
2060 111307 : i++;
2061 667551 : while ( i < nAnzStrings && sStrArray[i][0] != ']' )
2062 : {
2063 444937 : nPos = nPos + sStrArray[i].getLength();
2064 444937 : if ( bHadDash )
2065 : {
2066 331924 : *pStr += sStrArray[i];
2067 331924 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2068 331924 : nAnzResStrings--;
2069 : }
2070 : else
2071 : {
2072 113013 : if ( sStrArray[i][0] == '-' )
2073 : {
2074 110600 : bHadDash = true;
2075 110600 : pStr = &sStrArray[i];
2076 110600 : nTypeArray[i] = NF_SYMBOLTYPE_CURREXT;
2077 : }
2078 : else
2079 : {
2080 2413 : *pStr += sStrArray[i];
2081 2413 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2082 2413 : nAnzResStrings--;
2083 : }
2084 : }
2085 444937 : i++;
2086 : }
2087 111307 : if ( rStr.getLength() && i < nAnzStrings && sStrArray[i][0] == ']' )
2088 : {
2089 111307 : nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
2090 111307 : nPos = nPos + sStrArray[i].getLength();
2091 111307 : i++;
2092 : }
2093 : else
2094 : {
2095 0 : return nPos; // Error
2096 : }
2097 : }
2098 : else
2099 : {
2100 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2101 0 : nPos = nPos + sStrArray[i].getLength();
2102 0 : i++;
2103 : }
2104 111307 : break;
2105 : default: // Other Dels
2106 15736 : if (eScannedType == NUMBERFORMAT_PERCENT && cHere == '%')
2107 : {
2108 15736 : nTypeArray[i] = NF_SYMBOLTYPE_PERCENT;
2109 : }
2110 : else
2111 : {
2112 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2113 : }
2114 15736 : nPos = nPos + sStrArray[i].getLength();
2115 15736 : i++;
2116 15736 : break;
2117 : } // of switch (Del)
2118 : } // of else Del
2119 : else
2120 : {
2121 : SAL_WARN( "svl.numbers", "unknown NF_SYMBOLTYPE_..." );
2122 0 : nPos = nPos + sStrArray[i].getLength();
2123 0 : i++;
2124 : }
2125 : } // of while
2126 349109 : if (eScannedType == NUMBERFORMAT_FRACTION)
2127 : {
2128 31302 : if (bFrac)
2129 : {
2130 31302 : nCntExp = nCounter;
2131 : }
2132 0 : else if (bBlank)
2133 : {
2134 0 : nCntPost = nCounter;
2135 : }
2136 : else
2137 : {
2138 0 : nCntPre = nCounter;
2139 : }
2140 : }
2141 : else
2142 : {
2143 317807 : if (bExp)
2144 : {
2145 15950 : nCntExp = nCounter;
2146 : }
2147 301857 : else if (bDecSep)
2148 : {
2149 171079 : nCntPost = nCounter;
2150 : }
2151 : else
2152 : {
2153 130778 : nCntPre = nCounter;
2154 : }
2155 : }
2156 349109 : if (bThousand) // Expansion of grouping separators
2157 : {
2158 : sal_uInt16 nMaxPos;
2159 260406 : if (bFrac)
2160 : {
2161 0 : if (bBlank)
2162 : {
2163 0 : nMaxPos = nBlankPos;
2164 : }
2165 : else
2166 : {
2167 0 : nMaxPos = 0; // no grouping
2168 : }
2169 : }
2170 260406 : else if (bDecSep) // decimal separator present
2171 : {
2172 154338 : nMaxPos = nDecPos;
2173 : }
2174 106068 : else if (bExp) // 'E' exponent present
2175 : {
2176 0 : nMaxPos = nExpPos;
2177 : }
2178 : else // up to end
2179 : {
2180 106068 : nMaxPos = i;
2181 : }
2182 : // Insert separators at proper positions.
2183 260406 : sal_Int32 nCount = 0;
2184 260406 : utl::DigitGroupingIterator aGrouping( pLoc->getDigitGrouping());
2185 260406 : size_t nFirstDigitSymbol = nMaxPos;
2186 260406 : size_t nFirstGroupingSymbol = nMaxPos;
2187 260406 : i = nMaxPos;
2188 2694293 : while (i-- > 0)
2189 : {
2190 2173481 : if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2191 : {
2192 1041624 : nFirstDigitSymbol = i;
2193 1041624 : nCount = nCount + sStrArray[i].getLength(); // MSC converts += to int and then warns, so ...
2194 : // Insert separator only if not leftmost symbol.
2195 1041624 : if (i > 0 && nCount >= aGrouping.getPos())
2196 : {
2197 : DBG_ASSERT( sStrArray[i].getLength() == 1,
2198 : "ImpSvNumberformatScan::FinalScan: combined digits in group separator insertion");
2199 260406 : if (!InsertSymbol( i, NF_SYMBOLTYPE_THSEP, pFormatter->GetNumThousandSep()))
2200 : {
2201 : // nPos isn't correct here, but signals error
2202 0 : return nPos;
2203 : }
2204 : // i may have been decremented by 1
2205 260406 : nFirstDigitSymbol = i + 1;
2206 260406 : nFirstGroupingSymbol = i;
2207 260406 : aGrouping.advance();
2208 : }
2209 : }
2210 : }
2211 : // Generated something like "string",000; remove separator again.
2212 260406 : if (nFirstGroupingSymbol < nFirstDigitSymbol)
2213 : {
2214 0 : nTypeArray[nFirstGroupingSymbol] = NF_SYMBOLTYPE_EMPTY;
2215 0 : nAnzResStrings--;
2216 260406 : }
2217 : }
2218 : // Combine digits into groups to save memory (Info will be copied
2219 : // later, taking only non-empty symbols).
2220 2374004 : for (i = 0; i < nAnzStrings; ++i)
2221 : {
2222 2024895 : if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2223 : {
2224 851362 : OUString& rStr = sStrArray[i];
2225 2429188 : while (++i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2226 : {
2227 726464 : rStr += sStrArray[i];
2228 726464 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2229 726464 : nAnzResStrings--;
2230 : }
2231 : }
2232 : }
2233 349109 : break; // of NUMBERFORMAT_NUMBER
2234 : case NUMBERFORMAT_DATE:
2235 1840876 : while (i < nAnzStrings)
2236 : {
2237 : int nCalRet;
2238 1330884 : switch (nTypeArray[i])
2239 : {
2240 : case NF_SYMBOLTYPE_BLANK:
2241 : case NF_SYMBOLTYPE_STAR:
2242 : case NF_SYMBOLTYPE_STRING:
2243 16110 : nPos = nPos + sStrArray[i].getLength();
2244 16110 : i++;
2245 16110 : break;
2246 : case NF_SYMBOLTYPE_DEL:
2247 599442 : if (sStrArray[i] == sOldDateSep)
2248 : {
2249 70056 : nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
2250 70056 : nPos = nPos + sStrArray[i].getLength();
2251 70056 : if (bConvertMode)
2252 : {
2253 6334 : sStrArray[i] = pFormatter->GetDateSep();
2254 : }
2255 70056 : i++;
2256 : }
2257 529386 : else if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
2258 : {
2259 77174 : if ( nCalRet < 0 )
2260 : {
2261 0 : return nPos; // error
2262 : }
2263 : }
2264 : else
2265 : {
2266 452212 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2267 452212 : nPos = nPos + sStrArray[i].getLength();
2268 452212 : i++;
2269 : }
2270 599442 : break;
2271 : case NF_KEY_THAI_T :
2272 0 : bThaiT = true;
2273 : // fall thru
2274 : case NF_KEY_M: // M
2275 : case NF_KEY_MM: // MM
2276 : case NF_KEY_MMM: // MMM
2277 : case NF_KEY_MMMM: // MMMM
2278 : case NF_KEY_MMMMM: // MMMMM
2279 : case NF_KEY_Q: // Q
2280 : case NF_KEY_QQ: // QQ
2281 : case NF_KEY_D: // D
2282 : case NF_KEY_DD: // DD
2283 : case NF_KEY_DDD: // DDD
2284 : case NF_KEY_DDDD: // DDDD
2285 : case NF_KEY_YY: // YY
2286 : case NF_KEY_YYYY: // YYYY
2287 : case NF_KEY_NN: // NN
2288 : case NF_KEY_NNN: // NNN
2289 : case NF_KEY_NNNN: // NNNN
2290 : case NF_KEY_WW : // WW
2291 : case NF_KEY_AAA : // AAA
2292 : case NF_KEY_AAAA : // AAAA
2293 : case NF_KEY_EC : // E
2294 : case NF_KEY_EEC : // EE
2295 : case NF_KEY_G : // G
2296 : case NF_KEY_GG : // GG
2297 : case NF_KEY_GGG : // GGG
2298 : case NF_KEY_R : // R
2299 : case NF_KEY_RR : // RR
2300 715332 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2301 715332 : nPos = nPos + sStrArray[i].getLength();
2302 715332 : i++;
2303 715332 : break;
2304 : default: // Other keywords
2305 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2306 0 : nPos = nPos + sStrArray[i].getLength();
2307 0 : i++;
2308 0 : break;
2309 : }
2310 : } // of while
2311 254996 : break; // of NUMBERFORMAT_DATE
2312 : case NUMBERFORMAT_TIME:
2313 455008 : while (i < nAnzStrings)
2314 : {
2315 : sal_Unicode cChar;
2316 :
2317 338344 : switch (nTypeArray[i])
2318 : {
2319 : case NF_SYMBOLTYPE_BLANK:
2320 : case NF_SYMBOLTYPE_STAR:
2321 0 : nPos = nPos + sStrArray[i].getLength();
2322 0 : i++;
2323 0 : break;
2324 : case NF_SYMBOLTYPE_DEL:
2325 172372 : switch( sStrArray[i][0] )
2326 : {
2327 : case '0':
2328 16216 : if ( Is100SecZero( i, bDecSep ) )
2329 : {
2330 16216 : bDecSep = true;
2331 16216 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
2332 16216 : OUString& rStr = sStrArray[i];
2333 16216 : i++;
2334 16216 : nPos = nPos + sStrArray[i].getLength();
2335 16216 : nCounter++;
2336 63740 : while (i < nAnzStrings &&
2337 15654 : sStrArray[i][0] == '0')
2338 : {
2339 15654 : rStr += sStrArray[i];
2340 15654 : nPos = nPos + sStrArray[i].getLength();
2341 15654 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2342 15654 : nAnzResStrings--;
2343 15654 : nCounter++;
2344 15654 : i++;
2345 : }
2346 : }
2347 : else
2348 : {
2349 0 : return nPos;
2350 : }
2351 16216 : break;
2352 : case '#':
2353 : case '?':
2354 0 : return nPos;
2355 : case '[':
2356 16216 : if (bThousand) // Double
2357 : {
2358 0 : return nPos;
2359 : }
2360 16216 : bThousand = true; // Empty for Time
2361 16216 : cChar = pChrCls->uppercase(OUString(NextChar(i)))[0];
2362 16216 : if ( cChar == cOldKeyH )
2363 : {
2364 16216 : nThousand = 1; // H
2365 : }
2366 0 : else if ( cChar == cOldKeyMI )
2367 : {
2368 0 : nThousand = 2; // M
2369 : }
2370 0 : else if ( cChar == cOldKeyS )
2371 : {
2372 0 : nThousand = 3; // S
2373 : }
2374 : else
2375 : {
2376 0 : return nPos;
2377 : }
2378 16216 : nPos = nPos + sStrArray[i].getLength();
2379 16216 : i++;
2380 16216 : break;
2381 : case ']':
2382 16216 : if (!bThousand) // No preceding [
2383 : {
2384 0 : return nPos;
2385 : }
2386 16216 : nPos = nPos + sStrArray[i].getLength();
2387 16216 : i++;
2388 16216 : break;
2389 : default:
2390 123724 : nPos = nPos + sStrArray[i].getLength();
2391 123724 : if ( sStrArray[i] == sOldTimeSep )
2392 : {
2393 91424 : nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
2394 91424 : if ( bConvertMode )
2395 : {
2396 5124 : sStrArray[i] = pLoc->getTimeSep();
2397 : }
2398 : }
2399 32300 : else if ( sStrArray[i] == sOldTime100SecSep )
2400 : {
2401 16210 : bDecSep = true;
2402 16210 : nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
2403 16210 : if ( bConvertMode )
2404 : {
2405 542 : sStrArray[i] = pLoc->getTime100SecSep();
2406 : }
2407 : }
2408 : else
2409 : {
2410 16090 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2411 : }
2412 123724 : i++;
2413 123724 : break;
2414 : }
2415 172372 : break;
2416 : case NF_SYMBOLTYPE_STRING:
2417 90 : nPos = nPos + sStrArray[i].getLength();
2418 90 : i++;
2419 90 : break;
2420 : case NF_KEY_AMPM: // AM/PM
2421 : case NF_KEY_AP: // A/P
2422 16076 : bExp = true; // Abuse for A/P
2423 16076 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2424 16076 : nPos = nPos + sStrArray[i].getLength();
2425 16076 : i++;
2426 16076 : break;
2427 : case NF_KEY_THAI_T :
2428 0 : bThaiT = true;
2429 : // fall thru
2430 : case NF_KEY_MI: // M
2431 : case NF_KEY_MMI: // MM
2432 : case NF_KEY_H: // H
2433 : case NF_KEY_HH: // HH
2434 : case NF_KEY_S: // S
2435 : case NF_KEY_SS: // SS
2436 149806 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2437 149806 : nPos = nPos + sStrArray[i].getLength();
2438 149806 : i++;
2439 149806 : break;
2440 : default: // Other keywords
2441 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2442 0 : nPos = nPos + sStrArray[i].getLength();
2443 0 : i++;
2444 0 : break;
2445 : }
2446 : } // of while
2447 58332 : nCntPost = nCounter; // Zero counter
2448 58332 : if (bExp)
2449 : {
2450 16076 : nCntExp = 1; // Remembers AM/PM
2451 : }
2452 58332 : break; // of NUMBERFORMAT_TIME
2453 : case NUMBERFORMAT_DATETIME:
2454 208280 : while (i < nAnzStrings)
2455 : {
2456 : int nCalRet;
2457 176048 : switch (nTypeArray[i])
2458 : {
2459 : case NF_SYMBOLTYPE_BLANK:
2460 : case NF_SYMBOLTYPE_STAR:
2461 : case NF_SYMBOLTYPE_STRING:
2462 226 : nPos = nPos + sStrArray[i].getLength();
2463 226 : i++;
2464 226 : break;
2465 : case NF_SYMBOLTYPE_DEL:
2466 79786 : if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
2467 : {
2468 24 : if ( nCalRet < 0 )
2469 : {
2470 0 : return nPos; // Error
2471 : }
2472 : }
2473 : else
2474 : {
2475 79762 : switch( sStrArray[i][0] )
2476 : {
2477 : case '0':
2478 0 : if ( bTimePart && Is100SecZero( i, bDecSep ) )
2479 : {
2480 0 : bDecSep = true;
2481 0 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
2482 0 : OUString& rStr = sStrArray[i];
2483 0 : i++;
2484 0 : nPos = nPos + sStrArray[i].getLength();
2485 0 : nCounter++;
2486 0 : while (i < nAnzStrings &&
2487 0 : sStrArray[i][0] == '0')
2488 : {
2489 0 : rStr += sStrArray[i];
2490 0 : nPos = nPos + sStrArray[i].getLength();
2491 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2492 0 : nAnzResStrings--;
2493 0 : nCounter++;
2494 0 : i++;
2495 : }
2496 : }
2497 : else
2498 : {
2499 0 : return nPos;
2500 : }
2501 0 : break;
2502 : case '#':
2503 : case '?':
2504 0 : return nPos;
2505 : default:
2506 79762 : nPos = nPos + sStrArray[i].getLength();
2507 79762 : if (bTimePart)
2508 : {
2509 31598 : if ( sStrArray[i] == sOldTimeSep )
2510 : {
2511 23894 : nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
2512 23894 : if ( bConvertMode )
2513 : {
2514 354 : sStrArray[i] = pLoc->getTimeSep();
2515 : }
2516 : }
2517 7704 : else if ( sStrArray[i] == sOldTime100SecSep )
2518 : {
2519 0 : bDecSep = true;
2520 0 : nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
2521 0 : if ( bConvertMode )
2522 : {
2523 0 : sStrArray[i] = pLoc->getTime100SecSep();
2524 : }
2525 : }
2526 : else
2527 : {
2528 7704 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2529 : }
2530 : }
2531 : else
2532 : {
2533 48164 : if ( sStrArray[i] == sOldDateSep )
2534 : {
2535 32092 : nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
2536 32092 : if (bConvertMode)
2537 704 : sStrArray[i] = pFormatter->GetDateSep();
2538 : }
2539 : else
2540 : {
2541 16072 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2542 : }
2543 : }
2544 79762 : i++;
2545 79762 : break;
2546 : }
2547 : }
2548 79786 : break;
2549 : case NF_KEY_AMPM: // AM/PM
2550 : case NF_KEY_AP: // A/P
2551 7704 : bTimePart = true;
2552 7704 : bExp = true; // Abuse for A/P
2553 7704 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2554 7704 : nPos = nPos + sStrArray[i].getLength();
2555 7704 : i++;
2556 7704 : break;
2557 : case NF_KEY_MI: // M
2558 : case NF_KEY_MMI: // MM
2559 : case NF_KEY_H: // H
2560 : case NF_KEY_HH: // HH
2561 : case NF_KEY_S: // S
2562 : case NF_KEY_SS: // SS
2563 40076 : bTimePart = true;
2564 40076 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2565 40076 : nPos = nPos + sStrArray[i].getLength();
2566 40076 : i++;
2567 40076 : break;
2568 : case NF_KEY_M: // M
2569 : case NF_KEY_MM: // MM
2570 : case NF_KEY_MMM: // MMM
2571 : case NF_KEY_MMMM: // MMMM
2572 : case NF_KEY_MMMMM: // MMMMM
2573 : case NF_KEY_Q: // Q
2574 : case NF_KEY_QQ: // QQ
2575 : case NF_KEY_D: // D
2576 : case NF_KEY_DD: // DD
2577 : case NF_KEY_DDD: // DDD
2578 : case NF_KEY_DDDD: // DDDD
2579 : case NF_KEY_YY: // YY
2580 : case NF_KEY_YYYY: // YYYY
2581 : case NF_KEY_NN: // NN
2582 : case NF_KEY_NNN: // NNN
2583 : case NF_KEY_NNNN: // NNNN
2584 : case NF_KEY_WW : // WW
2585 : case NF_KEY_AAA : // AAA
2586 : case NF_KEY_AAAA : // AAAA
2587 : case NF_KEY_EC : // E
2588 : case NF_KEY_EEC : // EE
2589 : case NF_KEY_G : // G
2590 : case NF_KEY_GG : // GG
2591 : case NF_KEY_GGG : // GGG
2592 : case NF_KEY_R : // R
2593 : case NF_KEY_RR : // RR
2594 48256 : bTimePart = false;
2595 48256 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2596 48256 : nPos = nPos + sStrArray[i].getLength();
2597 48256 : i++;
2598 48256 : break;
2599 : case NF_KEY_THAI_T :
2600 0 : bThaiT = true;
2601 0 : sStrArray[i] = sKeyword[nTypeArray[i]];
2602 0 : nPos = nPos + sStrArray[i].getLength();
2603 0 : i++;
2604 0 : break;
2605 : default: // Other keywords
2606 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2607 0 : nPos = nPos + sStrArray[i].getLength();
2608 0 : i++;
2609 0 : break;
2610 : }
2611 : } // of while
2612 16116 : nCntPost = nCounter; // decimals (100th seconds)
2613 16116 : if (bExp)
2614 : {
2615 7704 : nCntExp = 1; // Remembers AM/PM
2616 : }
2617 16116 : break; // of NUMBERFORMAT_DATETIME
2618 : default:
2619 0 : break;
2620 : }
2621 704613 : if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
2622 31900 : (nCntPre + nCntPost == 0 || nCntExp == 0))
2623 : {
2624 0 : return nPos;
2625 : }
2626 688663 : else if (eScannedType == NUMBERFORMAT_FRACTION && (nCntExp > 8 || nCntExp == 0))
2627 : {
2628 0 : return nPos;
2629 : }
2630 688663 : if (bThaiT && !GetNatNumModifier())
2631 : {
2632 0 : SetNatNumModifier(1);
2633 : }
2634 688663 : if ( bConvertMode )
2635 : {
2636 : // strings containing keywords of the target locale must be quoted, so
2637 : // the user sees the difference and is able to edit the format string
2638 145620 : for ( i=0; i < nAnzStrings; i++ )
2639 : {
2640 140130 : if ( nTypeArray[i] == NF_SYMBOLTYPE_STRING &&
2641 14952 : sStrArray[i][0] != '\"' )
2642 : {
2643 10970 : if ( bConvertSystemToSystem && eScannedType == NUMBERFORMAT_CURRENCY )
2644 : {
2645 : // don't stringize automatic currency, will be converted
2646 0 : if ( sStrArray[i] == sOldCurSymbol )
2647 : {
2648 0 : continue; // for
2649 : }
2650 : // DM might be splitted into D and M
2651 0 : if ( sStrArray[i].getLength() < sOldCurSymbol.getLength() &&
2652 0 : pChrCls->uppercase( sStrArray[i], 0, 1 )[0] ==
2653 0 : sOldCurString[0] )
2654 : {
2655 0 : OUString aTmp( sStrArray[i] );
2656 0 : sal_uInt16 j = i + 1;
2657 0 : while ( aTmp.getLength() < sOldCurSymbol.getLength() &&
2658 0 : j < nAnzStrings &&
2659 0 : nTypeArray[j] == NF_SYMBOLTYPE_STRING )
2660 : {
2661 0 : aTmp += sStrArray[j++];
2662 : }
2663 0 : if ( pChrCls->uppercase( aTmp ) == sOldCurString )
2664 : {
2665 0 : sStrArray[i++] = aTmp;
2666 0 : for ( ; i<j; i++ )
2667 : {
2668 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2669 0 : nAnzResStrings--;
2670 : }
2671 0 : i = j - 1;
2672 0 : continue; // for
2673 0 : }
2674 : }
2675 : }
2676 10970 : OUString& rStr = sStrArray[i];
2677 10970 : sal_Int32 nLen = rStr.getLength();
2678 24992 : for ( sal_Int32 j = 0; j < nLen; j++ )
2679 : {
2680 14022 : if ( (j == 0 || rStr[j - 1] != '\\') && GetKeyWord( rStr, j ) )
2681 : {
2682 0 : rStr = "\"" + rStr + "\"";
2683 0 : break; // for
2684 : }
2685 : }
2686 : }
2687 : }
2688 : }
2689 : // Concatenate strings, remove quotes for output, and rebuild the format string
2690 688663 : rString = "";
2691 688663 : i = 0;
2692 7031703 : while (i < nAnzStrings)
2693 : {
2694 : sal_Int32 nStringPos;
2695 5654377 : sal_Int32 nArrPos = 0;
2696 5654377 : sal_uInt16 iPos = i;
2697 5654377 : switch ( nTypeArray[i] )
2698 : {
2699 : case NF_SYMBOLTYPE_STRING :
2700 603001 : nStringPos = rString.getLength();
2701 738027 : do
2702 : {
2703 749573 : if (sStrArray[i].getLength() == 2 &&
2704 11546 : sStrArray[i][0] == '\\')
2705 : {
2706 : // Unescape some simple forms of symbols even in the UI
2707 : // visible string to prevent duplicates that differ
2708 : // only in notation, originating from import.
2709 : // e.g. YYYY-MM-DD and YYYY\-MM\-DD are identical,
2710 : // but 0\ 000 0 and 0 000 0 in a French locale are not.
2711 :
2712 3194 : sal_Unicode c = sStrArray[i][1];
2713 :
2714 3194 : switch (c)
2715 : {
2716 : case '+':
2717 : case '-':
2718 974 : rString += OUString(c);
2719 974 : break;
2720 : case ' ':
2721 : case '.':
2722 : case '/':
2723 1648 : if (((eScannedType & NUMBERFORMAT_DATE) == 0) &&
2724 1608 : (StringEqualsChar( pFormatter->GetNumThousandSep(), c) ||
2725 1608 : StringEqualsChar( pFormatter->GetNumDecimalSep(), c) ||
2726 804 : (c == ' ' &&
2727 1608 : (StringEqualsChar( pFormatter->GetNumThousandSep(), cNoBreakSpace) ||
2728 804 : StringEqualsChar( pFormatter->GetNumThousandSep(), cNarrowNoBreakSpace)))))
2729 : {
2730 0 : rString += sStrArray[i];
2731 : }
2732 884 : else if ((eScannedType & NUMBERFORMAT_DATE) &&
2733 40 : StringEqualsChar( pFormatter->GetDateSep(), c))
2734 : {
2735 4 : rString += sStrArray[i];
2736 : }
2737 852 : else if ((eScannedType & NUMBERFORMAT_TIME) &&
2738 24 : (StringEqualsChar( pLoc->getTimeSep(), c) ||
2739 12 : StringEqualsChar( pLoc->getTime100SecSep(), c)))
2740 : {
2741 0 : rString += sStrArray[i];
2742 : }
2743 840 : else if (eScannedType & NUMBERFORMAT_FRACTION)
2744 : {
2745 6 : rString += sStrArray[i];
2746 : }
2747 : else
2748 : {
2749 834 : rString += OUString(c);
2750 : }
2751 844 : break;
2752 : default:
2753 1376 : rString += sStrArray[i];
2754 : }
2755 : }
2756 : else
2757 : {
2758 734833 : rString += sStrArray[i];
2759 : }
2760 738027 : if ( RemoveQuotes( sStrArray[i] ) > 0 )
2761 : {
2762 : // update currency up to quoted string
2763 8698 : if ( eScannedType == NUMBERFORMAT_CURRENCY )
2764 : {
2765 : // dM -> DM or DM -> $ in old automatic
2766 : // currency formats, oh my ..., why did we ever introduce them?
2767 130 : OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
2768 260 : sStrArray[iPos].getLength()-nArrPos ) );
2769 130 : sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
2770 130 : if ( nCPos >= 0 )
2771 : {
2772 0 : const OUString& rCur = bConvertMode && bConvertSystemToSystem ?
2773 0 : GetCurSymbol() : sOldCurSymbol;
2774 0 : sStrArray[iPos] = sStrArray[iPos].replaceAt( nArrPos + nCPos,
2775 : sOldCurString.getLength(),
2776 0 : rCur );
2777 0 : rString = rString.replaceAt( nStringPos + nCPos,
2778 : sOldCurString.getLength(),
2779 0 : rCur );
2780 : }
2781 130 : nStringPos = rString.getLength();
2782 130 : if ( iPos == i )
2783 : {
2784 124 : nArrPos = sStrArray[iPos].getLength();
2785 : }
2786 : else
2787 : {
2788 6 : nArrPos = sStrArray[iPos].getLength() + sStrArray[i].getLength();
2789 130 : }
2790 : }
2791 : }
2792 738027 : if ( iPos != i )
2793 : {
2794 135026 : sStrArray[iPos] += sStrArray[i];
2795 135026 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2796 135026 : nAnzResStrings--;
2797 : }
2798 738027 : i++;
2799 : }
2800 1447778 : while ( i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_STRING );
2801 :
2802 603001 : if ( i < nAnzStrings )
2803 : {
2804 574725 : i--; // enter switch on next symbol again
2805 : }
2806 603001 : if ( eScannedType == NUMBERFORMAT_CURRENCY && nStringPos < rString.getLength() )
2807 : {
2808 : // same as above, since last RemoveQuotes
2809 146349 : OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
2810 292698 : sStrArray[iPos].getLength()-nArrPos ) );
2811 146349 : sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
2812 146349 : if ( nCPos >= 0 )
2813 : {
2814 1798 : const OUString& rCur = bConvertMode && bConvertSystemToSystem ?
2815 80250 : GetCurSymbol() : sOldCurSymbol;
2816 160500 : sStrArray[iPos] = sStrArray[iPos].replaceAt( nArrPos + nCPos,
2817 : sOldCurString.getLength(),
2818 80250 : rCur );
2819 160500 : rString = rString.replaceAt( nStringPos + nCPos,
2820 80250 : sOldCurString.getLength(), rCur );
2821 146349 : }
2822 : }
2823 603001 : break;
2824 : case NF_SYMBOLTYPE_CURRENCY :
2825 111307 : rString += sStrArray[i];
2826 111307 : RemoveQuotes( sStrArray[i] );
2827 111307 : break;
2828 : case NF_KEY_THAI_T:
2829 0 : if (bThaiT && GetNatNumModifier() == 1)
2830 : {
2831 : // Remove T from format code, will be replaced with a [NatNum1] prefix.
2832 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2833 0 : nAnzResStrings--;
2834 : }
2835 : else
2836 : {
2837 0 : rString += sStrArray[i];
2838 : }
2839 0 : break;
2840 : case NF_SYMBOLTYPE_EMPTY :
2841 : // nothing
2842 1605228 : break;
2843 : default:
2844 3334841 : rString += sStrArray[i];
2845 : }
2846 5654377 : i++;
2847 : }
2848 1377330 : return 0;
2849 : }
2850 :
2851 849334 : sal_Int32 ImpSvNumberformatScan::RemoveQuotes( OUString& rStr )
2852 : {
2853 849334 : if ( rStr.getLength() > 1 )
2854 : {
2855 26013 : sal_Unicode c = rStr[0];
2856 26013 : sal_Int32 n = rStr.getLength() - 1;
2857 26013 : if ( c == '"' && rStr[n] == '"' )
2858 : {
2859 5504 : rStr = rStr.copy( 1, n-1);
2860 5504 : return 2;
2861 : }
2862 20509 : else if ( c == '\\' )
2863 : {
2864 3194 : rStr = rStr.copy(1);
2865 3194 : return 1;
2866 : }
2867 : }
2868 840636 : return 0;
2869 : }
2870 :
2871 688667 : sal_Int32 ImpSvNumberformatScan::ScanFormat( OUString& rString )
2872 : {
2873 688667 : sal_Int32 res = Symbol_Division(rString); // Lexical analysis
2874 688667 : if (!res)
2875 : {
2876 688667 : res = ScanType(); // Recognizing the Format type
2877 : }
2878 688667 : if (!res)
2879 : {
2880 688667 : res = FinalScan( rString ); // Type dependent final analysis
2881 : }
2882 688667 : return res; // res = control position; res = 0 => Format ok
2883 : }
2884 :
2885 688663 : void ImpSvNumberformatScan::CopyInfo(ImpSvNumberformatInfo* pInfo, sal_uInt16 nAnz)
2886 : {
2887 : size_t i,j;
2888 688663 : j = 0;
2889 688663 : i = 0;
2890 6809729 : while (i < nAnz && j < NF_MAX_FORMAT_SYMBOLS)
2891 : {
2892 5432403 : if (nTypeArray[j] != NF_SYMBOLTYPE_EMPTY)
2893 : {
2894 4049149 : pInfo->sStrArray[i] = sStrArray[j];
2895 4049149 : pInfo->nTypeArray[i] = nTypeArray[j];
2896 4049149 : i++;
2897 : }
2898 5432403 : j++;
2899 : }
2900 688663 : pInfo->eScannedType = eScannedType;
2901 688663 : pInfo->bThousand = bThousand;
2902 688663 : pInfo->nThousand = nThousand;
2903 688663 : pInfo->nCntPre = nCntPre;
2904 688663 : pInfo->nCntPost = nCntPost;
2905 688663 : pInfo->nCntExp = nCntExp;
2906 688663 : }
2907 :
2908 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|