LCOV - code coverage report
Current view: top level - svl/source/numbers - zforfind.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 753 1485 50.7 %
Date: 2012-08-25 Functions: 45 47 95.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 812 2374 34.2 %

           Branch data     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 <ctype.h>
      22                 :            : #include <stdlib.h>
      23                 :            : #include <float.h>
      24                 :            : #include <errno.h>
      25                 :            : #include <comphelper/string.hxx>
      26                 :            : #include <tools/date.hxx>
      27                 :            : #include <tools/debug.hxx>
      28                 :            : #include <rtl/math.hxx>
      29                 :            : #include <unotools/charclass.hxx>
      30                 :            : #include <unotools/calendarwrapper.hxx>
      31                 :            : #include <unotools/localedatawrapper.hxx>
      32                 :            : #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
      33                 :            : #include <unotools/digitgroupingiterator.hxx>
      34                 :            : 
      35                 :            : #include <svl/zforlist.hxx>         // NUMBERFORMAT_XXX
      36                 :            : #include "zforscan.hxx"
      37                 :            : #include <svl/zformat.hxx>
      38                 :            : 
      39                 :            : #define _ZFORFIND_CXX
      40                 :            : #include "zforfind.hxx"
      41                 :            : #undef _ZFORFIND_CXX
      42                 :            : 
      43                 :            : 
      44                 :            : #ifndef DBG_UTIL
      45                 :            : #define NF_TEST_CALENDAR 0
      46                 :            : #else
      47                 :            : #define NF_TEST_CALENDAR 0
      48                 :            : #endif
      49                 :            : #if NF_TEST_CALENDAR
      50                 :            : #include <comphelper/processfactory.hxx>
      51                 :            : #include <com/sun/star/i18n/XCalendar3.hpp>
      52                 :            : #endif
      53                 :            : 
      54                 :            : 
      55                 :            : const sal_uInt8 ImpSvNumberInputScan::nMatchedEndString    = 0x01;
      56                 :            : const sal_uInt8 ImpSvNumberInputScan::nMatchedMidString    = 0x02;
      57                 :            : const sal_uInt8 ImpSvNumberInputScan::nMatchedStartString  = 0x04;
      58                 :            : const sal_uInt8 ImpSvNumberInputScan::nMatchedVirgin       = 0x08;
      59                 :            : const sal_uInt8 ImpSvNumberInputScan::nMatchedUsedAsReturn = 0x10;
      60                 :            : 
      61                 :            : /* It is not clear how we want timezones to be handled. Convert them to local
      62                 :            :  * time isn't wanted, as it isn't done in any other place and timezone
      63                 :            :  * information isn't stored anywhere. Ignoring them and pretending local time
      64                 :            :  * may be wrong too and might not be what the user expects. Keep the input as
      65                 :            :  * string so that no information is lost.
      66                 :            :  * Anyway, defining NF_RECOGNIZE_ISO8601_TIMEZONES to 1 would be the way how it
      67                 :            :  * would work, together with the nTimezonePos handling in GetTimeRef(). */
      68                 :            : #define NF_RECOGNIZE_ISO8601_TIMEZONES 0
      69                 :            : 
      70                 :            : //---------------------------------------------------------------------------
      71                 :            : //      Konstruktor
      72                 :            : 
      73                 :       2191 : ImpSvNumberInputScan::ImpSvNumberInputScan( SvNumberFormatter* pFormatterP )
      74                 :            :         :
      75                 :            :         pUpperMonthText( NULL ),
      76                 :            :         pUpperAbbrevMonthText( NULL ),
      77                 :            :         pUpperGenitiveMonthText( NULL ),
      78                 :            :         pUpperGenitiveAbbrevMonthText( NULL ),
      79                 :            :         pUpperPartitiveMonthText( NULL ),
      80                 :            :         pUpperPartitiveAbbrevMonthText( NULL ),
      81                 :            :         pUpperDayText( NULL ),
      82                 :            :         pUpperAbbrevDayText( NULL ),
      83                 :            :         bTextInitialized( false ),
      84                 :            :         bScanGenitiveMonths( false ),
      85                 :            :         bScanPartitiveMonths( false ),
      86                 :            :         eScannedType( NUMBERFORMAT_UNDEFINED ),
      87 [ +  - ][ +  + ]:      46011 :         eSetType( NUMBERFORMAT_UNDEFINED )
           [ +  -  #  #  
                   #  # ]
      88                 :            : {
      89                 :       2191 :     pFormatter = pFormatterP;
      90         [ +  - ]:       2191 :     pNullDate = new Date(30,12,1899);
      91         [ +  - ]:       2191 :     nYear2000 = SvNumberFormatter::GetYear2000Default();
      92                 :       2191 :     Reset();
      93         [ +  - ]:       2191 :     ChangeIntl();
      94   [ #  #  #  # ]:       2191 : }
      95                 :            : 
      96                 :            : 
      97                 :            : //---------------------------------------------------------------------------
      98                 :            : //      Destruktor
      99                 :            : 
     100 [ +  - ][ +  - ]:      43780 : ImpSvNumberInputScan::~ImpSvNumberInputScan()
     101                 :            : {
     102                 :       1990 :     Reset();
     103                 :       1990 :     delete pNullDate;
     104 [ +  + ][ +  - ]:       2878 :     delete [] pUpperMonthText;
                 [ +  + ]
     105 [ +  + ][ +  + ]:       2878 :     delete [] pUpperAbbrevMonthText;
                 [ +  - ]
     106 [ +  + ][ +  + ]:       2878 :     delete [] pUpperGenitiveMonthText;
                 [ +  - ]
     107 [ +  + ][ +  + ]:       2878 :     delete [] pUpperGenitiveAbbrevMonthText;
                 [ +  - ]
     108 [ +  + ][ +  + ]:       2878 :     delete [] pUpperPartitiveMonthText;
                 [ +  - ]
     109 [ +  + ][ +  + ]:       2878 :     delete [] pUpperPartitiveAbbrevMonthText;
                 [ +  - ]
     110 [ +  + ][ +  + ]:       2508 :     delete [] pUpperDayText;
                 [ +  - ]
     111 [ +  + ][ +  + ]:       2508 :     delete [] pUpperAbbrevDayText;
                 [ +  - ]
     112 [ +  - ][ +  + ]:      43780 : }
           [ #  #  #  # ]
     113                 :            : 
     114                 :            : 
     115                 :            : //---------------------------------------------------------------------------
     116                 :            : //      Reset
     117                 :            : 
     118                 :      10938 : void ImpSvNumberInputScan::Reset()
     119                 :            : {
     120                 :      10938 :     nMonth       = 0;
     121                 :      10938 :     nMonthPos    = 0;
     122                 :      10938 :     nTimePos     = 0;
     123                 :      10938 :     nSign        = 0;
     124                 :      10938 :     nESign       = 0;
     125                 :      10938 :     nDecPos      = 0;
     126                 :      10938 :     nNegCheck    = 0;
     127                 :      10938 :     nAnzStrings  = 0;
     128                 :      10938 :     nAnzNums     = 0;
     129                 :      10938 :     nThousand    = 0;
     130                 :      10938 :     eScannedType = NUMBERFORMAT_UNDEFINED;
     131                 :      10938 :     nAmPm        = 0;
     132                 :      10938 :     nPosThousandString = 0;
     133                 :      10938 :     nLogical     = 0;
     134                 :      10938 :     nStringScanNumFor = 0;
     135                 :      10938 :     nStringScanSign = 0;
     136                 :      10938 :     nMatchedAllStrings = nMatchedVirgin;
     137                 :      10938 :     nMayBeIso8601 = 0;
     138                 :      10938 :     nTimezonePos = 0;
     139                 :      10938 :     nMayBeMonthDate = 0;
     140                 :      10938 :     nAcceptedDatePattern = -2;
     141                 :      10938 :     nDatePatternStart = 0;
     142                 :      10938 :     nCanForceToIso8601 = 0;
     143                 :      10938 : }
     144                 :            : 
     145                 :            : 
     146                 :            : //---------------------------------------------------------------------------
     147                 :            : //
     148                 :            : // static
     149                 :      33959 : inline bool ImpSvNumberInputScan::MyIsdigit( sal_Unicode c )
     150                 :            : {
     151 [ +  - ][ +  + ]:      33959 :     return c < 128 && isdigit( (unsigned char) c );
     152                 :            : }
     153                 :            : 
     154                 :            : 
     155                 :            : //---------------------------------------------------------------------------
     156                 :            : //
     157                 :       6757 : void ImpSvNumberInputScan::TransformInput( String& rStr )
     158                 :            : {
     159                 :            :     xub_StrLen nPos, nLen;
     160         [ +  + ]:      37750 :     for ( nPos = 0, nLen = rStr.Len(); nPos < nLen; ++nPos )
     161                 :            :     {
     162   [ -  +  #  # ]:      30993 :         if ( 256 <= rStr.GetChar( nPos ) &&
                 [ -  + ]
     163                 :          0 :                 pFormatter->GetCharClass()->isDigit( rStr, nPos ) )
     164                 :          0 :             break;
     165                 :            :     }
     166         [ -  + ]:       6757 :     if ( nPos < nLen )
     167                 :            :         rStr = pFormatter->GetNatNum()->getNativeNumberString( rStr,
     168 [ #  # ][ #  # ]:          0 :                 pFormatter->GetLocale(), 0 );
                 [ #  # ]
     169                 :       6757 : }
     170                 :            : 
     171                 :            : 
     172                 :            : //---------------------------------------------------------------------------
     173                 :            : //      StringToDouble
     174                 :            : //
     175                 :            : // Only simple unsigned floating point values without any error detection,
     176                 :            : // decimal separator has to be '.'
     177                 :            : 
     178                 :       2885 : double ImpSvNumberInputScan::StringToDouble( const String& rStr, bool bForceFraction )
     179                 :            : {
     180                 :       2885 :     double fNum = 0.0;
     181                 :       2885 :     double fFrac = 0.0;
     182                 :       2885 :     int nExp = 0;
     183                 :       2885 :     xub_StrLen nPos = 0;
     184                 :       2885 :     xub_StrLen nLen = rStr.Len();
     185                 :       2885 :     bool bPreSep = !bForceFraction;
     186                 :            : 
     187         [ +  + ]:       7757 :     while (nPos < nLen)
     188                 :            :     {
     189         [ +  + ]:       4872 :         if (rStr.GetChar(nPos) == '.')
     190                 :        252 :             bPreSep = false;
     191         [ +  + ]:       4620 :         else if (bPreSep)
     192                 :       4240 :             fNum = fNum * 10.0 + (double) (rStr.GetChar(nPos) - '0');
     193                 :            :         else
     194                 :            :         {
     195                 :        380 :             fFrac = fFrac * 10.0 + (double) (rStr.GetChar(nPos) - '0');
     196                 :        380 :             --nExp;
     197                 :            :         }
     198                 :       4872 :         nPos++;
     199                 :            :     }
     200         [ +  + ]:       2885 :     if ( fFrac )
     201                 :        190 :         return fNum + ::rtl::math::pow10Exp( fFrac, nExp );
     202                 :       2885 :     return fNum;
     203                 :            : }
     204                 :            : 
     205                 :            : 
     206                 :            : //---------------------------------------------------------------------------
     207                 :            : //       NextNumberStringSymbol
     208                 :            : //
     209                 :            : // Zerlegt die Eingabe in Zahlen und Strings fuer die weitere
     210                 :            : // Verarbeitung (Turing-Maschine).
     211                 :            : //---------------------------------------------------------------------------
     212                 :            : // Ausgangs Zustand = GetChar
     213                 :            : //---------------+-------------------+-----------------------+---------------
     214                 :            : // Alter Zustand | gelesenes Zeichen | Aktion                | Neuer Zustand
     215                 :            : //---------------+-------------------+-----------------------+---------------
     216                 :            : // GetChar       | Ziffer            | Symbol=Zeichen        | GetValue
     217                 :            : //               | Sonst             | Symbol=Zeichen        | GetString
     218                 :            : //---------------|-------------------+-----------------------+---------------
     219                 :            : // GetValue      | Ziffer            | Symbol=Symbol+Zeichen | GetValue
     220                 :            : //               | Sonst             | Dec(CharPos)          | Stop
     221                 :            : //---------------+-------------------+-----------------------+---------------
     222                 :            : // GetString     | Ziffer            | Dec(CharPos)          | Stop
     223                 :            : //               | Sonst             | Symbol=Symbol+Zeichen | GetString
     224                 :            : //---------------+-------------------+-----------------------+---------------
     225                 :            : 
     226                 :            : enum ScanState              // States der Turing-Maschine
     227                 :            : {
     228                 :            :     SsStop      = 0,
     229                 :            :     SsStart     = 1,
     230                 :            :     SsGetValue  = 2,
     231                 :            :     SsGetString = 3
     232                 :            : };
     233                 :            : 
     234                 :       9723 : bool ImpSvNumberInputScan::NextNumberStringSymbol(
     235                 :            :         const sal_Unicode*& pStr,
     236                 :            :         String& rSymbol )
     237                 :            : {
     238                 :       9723 :     bool isNumber = false;
     239                 :            :     sal_Unicode cToken;
     240                 :       9723 :     ScanState eState = SsStart;
     241                 :       9723 :     register const sal_Unicode* pHere = pStr;
     242                 :       9723 :     register xub_StrLen nChars = 0;
     243                 :            : 
     244 [ +  + ][ +  + ]:      43682 :     while ( ((cToken = *pHere) != 0) && eState != SsStop)
                 [ +  + ]
     245                 :            :     {
     246                 :      33959 :         pHere++;
     247   [ +  +  +  - ]:      33959 :         switch (eState)
     248                 :            :         {
     249                 :            :             case SsStart:
     250         [ +  + ]:       9723 :                 if ( MyIsdigit( cToken ) )
     251                 :            :                 {
     252                 :       5040 :                     eState = SsGetValue;
     253                 :       5040 :                     isNumber = true;
     254                 :            :                 }
     255                 :            :                 else
     256                 :       4683 :                     eState = SsGetString;
     257                 :       9723 :                 nChars++;
     258                 :       9723 :                 break;
     259                 :            :             case SsGetValue:
     260         [ +  + ]:       4011 :                 if ( MyIsdigit( cToken ) )
     261                 :       2986 :                     nChars++;
     262                 :            :                 else
     263                 :            :                 {
     264                 :       1025 :                     eState = SsStop;
     265                 :       1025 :                     pHere--;
     266                 :            :                 }
     267                 :       4011 :                 break;
     268                 :            :             case SsGetString:
     269         [ +  + ]:      20225 :                 if ( !MyIsdigit( cToken ) )
     270                 :      18284 :                     nChars++;
     271                 :            :                 else
     272                 :            :                 {
     273                 :       1941 :                     eState = SsStop;
     274                 :       1941 :                     pHere--;
     275                 :            :                 }
     276                 :      20225 :                 break;
     277                 :            :             default:
     278                 :          0 :                 break;
     279                 :            :         }   // switch
     280                 :            :     }   // while
     281                 :            : 
     282         [ +  - ]:       9723 :     if ( nChars )
     283                 :       9723 :         rSymbol.Assign( pStr, nChars );
     284                 :            :     else
     285                 :          0 :         rSymbol.Erase();
     286                 :            : 
     287                 :       9723 :     pStr = pHere;
     288                 :            : 
     289                 :       9723 :     return isNumber;
     290                 :            : }
     291                 :            : 
     292                 :            : 
     293                 :            : //---------------------------------------------------------------------------
     294                 :            : //      SkipThousands
     295                 :            : 
     296                 :            : // FIXME: should be grouping; it is only used though in case nAnzStrings is
     297                 :            : // near SV_MAX_ANZ_INPUT_STRINGS, in NumberStringDivision().
     298                 :            : 
     299                 :          0 : bool ImpSvNumberInputScan::SkipThousands(
     300                 :            :         const sal_Unicode*& pStr,
     301                 :            :         String& rSymbol )
     302                 :            : {
     303                 :          0 :     bool res = false;
     304                 :            :     sal_Unicode cToken;
     305                 :          0 :     const String& rThSep = pFormatter->GetNumThousandSep();
     306                 :          0 :     register const sal_Unicode* pHere = pStr;
     307                 :          0 :     ScanState eState = SsStart;
     308                 :          0 :     xub_StrLen nCounter = 0;                                // counts 3 digits
     309                 :            : 
     310 [ #  # ][ #  # ]:          0 :     while ( ((cToken = *pHere) != 0) && eState != SsStop)
                 [ #  # ]
     311                 :            :     {
     312                 :          0 :         pHere++;
     313      [ #  #  # ]:          0 :         switch (eState)
     314                 :            :         {
     315                 :            :             case SsStart:
     316         [ #  # ]:          0 :                 if ( StringPtrContains( rThSep, pHere-1, 0 ) )
     317                 :            :                 {
     318                 :          0 :                     nCounter = 0;
     319                 :          0 :                     eState = SsGetValue;
     320                 :          0 :                     pHere += rThSep.Len()-1;
     321                 :            :                 }
     322                 :            :                 else
     323                 :            :                 {
     324                 :          0 :                     eState = SsStop;
     325                 :          0 :                     pHere--;
     326                 :            :                 }
     327                 :          0 :                 break;
     328                 :            :             case SsGetValue:
     329         [ #  # ]:          0 :                 if ( MyIsdigit( cToken ) )
     330                 :            :                 {
     331                 :          0 :                     rSymbol += cToken;
     332                 :          0 :                     nCounter++;
     333         [ #  # ]:          0 :                     if (nCounter == 3)
     334                 :            :                     {
     335                 :          0 :                         eState = SsStart;
     336                 :          0 :                         res = true;                 // .000 combination found
     337                 :            :                     }
     338                 :            :                 }
     339                 :            :                 else
     340                 :            :                 {
     341                 :          0 :                     eState = SsStop;
     342                 :          0 :                     pHere--;
     343                 :            :                 }
     344                 :          0 :                 break;
     345                 :            :             default:
     346                 :          0 :                 break;
     347                 :            :         }   // switch
     348                 :            :     }   // while
     349                 :            : 
     350         [ #  # ]:          0 :     if (eState == SsGetValue)               // break witth less than 3 digits
     351                 :            :     {
     352         [ #  # ]:          0 :         if ( nCounter )
     353                 :          0 :             rSymbol.Erase( rSymbol.Len() - nCounter, nCounter );
     354                 :          0 :         pHere -= nCounter + rThSep.Len();       // put back ThSep also
     355                 :            :     }
     356                 :          0 :     pStr = pHere;
     357                 :            : 
     358                 :          0 :     return res;
     359                 :            : }
     360                 :            : 
     361                 :            : 
     362                 :            : //---------------------------------------------------------------------------
     363                 :            : //      NumberStringDivision
     364                 :            : 
     365                 :       6757 : void ImpSvNumberInputScan::NumberStringDivision( const String& rString )
     366                 :            : {
     367                 :       6757 :     const sal_Unicode* pStr = rString.GetBuffer();
     368                 :       6757 :     const sal_Unicode* const pEnd = pStr + rString.Len();
     369 [ +  + ][ +  - ]:      16480 :     while ( pStr < pEnd && nAnzStrings < SV_MAX_ANZ_INPUT_STRINGS )
                 [ +  + ]
     370                 :            :     {
     371 [ +  - ][ +  + ]:       9723 :         if ( NextNumberStringSymbol( pStr, sStrArray[nAnzStrings] ) )
     372                 :            :         {                                               // Zahl
     373                 :       5040 :             IsNum[nAnzStrings] = true;
     374                 :       5040 :             nNums[nAnzNums] = nAnzStrings;
     375                 :       5040 :             nAnzNums++;
     376 [ -  + ][ #  # ]:       5040 :             if (nAnzStrings >= SV_MAX_ANZ_INPUT_STRINGS - 7 &&
     377                 :            :                 nPosThousandString == 0)                // nur einmal
     378 [ #  # ][ #  # ]:          0 :                 if ( SkipThousands( pStr, sStrArray[nAnzStrings] ) )
     379                 :          0 :                     nPosThousandString = nAnzStrings;
     380                 :            :         }
     381                 :            :         else
     382                 :            :         {
     383                 :       4683 :             IsNum[nAnzStrings] = false;
     384                 :            :         }
     385                 :       9723 :         nAnzStrings++;
     386                 :            :     }
     387                 :       6757 : }
     388                 :            : 
     389                 :            : 
     390                 :            : //---------------------------------------------------------------------------
     391                 :            : // Whether rString contains rWhat at nPos
     392                 :            : 
     393                 :        977 : bool ImpSvNumberInputScan::StringContainsImpl( const String& rWhat,
     394                 :            :             const String& rString, xub_StrLen nPos )
     395                 :            : {
     396         [ +  + ]:        977 :     if ( nPos + rWhat.Len() <= rString.Len() )
     397                 :        736 :         return StringPtrContainsImpl( rWhat, rString.GetBuffer(), nPos );
     398                 :        977 :     return false;
     399                 :            : }
     400                 :            : 
     401                 :            : 
     402                 :            : //---------------------------------------------------------------------------
     403                 :            : // Whether pString contains rWhat at nPos
     404                 :            : 
     405                 :        736 : bool ImpSvNumberInputScan::StringPtrContainsImpl( const String& rWhat,
     406                 :            :             const sal_Unicode* pString, xub_StrLen nPos )
     407                 :            : {
     408         [ -  + ]:        736 :     if ( rWhat.Len() == 0 )
     409                 :          0 :         return false;
     410                 :        736 :     register const sal_Unicode* pWhat = rWhat.GetBuffer();
     411                 :        736 :     register const sal_Unicode* const pEnd = pWhat + rWhat.Len();
     412                 :        736 :     register const sal_Unicode* pStr = pString + nPos;
     413         [ +  + ]:       1632 :     while ( pWhat < pEnd )
     414                 :            :     {
     415         [ +  + ]:       1564 :         if ( *pWhat != *pStr )
     416                 :        668 :             return false;
     417                 :        896 :         pWhat++;
     418                 :        896 :         pStr++;
     419                 :            :     }
     420                 :        736 :     return true;
     421                 :            : }
     422                 :            : 
     423                 :            : 
     424                 :            : //---------------------------------------------------------------------------
     425                 :            : //      SkipChar
     426                 :            : //
     427                 :            : // ueberspringt genau das angegebene Zeichen
     428                 :            : 
     429                 :       4534 : inline bool ImpSvNumberInputScan::SkipChar( sal_Unicode c, const String& rString,
     430                 :            :         xub_StrLen& nPos )
     431                 :            : {
     432 [ +  + ][ +  + ]:       4534 :     if ((nPos < rString.Len()) && (rString.GetChar(nPos) == c))
                 [ +  + ]
     433                 :            :     {
     434                 :        330 :         nPos++;
     435                 :        330 :         return true;
     436                 :            :     }
     437                 :       4534 :     return false;
     438                 :            : }
     439                 :            : 
     440                 :            : 
     441                 :            : //---------------------------------------------------------------------------
     442                 :            : //      SkipBlanks
     443                 :            : //
     444                 :            : // Ueberspringt Leerzeichen
     445                 :            : 
     446                 :       3156 : inline void ImpSvNumberInputScan::SkipBlanks( const String& rString,
     447                 :            :         xub_StrLen& nPos )
     448                 :            : {
     449         [ +  + ]:       3156 :     if ( nPos < rString.Len() )
     450                 :            :     {
     451                 :       2202 :         register const sal_Unicode* p = rString.GetBuffer() + nPos;
     452         [ +  + ]:       2260 :         while ( *p == ' ' )
     453                 :            :         {
     454                 :         58 :             nPos++;
     455                 :         58 :             p++;
     456                 :            :         }
     457                 :            :     }
     458                 :       3156 : }
     459                 :            : 
     460                 :            : 
     461                 :            : //---------------------------------------------------------------------------
     462                 :            : //      SkipString
     463                 :            : //
     464                 :            : // jump over rWhat in rString at nPos
     465                 :            : 
     466                 :       1480 : inline bool ImpSvNumberInputScan::SkipString( const String& rWhat,
     467                 :            :         const String& rString, xub_StrLen& nPos )
     468                 :            : {
     469         [ +  + ]:       1480 :     if ( StringContains( rWhat, rString, nPos ) )
     470                 :            :     {
     471                 :         48 :         nPos = nPos + rWhat.Len();
     472                 :         48 :         return true;
     473                 :            :     }
     474                 :       1480 :     return false;
     475                 :            : }
     476                 :            : 
     477                 :            : 
     478                 :            : //---------------------------------------------------------------------------
     479                 :            : //      GetThousandSep
     480                 :            : //
     481                 :            : // recognizes exactly ,111 in {3} and {3,2} or ,11 in {3,2} grouping
     482                 :            : 
     483                 :        731 : inline bool ImpSvNumberInputScan::GetThousandSep(
     484                 :            :         const String& rString,
     485                 :            :         xub_StrLen& nPos,
     486                 :            :         sal_uInt16 nStringPos )
     487                 :            : {
     488                 :        731 :     const String& rSep = pFormatter->GetNumThousandSep();
     489                 :            :     // Is it an ordinary space instead of a non-breaking space?
     490                 :        731 :     bool bSpaceBreak = rSep.GetChar(0) == 0xa0 && rString.GetChar(0) == 0x20 &&
     491 [ #  # ][ #  # ]:        731 :         rSep.Len() == 1 && rString.Len() == 1;
           [ -  +  #  # ]
     492 [ +  - ][ +  + ]:       1462 :     if (!( (rString == rSep || bSpaceBreak)             // nothing else
     493                 :            :                 && nStringPos < nAnzStrings - 1         // safety first!
     494 [ +  + ][ -  + ]:        731 :                 && IsNum[nStringPos+1] ))               // number follows
         [ +  - ][ -  + ]
     495                 :        725 :         return false;                                   // no? => out
     496                 :            : 
     497                 :            :     utl::DigitGroupingIterator aGrouping(
     498 [ +  - ][ +  - ]:          6 :             pFormatter->GetLocaleData()->getDigitGrouping());
                 [ +  - ]
     499                 :            :     // Match ,### in {3} or ,## in {3,2}
     500                 :            :     /* FIXME: this could be refined to match ,## in {3,2} only if ,##,## or
     501                 :            :      * ,##,### and to match ,### in {3,2} only if it's the last. However,
     502                 :            :      * currently there is no track kept where group separators occur. In {3,2}
     503                 :            :      * #,###,### and #,##,## would be valid input, which maybe isn't even bad
     504                 :            :      * for #,###,###. Other combinations such as #,###,## maybe not. */
     505                 :          6 :     xub_StrLen nLen = sStrArray[nStringPos+1].Len();
     506 [ #  # ][ +  - ]:          6 :     if (nLen == aGrouping.get()                         // with 3 (or so) digits
           [ -  +  #  # ]
     507         [ #  # ]:          0 :             || nLen == aGrouping.advance().get()        // or with 2 (or 3 or so) digits
     508                 :            :             || nPosThousandString == nStringPos+1       // or concatenated
     509                 :            :        )
     510                 :            :     {
     511                 :          6 :         nPos = nPos + rSep.Len();
     512                 :          6 :         return true;
     513                 :            :     }
     514         [ +  - ]:        731 :     return false;
     515                 :            : }
     516                 :            : 
     517                 :            : 
     518                 :            : //---------------------------------------------------------------------------
     519                 :            : //      GetLogical
     520                 :            : //
     521                 :            : // Conversion of text to logial value
     522                 :            : // "true" =>  1:
     523                 :            : // "false"=> -1:
     524                 :            : // else   =>  0:
     525                 :            : 
     526                 :       2668 : short ImpSvNumberInputScan::GetLogical( const String& rString )
     527                 :            : {
     528                 :            :     short res;
     529                 :            : 
     530                 :       2668 :     const ImpSvNumberformatScan* pFS = pFormatter->GetFormatScanner();
     531         [ -  + ]:       2668 :     if ( rString == pFS->GetTrueString() )
     532                 :          0 :         res = 1;
     533         [ -  + ]:       2668 :     else if ( rString == pFS->GetFalseString() )
     534                 :          0 :         res = -1;
     535                 :            :     else
     536                 :       2668 :         res = 0;
     537                 :            : 
     538                 :       2668 :     return res;
     539                 :            : }
     540                 :            : 
     541                 :            : 
     542                 :            : //---------------------------------------------------------------------------
     543                 :            : //      GetMonth
     544                 :            : //
     545                 :            : // Converts a string containing a month name (JAN, January) at nPos into the
     546                 :            : // month number (negative if abbreviated), returns 0 if nothing found
     547                 :            : 
     548                 :       2022 : short ImpSvNumberInputScan::GetMonth( const String& rString, xub_StrLen& nPos )
     549                 :            : {
     550                 :            :     // #102136# The correct English form of month September abbreviated is
     551                 :            :     // SEPT, but almost every data contains SEP instead.
     552 [ +  + ][ +  - ]:       2022 :     static const String aSeptCorrect(RTL_CONSTASCII_USTRINGPARAM("SEPT") );
         [ +  - ][ #  # ]
     553 [ +  + ][ +  - ]:       2022 :     static const String aSepShortened(RTL_CONSTASCII_USTRINGPARAM("SEP") );
         [ +  - ][ #  # ]
     554                 :            : 
     555                 :       2022 :     short res = 0;      // no month found
     556                 :            : 
     557         [ +  + ]:       2022 :     if (rString.Len() > nPos)                           // only if needed
     558                 :            :     {
     559         [ +  + ]:       1075 :         if ( !bTextInitialized )
     560                 :        124 :             InitText();
     561                 :       1075 :         sal_Int16 nMonths = pFormatter->GetCalendar()->getNumberOfMonthsInYear();
     562         [ +  + ]:      13975 :         for ( sal_Int16 i = 0; i < nMonths; i++ )
     563                 :            :         {
     564 [ -  + ][ #  # ]:      12900 :             if ( bScanGenitiveMonths && StringContains( pUpperGenitiveMonthText[i], rString, nPos ) )
                 [ -  + ]
     565                 :            :             {                                           // genitive full names first
     566                 :          0 :                 nPos = nPos + pUpperGenitiveMonthText[i].Len();
     567                 :          0 :                 res = i+1;
     568                 :          0 :                 break;  // for
     569                 :            :             }
     570 [ -  + ][ #  # ]:      12900 :             else if ( bScanGenitiveMonths && StringContains( pUpperGenitiveAbbrevMonthText[i], rString, nPos ) )
                 [ -  + ]
     571                 :            :             {                                           // genitive abbreviated
     572                 :          0 :                 nPos = nPos + pUpperGenitiveAbbrevMonthText[i].Len();
     573                 :          0 :                 res = sal::static_int_cast< short >(-(i+1)); // negative
     574                 :          0 :                 break;  // for
     575                 :            :             }
     576 [ -  + ][ #  # ]:      12900 :             else if ( bScanPartitiveMonths && StringContains( pUpperPartitiveMonthText[i], rString, nPos ) )
                 [ -  + ]
     577                 :            :             {                                           // partitive full names
     578                 :          0 :                 nPos = nPos + pUpperPartitiveMonthText[i].Len();
     579                 :          0 :                 res = i+1;
     580                 :          0 :                 break;  // for
     581                 :            :             }
     582 [ -  + ][ #  # ]:      12900 :             else if ( bScanPartitiveMonths && StringContains( pUpperPartitiveAbbrevMonthText[i], rString, nPos ) )
                 [ -  + ]
     583                 :            :             {                                           // partitive abbreviated
     584                 :          0 :                 nPos = nPos + pUpperPartitiveAbbrevMonthText[i].Len();
     585                 :          0 :                 res = sal::static_int_cast< short >(-(i+1)); // negative
     586                 :          0 :                 break;  // for
     587                 :            :             }
     588         [ -  + ]:      12900 :             else if ( StringContains( pUpperMonthText[i], rString, nPos ) )
     589                 :            :             {                                           // noun full names
     590                 :          0 :                 nPos = nPos + pUpperMonthText[i].Len();
     591                 :          0 :                 res = i+1;
     592                 :          0 :                 break;  // for
     593                 :            :             }
     594         [ -  + ]:      12900 :             else if ( StringContains( pUpperAbbrevMonthText[i], rString, nPos ) )
     595                 :            :             {                                           // noun abbreviated
     596                 :          0 :                 nPos = nPos + pUpperAbbrevMonthText[i].Len();
     597                 :          0 :                 res = sal::static_int_cast< short >(-(i+1)); // negative
     598                 :          0 :                 break;  // for
     599                 :            :             }
     600         [ +  + ]:      12900 :             else if ( i == 8 && pUpperAbbrevMonthText[i] == aSeptCorrect &&
           [ -  +  #  # ]
                 [ -  + ]
     601                 :          0 :                     StringContains( aSepShortened, rString, nPos ) )
     602                 :            :             {                                           // #102136# SEPT/SEP
     603                 :          0 :                 nPos = nPos + aSepShortened.Len();
     604                 :          0 :                 res = sal::static_int_cast< short >(-(i+1)); // negative
     605                 :          0 :                 break;  // for
     606                 :            :             }
     607                 :            :         }
     608                 :            :     }
     609                 :            : 
     610                 :       2022 :     return res;
     611                 :            : }
     612                 :            : 
     613                 :            : 
     614                 :            : //---------------------------------------------------------------------------
     615                 :            : //      GetDayOfWeek
     616                 :            : //
     617                 :            : // Converts a string containing a DayOfWeek name (Mon, Monday) at nPos into the
     618                 :            : // DayOfWeek number + 1 (negative if abbreviated), returns 0 if nothing found
     619                 :            : 
     620                 :        970 : int ImpSvNumberInputScan::GetDayOfWeek( const String& rString, xub_StrLen& nPos )
     621                 :            : {
     622                 :        970 :     int res = 0;      // no day found
     623                 :            : 
     624         [ +  + ]:        970 :     if (rString.Len() > nPos)                           // only if needed
     625                 :            :     {
     626         [ -  + ]:        956 :         if ( !bTextInitialized )
     627                 :          0 :             InitText();
     628                 :        956 :         sal_Int16 nDays = pFormatter->GetCalendar()->getNumberOfDaysInWeek();
     629         [ +  + ]:       7648 :         for ( sal_Int16 i = 0; i < nDays; i++ )
     630                 :            :         {
     631         [ -  + ]:       6692 :             if ( StringContains( pUpperDayText[i], rString, nPos ) )
     632                 :            :             {                                           // full names first
     633                 :          0 :                 nPos = nPos + pUpperDayText[i].Len();
     634                 :          0 :                 res = i + 1;
     635                 :          0 :                 break;  // for
     636                 :            :             }
     637         [ -  + ]:       6692 :             if ( StringContains( pUpperAbbrevDayText[i], rString, nPos ) )
     638                 :            :             {                                           // abbreviated
     639                 :          0 :                 nPos = nPos + pUpperAbbrevDayText[i].Len();
     640                 :          0 :                 res = -(i + 1);                         // negative
     641                 :          0 :                 break;  // for
     642                 :            :             }
     643                 :            :         }
     644                 :            :     }
     645                 :            : 
     646                 :        970 :     return res;
     647                 :            : }
     648                 :            : 
     649                 :            : 
     650                 :            : //---------------------------------------------------------------------------
     651                 :            : //      GetCurrency
     652                 :            : //
     653                 :            : // Lesen eines Waehrungssysmbols
     654                 :            : // '$'   => true
     655                 :            : // sonst => false
     656                 :            : 
     657                 :        999 : bool ImpSvNumberInputScan::GetCurrency( const String& rString, xub_StrLen& nPos,
     658                 :            :             const SvNumberformat* pFormat )
     659                 :            : {
     660         [ +  + ]:        999 :     if ( rString.Len() > nPos )
     661                 :            :     {
     662         [ +  + ]:        979 :         if ( !aUpperCurrSymbol.Len() )
     663                 :            :         {   // if no format specified the currency of the initialized formatter
     664                 :            :             LanguageType eLang = (pFormat ? pFormat->GetLanguage() :
     665         [ +  - ]:        124 :                 pFormatter->GetLanguage());
     666                 :            :             aUpperCurrSymbol = pFormatter->GetCharClass()->uppercase(
     667 [ +  - ][ +  - ]:        124 :                 SvNumberFormatter::GetCurrencyEntry( eLang ).GetSymbol() );
     668                 :            :         }
     669         [ +  + ]:        979 :         if ( StringContains( aUpperCurrSymbol, rString, nPos ) )
     670                 :            :         {
     671                 :         20 :             nPos = nPos + aUpperCurrSymbol.Len();
     672                 :         20 :             return true;
     673                 :            :         }
     674         [ +  - ]:        959 :         if ( pFormat )
     675                 :            :         {
     676 [ +  - ][ +  - ]:        959 :             String aSymbol, aExtension;
     677 [ +  - ][ -  + ]:        959 :             if ( pFormat->GetNewCurrencySymbol( aSymbol, aExtension ) )
     678                 :            :             {
     679         [ #  # ]:          0 :                 if ( aSymbol.Len() <= rString.Len() - nPos )
     680                 :            :                 {
     681 [ #  # ][ #  # ]:          0 :                     aSymbol = pFormatter->GetCharClass()->uppercase(aSymbol);
                 [ #  # ]
     682 [ #  # ][ #  # ]:          0 :                     if ( StringContains( aSymbol, rString, nPos ) )
     683                 :            :                     {
     684                 :          0 :                         nPos = nPos + aSymbol.Len();
     685                 :        959 :                         return true;
     686                 :            :                     }
     687                 :            :                 }
     688 [ +  - ][ -  + ]:        959 :             }
         [ +  - ][ +  - ]
     689                 :            :         }
     690                 :            :     }
     691                 :            : 
     692                 :        999 :     return false;
     693                 :            : }
     694                 :            : 
     695                 :            : 
     696                 :            : //---------------------------------------------------------------------------
     697                 :            : //      GetTimeAmPm
     698                 :            : //
     699                 :            : // Lesen des Zeitsymbols (AM od. PM) f. kurze Zeitangabe
     700                 :            : //
     701                 :            : // Rueckgabe:
     702                 :            : //  "AM" od. "PM" => true
     703                 :            : //  sonst         => false
     704                 :            : //
     705                 :            : // nAmPos:
     706                 :            : //  "AM"  =>  1
     707                 :            : //  "PM"  => -1
     708                 :            : //  sonst =>  0
     709                 :            : 
     710                 :          9 : bool ImpSvNumberInputScan::GetTimeAmPm( const String& rString, xub_StrLen& nPos )
     711                 :            : {
     712                 :            : 
     713         [ +  + ]:          9 :     if ( rString.Len() > nPos )
     714                 :            :     {
     715                 :          3 :         const CharClass* pChr = pFormatter->GetCharClass();
     716                 :          3 :         const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
     717 [ +  - ][ +  - ]:          3 :         if ( StringContains( pChr->uppercase( pLoc->getTimeAM() ), rString, nPos ) )
         [ -  + ][ +  - ]
     718                 :            :         {
     719                 :          0 :             nAmPm = 1;
     720                 :          0 :             nPos = nPos + pLoc->getTimeAM().getLength();
     721                 :          0 :             return true;
     722                 :            :         }
     723 [ +  - ][ +  - ]:          3 :         else if ( StringContains( pChr->uppercase( pLoc->getTimePM() ), rString, nPos ) )
         [ +  - ][ -  + ]
     724                 :            :         {
     725                 :          0 :             nAmPm = -1;
     726                 :          0 :             nPos = nPos + pLoc->getTimePM().getLength();
     727                 :          0 :             return true;
     728                 :            :         }
     729                 :            :     }
     730                 :            : 
     731                 :          9 :     return false;
     732                 :            : }
     733                 :            : 
     734                 :            : 
     735                 :            : //---------------------------------------------------------------------------
     736                 :            : //      GetDecSep
     737                 :            : //
     738                 :            : // Lesen eines Dezimaltrenners (',')
     739                 :            : // ','   => true
     740                 :            : // sonst => false
     741                 :            : 
     742                 :       1771 : inline bool ImpSvNumberInputScan::GetDecSep( const String& rString, xub_StrLen& nPos )
     743                 :            : {
     744         [ +  + ]:       1771 :     if ( rString.Len() > nPos )
     745                 :            :     {
     746                 :       1707 :         const String& rSep = pFormatter->GetNumDecimalSep();
     747         [ +  + ]:       1707 :         if ( rString.Equals( rSep, nPos, rSep.Len() ) )
     748                 :            :         {
     749                 :        294 :             nPos = nPos + rSep.Len();
     750                 :        294 :             return true;
     751                 :            :         }
     752                 :            :     }
     753                 :       1771 :     return false;
     754                 :            : }
     755                 :            : 
     756                 :            : 
     757                 :            : //---------------------------------------------------------------------------
     758                 :            : // read a hundredth seconds separator
     759                 :            : 
     760                 :         24 : inline bool ImpSvNumberInputScan::GetTime100SecSep( const String& rString, xub_StrLen& nPos )
     761                 :            : {
     762         [ +  - ]:         24 :     if ( rString.Len() > nPos )
     763                 :            :     {
     764                 :         24 :         const String& rSep = pFormatter->GetLocaleData()->getTime100SecSep();
     765 [ -  + ][ +  - ]:         24 :         if ( rString.Equals( rSep, nPos, rSep.Len() ) )
     766                 :            :         {
     767                 :          0 :             nPos = nPos + rSep.Len();
     768                 :         24 :             return true;
     769         [ +  - ]:         24 :         }
     770                 :            :     }
     771                 :         24 :     return false;
     772                 :            : }
     773                 :            : 
     774                 :            : 
     775                 :            : //---------------------------------------------------------------------------
     776                 :            : //      GetSign
     777                 :            : //
     778                 :            : // Lesen eines Vorzeichens, auch Klammer !?!
     779                 :            : // '+'   =>  1
     780                 :            : // '-'   => -1
     781                 :            : // '('   => -1, nNegCheck = 1
     782                 :            : // sonst =>  0
     783                 :            : 
     784                 :       1019 : int ImpSvNumberInputScan::GetSign( const String& rString, xub_StrLen& nPos )
     785                 :            : {
     786         [ +  + ]:       1019 :     if (rString.Len() > nPos)
     787   [ -  -  +  + ]:        991 :         switch (rString.GetChar(nPos))
     788                 :            :         {
     789                 :            :             case '+':
     790                 :          0 :                 nPos++;
     791                 :          0 :                 return 1;
     792                 :            :             case '(':               // '(' aehnlich wie '-' ?!?
     793                 :          0 :                 nNegCheck = 1;
     794                 :            :                 //! fallthru
     795                 :            :             case '-':
     796                 :         12 :                 nPos++;
     797                 :         12 :                 return -1;
     798                 :            :             default:
     799                 :        979 :                 break;
     800                 :            :         }
     801                 :            : 
     802                 :       1019 :     return 0;
     803                 :            : }
     804                 :            : 
     805                 :            : 
     806                 :            : //---------------------------------------------------------------------------
     807                 :            : //      GetESign
     808                 :            : //
     809                 :            : // Lesen eines Vorzeichens, gedacht fuer Exponent ?!?
     810                 :            : // '+'   =>  1
     811                 :            : // '-'   => -1
     812                 :            : // sonst =>  0
     813                 :            : 
     814                 :          0 : short ImpSvNumberInputScan::GetESign( const String& rString, xub_StrLen& nPos )
     815                 :            : {
     816         [ #  # ]:          0 :     if (rString.Len() > nPos)
     817      [ #  #  # ]:          0 :         switch (rString.GetChar(nPos))
     818                 :            :         {
     819                 :            :             case '+':
     820                 :          0 :                 nPos++;
     821                 :          0 :                 return 1;
     822                 :            :             case '-':
     823                 :          0 :                 nPos++;
     824                 :          0 :                 return -1;
     825                 :            :             default:
     826                 :          0 :                 break;
     827                 :            :         }
     828                 :            : 
     829                 :          0 :     return 0;
     830                 :            : }
     831                 :            : 
     832                 :            : 
     833                 :            : //---------------------------------------------------------------------------
     834                 :            : //      GetNextNumber
     835                 :            : //
     836                 :            : // i counts string portions, j counts numbers thereof.
     837                 :            : // It should had been called SkipNumber instead.
     838                 :            : 
     839                 :       7885 : inline bool ImpSvNumberInputScan::GetNextNumber( sal_uInt16& i, sal_uInt16& j )
     840                 :            : {
     841 [ +  + ][ +  + ]:       7885 :     if ( i < nAnzStrings && IsNum[i] )
     842                 :            :     {
     843                 :       3796 :         j++;
     844                 :       3796 :         i++;
     845                 :       3796 :         return true;
     846                 :            :     }
     847                 :       7885 :     return false;
     848                 :            : }
     849                 :            : 
     850                 :            : 
     851                 :            : //---------------------------------------------------------------------------
     852                 :            : //      GetTimeRef
     853                 :            : 
     854                 :         24 : bool ImpSvNumberInputScan::GetTimeRef(
     855                 :            :         double& fOutNumber,
     856                 :            :         sal_uInt16 nIndex,          // j-value of the first numeric time part of input, default 0
     857                 :            :         sal_uInt16 nAnz )           // count of numeric time parts
     858                 :            : {
     859                 :         24 :     bool bRet = true;
     860                 :            :     sal_uInt16 nHour;
     861                 :         24 :     sal_uInt16 nMinute = 0;
     862                 :         24 :     sal_uInt16 nSecond = 0;
     863                 :         24 :     double fSecond100 = 0.0;
     864                 :         24 :     sal_uInt16 nStartIndex = nIndex;
     865                 :            : 
     866         [ -  + ]:         24 :     if (nTimezonePos)
     867                 :            :     {
     868                 :            :         // find first timezone number index and adjust count
     869         [ #  # ]:          0 :         for (sal_uInt16 j=0; j<nAnzNums; ++j)
     870                 :            :         {
     871         [ #  # ]:          0 :             if (nNums[j] == nTimezonePos)
     872                 :            :             {
     873                 :            :                 // nAnz is not total count, but count of time relevant strings.
     874 [ #  # ][ #  # ]:          0 :                 if (nStartIndex < j && j - nStartIndex < nAnz)
     875                 :          0 :                     nAnz = j - nStartIndex;
     876                 :          0 :                 break;  // for
     877                 :            :             }
     878                 :            :         }
     879                 :            :     }
     880                 :            : 
     881 [ -  + ][ #  # ]:         24 :     if (nDecPos == 2 && (nAnz == 3 || nAnz == 2))   // 20:45.5 or 45.5
                 [ #  # ]
     882                 :          0 :         nHour = 0;
     883         [ +  - ]:         24 :     else if (nIndex - nStartIndex < nAnz)
     884                 :         24 :         nHour   = (sal_uInt16) sStrArray[nNums[nIndex++]].ToInt32();
     885                 :            :     else
     886                 :            :     {
     887                 :          0 :         nHour = 0;
     888                 :          0 :         bRet = false;
     889                 :            :         SAL_WARN( "svl.items", "ImpSvNumberInputScan::GetTimeRef: bad number index");
     890                 :            :     }
     891 [ -  + ][ #  # ]:         24 :     if (nDecPos == 2 && nAnz == 2)                  // 45.5
     892                 :          0 :         nMinute = 0;
     893         [ +  - ]:         24 :     else if (nIndex - nStartIndex < nAnz)
     894                 :         24 :         nMinute = (sal_uInt16) sStrArray[nNums[nIndex++]].ToInt32();
     895         [ +  - ]:         24 :     if (nIndex - nStartIndex < nAnz)
     896                 :         24 :         nSecond = (sal_uInt16) sStrArray[nNums[nIndex++]].ToInt32();
     897         [ -  + ]:         24 :     if (nIndex - nStartIndex < nAnz)
     898                 :          0 :         fSecond100 = StringToDouble( sStrArray[nNums[nIndex]], true );
     899 [ -  + ][ #  # ]:         24 :     if (nAmPm && nHour > 12)                    // not a valid AM/PM clock time
     900                 :          0 :         bRet = false;
     901 [ -  + ][ #  # ]:         24 :     else if (nAmPm == -1 && nHour != 12)        // PM
     902                 :          0 :         nHour += 12;
     903 [ -  + ][ #  # ]:         24 :     else if (nAmPm == 1 && nHour == 12)         // 12 AM
     904                 :          0 :         nHour = 0;
     905                 :            : 
     906                 :            :     fOutNumber = ((double)nHour*3600 +
     907                 :            :                   (double)nMinute*60 +
     908                 :            :                   (double)nSecond +
     909                 :         24 :                   fSecond100)/86400.0;
     910                 :         24 :     return bRet;
     911                 :            : }
     912                 :            : 
     913                 :            : 
     914                 :            : //---------------------------------------------------------------------------
     915                 :            : //      ImplGetDay
     916                 :            : 
     917                 :        156 : sal_uInt16 ImpSvNumberInputScan::ImplGetDay( sal_uInt16 nIndex )
     918                 :            : {
     919                 :        156 :     sal_uInt16 nRes = 0;
     920                 :            : 
     921         [ +  - ]:        156 :     if (sStrArray[nNums[nIndex]].Len() <= 2)
     922                 :            :     {
     923                 :        156 :         sal_uInt16 nNum = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
     924         [ +  - ]:        156 :         if (nNum <= 31)
     925                 :        156 :             nRes = nNum;
     926                 :            :     }
     927                 :            : 
     928                 :        156 :     return nRes;
     929                 :            : }
     930                 :            : 
     931                 :            : 
     932                 :            : //---------------------------------------------------------------------------
     933                 :            : //      ImplGetMonth
     934                 :            : 
     935                 :        156 : sal_uInt16 ImpSvNumberInputScan::ImplGetMonth( sal_uInt16 nIndex )
     936                 :            : {
     937                 :            :     // preset invalid month number
     938                 :        156 :     sal_uInt16 nRes = pFormatter->GetCalendar()->getNumberOfMonthsInYear();
     939                 :            : 
     940         [ +  - ]:        156 :     if (sStrArray[nNums[nIndex]].Len() <= 2)
     941                 :            :     {
     942                 :        156 :         sal_uInt16 nNum = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
     943 [ +  - ][ +  - ]:        156 :         if ( 0 < nNum && nNum <= nRes )
     944                 :        156 :             nRes = nNum - 1;        // zero based for CalendarFieldIndex::MONTH
     945                 :            :     }
     946                 :            : 
     947                 :        156 :     return nRes;
     948                 :            : }
     949                 :            : 
     950                 :            : 
     951                 :            : //---------------------------------------------------------------------------
     952                 :            : //      ImplGetYear
     953                 :            : //
     954                 :            : // 30 -> 1930, 29 -> 2029, oder 56 -> 1756, 55 -> 1855, ...
     955                 :            : 
     956                 :        156 : sal_uInt16 ImpSvNumberInputScan::ImplGetYear( sal_uInt16 nIndex )
     957                 :            : {
     958                 :        156 :     sal_uInt16 nYear = 0;
     959                 :            : 
     960                 :        156 :     xub_StrLen nLen = sStrArray[nNums[nIndex]].Len();
     961         [ +  - ]:        156 :     if (nLen <= 4)
     962                 :            :     {
     963                 :        156 :         nYear = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
     964                 :            :         // A year < 100 entered with at least 3 digits with leading 0 is taken
     965                 :            :         // as is without expansion.
     966 [ #  # ][ -  + ]:        156 :         if (nYear < 100 && nLen < 3)
     967                 :          0 :             nYear = SvNumberFormatter::ExpandTwoDigitYear( nYear, nYear2000 );
     968                 :            :     }
     969                 :            : 
     970                 :        156 :     return nYear;
     971                 :            : }
     972                 :            : 
     973                 :            : //---------------------------------------------------------------------------
     974                 :            : 
     975                 :       1052 : bool ImpSvNumberInputScan::MayBeIso8601()
     976                 :            : {
     977         [ +  + ]:       1052 :     if (nMayBeIso8601 == 0)
     978                 :            :     {
     979                 :        506 :         nMayBeIso8601 = 1;
     980 [ +  - ][ +  - ]:        506 :         xub_StrLen nLen = ((nAnzNums >= 1 && nNums[0] < nAnzStrings) ? sStrArray[nNums[0]].Len() : 0);
     981         [ +  - ]:        506 :         if (nLen)
     982                 :            :         {
     983                 :            :             sal_Int32 n;
     984         [ +  + ]:       1410 :             if (nAnzNums >= 3 && nNums[2] < nAnzStrings &&
           [ +  -  +  + ]
         [ +  - ][ +  + ]
           [ +  -  +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
     985 [ +  - ][ +  + ]:        748 :                     comphelper::string::equals(sStrArray[nNums[0]+1], '-') && // separator year-month
                 [ #  # ]
     986                 :        183 :                     (n = sStrArray[nNums[1]].ToInt32()) >= 1 && n <= 12 &&  // month
     987 [ +  - ][ +  + ]:        662 :                     comphelper::string::equals(sStrArray[nNums[1]+1], '-') && // separator month-day
                 [ #  # ]
     988                 :        156 :                     (n = sStrArray[nNums[2]].ToInt32()) >= 1 && n <= 31)    // day
     989                 :            :                 // Year (nNums[0]) value not checked, may be anything, but
     990                 :            :                 // length (number of digits) is checked.
     991 [ -  + ][ #  # ]:        156 :                 nMayBeIso8601 = (nLen >= 4 ? 4 : (nLen == 3 ? 3 : (nLen > 0 ? 2 : 1)));
                 [ #  # ]
     992                 :            :         }
     993                 :            :     }
     994                 :       1052 :     return nMayBeIso8601 > 1;
     995                 :            : }
     996                 :            : 
     997                 :            : //---------------------------------------------------------------------------
     998                 :            : 
     999                 :        288 : bool ImpSvNumberInputScan::CanForceToIso8601( DateFormat eDateFormat )
    1000                 :            : {
    1001         [ +  + ]:        288 :     if (nCanForceToIso8601 == 0)
    1002                 :            :     {
    1003                 :        156 :         nCanForceToIso8601 = 1;
    1004                 :            :         do
    1005                 :            :         {
    1006         [ -  + ]:        156 :             if (!MayBeIso8601())
    1007                 :          0 :                 break;
    1008                 :            : 
    1009         [ +  - ]:        156 :             if (nMayBeIso8601 >= 3)
    1010                 :            :             {
    1011                 :        156 :                 nCanForceToIso8601 = 2; // at least 3 digits in year
    1012                 :        156 :                 break;
    1013                 :            :             }
    1014                 :            : 
    1015         [ #  # ]:          0 :             if (!comphelper::string::equals(pFormatter->GetDateSep(), '-'))
    1016                 :            :             {
    1017                 :          0 :                 nCanForceToIso8601 = 2; // date separator does not interfere
    1018                 :          0 :                 break;
    1019                 :            :             }
    1020                 :            : 
    1021                 :            :             sal_Int32 n;
    1022   [ #  #  #  # ]:          0 :             switch (eDateFormat)
    1023                 :            :             {
    1024                 :            :                 case DMY:               // "day" value out of range => ISO 8601 year
    1025 [ #  # ][ #  # ]:          0 :                     if ((n = sStrArray[nNums[0]].ToInt32()) < 1 || n > 31)
                 [ #  # ]
    1026                 :          0 :                         nCanForceToIso8601 = 2;
    1027                 :          0 :                     break;
    1028                 :            :                 case MDY:               // "month" value out of range => ISO 8601 year
    1029 [ #  # ][ #  # ]:          0 :                     if ((n = sStrArray[nNums[0]].ToInt32()) < 1 || n > 12)
                 [ #  # ]
    1030                 :          0 :                         nCanForceToIso8601 = 2;
    1031                 :          0 :                     break;
    1032                 :            :                 case YMD:               // always possible
    1033                 :          0 :                     nCanForceToIso8601 = 2;
    1034                 :        156 :                     break;
    1035                 :            :             }
    1036                 :            :         } while (0);
    1037                 :            :     }
    1038                 :        288 :     return nCanForceToIso8601 > 1;
    1039                 :            : }
    1040                 :            : 
    1041                 :            : //---------------------------------------------------------------------------
    1042                 :            : 
    1043                 :        356 : bool ImpSvNumberInputScan::MayBeMonthDate()
    1044                 :            : {
    1045         [ +  + ]:        356 :     if (nMayBeMonthDate == 0)
    1046                 :            :     {
    1047                 :        350 :         nMayBeMonthDate = 1;
    1048 [ +  + ][ +  - ]:        350 :         if (nAnzNums >= 2 && nNums[1] < nAnzStrings)
    1049                 :            :         {
    1050                 :            :             // "-Jan-"
    1051                 :        341 :             const String& rM = sStrArray[nNums[0]+1];
    1052 [ -  + ][ #  # ]:        341 :             if (rM.Len() >= 3 && rM.GetChar(0) == '-' && rM.GetChar( rM.Len()-1) == '-')
         [ #  # ][ -  + ]
    1053                 :            :             {
    1054                 :            :                 // Check year length assuming at least 3 digits (including
    1055                 :            :                 // leading zero). Two digit years 1..31 are out of luck here
    1056                 :            :                 // and may be taken as day of month.
    1057                 :          0 :                 bool bYear1 = (sStrArray[nNums[0]].Len() >= 3);
    1058                 :          0 :                 bool bYear2 = (sStrArray[nNums[1]].Len() >= 3);
    1059                 :            :                 sal_Int32 n;
    1060 [ #  # ][ #  # ]:          0 :                 bool bDay1 = (!bYear1 && (n = sStrArray[nNums[0]].ToInt32()) >= 1 && n <= 31);
                 [ #  # ]
    1061 [ #  # ][ #  # ]:          0 :                 bool bDay2 = (!bYear2 && (n = sStrArray[nNums[1]].ToInt32()) >= 1 && n <= 31);
                 [ #  # ]
    1062 [ #  # ][ #  # ]:          0 :                 if (bDay1 && !bDay2)
    1063                 :          0 :                     nMayBeMonthDate = 2;        // dd-month-yy
    1064 [ #  # ][ #  # ]:          0 :                 else if (!bDay1 && bDay2)
    1065                 :          0 :                     nMayBeMonthDate = 3;        // yy-month-dd
    1066 [ #  # ][ #  # ]:          0 :                 else if (bDay1 && bDay2)
    1067                 :            :                 {
    1068 [ #  # ][ #  # ]:          0 :                     if (bYear1 && !bYear2)
    1069                 :          0 :                         nMayBeMonthDate = 3;    // yy-month-dd
    1070 [ #  # ][ #  # ]:          0 :                     else if (!bYear1 && bYear2)
    1071                 :          0 :                         nMayBeMonthDate = 2;    // dd-month-yy
    1072                 :            :                 }
    1073                 :            :             }
    1074                 :            :         }
    1075                 :            :     }
    1076                 :        356 :     return nMayBeMonthDate > 1;
    1077                 :            : }
    1078                 :            : 
    1079                 :            : //---------------------------------------------------------------------------
    1080                 :            : 
    1081                 :       1073 : bool ImpSvNumberInputScan::IsAcceptedDatePattern( sal_uInt16 nStartPatternAt )
    1082                 :            : {
    1083         [ +  + ]:       1073 :     if (nAcceptedDatePattern >= -1)
    1084                 :        567 :         return (nAcceptedDatePattern >= 0);
    1085                 :            : 
    1086         [ -  + ]:        506 :     if (!nAnzNums)
    1087                 :          0 :         nAcceptedDatePattern = -1;
    1088         [ +  + ]:        506 :     else if (!sDateAcceptancePatterns.getLength())
    1089                 :            :     {
    1090         [ +  - ]:         54 :         sDateAcceptancePatterns = pFormatter->GetLocaleData()->getDateAcceptancePatterns();
    1091                 :            :         SAL_WARN_IF( !sDateAcceptancePatterns.getLength(), "nf.date", "ImpSvNumberInputScan::IsAcceptedDatePattern: no date acceptance patterns");
    1092         [ +  - ]:         54 :         nAcceptedDatePattern = (sDateAcceptancePatterns.getLength() ? -2 : -1);
    1093                 :            :     }
    1094                 :            : 
    1095         [ -  + ]:        506 :     if (nAcceptedDatePattern == -1)
    1096                 :          0 :         return false;
    1097                 :            : 
    1098                 :        506 :     nDatePatternStart = nStartPatternAt;    // remember start particle
    1099                 :            : 
    1100         [ +  + ]:       1518 :     for (sal_Int32 nPattern=0; nPattern < sDateAcceptancePatterns.getLength(); ++nPattern)
    1101                 :            :     {
    1102                 :       1012 :         sal_uInt16 nNext = nDatePatternStart;
    1103                 :       1012 :         bool bOk = true;
    1104                 :       1012 :         const rtl::OUString& rPat = sDateAcceptancePatterns[nPattern];
    1105                 :       1012 :         sal_Int32 nPat = 0;
    1106 [ +  - ][ +  + ]:       3036 :         for ( ; nPat < rPat.getLength() && bOk && nNext < nAnzStrings; ++nPat, ++nNext)
         [ +  - ][ +  + ]
    1107                 :            :         {
    1108         [ +  + ]:       2024 :             switch (rPat[nPat])
    1109                 :            :             {
    1110                 :            :                 case 'Y':
    1111                 :            :                 case 'M':
    1112                 :            :                 case 'D':
    1113                 :       1012 :                     bOk = IsNum[nNext];
    1114                 :       1012 :                     break;
    1115                 :            :                 default:
    1116                 :       1012 :                     bOk = !IsNum[nNext];
    1117         [ +  - ]:       1012 :                     if (bOk)
    1118                 :            :                     {
    1119                 :       1012 :                         const xub_StrLen nLen = sStrArray[nNext].Len();
    1120                 :       1012 :                         bOk = (rPat.indexOf( sStrArray[nNext], nPat) == nPat);
    1121         [ -  + ]:       1012 :                         if (bOk)
    1122                 :          0 :                             nPat += nLen - 1;
    1123 [ +  + ][ -  + ]:       1012 :                         else if (nPat + nLen > rPat.getLength() && sStrArray[nNext].GetChar(nLen-1) == ' ')
                 [ -  + ]
    1124                 :            :                         {
    1125                 :            :                             // Trailing blanks in input.
    1126 [ #  # ][ #  # ]:          0 :                             String aStr(comphelper::string::stripEnd(sStrArray[nNext], ' '));
                 [ #  # ]
    1127                 :            :                             // Expand again in case of pattern "M. D. " and
    1128                 :            :                             // input "M. D.  ", maybe fetched far, but..
    1129         [ #  # ]:          0 :                             aStr.Expand( rPat.getLength() - nPat, ' ');
    1130         [ #  # ]:          0 :                             bOk = (rPat.indexOf( aStr, nPat) == nPat);
    1131         [ #  # ]:          0 :                             if (bOk)
    1132         [ #  # ]:          0 :                                 nPat += aStr.Len() - 1;
    1133                 :            :                         }
    1134                 :            :                     }
    1135                 :       1012 :                     break;
    1136                 :            :             }
    1137                 :            :         }
    1138         [ -  + ]:       1012 :         if (bOk)
    1139                 :            :         {
    1140                 :            :             // Check for trailing characters mismatch.
    1141         [ #  # ]:          0 :             if (nNext < nAnzStrings)
    1142                 :            :             {
    1143                 :            :                 // Pattern end but not input end.
    1144         [ #  # ]:          0 :                 if (!IsNum[nNext])
    1145                 :            :                 {
    1146                 :            :                     // Trailing (or separating if time follows) blanks are ok.
    1147                 :          0 :                     xub_StrLen nPos = 0;
    1148                 :          0 :                     SkipBlanks( sStrArray[nNext], nPos);
    1149         [ #  # ]:          0 :                     if (nPos == sStrArray[nNext].Len())
    1150                 :            :                     {
    1151                 :          0 :                         nAcceptedDatePattern = nPattern;
    1152                 :          0 :                         return true;
    1153                 :            :                     }
    1154                 :            :                 }
    1155                 :            :             }
    1156         [ #  # ]:          0 :             else if (nPat == rPat.getLength())
    1157                 :            :             {
    1158                 :            :                 // Input end and pattern end => match.
    1159                 :          0 :                 nAcceptedDatePattern = nPattern;
    1160                 :          0 :                 return true;
    1161                 :            :             }
    1162                 :            :             // else Input end but not pattern end, no match.
    1163                 :            :         }
    1164                 :            :     }
    1165                 :        506 :     nAcceptedDatePattern = -1;
    1166                 :       1073 :     return false;
    1167                 :            : }
    1168                 :            : 
    1169                 :            : //---------------------------------------------------------------------------
    1170                 :            : 
    1171                 :        761 : bool ImpSvNumberInputScan::SkipDatePatternSeparator( sal_uInt16 nParticle, xub_StrLen & rPos )
    1172                 :            : {
    1173                 :            :     // If not initialized yet start with first number, if any.
    1174 [ +  - ][ +  - ]:        761 :     if (!IsAcceptedDatePattern( (nAnzNums ? nNums[0] : 0)))
    1175                 :        761 :         return false;
    1176                 :            : 
    1177 [ #  # ][ #  # ]:          0 :     if (nParticle < nDatePatternStart || nParticle >= nAnzStrings || IsNum[nParticle])
                 [ #  # ]
    1178                 :          0 :         return false;
    1179                 :            : 
    1180                 :          0 :     sal_uInt16 nNext = nDatePatternStart;
    1181                 :          0 :     const rtl::OUString& rPat = sDateAcceptancePatterns[nAcceptedDatePattern];
    1182 [ #  # ][ #  # ]:          0 :     for (sal_Int32 nPat = 0; nPat < rPat.getLength() && nNext < nAnzStrings; ++nPat, ++nNext)
                 [ #  # ]
    1183                 :            :     {
    1184         [ #  # ]:          0 :         switch (rPat[nPat])
    1185                 :            :         {
    1186                 :            :             case 'Y':
    1187                 :            :             case 'M':
    1188                 :            :             case 'D':
    1189                 :          0 :                 break;
    1190                 :            :             default:
    1191         [ #  # ]:          0 :                 if (nNext == nParticle)
    1192                 :            :                 {
    1193                 :          0 :                     const xub_StrLen nLen = sStrArray[nNext].Len();
    1194                 :          0 :                     bool bOk = (rPat.indexOf( sStrArray[nNext], nPat) == nPat);
    1195 [ #  # ][ #  # ]:          0 :                     if (!bOk && (nPat + nLen > rPat.getLength() && sStrArray[nNext].GetChar(nLen-1) == ' '))
         [ #  # ][ #  # ]
    1196                 :            :                     {
    1197                 :            :                         // The same ugly trailing blanks check as in
    1198                 :            :                         // IsAcceptedDatePattern().
    1199 [ #  # ][ #  # ]:          0 :                         String aStr(comphelper::string::stripEnd(sStrArray[nNext], ' '));
                 [ #  # ]
    1200         [ #  # ]:          0 :                         aStr.Expand( rPat.getLength() - nPat, ' ');
    1201 [ #  # ][ #  # ]:          0 :                         bOk = (rPat.indexOf( aStr, nPat) == nPat);
    1202                 :            :                     }
    1203         [ #  # ]:          0 :                     if (bOk)
    1204                 :            :                     {
    1205                 :          0 :                         rPos = nLen;    // yes, set, not add!
    1206                 :          0 :                         return true;
    1207                 :            :                     }
    1208                 :            :                     else
    1209                 :          0 :                         return false;
    1210                 :            :                 }
    1211                 :          0 :                 nPat += sStrArray[nNext].Len() - 1;
    1212                 :          0 :                 break;
    1213                 :            :         }
    1214                 :            :     }
    1215                 :        761 :     return false;
    1216                 :            : }
    1217                 :            : 
    1218                 :            : //---------------------------------------------------------------------------
    1219                 :            : 
    1220                 :        156 : sal_uInt32 ImpSvNumberInputScan::GetDatePatternOrder()
    1221                 :            : {
    1222                 :            :     // If not initialized yet start with first number, if any.
    1223 [ +  - ][ +  - ]:        156 :     if (!IsAcceptedDatePattern( (nAnzNums ? nNums[0] : 0)))
    1224                 :        156 :         return 0;
    1225                 :            : 
    1226                 :          0 :     sal_uInt32 nOrder = 0;
    1227                 :          0 :     const rtl::OUString& rPat = sDateAcceptancePatterns[nAcceptedDatePattern];
    1228 [ #  # ][ #  # ]:          0 :     for (sal_Int32 nPat = 0; nPat < rPat.getLength() && !(nOrder & 0xff0000); ++nPat)
                 [ #  # ]
    1229                 :            :     {
    1230         [ #  # ]:          0 :         switch (rPat[nPat])
    1231                 :            :         {
    1232                 :            :             case 'Y':
    1233                 :            :             case 'M':
    1234                 :            :             case 'D':
    1235                 :          0 :                 nOrder = (nOrder << 8) | rPat[nPat];
    1236                 :          0 :                 break;
    1237                 :            :         }
    1238                 :            :     }
    1239                 :        156 :     return nOrder;
    1240                 :            : }
    1241                 :            : 
    1242                 :            : //---------------------------------------------------------------------------
    1243                 :            : 
    1244                 :        156 : DateFormat ImpSvNumberInputScan::GetDateOrder()
    1245                 :            : {
    1246                 :        156 :     sal_uInt32 nOrder = GetDatePatternOrder();
    1247         [ +  - ]:        156 :     if (!nOrder)
    1248                 :        156 :         return pFormatter->GetLocaleData()->getDateFormat();
    1249   [ #  #  #  # ]:          0 :     switch ((nOrder & 0xff0000) >> 16)
    1250                 :            :     {
    1251                 :            :         case 'Y':
    1252 [ #  # ][ #  # ]:          0 :             if ((((nOrder & 0xff00) >> 8) == 'M') && ((nOrder & 0xff) == 'D'))
    1253                 :          0 :                 return YMD;
    1254                 :          0 :             break;
    1255                 :            :         case 'M':
    1256 [ #  # ][ #  # ]:          0 :             if ((((nOrder & 0xff00) >> 8) == 'D') && ((nOrder & 0xff) == 'Y'))
    1257                 :          0 :                 return MDY;
    1258                 :          0 :             break;
    1259                 :            :         case 'D':
    1260 [ #  # ][ #  # ]:          0 :             if ((((nOrder & 0xff00) >> 8) == 'M') && ((nOrder & 0xff) == 'Y'))
    1261                 :          0 :                 return DMY;
    1262                 :          0 :             break;
    1263                 :            :         default:
    1264                 :            :         case 0:
    1265   [ #  #  #  # ]:          0 :             switch ((nOrder & 0xff00) >> 8)
    1266                 :            :             {
    1267                 :            :                 case 'Y':
    1268         [ #  # ]:          0 :                     switch ((nOrder & 0xff))
    1269                 :            :                     {
    1270                 :            :                         case 'M':
    1271                 :          0 :                             return YMD;
    1272                 :            :                     }
    1273                 :          0 :                     break;
    1274                 :            :                 case 'M':
    1275      [ #  #  # ]:          0 :                     switch ((nOrder & 0xff))
    1276                 :            :                     {
    1277                 :            :                         case 'Y':
    1278                 :          0 :                             return DMY;
    1279                 :            :                         case 'D':
    1280                 :          0 :                             return MDY;
    1281                 :            :                     }
    1282                 :          0 :                     break;
    1283                 :            :                 case 'D':
    1284      [ #  #  # ]:          0 :                     switch ((nOrder & 0xff))
    1285                 :            :                     {
    1286                 :            :                         case 'Y':
    1287                 :          0 :                             return MDY;
    1288                 :            :                         case 'M':
    1289                 :          0 :                             return DMY;
    1290                 :            :                     }
    1291                 :          0 :                     break;
    1292                 :            :             }
    1293                 :            :     }
    1294                 :            :     SAL_WARN( "nf.date", "ImpSvNumberInputScan::GetDateOrder: undefined, falling back to locale's default");
    1295                 :        156 :     return pFormatter->GetLocaleData()->getDateFormat();
    1296                 :            : }
    1297                 :            : 
    1298                 :            : //---------------------------------------------------------------------------
    1299                 :            : //      GetDateRef
    1300                 :            : 
    1301                 :        156 : bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter,
    1302                 :            :         const SvNumberformat* pFormat )
    1303                 :            : {
    1304                 :            :     using namespace ::com::sun::star::i18n;
    1305                 :            :     NfEvalDateFormat eEDF;
    1306                 :            :     int nFormatOrder;
    1307 [ +  - ][ -  + ]:        156 :     if ( pFormat && ((pFormat->GetType() & NUMBERFORMAT_DATE) == NUMBERFORMAT_DATE) )
                 [ -  + ]
    1308                 :            :     {
    1309                 :          0 :         eEDF = pFormatter->GetEvalDateFormat();
    1310         [ #  # ]:          0 :         switch ( eEDF )
    1311                 :            :         {
    1312                 :            :             case NF_EVALDATEFORMAT_INTL :
    1313                 :            :             case NF_EVALDATEFORMAT_FORMAT :
    1314                 :          0 :                 nFormatOrder = 1;       // only one loop
    1315                 :          0 :             break;
    1316                 :            :             default:
    1317                 :          0 :                 nFormatOrder = 2;
    1318         [ #  # ]:          0 :                 if ( nMatchedAllStrings )
    1319                 :          0 :                     eEDF = NF_EVALDATEFORMAT_FORMAT_INTL;
    1320                 :            :                     // we have a complete match, use it
    1321                 :            :         }
    1322                 :            :     }
    1323                 :            :     else
    1324                 :            :     {
    1325                 :        156 :         eEDF = NF_EVALDATEFORMAT_INTL;
    1326                 :        156 :         nFormatOrder = 1;
    1327                 :            :     }
    1328                 :        156 :     bool res = true;
    1329                 :            : 
    1330                 :        156 :     const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
    1331                 :        156 :     CalendarWrapper* pCal = pFormatter->GetCalendar();
    1332         [ +  + ]:        312 :     for ( int nTryOrder = 1; nTryOrder <= nFormatOrder; nTryOrder++ )
    1333                 :            :     {
    1334 [ +  - ][ +  - ]:        156 :         pCal->setGregorianDateTime( Date( Date::SYSTEM ) );       // today
    1335         [ +  - ]:        156 :         String aOrgCalendar;        // empty => not changed yet
    1336                 :            :         DateFormat DateFmt;
    1337                 :            :         bool bFormatTurn;
    1338   [ +  -  -  -  :        156 :         switch ( eEDF )
                      - ]
    1339                 :            :         {
    1340                 :            :             case NF_EVALDATEFORMAT_INTL :
    1341                 :        156 :                 bFormatTurn = false;
    1342         [ +  - ]:        156 :                 DateFmt = GetDateOrder();
    1343                 :        156 :             break;
    1344                 :            :             case NF_EVALDATEFORMAT_FORMAT :
    1345                 :          0 :                 bFormatTurn = true;
    1346         [ #  # ]:          0 :                 DateFmt = pFormat->GetDateOrder();
    1347                 :          0 :             break;
    1348                 :            :             case NF_EVALDATEFORMAT_INTL_FORMAT :
    1349         [ #  # ]:          0 :                 if ( nTryOrder == 1 )
    1350                 :            :                 {
    1351                 :          0 :                     bFormatTurn = false;
    1352         [ #  # ]:          0 :                     DateFmt = GetDateOrder();
    1353                 :            :                 }
    1354                 :            :                 else
    1355                 :            :                 {
    1356                 :          0 :                     bFormatTurn = true;
    1357         [ #  # ]:          0 :                     DateFmt = pFormat->GetDateOrder();
    1358                 :            :                 }
    1359                 :          0 :             break;
    1360                 :            :             case NF_EVALDATEFORMAT_FORMAT_INTL :
    1361         [ #  # ]:          0 :                 if ( nTryOrder == 2 )
    1362                 :            :                 {
    1363                 :          0 :                     bFormatTurn = false;
    1364         [ #  # ]:          0 :                     DateFmt = GetDateOrder();
    1365                 :            :                 }
    1366                 :            :                 else
    1367                 :            :                 {
    1368                 :          0 :                     bFormatTurn = true;
    1369         [ #  # ]:          0 :                     DateFmt = pFormat->GetDateOrder();
    1370                 :            :                 }
    1371                 :          0 :             break;
    1372                 :            :             default:
    1373                 :            :                 OSL_FAIL( "ImpSvNumberInputScan::GetDateRef: unknown NfEvalDateFormat" );
    1374                 :          0 :                 DateFmt = YMD;
    1375                 :          0 :                 bFormatTurn = false;
    1376                 :            :         }
    1377                 :            :         if ( bFormatTurn )
    1378                 :            :         {
    1379                 :            : /* TODO:
    1380                 :            : We are currently not able to fully support a switch to another calendar during
    1381                 :            : input for the following reasons:
    1382                 :            : 1. We do have a problem if both (locale's default and format's) calendars
    1383                 :            :    define the same YMD order and use the same date separator, there is no way
    1384                 :            :    to distinguish between them if the input results in valid calendar input for
    1385                 :            :    both calendars. How to solve? Would NfEvalDateFormat be sufficient? Should
    1386                 :            :    it always be set to NF_EVALDATEFORMAT_FORMAT_INTL and thus the format's
    1387                 :            :    calendar be preferred? This could be confusing if a Calc cell was formatted
    1388                 :            :    different to the locale's default and has no content yet, then the user has
    1389                 :            :    no clue about the format or calendar being set.
    1390                 :            : 2. In Calc cell edit mode a date is always displayed and edited using the
    1391                 :            :    default edit format of the default calendar (normally being Gregorian). If
    1392                 :            :    input was ambiguous due to issue #1 we'd need a mechanism to tell that a
    1393                 :            :    date was edited and not newly entered. Not feasible. Otherwise we'd need a
    1394                 :            :    mechanism to use a specific edit format with a specific calendar according
    1395                 :            :    to the format set.
    1396                 :            : 3. For some calendars like Japanese Gengou we'd need era input, which isn't
    1397                 :            :    implemented at all. Though this is a rare and special case, forcing a
    1398                 :            :    calendar dependent edit format as suggested in item #2 might require era
    1399                 :            :    input, if it shouldn't result in a fallback to Gregorian calendar.
    1400                 :            : 4. Last and least: the GetMonth() method currently only matches month names of
    1401                 :            :    the default calendar. Alternating month names of the actual format's
    1402                 :            :    calendar would have to be implemented. No problem.
    1403                 :            : 
    1404                 :            : */
    1405                 :            : #ifdef THE_FUTURE
    1406                 :            :             if ( pFormat->IsOtherCalendar( nStringScanNumFor ) )
    1407                 :            :                 pFormat->SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime );
    1408                 :            :             else
    1409                 :            :                 pFormat->SwitchToSpecifiedCalendar( aOrgCalendar, fOrgDateTime,
    1410                 :            :                         nStringScanNumFor );
    1411                 :            : #endif
    1412                 :            :         }
    1413                 :            : 
    1414                 :        156 :         res = true;
    1415                 :        156 :         nCounter = 0;
    1416                 :            :         // For incomplete dates, always assume first day of month if not specified.
    1417         [ +  - ]:        156 :         pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 );
    1418                 :            : 
    1419   [ -  -  -  + ]:        156 :         switch (nAnzNums)       // count of numbers in string
    1420                 :            :         {
    1421                 :            :             case 0:                 // none
    1422         [ #  # ]:          0 :                 if (nMonthPos)          // only month (Jan)
    1423         [ #  # ]:          0 :                     pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
    1424                 :            :                 else
    1425                 :          0 :                     res = false;
    1426                 :          0 :                 break;
    1427                 :            : 
    1428                 :            :             case 1:                 // only one number
    1429                 :          0 :                 nCounter = 1;
    1430   [ #  #  #  # ]:          0 :                 switch (nMonthPos)  // where is the month
    1431                 :            :                 {
    1432                 :            :                     case 0:             // not found => only day entered
    1433 [ #  # ][ #  # ]:          0 :                         pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1434                 :          0 :                         break;
    1435                 :            :                     case 1:             // month at the beginning (Jan 01)
    1436         [ #  # ]:          0 :                         pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
    1437      [ #  #  # ]:          0 :                         switch (DateFmt)
    1438                 :            :                         {
    1439                 :            :                             case MDY:
    1440                 :            :                             case YMD:
    1441                 :            :                             {
    1442         [ #  # ]:          0 :                                 sal_uInt16 nDay = ImplGetDay(0);
    1443         [ #  # ]:          0 :                                 sal_uInt16 nYear = ImplGetYear(0);
    1444 [ #  # ][ #  # ]:          0 :                                 if (nDay == 0 || nDay > 32) {
    1445         [ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::YEAR, nYear);
    1446                 :            :                                 }
    1447                 :            :                                 else
    1448 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1449                 :          0 :                                 break;
    1450                 :            :                             }
    1451                 :            :                             case DMY:
    1452 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
    1453                 :          0 :                                 break;
    1454                 :            :                             default:
    1455                 :          0 :                                 res = false;
    1456                 :          0 :                                 break;
    1457                 :            :                         }
    1458                 :          0 :                         break;
    1459                 :            :                     case 3:             // month at the end (10 Jan)
    1460         [ #  # ]:          0 :                         pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
    1461      [ #  #  # ]:          0 :                         switch (DateFmt)
    1462                 :            :                         {
    1463                 :            :                             case DMY:
    1464 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1465                 :          0 :                                 break;
    1466                 :            :                             case YMD:
    1467 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
    1468                 :          0 :                                 break;
    1469                 :            :                             default:
    1470                 :          0 :                                 res = false;
    1471                 :          0 :                                 break;
    1472                 :            :                         }
    1473                 :          0 :                         break;
    1474                 :            :                     default:
    1475                 :          0 :                         res = false;
    1476                 :          0 :                         break;
    1477                 :            :                 }   // switch (nMonthPos)
    1478                 :          0 :                 break;
    1479                 :            : 
    1480                 :            :             case 2:                 // 2 numbers
    1481                 :          0 :                 nCounter = 2;
    1482   [ #  #  #  # ]:          0 :                 switch (nMonthPos)  // where is the month
    1483                 :            :                 {
    1484                 :            :                     case 0:             // not found
    1485                 :            :                     {
    1486                 :            :                         bool bHadExact;
    1487                 :            :                         sal_uInt32 nExactDateOrder = (bFormatTurn ?
    1488                 :            :                                 pFormat->GetExactDateOrder() :
    1489 [ #  # ][ #  # ]:          0 :                                 GetDatePatternOrder());
                 [ #  # ]
    1490 [ #  # ][ #  # ]:          0 :                         bool bIsExact = (0xff < nExactDateOrder && nExactDateOrder <= 0xffff);
    1491         [ #  # ]:          0 :                         if (bIsExact)
    1492                 :            :                         {   // formatted as date and exactly 2 parts
    1493                 :          0 :                             bHadExact = true;
    1494   [ #  #  #  # ]:          0 :                             switch ( (nExactDateOrder >> 8) & 0xff )
    1495                 :            :                             {
    1496                 :            :                                 case 'Y':
    1497 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
    1498                 :          0 :                                 break;
    1499                 :            :                                 case 'M':
    1500 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
    1501                 :          0 :                                 break;
    1502                 :            :                                 case 'D':
    1503 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1504                 :          0 :                                 break;
    1505                 :            :                                 default:
    1506                 :          0 :                                     bHadExact = false;
    1507                 :            :                             }
    1508   [ #  #  #  # ]:          0 :                             switch ( nExactDateOrder & 0xff )
    1509                 :            :                             {
    1510                 :            :                                 case 'Y':
    1511 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
    1512                 :          0 :                                 break;
    1513                 :            :                                 case 'M':
    1514 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
    1515                 :          0 :                                 break;
    1516                 :            :                                 case 'D':
    1517 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
    1518                 :          0 :                                 break;
    1519                 :            :                                 default:
    1520                 :          0 :                                     bHadExact = false;
    1521                 :            :                             }
    1522                 :            :                             SAL_WARN_IF( !bHadExact, "nf.date", "ImpSvNumberInputScan::GetDateRef: error in exact date order");
    1523                 :            :                         }
    1524                 :            :                         else
    1525                 :          0 :                             bHadExact = false;
    1526                 :            :                         // If input matched against a date acceptance pattern
    1527                 :            :                         // do not attempt to mess around with guessing the
    1528                 :            :                         // order, either it matches or it doesn't.
    1529 [ #  # ][ #  # ]:          0 :                         if ((bFormatTurn || !bIsExact) && (!bHadExact || !pCal->isValid()))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1530                 :            :                         {
    1531 [ #  # ][ #  # ]:          0 :                             if ( !bHadExact && nExactDateOrder )
    1532 [ #  # ][ #  # ]:          0 :                                 pCal->setGregorianDateTime( Date( Date::SYSTEM ) );   // reset today
    1533   [ #  #  #  # ]:          0 :                             switch (DateFmt)
    1534                 :            :                             {
    1535                 :            :                                 case MDY:
    1536                 :            :                                     // M D
    1537 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
    1538 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
    1539 [ #  # ][ #  # ]:          0 :                                     if ( !pCal->isValid() )             // 2nd try
    1540                 :            :                                     {                                   // M Y
    1541         [ #  # ]:          0 :                                         pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 );
    1542 [ #  # ][ #  # ]:          0 :                                         pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
    1543 [ #  # ][ #  # ]:          0 :                                         pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
    1544                 :            :                                     }
    1545                 :          0 :                                     break;
    1546                 :            :                                 case DMY:
    1547                 :            :                                     // D M
    1548 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1549 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
    1550 [ #  # ][ #  # ]:          0 :                                     if ( !pCal->isValid() )             // 2nd try
    1551                 :            :                                     {                                   // M Y
    1552         [ #  # ]:          0 :                                         pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 );
    1553 [ #  # ][ #  # ]:          0 :                                         pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
    1554 [ #  # ][ #  # ]:          0 :                                         pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
    1555                 :            :                                     }
    1556                 :          0 :                                     break;
    1557                 :            :                                 case YMD:
    1558                 :            :                                     // M D
    1559 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
    1560 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
    1561 [ #  # ][ #  # ]:          0 :                                     if ( !pCal->isValid() )             // 2nd try
    1562                 :            :                                     {                                   // Y M
    1563         [ #  # ]:          0 :                                         pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 );
    1564 [ #  # ][ #  # ]:          0 :                                         pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
    1565 [ #  # ][ #  # ]:          0 :                                         pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
    1566                 :            :                                     }
    1567                 :          0 :                                     break;
    1568                 :            :                                 default:
    1569                 :          0 :                                     res = false;
    1570                 :          0 :                                     break;
    1571                 :            :                             }
    1572                 :            :                         }
    1573                 :            :                     }
    1574                 :          0 :                     break;
    1575                 :            :                     case 1:             // month at the beginning (Jan 01 01)
    1576                 :            :                     {
    1577                 :            :                         // The input is valid as MDY in almost any
    1578                 :            :                         // constellation, there is no date order (M)YD except if
    1579                 :            :                         // set in a format applied.
    1580         [ #  # ]:          0 :                         pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
    1581 [ #  # ][ #  # ]:          0 :                         sal_uInt32 nExactDateOrder = (bFormatTurn ? pFormat->GetExactDateOrder() : 0);
    1582 [ #  # ][ #  # ]:          0 :                         if ((((nExactDateOrder >> 8) & 0xff) == 'Y') && ((nExactDateOrder & 0xff) == 'D'))
    1583                 :            :                         {
    1584 [ #  # ][ #  # ]:          0 :                             pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
    1585 [ #  # ][ #  # ]:          0 :                             pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
    1586                 :            :                         }
    1587                 :            :                         else
    1588                 :            :                         {
    1589 [ #  # ][ #  # ]:          0 :                             pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1590 [ #  # ][ #  # ]:          0 :                             pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
    1591                 :            :                         }
    1592                 :            :                     }
    1593                 :          0 :                     break;
    1594                 :            :                     case 2:             // month in the middle (10 Jan 94)
    1595                 :            :                     {
    1596         [ #  # ]:          0 :                         pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
    1597 [ #  # ][ #  # ]:          0 :                         DateFormat eDF = (MayBeMonthDate() ? (nMayBeMonthDate == 2 ? DMY : YMD) : DateFmt);
                 [ #  # ]
    1598      [ #  #  # ]:          0 :                         switch (eDF)
    1599                 :            :                         {
    1600                 :            :                             case DMY:
    1601 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1602 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
    1603                 :          0 :                                 break;
    1604                 :            :                             case YMD:
    1605 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
    1606 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
    1607                 :          0 :                                 break;
    1608                 :            :                             default:
    1609                 :          0 :                                 res = false;
    1610                 :          0 :                                 break;
    1611                 :            :                         }
    1612                 :            :                     }
    1613                 :          0 :                     break;
    1614                 :            :                     default:            // else, e.g. month at the end (94 10 Jan)
    1615                 :          0 :                         res = false;
    1616                 :          0 :                         break;
    1617                 :            :                 }   // switch (nMonthPos)
    1618                 :          0 :                 break;
    1619                 :            : 
    1620                 :            :             default:                // more than two numbers (31.12.94 8:23) (31.12. 8:23)
    1621   [ +  -  -  - ]:        156 :                 switch (nMonthPos)  // where is the month
    1622                 :            :                 {
    1623                 :            :                     case 0:             // not found
    1624                 :            :                     {
    1625                 :        156 :                         nCounter = 3;
    1626         [ +  + ]:        156 :                         if ( nTimePos > 1 )
    1627                 :            :                         {   // find first time number index (should only be 3 or 2 anyway)
    1628         [ +  - ]:        120 :                             for ( sal_uInt16 j = 0; j < nAnzNums; j++ )
    1629                 :            :                             {
    1630         [ +  + ]:         96 :                                 if ( nNums[j] == nTimePos - 2 )
    1631                 :            :                                 {
    1632                 :         24 :                                     nCounter = j;
    1633                 :         24 :                                     break;  // for
    1634                 :            :                                 }
    1635                 :            :                             }
    1636                 :            :                         }
    1637                 :            :                         // ISO 8601 yyyy-mm-dd forced recognition
    1638 [ +  - ][ +  - ]:        156 :                         DateFormat eDF = (CanForceToIso8601( DateFmt) ? YMD : DateFmt);
    1639   [ -  -  +  - ]:        156 :                         switch (eDF)
    1640                 :            :                         {
    1641                 :            :                             case MDY:
    1642 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
    1643 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
    1644         [ #  # ]:          0 :                                 if ( nCounter > 2 )
    1645 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(2) );
    1646                 :          0 :                                 break;
    1647                 :            :                             case DMY:
    1648 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1649 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
    1650         [ #  # ]:          0 :                                 if ( nCounter > 2 )
    1651 [ #  # ][ #  # ]:          0 :                                     pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(2) );
    1652                 :          0 :                                 break;
    1653                 :            :                             case YMD:
    1654         [ +  - ]:        156 :                                 if ( nCounter > 2 )
    1655 [ +  - ][ +  - ]:        156 :                                     pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(2) );
    1656 [ +  - ][ +  - ]:        156 :                                 pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
    1657 [ +  - ][ +  - ]:        156 :                                 pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
    1658                 :        156 :                                 break;
    1659                 :            :                             default:
    1660                 :          0 :                                 res = false;
    1661                 :          0 :                                 break;
    1662                 :            :                         }
    1663                 :            :                     }
    1664                 :        156 :                         break;
    1665                 :            :                     case 1:             // month at the beginning (Jan 01 01 8:23)
    1666                 :          0 :                         nCounter = 2;
    1667         [ #  # ]:          0 :                         switch (DateFmt)
    1668                 :            :                         {
    1669                 :            :                             case MDY:
    1670 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1671         [ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
    1672 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
    1673                 :          0 :                                 break;
    1674                 :            :                             default:
    1675                 :          0 :                                 res = false;
    1676                 :          0 :                                 break;
    1677                 :            :                         }
    1678                 :          0 :                         break;
    1679                 :            :                     case 2:             // month in the middle (10 Jan 94 8:23)
    1680                 :          0 :                         nCounter = 2;
    1681         [ #  # ]:          0 :                         pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
    1682      [ #  #  # ]:          0 :                         switch (DateFmt)
    1683                 :            :                         {
    1684                 :            :                             case DMY:
    1685 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
    1686 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
    1687                 :          0 :                                 break;
    1688                 :            :                             case YMD:
    1689 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
    1690 [ #  # ][ #  # ]:          0 :                                 pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
    1691                 :          0 :                                 break;
    1692                 :            :                             default:
    1693                 :          0 :                                 res = false;
    1694                 :          0 :                                 break;
    1695                 :            :                         }
    1696                 :          0 :                         break;
    1697                 :            :                     default:            // else, e.g. month at the end (94 10 Jan 8:23)
    1698                 :          0 :                         nCounter = 2;
    1699                 :          0 :                         res = false;
    1700                 :          0 :                         break;
    1701                 :            :                 }   // switch (nMonthPos)
    1702                 :        156 :                 break;
    1703                 :            :         }   // switch (nAnzNums)
    1704                 :            : 
    1705 [ +  - ][ +  - ]:        156 :         if ( res && pCal->isValid() )
         [ +  - ][ +  - ]
    1706                 :            :         {
    1707         [ +  - ]:        156 :             double fDiff = DateTime(*pNullDate) - pCal->getEpochStart();
    1708         [ +  - ]:        156 :             fDays = ::rtl::math::approxFloor( pCal->getLocalDateTime() );
    1709                 :        156 :             fDays -= fDiff;
    1710                 :        156 :             nTryOrder = nFormatOrder;   // break for
    1711                 :            :         }
    1712                 :            :         else
    1713                 :          0 :             res = false;
    1714                 :            : 
    1715         [ -  + ]:        156 :         if ( aOrgCalendar.Len() )
    1716 [ #  # ][ #  # ]:          0 :             pCal->loadCalendar( aOrgCalendar, pLoc->getLocale() );  // restore calendar
                 [ #  # ]
    1717                 :            : 
    1718                 :            : #if NF_TEST_CALENDAR
    1719                 :            : {
    1720                 :            :     using namespace ::com::sun::star;
    1721                 :            :     struct entry { const char* lan; const char* cou; const char* cal; };
    1722                 :            :     const entry cals[] = {
    1723                 :            :         { "en", "US",  "gregorian" },
    1724                 :            :         { "ar", "TN",      "hijri" },
    1725                 :            :         { "he", "IL",     "jewish" },
    1726                 :            :         { "ja", "JP",     "gengou" },
    1727                 :            :         { "ko", "KR", "hanja_yoil" },
    1728                 :            :         { "th", "TH",   "buddhist" },
    1729                 :            :         { "zh", "TW",        "ROC" },
    1730                 :            :         {0,0,0}
    1731                 :            :     };
    1732                 :            :     lang::Locale aLocale;
    1733                 :            :     bool bValid;
    1734                 :            :     sal_Int16 nDay, nMyMonth, nYear, nHour, nMinute, nSecond;
    1735                 :            :     sal_Int16 nDaySet, nMonthSet, nYearSet, nHourSet, nMinuteSet, nSecondSet;
    1736                 :            :     sal_Int16 nZO, nDST1, nDST2, nDST, nZOmillis, nDST1millis, nDST2millis, nDSTmillis;
    1737                 :            :     sal_Int32 nZoneInMillis, nDST1InMillis, nDST2InMillis;
    1738                 :            :     uno::Reference< lang::XMultiServiceFactory > xSMgr =
    1739                 :            :         ::comphelper::getProcessServiceFactory();
    1740                 :            :     uno::Reference< ::com::sun::star::i18n::XCalendar3 > xCal(
    1741                 :            :             xSMgr->createInstance( "com.sun.star.i18n.LocaleCalendar" ),
    1742                 :            :             uno::UNO_QUERY );
    1743                 :            :     for ( const entry* p = cals; p->lan; ++p )
    1744                 :            :     {
    1745                 :            :         aLocale.Language = ::rtl::OUString::createFromAscii( p->lan );
    1746                 :            :         aLocale.Country  = ::rtl::OUString::createFromAscii( p->cou );
    1747                 :            :         xCal->loadCalendar( ::rtl::OUString::createFromAscii( p->cal ),
    1748                 :            :                 aLocale );
    1749                 :            :         double nDateTime = 0.0;     // 1-Jan-1970 00:00:00
    1750                 :            :         nZO           = xCal->getValue( i18n::CalendarFieldIndex::ZONE_OFFSET );
    1751                 :            :         nZOmillis     = xCal->getValue( i18n::CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS );
    1752                 :            :         nZoneInMillis = static_cast<sal_Int32>(nZO) * 60000 +
    1753                 :            :             (nZO < 0 ? -1 : 1) * static_cast<sal_uInt16>(nZOmillis);
    1754                 :            :         nDST1         = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET );
    1755                 :            :         nDST1millis   = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS );
    1756                 :            :         nDST1InMillis = static_cast<sal_Int32>(nDST1) * 60000 +
    1757                 :            :             (nDST1 < 0 ? -1 : 1) * static_cast<sal_uInt16>(nDST1millis);
    1758                 :            :         nDateTime    -= (double)(nZoneInMillis + nDST1InMillis) / 1000.0 / 60.0 / 60.0 / 24.0;
    1759                 :            :         xCal->setDateTime( nDateTime );
    1760                 :            :         nDST2         = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET );
    1761                 :            :         nDST2millis   = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS );
    1762                 :            :         nDST2InMillis = static_cast<sal_Int32>(nDST2) * 60000 +
    1763                 :            :             (nDST2 < 0 ? -1 : 1) * static_cast<sal_uInt16>(nDST2millis);
    1764                 :            :         if ( nDST1InMillis != nDST2InMillis )
    1765                 :            :         {
    1766                 :            :             nDateTime = 0.0 - (double)(nZoneInMillis + nDST2InMillis) / 1000.0 / 60.0 / 60.0 / 24.0;
    1767                 :            :             xCal->setDateTime( nDateTime );
    1768                 :            :         }
    1769                 :            :         nDaySet    = xCal->getValue( i18n::CalendarFieldIndex::DAY_OF_MONTH );
    1770                 :            :         nMonthSet  = xCal->getValue( i18n::CalendarFieldIndex::MONTH );
    1771                 :            :         nYearSet   = xCal->getValue( i18n::CalendarFieldIndex::YEAR );
    1772                 :            :         nHourSet   = xCal->getValue( i18n::CalendarFieldIndex::HOUR );
    1773                 :            :         nMinuteSet = xCal->getValue( i18n::CalendarFieldIndex::MINUTE );
    1774                 :            :         nSecondSet = xCal->getValue( i18n::CalendarFieldIndex::SECOND );
    1775                 :            :         nZO        = xCal->getValue( i18n::CalendarFieldIndex::ZONE_OFFSET );
    1776                 :            :         nZOmillis  = xCal->getValue( i18n::CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS );
    1777                 :            :         nDST       = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET );
    1778                 :            :         nDSTmillis = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS );
    1779                 :            :         xCal->setValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, nDaySet );
    1780                 :            :         xCal->setValue( i18n::CalendarFieldIndex::MONTH, nMonthSet );
    1781                 :            :         xCal->setValue( i18n::CalendarFieldIndex::YEAR, nYearSet );
    1782                 :            :         xCal->setValue( i18n::CalendarFieldIndex::HOUR, nHourSet );
    1783                 :            :         xCal->setValue( i18n::CalendarFieldIndex::MINUTE, nMinuteSet );
    1784                 :            :         xCal->setValue( i18n::CalendarFieldIndex::SECOND, nSecondSet );
    1785                 :            :         bValid  = xCal->isValid();
    1786                 :            :         nDay    = xCal->getValue( i18n::CalendarFieldIndex::DAY_OF_MONTH );
    1787                 :            :         nMyMonth= xCal->getValue( i18n::CalendarFieldIndex::MONTH );
    1788                 :            :         nYear   = xCal->getValue( i18n::CalendarFieldIndex::YEAR );
    1789                 :            :         nHour   = xCal->getValue( i18n::CalendarFieldIndex::HOUR );
    1790                 :            :         nMinute = xCal->getValue( i18n::CalendarFieldIndex::MINUTE );
    1791                 :            :         nSecond = xCal->getValue( i18n::CalendarFieldIndex::SECOND );
    1792                 :            :         bValid = bValid && nDay == nDaySet && nMyMonth == nMonthSet && nYear ==
    1793                 :            :             nYearSet && nHour == nHourSet && nMinute == nMinuteSet && nSecond
    1794                 :            :             == nSecondSet;
    1795                 :            :     }
    1796                 :            : }
    1797                 :            : #endif  // NF_TEST_CALENDAR
    1798                 :            : 
    1799         [ +  - ]:        156 :     }
    1800                 :            : 
    1801                 :        156 :     return res;
    1802                 :            : }
    1803                 :            : 
    1804                 :            : 
    1805                 :            : //---------------------------------------------------------------------------
    1806                 :            : //      ScanStartString
    1807                 :            : //
    1808                 :            : // ersten String analysieren
    1809                 :            : // Alles weg => true
    1810                 :            : // sonst     => false
    1811                 :            : 
    1812                 :        990 : bool ImpSvNumberInputScan::ScanStartString( const String& rString,
    1813                 :            :         const SvNumberformat* pFormat )
    1814                 :            : {
    1815                 :        990 :     xub_StrLen nPos = 0;
    1816                 :            : 
    1817                 :            :     // First of all, eat leading blanks
    1818                 :        990 :     SkipBlanks(rString, nPos);
    1819                 :            : 
    1820                 :            :     // Yes, nMatchedAllStrings should know about the sign position
    1821                 :        990 :     nSign = GetSign(rString, nPos);
    1822         [ +  + ]:        990 :     if ( nSign )           // sign?
    1823                 :          8 :         SkipBlanks(rString, nPos);
    1824                 :            : 
    1825                 :            :     // #102371# match against format string only if start string is not a sign character
    1826 [ +  - ][ +  + ]:        990 :     if ( nMatchedAllStrings && !(nSign && rString.Len() == 1) )
         [ -  + ][ +  + ]
    1827                 :            :     {   // Match against format in any case, so later on for a "x1-2-3" input
    1828                 :            :         // we may distinguish between a xy-m-d (or similar) date and a x0-0-0
    1829                 :            :         // format. No sign detection here!
    1830 [ +  - ][ -  + ]:        982 :         if ( ScanStringNumFor( rString, nPos, pFormat, 0, true ) )
    1831                 :          0 :             nMatchedAllStrings |= nMatchedStartString;
    1832                 :            :         else
    1833                 :        982 :             nMatchedAllStrings = 0;
    1834                 :            :     }
    1835                 :            : 
    1836 [ +  - ][ -  + ]:        990 :     if ( GetDecSep(rString, nPos) )                 // decimal separator in start string
    1837                 :            :     {
    1838                 :          0 :         nDecPos = 1;
    1839                 :          0 :         SkipBlanks(rString, nPos);
    1840                 :            :     }
    1841 [ +  - ][ +  + ]:        990 :     else if ( GetCurrency(rString, nPos, pFormat) ) // currency (DM 1)?
    1842                 :            :     {
    1843                 :         20 :         eScannedType = NUMBERFORMAT_CURRENCY;       // !!! it IS currency !!!
    1844                 :         20 :         SkipBlanks(rString, nPos);
    1845         [ +  - ]:         20 :         if (nSign == 0)                             // no sign yet
    1846                 :            :         {
    1847                 :         20 :             nSign = GetSign(rString, nPos);
    1848         [ +  + ]:         20 :             if ( nSign )   // DM -1
    1849                 :          4 :                 SkipBlanks(rString, nPos);
    1850                 :            :         }
    1851 [ +  - ][ -  + ]:         20 :         if ( GetDecSep(rString, nPos) )             // decimal separator follows currency
    1852                 :            :         {
    1853                 :          0 :             nDecPos = 1;
    1854                 :          0 :             SkipBlanks(rString, nPos);
    1855                 :            :         }
    1856                 :            :     }
    1857                 :            :     else
    1858                 :            :     {
    1859         [ +  - ]:        970 :         nMonth = GetMonth(rString, nPos);
    1860         [ -  + ]:        970 :         if ( nMonth )    // month (Jan 1)?
    1861                 :            :         {
    1862                 :          0 :             eScannedType = NUMBERFORMAT_DATE;       // !!! it IS a date !!!
    1863                 :          0 :             nMonthPos = 1;                          // month at the beginning
    1864         [ #  # ]:          0 :             if ( nMonth < 0 )
    1865                 :          0 :                 SkipChar( '.', rString, nPos );     // abbreviated
    1866                 :          0 :             SkipBlanks(rString, nPos);
    1867                 :            :         }
    1868                 :            :         else
    1869                 :            :         {
    1870         [ +  - ]:        970 :             int nDayOfWeek = GetDayOfWeek( rString, nPos );
    1871         [ -  + ]:        970 :             if ( nDayOfWeek )
    1872                 :            :             {   // day of week is just parsed away
    1873                 :          0 :                 eScannedType = NUMBERFORMAT_DATE;       // !!! it IS a date !!!
    1874         [ #  # ]:          0 :                 if ( nPos < rString.Len() )
    1875                 :            :                 {
    1876         [ #  # ]:          0 :                     if ( nDayOfWeek < 0 )
    1877                 :            :                     {   // abbreviated
    1878         [ #  # ]:          0 :                         if ( rString.GetChar( nPos ) == '.' )
    1879                 :          0 :                             ++nPos;
    1880                 :            :                     }
    1881                 :            :                     else
    1882                 :            :                     {   // full long name
    1883                 :          0 :                         SkipBlanks(rString, nPos);
    1884 [ #  # ][ #  # ]:          0 :                         SkipString( pFormatter->GetLocaleData()->getLongDateDayOfWeekSep(), rString, nPos );
         [ #  # ][ #  # ]
    1885                 :            :                     }
    1886                 :          0 :                     SkipBlanks(rString, nPos);
    1887         [ #  # ]:          0 :                     nMonth = GetMonth(rString, nPos);
    1888         [ #  # ]:          0 :                     if ( nMonth ) // month (Jan 1)?
    1889                 :            :                     {
    1890                 :          0 :                         nMonthPos = 1;                  // month a the beginning
    1891         [ #  # ]:          0 :                         if ( nMonth < 0 )
    1892                 :          0 :                             SkipChar( '.', rString, nPos ); // abbreviated
    1893                 :          0 :                         SkipBlanks(rString, nPos);
    1894                 :            :                     }
    1895                 :            :                 }
    1896         [ #  # ]:          0 :                 if (!nMonth)
    1897                 :            :                 {
    1898                 :            :                     // Determine and remember following date pattern, if any.
    1899         [ #  # ]:          0 :                     IsAcceptedDatePattern( 1);
    1900                 :            :                 }
    1901                 :            :             }
    1902                 :            :         }
    1903                 :            :     }
    1904                 :            : 
    1905                 :            :     // skip any trailing '-' or '/' chars
    1906         [ +  + ]:        990 :     if (nPos < rString.Len())
    1907                 :            :     {
    1908 [ +  - ][ +  + ]:        974 :         while (SkipChar ('-', rString, nPos) || SkipChar ('/', rString, nPos)) {
                 [ +  + ]
    1909                 :            :             // do nothing
    1910                 :            :         }
    1911                 :            :     }
    1912         [ +  + ]:        990 :     if (nPos < rString.Len())                       // not everything consumed
    1913                 :            :     {
    1914                 :            :         // Does input StartString equal StartString of format?
    1915                 :            :         // This time with sign detection!
    1916 [ +  - ][ +  - ]:        956 :         if ( !ScanStringNumFor( rString, nPos, pFormat, 0 ) )
    1917                 :        956 :             return MatchedReturn();
    1918                 :            :     }
    1919                 :            : 
    1920                 :        990 :     return true;
    1921                 :            : }
    1922                 :            : 
    1923                 :            : 
    1924                 :            : //---------------------------------------------------------------------------
    1925                 :            : //      ScanMidString
    1926                 :            : //
    1927                 :            : // String in der Mitte analysieren
    1928                 :            : // Alles weg => true
    1929                 :            : // sonst     => false
    1930                 :            : 
    1931                 :        752 : bool ImpSvNumberInputScan::ScanMidString( const String& rString,
    1932                 :            :         sal_uInt16 nStringPos, const SvNumberformat* pFormat )
    1933                 :            : {
    1934                 :        752 :     xub_StrLen nPos = 0;
    1935                 :        752 :     short eOldScannedType = eScannedType;
    1936                 :            : 
    1937         [ +  + ]:        752 :     if ( nMatchedAllStrings )
    1938                 :            :     {   // Match against format in any case, so later on for a "1-2-3-4" input
    1939                 :            :         // we may distinguish between a y-m-d (or similar) date and a 0-0-0-0
    1940                 :            :         // format.
    1941 [ +  - ][ -  + ]:        477 :         if ( ScanStringNumFor( rString, 0, pFormat, nStringPos ) )
    1942                 :          0 :             nMatchedAllStrings |= nMatchedMidString;
    1943                 :            :         else
    1944                 :        477 :             nMatchedAllStrings = 0;
    1945                 :            :     }
    1946                 :            : 
    1947                 :        752 :     SkipBlanks(rString, nPos);
    1948 [ +  + ][ +  - ]:        752 :     if (GetDecSep(rString, nPos))                   // decimal separator?
    1949                 :            :     {
    1950 [ +  - ][ -  + ]:        294 :         if (nDecPos == 1 || nDecPos == 3)           // .12.4 or 1.E2.1
    1951                 :          0 :             return MatchedReturn();
    1952         [ +  + ]:        294 :         else if (nDecPos == 2)                      // . dup: 12.4.
    1953                 :            :         {
    1954 [ +  - ][ -  + ]:         42 :             if (bDecSepInDateSeps                   // . also date separator
                 [ -  + ]
    1955         [ +  - ]:         21 :                     || SkipDatePatternSeparator( nStringPos, nPos))
    1956                 :            :             {
    1957 [ #  # ][ #  # ]:          0 :                 if (    eScannedType != NUMBERFORMAT_UNDEFINED &&
                 [ #  # ]
    1958                 :            :                         eScannedType != NUMBERFORMAT_DATE &&
    1959                 :            :                         eScannedType != NUMBERFORMAT_DATETIME)  // already another type
    1960                 :          0 :                     return MatchedReturn();
    1961         [ #  # ]:          0 :                 if (eScannedType == NUMBERFORMAT_UNDEFINED)
    1962                 :          0 :                     eScannedType = NUMBERFORMAT_DATE;   // !!! it IS a date
    1963                 :          0 :                 SkipBlanks(rString, nPos);
    1964                 :            :             }
    1965                 :            :             else
    1966                 :         21 :                 return MatchedReturn();
    1967                 :            :         }
    1968                 :            :         else
    1969                 :            :         {
    1970                 :        273 :             nDecPos = 2;                            // . in mid string
    1971                 :        273 :             SkipBlanks(rString, nPos);
    1972                 :            :         }
    1973                 :            :     }
    1974 [ +  + ][ -  + ]:        482 :     else if ( ((eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME)
                 [ -  + ]
    1975         [ +  - ]:         24 :             && GetTime100SecSep( rString, nPos ) )
    1976                 :            :     {                                               // hundredth seconds separator
    1977         [ #  # ]:          0 :         if ( nDecPos )
    1978                 :          0 :             return MatchedReturn();
    1979                 :          0 :         nDecPos = 2;                                // . in mid string
    1980                 :          0 :         SkipBlanks(rString, nPos);
    1981                 :            :     }
    1982                 :            : 
    1983         [ -  + ]:        731 :     if (SkipChar('/', rString, nPos))               // fraction?
    1984                 :            :     {
    1985 [ #  # ][ #  # ]:          0 :         if (   eScannedType != NUMBERFORMAT_UNDEFINED   // already another type
    1986                 :            :             && eScannedType != NUMBERFORMAT_DATE)       // except date
    1987                 :          0 :             return MatchedReturn();                               // => jan/31/1994
    1988 [ #  # ][ #  # ]:          0 :         else if (    eScannedType != NUMBERFORMAT_DATE      // analyzed date until now
         [ #  # ][ #  # ]
    1989                 :            :                  && (    eSetType == NUMBERFORMAT_FRACTION  // and preset was fraction
    1990                 :            :                      || (nAnzNums == 3                      // or 3 numbers
    1991                 :            :                          && nStringPos > 2) ) )             // and what ???
    1992                 :            :         {
    1993                 :          0 :             SkipBlanks(rString, nPos);
    1994                 :          0 :             eScannedType = NUMBERFORMAT_FRACTION;   // !!! it IS a fraction
    1995                 :            :         }
    1996                 :            :         else
    1997                 :          0 :             nPos--;                                 // put '/' back
    1998                 :            :     }
    1999                 :            : 
    2000 [ +  - ][ +  + ]:        731 :     if (GetThousandSep(rString, nPos, nStringPos))  // 1,000
    2001                 :            :     {
    2002 [ -  + ][ #  # ]:          6 :         if (   eScannedType != NUMBERFORMAT_UNDEFINED   // already another type
    2003                 :            :             && eScannedType != NUMBERFORMAT_CURRENCY)   // except currency
    2004                 :          0 :             return MatchedReturn();
    2005                 :          6 :         nThousand++;
    2006                 :            :     }
    2007                 :            : 
    2008                 :        731 :     const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
    2009         [ +  - ]:        731 :     bool bDate = SkipDatePatternSeparator( nStringPos, nPos);   // 12/31  31.12.  12/31/1999  31.12.1999
    2010         [ +  - ]:        731 :     if (!bDate)
    2011                 :            :     {
    2012                 :        731 :         const String& rDate = pFormatter->GetDateSep();
    2013                 :        731 :         SkipBlanks(rString, nPos);
    2014         [ +  - ]:        731 :         bDate = SkipString( rDate, rString, nPos);      // 10.  10-  10/
    2015                 :            :     }
    2016 [ +  - ][ +  + ]:       2193 :     if (bDate
           [ -  +  +  + ]
                 [ +  + ]
    2017 [ +  - ][ +  - ]:       1078 :             || ((MayBeIso8601() || MayBeMonthDate())    // 1999-12-31  31-Dec-1999
    2018                 :        384 :                 && SkipChar( '-', rString, nPos)))
    2019                 :            :     {
    2020 [ +  + ][ -  + ]:        312 :         if (   eScannedType != NUMBERFORMAT_UNDEFINED   // already another type
    2021                 :            :             && eScannedType != NUMBERFORMAT_DATE)       // except date
    2022                 :          0 :             return MatchedReturn();
    2023                 :        312 :         SkipBlanks(rString, nPos);
    2024                 :        312 :         eScannedType = NUMBERFORMAT_DATE;           // !!! it IS a date
    2025         [ +  - ]:        312 :         short nTmpMonth = GetMonth(rString, nPos);  // 10. Jan 94
    2026 [ -  + ][ #  # ]:        312 :         if (nMonth && nTmpMonth)                    // month dup
    2027                 :          0 :             return MatchedReturn();
    2028         [ -  + ]:        312 :         if (nTmpMonth)
    2029                 :            :         {
    2030                 :          0 :             nMonth = nTmpMonth;
    2031                 :          0 :             nMonthPos = 2;                          // month in the middle
    2032 [ #  # ][ #  # ]:          0 :             if ( nMonth < 0 && SkipChar( '.', rString, nPos ) )
                 [ #  # ]
    2033                 :            :                 ;   // short month may be abbreviated Jan.
    2034         [ #  # ]:          0 :             else if ( SkipChar( '-', rString, nPos ) )
    2035                 :            :                 ;   // #79632# recognize 17-Jan-2001 to be a date
    2036                 :            :                     // #99065# short and long month name
    2037                 :            :             else
    2038 [ #  # ][ #  # ]:          0 :                 SkipString( pLoc->getLongDateMonthSep(), rString, nPos );
         [ #  # ][ #  # ]
    2039                 :          0 :             SkipBlanks(rString, nPos);
    2040                 :            :         }
    2041                 :            :     }
    2042                 :            : 
    2043         [ +  - ]:        731 :     short nTempMonth = GetMonth(rString, nPos);     // month in the middle (10 Jan 94)
    2044         [ -  + ]:        731 :     if (nTempMonth)
    2045                 :            :     {
    2046         [ #  # ]:          0 :         if (nMonth != 0)                            // month dup
    2047                 :          0 :             return MatchedReturn();
    2048 [ #  # ][ #  # ]:          0 :         if (   eScannedType != NUMBERFORMAT_UNDEFINED   // already another type
    2049                 :            :             && eScannedType != NUMBERFORMAT_DATE)       // except date
    2050                 :          0 :             return MatchedReturn();
    2051                 :          0 :         eScannedType = NUMBERFORMAT_DATE;           // !!! it IS a date
    2052                 :          0 :         nMonth = nTempMonth;
    2053                 :          0 :         nMonthPos = 2;                              // month in the middle
    2054         [ #  # ]:          0 :         if ( nMonth < 0 )
    2055                 :          0 :             SkipChar( '.', rString, nPos );         // abbreviated
    2056 [ #  # ][ #  # ]:          0 :         SkipString( pLoc->getLongDateMonthSep(), rString, nPos );
         [ #  # ][ #  # ]
    2057                 :          0 :         SkipBlanks(rString, nPos);
    2058                 :            :     }
    2059                 :            : 
    2060   [ +  -  -  + ]:       1462 :     if (    SkipChar('E', rString, nPos)            // 10E, 10e, 10,Ee
                 [ -  + ]
    2061                 :        731 :          || SkipChar('e', rString, nPos) )
    2062                 :            :     {
    2063         [ #  # ]:          0 :         if (eScannedType != NUMBERFORMAT_UNDEFINED) // already another type
    2064                 :          0 :             return MatchedReturn();
    2065                 :            :         else
    2066                 :            :         {
    2067                 :          0 :             SkipBlanks(rString, nPos);
    2068                 :          0 :             eScannedType = NUMBERFORMAT_SCIENTIFIC; // !!! it IS scientific
    2069 [ #  # ][ #  # ]:          0 :             if (    nThousand+2 == nAnzNums         // special case 1.E2
    2070                 :            :                  && nDecPos == 2 )
    2071                 :          0 :                 nDecPos = 3;                        // 1,100.E2 1,100,100.E3
    2072                 :            :         }
    2073                 :          0 :         nESign = GetESign(rString, nPos);           // signed exponent?
    2074                 :          0 :         SkipBlanks(rString, nPos);
    2075                 :            :     }
    2076                 :            : 
    2077 [ +  - ][ +  - ]:        731 :     const String& rTime = pLoc->getTimeSep();
    2078 [ +  - ][ +  + ]:        731 :     if ( SkipString(rTime, rString, nPos) )         // time separator?
    2079                 :            :     {
    2080         [ -  + ]:         48 :         if (nDecPos)                                // already . => maybe error
    2081                 :            :         {
    2082         [ #  # ]:          0 :             if (bDecSepInDateSeps)                  // . also date sep
    2083                 :            :             {
    2084 [ #  # ][ #  # ]:          0 :                 if (    eScannedType != NUMBERFORMAT_DATE &&    // already another type than date
    2085                 :            :                         eScannedType != NUMBERFORMAT_DATETIME)  // or date time
    2086                 :          0 :                     return MatchedReturn();
    2087         [ #  # ]:          0 :                 if (eScannedType == NUMBERFORMAT_DATE)
    2088                 :          0 :                     nDecPos = 0;                    // reset for time transition
    2089                 :            :             }
    2090                 :            :             else
    2091                 :          0 :                 return MatchedReturn();
    2092                 :            :         }
    2093 [ +  + ][ +  - ]:         48 :         if (   (   eScannedType == NUMBERFORMAT_DATE        // already date type
                 [ +  - ]
    2094                 :            :                 || eScannedType == NUMBERFORMAT_DATETIME)   // or date time
    2095                 :            :             && nAnzNums > 3)                                // and more than 3 numbers? (31.Dez.94 8:23)
    2096                 :            :         {
    2097                 :         48 :             SkipBlanks(rString, nPos);
    2098                 :         48 :             eScannedType = NUMBERFORMAT_DATETIME;   // !!! it IS date with time
    2099                 :            :         }
    2100 [ #  # ][ #  # ]:          0 :         else if (   eScannedType != NUMBERFORMAT_UNDEFINED  // already another type
    2101                 :            :                  && eScannedType != NUMBERFORMAT_TIME)      // except time
    2102                 :          0 :             return MatchedReturn();
    2103                 :            :         else
    2104                 :            :         {
    2105                 :          0 :             SkipBlanks(rString, nPos);
    2106                 :          0 :             eScannedType = NUMBERFORMAT_TIME;       // !!! it IS a time
    2107                 :            :         }
    2108         [ +  + ]:         48 :         if ( !nTimePos )
    2109                 :         24 :             nTimePos = nStringPos + 1;
    2110                 :            :     }
    2111                 :            : 
    2112         [ +  + ]:        731 :     if (nPos < rString.Len())
    2113                 :            :     {
    2114         [ -  + ]:         68 :         switch (eScannedType)
    2115                 :            :         {
    2116                 :            :             case NUMBERFORMAT_DATE:
    2117 [ #  # ][ #  # ]:          0 :                 if (nMonthPos == 1 && pLoc->getLongDateFormat() == MDY)
         [ #  # ][ #  # ]
    2118                 :            :                 {
    2119                 :            :                     // #68232# recognize long date separators like ", " in "September 5, 1999"
    2120 [ #  # ][ #  # ]:          0 :                     if (SkipString( pLoc->getLongDateDaySep(), rString, nPos ))
         [ #  # ][ #  # ]
                 [ #  # ]
    2121                 :          0 :                         SkipBlanks( rString, nPos );
    2122                 :            :                 }
    2123 [ #  # ][ #  # ]:          0 :                 else if (nStringPos == 5 && nPos == 0 && rString.Len() == 1 &&
           [ #  #  #  # ]
         [ #  # ][ #  # ]
    2124         [ #  # ]:          0 :                         rString.GetChar(0) == 'T' && MayBeIso8601())
    2125                 :            :                 {
    2126                 :            :                     // ISO 8601 combined date and time, yyyy-mm-ddThh:mm
    2127                 :          0 :                     ++nPos;
    2128                 :            :                 }
    2129                 :         68 :                 break;
    2130                 :            : #if NF_RECOGNIZE_ISO8601_TIMEZONES
    2131                 :            :             case NUMBERFORMAT_DATETIME:
    2132                 :            :                 if (nPos == 0 && rString.Len() == 1 && nStringPos >= 9 &&
    2133                 :            :                         MayBeIso8601())
    2134                 :            :                 {
    2135                 :            :                     // ISO 8601 timezone offset
    2136                 :            :                     switch (rString.GetChar(0))
    2137                 :            :                     {
    2138                 :            :                         case '+':
    2139                 :            :                         case '-':
    2140                 :            :                             if (nStringPos == nAnzStrings-2 ||
    2141                 :            :                                     nStringPos == nAnzStrings-4)
    2142                 :            :                             {
    2143                 :            :                                 ++nPos;     // yyyy-mm-ddThh:mm[:ss]+xx[[:]yy]
    2144                 :            :                                 // nTimezonePos needed for GetTimeRef()
    2145                 :            :                                 if (!nTimezonePos)
    2146                 :            :                                     nTimezonePos = nStringPos + 1;
    2147                 :            :                             }
    2148                 :            :                             break;
    2149                 :            :                         case ':':
    2150                 :            :                             if (nTimezonePos && nStringPos >= 11 &&
    2151                 :            :                                     nStringPos == nAnzStrings-2)
    2152                 :            :                                 ++nPos;     // yyyy-mm-ddThh:mm[:ss]+xx:yy
    2153                 :            :                             break;
    2154                 :            :                     }
    2155                 :            :                 }
    2156                 :            :                 break;
    2157                 :            : #endif
    2158                 :            :         }
    2159                 :            :     }
    2160                 :            : 
    2161         [ +  + ]:        731 :     if (nPos < rString.Len())                       // not everything consumed?
    2162                 :            :     {
    2163         [ -  + ]:         68 :         if ( nMatchedAllStrings & ~nMatchedVirgin )
    2164                 :          0 :             eScannedType = eOldScannedType;
    2165                 :            :         else
    2166                 :         68 :             return false;
    2167                 :            :     }
    2168                 :            : 
    2169         [ +  - ]:        752 :     return true;
    2170                 :            : }
    2171                 :            : 
    2172                 :            : 
    2173                 :            : //---------------------------------------------------------------------------
    2174                 :            : //      ScanEndString
    2175                 :            : //
    2176                 :            : // Schlussteil analysieren
    2177                 :            : // Alles weg => true
    2178                 :            : // sonst     => false
    2179                 :            : 
    2180                 :          9 : bool ImpSvNumberInputScan::ScanEndString( const String& rString,
    2181                 :            :         const SvNumberformat* pFormat )
    2182                 :            : {
    2183                 :          9 :     xub_StrLen nPos = 0;
    2184                 :            : 
    2185         [ +  + ]:          9 :     if ( nMatchedAllStrings )
    2186                 :            :     {   // Match against format in any case, so later on for a "1-2-3-4" input
    2187                 :            :         // we may distinguish between a y-m-d (or similar) date and a 0-0-0-0
    2188                 :            :         // format.
    2189 [ +  - ][ -  + ]:          3 :         if ( ScanStringNumFor( rString, 0, pFormat, 0xFFFF ) )
    2190                 :          0 :             nMatchedAllStrings |= nMatchedEndString;
    2191                 :            :         else
    2192                 :          3 :             nMatchedAllStrings = 0;
    2193                 :            :     }
    2194                 :            : 
    2195                 :          9 :     SkipBlanks(rString, nPos);
    2196 [ -  + ][ +  - ]:          9 :     if (GetDecSep(rString, nPos))                   // decimal separator?
    2197                 :            :     {
    2198 [ #  # ][ #  # ]:          0 :         if (nDecPos == 1 || nDecPos == 3)           // .12.4 or 12.E4.
    2199                 :          0 :             return MatchedReturn();
    2200         [ #  # ]:          0 :         else if (nDecPos == 2)                      // . dup: 12.4.
    2201                 :            :         {
    2202 [ #  # ][ #  # ]:          0 :             if (bDecSepInDateSeps                   // . also date separator
                 [ #  # ]
    2203         [ #  # ]:          0 :                     || SkipDatePatternSeparator( nAnzStrings-1, nPos))
    2204                 :            :             {
    2205 [ #  # ][ #  # ]:          0 :                 if (    eScannedType != NUMBERFORMAT_UNDEFINED &&
                 [ #  # ]
    2206                 :            :                         eScannedType != NUMBERFORMAT_DATE &&
    2207                 :            :                         eScannedType != NUMBERFORMAT_DATETIME)  // already another type
    2208                 :          0 :                     return MatchedReturn();
    2209         [ #  # ]:          0 :                 if (eScannedType == NUMBERFORMAT_UNDEFINED)
    2210                 :          0 :                     eScannedType = NUMBERFORMAT_DATE;   // !!! it IS a date
    2211                 :          0 :                 SkipBlanks(rString, nPos);
    2212                 :            :             }
    2213                 :            :             else
    2214                 :          0 :                 return MatchedReturn();
    2215                 :            :         }
    2216                 :            :         else
    2217                 :            :         {
    2218                 :          0 :             nDecPos = 3;                            // . in end string
    2219                 :          0 :             SkipBlanks(rString, nPos);
    2220                 :            :         }
    2221                 :            :     }
    2222                 :            : 
    2223 [ +  - ][ +  - ]:          9 :     if (   nSign == 0                               // conflict - not signed
    2224                 :            :         && eScannedType != NUMBERFORMAT_DATE)       // and not date
    2225                 :            : //!? catch time too?
    2226                 :            :     {                                               // not signed yet
    2227                 :          9 :         nSign = GetSign(rString, nPos);             // 1- DM
    2228         [ -  + ]:          9 :         if (nNegCheck)                              // '(' as sign
    2229                 :          0 :             return MatchedReturn();
    2230                 :            :     }
    2231                 :            : 
    2232                 :          9 :     SkipBlanks(rString, nPos);
    2233 [ #  # ][ -  + ]:          9 :     if (nNegCheck && SkipChar(')', rString, nPos))  // skip ')' if appropriate
                 [ -  + ]
    2234                 :            :     {
    2235                 :          0 :         nNegCheck = 0;
    2236                 :          0 :         SkipBlanks(rString, nPos);
    2237                 :            :     }
    2238                 :            : 
    2239 [ +  - ][ -  + ]:          9 :     if ( GetCurrency(rString, nPos, pFormat) )      // currency symbol?
    2240                 :            :     {
    2241         [ #  # ]:          0 :         if (eScannedType != NUMBERFORMAT_UNDEFINED) // currency dup
    2242                 :          0 :             return MatchedReturn();
    2243                 :            :         else
    2244                 :            :         {
    2245                 :          0 :             SkipBlanks(rString, nPos);
    2246                 :          0 :             eScannedType = NUMBERFORMAT_CURRENCY;
    2247                 :            :         }                                           // behind currency a '-' is allowed
    2248         [ #  # ]:          0 :         if (nSign == 0)                             // not signed yet
    2249                 :            :         {
    2250                 :          0 :             nSign = GetSign(rString, nPos);         // DM -
    2251                 :          0 :             SkipBlanks(rString, nPos);
    2252         [ #  # ]:          0 :             if (nNegCheck)                          // 3 DM (
    2253                 :          0 :                 return MatchedReturn();
    2254                 :            :         }
    2255         [ #  # ]:          0 :         if ( nNegCheck && eScannedType == NUMBERFORMAT_CURRENCY
           [ #  #  #  # ]
                 [ #  # ]
    2256                 :          0 :                        && SkipChar(')', rString, nPos) )
    2257                 :            :         {
    2258                 :          0 :             nNegCheck = 0;                          // ')' skipped
    2259                 :          0 :             SkipBlanks(rString, nPos);              // only if currency
    2260                 :            :         }
    2261                 :            :     }
    2262                 :            : 
    2263         [ -  + ]:          9 :     if ( SkipChar('%', rString, nPos) )             // 1 %
    2264                 :            :     {
    2265         [ #  # ]:          0 :         if (eScannedType != NUMBERFORMAT_UNDEFINED) // already another type
    2266                 :          0 :             return MatchedReturn();
    2267                 :          0 :         SkipBlanks(rString, nPos);
    2268                 :          0 :         eScannedType = NUMBERFORMAT_PERCENT;
    2269                 :            :     }
    2270                 :            : 
    2271                 :          9 :     const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
    2272 [ +  - ][ +  - ]:          9 :     const String& rTime = pLoc->getTimeSep();
    2273 [ +  - ][ -  + ]:          9 :     if ( SkipString(rTime, rString, nPos) )         // 10:
    2274                 :            :     {
    2275         [ #  # ]:          0 :         if (nDecPos)                                // already , => error
    2276                 :          0 :             return MatchedReturn();
    2277 [ #  # ][ #  # ]:          0 :         if (eScannedType == NUMBERFORMAT_DATE && nAnzNums > 2) // 31.Dez.94 8:
    2278                 :            :         {
    2279                 :          0 :             SkipBlanks(rString, nPos);
    2280                 :          0 :             eScannedType = NUMBERFORMAT_DATETIME;
    2281                 :            :         }
    2282 [ #  # ][ #  # ]:          0 :         else if (eScannedType != NUMBERFORMAT_UNDEFINED &&
    2283                 :            :                  eScannedType != NUMBERFORMAT_TIME) // already another type
    2284                 :          0 :             return MatchedReturn();
    2285                 :            :         else
    2286                 :            :         {
    2287                 :          0 :             SkipBlanks(rString, nPos);
    2288                 :          0 :             eScannedType = NUMBERFORMAT_TIME;
    2289                 :            :         }
    2290         [ #  # ]:          0 :         if ( !nTimePos )
    2291                 :          0 :             nTimePos = nAnzStrings;
    2292                 :            :     }
    2293                 :            : 
    2294         [ +  - ]:          9 :     bool bDate = SkipDatePatternSeparator( nAnzStrings-1, nPos);   // 12/31  31.12.  12/31/1999  31.12.1999
    2295         [ +  - ]:          9 :     if (!bDate)
    2296                 :            :     {
    2297                 :          9 :         const String& rDate = pFormatter->GetDateSep();
    2298         [ +  - ]:          9 :         bDate = SkipString( rDate, rString, nPos);      // 10.  10-  10/
    2299                 :            :     }
    2300 [ +  - ][ +  - ]:         27 :     if (bDate
           [ -  +  #  # ]
                 [ -  + ]
    2301 [ +  - ][ +  - ]:         18 :             || ((MayBeIso8601() || MayBeMonthDate())
    2302                 :          0 :                 && SkipChar( '-', rString, nPos)))
    2303                 :            :     {
    2304 [ #  # ][ #  # ]:          0 :         if (eScannedType != NUMBERFORMAT_UNDEFINED &&
    2305                 :            :             eScannedType != NUMBERFORMAT_DATE)          // already another type
    2306                 :          0 :             return MatchedReturn();
    2307                 :            :         else
    2308                 :            :         {
    2309                 :          0 :             SkipBlanks(rString, nPos);
    2310                 :          0 :             eScannedType = NUMBERFORMAT_DATE;
    2311                 :            :         }
    2312         [ #  # ]:          0 :         short nTmpMonth = GetMonth(rString, nPos);  // 10. Jan
    2313 [ #  # ][ #  # ]:          0 :         if (nMonth && nTmpMonth)                    // month dup
    2314                 :          0 :             return MatchedReturn();
    2315         [ #  # ]:          0 :         if (nTmpMonth)
    2316                 :            :         {
    2317                 :          0 :             nMonth = nTmpMonth;
    2318                 :          0 :             nMonthPos = 3;                          // month at end
    2319         [ #  # ]:          0 :             if ( nMonth < 0 )
    2320                 :          0 :                 SkipChar( '.', rString, nPos );     // abbreviated
    2321                 :          0 :             SkipBlanks(rString, nPos);
    2322                 :            :         }
    2323                 :            :     }
    2324                 :            : 
    2325         [ +  - ]:          9 :     short nTempMonth = GetMonth(rString, nPos);     // 10 Jan
    2326         [ -  + ]:          9 :     if (nTempMonth)
    2327                 :            :     {
    2328         [ #  # ]:          0 :         if (nMonth)                                 // month dup
    2329                 :          0 :             return MatchedReturn();
    2330 [ #  # ][ #  # ]:          0 :         if (eScannedType != NUMBERFORMAT_UNDEFINED &&
    2331                 :            :             eScannedType != NUMBERFORMAT_DATE)      // already another type
    2332                 :          0 :             return MatchedReturn();
    2333                 :          0 :         eScannedType = NUMBERFORMAT_DATE;
    2334                 :          0 :         nMonth = nTempMonth;
    2335                 :          0 :         nMonthPos = 3;                              // month at end
    2336         [ #  # ]:          0 :         if ( nMonth < 0 )
    2337                 :          0 :             SkipChar( '.', rString, nPos );         // abbreviated
    2338                 :          0 :         SkipBlanks(rString, nPos);
    2339                 :            :     }
    2340                 :            : 
    2341                 :          9 :     xub_StrLen nOrigPos = nPos;
    2342 [ +  - ][ -  + ]:          9 :     if (GetTimeAmPm(rString, nPos))
    2343                 :            :     {
    2344 [ #  # ][ #  # ]:          0 :         if (eScannedType != NUMBERFORMAT_UNDEFINED &&
                 [ #  # ]
    2345                 :            :             eScannedType != NUMBERFORMAT_TIME &&
    2346                 :            :             eScannedType != NUMBERFORMAT_DATETIME)  // already another type
    2347                 :          0 :             return MatchedReturn();
    2348                 :            :         else
    2349                 :            :         {
    2350                 :            :             // If not already scanned as time, 6.78am does not result in 6
    2351                 :            :             // seconds and 78 hundredths in the morning. Keep as suffix.
    2352 [ #  # ][ #  # ]:          0 :             if (eScannedType != NUMBERFORMAT_TIME && nDecPos == 2 && nAnzNums == 2)
                 [ #  # ]
    2353                 :          0 :                 nPos = nOrigPos;     // rewind am/pm
    2354                 :            :             else
    2355                 :            :             {
    2356                 :          0 :                 SkipBlanks(rString, nPos);
    2357         [ #  # ]:          0 :                 if ( eScannedType != NUMBERFORMAT_DATETIME )
    2358                 :          0 :                     eScannedType = NUMBERFORMAT_TIME;
    2359                 :            :             }
    2360                 :            :         }
    2361                 :            :     }
    2362                 :            : 
    2363 [ -  + ][ #  # ]:          9 :     if ( nNegCheck && SkipChar(')', rString, nPos) )
                 [ -  + ]
    2364                 :            :     {
    2365         [ #  # ]:          0 :         if (eScannedType == NUMBERFORMAT_CURRENCY)  // only if currency
    2366                 :            :         {
    2367                 :          0 :             nNegCheck = 0;                          // skip ')'
    2368                 :          0 :             SkipBlanks(rString, nPos);
    2369                 :            :         }
    2370                 :            :         else
    2371                 :          0 :             return MatchedReturn();
    2372                 :            :     }
    2373                 :            : 
    2374 [ +  + ][ +  - ]:          9 :     if ( nPos < rString.Len() &&
         [ -  + ][ -  + ]
    2375                 :            :             (eScannedType == NUMBERFORMAT_DATE
    2376                 :            :             || eScannedType == NUMBERFORMAT_DATETIME) )
    2377                 :            :     {   // day of week is just parsed away
    2378                 :          0 :         xub_StrLen nOldPos = nPos;
    2379 [ #  # ][ #  # ]:          0 :         const String& rSep = pFormatter->GetLocaleData()->getLongDateDayOfWeekSep();
    2380 [ #  # ][ #  # ]:          0 :         if ( StringContains( rSep, rString, nPos ) )
    2381                 :            :         {
    2382                 :          0 :             nPos = nPos + rSep.Len();
    2383                 :          0 :             SkipBlanks(rString, nPos);
    2384                 :            :         }
    2385         [ #  # ]:          0 :         int nDayOfWeek = GetDayOfWeek( rString, nPos );
    2386         [ #  # ]:          0 :         if ( nDayOfWeek )
    2387                 :            :         {
    2388         [ #  # ]:          0 :             if ( nPos < rString.Len() )
    2389                 :            :             {
    2390         [ #  # ]:          0 :                 if ( nDayOfWeek < 0 )
    2391                 :            :                 {   // short
    2392         [ #  # ]:          0 :                     if ( rString.GetChar( nPos ) == '.' )
    2393                 :          0 :                         ++nPos;
    2394                 :            :                 }
    2395                 :          0 :                 SkipBlanks(rString, nPos);
    2396                 :            :             }
    2397                 :            :         }
    2398                 :            :         else
    2399         [ #  # ]:          0 :             nPos = nOldPos;
    2400                 :            :     }
    2401                 :            : 
    2402                 :            : #if NF_RECOGNIZE_ISO8601_TIMEZONES
    2403                 :            :     if (nPos == 0 && eScannedType == NUMBERFORMAT_DATETIME &&
    2404                 :            :             rString.Len() == 1 && rString.GetChar(0) == 'Z' && MayBeIso8601())
    2405                 :            :     {
    2406                 :            :         // ISO 8601 timezone UTC yyyy-mm-ddThh:mmZ
    2407                 :            :         ++nPos;
    2408                 :            :     }
    2409                 :            : #endif
    2410                 :            : 
    2411         [ +  + ]:          9 :     if (nPos < rString.Len())                       // everything consumed?
    2412                 :            :     {
    2413                 :            :         // does input EndString equal EndString in Format?
    2414 [ +  - ][ +  - ]:          3 :         if ( !ScanStringNumFor( rString, nPos, pFormat, 0xFFFF ) )
    2415                 :          3 :             return false;
    2416                 :            :     }
    2417                 :            : 
    2418         [ +  - ]:          9 :     return true;
    2419                 :            : }
    2420                 :            : 
    2421                 :            : 
    2422                 :       2421 : bool ImpSvNumberInputScan::ScanStringNumFor(
    2423                 :            :         const String& rString,          // String to scan
    2424                 :            :         xub_StrLen nPos,                // Position until which was consumed
    2425                 :            :         const SvNumberformat* pFormat,  // The format to match
    2426                 :            :         sal_uInt16 nString,                 // Substring of format, 0xFFFF => last
    2427                 :            :         bool bDontDetectNegation        // Suppress sign detection
    2428                 :            :         )
    2429                 :            : {
    2430         [ +  + ]:       2421 :     if ( !pFormat )
    2431                 :         32 :         return false;
    2432         [ +  - ]:       2389 :     const ::utl::TransliterationWrapper* pTransliteration = pFormatter->GetTransliteration();
    2433                 :            :     const String* pStr;
    2434         [ +  - ]:       2389 :     rtl::OUString aString( rString );
    2435                 :       2389 :     bool bFound = false;
    2436                 :       2389 :     bool bFirst = true;
    2437                 :       2389 :     bool bContinue = true;
    2438                 :            :     sal_uInt16 nSub;
    2439         [ +  + ]:       2415 :     do
    2440                 :            :     {
    2441                 :            :         // Don't try "lower" subformats ff the very first match was the second
    2442                 :            :         // or third subformat.
    2443                 :       2415 :         nSub = nStringScanNumFor;
    2444         [ +  + ]:       7245 :         do
    2445                 :            :         {   // Step through subformats, first positive, then negative, then
    2446                 :            :             // other, but not the last (text) subformat.
    2447         [ +  - ]:       7245 :             pStr = pFormat->GetNumForString( nSub, nString, true );
    2448 [ +  + ][ +  - ]:       7245 :             if ( pStr && pTransliteration->isEqual( aString, *pStr ) )
         [ +  - ][ -  + ]
         [ +  + ][ +  - ]
           [ -  +  #  # ]
    2449                 :            :             {
    2450                 :          0 :                 bFound = true;
    2451                 :          0 :                 bContinue = false;
    2452                 :            :             }
    2453         [ +  + ]:       7245 :             else if ( nSub < 2 )
    2454                 :       4830 :                 ++nSub;
    2455                 :            :             else
    2456                 :       2415 :                 bContinue = false;
    2457                 :            :         } while ( bContinue );
    2458 [ +  - ][ +  + ]:       2415 :         if ( !bFound && bFirst && nPos )
                 [ +  + ]
    2459                 :            :         {   // try remaining substring
    2460                 :         26 :             bFirst = false;
    2461                 :         26 :             aString = aString.copy(nPos);
    2462                 :         26 :             bContinue = true;
    2463                 :            :         }
    2464                 :            :     } while ( bContinue );
    2465                 :            : 
    2466         [ +  - ]:       2389 :     if ( !bFound )
    2467                 :            :     {
    2468 [ +  + ][ +  + ]:       2389 :         if ( !bDontDetectNegation && (nString == 0) && !bFirst && (nSign < 0)
                 [ +  + ]
           [ -  +  #  # ]
                 [ -  + ]
    2469                 :          0 :                 && pFormat->IsNegativeRealNegative() )
    2470                 :            :         {   // simply negated twice? --1
    2471                 :          0 :             aString = comphelper::string::remove(aString, ' ');
    2472 [ #  # ][ #  # ]:          0 :             if ( (aString.getLength() == 1) && (aString[0] == '-') )
                 [ #  # ]
    2473                 :            :             {
    2474                 :          0 :                 bFound = true;
    2475                 :          0 :                 nStringScanSign = -1;
    2476                 :          0 :                 nSub = 0;       //! not 1
    2477                 :            :             }
    2478                 :            :         }
    2479         [ +  - ]:       2389 :         if ( !bFound )
    2480                 :       2389 :             return false;
    2481                 :            :     }
    2482         [ #  # ]:          0 :     else if ( !bDontDetectNegation && (nSub == 1) &&
           [ #  #  #  # ]
                 [ #  # ]
    2483                 :          0 :             pFormat->IsNegativeRealNegative() )
    2484                 :            :     {   // negative
    2485         [ #  # ]:          0 :         if ( nStringScanSign < 0 )
    2486                 :            :         {
    2487 [ #  # ][ #  # ]:          0 :             if ( (nSign < 0) && (nStringScanNumFor != 1) )
    2488                 :          0 :                 nStringScanSign = 1;        // triple negated --1 yyy
    2489                 :            :         }
    2490         [ #  # ]:          0 :         else if ( nStringScanSign == 0 )
    2491                 :            :         {
    2492         [ #  # ]:          0 :             if ( nSign < 0 )
    2493                 :            :             {   // nSign and nStringScanSign will be combined later,
    2494                 :            :                 // flip sign if doubly negated
    2495 [ #  # ][ #  # ]:          0 :                 if ( (nString == 0) && !bFirst
         [ #  # ][ #  # ]
    2496 [ #  # ][ #  # ]:          0 :                         && SvNumberformat::HasStringNegativeSign( aString ) )
         [ #  # ][ #  # ]
                 [ #  # ]
    2497                 :          0 :                     nStringScanSign = -1;   // direct double negation
    2498 [ #  # ][ #  # ]:          0 :                 else if ( pFormat->IsNegativeWithoutSign() )
    2499                 :          0 :                     nStringScanSign = -1;   // indirect double negation
    2500                 :            :             }
    2501                 :            :             else
    2502                 :          0 :                 nStringScanSign = -1;
    2503                 :            :         }
    2504                 :            :         else    // > 0
    2505                 :          0 :             nStringScanSign = -1;
    2506                 :            :     }
    2507                 :          0 :     nStringScanNumFor = nSub;
    2508                 :       2421 :     return true;
    2509                 :            : }
    2510                 :            : 
    2511                 :            : 
    2512                 :            : //---------------------------------------------------------------------------
    2513                 :            : //      IsNumberFormatMain
    2514                 :            : //
    2515                 :            : // Recognizes types of number, exponential, fraction, percent, currency, date, time.
    2516                 :            : // Else text => return false
    2517                 :            : 
    2518                 :       6757 : bool ImpSvNumberInputScan::IsNumberFormatMain(
    2519                 :            :         const String& rString,                  // string to be analyzed
    2520                 :            :         const SvNumberformat* pFormat )         // maybe number format set to match against
    2521                 :            : {
    2522                 :       6757 :     Reset();
    2523         [ +  - ]:       6757 :     NumberStringDivision( rString );            // breakdown into strings and numbers
    2524         [ -  + ]:       6757 :     if (nAnzStrings >= SV_MAX_ANZ_INPUT_STRINGS) // too many elements
    2525                 :          0 :         return false;                           // Njet, Nope, ...
    2526                 :            : 
    2527         [ +  + ]:       6757 :     if (nAnzNums == 0)                          // no number in input
    2528                 :            :     {
    2529         [ +  - ]:       2668 :         if ( nAnzStrings > 0 )
    2530                 :            :         {
    2531                 :            :             // Here we may change the original, we don't need it anymore.
    2532                 :            :             // This saves copies and ToUpper() in GetLogical() and is faster.
    2533 [ +  - ][ +  - ]:       2668 :             sStrArray[0] = comphelper::string::strip(sStrArray[0], ' ');
                 [ +  - ]
    2534                 :       2668 :             String& rStrArray = sStrArray[0];
    2535         [ +  - ]:       2668 :             nLogical = GetLogical( rStrArray );
    2536         [ -  + ]:       2668 :             if ( nLogical )
    2537                 :            :             {
    2538                 :          0 :                 eScannedType = NUMBERFORMAT_LOGICAL; // !!! it's a BOOLEAN
    2539                 :          0 :                 nMatchedAllStrings &= ~nMatchedVirgin;
    2540                 :          0 :                 return true;
    2541                 :            :             }
    2542                 :            :             else
    2543                 :       2668 :                 return false;                   // simple text
    2544                 :            :         }
    2545                 :            :         else
    2546                 :          0 :             return false;                       // simple text
    2547                 :            :     }
    2548                 :            : 
    2549                 :       4089 :     sal_uInt16 i = 0;                               // mark any symbol
    2550                 :       4089 :     sal_uInt16 j = 0;                               // mark only numbers
    2551                 :            : 
    2552   [ +  +  +  + ]:       4089 :     switch ( nAnzNums )
    2553                 :            :     {
    2554                 :            :         case 1 :                                // Exactly 1 number in input
    2555                 :            :         {                                       // nAnzStrings >= 1
    2556         [ +  + ]:       3542 :             if (GetNextNumber(i,j))             // i=1,0
    2557                 :            :             {                                   // Number at start
    2558         [ -  + ]:       2626 :                 if (eSetType == NUMBERFORMAT_FRACTION)  // Fraction 1 = 1/1
    2559                 :            :                 {
    2560 [ #  # ][ #  # ]:          0 :                     if (i >= nAnzStrings ||     // no end string nor decimal separator
                 [ #  # ]
    2561         [ #  # ]:          0 :                         sStrArray[i] == pFormatter->GetNumDecimalSep())
    2562                 :            :                     {
    2563                 :          0 :                         eScannedType = NUMBERFORMAT_FRACTION;
    2564                 :          0 :                         nMatchedAllStrings &= ~nMatchedVirgin;
    2565                 :          0 :                         return true;
    2566                 :            :                     }
    2567                 :            :                 }
    2568                 :            :             }
    2569                 :            :             else
    2570                 :            :             {                                   // Analyze start string
    2571 [ +  - ][ +  + ]:        916 :                 if (!ScanStartString( sStrArray[i], pFormat ))  // i=0
    2572                 :        906 :                     return false;               // already an error
    2573                 :         10 :                 i++;                            // next symbol, i=1
    2574                 :            :             }
    2575                 :       2636 :             GetNextNumber(i,j);                 // i=1,2
    2576         [ -  + ]:       2636 :             if (eSetType == NUMBERFORMAT_FRACTION)  // Fraction -1 = -1/1
    2577                 :            :             {
    2578 [ #  # ][ #  # ]:          0 :                 if (nSign && !nNegCheck &&      // Sign +, -
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2579                 :            :                     eScannedType == NUMBERFORMAT_UNDEFINED &&   // not date or currency
    2580                 :            :                     nDecPos == 0 &&             // no previous decimal separator
    2581                 :            :                     (i >= nAnzStrings ||        // no end string nor decimal separator
    2582         [ #  # ]:          0 :                         sStrArray[i] == pFormatter->GetNumDecimalSep())
    2583                 :            :                 )
    2584                 :            :                 {
    2585                 :          0 :                     eScannedType = NUMBERFORMAT_FRACTION;
    2586                 :          0 :                     nMatchedAllStrings &= ~nMatchedVirgin;
    2587                 :          0 :                     return true;
    2588                 :            :                 }
    2589                 :            :             }
    2590 [ +  + ][ +  - ]:       2636 :             if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat ))
         [ +  + ][ +  + ]
    2591                 :          3 :                     return false;
    2592                 :            :         }
    2593                 :       2633 :         break;
    2594                 :            :         case 2 :                                // Exactly 2 numbers in input
    2595                 :            :         {                                       // nAnzStrings >= 3
    2596         [ +  + ]:        296 :             if (!GetNextNumber(i,j))            // i=1,0
    2597                 :            :             {                                   // Analyze start string
    2598 [ +  - ][ +  + ]:         65 :                 if (!ScanStartString( sStrArray[i], pFormat ))
    2599                 :         41 :                     return false;               // already an error
    2600                 :         24 :                 i++;                            // i=1
    2601                 :            :             }
    2602                 :        255 :             GetNextNumber(i,j);                 // i=1,2
    2603 [ +  + ][ +  - ]:        255 :             if ( !ScanMidString( sStrArray[i], i, pFormat ) )
    2604                 :          9 :                 return false;
    2605                 :        246 :             i++;                                // next symbol, i=2,3
    2606                 :        246 :             GetNextNumber(i,j);                 // i=3,4
    2607 [ #  # ][ #  # ]:        246 :             if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat ))
         [ -  + ][ -  + ]
    2608                 :          0 :                 return false;
    2609         [ -  + ]:        246 :             if (eSetType == NUMBERFORMAT_FRACTION)  // -1,200. as fraction
    2610                 :            :             {
    2611 [ #  # ][ #  # ]:          0 :                 if (!nNegCheck  &&                  // no sign '('
         [ #  # ][ #  # ]
    2612                 :            :                     eScannedType == NUMBERFORMAT_UNDEFINED &&
    2613                 :            :                     (nDecPos == 0 || nDecPos == 3)  // no decimal separator or at end
    2614                 :            :                     )
    2615                 :            :                 {
    2616                 :          0 :                     eScannedType = NUMBERFORMAT_FRACTION;
    2617                 :          0 :                     nMatchedAllStrings &= ~nMatchedVirgin;
    2618                 :          0 :                     return true;
    2619                 :            :                 }
    2620                 :            :             }
    2621                 :            :         }
    2622                 :        246 :         break;
    2623                 :            :         case 3 :                                // Exactly 3 numbers in input
    2624                 :            :         {                                       // nAnzStrings >= 5
    2625         [ +  + ]:        200 :             if (!GetNextNumber(i,j))            // i=1,0
    2626                 :            :             {                                   // Analyze start string
    2627 [ +  - ][ +  - ]:          9 :                 if (!ScanStartString( sStrArray[i], pFormat ))
    2628                 :          9 :                     return false;               // already an error
    2629                 :          0 :                 i++;                            // i=1
    2630         [ #  # ]:          0 :                 if (nDecPos == 1)               // decimal separator at start => error
    2631                 :          0 :                     return false;
    2632                 :            :             }
    2633                 :        191 :             GetNextNumber(i,j);                 // i=1,2
    2634 [ +  + ][ +  - ]:        191 :             if ( !ScanMidString( sStrArray[i], i, pFormat ) )
    2635                 :         32 :                 return false;
    2636                 :        159 :             i++;                                // i=2,3
    2637         [ -  + ]:        159 :             if (eScannedType == NUMBERFORMAT_SCIENTIFIC)    // E only at end
    2638                 :          0 :                 return false;
    2639                 :        159 :             GetNextNumber(i,j);                 // i=3,4
    2640 [ +  + ][ +  - ]:        159 :             if ( !ScanMidString( sStrArray[i], i, pFormat ) )
    2641                 :         21 :                 return false;
    2642                 :        138 :             i++;                                // i=4,5
    2643                 :        138 :             GetNextNumber(i,j);                 // i=5,6
    2644 [ #  # ][ #  # ]:        138 :             if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat ))
         [ -  + ][ -  + ]
    2645                 :          0 :                 return false;
    2646         [ -  + ]:        138 :             if (eSetType == NUMBERFORMAT_FRACTION)  // -1,200,100. as fraction
    2647                 :            :             {
    2648 [ #  # ][ #  # ]:          0 :                 if (!nNegCheck  &&                  // no sign '('
         [ #  # ][ #  # ]
    2649                 :            :                     eScannedType == NUMBERFORMAT_UNDEFINED &&
    2650                 :            :                     (nDecPos == 0 || nDecPos == 3)  // no decimal separator or at end
    2651                 :            :                 )
    2652                 :            :                 {
    2653                 :          0 :                     eScannedType = NUMBERFORMAT_FRACTION;
    2654                 :          0 :                     nMatchedAllStrings &= ~nMatchedVirgin;
    2655                 :          0 :                     return true;
    2656                 :            :                 }
    2657                 :            :             }
    2658 [ -  + ][ #  # ]:        138 :             if ( eScannedType == NUMBERFORMAT_FRACTION && nDecPos )
    2659                 :          0 :                 return false;                   // #36857# not a real fraction
    2660                 :            :         }
    2661                 :        138 :         break;
    2662                 :            :         default:                                // More than 3 numbers in input
    2663                 :            :         {                                       // nAnzStrings >= 7
    2664         [ -  + ]:         51 :             if (!GetNextNumber(i,j))            // i=1,0
    2665                 :            :             {                                   // Analyze startstring
    2666 [ #  # ][ #  # ]:          0 :                 if (!ScanStartString( sStrArray[i], pFormat ))
    2667                 :          0 :                     return false;               // already an error
    2668                 :          0 :                 i++;                            // i=1
    2669         [ #  # ]:          0 :                 if (nDecPos == 1)               // decimal separator at start => error
    2670                 :          0 :                     return false;
    2671                 :            :             }
    2672                 :         51 :             GetNextNumber(i,j);                 // i=1,2
    2673 [ +  + ][ +  - ]:         51 :             if ( !ScanMidString( sStrArray[i], i, pFormat ) )
    2674                 :         27 :                 return false;
    2675                 :         24 :             i++;                                // i=2,3
    2676                 :         24 :             sal_uInt16 nThOld = 10;                 // just not 0 or 1
    2677 [ +  + ][ +  - ]:         48 :             while (nThOld != nThousand && j < nAnzNums-1)
                 [ +  + ]
    2678                 :            :                                                 // Execute at least one time
    2679                 :            :                                                 // but leave one number.
    2680                 :            :             {                                   // Loop over group separators
    2681                 :         24 :                 nThOld = nThousand;
    2682         [ -  + ]:         24 :                 if (eScannedType == NUMBERFORMAT_SCIENTIFIC)    // E only at end
    2683                 :          0 :                     return false;
    2684                 :         24 :                 GetNextNumber(i,j);
    2685 [ +  - ][ -  + ]:         24 :                 if ( i < nAnzStrings && !ScanMidString( sStrArray[i], i, pFormat ) )
         [ -  + ][ +  - ]
    2686                 :          0 :                     return false;
    2687                 :         24 :                 i++;
    2688                 :            :             }
    2689 [ -  + ][ #  # ]:         24 :             if (eScannedType == NUMBERFORMAT_DATE ||    // long date or
                 [ #  # ]
    2690                 :            :                 eScannedType == NUMBERFORMAT_TIME ||    // long time or
    2691                 :            :                 eScannedType == NUMBERFORMAT_UNDEFINED) // long number
    2692                 :            :             {
    2693         [ +  + ]:         96 :                 for (sal_uInt16 k = j; k < nAnzNums-1; k++)
    2694                 :            :                 {
    2695         [ -  + ]:         72 :                     if (eScannedType == NUMBERFORMAT_SCIENTIFIC)    // E only at endd
    2696                 :          0 :                         return false;
    2697                 :         72 :                     GetNextNumber(i,j);
    2698 [ +  - ][ -  + ]:         72 :                     if ( i < nAnzStrings && !ScanMidString( sStrArray[i], i, pFormat ) )
         [ -  + ][ +  - ]
    2699                 :          0 :                         return false;
    2700                 :         72 :                     i++;
    2701                 :            :                 }
    2702                 :            :             }
    2703                 :         24 :             GetNextNumber(i,j);
    2704 [ #  # ][ #  # ]:         24 :             if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat ))
         [ -  + ][ -  + ]
    2705                 :          0 :                 return false;
    2706         [ -  + ]:         24 :             if (eSetType == NUMBERFORMAT_FRACTION)  // -1,200,100. as fraction
    2707                 :            :             {
    2708 [ #  # ][ #  # ]:          0 :                 if (!nNegCheck  &&                  // no sign '('
         [ #  # ][ #  # ]
    2709                 :            :                     eScannedType == NUMBERFORMAT_UNDEFINED &&
    2710                 :            :                     (nDecPos == 0 || nDecPos == 3)  // no decimal separator or at end
    2711                 :            :                 )
    2712                 :            :                 {
    2713                 :          0 :                     eScannedType = NUMBERFORMAT_FRACTION;
    2714                 :          0 :                     nMatchedAllStrings &= ~nMatchedVirgin;
    2715                 :          0 :                     return true;
    2716                 :            :                 }
    2717                 :            :             }
    2718 [ -  + ][ #  # ]:         24 :             if ( eScannedType == NUMBERFORMAT_FRACTION && nDecPos )
    2719                 :          0 :                 return false;                       // #36857# not a real fraction
    2720                 :            :         }
    2721                 :            :     }
    2722                 :            : 
    2723         [ +  + ]:       3041 :     if (eScannedType == NUMBERFORMAT_UNDEFINED)
    2724                 :            :     {
    2725                 :       2865 :         nMatchedAllStrings &= ~nMatchedVirgin;
    2726                 :            :         // did match including nMatchedUsedAsReturn
    2727                 :       2865 :         bool bDidMatch = (nMatchedAllStrings != 0);
    2728         [ -  + ]:       2865 :         if ( nMatchedAllStrings )
    2729                 :            :         {
    2730                 :            :             bool bMatch = (pFormat ? pFormat->IsNumForStringElementCountEqual(
    2731 [ #  # ][ #  # ]:          0 :                         nStringScanNumFor, nAnzStrings, nAnzNums ) : false);
    2732         [ #  # ]:          0 :             if ( !bMatch )
    2733                 :          0 :                 nMatchedAllStrings = 0;
    2734                 :            :         }
    2735         [ -  + ]:       2865 :         if ( nMatchedAllStrings )
    2736                 :          0 :             eScannedType = eSetType;
    2737         [ -  + ]:       2865 :         else if ( bDidMatch )
    2738                 :          0 :             return false;
    2739                 :            :         else
    2740                 :       2865 :             eScannedType = NUMBERFORMAT_NUMBER;
    2741                 :            :             // everything else should have been recognized by now
    2742                 :            :     }
    2743         [ +  + ]:        176 :     else if ( eScannedType == NUMBERFORMAT_DATE )
    2744                 :            :     {   // the very relaxed date input checks may interfere with a preset format
    2745                 :        132 :         nMatchedAllStrings &= ~nMatchedVirgin;
    2746                 :        132 :         bool bWasReturn = ((nMatchedAllStrings & nMatchedUsedAsReturn) != 0);
    2747         [ -  + ]:        132 :         if ( nMatchedAllStrings )
    2748                 :            :         {
    2749                 :            :             bool bMatch = (pFormat ? pFormat->IsNumForStringElementCountEqual(
    2750 [ #  # ][ #  # ]:          0 :                         nStringScanNumFor, nAnzStrings, nAnzNums ) : false);
    2751         [ #  # ]:          0 :             if ( !bMatch )
    2752                 :          0 :                 nMatchedAllStrings = 0;
    2753                 :            :         }
    2754         [ -  + ]:        132 :         if ( nMatchedAllStrings )
    2755                 :          0 :             eScannedType = eSetType;
    2756         [ -  + ]:        132 :         else if ( bWasReturn )
    2757                 :          0 :             return false;
    2758                 :            :     }
    2759                 :            :     else
    2760                 :         44 :         nMatchedAllStrings = 0;  // reset flag to no substrings matched
    2761                 :            : 
    2762                 :       6757 :     return true;
    2763                 :            : }
    2764                 :            : 
    2765                 :            : 
    2766                 :            : //---------------------------------------------------------------------------
    2767                 :            : // return true or false depending on the nMatched... state and remember usage
    2768                 :        977 : bool ImpSvNumberInputScan::MatchedReturn()
    2769                 :            : {
    2770         [ -  + ]:        977 :     if ( nMatchedAllStrings & ~nMatchedVirgin )
    2771                 :            :     {
    2772                 :          0 :         nMatchedAllStrings |= nMatchedUsedAsReturn;
    2773                 :          0 :         return true;
    2774                 :            :     }
    2775                 :        977 :     return false;
    2776                 :            : }
    2777                 :            : 
    2778                 :            : 
    2779                 :            : //---------------------------------------------------------------------------
    2780                 :            : // Initialize uppercase months and weekdays
    2781                 :            : 
    2782                 :        124 : void ImpSvNumberInputScan::InitText()
    2783                 :            : {
    2784                 :            :     sal_Int32 j, nElems;
    2785                 :        124 :     const CharClass* pChrCls = pFormatter->GetCharClass();
    2786         [ +  - ]:        124 :     const CalendarWrapper* pCal = pFormatter->GetCalendar();
    2787                 :            : 
    2788 [ +  + ][ +  + ]:        340 :     delete [] pUpperMonthText;
                 [ +  - ]
    2789 [ +  + ][ +  + ]:        340 :     delete [] pUpperAbbrevMonthText;
                 [ +  - ]
    2790                 :            :     ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem2 > xElems
    2791         [ +  - ]:        124 :         = pCal->getMonths();
    2792                 :        124 :     nElems = xElems.getLength();
    2793 [ +  - ][ +  +  :       1612 :     pUpperMonthText = new String[nElems];
             #  #  #  # ]
                 [ +  - ]
    2794 [ +  - ][ +  - ]:       1612 :     pUpperAbbrevMonthText = new String[nElems];
           [ +  +  #  #  
                   #  # ]
    2795         [ +  + ]:       1612 :     for ( j=0; j<nElems; j++ )
    2796                 :            :     {
    2797 [ +  - ][ +  - ]:       1488 :         pUpperMonthText[j] = pChrCls->uppercase( xElems[j].FullName );
                 [ +  - ]
    2798 [ +  - ][ +  - ]:       1488 :         pUpperAbbrevMonthText[j] = pChrCls->uppercase( xElems[j].AbbrevName );
                 [ +  - ]
    2799                 :            :     }
    2800                 :            : 
    2801 [ +  + ][ +  + ]:        340 :     delete [] pUpperGenitiveMonthText;
                 [ +  - ]
    2802 [ +  + ][ +  + ]:        340 :     delete [] pUpperGenitiveAbbrevMonthText;
                 [ +  - ]
    2803 [ +  - ][ +  - ]:        124 :     xElems = pCal->getGenitiveMonths();
                 [ +  - ]
    2804                 :        124 :     bScanGenitiveMonths = (nElems != xElems.getLength());
    2805                 :        124 :     nElems = xElems.getLength();
    2806 [ +  - ][ +  +  :       1612 :     pUpperGenitiveMonthText = new String[nElems];
             #  #  #  # ]
                 [ +  - ]
    2807 [ +  - ][ +  - ]:       1612 :     pUpperGenitiveAbbrevMonthText = new String[nElems];
           [ +  +  #  #  
                   #  # ]
    2808         [ +  + ]:       1612 :     for ( j=0; j<nElems; j++ )
    2809                 :            :     {
    2810 [ +  - ][ +  - ]:       1488 :         pUpperGenitiveMonthText[j] = pChrCls->uppercase( xElems[j].FullName );
                 [ +  - ]
    2811 [ +  - ][ +  - ]:       1488 :         pUpperGenitiveAbbrevMonthText[j] = pChrCls->uppercase( xElems[j].AbbrevName );
                 [ +  - ]
    2812 [ +  - ][ -  + ]:       4464 :         if (!bScanGenitiveMonths &&
         [ -  + ][ +  - ]
    2813         [ +  - ]:       1488 :                 (pUpperGenitiveMonthText[j] != pUpperMonthText[j] ||
    2814         [ +  - ]:       1488 :                  pUpperGenitiveAbbrevMonthText[j] != pUpperAbbrevMonthText[j]))
    2815                 :          0 :             bScanGenitiveMonths = true;
    2816                 :            :     }
    2817                 :            : 
    2818 [ +  + ][ +  + ]:        340 :     delete [] pUpperPartitiveMonthText;
                 [ +  - ]
    2819 [ +  + ][ +  + ]:        340 :     delete [] pUpperPartitiveAbbrevMonthText;
                 [ +  - ]
    2820 [ +  - ][ +  - ]:        124 :     xElems = pCal->getPartitiveMonths();
                 [ +  - ]
    2821                 :        124 :     bScanPartitiveMonths = (nElems != xElems.getLength());
    2822                 :        124 :     nElems = xElems.getLength();
    2823 [ +  - ][ +  +  :       1612 :     pUpperPartitiveMonthText = new String[nElems];
             #  #  #  # ]
                 [ +  - ]
    2824 [ +  - ][ +  - ]:       1612 :     pUpperPartitiveAbbrevMonthText = new String[nElems];
           [ +  +  #  #  
                   #  # ]
    2825         [ +  + ]:       1612 :     for ( j=0; j<nElems; j++ )
    2826                 :            :     {
    2827 [ +  - ][ +  - ]:       1488 :         pUpperPartitiveMonthText[j] = pChrCls->uppercase( xElems[j].FullName );
                 [ +  - ]
    2828 [ +  - ][ +  - ]:       1488 :         pUpperPartitiveAbbrevMonthText[j] = pChrCls->uppercase( xElems[j].AbbrevName );
                 [ +  - ]
    2829 [ +  - ][ -  + ]:       4464 :         if (!bScanPartitiveMonths &&
         [ -  + ][ +  - ]
    2830         [ +  - ]:       1488 :                 (pUpperPartitiveMonthText[j] != pUpperGenitiveMonthText[j] ||
    2831         [ +  - ]:       1488 :                  pUpperPartitiveAbbrevMonthText[j] != pUpperGenitiveAbbrevMonthText[j]))
    2832                 :          0 :             bScanPartitiveMonths = true;
    2833                 :            :     }
    2834                 :            : 
    2835 [ +  + ][ +  + ]:        250 :     delete [] pUpperDayText;
                 [ +  - ]
    2836 [ +  + ][ +  + ]:        250 :     delete [] pUpperAbbrevDayText;
                 [ +  - ]
    2837 [ +  - ][ +  - ]:        124 :     xElems = pCal->getDays();
                 [ +  - ]
    2838                 :        124 :     nElems = xElems.getLength();
    2839 [ +  - ][ +  +  :        992 :     pUpperDayText = new String[nElems];
             #  #  #  # ]
                 [ +  - ]
    2840 [ +  - ][ +  - ]:        992 :     pUpperAbbrevDayText = new String[nElems];
           [ +  +  #  #  
                   #  # ]
    2841         [ +  + ]:        992 :     for ( j=0; j<nElems; j++ )
    2842                 :            :     {
    2843 [ +  - ][ +  - ]:        868 :         pUpperDayText[j] = pChrCls->uppercase( xElems[j].FullName );
                 [ +  - ]
    2844 [ +  - ][ +  - ]:        868 :         pUpperAbbrevDayText[j] = pChrCls->uppercase( xElems[j].AbbrevName );
                 [ +  - ]
    2845                 :            :     }
    2846                 :            : 
    2847         [ +  - ]:        124 :     bTextInitialized = true;
    2848                 :        124 : }
    2849                 :            : 
    2850                 :            : 
    2851                 :            : //===========================================================================
    2852                 :            : //          P U B L I C
    2853                 :            : 
    2854                 :            : //---------------------------------------------------------------------------
    2855                 :            : //      ChangeIntl
    2856                 :            : //
    2857                 :            : // MUST be called if International/Locale is changed
    2858                 :            : 
    2859                 :       8868 : void ImpSvNumberInputScan::ChangeIntl()
    2860                 :            : {
    2861                 :       8868 :     sal_Unicode cDecSep = pFormatter->GetNumDecimalSep().GetChar(0);
    2862                 :            :     bDecSepInDateSeps = ( cDecSep == '-' ||
    2863 [ -  + ][ +  - ]:       8868 :                           cDecSep == pFormatter->GetDateSep().GetChar(0) );
    2864                 :       8868 :     bTextInitialized = false;
    2865                 :       8868 :     aUpperCurrSymbol.Erase();
    2866         [ +  + ]:       8868 :     if (sDateAcceptancePatterns.getLength())
    2867         [ +  - ]:         12 :         sDateAcceptancePatterns = ::com::sun::star::uno::Sequence< ::rtl::OUString >();
    2868                 :       8868 : }
    2869                 :            : 
    2870                 :            : 
    2871                 :            : //---------------------------------------------------------------------------
    2872                 :            : //      ChangeNullDate
    2873                 :            : 
    2874                 :       1617 : void ImpSvNumberInputScan::ChangeNullDate(
    2875                 :            :         const sal_uInt16 Day,
    2876                 :            :         const sal_uInt16 Month,
    2877                 :            :         const sal_uInt16 Year )
    2878                 :            : {
    2879         [ +  - ]:       1617 :     if ( pNullDate )
    2880                 :       1617 :         *pNullDate = Date(Day, Month, Year);
    2881                 :            :     else
    2882                 :          0 :         pNullDate = new Date(Day, Month, Year);
    2883                 :       1617 : }
    2884                 :            : 
    2885                 :            : 
    2886                 :            : //---------------------------------------------------------------------------
    2887                 :            : //      IsNumberFormat
    2888                 :            : //
    2889                 :            : // => does rString represent a number (also date, time et al)
    2890                 :            : 
    2891                 :       6829 : bool ImpSvNumberInputScan::IsNumberFormat(
    2892                 :            :         const String& rString,                  // string to be analyzed
    2893                 :            :         short& F_Type,                          // IN: old type, OUT: new type
    2894                 :            :         double& fOutNumber,                     // OUT: number if convertable
    2895                 :            :         const SvNumberformat* pFormat )         // maybe a number format to match against
    2896                 :            : {
    2897         [ +  - ]:       6829 :     String sResString;
    2898         [ +  - ]:       6829 :     String aString;
    2899                 :            :     bool res;                                   // return value
    2900                 :       6829 :     eSetType = F_Type;                          // old type set
    2901                 :            : 
    2902         [ +  + ]:       6829 :     if ( !rString.Len() )
    2903                 :         69 :         res = false;
    2904         [ +  + ]:       6760 :     else if (rString.Len() > 308)               // arbitrary
    2905                 :          3 :         res = false;
    2906                 :            :     else
    2907                 :            :     {
    2908                 :            :         // NoMoreUpperNeeded, all comparisons on UpperCase
    2909 [ +  - ][ +  - ]:       6757 :         aString = pFormatter->GetCharClass()->uppercase( rString );
                 [ +  - ]
    2910                 :            :         // convert native number to ASCII if necessary
    2911         [ +  - ]:       6757 :         TransformInput( aString );
    2912         [ +  - ]:       6757 :         res = IsNumberFormatMain( aString, pFormat );
    2913                 :            :     }
    2914                 :            : 
    2915         [ +  + ]:       6829 :     if (res)
    2916                 :            :     {
    2917 [ +  - ][ +  + ]:       3041 :         if ( nNegCheck                              // ')' not found for '('
         [ +  - ][ -  + ]
    2918                 :            :                 || (nSign && (eScannedType == NUMBERFORMAT_DATE
    2919                 :            :                     || eScannedType == NUMBERFORMAT_DATETIME))
    2920                 :            :             )                                       // signed date/datetime
    2921                 :          0 :             res = false;
    2922                 :            :         else
    2923                 :            :         {                                           // check count of partial number strings
    2924   [ +  -  +  -  :       3041 :             switch (eScannedType)
                   +  - ]
    2925                 :            :             {
    2926                 :            :                 case NUMBERFORMAT_PERCENT:
    2927                 :            :                 case NUMBERFORMAT_CURRENCY:
    2928                 :            :                 case NUMBERFORMAT_NUMBER:
    2929         [ -  + ]:       2885 :                     if (nDecPos == 1)               // .05
    2930                 :            :                     {
    2931                 :            :                         // matched MidStrings function like group separators
    2932         [ #  # ]:          0 :                         if ( nMatchedAllStrings )
    2933                 :          0 :                             nThousand = nAnzNums - 1;
    2934         [ #  # ]:          0 :                         else if ( nAnzNums != 1 )
    2935                 :          0 :                             res = false;
    2936                 :            :                     }
    2937         [ +  + ]:       2885 :                     else if (nDecPos == 2)          // 1.05
    2938                 :            :                     {
    2939                 :            :                         // matched MidStrings function like group separators
    2940         [ -  + ]:        252 :                         if ( nMatchedAllStrings )
    2941                 :          0 :                             nThousand = nAnzNums - 1;
    2942         [ -  + ]:        252 :                         else if ( nAnzNums != nThousand+2 )
    2943                 :          0 :                             res = false;
    2944                 :            :                     }
    2945                 :            :                     else                            // 1,100 or 1,100.
    2946                 :            :                     {
    2947                 :            :                         // matched MidStrings function like group separators
    2948         [ -  + ]:       2633 :                         if ( nMatchedAllStrings )
    2949                 :          0 :                             nThousand = nAnzNums - 1;
    2950         [ -  + ]:       2633 :                         else if ( nAnzNums != nThousand+1 )
    2951                 :          0 :                             res = false;
    2952                 :            :                     }
    2953                 :       2885 :                     break;
    2954                 :            : 
    2955                 :            :                 case NUMBERFORMAT_SCIENTIFIC:       // 1.0e-2
    2956         [ #  # ]:          0 :                     if (nDecPos == 1)               // .05
    2957                 :            :                     {
    2958         [ #  # ]:          0 :                         if (nAnzNums != 2)
    2959                 :          0 :                             res = false;
    2960                 :            :                     }
    2961         [ #  # ]:          0 :                     else if (nDecPos == 2)          // 1.05
    2962                 :            :                     {
    2963         [ #  # ]:          0 :                         if (nAnzNums != nThousand+3)
    2964                 :          0 :                             res = false;
    2965                 :            :                     }
    2966                 :            :                     else                            // 1,100 or 1,100.
    2967                 :            :                     {
    2968         [ #  # ]:          0 :                         if (nAnzNums != nThousand+2)
    2969                 :          0 :                             res = false;
    2970                 :            :                     }
    2971                 :          0 :                     break;
    2972                 :            : 
    2973                 :            :                 case NUMBERFORMAT_DATE:
    2974         [ -  + ]:        132 :                     if (nMonth)
    2975                 :            :                     {                               // month name and numbers
    2976         [ #  # ]:          0 :                         if (nAnzNums > 2)
    2977                 :          0 :                             res = false;
    2978                 :            :                     }
    2979                 :            :                     else
    2980                 :            :                     {
    2981         [ -  + ]:        132 :                         if (nAnzNums > 3)
    2982                 :          0 :                             res = false;
    2983                 :            :                         else
    2984         [ +  - ]:        132 :                             res = IsAcceptedDatePattern( nNums[0]) ||
    2985 [ +  - ][ +  - ]:        132 :                                 MayBeIso8601() || nMatchedAllStrings;
         [ -  + ][ #  # ]
    2986                 :            :                     }
    2987                 :        132 :                     break;
    2988                 :            : 
    2989                 :            :                 case NUMBERFORMAT_TIME:
    2990         [ #  # ]:          0 :                     if (nDecPos)
    2991                 :            :                     {                               // hundredth seconds included
    2992         [ #  # ]:          0 :                         if (nAnzNums > 4)
    2993                 :          0 :                             res = false;
    2994                 :            :                     }
    2995                 :            :                     else
    2996                 :            :                     {
    2997         [ #  # ]:          0 :                         if (nAnzNums > 3)
    2998                 :          0 :                             res = false;
    2999                 :            :                     }
    3000                 :          0 :                     break;
    3001                 :            : 
    3002                 :            :                 case NUMBERFORMAT_DATETIME:
    3003         [ -  + ]:         24 :                     if (nMonth)
    3004                 :            :                     {                               // month name and numbers
    3005         [ #  # ]:          0 :                         if (nDecPos)
    3006                 :            :                         {                           // hundredth seconds included
    3007         [ #  # ]:          0 :                             if (nAnzNums > 6)
    3008                 :          0 :                                 res = false;
    3009                 :            :                         }
    3010                 :            :                         else
    3011                 :            :                         {
    3012         [ #  # ]:          0 :                             if (nAnzNums > 5)
    3013                 :          0 :                                 res = false;
    3014                 :            :                         }
    3015                 :            :                     }
    3016                 :            :                     else
    3017                 :            :                     {
    3018         [ -  + ]:         24 :                         if (nDecPos)
    3019                 :            :                         {                           // hundredth seconds included
    3020         [ #  # ]:          0 :                             if (nAnzNums > 7)
    3021                 :          0 :                                 res = false;
    3022                 :            :                         }
    3023                 :            :                         else
    3024                 :            :                         {
    3025         [ -  + ]:         24 :                             if (nAnzNums > 6)
    3026                 :          0 :                                 res = false;
    3027                 :            :                         }
    3028         [ +  - ]:         24 :                         if (res)
    3029         [ +  - ]:         24 :                             res = IsAcceptedDatePattern( nNums[0]) ||
    3030 [ +  - ][ +  - ]:         24 :                                 MayBeIso8601() || nMatchedAllStrings;
         [ -  + ][ #  # ]
    3031                 :            :                     }
    3032                 :         24 :                     break;
    3033                 :            : 
    3034                 :            :                 default:
    3035                 :       3041 :                     break;
    3036                 :            :             }   // switch
    3037                 :            :         }   // else
    3038                 :            :     }   // if (res)
    3039                 :            : 
    3040         [ +  + ]:       6829 :     if (res)
    3041                 :            :     {                                           // we finally have a number
    3042   [ -  +  -  -  :       3041 :         switch (eScannedType)
                +  +  - ]
    3043                 :            :         {
    3044                 :            :             case NUMBERFORMAT_LOGICAL:
    3045         [ #  # ]:          0 :                 if      (nLogical ==  1)
    3046                 :          0 :                     fOutNumber = 1.0;           // True
    3047         [ #  # ]:          0 :                 else if (nLogical == -1)
    3048                 :          0 :                     fOutNumber = 0.0;           // False
    3049                 :            :                 else
    3050                 :          0 :                     res = false;                // Oops
    3051                 :          0 :                 break;
    3052                 :            : 
    3053                 :            :             case NUMBERFORMAT_PERCENT:
    3054                 :            :             case NUMBERFORMAT_CURRENCY:
    3055                 :            :             case NUMBERFORMAT_NUMBER:
    3056                 :            :             case NUMBERFORMAT_SCIENTIFIC:
    3057                 :            :             case NUMBERFORMAT_DEFINED:          // if no category detected handle as number
    3058                 :            :             {
    3059         [ -  + ]:       2885 :                 if ( nDecPos == 1 )                         // . at start
    3060         [ #  # ]:          0 :                     sResString.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "0." ) );
    3061                 :            :                 else
    3062         [ +  - ]:       2885 :                     sResString.Erase();
    3063                 :            :                 sal_uInt16 k;
    3064         [ +  + ]:       5776 :                 for ( k = 0; k <= nThousand; k++)
    3065         [ +  - ]:       2891 :                     sResString += sStrArray[nNums[k]];  // integer part
    3066 [ +  + ][ +  - ]:       2885 :                 if ( nDecPos == 2 && k < nAnzNums )     // . somewhere
    3067                 :            :                 {
    3068         [ +  - ]:        252 :                     sResString += '.';
    3069                 :            :                     sal_uInt16 nStop = (eScannedType == NUMBERFORMAT_SCIENTIFIC ?
    3070         [ -  + ]:        252 :                             nAnzNums-1 : nAnzNums);
    3071         [ +  + ]:        504 :                     for ( ; k < nStop; k++)
    3072         [ +  - ]:        252 :                         sResString += sStrArray[nNums[k]];  // fractional part
    3073                 :            :                 }
    3074                 :            : 
    3075         [ +  - ]:       2885 :                 if (eScannedType != NUMBERFORMAT_SCIENTIFIC)
    3076                 :       2885 :                     fOutNumber = StringToDouble(sResString);
    3077                 :            :                 else
    3078                 :            :                 {                                           // append exponent
    3079         [ #  # ]:          0 :                     sResString += 'E';
    3080         [ #  # ]:          0 :                     if ( nESign == -1 )
    3081         [ #  # ]:          0 :                         sResString += '-';
    3082         [ #  # ]:          0 :                     sResString += sStrArray[nNums[nAnzNums-1]];
    3083                 :            :                     rtl_math_ConversionStatus eStatus;
    3084                 :            :                     fOutNumber = ::rtl::math::stringToDouble(
    3085         [ #  # ]:          0 :                         sResString, '.', ',', &eStatus, NULL );
    3086         [ #  # ]:          0 :                     if ( eStatus == rtl_math_ConversionStatus_OutOfRange )
    3087                 :            :                     {
    3088                 :          0 :                         F_Type = NUMBERFORMAT_TEXT;         // overflow/underflow -> Text
    3089         [ #  # ]:          0 :                         if (nESign == -1)
    3090                 :          0 :                             fOutNumber = 0.0;
    3091                 :            :                         else
    3092                 :          0 :                             fOutNumber = DBL_MAX;
    3093                 :          0 : /*!*/                   return true;
    3094                 :            :                     }
    3095                 :            :                 }
    3096                 :            : 
    3097         [ -  + ]:       2885 :                 if ( nStringScanSign )
    3098                 :            :                 {
    3099         [ #  # ]:          0 :                     if ( nSign )
    3100                 :          0 :                         nSign *= nStringScanSign;
    3101                 :            :                     else
    3102                 :          0 :                         nSign = nStringScanSign;
    3103                 :            :                 }
    3104         [ +  + ]:       2885 :                 if ( nSign < 0 )
    3105                 :         12 :                     fOutNumber = -fOutNumber;
    3106                 :            : 
    3107         [ -  + ]:       2885 :                 if (eScannedType == NUMBERFORMAT_PERCENT)
    3108                 :          0 :                     fOutNumber/= 100.0;
    3109                 :            :             }
    3110                 :       2885 :             break;
    3111                 :            : 
    3112                 :            :             case NUMBERFORMAT_FRACTION:
    3113         [ #  # ]:          0 :                 if (nAnzNums == 1)
    3114                 :          0 :                     fOutNumber = StringToDouble(sStrArray[nNums[0]]);
    3115         [ #  # ]:          0 :                 else if (nAnzNums == 2)
    3116                 :            :                 {
    3117         [ #  # ]:          0 :                     if (nThousand == 1)
    3118                 :            :                     {
    3119         [ #  # ]:          0 :                         sResString = sStrArray[nNums[0]];
    3120         [ #  # ]:          0 :                         sResString += sStrArray[nNums[1]];  // integer part
    3121                 :          0 :                         fOutNumber = StringToDouble(sResString);
    3122                 :            :                     }
    3123                 :            :                     else
    3124                 :            :                     {
    3125                 :          0 :                         double fZaehler = StringToDouble(sStrArray[nNums[0]]);
    3126                 :          0 :                         double fNenner = StringToDouble(sStrArray[nNums[1]]);
    3127         [ #  # ]:          0 :                         if (fNenner != 0.0)
    3128                 :          0 :                             fOutNumber = fZaehler/fNenner;
    3129                 :            :                         else
    3130                 :          0 :                             res = false;
    3131                 :            :                     }
    3132                 :            :                 }
    3133                 :            :                 else                                        // nAnzNums > 2
    3134                 :            :                 {
    3135                 :          0 :                     sal_uInt16 k = 1;
    3136         [ #  # ]:          0 :                     sResString = sStrArray[nNums[0]];
    3137         [ #  # ]:          0 :                     if (nThousand > 0)
    3138         [ #  # ]:          0 :                         for (k = 1; k <= nThousand; k++)
    3139         [ #  # ]:          0 :                             sResString += sStrArray[nNums[k]];
    3140                 :          0 :                     fOutNumber = StringToDouble(sResString);
    3141                 :            : 
    3142         [ #  # ]:          0 :                     if (k == nAnzNums-2)
    3143                 :            :                     {
    3144                 :          0 :                         double fZaehler = StringToDouble(sStrArray[nNums[k]]);
    3145                 :          0 :                         double fNenner = StringToDouble(sStrArray[nNums[k+1]]);
    3146         [ #  # ]:          0 :                         if (fNenner != 0.0)
    3147                 :          0 :                             fOutNumber += fZaehler/fNenner;
    3148                 :            :                         else
    3149                 :          0 :                             res = false;
    3150                 :            :                     }
    3151                 :            :                 }
    3152                 :            : 
    3153         [ #  # ]:          0 :                 if ( nStringScanSign )
    3154                 :            :                 {
    3155         [ #  # ]:          0 :                     if ( nSign )
    3156                 :          0 :                         nSign *= nStringScanSign;
    3157                 :            :                     else
    3158                 :          0 :                         nSign = nStringScanSign;
    3159                 :            :                 }
    3160         [ #  # ]:          0 :                 if ( nSign < 0 )
    3161                 :          0 :                     fOutNumber = -fOutNumber;
    3162                 :          0 :                 break;
    3163                 :            : 
    3164                 :            :             case NUMBERFORMAT_TIME:
    3165         [ #  # ]:          0 :                 res = GetTimeRef(fOutNumber, 0, nAnzNums);
    3166         [ #  # ]:          0 :                 if ( nSign < 0 )
    3167                 :          0 :                     fOutNumber = -fOutNumber;
    3168                 :          0 :                 break;
    3169                 :            : 
    3170                 :            :             case NUMBERFORMAT_DATE:
    3171                 :            :             {
    3172                 :        132 :                 sal_uInt16 nCounter = 0;                        // dummy here
    3173         [ +  - ]:        132 :                 res = GetDateRef( fOutNumber, nCounter, pFormat );
    3174                 :            :             }
    3175                 :        132 :             break;
    3176                 :            : 
    3177                 :            :             case NUMBERFORMAT_DATETIME:
    3178                 :            :             {
    3179                 :         24 :                 sal_uInt16 nCounter = 0;                        // needed here
    3180         [ +  - ]:         24 :                 res = GetDateRef( fOutNumber, nCounter, pFormat );
    3181         [ +  - ]:         24 :                 if ( res )
    3182                 :            :                 {
    3183                 :            :                     double fTime;
    3184         [ +  - ]:         24 :                     res = GetTimeRef( fTime, nCounter, nAnzNums - nCounter );
    3185                 :         24 :                     fOutNumber += fTime;
    3186                 :            :                 }
    3187                 :            :             }
    3188                 :         24 :             break;
    3189                 :            : 
    3190                 :            :             default:
    3191                 :            :                 SAL_WARN( "svl.items", "Some number recognized but what's it?" );
    3192                 :          0 :                 fOutNumber = 0.0;
    3193                 :       3041 :                 break;
    3194                 :            :         }
    3195                 :            :     }
    3196                 :            : 
    3197         [ +  + ]:       6829 :     if (res)        // overflow/underflow -> Text
    3198                 :            :     {
    3199         [ -  + ]:       3041 :         if      (fOutNumber < -DBL_MAX) // -1.7E308
    3200                 :            :         {
    3201                 :          0 :             F_Type = NUMBERFORMAT_TEXT;
    3202                 :          0 :             fOutNumber = -DBL_MAX;
    3203                 :          0 :             return true;
    3204                 :            :         }
    3205         [ -  + ]:       3041 :         else if (fOutNumber >  DBL_MAX) // 1.7E308
    3206                 :            :         {
    3207                 :          0 :             F_Type = NUMBERFORMAT_TEXT;
    3208                 :          0 :             fOutNumber = DBL_MAX;
    3209                 :          0 :             return true;
    3210                 :            :         }
    3211                 :            :     }
    3212                 :            : 
    3213         [ +  + ]:       6829 :     if (res == false)
    3214                 :            :     {
    3215                 :       3788 :         eScannedType = NUMBERFORMAT_TEXT;
    3216                 :       3788 :         fOutNumber = 0.0;
    3217                 :            :     }
    3218                 :            : 
    3219                 :       6829 :     F_Type = eScannedType;
    3220 [ +  - ][ +  - ]:       6829 :     return res;
    3221                 :            : }
    3222                 :            : 
    3223                 :            : 
    3224                 :            : 
    3225                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10