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 { 53 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 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 117 ImpSvNumberformatScan::~ImpSvNumberformatScan() 118 { 119 delete pNullDate; 120 Reset(); 121 } 122 123 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 134 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 164 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 175 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]. */ 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 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 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 464 void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec) 465 { 466 nStandardPrec = nPrec; 467 } 468 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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