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

Generated by: LCOV version 1.10