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 4 : 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 8 : };
61 4 : return &aEnglishColors[0];
62 : }
63 : };
64 :
65 : struct theEnglishColors
66 : : public rtl::StaticAggregate< const OUString, ImplEnglishColors> {};
67 :
68 : }
69 :
70 824 : ImpSvNumberformatScan::ImpSvNumberformatScan( SvNumberFormatter* pFormatterP )
71 : {
72 824 : pFormatter = pFormatterP;
73 824 : bConvertMode = false;
74 : //! All keywords MUST be UPPERCASE!
75 824 : sKeyword[NF_KEY_E] = "E"; // Exponent
76 824 : sKeyword[NF_KEY_AMPM] = "AM/PM"; // AM/PM
77 824 : sKeyword[NF_KEY_AP] = "A/P"; // AM/PM short
78 824 : sKeyword[NF_KEY_MI] = "M"; // Minute
79 824 : sKeyword[NF_KEY_MMI] = "MM"; // Minute 02
80 824 : sKeyword[NF_KEY_S] = "S"; // Second
81 824 : sKeyword[NF_KEY_SS] = "SS"; // Second 02
82 824 : sKeyword[NF_KEY_Q] = "Q"; // Quarter short 'Q'
83 824 : sKeyword[NF_KEY_QQ] = "QQ"; // Quarter long
84 824 : sKeyword[NF_KEY_NN] = "NN"; // Day of week short
85 824 : sKeyword[NF_KEY_NNN] = "NNN"; // Day of week long
86 824 : sKeyword[NF_KEY_NNNN] = "NNNN"; // Day of week long incl. separator
87 824 : sKeyword[NF_KEY_WW] = "WW"; // Week of year
88 824 : sKeyword[NF_KEY_CCC] = "CCC"; // Currency abbreviation
89 824 : bKeywordsNeedInit = true; // locale dependent keywords
90 824 : bCompatCurNeedInit = true; // locale dependent compatibility currency strings
91 :
92 824 : StandardColor[0] = Color(COL_BLACK);
93 824 : StandardColor[1] = Color(COL_LIGHTBLUE);
94 824 : StandardColor[2] = Color(COL_LIGHTGREEN);
95 824 : StandardColor[3] = Color(COL_LIGHTCYAN);
96 824 : StandardColor[4] = Color(COL_LIGHTRED);
97 824 : StandardColor[5] = Color(COL_LIGHTMAGENTA);
98 824 : StandardColor[6] = Color(COL_BROWN);
99 824 : StandardColor[7] = Color(COL_GRAY);
100 824 : StandardColor[8] = Color(COL_YELLOW);
101 824 : StandardColor[9] = Color(COL_WHITE);
102 :
103 824 : pNullDate = new Date(30,12,1899);
104 824 : nStandardPrec = 2;
105 :
106 824 : sErrStr = "###";
107 824 : Reset();
108 824 : }
109 :
110 33372 : ImpSvNumberformatScan::~ImpSvNumberformatScan()
111 : {
112 324 : delete pNullDate;
113 324 : Reset();
114 33048 : }
115 :
116 7878 : void ImpSvNumberformatScan::ChangeIntl()
117 : {
118 7878 : bKeywordsNeedInit = true;
119 7878 : bCompatCurNeedInit = true;
120 : // may be initialized by InitSpecialKeyword()
121 7878 : sKeyword[NF_KEY_TRUE] = "";
122 7878 : sKeyword[NF_KEY_FALSE] = "";
123 7878 : }
124 :
125 16908 : void ImpSvNumberformatScan::InitSpecialKeyword( NfKeywordIndex eIdx ) const
126 : {
127 16908 : switch ( eIdx )
128 : {
129 : case NF_KEY_TRUE :
130 8454 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] =
131 16908 : pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getTrueWord() );
132 8454 : 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 8454 : break;
138 : case NF_KEY_FALSE :
139 8454 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] =
140 16908 : pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getFalseWord() );
141 8454 : 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 8454 : break;
147 : default:
148 : SAL_WARN( "svl.numbers", "InitSpecialKeyword: unknown request" );
149 : }
150 16908 : }
151 :
152 8436 : void ImpSvNumberformatScan::InitCompatCur() const
153 : {
154 8436 : ImpSvNumberformatScan* pThis = (ImpSvNumberformatScan*)this;
155 : // currency symbol for old style ("automatic") compatibility format codes
156 8436 : pFormatter->GetCompatibilityCurrency( pThis->sCurSymbol, pThis->sCurAbbrev );
157 : // currency symbol upper case
158 8436 : pThis->sCurString = pFormatter->GetCharClass()->uppercase( sCurSymbol );
159 8436 : bCompatCurNeedInit = false;
160 8436 : }
161 :
162 10628 : void ImpSvNumberformatScan::InitKeywords() const
163 : {
164 10628 : if ( !bKeywordsNeedInit )
165 12820 : return ;
166 8436 : ((ImpSvNumberformatScan*)this)->SetDependentKeywords();
167 8436 : bKeywordsNeedInit = false;
168 : }
169 :
170 : /** Extract the name of General, Standard, Whatever, ignoring leading modifiers
171 : such as [NatNum1]. */
172 8436 : static OUString lcl_extractStandardGeneralName( const ::rtl::OUString & rCode )
173 : {
174 8436 : OUString aStr;
175 8436 : const sal_Unicode* p = rCode.getStr();
176 8436 : const sal_Unicode* const pStop = p + rCode.getLength();
177 8436 : const sal_Unicode* pBeg = p; // name begins here
178 8436 : bool bMod = false;
179 8436 : bool bDone = false;
180 75930 : while (p < pStop && !bDone)
181 : {
182 59058 : 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 59058 : ++p;
205 59058 : if (bMod)
206 : {
207 0 : pBeg = p;
208 : }
209 : }
210 8436 : if (pBeg < p)
211 : {
212 8436 : aStr = rCode.copy( pBeg - rCode.getStr(), p - pBeg);
213 : }
214 8436 : return aStr;
215 : }
216 :
217 8436 : void ImpSvNumberformatScan::SetDependentKeywords()
218 : {
219 : using namespace ::com::sun::star;
220 : using namespace ::com::sun::star::uno;
221 :
222 8436 : const CharClass* pCharClass = pFormatter->GetCharClass();
223 8436 : 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 8436 : const LanguageTag& rLoadedLocale = pLocaleData->getLoadedLanguageTag();
227 8436 : LanguageType eLang = rLoadedLocale.getLanguageType( false);
228 : NumberFormatCodeWrapper aNumberFormatCode( comphelper::getComponentContext(pFormatter->GetServiceManager()),
229 8436 : rLoadedLocale.getLocale() );
230 :
231 8436 : i18n::NumberFormatCode aFormat = aNumberFormatCode.getFormatCode( NF_NUMBER_STANDARD );
232 8436 : sNameStandardFormat = lcl_extractStandardGeneralName( aFormat.Code);
233 8436 : sKeyword[NF_KEY_GENERAL] = pCharClass->uppercase( sNameStandardFormat );
234 :
235 : // preset new calendar keywords
236 8436 : sKeyword[NF_KEY_AAA] = "AAA";
237 8436 : sKeyword[NF_KEY_AAAA] = "AAAA";
238 8436 : sKeyword[NF_KEY_EC] = "E";
239 8436 : sKeyword[NF_KEY_EEC] = "EE";
240 8436 : sKeyword[NF_KEY_G] = "G";
241 8436 : sKeyword[NF_KEY_GG] = "GG";
242 8436 : sKeyword[NF_KEY_GGG] = "GGG";
243 8436 : sKeyword[NF_KEY_R] = "R";
244 8436 : 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 8436 : if (eLang == LANGUAGE_THAI)
249 : {
250 0 : sKeyword[NF_KEY_THAI_T] = "T";
251 : }
252 : else
253 : {
254 8436 : sKeyword[NF_KEY_THAI_T] = "t";
255 : }
256 8436 : 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 2 : sKeyword[NF_KEY_M] = "M"; // month 1
265 2 : sKeyword[NF_KEY_MM] = "MM"; // month 01
266 2 : sKeyword[NF_KEY_MMM] = "MMM"; // month Jan
267 2 : sKeyword[NF_KEY_MMMM] = "MMMM"; // month Januar
268 2 : sKeyword[NF_KEY_MMMMM] = "MMMMM";// month J
269 2 : sKeyword[NF_KEY_H] = "H"; // hour 2
270 2 : sKeyword[NF_KEY_HH] = "HH"; // hour 02
271 2 : sKeyword[NF_KEY_D] = "T";
272 2 : sKeyword[NF_KEY_DD] = "TT";
273 2 : sKeyword[NF_KEY_DDD] = "TTT";
274 2 : sKeyword[NF_KEY_DDDD] = "TTTT";
275 2 : sKeyword[NF_KEY_YY] = "JJ";
276 2 : sKeyword[NF_KEY_YYYY] = "JJJJ";
277 2 : sKeyword[NF_KEY_BOOLEAN] = "LOGISCH";
278 2 : sKeyword[NF_KEY_COLOR] = "FARBE";
279 2 : sKeyword[NF_KEY_BLACK] = "SCHWARZ";
280 2 : sKeyword[NF_KEY_BLUE] = "BLAU";
281 2 : sKeyword[NF_KEY_GREEN] = OUString( "GR" "\xDC" "N", 4, RTL_TEXTENCODING_ISO_8859_1 );
282 2 : sKeyword[NF_KEY_CYAN] = "CYAN";
283 2 : sKeyword[NF_KEY_RED] = "ROT";
284 2 : sKeyword[NF_KEY_MAGENTA] = "MAGENTA";
285 2 : sKeyword[NF_KEY_BROWN] = "BRAUN";
286 2 : sKeyword[NF_KEY_GREY] = "GRAU";
287 2 : sKeyword[NF_KEY_YELLOW] = "GELB";
288 2 : sKeyword[NF_KEY_WHITE] = "WEISS";
289 2 : break;
290 : default:
291 : // day
292 8434 : 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 4 : sKeyword[NF_KEY_D] = "J";
312 4 : sKeyword[NF_KEY_DD] = "JJ";
313 4 : sKeyword[NF_KEY_DDD] = "JJJ";
314 4 : sKeyword[NF_KEY_DDDD] = "JJJJ";
315 4 : 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 8430 : sKeyword[NF_KEY_D] = "D";
324 8430 : sKeyword[NF_KEY_DD] = "DD";
325 8430 : sKeyword[NF_KEY_DDD] = "DDD";
326 8430 : sKeyword[NF_KEY_DDDD] = "DDDD";
327 : }
328 : // month
329 8434 : 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 8434 : sKeyword[NF_KEY_M] = "M";
340 8434 : sKeyword[NF_KEY_MM] = "MM";
341 8434 : sKeyword[NF_KEY_MMM] = "MMM";
342 8434 : sKeyword[NF_KEY_MMMM] = "MMMM";
343 8434 : sKeyword[NF_KEY_MMMMM] = "MMMMM";
344 : }
345 : // year
346 8434 : 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 4 : sKeyword[NF_KEY_YY] = "AA";
379 4 : sKeyword[NF_KEY_YYYY] = "AAAA";
380 : // must exchange the day of week name code, same as Xcl
381 4 : sKeyword[NF_KEY_AAA] = "OOO";
382 4 : sKeyword[NF_KEY_AAAA] = "OOOO";
383 4 : 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 8430 : sKeyword[NF_KEY_YY] = "YY";
395 8430 : sKeyword[NF_KEY_YYYY] = "YYYY";
396 : }
397 : // hour
398 8434 : 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 8434 : sKeyword[NF_KEY_H] = "H";
417 8434 : sKeyword[NF_KEY_HH] = "HH";
418 : }
419 : // boolean
420 8434 : sKeyword[NF_KEY_BOOLEAN] = "BOOLEAN";
421 : // colours
422 8434 : sKeyword[NF_KEY_COLOR] = "COLOR";
423 8434 : sKeyword[NF_KEY_BLACK] = "BLACK";
424 8434 : sKeyword[NF_KEY_BLUE] = "BLUE";
425 8434 : sKeyword[NF_KEY_GREEN] = "GREEN";
426 8434 : sKeyword[NF_KEY_CYAN] = "CYAN";
427 8434 : sKeyword[NF_KEY_RED] = "RED";
428 8434 : sKeyword[NF_KEY_MAGENTA] = "MAGENTA";
429 8434 : sKeyword[NF_KEY_BROWN] = "BROWN";
430 8434 : sKeyword[NF_KEY_GREY] = "GREY";
431 8434 : sKeyword[NF_KEY_YELLOW] = "YELLOW";
432 8434 : sKeyword[NF_KEY_WHITE] = "WHITE";
433 8434 : break;
434 : }
435 :
436 : // boolean keyords
437 8436 : InitSpecialKeyword( NF_KEY_TRUE );
438 8436 : InitSpecialKeyword( NF_KEY_FALSE );
439 :
440 : // compatibility currency strings
441 8436 : InitCompatCur();
442 8436 : }
443 :
444 1120 : void ImpSvNumberformatScan::ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear)
445 : {
446 1120 : if ( pNullDate )
447 1120 : *pNullDate = Date(nDay, nMonth, nYear);
448 : else
449 0 : pNullDate = new Date(nDay, nMonth, nYear);
450 1120 : }
451 :
452 1330 : void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec)
453 : {
454 1330 : nStandardPrec = nPrec;
455 1330 : }
456 :
457 7108 : Color* ImpSvNumberformatScan::GetColor(OUString& sStr)
458 : {
459 7108 : OUString sString = pFormatter->GetCharClass()->uppercase(sStr);
460 7108 : const NfKeywordTable & rKeyword = GetKeywords();
461 7108 : size_t i = 0;
462 46584 : while (i < NF_MAX_DEFAULT_COLORS && sString != rKeyword[NF_KEY_FIRSTCOLOR+i] )
463 : {
464 32368 : i++;
465 : }
466 7108 : if ( i >= NF_MAX_DEFAULT_COLORS )
467 : {
468 656 : const OUString* pEnglishColors = theEnglishColors::get();
469 656 : size_t j = 0;
470 7872 : while ( j < NF_MAX_DEFAULT_COLORS && sString != pEnglishColors[j] )
471 : {
472 6560 : ++j;
473 : }
474 656 : if ( j < NF_MAX_DEFAULT_COLORS )
475 : {
476 0 : i = j;
477 : }
478 : }
479 :
480 7108 : Color* pResult = NULL;
481 7108 : if (i >= NF_MAX_DEFAULT_COLORS)
482 : {
483 656 : const OUString& rColorWord = rKeyword[NF_KEY_COLOR];
484 656 : sal_Int32 nPos = sString.startsWith(rColorWord);
485 656 : 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 6452 : sStr = "";
515 6452 : if (bConvertMode)
516 : {
517 330 : pFormatter->ChangeIntl(eNewLnge);
518 330 : sStr = GetKeywords()[NF_KEY_FIRSTCOLOR+i]; // red -> rot
519 330 : pFormatter->ChangeIntl(eTmpLnge);
520 : }
521 : else
522 : {
523 6122 : sStr = rKeyword[NF_KEY_FIRSTCOLOR+i];
524 : }
525 6452 : pResult = &(StandardColor[i]);
526 : }
527 7108 : return pResult;
528 : }
529 :
530 197230 : short ImpSvNumberformatScan::GetKeyWord( const OUString& sSymbol, sal_Int32 nPos )
531 : {
532 197230 : OUString sString = pFormatter->GetCharClass()->uppercase( sSymbol, nPos, sSymbol.getLength() - nPos );
533 197230 : const NfKeywordTable & rKeyword = GetKeywords();
534 : // #77026# for the Xcl perverts: the GENERAL keyword is recognized anywhere
535 197230 : if ( sString.startsWith( rKeyword[NF_KEY_GENERAL] ))
536 : {
537 1032 : return NF_KEY_GENERAL;
538 : }
539 : //! MUST be a reverse search to find longer strings first
540 196198 : short i = NF_KEYWORD_ENTRIES_COUNT-1;
541 196198 : bool bFound = false;
542 2096264 : for ( ; i > NF_KEY_LASTKEYWORD_SO5; --i )
543 : {
544 1921048 : bFound = sString.startsWith(rKeyword[i]);
545 1921048 : if ( bFound )
546 : {
547 20982 : break;
548 : }
549 : }
550 : // new keywords take precedence over old keywords
551 196198 : if ( !bFound )
552 : {
553 : // skip the gap of colors et al between new and old keywords and search on
554 175216 : i = NF_KEY_LASTKEYWORD;
555 3321366 : while ( i > 0 && sString.indexOf(rKeyword[i]) != 0 )
556 : {
557 2970934 : i--;
558 : }
559 175216 : 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 1994 : short j = i - 1;
564 7976 : while ( j > 0 && sString.indexOf(rKeyword[j]) != 0 )
565 : {
566 3988 : j--;
567 : }
568 1994 : if ( j && rKeyword[j].getLength() > rKeyword[i].getLength() )
569 : {
570 1994 : return j;
571 : }
572 : }
573 : }
574 : // The Thai T NatNum modifier during Xcl import.
575 196682 : if (i == 0 && bConvertMode &&
576 2478 : 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 194204 : 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 723576 : short ImpSvNumberformatScan::Next_Symbol( const OUString& rStr,
637 : sal_Int32& nPos,
638 : OUString& sSymbol )
639 : {
640 723576 : if ( bKeywordsNeedInit )
641 : {
642 0 : InitKeywords();
643 : }
644 723576 : const CharClass* pChrCls = pFormatter->GetCharClass();
645 723576 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
646 723576 : const sal_Int32 nStart = nPos;
647 723576 : short eType = 0;
648 723576 : ScanState eState = SsStart;
649 723576 : sSymbol = "";
650 2211440 : while ( nPos < rStr.getLength() && eState != SsStop )
651 : {
652 764328 : sal_Unicode cToken = rStr[nPos++];
653 764328 : 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 725564 : if ( nCurrPos >= 0 && sCurString.getLength() > 1 &&
663 1024 : nPos-1 + sCurString.getLength() <= rStr.getLength() &&
664 944 : !(nPos > 1 && rStr[nPos-2] == '[') )
665 : {
666 472 : OUString aTest = pChrCls->uppercase( rStr.copy( nPos-1, sCurString.getLength() ) );
667 472 : if ( aTest == sCurString )
668 : {
669 40 : sSymbol = rStr.copy( --nPos, sCurString.getLength() );
670 40 : nPos = nPos + sSymbol.getLength();
671 40 : eState = SsStop;
672 40 : eType = NF_SYMBOLTYPE_STRING;
673 40 : return eType;
674 472 : }
675 : }
676 723536 : 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 465416 : eType = NF_SYMBOLTYPE_DEL;
693 465416 : sSymbol += OUString(cToken);
694 465416 : eState = SsStop;
695 465416 : break;
696 : case '*':
697 4624 : eType = NF_SYMBOLTYPE_STAR;
698 4624 : sSymbol += OUString(cToken);
699 4624 : eState = SsGetStar;
700 4624 : break;
701 : case '_':
702 4024 : eType = NF_SYMBOLTYPE_BLANK;
703 4024 : sSymbol += OUString(cToken);
704 4024 : eState = SsGetBlank;
705 4024 : break;
706 : case '"':
707 1078 : eType = NF_SYMBOLTYPE_STRING;
708 1078 : eState = SsGetString;
709 1078 : sSymbol += OUString(cToken);
710 1078 : break;
711 : case '\\':
712 720 : eType = NF_SYMBOLTYPE_STRING;
713 720 : eState = SsGetChar;
714 720 : sSymbol += OUString(cToken);
715 720 : break;
716 : case '$':
717 : case '+':
718 : case '(':
719 : case ')':
720 43268 : eType = NF_SYMBOLTYPE_STRING;
721 43268 : eState = SsStop;
722 43268 : sSymbol += OUString(cToken);
723 43268 : break;
724 : default :
725 1021982 : if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cToken) ||
726 204406 : StringEqualsChar( pFormatter->GetNumThousandSep(), cToken) ||
727 204406 : StringEqualsChar( pFormatter->GetDateSep(), cToken) ||
728 204382 : StringEqualsChar( pLoc->getTimeSep(), cToken) ||
729 204382 : StringEqualsChar( pLoc->getTime100SecSep(), cToken))
730 : {
731 : // Another separator than pre-known ASCII
732 24 : eType = NF_SYMBOLTYPE_DEL;
733 24 : sSymbol += OUString(cToken);
734 24 : eState = SsStop;
735 : }
736 204382 : else if ( pChrCls->isLetter( rStr, nPos-1 ) )
737 : {
738 166060 : short nTmpType = GetKeyWord( rStr, nPos-1 );
739 166060 : if ( nTmpType )
740 : {
741 148150 : bool bCurrency = false;
742 : // "Automatic" currency may start with keyword,
743 : // like "R" (Rand) and 'R' (era)
744 592598 : if ( nCurrPos != STRING_NOTFOUND &&
745 296300 : nPos-1 + sCurString.getLength() <= rStr.getLength() &&
746 148148 : 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 148150 : if ( bCurrency )
755 : {
756 0 : eState = SsGetWord;
757 0 : sSymbol += OUString(cToken);
758 : }
759 : else
760 : {
761 148150 : eType = nTmpType;
762 148150 : sal_Int32 nLen = sKeyword[eType].getLength();
763 148150 : sSymbol = rStr.copy( nPos-1, nLen );
764 148150 : if ( eType == NF_KEY_E || IsAmbiguousE( eType ) )
765 : {
766 10970 : sal_Unicode cNext = rStr[nPos];
767 10970 : switch ( cNext )
768 : {
769 : case '+' :
770 : case '-' : // E+ E- combine to one symbol
771 2074 : sSymbol += OUString(cNext);
772 2074 : eType = NF_KEY_E;
773 2074 : nPos++;
774 2074 : break;
775 : case '0' :
776 : case '#' : // scientific E without sign
777 0 : eType = NF_KEY_E;
778 0 : break;
779 : }
780 : }
781 148150 : nPos--;
782 148150 : nPos = nPos + nLen;
783 148150 : eState = SsStop;
784 : }
785 : }
786 : else
787 : {
788 17910 : eState = SsGetWord;
789 17910 : sSymbol += OUString(cToken);
790 : }
791 : }
792 : else
793 : {
794 38322 : eType = NF_SYMBOLTYPE_STRING;
795 38322 : eState = SsStop;
796 38322 : sSymbol += OUString(cToken);
797 : }
798 204406 : break;
799 : }
800 723536 : break;
801 : case SsGetChar:
802 720 : sSymbol += OUString(cToken);
803 720 : eState = SsStop;
804 720 : break;
805 : case SsGetString:
806 2612 : if (cToken == '"')
807 : {
808 1078 : eState = SsStop;
809 : }
810 2612 : sSymbol += OUString(cToken);
811 2612 : break;
812 : case SsGetWord:
813 28772 : if ( pChrCls->isLetter( rStr, nPos-1 ) )
814 : {
815 28708 : short nTmpType = GetKeyWord( rStr, nPos-1 );
816 28708 : if ( nTmpType )
817 : {
818 : // beginning of keyword, stop scan and put back
819 16834 : eType = NF_SYMBOLTYPE_STRING;
820 16834 : eState = SsStop;
821 16834 : nPos--;
822 : }
823 : else
824 : {
825 11874 : sSymbol += OUString(cToken);
826 : }
827 : }
828 : else
829 : {
830 64 : bool bDontStop = false;
831 : sal_Unicode cNext;
832 64 : 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 64 : if ( eState != SsStop && !bDontStop )
853 : {
854 64 : eState = SsStop;
855 64 : nPos--;
856 64 : eType = NF_SYMBOLTYPE_STRING;
857 : }
858 : }
859 28772 : break;
860 : case SsGetStar:
861 4624 : eState = SsStop;
862 4624 : sSymbol += OUString(cToken);
863 4624 : nRepPos = (nPos - nStart) - 1; // everytime > 0!!
864 4624 : break;
865 : case SsGetBlank:
866 4024 : eState = SsStop;
867 4024 : sSymbol += OUString(cToken);
868 4024 : break;
869 : default:
870 0 : break;
871 : } // of switch
872 : } // of while
873 723536 : if (eState == SsGetWord)
874 : {
875 1012 : eType = NF_SYMBOLTYPE_STRING;
876 : }
877 723536 : return eType;
878 : }
879 :
880 88738 : sal_Int32 ImpSvNumberformatScan::Symbol_Division(const OUString& rString)
881 : {
882 88738 : nCurrPos = -1;
883 : // Ist Waehrung im Spiel?
884 88738 : OUString sString = pFormatter->GetCharClass()->uppercase(rString);
885 88738 : sal_Int32 nCPos = 0;
886 266514 : while (nCPos >= 0)
887 : {
888 89038 : nCPos = sString.indexOf(GetCurString(),nCPos);
889 89038 : if (nCPos >= 0)
890 : {
891 : // in Quotes?
892 24846 : sal_Int32 nQ = SvNumberformat::GetQuoteEnd( sString, nCPos );
893 24846 : if ( nQ < 0 )
894 : {
895 : sal_Unicode c;
896 44002 : if ( nCPos == 0 ||
897 19424 : ((c = sString[nCPos-1]) != '"'
898 : && c != '\\') ) // dm kann durch "dm
899 : { // \d geschuetzt werden
900 24546 : nCurrPos = nCPos;
901 24546 : nCPos = -1;
902 : }
903 : else
904 : {
905 32 : nCPos++; // weitersuchen
906 : }
907 : }
908 : else
909 : {
910 268 : nCPos = nQ + 1; // weitersuchen
911 : }
912 : }
913 : }
914 88738 : nAnzStrings = 0;
915 88738 : bool bStar = false; // wird bei '*'Detektion gesetzt
916 88738 : Reset();
917 :
918 88738 : sal_Int32 nPos = 0;
919 88738 : const sal_Int32 nLen = rString.getLength();
920 901052 : while (nPos < nLen && nAnzStrings < NF_MAX_FORMAT_SYMBOLS)
921 : {
922 723576 : nTypeArray[nAnzStrings] = Next_Symbol(rString, nPos, sStrArray[nAnzStrings]);
923 723576 : if (nTypeArray[nAnzStrings] == NF_SYMBOLTYPE_STAR)
924 : { // Ueberwachung des '*'
925 4624 : if (bStar)
926 : {
927 0 : return nPos; // Fehler: doppelter '*'
928 : }
929 : else
930 : {
931 4624 : bStar = true;
932 : }
933 : }
934 723576 : nAnzStrings++;
935 : }
936 :
937 88738 : return 0; // 0 => ok
938 : }
939 :
940 628072 : void ImpSvNumberformatScan::SkipStrings(sal_uInt16& i, sal_Int32& nPos)
941 : {
942 2377570 : while (i < nAnzStrings && ( nTypeArray[i] == NF_SYMBOLTYPE_STRING
943 547982 : || nTypeArray[i] == NF_SYMBOLTYPE_BLANK
944 543958 : || nTypeArray[i] == NF_SYMBOLTYPE_STAR) )
945 : {
946 29486 : nPos = nPos + sStrArray[i].getLength();
947 29486 : i++;
948 : }
949 628072 : }
950 :
951 26056 : sal_uInt16 ImpSvNumberformatScan::PreviousKeyword(sal_uInt16 i)
952 : {
953 26056 : short res = 0;
954 26056 : if (i > 0 && i < nAnzStrings)
955 : {
956 16976 : i--;
957 55050 : while (i > 0 && nTypeArray[i] <= 0)
958 : {
959 21098 : i--;
960 : }
961 16976 : if (nTypeArray[i] > 0)
962 : {
963 16976 : res = nTypeArray[i];
964 : }
965 : }
966 26056 : return res;
967 : }
968 :
969 21936 : sal_uInt16 ImpSvNumberformatScan::NextKeyword(sal_uInt16 i)
970 : {
971 21936 : short res = 0;
972 21936 : if (i < nAnzStrings-1)
973 : {
974 20736 : i++;
975 60070 : while (i < nAnzStrings-1 && nTypeArray[i] <= 0)
976 : {
977 18598 : i++;
978 : }
979 20736 : if (nTypeArray[i] > 0)
980 : {
981 20726 : res = nTypeArray[i];
982 : }
983 : }
984 21936 : return res;
985 : }
986 :
987 34 : short ImpSvNumberformatScan::PreviousType( sal_uInt16 i )
988 : {
989 34 : if ( i > 0 && i < nAnzStrings )
990 : {
991 68 : do
992 : {
993 34 : i--;
994 : }
995 34 : while ( i > 0 && nTypeArray[i] == NF_SYMBOLTYPE_EMPTY );
996 34 : return nTypeArray[i];
997 : }
998 0 : return 0;
999 : }
1000 :
1001 53808 : sal_Unicode ImpSvNumberformatScan::PreviousChar(sal_uInt16 i)
1002 : {
1003 53808 : sal_Unicode res = ' ';
1004 53808 : if (i > 0 && i < nAnzStrings)
1005 : {
1006 44728 : i--;
1007 242740 : while (i > 0 &&
1008 38334 : ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
1009 38326 : nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
1010 38290 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1011 38290 : nTypeArray[i] == NF_SYMBOLTYPE_BLANK ))
1012 : {
1013 44 : i--;
1014 : }
1015 44728 : if (sStrArray[i].getLength() > 0)
1016 : {
1017 44728 : res = sStrArray[i][sStrArray[i].getLength()-1];
1018 : }
1019 : }
1020 53808 : return res;
1021 : }
1022 :
1023 36154 : sal_Unicode ImpSvNumberformatScan::NextChar(sal_uInt16 i)
1024 : {
1025 36154 : sal_Unicode res = ' ';
1026 36154 : if (i < nAnzStrings-1)
1027 : {
1028 36154 : i++;
1029 216780 : while (i < nAnzStrings-1 &&
1030 36118 : ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
1031 36118 : nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
1032 36118 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1033 36118 : nTypeArray[i] == NF_SYMBOLTYPE_BLANK))
1034 : {
1035 0 : i++;
1036 : }
1037 36154 : if (sStrArray[i].getLength() > 0)
1038 : {
1039 36154 : res = sStrArray[i][0];
1040 : }
1041 : }
1042 36154 : return res;
1043 : }
1044 :
1045 8 : bool ImpSvNumberformatScan::IsLastBlankBeforeFrac(sal_uInt16 i)
1046 : {
1047 8 : bool res = true;
1048 8 : if (i < nAnzStrings-1)
1049 : {
1050 8 : bool bStop = false;
1051 8 : i++;
1052 28 : while (i < nAnzStrings-1 && !bStop)
1053 : {
1054 12 : i++;
1055 24 : if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
1056 12 : sStrArray[i][0] == '/')
1057 : {
1058 8 : bStop = true;
1059 : }
1060 8 : else if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
1061 4 : sStrArray[i][0] == ' ')
1062 : {
1063 0 : res = false;
1064 : }
1065 : }
1066 8 : if (!bStop) // kein '/'{
1067 : {
1068 0 : res = false;
1069 : }
1070 : }
1071 : else
1072 : {
1073 0 : res = false; // kein '/' mehr
1074 : }
1075 8 : return res;
1076 : }
1077 :
1078 89886 : void ImpSvNumberformatScan::Reset()
1079 : {
1080 89886 : nAnzStrings = 0;
1081 89886 : 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 89886 : eScannedType = NUMBERFORMAT_UNDEFINED;
1091 89886 : nRepPos = 0;
1092 89886 : bExp = false;
1093 89886 : bThousand = false;
1094 89886 : nThousand = 0;
1095 89886 : bDecSep = false;
1096 89886 : nDecPos = (sal_uInt16)-1;
1097 89886 : nExpPos = (sal_uInt16)-1;
1098 89886 : nBlankPos = (sal_uInt16)-1;
1099 89886 : nCntPre = 0;
1100 89886 : nCntPost = 0;
1101 89886 : nCntExp = 0;
1102 89886 : bFrac = false;
1103 89886 : bBlank = false;
1104 89886 : nNatNumModifier = 0;
1105 89886 : }
1106 :
1107 6248 : bool ImpSvNumberformatScan::Is100SecZero( sal_uInt16 i, bool bHadDecSep )
1108 : {
1109 6248 : sal_uInt16 nIndexPre = PreviousKeyword( i );
1110 : return (nIndexPre == NF_KEY_S || nIndexPre == NF_KEY_SS) &&
1111 : (bHadDecSep ||
1112 6248 : ( i > 0 && nTypeArray[i-1] == NF_SYMBOLTYPE_STRING));
1113 : // SS"any"00 take "any" as a valid decimal separator
1114 : }
1115 :
1116 88738 : sal_Int32 ImpSvNumberformatScan::ScanType()
1117 : {
1118 88738 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1119 :
1120 88738 : sal_Int32 nPos = 0;
1121 88738 : sal_uInt16 i = 0;
1122 : short eNewType;
1123 88738 : bool bMatchBracket = false;
1124 88738 : bool bHaveGeneral = false; // if General/Standard encountered
1125 :
1126 88738 : SkipStrings(i, nPos);
1127 716810 : while (i < nAnzStrings)
1128 : {
1129 539334 : if (nTypeArray[i] > 0)
1130 : { // keyword
1131 : sal_uInt16 nIndexPre;
1132 : sal_uInt16 nIndexNex;
1133 : sal_Unicode cChar;
1134 :
1135 124382 : switch (nTypeArray[i])
1136 : {
1137 : case NF_KEY_E: // E
1138 2074 : eNewType = NUMBERFORMAT_SCIENTIFIC;
1139 2074 : 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 18460 : eNewType = NUMBERFORMAT_TIME;
1147 18460 : break;
1148 : case NF_KEY_M: // M
1149 : case NF_KEY_MM: // MM
1150 : // minute or month
1151 19808 : nIndexPre = PreviousKeyword(i);
1152 19808 : nIndexNex = NextKeyword(i);
1153 19808 : cChar = PreviousChar(i);
1154 19808 : 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 9936 : eNewType = NUMBERFORMAT_TIME;
1161 9936 : nTypeArray[i] -= 2; // 6 -> 4, 7 -> 5
1162 : }
1163 : else
1164 : {
1165 9872 : eNewType = NUMBERFORMAT_DATE;
1166 : }
1167 19808 : 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 82014 : eNewType = NUMBERFORMAT_DATE;
1193 82014 : break;
1194 : case NF_KEY_CCC: // CCC
1195 994 : eNewType = NUMBERFORMAT_CURRENCY;
1196 994 : break;
1197 : case NF_KEY_GENERAL: // Standard
1198 1032 : eNewType = NUMBERFORMAT_NUMBER;
1199 1032 : bHaveGeneral = true;
1200 1032 : break;
1201 : default:
1202 0 : eNewType = NUMBERFORMAT_UNDEFINED;
1203 0 : break;
1204 : }
1205 : }
1206 : else
1207 : { // control character
1208 414952 : switch ( sStrArray[i][0] )
1209 : {
1210 : case '#':
1211 : case '?':
1212 116256 : eNewType = NUMBERFORMAT_NUMBER;
1213 116256 : break;
1214 : case '0':
1215 91106 : if ( (eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME )
1216 : {
1217 4120 : if ( Is100SecZero( i, bDecSep ) )
1218 : {
1219 4120 : bDecSep = true; // subsequent 0's
1220 4120 : eNewType = NUMBERFORMAT_TIME;
1221 : }
1222 : else
1223 : {
1224 0 : return nPos; // Error
1225 : }
1226 : }
1227 : else
1228 : {
1229 86986 : eNewType = NUMBERFORMAT_NUMBER;
1230 : }
1231 91106 : break;
1232 : case '%':
1233 2010 : eNewType = NUMBERFORMAT_PERCENT;
1234 2010 : break;
1235 : case '/':
1236 17664 : eNewType = NUMBERFORMAT_FRACTION;
1237 17664 : break;
1238 : case '[':
1239 70598 : if ( i < nAnzStrings-1 &&
1240 24242 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1241 22114 : sStrArray[i+1][0] == '$' )
1242 : { // as of SV_NUMBERFORMATTER_VERSION_NEW_CURR
1243 14210 : eNewType = NUMBERFORMAT_CURRENCY;
1244 14210 : bMatchBracket = true;
1245 : }
1246 27968 : else if ( i < nAnzStrings-1 &&
1247 10032 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1248 7904 : sStrArray[i+1][0] == '~' )
1249 : { // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1250 7904 : eNewType = NUMBERFORMAT_DATE;
1251 7904 : bMatchBracket = true;
1252 : }
1253 : else
1254 : {
1255 2128 : sal_uInt16 nIndexNex = NextKeyword(i);
1256 2128 : 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 2128 : eNewType = NUMBERFORMAT_TIME;
1263 : else
1264 : {
1265 0 : return nPos; // Error
1266 : }
1267 : }
1268 24242 : break;
1269 : case '@':
1270 1260 : eNewType = NUMBERFORMAT_TEXT;
1271 1260 : break;
1272 : default:
1273 162414 : if (pLoc->getTime100SecSep().equals(sStrArray[i]))
1274 : {
1275 29440 : bDecSep = true; // for SS,0
1276 : }
1277 162414 : eNewType = NUMBERFORMAT_UNDEFINED;
1278 162414 : break;
1279 : }
1280 : }
1281 539334 : if (eScannedType == NUMBERFORMAT_UNDEFINED)
1282 : {
1283 100790 : eScannedType = eNewType;
1284 : }
1285 438544 : else if (eScannedType == NUMBERFORMAT_TEXT || eNewType == NUMBERFORMAT_TEXT)
1286 : {
1287 16 : eScannedType = NUMBERFORMAT_TEXT; // Text bleibt immer Text
1288 : }
1289 438528 : else if (eNewType == NUMBERFORMAT_UNDEFINED)
1290 : { // bleibt wie bisher
1291 : }
1292 288364 : else if (eScannedType != eNewType)
1293 : {
1294 107856 : switch (eScannedType)
1295 : {
1296 : case NUMBERFORMAT_DATE:
1297 15758 : switch (eNewType)
1298 : {
1299 : case NUMBERFORMAT_TIME:
1300 2090 : eScannedType = NUMBERFORMAT_DATETIME;
1301 2090 : break;
1302 : case NUMBERFORMAT_FRACTION: // DD/MM
1303 13668 : 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 15758 : 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 4074 : switch (eNewType)
1337 : {
1338 : case NUMBERFORMAT_TIME:
1339 : case NUMBERFORMAT_DATE:
1340 4074 : 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 4074 : 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 5076 : switch (eNewType)
1366 : {
1367 : case NUMBERFORMAT_NUMBER: // nur Zahl nach E
1368 5076 : break;
1369 : default:
1370 0 : return nPos;
1371 : }
1372 5076 : break;
1373 : case NUMBERFORMAT_NUMBER:
1374 9178 : switch (eNewType)
1375 : {
1376 : case NUMBERFORMAT_SCIENTIFIC:
1377 : case NUMBERFORMAT_PERCENT:
1378 : case NUMBERFORMAT_FRACTION:
1379 : case NUMBERFORMAT_CURRENCY:
1380 9178 : eScannedType = eNewType;
1381 9178 : 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 9178 : break;
1393 : case NUMBERFORMAT_FRACTION:
1394 4994 : switch (eNewType)
1395 : {
1396 : case NUMBERFORMAT_NUMBER: // nur Zahl nach Bruch
1397 4994 : break;
1398 : default:
1399 0 : return nPos;
1400 : }
1401 4994 : break;
1402 : default:
1403 68776 : break;
1404 : }
1405 : }
1406 539334 : nPos = nPos + sStrArray[i].getLength(); // Korrekturposition
1407 539334 : i++;
1408 539334 : if ( bMatchBracket )
1409 : { // no type detection inside of matching brackets if [$...], [~...]
1410 198984 : while ( bMatchBracket && i < nAnzStrings )
1411 : {
1412 205244 : if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL
1413 50488 : && sStrArray[i][0] == ']' )
1414 : {
1415 22114 : bMatchBracket = false;
1416 : }
1417 : else
1418 : {
1419 132642 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1420 : }
1421 154756 : nPos = nPos + sStrArray[i].getLength();
1422 154756 : i++;
1423 : }
1424 22114 : if ( bMatchBracket )
1425 : {
1426 0 : return nPos; // missing closing bracket at end of code
1427 : }
1428 : }
1429 539334 : SkipStrings(i, nPos);
1430 : }
1431 :
1432 99074 : if ((eScannedType == NUMBERFORMAT_NUMBER ||
1433 : eScannedType == NUMBERFORMAT_UNDEFINED) &&
1434 10336 : nCurrPos >= 0 && !bHaveGeneral)
1435 : {
1436 10336 : eScannedType = NUMBERFORMAT_CURRENCY; // old "automatic" currency
1437 : }
1438 88738 : if (eScannedType == NUMBERFORMAT_UNDEFINED)
1439 : {
1440 182 : eScannedType = NUMBERFORMAT_DEFINED;
1441 : }
1442 88738 : return 0; // Alles ok
1443 : }
1444 :
1445 33958 : bool ImpSvNumberformatScan::InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr )
1446 : {
1447 33958 : if (nAnzStrings >= NF_MAX_FORMAT_SYMBOLS || nPos > nAnzStrings)
1448 : {
1449 0 : return false;
1450 : }
1451 33958 : if (nPos > 0 && nTypeArray[nPos-1] == NF_SYMBOLTYPE_EMPTY)
1452 : {
1453 33958 : --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 33958 : ++nAnzResStrings;
1469 33958 : nTypeArray[nPos] = static_cast<short>(eType);
1470 33958 : sStrArray[nPos] = rStr;
1471 33958 : return true;
1472 : }
1473 :
1474 72104 : int ImpSvNumberformatScan::FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i,
1475 : sal_uInt16& rAnzResStrings )
1476 : {
1477 87912 : if ( sStrArray[i][0] == '[' &&
1478 : i < nAnzStrings-1 &&
1479 7904 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1480 7904 : sStrArray[i+1][0] == '~' )
1481 : {
1482 : // [~calendarID]
1483 : // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1484 7904 : nPos = nPos + sStrArray[i].getLength(); // [
1485 7904 : nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
1486 7904 : nPos = nPos + sStrArray[++i].getLength(); // ~
1487 7904 : sStrArray[i-1] += sStrArray[i]; // [~
1488 7904 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1489 7904 : rAnzResStrings--;
1490 7904 : if ( ++i >= nAnzStrings )
1491 : {
1492 0 : return -1; // error
1493 : }
1494 7904 : nPos = nPos + sStrArray[i].getLength(); // calendarID
1495 7904 : OUString& rStr = sStrArray[i];
1496 7904 : nTypeArray[i] = NF_SYMBOLTYPE_CALENDAR; // convert
1497 7904 : i++;
1498 47424 : while ( i < nAnzStrings && sStrArray[i][0] != ']' )
1499 : {
1500 31616 : nPos = nPos + sStrArray[i].getLength();
1501 31616 : rStr += sStrArray[i];
1502 31616 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1503 31616 : rAnzResStrings--;
1504 31616 : i++;
1505 : }
1506 15808 : if ( rStr.getLength() && i < nAnzStrings &&
1507 7904 : sStrArray[i][0] == ']' )
1508 : {
1509 7904 : nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
1510 7904 : nPos = nPos + sStrArray[i].getLength();
1511 7904 : i++;
1512 : }
1513 : else
1514 : {
1515 0 : return -1; // error
1516 : }
1517 7904 : return 1;
1518 : }
1519 64200 : return 0;
1520 : }
1521 :
1522 88738 : sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
1523 : {
1524 88738 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1525 :
1526 : // save values for convert mode
1527 88738 : OUString sOldDecSep = pFormatter->GetNumDecimalSep();
1528 88738 : OUString sOldThousandSep = pFormatter->GetNumThousandSep();
1529 88738 : OUString sOldDateSep = pFormatter->GetDateSep();
1530 88738 : OUString sOldTimeSep = pLoc->getTimeSep();
1531 88738 : OUString sOldTime100SecSep= pLoc->getTime100SecSep();
1532 88738 : OUString sOldCurSymbol = GetCurSymbol();
1533 88738 : OUString sOldCurString = GetCurString();
1534 88738 : sal_Unicode cOldKeyH = sKeyword[NF_KEY_H][0];
1535 88738 : sal_Unicode cOldKeyMI = sKeyword[NF_KEY_MI][0];
1536 88738 : 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 88738 : if ( sOldThousandSep[0] == cNonBreakingSpace && sOldThousandSep.getLength() == 1 )
1543 : {
1544 134 : sOldThousandSep = " ";
1545 : }
1546 : // change locale data et al
1547 88738 : if (bConvertMode)
1548 : {
1549 5702 : pFormatter->ChangeIntl(eNewLnge);
1550 : //! pointer may have changed
1551 5702 : pLoc = pFormatter->GetLocaleData();
1552 : //! init new keywords
1553 5702 : InitKeywords();
1554 : }
1555 88738 : const CharClass* pChrCls = pFormatter->GetCharClass();
1556 :
1557 88738 : sal_Int32 nPos = 0; // error correction position
1558 88738 : sal_uInt16 i = 0; // symbol loop counter
1559 88738 : sal_uInt16 nCounter = 0; // counts digits
1560 88738 : nAnzResStrings = nAnzStrings; // counts remaining symbols
1561 88738 : bDecSep = false; // reset in case already used in TypeCheck
1562 88738 : bool bThaiT = false; // Thai T NatNum modifier present
1563 88738 : bool bTimePart = false;
1564 :
1565 88738 : switch (eScannedType)
1566 : {
1567 : case NUMBERFORMAT_TEXT:
1568 : case NUMBERFORMAT_DEFINED:
1569 5182 : while (i < nAnzStrings)
1570 : {
1571 2298 : switch (nTypeArray[i])
1572 : {
1573 : case NF_SYMBOLTYPE_BLANK:
1574 : case NF_SYMBOLTYPE_STAR:
1575 788 : break;
1576 : case NF_KEY_GENERAL : // #77026# "General" is the same as "@"
1577 0 : break;
1578 : default:
1579 2786 : if ( nTypeArray[i] != NF_SYMBOLTYPE_DEL ||
1580 1276 : sStrArray[i][0] != '@' )
1581 : {
1582 250 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1583 : }
1584 1510 : break;
1585 : }
1586 2298 : nPos = nPos + sStrArray[i].getLength();
1587 2298 : i++;
1588 : } // of while
1589 1442 : break;
1590 :
1591 : case NUMBERFORMAT_NUMBER:
1592 : case NUMBERFORMAT_PERCENT:
1593 : case NUMBERFORMAT_CURRENCY:
1594 : case NUMBERFORMAT_SCIENTIFIC:
1595 : case NUMBERFORMAT_FRACTION:
1596 331788 : while (i < nAnzStrings)
1597 : {
1598 : // TODO: rechecking eScannedType is unnecessary.
1599 : // This switch-case is for eScannedType == NUMBERFORMAT_FRACTION anyway
1600 283026 : if (eScannedType == NUMBERFORMAT_FRACTION && // special case
1601 23960 : nTypeArray[i] == NF_SYMBOLTYPE_DEL && // # ### #/#
1602 17982 : StringEqualsChar( sOldThousandSep, ' ' ) && // e.g. France or Sweden
1603 36 : StringEqualsChar( sStrArray[i], ' ' ) &&
1604 8 : !bFrac &&
1605 8 : IsLastBlankBeforeFrac(i) )
1606 : {
1607 8 : nTypeArray[i] = NF_SYMBOLTYPE_STRING; // del->string
1608 : } // kein Taus.p.
1609 :
1610 944066 : if (nTypeArray[i] == NF_SYMBOLTYPE_BLANK ||
1611 237684 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1612 233172 : nTypeArray[i] == NF_KEY_CCC || // CCC
1613 232178 : nTypeArray[i] == NF_KEY_GENERAL ) // Standard
1614 : {
1615 9886 : if (nTypeArray[i] == NF_KEY_GENERAL)
1616 : {
1617 1032 : nThousand = FLAG_STANDARD_IN_FORMAT;
1618 1032 : if ( bConvertMode )
1619 : {
1620 38 : sStrArray[i] = sNameStandardFormat;
1621 : }
1622 : }
1623 9886 : nPos = nPos + sStrArray[i].getLength();
1624 9886 : i++;
1625 : }
1626 439888 : else if (nTypeArray[i] == NF_SYMBOLTYPE_STRING || // Strings oder
1627 208742 : nTypeArray[i] > 0) // Keywords
1628 : {
1629 26552 : if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
1630 2074 : nTypeArray[i] == NF_KEY_E) // E+
1631 : {
1632 2074 : if (bExp) // doppelt
1633 : {
1634 0 : return nPos;
1635 : }
1636 2074 : bExp = true;
1637 2074 : nExpPos = i;
1638 2074 : if (bDecSep)
1639 : {
1640 2074 : nCntPost = nCounter;
1641 : }
1642 : else
1643 : {
1644 0 : nCntPre = nCounter;
1645 : }
1646 2074 : nCounter = 0;
1647 2074 : nTypeArray[i] = NF_SYMBOLTYPE_EXP;
1648 : }
1649 28390 : else if (eScannedType == NUMBERFORMAT_FRACTION &&
1650 5986 : sStrArray[i][0] == ' ')
1651 : {
1652 3988 : if (!bBlank && !bFrac) // nicht doppelt oder hinter /
1653 : {
1654 8 : if (bDecSep && nCounter > 0) // Nachkommastellen
1655 : {
1656 0 : return nPos; // Fehler
1657 : }
1658 8 : bBlank = true;
1659 8 : nBlankPos = i;
1660 8 : nCntPre = nCounter;
1661 8 : nCounter = 0;
1662 : }
1663 3988 : nTypeArray[i] = NF_SYMBOLTYPE_FRACBLANK;
1664 : }
1665 18416 : else if (nTypeArray[i] == NF_KEY_THAI_T)
1666 : {
1667 0 : bThaiT = true;
1668 0 : sStrArray[i] = sKeyword[nTypeArray[i]];
1669 : }
1670 21096 : else if (sStrArray[i][0] >= '0' &&
1671 2680 : sStrArray[i][0] <= '9')
1672 : {
1673 1990 : OUString sDiv;
1674 1990 : sal_uInt16 j = i;
1675 7960 : while(j < nAnzStrings)
1676 : {
1677 3980 : sDiv += sStrArray[j++];
1678 : }
1679 1990 : if (OUString::valueOf(sDiv.toInt32()) == sDiv)
1680 : {
1681 : /* Found a Divisor */
1682 7960 : while (i < j)
1683 : {
1684 3980 : nTypeArray[i++] = NF_SYMBOLTYPE_FRAC_FDIV;
1685 : }
1686 1990 : i = j - 1; // Stop the loop
1687 1990 : if (nCntPost)
1688 : {
1689 1990 : 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 1990 : if ( ( eScannedType != NUMBERFORMAT_FRACTION ) && (!nCntPre) )
1698 : {
1699 0 : nCntPre++;
1700 : }
1701 1990 : }
1702 : }
1703 : else
1704 : {
1705 16426 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1706 : }
1707 24478 : nPos = nPos + sStrArray[i].getLength();
1708 24478 : i++;
1709 : }
1710 206668 : else if (nTypeArray[i] == NF_SYMBOLTYPE_DEL)
1711 : {
1712 206668 : sal_Unicode cHere = sStrArray[i][0];
1713 206668 : sal_Unicode cSaved = cHere;
1714 : // Handle not pre-known separators in switch.
1715 : sal_Unicode cSimplified;
1716 206668 : if (StringEqualsChar( pFormatter->GetNumThousandSep(), cHere))
1717 : {
1718 33910 : cSimplified = ',';
1719 : }
1720 172758 : else if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cHere))
1721 : {
1722 24348 : cSimplified = '.';
1723 : }
1724 : else
1725 : {
1726 148410 : cSimplified = cHere;
1727 : }
1728 :
1729 206668 : OUString& rStr = sStrArray[i];
1730 :
1731 206668 : switch ( cSimplified )
1732 : {
1733 : case '#':
1734 : case '0':
1735 : case '?':
1736 106752 : if (nThousand > 0) // #... #
1737 : {
1738 0 : return nPos; // Fehler
1739 : }
1740 106752 : else if (bFrac && cHere == '0')
1741 : {
1742 0 : return nPos; // 0 im Nenner
1743 : }
1744 106752 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1745 106752 : nPos = nPos + rStr.getLength();
1746 106752 : i++;
1747 106752 : nCounter++;
1748 696582 : while (i < nAnzStrings &&
1749 171670 : (sStrArray[i][0] == '#' ||
1750 136630 : sStrArray[i][0] == '0' ||
1751 80276 : sStrArray[i][0] == '?'))
1752 : {
1753 94502 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1754 94502 : nPos = nPos + sStrArray[i].getLength();
1755 94502 : nCounter++;
1756 94502 : i++;
1757 : }
1758 106752 : break;
1759 : case '-':
1760 20186 : if ( bDecSep && nDecPos+1 == i &&
1761 3976 : nTypeArray[nDecPos] == NF_SYMBOLTYPE_DECSEP )
1762 : {
1763 : // "0.--"
1764 3976 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1765 3976 : nPos = nPos + rStr.getLength();
1766 3976 : i++;
1767 3976 : nCounter++;
1768 15920 : while (i < nAnzStrings &&
1769 3992 : (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 7952 : if ( eScannedType == NUMBERFORMAT_CURRENCY
1776 3976 : && rStr.getLength() >= 2 &&
1777 : (i == nAnzStrings-1 ||
1778 0 : sStrArray[i+1][0] != '-') )
1779 : {
1780 0 : break;
1781 : }
1782 3976 : rStr += sStrArray[i];
1783 3976 : nPos = nPos + sStrArray[i].getLength();
1784 3976 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1785 3976 : nAnzResStrings--;
1786 3976 : nCounter++;
1787 3976 : i++;
1788 : }
1789 : }
1790 : else
1791 : {
1792 12234 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1793 12234 : nPos = nPos + sStrArray[i].getLength();
1794 12234 : i++;
1795 : }
1796 16210 : break;
1797 : case '.':
1798 : case ',':
1799 : case '\'':
1800 : case ' ':
1801 63490 : if ( StringEqualsChar( sOldThousandSep, cSaved ) )
1802 : {
1803 : // previous char with skip empty
1804 34000 : sal_Unicode cPre = PreviousChar(i);
1805 : sal_Unicode cNext;
1806 34000 : 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 67992 : else if (i > 0 && i < nAnzStrings-1 &&
1822 : (cPre == '#' || cPre == '0') &&
1823 33992 : ((cNext = NextChar(i)) == '#' || cNext == '0')) // #,#
1824 : {
1825 33958 : nPos = nPos + sStrArray[i].getLength();
1826 33958 : if (!bThousand) // only once
1827 : {
1828 33958 : bThousand = true;
1829 : }
1830 : // Eat it, will be reinserted at proper
1831 : // grouping positions further down.
1832 33958 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1833 33958 : nAnzResStrings--;
1834 33958 : i++;
1835 : }
1836 76 : else if (i > 0 && (cPre == '#' || cPre == '0')
1837 34 : && PreviousType(i) == NF_SYMBOLTYPE_DIGIT
1838 : && nThousand < FLAG_STANDARD_IN_FORMAT )
1839 : { // #,,,,
1840 34 : if ( StringEqualsChar( sOldThousandSep, ' ' ) )
1841 : {
1842 : // strange, those French..
1843 34 : bool bFirst = true;
1844 : // set a hard Non-Breaking Space or ConvertMode
1845 34 : const OUString& rSepF = pFormatter->GetNumThousandSep();
1846 136 : while ( i < nAnzStrings &&
1847 34 : sStrArray[i] == sOldThousandSep &&
1848 34 : 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 68 : if ( i < nAnzStrings-1 &&
1868 34 : sStrArray[i] == sOldThousandSep )
1869 : {
1870 : // something following last space
1871 : // => space if currency contained,
1872 : // else separator
1873 34 : nPos = nPos + sStrArray[i].getLength();
1874 116 : if ( (nPos <= nCurrPos &&
1875 32 : nCurrPos < nPos + sStrArray[i+1].getLength()) ||
1876 18 : nTypeArray[i+1] == NF_KEY_CCC ||
1877 : (i < nAnzStrings-2 &&
1878 16 : sStrArray[i+1][0] == '[' &&
1879 16 : sStrArray[i+2][0] == '$') )
1880 : {
1881 34 : 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 34 : 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 8 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1918 8 : nPos = nPos + rStr.getLength();
1919 8 : i++;
1920 16 : 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 29490 : else if ( StringEqualsChar( sOldDecSep, cSaved ) )
1931 : {
1932 24348 : if (bBlank || bFrac) // . behind / or ' '
1933 : {
1934 0 : return nPos; // error
1935 : }
1936 24348 : 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 24348 : 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 24348 : nPos = nPos + sStrArray[i].getLength();
1960 24348 : nTypeArray[i] = NF_SYMBOLTYPE_DECSEP;
1961 24348 : sStrArray[i] = pFormatter->GetNumDecimalSep();
1962 24348 : bDecSep = true;
1963 24348 : nDecPos = i;
1964 24348 : nCntPre = nCounter;
1965 24348 : nCounter = 0;
1966 :
1967 24348 : i++;
1968 : }
1969 : } // of else = DecSep
1970 : else // . without meaning
1971 : {
1972 9122 : if (cSaved == ' ' &&
1973 : eScannedType == NUMBERFORMAT_FRACTION &&
1974 3980 : StringEqualsChar( sStrArray[i], ' ' ) )
1975 : {
1976 3980 : if (!bBlank && !bFrac) // no dups
1977 : { // or behind /
1978 3980 : if (bDecSep && nCounter > 0)// dec.
1979 : {
1980 0 : return nPos; // error
1981 : }
1982 3980 : bBlank = true;
1983 3980 : nBlankPos = i;
1984 3980 : nCntPre = nCounter;
1985 3980 : nCounter = 0;
1986 : }
1987 3980 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1988 3980 : nPos = nPos + sStrArray[i].getLength();
1989 : }
1990 : else
1991 : {
1992 1162 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1993 1162 : nPos = nPos + rStr.getLength();
1994 1162 : i++;
1995 2324 : 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 63490 : break;
2006 : case '/':
2007 3996 : if (eScannedType == NUMBERFORMAT_FRACTION)
2008 : {
2009 7992 : if ( i == 0 ||
2010 3996 : (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 3996 : else if (!bFrac || (bDecSep && nCounter > 0))
2016 : {
2017 3996 : bFrac = true;
2018 3996 : nCntPost = nCounter;
2019 3996 : nCounter = 0;
2020 3996 : nTypeArray[i] = NF_SYMBOLTYPE_FRAC;
2021 3996 : nPos = nPos + sStrArray[i].getLength();
2022 3996 : 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 3996 : break;
2036 : case '[' :
2037 42630 : if ( eScannedType == NUMBERFORMAT_CURRENCY &&
2038 : i < nAnzStrings-1 &&
2039 14210 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
2040 14210 : sStrArray[i+1][0] == '$' )
2041 : {
2042 : // [$DM-xxx]
2043 : // ab SV_NUMBERFORMATTER_VERSION_NEW_CURR
2044 14210 : nPos = nPos + sStrArray[i].getLength(); // [
2045 14210 : nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
2046 14210 : nPos = nPos + sStrArray[++i].getLength(); // $
2047 14210 : sStrArray[i-1] += sStrArray[i]; // [$
2048 14210 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2049 14210 : nAnzResStrings--;
2050 14210 : if ( ++i >= nAnzStrings )
2051 : {
2052 0 : return nPos; // Fehler
2053 : }
2054 14210 : nPos = nPos + sStrArray[i].getLength(); // DM
2055 14210 : OUString* pStr = &sStrArray[i];
2056 14210 : nTypeArray[i] = NF_SYMBOLTYPE_CURRENCY; // wandeln
2057 14210 : bool bHadDash = false;
2058 14210 : i++;
2059 85218 : while ( i < nAnzStrings && sStrArray[i][0] != ']' )
2060 : {
2061 56798 : nPos = nPos + sStrArray[i].getLength();
2062 56798 : if ( bHadDash )
2063 : {
2064 42548 : *pStr += sStrArray[i];
2065 42548 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2066 42548 : nAnzResStrings--;
2067 : }
2068 : else
2069 : {
2070 14250 : if ( sStrArray[i][0] == '-' )
2071 : {
2072 14188 : bHadDash = true;
2073 14188 : pStr = &sStrArray[i];
2074 14188 : nTypeArray[i] = NF_SYMBOLTYPE_CURREXT;
2075 : }
2076 : else
2077 : {
2078 62 : *pStr += sStrArray[i];
2079 62 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2080 62 : nAnzResStrings--;
2081 : }
2082 : }
2083 56798 : i++;
2084 : }
2085 14210 : if ( rStr.getLength() && i < nAnzStrings && sStrArray[i][0] == ']' )
2086 : {
2087 14210 : nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
2088 14210 : nPos = nPos + sStrArray[i].getLength();
2089 14210 : 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 14210 : break;
2103 : default: // andere Dels
2104 2010 : if (eScannedType == NUMBERFORMAT_PERCENT && cHere == '%')
2105 : {
2106 2010 : nTypeArray[i] = NF_SYMBOLTYPE_PERCENT;
2107 : }
2108 : else
2109 : {
2110 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2111 : }
2112 2010 : nPos = nPos + sStrArray[i].getLength();
2113 2010 : i++;
2114 2010 : 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 45378 : if (eScannedType == NUMBERFORMAT_FRACTION)
2125 : {
2126 3996 : if (bFrac)
2127 : {
2128 3996 : 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 41382 : if (bExp)
2142 : {
2143 2074 : nCntExp = nCounter;
2144 : }
2145 39308 : else if (bDecSep)
2146 : {
2147 22274 : nCntPost = nCounter;
2148 : }
2149 : else
2150 : {
2151 17034 : nCntPre = nCounter;
2152 : }
2153 : }
2154 45378 : if (bThousand) // Expansion of grouping separators
2155 : {
2156 : sal_uInt16 nMaxPos;
2157 33958 : 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 33958 : else if (bDecSep) // decimal separator present
2169 : {
2170 20104 : nMaxPos = nDecPos;
2171 : }
2172 13854 : else if (bExp) // 'E' exponent present
2173 : {
2174 0 : nMaxPos = nExpPos;
2175 : }
2176 : else // up to end
2177 : {
2178 13854 : nMaxPos = i;
2179 : }
2180 : // Insert separators at proper positions.
2181 33958 : sal_Int32 nCount = 0;
2182 33958 : utl::DigitGroupingIterator aGrouping( pLoc->getDigitGrouping());
2183 33958 : size_t nFirstDigitSymbol = nMaxPos;
2184 33958 : size_t nFirstGroupingSymbol = nMaxPos;
2185 33958 : i = nMaxPos;
2186 349956 : while (i-- > 0)
2187 : {
2188 282040 : if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2189 : {
2190 135832 : nFirstDigitSymbol = i;
2191 135832 : nCount = nCount + sStrArray[i].getLength(); // MSC converts += to int and then warns, so ...
2192 : // Insert separator only if not leftmost symbol.
2193 135832 : if (i > 0 && nCount >= aGrouping.getPos())
2194 : {
2195 : DBG_ASSERT( sStrArray[i].getLength() == 1,
2196 : "ImpSvNumberformatScan::FinalScan: combined digits in group separator insertion");
2197 33958 : 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 33958 : nFirstDigitSymbol = i + 1;
2204 33958 : nFirstGroupingSymbol = i;
2205 33958 : aGrouping.advance();
2206 : }
2207 : }
2208 : }
2209 : // Generated something like "string",000; remove separator again.
2210 33958 : if (nFirstGroupingSymbol < nFirstDigitSymbol)
2211 : {
2212 0 : nTypeArray[nFirstGroupingSymbol] = NF_SYMBOLTYPE_EMPTY;
2213 0 : nAnzResStrings--;
2214 33958 : }
2215 : }
2216 : // Combine digits into groups to save memory (Info will be copied
2217 : // later, taking only non-empty symbols).
2218 306680 : for (i = 0; i < nAnzStrings; ++i)
2219 : {
2220 261302 : if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2221 : {
2222 110728 : OUString& rStr = sStrArray[i];
2223 315958 : while (++i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2224 : {
2225 94502 : rStr += sStrArray[i];
2226 94502 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2227 94502 : nAnzResStrings--;
2228 : }
2229 : }
2230 : }
2231 45378 : break; // of NUMBERFORMAT_NUMBER
2232 : case NUMBERFORMAT_DATE:
2233 223060 : while (i < nAnzStrings)
2234 : {
2235 : int nCalRet;
2236 159100 : switch (nTypeArray[i])
2237 : {
2238 : case NF_SYMBOLTYPE_BLANK:
2239 : case NF_SYMBOLTYPE_STAR:
2240 : case NF_SYMBOLTYPE_STRING:
2241 2120 : nPos = nPos + sStrArray[i].getLength();
2242 2120 : i++;
2243 2120 : break;
2244 : case NF_SYMBOLTYPE_DEL:
2245 71360 : if (sStrArray[i] == sOldDateSep)
2246 : {
2247 9570 : nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
2248 9570 : nPos = nPos + sStrArray[i].getLength();
2249 9570 : if (bConvertMode)
2250 : {
2251 1566 : sStrArray[i] = pFormatter->GetDateSep();
2252 : }
2253 9570 : i++;
2254 : }
2255 61790 : else if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
2256 : {
2257 7904 : if ( nCalRet < 0 )
2258 : {
2259 0 : return nPos; // error
2260 : }
2261 : }
2262 : else
2263 : {
2264 53886 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2265 53886 : nPos = nPos + sStrArray[i].getLength();
2266 53886 : i++;
2267 : }
2268 71360 : 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 85620 : sStrArray[i] = OUString(sKeyword[nTypeArray[i]]); // tTtT -> TTTT
2299 85620 : nPos = nPos + sStrArray[i].getLength();
2300 85620 : i++;
2301 85620 : 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 31980 : break; // of NUMBERFORMAT_DATE
2310 : case NUMBERFORMAT_TIME:
2311 60830 : while (i < nAnzStrings)
2312 : {
2313 : sal_Unicode cChar;
2314 :
2315 45134 : 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 22868 : switch( sStrArray[i][0] )
2324 : {
2325 : case '0':
2326 2128 : if ( Is100SecZero( i, bDecSep ) )
2327 : {
2328 2128 : bDecSep = true;
2329 2128 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
2330 2128 : OUString& rStr = sStrArray[i];
2331 2128 : i++;
2332 2128 : nPos = nPos + sStrArray[i].getLength();
2333 2128 : nCounter++;
2334 8240 : while (i < nAnzStrings &&
2335 1992 : sStrArray[i][0] == '0')
2336 : {
2337 1992 : rStr += sStrArray[i];
2338 1992 : nPos = nPos + sStrArray[i].getLength();
2339 1992 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2340 1992 : nAnzResStrings--;
2341 1992 : nCounter++;
2342 1992 : i++;
2343 : }
2344 : }
2345 : else
2346 : {
2347 0 : return nPos;
2348 : }
2349 2128 : break;
2350 : case '#':
2351 : case '?':
2352 0 : return nPos;
2353 : case '[':
2354 2128 : if (bThousand) // doppelt
2355 : {
2356 0 : return nPos;
2357 : }
2358 2128 : bThousand = true; // bei Time frei
2359 2128 : cChar = pChrCls->uppercase(rtl::OUString(NextChar(i)))[0];
2360 2128 : if ( cChar == cOldKeyH )
2361 : {
2362 2128 : 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 2128 : nPos = nPos + sStrArray[i].getLength();
2377 2128 : i++;
2378 2128 : break;
2379 : case ']':
2380 2128 : if (!bThousand) // kein [ vorher
2381 : {
2382 0 : return nPos;
2383 : }
2384 2128 : nPos = nPos + sStrArray[i].getLength();
2385 2128 : i++;
2386 2128 : break;
2387 : default:
2388 16484 : nPos = nPos + sStrArray[i].getLength();
2389 16484 : if ( sStrArray[i] == sOldTimeSep )
2390 : {
2391 12268 : nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
2392 12268 : if ( bConvertMode )
2393 : {
2394 1274 : sStrArray[i] = pLoc->getTimeSep();
2395 : }
2396 : }
2397 4216 : else if ( sStrArray[i] == sOldTime100SecSep )
2398 : {
2399 2124 : bDecSep = true;
2400 2124 : nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
2401 2124 : if ( bConvertMode )
2402 : {
2403 130 : sStrArray[i] = pLoc->getTime100SecSep();
2404 : }
2405 : }
2406 : else
2407 : {
2408 2092 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2409 : }
2410 16484 : i++;
2411 16484 : break;
2412 : }
2413 22868 : break;
2414 : case NF_SYMBOLTYPE_STRING:
2415 34 : nPos = nPos + sStrArray[i].getLength();
2416 34 : i++;
2417 34 : break;
2418 : case NF_KEY_AMPM: // AM/PM
2419 : case NF_KEY_AP: // A/P
2420 2100 : bExp = true; // missbraucht fuer A/P
2421 2100 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2422 2100 : nPos = nPos + sStrArray[i].getLength();
2423 2100 : i++;
2424 2100 : 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 20132 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2435 20132 : nPos = nPos + sStrArray[i].getLength();
2436 20132 : i++;
2437 20132 : 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 7848 : nCntPost = nCounter; // Zaehler der Nullen
2446 7848 : if (bExp)
2447 : {
2448 2100 : nCntExp = 1; // merkt AM/PM
2449 : }
2450 7848 : break; // of NUMBERFORMAT_TIME
2451 : case NUMBERFORMAT_DATETIME:
2452 26956 : while (i < nAnzStrings)
2453 : {
2454 : int nCalRet;
2455 22776 : switch (nTypeArray[i])
2456 : {
2457 : case NF_SYMBOLTYPE_BLANK:
2458 : case NF_SYMBOLTYPE_STAR:
2459 : case NF_SYMBOLTYPE_STRING:
2460 32 : nPos = nPos + sStrArray[i].getLength();
2461 32 : i++;
2462 32 : break;
2463 : case NF_SYMBOLTYPE_DEL:
2464 10314 : 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 10314 : 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 10314 : nPos = nPos + sStrArray[i].getLength();
2505 10314 : if (bTimePart)
2506 : {
2507 4066 : if ( sStrArray[i] == sOldTimeSep )
2508 : {
2509 3078 : nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
2510 3078 : if ( bConvertMode )
2511 : {
2512 90 : sStrArray[i] = pLoc->getTimeSep();
2513 : }
2514 : }
2515 988 : 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 988 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2527 : }
2528 : }
2529 : else
2530 : {
2531 6248 : if ( sStrArray[i] == sOldDateSep )
2532 : {
2533 4168 : nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
2534 4168 : if (bConvertMode)
2535 180 : sStrArray[i] = pFormatter->GetDateSep();
2536 : }
2537 : else
2538 : {
2539 2080 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2540 : }
2541 : }
2542 10314 : i++;
2543 10314 : break;
2544 : }
2545 : }
2546 10314 : break;
2547 : case NF_KEY_AMPM: // AM/PM
2548 : case NF_KEY_AP: // A/P
2549 988 : bTimePart = true;
2550 988 : bExp = true; // missbraucht fuer A/P
2551 988 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2552 988 : nPos = nPos + sStrArray[i].getLength();
2553 988 : i++;
2554 988 : 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 5176 : bTimePart = true;
2562 5176 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2563 5176 : nPos = nPos + sStrArray[i].getLength();
2564 5176 : i++;
2565 5176 : 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 6266 : bTimePart = false;
2593 6266 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2594 6266 : nPos = nPos + sStrArray[i].getLength();
2595 6266 : i++;
2596 6266 : 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 2090 : nCntPost = nCounter; // decimals (100th seconds)
2611 2090 : if (bExp)
2612 : {
2613 988 : nCntExp = 1; // merkt AM/PM
2614 : }
2615 2090 : break; // of NUMBERFORMAT_DATETIME
2616 : default:
2617 0 : break;
2618 : }
2619 88738 : if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
2620 : (nCntPre + nCntPost == 0 || nCntExp == 0))
2621 : {
2622 0 : return nPos;
2623 : }
2624 88738 : else if (eScannedType == NUMBERFORMAT_FRACTION && (nCntExp > 8 || nCntExp == 0))
2625 : {
2626 0 : return nPos;
2627 : }
2628 88738 : if (bThaiT && !GetNatNumModifier())
2629 : {
2630 0 : SetNatNumModifier(1);
2631 : }
2632 88738 : 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 35694 : for ( i=0; i < nAnzStrings; i++ )
2637 : {
2638 33268 : if ( nTypeArray[i] == NF_SYMBOLTYPE_STRING &&
2639 3276 : sStrArray[i][0] != '\"' )
2640 : {
2641 2462 : 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 2462 : OUString& rStr = sStrArray[i];
2675 2462 : sal_Int32 nLen = rStr.getLength();
2676 5644 : for ( sal_Int32 j = 0; j < nLen; j++ )
2677 : {
2678 3182 : 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 88738 : rString = "";
2689 88738 : i = 0;
2690 883722 : while (i < nAnzStrings)
2691 : {
2692 : sal_Int32 nStringPos;
2693 706246 : sal_Int32 nArrPos = 0;
2694 706246 : sal_uInt16 iPos = i;
2695 706246 : switch ( nTypeArray[i] )
2696 : {
2697 : case NF_SYMBOLTYPE_STRING :
2698 74016 : nStringPos = rString.getLength();
2699 178790 : do
2700 : {
2701 93088 : if (sStrArray[i].getLength() == 2 &&
2702 1742 : 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 720 : sal_Unicode c = sStrArray[i][1];
2711 :
2712 720 : switch (c)
2713 : {
2714 : case '+':
2715 : case '-':
2716 178 : rString += OUString(c);
2717 178 : break;
2718 : case ' ':
2719 : case '.':
2720 : case '/':
2721 524 : if (((eScannedType & NUMBERFORMAT_DATE) == 0) &&
2722 122 : (StringEqualsChar( pFormatter->GetNumThousandSep(), c) ||
2723 122 : StringEqualsChar( pFormatter->GetNumDecimalSep(), c) ||
2724 122 : (c == ' ' && StringEqualsChar( pFormatter->GetNumThousandSep(), cNonBreakingSpace))))
2725 : {
2726 0 : rString += sStrArray[i];
2727 : }
2728 194 : else if ((eScannedType & NUMBERFORMAT_DATE) &&
2729 36 : StringEqualsChar( pFormatter->GetDateSep(), c))
2730 : {
2731 0 : rString += sStrArray[i];
2732 : }
2733 182 : else if ((eScannedType & NUMBERFORMAT_TIME) &&
2734 12 : (StringEqualsChar( pLoc->getTimeSep(), c) ||
2735 12 : StringEqualsChar( pLoc->getTime100SecSep(), c)))
2736 : {
2737 0 : rString += sStrArray[i];
2738 : }
2739 158 : else if (eScannedType & NUMBERFORMAT_FRACTION)
2740 : {
2741 6 : rString += sStrArray[i];
2742 : }
2743 : else
2744 : {
2745 152 : rString += OUString(c);
2746 : }
2747 158 : break;
2748 : default:
2749 384 : rString += sStrArray[i];
2750 : }
2751 : }
2752 : else
2753 : {
2754 90626 : rString += sStrArray[i];
2755 : }
2756 91346 : if ( RemoveQuotes( sStrArray[i] ) > 0 )
2757 : {
2758 : // update currency up to quoted string
2759 1798 : 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 40 : OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
2765 80 : sStrArray[iPos].getLength()-nArrPos ) );
2766 40 : sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
2767 40 : 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 40 : nStringPos = rString.getLength();
2779 40 : if ( iPos == i )
2780 : {
2781 40 : nArrPos = sStrArray[iPos].getLength();
2782 : }
2783 : else
2784 : {
2785 0 : nArrPos = sStrArray[iPos].getLength() + sStrArray[i].getLength();
2786 40 : }
2787 : }
2788 : }
2789 91346 : if ( iPos != i )
2790 : {
2791 17330 : sStrArray[iPos] += sStrArray[i];
2792 17330 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2793 17330 : nAnzResStrings--;
2794 : }
2795 91346 : i++;
2796 : }
2797 87444 : while ( i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_STRING );
2798 :
2799 74016 : if ( i < nAnzStrings )
2800 : {
2801 70114 : i--; // enter switch on next symbol again
2802 : }
2803 74016 : if ( eScannedType == NUMBERFORMAT_CURRENCY && nStringPos < rString.getLength() )
2804 : {
2805 : // same as above, since last RemoveQuotes
2806 18726 : OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
2807 37452 : sStrArray[iPos].getLength()-nArrPos ) );
2808 18726 : sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
2809 18726 : if ( nCPos >= 0 )
2810 : {
2811 : const OUString& rCur = bConvertMode && bConvertSystemToSystem ?
2812 10336 : GetCurSymbol() : sOldCurSymbol;
2813 20672 : sStrArray[iPos] = sStrArray[iPos].replaceAt( nArrPos + nCPos,
2814 : sOldCurString.getLength(),
2815 31008 : rCur );
2816 : rString = rString.replaceAt( nStringPos + nCPos,
2817 10336 : sOldCurString.getLength(), rCur );
2818 18726 : }
2819 : }
2820 74016 : break;
2821 : case NF_SYMBOLTYPE_CURRENCY :
2822 14210 : rString += sStrArray[i];
2823 14210 : RemoveQuotes( sStrArray[i] );
2824 14210 : 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 196810 : break;
2840 : default:
2841 421210 : rString += sStrArray[i];
2842 : }
2843 706246 : i++;
2844 : }
2845 88738 : return 0;
2846 : }
2847 :
2848 105556 : sal_Int32 ImpSvNumberformatScan::RemoveQuotes( OUString& rStr )
2849 : {
2850 105556 : if ( rStr.getLength() > 1 )
2851 : {
2852 3852 : sal_Unicode c = rStr[0];
2853 3852 : sal_Int32 n = rStr.getLength() - 1;
2854 3852 : if ( c == '"' && rStr[n] == '"' )
2855 : {
2856 1078 : rStr = rStr.copy(1,n);
2857 1078 : return 2;
2858 : }
2859 2774 : else if ( c == '\\' )
2860 : {
2861 720 : rStr = rStr.copy(1);
2862 720 : return 1;
2863 : }
2864 : }
2865 103758 : return 0;
2866 : }
2867 :
2868 88738 : sal_Int32 ImpSvNumberformatScan::ScanFormat( OUString& rString )
2869 : {
2870 88738 : sal_Int32 res = Symbol_Division(rString); //lexikalische Analyse
2871 88738 : if (!res)
2872 : {
2873 88738 : res = ScanType(); // Erkennung des Formattyps
2874 : }
2875 88738 : if (!res)
2876 : {
2877 88738 : res = FinalScan( rString ); // Typabhaengige Endanalyse
2878 : }
2879 88738 : return res; // res = Kontrollposition
2880 : // res = 0 => Format ok
2881 : }
2882 :
2883 88738 : void ImpSvNumberformatScan::CopyInfo(ImpSvNumberformatInfo* pInfo, sal_uInt16 nAnz)
2884 : {
2885 : size_t i,j;
2886 88738 : j = 0;
2887 88738 : i = 0;
2888 855428 : while (i < nAnz && j < NF_MAX_FORMAT_SYMBOLS)
2889 : {
2890 677952 : if (nTypeArray[j] != NF_SYMBOLTYPE_EMPTY)
2891 : {
2892 509436 : pInfo->sStrArray[i] = sStrArray[j];
2893 509436 : pInfo->nTypeArray[i] = nTypeArray[j];
2894 509436 : i++;
2895 : }
2896 677952 : j++;
2897 : }
2898 88738 : pInfo->eScannedType = eScannedType;
2899 88738 : pInfo->bThousand = bThousand;
2900 88738 : pInfo->nThousand = nThousand;
2901 88738 : pInfo->nCntPre = nCntPre;
2902 88738 : pInfo->nCntPost = nCntPost;
2903 88738 : pInfo->nCntExp = nCntExp;
2904 88738 : }
2905 :
2906 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|