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

Generated by: LCOV version 1.10