xref: /AOO41X/main/svl/source/numbers/zforscan.cxx (revision 40df464ee80f942fd2baf5effc726656f4be12a0)
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 ()__anond05094f40111::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;  // everytime > 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