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

Generated by: LCOV version 1.10