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