1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: zforscan.cxx,v $
10 * $Revision: 1.49.140.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
37 #include <tools/debug.hxx>
38 #include <i18npool/mslangid.hxx>
39 #include <unotools/charclass.hxx>
40 #include <unotools/localedatawrapper.hxx>
41 #include <unotools/numberformatcodewrapper.hxx>
42 #include <rtl/instance.hxx>
44 #include <svtools/zforlist.hxx>
45 #include <svtools/zformat.hxx>
46 #include <unotools/digitgroupingiterator.hxx>
49 #include "zforscan.hxx"
51 #include "nfsymbol.hxx"
54 const sal_Unicode cNonBreakingSpace
= 0xA0;
58 struct ImplEnglishColors
60 const String
* operator()()
62 static const String aEnglishColors
[NF_MAX_DEFAULT_COLORS
] =
64 String( RTL_CONSTASCII_USTRINGPARAM( "BLACK" ) ),
65 String( RTL_CONSTASCII_USTRINGPARAM( "BLUE" ) ),
66 String( RTL_CONSTASCII_USTRINGPARAM( "GREEN" ) ),
67 String( RTL_CONSTASCII_USTRINGPARAM( "CYAN" ) ),
68 String( RTL_CONSTASCII_USTRINGPARAM( "RED" ) ),
69 String( RTL_CONSTASCII_USTRINGPARAM( "MAGENTA" ) ),
70 String( RTL_CONSTASCII_USTRINGPARAM( "BROWN" ) ),
71 String( RTL_CONSTASCII_USTRINGPARAM( "GREY" ) ),
72 String( RTL_CONSTASCII_USTRINGPARAM( "YELLOW" ) ),
73 String( RTL_CONSTASCII_USTRINGPARAM( "WHITE" ) )
75 return &aEnglishColors
[0];
79 struct theEnglishColors
80 : public rtl::StaticAggregate
< const String
, ImplEnglishColors
> {};
84 ImpSvNumberformatScan::ImpSvNumberformatScan( SvNumberFormatter
* pFormatterP
)
86 pFormatter
= pFormatterP
;
88 //! All keywords MUST be UPPERCASE!
89 sKeyword
[NF_KEY_E
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "E" ) ); // Exponent
90 sKeyword
[NF_KEY_AMPM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AM/PM" ) ); // AM/PM
91 sKeyword
[NF_KEY_AP
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "A/P" ) ); // AM/PM short
92 sKeyword
[NF_KEY_MI
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "M" ) ); // Minute
93 sKeyword
[NF_KEY_MMI
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MM" ) ); // Minute 02
94 sKeyword
[NF_KEY_S
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "S" ) ); // Second
95 sKeyword
[NF_KEY_SS
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "SS" ) ); // Second 02
96 sKeyword
[NF_KEY_Q
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Q" ) ); // Quarter short 'Q'
97 sKeyword
[NF_KEY_QQ
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "QQ" ) ); // Quarter long
98 sKeyword
[NF_KEY_NN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NN" ) ); // Day of week short
99 sKeyword
[NF_KEY_NNN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NNN" ) ); // Day of week long
100 sKeyword
[NF_KEY_NNNN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NNNN" ) ); // Day of week long incl. separator
101 sKeyword
[NF_KEY_WW
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "WW" ) ); // Week of year
102 sKeyword
[NF_KEY_CCC
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "CCC" ) ); // Currency abbreviation
103 bKeywordsNeedInit
= TRUE
; // locale dependent keywords
104 bCompatCurNeedInit
= TRUE
; // locale dependent compatibility currency strings
106 StandardColor
[0] = Color(COL_BLACK
);
107 StandardColor
[1] = Color(COL_LIGHTBLUE
);
108 StandardColor
[2] = Color(COL_LIGHTGREEN
);
109 StandardColor
[3] = Color(COL_LIGHTCYAN
);
110 StandardColor
[4] = Color(COL_LIGHTRED
);
111 StandardColor
[5] = Color(COL_LIGHTMAGENTA
);
112 StandardColor
[6] = Color(COL_BROWN
);
113 StandardColor
[7] = Color(COL_GRAY
);
114 StandardColor
[8] = Color(COL_YELLOW
);
115 StandardColor
[9] = Color(COL_WHITE
);
117 pNullDate
= new Date(30,12,1899);
120 sErrStr
.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "###" ) );
124 ImpSvNumberformatScan::~ImpSvNumberformatScan()
131 void ImpSvNumberformatScan::ChangeIntl()
133 bKeywordsNeedInit
= TRUE
;
134 bCompatCurNeedInit
= TRUE
;
135 // may be initialized by InitSpecialKeyword()
136 sKeyword
[NF_KEY_TRUE
].Erase();
137 sKeyword
[NF_KEY_FALSE
].Erase();
141 void ImpSvNumberformatScan::InitSpecialKeyword( NfKeywordIndex eIdx
) const
146 ((ImpSvNumberformatScan
*)this)->sKeyword
[NF_KEY_TRUE
] =
147 pFormatter
->GetCharClass()->upper(
148 pFormatter
->GetLocaleData()->getTrueWord() );
149 if ( !sKeyword
[NF_KEY_TRUE
].Len() )
151 DBG_ERRORFILE( "InitSpecialKeyword: TRUE_WORD?" );
152 ((ImpSvNumberformatScan
*)this)->sKeyword
[NF_KEY_TRUE
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TRUE" ) );
156 ((ImpSvNumberformatScan
*)this)->sKeyword
[NF_KEY_FALSE
] =
157 pFormatter
->GetCharClass()->upper(
158 pFormatter
->GetLocaleData()->getFalseWord() );
159 if ( !sKeyword
[NF_KEY_FALSE
].Len() )
161 DBG_ERRORFILE( "InitSpecialKeyword: FALSE_WORD?" );
162 ((ImpSvNumberformatScan
*)this)->sKeyword
[NF_KEY_FALSE
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "FALSE" ) );
166 DBG_ERRORFILE( "InitSpecialKeyword: unknown request" );
171 void ImpSvNumberformatScan::InitCompatCur() const
173 ImpSvNumberformatScan
* pThis
= (ImpSvNumberformatScan
*)this;
174 // currency symbol for old style ("automatic") compatibility format codes
175 pFormatter
->GetCompatibilityCurrency( pThis
->sCurSymbol
, pThis
->sCurAbbrev
);
176 // currency symbol upper case
177 pThis
->sCurString
= pFormatter
->GetCharClass()->upper( sCurSymbol
);
178 bCompatCurNeedInit
= FALSE
;
182 void ImpSvNumberformatScan::InitKeywords() const
184 if ( !bKeywordsNeedInit
)
186 ((ImpSvNumberformatScan
*)this)->SetDependentKeywords();
187 bKeywordsNeedInit
= FALSE
;
191 /** Extract the name of General, Standard, Whatever, ignoring leading modifiers
192 such as [NatNum1]. */
193 static String
lcl_extractStandardGeneralName( const ::rtl::OUString
& rCode
)
196 const sal_Unicode
* p
= rCode
.getStr();
197 const sal_Unicode
* const pStop
= p
+ rCode
.getLength();
198 const sal_Unicode
* pBeg
= p
; // name begins here
201 while (p
< pStop
&& !bDone
)
214 // else: would be a locale data error, easily to be spotted in
221 --p
; // put back, increment by one follows
230 aStr
= rCode
.copy( pBeg
- rCode
.getStr(), p
- pBeg
);
235 void ImpSvNumberformatScan::SetDependentKeywords()
237 using namespace ::com::sun::star
;
238 using namespace ::com::sun::star::uno
;
240 const CharClass
* pCharClass
= pFormatter
->GetCharClass();
241 const LocaleDataWrapper
* pLocaleData
= pFormatter
->GetLocaleData();
242 // #80023# be sure to generate keywords for the loaded Locale, not for the
243 // requested Locale, otherwise number format codes might not match
244 lang::Locale aLoadedLocale
= pLocaleData
->getLoadedLocale();
245 LanguageType eLang
= MsLangId::convertLocaleToLanguage( aLoadedLocale
);
246 NumberFormatCodeWrapper
aNumberFormatCode( pFormatter
->GetServiceManager(), aLoadedLocale
);
248 i18n::NumberFormatCode aFormat
= aNumberFormatCode
.getFormatCode( NF_NUMBER_STANDARD
);
249 sNameStandardFormat
= lcl_extractStandardGeneralName( aFormat
.Code
);
250 sKeyword
[NF_KEY_GENERAL
] = pCharClass
->upper( sNameStandardFormat
);
252 // preset new calendar keywords
253 sKeyword
[NF_KEY_AAA
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AAA" ) );
254 sKeyword
[NF_KEY_AAAA
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AAAA" ) );
255 sKeyword
[NF_KEY_EC
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "E" ) );
256 sKeyword
[NF_KEY_EEC
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "EE" ) );
257 sKeyword
[NF_KEY_G
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "G" ) );
258 sKeyword
[NF_KEY_GG
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GG" ) );
259 sKeyword
[NF_KEY_GGG
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GGG" ) );
260 sKeyword
[NF_KEY_R
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "R" ) );
261 sKeyword
[NF_KEY_RR
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "RR" ) );
263 // Thai T NatNum special. Other locale's small letter 't' results in upper
264 // case comparison not matching but length does in conversion mode. Ugly.
265 if (eLang
== LANGUAGE_THAI
)
266 sKeyword
[NF_KEY_THAI_T
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "T"));
268 sKeyword
[NF_KEY_THAI_T
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "t"));
272 case LANGUAGE_GERMAN
:
273 case LANGUAGE_GERMAN_SWISS
:
274 case LANGUAGE_GERMAN_AUSTRIAN
:
275 case LANGUAGE_GERMAN_LUXEMBOURG
:
276 case LANGUAGE_GERMAN_LIECHTENSTEIN
:
278 //! all capital letters
279 sKeyword
[NF_KEY_M
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "M" ) ); // month 1
280 sKeyword
[NF_KEY_MM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MM" ) ); // month 01
281 sKeyword
[NF_KEY_MMM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMM" ) ); // month Jan
282 sKeyword
[NF_KEY_MMMM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMM" ) ); // month Januar
283 sKeyword
[NF_KEY_MMMMM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMMM" ) );// month J
284 sKeyword
[NF_KEY_H
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "H" ) ); // hour 2
285 sKeyword
[NF_KEY_HH
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "HH" ) ); // hour 02
286 sKeyword
[NF_KEY_D
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "T" ) );
287 sKeyword
[NF_KEY_DD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TT" ) );
288 sKeyword
[NF_KEY_DDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TTT" ) );
289 sKeyword
[NF_KEY_DDDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TTTT" ) );
290 sKeyword
[NF_KEY_YY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJ" ) );
291 sKeyword
[NF_KEY_YYYY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJJ" ) );
292 sKeyword
[NF_KEY_BOOLEAN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "LOGISCH" ) );
293 sKeyword
[NF_KEY_COLOR
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "FARBE" ) );
294 sKeyword
[NF_KEY_BLACK
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "SCHWARZ" ) );
295 sKeyword
[NF_KEY_BLUE
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BLAU" ) );
296 sKeyword
[NF_KEY_GREEN
] = UniString( "GR" "\xDC" "N", RTL_TEXTENCODING_ISO_8859_1
);
297 sKeyword
[NF_KEY_CYAN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "CYAN" ) );
298 sKeyword
[NF_KEY_RED
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "ROT" ) );
299 sKeyword
[NF_KEY_MAGENTA
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MAGENTA" ) );
300 sKeyword
[NF_KEY_BROWN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BRAUN" ) );
301 sKeyword
[NF_KEY_GREY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GRAU" ) );
302 sKeyword
[NF_KEY_YELLOW
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GELB" ) );
303 sKeyword
[NF_KEY_WHITE
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "WEISS" ) );
311 case LANGUAGE_ITALIAN
:
312 case LANGUAGE_ITALIAN_SWISS
:
313 sKeyword
[NF_KEY_D
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "G" ) );
314 sKeyword
[NF_KEY_DD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GG" ) );
315 sKeyword
[NF_KEY_DDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GGG" ) );
316 sKeyword
[NF_KEY_DDDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GGGG" ) );
317 // must exchange the era code, same as Xcl
318 sKeyword
[NF_KEY_G
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "X" ) );
319 sKeyword
[NF_KEY_GG
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "XX" ) );
320 sKeyword
[NF_KEY_GGG
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "XXX" ) );
322 case LANGUAGE_FRENCH
:
323 case LANGUAGE_FRENCH_BELGIAN
:
324 case LANGUAGE_FRENCH_CANADIAN
:
325 case LANGUAGE_FRENCH_SWISS
:
326 case LANGUAGE_FRENCH_LUXEMBOURG
:
327 case LANGUAGE_FRENCH_MONACO
:
328 sKeyword
[NF_KEY_D
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "J" ) );
329 sKeyword
[NF_KEY_DD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJ" ) );
330 sKeyword
[NF_KEY_DDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJ" ) );
331 sKeyword
[NF_KEY_DDDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJJ" ) );
333 case LANGUAGE_FINNISH
:
334 sKeyword
[NF_KEY_D
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "P" ) );
335 sKeyword
[NF_KEY_DD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "PP" ) );
336 sKeyword
[NF_KEY_DDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "PPP" ) );
337 sKeyword
[NF_KEY_DDDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "PPPP" ) );
340 sKeyword
[NF_KEY_D
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D" ) );
341 sKeyword
[NF_KEY_DD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DD" ) );
342 sKeyword
[NF_KEY_DDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDD" ) );
343 sKeyword
[NF_KEY_DDDD
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDDD" ) );
348 case LANGUAGE_FINNISH
:
349 sKeyword
[NF_KEY_M
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "K" ) );
350 sKeyword
[NF_KEY_MM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KK" ) );
351 sKeyword
[NF_KEY_MMM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KKK" ) );
352 sKeyword
[NF_KEY_MMMM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KKKK" ) );
353 sKeyword
[NF_KEY_MMMMM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KKKKK" ) );
356 sKeyword
[NF_KEY_M
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "M" ) );
357 sKeyword
[NF_KEY_MM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MM" ) );
358 sKeyword
[NF_KEY_MMM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMM" ) );
359 sKeyword
[NF_KEY_MMMM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMM" ) );
360 sKeyword
[NF_KEY_MMMMM
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMMM" ) );
365 case LANGUAGE_ITALIAN
:
366 case LANGUAGE_ITALIAN_SWISS
:
367 case LANGUAGE_FRENCH
:
368 case LANGUAGE_FRENCH_BELGIAN
:
369 case LANGUAGE_FRENCH_CANADIAN
:
370 case LANGUAGE_FRENCH_SWISS
:
371 case LANGUAGE_FRENCH_LUXEMBOURG
:
372 case LANGUAGE_FRENCH_MONACO
:
373 case LANGUAGE_PORTUGUESE
:
374 case LANGUAGE_PORTUGUESE_BRAZILIAN
:
375 case LANGUAGE_SPANISH_MODERN
:
376 case LANGUAGE_SPANISH_DATED
:
377 case LANGUAGE_SPANISH_MEXICAN
:
378 case LANGUAGE_SPANISH_GUATEMALA
:
379 case LANGUAGE_SPANISH_COSTARICA
:
380 case LANGUAGE_SPANISH_PANAMA
:
381 case LANGUAGE_SPANISH_DOMINICAN_REPUBLIC
:
382 case LANGUAGE_SPANISH_VENEZUELA
:
383 case LANGUAGE_SPANISH_COLOMBIA
:
384 case LANGUAGE_SPANISH_PERU
:
385 case LANGUAGE_SPANISH_ARGENTINA
:
386 case LANGUAGE_SPANISH_ECUADOR
:
387 case LANGUAGE_SPANISH_CHILE
:
388 case LANGUAGE_SPANISH_URUGUAY
:
389 case LANGUAGE_SPANISH_PARAGUAY
:
390 case LANGUAGE_SPANISH_BOLIVIA
:
391 case LANGUAGE_SPANISH_EL_SALVADOR
:
392 case LANGUAGE_SPANISH_HONDURAS
:
393 case LANGUAGE_SPANISH_NICARAGUA
:
394 case LANGUAGE_SPANISH_PUERTO_RICO
:
395 sKeyword
[NF_KEY_YY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AA" ) );
396 sKeyword
[NF_KEY_YYYY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AAAA" ) );
397 // must exchange the day of week name code, same as Xcl
398 sKeyword
[NF_KEY_AAA
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "OOO" ) );
399 sKeyword
[NF_KEY_AAAA
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "OOOO" ) );
401 case LANGUAGE_DUTCH
:
402 case LANGUAGE_DUTCH_BELGIAN
:
403 sKeyword
[NF_KEY_YY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJ" ) );
404 sKeyword
[NF_KEY_YYYY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJJ" ) );
406 case LANGUAGE_FINNISH
:
407 sKeyword
[NF_KEY_YY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "VV" ) );
408 sKeyword
[NF_KEY_YYYY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "VVVV" ) );
411 sKeyword
[NF_KEY_YY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "YY" ) );
412 sKeyword
[NF_KEY_YYYY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "YYYY" ) );
417 case LANGUAGE_DUTCH
:
418 case LANGUAGE_DUTCH_BELGIAN
:
419 sKeyword
[NF_KEY_H
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "U" ) );
420 sKeyword
[NF_KEY_HH
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "UU" ) );
422 case LANGUAGE_FINNISH
:
423 case LANGUAGE_SWEDISH
:
424 case LANGUAGE_SWEDISH_FINLAND
:
425 case LANGUAGE_DANISH
:
426 case LANGUAGE_NORWEGIAN
:
427 case LANGUAGE_NORWEGIAN_BOKMAL
:
428 case LANGUAGE_NORWEGIAN_NYNORSK
:
429 sKeyword
[NF_KEY_H
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "T" ) );
430 sKeyword
[NF_KEY_HH
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TT" ) );
433 sKeyword
[NF_KEY_H
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "H" ) );
434 sKeyword
[NF_KEY_HH
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "HH" ) );
437 sKeyword
[NF_KEY_BOOLEAN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BOOLEAN" ) );
439 sKeyword
[NF_KEY_COLOR
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "COLOR" ) );
440 sKeyword
[NF_KEY_BLACK
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BLACK" ) );
441 sKeyword
[NF_KEY_BLUE
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BLUE" ) );
442 sKeyword
[NF_KEY_GREEN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GREEN" ) );
443 sKeyword
[NF_KEY_CYAN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "CYAN" ) );
444 sKeyword
[NF_KEY_RED
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "RED" ) );
445 sKeyword
[NF_KEY_MAGENTA
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MAGENTA" ) );
446 sKeyword
[NF_KEY_BROWN
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BROWN" ) );
447 sKeyword
[NF_KEY_GREY
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GREY" ) );
448 sKeyword
[NF_KEY_YELLOW
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "YELLOW" ) );
449 sKeyword
[NF_KEY_WHITE
].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "WHITE" ) );
455 InitSpecialKeyword( NF_KEY_TRUE
);
456 InitSpecialKeyword( NF_KEY_FALSE
);
458 // compatibility currency strings
463 void ImpSvNumberformatScan::ChangeNullDate(USHORT nDay
, USHORT nMonth
, USHORT nYear
)
466 *pNullDate
= Date(nDay
, nMonth
, nYear
);
468 pNullDate
= new Date(nDay
, nMonth
, nYear
);
471 void ImpSvNumberformatScan::ChangeStandardPrec(short nPrec
)
473 nStandardPrec
= nPrec
;
476 Color
* ImpSvNumberformatScan::GetColor(String
& sStr
)
478 String sString
= pFormatter
->GetCharClass()->upper(sStr
);
479 const String
* pKeyword
= GetKeywords();
481 while (i
< NF_MAX_DEFAULT_COLORS
&&
482 sString
!= pKeyword
[NF_KEY_FIRSTCOLOR
+i
] )
484 if ( i
>= NF_MAX_DEFAULT_COLORS
)
486 const String
* pEnglishColors
= theEnglishColors::get();
488 while ( j
< NF_MAX_DEFAULT_COLORS
&&
489 sString
!= pEnglishColors
[j
] )
491 if ( j
< NF_MAX_DEFAULT_COLORS
)
494 if (i
>= NF_MAX_DEFAULT_COLORS
)
496 const String
& rColorWord
= pKeyword
[NF_KEY_COLOR
];
497 xub_StrLen nPos
= sString
.Match(rColorWord
);
501 sStr
.EraseLeadingChars();
502 sStr
.EraseTrailingChars();
505 pFormatter
->ChangeIntl(eNewLnge
);
506 sStr
.Insert( GetKeywords()[NF_KEY_COLOR
], 0 ); // Color -> FARBE
507 pFormatter
->ChangeIntl(eTmpLnge
);
510 sStr
.Insert(rColorWord
,0);
511 sString
.Erase(0, nPos
);
512 sString
.EraseLeadingChars();
513 sString
.EraseTrailingChars();
515 if ( CharClass::isAsciiNumeric( sString
) )
517 long nIndex
= sString
.ToInt32();
518 if (nIndex
> 0 && nIndex
<= 64)
519 return pFormatter
->GetUserDefColor((USHORT
)nIndex
-1);
534 pFormatter
->ChangeIntl(eNewLnge
);
535 sStr
= GetKeywords()[NF_KEY_FIRSTCOLOR
+i
]; // red -> rot
536 pFormatter
->ChangeIntl(eTmpLnge
);
539 sStr
= pKeyword
[NF_KEY_FIRSTCOLOR
+i
];
541 return &(StandardColor
[i
]);
546 short ImpSvNumberformatScan::GetKeyWord( const String
& sSymbol
, xub_StrLen nPos
)
548 String sString
= pFormatter
->GetCharClass()->toUpper( sSymbol
, nPos
, sSymbol
.Len() - nPos
);
549 const String
* pKeyword
= GetKeywords();
550 // #77026# for the Xcl perverts: the GENERAL keyword is recognized anywhere
551 if ( sString
.Search( pKeyword
[NF_KEY_GENERAL
] ) == 0 )
552 return NF_KEY_GENERAL
;
553 //! MUST be a reverse search to find longer strings first
554 short i
= NF_KEYWORD_ENTRIES_COUNT
-1;
556 for ( ; i
> NF_KEY_LASTKEYWORD_SO5
; --i
)
558 bFound
= sString
.Search(pKeyword
[i
]) == 0;
564 // new keywords take precedence over old keywords
566 { // skip the gap of colors et al between new and old keywords and search on
567 i
= NF_KEY_LASTKEYWORD
;
568 while ( i
> 0 && sString
.Search(pKeyword
[i
]) != 0 )
570 if ( i
> NF_KEY_LASTOLDKEYWORD
&& sString
!= pKeyword
[i
] )
571 { // found something, but maybe it's something else?
572 // e.g. new NNN is found in NNNN, for NNNN we must search on
574 while ( j
> 0 && sString
.Search(pKeyword
[j
]) != 0 )
576 if ( j
&& pKeyword
[j
].Len() > pKeyword
[i
].Len() )
580 // The Thai T NatNum modifier during Xcl import.
581 if (i
== 0 && bConvertMode
&& sString
.GetChar(0) == 'T' && eTmpLnge
==
582 LANGUAGE_ENGLISH_US
&& MsLangId::getRealLanguage( eNewLnge
) ==
585 return i
; // 0 => not found
588 //---------------------------------------------------------------------------
590 //---------------------------------------------------------------------------
591 // Zerlegt die Eingabe in Symbole fuer die weitere
592 // Verarbeitung (Turing-Maschine).
593 //---------------------------------------------------------------------------
594 // Ausgangs Zustand = SsStart
595 //---------------+-------------------+-----------------------+---------------
596 // Alter Zustand | gelesenes Zeichen | Aktion | Neuer Zustand
597 //---------------+-------------------+-----------------------+---------------
598 // SsStart | Buchstabe | Symbol=Zeichen | SsGetWord
599 // | " | Typ = String | SsGetString
600 // | \ | Typ = String | SsGetChar
601 // | * | Typ = Star | SsGetStar
602 // | _ | Typ = Blank | SsGetBlank
603 // | @ # 0 ? / . , % [ | Symbol = Zeichen; |
604 // | ] ' Blank | Typ = Steuerzeichen | SsStop
605 // | $ - + ( ) : | Typ = String; |
606 // | | | Typ = Comment | SsStop
607 // | Sonst | Symbol = Zeichen | SsStop
608 //---------------|-------------------+-----------------------+---------------
609 // SsGetChar | Sonst | Symbol=Zeichen | SsStop
610 //---------------+-------------------+-----------------------+---------------
611 // GetString | " | | SsStop
612 // | Sonst | Symbol+=Zeichen | GetString
613 //---------------+-------------------+-----------------------+---------------
614 // SsGetWord | Buchstabe | Symbol += Zeichen |
615 // | + - (E+ E-)| Symbol += Zeichen | SsStop
616 // | / (AM/PM)| Symbol += Zeichen |
617 // | Sonst | Pos--, if Key Typ=Word| SsStop
618 //---------------+-------------------+-----------------------+---------------
619 // SsGetStar | Sonst | Symbol+=Zeichen | SsStop
620 // | | markiere Sonderfall * |
621 //---------------+-------------------+-----------------------+---------------
622 // SsGetBlank | Sonst | Symbol+=Zeichen | SsStop
623 // | | markiere Sonderfall _ |
624 //---------------+-------------------+-----------------------+---------------
625 // Wurde im State SsGetWord ein Schluesselwort erkannt (auch als
626 // Anfangsteilwort des Symbols)
627 // so werden die restlichen Buchstaben zurueckgeschrieben !!
640 short ImpSvNumberformatScan::Next_Symbol( const String
& rStr
,
641 xub_StrLen
& nPos
, String
& sSymbol
)
643 if ( bKeywordsNeedInit
)
645 const CharClass
* pChrCls
= pFormatter
->GetCharClass();
646 const LocaleDataWrapper
* pLoc
= pFormatter
->GetLocaleData();
647 const xub_StrLen nStart
= nPos
;
649 ScanState eState
= SsStart
;
651 while ( nPos
< rStr
.Len() && eState
!= SsStop
)
653 sal_Unicode cToken
= rStr
.GetChar( nPos
++ );
658 // Fetch any currency longer than one character and don't get
659 // confused later on by "E/" or other combinations of letters
660 // and meaningful symbols. Necessary for old automatic currency.
661 // #96158# But don't do it if we're starting a "[...]" section,
662 // for example a "[$...]" new currency symbol to not parse away
663 // "$U" (symbol) of "[$UYU]" (abbreviation).
664 if ( nCurrPos
!= STRING_NOTFOUND
&& sCurString
.Len() > 1 &&
665 nPos
-1 + sCurString
.Len() <= rStr
.Len() &&
666 !(nPos
> 1 && rStr
.GetChar( nPos
-2 ) == '[') )
668 String
aTest( rStr
.Copy( nPos
-1, sCurString
.Len() ) );
669 pChrCls
->toUpper( aTest
);
670 if ( aTest
== sCurString
)
672 sSymbol
= rStr
.Copy( --nPos
, sCurString
.Len() );
673 nPos
= nPos
+ sSymbol
.Len();
675 eType
= NF_SYMBOLTYPE_STRING
;
696 eType
= NF_SYMBOLTYPE_DEL
;
703 eType
= NF_SYMBOLTYPE_STAR
;
710 eType
= NF_SYMBOLTYPE_BLANK
;
715 #if NF_COMMENT_IN_FORMATSTRING
717 eType
= NF_SYMBOLTYPE_COMMENT
;
719 sSymbol
.Append( rStr
.GetBuffer() + (nPos
-1), rStr
.Len() - (nPos
-1) );
724 eType
= NF_SYMBOLTYPE_STRING
;
725 eState
= SsGetString
;
729 eType
= NF_SYMBOLTYPE_STRING
;
737 eType
= NF_SYMBOLTYPE_STRING
;
743 if (StringEqualsChar( pFormatter
->GetNumDecimalSep(), cToken
) ||
744 StringEqualsChar( pFormatter
->GetNumThousandSep(), cToken
) ||
745 StringEqualsChar( pFormatter
->GetDateSep(), cToken
) ||
746 StringEqualsChar( pLoc
->getTimeSep(), cToken
) ||
747 StringEqualsChar( pLoc
->getTime100SecSep(), cToken
))
749 // Another separator than pre-known ASCII
750 eType
= NF_SYMBOLTYPE_DEL
;
754 else if ( pChrCls
->isLetter( rStr
, nPos
-1 ) )
756 short nTmpType
= GetKeyWord( rStr
, nPos
-1 );
759 BOOL bCurrency
= FALSE
;
760 // "Automatic" currency may start with keyword,
761 // like "R" (Rand) and 'R' (era)
762 if ( nCurrPos
!= STRING_NOTFOUND
&&
763 nPos
-1 + sCurString
.Len() <= rStr
.Len() &&
764 sCurString
.Search( sKeyword
[nTmpType
] ) == 0 )
766 String
aTest( rStr
.Copy( nPos
-1, sCurString
.Len() ) );
767 pChrCls
->toUpper( aTest
);
768 if ( aTest
== sCurString
)
779 xub_StrLen nLen
= sKeyword
[eType
].Len();
780 sSymbol
= rStr
.Copy( nPos
-1, nLen
);
781 if ( eType
== NF_KEY_E
|| IsAmbiguousE( eType
) )
783 sal_Unicode cNext
= rStr
.GetChar(nPos
);
787 case '-' : // E+ E- combine to one symbol
793 case '#' : // scientific E without sign
811 eType
= NF_SYMBOLTYPE_STRING
;
835 if ( pChrCls
->isLetter( rStr
, nPos
-1 ) )
837 short nTmpType
= GetKeyWord( rStr
, nPos
-1 );
839 { // beginning of keyword, stop scan and put back
840 eType
= NF_SYMBOLTYPE_STRING
;
849 BOOL bDontStop
= FALSE
;
852 case '/': // AM/PM, A/P
854 sal_Unicode cNext
= rStr
.GetChar(nPos
);
855 if ( cNext
== 'P' || cNext
== 'p' )
857 xub_StrLen nLen
= sSymbol
.Len();
859 && (sSymbol
.GetChar(0) == 'A' || sSymbol
.GetChar(0) == 'a')
860 && (nLen
== 1 || (nLen
== 2
861 && (sSymbol
.GetChar(1) == 'M' || sSymbol
.GetChar(1) == 'm')
862 && (rStr
.GetChar(nPos
+1) == 'M' || rStr
.GetChar(nPos
+1) == 'm'))) )
871 // anything not recognized will stop the scan
872 if ( eState
!= SsStop
&& !bDontStop
)
876 eType
= NF_SYMBOLTYPE_STRING
;
885 nRepPos
= (nPos
- nStart
) - 1; // everytime > 0!!
898 if (eState
== SsGetWord
)
899 eType
= NF_SYMBOLTYPE_STRING
;
903 xub_StrLen
ImpSvNumberformatScan::Symbol_Division(const String
& rString
)
905 nCurrPos
= STRING_NOTFOUND
;
906 // Ist Waehrung im Spiel?
907 String sString
= pFormatter
->GetCharClass()->upper(rString
);
908 xub_StrLen nCPos
= 0;
909 while (nCPos
!= STRING_NOTFOUND
)
911 nCPos
= sString
.Search(GetCurString(),nCPos
);
912 if (nCPos
!= STRING_NOTFOUND
)
915 xub_StrLen nQ
= SvNumberformat::GetQuoteEnd( sString
, nCPos
);
916 if ( nQ
== STRING_NOTFOUND
)
920 ((c
= sString
.GetChar(xub_StrLen(nCPos
-1))) != '"'
921 && c
!= '\\') ) // dm kann durch "dm
922 { // \d geschuetzt werden
924 nCPos
= STRING_NOTFOUND
; // Abbruch
927 nCPos
++; // weitersuchen
930 nCPos
= nQ
+ 1; // weitersuchen
934 BOOL bStar
= FALSE
; // wird bei '*'Detektion gesetzt
938 const xub_StrLen nLen
= rString
.Len();
939 while (nPos
< nLen
&& nAnzStrings
< NF_MAX_FORMAT_SYMBOLS
)
941 nTypeArray
[nAnzStrings
] = Next_Symbol(rString
, nPos
, sStrArray
[nAnzStrings
]);
942 if (nTypeArray
[nAnzStrings
] == NF_SYMBOLTYPE_STAR
)
943 { // Ueberwachung des '*'
945 return nPos
; // Fehler: doppelter '*'
955 void ImpSvNumberformatScan::SkipStrings(USHORT
& i
, xub_StrLen
& nPos
)
957 while (i
< nAnzStrings
&& ( nTypeArray
[i
] == NF_SYMBOLTYPE_STRING
958 || nTypeArray
[i
] == NF_SYMBOLTYPE_BLANK
959 || nTypeArray
[i
] == NF_SYMBOLTYPE_STAR
) )
961 nPos
= nPos
+ sStrArray
[i
].Len();
967 USHORT
ImpSvNumberformatScan::PreviousKeyword(USHORT i
)
970 if (i
> 0 && i
< nAnzStrings
)
973 while (i
> 0 && nTypeArray
[i
] <= 0)
975 if (nTypeArray
[i
] > 0)
981 USHORT
ImpSvNumberformatScan::NextKeyword(USHORT i
)
984 if (i
< nAnzStrings
-1)
987 while (i
< nAnzStrings
-1 && nTypeArray
[i
] <= 0)
989 if (nTypeArray
[i
] > 0)
995 short ImpSvNumberformatScan::PreviousType( USHORT i
)
997 if ( i
> 0 && i
< nAnzStrings
)
1002 } while ( i
> 0 && nTypeArray
[i
] == NF_SYMBOLTYPE_EMPTY
);
1003 return nTypeArray
[i
];
1008 sal_Unicode
ImpSvNumberformatScan::PreviousChar(USHORT i
)
1010 sal_Unicode res
= ' ';
1011 if (i
> 0 && i
< nAnzStrings
)
1014 while (i
> 0 && ( nTypeArray
[i
] == NF_SYMBOLTYPE_EMPTY
1015 || nTypeArray
[i
] == NF_SYMBOLTYPE_STRING
1016 || nTypeArray
[i
] == NF_SYMBOLTYPE_STAR
1017 || nTypeArray
[i
] == NF_SYMBOLTYPE_BLANK
) )
1019 if (sStrArray
[i
].Len() > 0)
1020 res
= sStrArray
[i
].GetChar(xub_StrLen(sStrArray
[i
].Len()-1));
1025 sal_Unicode
ImpSvNumberformatScan::NextChar(USHORT i
)
1027 sal_Unicode res
= ' ';
1028 if (i
< nAnzStrings
-1)
1031 while (i
< nAnzStrings
-1 &&
1032 ( nTypeArray
[i
] == NF_SYMBOLTYPE_EMPTY
1033 || nTypeArray
[i
] == NF_SYMBOLTYPE_STRING
1034 || nTypeArray
[i
] == NF_SYMBOLTYPE_STAR
1035 || nTypeArray
[i
] == NF_SYMBOLTYPE_BLANK
))
1037 if (sStrArray
[i
].Len() > 0)
1038 res
= sStrArray
[i
].GetChar(0);
1043 BOOL
ImpSvNumberformatScan::IsLastBlankBeforeFrac(USHORT i
)
1046 if (i
< nAnzStrings
-1)
1050 while (i
< nAnzStrings
-1 && !bStop
)
1053 if ( nTypeArray
[i
] == NF_SYMBOLTYPE_DEL
&&
1054 sStrArray
[i
].GetChar(0) == '/')
1056 else if ( nTypeArray
[i
] == NF_SYMBOLTYPE_DEL
&&
1057 sStrArray
[i
].GetChar(0) == ' ')
1060 if (!bStop
) // kein '/'
1064 res
= FALSE
; // kein '/' mehr
1069 void ImpSvNumberformatScan::Reset()
1074 // ER 20.06.97 14:05 nicht noetig, wenn nAnzStrings beachtet wird
1075 for (size_t i
= 0; i
< NF_MAX_FORMAT_SYMBOLS
; i
++)
1077 sStrArray
[i
].Erase();
1081 eScannedType
= NUMBERFORMAT_UNDEFINED
;
1088 nExpPos
= (USHORT
) -1;
1089 nBlankPos
= (USHORT
) -1;
1095 nNatNumModifier
= 0;
1099 BOOL
ImpSvNumberformatScan::Is100SecZero( USHORT i
, BOOL bHadDecSep
)
1101 USHORT nIndexPre
= PreviousKeyword( i
);
1102 return (nIndexPre
== NF_KEY_S
|| nIndexPre
== NF_KEY_SS
)
1103 && (bHadDecSep
// S, SS ','
1104 || (i
>0 && nTypeArray
[i
-1] == NF_SYMBOLTYPE_STRING
));
1105 // SS"any"00 take "any" as a valid decimal separator
1109 xub_StrLen
ImpSvNumberformatScan::ScanType(const String
&)
1111 const LocaleDataWrapper
* pLoc
= pFormatter
->GetLocaleData();
1113 xub_StrLen nPos
= 0;
1116 BOOL bMatchBracket
= FALSE
;
1117 bool bHaveGeneral
= false; // if General/Standard encountered
1119 SkipStrings(i
, nPos
);
1120 while (i
< nAnzStrings
)
1122 if (nTypeArray
[i
] > 0)
1124 switch (nTypeArray
[i
])
1127 eNewType
= NUMBERFORMAT_SCIENTIFIC
;
1129 case NF_KEY_AMPM
: // AM,A,PM,P
1132 case NF_KEY_HH
: // HH
1134 case NF_KEY_SS
: // SS
1135 eNewType
= NUMBERFORMAT_TIME
;
1138 case NF_KEY_MM
: // MM
1139 { // minute or month
1140 USHORT nIndexPre
= PreviousKeyword(i
);
1141 USHORT nIndexNex
= NextKeyword(i
);
1142 sal_Unicode cChar
= PreviousChar(i
);
1143 if (nIndexPre
== NF_KEY_H
|| // H
1144 nIndexPre
== NF_KEY_HH
|| // HH
1145 nIndexNex
== NF_KEY_S
|| // S
1146 nIndexNex
== NF_KEY_SS
|| // SS
1147 cChar
== '[' ) // [M
1149 eNewType
= NUMBERFORMAT_TIME
;
1150 nTypeArray
[i
] -= 2; // 6 -> 4, 7 -> 5
1153 eNewType
= NUMBERFORMAT_DATE
;
1156 case NF_KEY_MMM
: // MMM
1157 case NF_KEY_MMMM
: // MMMM
1158 case NF_KEY_MMMMM
: // MMMMM
1160 case NF_KEY_QQ
: // QQ
1162 case NF_KEY_DD
: // DD
1163 case NF_KEY_DDD
: // DDD
1164 case NF_KEY_DDDD
: // DDDD
1165 case NF_KEY_YY
: // YY
1166 case NF_KEY_YYYY
: // YYYY
1167 case NF_KEY_NN
: // NN
1168 case NF_KEY_NNN
: // NNN
1169 case NF_KEY_NNNN
: // NNNN
1170 case NF_KEY_WW
: // WW
1171 case NF_KEY_AAA
: // AAA
1172 case NF_KEY_AAAA
: // AAAA
1173 case NF_KEY_EC
: // E
1174 case NF_KEY_EEC
: // EE
1175 case NF_KEY_G
: // G
1176 case NF_KEY_GG
: // GG
1177 case NF_KEY_GGG
: // GGG
1178 case NF_KEY_R
: // R
1179 case NF_KEY_RR
: // RR
1180 eNewType
= NUMBERFORMAT_DATE
;
1182 case NF_KEY_CCC
: // CCC
1183 eNewType
= NUMBERFORMAT_CURRENCY
;
1185 case NF_KEY_GENERAL
: // Standard
1186 eNewType
= NUMBERFORMAT_NUMBER
;
1187 bHaveGeneral
= true;
1190 eNewType
= NUMBERFORMAT_UNDEFINED
;
1195 { // control character
1196 switch ( sStrArray
[i
].GetChar(0) )
1200 eNewType
= NUMBERFORMAT_NUMBER
;
1204 if ( (eScannedType
& NUMBERFORMAT_TIME
) == NUMBERFORMAT_TIME
)
1206 if ( Is100SecZero( i
, bDecSep
) )
1208 bDecSep
= TRUE
; // subsequent 0's
1209 eNewType
= NUMBERFORMAT_TIME
;
1212 return nPos
; // Error
1215 eNewType
= NUMBERFORMAT_NUMBER
;
1219 eNewType
= NUMBERFORMAT_PERCENT
;
1222 eNewType
= NUMBERFORMAT_FRACTION
;
1226 if ( i
< nAnzStrings
-1 &&
1227 nTypeArray
[i
+1] == NF_SYMBOLTYPE_STRING
&&
1228 sStrArray
[i
+1].GetChar(0) == '$' )
1229 { // as of SV_NUMBERFORMATTER_VERSION_NEW_CURR
1230 eNewType
= NUMBERFORMAT_CURRENCY
;
1231 bMatchBracket
= TRUE
;
1233 else if ( i
< nAnzStrings
-1 &&
1234 nTypeArray
[i
+1] == NF_SYMBOLTYPE_STRING
&&
1235 sStrArray
[i
+1].GetChar(0) == '~' )
1236 { // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1237 eNewType
= NUMBERFORMAT_DATE
;
1238 bMatchBracket
= TRUE
;
1242 USHORT nIndexNex
= NextKeyword(i
);
1243 if (nIndexNex
== NF_KEY_H
|| // H
1244 nIndexNex
== NF_KEY_HH
|| // HH
1245 nIndexNex
== NF_KEY_M
|| // M
1246 nIndexNex
== NF_KEY_MM
|| // MM
1247 nIndexNex
== NF_KEY_S
|| // S
1248 nIndexNex
== NF_KEY_SS
) // SS
1249 eNewType
= NUMBERFORMAT_TIME
;
1251 return nPos
; // Error
1256 eNewType
= NUMBERFORMAT_TEXT
;
1259 if ( sStrArray
[i
] == pLoc
->getTime100SecSep() )
1260 bDecSep
= TRUE
; // for SS,0
1261 eNewType
= NUMBERFORMAT_UNDEFINED
;
1265 if (eScannedType
== NUMBERFORMAT_UNDEFINED
)
1266 eScannedType
= eNewType
;
1267 else if (eScannedType
== NUMBERFORMAT_TEXT
|| eNewType
== NUMBERFORMAT_TEXT
)
1268 eScannedType
= NUMBERFORMAT_TEXT
; // Text bleibt immer Text
1269 else if (eNewType
== NUMBERFORMAT_UNDEFINED
)
1270 { // bleibt wie bisher
1272 else if (eScannedType
!= eNewType
)
1274 switch (eScannedType
)
1276 case NUMBERFORMAT_DATE
:
1280 case NUMBERFORMAT_TIME
:
1281 eScannedType
= NUMBERFORMAT_DATETIME
;
1283 case NUMBERFORMAT_FRACTION
: // DD/MM
1287 if (nCurrPos
!= STRING_NOTFOUND
)
1288 eScannedType
= NUMBERFORMAT_UNDEFINED
;
1289 else if ( sStrArray
[i
] != pFormatter
->GetDateSep() )
1295 case NUMBERFORMAT_TIME
:
1299 case NUMBERFORMAT_DATE
:
1300 eScannedType
= NUMBERFORMAT_DATETIME
;
1302 case NUMBERFORMAT_FRACTION
: // MM/SS
1306 if (nCurrPos
!= STRING_NOTFOUND
)
1307 eScannedType
= NUMBERFORMAT_UNDEFINED
;
1308 else if ( sStrArray
[i
] != pLoc
->getTimeSep() )
1314 case NUMBERFORMAT_DATETIME
:
1318 case NUMBERFORMAT_TIME
:
1319 case NUMBERFORMAT_DATE
:
1321 case NUMBERFORMAT_FRACTION
: // DD/MM
1325 if (nCurrPos
!= STRING_NOTFOUND
)
1326 eScannedType
= NUMBERFORMAT_UNDEFINED
;
1327 else if ( sStrArray
[i
] != pFormatter
->GetDateSep()
1328 && sStrArray
[i
] != pLoc
->getTimeSep() )
1334 case NUMBERFORMAT_PERCENT
:
1338 case NUMBERFORMAT_NUMBER
: // nur Zahl nach Prozent
1345 case NUMBERFORMAT_SCIENTIFIC
:
1349 case NUMBERFORMAT_NUMBER
: // nur Zahl nach E
1356 case NUMBERFORMAT_NUMBER
:
1360 case NUMBERFORMAT_SCIENTIFIC
:
1361 case NUMBERFORMAT_PERCENT
:
1362 case NUMBERFORMAT_FRACTION
:
1363 case NUMBERFORMAT_CURRENCY
:
1364 eScannedType
= eNewType
;
1367 if (nCurrPos
!= STRING_NOTFOUND
)
1368 eScannedType
= NUMBERFORMAT_UNDEFINED
;
1374 case NUMBERFORMAT_FRACTION
:
1378 case NUMBERFORMAT_NUMBER
: // nur Zahl nach Bruch
1389 nPos
= nPos
+ sStrArray
[i
].Len(); // Korrekturposition
1391 if ( bMatchBracket
)
1392 { // no type detection inside of matching brackets if [$...], [~...]
1393 while ( bMatchBracket
&& i
< nAnzStrings
)
1395 if ( nTypeArray
[i
] == NF_SYMBOLTYPE_DEL
1396 && sStrArray
[i
].GetChar(0) == ']' )
1397 bMatchBracket
= FALSE
;
1399 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1400 nPos
= nPos
+ sStrArray
[i
].Len();
1403 if ( bMatchBracket
)
1404 return nPos
; // missing closing bracket at end of code
1406 SkipStrings(i
, nPos
);
1409 if ((eScannedType
== NUMBERFORMAT_NUMBER
|| eScannedType
== NUMBERFORMAT_UNDEFINED
)
1410 && nCurrPos
!= STRING_NOTFOUND
&& !bHaveGeneral
)
1411 eScannedType
= NUMBERFORMAT_CURRENCY
; // old "automatic" currency
1412 if (eScannedType
== NUMBERFORMAT_UNDEFINED
)
1413 eScannedType
= NUMBERFORMAT_DEFINED
;
1414 return 0; // Alles ok
1418 bool ImpSvNumberformatScan::InsertSymbol( USHORT
& nPos
, svt::NfSymbolType eType
, const String
& rStr
)
1420 if (nAnzStrings
>= NF_MAX_FORMAT_SYMBOLS
|| nPos
> nAnzStrings
)
1423 if (nPos
> 0 && nTypeArray
[nPos
-1] == NF_SYMBOLTYPE_EMPTY
)
1424 --nPos
; // reuse position
1428 for (size_t i
= nAnzStrings
; i
> nPos
; --i
)
1430 nTypeArray
[i
] = nTypeArray
[i
-1];
1431 sStrArray
[i
] = sStrArray
[i
-1];
1434 nTypeArray
[nPos
] = static_cast<short>(eType
);
1435 sStrArray
[nPos
] = rStr
;
1440 int ImpSvNumberformatScan::FinalScanGetCalendar( xub_StrLen
& nPos
, USHORT
& i
,
1441 USHORT
& rAnzResStrings
)
1443 if ( sStrArray
[i
].GetChar(0) == '[' &&
1444 i
< nAnzStrings
-1 &&
1445 nTypeArray
[i
+1] == NF_SYMBOLTYPE_STRING
&&
1446 sStrArray
[i
+1].GetChar(0) == '~' )
1448 // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
1449 nPos
= nPos
+ sStrArray
[i
].Len(); // [
1450 nTypeArray
[i
] = NF_SYMBOLTYPE_CALDEL
;
1451 nPos
= nPos
+ sStrArray
[++i
].Len(); // ~
1452 sStrArray
[i
-1] += sStrArray
[i
]; // [~
1453 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1455 if ( ++i
>= nAnzStrings
)
1457 nPos
= nPos
+ sStrArray
[i
].Len(); // calendarID
1458 String
& rStr
= sStrArray
[i
];
1459 nTypeArray
[i
] = NF_SYMBOLTYPE_CALENDAR
; // convert
1461 while ( i
< nAnzStrings
&&
1462 sStrArray
[i
].GetChar(0) != ']' )
1464 nPos
= nPos
+ sStrArray
[i
].Len();
1465 rStr
+= sStrArray
[i
];
1466 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1470 if ( rStr
.Len() && i
< nAnzStrings
&&
1471 sStrArray
[i
].GetChar(0) == ']' )
1473 nTypeArray
[i
] = NF_SYMBOLTYPE_CALDEL
;
1474 nPos
= nPos
+ sStrArray
[i
].Len();
1484 xub_StrLen
ImpSvNumberformatScan::FinalScan( String
& rString
, String
& rComment
)
1486 const LocaleDataWrapper
* pLoc
= pFormatter
->GetLocaleData();
1488 // save values for convert mode
1489 String sOldDecSep
= pFormatter
->GetNumDecimalSep();
1490 String sOldThousandSep
= pFormatter
->GetNumThousandSep();
1491 String sOldDateSep
= pFormatter
->GetDateSep();
1492 String sOldTimeSep
= pLoc
->getTimeSep();
1493 String sOldTime100SecSep
= pLoc
->getTime100SecSep();
1494 String sOldCurSymbol
= GetCurSymbol();
1495 String sOldCurString
= GetCurString();
1496 sal_Unicode cOldKeyH
= sKeyword
[NF_KEY_H
].GetChar(0);
1497 sal_Unicode cOldKeyMI
= sKeyword
[NF_KEY_MI
].GetChar(0);
1498 sal_Unicode cOldKeyS
= sKeyword
[NF_KEY_S
].GetChar(0);
1500 // If the group separator is a Non-Breaking Space (French) continue with a
1501 // normal space instead so queries on space work correctly.
1502 // The format string is adjusted to allow both.
1503 // For output of the format code string the LocaleData characters are used.
1504 if ( sOldThousandSep
.GetChar(0) == cNonBreakingSpace
&& sOldThousandSep
.Len() == 1 )
1505 sOldThousandSep
= ' ';
1507 // change locale data et al
1510 pFormatter
->ChangeIntl(eNewLnge
);
1511 //! pointer may have changed
1512 pLoc
= pFormatter
->GetLocaleData();
1513 //! init new keywords
1516 const CharClass
* pChrCls
= pFormatter
->GetCharClass();
1518 xub_StrLen nPos
= 0; // error correction position
1519 USHORT i
= 0; // symbol loop counter
1520 USHORT nCounter
= 0; // counts digits
1521 nAnzResStrings
= nAnzStrings
; // counts remaining symbols
1522 bDecSep
= FALSE
; // reset in case already used in TypeCheck
1523 bool bThaiT
= false; // Thai T NatNum modifier present
1525 switch (eScannedType
)
1527 case NUMBERFORMAT_TEXT
:
1528 case NUMBERFORMAT_DEFINED
:
1530 while (i
< nAnzStrings
)
1532 switch (nTypeArray
[i
])
1534 case NF_SYMBOLTYPE_BLANK
:
1535 case NF_SYMBOLTYPE_STAR
:
1537 case NF_SYMBOLTYPE_COMMENT
:
1539 String
& rStr
= sStrArray
[i
];
1540 nPos
= nPos
+ rStr
.Len();
1541 SvNumberformat::EraseCommentBraces( rStr
);
1543 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1547 case NF_KEY_GENERAL
: // #77026# "General" is the same as "@"
1551 if ( nTypeArray
[i
] != NF_SYMBOLTYPE_DEL
||
1552 sStrArray
[i
].GetChar(0) != '@' )
1553 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1557 nPos
= nPos
+ sStrArray
[i
].Len();
1562 case NUMBERFORMAT_NUMBER
:
1563 case NUMBERFORMAT_PERCENT
:
1564 case NUMBERFORMAT_CURRENCY
:
1565 case NUMBERFORMAT_SCIENTIFIC
:
1566 case NUMBERFORMAT_FRACTION
:
1568 sal_Unicode cThousandFill
= ' ';
1569 while (i
< nAnzStrings
)
1571 if (eScannedType
== NUMBERFORMAT_FRACTION
&& // special case
1572 nTypeArray
[i
] == NF_SYMBOLTYPE_DEL
&& // # ### #/#
1573 StringEqualsChar( sOldThousandSep
, ' ' ) && // e.g. France or Sweden
1574 StringEqualsChar( sStrArray
[i
], ' ' ) &&
1576 IsLastBlankBeforeFrac(i
) )
1578 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
; // del->string
1582 if (nTypeArray
[i
] == NF_SYMBOLTYPE_BLANK
||
1583 nTypeArray
[i
] == NF_SYMBOLTYPE_STAR
||
1584 nTypeArray
[i
] == NF_KEY_CCC
|| // CCC
1585 nTypeArray
[i
] == NF_KEY_GENERAL
) // Standard
1587 if (nTypeArray
[i
] == NF_KEY_GENERAL
)
1589 nThousand
= FLAG_STANDARD_IN_FORMAT
;
1591 sStrArray
[i
] = sNameStandardFormat
;
1593 nPos
= nPos
+ sStrArray
[i
].Len();
1596 else if (nTypeArray
[i
] == NF_SYMBOLTYPE_STRING
|| // Strings oder
1597 nTypeArray
[i
] > 0) // Keywords
1599 if (eScannedType
== NUMBERFORMAT_SCIENTIFIC
&&
1600 nTypeArray
[i
] == NF_KEY_E
) // E+
1602 if (bExp
) // doppelt
1607 nCntPost
= nCounter
;
1611 nTypeArray
[i
] = NF_SYMBOLTYPE_EXP
;
1613 else if (eScannedType
== NUMBERFORMAT_FRACTION
&&
1614 sStrArray
[i
].GetChar(0) == ' ')
1616 if (!bBlank
&& !bFrac
) // nicht doppelt oder hinter /
1618 if (bDecSep
&& nCounter
> 0) // Nachkommastellen
1619 return nPos
; // Fehler
1625 nTypeArray
[i
] = NF_SYMBOLTYPE_FRACBLANK
;
1627 else if (nTypeArray
[i
] == NF_KEY_THAI_T
)
1630 sStrArray
[i
] = sKeyword
[nTypeArray
[i
]];
1633 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1634 nPos
= nPos
+ sStrArray
[i
].Len();
1637 else if (nTypeArray
[i
] == NF_SYMBOLTYPE_DEL
)
1639 sal_Unicode cHere
= sStrArray
[i
].GetChar(0);
1640 // Handle not pre-known separators in switch.
1641 sal_Unicode cSimplified
;
1642 if (StringEqualsChar( pFormatter
->GetNumThousandSep(), cHere
))
1644 else if (StringEqualsChar( pFormatter
->GetNumDecimalSep(), cHere
))
1647 cSimplified
= cHere
;
1648 switch ( cSimplified
)
1654 if (nThousand
> 0) // #... #
1655 return nPos
; // Fehler
1656 else if (bFrac
&& cHere
== '0')
1657 return nPos
; // 0 im Nenner
1658 nTypeArray
[i
] = NF_SYMBOLTYPE_DIGIT
;
1659 String
& rStr
= sStrArray
[i
];
1660 nPos
= nPos
+ rStr
.Len();
1663 while (i
< nAnzStrings
&&
1664 (sStrArray
[i
].GetChar(0) == '#' ||
1665 sStrArray
[i
].GetChar(0) == '0' ||
1666 sStrArray
[i
].GetChar(0) == '?')
1669 nTypeArray
[i
] = NF_SYMBOLTYPE_DIGIT
;
1670 nPos
= nPos
+ sStrArray
[i
].Len();
1678 if ( bDecSep
&& nDecPos
+1 == i
&&
1679 nTypeArray
[nDecPos
] == NF_SYMBOLTYPE_DECSEP
)
1681 nTypeArray
[i
] = NF_SYMBOLTYPE_DIGIT
;
1682 String
& rStr
= sStrArray
[i
];
1683 nPos
= nPos
+ rStr
.Len();
1686 while (i
< nAnzStrings
&&
1687 (sStrArray
[i
].GetChar(0) == '-') )
1689 // If more than two dashes are present in
1690 // currency formats the last dash will be
1691 // interpreted literally as a minus sign.
1692 // Has to be this ugly. Period.
1693 if ( eScannedType
== NUMBERFORMAT_CURRENCY
1694 && rStr
.Len() >= 2 &&
1695 (i
== nAnzStrings
-1 ||
1696 sStrArray
[i
+1].GetChar(0) != '-') )
1698 rStr
+= sStrArray
[i
];
1699 nPos
= nPos
+ sStrArray
[i
].Len();
1700 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1708 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1709 nPos
= nPos
+ sStrArray
[i
].Len();
1719 sal_Unicode cSep
= cHere
; // remember
1720 if ( StringEqualsChar( sOldThousandSep
, cSep
) )
1722 // previous char with skip empty
1723 sal_Unicode cPre
= PreviousChar(i
);
1725 if (bExp
|| bBlank
|| bFrac
)
1726 { // after E, / or ' '
1727 if ( !StringEqualsChar( sOldThousandSep
, ' ' ) )
1729 nPos
= nPos
+ sStrArray
[i
].Len();
1730 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1735 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1737 else if (i
> 0 && i
< nAnzStrings
-1 &&
1738 (cPre
== '#' || cPre
== '0') &&
1739 ((cNext
= NextChar(i
)) == '#' || cNext
== '0')
1742 nPos
= nPos
+ sStrArray
[i
].Len();
1743 if (!bThousand
) // only once
1746 cThousandFill
= sStrArray
[i
+1].GetChar(0);
1748 // Eat it, will be reinserted at proper
1749 // grouping positions further down.
1750 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1754 else if (i
> 0 && (cPre
== '#' || cPre
== '0')
1755 && PreviousType(i
) == NF_SYMBOLTYPE_DIGIT
1756 && nThousand
< FLAG_STANDARD_IN_FORMAT
)
1758 if ( StringEqualsChar( sOldThousandSep
, ' ' ) )
1759 { // strange, those French..
1761 String
& rStr
= sStrArray
[i
];
1762 // set a hard Non-Breaking Space or ConvertMode
1763 const String
& rSepF
= pFormatter
->GetNumThousandSep();
1764 while ( i
< nAnzStrings
1765 && sStrArray
[i
] == sOldThousandSep
1766 && StringEqualsChar( sOldThousandSep
, NextChar(i
) ) )
1767 { // last was a space or another space
1768 // is following => separator
1769 nPos
= nPos
+ sStrArray
[i
].Len();
1774 nTypeArray
[i
] = NF_SYMBOLTYPE_THSEP
;
1779 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1785 if ( i
< nAnzStrings
-1
1786 && sStrArray
[i
] == sOldThousandSep
)
1787 { // something following last space
1788 // => space if currency contained,
1790 nPos
= nPos
+ sStrArray
[i
].Len();
1791 if ( (nPos
<= nCurrPos
&&
1792 nCurrPos
< nPos
+ sStrArray
[i
+1].Len())
1793 || nTypeArray
[i
+1] == NF_KEY_CCC
1794 || (i
< nAnzStrings
-2 &&
1795 sStrArray
[i
+1].GetChar(0) == '[' &&
1796 sStrArray
[i
+2].GetChar(0) == '$') )
1798 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1806 nTypeArray
[i
] = NF_SYMBOLTYPE_THSEP
;
1811 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1824 nTypeArray
[i
] = NF_SYMBOLTYPE_THSEP
;
1825 nPos
= nPos
+ sStrArray
[i
].Len();
1826 sStrArray
[i
] = pFormatter
->GetNumThousandSep();
1828 } while (i
< nAnzStrings
&&
1829 sStrArray
[i
] == sOldThousandSep
);
1834 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1835 String
& rStr
= sStrArray
[i
];
1836 nPos
= nPos
+ rStr
.Len();
1838 while ( i
< nAnzStrings
&&
1839 sStrArray
[i
] == sOldThousandSep
)
1841 rStr
+= sStrArray
[i
];
1842 nPos
= nPos
+ sStrArray
[i
].Len();
1843 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1849 else if ( StringEqualsChar( sOldDecSep
, cSep
) )
1851 if (bBlank
|| bFrac
) // . behind / or ' '
1852 return nPos
; // error
1853 else if (bExp
) // behind E
1855 nPos
= nPos
+ sStrArray
[i
].Len();
1856 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1860 else if (bDecSep
) // any .
1862 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1863 String
& rStr
= sStrArray
[i
];
1864 nPos
= nPos
+ rStr
.Len();
1866 while ( i
< nAnzStrings
&&
1867 sStrArray
[i
] == sOldDecSep
)
1869 rStr
+= sStrArray
[i
];
1870 nPos
= nPos
+ sStrArray
[i
].Len();
1871 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1878 nPos
= nPos
+ sStrArray
[i
].Len();
1879 nTypeArray
[i
] = NF_SYMBOLTYPE_DECSEP
;
1880 sStrArray
[i
] = pFormatter
->GetNumDecimalSep();
1888 } // of else = DecSep
1889 else // . without meaning
1892 eScannedType
== NUMBERFORMAT_FRACTION
&&
1893 StringEqualsChar( sStrArray
[i
], ' ' ) )
1895 if (!bBlank
&& !bFrac
) // no dups
1897 if (bDecSep
&& nCounter
> 0)// dec.
1898 return nPos
; // error
1904 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1905 nPos
= nPos
+ sStrArray
[i
].Len();
1909 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1910 String
& rStr
= sStrArray
[i
];
1911 nPos
= nPos
+ rStr
.Len();
1913 while (i
< nAnzStrings
&&
1914 StringEqualsChar( sStrArray
[i
], cSep
) )
1916 rStr
+= sStrArray
[i
];
1917 nPos
= nPos
+ sStrArray
[i
].Len();
1918 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1928 if (eScannedType
== NUMBERFORMAT_FRACTION
)
1931 (nTypeArray
[i
-1] != NF_SYMBOLTYPE_DIGIT
&&
1932 nTypeArray
[i
-1] != NF_SYMBOLTYPE_EMPTY
) )
1933 return nPos
? nPos
: 1; // /? not allowed
1934 else if (!bFrac
|| (bDecSep
&& nCounter
> 0))
1937 nCntPost
= nCounter
;
1939 nTypeArray
[i
] = NF_SYMBOLTYPE_FRAC
;
1940 nPos
= nPos
+ sStrArray
[i
].Len();
1943 else // / doppelt od. , imZaehl
1944 return nPos
; // Fehler
1948 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
1949 nPos
= nPos
+ sStrArray
[i
].Len();
1956 if ( eScannedType
== NUMBERFORMAT_CURRENCY
&&
1957 i
< nAnzStrings
-1 &&
1958 nTypeArray
[i
+1] == NF_SYMBOLTYPE_STRING
&&
1959 sStrArray
[i
+1].GetChar(0) == '$' )
1961 // ab SV_NUMBERFORMATTER_VERSION_NEW_CURR
1962 nPos
= nPos
+ sStrArray
[i
].Len(); // [
1963 nTypeArray
[i
] = NF_SYMBOLTYPE_CURRDEL
;
1964 nPos
= nPos
+ sStrArray
[++i
].Len(); // $
1965 sStrArray
[i
-1] += sStrArray
[i
]; // [$
1966 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1968 if ( ++i
>= nAnzStrings
)
1969 return nPos
; // Fehler
1970 nPos
= nPos
+ sStrArray
[i
].Len(); // DM
1971 String
& rStr
= sStrArray
[i
];
1972 String
* pStr
= &sStrArray
[i
];
1973 nTypeArray
[i
] = NF_SYMBOLTYPE_CURRENCY
; // wandeln
1974 BOOL bHadDash
= FALSE
;
1976 while ( i
< nAnzStrings
&&
1977 sStrArray
[i
].GetChar(0) != ']' )
1979 nPos
= nPos
+ sStrArray
[i
].Len();
1982 *pStr
+= sStrArray
[i
];
1983 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
1988 if ( sStrArray
[i
].GetChar(0) == '-' )
1991 pStr
= &sStrArray
[i
];
1992 nTypeArray
[i
] = NF_SYMBOLTYPE_CURREXT
;
1996 *pStr
+= sStrArray
[i
];
1997 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2003 if ( rStr
.Len() && i
< nAnzStrings
&&
2004 sStrArray
[i
].GetChar(0) == ']' )
2006 nTypeArray
[i
] = NF_SYMBOLTYPE_CURRDEL
;
2007 nPos
= nPos
+ sStrArray
[i
].Len();
2011 return nPos
; // Fehler
2015 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
2016 nPos
= nPos
+ sStrArray
[i
].Len();
2021 default: // andere Dels
2023 if (eScannedType
== NUMBERFORMAT_PERCENT
&&
2025 nTypeArray
[i
] = NF_SYMBOLTYPE_PERCENT
;
2027 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
2028 nPos
= nPos
+ sStrArray
[i
].Len();
2032 } // of switch (Del)
2034 else if ( nTypeArray
[i
] == NF_SYMBOLTYPE_COMMENT
)
2036 String
& rStr
= sStrArray
[i
];
2037 nPos
= nPos
+ rStr
.Len();
2038 SvNumberformat::EraseCommentBraces( rStr
);
2040 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2046 DBG_ERRORFILE( "unknown NF_SYMBOLTYPE_..." );
2047 nPos
= nPos
+ sStrArray
[i
].Len();
2051 if (eScannedType
== NUMBERFORMAT_FRACTION
)
2056 nCntPost
= nCounter
;
2065 nCntPost
= nCounter
;
2069 if (bThousand
) // Expansion of grouping separators
2075 nMaxPos
= nBlankPos
;
2077 nMaxPos
= 0; // no grouping
2079 else if (bDecSep
) // decimal separator present
2081 else if (bExp
) // 'E' exponent present
2085 // Insert separators at proper positions.
2086 xub_StrLen nCount
= 0;
2087 utl::DigitGroupingIterator
aGrouping( pLoc
->getDigitGrouping());
2088 size_t nFirstDigitSymbol
= nMaxPos
;
2089 size_t nFirstGroupingSymbol
= nMaxPos
;
2093 if (nTypeArray
[i
] == NF_SYMBOLTYPE_DIGIT
)
2095 nFirstDigitSymbol
= i
;
2096 nCount
= nCount
+ sStrArray
[i
].Len(); // MSC converts += to int and then warns, so ...
2097 // Insert separator only if not leftmost symbol.
2098 if (i
> 0 && nCount
>= aGrouping
.getPos())
2100 DBG_ASSERT( sStrArray
[i
].Len() == 1,
2101 "ImpSvNumberformatScan::FinalScan: combined digits in group separator insertion");
2102 if (!InsertSymbol( i
, NF_SYMBOLTYPE_THSEP
,
2103 pFormatter
->GetNumThousandSep()))
2104 // nPos isn't correct here, but signals error
2106 // i may have been decremented by 1
2107 nFirstDigitSymbol
= i
+ 1;
2108 nFirstGroupingSymbol
= i
;
2109 aGrouping
.advance();
2113 // Generated something like "string",000; remove separator again.
2114 if (nFirstGroupingSymbol
< nFirstDigitSymbol
)
2116 nTypeArray
[nFirstGroupingSymbol
] = NF_SYMBOLTYPE_EMPTY
;
2120 // Combine digits into groups to save memory (Info will be copied
2121 // later, taking only non-empty symbols).
2122 for (i
= 0; i
< nAnzStrings
; ++i
)
2124 if (nTypeArray
[i
] == NF_SYMBOLTYPE_DIGIT
)
2126 String
& rStr
= sStrArray
[i
];
2127 while (++i
< nAnzStrings
&&
2128 nTypeArray
[i
] == NF_SYMBOLTYPE_DIGIT
)
2130 rStr
+= sStrArray
[i
];
2131 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2137 break; // of NUMBERFORMAT_NUMBER
2138 case NUMBERFORMAT_DATE
:
2140 while (i
< nAnzStrings
)
2142 switch (nTypeArray
[i
])
2144 case NF_SYMBOLTYPE_BLANK
:
2145 case NF_SYMBOLTYPE_STAR
:
2146 case NF_SYMBOLTYPE_STRING
:
2147 nPos
= nPos
+ sStrArray
[i
].Len();
2150 case NF_SYMBOLTYPE_COMMENT
:
2152 String
& rStr
= sStrArray
[i
];
2153 nPos
= nPos
+ rStr
.Len();
2154 SvNumberformat::EraseCommentBraces( rStr
);
2156 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2161 case NF_SYMBOLTYPE_DEL
:
2164 if (sStrArray
[i
] == sOldDateSep
)
2166 nTypeArray
[i
] = NF_SYMBOLTYPE_DATESEP
;
2167 nPos
= nPos
+ sStrArray
[i
].Len();
2169 sStrArray
[i
] = pFormatter
->GetDateSep();
2172 else if ( (nCalRet
= FinalScanGetCalendar( nPos
, i
, nAnzResStrings
)) != 0 )
2175 return nPos
; // error
2179 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
2180 nPos
= nPos
+ sStrArray
[i
].Len();
2185 case NF_KEY_THAI_T
:
2189 case NF_KEY_MM
: // MM
2190 case NF_KEY_MMM
: // MMM
2191 case NF_KEY_MMMM
: // MMMM
2192 case NF_KEY_MMMMM
: // MMMMM
2194 case NF_KEY_QQ
: // QQ
2196 case NF_KEY_DD
: // DD
2197 case NF_KEY_DDD
: // DDD
2198 case NF_KEY_DDDD
: // DDDD
2199 case NF_KEY_YY
: // YY
2200 case NF_KEY_YYYY
: // YYYY
2201 case NF_KEY_NN
: // NN
2202 case NF_KEY_NNN
: // NNN
2203 case NF_KEY_NNNN
: // NNNN
2204 case NF_KEY_WW
: // WW
2205 case NF_KEY_AAA
: // AAA
2206 case NF_KEY_AAAA
: // AAAA
2207 case NF_KEY_EC
: // E
2208 case NF_KEY_EEC
: // EE
2209 case NF_KEY_G
: // G
2210 case NF_KEY_GG
: // GG
2211 case NF_KEY_GGG
: // GGG
2212 case NF_KEY_R
: // R
2213 case NF_KEY_RR
: // RR
2214 sStrArray
[i
] = sKeyword
[nTypeArray
[i
]]; // tTtT -> TTTT
2215 nPos
= nPos
+ sStrArray
[i
].Len();
2218 default: // andere Keywords
2219 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
2220 nPos
= nPos
+ sStrArray
[i
].Len();
2226 break; // of NUMBERFORMAT_DATE
2227 case NUMBERFORMAT_TIME
:
2229 while (i
< nAnzStrings
)
2231 switch (nTypeArray
[i
])
2233 case NF_SYMBOLTYPE_BLANK
:
2234 case NF_SYMBOLTYPE_STAR
:
2236 nPos
= nPos
+ sStrArray
[i
].Len();
2240 case NF_SYMBOLTYPE_DEL
:
2242 switch( sStrArray
[i
].GetChar(0) )
2246 if ( Is100SecZero( i
, bDecSep
) )
2249 nTypeArray
[i
] = NF_SYMBOLTYPE_DIGIT
;
2250 String
& rStr
= sStrArray
[i
];
2252 nPos
= nPos
+ sStrArray
[i
].Len();
2254 while (i
< nAnzStrings
&&
2255 sStrArray
[i
].GetChar(0) == '0')
2257 rStr
+= sStrArray
[i
];
2258 nPos
= nPos
+ sStrArray
[i
].Len();
2259 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2274 if (bThousand
) // doppelt
2276 bThousand
= TRUE
; // bei Time frei
2277 sal_Unicode cChar
= pChrCls
->upper( NextChar(i
) ).GetChar(0);
2278 if ( cChar
== cOldKeyH
)
2280 else if ( cChar
== cOldKeyMI
)
2282 else if ( cChar
== cOldKeyS
)
2286 nPos
= nPos
+ sStrArray
[i
].Len();
2292 if (!bThousand
) // kein [ vorher
2294 nPos
= nPos
+ sStrArray
[i
].Len();
2300 nPos
= nPos
+ sStrArray
[i
].Len();
2301 if ( sStrArray
[i
] == sOldTimeSep
)
2303 nTypeArray
[i
] = NF_SYMBOLTYPE_TIMESEP
;
2305 sStrArray
[i
] = pLoc
->getTimeSep();
2307 else if ( sStrArray
[i
] == sOldTime100SecSep
)
2310 nTypeArray
[i
] = NF_SYMBOLTYPE_TIME100SECSEP
;
2312 sStrArray
[i
] = pLoc
->getTime100SecSep();
2315 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
2322 case NF_SYMBOLTYPE_STRING
:
2324 nPos
= nPos
+ sStrArray
[i
].Len();
2328 case NF_SYMBOLTYPE_COMMENT
:
2330 String
& rStr
= sStrArray
[i
];
2331 nPos
= nPos
+ rStr
.Len();
2332 SvNumberformat::EraseCommentBraces( rStr
);
2334 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2339 case NF_KEY_AMPM
: // AM/PM
2340 case NF_KEY_AP
: // A/P
2342 bExp
= TRUE
; // missbraucht fuer A/P
2343 sStrArray
[i
] = sKeyword
[nTypeArray
[i
]]; // tTtT -> TTTT
2344 nPos
= nPos
+ sStrArray
[i
].Len();
2348 case NF_KEY_THAI_T
:
2351 case NF_KEY_MI
: // M
2352 case NF_KEY_MMI
: // MM
2354 case NF_KEY_HH
: // HH
2356 case NF_KEY_SS
: // SS
2358 sStrArray
[i
] = sKeyword
[nTypeArray
[i
]]; // tTtT -> TTTT
2359 nPos
= nPos
+ sStrArray
[i
].Len();
2363 default: // andere Keywords
2365 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
2366 nPos
= nPos
+ sStrArray
[i
].Len();
2372 nCntPost
= nCounter
; // Zaehler der Nullen
2374 nCntExp
= 1; // merkt AM/PM
2376 break; // of NUMBERFORMAT_TIME
2377 case NUMBERFORMAT_DATETIME
:
2379 BOOL bTimePart
= FALSE
;
2380 while (i
< nAnzStrings
)
2382 switch (nTypeArray
[i
])
2384 case NF_SYMBOLTYPE_BLANK
:
2385 case NF_SYMBOLTYPE_STAR
:
2386 case NF_SYMBOLTYPE_STRING
:
2387 nPos
= nPos
+ sStrArray
[i
].Len();
2390 case NF_SYMBOLTYPE_COMMENT
:
2392 String
& rStr
= sStrArray
[i
];
2393 nPos
= nPos
+ rStr
.Len();
2394 SvNumberformat::EraseCommentBraces( rStr
);
2396 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2401 case NF_SYMBOLTYPE_DEL
:
2404 if ( (nCalRet
= FinalScanGetCalendar( nPos
, i
, nAnzResStrings
)) != 0 )
2407 return nPos
; // error
2411 switch( sStrArray
[i
].GetChar(0) )
2415 if ( bTimePart
&& Is100SecZero( i
, bDecSep
) )
2418 nTypeArray
[i
] = NF_SYMBOLTYPE_DIGIT
;
2419 String
& rStr
= sStrArray
[i
];
2421 nPos
= nPos
+ sStrArray
[i
].Len();
2423 while (i
< nAnzStrings
&&
2424 sStrArray
[i
].GetChar(0) == '0')
2426 rStr
+= sStrArray
[i
];
2427 nPos
= nPos
+ sStrArray
[i
].Len();
2428 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2443 nPos
= nPos
+ sStrArray
[i
].Len();
2446 if ( sStrArray
[i
] == sOldTimeSep
)
2448 nTypeArray
[i
] = NF_SYMBOLTYPE_TIMESEP
;
2450 sStrArray
[i
] = pLoc
->getTimeSep();
2452 else if ( sStrArray
[i
] == sOldTime100SecSep
)
2455 nTypeArray
[i
] = NF_SYMBOLTYPE_TIME100SECSEP
;
2457 sStrArray
[i
] = pLoc
->getTime100SecSep();
2460 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
2464 if ( sStrArray
[i
] == sOldDateSep
)
2466 nTypeArray
[i
] = NF_SYMBOLTYPE_DATESEP
;
2468 sStrArray
[i
] = pFormatter
->GetDateSep();
2471 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
2479 case NF_KEY_AMPM
: // AM/PM
2480 case NF_KEY_AP
: // A/P
2483 bExp
= TRUE
; // missbraucht fuer A/P
2484 sStrArray
[i
] = sKeyword
[nTypeArray
[i
]]; // tTtT -> TTTT
2485 nPos
= nPos
+ sStrArray
[i
].Len();
2489 case NF_KEY_MI
: // M
2490 case NF_KEY_MMI
: // MM
2492 case NF_KEY_HH
: // HH
2494 case NF_KEY_SS
: // SS
2496 sStrArray
[i
] = sKeyword
[nTypeArray
[i
]]; // tTtT -> TTTT
2497 nPos
= nPos
+ sStrArray
[i
].Len();
2501 case NF_KEY_MM
: // MM
2502 case NF_KEY_MMM
: // MMM
2503 case NF_KEY_MMMM
: // MMMM
2504 case NF_KEY_MMMMM
: // MMMMM
2506 case NF_KEY_QQ
: // QQ
2508 case NF_KEY_DD
: // DD
2509 case NF_KEY_DDD
: // DDD
2510 case NF_KEY_DDDD
: // DDDD
2511 case NF_KEY_YY
: // YY
2512 case NF_KEY_YYYY
: // YYYY
2513 case NF_KEY_NN
: // NN
2514 case NF_KEY_NNN
: // NNN
2515 case NF_KEY_NNNN
: // NNNN
2516 case NF_KEY_WW
: // WW
2517 case NF_KEY_AAA
: // AAA
2518 case NF_KEY_AAAA
: // AAAA
2519 case NF_KEY_EC
: // E
2520 case NF_KEY_EEC
: // EE
2521 case NF_KEY_G
: // G
2522 case NF_KEY_GG
: // GG
2523 case NF_KEY_GGG
: // GGG
2524 case NF_KEY_R
: // R
2525 case NF_KEY_RR
: // RR
2527 sStrArray
[i
] = sKeyword
[nTypeArray
[i
]]; // tTtT -> TTTT
2528 nPos
= nPos
+ sStrArray
[i
].Len();
2531 case NF_KEY_THAI_T
:
2533 sStrArray
[i
] = sKeyword
[nTypeArray
[i
]];
2534 nPos
= nPos
+ sStrArray
[i
].Len();
2537 default: // andere Keywords
2538 nTypeArray
[i
] = NF_SYMBOLTYPE_STRING
;
2539 nPos
= nPos
+ sStrArray
[i
].Len();
2544 nCntPost
= nCounter
; // decimals (100th seconds)
2546 nCntExp
= 1; // merkt AM/PM
2548 break; // of NUMBERFORMAT_DATETIME
2552 if (eScannedType
== NUMBERFORMAT_SCIENTIFIC
&&
2553 (nCntPre
+ nCntPost
== 0 || nCntExp
== 0))
2555 else if (eScannedType
== NUMBERFORMAT_FRACTION
&& (nCntExp
> 8 || nCntExp
== 0))
2558 if (bThaiT
&& !GetNatNumModifier())
2559 SetNatNumModifier(1);
2562 { // strings containing keywords of the target locale must be quoted, so
2563 // the user sees the difference and is able to edit the format string
2564 for ( i
=0; i
< nAnzStrings
; i
++ )
2566 if ( nTypeArray
[i
] == NF_SYMBOLTYPE_STRING
&&
2567 sStrArray
[i
].GetChar(0) != '\"' )
2569 if ( bConvertSystemToSystem
&& eScannedType
== NUMBERFORMAT_CURRENCY
)
2570 { // don't stringize automatic currency, will be converted
2571 if ( sStrArray
[i
] == sOldCurSymbol
)
2573 // DM might be splitted into D and M
2574 if ( sStrArray
[i
].Len() < sOldCurSymbol
.Len() &&
2575 pChrCls
->toUpper( sStrArray
[i
], 0, 1 ).GetChar(0) ==
2576 sOldCurString
.GetChar(0) )
2578 String
aTmp( sStrArray
[i
] );
2580 while ( aTmp
.Len() < sOldCurSymbol
.Len() &&
2582 nTypeArray
[j
] == NF_SYMBOLTYPE_STRING
)
2584 aTmp
+= sStrArray
[j
++];
2586 if ( pChrCls
->upper( aTmp
) == sOldCurString
)
2588 sStrArray
[i
++] = aTmp
;
2591 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2599 String
& rStr
= sStrArray
[i
];
2600 xub_StrLen nLen
= rStr
.Len();
2601 for ( xub_StrLen j
=0; j
<nLen
; j
++ )
2603 if ( (j
== 0 || rStr
.GetChar(j
-1) != '\\') && GetKeyWord( rStr
, j
) )
2605 rStr
.Insert( '\"', 0 );
2613 // concatenate strings, remove quotes for output, and rebuild the format string
2616 while (i
< nAnzStrings
)
2618 switch ( nTypeArray
[i
] )
2620 case NF_SYMBOLTYPE_STRING
:
2622 xub_StrLen nStringPos
= rString
.Len();
2623 xub_StrLen nArrPos
= 0;
2627 if (sStrArray
[i
].Len() == 2 &&
2628 sStrArray
[i
].GetChar(0) == '\\')
2630 // Unescape some simple forms of symbols even in the UI
2631 // visible string to prevent duplicates that differ
2632 // only in notation, originating from import.
2633 // e.g. YYYY-MM-DD and YYYY\-MM\-DD are identical,
2634 // but 0\ 000 0 and 0 000 0 in a French locale are not.
2635 sal_Unicode c
= sStrArray
[i
].GetChar(1);
2645 if (((eScannedType
& NUMBERFORMAT_DATE
) == 0)
2646 && (StringEqualsChar(
2647 pFormatter
->GetNumThousandSep(),
2648 c
) || StringEqualsChar(
2649 pFormatter
->GetNumDecimalSep(),
2652 pFormatter
->GetNumThousandSep(),
2653 cNonBreakingSpace
))))
2654 rString
+= sStrArray
[i
];
2655 else if ((eScannedType
& NUMBERFORMAT_DATE
) &&
2657 pFormatter
->GetDateSep(), c
))
2658 rString
+= sStrArray
[i
];
2659 else if ((eScannedType
& NUMBERFORMAT_TIME
) &&
2660 (StringEqualsChar( pLoc
->getTimeSep(),
2663 pLoc
->getTime100SecSep(), c
)))
2664 rString
+= sStrArray
[i
];
2665 else if (eScannedType
& NUMBERFORMAT_FRACTION
)
2666 rString
+= sStrArray
[i
];
2671 rString
+= sStrArray
[i
];
2675 rString
+= sStrArray
[i
];
2676 if ( RemoveQuotes( sStrArray
[i
] ) > 0 )
2677 { // update currency up to quoted string
2678 if ( eScannedType
== NUMBERFORMAT_CURRENCY
)
2679 { // dM -> DM or DM -> $ in old automatic
2680 // currency formats, oh my ..., why did we ever
2682 String
aTmp( pChrCls
->toUpper(
2683 sStrArray
[iPos
], nArrPos
,
2684 sStrArray
[iPos
].Len()-nArrPos
) );
2685 xub_StrLen nCPos
= aTmp
.Search( sOldCurString
);
2686 if ( nCPos
!= STRING_NOTFOUND
)
2688 const String
& rCur
=
2689 bConvertMode
&& bConvertSystemToSystem
?
2690 GetCurSymbol() : sOldCurSymbol
;
2691 sStrArray
[iPos
].Replace( nArrPos
+nCPos
,
2692 sOldCurString
.Len(), rCur
);
2693 rString
.Replace( nStringPos
+nCPos
,
2694 sOldCurString
.Len(), rCur
);
2696 nStringPos
= rString
.Len();
2698 nArrPos
= sStrArray
[iPos
].Len();
2700 nArrPos
= sStrArray
[iPos
].Len() + sStrArray
[i
].Len();
2705 sStrArray
[iPos
] += sStrArray
[i
];
2706 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2710 } while ( i
< nAnzStrings
&& nTypeArray
[i
] == NF_SYMBOLTYPE_STRING
);
2711 if ( i
< nAnzStrings
)
2712 i
--; // enter switch on next symbol again
2713 if ( eScannedType
== NUMBERFORMAT_CURRENCY
&& nStringPos
< rString
.Len() )
2714 { // same as above, since last RemoveQuotes
2715 String
aTmp( pChrCls
->toUpper(
2716 sStrArray
[iPos
], nArrPos
,
2717 sStrArray
[iPos
].Len()-nArrPos
) );
2718 xub_StrLen nCPos
= aTmp
.Search( sOldCurString
);
2719 if ( nCPos
!= STRING_NOTFOUND
)
2721 const String
& rCur
=
2722 bConvertMode
&& bConvertSystemToSystem
?
2723 GetCurSymbol() : sOldCurSymbol
;
2724 sStrArray
[iPos
].Replace( nArrPos
+nCPos
,
2725 sOldCurString
.Len(), rCur
);
2726 rString
.Replace( nStringPos
+nCPos
,
2727 sOldCurString
.Len(), rCur
);
2732 case NF_SYMBOLTYPE_CURRENCY
:
2734 rString
+= sStrArray
[i
];
2735 RemoveQuotes( sStrArray
[i
] );
2739 if (bThaiT
&& GetNatNumModifier() == 1)
2740 { // Remove T from format code, will be replaced with a [NatNum1] prefix.
2741 nTypeArray
[i
] = NF_SYMBOLTYPE_EMPTY
;
2745 rString
+= sStrArray
[i
];
2747 case NF_SYMBOLTYPE_EMPTY
:
2751 rString
+= sStrArray
[i
];
2759 xub_StrLen
ImpSvNumberformatScan::RemoveQuotes( String
& rStr
)
2761 if ( rStr
.Len() > 1 )
2763 sal_Unicode c
= rStr
.GetChar(0);
2765 if ( c
== '"' && rStr
.GetChar( (n
= xub_StrLen(rStr
.Len()-1)) ) == '"' )
2771 else if ( c
== '\\' )
2781 xub_StrLen
ImpSvNumberformatScan::ScanFormat( String
& rString
, String
& rComment
)
2783 xub_StrLen res
= Symbol_Division(rString
); //lexikalische Analyse
2785 res
= ScanType(rString
); // Erkennung des Formattyps
2787 res
= FinalScan( rString
, rComment
); // Typabhaengige Endanalyse
2788 return res
; // res = Kontrollposition
2789 // res = 0 => Format ok
2792 void ImpSvNumberformatScan::CopyInfo(ImpSvNumberformatInfo
* pInfo
, USHORT nAnz
)
2797 while (i
< nAnz
&& j
< NF_MAX_FORMAT_SYMBOLS
)
2799 if (nTypeArray
[j
] != NF_SYMBOLTYPE_EMPTY
)
2801 pInfo
->sStrArray
[i
] = sStrArray
[j
];
2802 pInfo
->nTypeArray
[i
] = nTypeArray
[j
];
2807 pInfo
->eScannedType
= eScannedType
;
2808 pInfo
->bThousand
= bThousand
;
2809 pInfo
->nThousand
= nThousand
;
2810 pInfo
->nCntPre
= nCntPre
;
2811 pInfo
->nCntPost
= nCntPost
;
2812 pInfo
->nCntExp
= nCntExp
;