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