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