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