LCOV - code coverage report
Current view: top level - libreoffice/svl/source/numbers - zforscan.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1128 1445 78.1 %
Date: 2012-12-17 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           4 :         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           8 :             };
      61           4 :             return &aEnglishColors[0];
      62             :         }
      63             :     };
      64             : 
      65             :     struct theEnglishColors
      66             :             : public rtl::StaticAggregate< const OUString, ImplEnglishColors> {};
      67             : 
      68             : }
      69             : 
      70         824 : ImpSvNumberformatScan::ImpSvNumberformatScan( SvNumberFormatter* pFormatterP )
      71             : {
      72         824 :     pFormatter = pFormatterP;
      73         824 :     bConvertMode = false;
      74             :     //! All keywords MUST be UPPERCASE!
      75         824 :     sKeyword[NF_KEY_E] =     "E";        // Exponent
      76         824 :     sKeyword[NF_KEY_AMPM] =  "AM/PM";    // AM/PM
      77         824 :     sKeyword[NF_KEY_AP] =    "A/P";      // AM/PM short
      78         824 :     sKeyword[NF_KEY_MI] =    "M";        // Minute
      79         824 :     sKeyword[NF_KEY_MMI] =   "MM";       // Minute 02
      80         824 :     sKeyword[NF_KEY_S] =     "S";        // Second
      81         824 :     sKeyword[NF_KEY_SS] =    "SS";       // Second 02
      82         824 :     sKeyword[NF_KEY_Q] =     "Q";        // Quarter short 'Q'
      83         824 :     sKeyword[NF_KEY_QQ] =    "QQ";       // Quarter long
      84         824 :     sKeyword[NF_KEY_NN] =    "NN";       // Day of week short
      85         824 :     sKeyword[NF_KEY_NNN] =   "NNN";      // Day of week long
      86         824 :     sKeyword[NF_KEY_NNNN] =  "NNNN";     // Day of week long incl. separator
      87         824 :     sKeyword[NF_KEY_WW] =    "WW";       // Week of year
      88         824 :     sKeyword[NF_KEY_CCC] =   "CCC";      // Currency abbreviation
      89         824 :     bKeywordsNeedInit = true;   // locale dependent keywords
      90         824 :     bCompatCurNeedInit = true;  // locale dependent compatibility currency strings
      91             : 
      92         824 :     StandardColor[0]  =  Color(COL_BLACK);
      93         824 :     StandardColor[1]  =  Color(COL_LIGHTBLUE);
      94         824 :     StandardColor[2]  =  Color(COL_LIGHTGREEN);
      95         824 :     StandardColor[3]  =  Color(COL_LIGHTCYAN);
      96         824 :     StandardColor[4]  =  Color(COL_LIGHTRED);
      97         824 :     StandardColor[5]  =  Color(COL_LIGHTMAGENTA);
      98         824 :     StandardColor[6]  =  Color(COL_BROWN);
      99         824 :     StandardColor[7]  =  Color(COL_GRAY);
     100         824 :     StandardColor[8]  =  Color(COL_YELLOW);
     101         824 :     StandardColor[9]  =  Color(COL_WHITE);
     102             : 
     103         824 :     pNullDate = new Date(30,12,1899);
     104         824 :     nStandardPrec = 2;
     105             : 
     106         824 :     sErrStr =  "###";
     107         824 :     Reset();
     108         824 : }
     109             : 
     110       33372 : ImpSvNumberformatScan::~ImpSvNumberformatScan()
     111             : {
     112         324 :     delete pNullDate;
     113         324 :     Reset();
     114       33048 : }
     115             : 
     116        7878 : void ImpSvNumberformatScan::ChangeIntl()
     117             : {
     118        7878 :     bKeywordsNeedInit = true;
     119        7878 :     bCompatCurNeedInit = true;
     120             :     // may be initialized by InitSpecialKeyword()
     121        7878 :     sKeyword[NF_KEY_TRUE] = "";
     122        7878 :     sKeyword[NF_KEY_FALSE] = "";
     123        7878 : }
     124             : 
     125       16908 : void ImpSvNumberformatScan::InitSpecialKeyword( NfKeywordIndex eIdx ) const
     126             : {
     127       16908 :     switch ( eIdx )
     128             :     {
     129             :     case NF_KEY_TRUE :
     130        8454 :         ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] =
     131       16908 :             pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getTrueWord() );
     132        8454 :         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        8454 :         break;
     138             :     case NF_KEY_FALSE :
     139        8454 :         ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] =
     140       16908 :             pFormatter->GetCharClass()->uppercase( pFormatter->GetLocaleData()->getFalseWord() );
     141        8454 :         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        8454 :         break;
     147             :     default:
     148             :         SAL_WARN( "svl.numbers", "InitSpecialKeyword: unknown request" );
     149             :     }
     150       16908 : }
     151             : 
     152        8436 : void ImpSvNumberformatScan::InitCompatCur() const
     153             : {
     154        8436 :     ImpSvNumberformatScan* pThis = (ImpSvNumberformatScan*)this;
     155             :     // currency symbol for old style ("automatic") compatibility format codes
     156        8436 :     pFormatter->GetCompatibilityCurrency( pThis->sCurSymbol, pThis->sCurAbbrev );
     157             :     // currency symbol upper case
     158        8436 :     pThis->sCurString = pFormatter->GetCharClass()->uppercase( sCurSymbol );
     159        8436 :     bCompatCurNeedInit = false;
     160        8436 : }
     161             : 
     162       10628 : void ImpSvNumberformatScan::InitKeywords() const
     163             : {
     164       10628 :     if ( !bKeywordsNeedInit )
     165       12820 :         return ;
     166        8436 :     ((ImpSvNumberformatScan*)this)->SetDependentKeywords();
     167        8436 :     bKeywordsNeedInit = false;
     168             : }
     169             : 
     170             : /** Extract the name of General, Standard, Whatever, ignoring leading modifiers
     171             :     such as [NatNum1]. */
     172        8436 : static OUString lcl_extractStandardGeneralName( const ::rtl::OUString & rCode )
     173             : {
     174        8436 :     OUString aStr;
     175        8436 :     const sal_Unicode* p = rCode.getStr();
     176        8436 :     const sal_Unicode* const pStop = p + rCode.getLength();
     177        8436 :     const sal_Unicode* pBeg = p;    // name begins here
     178        8436 :     bool bMod = false;
     179        8436 :     bool bDone = false;
     180       75930 :     while (p < pStop && !bDone)
     181             :     {
     182       59058 :         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       59058 :         ++p;
     205       59058 :         if (bMod)
     206             :         {
     207           0 :             pBeg = p;
     208             :         }
     209             :     }
     210        8436 :     if (pBeg < p)
     211             :     {
     212        8436 :         aStr = rCode.copy( pBeg - rCode.getStr(), p - pBeg);
     213             :     }
     214        8436 :     return aStr;
     215             : }
     216             : 
     217        8436 : void ImpSvNumberformatScan::SetDependentKeywords()
     218             : {
     219             :     using namespace ::com::sun::star;
     220             :     using namespace ::com::sun::star::uno;
     221             : 
     222        8436 :     const CharClass* pCharClass = pFormatter->GetCharClass();
     223        8436 :     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        8436 :     const LanguageTag& rLoadedLocale = pLocaleData->getLoadedLanguageTag();
     227        8436 :     LanguageType eLang = rLoadedLocale.getLanguageType( false);
     228             :     NumberFormatCodeWrapper aNumberFormatCode( comphelper::getComponentContext(pFormatter->GetServiceManager()),
     229        8436 :             rLoadedLocale.getLocale() );
     230             : 
     231        8436 :     i18n::NumberFormatCode aFormat = aNumberFormatCode.getFormatCode( NF_NUMBER_STANDARD );
     232        8436 :     sNameStandardFormat = lcl_extractStandardGeneralName( aFormat.Code);
     233        8436 :     sKeyword[NF_KEY_GENERAL] = pCharClass->uppercase( sNameStandardFormat );
     234             : 
     235             :     // preset new calendar keywords
     236        8436 :     sKeyword[NF_KEY_AAA] =   "AAA";
     237        8436 :     sKeyword[NF_KEY_AAAA] =  "AAAA";
     238        8436 :     sKeyword[NF_KEY_EC] =    "E";
     239        8436 :     sKeyword[NF_KEY_EEC] =   "EE";
     240        8436 :     sKeyword[NF_KEY_G] =     "G";
     241        8436 :     sKeyword[NF_KEY_GG] =    "GG";
     242        8436 :     sKeyword[NF_KEY_GGG] =   "GGG";
     243        8436 :     sKeyword[NF_KEY_R] =     "R";
     244        8436 :     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        8436 :     if (eLang == LANGUAGE_THAI)
     249             :     {
     250           0 :         sKeyword[NF_KEY_THAI_T] = "T";
     251             :     }
     252             :     else
     253             :     {
     254        8436 :         sKeyword[NF_KEY_THAI_T] = "t";
     255             :     }
     256        8436 :     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           2 :         sKeyword[NF_KEY_M] =         "M";            // month 1
     265           2 :         sKeyword[NF_KEY_MM] =        "MM";           // month 01
     266           2 :         sKeyword[NF_KEY_MMM] =       "MMM";      // month Jan
     267           2 :         sKeyword[NF_KEY_MMMM] =      "MMMM"; // month Januar
     268           2 :         sKeyword[NF_KEY_MMMMM] =     "MMMMM";// month J
     269           2 :         sKeyword[NF_KEY_H] =         "H";            // hour 2
     270           2 :         sKeyword[NF_KEY_HH] =        "HH";           // hour 02
     271           2 :         sKeyword[NF_KEY_D] =         "T";
     272           2 :         sKeyword[NF_KEY_DD] =        "TT";
     273           2 :         sKeyword[NF_KEY_DDD] =       "TTT";
     274           2 :         sKeyword[NF_KEY_DDDD] =      "TTTT";
     275           2 :         sKeyword[NF_KEY_YY] =        "JJ";
     276           2 :         sKeyword[NF_KEY_YYYY] =      "JJJJ";
     277           2 :         sKeyword[NF_KEY_BOOLEAN] =   "LOGISCH";
     278           2 :         sKeyword[NF_KEY_COLOR] =     "FARBE";
     279           2 :         sKeyword[NF_KEY_BLACK] =     "SCHWARZ";
     280           2 :         sKeyword[NF_KEY_BLUE] =      "BLAU";
     281           2 :         sKeyword[NF_KEY_GREEN] = OUString( "GR" "\xDC" "N", 4, RTL_TEXTENCODING_ISO_8859_1 );
     282           2 :         sKeyword[NF_KEY_CYAN] =      "CYAN";
     283           2 :         sKeyword[NF_KEY_RED] =       "ROT";
     284           2 :         sKeyword[NF_KEY_MAGENTA] =   "MAGENTA";
     285           2 :         sKeyword[NF_KEY_BROWN] =     "BRAUN";
     286           2 :         sKeyword[NF_KEY_GREY] =      "GRAU";
     287           2 :         sKeyword[NF_KEY_YELLOW] =    "GELB";
     288           2 :         sKeyword[NF_KEY_WHITE] =     "WEISS";
     289           2 :         break;
     290             :     default:
     291             :         // day
     292        8434 :         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           4 :             sKeyword[NF_KEY_D] = "J";
     312           4 :             sKeyword[NF_KEY_DD] = "JJ";
     313           4 :             sKeyword[NF_KEY_DDD] = "JJJ";
     314           4 :             sKeyword[NF_KEY_DDDD] = "JJJJ";
     315           4 :             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        8430 :             sKeyword[NF_KEY_D] = "D";
     324        8430 :             sKeyword[NF_KEY_DD] = "DD";
     325        8430 :             sKeyword[NF_KEY_DDD] = "DDD";
     326        8430 :             sKeyword[NF_KEY_DDDD] = "DDDD";
     327             :         }
     328             :         // month
     329        8434 :         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        8434 :             sKeyword[NF_KEY_M] = "M";
     340        8434 :             sKeyword[NF_KEY_MM] = "MM";
     341        8434 :             sKeyword[NF_KEY_MMM] = "MMM";
     342        8434 :             sKeyword[NF_KEY_MMMM] = "MMMM";
     343        8434 :             sKeyword[NF_KEY_MMMMM] = "MMMMM";
     344             :         }
     345             :         // year
     346        8434 :         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           4 :             sKeyword[NF_KEY_YY] = "AA";
     379           4 :             sKeyword[NF_KEY_YYYY] = "AAAA";
     380             :             // must exchange the day of week name code, same as Xcl
     381           4 :             sKeyword[NF_KEY_AAA] =   "OOO";
     382           4 :             sKeyword[NF_KEY_AAAA] =  "OOOO";
     383           4 :             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        8430 :             sKeyword[NF_KEY_YY] = "YY";
     395        8430 :             sKeyword[NF_KEY_YYYY] = "YYYY";
     396             :         }
     397             :         // hour
     398        8434 :         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        8434 :             sKeyword[NF_KEY_H] = "H";
     417        8434 :             sKeyword[NF_KEY_HH] = "HH";
     418             :         }
     419             :         // boolean
     420        8434 :         sKeyword[NF_KEY_BOOLEAN] = "BOOLEAN";
     421             :         // colours
     422        8434 :         sKeyword[NF_KEY_COLOR] =     "COLOR";
     423        8434 :         sKeyword[NF_KEY_BLACK] =     "BLACK";
     424        8434 :         sKeyword[NF_KEY_BLUE] =      "BLUE";
     425        8434 :         sKeyword[NF_KEY_GREEN] =     "GREEN";
     426        8434 :         sKeyword[NF_KEY_CYAN] =      "CYAN";
     427        8434 :         sKeyword[NF_KEY_RED] =       "RED";
     428        8434 :         sKeyword[NF_KEY_MAGENTA] =   "MAGENTA";
     429        8434 :         sKeyword[NF_KEY_BROWN] =     "BROWN";
     430        8434 :         sKeyword[NF_KEY_GREY] =      "GREY";
     431        8434 :         sKeyword[NF_KEY_YELLOW] =    "YELLOW";
     432        8434 :         sKeyword[NF_KEY_WHITE] =     "WHITE";
     433        8434 :         break;
     434             :     }
     435             : 
     436             :     // boolean keyords
     437        8436 :     InitSpecialKeyword( NF_KEY_TRUE );
     438        8436 :     InitSpecialKeyword( NF_KEY_FALSE );
     439             : 
     440             :     // compatibility currency strings
     441        8436 :     InitCompatCur();
     442        8436 : }
     443             : 
     444        1120 : void ImpSvNumberformatScan::ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear)
     445             : {
     446        1120 :     if ( pNullDate )
     447        1120 :         *pNullDate = Date(nDay, nMonth, nYear);
     448             :     else
     449           0 :         pNullDate = new Date(nDay, nMonth, nYear);
     450        1120 : }
     451             : 
     452        1330 : void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec)
     453             : {
     454        1330 :     nStandardPrec = nPrec;
     455        1330 : }
     456             : 
     457        7108 : Color* ImpSvNumberformatScan::GetColor(OUString& sStr)
     458             : {
     459        7108 :     OUString sString = pFormatter->GetCharClass()->uppercase(sStr);
     460        7108 :     const NfKeywordTable & rKeyword = GetKeywords();
     461        7108 :     size_t i = 0;
     462       46584 :     while (i < NF_MAX_DEFAULT_COLORS && sString != rKeyword[NF_KEY_FIRSTCOLOR+i] )
     463             :     {
     464       32368 :         i++;
     465             :     }
     466        7108 :     if ( i >= NF_MAX_DEFAULT_COLORS )
     467             :     {
     468         656 :         const OUString* pEnglishColors = theEnglishColors::get();
     469         656 :         size_t j = 0;
     470        7872 :         while ( j < NF_MAX_DEFAULT_COLORS && sString != pEnglishColors[j] )
     471             :         {
     472        6560 :             ++j;
     473             :         }
     474         656 :         if ( j < NF_MAX_DEFAULT_COLORS )
     475             :         {
     476           0 :             i = j;
     477             :         }
     478             :     }
     479             : 
     480        7108 :     Color* pResult = NULL;
     481        7108 :     if (i >= NF_MAX_DEFAULT_COLORS)
     482             :     {
     483         656 :         const OUString& rColorWord = rKeyword[NF_KEY_COLOR];
     484         656 :         sal_Int32 nPos = sString.startsWith(rColorWord);
     485         656 :         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        6452 :         sStr = "";
     515        6452 :         if (bConvertMode)
     516             :         {
     517         330 :             pFormatter->ChangeIntl(eNewLnge);
     518         330 :             sStr = GetKeywords()[NF_KEY_FIRSTCOLOR+i];           // red -> rot
     519         330 :             pFormatter->ChangeIntl(eTmpLnge);
     520             :         }
     521             :         else
     522             :         {
     523        6122 :             sStr = rKeyword[NF_KEY_FIRSTCOLOR+i];
     524             :         }
     525        6452 :         pResult = &(StandardColor[i]);
     526             :     }
     527        7108 :     return pResult;
     528             : }
     529             : 
     530      197230 : short ImpSvNumberformatScan::GetKeyWord( const OUString& sSymbol, sal_Int32 nPos )
     531             : {
     532      197230 :     OUString sString = pFormatter->GetCharClass()->uppercase( sSymbol, nPos, sSymbol.getLength() - nPos );
     533      197230 :     const NfKeywordTable & rKeyword = GetKeywords();
     534             :     // #77026# for the Xcl perverts: the GENERAL keyword is recognized anywhere
     535      197230 :     if ( sString.startsWith( rKeyword[NF_KEY_GENERAL] ))
     536             :     {
     537        1032 :         return NF_KEY_GENERAL;
     538             :     }
     539             :     //! MUST be a reverse search to find longer strings first
     540      196198 :     short i = NF_KEYWORD_ENTRIES_COUNT-1;
     541      196198 :     bool bFound = false;
     542     2096264 :     for ( ; i > NF_KEY_LASTKEYWORD_SO5; --i )
     543             :     {
     544     1921048 :         bFound = sString.startsWith(rKeyword[i]);
     545     1921048 :         if ( bFound )
     546             :         {
     547       20982 :             break;
     548             :         }
     549             :     }
     550             :     // new keywords take precedence over old keywords
     551      196198 :     if ( !bFound )
     552             :     {
     553             :         // skip the gap of colors et al between new and old keywords and search on
     554      175216 :         i = NF_KEY_LASTKEYWORD;
     555     3321366 :         while ( i > 0 && sString.indexOf(rKeyword[i]) != 0 )
     556             :         {
     557     2970934 :             i--;
     558             :         }
     559      175216 :         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        1994 :             short j = i - 1;
     564        7976 :             while ( j > 0 && sString.indexOf(rKeyword[j]) != 0 )
     565             :             {
     566        3988 :                 j--;
     567             :             }
     568        1994 :             if ( j && rKeyword[j].getLength() > rKeyword[i].getLength() )
     569             :             {
     570        1994 :                 return j;
     571             :             }
     572             :         }
     573             :     }
     574             :     // The Thai T NatNum modifier during Xcl import.
     575      196682 :     if (i == 0 && bConvertMode &&
     576        2478 :         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      194204 :     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      723576 : short ImpSvNumberformatScan::Next_Symbol( const OUString& rStr,
     637             :                                           sal_Int32& nPos,
     638             :                                           OUString& sSymbol )
     639             : {
     640      723576 :     if ( bKeywordsNeedInit )
     641             :     {
     642           0 :         InitKeywords();
     643             :     }
     644      723576 :     const CharClass* pChrCls = pFormatter->GetCharClass();
     645      723576 :     const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
     646      723576 :     const sal_Int32 nStart = nPos;
     647      723576 :     short eType = 0;
     648      723576 :     ScanState eState = SsStart;
     649      723576 :     sSymbol = "";
     650     2211440 :     while ( nPos < rStr.getLength() && eState != SsStop )
     651             :     {
     652      764328 :         sal_Unicode cToken = rStr[nPos++];
     653      764328 :         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      725564 :             if ( nCurrPos >= 0 && sCurString.getLength() > 1 &&
     663        1024 :                  nPos-1 + sCurString.getLength() <= rStr.getLength() &&
     664         944 :                  !(nPos > 1 && rStr[nPos-2] == '[') )
     665             :             {
     666         472 :                 OUString aTest = pChrCls->uppercase( rStr.copy( nPos-1, sCurString.getLength() ) );
     667         472 :                 if ( aTest == sCurString )
     668             :                 {
     669          40 :                     sSymbol = rStr.copy( --nPos, sCurString.getLength() );
     670          40 :                     nPos = nPos + sSymbol.getLength();
     671          40 :                     eState = SsStop;
     672          40 :                     eType = NF_SYMBOLTYPE_STRING;
     673          40 :                     return eType;
     674         472 :                 }
     675             :             }
     676      723536 :             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      465416 :                 eType = NF_SYMBOLTYPE_DEL;
     693      465416 :                 sSymbol += OUString(cToken);
     694      465416 :                 eState = SsStop;
     695      465416 :                 break;
     696             :             case '*':
     697        4624 :                 eType = NF_SYMBOLTYPE_STAR;
     698        4624 :                 sSymbol += OUString(cToken);
     699        4624 :                 eState = SsGetStar;
     700        4624 :                 break;
     701             :             case '_':
     702        4024 :                 eType = NF_SYMBOLTYPE_BLANK;
     703        4024 :                 sSymbol += OUString(cToken);
     704        4024 :                 eState = SsGetBlank;
     705        4024 :                 break;
     706             :             case '"':
     707        1078 :                 eType = NF_SYMBOLTYPE_STRING;
     708        1078 :                 eState = SsGetString;
     709        1078 :                 sSymbol += OUString(cToken);
     710        1078 :                 break;
     711             :             case '\\':
     712         720 :                 eType = NF_SYMBOLTYPE_STRING;
     713         720 :                 eState = SsGetChar;
     714         720 :                 sSymbol += OUString(cToken);
     715         720 :                 break;
     716             :             case '$':
     717             :             case '+':
     718             :             case '(':
     719             :             case ')':
     720       43268 :                 eType = NF_SYMBOLTYPE_STRING;
     721       43268 :                 eState = SsStop;
     722       43268 :                 sSymbol += OUString(cToken);
     723       43268 :                 break;
     724             :             default :
     725     1021982 :                 if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cToken) ||
     726      204406 :                     StringEqualsChar( pFormatter->GetNumThousandSep(), cToken) ||
     727      204406 :                     StringEqualsChar( pFormatter->GetDateSep(), cToken) ||
     728      204382 :                     StringEqualsChar( pLoc->getTimeSep(), cToken) ||
     729      204382 :                     StringEqualsChar( pLoc->getTime100SecSep(), cToken))
     730             :                 {
     731             :                     // Another separator than pre-known ASCII
     732          24 :                     eType = NF_SYMBOLTYPE_DEL;
     733          24 :                     sSymbol += OUString(cToken);
     734          24 :                     eState = SsStop;
     735             :                 }
     736      204382 :                 else if ( pChrCls->isLetter( rStr, nPos-1 ) )
     737             :                 {
     738      166060 :                     short nTmpType = GetKeyWord( rStr, nPos-1 );
     739      166060 :                     if ( nTmpType )
     740             :                     {
     741      148150 :                         bool bCurrency = false;
     742             :                         // "Automatic" currency may start with keyword,
     743             :                         // like "R" (Rand) and 'R' (era)
     744      592598 :                         if ( nCurrPos != STRING_NOTFOUND &&
     745      296300 :                              nPos-1 + sCurString.getLength() <= rStr.getLength() &&
     746      148148 :                              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      148150 :                         if ( bCurrency )
     755             :                         {
     756           0 :                             eState = SsGetWord;
     757           0 :                             sSymbol += OUString(cToken);
     758             :                         }
     759             :                         else
     760             :                         {
     761      148150 :                             eType = nTmpType;
     762      148150 :                             sal_Int32 nLen = sKeyword[eType].getLength();
     763      148150 :                             sSymbol = rStr.copy( nPos-1, nLen );
     764      148150 :                             if ( eType == NF_KEY_E || IsAmbiguousE( eType ) )
     765             :                             {
     766       10970 :                                 sal_Unicode cNext = rStr[nPos];
     767       10970 :                                 switch ( cNext )
     768             :                                 {
     769             :                                 case '+' :
     770             :                                 case '-' :  // E+ E- combine to one symbol
     771        2074 :                                     sSymbol += OUString(cNext);
     772        2074 :                                     eType = NF_KEY_E;
     773        2074 :                                     nPos++;
     774        2074 :                                     break;
     775             :                                 case '0' :
     776             :                                 case '#' :  // scientific E without sign
     777           0 :                                     eType = NF_KEY_E;
     778           0 :                                     break;
     779             :                                 }
     780             :                             }
     781      148150 :                             nPos--;
     782      148150 :                             nPos = nPos + nLen;
     783      148150 :                             eState = SsStop;
     784             :                         }
     785             :                     }
     786             :                     else
     787             :                     {
     788       17910 :                         eState = SsGetWord;
     789       17910 :                         sSymbol += OUString(cToken);
     790             :                     }
     791             :                 }
     792             :                 else
     793             :                 {
     794       38322 :                     eType = NF_SYMBOLTYPE_STRING;
     795       38322 :                     eState = SsStop;
     796       38322 :                     sSymbol += OUString(cToken);
     797             :                 }
     798      204406 :                 break;
     799             :             }
     800      723536 :             break;
     801             :         case SsGetChar:
     802         720 :             sSymbol += OUString(cToken);
     803         720 :             eState = SsStop;
     804         720 :             break;
     805             :         case SsGetString:
     806        2612 :             if (cToken == '"')
     807             :             {
     808        1078 :                 eState = SsStop;
     809             :             }
     810        2612 :             sSymbol += OUString(cToken);
     811        2612 :             break;
     812             :         case SsGetWord:
     813       28772 :             if ( pChrCls->isLetter( rStr, nPos-1 ) )
     814             :             {
     815       28708 :                 short nTmpType = GetKeyWord( rStr, nPos-1 );
     816       28708 :                 if ( nTmpType )
     817             :                 {
     818             :                     // beginning of keyword, stop scan and put back
     819       16834 :                     eType = NF_SYMBOLTYPE_STRING;
     820       16834 :                     eState = SsStop;
     821       16834 :                     nPos--;
     822             :                 }
     823             :                 else
     824             :                 {
     825       11874 :                     sSymbol += OUString(cToken);
     826             :                 }
     827             :             }
     828             :             else
     829             :             {
     830          64 :                 bool bDontStop = false;
     831             :                 sal_Unicode cNext;
     832          64 :                 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          64 :                 if ( eState != SsStop && !bDontStop )
     853             :                 {
     854          64 :                     eState = SsStop;
     855          64 :                     nPos--;
     856          64 :                     eType = NF_SYMBOLTYPE_STRING;
     857             :                 }
     858             :             }
     859       28772 :             break;
     860             :         case SsGetStar:
     861        4624 :             eState = SsStop;
     862        4624 :             sSymbol += OUString(cToken);
     863        4624 :             nRepPos = (nPos - nStart) - 1;  // everytime > 0!!
     864        4624 :             break;
     865             :         case SsGetBlank:
     866        4024 :             eState = SsStop;
     867        4024 :             sSymbol += OUString(cToken);
     868        4024 :             break;
     869             :         default:
     870           0 :             break;
     871             :         }                                   // of switch
     872             :     }                                       // of while
     873      723536 :     if (eState == SsGetWord)
     874             :     {
     875        1012 :         eType = NF_SYMBOLTYPE_STRING;
     876             :     }
     877      723536 :     return eType;
     878             : }
     879             : 
     880       88738 : sal_Int32 ImpSvNumberformatScan::Symbol_Division(const OUString& rString)
     881             : {
     882       88738 :     nCurrPos = -1;
     883             :                                                     // Ist Waehrung im Spiel?
     884       88738 :     OUString sString = pFormatter->GetCharClass()->uppercase(rString);
     885       88738 :     sal_Int32 nCPos = 0;
     886      266514 :     while (nCPos >= 0)
     887             :     {
     888       89038 :         nCPos = sString.indexOf(GetCurString(),nCPos);
     889       89038 :         if (nCPos >= 0)
     890             :         {
     891             :             // in Quotes?
     892       24846 :             sal_Int32 nQ = SvNumberformat::GetQuoteEnd( sString, nCPos );
     893       24846 :             if ( nQ < 0 )
     894             :             {
     895             :                 sal_Unicode c;
     896       44002 :                 if ( nCPos == 0 ||
     897       19424 :                     ((c = sString[nCPos-1]) != '"'
     898             :                             && c != '\\') )         // dm kann durch "dm
     899             :                 {                                   // \d geschuetzt werden
     900       24546 :                     nCurrPos = nCPos;
     901       24546 :                     nCPos = -1;
     902             :                 }
     903             :                 else
     904             :                 {
     905          32 :                     nCPos++;                        // weitersuchen
     906             :                 }
     907             :             }
     908             :             else
     909             :             {
     910         268 :                 nCPos = nQ + 1;                     // weitersuchen
     911             :             }
     912             :         }
     913             :     }
     914       88738 :     nAnzStrings = 0;
     915       88738 :     bool bStar = false;                 // wird bei '*'Detektion gesetzt
     916       88738 :     Reset();
     917             : 
     918       88738 :     sal_Int32 nPos = 0;
     919       88738 :     const sal_Int32 nLen = rString.getLength();
     920      901052 :     while (nPos < nLen && nAnzStrings < NF_MAX_FORMAT_SYMBOLS)
     921             :     {
     922      723576 :         nTypeArray[nAnzStrings] = Next_Symbol(rString, nPos, sStrArray[nAnzStrings]);
     923      723576 :         if (nTypeArray[nAnzStrings] == NF_SYMBOLTYPE_STAR)
     924             :         {                               // Ueberwachung des '*'
     925        4624 :             if (bStar)
     926             :             {
     927           0 :                 return nPos;        // Fehler: doppelter '*'
     928             :             }
     929             :             else
     930             :             {
     931        4624 :                 bStar = true;
     932             :             }
     933             :         }
     934      723576 :         nAnzStrings++;
     935             :     }
     936             : 
     937       88738 :     return 0;                       // 0 => ok
     938             : }
     939             : 
     940      628072 : void ImpSvNumberformatScan::SkipStrings(sal_uInt16& i, sal_Int32& nPos)
     941             : {
     942     2377570 :     while (i < nAnzStrings && (   nTypeArray[i] == NF_SYMBOLTYPE_STRING
     943      547982 :                                || nTypeArray[i] == NF_SYMBOLTYPE_BLANK
     944      543958 :                                || nTypeArray[i] == NF_SYMBOLTYPE_STAR) )
     945             :     {
     946       29486 :         nPos = nPos + sStrArray[i].getLength();
     947       29486 :         i++;
     948             :     }
     949      628072 : }
     950             : 
     951       26056 : sal_uInt16 ImpSvNumberformatScan::PreviousKeyword(sal_uInt16 i)
     952             : {
     953       26056 :     short res = 0;
     954       26056 :     if (i > 0 && i < nAnzStrings)
     955             :     {
     956       16976 :         i--;
     957       55050 :         while (i > 0 && nTypeArray[i] <= 0)
     958             :         {
     959       21098 :             i--;
     960             :         }
     961       16976 :         if (nTypeArray[i] > 0)
     962             :         {
     963       16976 :             res = nTypeArray[i];
     964             :         }
     965             :     }
     966       26056 :     return res;
     967             : }
     968             : 
     969       21936 : sal_uInt16 ImpSvNumberformatScan::NextKeyword(sal_uInt16 i)
     970             : {
     971       21936 :     short res = 0;
     972       21936 :     if (i < nAnzStrings-1)
     973             :     {
     974       20736 :         i++;
     975       60070 :         while (i < nAnzStrings-1 && nTypeArray[i] <= 0)
     976             :         {
     977       18598 :             i++;
     978             :         }
     979       20736 :         if (nTypeArray[i] > 0)
     980             :         {
     981       20726 :             res = nTypeArray[i];
     982             :         }
     983             :     }
     984       21936 :     return res;
     985             : }
     986             : 
     987          34 : short ImpSvNumberformatScan::PreviousType( sal_uInt16 i )
     988             : {
     989          34 :     if ( i > 0 && i < nAnzStrings )
     990             :     {
     991          68 :         do
     992             :         {
     993          34 :             i--;
     994             :         }
     995          34 :         while ( i > 0 && nTypeArray[i] == NF_SYMBOLTYPE_EMPTY );
     996          34 :         return nTypeArray[i];
     997             :     }
     998           0 :     return 0;
     999             : }
    1000             : 
    1001       53808 : sal_Unicode ImpSvNumberformatScan::PreviousChar(sal_uInt16 i)
    1002             : {
    1003       53808 :     sal_Unicode res = ' ';
    1004       53808 :     if (i > 0 && i < nAnzStrings)
    1005             :     {
    1006       44728 :         i--;
    1007      242740 :         while (i > 0 &&
    1008       38334 :                ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
    1009       38326 :                  nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
    1010       38290 :                  nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
    1011       38290 :                  nTypeArray[i] == NF_SYMBOLTYPE_BLANK ))
    1012             :         {
    1013          44 :             i--;
    1014             :         }
    1015       44728 :         if (sStrArray[i].getLength() > 0)
    1016             :         {
    1017       44728 :             res = sStrArray[i][sStrArray[i].getLength()-1];
    1018             :         }
    1019             :     }
    1020       53808 :     return res;
    1021             : }
    1022             : 
    1023       36154 : sal_Unicode ImpSvNumberformatScan::NextChar(sal_uInt16 i)
    1024             : {
    1025       36154 :     sal_Unicode res = ' ';
    1026       36154 :     if (i < nAnzStrings-1)
    1027             :     {
    1028       36154 :         i++;
    1029      216780 :         while (i < nAnzStrings-1 &&
    1030       36118 :                ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ||
    1031       36118 :                  nTypeArray[i] == NF_SYMBOLTYPE_STRING ||
    1032       36118 :                  nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
    1033       36118 :                  nTypeArray[i] == NF_SYMBOLTYPE_BLANK))
    1034             :         {
    1035           0 :             i++;
    1036             :         }
    1037       36154 :         if (sStrArray[i].getLength() > 0)
    1038             :         {
    1039       36154 :             res = sStrArray[i][0];
    1040             :         }
    1041             :     }
    1042       36154 :     return res;
    1043             : }
    1044             : 
    1045           8 : bool ImpSvNumberformatScan::IsLastBlankBeforeFrac(sal_uInt16 i)
    1046             : {
    1047           8 :     bool res = true;
    1048           8 :     if (i < nAnzStrings-1)
    1049             :     {
    1050           8 :         bool bStop = false;
    1051           8 :         i++;
    1052          28 :         while (i < nAnzStrings-1 && !bStop)
    1053             :         {
    1054          12 :             i++;
    1055          24 :             if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
    1056          12 :                  sStrArray[i][0] == '/')
    1057             :             {
    1058           8 :                 bStop = true;
    1059             :             }
    1060           8 :             else if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
    1061           4 :                       sStrArray[i][0] == ' ')
    1062             :             {
    1063           0 :                 res = false;
    1064             :             }
    1065             :         }
    1066           8 :         if (!bStop)                                 // kein '/'{
    1067             :         {
    1068           0 :             res = false;
    1069             :         }
    1070             :     }
    1071             :     else
    1072             :     {
    1073           0 :         res = false;                                // kein '/' mehr
    1074             :     }
    1075           8 :     return res;
    1076             : }
    1077             : 
    1078       89886 : void ImpSvNumberformatScan::Reset()
    1079             : {
    1080       89886 :     nAnzStrings = 0;
    1081       89886 :     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       89886 :     eScannedType = NUMBERFORMAT_UNDEFINED;
    1091       89886 :     nRepPos = 0;
    1092       89886 :     bExp = false;
    1093       89886 :     bThousand = false;
    1094       89886 :     nThousand = 0;
    1095       89886 :     bDecSep = false;
    1096       89886 :     nDecPos = (sal_uInt16)-1;
    1097       89886 :     nExpPos = (sal_uInt16)-1;
    1098       89886 :     nBlankPos = (sal_uInt16)-1;
    1099       89886 :     nCntPre = 0;
    1100       89886 :     nCntPost = 0;
    1101       89886 :     nCntExp = 0;
    1102       89886 :     bFrac = false;
    1103       89886 :     bBlank = false;
    1104       89886 :     nNatNumModifier = 0;
    1105       89886 : }
    1106             : 
    1107        6248 : bool ImpSvNumberformatScan::Is100SecZero( sal_uInt16 i, bool bHadDecSep )
    1108             : {
    1109        6248 :     sal_uInt16 nIndexPre = PreviousKeyword( i );
    1110             :     return (nIndexPre == NF_KEY_S || nIndexPre == NF_KEY_SS) &&
    1111             :             (bHadDecSep ||
    1112        6248 :              ( i > 0 && nTypeArray[i-1] == NF_SYMBOLTYPE_STRING));
    1113             :                 // SS"any"00  take "any" as a valid decimal separator
    1114             : }
    1115             : 
    1116       88738 : sal_Int32 ImpSvNumberformatScan::ScanType()
    1117             : {
    1118       88738 :     const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
    1119             : 
    1120       88738 :     sal_Int32 nPos = 0;
    1121       88738 :     sal_uInt16 i = 0;
    1122             :     short eNewType;
    1123       88738 :     bool bMatchBracket = false;
    1124       88738 :     bool bHaveGeneral = false;      // if General/Standard encountered
    1125             : 
    1126       88738 :     SkipStrings(i, nPos);
    1127      716810 :     while (i < nAnzStrings)
    1128             :     {
    1129      539334 :         if (nTypeArray[i] > 0)
    1130             :         {                                       // keyword
    1131             :             sal_uInt16 nIndexPre;
    1132             :             sal_uInt16 nIndexNex;
    1133             :             sal_Unicode cChar;
    1134             : 
    1135      124382 :             switch (nTypeArray[i])
    1136             :             {
    1137             :             case NF_KEY_E:                          // E
    1138        2074 :                 eNewType = NUMBERFORMAT_SCIENTIFIC;
    1139        2074 :                 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       18460 :                 eNewType = NUMBERFORMAT_TIME;
    1147       18460 :                 break;
    1148             :             case NF_KEY_M:                          // M
    1149             :             case NF_KEY_MM:                         // MM
    1150             :                 // minute or month
    1151       19808 :                 nIndexPre = PreviousKeyword(i);
    1152       19808 :                 nIndexNex = NextKeyword(i);
    1153       19808 :                 cChar = PreviousChar(i);
    1154       19808 :                 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        9936 :                     eNewType = NUMBERFORMAT_TIME;
    1161        9936 :                     nTypeArray[i] -= 2;         // 6 -> 4, 7 -> 5
    1162             :                 }
    1163             :                 else
    1164             :                 {
    1165        9872 :                     eNewType = NUMBERFORMAT_DATE;
    1166             :                 }
    1167       19808 :                 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       82014 :                 eNewType = NUMBERFORMAT_DATE;
    1193       82014 :                 break;
    1194             :             case NF_KEY_CCC:                // CCC
    1195         994 :                 eNewType = NUMBERFORMAT_CURRENCY;
    1196         994 :                 break;
    1197             :             case NF_KEY_GENERAL:            // Standard
    1198        1032 :                 eNewType = NUMBERFORMAT_NUMBER;
    1199        1032 :                 bHaveGeneral = true;
    1200        1032 :                 break;
    1201             :             default:
    1202           0 :                 eNewType = NUMBERFORMAT_UNDEFINED;
    1203           0 :                 break;
    1204             :             }
    1205             :         }
    1206             :         else
    1207             :         {                                       // control character
    1208      414952 :             switch ( sStrArray[i][0] )
    1209             :             {
    1210             :             case '#':
    1211             :             case '?':
    1212      116256 :                 eNewType = NUMBERFORMAT_NUMBER;
    1213      116256 :                 break;
    1214             :             case '0':
    1215       91106 :                 if ( (eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME )
    1216             :                 {
    1217        4120 :                     if ( Is100SecZero( i, bDecSep ) )
    1218             :                     {
    1219        4120 :                         bDecSep = true;                 // subsequent 0's
    1220        4120 :                         eNewType = NUMBERFORMAT_TIME;
    1221             :                     }
    1222             :                     else
    1223             :                     {
    1224           0 :                         return nPos;                    // Error
    1225             :                     }
    1226             :                 }
    1227             :                 else
    1228             :                 {
    1229       86986 :                     eNewType = NUMBERFORMAT_NUMBER;
    1230             :                 }
    1231       91106 :                 break;
    1232             :             case '%':
    1233        2010 :                 eNewType = NUMBERFORMAT_PERCENT;
    1234        2010 :                 break;
    1235             :             case '/':
    1236       17664 :                 eNewType = NUMBERFORMAT_FRACTION;
    1237       17664 :                 break;
    1238             :             case '[':
    1239       70598 :                 if ( i < nAnzStrings-1 &&
    1240       24242 :                      nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
    1241       22114 :                      sStrArray[i+1][0] == '$' )
    1242             :                 {   // as of SV_NUMBERFORMATTER_VERSION_NEW_CURR
    1243       14210 :                     eNewType = NUMBERFORMAT_CURRENCY;
    1244       14210 :                     bMatchBracket = true;
    1245             :                 }
    1246       27968 :                 else if ( i < nAnzStrings-1 &&
    1247       10032 :                           nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
    1248        7904 :                           sStrArray[i+1][0] == '~' )
    1249             :                 {   // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
    1250        7904 :                     eNewType = NUMBERFORMAT_DATE;
    1251        7904 :                     bMatchBracket = true;
    1252             :                 }
    1253             :                 else
    1254             :                 {
    1255        2128 :                     sal_uInt16 nIndexNex = NextKeyword(i);
    1256        2128 :                     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        2128 :                         eNewType = NUMBERFORMAT_TIME;
    1263             :                     else
    1264             :                     {
    1265           0 :                         return nPos;                // Error
    1266             :                     }
    1267             :                 }
    1268       24242 :                 break;
    1269             :             case '@':
    1270        1260 :                 eNewType = NUMBERFORMAT_TEXT;
    1271        1260 :                 break;
    1272             :             default:
    1273      162414 :                 if (pLoc->getTime100SecSep().equals(sStrArray[i]))
    1274             :                 {
    1275       29440 :                     bDecSep = true;                     // for SS,0
    1276             :                 }
    1277      162414 :                 eNewType = NUMBERFORMAT_UNDEFINED;
    1278      162414 :                 break;
    1279             :             }
    1280             :         }
    1281      539334 :         if (eScannedType == NUMBERFORMAT_UNDEFINED)
    1282             :         {
    1283      100790 :             eScannedType = eNewType;
    1284             :         }
    1285      438544 :         else if (eScannedType == NUMBERFORMAT_TEXT || eNewType == NUMBERFORMAT_TEXT)
    1286             :         {
    1287          16 :             eScannedType = NUMBERFORMAT_TEXT;               // Text bleibt immer Text
    1288             :         }
    1289      438528 :         else if (eNewType == NUMBERFORMAT_UNDEFINED)
    1290             :         {                                           // bleibt wie bisher
    1291             :         }
    1292      288364 :         else if (eScannedType != eNewType)
    1293             :         {
    1294      107856 :             switch (eScannedType)
    1295             :             {
    1296             :             case NUMBERFORMAT_DATE:
    1297       15758 :                 switch (eNewType)
    1298             :                 {
    1299             :                 case NUMBERFORMAT_TIME:
    1300        2090 :                     eScannedType = NUMBERFORMAT_DATETIME;
    1301        2090 :                     break;
    1302             :                 case NUMBERFORMAT_FRACTION:         // DD/MM
    1303       13668 :                     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       15758 :                 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        4074 :                 switch (eNewType)
    1337             :                 {
    1338             :                 case NUMBERFORMAT_TIME:
    1339             :                 case NUMBERFORMAT_DATE:
    1340        4074 :                     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        4074 :                 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        5076 :                 switch (eNewType)
    1366             :                 {
    1367             :                 case NUMBERFORMAT_NUMBER:   // nur Zahl nach E
    1368        5076 :                     break;
    1369             :                 default:
    1370           0 :                     return nPos;
    1371             :                 }
    1372        5076 :                 break;
    1373             :             case NUMBERFORMAT_NUMBER:
    1374        9178 :                 switch (eNewType)
    1375             :                 {
    1376             :                 case NUMBERFORMAT_SCIENTIFIC:
    1377             :                 case NUMBERFORMAT_PERCENT:
    1378             :                 case NUMBERFORMAT_FRACTION:
    1379             :                 case NUMBERFORMAT_CURRENCY:
    1380        9178 :                     eScannedType = eNewType;
    1381        9178 :                     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        9178 :                 break;
    1393             :             case NUMBERFORMAT_FRACTION:
    1394        4994 :                 switch (eNewType)
    1395             :                 {
    1396             :                 case NUMBERFORMAT_NUMBER:           // nur Zahl nach Bruch
    1397        4994 :                     break;
    1398             :                 default:
    1399           0 :                     return nPos;
    1400             :                 }
    1401        4994 :                 break;
    1402             :             default:
    1403       68776 :                 break;
    1404             :             }
    1405             :         }
    1406      539334 :         nPos = nPos + sStrArray[i].getLength();           // Korrekturposition
    1407      539334 :         i++;
    1408      539334 :         if ( bMatchBracket )
    1409             :         {   // no type detection inside of matching brackets if [$...], [~...]
    1410      198984 :             while ( bMatchBracket && i < nAnzStrings )
    1411             :             {
    1412      205244 :                 if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL
    1413       50488 :                      && sStrArray[i][0] == ']' )
    1414             :                 {
    1415       22114 :                     bMatchBracket = false;
    1416             :                 }
    1417             :                 else
    1418             :                 {
    1419      132642 :                     nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    1420             :                 }
    1421      154756 :                 nPos = nPos + sStrArray[i].getLength();
    1422      154756 :                 i++;
    1423             :             }
    1424       22114 :             if ( bMatchBracket )
    1425             :             {
    1426           0 :                 return nPos;    // missing closing bracket at end of code
    1427             :             }
    1428             :         }
    1429      539334 :         SkipStrings(i, nPos);
    1430             :     }
    1431             : 
    1432       99074 :     if ((eScannedType == NUMBERFORMAT_NUMBER ||
    1433             :          eScannedType == NUMBERFORMAT_UNDEFINED) &&
    1434       10336 :         nCurrPos >= 0 && !bHaveGeneral)
    1435             :     {
    1436       10336 :         eScannedType = NUMBERFORMAT_CURRENCY;   // old "automatic" currency
    1437             :     }
    1438       88738 :     if (eScannedType == NUMBERFORMAT_UNDEFINED)
    1439             :     {
    1440         182 :         eScannedType = NUMBERFORMAT_DEFINED;
    1441             :     }
    1442       88738 :     return 0;                               // Alles ok
    1443             : }
    1444             : 
    1445       33958 : bool ImpSvNumberformatScan::InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr )
    1446             : {
    1447       33958 :     if (nAnzStrings >= NF_MAX_FORMAT_SYMBOLS || nPos > nAnzStrings)
    1448             :     {
    1449           0 :         return false;
    1450             :     }
    1451       33958 :     if (nPos > 0 && nTypeArray[nPos-1] == NF_SYMBOLTYPE_EMPTY)
    1452             :     {
    1453       33958 :         --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       33958 :     ++nAnzResStrings;
    1469       33958 :     nTypeArray[nPos] = static_cast<short>(eType);
    1470       33958 :     sStrArray[nPos] = rStr;
    1471       33958 :     return true;
    1472             : }
    1473             : 
    1474       72104 : int ImpSvNumberformatScan::FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i,
    1475             :                                                  sal_uInt16& rAnzResStrings )
    1476             : {
    1477       87912 :     if ( sStrArray[i][0] == '[' &&
    1478             :          i < nAnzStrings-1 &&
    1479        7904 :          nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
    1480        7904 :          sStrArray[i+1][0] == '~' )
    1481             :     {
    1482             :         // [~calendarID]
    1483             :         // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
    1484        7904 :         nPos = nPos + sStrArray[i].getLength();           // [
    1485        7904 :         nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
    1486        7904 :         nPos = nPos + sStrArray[++i].getLength();     // ~
    1487        7904 :         sStrArray[i-1] += sStrArray[i];     // [~
    1488        7904 :         nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    1489        7904 :         rAnzResStrings--;
    1490        7904 :         if ( ++i >= nAnzStrings )
    1491             :         {
    1492           0 :             return -1;      // error
    1493             :         }
    1494        7904 :         nPos = nPos + sStrArray[i].getLength();           // calendarID
    1495        7904 :         OUString& rStr = sStrArray[i];
    1496        7904 :         nTypeArray[i] = NF_SYMBOLTYPE_CALENDAR; // convert
    1497        7904 :         i++;
    1498       47424 :         while ( i < nAnzStrings && sStrArray[i][0] != ']' )
    1499             :         {
    1500       31616 :             nPos = nPos + sStrArray[i].getLength();
    1501       31616 :             rStr += sStrArray[i];
    1502       31616 :             nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    1503       31616 :             rAnzResStrings--;
    1504       31616 :             i++;
    1505             :         }
    1506       15808 :         if ( rStr.getLength() && i < nAnzStrings &&
    1507        7904 :              sStrArray[i][0] == ']' )
    1508             :         {
    1509        7904 :             nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
    1510        7904 :             nPos = nPos + sStrArray[i].getLength();
    1511        7904 :             i++;
    1512             :         }
    1513             :         else
    1514             :         {
    1515           0 :             return -1;      // error
    1516             :         }
    1517        7904 :         return 1;
    1518             :     }
    1519       64200 :     return 0;
    1520             : }
    1521             : 
    1522       88738 : sal_Int32 ImpSvNumberformatScan::FinalScan( OUString& rString )
    1523             : {
    1524       88738 :     const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
    1525             : 
    1526             :     // save values for convert mode
    1527       88738 :     OUString sOldDecSep       = pFormatter->GetNumDecimalSep();
    1528       88738 :     OUString sOldThousandSep  = pFormatter->GetNumThousandSep();
    1529       88738 :     OUString sOldDateSep      = pFormatter->GetDateSep();
    1530       88738 :     OUString sOldTimeSep      = pLoc->getTimeSep();
    1531       88738 :     OUString sOldTime100SecSep= pLoc->getTime100SecSep();
    1532       88738 :     OUString sOldCurSymbol    = GetCurSymbol();
    1533       88738 :     OUString sOldCurString = GetCurString();
    1534       88738 :     sal_Unicode cOldKeyH    = sKeyword[NF_KEY_H][0];
    1535       88738 :     sal_Unicode cOldKeyMI   = sKeyword[NF_KEY_MI][0];
    1536       88738 :     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       88738 :     if ( sOldThousandSep[0] == cNonBreakingSpace && sOldThousandSep.getLength() == 1 )
    1543             :     {
    1544         134 :         sOldThousandSep = " ";
    1545             :     }
    1546             :     // change locale data et al
    1547       88738 :     if (bConvertMode)
    1548             :     {
    1549        5702 :         pFormatter->ChangeIntl(eNewLnge);
    1550             :         //! pointer may have changed
    1551        5702 :         pLoc = pFormatter->GetLocaleData();
    1552             :         //! init new keywords
    1553        5702 :         InitKeywords();
    1554             :     }
    1555       88738 :     const CharClass* pChrCls = pFormatter->GetCharClass();
    1556             : 
    1557       88738 :     sal_Int32 nPos = 0;                    // error correction position
    1558       88738 :     sal_uInt16 i = 0;                      // symbol loop counter
    1559       88738 :     sal_uInt16 nCounter = 0;               // counts digits
    1560       88738 :     nAnzResStrings = nAnzStrings;          // counts remaining symbols
    1561       88738 :     bDecSep = false;                       // reset in case already used in TypeCheck
    1562       88738 :     bool bThaiT = false;                   // Thai T NatNum modifier present
    1563       88738 :     bool bTimePart = false;
    1564             : 
    1565       88738 :     switch (eScannedType)
    1566             :     {
    1567             :     case NUMBERFORMAT_TEXT:
    1568             :     case NUMBERFORMAT_DEFINED:
    1569        5182 :         while (i < nAnzStrings)
    1570             :         {
    1571        2298 :             switch (nTypeArray[i])
    1572             :             {
    1573             :             case NF_SYMBOLTYPE_BLANK:
    1574             :             case NF_SYMBOLTYPE_STAR:
    1575         788 :                 break;
    1576             :             case NF_KEY_GENERAL :   // #77026# "General" is the same as "@"
    1577           0 :                 break;
    1578             :             default:
    1579        2786 :                 if ( nTypeArray[i] != NF_SYMBOLTYPE_DEL ||
    1580        1276 :                      sStrArray[i][0] != '@' )
    1581             :                 {
    1582         250 :                     nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    1583             :                 }
    1584        1510 :                 break;
    1585             :             }
    1586        2298 :             nPos = nPos + sStrArray[i].getLength();
    1587        2298 :             i++;
    1588             :         }                                       // of while
    1589        1442 :         break;
    1590             : 
    1591             :     case NUMBERFORMAT_NUMBER:
    1592             :     case NUMBERFORMAT_PERCENT:
    1593             :     case NUMBERFORMAT_CURRENCY:
    1594             :     case NUMBERFORMAT_SCIENTIFIC:
    1595             :     case NUMBERFORMAT_FRACTION:
    1596      331788 :         while (i < nAnzStrings)
    1597             :         {
    1598             :             // TODO: rechecking eScannedType is unnecessary.
    1599             :             // This switch-case is for eScannedType == NUMBERFORMAT_FRACTION anyway
    1600      283026 :             if (eScannedType == NUMBERFORMAT_FRACTION &&    // special case
    1601       23960 :                 nTypeArray[i] == NF_SYMBOLTYPE_DEL &&           // # ### #/#
    1602       17982 :                 StringEqualsChar( sOldThousandSep, ' ' ) && // e.g. France or Sweden
    1603          36 :                 StringEqualsChar( sStrArray[i], ' ' ) &&
    1604           8 :                 !bFrac                          &&
    1605           8 :                 IsLastBlankBeforeFrac(i) )
    1606             :             {
    1607           8 :                 nTypeArray[i] = NF_SYMBOLTYPE_STRING;           // del->string
    1608             :             }                                               // kein Taus.p.
    1609             : 
    1610      944066 :             if (nTypeArray[i] == NF_SYMBOLTYPE_BLANK    ||
    1611      237684 :                 nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
    1612      233172 :                 nTypeArray[i] == NF_KEY_CCC         ||  // CCC
    1613      232178 :                 nTypeArray[i] == NF_KEY_GENERAL )       // Standard
    1614             :             {
    1615        9886 :                 if (nTypeArray[i] == NF_KEY_GENERAL)
    1616             :                 {
    1617        1032 :                     nThousand = FLAG_STANDARD_IN_FORMAT;
    1618        1032 :                     if ( bConvertMode )
    1619             :                     {
    1620          38 :                         sStrArray[i] = sNameStandardFormat;
    1621             :                     }
    1622             :                 }
    1623        9886 :                 nPos = nPos + sStrArray[i].getLength();
    1624        9886 :                 i++;
    1625             :             }
    1626      439888 :             else if (nTypeArray[i] == NF_SYMBOLTYPE_STRING ||  // Strings oder
    1627      208742 :                      nTypeArray[i] > 0)                     // Keywords
    1628             :             {
    1629       26552 :                 if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
    1630        2074 :                     nTypeArray[i] == NF_KEY_E)         // E+
    1631             :                 {
    1632        2074 :                     if (bExp)                               // doppelt
    1633             :                     {
    1634           0 :                         return nPos;
    1635             :                     }
    1636        2074 :                     bExp = true;
    1637        2074 :                     nExpPos = i;
    1638        2074 :                     if (bDecSep)
    1639             :                     {
    1640        2074 :                         nCntPost = nCounter;
    1641             :                     }
    1642             :                     else
    1643             :                     {
    1644           0 :                         nCntPre = nCounter;
    1645             :                     }
    1646        2074 :                     nCounter = 0;
    1647        2074 :                     nTypeArray[i] = NF_SYMBOLTYPE_EXP;
    1648             :                 }
    1649       28390 :                 else if (eScannedType == NUMBERFORMAT_FRACTION &&
    1650        5986 :                          sStrArray[i][0] == ' ')
    1651             :                 {
    1652        3988 :                     if (!bBlank && !bFrac)  // nicht doppelt oder hinter /
    1653             :                     {
    1654           8 :                         if (bDecSep && nCounter > 0)    // Nachkommastellen
    1655             :                         {
    1656           0 :                             return nPos;                // Fehler
    1657             :                         }
    1658           8 :                         bBlank = true;
    1659           8 :                         nBlankPos = i;
    1660           8 :                         nCntPre = nCounter;
    1661           8 :                         nCounter = 0;
    1662             :                     }
    1663        3988 :                     nTypeArray[i] = NF_SYMBOLTYPE_FRACBLANK;
    1664             :                 }
    1665       18416 :                 else if (nTypeArray[i] == NF_KEY_THAI_T)
    1666             :                 {
    1667           0 :                     bThaiT = true;
    1668           0 :                     sStrArray[i] = sKeyword[nTypeArray[i]];
    1669             :                 }
    1670       21096 :                 else if (sStrArray[i][0] >= '0' &&
    1671        2680 :                          sStrArray[i][0] <= '9')
    1672             :                 {
    1673        1990 :                     OUString sDiv;
    1674        1990 :                     sal_uInt16 j = i;
    1675        7960 :                     while(j < nAnzStrings)
    1676             :                     {
    1677        3980 :                         sDiv += sStrArray[j++];
    1678             :                     }
    1679        1990 :                     if (OUString::valueOf(sDiv.toInt32()) == sDiv)
    1680             :                     {
    1681             :                         /* Found a Divisor */
    1682        7960 :                         while (i < j)
    1683             :                         {
    1684        3980 :                             nTypeArray[i++] = NF_SYMBOLTYPE_FRAC_FDIV;
    1685             :                         }
    1686        1990 :                         i = j - 1;                            // Stop the loop
    1687        1990 :                         if (nCntPost)
    1688             :                         {
    1689        1990 :                             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        1990 :                         if ( ( eScannedType != NUMBERFORMAT_FRACTION ) && (!nCntPre) )
    1698             :                         {
    1699           0 :                             nCntPre++;
    1700             :                         }
    1701        1990 :                     }
    1702             :                 }
    1703             :                 else
    1704             :                 {
    1705       16426 :                     nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    1706             :                 }
    1707       24478 :                 nPos = nPos + sStrArray[i].getLength();
    1708       24478 :                 i++;
    1709             :             }
    1710      206668 :             else if (nTypeArray[i] == NF_SYMBOLTYPE_DEL)
    1711             :             {
    1712      206668 :                 sal_Unicode cHere = sStrArray[i][0];
    1713      206668 :                 sal_Unicode cSaved = cHere;
    1714             :                 // Handle not pre-known separators in switch.
    1715             :                 sal_Unicode cSimplified;
    1716      206668 :                 if (StringEqualsChar( pFormatter->GetNumThousandSep(), cHere))
    1717             :                 {
    1718       33910 :                     cSimplified = ',';
    1719             :                 }
    1720      172758 :                 else if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cHere))
    1721             :                 {
    1722       24348 :                     cSimplified = '.';
    1723             :                 }
    1724             :                 else
    1725             :                 {
    1726      148410 :                     cSimplified = cHere;
    1727             :                 }
    1728             : 
    1729      206668 :                 OUString& rStr = sStrArray[i];
    1730             : 
    1731      206668 :                 switch ( cSimplified )
    1732             :                 {
    1733             :                 case '#':
    1734             :                 case '0':
    1735             :                 case '?':
    1736      106752 :                     if (nThousand > 0)                  // #... #
    1737             :                     {
    1738           0 :                         return nPos;                    // Fehler
    1739             :                     }
    1740      106752 :                     else if (bFrac && cHere == '0')
    1741             :                     {
    1742           0 :                         return nPos;                    // 0 im Nenner
    1743             :                     }
    1744      106752 :                     nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
    1745      106752 :                     nPos = nPos + rStr.getLength();
    1746      106752 :                     i++;
    1747      106752 :                     nCounter++;
    1748      696582 :                     while (i < nAnzStrings &&
    1749      171670 :                            (sStrArray[i][0] == '#' ||
    1750      136630 :                             sStrArray[i][0] == '0' ||
    1751       80276 :                             sStrArray[i][0] == '?'))
    1752             :                     {
    1753       94502 :                         nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
    1754       94502 :                         nPos = nPos + sStrArray[i].getLength();
    1755       94502 :                         nCounter++;
    1756       94502 :                         i++;
    1757             :                     }
    1758      106752 :                     break;
    1759             :                 case '-':
    1760       20186 :                     if ( bDecSep && nDecPos+1 == i &&
    1761        3976 :                          nTypeArray[nDecPos] == NF_SYMBOLTYPE_DECSEP )
    1762             :                     {
    1763             :                         // "0.--"
    1764        3976 :                         nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
    1765        3976 :                         nPos = nPos + rStr.getLength();
    1766        3976 :                         i++;
    1767        3976 :                         nCounter++;
    1768       15920 :                         while (i < nAnzStrings &&
    1769        3992 :                                (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        7952 :                             if ( eScannedType == NUMBERFORMAT_CURRENCY
    1776        3976 :                                  && rStr.getLength() >= 2 &&
    1777             :                                  (i == nAnzStrings-1 ||
    1778           0 :                                   sStrArray[i+1][0] != '-') )
    1779             :                             {
    1780           0 :                                 break;
    1781             :                             }
    1782        3976 :                             rStr += sStrArray[i];
    1783        3976 :                             nPos = nPos + sStrArray[i].getLength();
    1784        3976 :                             nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    1785        3976 :                             nAnzResStrings--;
    1786        3976 :                             nCounter++;
    1787        3976 :                             i++;
    1788             :                         }
    1789             :                     }
    1790             :                     else
    1791             :                     {
    1792       12234 :                         nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    1793       12234 :                         nPos = nPos + sStrArray[i].getLength();
    1794       12234 :                         i++;
    1795             :                     }
    1796       16210 :                     break;
    1797             :                 case '.':
    1798             :                 case ',':
    1799             :                 case '\'':
    1800             :                 case ' ':
    1801       63490 :                     if ( StringEqualsChar( sOldThousandSep, cSaved ) )
    1802             :                     {
    1803             :                         // previous char with skip empty
    1804       34000 :                         sal_Unicode cPre = PreviousChar(i);
    1805             :                         sal_Unicode cNext;
    1806       34000 :                         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       67992 :                         else if (i > 0 && i < nAnzStrings-1   &&
    1822             :                                  (cPre == '#' || cPre == '0')      &&
    1823       33992 :                                  ((cNext = NextChar(i)) == '#' || cNext == '0')) // #,#
    1824             :                         {
    1825       33958 :                             nPos = nPos + sStrArray[i].getLength();
    1826       33958 :                             if (!bThousand)                 // only once
    1827             :                             {
    1828       33958 :                                 bThousand = true;
    1829             :                             }
    1830             :                             // Eat it, will be reinserted at proper
    1831             :                             // grouping positions further down.
    1832       33958 :                             nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    1833       33958 :                             nAnzResStrings--;
    1834       33958 :                             i++;
    1835             :                         }
    1836          76 :                         else if (i > 0 && (cPre == '#' || cPre == '0')
    1837          34 :                                  && PreviousType(i) == NF_SYMBOLTYPE_DIGIT
    1838             :                                  && nThousand < FLAG_STANDARD_IN_FORMAT )
    1839             :                         {                                   // #,,,,
    1840          34 :                             if ( StringEqualsChar( sOldThousandSep, ' ' ) )
    1841             :                             {
    1842             :                                 // strange, those French..
    1843          34 :                                 bool bFirst = true;
    1844             :                                 //  set a hard Non-Breaking Space or ConvertMode
    1845          34 :                                 const OUString& rSepF = pFormatter->GetNumThousandSep();
    1846         136 :                                 while ( i < nAnzStrings &&
    1847          34 :                                         sStrArray[i] == sOldThousandSep &&
    1848          34 :                                         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          68 :                                 if ( i < nAnzStrings-1 &&
    1868          34 :                                      sStrArray[i] == sOldThousandSep )
    1869             :                                 {
    1870             :                                     // something following last space
    1871             :                                     // => space if currency contained,
    1872             :                                     // else separator
    1873          34 :                                     nPos = nPos + sStrArray[i].getLength();
    1874         116 :                                     if ( (nPos <= nCurrPos &&
    1875          32 :                                           nCurrPos < nPos + sStrArray[i+1].getLength()) ||
    1876          18 :                                          nTypeArray[i+1] == NF_KEY_CCC ||
    1877             :                                          (i < nAnzStrings-2 &&
    1878          16 :                                           sStrArray[i+1][0] == '[' &&
    1879          16 :                                           sStrArray[i+2][0] == '$') )
    1880             :                                     {
    1881          34 :                                         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          34 :                                     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           8 :                             nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    1918           8 :                             nPos = nPos + rStr.getLength();
    1919           8 :                             i++;
    1920          16 :                             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       29490 :                     else if ( StringEqualsChar( sOldDecSep, cSaved ) )
    1931             :                     {
    1932       24348 :                         if (bBlank || bFrac)    // . behind / or ' '
    1933             :                         {
    1934           0 :                             return nPos;        // error
    1935             :                         }
    1936       24348 :                         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       24348 :                         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       24348 :                             nPos = nPos + sStrArray[i].getLength();
    1960       24348 :                             nTypeArray[i] = NF_SYMBOLTYPE_DECSEP;
    1961       24348 :                             sStrArray[i] = pFormatter->GetNumDecimalSep();
    1962       24348 :                             bDecSep = true;
    1963       24348 :                             nDecPos = i;
    1964       24348 :                             nCntPre = nCounter;
    1965       24348 :                             nCounter = 0;
    1966             : 
    1967       24348 :                             i++;
    1968             :                         }
    1969             :                     }                           // of else = DecSep
    1970             :                     else                        // . without meaning
    1971             :                     {
    1972        9122 :                         if (cSaved == ' ' &&
    1973             :                             eScannedType == NUMBERFORMAT_FRACTION &&
    1974        3980 :                             StringEqualsChar( sStrArray[i], ' ' ) )
    1975             :                         {
    1976        3980 :                             if (!bBlank && !bFrac)  // no dups
    1977             :                             {                       // or behind /
    1978        3980 :                                 if (bDecSep && nCounter > 0)// dec.
    1979             :                                 {
    1980           0 :                                     return nPos;            // error
    1981             :                                 }
    1982        3980 :                                 bBlank = true;
    1983        3980 :                                 nBlankPos = i;
    1984        3980 :                                 nCntPre = nCounter;
    1985        3980 :                                 nCounter = 0;
    1986             :                             }
    1987        3980 :                             nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    1988        3980 :                             nPos = nPos + sStrArray[i].getLength();
    1989             :                         }
    1990             :                         else
    1991             :                         {
    1992        1162 :                             nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    1993        1162 :                             nPos = nPos + rStr.getLength();
    1994        1162 :                             i++;
    1995        2324 :                             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       63490 :                     break;
    2006             :                 case '/':
    2007        3996 :                     if (eScannedType == NUMBERFORMAT_FRACTION)
    2008             :                     {
    2009        7992 :                         if ( i == 0 ||
    2010        3996 :                              (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        3996 :                         else if (!bFrac || (bDecSep && nCounter > 0))
    2016             :                         {
    2017        3996 :                             bFrac = true;
    2018        3996 :                             nCntPost = nCounter;
    2019        3996 :                             nCounter = 0;
    2020        3996 :                             nTypeArray[i] = NF_SYMBOLTYPE_FRAC;
    2021        3996 :                             nPos = nPos + sStrArray[i].getLength();
    2022        3996 :                             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        3996 :                     break;
    2036             :                 case '[' :
    2037       42630 :                     if ( eScannedType == NUMBERFORMAT_CURRENCY &&
    2038             :                          i < nAnzStrings-1 &&
    2039       14210 :                          nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
    2040       14210 :                          sStrArray[i+1][0] == '$' )
    2041             :                     {
    2042             :                         // [$DM-xxx]
    2043             :                         // ab SV_NUMBERFORMATTER_VERSION_NEW_CURR
    2044       14210 :                         nPos = nPos + sStrArray[i].getLength();           // [
    2045       14210 :                         nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
    2046       14210 :                         nPos = nPos + sStrArray[++i].getLength();     // $
    2047       14210 :                         sStrArray[i-1] += sStrArray[i];     // [$
    2048       14210 :                         nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    2049       14210 :                         nAnzResStrings--;
    2050       14210 :                         if ( ++i >= nAnzStrings )
    2051             :                         {
    2052           0 :                             return nPos;        // Fehler
    2053             :                         }
    2054       14210 :                         nPos = nPos + sStrArray[i].getLength();           // DM
    2055       14210 :                         OUString* pStr = &sStrArray[i];
    2056       14210 :                         nTypeArray[i] = NF_SYMBOLTYPE_CURRENCY; // wandeln
    2057       14210 :                         bool bHadDash = false;
    2058       14210 :                         i++;
    2059       85218 :                         while ( i < nAnzStrings && sStrArray[i][0] != ']' )
    2060             :                         {
    2061       56798 :                             nPos = nPos + sStrArray[i].getLength();
    2062       56798 :                             if ( bHadDash )
    2063             :                             {
    2064       42548 :                                 *pStr += sStrArray[i];
    2065       42548 :                                 nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    2066       42548 :                                 nAnzResStrings--;
    2067             :                             }
    2068             :                             else
    2069             :                             {
    2070       14250 :                                 if ( sStrArray[i][0] == '-' )
    2071             :                                 {
    2072       14188 :                                     bHadDash = true;
    2073       14188 :                                     pStr = &sStrArray[i];
    2074       14188 :                                     nTypeArray[i] = NF_SYMBOLTYPE_CURREXT;
    2075             :                                 }
    2076             :                                 else
    2077             :                                 {
    2078          62 :                                     *pStr += sStrArray[i];
    2079          62 :                                     nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    2080          62 :                                     nAnzResStrings--;
    2081             :                                 }
    2082             :                             }
    2083       56798 :                             i++;
    2084             :                         }
    2085       14210 :                         if ( rStr.getLength() && i < nAnzStrings && sStrArray[i][0] == ']' )
    2086             :                         {
    2087       14210 :                             nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
    2088       14210 :                             nPos = nPos + sStrArray[i].getLength();
    2089       14210 :                             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       14210 :                     break;
    2103             :                 default:                    // andere Dels
    2104        2010 :                     if (eScannedType == NUMBERFORMAT_PERCENT && cHere == '%')
    2105             :                     {
    2106        2010 :                         nTypeArray[i] = NF_SYMBOLTYPE_PERCENT;
    2107             :                     }
    2108             :                     else
    2109             :                     {
    2110           0 :                         nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    2111             :                     }
    2112        2010 :                     nPos = nPos + sStrArray[i].getLength();
    2113        2010 :                     i++;
    2114        2010 :                     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       45378 :         if (eScannedType == NUMBERFORMAT_FRACTION)
    2125             :         {
    2126        3996 :             if (bFrac)
    2127             :             {
    2128        3996 :                 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       41382 :             if (bExp)
    2142             :             {
    2143        2074 :                 nCntExp = nCounter;
    2144             :             }
    2145       39308 :             else if (bDecSep)
    2146             :             {
    2147       22274 :                 nCntPost = nCounter;
    2148             :             }
    2149             :             else
    2150             :             {
    2151       17034 :                 nCntPre = nCounter;
    2152             :             }
    2153             :         }
    2154       45378 :         if (bThousand)                          // Expansion of grouping separators
    2155             :         {
    2156             :             sal_uInt16 nMaxPos;
    2157       33958 :             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       33958 :             else if (bDecSep)                   // decimal separator present
    2169             :             {
    2170       20104 :                 nMaxPos = nDecPos;
    2171             :             }
    2172       13854 :             else if (bExp)                      // 'E' exponent present
    2173             :             {
    2174           0 :                 nMaxPos = nExpPos;
    2175             :             }
    2176             :             else                                // up to end
    2177             :             {
    2178       13854 :                 nMaxPos = i;
    2179             :             }
    2180             :             // Insert separators at proper positions.
    2181       33958 :             sal_Int32 nCount = 0;
    2182       33958 :             utl::DigitGroupingIterator aGrouping( pLoc->getDigitGrouping());
    2183       33958 :             size_t nFirstDigitSymbol = nMaxPos;
    2184       33958 :             size_t nFirstGroupingSymbol = nMaxPos;
    2185       33958 :             i = nMaxPos;
    2186      349956 :             while (i-- > 0)
    2187             :             {
    2188      282040 :                 if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
    2189             :                 {
    2190      135832 :                     nFirstDigitSymbol = i;
    2191      135832 :                     nCount = nCount + sStrArray[i].getLength();   // MSC converts += to int and then warns, so ...
    2192             :                     // Insert separator only if not leftmost symbol.
    2193      135832 :                     if (i > 0 && nCount >= aGrouping.getPos())
    2194             :                     {
    2195             :                         DBG_ASSERT( sStrArray[i].getLength() == 1,
    2196             :                                     "ImpSvNumberformatScan::FinalScan: combined digits in group separator insertion");
    2197       33958 :                         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       33958 :                         nFirstDigitSymbol = i + 1;
    2204       33958 :                         nFirstGroupingSymbol = i;
    2205       33958 :                         aGrouping.advance();
    2206             :                     }
    2207             :                 }
    2208             :             }
    2209             :             // Generated something like "string",000; remove separator again.
    2210       33958 :             if (nFirstGroupingSymbol < nFirstDigitSymbol)
    2211             :             {
    2212           0 :                 nTypeArray[nFirstGroupingSymbol] = NF_SYMBOLTYPE_EMPTY;
    2213           0 :                 nAnzResStrings--;
    2214       33958 :             }
    2215             :         }
    2216             :         // Combine digits into groups to save memory (Info will be copied
    2217             :         // later, taking only non-empty symbols).
    2218      306680 :         for (i = 0; i < nAnzStrings; ++i)
    2219             :         {
    2220      261302 :             if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
    2221             :             {
    2222      110728 :                 OUString& rStr = sStrArray[i];
    2223      315958 :                 while (++i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
    2224             :                 {
    2225       94502 :                     rStr += sStrArray[i];
    2226       94502 :                     nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    2227       94502 :                     nAnzResStrings--;
    2228             :                 }
    2229             :             }
    2230             :         }
    2231       45378 :         break;                                      // of NUMBERFORMAT_NUMBER
    2232             :     case NUMBERFORMAT_DATE:
    2233      223060 :         while (i < nAnzStrings)
    2234             :         {
    2235             :             int nCalRet;
    2236      159100 :             switch (nTypeArray[i])
    2237             :             {
    2238             :             case NF_SYMBOLTYPE_BLANK:
    2239             :             case NF_SYMBOLTYPE_STAR:
    2240             :             case NF_SYMBOLTYPE_STRING:
    2241        2120 :                 nPos = nPos + sStrArray[i].getLength();
    2242        2120 :                 i++;
    2243        2120 :                 break;
    2244             :             case NF_SYMBOLTYPE_DEL:
    2245       71360 :                 if (sStrArray[i] == sOldDateSep)
    2246             :                 {
    2247        9570 :                     nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
    2248        9570 :                     nPos = nPos + sStrArray[i].getLength();
    2249        9570 :                     if (bConvertMode)
    2250             :                     {
    2251        1566 :                         sStrArray[i] = pFormatter->GetDateSep();
    2252             :                     }
    2253        9570 :                     i++;
    2254             :                 }
    2255       61790 :                 else if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
    2256             :                 {
    2257        7904 :                     if ( nCalRet < 0  )
    2258             :                     {
    2259           0 :                         return nPos;        // error
    2260             :                     }
    2261             :                 }
    2262             :                 else
    2263             :                 {
    2264       53886 :                     nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    2265       53886 :                     nPos = nPos + sStrArray[i].getLength();
    2266       53886 :                     i++;
    2267             :                 }
    2268       71360 :                 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       85620 :                 sStrArray[i] = OUString(sKeyword[nTypeArray[i]]); // tTtT -> TTTT
    2299       85620 :                 nPos = nPos + sStrArray[i].getLength();
    2300       85620 :                 i++;
    2301       85620 :                 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       31980 :         break;                                      // of NUMBERFORMAT_DATE
    2310             :     case NUMBERFORMAT_TIME:
    2311       60830 :         while (i < nAnzStrings)
    2312             :         {
    2313             :             sal_Unicode cChar;
    2314             : 
    2315       45134 :             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       22868 :                 switch( sStrArray[i][0] )
    2324             :                 {
    2325             :                 case '0':
    2326        2128 :                     if ( Is100SecZero( i, bDecSep ) )
    2327             :                     {
    2328        2128 :                         bDecSep = true;
    2329        2128 :                         nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
    2330        2128 :                         OUString& rStr = sStrArray[i];
    2331        2128 :                         i++;
    2332        2128 :                         nPos = nPos + sStrArray[i].getLength();
    2333        2128 :                         nCounter++;
    2334        8240 :                         while (i < nAnzStrings &&
    2335        1992 :                                sStrArray[i][0] == '0')
    2336             :                         {
    2337        1992 :                             rStr += sStrArray[i];
    2338        1992 :                             nPos = nPos + sStrArray[i].getLength();
    2339        1992 :                             nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    2340        1992 :                             nAnzResStrings--;
    2341        1992 :                             nCounter++;
    2342        1992 :                             i++;
    2343             :                         }
    2344             :                     }
    2345             :                     else
    2346             :                     {
    2347           0 :                         return nPos;
    2348             :                     }
    2349        2128 :                     break;
    2350             :                 case '#':
    2351             :                 case '?':
    2352           0 :                     return nPos;
    2353             :                 case '[':
    2354        2128 :                     if (bThousand)              // doppelt
    2355             :                     {
    2356           0 :                         return nPos;
    2357             :                     }
    2358        2128 :                     bThousand = true;           // bei Time frei
    2359        2128 :                     cChar = pChrCls->uppercase(rtl::OUString(NextChar(i)))[0];
    2360        2128 :                     if ( cChar == cOldKeyH )
    2361             :                     {
    2362        2128 :                         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        2128 :                     nPos = nPos + sStrArray[i].getLength();
    2377        2128 :                     i++;
    2378        2128 :                     break;
    2379             :                 case ']':
    2380        2128 :                     if (!bThousand)             // kein [ vorher
    2381             :                     {
    2382           0 :                         return nPos;
    2383             :                     }
    2384        2128 :                     nPos = nPos + sStrArray[i].getLength();
    2385        2128 :                     i++;
    2386        2128 :                     break;
    2387             :                 default:
    2388       16484 :                     nPos = nPos + sStrArray[i].getLength();
    2389       16484 :                     if ( sStrArray[i] == sOldTimeSep )
    2390             :                     {
    2391       12268 :                         nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
    2392       12268 :                         if ( bConvertMode )
    2393             :                         {
    2394        1274 :                             sStrArray[i] = pLoc->getTimeSep();
    2395             :                         }
    2396             :                     }
    2397        4216 :                     else if ( sStrArray[i] == sOldTime100SecSep )
    2398             :                     {
    2399        2124 :                         bDecSep = true;
    2400        2124 :                         nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
    2401        2124 :                         if ( bConvertMode )
    2402             :                         {
    2403         130 :                             sStrArray[i] = pLoc->getTime100SecSep();
    2404             :                         }
    2405             :                     }
    2406             :                     else
    2407             :                     {
    2408        2092 :                         nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    2409             :                     }
    2410       16484 :                     i++;
    2411       16484 :                     break;
    2412             :                 }
    2413       22868 :                 break;
    2414             :             case NF_SYMBOLTYPE_STRING:
    2415          34 :                 nPos = nPos + sStrArray[i].getLength();
    2416          34 :                 i++;
    2417          34 :                 break;
    2418             :             case NF_KEY_AMPM:                       // AM/PM
    2419             :             case NF_KEY_AP:                         // A/P
    2420        2100 :                 bExp = true;                    // missbraucht fuer A/P
    2421        2100 :                 sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
    2422        2100 :                 nPos = nPos + sStrArray[i].getLength();
    2423        2100 :                 i++;
    2424        2100 :                 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       20132 :                 sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
    2435       20132 :                 nPos = nPos + sStrArray[i].getLength();
    2436       20132 :                 i++;
    2437       20132 :                 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        7848 :         nCntPost = nCounter;                    // Zaehler der Nullen
    2446        7848 :         if (bExp)
    2447             :         {
    2448        2100 :             nCntExp = 1;                        // merkt AM/PM
    2449             :         }
    2450        7848 :         break;                                      // of NUMBERFORMAT_TIME
    2451             :     case NUMBERFORMAT_DATETIME:
    2452       26956 :         while (i < nAnzStrings)
    2453             :         {
    2454             :             int nCalRet;
    2455       22776 :             switch (nTypeArray[i])
    2456             :             {
    2457             :             case NF_SYMBOLTYPE_BLANK:
    2458             :             case NF_SYMBOLTYPE_STAR:
    2459             :             case NF_SYMBOLTYPE_STRING:
    2460          32 :                 nPos = nPos + sStrArray[i].getLength();
    2461          32 :                 i++;
    2462          32 :                 break;
    2463             :             case NF_SYMBOLTYPE_DEL:
    2464       10314 :                 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       10314 :                     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       10314 :                         nPos = nPos + sStrArray[i].getLength();
    2505       10314 :                         if (bTimePart)
    2506             :                         {
    2507        4066 :                             if ( sStrArray[i] == sOldTimeSep )
    2508             :                             {
    2509        3078 :                                 nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
    2510        3078 :                                 if ( bConvertMode )
    2511             :                                 {
    2512          90 :                                     sStrArray[i] = pLoc->getTimeSep();
    2513             :                                 }
    2514             :                             }
    2515         988 :                             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         988 :                                 nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    2527             :                             }
    2528             :                         }
    2529             :                         else
    2530             :                         {
    2531        6248 :                             if ( sStrArray[i] == sOldDateSep )
    2532             :                             {
    2533        4168 :                                 nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
    2534        4168 :                                 if (bConvertMode)
    2535         180 :                                     sStrArray[i] = pFormatter->GetDateSep();
    2536             :                             }
    2537             :                             else
    2538             :                             {
    2539        2080 :                                 nTypeArray[i] = NF_SYMBOLTYPE_STRING;
    2540             :                             }
    2541             :                         }
    2542       10314 :                         i++;
    2543       10314 :                         break;
    2544             :                     }
    2545             :                 }
    2546       10314 :                 break;
    2547             :             case NF_KEY_AMPM:                       // AM/PM
    2548             :             case NF_KEY_AP:                         // A/P
    2549         988 :                 bTimePart = true;
    2550         988 :                 bExp = true;                    // missbraucht fuer A/P
    2551         988 :                 sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
    2552         988 :                 nPos = nPos + sStrArray[i].getLength();
    2553         988 :                 i++;
    2554         988 :                 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        5176 :                 bTimePart = true;
    2562        5176 :                 sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
    2563        5176 :                 nPos = nPos + sStrArray[i].getLength();
    2564        5176 :                 i++;
    2565        5176 :                 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        6266 :                 bTimePart = false;
    2593        6266 :                 sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
    2594        6266 :                 nPos = nPos + sStrArray[i].getLength();
    2595        6266 :                 i++;
    2596        6266 :                 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        2090 :         nCntPost = nCounter;                    // decimals (100th seconds)
    2611        2090 :         if (bExp)
    2612             :         {
    2613         988 :             nCntExp = 1;                        // merkt AM/PM
    2614             :         }
    2615        2090 :         break;                                      // of NUMBERFORMAT_DATETIME
    2616             :     default:
    2617           0 :         break;
    2618             :     }
    2619       88738 :     if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
    2620             :         (nCntPre + nCntPost == 0 || nCntExp == 0))
    2621             :     {
    2622           0 :         return nPos;
    2623             :     }
    2624       88738 :     else if (eScannedType == NUMBERFORMAT_FRACTION && (nCntExp > 8 || nCntExp == 0))
    2625             :     {
    2626           0 :         return nPos;
    2627             :     }
    2628       88738 :     if (bThaiT && !GetNatNumModifier())
    2629             :     {
    2630           0 :         SetNatNumModifier(1);
    2631             :     }
    2632       88738 :     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       35694 :         for ( i=0; i < nAnzStrings; i++ )
    2637             :         {
    2638       33268 :             if ( nTypeArray[i] == NF_SYMBOLTYPE_STRING &&
    2639        3276 :                  sStrArray[i][0] != '\"' )
    2640             :             {
    2641        2462 :                 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        2462 :                 OUString& rStr = sStrArray[i];
    2675        2462 :                 sal_Int32 nLen = rStr.getLength();
    2676        5644 :                 for ( sal_Int32 j = 0; j < nLen; j++ )
    2677             :                 {
    2678        3182 :                     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       88738 :     rString = "";
    2689       88738 :     i = 0;
    2690      883722 :     while (i < nAnzStrings)
    2691             :     {
    2692             :         sal_Int32 nStringPos;
    2693      706246 :         sal_Int32 nArrPos = 0;
    2694      706246 :         sal_uInt16 iPos = i;
    2695      706246 :         switch ( nTypeArray[i] )
    2696             :         {
    2697             :         case NF_SYMBOLTYPE_STRING :
    2698       74016 :             nStringPos = rString.getLength();
    2699      178790 :             do
    2700             :             {
    2701       93088 :                 if (sStrArray[i].getLength() == 2 &&
    2702        1742 :                     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         720 :                     sal_Unicode c = sStrArray[i][1];
    2711             : 
    2712         720 :                     switch (c)
    2713             :                     {
    2714             :                     case '+':
    2715             :                     case '-':
    2716         178 :                         rString += OUString(c);
    2717         178 :                         break;
    2718             :                     case ' ':
    2719             :                     case '.':
    2720             :                     case '/':
    2721         524 :                         if (((eScannedType & NUMBERFORMAT_DATE) == 0) &&
    2722         122 :                             (StringEqualsChar( pFormatter->GetNumThousandSep(), c) ||
    2723         122 :                              StringEqualsChar( pFormatter->GetNumDecimalSep(), c) ||
    2724         122 :                              (c == ' ' && StringEqualsChar( pFormatter->GetNumThousandSep(), cNonBreakingSpace))))
    2725             :                         {
    2726           0 :                             rString += sStrArray[i];
    2727             :                         }
    2728         194 :                         else if ((eScannedType & NUMBERFORMAT_DATE) &&
    2729          36 :                                  StringEqualsChar( pFormatter->GetDateSep(), c))
    2730             :                         {
    2731           0 :                             rString += sStrArray[i];
    2732             :                         }
    2733         182 :                         else if ((eScannedType & NUMBERFORMAT_TIME) &&
    2734          12 :                                  (StringEqualsChar( pLoc->getTimeSep(), c) ||
    2735          12 :                                   StringEqualsChar( pLoc->getTime100SecSep(), c)))
    2736             :                         {
    2737           0 :                             rString += sStrArray[i];
    2738             :                         }
    2739         158 :                         else if (eScannedType & NUMBERFORMAT_FRACTION)
    2740             :                         {
    2741           6 :                             rString += sStrArray[i];
    2742             :                         }
    2743             :                         else
    2744             :                         {
    2745         152 :                             rString += OUString(c);
    2746             :                         }
    2747         158 :                         break;
    2748             :                     default:
    2749         384 :                         rString += sStrArray[i];
    2750             :                     }
    2751             :                 }
    2752             :                 else
    2753             :                 {
    2754       90626 :                     rString += sStrArray[i];
    2755             :                 }
    2756       91346 :                 if ( RemoveQuotes( sStrArray[i] ) > 0 )
    2757             :                 {
    2758             :                     // update currency up to quoted string
    2759        1798 :                     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          40 :                         OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
    2765          80 :                                                            sStrArray[iPos].getLength()-nArrPos ) );
    2766          40 :                         sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
    2767          40 :                         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          40 :                         nStringPos = rString.getLength();
    2779          40 :                         if ( iPos == i )
    2780             :                         {
    2781          40 :                             nArrPos = sStrArray[iPos].getLength();
    2782             :                         }
    2783             :                         else
    2784             :                         {
    2785           0 :                             nArrPos = sStrArray[iPos].getLength() + sStrArray[i].getLength();
    2786          40 :                         }
    2787             :                     }
    2788             :                 }
    2789       91346 :                 if ( iPos != i )
    2790             :                 {
    2791       17330 :                     sStrArray[iPos] += sStrArray[i];
    2792       17330 :                     nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
    2793       17330 :                     nAnzResStrings--;
    2794             :                 }
    2795       91346 :                 i++;
    2796             :             }
    2797       87444 :             while ( i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_STRING );
    2798             : 
    2799       74016 :             if ( i < nAnzStrings )
    2800             :             {
    2801       70114 :                 i--;    // enter switch on next symbol again
    2802             :             }
    2803       74016 :             if ( eScannedType == NUMBERFORMAT_CURRENCY && nStringPos < rString.getLength() )
    2804             :             {
    2805             :                 // same as above, since last RemoveQuotes
    2806       18726 :                 OUString aTmp( pChrCls->uppercase( sStrArray[iPos], nArrPos,
    2807       37452 :                                                    sStrArray[iPos].getLength()-nArrPos ) );
    2808       18726 :                 sal_Int32 nCPos = aTmp.indexOf( sOldCurString );
    2809       18726 :                 if ( nCPos >= 0 )
    2810             :                 {
    2811             :                     const OUString& rCur = bConvertMode && bConvertSystemToSystem ?
    2812       10336 :                         GetCurSymbol() : sOldCurSymbol;
    2813       20672 :                     sStrArray[iPos] = sStrArray[iPos].replaceAt( nArrPos + nCPos,
    2814             :                                                                  sOldCurString.getLength(),
    2815       31008 :                                                                  rCur );
    2816             :                     rString = rString.replaceAt( nStringPos + nCPos,
    2817       10336 :                                                  sOldCurString.getLength(), rCur );
    2818       18726 :                 }
    2819             :             }
    2820       74016 :             break;
    2821             :         case NF_SYMBOLTYPE_CURRENCY :
    2822       14210 :             rString += sStrArray[i];
    2823       14210 :             RemoveQuotes( sStrArray[i] );
    2824       14210 :             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      196810 :             break;
    2840             :         default:
    2841      421210 :             rString += sStrArray[i];
    2842             :         }
    2843      706246 :         i++;
    2844             :     }
    2845       88738 :     return 0;
    2846             : }
    2847             : 
    2848      105556 : sal_Int32 ImpSvNumberformatScan::RemoveQuotes( OUString& rStr )
    2849             : {
    2850      105556 :     if ( rStr.getLength() > 1 )
    2851             :     {
    2852        3852 :         sal_Unicode c = rStr[0];
    2853        3852 :         sal_Int32 n = rStr.getLength() - 1;
    2854        3852 :         if ( c == '"' && rStr[n] == '"' )
    2855             :         {
    2856        1078 :             rStr = rStr.copy(1,n);
    2857        1078 :             return 2;
    2858             :         }
    2859        2774 :         else if ( c == '\\' )
    2860             :         {
    2861         720 :             rStr = rStr.copy(1);
    2862         720 :             return 1;
    2863             :         }
    2864             :     }
    2865      103758 :     return 0;
    2866             : }
    2867             : 
    2868       88738 : sal_Int32 ImpSvNumberformatScan::ScanFormat( OUString& rString )
    2869             : {
    2870       88738 :     sal_Int32 res = Symbol_Division(rString);  //lexikalische Analyse
    2871       88738 :     if (!res)
    2872             :     {
    2873       88738 :         res = ScanType(); // Erkennung des Formattyps
    2874             :     }
    2875       88738 :     if (!res)
    2876             :     {
    2877       88738 :         res = FinalScan( rString );         // Typabhaengige Endanalyse
    2878             :     }
    2879       88738 :     return res;                             // res = Kontrollposition
    2880             :                                             // res = 0 => Format ok
    2881             : }
    2882             : 
    2883       88738 : void ImpSvNumberformatScan::CopyInfo(ImpSvNumberformatInfo* pInfo, sal_uInt16 nAnz)
    2884             : {
    2885             :     size_t i,j;
    2886       88738 :     j = 0;
    2887       88738 :     i = 0;
    2888      855428 :     while (i < nAnz && j < NF_MAX_FORMAT_SYMBOLS)
    2889             :     {
    2890      677952 :         if (nTypeArray[j] != NF_SYMBOLTYPE_EMPTY)
    2891             :         {
    2892      509436 :             pInfo->sStrArray[i]  = sStrArray[j];
    2893      509436 :             pInfo->nTypeArray[i] = nTypeArray[j];
    2894      509436 :             i++;
    2895             :         }
    2896      677952 :         j++;
    2897             :     }
    2898       88738 :     pInfo->eScannedType = eScannedType;
    2899       88738 :     pInfo->bThousand    = bThousand;
    2900       88738 :     pInfo->nThousand    = nThousand;
    2901       88738 :     pInfo->nCntPre      = nCntPre;
    2902       88738 :     pInfo->nCntPost     = nCntPost;
    2903       88738 :     pInfo->nCntExp      = nCntExp;
    2904       88738 : }
    2905             : 
    2906             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10