LCOV - code coverage report
Current view: top level - svl/source/numbers - zforscan.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1165 1478 78.8 %
Date: 2015-06-13 12:38:46 Functions: 32 32 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11