Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <stdlib.h>
22 : #include <comphelper/string.hxx>
23 : #include <tools/debug.hxx>
24 : #include <i18nlangtag/mslangid.hxx>
25 : #include <unotools/charclass.hxx>
26 : #include <unotools/localedatawrapper.hxx>
27 : #include <unotools/numberformatcodewrapper.hxx>
28 : #include <rtl/instance.hxx>
29 :
30 : #include <svl/zforlist.hxx>
31 : #include <svl/zformat.hxx>
32 : #include <unotools/digitgroupingiterator.hxx>
33 :
34 : #include "zforscan.hxx"
35 :
36 : #include <svl/nfsymbol.hxx>
37 : using namespace svt;
38 :
39 : const sal_Unicode cNonBreakingSpace = 0xA0;
40 :
41 : namespace
42 : {
43 : struct ImplEnglishColors
44 : {
45 6 : const OUString* operator()()
46 : {
47 : static const OUString aEnglishColors[NF_MAX_DEFAULT_COLORS] =
48 : {
49 : OUString( "BLACK" ),
50 : OUString( "BLUE" ),
51 : OUString( "GREEN" ),
52 : OUString( "CYAN" ),
53 : OUString( "RED" ),
54 : OUString( "MAGENTA" ),
55 : OUString( "BROWN" ),
56 : OUString( "GREY" ),
57 : OUString( "YELLOW" ),
58 : OUString( "WHITE" )
59 12 : };
60 6 : return &aEnglishColors[0];
61 : }
62 : };
63 :
64 : struct theEnglishColors
65 : : public rtl::StaticAggregate< const OUString, ImplEnglishColors> {};
66 :
67 : }
68 :
69 1451 : ImpSvNumberformatScan::ImpSvNumberformatScan( SvNumberFormatter* pFormatterP )
70 : {
71 1451 : pFormatter = pFormatterP;
72 1451 : bConvertMode = false;
73 1451 : bConvertSystemToSystem = false;
74 : //! All keywords MUST be UPPERCASE!
75 1451 : sKeyword[NF_KEY_E] = "E"; // Exponent
76 1451 : sKeyword[NF_KEY_AMPM] = "AM/PM"; // AM/PM
77 1451 : sKeyword[NF_KEY_AP] = "A/P"; // AM/PM short
78 1451 : sKeyword[NF_KEY_MI] = "M"; // Minute
79 1451 : sKeyword[NF_KEY_MMI] = "MM"; // Minute 02
80 1451 : sKeyword[NF_KEY_S] = "S"; // Second
81 1451 : sKeyword[NF_KEY_SS] = "SS"; // Second 02
82 1451 : sKeyword[NF_KEY_Q] = "Q"; // Quarter short 'Q'
83 1451 : sKeyword[NF_KEY_QQ] = "QQ"; // Quarter long
84 1451 : sKeyword[NF_KEY_NN] = "NN"; // Day of week short
85 1451 : sKeyword[NF_KEY_NNN] = "NNN"; // Day of week long
86 1451 : sKeyword[NF_KEY_NNNN] = "NNNN"; // Day of week long incl. separator
87 1451 : sKeyword[NF_KEY_WW] = "WW"; // Week of year
88 1451 : sKeyword[NF_KEY_CCC] = "CCC"; // Currency abbreviation
89 1451 : bKeywordsNeedInit = true; // locale dependent keywords
90 1451 : bCompatCurNeedInit = true; // locale dependent compatibility currency strings
91 :
92 1451 : StandardColor[0] = Color(COL_BLACK);
93 1451 : StandardColor[1] = Color(COL_LIGHTBLUE);
94 1451 : StandardColor[2] = Color(COL_LIGHTGREEN);
95 1451 : StandardColor[3] = Color(COL_LIGHTCYAN);
96 1451 : StandardColor[4] = Color(COL_LIGHTRED);
97 1451 : StandardColor[5] = Color(COL_LIGHTMAGENTA);
98 1451 : StandardColor[6] = Color(COL_BROWN);
99 1451 : StandardColor[7] = Color(COL_GRAY);
100 1451 : StandardColor[8] = Color(COL_YELLOW);
101 1451 : StandardColor[9] = Color(COL_WHITE);
102 :
103 1451 : pNullDate = new Date(30,12,1899);
104 1451 : nStandardPrec = 2;
105 :
106 1451 : sErrStr = "###";
107 1451 : Reset();
108 1451 : }
109 :
110 2758 : ImpSvNumberformatScan::~ImpSvNumberformatScan()
111 : {
112 1379 : delete pNullDate;
113 1379 : Reset();
114 1379 : }
115 :
116 11637 : void ImpSvNumberformatScan::ChangeIntl()
117 : {
118 11637 : bKeywordsNeedInit = true;
119 11637 : bCompatCurNeedInit = true;
120 : // may be initialized by InitSpecialKeyword()
121 11637 : sKeyword[NF_KEY_TRUE] = "";
122 11637 : sKeyword[NF_KEY_FALSE] = "";
123 11637 : }
124 :
125 22574 : void ImpSvNumberformatScan::InitSpecialKeyword( NfKeywordIndex eIdx ) const
126 : {
127 22574 : switch ( eIdx )
128 : {
129 : case NF_KEY_TRUE :
130 22580 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] =
131 22580 : pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getTrueWord() );
132 11290 : 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 11290 : break;
138 : case NF_KEY_FALSE :
139 22568 : ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] =
140 22568 : pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getFalseWord() );
141 11284 : 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 11284 : break;
147 : default:
148 : SAL_WARN( "svl.numbers", "InitSpecialKeyword: unknown request" );
149 : }
150 22574 : }
151 :
152 9521 : void ImpSvNumberformatScan::InitCompatCur() const
153 : {
154 9521 : ImpSvNumberformatScan* pThis = (ImpSvNumberformatScan*)this;
155 : // currency symbol for old style ("automatic") compatibility format codes
156 9521 : pFormatter->GetCompatibilityCurrency( pThis->sCurSymbol, pThis->sCurAbbrev );
157 : // currency symbol upper case
158 9521 : pThis->sCurString = pFormatter->GetCharClass()->uppercase( sCurSymbol );
159 9521 : bCompatCurNeedInit = false;
160 9521 : }
161 :
162 11886 : void ImpSvNumberformatScan::InitKeywords() const
163 : {
164 11886 : if ( !bKeywordsNeedInit )
165 14251 : return ;
166 9521 : ((ImpSvNumberformatScan*)this)->SetDependentKeywords();
167 9521 : bKeywordsNeedInit = false;
168 : }
169 :
170 : /** Extract the name of General, Standard, Whatever, ignoring leading modifiers
171 : such as [NatNum1]. */
172 9521 : static OUString lcl_extractStandardGeneralName( const OUString & rCode )
173 : {
174 9521 : OUString aStr;
175 9521 : const sal_Unicode* p = rCode.getStr();
176 9521 : const sal_Unicode* const pStop = p + rCode.getLength();
177 9521 : const sal_Unicode* pBeg = p; // name begins here
178 9521 : bool bMod = false;
179 9521 : bool bDone = false;
180 85714 : while (p < pStop && !bDone)
181 : {
182 66672 : 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 66672 : ++p;
205 66672 : if (bMod)
206 : {
207 0 : pBeg = p;
208 : }
209 : }
210 9521 : if (pBeg < p)
211 : {
212 9521 : aStr = rCode.copy( pBeg - rCode.getStr(), p - pBeg);
213 : }
214 9521 : return aStr;
215 : }
216 :
217 9521 : void ImpSvNumberformatScan::SetDependentKeywords()
218 : {
219 : using namespace ::com::sun::star;
220 : using namespace ::com::sun::star::uno;
221 :
222 9521 : const CharClass* pCharClass = pFormatter->GetCharClass();
223 9521 : 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 9521 : const LanguageTag& rLoadedLocale = pLocaleData->getLoadedLanguageTag();
227 9521 : LanguageType eLang = rLoadedLocale.getLanguageType( false);
228 : NumberFormatCodeWrapper aNumberFormatCode( pFormatter->GetComponentContext(),
229 19042 : rLoadedLocale.getLocale() );
230 :
231 19042 : i18n::NumberFormatCode aFormat = aNumberFormatCode.getFormatCode( NF_NUMBER_STANDARD );
232 9521 : sNameStandardFormat = lcl_extractStandardGeneralName( aFormat.Code);
233 9521 : sKeyword[NF_KEY_GENERAL] = pCharClass->uppercase( sNameStandardFormat );
234 :
235 : // preset new calendar keywords
236 9521 : sKeyword[NF_KEY_AAA] = "AAA";
237 9521 : sKeyword[NF_KEY_AAAA] = "AAAA";
238 9521 : sKeyword[NF_KEY_EC] = "E";
239 9521 : sKeyword[NF_KEY_EEC] = "EE";
240 9521 : sKeyword[NF_KEY_G] = "G";
241 9521 : sKeyword[NF_KEY_GG] = "GG";
242 9521 : sKeyword[NF_KEY_GGG] = "GGG";
243 9521 : sKeyword[NF_KEY_R] = "R";
244 9521 : 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 9521 : if (eLang == LANGUAGE_THAI)
249 : {
250 4 : sKeyword[NF_KEY_THAI_T] = "T";
251 : }
252 : else
253 : {
254 9517 : sKeyword[NF_KEY_THAI_T] = "t";
255 : }
256 9521 : 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 14 : sKeyword[NF_KEY_M] = "M"; // month 1
265 14 : sKeyword[NF_KEY_MM] = "MM"; // month 01
266 14 : sKeyword[NF_KEY_MMM] = "MMM"; // month Jan
267 14 : sKeyword[NF_KEY_MMMM] = "MMMM"; // month Januar
268 14 : sKeyword[NF_KEY_MMMMM] = "MMMMM"; // month J
269 14 : sKeyword[NF_KEY_H] = "H"; // hour 2
270 14 : sKeyword[NF_KEY_HH] = "HH"; // hour 02
271 14 : sKeyword[NF_KEY_D] = "T";
272 14 : sKeyword[NF_KEY_DD] = "TT";
273 14 : sKeyword[NF_KEY_DDD] = "TTT";
274 14 : sKeyword[NF_KEY_DDDD] = "TTTT";
275 14 : sKeyword[NF_KEY_YY] = "JJ";
276 14 : sKeyword[NF_KEY_YYYY] = "JJJJ";
277 14 : sKeyword[NF_KEY_BOOLEAN] = "LOGISCH";
278 14 : sKeyword[NF_KEY_COLOR] = "FARBE";
279 14 : sKeyword[NF_KEY_BLACK] = "SCHWARZ";
280 14 : sKeyword[NF_KEY_BLUE] = "BLAU";
281 14 : sKeyword[NF_KEY_GREEN] = OUString( "GR" "\xDC" "N", 4, RTL_TEXTENCODING_ISO_8859_1 );
282 14 : sKeyword[NF_KEY_CYAN] = "CYAN";
283 14 : sKeyword[NF_KEY_RED] = "ROT";
284 14 : sKeyword[NF_KEY_MAGENTA] = "MAGENTA";
285 14 : sKeyword[NF_KEY_BROWN] = "BRAUN";
286 14 : sKeyword[NF_KEY_GREY] = "GRAU";
287 14 : sKeyword[NF_KEY_YELLOW] = "GELB";
288 14 : sKeyword[NF_KEY_WHITE] = "WEISS";
289 14 : break;
290 : default:
291 : // day
292 9507 : 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 3 : sKeyword[NF_KEY_D] = "J";
312 3 : sKeyword[NF_KEY_DD] = "JJ";
313 3 : sKeyword[NF_KEY_DDD] = "JJJ";
314 3 : sKeyword[NF_KEY_DDDD] = "JJJJ";
315 3 : 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 9504 : sKeyword[NF_KEY_D] = "D";
324 9504 : sKeyword[NF_KEY_DD] = "DD";
325 9504 : sKeyword[NF_KEY_DDD] = "DDD";
326 9504 : sKeyword[NF_KEY_DDDD] = "DDDD";
327 : }
328 : // month
329 9507 : 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 9507 : sKeyword[NF_KEY_M] = "M";
340 9507 : sKeyword[NF_KEY_MM] = "MM";
341 9507 : sKeyword[NF_KEY_MMM] = "MMM";
342 9507 : sKeyword[NF_KEY_MMMM] = "MMMM";
343 9507 : sKeyword[NF_KEY_MMMMM] = "MMMMM";
344 : }
345 : // year
346 9507 : 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 3 : sKeyword[NF_KEY_YY] = "AA";
379 3 : sKeyword[NF_KEY_YYYY] = "AAAA";
380 : // must exchange the day of week name code, same as Xcl
381 3 : sKeyword[NF_KEY_AAA] = "OOO";
382 3 : sKeyword[NF_KEY_AAAA] = "OOOO";
383 3 : 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 9504 : sKeyword[NF_KEY_YY] = "YY";
395 9504 : sKeyword[NF_KEY_YYYY] = "YYYY";
396 : }
397 : // hour
398 9507 : 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 4 : sKeyword[NF_KEY_H] = "T";
413 4 : sKeyword[NF_KEY_HH] = "TT";
414 4 : break;
415 : default:
416 9503 : sKeyword[NF_KEY_H] = "H";
417 9503 : sKeyword[NF_KEY_HH] = "HH";
418 : }
419 : // boolean
420 9507 : sKeyword[NF_KEY_BOOLEAN] = "BOOLEAN";
421 : // colours
422 9507 : sKeyword[NF_KEY_COLOR] = "COLOR";
423 9507 : sKeyword[NF_KEY_BLACK] = "BLACK";
424 9507 : sKeyword[NF_KEY_BLUE] = "BLUE";
425 9507 : sKeyword[NF_KEY_GREEN] = "GREEN";
426 9507 : sKeyword[NF_KEY_CYAN] = "CYAN";
427 9507 : sKeyword[NF_KEY_RED] = "RED";
428 9507 : sKeyword[NF_KEY_MAGENTA] = "MAGENTA";
429 9507 : sKeyword[NF_KEY_BROWN] = "BROWN";
430 9507 : sKeyword[NF_KEY_GREY] = "GREY";
431 9507 : sKeyword[NF_KEY_YELLOW] = "YELLOW";
432 9507 : sKeyword[NF_KEY_WHITE] = "WHITE";
433 9507 : break;
434 : }
435 :
436 : // boolean keyords
437 9521 : InitSpecialKeyword( NF_KEY_TRUE );
438 9521 : InitSpecialKeyword( NF_KEY_FALSE );
439 :
440 : // compatibility currency strings
441 19042 : InitCompatCur();
442 9521 : }
443 :
444 1378 : void ImpSvNumberformatScan::ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear)
445 : {
446 1378 : if ( pNullDate )
447 1378 : *pNullDate = Date(nDay, nMonth, nYear);
448 : else
449 0 : pNullDate = new Date(nDay, nMonth, nYear);
450 1378 : }
451 :
452 2134 : void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec)
453 : {
454 2134 : nStandardPrec = nPrec;
455 2134 : }
456 :
457 11638 : Color* ImpSvNumberformatScan::GetColor(OUString& sStr)
458 : {
459 11638 : OUString sString = pFormatter->GetCharClass()->uppercase(sStr);
460 11638 : const NfKeywordTable & rKeyword = GetKeywords();
461 11638 : size_t i = 0;
462 76074 : while (i < NF_MAX_DEFAULT_COLORS && sString != rKeyword[NF_KEY_FIRSTCOLOR+i] )
463 : {
464 52798 : i++;
465 : }
466 11638 : if ( i >= NF_MAX_DEFAULT_COLORS )
467 : {
468 1041 : const OUString* pEnglishColors = theEnglishColors::get();
469 1041 : size_t j = 0;
470 12492 : while ( j < NF_MAX_DEFAULT_COLORS && sString != pEnglishColors[j] )
471 : {
472 10410 : ++j;
473 : }
474 1041 : if ( j < NF_MAX_DEFAULT_COLORS )
475 : {
476 0 : i = j;
477 : }
478 : }
479 :
480 11638 : Color* pResult = NULL;
481 11638 : if (i >= NF_MAX_DEFAULT_COLORS)
482 : {
483 1041 : const OUString& rColorWord = rKeyword[NF_KEY_COLOR];
484 1041 : if (sString.startsWith(rColorWord))
485 : {
486 0 : sal_Int32 nPos = rColorWord.getLength();
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 10597 : sStr = "";
515 10597 : if (bConvertMode)
516 : {
517 405 : pFormatter->ChangeIntl(eNewLnge);
518 405 : sStr = GetKeywords()[NF_KEY_FIRSTCOLOR+i]; // red -> rot
519 405 : pFormatter->ChangeIntl(eTmpLnge);
520 : }
521 : else
522 : {
523 10192 : sStr = rKeyword[NF_KEY_FIRSTCOLOR+i];
524 : }
525 10597 : pResult = &(StandardColor[i]);
526 : }
527 11638 : return pResult;
528 : }
529 :
530 363954 : short ImpSvNumberformatScan::GetKeyWord( const OUString& sSymbol, sal_Int32 nPos )
531 : {
532 363954 : OUString sString = pFormatter->GetCharClass()->uppercase( sSymbol, nPos, sSymbol.getLength() - nPos );
533 363954 : const NfKeywordTable & rKeyword = GetKeywords();
534 : // #77026# for the Xcl perverts: the GENERAL keyword is recognized anywhere
535 363954 : if ( sString.startsWith( rKeyword[NF_KEY_GENERAL] ))
536 : {
537 1704 : return NF_KEY_GENERAL;
538 : }
539 : //! MUST be a reverse search to find longer strings first
540 362250 : short i = NF_KEYWORD_ENTRIES_COUNT-1;
541 362250 : bool bFound = false;
542 3861599 : for ( ; i > NF_KEY_LASTKEYWORD_SO5; --i )
543 : {
544 3540330 : bFound = sString.startsWith(rKeyword[i]);
545 3540330 : if ( bFound )
546 : {
547 40981 : break;
548 : }
549 : }
550 : // new keywords take precedence over old keywords
551 362250 : if ( !bFound )
552 : {
553 : // skip the gap of colors et al between new and old keywords and search on
554 321269 : i = NF_KEY_LASTKEYWORD;
555 6104387 : while ( i > 0 && sString.indexOf(rKeyword[i]) != 0 )
556 : {
557 5461849 : i--;
558 : }
559 321269 : 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 6590 : short j = i - 1;
564 26360 : while ( j > 0 && sString.indexOf(rKeyword[j]) != 0 )
565 : {
566 13180 : j--;
567 : }
568 6590 : if ( j && rKeyword[j].getLength() > rKeyword[i].getLength() )
569 : {
570 6590 : return j;
571 : }
572 : }
573 : }
574 : // The Thai T NatNum modifier during Xcl import.
575 422107 : if (i == 0 && bConvertMode &&
576 3080 : sString[0] == 'T' &&
577 355660 : eTmpLnge == LANGUAGE_ENGLISH_US &&
578 0 : MsLangId::getRealLanguage( eNewLnge) == LANGUAGE_THAI)
579 : {
580 0 : i = NF_KEY_THAI_T;
581 : }
582 355660 : return i; // 0 => not found
583 : }
584 :
585 : /**
586 : * Next_Symbol
587 : *
588 : * Splits up the input for further processing (by the Turing machine).
589 : *
590 : * Starting state = SsStar
591 : *
592 : * ---------------+-------------------+---------------------------+---------------
593 : * Old state | Character read | Event | New state
594 : * ---------------+-------------------+---------------------------+---------------
595 : * SsStart | Character | Symbol = Character | SsGetWord
596 : * | " | Type = String | SsGetString
597 : * | \ | Type = String | SsGetChar
598 : * | * | Type = Star | SsGetStar
599 : * | _ | Type = Blank | SsGetBlank
600 : * | @ # 0 ? / . , % [ | Symbol = Character; |
601 : * | ] ' Blank | Type = Control character | SsStop
602 : * | $ - + ( ) : | Type = String; |
603 : * | Else | Symbol = Character | SsStop
604 : * ---------------|-------------------+---------------------------+---------------
605 : * SsGetChar | Else | Symbol = Character | SsStop
606 : * ---------------+-------------------+---------------------------+---------------
607 : * GetString | " | | SsStop
608 : * | Else | Symbol += Character | GetString
609 : * ---------------+-------------------+---------------------------+---------------
610 : * SsGetWord | Character | Symbol += Character |
611 : * | + - (E+ E-)| Symbol += Character | SsStop
612 : * | / (AM/PM)| Symbol += Character |
613 : * | Else | Pos--, if Key Type = Word | SsStop
614 : * ---------------+-------------------+---------------------------+---------------
615 : * SsGetStar | Else | Symbol += Character | SsStop
616 : * | | Mark special case * |
617 : * ---------------+-------------------+---------------------------+---------------
618 : * SsGetBlank | Else | Symbol + =Character | SsStop
619 : * | | Mark special case _ |
620 : * ---------------------------------------------------------------+--------------
621 : *
622 : * If we recognize a keyword in the state SsGetWord (even as the symbol's start text)
623 : * we write back the rest of the characters!
624 : */
625 :
626 : enum ScanState
627 : {
628 : SsStop = 0,
629 : SsStart = 1,
630 : SsGetChar = 2,
631 : SsGetString = 3,
632 : SsGetWord = 4,
633 : SsGetStar = 5,
634 : SsGetBlank = 6
635 : };
636 :
637 1243782 : short ImpSvNumberformatScan::Next_Symbol( const OUString& rStr,
638 : sal_Int32& nPos,
639 : OUString& sSymbol )
640 : {
641 1243782 : if ( bKeywordsNeedInit )
642 : {
643 0 : InitKeywords();
644 : }
645 1243782 : const CharClass* pChrCls = pFormatter->GetCharClass();
646 1243782 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
647 1243782 : const sal_Int32 nStart = nPos;
648 1243782 : short eType = 0;
649 1243782 : ScanState eState = SsStart;
650 1243782 : sSymbol = "";
651 3809300 : while ( nPos < rStr.getLength() && eState != SsStop )
652 : {
653 1321976 : sal_Unicode cToken = rStr[nPos++];
654 1321976 : switch (eState)
655 : {
656 : case SsStart:
657 : // Fetch any currency longer than one character and don't get
658 : // confused later on by "E/" or other combinations of letters
659 : // and meaningful symbols. Necessary for old automatic currency.
660 : // #96158# But don't do it if we're starting a "[...]" section,
661 : // for example a "[$...]" new currency symbol to not parse away
662 : // "$U" (symbol) of "[$UYU]" (abbreviation).
663 3003559 : if ( nCurrPos >= 0 && sCurString.getLength() > 1 &&
664 1252478 : nPos-1 + sCurString.getLength() <= rStr.getLength() &&
665 5524 : !(nPos > 1 && rStr[nPos-2] == '[') )
666 : {
667 2762 : OUString aTest = pChrCls->uppercase( rStr.copy( nPos-1, sCurString.getLength() ) );
668 2762 : if ( aTest == sCurString )
669 : {
670 240 : sSymbol = rStr.copy( --nPos, sCurString.getLength() );
671 240 : nPos = nPos + sSymbol.getLength();
672 240 : eState = SsStop;
673 240 : eType = NF_SYMBOLTYPE_STRING;
674 240 : return eType;
675 2522 : }
676 : }
677 1243542 : switch (cToken)
678 : {
679 : case '#':
680 : case '0':
681 : case '?':
682 : case '%':
683 : case '@':
684 : case '[':
685 : case ']':
686 : case ',':
687 : case '.':
688 : case '/':
689 : case '\'':
690 : case ' ':
691 : case ':':
692 : case '-':
693 784526 : eType = NF_SYMBOLTYPE_DEL;
694 784526 : sSymbol += OUString(cToken);
695 784526 : eState = SsStop;
696 784526 : break;
697 : case '*':
698 7760 : eType = NF_SYMBOLTYPE_STAR;
699 7760 : sSymbol += OUString(cToken);
700 7760 : eState = SsGetStar;
701 7760 : break;
702 : case '_':
703 6487 : eType = NF_SYMBOLTYPE_BLANK;
704 6487 : sSymbol += OUString(cToken);
705 6487 : eState = SsGetBlank;
706 6487 : break;
707 : case '"':
708 1786 : eType = NF_SYMBOLTYPE_STRING;
709 1786 : eState = SsGetString;
710 1786 : sSymbol += OUString(cToken);
711 1786 : break;
712 : case '\\':
713 1275 : eType = NF_SYMBOLTYPE_STRING;
714 1275 : eState = SsGetChar;
715 1275 : sSymbol += OUString(cToken);
716 1275 : break;
717 : case '$':
718 : case '+':
719 : case '(':
720 : case ')':
721 71481 : eType = NF_SYMBOLTYPE_STRING;
722 71481 : eState = SsStop;
723 71481 : sSymbol += OUString(cToken);
724 71481 : break;
725 : default :
726 1110681 : if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cToken) ||
727 740454 : StringEqualsChar( pFormatter->GetNumThousandSep(), cToken) ||
728 740442 : StringEqualsChar( pFormatter->GetDateSep(), cToken) ||
729 1110657 : StringEqualsChar( pLoc->getTimeSep(), cToken) ||
730 370215 : StringEqualsChar( pLoc->getTime100SecSep(), cToken))
731 : {
732 : // Another separator than pre-known ASCII
733 12 : eType = NF_SYMBOLTYPE_DEL;
734 12 : sSymbol += OUString(cToken);
735 12 : eState = SsStop;
736 : }
737 370215 : else if ( pChrCls->isLetter( rStr, nPos-1 ) )
738 : {
739 302642 : short nTmpType = GetKeyWord( rStr, nPos-1 );
740 302642 : if ( nTmpType )
741 : {
742 265691 : bool bCurrency = false;
743 : // "Automatic" currency may start with keyword,
744 : // like "R" (Rand) and 'R' (era)
745 531904 : if ( nCurrPos >= 0 &&
746 266213 : nPos-1 + sCurString.getLength() <= rStr.getLength() &&
747 522 : sCurString.indexOf( sKeyword[nTmpType] ) == 0 )
748 : {
749 0 : OUString aTest = pChrCls->uppercase( rStr.copy( nPos-1, sCurString.getLength() ) );
750 0 : if ( aTest == sCurString )
751 : {
752 0 : bCurrency = true;
753 0 : }
754 : }
755 265691 : if ( bCurrency )
756 : {
757 0 : eState = SsGetWord;
758 0 : sSymbol += OUString(cToken);
759 : }
760 : else
761 : {
762 265691 : eType = nTmpType;
763 265691 : sal_Int32 nLen = sKeyword[eType].getLength();
764 265691 : sSymbol = rStr.copy( nPos-1, nLen );
765 265691 : if ( eType == NF_KEY_E || IsAmbiguousE( eType ) )
766 : {
767 21881 : sal_Unicode cNext = rStr[nPos];
768 21881 : switch ( cNext )
769 : {
770 : case '+' :
771 : case '-' : // E+ E- combine to one symbol
772 3404 : sSymbol += OUString(cNext);
773 3404 : eType = NF_KEY_E;
774 3404 : nPos++;
775 3404 : break;
776 : case '0' :
777 : case '#' : // scientific E without sign
778 0 : eType = NF_KEY_E;
779 0 : break;
780 : }
781 : }
782 265691 : nPos--;
783 265691 : nPos = nPos + nLen;
784 265691 : eState = SsStop;
785 : }
786 : }
787 : else
788 : {
789 36951 : eState = SsGetWord;
790 36951 : sSymbol += OUString(cToken);
791 : }
792 : }
793 : else
794 : {
795 67573 : eType = NF_SYMBOLTYPE_STRING;
796 67573 : eState = SsStop;
797 67573 : sSymbol += OUString(cToken);
798 : }
799 370227 : break;
800 : }
801 1243542 : break;
802 : case SsGetChar:
803 1275 : sSymbol += OUString(cToken);
804 1275 : eState = SsStop;
805 1275 : break;
806 : case SsGetString:
807 4060 : if (cToken == '"')
808 : {
809 1786 : eState = SsStop;
810 : }
811 4060 : sSymbol += OUString(cToken);
812 4060 : break;
813 : case SsGetWord:
814 58612 : if ( pChrCls->isLetter( rStr, nPos-1 ) )
815 : {
816 58232 : short nTmpType = GetKeyWord( rStr, nPos-1 );
817 58232 : if ( nTmpType )
818 : {
819 : // beginning of keyword, stop scan and put back
820 34896 : eType = NF_SYMBOLTYPE_STRING;
821 34896 : eState = SsStop;
822 34896 : nPos--;
823 : }
824 : else
825 : {
826 23336 : sSymbol += OUString(cToken);
827 : }
828 : }
829 : else
830 : {
831 380 : bool bDontStop = false;
832 : sal_Unicode cNext;
833 380 : switch (cToken)
834 : {
835 : case '/': // AM/PM, A/P
836 0 : cNext = rStr[nPos];
837 0 : if ( cNext == 'P' || cNext == 'p' )
838 : {
839 0 : sal_Int32 nLen = sSymbol.getLength();
840 0 : if ( 1 <= nLen &&
841 0 : (sSymbol[0] == 'A' || sSymbol[0] == 'a') &&
842 0 : (nLen == 1 ||
843 0 : (nLen == 2 && (sSymbol[1] == 'M' || sSymbol[1] == 'm')
844 0 : && (rStr[nPos + 1] == 'M' || rStr[nPos + 1] == 'm'))))
845 : {
846 0 : sSymbol += OUString(cToken);
847 0 : bDontStop = true;
848 : }
849 : }
850 0 : break;
851 : }
852 : // anything not recognized will stop the scan
853 380 : if ( eState != SsStop && !bDontStop )
854 : {
855 380 : eState = SsStop;
856 380 : nPos--;
857 380 : eType = NF_SYMBOLTYPE_STRING;
858 : }
859 : }
860 58612 : break;
861 : case SsGetStar:
862 7760 : eState = SsStop;
863 7760 : sSymbol += OUString(cToken);
864 7760 : nRepPos = (nPos - nStart) - 1; // everytime > 0!!
865 7760 : break;
866 : case SsGetBlank:
867 6487 : eState = SsStop;
868 6487 : sSymbol += OUString(cToken);
869 6487 : break;
870 : default:
871 0 : break;
872 : } // of switch
873 : } // of while
874 1243542 : if (eState == SsGetWord)
875 : {
876 1675 : eType = NF_SYMBOLTYPE_STRING;
877 : }
878 1243542 : return eType;
879 : }
880 :
881 148244 : sal_Int32 ImpSvNumberformatScan::Symbol_Division(const OUString& rString)
882 : {
883 148244 : nCurrPos = -1;
884 : // Do we have some sort of currency?
885 148244 : OUString sString = pFormatter->GetCharClass()->uppercase(rString);
886 148244 : sal_Int32 nCPos = 0;
887 445014 : while (nCPos >= 0)
888 : {
889 148526 : nCPos = sString.indexOf(GetCurString(),nCPos);
890 148526 : if (nCPos >= 0)
891 : {
892 : // In Quotes?
893 41289 : sal_Int32 nQ = SvNumberformat::GetQuoteEnd( sString, nCPos );
894 41289 : if ( nQ < 0 )
895 : {
896 : sal_Unicode c;
897 114621 : if ( nCPos == 0 ||
898 32543 : ((c = sString[nCPos-1]) != '"'
899 32543 : && c != '\\') ) // dm can be protected by "dm \d
900 : {
901 41007 : nCurrPos = nCPos;
902 41007 : nCPos = -1;
903 : }
904 : else
905 : {
906 64 : nCPos++; // Continue search
907 : }
908 : }
909 : else
910 : {
911 218 : nCPos = nQ + 1; // Continue search
912 : }
913 : }
914 : }
915 148244 : nAnzStrings = 0;
916 148244 : bool bStar = false; // Is set on detecting '*'
917 148244 : Reset();
918 :
919 148244 : sal_Int32 nPos = 0;
920 148244 : const sal_Int32 nLen = rString.getLength();
921 1540270 : while (nPos < nLen && nAnzStrings < NF_MAX_FORMAT_SYMBOLS)
922 : {
923 1243782 : nTypeArray[nAnzStrings] = Next_Symbol(rString, nPos, sStrArray[nAnzStrings]);
924 1243782 : if (nTypeArray[nAnzStrings] == NF_SYMBOLTYPE_STAR)
925 : { // Monitoring the '*'
926 7760 : if (bStar)
927 : {
928 0 : return nPos; // Error: double '*'
929 : }
930 : else
931 : {
932 7760 : bStar = true;
933 : }
934 : }
935 1243782 : nAnzStrings++;
936 : }
937 :
938 148244 : return 0; // 0 => ok
939 : }
940 :
941 1061241 : void ImpSvNumberformatScan::SkipStrings(sal_uInt16& i, sal_Int32& nPos)
942 : {
943 2171061 : while (i < nAnzStrings && ( nTypeArray[i] == NF_SYMBOLTYPE_STRING
944 927244 : || nTypeArray[i] == NF_SYMBOLTYPE_BLANK
945 920757 : || nTypeArray[i] == NF_SYMBOLTYPE_STAR) )
946 : {
947 48579 : nPos = nPos + sStrArray[i].getLength();
948 48579 : i++;
949 : }
950 1061241 : }
951 :
952 42332 : sal_uInt16 ImpSvNumberformatScan::PreviousKeyword(sal_uInt16 i)
953 : {
954 42332 : short res = 0;
955 42332 : if (i > 0 && i < nAnzStrings)
956 : {
957 27988 : i--;
958 90788 : while (i > 0 && nTypeArray[i] <= 0)
959 : {
960 34812 : i--;
961 : }
962 27988 : if (nTypeArray[i] > 0)
963 : {
964 27985 : res = nTypeArray[i];
965 : }
966 : }
967 42332 : return res;
968 : }
969 :
970 35531 : sal_uInt16 ImpSvNumberformatScan::NextKeyword(sal_uInt16 i)
971 : {
972 35531 : short res = 0;
973 35531 : if (i < nAnzStrings-1)
974 : {
975 33623 : i++;
976 97381 : while (i < nAnzStrings-1 && nTypeArray[i] <= 0)
977 : {
978 30135 : i++;
979 : }
980 33623 : if (nTypeArray[i] > 0)
981 : {
982 33605 : res = nTypeArray[i];
983 : }
984 : }
985 35531 : return res;
986 : }
987 :
988 34 : short ImpSvNumberformatScan::PreviousType( sal_uInt16 i )
989 : {
990 34 : if ( i > 0 && i < nAnzStrings )
991 : {
992 34 : do
993 : {
994 34 : i--;
995 : }
996 34 : while ( i > 0 && nTypeArray[i] == NF_SYMBOLTYPE_EMPTY );
997 34 : return nTypeArray[i];
998 : }
999 0 : return 0;
1000 : }
1001 :
1002 88216 : sal_Unicode ImpSvNumberformatScan::PreviousChar(sal_uInt16 i)
1003 : {
1004 88216 : sal_Unicode res = ' ';
1005 88216 : if (i > 0 && i < nAnzStrings)
1006 : {
1007 73872 : i--;
1008 211126 : while (i > 0 &&
1009 126628 : ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
1010 126564 : nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
1011 126508 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1012 63254 : nTypeArray[i] == NF_SYMBOLTYPE_BLANK ))
1013 : {
1014 64 : i--;
1015 : }
1016 73872 : if (sStrArray[i].getLength() > 0)
1017 : {
1018 73872 : res = sStrArray[i][sStrArray[i].getLength()-1];
1019 : }
1020 : }
1021 88216 : return res;
1022 : }
1023 :
1024 59651 : sal_Unicode ImpSvNumberformatScan::NextChar(sal_uInt16 i)
1025 : {
1026 59651 : sal_Unicode res = ' ';
1027 59651 : if (i < nAnzStrings-1)
1028 : {
1029 59651 : i++;
1030 178917 : while (i < nAnzStrings-1 &&
1031 119230 : ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
1032 119230 : nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
1033 119230 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1034 59615 : nTypeArray[i] == NF_SYMBOLTYPE_BLANK))
1035 : {
1036 0 : i++;
1037 : }
1038 59651 : if (sStrArray[i].getLength() > 0)
1039 : {
1040 59651 : res = sStrArray[i][0];
1041 : }
1042 : }
1043 59651 : return res;
1044 : }
1045 :
1046 8 : bool ImpSvNumberformatScan::IsLastBlankBeforeFrac(sal_uInt16 i)
1047 : {
1048 8 : bool res = true;
1049 8 : if (i < nAnzStrings-1)
1050 : {
1051 8 : bool bStop = false;
1052 8 : i++;
1053 28 : while (i < nAnzStrings-1 && !bStop)
1054 : {
1055 12 : i++;
1056 24 : if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
1057 12 : sStrArray[i][0] == '/')
1058 : {
1059 8 : bStop = true;
1060 : }
1061 8 : else if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
1062 4 : sStrArray[i][0] == ' ')
1063 : {
1064 0 : res = false;
1065 : }
1066 : }
1067 8 : if (!bStop) // no '/'{
1068 : {
1069 0 : res = false;
1070 : }
1071 : }
1072 : else
1073 : {
1074 0 : res = false; // no '/' any more
1075 : }
1076 8 : return res;
1077 : }
1078 :
1079 151074 : void ImpSvNumberformatScan::Reset()
1080 : {
1081 151074 : nAnzStrings = 0;
1082 151074 : nAnzResStrings = 0;
1083 151074 : eScannedType = NUMBERFORMAT_UNDEFINED;
1084 151074 : nRepPos = 0;
1085 151074 : bExp = false;
1086 151074 : bThousand = false;
1087 151074 : nThousand = 0;
1088 151074 : bDecSep = false;
1089 151074 : nDecPos = (sal_uInt16)-1;
1090 151074 : nExpPos = (sal_uInt16)-1;
1091 151074 : nBlankPos = (sal_uInt16)-1;
1092 151074 : nCntPre = 0;
1093 151074 : nCntPost = 0;
1094 151074 : nCntExp = 0;
1095 151074 : bFrac = false;
1096 151074 : bBlank = false;
1097 151074 : nNatNumModifier = 0;
1098 151074 : }
1099 :
1100 10271 : bool ImpSvNumberformatScan::Is100SecZero( sal_uInt16 i, bool bHadDecSep )
1101 : {
1102 10271 : sal_uInt16 nIndexPre = PreviousKeyword( i );
1103 20542 : return (nIndexPre == NF_KEY_S || nIndexPre == NF_KEY_SS) &&
1104 6 : (bHadDecSep ||
1105 10277 : ( i > 0 && nTypeArray[i-1] == NF_SYMBOLTYPE_STRING));
1106 : // SS"any"00 take "any" as a valid decimal separator
1107 : }
1108 :
1109 148244 : sal_Int32 ImpSvNumberformatScan::ScanType()
1110 : {
1111 148244 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1112 :
1113 148244 : sal_Int32 nPos = 0;
1114 148244 : sal_uInt16 i = 0;
1115 : short eNewType;
1116 148244 : bool bMatchBracket = false;
1117 148244 : bool bHaveGeneral = false; // if General/Standard encountered
1118 :
1119 148244 : SkipStrings(i, nPos);
1120 1209485 : while (i < nAnzStrings)
1121 : {
1122 912997 : if (nTypeArray[i] > 0)
1123 : { // keyword
1124 : sal_uInt16 nIndexPre;
1125 : sal_uInt16 nIndexNex;
1126 : sal_Unicode cChar;
1127 :
1128 215935 : switch (nTypeArray[i])
1129 : {
1130 : case NF_KEY_E: // E
1131 3404 : eNewType = NUMBERFORMAT_SCIENTIFIC;
1132 3404 : break;
1133 : case NF_KEY_AMPM: // AM,A,PM,P
1134 : case NF_KEY_AP:
1135 : case NF_KEY_H: // H
1136 : case NF_KEY_HH: // HH
1137 : case NF_KEY_S: // S
1138 : case NF_KEY_SS: // SS
1139 29915 : eNewType = NUMBERFORMAT_TIME;
1140 29915 : break;
1141 : case NF_KEY_M: // M
1142 : case NF_KEY_MM: // MM
1143 : // minute or month
1144 32061 : nIndexPre = PreviousKeyword(i);
1145 32061 : nIndexNex = NextKeyword(i);
1146 32061 : cChar = PreviousChar(i);
1147 32061 : if (nIndexPre == NF_KEY_H || // H
1148 17989 : nIndexPre == NF_KEY_HH || // HH
1149 17989 : nIndexNex == NF_KEY_S || // S
1150 16045 : nIndexNex == NF_KEY_SS || // SS
1151 : cChar == '[' ) // [M
1152 : {
1153 16016 : eNewType = NUMBERFORMAT_TIME;
1154 16016 : nTypeArray[i] -= 2; // 6 -> 4, 7 -> 5
1155 : }
1156 : else
1157 : {
1158 16045 : eNewType = NUMBERFORMAT_DATE;
1159 : }
1160 32061 : break;
1161 : case NF_KEY_MMM: // MMM
1162 : case NF_KEY_MMMM: // MMMM
1163 : case NF_KEY_MMMMM: // MMMMM
1164 : case NF_KEY_Q: // Q
1165 : case NF_KEY_QQ: // QQ
1166 : case NF_KEY_D: // D
1167 : case NF_KEY_DD: // DD
1168 : case NF_KEY_DDD: // DDD
1169 : case NF_KEY_DDDD: // DDDD
1170 : case NF_KEY_YY: // YY
1171 : case NF_KEY_YYYY: // YYYY
1172 : case NF_KEY_NN: // NN
1173 : case NF_KEY_NNN: // NNN
1174 : case NF_KEY_NNNN: // NNNN
1175 : case NF_KEY_WW : // WW
1176 : case NF_KEY_AAA : // AAA
1177 : case NF_KEY_AAAA : // AAAA
1178 : case NF_KEY_EC : // E
1179 : case NF_KEY_EEC : // EE
1180 : case NF_KEY_G : // G
1181 : case NF_KEY_GG : // GG
1182 : case NF_KEY_GGG : // GGG
1183 : case NF_KEY_R : // R
1184 : case NF_KEY_RR : // RR
1185 147187 : eNewType = NUMBERFORMAT_DATE;
1186 147187 : break;
1187 : case NF_KEY_CCC: // CCC
1188 1664 : eNewType = NUMBERFORMAT_CURRENCY;
1189 1664 : break;
1190 : case NF_KEY_GENERAL: // Standard
1191 1704 : eNewType = NUMBERFORMAT_NUMBER;
1192 1704 : bHaveGeneral = true;
1193 1704 : break;
1194 : default:
1195 0 : eNewType = NUMBERFORMAT_UNDEFINED;
1196 0 : break;
1197 : }
1198 : }
1199 : else
1200 : { // control character
1201 697062 : switch ( sStrArray[i][0] )
1202 : {
1203 : case '#':
1204 : case '?':
1205 192215 : eNewType = NUMBERFORMAT_NUMBER;
1206 192215 : break;
1207 : case '0':
1208 151316 : if ( (eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME )
1209 : {
1210 6801 : if ( Is100SecZero( i, bDecSep ) )
1211 : {
1212 6801 : bDecSep = true; // subsequent 0's
1213 6801 : eNewType = NUMBERFORMAT_TIME;
1214 : }
1215 : else
1216 : {
1217 0 : return nPos; // Error
1218 : }
1219 : }
1220 : else
1221 : {
1222 144515 : eNewType = NUMBERFORMAT_NUMBER;
1223 : }
1224 151316 : break;
1225 : case '%':
1226 3339 : eNewType = NUMBERFORMAT_PERCENT;
1227 3339 : break;
1228 : case '/':
1229 28500 : eNewType = NUMBERFORMAT_FRACTION;
1230 28500 : break;
1231 : case '[':
1232 131385 : if ( i < nAnzStrings-1 &&
1233 84120 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1234 40325 : sStrArray[i+1][0] == '$' )
1235 : { // as of SV_NUMBERFORMATTER_VERSION_NEW_CURR
1236 23958 : eNewType = NUMBERFORMAT_CURRENCY;
1237 23958 : bMatchBracket = true;
1238 : }
1239 59511 : else if ( i < nAnzStrings-1 &&
1240 36204 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1241 16367 : sStrArray[i+1][0] == '~' )
1242 : { // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1243 16367 : eNewType = NUMBERFORMAT_DATE;
1244 16367 : bMatchBracket = true;
1245 : }
1246 : else
1247 : {
1248 3470 : sal_uInt16 nIndexNex = NextKeyword(i);
1249 3470 : if (nIndexNex == NF_KEY_H || // H
1250 0 : nIndexNex == NF_KEY_HH || // HH
1251 0 : nIndexNex == NF_KEY_M || // M
1252 0 : nIndexNex == NF_KEY_MM || // MM
1253 0 : nIndexNex == NF_KEY_S || // S
1254 : nIndexNex == NF_KEY_SS ) // SS
1255 3470 : eNewType = NUMBERFORMAT_TIME;
1256 : else
1257 : {
1258 0 : return nPos; // Error
1259 : }
1260 : }
1261 43795 : break;
1262 : case '@':
1263 2067 : eNewType = NUMBERFORMAT_TEXT;
1264 2067 : break;
1265 : default:
1266 275830 : if (pLoc->getTime100SecSep().equals(sStrArray[i]))
1267 : {
1268 48779 : bDecSep = true; // for SS,0
1269 : }
1270 275830 : eNewType = NUMBERFORMAT_UNDEFINED;
1271 275830 : break;
1272 : }
1273 : }
1274 912997 : if (eScannedType == NUMBERFORMAT_UNDEFINED)
1275 : {
1276 168328 : eScannedType = eNewType;
1277 : }
1278 744669 : else if (eScannedType == NUMBERFORMAT_TEXT || eNewType == NUMBERFORMAT_TEXT)
1279 : {
1280 20 : eScannedType = NUMBERFORMAT_TEXT; // Text always remains text
1281 : }
1282 744649 : else if (eNewType == NUMBERFORMAT_UNDEFINED)
1283 : { // Remains as is
1284 : }
1285 489190 : else if (eScannedType != eNewType)
1286 : {
1287 178827 : switch (eScannedType)
1288 : {
1289 : case NUMBERFORMAT_DATE:
1290 25298 : switch (eNewType)
1291 : {
1292 : case NUMBERFORMAT_TIME:
1293 3457 : eScannedType = NUMBERFORMAT_DATETIME;
1294 3457 : break;
1295 : case NUMBERFORMAT_FRACTION: // DD/MM
1296 21841 : break;
1297 : default:
1298 0 : if (nCurrPos >= 0)
1299 : {
1300 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1301 : }
1302 0 : else if ( sStrArray[i] != OUString(pFormatter->GetDateSep()) )
1303 : {
1304 0 : return nPos;
1305 : }
1306 : }
1307 25298 : break;
1308 : case NUMBERFORMAT_TIME:
1309 0 : switch (eNewType)
1310 : {
1311 : case NUMBERFORMAT_DATE:
1312 0 : eScannedType = NUMBERFORMAT_DATETIME;
1313 0 : break;
1314 : case NUMBERFORMAT_FRACTION: // MM/SS
1315 0 : break;
1316 : default:
1317 0 : if (nCurrPos >= 0)
1318 : {
1319 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1320 : }
1321 0 : else if (!pLoc->getTimeSep().equals(sStrArray[i]))
1322 : {
1323 0 : return nPos;
1324 : }
1325 0 : break;
1326 : }
1327 0 : break;
1328 : case NUMBERFORMAT_DATETIME:
1329 6760 : switch (eNewType)
1330 : {
1331 : case NUMBERFORMAT_TIME:
1332 : case NUMBERFORMAT_DATE:
1333 6760 : break;
1334 : case NUMBERFORMAT_FRACTION: // DD/MM
1335 0 : break;
1336 : default:
1337 0 : if (nCurrPos >= 0)
1338 : {
1339 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1340 : }
1341 0 : else if ( OUString(pFormatter->GetDateSep()) != sStrArray[i] &&
1342 0 : !pLoc->getTimeSep().equals(sStrArray[i]) )
1343 : {
1344 0 : return nPos;
1345 : }
1346 : }
1347 6760 : break;
1348 : case NUMBERFORMAT_PERCENT:
1349 0 : switch (eNewType)
1350 : {
1351 : case NUMBERFORMAT_NUMBER: // Only number to percent
1352 0 : break;
1353 : default:
1354 0 : return nPos;
1355 : }
1356 0 : break;
1357 : case NUMBERFORMAT_SCIENTIFIC:
1358 8400 : switch (eNewType)
1359 : {
1360 : case NUMBERFORMAT_NUMBER: // Only number to E
1361 8400 : break;
1362 : default:
1363 0 : return nPos;
1364 : }
1365 8400 : break;
1366 : case NUMBERFORMAT_NUMBER:
1367 15492 : switch (eNewType)
1368 : {
1369 : case NUMBERFORMAT_SCIENTIFIC:
1370 : case NUMBERFORMAT_PERCENT:
1371 : case NUMBERFORMAT_FRACTION:
1372 : case NUMBERFORMAT_CURRENCY:
1373 15492 : eScannedType = eNewType;
1374 15492 : break;
1375 : default:
1376 0 : if (nCurrPos >= 0)
1377 : {
1378 0 : eScannedType = NUMBERFORMAT_UNDEFINED;
1379 : }
1380 : else
1381 : {
1382 0 : return nPos;
1383 : }
1384 : }
1385 15492 : break;
1386 : case NUMBERFORMAT_FRACTION:
1387 8323 : switch (eNewType)
1388 : {
1389 : case NUMBERFORMAT_NUMBER: // Only number to fraction
1390 8323 : break;
1391 : default:
1392 0 : return nPos;
1393 : }
1394 8323 : break;
1395 : default:
1396 114554 : break;
1397 : }
1398 : }
1399 912997 : nPos = nPos + sStrArray[i].getLength(); // Position of correction
1400 912997 : i++;
1401 912997 : if ( bMatchBracket )
1402 : { // no type detection inside of matching brackets if [$...], [~...]
1403 362856 : while ( bMatchBracket && i < nAnzStrings )
1404 : {
1405 564412 : if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL
1406 282206 : && sStrArray[i][0] == ']' )
1407 : {
1408 40325 : bMatchBracket = false;
1409 : }
1410 : else
1411 : {
1412 241881 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1413 : }
1414 282206 : nPos = nPos + sStrArray[i].getLength();
1415 282206 : i++;
1416 : }
1417 40325 : if ( bMatchBracket )
1418 : {
1419 0 : return nPos; // missing closing bracket at end of code
1420 : }
1421 : }
1422 912997 : SkipStrings(i, nPos);
1423 : }
1424 :
1425 260323 : if ((eScannedType == NUMBERFORMAT_NUMBER ||
1426 148511 : eScannedType == NUMBERFORMAT_UNDEFINED) &&
1427 53529 : nCurrPos >= 0 && !bHaveGeneral)
1428 : {
1429 17097 : eScannedType = NUMBERFORMAT_CURRENCY; // old "automatic" currency
1430 : }
1431 148244 : if (eScannedType == NUMBERFORMAT_UNDEFINED)
1432 : {
1433 261 : eScannedType = NUMBERFORMAT_DEFINED;
1434 : }
1435 148244 : return 0; // All is fine
1436 : }
1437 :
1438 56113 : bool ImpSvNumberformatScan::InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr )
1439 : {
1440 56113 : if (nAnzStrings >= NF_MAX_FORMAT_SYMBOLS || nPos > nAnzStrings)
1441 : {
1442 0 : return false;
1443 : }
1444 56113 : if (nPos > 0 && nTypeArray[nPos-1] == NF_SYMBOLTYPE_EMPTY)
1445 : {
1446 56113 : --nPos; // reuse position
1447 : }
1448 : else
1449 : {
1450 0 : if ((size_t) (nAnzStrings + 1) >= NF_MAX_FORMAT_SYMBOLS)
1451 : {
1452 0 : return false;
1453 : }
1454 0 : ++nAnzStrings;
1455 0 : for (size_t i = nAnzStrings; i > nPos; --i)
1456 : {
1457 0 : nTypeArray[i] = nTypeArray[i-1];
1458 0 : sStrArray[i] = sStrArray[i-1];
1459 : }
1460 : }
1461 56113 : ++nAnzResStrings;
1462 56113 : nTypeArray[nPos] = static_cast<short>(eType);
1463 56113 : sStrArray[nPos] = rStr;
1464 56113 : return true;
1465 : }
1466 :
1467 129432 : int ImpSvNumberformatScan::FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i,
1468 : sal_uInt16& rAnzResStrings )
1469 : {
1470 388296 : if ( i < nAnzStrings-1 &&
1471 145799 : sStrArray[i][0] == '[' &&
1472 162166 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
1473 16367 : sStrArray[i+1][0] == '~' )
1474 : {
1475 : // [~calendarID]
1476 : // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1477 16367 : nPos = nPos + sStrArray[i].getLength(); // [
1478 16367 : nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
1479 16367 : nPos = nPos + sStrArray[++i].getLength(); // ~
1480 16367 : sStrArray[i-1] += sStrArray[i]; // [~
1481 16367 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1482 16367 : rAnzResStrings--;
1483 16367 : if ( ++i >= nAnzStrings )
1484 : {
1485 0 : return -1; // error
1486 : }
1487 16367 : nPos = nPos + sStrArray[i].getLength(); // calendarID
1488 16367 : OUString& rStr = sStrArray[i];
1489 16367 : nTypeArray[i] = NF_SYMBOLTYPE_CALENDAR; // convert
1490 16367 : i++;
1491 98289 : while ( i < nAnzStrings && sStrArray[i][0] != ']' )
1492 : {
1493 65555 : nPos = nPos + sStrArray[i].getLength();
1494 65555 : rStr += sStrArray[i];
1495 65555 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1496 65555 : rAnzResStrings--;
1497 65555 : i++;
1498 : }
1499 32734 : if ( rStr.getLength() && i < nAnzStrings &&
1500 16367 : sStrArray[i][0] == ']' )
1501 : {
1502 16367 : nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
1503 16367 : nPos = nPos + sStrArray[i].getLength();
1504 16367 : i++;
1505 : }
1506 : else
1507 : {
1508 0 : return -1; // error
1509 : }
1510 16367 : return 1;
1511 : }
1512 113065 : return 0;
1513 : }
1514 :
1515 148244 : sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
1516 : {
1517 148244 : const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1518 :
1519 : // save values for convert mode
1520 148244 : OUString sOldDecSep = pFormatter->GetNumDecimalSep();
1521 296488 : OUString sOldThousandSep = pFormatter->GetNumThousandSep();
1522 296488 : OUString sOldDateSep = pFormatter->GetDateSep();
1523 296488 : OUString sOldTimeSep = pLoc->getTimeSep();
1524 296488 : OUString sOldTime100SecSep= pLoc->getTime100SecSep();
1525 296488 : OUString sOldCurSymbol = GetCurSymbol();
1526 296488 : OUString sOldCurString = GetCurString();
1527 148244 : sal_Unicode cOldKeyH = sKeyword[NF_KEY_H][0];
1528 148244 : sal_Unicode cOldKeyMI = sKeyword[NF_KEY_MI][0];
1529 148244 : sal_Unicode cOldKeyS = sKeyword[NF_KEY_S][0];
1530 :
1531 : // If the group separator is a Non-Breaking Space (French) continue with a
1532 : // normal space instead so queries on space work correctly.
1533 : // The format string is adjusted to allow both.
1534 : // For output of the format code string the LocaleData characters are used.
1535 148244 : if ( sOldThousandSep[0] == cNonBreakingSpace && sOldThousandSep.getLength() == 1 )
1536 : {
1537 134 : sOldThousandSep = " ";
1538 : }
1539 : // change locale data et al
1540 148244 : if (bConvertMode)
1541 : {
1542 6008 : pFormatter->ChangeIntl(eNewLnge);
1543 : //! pointer may have changed
1544 6008 : pLoc = pFormatter->GetLocaleData();
1545 : //! init new keywords
1546 6008 : InitKeywords();
1547 : }
1548 148244 : const CharClass* pChrCls = pFormatter->GetCharClass();
1549 :
1550 148244 : sal_Int32 nPos = 0; // error correction position
1551 148244 : sal_uInt16 i = 0; // symbol loop counter
1552 148244 : sal_uInt16 nCounter = 0; // counts digits
1553 148244 : nAnzResStrings = nAnzStrings; // counts remaining symbols
1554 148244 : bDecSep = false; // reset in case already used in TypeCheck
1555 148244 : bool bThaiT = false; // Thai T NatNum modifier present
1556 148244 : bool bTimePart = false;
1557 :
1558 148244 : switch (eScannedType)
1559 : {
1560 : case NUMBERFORMAT_TEXT:
1561 : case NUMBERFORMAT_DEFINED:
1562 8443 : while (i < nAnzStrings)
1563 : {
1564 3787 : switch (nTypeArray[i])
1565 : {
1566 : case NF_SYMBOLTYPE_BLANK:
1567 : case NF_SYMBOLTYPE_STAR:
1568 1316 : break;
1569 : case NF_KEY_GENERAL : // #77026# "General" is the same as "@"
1570 0 : break;
1571 : default:
1572 4570 : if ( nTypeArray[i] != NF_SYMBOLTYPE_DEL ||
1573 2099 : sStrArray[i][0] != '@' )
1574 : {
1575 404 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1576 : }
1577 2471 : break;
1578 : }
1579 3787 : nPos = nPos + sStrArray[i].getLength();
1580 3787 : i++;
1581 : } // of while
1582 2328 : break;
1583 :
1584 : case NUMBERFORMAT_NUMBER:
1585 : case NUMBERFORMAT_PERCENT:
1586 : case NUMBERFORMAT_CURRENCY:
1587 : case NUMBERFORMAT_SCIENTIFIC:
1588 : case NUMBERFORMAT_FRACTION:
1589 550340 : while (i < nAnzStrings)
1590 : {
1591 : // TODO: rechecking eScannedType is unnecessary.
1592 : // This switch-case is for eScannedType == NUMBERFORMAT_FRACTION anyway
1593 839843 : if (eScannedType == NUMBERFORMAT_FRACTION && // special case
1594 69906 : nTypeArray[i] == NF_SYMBOLTYPE_DEL && // # ### #/#
1595 29999 : StringEqualsChar( sOldThousandSep, ' ' ) && // e.g. France or Sweden
1596 44 : StringEqualsChar( sStrArray[i], ' ' ) &&
1597 399966 : !bFrac &&
1598 8 : IsLastBlankBeforeFrac(i) )
1599 : {
1600 8 : nTypeArray[i] = NF_SYMBOLTYPE_STRING; // del->string
1601 : } // No thousands marker
1602 :
1603 794539 : if (nTypeArray[i] == NF_SYMBOLTYPE_BLANK ||
1604 781608 : nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
1605 772374 : nTypeArray[i] == NF_KEY_CCC || // CCC
1606 385355 : nTypeArray[i] == NF_KEY_GENERAL ) // Standard
1607 : {
1608 16299 : if (nTypeArray[i] == NF_KEY_GENERAL)
1609 : {
1610 1704 : nThousand = FLAG_STANDARD_IN_FORMAT;
1611 1704 : if ( bConvertMode )
1612 : {
1613 36 : sStrArray[i] = sNameStandardFormat;
1614 : }
1615 : }
1616 16299 : nPos = nPos + sStrArray[i].getLength();
1617 16299 : i++;
1618 : }
1619 730326 : else if (nTypeArray[i] == NF_SYMBOLTYPE_STRING || // No Strings or
1620 346675 : nTypeArray[i] > 0) // Keywords
1621 : {
1622 43784 : if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
1623 3404 : nTypeArray[i] == NF_KEY_E) // E+
1624 : {
1625 3404 : if (bExp) // Double
1626 : {
1627 0 : return nPos;
1628 : }
1629 3404 : bExp = true;
1630 3404 : nExpPos = i;
1631 3404 : if (bDecSep)
1632 : {
1633 3403 : nCntPost = nCounter;
1634 : }
1635 : else
1636 : {
1637 1 : nCntPre = nCounter;
1638 : }
1639 3404 : nCounter = 0;
1640 3404 : nTypeArray[i] = NF_SYMBOLTYPE_EXP;
1641 : }
1642 46964 : else if (eScannedType == NUMBERFORMAT_FRACTION &&
1643 9988 : sStrArray[i][0] == ' ')
1644 : {
1645 6656 : if (!bBlank && !bFrac) // Not double or after a /
1646 : {
1647 8 : if (bDecSep && nCounter > 0) // Decimal places
1648 : {
1649 0 : return nPos; // Error
1650 : }
1651 8 : bBlank = true;
1652 8 : nBlankPos = i;
1653 8 : nCntPre = nCounter;
1654 8 : nCounter = 0;
1655 : }
1656 6656 : nTypeArray[i] = NF_SYMBOLTYPE_FRACBLANK;
1657 : }
1658 30320 : else if (nTypeArray[i] == NF_KEY_THAI_T)
1659 : {
1660 0 : bThaiT = true;
1661 0 : sStrArray[i] = sKeyword[nTypeArray[i]];
1662 : }
1663 35205 : else if (sStrArray[i][0] >= '0' &&
1664 4885 : sStrArray[i][0] <= '9')
1665 : {
1666 3329 : OUString sDiv;
1667 3329 : sal_uInt16 j = i;
1668 13316 : while(j < nAnzStrings)
1669 : {
1670 6658 : sDiv += sStrArray[j++];
1671 : }
1672 3329 : if (OUString::valueOf(sDiv.toInt32()) == sDiv)
1673 : {
1674 : // Found a Divisor
1675 13316 : while (i < j)
1676 : {
1677 6658 : nTypeArray[i++] = NF_SYMBOLTYPE_FRAC_FDIV;
1678 : }
1679 3329 : i = j - 1; // Stop the loop
1680 3329 : if (nCntPost)
1681 : {
1682 3329 : nCounter = nCntPost;
1683 : }
1684 0 : else if (nCntPre)
1685 : {
1686 0 : nCounter = nCntPre;
1687 : }
1688 : // don't artificially increment nCntPre for forced denominator
1689 3329 : if ( ( eScannedType != NUMBERFORMAT_FRACTION ) && (!nCntPre) )
1690 : {
1691 0 : nCntPre++;
1692 : }
1693 3329 : }
1694 : }
1695 : else
1696 : {
1697 26991 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1698 : }
1699 40380 : nPos = nPos + sStrArray[i].getLength();
1700 40380 : i++;
1701 : }
1702 343271 : else if (nTypeArray[i] == NF_SYMBOLTYPE_DEL)
1703 : {
1704 343271 : sal_Unicode cHere = sStrArray[i][0];
1705 343271 : sal_Unicode cSaved = cHere;
1706 : // Handle not pre-known separators in switch.
1707 : sal_Unicode cSimplified;
1708 343271 : if (StringEqualsChar( pFormatter->GetNumThousandSep(), cHere))
1709 : {
1710 56065 : cSimplified = ',';
1711 : }
1712 287206 : else if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cHere))
1713 : {
1714 40356 : cSimplified = '.';
1715 : }
1716 : else
1717 : {
1718 246850 : cSimplified = cHere;
1719 : }
1720 :
1721 343271 : OUString& rStr = sStrArray[i];
1722 :
1723 343271 : switch ( cSimplified )
1724 : {
1725 : case '#':
1726 : case '0':
1727 : case '?':
1728 176691 : if (nThousand > 0) // #... #
1729 : {
1730 0 : return nPos; // Error
1731 : }
1732 176691 : else if (bFrac && cHere == '0')
1733 : {
1734 0 : return nPos; // Denominator is 0
1735 : }
1736 176691 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1737 176691 : nPos = nPos + rStr.getLength();
1738 176691 : i++;
1739 176691 : nCounter++;
1740 950998 : while (i < nAnzStrings &&
1741 510508 : (sStrArray[i][0] == '#' ||
1742 358976 : sStrArray[i][0] == '0' ||
1743 132662 : sStrArray[i][0] == '?'))
1744 : {
1745 156711 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1746 156711 : nPos = nPos + sStrArray[i].getLength();
1747 156711 : nCounter++;
1748 156711 : i++;
1749 : }
1750 176691 : break;
1751 : case '-':
1752 40351 : if ( bDecSep && nDecPos+1 == i &&
1753 6656 : nTypeArray[nDecPos] == NF_SYMBOLTYPE_DECSEP )
1754 : {
1755 : // "0.--"
1756 6656 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
1757 6656 : nPos = nPos + rStr.getLength();
1758 6656 : i++;
1759 6656 : nCounter++;
1760 26668 : while (i < nAnzStrings &&
1761 6700 : (sStrArray[i][0] == '-') )
1762 : {
1763 : // If more than two dashes are present in
1764 : // currency formats the last dash will be
1765 : // interpreted literally as a minus sign.
1766 : // Has to be this ugly. Period.
1767 13312 : if ( eScannedType == NUMBERFORMAT_CURRENCY
1768 6656 : && rStr.getLength() >= 2 &&
1769 0 : (i == nAnzStrings-1 ||
1770 0 : sStrArray[i+1][0] != '-') )
1771 : {
1772 0 : break;
1773 : }
1774 6656 : rStr += sStrArray[i];
1775 6656 : nPos = nPos + sStrArray[i].getLength();
1776 6656 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1777 6656 : nAnzResStrings--;
1778 6656 : nCounter++;
1779 6656 : i++;
1780 : }
1781 : }
1782 : else
1783 : {
1784 20383 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1785 20383 : nPos = nPos + sStrArray[i].getLength();
1786 20383 : i++;
1787 : }
1788 27039 : break;
1789 : case '.':
1790 : case ',':
1791 : case '\'':
1792 : case ' ':
1793 105585 : if ( StringEqualsChar( sOldThousandSep, cSaved ) )
1794 : {
1795 : // previous char with skip empty
1796 56155 : sal_Unicode cPre = PreviousChar(i);
1797 : sal_Unicode cNext;
1798 56155 : if (bExp || bBlank || bFrac)
1799 : {
1800 : // after E, / or ' '
1801 0 : if ( !StringEqualsChar( sOldThousandSep, ' ' ) )
1802 : {
1803 0 : nPos = nPos + sStrArray[i].getLength();
1804 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1805 0 : nAnzResStrings--;
1806 0 : i++; // eat it
1807 : }
1808 : else
1809 : {
1810 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1811 : }
1812 : }
1813 168465 : else if (i > 0 && i < nAnzStrings-1 &&
1814 168457 : (cPre == '#' || cPre == '0') &&
1815 56181 : ((cNext = NextChar(i)) == '#' || cNext == '0')) // #,#
1816 : {
1817 56113 : nPos = nPos + sStrArray[i].getLength();
1818 56113 : if (!bThousand) // only once
1819 : {
1820 56113 : bThousand = true;
1821 : }
1822 : // Eat it, will be reinserted at proper grouping positions further down.
1823 56113 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1824 56113 : nAnzResStrings--;
1825 56113 : i++;
1826 : }
1827 126 : else if (i > 0 && (cPre == '#' || cPre == '0')
1828 34 : && PreviousType(i) == NF_SYMBOLTYPE_DIGIT
1829 76 : && nThousand < FLAG_STANDARD_IN_FORMAT )
1830 : { // #,,,,
1831 34 : if ( StringEqualsChar( sOldThousandSep, ' ' ) )
1832 : {
1833 : // strange, those French..
1834 34 : bool bFirst = true;
1835 : // set a hard Non-Breaking Space or ConvertMode
1836 34 : const OUString& rSepF = pFormatter->GetNumThousandSep();
1837 136 : while ( i < nAnzStrings &&
1838 68 : sStrArray[i] == sOldThousandSep &&
1839 34 : StringEqualsChar( sOldThousandSep, NextChar(i) ) )
1840 : { // last was a space or another space
1841 : // is following => separator
1842 0 : nPos = nPos + sStrArray[i].getLength();
1843 0 : if ( bFirst )
1844 : {
1845 0 : bFirst = false;
1846 0 : rStr = rSepF;
1847 0 : nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
1848 : }
1849 : else
1850 : {
1851 0 : rStr += rSepF;
1852 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1853 0 : nAnzResStrings--;
1854 : }
1855 0 : nThousand++;
1856 0 : i++;
1857 : }
1858 68 : if ( i < nAnzStrings-1 &&
1859 34 : sStrArray[i] == sOldThousandSep )
1860 : {
1861 : // something following last space
1862 : // => space if currency contained,
1863 : // else separator
1864 34 : nPos = nPos + sStrArray[i].getLength();
1865 100 : if ( (nPos <= nCurrPos &&
1866 50 : nCurrPos < nPos + sStrArray[i+1].getLength()) ||
1867 102 : nTypeArray[i+1] == NF_KEY_CCC ||
1868 32 : (i < nAnzStrings-2 &&
1869 32 : sStrArray[i+1][0] == '[' &&
1870 16 : sStrArray[i+2][0] == '$') )
1871 : {
1872 34 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1873 : }
1874 : else
1875 : {
1876 0 : if ( bFirst )
1877 : {
1878 0 : bFirst = false;
1879 0 : rStr = rSepF;
1880 0 : nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
1881 : }
1882 : else
1883 : {
1884 0 : rStr += rSepF;
1885 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1886 0 : nAnzResStrings--;
1887 : }
1888 0 : nThousand++;
1889 : }
1890 34 : i++;
1891 : }
1892 : }
1893 : else
1894 : {
1895 0 : do
1896 : {
1897 0 : nThousand++;
1898 0 : nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
1899 0 : nPos = nPos + sStrArray[i].getLength();
1900 0 : sStrArray[i] = pFormatter->GetNumThousandSep();
1901 0 : i++;
1902 : }
1903 0 : while (i < nAnzStrings && sStrArray[i] == sOldThousandSep);
1904 : }
1905 : }
1906 : else // any grsep
1907 : {
1908 8 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1909 8 : nPos = nPos + rStr.getLength();
1910 8 : i++;
1911 16 : while ( i < nAnzStrings && sStrArray[i] == sOldThousandSep )
1912 : {
1913 0 : rStr += sStrArray[i];
1914 0 : nPos = nPos + sStrArray[i].getLength();
1915 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1916 0 : nAnzResStrings--;
1917 0 : i++;
1918 : }
1919 : }
1920 : }
1921 49430 : else if ( StringEqualsChar( sOldDecSep, cSaved ) )
1922 : {
1923 40356 : if (bBlank || bFrac) // . behind / or ' '
1924 : {
1925 0 : return nPos; // error
1926 : }
1927 40356 : else if (bExp) // behind E
1928 : {
1929 0 : nPos = nPos + sStrArray[i].getLength();
1930 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1931 0 : nAnzResStrings--;
1932 0 : i++; // eat it
1933 : }
1934 40356 : else if (bDecSep) // any .
1935 : {
1936 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1937 0 : nPos = nPos + rStr.getLength();
1938 0 : i++;
1939 0 : while ( i < nAnzStrings && sStrArray[i] == sOldDecSep )
1940 : {
1941 0 : rStr += sStrArray[i];
1942 0 : nPos = nPos + sStrArray[i].getLength();
1943 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1944 0 : nAnzResStrings--;
1945 0 : i++;
1946 : }
1947 : }
1948 : else
1949 : {
1950 40356 : nPos = nPos + sStrArray[i].getLength();
1951 40356 : nTypeArray[i] = NF_SYMBOLTYPE_DECSEP;
1952 40356 : sStrArray[i] = pFormatter->GetNumDecimalSep();
1953 40356 : bDecSep = true;
1954 40356 : nDecPos = i;
1955 40356 : nCntPre = nCounter;
1956 40356 : nCounter = 0;
1957 :
1958 40356 : i++;
1959 : }
1960 : } // of else = DecSep
1961 : else // . without meaning
1962 : {
1963 18148 : if (cSaved == ' ' &&
1964 15722 : eScannedType == NUMBERFORMAT_FRACTION &&
1965 6648 : StringEqualsChar( sStrArray[i], ' ' ) )
1966 : {
1967 6648 : if (!bBlank && !bFrac) // no dups
1968 : { // or behind /
1969 6648 : if (bDecSep && nCounter > 0) // dec.
1970 : {
1971 0 : return nPos; // error
1972 : }
1973 6648 : bBlank = true;
1974 6648 : nBlankPos = i;
1975 6648 : nCntPre = nCounter;
1976 6648 : nCounter = 0;
1977 : }
1978 6648 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1979 6648 : nPos = nPos + sStrArray[i].getLength();
1980 : }
1981 : else
1982 : {
1983 2426 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
1984 2426 : nPos = nPos + rStr.getLength();
1985 2426 : i++;
1986 4852 : while (i < nAnzStrings && StringEqualsChar( sStrArray[i], cSaved ) )
1987 : {
1988 0 : rStr += sStrArray[i];
1989 0 : nPos = nPos + sStrArray[i].getLength();
1990 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
1991 0 : nAnzResStrings--;
1992 0 : i++;
1993 : }
1994 : }
1995 : }
1996 105585 : break;
1997 : case '/':
1998 6659 : if (eScannedType == NUMBERFORMAT_FRACTION)
1999 : {
2000 13318 : if ( i == 0 ||
2001 6659 : (nTypeArray[i-1] != NF_SYMBOLTYPE_DIGIT &&
2002 0 : nTypeArray[i-1] != NF_SYMBOLTYPE_EMPTY) )
2003 : {
2004 0 : return nPos ? nPos : 1; // /? not allowed
2005 : }
2006 6659 : else if (!bFrac || (bDecSep && nCounter > 0))
2007 : {
2008 6659 : bFrac = true;
2009 6659 : nCntPost = nCounter;
2010 6659 : nCounter = 0;
2011 6659 : nTypeArray[i] = NF_SYMBOLTYPE_FRAC;
2012 6659 : nPos = nPos + sStrArray[i].getLength();
2013 6659 : i++;
2014 : }
2015 : else // / double or in , in the denominator
2016 : {
2017 0 : return nPos; // Error
2018 : }
2019 : }
2020 : else
2021 : {
2022 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2023 0 : nPos = nPos + sStrArray[i].getLength();
2024 0 : i++;
2025 : }
2026 6659 : break;
2027 : case '[' :
2028 71874 : if ( eScannedType == NUMBERFORMAT_CURRENCY &&
2029 47916 : i < nAnzStrings-1 &&
2030 71874 : nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
2031 23958 : sStrArray[i+1][0] == '$' )
2032 : {
2033 : // [$DM-xxx]
2034 : // As of SV_NUMBERFORMATTER_VERSION_NEW_CURR
2035 23958 : nPos = nPos + sStrArray[i].getLength(); // [
2036 23958 : nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
2037 23958 : nPos = nPos + sStrArray[++i].getLength(); // $
2038 23958 : sStrArray[i-1] += sStrArray[i]; // [$
2039 23958 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2040 23958 : nAnzResStrings--;
2041 23958 : if ( ++i >= nAnzStrings )
2042 : {
2043 0 : return nPos; // Error
2044 : }
2045 23958 : nPos = nPos + sStrArray[i].getLength(); // DM
2046 23958 : OUString* pStr = &sStrArray[i];
2047 23958 : nTypeArray[i] = NF_SYMBOLTYPE_CURRENCY; // convert
2048 23958 : bool bHadDash = false;
2049 23958 : i++;
2050 143592 : while ( i < nAnzStrings && sStrArray[i][0] != ']' )
2051 : {
2052 95676 : nPos = nPos + sStrArray[i].getLength();
2053 95676 : if ( bHadDash )
2054 : {
2055 70880 : *pStr += sStrArray[i];
2056 70880 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2057 70880 : nAnzResStrings--;
2058 : }
2059 : else
2060 : {
2061 24796 : if ( sStrArray[i][0] == '-' )
2062 : {
2063 23630 : bHadDash = true;
2064 23630 : pStr = &sStrArray[i];
2065 23630 : nTypeArray[i] = NF_SYMBOLTYPE_CURREXT;
2066 : }
2067 : else
2068 : {
2069 1166 : *pStr += sStrArray[i];
2070 1166 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2071 1166 : nAnzResStrings--;
2072 : }
2073 : }
2074 95676 : i++;
2075 : }
2076 23958 : if ( rStr.getLength() && i < nAnzStrings && sStrArray[i][0] == ']' )
2077 : {
2078 23958 : nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
2079 23958 : nPos = nPos + sStrArray[i].getLength();
2080 23958 : i++;
2081 : }
2082 : else
2083 : {
2084 0 : return nPos; // Error
2085 : }
2086 : }
2087 : else
2088 : {
2089 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2090 0 : nPos = nPos + sStrArray[i].getLength();
2091 0 : i++;
2092 : }
2093 23958 : break;
2094 : default: // Other Dels
2095 3339 : if (eScannedType == NUMBERFORMAT_PERCENT && cHere == '%')
2096 : {
2097 3339 : nTypeArray[i] = NF_SYMBOLTYPE_PERCENT;
2098 : }
2099 : else
2100 : {
2101 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2102 : }
2103 3339 : nPos = nPos + sStrArray[i].getLength();
2104 3339 : i++;
2105 3339 : break;
2106 : } // of switch (Del)
2107 : } // of else Del
2108 : else
2109 : {
2110 : SAL_WARN( "svl.numbers", "unknown NF_SYMBOLTYPE_..." );
2111 0 : nPos = nPos + sStrArray[i].getLength();
2112 0 : i++;
2113 : }
2114 : } // of while
2115 75195 : if (eScannedType == NUMBERFORMAT_FRACTION)
2116 : {
2117 6659 : if (bFrac)
2118 : {
2119 6659 : nCntExp = nCounter;
2120 : }
2121 0 : else if (bBlank)
2122 : {
2123 0 : nCntPost = nCounter;
2124 : }
2125 : else
2126 : {
2127 0 : nCntPre = nCounter;
2128 : }
2129 : }
2130 : else
2131 : {
2132 68536 : if (bExp)
2133 : {
2134 3404 : nCntExp = nCounter;
2135 : }
2136 65132 : else if (bDecSep)
2137 : {
2138 36953 : nCntPost = nCounter;
2139 : }
2140 : else
2141 : {
2142 28179 : nCntPre = nCounter;
2143 : }
2144 : }
2145 75195 : if (bThousand) // Expansion of grouping separators
2146 : {
2147 : sal_uInt16 nMaxPos;
2148 56113 : if (bFrac)
2149 : {
2150 0 : if (bBlank)
2151 : {
2152 0 : nMaxPos = nBlankPos;
2153 : }
2154 : else
2155 : {
2156 0 : nMaxPos = 0; // no grouping
2157 : }
2158 : }
2159 56113 : else if (bDecSep) // decimal separator present
2160 : {
2161 33263 : nMaxPos = nDecPos;
2162 : }
2163 22850 : else if (bExp) // 'E' exponent present
2164 : {
2165 0 : nMaxPos = nExpPos;
2166 : }
2167 : else // up to end
2168 : {
2169 22850 : nMaxPos = i;
2170 : }
2171 : // Insert separators at proper positions.
2172 56113 : sal_Int32 nCount = 0;
2173 56113 : utl::DigitGroupingIterator aGrouping( pLoc->getDigitGrouping());
2174 56113 : size_t nFirstDigitSymbol = nMaxPos;
2175 56113 : size_t nFirstGroupingSymbol = nMaxPos;
2176 56113 : i = nMaxPos;
2177 579416 : while (i-- > 0)
2178 : {
2179 467190 : if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2180 : {
2181 224452 : nFirstDigitSymbol = i;
2182 224452 : nCount = nCount + sStrArray[i].getLength(); // MSC converts += to int and then warns, so ...
2183 : // Insert separator only if not leftmost symbol.
2184 224452 : if (i > 0 && nCount >= aGrouping.getPos())
2185 : {
2186 : DBG_ASSERT( sStrArray[i].getLength() == 1,
2187 : "ImpSvNumberformatScan::FinalScan: combined digits in group separator insertion");
2188 56113 : if (!InsertSymbol( i, NF_SYMBOLTYPE_THSEP, pFormatter->GetNumThousandSep()))
2189 : {
2190 : // nPos isn't correct here, but signals error
2191 0 : return nPos;
2192 : }
2193 : // i may have been decremented by 1
2194 56113 : nFirstDigitSymbol = i + 1;
2195 56113 : nFirstGroupingSymbol = i;
2196 56113 : aGrouping.advance();
2197 : }
2198 : }
2199 : }
2200 : // Generated something like "string",000; remove separator again.
2201 56113 : if (nFirstGroupingSymbol < nFirstDigitSymbol)
2202 : {
2203 0 : nTypeArray[nFirstGroupingSymbol] = NF_SYMBOLTYPE_EMPTY;
2204 0 : nAnzResStrings--;
2205 56113 : }
2206 : }
2207 : // Combine digits into groups to save memory (Info will be copied
2208 : // later, taking only non-empty symbols).
2209 511893 : for (i = 0; i < nAnzStrings; ++i)
2210 : {
2211 436698 : if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2212 : {
2213 183347 : OUString& rStr = sStrArray[i];
2214 523405 : while (++i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
2215 : {
2216 156711 : rStr += sStrArray[i];
2217 156711 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2218 156711 : nAnzResStrings--;
2219 : }
2220 : }
2221 : }
2222 75195 : break; // of NUMBERFORMAT_NUMBER
2223 : case NUMBERFORMAT_DATE:
2224 393383 : while (i < nAnzStrings)
2225 : {
2226 : int nCalRet;
2227 283991 : switch (nTypeArray[i])
2228 : {
2229 : case NF_SYMBOLTYPE_BLANK:
2230 : case NF_SYMBOLTYPE_STAR:
2231 : case NF_SYMBOLTYPE_STRING:
2232 3534 : nPos = nPos + sStrArray[i].getLength();
2233 3534 : i++;
2234 3534 : break;
2235 : case NF_SYMBOLTYPE_DEL:
2236 127580 : if (sStrArray[i] == sOldDateSep)
2237 : {
2238 15226 : nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
2239 15226 : nPos = nPos + sStrArray[i].getLength();
2240 15226 : if (bConvertMode)
2241 : {
2242 1659 : sStrArray[i] = pFormatter->GetDateSep();
2243 : }
2244 15226 : i++;
2245 : }
2246 112354 : else if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
2247 : {
2248 16355 : if ( nCalRet < 0 )
2249 : {
2250 0 : return nPos; // error
2251 : }
2252 : }
2253 : else
2254 : {
2255 95999 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2256 95999 : nPos = nPos + sStrArray[i].getLength();
2257 95999 : i++;
2258 : }
2259 127580 : break;
2260 : case NF_KEY_THAI_T :
2261 0 : bThaiT = true;
2262 : // fall thru
2263 : case NF_KEY_M: // M
2264 : case NF_KEY_MM: // MM
2265 : case NF_KEY_MMM: // MMM
2266 : case NF_KEY_MMMM: // MMMM
2267 : case NF_KEY_MMMMM: // MMMMM
2268 : case NF_KEY_Q: // Q
2269 : case NF_KEY_QQ: // QQ
2270 : case NF_KEY_D: // D
2271 : case NF_KEY_DD: // DD
2272 : case NF_KEY_DDD: // DDD
2273 : case NF_KEY_DDDD: // DDDD
2274 : case NF_KEY_YY: // YY
2275 : case NF_KEY_YYYY: // YYYY
2276 : case NF_KEY_NN: // NN
2277 : case NF_KEY_NNN: // NNN
2278 : case NF_KEY_NNNN: // NNNN
2279 : case NF_KEY_WW : // WW
2280 : case NF_KEY_AAA : // AAA
2281 : case NF_KEY_AAAA : // AAAA
2282 : case NF_KEY_EC : // E
2283 : case NF_KEY_EEC : // EE
2284 : case NF_KEY_G : // G
2285 : case NF_KEY_GG : // GG
2286 : case NF_KEY_GGG : // GGG
2287 : case NF_KEY_R : // R
2288 : case NF_KEY_RR : // RR
2289 152877 : sStrArray[i] = OUString(sKeyword[nTypeArray[i]]); // tTtT -> TTTT
2290 152877 : nPos = nPos + sStrArray[i].getLength();
2291 152877 : i++;
2292 152877 : break;
2293 : default: // Other keywords
2294 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2295 0 : nPos = nPos + sStrArray[i].getLength();
2296 0 : i++;
2297 0 : break;
2298 : }
2299 : } // of while
2300 54696 : break; // of NUMBERFORMAT_DATE
2301 : case NUMBERFORMAT_TIME:
2302 97887 : while (i < nAnzStrings)
2303 : {
2304 : sal_Unicode cChar;
2305 :
2306 72751 : switch (nTypeArray[i])
2307 : {
2308 : case NF_SYMBOLTYPE_BLANK:
2309 : case NF_SYMBOLTYPE_STAR:
2310 0 : nPos = nPos + sStrArray[i].getLength();
2311 0 : i++;
2312 0 : break;
2313 : case NF_SYMBOLTYPE_DEL:
2314 37000 : switch( sStrArray[i][0] )
2315 : {
2316 : case '0':
2317 3470 : if ( Is100SecZero( i, bDecSep ) )
2318 : {
2319 3470 : bDecSep = true;
2320 3470 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
2321 3470 : OUString& rStr = sStrArray[i];
2322 3470 : i++;
2323 3470 : nPos = nPos + sStrArray[i].getLength();
2324 3470 : nCounter++;
2325 13602 : while (i < nAnzStrings &&
2326 3331 : sStrArray[i][0] == '0')
2327 : {
2328 3331 : rStr += sStrArray[i];
2329 3331 : nPos = nPos + sStrArray[i].getLength();
2330 3331 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2331 3331 : nAnzResStrings--;
2332 3331 : nCounter++;
2333 3331 : i++;
2334 : }
2335 : }
2336 : else
2337 : {
2338 0 : return nPos;
2339 : }
2340 3470 : break;
2341 : case '#':
2342 : case '?':
2343 0 : return nPos;
2344 : case '[':
2345 3470 : if (bThousand) // Double
2346 : {
2347 0 : return nPos;
2348 : }
2349 3470 : bThousand = true; // Empty for Time
2350 3470 : cChar = pChrCls->uppercase(OUString(NextChar(i)))[0];
2351 3470 : if ( cChar == cOldKeyH )
2352 : {
2353 3470 : nThousand = 1; // H
2354 : }
2355 0 : else if ( cChar == cOldKeyMI )
2356 : {
2357 0 : nThousand = 2; // M
2358 : }
2359 0 : else if ( cChar == cOldKeyS )
2360 : {
2361 0 : nThousand = 3; // S
2362 : }
2363 : else
2364 : {
2365 0 : return nPos;
2366 : }
2367 3470 : nPos = nPos + sStrArray[i].getLength();
2368 3470 : i++;
2369 3470 : break;
2370 : case ']':
2371 3470 : if (!bThousand) // No preceding [
2372 : {
2373 0 : return nPos;
2374 : }
2375 3470 : nPos = nPos + sStrArray[i].getLength();
2376 3470 : i++;
2377 3470 : break;
2378 : default:
2379 26590 : nPos = nPos + sStrArray[i].getLength();
2380 26590 : if ( sStrArray[i] == sOldTimeSep )
2381 : {
2382 19686 : nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
2383 19686 : if ( bConvertMode )
2384 : {
2385 1313 : sStrArray[i] = pLoc->getTimeSep();
2386 : }
2387 : }
2388 6904 : else if ( sStrArray[i] == sOldTime100SecSep )
2389 : {
2390 3467 : bDecSep = true;
2391 3467 : nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
2392 3467 : if ( bConvertMode )
2393 : {
2394 133 : sStrArray[i] = pLoc->getTime100SecSep();
2395 : }
2396 : }
2397 : else
2398 : {
2399 3437 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2400 : }
2401 26590 : i++;
2402 26590 : break;
2403 : }
2404 37000 : break;
2405 : case NF_SYMBOLTYPE_STRING:
2406 37 : nPos = nPos + sStrArray[i].getLength();
2407 37 : i++;
2408 37 : break;
2409 : case NF_KEY_AMPM: // AM/PM
2410 : case NF_KEY_AP: // A/P
2411 3440 : bExp = true; // Abuse for A/P
2412 3440 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2413 3440 : nPos = nPos + sStrArray[i].getLength();
2414 3440 : i++;
2415 3440 : break;
2416 : case NF_KEY_THAI_T :
2417 0 : bThaiT = true;
2418 : // fall thru
2419 : case NF_KEY_MI: // M
2420 : case NF_KEY_MMI: // MM
2421 : case NF_KEY_H: // H
2422 : case NF_KEY_HH: // HH
2423 : case NF_KEY_S: // S
2424 : case NF_KEY_SS: // SS
2425 32274 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2426 32274 : nPos = nPos + sStrArray[i].getLength();
2427 32274 : i++;
2428 32274 : break;
2429 : default: // Other keywords
2430 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2431 0 : nPos = nPos + sStrArray[i].getLength();
2432 0 : i++;
2433 0 : break;
2434 : }
2435 : } // of while
2436 12568 : nCntPost = nCounter; // Zero counter
2437 12568 : if (bExp)
2438 : {
2439 3440 : nCntExp = 1; // Remembers AM/PM
2440 : }
2441 12568 : break; // of NUMBERFORMAT_TIME
2442 : case NUMBERFORMAT_DATETIME:
2443 44632 : while (i < nAnzStrings)
2444 : {
2445 : int nCalRet;
2446 37718 : switch (nTypeArray[i])
2447 : {
2448 : case NF_SYMBOLTYPE_BLANK:
2449 : case NF_SYMBOLTYPE_STAR:
2450 : case NF_SYMBOLTYPE_STRING:
2451 68 : nPos = nPos + sStrArray[i].getLength();
2452 68 : i++;
2453 68 : break;
2454 : case NF_SYMBOLTYPE_DEL:
2455 17078 : if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
2456 : {
2457 12 : if ( nCalRet < 0 )
2458 : {
2459 0 : return nPos; // Error
2460 : }
2461 : }
2462 : else
2463 : {
2464 17066 : switch( sStrArray[i][0] )
2465 : {
2466 : case '0':
2467 0 : if ( bTimePart && Is100SecZero( i, bDecSep ) )
2468 : {
2469 0 : bDecSep = true;
2470 0 : nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
2471 0 : OUString& rStr = sStrArray[i];
2472 0 : i++;
2473 0 : nPos = nPos + sStrArray[i].getLength();
2474 0 : nCounter++;
2475 0 : while (i < nAnzStrings &&
2476 0 : sStrArray[i][0] == '0')
2477 : {
2478 0 : rStr += sStrArray[i];
2479 0 : nPos = nPos + sStrArray[i].getLength();
2480 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2481 0 : nAnzResStrings--;
2482 0 : nCounter++;
2483 0 : i++;
2484 : }
2485 : }
2486 : else
2487 : {
2488 0 : return nPos;
2489 : }
2490 0 : break;
2491 : case '#':
2492 : case '?':
2493 0 : return nPos;
2494 : default:
2495 17066 : nPos = nPos + sStrArray[i].getLength();
2496 17066 : if (bTimePart)
2497 : {
2498 6742 : if ( sStrArray[i] == sOldTimeSep )
2499 : {
2500 5113 : nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
2501 5113 : if ( bConvertMode )
2502 : {
2503 95 : sStrArray[i] = pLoc->getTimeSep();
2504 : }
2505 : }
2506 1629 : else if ( sStrArray[i] == sOldTime100SecSep )
2507 : {
2508 0 : bDecSep = true;
2509 0 : nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
2510 0 : if ( bConvertMode )
2511 : {
2512 0 : sStrArray[i] = pLoc->getTime100SecSep();
2513 : }
2514 : }
2515 : else
2516 : {
2517 1629 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2518 : }
2519 : }
2520 : else
2521 : {
2522 10324 : if ( sStrArray[i] == sOldDateSep )
2523 : {
2524 6880 : nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
2525 6880 : if (bConvertMode)
2526 188 : sStrArray[i] = pFormatter->GetDateSep();
2527 : }
2528 : else
2529 : {
2530 3444 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2531 : }
2532 : }
2533 17066 : i++;
2534 17066 : break;
2535 : }
2536 : }
2537 17078 : break;
2538 : case NF_KEY_AMPM: // AM/PM
2539 : case NF_KEY_AP: // A/P
2540 1629 : bTimePart = true;
2541 1629 : bExp = true; // Abuse for A/P
2542 1629 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2543 1629 : nPos = nPos + sStrArray[i].getLength();
2544 1629 : i++;
2545 1629 : break;
2546 : case NF_KEY_MI: // M
2547 : case NF_KEY_MMI: // MM
2548 : case NF_KEY_H: // H
2549 : case NF_KEY_HH: // HH
2550 : case NF_KEY_S: // S
2551 : case NF_KEY_SS: // SS
2552 8588 : bTimePart = true;
2553 8588 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2554 8588 : nPos = nPos + sStrArray[i].getLength();
2555 8588 : i++;
2556 8588 : break;
2557 : case NF_KEY_M: // M
2558 : case NF_KEY_MM: // MM
2559 : case NF_KEY_MMM: // MMM
2560 : case NF_KEY_MMMM: // MMMM
2561 : case NF_KEY_MMMMM: // MMMMM
2562 : case NF_KEY_Q: // Q
2563 : case NF_KEY_QQ: // QQ
2564 : case NF_KEY_D: // D
2565 : case NF_KEY_DD: // DD
2566 : case NF_KEY_DDD: // DDD
2567 : case NF_KEY_DDDD: // DDDD
2568 : case NF_KEY_YY: // YY
2569 : case NF_KEY_YYYY: // YYYY
2570 : case NF_KEY_NN: // NN
2571 : case NF_KEY_NNN: // NNN
2572 : case NF_KEY_NNNN: // NNNN
2573 : case NF_KEY_WW : // WW
2574 : case NF_KEY_AAA : // AAA
2575 : case NF_KEY_AAAA : // AAAA
2576 : case NF_KEY_EC : // E
2577 : case NF_KEY_EEC : // EE
2578 : case NF_KEY_G : // G
2579 : case NF_KEY_GG : // GG
2580 : case NF_KEY_GGG : // GGG
2581 : case NF_KEY_R : // R
2582 : case NF_KEY_RR : // RR
2583 10355 : bTimePart = false;
2584 10355 : sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
2585 10355 : nPos = nPos + sStrArray[i].getLength();
2586 10355 : i++;
2587 10355 : break;
2588 : case NF_KEY_THAI_T :
2589 0 : bThaiT = true;
2590 0 : sStrArray[i] = sKeyword[nTypeArray[i]];
2591 0 : nPos = nPos + sStrArray[i].getLength();
2592 0 : i++;
2593 0 : break;
2594 : default: // Other keywords
2595 0 : nTypeArray[i] = NF_SYMBOLTYPE_STRING;
2596 0 : nPos = nPos + sStrArray[i].getLength();
2597 0 : i++;
2598 0 : break;
2599 : }
2600 : } // of while
2601 3457 : nCntPost = nCounter; // decimals (100th seconds)
2602 3457 : if (bExp)
2603 : {
2604 1629 : nCntExp = 1; // Remembers AM/PM
2605 : }
2606 3457 : break; // of NUMBERFORMAT_DATETIME
2607 : default:
2608 0 : break;
2609 : }
2610 151648 : if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
2611 6808 : (nCntPre + nCntPost == 0 || nCntExp == 0))
2612 : {
2613 0 : return nPos;
2614 : }
2615 148244 : else if (eScannedType == NUMBERFORMAT_FRACTION && (nCntExp > 8 || nCntExp == 0))
2616 : {
2617 0 : return nPos;
2618 : }
2619 148244 : if (bThaiT && !GetNatNumModifier())
2620 : {
2621 0 : SetNatNumModifier(1);
2622 : }
2623 148244 : if ( bConvertMode )
2624 : {
2625 : // strings containing keywords of the target locale must be quoted, so
2626 : // the user sees the difference and is able to edit the format string
2627 42276 : for ( i=0; i < nAnzStrings; i++ )
2628 : {
2629 40872 : if ( nTypeArray[i] == NF_SYMBOLTYPE_STRING &&
2630 4604 : sStrArray[i][0] != '\"' )
2631 : {
2632 3080 : if ( bConvertSystemToSystem && eScannedType == NUMBERFORMAT_CURRENCY )
2633 : {
2634 : // don't stringize automatic currency, will be converted
2635 0 : if ( sStrArray[i] == sOldCurSymbol )
2636 : {
2637 0 : continue; // for
2638 : }
2639 : // DM might be splitted into D and M
2640 0 : if ( sStrArray[i].getLength() < sOldCurSymbol.getLength() &&
2641 0 : pChrCls->uppercase( sStrArray[i], 0, 1 )[0] ==
2642 0 : sOldCurString[0] )
2643 : {
2644 0 : OUString aTmp( sStrArray[i] );
2645 0 : sal_uInt16 j = i + 1;
2646 0 : while ( aTmp.getLength() < sOldCurSymbol.getLength() &&
2647 0 : j < nAnzStrings &&
2648 0 : nTypeArray[j] == NF_SYMBOLTYPE_STRING )
2649 : {
2650 0 : aTmp += sStrArray[j++];
2651 : }
2652 0 : if ( pChrCls->uppercase( aTmp ) == sOldCurString )
2653 : {
2654 0 : sStrArray[i++] = aTmp;
2655 0 : for ( ; i<j; i++ )
2656 : {
2657 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2658 0 : nAnzResStrings--;
2659 : }
2660 0 : i = j - 1;
2661 0 : continue; // for
2662 0 : }
2663 : }
2664 : }
2665 3080 : OUString& rStr = sStrArray[i];
2666 3080 : sal_Int32 nLen = rStr.getLength();
2667 7433 : for ( sal_Int32 j = 0; j < nLen; j++ )
2668 : {
2669 4353 : if ( (j == 0 || rStr[j - 1] != '\\') && GetKeyWord( rStr, j ) )
2670 : {
2671 0 : rStr = "\"" + rStr + "\"";
2672 0 : break; // for
2673 : }
2674 : }
2675 : }
2676 : }
2677 : }
2678 : // Concatenate strings, remove quotes for output, and rebuild the format string
2679 148244 : rString = "";
2680 148244 : i = 0;
2681 1511229 : while (i < nAnzStrings)
2682 : {
2683 : sal_Int32 nStringPos;
2684 1214741 : sal_Int32 nArrPos = 0;
2685 1214741 : sal_uInt16 iPos = i;
2686 1214741 : switch ( nTypeArray[i] )
2687 : {
2688 : case NF_SYMBOLTYPE_STRING :
2689 129353 : nStringPos = rString.getLength();
2690 158394 : do
2691 : {
2692 161447 : if (sStrArray[i].getLength() == 2 &&
2693 3053 : sStrArray[i][0] == '\\')
2694 : {
2695 : // Unescape some simple forms of symbols even in the UI
2696 : // visible string to prevent duplicates that differ
2697 : // only in notation, originating from import.
2698 : // e.g. YYYY-MM-DD and YYYY\-MM\-DD are identical,
2699 : // but 0\ 000 0 and 0 000 0 in a French locale are not.
2700 :
2701 1275 : sal_Unicode c = sStrArray[i][1];
2702 :
2703 1275 : switch (c)
2704 : {
2705 : case '+':
2706 : case '-':
2707 487 : rString += OUString(c);
2708 487 : break;
2709 : case ' ':
2710 : case '.':
2711 : case '/':
2712 782 : if (((eScannedType & NUMBERFORMAT_DATE) == 0) &&
2713 762 : (StringEqualsChar( pFormatter->GetNumThousandSep(), c) ||
2714 762 : StringEqualsChar( pFormatter->GetNumDecimalSep(), c) ||
2715 381 : (c == ' ' && StringEqualsChar( pFormatter->GetNumThousandSep(), cNonBreakingSpace))))
2716 : {
2717 0 : rString += sStrArray[i];
2718 : }
2719 421 : else if ((eScannedType & NUMBERFORMAT_DATE) &&
2720 20 : StringEqualsChar( pFormatter->GetDateSep(), c))
2721 : {
2722 2 : rString += sStrArray[i];
2723 : }
2724 405 : else if ((eScannedType & NUMBERFORMAT_TIME) &&
2725 12 : (StringEqualsChar( pLoc->getTimeSep(), c) ||
2726 6 : StringEqualsChar( pLoc->getTime100SecSep(), c)))
2727 : {
2728 0 : rString += sStrArray[i];
2729 : }
2730 399 : else if (eScannedType & NUMBERFORMAT_FRACTION)
2731 : {
2732 3 : rString += sStrArray[i];
2733 : }
2734 : else
2735 : {
2736 396 : rString += OUString(c);
2737 : }
2738 401 : break;
2739 : default:
2740 387 : rString += sStrArray[i];
2741 : }
2742 : }
2743 : else
2744 : {
2745 157119 : rString += sStrArray[i];
2746 : }
2747 158394 : if ( RemoveQuotes( sStrArray[i] ) > 0 )
2748 : {
2749 : // update currency up to quoted string
2750 3061 : if ( eScannedType == NUMBERFORMAT_CURRENCY )
2751 : {
2752 : // dM -> DM or DM -> $ in old automatic
2753 : // currency formats, oh my ..., why did we ever introduce them?
2754 22 : OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
2755 44 : sStrArray[iPos].getLength()-nArrPos ) );
2756 22 : sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
2757 22 : if ( nCPos >= 0 )
2758 : {
2759 0 : const OUString& rCur = bConvertMode && bConvertSystemToSystem ?
2760 0 : GetCurSymbol() : sOldCurSymbol;
2761 0 : sStrArray[iPos] = sStrArray[iPos].replaceAt( nArrPos + nCPos,
2762 : sOldCurString.getLength(),
2763 0 : rCur );
2764 0 : rString = rString.replaceAt( nStringPos + nCPos,
2765 : sOldCurString.getLength(),
2766 0 : rCur );
2767 : }
2768 22 : nStringPos = rString.getLength();
2769 22 : if ( iPos == i )
2770 : {
2771 22 : nArrPos = sStrArray[iPos].getLength();
2772 : }
2773 : else
2774 : {
2775 0 : nArrPos = sStrArray[iPos].getLength() + sStrArray[i].getLength();
2776 22 : }
2777 : }
2778 : }
2779 158394 : if ( iPos != i )
2780 : {
2781 29041 : sStrArray[iPos] += sStrArray[i];
2782 29041 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2783 29041 : nAnzResStrings--;
2784 : }
2785 158394 : i++;
2786 : }
2787 310690 : while ( i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_STRING );
2788 :
2789 129353 : if ( i < nAnzStrings )
2790 : {
2791 123255 : i--; // enter switch on next symbol again
2792 : }
2793 129353 : if ( eScannedType == NUMBERFORMAT_CURRENCY && nStringPos < rString.getLength() )
2794 : {
2795 : // same as above, since last RemoveQuotes
2796 31465 : OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
2797 62930 : sStrArray[iPos].getLength()-nArrPos ) );
2798 31465 : sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
2799 31465 : if ( nCPos >= 0 )
2800 : {
2801 361 : const OUString& rCur = bConvertMode && bConvertSystemToSystem ?
2802 17097 : GetCurSymbol() : sOldCurSymbol;
2803 34194 : sStrArray[iPos] = sStrArray[iPos].replaceAt( nArrPos + nCPos,
2804 : sOldCurString.getLength(),
2805 17097 : rCur );
2806 34194 : rString = rString.replaceAt( nStringPos + nCPos,
2807 17097 : sOldCurString.getLength(), rCur );
2808 31465 : }
2809 : }
2810 129353 : break;
2811 : case NF_SYMBOLTYPE_CURRENCY :
2812 23958 : rString += sStrArray[i];
2813 23958 : RemoveQuotes( sStrArray[i] );
2814 23958 : break;
2815 : case NF_KEY_THAI_T:
2816 0 : if (bThaiT && GetNatNumModifier() == 1)
2817 : {
2818 : // Remove T from format code, will be replaced with a [NatNum1] prefix.
2819 0 : nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
2820 0 : nAnzResStrings--;
2821 : }
2822 : else
2823 : {
2824 0 : rString += sStrArray[i];
2825 : }
2826 0 : break;
2827 : case NF_SYMBOLTYPE_EMPTY :
2828 : // nothing
2829 344624 : break;
2830 : default:
2831 716806 : rString += sStrArray[i];
2832 : }
2833 1214741 : i++;
2834 : }
2835 296488 : return 0;
2836 : }
2837 :
2838 182352 : sal_Int32 ImpSvNumberformatScan::RemoveQuotes( OUString& rStr )
2839 : {
2840 182352 : if ( rStr.getLength() > 1 )
2841 : {
2842 6901 : sal_Unicode c = rStr[0];
2843 6901 : sal_Int32 n = rStr.getLength() - 1;
2844 6901 : if ( c == '"' && rStr[n] == '"' )
2845 : {
2846 1786 : rStr = rStr.copy( 1, n-1);
2847 1786 : return 2;
2848 : }
2849 5115 : else if ( c == '\\' )
2850 : {
2851 1275 : rStr = rStr.copy(1);
2852 1275 : return 1;
2853 : }
2854 : }
2855 179291 : return 0;
2856 : }
2857 :
2858 148244 : sal_Int32 ImpSvNumberformatScan::ScanFormat( OUString& rString )
2859 : {
2860 148244 : sal_Int32 res = Symbol_Division(rString); // Lexical analysis
2861 148244 : if (!res)
2862 : {
2863 148244 : res = ScanType(); // Recognizing the Format type
2864 : }
2865 148244 : if (!res)
2866 : {
2867 148244 : res = FinalScan( rString ); // Type dependent final analysis
2868 : }
2869 148244 : return res; // res = control position; res = 0 => Format ok
2870 : }
2871 :
2872 148244 : void ImpSvNumberformatScan::CopyInfo(ImpSvNumberformatInfo* pInfo, sal_uInt16 nAnz)
2873 : {
2874 : size_t i,j;
2875 148244 : j = 0;
2876 148244 : i = 0;
2877 1463863 : while (i < nAnz && j < NF_MAX_FORMAT_SYMBOLS)
2878 : {
2879 1167375 : if (nTypeArray[j] != NF_SYMBOLTYPE_EMPTY)
2880 : {
2881 870117 : pInfo->sStrArray[i] = sStrArray[j];
2882 870117 : pInfo->nTypeArray[i] = nTypeArray[j];
2883 870117 : i++;
2884 : }
2885 1167375 : j++;
2886 : }
2887 148244 : pInfo->eScannedType = eScannedType;
2888 148244 : pInfo->bThousand = bThousand;
2889 148244 : pInfo->nThousand = nThousand;
2890 148244 : pInfo->nCntPre = nCntPre;
2891 148244 : pInfo->nCntPost = nCntPost;
2892 148244 : pInfo->nCntExp = nCntExp;
2893 148244 : }
2894 :
2895 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|