LCOV - code coverage report
Current view: top level - vcl/source/control - field2.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 793 1599 49.6 %
Date: 2014-11-03 Functions: 95 143 66.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "sal/config.h"
      21             : 
      22             : #include <algorithm>
      23             : 
      24             : #include <tools/diagnose_ex.h>
      25             : #include <comphelper/processfactory.hxx>
      26             : #include <comphelper/string.hxx>
      27             : #include <tools/rc.h>
      28             : #include <vcl/svapp.hxx>
      29             : #include <vcl/event.hxx>
      30             : #include <vcl/field.hxx>
      31             : #include <vcl/unohelp.hxx>
      32             : #include <vcl/settings.hxx>
      33             : 
      34             : #include <svdata.hxx>
      35             : 
      36             : #include <i18nlangtag/mslangid.hxx>
      37             : 
      38             : #include <com/sun/star/lang/Locale.hpp>
      39             : #include <com/sun/star/i18n/XCharacterClassification.hpp>
      40             : #include <com/sun/star/i18n/KCharacterType.hpp>
      41             : 
      42             : #include <unotools/localedatawrapper.hxx>
      43             : #include <unotools/calendarwrapper.hxx>
      44             : #include <unotools/charclass.hxx>
      45             : #include <unotools/misccfg.hxx>
      46             : 
      47             : using namespace ::com::sun::star;
      48             : using namespace ::comphelper;
      49             : 
      50             : #define EDITMASK_LITERAL       'L'
      51             : #define EDITMASK_ALPHA         'a'
      52             : #define EDITMASK_UPPERALPHA    'A'
      53             : #define EDITMASK_ALPHANUM      'c'
      54             : #define EDITMASK_UPPERALPHANUM 'C'
      55             : #define EDITMASK_NUM           'N'
      56             : #define EDITMASK_NUMSPACE      'n'
      57             : #define EDITMASK_ALLCHAR       'x'
      58             : #define EDITMASK_UPPERALLCHAR  'X'
      59             : 
      60         140 : uno::Reference< i18n::XCharacterClassification > ImplGetCharClass()
      61             : {
      62         140 :     static uno::Reference< i18n::XCharacterClassification > xCharClass;
      63         140 :     if ( !xCharClass.is() )
      64           4 :         xCharClass = vcl::unohelper::CreateCharacterClassification();
      65             : 
      66         140 :     return xCharClass;
      67             : }
      68             : 
      69         624 : static sal_Unicode* ImplAddString( sal_Unicode* pBuf, const OUString& rStr )
      70             : {
      71         624 :     if ( rStr.getLength() == 1 )
      72         624 :         *pBuf++ = rStr[0];
      73           0 :     else if ( rStr.isEmpty() )
      74             :         ;
      75             :     else
      76             :     {
      77           0 :         memcpy( pBuf, rStr.getStr(), rStr.getLength() * sizeof(sal_Unicode) );
      78           0 :         pBuf += rStr.getLength();
      79             :     }
      80         624 :     return pBuf;
      81             : }
      82             : 
      83         936 : static sal_Unicode* ImplAddNum( sal_Unicode* pBuf, sal_uLong nNumber, int nMinLen )
      84             : {
      85             :     // fill temp buffer with digits
      86             :     sal_Unicode aTempBuf[30];
      87         936 :     sal_Unicode* pTempBuf = aTempBuf;
      88        1474 :     do
      89             :     {
      90        1474 :         *pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
      91        1474 :         pTempBuf++;
      92        1474 :         nNumber /= 10;
      93        1474 :         if ( nMinLen )
      94        1474 :             nMinLen--;
      95             :     }
      96             :     while ( nNumber );
      97             : 
      98             :     // fill with zeros up to the minimal length
      99        2622 :     while ( nMinLen > 0 )
     100             :     {
     101         750 :         *pBuf = '0';
     102         750 :         pBuf++;
     103         750 :         nMinLen--;
     104             :     }
     105             : 
     106             :     // copy temp buffer to real buffer
     107        1474 :     do
     108             :     {
     109        1474 :         pTempBuf--;
     110        1474 :         *pBuf = *pTempBuf;
     111        1474 :         pBuf++;
     112             :     }
     113             :     while ( pTempBuf != aTempBuf );
     114             : 
     115         936 :     return pBuf;
     116             : }
     117             : 
     118        1758 : static sal_uInt16 ImplGetNum( const sal_Unicode*& rpBuf, bool& rbError )
     119             : {
     120        1758 :     if ( !*rpBuf )
     121             :     {
     122           0 :         rbError = true;
     123           0 :         return 0;
     124             :     }
     125             : 
     126        1758 :     sal_uInt16 nNumber = 0;
     127        7716 :     while( ( *rpBuf >= '0' ) && ( *rpBuf <= '9' ) )
     128             :     {
     129        4200 :         nNumber *= 10;
     130        4200 :         nNumber += *rpBuf - '0';
     131        4200 :         rpBuf++;
     132             :     }
     133             : 
     134        1758 :     return nNumber;
     135             : }
     136             : 
     137        1758 : static void ImplSkipDelimiters( const sal_Unicode*& rpBuf )
     138             : {
     139        7618 :     while( ( *rpBuf == ',' ) || ( *rpBuf == '.' ) || ( *rpBuf == ';' ) ||
     140        5860 :            ( *rpBuf == ':' ) || ( *rpBuf == '-' ) || ( *rpBuf == '/' ) )
     141             :     {
     142        1172 :         rpBuf++;
     143             :     }
     144        1758 : }
     145             : 
     146         140 : static bool ImplIsPatternChar( sal_Unicode cChar, sal_Char cEditMask )
     147             : {
     148         140 :     sal_Int32 nType = 0;
     149             : 
     150             :     try
     151             :     {
     152         140 :         OUString aCharStr(cChar);
     153         280 :         nType = ImplGetCharClass()->getStringType( aCharStr, 0, aCharStr.getLength(),
     154         280 :                 Application::GetSettings().GetLanguageTag().getLocale() );
     155             :     }
     156           0 :     catch (const ::com::sun::star::uno::Exception&)
     157             :     {
     158             :         SAL_WARN( "vcl.control", "ImplIsPatternChar: Exception caught!" );
     159             :         DBG_UNHANDLED_EXCEPTION();
     160           0 :         return false;
     161             :     }
     162             : 
     163         140 :     if ( (cEditMask == EDITMASK_ALPHA) || (cEditMask == EDITMASK_UPPERALPHA) )
     164             :     {
     165           0 :         if( !CharClass::isLetterType( nType ) )
     166           0 :             return false;
     167             :     }
     168         140 :     else if ( cEditMask == EDITMASK_NUM )
     169             :     {
     170          80 :         if( !CharClass::isNumericType( nType ) )
     171          80 :             return false;
     172             :     }
     173          60 :     else if ( (cEditMask == EDITMASK_ALPHANUM) || (cEditMask == EDITMASK_UPPERALPHANUM) )
     174             :     {
     175          96 :         if( !CharClass::isLetterNumericType( nType ) )
     176           0 :             return false;
     177             :     }
     178          12 :     else if ( (cEditMask == EDITMASK_ALLCHAR) || (cEditMask == EDITMASK_UPPERALLCHAR) )
     179             :     {
     180           0 :         if ( cChar < 32 )
     181           0 :             return false;
     182             :     }
     183          12 :     else if ( cEditMask == EDITMASK_NUMSPACE )
     184             :     {
     185           0 :         if ( !CharClass::isNumericType( nType ) && ( cChar != ' ' ) )
     186           0 :             return false;
     187             :     }
     188             :     else
     189          12 :         return false;
     190             : 
     191          48 :     return true;
     192             : }
     193             : 
     194         140 : static sal_Unicode ImplPatternChar( sal_Unicode cChar, sal_Char cEditMask )
     195             : {
     196         140 :     if ( ImplIsPatternChar( cChar, cEditMask ) )
     197             :     {
     198          48 :         if ( (cEditMask == EDITMASK_UPPERALPHA) ||
     199          48 :              (cEditMask == EDITMASK_UPPERALPHANUM) ||
     200             :              ( cEditMask == EDITMASK_UPPERALLCHAR ) )
     201             :         {
     202           0 :             cChar = ImplGetCharClass()->toUpper(OUString(cChar), 0, 1,
     203           0 :                     Application::GetSettings().GetLanguageTag().getLocale())[0];
     204             :         }
     205          48 :         return cChar;
     206             :     }
     207             :     else
     208          92 :         return 0;
     209             : }
     210             : 
     211           0 : static bool ImplCommaPointCharEqual( sal_Unicode c1, sal_Unicode c2 )
     212             : {
     213           0 :     if ( c1 == c2 )
     214           0 :         return true;
     215           0 :     else if ( ((c1 == '.') || (c1 == ',')) &&
     216           0 :               ((c2 == '.') || (c2 == ',')) )
     217           0 :         return true;
     218             :     else
     219           0 :         return false;
     220             : }
     221             : 
     222         190 : static OUString ImplPatternReformat( const OUString& rStr,
     223             :                                      const OString& rEditMask,
     224             :                                      const OUString& rLiteralMask,
     225             :                                      sal_uInt16 nFormatFlags )
     226             : {
     227         190 :     if (rEditMask.isEmpty())
     228         106 :         return rStr;
     229             : 
     230          84 :     OUString    aStr    = rStr;
     231         168 :     OUStringBuffer    aOutStr = OUString(rLiteralMask);
     232             :     sal_Unicode cTempChar;
     233             :     sal_Unicode cChar;
     234             :     sal_Unicode cLiteral;
     235             :     sal_Char    cMask;
     236          84 :     sal_Int32   nStrIndex = 0;
     237          84 :     sal_Int32   i = 0;
     238             :     sal_Int32   n;
     239             : 
     240         308 :     while ( i < rEditMask.getLength() )
     241             :     {
     242         202 :         if ( nStrIndex >= aStr.getLength() )
     243          62 :             break;
     244             : 
     245         140 :         cChar = aStr[nStrIndex];
     246         140 :         cLiteral = rLiteralMask[i];
     247         140 :         cMask = rEditMask[i];
     248             : 
     249             :         // current position is a literal
     250         140 :         if ( cMask == EDITMASK_LITERAL )
     251             :         {
     252             :             // if it is a literal copy otherwise ignore because it might be the next valid
     253             :             // character of the string
     254           0 :             if ( ImplCommaPointCharEqual( cChar, cLiteral ) )
     255           0 :                 nStrIndex++;
     256             :             else
     257             :             {
     258             :                 // Otherwise we check if it is a invalid character. This is the case if it does not
     259             :                 // fit in the pattern of the next non-literal character.
     260           0 :                 n = i+1;
     261           0 :                 while ( n < rEditMask.getLength() )
     262             :                 {
     263           0 :                     if ( rEditMask[n] != EDITMASK_LITERAL )
     264             :                     {
     265           0 :                         if ( !ImplIsPatternChar( cChar, rEditMask[n] ) )
     266           0 :                             nStrIndex++;
     267           0 :                         break;
     268             :                     }
     269             : 
     270           0 :                     n++;
     271             :                 }
     272             :             }
     273             :         }
     274             :         else
     275             :         {
     276             :             // valid character at this position
     277         140 :             cTempChar = ImplPatternChar( cChar, cMask );
     278         140 :             if ( cTempChar )
     279             :             {
     280             :                 // use this character
     281          48 :                 aOutStr[i] = cTempChar;
     282          48 :                 nStrIndex++;
     283             :             }
     284             :             else
     285             :             {
     286             :                 // copy if it is a literal character
     287          92 :                 if ( cLiteral == cChar )
     288          74 :                     nStrIndex++;
     289             :                 else
     290             :                 {
     291             :                     // If the invalid character might be the next literal character then we jump
     292             :                     // ahead to it, otherwise we ignore it. Do only if empty literals are allowed.
     293          18 :                     if ( nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS )
     294             :                     {
     295           0 :                         n = i;
     296           0 :                         while ( n < rEditMask.getLength() )
     297             :                         {
     298           0 :                             if ( rEditMask[n] == EDITMASK_LITERAL )
     299             :                             {
     300           0 :                                 if ( ImplCommaPointCharEqual( cChar, rLiteralMask[n] ) )
     301           0 :                                     i = n+1;
     302             : 
     303           0 :                                 break;
     304             :                             }
     305             : 
     306           0 :                             n++;
     307             :                         }
     308             :                     }
     309             : 
     310          18 :                     nStrIndex++;
     311          18 :                     continue;
     312             :                 }
     313             :             }
     314             :         }
     315             : 
     316         122 :         i++;
     317             :     }
     318             : 
     319         168 :     return aOutStr.makeStringAndClear();
     320             : }
     321             : 
     322           0 : static void ImplPatternMaxPos( const OUString& rStr, const OString& rEditMask,
     323             :                                sal_uInt16 nFormatFlags, bool bSameMask,
     324             :                                sal_Int32 nCursorPos, sal_Int32& rPos )
     325             : {
     326             : 
     327             :     // last position must not be longer than the contained string
     328           0 :     sal_Int32 nMaxPos = rStr.getLength();
     329             : 
     330             :     // if non empty literals are allowed ignore blanks at the end as well
     331           0 :     if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
     332             :     {
     333           0 :         while ( nMaxPos )
     334             :         {
     335           0 :             if ( (rEditMask[nMaxPos-1] != EDITMASK_LITERAL) &&
     336           0 :                  (rStr[nMaxPos-1] != ' ') )
     337           0 :                 break;
     338           0 :             nMaxPos--;
     339             :         }
     340             : 
     341             :         // if we are in front of a literal, continue search until first character after the literal
     342           0 :         sal_Int32 nTempPos = nMaxPos;
     343           0 :         while ( nTempPos < rEditMask.getLength() )
     344             :         {
     345           0 :             if ( rEditMask[nTempPos] != EDITMASK_LITERAL )
     346             :             {
     347           0 :                 nMaxPos = nTempPos;
     348           0 :                 break;
     349             :             }
     350           0 :             nTempPos++;
     351             :         }
     352             :     }
     353             : 
     354           0 :     if ( rPos > nMaxPos )
     355           0 :         rPos = nMaxPos;
     356             : 
     357             :     // character should not move left
     358           0 :     if ( rPos < nCursorPos )
     359           0 :         rPos = nCursorPos;
     360           0 : }
     361             : 
     362           0 : static void ImplPatternProcessStrictModify( Edit* pEdit,
     363             :                                             const OString& rEditMask,
     364             :                                             const OUString& rLiteralMask,
     365             :                                             sal_uInt16 nFormatFlags, bool bSameMask )
     366             : {
     367           0 :     OUString aText = pEdit->GetText();
     368             : 
     369             :     // remove leading blanks
     370           0 :     if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
     371             :     {
     372           0 :         sal_Int32 i = 0;
     373           0 :         sal_Int32 nMaxLen = aText.getLength();
     374           0 :         while ( i < nMaxLen )
     375             :         {
     376           0 :             if ( (rEditMask[i] != EDITMASK_LITERAL) &&
     377           0 :                  (aText[i] != ' ') )
     378           0 :                 break;
     379             : 
     380           0 :             i++;
     381             :         }
     382             :         // keep all literal characters
     383           0 :         while ( i && (rEditMask[i] == EDITMASK_LITERAL) )
     384           0 :             i--;
     385           0 :         aText = aText.copy( i );
     386             :     }
     387             : 
     388           0 :     OUString aNewText = ImplPatternReformat( aText, rEditMask, rLiteralMask, nFormatFlags );
     389           0 :     if ( aNewText != aText )
     390             :     {
     391             :         // adjust selection such that it remains at the end if it was there before
     392           0 :         Selection aSel = pEdit->GetSelection();
     393           0 :         sal_Int64 nMaxSel = std::max( aSel.Min(), aSel.Max() );
     394           0 :         if ( nMaxSel >= aText.getLength() )
     395             :         {
     396           0 :             sal_Int32 nMaxPos = aNewText.getLength();
     397           0 :             ImplPatternMaxPos( aNewText, rEditMask, nFormatFlags, bSameMask, nMaxSel, nMaxPos );
     398           0 :             if ( aSel.Min() == aSel.Max() )
     399             :             {
     400           0 :                 aSel.Min() = nMaxPos;
     401           0 :                 aSel.Max() = aSel.Min();
     402             :             }
     403           0 :             else if ( aSel.Min() > aSel.Max() )
     404           0 :                 aSel.Min() = nMaxPos;
     405             :             else
     406           0 :                 aSel.Max() = nMaxPos;
     407             :         }
     408           0 :         pEdit->SetText( aNewText, aSel );
     409           0 :     }
     410           0 : }
     411             : 
     412           0 : static sal_Int32 ImplPatternLeftPos(const OString& rEditMask, sal_Int32 nCursorPos)
     413             : {
     414             :     // search non-literal predecessor
     415           0 :     sal_Int32 nNewPos = nCursorPos;
     416           0 :     sal_Int32 nTempPos = nNewPos;
     417           0 :     while ( nTempPos )
     418             :     {
     419           0 :         if ( rEditMask[nTempPos-1] != EDITMASK_LITERAL )
     420             :         {
     421           0 :             nNewPos = nTempPos-1;
     422           0 :             break;
     423             :         }
     424           0 :         nTempPos--;
     425             :     }
     426           0 :     return nNewPos;
     427             : }
     428             : 
     429           0 : static sal_Int32 ImplPatternRightPos( const OUString& rStr, const OString& rEditMask,
     430             :                                        sal_uInt16 nFormatFlags, bool bSameMask,
     431             :                                        sal_Int32 nCursorPos )
     432             : {
     433             :     // search non-literal successor
     434           0 :     sal_Int32 nNewPos = nCursorPos;
     435           0 :     sal_Int32 nTempPos = nNewPos;
     436           0 :     while ( nTempPos < rEditMask.getLength() )
     437             :     {
     438           0 :         if ( rEditMask[nTempPos+1] != EDITMASK_LITERAL )
     439             :         {
     440           0 :             nNewPos = nTempPos+1;
     441           0 :             break;
     442             :         }
     443           0 :         nTempPos++;
     444             :     }
     445           0 :     ImplPatternMaxPos( rStr, rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
     446           0 :     return nNewPos;
     447             : }
     448             : 
     449           0 : static bool ImplPatternProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
     450             :                                         const OString& rEditMask,
     451             :                                         const OUString& rLiteralMask,
     452             :                                         bool bStrictFormat,
     453             :                                         sal_uInt16 nFormatFlags,
     454             :                                         bool bSameMask,
     455             :                                         bool& rbInKeyInput )
     456             : {
     457           0 :     if ( rEditMask.isEmpty() || !bStrictFormat )
     458           0 :         return false;
     459             : 
     460           0 :     Selection   aOldSel     = pEdit->GetSelection();
     461           0 :     vcl::KeyCode aCode      = rKEvt.GetKeyCode();
     462           0 :     sal_Unicode cChar       = rKEvt.GetCharCode();
     463           0 :     sal_uInt16      nKeyCode    = aCode.GetCode();
     464           0 :     bool        bShift      = aCode.IsShift();
     465           0 :     sal_Int32  nCursorPos = static_cast<sal_Int32>(aOldSel.Max());
     466             :     sal_Int32  nNewPos;
     467             :     sal_Int32  nTempPos;
     468             : 
     469           0 :     if ( nKeyCode && !aCode.IsMod1() && !aCode.IsMod2() )
     470             :     {
     471           0 :         if ( nKeyCode == KEY_LEFT )
     472             :         {
     473           0 :             Selection aSel( ImplPatternLeftPos( rEditMask, nCursorPos ) );
     474           0 :             if ( bShift )
     475           0 :                 aSel.Min() = aOldSel.Min();
     476           0 :             pEdit->SetSelection( aSel );
     477           0 :             return true;
     478             :         }
     479           0 :         else if ( nKeyCode == KEY_RIGHT )
     480             :         {
     481             :             // Use the start of selection as minimum; even a small position is allowed in case that
     482             :             // all was selected by the focus
     483           0 :             Selection aSel( aOldSel );
     484           0 :             aSel.Justify();
     485           0 :             nCursorPos = aSel.Min();
     486           0 :             aSel.Max() = ImplPatternRightPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos );
     487           0 :             if ( bShift )
     488           0 :                 aSel.Min() = aOldSel.Min();
     489             :             else
     490           0 :                 aSel.Min() = aSel.Max();
     491           0 :             pEdit->SetSelection( aSel );
     492           0 :             return true;
     493             :         }
     494           0 :         else if ( nKeyCode == KEY_HOME )
     495             :         {
     496             :             // Home is the position of the first non-literal character
     497           0 :             nNewPos = 0;
     498           0 :             while ( (nNewPos < rEditMask.getLength()) &&
     499           0 :                     (rEditMask[nNewPos] == EDITMASK_LITERAL) )
     500           0 :                 nNewPos++;
     501             : 
     502             :             // Home should not move to the right
     503           0 :             if ( nCursorPos < nNewPos )
     504           0 :                 nNewPos = nCursorPos;
     505           0 :             Selection aSel( nNewPos );
     506           0 :             if ( bShift )
     507           0 :                 aSel.Min() = aOldSel.Min();
     508           0 :             pEdit->SetSelection( aSel );
     509           0 :             return true;
     510             :         }
     511           0 :         else if ( nKeyCode == KEY_END )
     512             :         {
     513             :             // End is position of last non-literal character
     514           0 :             nNewPos = rEditMask.getLength();
     515           0 :             while ( nNewPos &&
     516           0 :                     (rEditMask[nNewPos-1] == EDITMASK_LITERAL) )
     517           0 :                 nNewPos--;
     518             :             // Use the start of selection as minimum; even a small position is allowed in case that
     519             :             // all was selected by the focus
     520           0 :             Selection aSel( aOldSel );
     521           0 :             aSel.Justify();
     522           0 :             nCursorPos = static_cast<sal_Int32>(aSel.Min());
     523           0 :             ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
     524           0 :             aSel.Max() = nNewPos;
     525           0 :             if ( bShift )
     526           0 :                 aSel.Min() = aOldSel.Min();
     527             :             else
     528           0 :                 aSel.Min() = aSel.Max();
     529           0 :             pEdit->SetSelection( aSel );
     530           0 :             return true;
     531             :         }
     532           0 :         else if ( (nKeyCode == KEY_BACKSPACE) || (nKeyCode == KEY_DELETE) )
     533             :         {
     534           0 :             OUString          aOldStr( pEdit->GetText() );
     535           0 :             OUStringBuffer    aStr( aOldStr );
     536           0 :             Selection   aSel = aOldSel;
     537             : 
     538           0 :             aSel.Justify();
     539           0 :             nNewPos = static_cast<sal_Int32>(aSel.Min());
     540             : 
     541             :              // if selection then delete it
     542           0 :             if ( aSel.Len() )
     543             :             {
     544           0 :                 if ( bSameMask )
     545           0 :                     aStr.remove( static_cast<sal_Int32>(aSel.Min()), static_cast<sal_Int32>(aSel.Len()) );
     546             :                 else
     547             :                 {
     548           0 :                     OUString aRep = rLiteralMask.copy( static_cast<sal_Int32>(aSel.Min()), static_cast<sal_Int32>(aSel.Len()) );
     549           0 :                     aStr.remove( aSel.Min(), aRep.getLength() );
     550           0 :                     aStr.insert( aSel.Min(), aRep );
     551             :                 }
     552             :             }
     553             :             else
     554             :             {
     555           0 :                 if ( nKeyCode == KEY_BACKSPACE )
     556             :                 {
     557           0 :                     nTempPos = nNewPos;
     558           0 :                     nNewPos = ImplPatternLeftPos( rEditMask, nTempPos );
     559             :                 }
     560             :                 else
     561           0 :                     nTempPos = ImplPatternRightPos( aStr.toString(), rEditMask, nFormatFlags, bSameMask, nNewPos );
     562             : 
     563           0 :                 if ( nNewPos != nTempPos )
     564             :                 {
     565           0 :                     if ( bSameMask )
     566             :                     {
     567           0 :                         if ( rEditMask[nNewPos] != EDITMASK_LITERAL )
     568           0 :                             aStr.remove( nNewPos, 1 );
     569             :                     }
     570             :                     else
     571             :                     {
     572           0 :                         aStr[nNewPos] = rLiteralMask[nNewPos];
     573             :                     }
     574             :                 }
     575             :             }
     576             : 
     577           0 :             if ( aOldStr != aStr.toString() )
     578             :             {
     579           0 :                 if ( bSameMask )
     580           0 :                     aStr = ImplPatternReformat( aStr.toString(), rEditMask, rLiteralMask, nFormatFlags );
     581           0 :                 rbInKeyInput = true;
     582           0 :                 pEdit->SetText( aStr.toString(), Selection( nNewPos ) );
     583           0 :                 pEdit->SetModifyFlag();
     584           0 :                 pEdit->Modify();
     585           0 :                 rbInKeyInput = false;
     586             :             }
     587             :             else
     588           0 :                 pEdit->SetSelection( Selection( nNewPos ) );
     589             : 
     590           0 :             return true;
     591             :         }
     592           0 :         else if ( nKeyCode == KEY_INSERT )
     593             :         {
     594             :             // you can only set InsertModus for a PatternField if the
     595             :             // mask is equal at all input positions
     596           0 :             if ( !bSameMask )
     597             :             {
     598           0 :                 return true;
     599             :             }
     600             :         }
     601             :     }
     602             : 
     603           0 :     if ( rKEvt.GetKeyCode().IsMod2() || (cChar < 32) || (cChar == 127) )
     604           0 :         return false;
     605             : 
     606           0 :     Selection aSel = aOldSel;
     607           0 :     aSel.Justify();
     608           0 :     nNewPos = aSel.Min();
     609             : 
     610           0 :     if ( nNewPos < rEditMask.getLength() )
     611             :     {
     612           0 :         sal_Unicode cPattChar = ImplPatternChar( cChar, rEditMask[nNewPos] );
     613           0 :         if ( cPattChar )
     614           0 :             cChar = cPattChar;
     615             :         else
     616             :         {
     617             :             // If no valid character, check if the user wanted to jump to next literal. We do this
     618             :             // only if we're after a character, so that literals that were skipped automatically
     619             :             // do not influence the position anymore.
     620           0 :             if ( nNewPos &&
     621           0 :                  (rEditMask[nNewPos-1] != EDITMASK_LITERAL) &&
     622           0 :                  !aSel.Len() )
     623             :             {
     624             :                 // search for next character not being a literal
     625           0 :                 nTempPos = nNewPos;
     626           0 :                 while ( nTempPos < rEditMask.getLength() )
     627             :                 {
     628           0 :                     if ( rEditMask[nTempPos] == EDITMASK_LITERAL )
     629             :                     {
     630             :                         // only valid if no literal present
     631           0 :                         if ( (rEditMask[nTempPos+1] != EDITMASK_LITERAL ) &&
     632           0 :                              ImplCommaPointCharEqual( cChar, rLiteralMask[nTempPos] ) )
     633             :                         {
     634           0 :                             nTempPos++;
     635           0 :                             ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nNewPos, nTempPos );
     636           0 :                             if ( nTempPos > nNewPos )
     637             :                             {
     638           0 :                                 pEdit->SetSelection( Selection( nTempPos ) );
     639           0 :                                 return true;
     640             :                             }
     641             :                         }
     642           0 :                         break;
     643             :                     }
     644           0 :                     nTempPos++;
     645             :                 }
     646             :             }
     647             : 
     648           0 :             cChar = 0;
     649             :         }
     650             :     }
     651             :     else
     652           0 :         cChar = 0;
     653           0 :     if ( cChar )
     654             :     {
     655           0 :         OUStringBuffer  aStr = pEdit->GetText();
     656           0 :         bool        bError = false;
     657           0 :         if ( bSameMask && pEdit->IsInsertMode() )
     658             :         {
     659             :             // crop spaces and literals at the end until current position
     660           0 :             sal_Int32 n = aStr.getLength();
     661           0 :             while ( n && (n > nNewPos) )
     662             :             {
     663           0 :                 if ( (aStr[n-1] != ' ') &&
     664           0 :                      ((n > rEditMask.getLength()) || (rEditMask[n-1] != EDITMASK_LITERAL)) )
     665           0 :                     break;
     666             : 
     667           0 :                 n--;
     668             :             }
     669           0 :             aStr.truncate( n );
     670             : 
     671           0 :             if ( aSel.Len() )
     672           0 :                 aStr.remove( aSel.Min(), aSel.Len() );
     673             : 
     674           0 :             if ( aStr.getLength() < rEditMask.getLength() )
     675             :             {
     676             :                 // possibly extend string until cursor position
     677           0 :                 if ( aStr.getLength() < nNewPos )
     678           0 :                     aStr.append( rLiteralMask.copy( aStr.getLength(), nNewPos-aStr.getLength() ));
     679           0 :                 if ( nNewPos < aStr.getLength() )
     680           0 :                     aStr.insert( cChar, nNewPos );
     681           0 :                 else if ( nNewPos < rEditMask.getLength() )
     682           0 :                     aStr.append(cChar);
     683           0 :                 aStr = ImplPatternReformat( aStr.toString(), rEditMask, rLiteralMask, nFormatFlags );
     684             :             }
     685             :             else
     686           0 :                 bError = true;
     687             :         }
     688             :         else
     689             :         {
     690           0 :             if ( aSel.Len() )
     691             :             {
     692             :                 // delete selection
     693           0 :                 OUString aRep = rLiteralMask.copy( aSel.Min(), aSel.Len() );
     694           0 :                 aStr.remove( aSel.Min(), aRep.getLength() );
     695           0 :                 aStr.insert( aSel.Min(), aRep );
     696             :             }
     697             : 
     698           0 :             if ( nNewPos < aStr.getLength() )
     699           0 :                 aStr[nNewPos] = cChar;
     700           0 :             else if ( nNewPos < rEditMask.getLength() )
     701           0 :                 aStr.append(cChar);
     702             :         }
     703             : 
     704           0 :         if ( !bError )
     705             :         {
     706           0 :             rbInKeyInput = true;
     707           0 :             Selection aNewSel( ImplPatternRightPos( aStr.toString(), rEditMask, nFormatFlags, bSameMask, nNewPos ) );
     708           0 :             pEdit->SetText( aStr.toString(), aNewSel );
     709           0 :             pEdit->SetModifyFlag();
     710           0 :             pEdit->Modify();
     711           0 :             rbInKeyInput = false;
     712           0 :         }
     713             :     }
     714             : 
     715           0 :     return true;
     716             : }
     717             : 
     718         160 : void PatternFormatter::ImplSetMask(const OString& rEditMask, const OUString& rLiteralMask)
     719             : {
     720         160 :     m_aEditMask     = rEditMask;
     721         160 :     maLiteralMask   = rLiteralMask;
     722         160 :     mbSameMask      = true;
     723             : 
     724         160 :     if ( m_aEditMask.getLength() != maLiteralMask.getLength() )
     725             :     {
     726          28 :         OUStringBuffer aBuf(maLiteralMask);
     727          28 :         if (m_aEditMask.getLength() < aBuf.getLength())
     728           0 :             aBuf.remove(m_aEditMask.getLength(), aBuf.getLength() - m_aEditMask.getLength());
     729             :         else
     730          28 :             comphelper::string::padToLength(aBuf, m_aEditMask.getLength(), ' ');
     731          28 :         maLiteralMask = aBuf.makeStringAndClear();
     732             :     }
     733             : 
     734             :     // Strict mode allows only the input mode if only equal characters are allowed as mask and if
     735             :     // only spaces are specified which are not allowed by the mask
     736         160 :     sal_Int32   i = 0;
     737         160 :     sal_Char    c = 0;
     738         362 :     while ( i < rEditMask.getLength() )
     739             :     {
     740         100 :         sal_Char cTemp = rEditMask[i];
     741         100 :         if ( cTemp != EDITMASK_LITERAL )
     742             :         {
     743         100 :             if ( (cTemp == EDITMASK_ALLCHAR) ||
     744         100 :                  (cTemp == EDITMASK_UPPERALLCHAR) ||
     745             :                  (cTemp == EDITMASK_NUMSPACE) )
     746             :             {
     747           0 :                 mbSameMask = false;
     748           0 :                 break;
     749             :             }
     750         100 :             if ( i < rLiteralMask.getLength() )
     751             :             {
     752          60 :                 if ( rLiteralMask[i] != ' ' )
     753             :                 {
     754          52 :                     mbSameMask = false;
     755          52 :                     break;
     756             :                 }
     757             :             }
     758          48 :             if ( !c )
     759          18 :                 c = cTemp;
     760          48 :             if ( cTemp != c )
     761             :             {
     762           6 :                 mbSameMask = false;
     763           6 :                 break;
     764             :             }
     765             :         }
     766          42 :         i++;
     767             :     }
     768         160 : }
     769             : 
     770          16 : PatternFormatter::PatternFormatter()
     771             : {
     772          16 :     mnFormatFlags       = 0;
     773          16 :     mbSameMask          = true;
     774          16 :     mbInPattKeyInput    = false;
     775          16 : }
     776             : 
     777          16 : PatternFormatter::~PatternFormatter()
     778             : {
     779          16 : }
     780             : 
     781         160 : void PatternFormatter::SetMask( const OString& rEditMask,
     782             :                                 const OUString& rLiteralMask )
     783             : {
     784         160 :     ImplSetMask( rEditMask, rLiteralMask );
     785         160 :     ReformatAll();
     786         160 : }
     787             : 
     788         160 : void PatternFormatter::SetString( const OUString& rStr )
     789             : {
     790         160 :     maFieldString = rStr;
     791         160 :     if ( GetField() )
     792             :     {
     793         160 :         GetField()->SetText( rStr );
     794         160 :         MarkToBeReformatted( false );
     795             :     }
     796         160 : }
     797             : 
     798           0 : OUString PatternFormatter::GetString() const
     799             : {
     800           0 :     if ( !GetField() )
     801           0 :         return OUString();
     802             :     else
     803           0 :         return ImplPatternReformat( GetField()->GetText(), m_aEditMask, maLiteralMask, mnFormatFlags );
     804             : }
     805             : 
     806         190 : void PatternFormatter::Reformat()
     807             : {
     808         190 :     if ( GetField() )
     809             :     {
     810         190 :         ImplSetText( ImplPatternReformat( GetField()->GetText(), m_aEditMask, maLiteralMask, mnFormatFlags ) );
     811         190 :         if ( !mbSameMask && IsStrictFormat() && !GetField()->IsReadOnly() )
     812           0 :             GetField()->SetInsertMode( false );
     813             :     }
     814         190 : }
     815             : 
     816          16 : PatternField::PatternField( vcl::Window* pParent, WinBits nWinStyle ) :
     817          16 :     SpinField( pParent, nWinStyle )
     818             : {
     819          16 :     SetField( this );
     820          16 :     Reformat();
     821          16 : }
     822             : 
     823          32 : PatternField::~PatternField()
     824             : {
     825          32 : }
     826             : 
     827           0 : bool PatternField::PreNotify( NotifyEvent& rNEvt )
     828             : {
     829           0 :     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
     830             :     {
     831           0 :         if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
     832           0 :                                          IsStrictFormat(), GetFormatFlags(),
     833           0 :                                          ImplIsSameMask(), ImplGetInPattKeyInput() ) )
     834           0 :             return true;
     835             :     }
     836             : 
     837           0 :     return SpinField::PreNotify( rNEvt );
     838             : }
     839             : 
     840          16 : bool PatternField::Notify( NotifyEvent& rNEvt )
     841             : {
     842          16 :     if ( rNEvt.GetType() == EVENT_GETFOCUS )
     843           0 :         MarkToBeReformatted( false );
     844          16 :     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
     845             :     {
     846           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
     847           0 :             Reformat();
     848             :     }
     849             : 
     850          16 :     return SpinField::Notify( rNEvt );
     851             : }
     852             : 
     853           0 : void PatternField::Modify()
     854             : {
     855           0 :     if ( !ImplGetInPattKeyInput() )
     856             :     {
     857           0 :         if ( IsStrictFormat() )
     858           0 :             ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
     859             :         else
     860           0 :             MarkToBeReformatted( true );
     861             :     }
     862             : 
     863           0 :     SpinField::Modify();
     864           0 : }
     865             : 
     866           0 : PatternBox::PatternBox( vcl::Window* pParent, WinBits nWinStyle ) :
     867           0 :     ComboBox( pParent, nWinStyle )
     868             : {
     869           0 :     SetField( this );
     870           0 :     Reformat();
     871           0 : }
     872             : 
     873           0 : PatternBox::~PatternBox()
     874             : {
     875           0 : }
     876             : 
     877           0 : bool PatternBox::PreNotify( NotifyEvent& rNEvt )
     878             : {
     879           0 :     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
     880             :     {
     881           0 :         if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
     882           0 :                                          IsStrictFormat(), GetFormatFlags(),
     883           0 :                                          ImplIsSameMask(), ImplGetInPattKeyInput() ) )
     884           0 :             return true;
     885             :     }
     886             : 
     887           0 :     return ComboBox::PreNotify( rNEvt );
     888             : }
     889             : 
     890           0 : bool PatternBox::Notify( NotifyEvent& rNEvt )
     891             : {
     892           0 :     if ( rNEvt.GetType() == EVENT_GETFOCUS )
     893           0 :         MarkToBeReformatted( false );
     894           0 :     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
     895             :     {
     896           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
     897           0 :             Reformat();
     898             :     }
     899             : 
     900           0 :     return ComboBox::Notify( rNEvt );
     901             : }
     902             : 
     903           0 : void PatternBox::Modify()
     904             : {
     905           0 :     if ( !ImplGetInPattKeyInput() )
     906             :     {
     907           0 :         if ( IsStrictFormat() )
     908           0 :             ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
     909             :         else
     910           0 :             MarkToBeReformatted( true );
     911             :     }
     912             : 
     913           0 :     ComboBox::Modify();
     914           0 : }
     915             : 
     916           0 : void PatternBox::ReformatAll()
     917             : {
     918           0 :     OUString aStr;
     919           0 :     SetUpdateMode( false );
     920           0 :     sal_uInt16 nEntryCount = GetEntryCount();
     921           0 :     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
     922             :     {
     923           0 :         aStr = ImplPatternReformat( GetEntry( i ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
     924           0 :         RemoveEntryAt(i);
     925           0 :         InsertEntry( aStr, i );
     926             :     }
     927           0 :     PatternFormatter::Reformat();
     928           0 :     SetUpdateMode( true );
     929           0 : }
     930             : 
     931           8 : static ExtDateFieldFormat ImplGetExtFormat( DateFormat eOld )
     932             : {
     933           8 :     switch( eOld )
     934             :     {
     935           0 :         case DMY:   return XTDATEF_SHORT_DDMMYY;
     936           8 :         case MDY:   return XTDATEF_SHORT_MMDDYY;
     937           0 :         default:    return XTDATEF_SHORT_YYMMDD;
     938             :     }
     939             : }
     940             : 
     941         332 : static sal_uInt16 ImplCutNumberFromString( OUString& rStr )
     942             : {
     943         332 :     sal_Int32 i1 = 0;
     944        2194 :     while (i1 != rStr.getLength() && !(rStr[i1] >= '0' && rStr[i1] <= '9')) {
     945        1530 :         ++i1;
     946             :     }
     947         332 :     sal_Int32 i2 = i1;
     948        1348 :     while (i2 != rStr.getLength() && rStr[i2] >= '0' && rStr[i2] <= '9') {
     949         684 :         ++i2;
     950             :     }
     951         332 :     sal_Int32 nValue = rStr.copy(i1, i2-i1).toInt32();
     952         332 :     rStr = rStr.copy(std::min(i2+1, rStr.getLength()));
     953         332 :     return nValue;
     954             : }
     955             : 
     956        1736 : static bool ImplCutMonthName( OUString& rStr, const OUString& _rLookupMonthName )
     957             : {
     958        1736 :     sal_Int32 index = 0;
     959        1736 :     rStr = rStr.replaceFirst(_rLookupMonthName, OUString(), &index);
     960        1736 :     return index >= 0;
     961             : }
     962             : 
     963         156 : static sal_uInt16 ImplCutMonthFromString( OUString& rStr, const CalendarWrapper& rCalendarWrapper )
     964             : {
     965             :     // search for a month' name
     966         956 :     for ( sal_uInt16 i=1; i <= 12; i++ )
     967             :     {
     968         936 :         OUString aMonthName = rCalendarWrapper.getMonths()[i-1].FullName;
     969             :         // long month name?
     970         936 :         if ( ImplCutMonthName( rStr, aMonthName ) )
     971         136 :             return i;
     972             : 
     973             :         // short month name?
     974        1600 :         OUString aAbbrevMonthName = rCalendarWrapper.getMonths()[i-1].AbbrevName;
     975         800 :         if ( ImplCutMonthName( rStr, aAbbrevMonthName ) )
     976           0 :             return i;
     977         800 :     }
     978             : 
     979          20 :     return ImplCutNumberFromString( rStr );
     980             : }
     981             : 
     982         974 : static OUString ImplGetDateSep( const LocaleDataWrapper& rLocaleDataWrapper, ExtDateFieldFormat eFormat )
     983             : {
     984         974 :     if ( ( eFormat == XTDATEF_SHORT_YYMMDD_DIN5008 ) || ( eFormat == XTDATEF_SHORT_YYYYMMDD_DIN5008 ) )
     985           0 :         return OUString("-");
     986             :     else
     987         974 :         return rLocaleDataWrapper.getDateSep();
     988             : }
     989             : 
     990           0 : static bool ImplDateProcessKeyInput( Edit*, const KeyEvent& rKEvt, ExtDateFieldFormat eFormat,
     991             :                                      const LocaleDataWrapper& rLocaleDataWrapper  )
     992             : {
     993           0 :     sal_Unicode cChar = rKEvt.GetCharCode();
     994           0 :     sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
     995           0 :     if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
     996           0 :          (nGroup == KEYGROUP_MISC)||
     997           0 :          ((cChar >= '0') && (cChar <= '9')) ||
     998           0 :          (cChar == ImplGetDateSep( rLocaleDataWrapper, eFormat )[0]) )
     999           0 :         return false;
    1000             :     else
    1001           0 :         return true;
    1002             : }
    1003             : 
    1004         748 : static bool ImplDateGetValue( const OUString& rStr, Date& rDate, ExtDateFieldFormat eDateFormat,
    1005             :                               const LocaleDataWrapper& rLocaleDataWrapper, const CalendarWrapper& rCalendarWrapper,
    1006             :                               const AllSettings& )
    1007             : {
    1008         748 :     sal_uInt16 nDay = 0;
    1009         748 :     sal_uInt16 nMonth = 0;
    1010         748 :     sal_uInt16 nYear = 0;
    1011         748 :     bool bYear = true;
    1012         748 :     bool bError = false;
    1013         748 :     OUString aStr( rStr );
    1014             : 
    1015         748 :     if ( eDateFormat == XTDATEF_SYSTEM_LONG )
    1016             :     {
    1017         156 :         DateFormat eFormat = rLocaleDataWrapper.getLongDateFormat();
    1018         156 :         switch( eFormat )
    1019             :         {
    1020             :             case MDY:
    1021         156 :                 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
    1022         156 :                 nDay = ImplCutNumberFromString( aStr );
    1023         156 :                 nYear  = ImplCutNumberFromString( aStr );
    1024         156 :                 break;
    1025             :             case DMY:
    1026           0 :                 nDay = ImplCutNumberFromString( aStr );
    1027           0 :                 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
    1028           0 :                 nYear  = ImplCutNumberFromString( aStr );
    1029           0 :                 break;
    1030             :             case YMD:
    1031             :             default:
    1032           0 :                 nYear = ImplCutNumberFromString( aStr );
    1033           0 :                 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
    1034           0 :                 nDay  = ImplCutNumberFromString( aStr );
    1035           0 :                 break;
    1036             :         }
    1037             :     }
    1038             :     else
    1039             :     {
    1040             :         // Check if year is present:
    1041         592 :         OUString aDateSep = ImplGetDateSep( rLocaleDataWrapper, eDateFormat );
    1042         592 :         sal_Int32 nSepPos = aStr.indexOf( aDateSep );
    1043         592 :         if ( nSepPos < 0 )
    1044           6 :             return false;
    1045         586 :         nSepPos = aStr.indexOf( aDateSep, nSepPos+1 );
    1046         586 :         if ( ( nSepPos < 0 ) || ( nSepPos == (aStr.getLength()-1) ) )
    1047             :         {
    1048           0 :             bYear = false;
    1049           0 :             nYear = Date( Date::SYSTEM ).GetYear();
    1050             :         }
    1051             : 
    1052         586 :         const sal_Unicode* pBuf = aStr.getStr();
    1053         586 :         ImplSkipDelimiters( pBuf );
    1054             : 
    1055         586 :         switch ( eDateFormat )
    1056             :         {
    1057             :             case XTDATEF_SHORT_DDMMYY:
    1058             :             case XTDATEF_SHORT_DDMMYYYY:
    1059             :             {
    1060          42 :                 nDay = ImplGetNum( pBuf, bError );
    1061          42 :                 ImplSkipDelimiters( pBuf );
    1062          42 :                 nMonth = ImplGetNum( pBuf, bError );
    1063          42 :                 ImplSkipDelimiters( pBuf );
    1064          42 :                 if ( bYear )
    1065          42 :                     nYear = ImplGetNum( pBuf, bError );
    1066             :             }
    1067          42 :             break;
    1068             :             case XTDATEF_SHORT_MMDDYY:
    1069             :             case XTDATEF_SHORT_MMDDYYYY:
    1070             :             {
    1071         544 :                 nMonth = ImplGetNum( pBuf, bError );
    1072         544 :                 ImplSkipDelimiters( pBuf );
    1073         544 :                 nDay = ImplGetNum( pBuf, bError );
    1074         544 :                 ImplSkipDelimiters( pBuf );
    1075         544 :                 if ( bYear )
    1076         544 :                     nYear = ImplGetNum( pBuf, bError );
    1077             :             }
    1078         544 :             break;
    1079             :             case XTDATEF_SHORT_YYMMDD:
    1080             :             case XTDATEF_SHORT_YYYYMMDD:
    1081             :             case XTDATEF_SHORT_YYMMDD_DIN5008:
    1082             :             case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1083             :             {
    1084           0 :                 if ( bYear )
    1085           0 :                     nYear = ImplGetNum( pBuf, bError );
    1086           0 :                 ImplSkipDelimiters( pBuf );
    1087           0 :                 nMonth = ImplGetNum( pBuf, bError );
    1088           0 :                 ImplSkipDelimiters( pBuf );
    1089           0 :                 nDay = ImplGetNum( pBuf, bError );
    1090             :             }
    1091           0 :             break;
    1092             : 
    1093             :             default:
    1094             :             {
    1095             :                 OSL_FAIL( "DateFormat???" );
    1096             :             }
    1097         586 :         }
    1098             :     }
    1099             : 
    1100         742 :     if ( bError || !nDay || !nMonth )
    1101         272 :         return false;
    1102             : 
    1103         470 :     Date aNewDate( nDay, nMonth, nYear );
    1104         470 :     DateFormatter::ExpandCentury( aNewDate, utl::MiscCfg().GetYear2000() );
    1105         470 :     if ( aNewDate.IsValidDate() )
    1106             :     {
    1107         470 :         rDate = aNewDate;
    1108         470 :         return true;
    1109             :     }
    1110           0 :     return false;
    1111             : }
    1112             : 
    1113         330 : bool DateFormatter::ImplDateReformat( const OUString& rStr, OUString& rOutStr, const AllSettings& rSettings )
    1114             : {
    1115         330 :     Date aDate( 0, 0, 0 );
    1116         330 :     if ( !ImplDateGetValue( rStr, aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
    1117         146 :         return true;
    1118             : 
    1119         184 :     Date aTempDate = aDate;
    1120         184 :     if ( aTempDate > GetMax() )
    1121          54 :         aTempDate = GetMax();
    1122         130 :     else if ( aTempDate < GetMin() )
    1123           4 :         aTempDate = GetMin();
    1124             : 
    1125         184 :     if ( GetErrorHdl().IsSet() && (aDate != aTempDate) )
    1126             :     {
    1127           0 :         maCorrectedDate = aTempDate;
    1128           0 :         if( !GetErrorHdl().Call( this ) )
    1129             :         {
    1130           0 :             maCorrectedDate = Date( Date::SYSTEM );
    1131           0 :             return false;
    1132             :         }
    1133             :         else
    1134           0 :             maCorrectedDate = Date( Date::SYSTEM );
    1135             :     }
    1136             : 
    1137         184 :     rOutStr = ImplGetDateAsText( aTempDate, rSettings );
    1138             : 
    1139         184 :     return true;
    1140             : }
    1141             : 
    1142         382 : OUString DateFormatter::ImplGetDateAsText( const Date& rDate,
    1143             :                                            const AllSettings& ) const
    1144             : {
    1145         382 :     bool bShowCentury = false;
    1146         382 :     switch ( GetExtDateFormat() )
    1147             :     {
    1148             :         case XTDATEF_SYSTEM_SHORT_YYYY:
    1149             :         case XTDATEF_SYSTEM_LONG:
    1150             :         case XTDATEF_SHORT_DDMMYYYY:
    1151             :         case XTDATEF_SHORT_MMDDYYYY:
    1152             :         case XTDATEF_SHORT_YYYYMMDD:
    1153             :         case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1154             :         {
    1155         158 :             bShowCentury = true;
    1156             :         }
    1157         158 :         break;
    1158             :         default:
    1159             :         {
    1160         224 :             bShowCentury = false;
    1161             :         }
    1162             :     }
    1163             : 
    1164         382 :     if ( !bShowCentury )
    1165             :     {
    1166             :         // Check if I have to use force showing the century
    1167         224 :         sal_uInt16 nTwoDigitYearStart = utl::MiscCfg().GetYear2000();
    1168         224 :         sal_uInt16 nYear = rDate.GetYear();
    1169             : 
    1170             :         // If year is not in double digit range
    1171         224 :         if ( (nYear < nTwoDigitYearStart) || (nYear >= nTwoDigitYearStart+100) )
    1172          88 :             bShowCentury = true;
    1173             :     }
    1174             : 
    1175             :     sal_Unicode aBuf[128];
    1176         382 :     sal_Unicode* pBuf = aBuf;
    1177             : 
    1178         382 :     OUString aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), GetExtDateFormat( true ) );
    1179         382 :     sal_uInt16 nDay = rDate.GetDay();
    1180         382 :     sal_uInt16 nMonth = rDate.GetMonth();
    1181         382 :     sal_uInt16 nYear = rDate.GetYear();
    1182         382 :     sal_uInt16 nYearLen = bShowCentury ? 4 : 2;
    1183             : 
    1184         382 :     if ( !bShowCentury )
    1185         136 :         nYear %= 100;
    1186             : 
    1187         382 :     switch ( GetExtDateFormat( true ) )
    1188             :     {
    1189             :         case XTDATEF_SYSTEM_LONG:
    1190             :         {
    1191          70 :             return ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, false, 1, !bShowCentury );
    1192             :         }
    1193             :         case XTDATEF_SHORT_DDMMYY:
    1194             :         case XTDATEF_SHORT_DDMMYYYY:
    1195             :         {
    1196          22 :             pBuf = ImplAddNum( pBuf, nDay, 2 );
    1197          22 :             pBuf = ImplAddString( pBuf, aDateSep );
    1198          22 :             pBuf = ImplAddNum( pBuf, nMonth, 2 );
    1199          22 :             pBuf = ImplAddString( pBuf, aDateSep );
    1200          22 :             pBuf = ImplAddNum( pBuf, nYear, nYearLen );
    1201             :         }
    1202          22 :         break;
    1203             :         case XTDATEF_SHORT_MMDDYY:
    1204             :         case XTDATEF_SHORT_MMDDYYYY:
    1205             :         {
    1206         290 :             pBuf = ImplAddNum( pBuf, nMonth, 2 );
    1207         290 :             pBuf = ImplAddString( pBuf, aDateSep );
    1208         290 :             pBuf = ImplAddNum( pBuf, nDay, 2 );
    1209         290 :             pBuf = ImplAddString( pBuf, aDateSep );
    1210         290 :             pBuf = ImplAddNum( pBuf, nYear, nYearLen );
    1211             :         }
    1212         290 :         break;
    1213             :         case XTDATEF_SHORT_YYMMDD:
    1214             :         case XTDATEF_SHORT_YYYYMMDD:
    1215             :         case XTDATEF_SHORT_YYMMDD_DIN5008:
    1216             :         case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1217             :         {
    1218           0 :             pBuf = ImplAddNum( pBuf, nYear, nYearLen );
    1219           0 :             pBuf = ImplAddString( pBuf, aDateSep );
    1220           0 :             pBuf = ImplAddNum( pBuf, nMonth, 2 );
    1221           0 :             pBuf = ImplAddString( pBuf, aDateSep );
    1222           0 :             pBuf = ImplAddNum( pBuf, nDay, 2 );
    1223             :         }
    1224           0 :         break;
    1225             :         default:
    1226             :         {
    1227             :             OSL_FAIL( "DateFormat???" );
    1228             :         }
    1229             :     }
    1230             : 
    1231         312 :     return OUString(aBuf, pBuf-aBuf);
    1232             : }
    1233             : 
    1234           4 : static void ImplDateIncrementDay( Date& rDate, bool bUp )
    1235             : {
    1236           4 :     DateFormatter::ExpandCentury( rDate );
    1237             : 
    1238           4 :     if ( bUp )
    1239             :     {
    1240           4 :         if ( (rDate.GetDay() != 31) || (rDate.GetMonth() != 12) || (rDate.GetYear() != 9999) )
    1241           4 :             rDate++;
    1242             :     }
    1243             :     else
    1244             :     {
    1245           0 :         if ( (rDate.GetDay() != 1 ) || (rDate.GetMonth() != 1) || (rDate.GetYear() != 0) )
    1246           0 :             rDate--;
    1247             :     }
    1248           4 : }
    1249             : 
    1250           8 : static void ImplDateIncrementMonth( Date& rDate, bool bUp )
    1251             : {
    1252           8 :     DateFormatter::ExpandCentury( rDate );
    1253             : 
    1254           8 :     sal_uInt16 nMonth = rDate.GetMonth();
    1255           8 :     sal_uInt16 nYear = rDate.GetYear();
    1256           8 :     if ( bUp )
    1257             :     {
    1258           4 :         if ( (nMonth == 12) && (nYear < 9999) )
    1259             :         {
    1260           0 :             rDate.SetMonth( 1 );
    1261           0 :             rDate.SetYear( nYear + 1 );
    1262             :         }
    1263             :         else
    1264             :         {
    1265           4 :             if ( nMonth < 12 )
    1266           4 :                 rDate.SetMonth( nMonth + 1 );
    1267             :         }
    1268             :     }
    1269             :     else
    1270             :     {
    1271           4 :         if ( (nMonth == 1) && (nYear > 0) )
    1272             :         {
    1273           0 :             rDate.SetMonth( 12 );
    1274           0 :             rDate.SetYear( nYear - 1 );
    1275             :         }
    1276             :         else
    1277             :         {
    1278           4 :             if ( nMonth > 1 )
    1279           4 :                 rDate.SetMonth( nMonth - 1 );
    1280             :         }
    1281             :     }
    1282             : 
    1283           8 :     sal_uInt16 nDaysInMonth = Date::GetDaysInMonth( rDate.GetMonth(), rDate.GetYear());
    1284           8 :     if ( rDate.GetDay() > nDaysInMonth )
    1285           0 :         rDate.SetDay( nDaysInMonth );
    1286           8 : }
    1287             : 
    1288           0 : static void ImplDateIncrementYear( Date& rDate, bool bUp )
    1289             : {
    1290           0 :     DateFormatter::ExpandCentury( rDate );
    1291             : 
    1292           0 :     sal_uInt16 nYear = rDate.GetYear();
    1293           0 :     sal_uInt16 nMonth = rDate.GetMonth();
    1294           0 :     if ( bUp )
    1295             :     {
    1296           0 :         if ( nYear < 9999 )
    1297           0 :             rDate.SetYear( nYear + 1 );
    1298             :     }
    1299             :     else
    1300             :     {
    1301           0 :         if ( nYear > 0 )
    1302           0 :             rDate.SetYear( nYear - 1 );
    1303             :     }
    1304           0 :     if (nMonth == 2)
    1305             :     {
    1306             :         // Handle February 29 from leap year to non-leap year.
    1307           0 :         sal_uInt16 nDay = rDate.GetDay();
    1308           0 :         if (nDay > 28)
    1309             :         {
    1310             :             // The check would not be necessary if it was guaranteed that the
    1311             :             // date was valid before and actually was a leap year,
    1312             :             // de-/incrementing a leap year with 29 always results in 28.
    1313           0 :             sal_uInt16 nDaysInMonth = Date::GetDaysInMonth( nMonth, rDate.GetYear());
    1314           0 :             if (nDay > nDaysInMonth)
    1315           0 :                 rDate.SetDay( nDaysInMonth);
    1316             :         }
    1317             :     }
    1318           0 : }
    1319             : 
    1320         100 : bool DateFormatter::ImplAllowMalformedInput() const
    1321             : {
    1322         100 :     return !IsEnforceValidValue();
    1323             : }
    1324             : 
    1325          12 : void DateField::ImplDateSpinArea( bool bUp )
    1326             : {
    1327             :     // increment days if all is selected
    1328          12 :     if ( GetField() )
    1329             :     {
    1330          12 :         Date aDate( GetDate() );
    1331          12 :         Selection aSelection = GetField()->GetSelection();
    1332          12 :         aSelection.Justify();
    1333          12 :         OUString aText( GetText() );
    1334          12 :         if ( (sal_Int32)aSelection.Len() == aText.getLength() )
    1335           4 :             ImplDateIncrementDay( aDate, bUp );
    1336             :         else
    1337             :         {
    1338           8 :             sal_Int8 nDateArea = 0;
    1339             : 
    1340           8 :             ExtDateFieldFormat eFormat = GetExtDateFormat( true );
    1341           8 :             if ( eFormat == XTDATEF_SYSTEM_LONG )
    1342             :             {
    1343           8 :                 eFormat = ImplGetExtFormat( ImplGetLocaleDataWrapper().getLongDateFormat() );
    1344           8 :                 nDateArea = 1;
    1345             :             }
    1346             :             else
    1347             :             {
    1348             :                 // search area
    1349           0 :                 sal_Int32 nPos = 0;
    1350           0 :                 OUString aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), eFormat );
    1351           0 :                 for ( sal_Int8 i = 1; i <= 3; i++ )
    1352             :                 {
    1353           0 :                     nPos = aText.indexOf( aDateSep, nPos );
    1354           0 :                     if ( nPos >= (sal_Int32)aSelection.Max() )
    1355             :                     {
    1356           0 :                         nDateArea = i;
    1357           0 :                         break;
    1358             :                     }
    1359             :                     else
    1360           0 :                         nPos++;
    1361           0 :                 }
    1362             :             }
    1363             : 
    1364           8 :             switch( eFormat )
    1365             :             {
    1366             :                 case XTDATEF_SHORT_MMDDYY:
    1367             :                 case XTDATEF_SHORT_MMDDYYYY:
    1368           8 :                 switch( nDateArea )
    1369             :                 {
    1370           8 :                     case 1: ImplDateIncrementMonth( aDate, bUp );
    1371           8 :                             break;
    1372           0 :                     case 2: ImplDateIncrementDay( aDate, bUp );
    1373           0 :                             break;
    1374           0 :                     case 3: ImplDateIncrementYear( aDate, bUp );
    1375           0 :                             break;
    1376             :                 }
    1377           8 :                 break;
    1378             :                 case XTDATEF_SHORT_DDMMYY:
    1379             :                 case XTDATEF_SHORT_DDMMYYYY:
    1380           0 :                 switch( nDateArea )
    1381             :                 {
    1382           0 :                     case 1: ImplDateIncrementDay( aDate, bUp );
    1383           0 :                             break;
    1384           0 :                     case 2: ImplDateIncrementMonth( aDate, bUp );
    1385           0 :                             break;
    1386           0 :                     case 3: ImplDateIncrementYear( aDate, bUp );
    1387           0 :                             break;
    1388             :                 }
    1389           0 :                 break;
    1390             :                 case XTDATEF_SHORT_YYMMDD:
    1391             :                 case XTDATEF_SHORT_YYYYMMDD:
    1392             :                 case XTDATEF_SHORT_YYMMDD_DIN5008:
    1393             :                 case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1394           0 :                 switch( nDateArea )
    1395             :                 {
    1396           0 :                     case 1: ImplDateIncrementYear( aDate, bUp );
    1397           0 :                             break;
    1398           0 :                     case 2: ImplDateIncrementMonth( aDate, bUp );
    1399           0 :                             break;
    1400           0 :                     case 3: ImplDateIncrementDay( aDate, bUp );
    1401           0 :                             break;
    1402             :                 }
    1403           0 :                 break;
    1404             :                 default:
    1405             :                     OSL_FAIL( "invalid conversion" );
    1406           0 :                     break;
    1407             :             }
    1408             :         }
    1409             : 
    1410          12 :         ImplNewFieldValue( aDate );
    1411             :     }
    1412          12 : }
    1413             : 
    1414          60 : void DateFormatter::ImplInit()
    1415             : {
    1416          60 :     mbLongFormat        = false;
    1417          60 :     mbShowDateCentury   = true;
    1418          60 :     mpCalendarWrapper   = NULL;
    1419          60 :     mnDateFormat        = 0xFFFF;
    1420          60 :     mnExtDateFormat     = XTDATEF_SYSTEM_SHORT;
    1421          60 : }
    1422             : 
    1423          60 : DateFormatter::DateFormatter() :
    1424             :     maFieldDate( 0 ),
    1425             :     maLastDate( 0 ),
    1426             :     maMin( 1, 1, 1900 ),
    1427             :     maMax( 31, 12, 2200 ),
    1428             :     maCorrectedDate( Date::SYSTEM ),
    1429          60 :     mbEnforceValidValue( true )
    1430             : {
    1431          60 :     ImplInit();
    1432          60 : }
    1433             : 
    1434           0 : void DateFormatter::ImplLoadRes( const ResId& rResId )
    1435             : {
    1436           0 :     ResMgr*     pMgr = rResId.GetResMgr();
    1437           0 :     if( pMgr )
    1438             :     {
    1439           0 :         sal_uLong       nMask = pMgr->ReadLong();
    1440             : 
    1441           0 :         if ( DATEFORMATTER_MIN & nMask )
    1442             :         {
    1443           0 :             maMin = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
    1444           0 :             pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
    1445             :         }
    1446           0 :         if ( DATEFORMATTER_MAX & nMask )
    1447             :         {
    1448           0 :             maMax = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
    1449           0 :             pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
    1450             :         }
    1451           0 :         if ( DATEFORMATTER_LONGFORMAT & nMask )
    1452           0 :             mbLongFormat = pMgr->ReadShort() != 0;
    1453             : 
    1454           0 :         if ( DATEFORMATTER_STRICTFORMAT & nMask )
    1455           0 :             SetStrictFormat( pMgr->ReadShort() != 0 );
    1456             : 
    1457           0 :         if ( DATEFORMATTER_VALUE & nMask )
    1458             :         {
    1459           0 :             maFieldDate = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
    1460           0 :             pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
    1461           0 :             if ( maFieldDate > maMax )
    1462           0 :                 maFieldDate = maMax;
    1463           0 :             if ( maFieldDate < maMin )
    1464           0 :                 maFieldDate = maMin;
    1465           0 :             maLastDate = maFieldDate;
    1466             :         }
    1467             :     }
    1468           0 : }
    1469             : 
    1470         120 : DateFormatter::~DateFormatter()
    1471             : {
    1472          60 :     delete mpCalendarWrapper;
    1473          60 :     mpCalendarWrapper = NULL;
    1474          60 : }
    1475             : 
    1476           0 : void DateFormatter::SetLocale( const ::com::sun::star::lang::Locale& rLocale )
    1477             : {
    1478           0 :     delete mpCalendarWrapper;
    1479           0 :     mpCalendarWrapper = NULL;
    1480           0 :     FormatterBase::SetLocale( rLocale );
    1481           0 : }
    1482             : 
    1483         818 : CalendarWrapper& DateFormatter::GetCalendarWrapper() const
    1484             : {
    1485         818 :     if ( !mpCalendarWrapper )
    1486             :     {
    1487          60 :         ((DateFormatter*)this)->mpCalendarWrapper = new CalendarWrapper( comphelper::getProcessComponentContext() );
    1488          60 :         mpCalendarWrapper->loadDefaultCalendar( GetLocale() );
    1489             :     }
    1490             : 
    1491         818 :     return *mpCalendarWrapper;
    1492             : }
    1493             : 
    1494          90 : void DateFormatter::SetExtDateFormat( ExtDateFieldFormat eFormat )
    1495             : {
    1496          90 :     mnExtDateFormat = eFormat;
    1497          90 :     ReformatAll();
    1498          90 : }
    1499             : 
    1500        1914 : ExtDateFieldFormat DateFormatter::GetExtDateFormat( bool bResolveSystemFormat ) const
    1501             : {
    1502        1914 :     ExtDateFieldFormat eDateFormat = (ExtDateFieldFormat)mnExtDateFormat;
    1503             : 
    1504        1914 :     if ( bResolveSystemFormat && ( eDateFormat <= XTDATEF_SYSTEM_SHORT_YYYY ) )
    1505             :     {
    1506        1056 :         bool bShowCentury = (eDateFormat == XTDATEF_SYSTEM_SHORT_YYYY);
    1507        1056 :         switch ( ImplGetLocaleDataWrapper().getDateFormat() )
    1508             :         {
    1509           0 :             case DMY:   eDateFormat = bShowCentury ? XTDATEF_SHORT_DDMMYYYY : XTDATEF_SHORT_DDMMYY;
    1510           0 :                         break;
    1511        1056 :             case MDY:   eDateFormat = bShowCentury ? XTDATEF_SHORT_MMDDYYYY : XTDATEF_SHORT_MMDDYY;
    1512        1056 :                         break;
    1513           0 :             default:    eDateFormat = bShowCentury ? XTDATEF_SHORT_YYYYMMDD : XTDATEF_SHORT_YYMMDD;
    1514             : 
    1515             :         }
    1516             :     }
    1517             : 
    1518        1914 :     return eDateFormat;
    1519             : }
    1520             : 
    1521         280 : void DateFormatter::ReformatAll()
    1522             : {
    1523         280 :     Reformat();
    1524         280 : }
    1525             : 
    1526          80 : void DateFormatter::SetMin( const Date& rNewMin )
    1527             : {
    1528          80 :     maMin = rNewMin;
    1529          80 :     if ( !IsEmptyFieldValue() )
    1530          72 :         ReformatAll();
    1531          80 : }
    1532             : 
    1533          80 : void DateFormatter::SetMax( const Date& rNewMax )
    1534             : {
    1535          80 :     maMax = rNewMax;
    1536          80 :     if ( !IsEmptyFieldValue() )
    1537          72 :         ReformatAll();
    1538          80 : }
    1539             : 
    1540           8 : void DateFormatter::SetLongFormat( bool bLong )
    1541             : {
    1542           8 :     mbLongFormat = bLong;
    1543             : 
    1544             :     // #91913# Remove LongFormat and DateShowCentury - redundant
    1545           8 :     if ( bLong )
    1546             :     {
    1547           8 :         SetExtDateFormat( XTDATEF_SYSTEM_LONG );
    1548             :     }
    1549             :     else
    1550             :     {
    1551           0 :         if( mnExtDateFormat == XTDATEF_SYSTEM_LONG )
    1552           0 :             SetExtDateFormat( XTDATEF_SYSTEM_SHORT );
    1553             :     }
    1554             : 
    1555           8 :     ReformatAll();
    1556           8 : }
    1557             : 
    1558          12 : void DateFormatter::SetShowDateCentury( bool bShowDateCentury )
    1559             : {
    1560          12 :     mbShowDateCentury = bShowDateCentury;
    1561             : 
    1562             :     // #91913# Remove LongFormat and DateShowCentury - redundant
    1563          12 :     if ( bShowDateCentury )
    1564             :     {
    1565          12 :         switch ( GetExtDateFormat() )
    1566             :         {
    1567             :             case XTDATEF_SYSTEM_SHORT:
    1568             :             case XTDATEF_SYSTEM_SHORT_YY:
    1569           6 :                 SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );  break;
    1570             :             case XTDATEF_SHORT_DDMMYY:
    1571           0 :                 SetExtDateFormat( XTDATEF_SHORT_DDMMYYYY );     break;
    1572             :             case XTDATEF_SHORT_MMDDYY:
    1573           0 :                 SetExtDateFormat( XTDATEF_SHORT_MMDDYYYY );     break;
    1574             :             case XTDATEF_SHORT_YYMMDD:
    1575           0 :                 SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD );     break;
    1576             :             case XTDATEF_SHORT_YYMMDD_DIN5008:
    1577           0 :                 SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD_DIN5008 ); break;
    1578             :             default:
    1579             :                 ;
    1580             :         }
    1581             :     }
    1582             :     else
    1583             :     {
    1584           0 :         switch ( GetExtDateFormat() )
    1585             :         {
    1586             :             case XTDATEF_SYSTEM_SHORT:
    1587             :             case XTDATEF_SYSTEM_SHORT_YYYY:
    1588           0 :                 SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YY );    break;
    1589             :             case XTDATEF_SHORT_DDMMYYYY:
    1590           0 :                 SetExtDateFormat( XTDATEF_SHORT_DDMMYY );       break;
    1591             :             case XTDATEF_SHORT_MMDDYYYY:
    1592           0 :                 SetExtDateFormat( XTDATEF_SHORT_MMDDYY );       break;
    1593             :             case XTDATEF_SHORT_YYYYMMDD:
    1594           0 :                 SetExtDateFormat( XTDATEF_SHORT_YYMMDD );       break;
    1595             :             case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1596           0 :                 SetExtDateFormat( XTDATEF_SHORT_YYMMDD_DIN5008 );  break;
    1597             :             default:
    1598             :                 ;
    1599             :         }
    1600             :     }
    1601             : 
    1602          12 :     ReformatAll();
    1603          12 : }
    1604             : 
    1605         178 : void DateFormatter::SetDate( const Date& rNewDate )
    1606             : {
    1607         178 :     SetUserDate( rNewDate );
    1608         178 :     maFieldDate = maLastDate;
    1609         178 :     maLastDate = GetDate();
    1610         178 : }
    1611             : 
    1612         178 : void DateFormatter::SetUserDate( const Date& rNewDate )
    1613             : {
    1614         178 :     ImplSetUserDate( rNewDate );
    1615         178 : }
    1616             : 
    1617         198 : void DateFormatter::ImplSetUserDate( const Date& rNewDate, Selection* pNewSelection )
    1618             : {
    1619         198 :     Date aNewDate = rNewDate;
    1620         198 :     if ( aNewDate > maMax )
    1621          34 :         aNewDate = maMax;
    1622         164 :     else if ( aNewDate < maMin )
    1623          42 :         aNewDate = maMin;
    1624         198 :     maLastDate = aNewDate;
    1625             : 
    1626         198 :     if ( GetField() )
    1627         198 :         ImplSetText( ImplGetDateAsText( aNewDate, GetFieldSettings() ), pNewSelection );
    1628         198 : }
    1629             : 
    1630          20 : void DateFormatter::ImplNewFieldValue( const Date& rDate )
    1631             : {
    1632          20 :     if ( GetField() )
    1633             :     {
    1634          20 :         Selection aSelection = GetField()->GetSelection();
    1635          20 :         aSelection.Justify();
    1636          20 :         OUString aText = GetField()->GetText();
    1637             : 
    1638             :         // If selected until the end then keep it that way
    1639          20 :         if ( (sal_Int32)aSelection.Max() == aText.getLength() )
    1640             :         {
    1641          20 :             if ( !aSelection.Len() )
    1642          20 :                 aSelection.Min() = SELECTION_MAX;
    1643          20 :             aSelection.Max() = SELECTION_MAX;
    1644             :         }
    1645             : 
    1646          20 :         Date aOldLastDate  = maLastDate;
    1647          20 :         ImplSetUserDate( rDate, &aSelection );
    1648          20 :         maLastDate = aOldLastDate;
    1649             : 
    1650             :         // Modify at Edit is only set at KeyInput
    1651          20 :         if ( GetField()->GetText() != aText )
    1652             :         {
    1653          20 :             GetField()->SetModifyFlag();
    1654          20 :             GetField()->Modify();
    1655          20 :         }
    1656             :     }
    1657          20 : }
    1658             : 
    1659         234 : Date DateFormatter::GetDate() const
    1660             : {
    1661         234 :     Date aDate( 0, 0, 0 );
    1662             : 
    1663         234 :     if ( GetField() )
    1664             :     {
    1665         234 :         if ( ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
    1666             :         {
    1667         134 :             if ( aDate > maMax )
    1668           4 :                 aDate = maMax;
    1669         130 :             else if ( aDate < maMin )
    1670           0 :                 aDate = maMin;
    1671             :         }
    1672             :         else
    1673             :         {
    1674             :             // !!! We should find out why dates are treated differently than other fields (see
    1675             :             // also bug: 52384)
    1676             : 
    1677         100 :             if ( !ImplAllowMalformedInput() )
    1678             :             {
    1679          88 :                 if ( maLastDate.GetDate() )
    1680          88 :                     aDate = maLastDate;
    1681           0 :                 else if ( !IsEmptyFieldValueEnabled() )
    1682           0 :                     aDate = Date( Date::SYSTEM );
    1683             :             }
    1684             :             else
    1685          12 :                 aDate = GetInvalidDate();
    1686             :         }
    1687             :     }
    1688             : 
    1689         234 :     return aDate;
    1690             : }
    1691             : 
    1692           4 : void DateFormatter::SetEmptyDate()
    1693             : {
    1694           4 :     FormatterBase::SetEmptyFieldValue();
    1695           4 : }
    1696             : 
    1697          56 : bool DateFormatter::IsEmptyDate() const
    1698             : {
    1699          56 :     bool bEmpty = FormatterBase::IsEmptyFieldValue();
    1700             : 
    1701          56 :     if ( GetField() && MustBeReformatted() && IsEmptyFieldValueEnabled() )
    1702             :     {
    1703          48 :         if ( GetField()->GetText().isEmpty() )
    1704             :         {
    1705           8 :             bEmpty = true;
    1706             :         }
    1707          40 :         else if ( !maLastDate.GetDate() )
    1708             :         {
    1709           0 :             Date aDate( Date::EMPTY );
    1710           0 :             bEmpty = !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
    1711             :         }
    1712             :     }
    1713          56 :     return bEmpty;
    1714             : }
    1715             : 
    1716         340 : void DateFormatter::Reformat()
    1717             : {
    1718         340 :     if ( !GetField() )
    1719          10 :         return;
    1720             : 
    1721         340 :     if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
    1722          10 :         return;
    1723             : 
    1724         330 :     OUString aStr;
    1725         330 :     bool bOK = ImplDateReformat( GetField()->GetText(), aStr, GetFieldSettings() );
    1726         330 :     if( !bOK )
    1727           0 :         return;
    1728             : 
    1729         330 :     if ( !aStr.isEmpty() )
    1730             :     {
    1731         184 :         ImplSetText( aStr );
    1732         184 :         ImplDateGetValue( aStr, maLastDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
    1733             :     }
    1734             :     else
    1735             :     {
    1736         146 :         if ( maLastDate.GetDate() )
    1737          78 :             SetDate( maLastDate );
    1738          68 :         else if ( !IsEmptyFieldValueEnabled() )
    1739          60 :             SetDate( Date( Date::SYSTEM ) );
    1740             :         else
    1741             :         {
    1742           8 :             ImplSetText( OUString() );
    1743           8 :             SetEmptyFieldValueData( true );
    1744             :         }
    1745         330 :     }
    1746             : }
    1747             : 
    1748          12 : void DateFormatter::ExpandCentury( Date& rDate )
    1749             : {
    1750          12 :     ExpandCentury( rDate, utl::MiscCfg().GetYear2000() );
    1751          12 : }
    1752             : 
    1753         482 : void DateFormatter::ExpandCentury( Date& rDate, sal_uInt16 nTwoDigitYearStart )
    1754             : {
    1755         482 :     sal_uInt16 nDateYear = rDate.GetYear();
    1756         482 :     if ( nDateYear < 100 )
    1757             :     {
    1758         296 :         sal_uInt16 nCentury = nTwoDigitYearStart / 100;
    1759         296 :         if ( nDateYear < (nTwoDigitYearStart % 100) )
    1760         280 :             nCentury++;
    1761         296 :         rDate.SetYear( nDateYear + (nCentury*100) );
    1762             :     }
    1763         482 : }
    1764             : 
    1765          60 : DateField::DateField( vcl::Window* pParent, WinBits nWinStyle ) :
    1766             :     SpinField( pParent, nWinStyle ),
    1767          60 :     maFirst( GetMin() ),
    1768         120 :     maLast( GetMax() )
    1769             : {
    1770          60 :     SetField( this );
    1771          60 :     SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
    1772          60 :     Reformat();
    1773          60 :     ResetLastDate();
    1774          60 : }
    1775             : 
    1776           0 : DateField::DateField( vcl::Window* pParent, const ResId& rResId ) :
    1777             :     SpinField( WINDOW_DATEFIELD ),
    1778           0 :     maFirst( GetMin() ),
    1779           0 :     maLast( GetMax() )
    1780             : {
    1781           0 :     rResId.SetRT( RSC_DATEFIELD );
    1782           0 :     WinBits nStyle = ImplInitRes( rResId );
    1783           0 :     SpinField::ImplInit( pParent, nStyle );
    1784           0 :     SetField( this );
    1785           0 :     SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
    1786           0 :     ImplLoadRes( rResId );
    1787             : 
    1788           0 :     if ( !(nStyle & WB_HIDE ) )
    1789           0 :         Show();
    1790             : 
    1791           0 :     ResetLastDate();
    1792           0 : }
    1793             : 
    1794           0 : void DateField::ImplLoadRes( const ResId& rResId )
    1795             : {
    1796           0 :     SpinField::ImplLoadRes( rResId );
    1797             : 
    1798           0 :     ResMgr* pMgr = rResId.GetResMgr();
    1799           0 :     if( pMgr )
    1800             :     {
    1801           0 :         DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
    1802             : 
    1803           0 :         sal_uLong  nMask = ReadLongRes();
    1804           0 :         if ( DATEFIELD_FIRST & nMask )
    1805             :         {
    1806           0 :             maFirst = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
    1807           0 :             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
    1808             :         }
    1809           0 :         if ( DATEFIELD_LAST & nMask )
    1810             :         {
    1811           0 :             maLast = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
    1812           0 :             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
    1813             :         }
    1814             :     }
    1815             : 
    1816           0 :     Reformat();
    1817           0 : }
    1818             : 
    1819          60 : DateField::~DateField()
    1820             : {
    1821          60 : }
    1822             : 
    1823           0 : bool DateField::PreNotify( NotifyEvent& rNEvt )
    1824             : {
    1825           0 :     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
    1826           0 :          ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
    1827           0 :          !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    1828             :     {
    1829           0 :         if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( true ), ImplGetLocaleDataWrapper() ) )
    1830           0 :             return true;
    1831             :     }
    1832             : 
    1833           0 :     return SpinField::PreNotify( rNEvt );
    1834             : }
    1835             : 
    1836          62 : bool DateField::Notify( NotifyEvent& rNEvt )
    1837             : {
    1838          62 :     if ( rNEvt.GetType() == EVENT_GETFOCUS )
    1839           0 :         MarkToBeReformatted( false );
    1840          62 :     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
    1841             :     {
    1842           0 :         if ( MustBeReformatted() )
    1843             :         {
    1844             :             // !!! We should find out why dates are treated differently than other fields (see
    1845             :             // also bug: 52384)
    1846             : 
    1847           0 :             bool bTextLen = !GetText().isEmpty();
    1848           0 :             if ( bTextLen || !IsEmptyFieldValueEnabled() )
    1849             :             {
    1850           0 :                 if ( !ImplAllowMalformedInput() )
    1851           0 :                     Reformat();
    1852             :                 else
    1853             :                 {
    1854           0 :                     Date aDate( 0, 0, 0 );
    1855           0 :                     if ( ImplDateGetValue( GetText(), aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
    1856             :                         // even with strict text analysis, our text is a valid date -> do a complete
    1857             :                         // reformat
    1858           0 :                         Reformat();
    1859             :                 }
    1860             :             }
    1861           0 :             else if ( !bTextLen && IsEmptyFieldValueEnabled() )
    1862             :             {
    1863           0 :                 ResetLastDate();
    1864           0 :                 SetEmptyFieldValueData( true );
    1865             :             }
    1866             :         }
    1867             :     }
    1868             : 
    1869          62 :     return SpinField::Notify( rNEvt );
    1870             : }
    1871             : 
    1872         380 : void DateField::DataChanged( const DataChangedEvent& rDCEvt )
    1873             : {
    1874         380 :     SpinField::DataChanged( rDCEvt );
    1875             : 
    1876         380 :     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & (SETTINGS_LOCALE|SETTINGS_MISC)) )
    1877             :     {
    1878           0 :         if ( IsDefaultLocale() && ( rDCEvt.GetFlags() & SETTINGS_LOCALE ) )
    1879           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    1880           0 :         ReformatAll();
    1881             :     }
    1882         380 : }
    1883             : 
    1884         176 : void DateField::Modify()
    1885             : {
    1886         176 :     MarkToBeReformatted( true );
    1887         176 :     SpinField::Modify();
    1888         176 : }
    1889             : 
    1890           8 : void DateField::Up()
    1891             : {
    1892           8 :     ImplDateSpinArea( true );
    1893           8 :     SpinField::Up();
    1894           8 : }
    1895             : 
    1896           4 : void DateField::Down()
    1897             : {
    1898           4 :     ImplDateSpinArea( false );
    1899           4 :     SpinField::Down();
    1900           4 : }
    1901             : 
    1902           4 : void DateField::First()
    1903             : {
    1904           4 :     ImplNewFieldValue( maFirst );
    1905           4 :     SpinField::First();
    1906           4 : }
    1907             : 
    1908           4 : void DateField::Last()
    1909             : {
    1910           4 :     ImplNewFieldValue( maLast );
    1911           4 :     SpinField::Last();
    1912           4 : }
    1913             : 
    1914           0 : DateBox::DateBox( vcl::Window* pParent, WinBits nWinStyle ) :
    1915           0 :     ComboBox( pParent, nWinStyle )
    1916             : {
    1917           0 :     SetField( this );
    1918           0 :     SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
    1919           0 :     Reformat();
    1920           0 : }
    1921             : 
    1922           0 : DateBox::~DateBox()
    1923             : {
    1924           0 : }
    1925             : 
    1926           0 : bool DateBox::PreNotify( NotifyEvent& rNEvt )
    1927             : {
    1928           0 :     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
    1929           0 :          ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
    1930           0 :          !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    1931             :     {
    1932           0 :         if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( true ), ImplGetLocaleDataWrapper() ) )
    1933           0 :             return true;
    1934             :     }
    1935             : 
    1936           0 :     return ComboBox::PreNotify( rNEvt );
    1937             : }
    1938             : 
    1939           0 : void DateBox::DataChanged( const DataChangedEvent& rDCEvt )
    1940             : {
    1941           0 :     ComboBox::DataChanged( rDCEvt );
    1942             : 
    1943           0 :     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
    1944             :     {
    1945           0 :         if ( IsDefaultLocale() )
    1946           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    1947           0 :         ReformatAll();
    1948             :     }
    1949           0 : }
    1950             : 
    1951           0 : bool DateBox::Notify( NotifyEvent& rNEvt )
    1952             : {
    1953           0 :     if ( rNEvt.GetType() == EVENT_GETFOCUS )
    1954           0 :         MarkToBeReformatted( false );
    1955           0 :     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
    1956             :     {
    1957           0 :         if ( MustBeReformatted() )
    1958             :         {
    1959           0 :             bool bTextLen = !GetText().isEmpty();
    1960           0 :             if ( bTextLen || !IsEmptyFieldValueEnabled() )
    1961           0 :                 Reformat();
    1962           0 :             else if ( !bTextLen && IsEmptyFieldValueEnabled() )
    1963             :             {
    1964           0 :                 ResetLastDate();
    1965           0 :                 SetEmptyFieldValueData( true );
    1966             :             }
    1967             :         }
    1968             :     }
    1969             : 
    1970           0 :     return ComboBox::Notify( rNEvt );
    1971             : }
    1972             : 
    1973           0 : void DateBox::Modify()
    1974             : {
    1975           0 :     MarkToBeReformatted( true );
    1976           0 :     ComboBox::Modify();
    1977           0 : }
    1978             : 
    1979           0 : void DateBox::ReformatAll()
    1980             : {
    1981           0 :     OUString aStr;
    1982           0 :     SetUpdateMode( false );
    1983           0 :     sal_uInt16 nEntryCount = GetEntryCount();
    1984           0 :     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
    1985             :     {
    1986           0 :         ImplDateReformat( GetEntry( i ), aStr, GetFieldSettings() );
    1987           0 :         RemoveEntryAt(i);
    1988           0 :         InsertEntry( aStr, i );
    1989             :     }
    1990           0 :     DateFormatter::Reformat();
    1991           0 :     SetUpdateMode( true );
    1992           0 : }
    1993             : 
    1994           0 : static bool ImplTimeProcessKeyInput( Edit*, const KeyEvent& rKEvt,
    1995             :                                      bool bStrictFormat, bool bDuration,
    1996             :                                      TimeFieldFormat eFormat,
    1997             :                                      const LocaleDataWrapper& rLocaleDataWrapper  )
    1998             : {
    1999           0 :     sal_Unicode cChar = rKEvt.GetCharCode();
    2000             : 
    2001           0 :     if ( !bStrictFormat )
    2002           0 :         return false;
    2003             :     else
    2004             :     {
    2005           0 :         sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
    2006           0 :         if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
    2007           0 :              (nGroup == KEYGROUP_MISC)   ||
    2008           0 :              ((cChar >= '0') && (cChar <= '9')) ||
    2009           0 :              string::equals(rLocaleDataWrapper.getTimeSep(), cChar) ||
    2010           0 :              (rLocaleDataWrapper.getTimeAM().indexOf(cChar) != -1) ||
    2011           0 :              (rLocaleDataWrapper.getTimePM().indexOf(cChar) != -1) ||
    2012             :              // Accept AM/PM:
    2013           0 :              (cChar == 'a') || (cChar == 'A') || (cChar == 'm') || (cChar == 'M') || (cChar == 'p') || (cChar == 'P') ||
    2014           0 :              ((eFormat == TimeFieldFormat::F_100TH_SEC) && string::equals(rLocaleDataWrapper.getTime100SecSep(), cChar)) ||
    2015           0 :              ((eFormat == TimeFieldFormat::F_SEC_CS) && string::equals(rLocaleDataWrapper.getTime100SecSep(), cChar)) ||
    2016           0 :              (bDuration && (cChar == '-')) )
    2017           0 :             return false;
    2018             :         else
    2019           0 :             return true;
    2020             :     }
    2021             : }
    2022             : 
    2023          22 : static bool ImplIsOnlyDigits( const OUStringBuffer& _rStr )
    2024             : {
    2025          22 :     const sal_Unicode* _pChr = _rStr.getStr();
    2026          66 :     for ( sal_Int32 i = 0; i < _rStr.getLength(); ++i, ++_pChr )
    2027             :     {
    2028          44 :         if ( *_pChr < '0' || *_pChr > '9' )
    2029           0 :             return false;
    2030             :     }
    2031          22 :     return true;
    2032             : }
    2033             : 
    2034         854 : static bool ImplIsValidTimePortion( bool _bSkipInvalidCharacters, const OUStringBuffer& _rStr )
    2035             : {
    2036         854 :     if ( !_bSkipInvalidCharacters )
    2037             :     {
    2038          22 :         if ( ( _rStr.getLength() > 2 ) || _rStr.isEmpty() || !ImplIsOnlyDigits( _rStr ) )
    2039           0 :             return false;
    2040             :     }
    2041         854 :     return true;
    2042             : }
    2043             : 
    2044         854 : static bool ImplCutTimePortion( OUStringBuffer& _rStr, sal_Int32 _nSepPos, bool _bSkipInvalidCharacters, short* _pPortion )
    2045             : {
    2046         854 :     OUString sPortion(_rStr.getStr(), _nSepPos );
    2047        1708 :     _rStr = _nSepPos < _rStr.getLength()
    2048         854 :         ? _rStr.copy( _nSepPos + 1 ) : OUStringBuffer();
    2049             : 
    2050         854 :     if ( !ImplIsValidTimePortion( _bSkipInvalidCharacters, sPortion ) )
    2051           0 :         return false;
    2052         854 :     *_pPortion = (short)sPortion.toInt32();
    2053         854 :     return true;
    2054             : }
    2055             : 
    2056         702 : static bool ImplTimeGetValue( const OUString& rStr, tools::Time& rTime,
    2057             :                               TimeFieldFormat eFormat, bool bDuration,
    2058             :                               const LocaleDataWrapper& rLocaleDataWrapper, bool _bSkipInvalidCharacters = true )
    2059             : {
    2060         702 :     OUStringBuffer    aStr    = rStr;
    2061         702 :     short       nHour   = 0;
    2062         702 :     short       nMinute = 0;
    2063         702 :     short       nSecond = 0;
    2064         702 :     sal_Int64   nNanoSec = 0;
    2065         702 :     tools::Time        aTime( 0, 0, 0 );
    2066             : 
    2067         702 :     if ( rStr.isEmpty() )
    2068          24 :         return false;
    2069             : 
    2070             :     // Search for separators
    2071         678 :     if (!rLocaleDataWrapper.getTimeSep().isEmpty())
    2072             :     {
    2073         678 :         OUStringBuffer aSepStr(",.;:/");
    2074         678 :         if ( !bDuration )
    2075         656 :             aSepStr.append('-');
    2076             : 
    2077             :         // Replace characters above by the separator character
    2078        4724 :         for (sal_Int32 i = 0; i < aSepStr.getLength(); ++i)
    2079             :         {
    2080        4046 :             if (string::equals(rLocaleDataWrapper.getTimeSep(), aSepStr[i]))
    2081         678 :                 continue;
    2082       24582 :             for ( sal_Int32 j = 0; j < aStr.getLength(); j++ )
    2083             :             {
    2084       21214 :                 if (aStr[j] == aSepStr[i])
    2085           0 :                     aStr[j] = rLocaleDataWrapper.getTimeSep()[0];
    2086             :             }
    2087         678 :         }
    2088             :     }
    2089             : 
    2090         678 :     bool bNegative = false;
    2091         678 :     sal_Int32 nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    2092         678 :     if ( aStr[0] == '-' )
    2093           0 :         bNegative = true;
    2094         678 :     if ( eFormat != TimeFieldFormat::F_SEC_CS )
    2095             :     {
    2096         678 :         if ( nSepPos < 0 )
    2097          30 :             nSepPos = aStr.getLength();
    2098         678 :         if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nHour ) )
    2099           0 :             return false;
    2100             : 
    2101         678 :         nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    2102         678 :         if ( !aStr.isEmpty() && aStr[0] == '-' )
    2103           0 :             bNegative = true;
    2104         678 :         if ( nSepPos >= 0 )
    2105             :         {
    2106         176 :             if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nMinute ) )
    2107           0 :                 return false;
    2108             : 
    2109         176 :             nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    2110         176 :             if ( !aStr.isEmpty() && aStr[0] == '-' )
    2111           0 :                 bNegative = true;
    2112         176 :             if ( nSepPos >= 0 )
    2113             :             {
    2114           0 :                 if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nSecond ) )
    2115           0 :                     return false;
    2116           0 :                 if ( !aStr.isEmpty() && aStr[0] == '-' )
    2117           0 :                     bNegative = true;
    2118           0 :                 nNanoSec = aStr.toString().toInt64();
    2119             :             }
    2120             :             else
    2121         176 :                 nSecond = (short)aStr.toString().toInt32();
    2122             :         }
    2123             :         else
    2124         502 :             nMinute = (short)aStr.toString().toInt32();
    2125             :     }
    2126           0 :     else if ( nSepPos < 0 )
    2127             :     {
    2128           0 :         nSecond = (short)aStr.toString().toInt32();
    2129           0 :         nMinute += nSecond / 60;
    2130           0 :         nSecond %= 60;
    2131           0 :         nHour += nMinute / 60;
    2132           0 :         nMinute %= 60;
    2133             :     }
    2134             :     else
    2135             :     {
    2136           0 :         nSecond = (short)aStr.copy( 0, nSepPos ).toString().toInt32();
    2137           0 :         aStr.remove( 0, nSepPos+1 );
    2138             : 
    2139           0 :         nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    2140           0 :         if ( !aStr.isEmpty() && aStr[0] == '-' )
    2141           0 :             bNegative = true;
    2142           0 :         if ( nSepPos >= 0 )
    2143             :         {
    2144           0 :             nMinute = nSecond;
    2145           0 :             nSecond = (short)aStr.copy( 0, nSepPos ).toString().toInt32();
    2146           0 :             aStr.remove( 0, nSepPos+1 );
    2147             : 
    2148           0 :             nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    2149           0 :             if ( !aStr.isEmpty() && aStr[0] == '-' )
    2150           0 :                 bNegative = true;
    2151           0 :             if ( nSepPos >= 0 )
    2152             :             {
    2153           0 :                 nHour   = nMinute;
    2154           0 :                 nMinute = nSecond;
    2155           0 :                 nSecond = (short)aStr.copy( 0, nSepPos ).toString().toInt32();
    2156           0 :                 aStr.remove( 0, nSepPos+1 );
    2157             :             }
    2158             :             else
    2159             :             {
    2160           0 :                 nHour += nMinute / 60;
    2161           0 :                 nMinute %= 60;
    2162             :             }
    2163             :         }
    2164             :         else
    2165             :         {
    2166           0 :             nMinute += nSecond / 60;
    2167           0 :             nSecond %= 60;
    2168           0 :             nHour += nMinute / 60;
    2169           0 :             nMinute %= 60;
    2170             :         }
    2171           0 :         nNanoSec = aStr.toString().toInt64();
    2172             :     }
    2173             : 
    2174         678 :     if ( nNanoSec )
    2175             :     {
    2176             :         assert(aStr.getLength() >= 1);
    2177             : 
    2178           0 :         sal_Int32 nLen = 1; // at least one digit, otherwise nNanoSec==0
    2179             : 
    2180           0 :         while ( aStr.getLength() > nLen && aStr[nLen] >= '0' && aStr[nLen] <= '9' )
    2181           0 :             nLen++;
    2182             : 
    2183           0 :         while ( nLen < 9)
    2184             :         {
    2185           0 :             nNanoSec *= 10;
    2186           0 :             ++nLen;
    2187             :         }
    2188           0 :         while ( nLen > 9 )
    2189             :         {
    2190             :             // round if negative?
    2191           0 :             nNanoSec = (nNanoSec + 5) / 10;
    2192           0 :             --nLen;
    2193             :         }
    2194             :     }
    2195             : 
    2196             :     assert(nNanoSec > -1000000000 && nNanoSec < 1000000000);
    2197         678 :     if ( (nMinute > 59) || (nSecond > 59) || (nNanoSec > 1000000000) )
    2198           0 :         return false;
    2199             : 
    2200         678 :     if ( eFormat == TimeFieldFormat::F_NONE )
    2201         484 :         nSecond = nNanoSec = 0;
    2202         194 :     else if ( eFormat == TimeFieldFormat::F_SEC )
    2203         194 :         nNanoSec = 0;
    2204             : 
    2205         678 :     if ( !bDuration )
    2206             :     {
    2207        1312 :         if ( bNegative || (nHour < 0) || (nMinute < 0) ||
    2208        1312 :              (nSecond < 0) || (nNanoSec < 0) )
    2209           0 :             return false;
    2210             : 
    2211         656 :         OUString aUpperCaseStr = aStr.toString().toAsciiUpperCase();
    2212        1312 :         OUString aAM(rLocaleDataWrapper.getTimeAM().toAsciiUpperCase());
    2213        1312 :         OUString aPM(rLocaleDataWrapper.getTimePM().toAsciiUpperCase());
    2214        1312 :         OUString aAM2("AM");  // aAM is localized
    2215        1312 :         OUString aPM2("PM");  // aPM is localized
    2216             : 
    2217         656 :         if ( (nHour < 12) && ( ( aUpperCaseStr.indexOf( aPM ) >= 0 ) || ( aUpperCaseStr.indexOf( aPM2 ) >= 0 ) ) )
    2218           0 :             nHour += 12;
    2219             : 
    2220         656 :         if ( (nHour == 12) && ( ( aUpperCaseStr.indexOf( aAM ) >= 0 ) || ( aUpperCaseStr.indexOf( aAM2 ) >= 0 ) ) )
    2221           0 :             nHour = 0;
    2222             : 
    2223        1312 :         aTime = tools::Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
    2224        1312 :                       (sal_uInt32)nNanoSec );
    2225             :     }
    2226             :     else
    2227             :     {
    2228             :         assert( !bNegative || (nHour < 0) || (nMinute < 0) ||
    2229             :              (nSecond < 0) || (nNanoSec < 0) );
    2230          44 :         if ( bNegative || (nHour < 0) || (nMinute < 0) ||
    2231          44 :              (nSecond < 0) || (nNanoSec < 0) )
    2232             :         {
    2233             :             // LEM TODO: this looks weird... I think buggy when parsing "05:-02:18"
    2234           0 :             bNegative   = true;
    2235           0 :             nHour       = nHour < 0 ? -nHour : nHour;
    2236           0 :             nMinute     = nMinute < 0 ? -nMinute : nMinute;
    2237           0 :             nSecond     = nSecond < 0 ? -nSecond : nSecond;
    2238           0 :             nNanoSec    = nNanoSec < 0 ? -nNanoSec : nNanoSec;
    2239             :         }
    2240             : 
    2241          44 :         aTime = tools::Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
    2242          22 :                       (sal_uInt32)nNanoSec );
    2243          22 :         if ( bNegative )
    2244           0 :             aTime = -aTime;
    2245             :     }
    2246             : 
    2247         678 :     rTime = aTime;
    2248             : 
    2249         678 :     return true;
    2250             : }
    2251             : 
    2252         312 : bool TimeFormatter::ImplTimeReformat( const OUString& rStr, OUString& rOutStr )
    2253             : {
    2254         312 :     tools::Time aTime( 0, 0, 0 );
    2255         312 :     if ( !ImplTimeGetValue( rStr, aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ) )
    2256          20 :         return true;
    2257             : 
    2258         292 :     tools::Time aTempTime = aTime;
    2259         292 :     if ( aTempTime > GetMax() )
    2260           0 :         aTempTime = GetMax() ;
    2261         292 :     else if ( aTempTime < GetMin() )
    2262          44 :         aTempTime = GetMin();
    2263             : 
    2264         292 :     if ( GetErrorHdl().IsSet() && (aTime != aTempTime) )
    2265             :     {
    2266           0 :         maCorrectedTime = aTempTime;
    2267           0 :         if ( !GetErrorHdl().Call( this ) )
    2268             :         {
    2269           0 :             maCorrectedTime = tools::Time( tools::Time::SYSTEM );
    2270           0 :             return false;
    2271             :         }
    2272             :         else
    2273           0 :             maCorrectedTime = tools::Time( tools::Time::SYSTEM );
    2274             :     }
    2275             : 
    2276         292 :     bool bSecond = false;
    2277         292 :     bool b100Sec = false;
    2278         292 :     if ( meFormat != TimeFieldFormat::F_NONE )
    2279          88 :         bSecond = true;
    2280         292 :     if ( meFormat == TimeFieldFormat::F_100TH_SEC )
    2281           0 :         b100Sec = true;
    2282             : 
    2283         292 :     if ( meFormat == TimeFieldFormat::F_SEC_CS )
    2284             :     {
    2285           0 :         sal_uLong n  = aTempTime.GetHour() * 3600L;
    2286           0 :         n       += aTempTime.GetMin()  * 60L;
    2287           0 :         n       += aTempTime.GetSec();
    2288           0 :         rOutStr  = OUString::number( n );
    2289           0 :         rOutStr += ImplGetLocaleDataWrapper().getTime100SecSep();
    2290           0 :         std::ostringstream ostr;
    2291           0 :         ostr.fill('0');
    2292           0 :         ostr.width(9);
    2293           0 :         ostr << aTempTime.GetNanoSec();
    2294           0 :         rOutStr += OUString::createFromAscii(ostr.str().c_str());
    2295             :     }
    2296         292 :     else if ( mbDuration )
    2297          10 :         rOutStr = ImplGetLocaleDataWrapper().getDuration( aTempTime, bSecond, b100Sec );
    2298             :     else
    2299             :     {
    2300         282 :         rOutStr = ImplGetLocaleDataWrapper().getTime( aTempTime, bSecond, b100Sec );
    2301         282 :         if ( GetTimeFormat() == HOUR_12 )
    2302             :         {
    2303          82 :             if ( aTempTime.GetHour() > 12 )
    2304             :             {
    2305           0 :                 tools::Time aT( aTempTime );
    2306           0 :                 aT.SetHour( aT.GetHour() % 12 );
    2307           0 :                 rOutStr = ImplGetLocaleDataWrapper().getTime( aT, bSecond, b100Sec );
    2308             :             }
    2309             :             // Don't use LocaleDataWrapper, we want AM/PM
    2310          82 :             if ( aTempTime.GetHour() < 12 )
    2311          82 :                 rOutStr += "AM"; // ImplGetLocaleDataWrapper().getTimeAM();
    2312             :             else
    2313           0 :                 rOutStr += "PM"; // ImplGetLocaleDataWrapper().getTimePM();
    2314             :         }
    2315             :     }
    2316             : 
    2317         292 :     return true;
    2318             : }
    2319          98 : bool TimeFormatter::ImplAllowMalformedInput() const
    2320             : {
    2321          98 :     return !IsEnforceValidValue();
    2322             : }
    2323             : 
    2324          12 : void TimeField::ImplTimeSpinArea( bool bUp )
    2325             : {
    2326          12 :     if ( GetField() )
    2327             :     {
    2328          12 :         sal_Int32 nTimeArea = 0;
    2329          12 :         tools::Time aTime( GetTime() );
    2330          12 :         OUString aText( GetText() );
    2331          12 :         Selection aSelection( GetField()->GetSelection() );
    2332             : 
    2333             :         // Area search
    2334          12 :         if ( GetFormat() != TimeFieldFormat::F_SEC_CS )
    2335             :         {
    2336             :             //Which area is the cursor in of HH:MM:SS.TT
    2337          20 :             for ( sal_Int32 i = 1, nPos = 0; i <= 4; i++ )
    2338             :             {
    2339          20 :                 sal_Int32 nPos1 = aText.indexOf( ImplGetLocaleDataWrapper().getTimeSep(), nPos );
    2340          20 :                 sal_Int32 nPos2 = aText.indexOf( ImplGetLocaleDataWrapper().getTime100SecSep(), nPos );
    2341             :                 //which ever comes first, bearing in mind that one might not be there
    2342          20 :                 if (nPos1 >= 0 && nPos2 >= 0)
    2343           0 :                     nPos = nPos1 < nPos2 ? nPos1 : nPos2;
    2344          20 :                 else if (nPos1 >= 0)
    2345           8 :                     nPos = nPos1;
    2346             :                 else
    2347          12 :                     nPos = nPos2;
    2348          20 :                 if ( nPos < 0 || nPos >= aSelection.Max() )
    2349             :                 {
    2350          12 :                     nTimeArea = i;
    2351          12 :                     break;
    2352             :                 }
    2353             :                 else
    2354           8 :                     nPos++;
    2355             :             }
    2356             :         }
    2357             :         else
    2358             :         {
    2359           0 :             sal_Int32 nPos = aText.indexOf( ImplGetLocaleDataWrapper().getTime100SecSep() );
    2360           0 :             if ( nPos < 0 || nPos >= aSelection.Max() )
    2361           0 :                 nTimeArea = 3;
    2362             :             else
    2363           0 :                 nTimeArea = 4;
    2364             :         }
    2365             : 
    2366          12 :         if ( nTimeArea )
    2367             :         {
    2368          12 :             tools::Time aAddTime( 0, 0, 0 );
    2369          12 :             if ( nTimeArea == 1 )
    2370           4 :                 aAddTime = tools::Time( 1, 0 );
    2371           8 :             else if ( nTimeArea == 2 )
    2372           8 :                 aAddTime = tools::Time( 0, 1 );
    2373           0 :             else if ( nTimeArea == 3 )
    2374           0 :                 aAddTime = tools::Time( 0, 0, 1 );
    2375           0 :             else if ( nTimeArea == 4 )
    2376           0 :                 aAddTime = tools::Time( 0, 0, 0, 1 );
    2377             : 
    2378          12 :             if ( !bUp )
    2379           4 :                 aAddTime = -aAddTime;
    2380             : 
    2381          12 :             aTime += aAddTime;
    2382          12 :             if ( !IsDuration() )
    2383             :             {
    2384          12 :                 tools::Time aAbsMaxTime( 23, 59, 59, 999999999 );
    2385          12 :                 if ( aTime > aAbsMaxTime )
    2386           0 :                     aTime = aAbsMaxTime;
    2387          12 :                 tools::Time aAbsMinTime( 0, 0 );
    2388          12 :                 if ( aTime < aAbsMinTime )
    2389           0 :                     aTime = aAbsMinTime;
    2390             :             }
    2391          12 :             ImplNewFieldValue( aTime );
    2392          12 :         }
    2393             : 
    2394             :     }
    2395          12 : }
    2396             : 
    2397          34 : void TimeFormatter::ImplInit()
    2398             : {
    2399          34 :     meFormat        = TimeFieldFormat::F_NONE;
    2400          34 :     mbDuration      = false;
    2401          34 :     mnTimeFormat    = HOUR_24;  // Should become a ExtTimeFieldFormat in next implementation, merge with mbDuration and meFormat
    2402          34 : }
    2403             : 
    2404          34 : TimeFormatter::TimeFormatter() :
    2405             :     maLastTime( 0, 0 ),
    2406             :     maMin( 0, 0 ),
    2407             :     maMax( 23, 59, 59, 999999999 ),
    2408             :     maCorrectedTime( tools::Time::SYSTEM ),
    2409             :     mbEnforceValidValue( true ),
    2410          34 :     maFieldTime( 0, 0 )
    2411             : {
    2412          34 :     ImplInit();
    2413          34 : }
    2414             : 
    2415           0 : void TimeFormatter::ImplLoadRes( const ResId& rResId )
    2416             : {
    2417           0 :     ResMgr* pMgr = rResId.GetResMgr();
    2418           0 :     if( pMgr )
    2419             :     {
    2420           0 :         sal_uLong   nMask = pMgr->ReadLong();
    2421             : 
    2422           0 :         if ( TIMEFORMATTER_MIN & nMask )
    2423             :         {
    2424           0 :             SetMin( tools::Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
    2425           0 :             pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
    2426             :         }
    2427             : 
    2428           0 :         if ( TIMEFORMATTER_MAX & nMask )
    2429             :         {
    2430           0 :             SetMax( tools::Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
    2431           0 :             pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
    2432             :         }
    2433             : 
    2434           0 :         if ( TIMEFORMATTER_TIMEFIELDFORMAT & nMask )
    2435           0 :             meFormat = (TimeFieldFormat)pMgr->ReadLong();
    2436             : 
    2437           0 :         if ( TIMEFORMATTER_DURATION & nMask )
    2438           0 :             mbDuration = pMgr->ReadShort() != 0;
    2439             : 
    2440           0 :         if ( TIMEFORMATTER_STRICTFORMAT & nMask )
    2441           0 :             SetStrictFormat( pMgr->ReadShort() != 0 );
    2442             : 
    2443           0 :         if ( TIMEFORMATTER_VALUE & nMask )
    2444             :         {
    2445           0 :             maFieldTime = tools::Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
    2446           0 :             if ( maFieldTime > GetMax() )
    2447           0 :                 maFieldTime = GetMax();
    2448           0 :             if ( maFieldTime < GetMin() )
    2449           0 :                 maFieldTime = GetMin();
    2450           0 :             maLastTime = maFieldTime;
    2451             : 
    2452           0 :             pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
    2453             :         }
    2454             :     }
    2455           0 : }
    2456             : 
    2457          34 : TimeFormatter::~TimeFormatter()
    2458             : {
    2459          34 : }
    2460             : 
    2461         288 : void TimeFormatter::ReformatAll()
    2462             : {
    2463         288 :     Reformat();
    2464         288 : }
    2465             : 
    2466          58 : void TimeFormatter::SetMin( const tools::Time& rNewMin )
    2467             : {
    2468          58 :     maMin = rNewMin;
    2469          58 :     if ( !IsEmptyFieldValue() )
    2470          58 :         ReformatAll();
    2471          58 : }
    2472             : 
    2473          58 : void TimeFormatter::SetMax( const tools::Time& rNewMax )
    2474             : {
    2475          58 :     maMax = rNewMax;
    2476          58 :     if ( !IsEmptyFieldValue() )
    2477          58 :         ReformatAll();
    2478          58 : }
    2479             : 
    2480          48 : void TimeFormatter::SetTimeFormat( TimeFormatter::TimeFormat eNewFormat )
    2481             : {
    2482          48 :     mnTimeFormat = sal::static_int_cast<sal_uInt16>(eNewFormat);
    2483          48 : }
    2484             : 
    2485             : 
    2486          50 : void TimeFormatter::SetFormat( TimeFieldFormat eNewFormat )
    2487             : {
    2488          50 :     meFormat = eNewFormat;
    2489          50 :     ReformatAll();
    2490          50 : }
    2491             : 
    2492          50 : void TimeFormatter::SetDuration( bool bNewDuration )
    2493             : {
    2494          50 :     mbDuration = bNewDuration;
    2495          50 :     ReformatAll();
    2496          50 : }
    2497             : 
    2498          30 : void TimeFormatter::SetTime( const tools::Time& rNewTime )
    2499             : {
    2500          30 :     SetUserTime( rNewTime );
    2501          30 :     maFieldTime = maLastTime;
    2502          30 :     SetEmptyFieldValueData( false );
    2503          30 : }
    2504             : 
    2505          20 : void TimeFormatter::ImplNewFieldValue( const tools::Time& rTime )
    2506             : {
    2507          20 :     if ( GetField() )
    2508             :     {
    2509          20 :         Selection aSelection = GetField()->GetSelection();
    2510          20 :         aSelection.Justify();
    2511          20 :         OUString aText = GetField()->GetText();
    2512             : 
    2513             :         // If selected until the end then keep it that way
    2514          20 :         if ( (sal_Int32)aSelection.Max() == aText.getLength() )
    2515             :         {
    2516          20 :             if ( !aSelection.Len() )
    2517          20 :                 aSelection.Min() = SELECTION_MAX;
    2518          20 :             aSelection.Max() = SELECTION_MAX;
    2519             :         }
    2520             : 
    2521          20 :         tools::Time aOldLastTime = maLastTime;
    2522          20 :         ImplSetUserTime( rTime, &aSelection );
    2523          20 :         maLastTime = aOldLastTime;
    2524             : 
    2525             :         // Modify at Edit is only set at KeyInput
    2526          20 :         if ( GetField()->GetText() != aText )
    2527             :         {
    2528          16 :             GetField()->SetModifyFlag();
    2529          16 :             GetField()->Modify();
    2530          20 :         }
    2531             :     }
    2532          20 : }
    2533             : 
    2534         100 : void TimeFormatter::ImplSetUserTime( const tools::Time& rNewTime, Selection* pNewSelection )
    2535             : {
    2536         100 :     tools::Time aNewTime = rNewTime;
    2537         100 :     if ( aNewTime > GetMax() )
    2538           8 :         aNewTime = GetMax();
    2539          92 :     else if ( aNewTime < GetMin() )
    2540           0 :         aNewTime = GetMin();
    2541         100 :     maLastTime = aNewTime;
    2542             : 
    2543         100 :     if ( GetField() )
    2544             :     {
    2545         100 :         OUString aStr;
    2546         100 :         bool bSec    = false;
    2547         100 :         bool b100Sec = false;
    2548         100 :         if ( meFormat != TimeFieldFormat::F_NONE )
    2549          22 :             bSec = true;
    2550         100 :         if ( meFormat == TimeFieldFormat::F_100TH_SEC || meFormat == TimeFieldFormat::F_SEC_CS )
    2551           0 :             b100Sec = true;
    2552         100 :         if ( meFormat == TimeFieldFormat::F_SEC_CS )
    2553             :         {
    2554           0 :             sal_uLong n  = aNewTime.GetHour() * 3600L;
    2555           0 :             n       += aNewTime.GetMin()  * 60L;
    2556           0 :             n       += aNewTime.GetSec();
    2557           0 :             aStr     = OUString::number( n );
    2558           0 :             aStr    += ImplGetLocaleDataWrapper().getTime100SecSep();
    2559           0 :             std::ostringstream ostr;
    2560           0 :             ostr.fill('0');
    2561           0 :             ostr.width(9);
    2562           0 :             ostr << aNewTime.GetNanoSec();
    2563           0 :             aStr += OUString::createFromAscii(ostr.str().c_str());
    2564             :         }
    2565         100 :         else if ( mbDuration )
    2566             :         {
    2567           2 :             aStr = ImplGetLocaleDataWrapper().getDuration( aNewTime, bSec, b100Sec );
    2568             :         }
    2569             :         else
    2570             :         {
    2571          98 :             aStr = ImplGetLocaleDataWrapper().getTime( aNewTime, bSec, b100Sec );
    2572          98 :             if ( GetTimeFormat() == HOUR_12 )
    2573             :             {
    2574          18 :                 if ( aNewTime.GetHour() > 12 )
    2575             :                 {
    2576           0 :                     tools::Time aT( aNewTime );
    2577           0 :                     aT.SetHour( aT.GetHour() % 12 );
    2578           0 :                     aStr = ImplGetLocaleDataWrapper().getTime( aT, bSec, b100Sec );
    2579             :                 }
    2580             :                 // Don't use LocaleDataWrapper, we want AM/PM
    2581          18 :                 if ( aNewTime.GetHour() < 12 )
    2582          18 :                     aStr += "AM"; // ImplGetLocaleDataWrapper().getTimeAM();
    2583             :                 else
    2584           0 :                     aStr += "PM"; // ImplGetLocaleDataWrapper().getTimePM();
    2585             :             }
    2586             :         }
    2587             : 
    2588         100 :         ImplSetText( aStr, pNewSelection );
    2589             :     }
    2590         100 : }
    2591             : 
    2592          80 : void TimeFormatter::SetUserTime( const tools::Time& rNewTime )
    2593             : {
    2594          80 :     ImplSetUserTime( rNewTime );
    2595          80 : }
    2596             : 
    2597          98 : tools::Time TimeFormatter::GetTime() const
    2598             : {
    2599          98 :     tools::Time aTime( 0, 0, 0 );
    2600             : 
    2601          98 :     if ( GetField() )
    2602             :     {
    2603          98 :         bool bAllowMailformed = ImplAllowMalformedInput();
    2604          98 :         if ( ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
    2605             :         {
    2606          94 :             if ( aTime > GetMax() )
    2607           0 :                 aTime = GetMax();
    2608          94 :             else if ( aTime < GetMin() )
    2609           0 :                 aTime = GetMin();
    2610             :         }
    2611             :         else
    2612             :         {
    2613           4 :             if ( bAllowMailformed )
    2614           0 :                 aTime = GetInvalidTime();
    2615             :             else
    2616           4 :                 aTime = maLastTime;
    2617             :         }
    2618             :     }
    2619             : 
    2620          98 :     return aTime;
    2621             : }
    2622             : 
    2623         322 : void TimeFormatter::Reformat()
    2624             : {
    2625         322 :     if ( !GetField() )
    2626          10 :         return;
    2627             : 
    2628         322 :     if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
    2629          10 :         return;
    2630             : 
    2631         312 :     OUString aStr;
    2632         312 :     bool bOK = ImplTimeReformat( GetField()->GetText(), aStr );
    2633         312 :     if ( !bOK )
    2634           0 :         return;
    2635             : 
    2636         312 :     if ( !aStr.isEmpty() )
    2637             :     {
    2638         292 :         ImplSetText( aStr );
    2639         292 :         ImplTimeGetValue( aStr, maLastTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
    2640             :     }
    2641             :     else
    2642          20 :         SetTime( maLastTime );
    2643             : }
    2644             : 
    2645          34 : TimeField::TimeField( vcl::Window* pParent, WinBits nWinStyle ) :
    2646             :     SpinField( pParent, nWinStyle ),
    2647          34 :     maFirst( GetMin() ),
    2648          68 :     maLast( GetMax() )
    2649             : {
    2650          34 :     SetField( this );
    2651          34 :     SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, false, false ) );
    2652          34 :     Reformat();
    2653          34 : }
    2654             : 
    2655           0 : TimeField::TimeField( vcl::Window* pParent, const ResId& rResId ) :
    2656             :     SpinField( WINDOW_TIMEFIELD ),
    2657           0 :     maFirst( GetMin() ),
    2658           0 :     maLast( GetMax() )
    2659             : {
    2660           0 :     rResId.SetRT( RSC_TIMEFIELD );
    2661           0 :     WinBits nStyle = ImplInitRes( rResId );
    2662           0 :     SpinField::ImplInit( pParent, nStyle );
    2663           0 :     SetField( this );
    2664           0 :     SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, false, false ) );
    2665           0 :     ImplLoadRes( rResId );
    2666             : 
    2667           0 :     if ( !(nStyle & WB_HIDE ) )
    2668           0 :         Show();
    2669           0 : }
    2670             : 
    2671           0 : void TimeField::ImplLoadRes( const ResId& rResId )
    2672             : {
    2673           0 :     SpinField::ImplLoadRes( rResId );
    2674           0 :     ResMgr* pMgr = rResId.GetResMgr();
    2675           0 :     if( pMgr )
    2676             :     {
    2677           0 :         TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
    2678             : 
    2679           0 :         sal_uLong      nMask = ReadLongRes();
    2680             : 
    2681           0 :         if ( TIMEFIELD_FIRST & nMask )
    2682             :         {
    2683           0 :             maFirst = tools::Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
    2684           0 :             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
    2685             :         }
    2686           0 :         if ( TIMEFIELD_LAST & nMask )
    2687             :         {
    2688           0 :             maLast = tools::Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
    2689           0 :             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
    2690             :         }
    2691             :     }
    2692             : 
    2693           0 :     Reformat();
    2694           0 : }
    2695             : 
    2696          68 : TimeField::~TimeField()
    2697             : {
    2698          68 : }
    2699             : 
    2700           0 : bool TimeField::PreNotify( NotifyEvent& rNEvt )
    2701             : {
    2702           0 :     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    2703             :     {
    2704           0 :         if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
    2705           0 :             return true;
    2706             :     }
    2707             : 
    2708           0 :     return SpinField::PreNotify( rNEvt );
    2709             : }
    2710             : 
    2711          24 : bool TimeField::Notify( NotifyEvent& rNEvt )
    2712             : {
    2713          24 :     if ( rNEvt.GetType() == EVENT_GETFOCUS )
    2714           0 :         MarkToBeReformatted( false );
    2715          24 :     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
    2716             :     {
    2717           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
    2718             :         {
    2719           0 :             if ( !ImplAllowMalformedInput() )
    2720           0 :                 Reformat();
    2721             :             else
    2722             :             {
    2723           0 :                 tools::Time aTime( 0, 0, 0 );
    2724           0 :                 if ( ImplTimeGetValue( GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), false ) )
    2725             :                     // even with strict text analysis, our text is a valid time -> do a complete
    2726             :                     // reformat
    2727           0 :                     Reformat();
    2728             :             }
    2729             :         }
    2730             :     }
    2731             : 
    2732          24 :     return SpinField::Notify( rNEvt );
    2733             : }
    2734             : 
    2735         292 : void TimeField::DataChanged( const DataChangedEvent& rDCEvt )
    2736             : {
    2737         292 :     SpinField::DataChanged( rDCEvt );
    2738             : 
    2739         292 :     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
    2740             :     {
    2741           0 :         if ( IsDefaultLocale() )
    2742           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    2743           0 :         ReformatAll();
    2744             :     }
    2745         292 : }
    2746             : 
    2747         112 : void TimeField::Modify()
    2748             : {
    2749         112 :     MarkToBeReformatted( true );
    2750         112 :     SpinField::Modify();
    2751         112 : }
    2752             : 
    2753           8 : void TimeField::Up()
    2754             : {
    2755           8 :     ImplTimeSpinArea( true );
    2756           8 :     SpinField::Up();
    2757           8 : }
    2758             : 
    2759           4 : void TimeField::Down()
    2760             : {
    2761           4 :     ImplTimeSpinArea( false );
    2762           4 :     SpinField::Down();
    2763           4 : }
    2764             : 
    2765           4 : void TimeField::First()
    2766             : {
    2767           4 :     ImplNewFieldValue( maFirst );
    2768           4 :     SpinField::First();
    2769           4 : }
    2770             : 
    2771           4 : void TimeField::Last()
    2772             : {
    2773           4 :     ImplNewFieldValue( maLast );
    2774           4 :     SpinField::Last();
    2775           4 : }
    2776             : 
    2777          50 : void TimeField::SetExtFormat( ExtTimeFieldFormat eFormat )
    2778             : {
    2779          50 :     switch ( eFormat )
    2780             :     {
    2781             :         case EXTTIMEF_24H_SHORT:
    2782             :         {
    2783          20 :             SetTimeFormat( HOUR_24 );
    2784          20 :             SetDuration( false );
    2785          20 :             SetFormat( TimeFieldFormat::F_NONE );
    2786             :         }
    2787          20 :         break;
    2788             :         case EXTTIMEF_24H_LONG:
    2789             :         {
    2790          12 :             SetTimeFormat( HOUR_24 );
    2791          12 :             SetDuration( false );
    2792          12 :             SetFormat( TimeFieldFormat::F_SEC );
    2793             :         }
    2794          12 :         break;
    2795             :         case EXTTIMEF_12H_SHORT:
    2796             :         {
    2797          10 :             SetTimeFormat( HOUR_12 );
    2798          10 :             SetDuration( false );
    2799          10 :             SetFormat( TimeFieldFormat::F_NONE );
    2800             :         }
    2801          10 :         break;
    2802             :         case EXTTIMEF_12H_LONG:
    2803             :         {
    2804           6 :             SetTimeFormat( HOUR_12 );
    2805           6 :             SetDuration( false );
    2806           6 :             SetFormat( TimeFieldFormat::F_SEC );
    2807             :         }
    2808           6 :         break;
    2809             :         case EXTTIMEF_DURATION_SHORT:
    2810             :         {
    2811           2 :             SetDuration( true );
    2812           2 :             SetFormat( TimeFieldFormat::F_NONE );
    2813             :         }
    2814           2 :         break;
    2815             :         case EXTTIMEF_DURATION_LONG:
    2816             :         {
    2817           0 :             SetDuration( true );
    2818           0 :             SetFormat( TimeFieldFormat::F_SEC );
    2819             :         }
    2820           0 :         break;
    2821             :         default:    OSL_FAIL( "ExtTimeFieldFormat unknown!" );
    2822             :     }
    2823             : 
    2824          50 :     if ( GetField() && !GetField()->GetText().isEmpty() )
    2825          50 :         SetUserTime( GetTime() );
    2826          50 :     ReformatAll();
    2827          50 : }
    2828             : 
    2829           0 : TimeBox::TimeBox( vcl::Window* pParent, WinBits nWinStyle ) :
    2830           0 :     ComboBox( pParent, nWinStyle )
    2831             : {
    2832           0 :     SetField( this );
    2833           0 :     SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, false, false ) );
    2834           0 :     Reformat();
    2835           0 : }
    2836             : 
    2837           0 : TimeBox::~TimeBox()
    2838             : {
    2839           0 : }
    2840             : 
    2841           0 : bool TimeBox::PreNotify( NotifyEvent& rNEvt )
    2842             : {
    2843           0 :     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    2844             :     {
    2845           0 :         if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
    2846           0 :             return true;
    2847             :     }
    2848             : 
    2849           0 :     return ComboBox::PreNotify( rNEvt );
    2850             : }
    2851             : 
    2852           0 : bool TimeBox::Notify( NotifyEvent& rNEvt )
    2853             : {
    2854           0 :     if ( rNEvt.GetType() == EVENT_GETFOCUS )
    2855           0 :         MarkToBeReformatted( false );
    2856           0 :     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
    2857             :     {
    2858           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
    2859           0 :             Reformat();
    2860             :     }
    2861             : 
    2862           0 :     return ComboBox::Notify( rNEvt );
    2863             : }
    2864             : 
    2865           0 : void TimeBox::DataChanged( const DataChangedEvent& rDCEvt )
    2866             : {
    2867           0 :     ComboBox::DataChanged( rDCEvt );
    2868             : 
    2869           0 :     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
    2870             :     {
    2871           0 :         if ( IsDefaultLocale() )
    2872           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    2873           0 :         ReformatAll();
    2874             :     }
    2875           0 : }
    2876             : 
    2877           0 : void TimeBox::Modify()
    2878             : {
    2879           0 :     MarkToBeReformatted( true );
    2880           0 :     ComboBox::Modify();
    2881           0 : }
    2882             : 
    2883           0 : void TimeBox::ReformatAll()
    2884             : {
    2885           0 :     OUString aStr;
    2886           0 :     SetUpdateMode( false );
    2887           0 :     sal_uInt16 nEntryCount = GetEntryCount();
    2888           0 :     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
    2889             :     {
    2890           0 :         ImplTimeReformat( GetEntry( i ), aStr );
    2891           0 :         RemoveEntryAt(i);
    2892           0 :         InsertEntry( aStr, i );
    2893             :     }
    2894           0 :     TimeFormatter::Reformat();
    2895           0 :     SetUpdateMode( true );
    2896        1233 : }
    2897             : 
    2898             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10