LCOV - code coverage report
Current view: top level - vcl/source/control - field2.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 780 1486 52.5 %
Date: 2015-06-13 12:38:46 Functions: 87 125 69.6 %
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          71 : uno::Reference< i18n::XCharacterClassification > ImplGetCharClass()
      61             : {
      62          71 :     static uno::Reference< i18n::XCharacterClassification > xCharClass;
      63          71 :     if ( !xCharClass.is() )
      64           2 :         xCharClass = vcl::unohelper::CreateCharacterClassification();
      65             : 
      66          71 :     return xCharClass;
      67             : }
      68             : 
      69         328 : static sal_Unicode* ImplAddString( sal_Unicode* pBuf, const OUString& rStr )
      70             : {
      71         328 :     if ( rStr.getLength() == 1 )
      72         328 :         *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         328 :     return pBuf;
      81             : }
      82             : 
      83         492 : 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         492 :     sal_Unicode* pTempBuf = aTempBuf;
      88         807 :     do
      89             :     {
      90         807 :         *pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
      91         807 :         pTempBuf++;
      92         807 :         nNumber /= 10;
      93         807 :         if ( nMinLen )
      94         807 :             nMinLen--;
      95             :     }
      96             :     while ( nNumber );
      97             : 
      98             :     // fill with zeros up to the minimal length
      99        1349 :     while ( nMinLen > 0 )
     100             :     {
     101         365 :         *pBuf = '0';
     102         365 :         pBuf++;
     103         365 :         nMinLen--;
     104             :     }
     105             : 
     106             :     // copy temp buffer to real buffer
     107         807 :     do
     108             :     {
     109         807 :         pTempBuf--;
     110         807 :         *pBuf = *pTempBuf;
     111         807 :         pBuf++;
     112             :     }
     113             :     while ( pTempBuf != aTempBuf );
     114             : 
     115         492 :     return pBuf;
     116             : }
     117             : 
     118         933 : static sal_uInt16 ImplGetNum( const sal_Unicode*& rpBuf, bool& rbError )
     119             : {
     120         933 :     if ( !*rpBuf )
     121             :     {
     122           0 :         rbError = true;
     123           0 :         return 0;
     124             :     }
     125             : 
     126         933 :     sal_uInt16 nNumber = 0;
     127        4102 :     while( ( *rpBuf >= '0' ) && ( *rpBuf <= '9' ) )
     128             :     {
     129        2236 :         nNumber *= 10;
     130        2236 :         nNumber += *rpBuf - '0';
     131        2236 :         rpBuf++;
     132             :     }
     133             : 
     134         933 :     return nNumber;
     135             : }
     136             : 
     137         933 : static void ImplSkipDelimiters( const sal_Unicode*& rpBuf )
     138             : {
     139        4043 :     while( ( *rpBuf == ',' ) || ( *rpBuf == '.' ) || ( *rpBuf == ';' ) ||
     140        3110 :            ( *rpBuf == ':' ) || ( *rpBuf == '-' ) || ( *rpBuf == '/' ) )
     141             :     {
     142         622 :         rpBuf++;
     143             :     }
     144         933 : }
     145             : 
     146          71 : static bool ImplIsPatternChar( sal_Unicode cChar, sal_Char cEditMask )
     147             : {
     148          71 :     sal_Int32 nType = 0;
     149             : 
     150             :     try
     151             :     {
     152          71 :         OUString aCharStr(cChar);
     153         142 :         nType = ImplGetCharClass()->getStringType( aCharStr, 0, aCharStr.getLength(),
     154         142 :                 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          71 :     if ( (cEditMask == EDITMASK_ALPHA) || (cEditMask == EDITMASK_UPPERALPHA) )
     164             :     {
     165           0 :         if( !CharClass::isLetterType( nType ) )
     166           0 :             return false;
     167             :     }
     168          71 :     else if ( cEditMask == EDITMASK_NUM )
     169             :     {
     170          41 :         if( !CharClass::isNumericType( nType ) )
     171          41 :             return false;
     172             :     }
     173          30 :     else if ( (cEditMask == EDITMASK_ALPHANUM) || (cEditMask == EDITMASK_UPPERALPHANUM) )
     174             :     {
     175          48 :         if( !CharClass::isLetterNumericType( nType ) )
     176           0 :             return false;
     177             :     }
     178           6 :     else if ( (cEditMask == EDITMASK_ALLCHAR) || (cEditMask == EDITMASK_UPPERALLCHAR) )
     179             :     {
     180           0 :         if ( cChar < 32 )
     181           0 :             return false;
     182             :     }
     183           6 :     else if ( cEditMask == EDITMASK_NUMSPACE )
     184             :     {
     185           0 :         if ( !CharClass::isNumericType( nType ) && ( cChar != ' ' ) )
     186           0 :             return false;
     187             :     }
     188             :     else
     189           6 :         return false;
     190             : 
     191          24 :     return true;
     192             : }
     193             : 
     194          71 : static sal_Unicode ImplPatternChar( sal_Unicode cChar, sal_Char cEditMask )
     195             : {
     196          71 :     if ( ImplIsPatternChar( cChar, cEditMask ) )
     197             :     {
     198          24 :         if ( (cEditMask == EDITMASK_UPPERALPHA) ||
     199          24 :              (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          24 :         return cChar;
     206             :     }
     207             :     else
     208          47 :         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          96 : static OUString ImplPatternReformat( const OUString& rStr,
     223             :                                      const OString& rEditMask,
     224             :                                      const OUString& rLiteralMask,
     225             :                                      sal_uInt16 nFormatFlags )
     226             : {
     227          96 :     if (rEditMask.isEmpty())
     228          53 :         return rStr;
     229             : 
     230          43 :     OUString    aStr    = rStr;
     231          86 :     OUStringBuffer    aOutStr = OUString(rLiteralMask);
     232             :     sal_Unicode cTempChar;
     233             :     sal_Unicode cChar;
     234             :     sal_Unicode cLiteral;
     235             :     sal_Char    cMask;
     236          43 :     sal_Int32   nStrIndex = 0;
     237          43 :     sal_Int32   i = 0;
     238             :     sal_Int32   n;
     239             : 
     240         157 :     while ( i < rEditMask.getLength() )
     241             :     {
     242         103 :         if ( nStrIndex >= aStr.getLength() )
     243          32 :             break;
     244             : 
     245          71 :         cChar = aStr[nStrIndex];
     246          71 :         cLiteral = rLiteralMask[i];
     247          71 :         cMask = rEditMask[i];
     248             : 
     249             :         // current position is a literal
     250          71 :         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          71 :             cTempChar = ImplPatternChar( cChar, cMask );
     278          71 :             if ( cTempChar )
     279             :             {
     280             :                 // use this character
     281          24 :                 aOutStr[i] = cTempChar;
     282          24 :                 nStrIndex++;
     283             :             }
     284             :             else
     285             :             {
     286             :                 // copy if it is a literal character
     287          47 :                 if ( cLiteral == cChar )
     288          38 :                     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           9 :                     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           9 :                     nStrIndex++;
     311           9 :                     continue;
     312             :                 }
     313             :             }
     314             :         }
     315             : 
     316          62 :         i++;
     317             :     }
     318             : 
     319          86 :     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          81 : void PatternFormatter::ImplSetMask(const OString& rEditMask, const OUString& rLiteralMask)
     719             : {
     720          81 :     m_aEditMask     = rEditMask;
     721          81 :     maLiteralMask   = rLiteralMask;
     722          81 :     mbSameMask      = true;
     723             : 
     724          81 :     if ( m_aEditMask.getLength() != maLiteralMask.getLength() )
     725             :     {
     726          14 :         OUStringBuffer aBuf(maLiteralMask);
     727          14 :         if (m_aEditMask.getLength() < aBuf.getLength())
     728           0 :             aBuf.remove(m_aEditMask.getLength(), aBuf.getLength() - m_aEditMask.getLength());
     729             :         else
     730          14 :             comphelper::string::padToLength(aBuf, m_aEditMask.getLength(), ' ');
     731          14 :         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          81 :     sal_Int32   i = 0;
     737          81 :     sal_Char    c = 0;
     738         183 :     while ( i < rEditMask.getLength() )
     739             :     {
     740          51 :         sal_Char cTemp = rEditMask[i];
     741          51 :         if ( cTemp != EDITMASK_LITERAL )
     742             :         {
     743          51 :             if ( (cTemp == EDITMASK_ALLCHAR) ||
     744          51 :                  (cTemp == EDITMASK_UPPERALLCHAR) ||
     745             :                  (cTemp == EDITMASK_NUMSPACE) )
     746             :             {
     747           0 :                 mbSameMask = false;
     748           0 :                 break;
     749             :             }
     750          51 :             if ( i < rLiteralMask.getLength() )
     751             :             {
     752          31 :                 if ( rLiteralMask[i] != ' ' )
     753             :                 {
     754          27 :                     mbSameMask = false;
     755          27 :                     break;
     756             :                 }
     757             :             }
     758          24 :             if ( !c )
     759           9 :                 c = cTemp;
     760          24 :             if ( cTemp != c )
     761             :             {
     762           3 :                 mbSameMask = false;
     763           3 :                 break;
     764             :             }
     765             :         }
     766          21 :         i++;
     767             :     }
     768          81 : }
     769             : 
     770           8 : PatternFormatter::PatternFormatter()
     771             : {
     772           8 :     mnFormatFlags       = 0;
     773           8 :     mbSameMask          = true;
     774           8 :     mbInPattKeyInput    = false;
     775           8 : }
     776             : 
     777           0 : PatternFormatter::~PatternFormatter()
     778             : {
     779           0 : }
     780             : 
     781          81 : void PatternFormatter::SetMask( const OString& rEditMask,
     782             :                                 const OUString& rLiteralMask )
     783             : {
     784          81 :     ImplSetMask( rEditMask, rLiteralMask );
     785          81 :     ReformatAll();
     786          81 : }
     787             : 
     788          81 : void PatternFormatter::SetString( const OUString& rStr )
     789             : {
     790          81 :     maFieldString = rStr;
     791          81 :     if ( GetField() )
     792             :     {
     793          81 :         GetField()->SetText( rStr );
     794          81 :         MarkToBeReformatted( false );
     795             :     }
     796          81 : }
     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          96 : void PatternFormatter::Reformat()
     807             : {
     808          96 :     if ( GetField() )
     809             :     {
     810          96 :         ImplSetText( ImplPatternReformat( GetField()->GetText(), m_aEditMask, maLiteralMask, mnFormatFlags ) );
     811          96 :         if ( !mbSameMask && IsStrictFormat() && !GetField()->IsReadOnly() )
     812           0 :             GetField()->SetInsertMode( false );
     813             :     }
     814          96 : }
     815             : 
     816           8 : PatternField::PatternField( vcl::Window* pParent, WinBits nWinStyle ) :
     817           8 :     SpinField( pParent, nWinStyle )
     818             : {
     819           8 :     SetField( this );
     820           8 :     Reformat();
     821           8 : }
     822             : 
     823           0 : bool PatternField::PreNotify( NotifyEvent& rNEvt )
     824             : {
     825           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
     826             :     {
     827           0 :         if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
     828           0 :                                          IsStrictFormat(), GetFormatFlags(),
     829           0 :                                          ImplIsSameMask(), ImplGetInPattKeyInput() ) )
     830           0 :             return true;
     831             :     }
     832             : 
     833           0 :     return SpinField::PreNotify( rNEvt );
     834             : }
     835             : 
     836           8 : bool PatternField::Notify( NotifyEvent& rNEvt )
     837             : {
     838           8 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
     839           0 :         MarkToBeReformatted( false );
     840           8 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
     841             :     {
     842           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
     843           0 :             Reformat();
     844             :     }
     845             : 
     846           8 :     return SpinField::Notify( rNEvt );
     847             : }
     848             : 
     849           0 : void PatternField::Modify()
     850             : {
     851           0 :     if ( !ImplGetInPattKeyInput() )
     852             :     {
     853           0 :         if ( IsStrictFormat() )
     854           0 :             ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
     855             :         else
     856           0 :             MarkToBeReformatted( true );
     857             :     }
     858             : 
     859           0 :     SpinField::Modify();
     860           0 : }
     861             : 
     862           0 : PatternBox::PatternBox( vcl::Window* pParent, WinBits nWinStyle ) :
     863           0 :     ComboBox( pParent, nWinStyle )
     864             : {
     865           0 :     SetField( this );
     866           0 :     Reformat();
     867           0 : }
     868             : 
     869           0 : bool PatternBox::PreNotify( NotifyEvent& rNEvt )
     870             : {
     871           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
     872             :     {
     873           0 :         if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
     874           0 :                                          IsStrictFormat(), GetFormatFlags(),
     875           0 :                                          ImplIsSameMask(), ImplGetInPattKeyInput() ) )
     876           0 :             return true;
     877             :     }
     878             : 
     879           0 :     return ComboBox::PreNotify( rNEvt );
     880             : }
     881             : 
     882           0 : bool PatternBox::Notify( NotifyEvent& rNEvt )
     883             : {
     884           0 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
     885           0 :         MarkToBeReformatted( false );
     886           0 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
     887             :     {
     888           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
     889           0 :             Reformat();
     890             :     }
     891             : 
     892           0 :     return ComboBox::Notify( rNEvt );
     893             : }
     894             : 
     895           0 : void PatternBox::Modify()
     896             : {
     897           0 :     if ( !ImplGetInPattKeyInput() )
     898             :     {
     899           0 :         if ( IsStrictFormat() )
     900           0 :             ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
     901             :         else
     902           0 :             MarkToBeReformatted( true );
     903             :     }
     904             : 
     905           0 :     ComboBox::Modify();
     906           0 : }
     907             : 
     908           0 : void PatternBox::ReformatAll()
     909             : {
     910           0 :     OUString aStr;
     911           0 :     SetUpdateMode( false );
     912           0 :     sal_uInt16 nEntryCount = GetEntryCount();
     913           0 :     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
     914             :     {
     915           0 :         aStr = ImplPatternReformat( GetEntry( i ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
     916           0 :         RemoveEntryAt(i);
     917           0 :         InsertEntry( aStr, i );
     918             :     }
     919           0 :     PatternFormatter::Reformat();
     920           0 :     SetUpdateMode( true );
     921           0 : }
     922             : 
     923           4 : static ExtDateFieldFormat ImplGetExtFormat( DateFormat eOld )
     924             : {
     925           4 :     switch( eOld )
     926             :     {
     927           0 :         case DMY:   return XTDATEF_SHORT_DDMMYY;
     928           4 :         case MDY:   return XTDATEF_SHORT_MMDDYY;
     929           0 :         default:    return XTDATEF_SHORT_YYMMDD;
     930             :     }
     931             : }
     932             : 
     933         166 : static sal_uInt16 ImplCutNumberFromString( OUString& rStr )
     934             : {
     935         166 :     sal_Int32 i1 = 0;
     936        1113 :     while (i1 != rStr.getLength() && !(rStr[i1] >= '0' && rStr[i1] <= '9')) {
     937         781 :         ++i1;
     938             :     }
     939         166 :     sal_Int32 i2 = i1;
     940         682 :     while (i2 != rStr.getLength() && rStr[i2] >= '0' && rStr[i2] <= '9') {
     941         350 :         ++i2;
     942             :     }
     943         166 :     sal_Int32 nValue = rStr.copy(i1, i2-i1).toInt32();
     944         166 :     rStr = rStr.copy(std::min(i2+1, rStr.getLength()));
     945         166 :     return nValue;
     946             : }
     947             : 
     948         788 : static bool ImplCutMonthName( OUString& rStr, const OUString& _rLookupMonthName )
     949             : {
     950         788 :     sal_Int32 index = 0;
     951         788 :     rStr = rStr.replaceFirst(_rLookupMonthName, OUString(), &index);
     952         788 :     return index >= 0;
     953             : }
     954             : 
     955          78 : static sal_uInt16 ImplCutMonthFromString( OUString& rStr, const CalendarWrapper& rCalendarWrapper )
     956             : {
     957             :     // search for a month' name
     958         438 :     for ( sal_uInt16 i=1; i <= 12; i++ )
     959             :     {
     960         428 :         OUString aMonthName = rCalendarWrapper.getMonths()[i-1].FullName;
     961             :         // long month name?
     962         428 :         if ( ImplCutMonthName( rStr, aMonthName ) )
     963          68 :             return i;
     964             : 
     965             :         // short month name?
     966         720 :         OUString aAbbrevMonthName = rCalendarWrapper.getMonths()[i-1].AbbrevName;
     967         360 :         if ( ImplCutMonthName( rStr, aAbbrevMonthName ) )
     968           0 :             return i;
     969         360 :     }
     970             : 
     971          10 :     return ImplCutNumberFromString( rStr );
     972             : }
     973             : 
     974         513 : static OUString ImplGetDateSep( const LocaleDataWrapper& rLocaleDataWrapper, ExtDateFieldFormat eFormat )
     975             : {
     976         513 :     if ( ( eFormat == XTDATEF_SHORT_YYMMDD_DIN5008 ) || ( eFormat == XTDATEF_SHORT_YYYYMMDD_DIN5008 ) )
     977           0 :         return OUString("-");
     978             :     else
     979         513 :         return rLocaleDataWrapper.getDateSep();
     980             : }
     981             : 
     982           0 : static bool ImplDateProcessKeyInput( Edit*, const KeyEvent& rKEvt, ExtDateFieldFormat eFormat,
     983             :                                      const LocaleDataWrapper& rLocaleDataWrapper  )
     984             : {
     985           0 :     sal_Unicode cChar = rKEvt.GetCharCode();
     986           0 :     sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
     987           0 :     if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
     988           0 :          (nGroup == KEYGROUP_MISC)||
     989           0 :          ((cChar >= '0') && (cChar <= '9')) ||
     990           0 :          (cChar == ImplGetDateSep( rLocaleDataWrapper, eFormat )[0]) )
     991           0 :         return false;
     992             :     else
     993           0 :         return true;
     994             : }
     995             : 
     996         392 : static bool ImplDateGetValue( const OUString& rStr, Date& rDate, ExtDateFieldFormat eDateFormat,
     997             :                               const LocaleDataWrapper& rLocaleDataWrapper, const CalendarWrapper& rCalendarWrapper,
     998             :                               const AllSettings& )
     999             : {
    1000         392 :     sal_uInt16 nDay = 0;
    1001         392 :     sal_uInt16 nMonth = 0;
    1002         392 :     sal_uInt16 nYear = 0;
    1003         392 :     bool bError = false;
    1004         392 :     OUString aStr( rStr );
    1005             : 
    1006         392 :     if ( eDateFormat == XTDATEF_SYSTEM_LONG )
    1007             :     {
    1008          78 :         DateFormat eFormat = rLocaleDataWrapper.getLongDateFormat();
    1009          78 :         switch( eFormat )
    1010             :         {
    1011             :             case MDY:
    1012          78 :                 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
    1013          78 :                 nDay = ImplCutNumberFromString( aStr );
    1014          78 :                 nYear  = ImplCutNumberFromString( aStr );
    1015          78 :                 break;
    1016             :             case DMY:
    1017           0 :                 nDay = ImplCutNumberFromString( aStr );
    1018           0 :                 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
    1019           0 :                 nYear  = ImplCutNumberFromString( aStr );
    1020           0 :                 break;
    1021             :             case YMD:
    1022             :             default:
    1023           0 :                 nYear = ImplCutNumberFromString( aStr );
    1024           0 :                 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
    1025           0 :                 nDay  = ImplCutNumberFromString( aStr );
    1026           0 :                 break;
    1027             :         }
    1028             :     }
    1029             :     else
    1030             :     {
    1031         314 :         bool bYear = true;
    1032             : 
    1033             :         // Check if year is present:
    1034         314 :         OUString aDateSep = ImplGetDateSep( rLocaleDataWrapper, eDateFormat );
    1035         314 :         sal_Int32 nSepPos = aStr.indexOf( aDateSep );
    1036         314 :         if ( nSepPos < 0 )
    1037           3 :             return false;
    1038         311 :         nSepPos = aStr.indexOf( aDateSep, nSepPos+1 );
    1039         311 :         if ( ( nSepPos < 0 ) || ( nSepPos == (aStr.getLength()-1) ) )
    1040             :         {
    1041           0 :             bYear = false;
    1042           0 :             nYear = Date( Date::SYSTEM ).GetYear();
    1043             :         }
    1044             : 
    1045         311 :         const sal_Unicode* pBuf = aStr.getStr();
    1046         311 :         ImplSkipDelimiters( pBuf );
    1047             : 
    1048         311 :         switch ( eDateFormat )
    1049             :         {
    1050             :             case XTDATEF_SHORT_DDMMYY:
    1051             :             case XTDATEF_SHORT_DDMMYYYY:
    1052             :             {
    1053           7 :                 nDay = ImplGetNum( pBuf, bError );
    1054           7 :                 ImplSkipDelimiters( pBuf );
    1055           7 :                 nMonth = ImplGetNum( pBuf, bError );
    1056           7 :                 ImplSkipDelimiters( pBuf );
    1057           7 :                 if ( bYear )
    1058           7 :                     nYear = ImplGetNum( pBuf, bError );
    1059             :             }
    1060           7 :             break;
    1061             :             case XTDATEF_SHORT_MMDDYY:
    1062             :             case XTDATEF_SHORT_MMDDYYYY:
    1063             :             {
    1064         304 :                 nMonth = ImplGetNum( pBuf, bError );
    1065         304 :                 ImplSkipDelimiters( pBuf );
    1066         304 :                 nDay = ImplGetNum( pBuf, bError );
    1067         304 :                 ImplSkipDelimiters( pBuf );
    1068         304 :                 if ( bYear )
    1069         304 :                     nYear = ImplGetNum( pBuf, bError );
    1070             :             }
    1071         304 :             break;
    1072             :             case XTDATEF_SHORT_YYMMDD:
    1073             :             case XTDATEF_SHORT_YYYYMMDD:
    1074             :             case XTDATEF_SHORT_YYMMDD_DIN5008:
    1075             :             case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1076             :             {
    1077           0 :                 if ( bYear )
    1078           0 :                     nYear = ImplGetNum( pBuf, bError );
    1079           0 :                 ImplSkipDelimiters( pBuf );
    1080           0 :                 nMonth = ImplGetNum( pBuf, bError );
    1081           0 :                 ImplSkipDelimiters( pBuf );
    1082           0 :                 nDay = ImplGetNum( pBuf, bError );
    1083             :             }
    1084           0 :             break;
    1085             : 
    1086             :             default:
    1087             :             {
    1088             :                 OSL_FAIL( "DateFormat???" );
    1089             :             }
    1090         311 :         }
    1091             :     }
    1092             : 
    1093         389 :     if ( bError || !nDay || !nMonth )
    1094         130 :         return false;
    1095             : 
    1096         259 :     Date aNewDate( nDay, nMonth, nYear );
    1097         259 :     DateFormatter::ExpandCentury( aNewDate, utl::MiscCfg().GetYear2000() );
    1098         259 :     if ( aNewDate.IsValidDate() )
    1099             :     {
    1100         257 :         rDate = aNewDate;
    1101         257 :         return true;
    1102             :     }
    1103           2 :     return false;
    1104             : }
    1105             : 
    1106         175 : bool DateFormatter::ImplDateReformat( const OUString& rStr, OUString& rOutStr, const AllSettings& rSettings )
    1107             : {
    1108         175 :     Date aDate( 0, 0, 0 );
    1109         175 :     if ( !ImplDateGetValue( rStr, aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
    1110          75 :         return true;
    1111             : 
    1112         100 :     Date aTempDate = aDate;
    1113         100 :     if ( aTempDate > GetMax() )
    1114          25 :         aTempDate = GetMax();
    1115          75 :     else if ( aTempDate < GetMin() )
    1116           2 :         aTempDate = GetMin();
    1117             : 
    1118         100 :     if ( GetErrorHdl().IsSet() && (aDate != aTempDate) )
    1119             :     {
    1120           0 :         maCorrectedDate = aTempDate;
    1121           0 :         if( !GetErrorHdl().Call( this ) )
    1122             :         {
    1123           0 :             maCorrectedDate = Date( Date::SYSTEM );
    1124           0 :             return false;
    1125             :         }
    1126             :         else
    1127           0 :             maCorrectedDate = Date( Date::SYSTEM );
    1128             :     }
    1129             : 
    1130         100 :     rOutStr = ImplGetDateAsText( aTempDate, rSettings );
    1131             : 
    1132         100 :     return true;
    1133             : }
    1134             : 
    1135         199 : OUString DateFormatter::ImplGetDateAsText( const Date& rDate,
    1136             :                                            const AllSettings& ) const
    1137             : {
    1138         199 :     bool bShowCentury = false;
    1139         199 :     switch ( GetExtDateFormat() )
    1140             :     {
    1141             :         case XTDATEF_SYSTEM_SHORT_YYYY:
    1142             :         case XTDATEF_SYSTEM_LONG:
    1143             :         case XTDATEF_SHORT_DDMMYYYY:
    1144             :         case XTDATEF_SHORT_MMDDYYYY:
    1145             :         case XTDATEF_SHORT_YYYYMMDD:
    1146             :         case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1147             :         {
    1148          91 :             bShowCentury = true;
    1149             :         }
    1150          91 :         break;
    1151             :         default:
    1152             :         {
    1153         108 :             bShowCentury = false;
    1154             :         }
    1155             :     }
    1156             : 
    1157         199 :     if ( !bShowCentury )
    1158             :     {
    1159             :         // Check if I have to use force showing the century
    1160         108 :         sal_uInt16 nTwoDigitYearStart = utl::MiscCfg().GetYear2000();
    1161         108 :         sal_uInt16 nYear = rDate.GetYear();
    1162             : 
    1163             :         // If year is not in double digit range
    1164         108 :         if ( (nYear < nTwoDigitYearStart) || (nYear >= nTwoDigitYearStart+100) )
    1165          38 :             bShowCentury = true;
    1166             :     }
    1167             : 
    1168             :     sal_Unicode aBuf[128];
    1169         199 :     sal_Unicode* pBuf = aBuf;
    1170             : 
    1171         199 :     OUString aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), GetExtDateFormat( true ) );
    1172         199 :     sal_uInt16 nDay = rDate.GetDay();
    1173         199 :     sal_uInt16 nMonth = rDate.GetMonth();
    1174         199 :     sal_uInt16 nYear = rDate.GetYear();
    1175         199 :     sal_uInt16 nYearLen = bShowCentury ? 4 : 2;
    1176             : 
    1177         199 :     if ( !bShowCentury )
    1178          70 :         nYear %= 100;
    1179             : 
    1180         199 :     switch ( GetExtDateFormat( true ) )
    1181             :     {
    1182             :         case XTDATEF_SYSTEM_LONG:
    1183             :         {
    1184          35 :             return ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, false, 1, !bShowCentury );
    1185             :         }
    1186             :         case XTDATEF_SHORT_DDMMYY:
    1187             :         case XTDATEF_SHORT_DDMMYYYY:
    1188             :         {
    1189           3 :             pBuf = ImplAddNum( pBuf, nDay, 2 );
    1190           3 :             pBuf = ImplAddString( pBuf, aDateSep );
    1191           3 :             pBuf = ImplAddNum( pBuf, nMonth, 2 );
    1192           3 :             pBuf = ImplAddString( pBuf, aDateSep );
    1193           3 :             pBuf = ImplAddNum( pBuf, nYear, nYearLen );
    1194             :         }
    1195           3 :         break;
    1196             :         case XTDATEF_SHORT_MMDDYY:
    1197             :         case XTDATEF_SHORT_MMDDYYYY:
    1198             :         {
    1199         161 :             pBuf = ImplAddNum( pBuf, nMonth, 2 );
    1200         161 :             pBuf = ImplAddString( pBuf, aDateSep );
    1201         161 :             pBuf = ImplAddNum( pBuf, nDay, 2 );
    1202         161 :             pBuf = ImplAddString( pBuf, aDateSep );
    1203         161 :             pBuf = ImplAddNum( pBuf, nYear, nYearLen );
    1204             :         }
    1205         161 :         break;
    1206             :         case XTDATEF_SHORT_YYMMDD:
    1207             :         case XTDATEF_SHORT_YYYYMMDD:
    1208             :         case XTDATEF_SHORT_YYMMDD_DIN5008:
    1209             :         case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1210             :         {
    1211           0 :             pBuf = ImplAddNum( pBuf, nYear, nYearLen );
    1212           0 :             pBuf = ImplAddString( pBuf, aDateSep );
    1213           0 :             pBuf = ImplAddNum( pBuf, nMonth, 2 );
    1214           0 :             pBuf = ImplAddString( pBuf, aDateSep );
    1215           0 :             pBuf = ImplAddNum( pBuf, nDay, 2 );
    1216             :         }
    1217           0 :         break;
    1218             :         default:
    1219             :         {
    1220             :             OSL_FAIL( "DateFormat???" );
    1221             :         }
    1222             :     }
    1223             : 
    1224         164 :     return OUString(aBuf, pBuf-aBuf);
    1225             : }
    1226             : 
    1227           2 : static void ImplDateIncrementDay( Date& rDate, bool bUp )
    1228             : {
    1229           2 :     DateFormatter::ExpandCentury( rDate );
    1230             : 
    1231           2 :     if ( bUp )
    1232             :     {
    1233           2 :         if ( (rDate.GetDay() != 31) || (rDate.GetMonth() != 12) || (rDate.GetYear() != 9999) )
    1234           2 :             ++rDate;
    1235             :     }
    1236             :     else
    1237             :     {
    1238           0 :         if ( (rDate.GetDay() != 1 ) || (rDate.GetMonth() != 1) || (rDate.GetYear() != 0) )
    1239           0 :             --rDate;
    1240             :     }
    1241           2 : }
    1242             : 
    1243           4 : static void ImplDateIncrementMonth( Date& rDate, bool bUp )
    1244             : {
    1245           4 :     DateFormatter::ExpandCentury( rDate );
    1246             : 
    1247           4 :     sal_uInt16 nMonth = rDate.GetMonth();
    1248           4 :     sal_uInt16 nYear = rDate.GetYear();
    1249           4 :     if ( bUp )
    1250             :     {
    1251           2 :         if ( (nMonth == 12) && (nYear < 9999) )
    1252             :         {
    1253           0 :             rDate.SetMonth( 1 );
    1254           0 :             rDate.SetYear( nYear + 1 );
    1255             :         }
    1256             :         else
    1257             :         {
    1258           2 :             if ( nMonth < 12 )
    1259           2 :                 rDate.SetMonth( nMonth + 1 );
    1260             :         }
    1261             :     }
    1262             :     else
    1263             :     {
    1264           2 :         if ( (nMonth == 1) && (nYear > 0) )
    1265             :         {
    1266           0 :             rDate.SetMonth( 12 );
    1267           0 :             rDate.SetYear( nYear - 1 );
    1268             :         }
    1269             :         else
    1270             :         {
    1271           2 :             if ( nMonth > 1 )
    1272           2 :                 rDate.SetMonth( nMonth - 1 );
    1273             :         }
    1274             :     }
    1275             : 
    1276           4 :     sal_uInt16 nDaysInMonth = Date::GetDaysInMonth( rDate.GetMonth(), rDate.GetYear());
    1277           4 :     if ( rDate.GetDay() > nDaysInMonth )
    1278           0 :         rDate.SetDay( nDaysInMonth );
    1279           4 : }
    1280             : 
    1281           0 : static void ImplDateIncrementYear( Date& rDate, bool bUp )
    1282             : {
    1283           0 :     DateFormatter::ExpandCentury( rDate );
    1284             : 
    1285           0 :     sal_uInt16 nYear = rDate.GetYear();
    1286           0 :     sal_uInt16 nMonth = rDate.GetMonth();
    1287           0 :     if ( bUp )
    1288             :     {
    1289           0 :         if ( nYear < 9999 )
    1290           0 :             rDate.SetYear( nYear + 1 );
    1291             :     }
    1292             :     else
    1293             :     {
    1294           0 :         if ( nYear > 0 )
    1295           0 :             rDate.SetYear( nYear - 1 );
    1296             :     }
    1297           0 :     if (nMonth == 2)
    1298             :     {
    1299             :         // Handle February 29 from leap year to non-leap year.
    1300           0 :         sal_uInt16 nDay = rDate.GetDay();
    1301           0 :         if (nDay > 28)
    1302             :         {
    1303             :             // The check would not be necessary if it was guaranteed that the
    1304             :             // date was valid before and actually was a leap year,
    1305             :             // de-/incrementing a leap year with 29 always results in 28.
    1306           0 :             sal_uInt16 nDaysInMonth = Date::GetDaysInMonth( nMonth, rDate.GetYear());
    1307           0 :             if (nDay > nDaysInMonth)
    1308           0 :                 rDate.SetDay( nDaysInMonth);
    1309             :         }
    1310             :     }
    1311           0 : }
    1312             : 
    1313          46 : bool DateFormatter::ImplAllowMalformedInput() const
    1314             : {
    1315          46 :     return !IsEnforceValidValue();
    1316             : }
    1317             : 
    1318           6 : void DateField::ImplDateSpinArea( bool bUp )
    1319             : {
    1320             :     // increment days if all is selected
    1321           6 :     if ( GetField() )
    1322             :     {
    1323           6 :         Date aDate( GetDate() );
    1324           6 :         Selection aSelection = GetField()->GetSelection();
    1325           6 :         aSelection.Justify();
    1326           6 :         OUString aText( GetText() );
    1327           6 :         if ( (sal_Int32)aSelection.Len() == aText.getLength() )
    1328           2 :             ImplDateIncrementDay( aDate, bUp );
    1329             :         else
    1330             :         {
    1331           4 :             sal_Int8 nDateArea = 0;
    1332             : 
    1333           4 :             ExtDateFieldFormat eFormat = GetExtDateFormat( true );
    1334           4 :             if ( eFormat == XTDATEF_SYSTEM_LONG )
    1335             :             {
    1336           4 :                 eFormat = ImplGetExtFormat( ImplGetLocaleDataWrapper().getLongDateFormat() );
    1337           4 :                 nDateArea = 1;
    1338             :             }
    1339             :             else
    1340             :             {
    1341             :                 // search area
    1342           0 :                 sal_Int32 nPos = 0;
    1343           0 :                 OUString aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), eFormat );
    1344           0 :                 for ( sal_Int8 i = 1; i <= 3; i++ )
    1345             :                 {
    1346           0 :                     nPos = aText.indexOf( aDateSep, nPos );
    1347           0 :                     if ( nPos >= (sal_Int32)aSelection.Max() )
    1348             :                     {
    1349           0 :                         nDateArea = i;
    1350           0 :                         break;
    1351             :                     }
    1352             :                     else
    1353           0 :                         nPos++;
    1354           0 :                 }
    1355             :             }
    1356             : 
    1357           4 :             switch( eFormat )
    1358             :             {
    1359             :                 case XTDATEF_SHORT_MMDDYY:
    1360             :                 case XTDATEF_SHORT_MMDDYYYY:
    1361           4 :                 switch( nDateArea )
    1362             :                 {
    1363           4 :                     case 1: ImplDateIncrementMonth( aDate, bUp );
    1364           4 :                             break;
    1365           0 :                     case 2: ImplDateIncrementDay( aDate, bUp );
    1366           0 :                             break;
    1367           0 :                     case 3: ImplDateIncrementYear( aDate, bUp );
    1368           0 :                             break;
    1369             :                 }
    1370           4 :                 break;
    1371             :                 case XTDATEF_SHORT_DDMMYY:
    1372             :                 case XTDATEF_SHORT_DDMMYYYY:
    1373           0 :                 switch( nDateArea )
    1374             :                 {
    1375           0 :                     case 1: ImplDateIncrementDay( aDate, bUp );
    1376           0 :                             break;
    1377           0 :                     case 2: ImplDateIncrementMonth( aDate, bUp );
    1378           0 :                             break;
    1379           0 :                     case 3: ImplDateIncrementYear( aDate, bUp );
    1380           0 :                             break;
    1381             :                 }
    1382           0 :                 break;
    1383             :                 case XTDATEF_SHORT_YYMMDD:
    1384             :                 case XTDATEF_SHORT_YYYYMMDD:
    1385             :                 case XTDATEF_SHORT_YYMMDD_DIN5008:
    1386             :                 case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1387           0 :                 switch( nDateArea )
    1388             :                 {
    1389           0 :                     case 1: ImplDateIncrementYear( aDate, bUp );
    1390           0 :                             break;
    1391           0 :                     case 2: ImplDateIncrementMonth( aDate, bUp );
    1392           0 :                             break;
    1393           0 :                     case 3: ImplDateIncrementDay( aDate, bUp );
    1394           0 :                             break;
    1395             :                 }
    1396           0 :                 break;
    1397             :                 default:
    1398             :                     OSL_FAIL( "invalid conversion" );
    1399           0 :                     break;
    1400             :             }
    1401             :         }
    1402             : 
    1403           6 :         ImplNewFieldValue( aDate );
    1404             :     }
    1405           6 : }
    1406             : 
    1407          34 : void DateFormatter::ImplInit()
    1408             : {
    1409          34 :     mbLongFormat        = false;
    1410          34 :     mbShowDateCentury   = true;
    1411          34 :     mpCalendarWrapper   = NULL;
    1412          34 :     mnDateFormat        = 0xFFFF;
    1413          34 :     mnExtDateFormat     = XTDATEF_SYSTEM_SHORT;
    1414          34 : }
    1415             : 
    1416          34 : DateFormatter::DateFormatter() :
    1417             :     maFieldDate( 0 ),
    1418             :     maLastDate( 0 ),
    1419             :     maMin( 1, 1, 1900 ),
    1420             :     maMax( 31, 12, 2200 ),
    1421             :     maCorrectedDate( Date::SYSTEM ),
    1422          34 :     mbEnforceValidValue( true )
    1423             : {
    1424          34 :     ImplInit();
    1425          34 : }
    1426             : 
    1427           0 : DateFormatter::~DateFormatter()
    1428             : {
    1429           0 :     delete mpCalendarWrapper;
    1430           0 :     mpCalendarWrapper = NULL;
    1431           0 : }
    1432             : 
    1433           0 : void DateFormatter::SetLocale( const ::com::sun::star::lang::Locale& rLocale )
    1434             : {
    1435           0 :     delete mpCalendarWrapper;
    1436           0 :     mpCalendarWrapper = NULL;
    1437           0 :     FormatterBase::SetLocale( rLocale );
    1438           0 : }
    1439             : 
    1440         427 : CalendarWrapper& DateFormatter::GetCalendarWrapper() const
    1441             : {
    1442         427 :     if ( !mpCalendarWrapper )
    1443             :     {
    1444          34 :         const_cast<DateFormatter*>(this)->mpCalendarWrapper = new CalendarWrapper( comphelper::getProcessComponentContext() );
    1445          34 :         mpCalendarWrapper->loadDefaultCalendar( GetLocale() );
    1446             :     }
    1447             : 
    1448         427 :     return *mpCalendarWrapper;
    1449             : }
    1450             : 
    1451          49 : void DateFormatter::SetExtDateFormat( ExtDateFieldFormat eFormat )
    1452             : {
    1453          49 :     mnExtDateFormat = eFormat;
    1454          49 :     ReformatAll();
    1455          49 : }
    1456             : 
    1457         999 : ExtDateFieldFormat DateFormatter::GetExtDateFormat( bool bResolveSystemFormat ) const
    1458             : {
    1459         999 :     ExtDateFieldFormat eDateFormat = (ExtDateFieldFormat)mnExtDateFormat;
    1460             : 
    1461         999 :     if ( bResolveSystemFormat && ( eDateFormat <= XTDATEF_SYSTEM_SHORT_YYYY ) )
    1462             :     {
    1463         544 :         bool bShowCentury = (eDateFormat == XTDATEF_SYSTEM_SHORT_YYYY);
    1464         544 :         switch ( ImplGetLocaleDataWrapper().getDateFormat() )
    1465             :         {
    1466           0 :             case DMY:   eDateFormat = bShowCentury ? XTDATEF_SHORT_DDMMYYYY : XTDATEF_SHORT_DDMMYY;
    1467           0 :                         break;
    1468         544 :             case MDY:   eDateFormat = bShowCentury ? XTDATEF_SHORT_MMDDYYYY : XTDATEF_SHORT_MMDDYY;
    1469         544 :                         break;
    1470           0 :             default:    eDateFormat = bShowCentury ? XTDATEF_SHORT_YYYYMMDD : XTDATEF_SHORT_YYMMDD;
    1471             : 
    1472             :         }
    1473             :     }
    1474             : 
    1475         999 :     return eDateFormat;
    1476             : }
    1477             : 
    1478         148 : void DateFormatter::ReformatAll()
    1479             : {
    1480         148 :     Reformat();
    1481         148 : }
    1482             : 
    1483          44 : void DateFormatter::SetMin( const Date& rNewMin )
    1484             : {
    1485          44 :     maMin = rNewMin;
    1486          44 :     if ( !IsEmptyFieldValue() )
    1487          38 :         ReformatAll();
    1488          44 : }
    1489             : 
    1490          44 : void DateFormatter::SetMax( const Date& rNewMax )
    1491             : {
    1492          44 :     maMax = rNewMax;
    1493          44 :     if ( !IsEmptyFieldValue() )
    1494          38 :         ReformatAll();
    1495          44 : }
    1496             : 
    1497           4 : void DateFormatter::SetLongFormat( bool bLong )
    1498             : {
    1499           4 :     mbLongFormat = bLong;
    1500             : 
    1501             :     // #91913# Remove LongFormat and DateShowCentury - redundant
    1502           4 :     if ( bLong )
    1503             :     {
    1504           4 :         SetExtDateFormat( XTDATEF_SYSTEM_LONG );
    1505             :     }
    1506             :     else
    1507             :     {
    1508           0 :         if( mnExtDateFormat == XTDATEF_SYSTEM_LONG )
    1509           0 :             SetExtDateFormat( XTDATEF_SYSTEM_SHORT );
    1510             :     }
    1511             : 
    1512           4 :     ReformatAll();
    1513           4 : }
    1514             : 
    1515           6 : void DateFormatter::SetShowDateCentury( bool bShowDateCentury )
    1516             : {
    1517           6 :     mbShowDateCentury = bShowDateCentury;
    1518             : 
    1519             :     // #91913# Remove LongFormat and DateShowCentury - redundant
    1520           6 :     if ( bShowDateCentury )
    1521             :     {
    1522           6 :         switch ( GetExtDateFormat() )
    1523             :         {
    1524             :             case XTDATEF_SYSTEM_SHORT:
    1525             :             case XTDATEF_SYSTEM_SHORT_YY:
    1526           3 :                 SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );  break;
    1527             :             case XTDATEF_SHORT_DDMMYY:
    1528           0 :                 SetExtDateFormat( XTDATEF_SHORT_DDMMYYYY );     break;
    1529             :             case XTDATEF_SHORT_MMDDYY:
    1530           0 :                 SetExtDateFormat( XTDATEF_SHORT_MMDDYYYY );     break;
    1531             :             case XTDATEF_SHORT_YYMMDD:
    1532           0 :                 SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD );     break;
    1533             :             case XTDATEF_SHORT_YYMMDD_DIN5008:
    1534           0 :                 SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD_DIN5008 ); break;
    1535             :             default:
    1536             :                 ;
    1537             :         }
    1538             :     }
    1539             :     else
    1540             :     {
    1541           0 :         switch ( GetExtDateFormat() )
    1542             :         {
    1543             :             case XTDATEF_SYSTEM_SHORT:
    1544             :             case XTDATEF_SYSTEM_SHORT_YYYY:
    1545           0 :                 SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YY );    break;
    1546             :             case XTDATEF_SHORT_DDMMYYYY:
    1547           0 :                 SetExtDateFormat( XTDATEF_SHORT_DDMMYY );       break;
    1548             :             case XTDATEF_SHORT_MMDDYYYY:
    1549           0 :                 SetExtDateFormat( XTDATEF_SHORT_MMDDYY );       break;
    1550             :             case XTDATEF_SHORT_YYYYMMDD:
    1551           0 :                 SetExtDateFormat( XTDATEF_SHORT_YYMMDD );       break;
    1552             :             case XTDATEF_SHORT_YYYYMMDD_DIN5008:
    1553           0 :                 SetExtDateFormat( XTDATEF_SHORT_YYMMDD_DIN5008 );  break;
    1554             :             default:
    1555             :                 ;
    1556             :         }
    1557             :     }
    1558             : 
    1559           6 :     ReformatAll();
    1560           6 : }
    1561             : 
    1562          89 : void DateFormatter::SetDate( const Date& rNewDate )
    1563             : {
    1564          89 :     SetUserDate( rNewDate );
    1565          89 :     maFieldDate = maLastDate;
    1566          89 :     maLastDate = GetDate();
    1567          89 : }
    1568             : 
    1569          89 : void DateFormatter::SetUserDate( const Date& rNewDate )
    1570             : {
    1571          89 :     ImplSetUserDate( rNewDate );
    1572          89 : }
    1573             : 
    1574          99 : void DateFormatter::ImplSetUserDate( const Date& rNewDate, Selection* pNewSelection )
    1575             : {
    1576          99 :     Date aNewDate = rNewDate;
    1577          99 :     if ( aNewDate > maMax )
    1578          15 :         aNewDate = maMax;
    1579          84 :     else if ( aNewDate < maMin )
    1580          21 :         aNewDate = maMin;
    1581          99 :     maLastDate = aNewDate;
    1582             : 
    1583          99 :     if ( GetField() )
    1584          99 :         ImplSetText( ImplGetDateAsText( aNewDate, GetFieldSettings() ), pNewSelection );
    1585          99 : }
    1586             : 
    1587          10 : void DateFormatter::ImplNewFieldValue( const Date& rDate )
    1588             : {
    1589          10 :     if ( GetField() )
    1590             :     {
    1591          10 :         Selection aSelection = GetField()->GetSelection();
    1592          10 :         aSelection.Justify();
    1593          10 :         OUString aText = GetField()->GetText();
    1594             : 
    1595             :         // If selected until the end then keep it that way
    1596          10 :         if ( (sal_Int32)aSelection.Max() == aText.getLength() )
    1597             :         {
    1598          10 :             if ( !aSelection.Len() )
    1599          10 :                 aSelection.Min() = SELECTION_MAX;
    1600          10 :             aSelection.Max() = SELECTION_MAX;
    1601             :         }
    1602             : 
    1603          10 :         Date aOldLastDate  = maLastDate;
    1604          10 :         ImplSetUserDate( rDate, &aSelection );
    1605          10 :         maLastDate = aOldLastDate;
    1606             : 
    1607             :         // Modify at Edit is only set at KeyInput
    1608          10 :         if ( GetField()->GetText() != aText )
    1609             :         {
    1610          10 :             GetField()->SetModifyFlag();
    1611          10 :             GetField()->Modify();
    1612          10 :         }
    1613             :     }
    1614          10 : }
    1615             : 
    1616         117 : Date DateFormatter::GetDate() const
    1617             : {
    1618         117 :     Date aDate( 0, 0, 0 );
    1619             : 
    1620         117 :     if ( GetField() )
    1621             :     {
    1622         117 :         if ( ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
    1623             :         {
    1624          71 :             if ( aDate > maMax )
    1625           2 :                 aDate = maMax;
    1626          69 :             else if ( aDate < maMin )
    1627           0 :                 aDate = maMin;
    1628             :         }
    1629             :         else
    1630             :         {
    1631             :             // !!! We should find out why dates are treated differently than other fields (see
    1632             :             // also bug: 52384)
    1633             : 
    1634          46 :             if ( !ImplAllowMalformedInput() )
    1635             :             {
    1636          41 :                 if ( maLastDate.GetDate() )
    1637          41 :                     aDate = maLastDate;
    1638           0 :                 else if ( !IsEmptyFieldValueEnabled() )
    1639           0 :                     aDate = Date( Date::SYSTEM );
    1640             :             }
    1641             :             else
    1642           5 :                 aDate = GetInvalidDate();
    1643             :         }
    1644             :     }
    1645             : 
    1646         117 :     return aDate;
    1647             : }
    1648             : 
    1649           2 : void DateFormatter::SetEmptyDate()
    1650             : {
    1651           2 :     FormatterBase::SetEmptyFieldValue();
    1652           2 : }
    1653             : 
    1654          28 : bool DateFormatter::IsEmptyDate() const
    1655             : {
    1656          28 :     bool bEmpty = FormatterBase::IsEmptyFieldValue();
    1657             : 
    1658          28 :     if ( GetField() && MustBeReformatted() && IsEmptyFieldValueEnabled() )
    1659             :     {
    1660          24 :         if ( GetField()->GetText().isEmpty() )
    1661             :         {
    1662           4 :             bEmpty = true;
    1663             :         }
    1664          20 :         else if ( !maLastDate.GetDate() )
    1665             :         {
    1666           0 :             Date aDate( Date::EMPTY );
    1667           0 :             bEmpty = !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
    1668             :         }
    1669             :     }
    1670          28 :     return bEmpty;
    1671             : }
    1672             : 
    1673         182 : void DateFormatter::Reformat()
    1674             : {
    1675         182 :     if ( !GetField() )
    1676           7 :         return;
    1677             : 
    1678         182 :     if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
    1679           7 :         return;
    1680             : 
    1681         175 :     OUString aStr;
    1682         175 :     bool bOK = ImplDateReformat( GetField()->GetText(), aStr, GetFieldSettings() );
    1683         175 :     if( !bOK )
    1684           0 :         return;
    1685             : 
    1686         175 :     if ( !aStr.isEmpty() )
    1687             :     {
    1688         100 :         ImplSetText( aStr );
    1689         100 :         ImplDateGetValue( aStr, maLastDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
    1690             :     }
    1691             :     else
    1692             :     {
    1693          75 :         if ( maLastDate.GetDate() )
    1694          35 :             SetDate( maLastDate );
    1695          40 :         else if ( !IsEmptyFieldValueEnabled() )
    1696          34 :             SetDate( Date( Date::SYSTEM ) );
    1697             :         else
    1698             :         {
    1699           6 :             ImplSetText( OUString() );
    1700           6 :             SetEmptyFieldValueData( true );
    1701             :         }
    1702         175 :     }
    1703             : }
    1704             : 
    1705           6 : void DateFormatter::ExpandCentury( Date& rDate )
    1706             : {
    1707           6 :     ExpandCentury( rDate, utl::MiscCfg().GetYear2000() );
    1708           6 : }
    1709             : 
    1710         265 : void DateFormatter::ExpandCentury( Date& rDate, sal_uInt16 nTwoDigitYearStart )
    1711             : {
    1712         265 :     sal_uInt16 nDateYear = rDate.GetYear();
    1713         265 :     if ( nDateYear < 100 )
    1714             :     {
    1715         152 :         sal_uInt16 nCentury = nTwoDigitYearStart / 100;
    1716         152 :         if ( nDateYear < (nTwoDigitYearStart % 100) )
    1717         144 :             nCentury++;
    1718         152 :         rDate.SetYear( nDateYear + (nCentury*100) );
    1719             :     }
    1720         265 : }
    1721             : 
    1722          34 : DateField::DateField( vcl::Window* pParent, WinBits nWinStyle ) :
    1723             :     SpinField( pParent, nWinStyle ),
    1724          34 :     maFirst( GetMin() ),
    1725          68 :     maLast( GetMax() )
    1726             : {
    1727          34 :     SetField( this );
    1728          34 :     SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
    1729          34 :     Reformat();
    1730          34 :     ResetLastDate();
    1731          34 : }
    1732             : 
    1733           0 : bool DateField::PreNotify( NotifyEvent& rNEvt )
    1734             : {
    1735           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && IsStrictFormat() &&
    1736           0 :          ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
    1737           0 :          !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    1738             :     {
    1739           0 :         if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( true ), ImplGetLocaleDataWrapper() ) )
    1740           0 :             return true;
    1741             :     }
    1742             : 
    1743           0 :     return SpinField::PreNotify( rNEvt );
    1744             : }
    1745             : 
    1746          60 : bool DateField::Notify( NotifyEvent& rNEvt )
    1747             : {
    1748          60 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
    1749           0 :         MarkToBeReformatted( false );
    1750          60 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
    1751             :     {
    1752           0 :         if ( MustBeReformatted() )
    1753             :         {
    1754             :             // !!! We should find out why dates are treated differently than other fields (see
    1755             :             // also bug: 52384)
    1756             : 
    1757           0 :             bool bTextLen = !GetText().isEmpty();
    1758           0 :             if ( bTextLen || !IsEmptyFieldValueEnabled() )
    1759             :             {
    1760           0 :                 if ( !ImplAllowMalformedInput() )
    1761           0 :                     Reformat();
    1762             :                 else
    1763             :                 {
    1764           0 :                     Date aDate( 0, 0, 0 );
    1765           0 :                     if ( ImplDateGetValue( GetText(), aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
    1766             :                         // even with strict text analysis, our text is a valid date -> do a complete
    1767             :                         // reformat
    1768           0 :                         Reformat();
    1769             :                 }
    1770             :             }
    1771           0 :             else if ( !bTextLen && IsEmptyFieldValueEnabled() )
    1772             :             {
    1773           0 :                 ResetLastDate();
    1774           0 :                 SetEmptyFieldValueData( true );
    1775             :             }
    1776             :         }
    1777             :     }
    1778             : 
    1779          60 :     return SpinField::Notify( rNEvt );
    1780             : }
    1781             : 
    1782         314 : void DateField::DataChanged( const DataChangedEvent& rDCEvt )
    1783             : {
    1784         314 :     SpinField::DataChanged( rDCEvt );
    1785             : 
    1786         314 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & (AllSettingsFlags::LOCALE|AllSettingsFlags::MISC)) )
    1787             :     {
    1788           0 :         if ( IsDefaultLocale() && ( rDCEvt.GetFlags() & AllSettingsFlags::LOCALE ) )
    1789           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    1790           0 :         ReformatAll();
    1791             :     }
    1792         314 : }
    1793             : 
    1794          92 : void DateField::Modify()
    1795             : {
    1796          92 :     MarkToBeReformatted( true );
    1797          92 :     SpinField::Modify();
    1798          92 : }
    1799             : 
    1800           4 : void DateField::Up()
    1801             : {
    1802           4 :     ImplDateSpinArea( true );
    1803           4 :     SpinField::Up();
    1804           4 : }
    1805             : 
    1806           2 : void DateField::Down()
    1807             : {
    1808           2 :     ImplDateSpinArea( false );
    1809           2 :     SpinField::Down();
    1810           2 : }
    1811             : 
    1812           2 : void DateField::First()
    1813             : {
    1814           2 :     ImplNewFieldValue( maFirst );
    1815           2 :     SpinField::First();
    1816           2 : }
    1817             : 
    1818           2 : void DateField::Last()
    1819             : {
    1820           2 :     ImplNewFieldValue( maLast );
    1821           2 :     SpinField::Last();
    1822           2 : }
    1823             : 
    1824           0 : DateBox::DateBox( vcl::Window* pParent, WinBits nWinStyle ) :
    1825           0 :     ComboBox( pParent, nWinStyle )
    1826             : {
    1827           0 :     SetField( this );
    1828           0 :     SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
    1829           0 :     Reformat();
    1830           0 : }
    1831             : 
    1832           0 : bool DateBox::PreNotify( NotifyEvent& rNEvt )
    1833             : {
    1834           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && IsStrictFormat() &&
    1835           0 :          ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
    1836           0 :          !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    1837             :     {
    1838           0 :         if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( true ), ImplGetLocaleDataWrapper() ) )
    1839           0 :             return true;
    1840             :     }
    1841             : 
    1842           0 :     return ComboBox::PreNotify( rNEvt );
    1843             : }
    1844             : 
    1845           0 : void DateBox::DataChanged( const DataChangedEvent& rDCEvt )
    1846             : {
    1847           0 :     ComboBox::DataChanged( rDCEvt );
    1848             : 
    1849           0 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
    1850             :     {
    1851           0 :         if ( IsDefaultLocale() )
    1852           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    1853           0 :         ReformatAll();
    1854             :     }
    1855           0 : }
    1856             : 
    1857           0 : bool DateBox::Notify( NotifyEvent& rNEvt )
    1858             : {
    1859           0 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
    1860           0 :         MarkToBeReformatted( false );
    1861           0 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
    1862             :     {
    1863           0 :         if ( MustBeReformatted() )
    1864             :         {
    1865           0 :             bool bTextLen = !GetText().isEmpty();
    1866           0 :             if ( bTextLen || !IsEmptyFieldValueEnabled() )
    1867           0 :                 Reformat();
    1868           0 :             else if ( !bTextLen && IsEmptyFieldValueEnabled() )
    1869             :             {
    1870           0 :                 ResetLastDate();
    1871           0 :                 SetEmptyFieldValueData( true );
    1872             :             }
    1873             :         }
    1874             :     }
    1875             : 
    1876           0 :     return ComboBox::Notify( rNEvt );
    1877             : }
    1878             : 
    1879           0 : void DateBox::Modify()
    1880             : {
    1881           0 :     MarkToBeReformatted( true );
    1882           0 :     ComboBox::Modify();
    1883           0 : }
    1884             : 
    1885           0 : void DateBox::ReformatAll()
    1886             : {
    1887           0 :     OUString aStr;
    1888           0 :     SetUpdateMode( false );
    1889           0 :     sal_uInt16 nEntryCount = GetEntryCount();
    1890           0 :     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
    1891             :     {
    1892           0 :         ImplDateReformat( GetEntry( i ), aStr, GetFieldSettings() );
    1893           0 :         RemoveEntryAt(i);
    1894           0 :         InsertEntry( aStr, i );
    1895             :     }
    1896           0 :     DateFormatter::Reformat();
    1897           0 :     SetUpdateMode( true );
    1898           0 : }
    1899             : 
    1900           0 : static bool ImplTimeProcessKeyInput( Edit*, const KeyEvent& rKEvt,
    1901             :                                      bool bStrictFormat, bool bDuration,
    1902             :                                      TimeFieldFormat eFormat,
    1903             :                                      const LocaleDataWrapper& rLocaleDataWrapper  )
    1904             : {
    1905           0 :     sal_Unicode cChar = rKEvt.GetCharCode();
    1906             : 
    1907           0 :     if ( !bStrictFormat )
    1908           0 :         return false;
    1909             :     else
    1910             :     {
    1911           0 :         sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
    1912           0 :         if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
    1913           0 :              (nGroup == KEYGROUP_MISC)   ||
    1914           0 :              ((cChar >= '0') && (cChar <= '9')) ||
    1915           0 :              string::equals(rLocaleDataWrapper.getTimeSep(), cChar) ||
    1916           0 :              (rLocaleDataWrapper.getTimeAM().indexOf(cChar) != -1) ||
    1917           0 :              (rLocaleDataWrapper.getTimePM().indexOf(cChar) != -1) ||
    1918             :              // Accept AM/PM:
    1919           0 :              (cChar == 'a') || (cChar == 'A') || (cChar == 'm') || (cChar == 'M') || (cChar == 'p') || (cChar == 'P') ||
    1920           0 :              ((eFormat == TimeFieldFormat::F_100TH_SEC) && string::equals(rLocaleDataWrapper.getTime100SecSep(), cChar)) ||
    1921           0 :              ((eFormat == TimeFieldFormat::F_SEC_CS) && string::equals(rLocaleDataWrapper.getTime100SecSep(), cChar)) ||
    1922           0 :              (bDuration && (cChar == '-')) )
    1923           0 :             return false;
    1924             :         else
    1925           0 :             return true;
    1926             :     }
    1927             : }
    1928             : 
    1929          12 : static bool ImplIsOnlyDigits( const OUStringBuffer& _rStr )
    1930             : {
    1931          12 :     const sal_Unicode* _pChr = _rStr.getStr();
    1932          36 :     for ( sal_Int32 i = 0; i < _rStr.getLength(); ++i, ++_pChr )
    1933             :     {
    1934          24 :         if ( *_pChr < '0' || *_pChr > '9' )
    1935           0 :             return false;
    1936             :     }
    1937          12 :     return true;
    1938             : }
    1939             : 
    1940         440 : static bool ImplIsValidTimePortion( bool _bSkipInvalidCharacters, const OUStringBuffer& _rStr )
    1941             : {
    1942         440 :     if ( !_bSkipInvalidCharacters )
    1943             :     {
    1944          12 :         if ( ( _rStr.getLength() > 2 ) || _rStr.isEmpty() || !ImplIsOnlyDigits( _rStr ) )
    1945           0 :             return false;
    1946             :     }
    1947         440 :     return true;
    1948             : }
    1949             : 
    1950         440 : static bool ImplCutTimePortion( OUStringBuffer& _rStr, sal_Int32 _nSepPos, bool _bSkipInvalidCharacters, short* _pPortion )
    1951             : {
    1952         440 :     OUString sPortion(_rStr.getStr(), _nSepPos );
    1953         880 :     _rStr = _nSepPos < _rStr.getLength()
    1954         440 :         ? _rStr.copy( _nSepPos + 1 ) : OUStringBuffer();
    1955             : 
    1956         440 :     if ( !ImplIsValidTimePortion( _bSkipInvalidCharacters, sPortion ) )
    1957           0 :         return false;
    1958         440 :     *_pPortion = (short)sPortion.toInt32();
    1959         440 :     return true;
    1960             : }
    1961             : 
    1962         364 : static bool ImplTimeGetValue( const OUString& rStr, tools::Time& rTime,
    1963             :                               TimeFieldFormat eFormat, bool bDuration,
    1964             :                               const LocaleDataWrapper& rLocaleDataWrapper, bool _bSkipInvalidCharacters = true )
    1965             : {
    1966         364 :     OUStringBuffer    aStr    = rStr;
    1967         364 :     short       nHour   = 0;
    1968         364 :     short       nMinute = 0;
    1969         364 :     short       nSecond = 0;
    1970         364 :     sal_Int64   nNanoSec = 0;
    1971         364 :     tools::Time        aTime( 0, 0, 0 );
    1972             : 
    1973         364 :     if ( rStr.isEmpty() )
    1974          12 :         return false;
    1975             : 
    1976             :     // Search for separators
    1977         352 :     if (!rLocaleDataWrapper.getTimeSep().isEmpty())
    1978             :     {
    1979         352 :         OUStringBuffer aSepStr(",.;:/");
    1980         352 :         if ( !bDuration )
    1981         341 :             aSepStr.append('-');
    1982             : 
    1983             :         // Replace characters above by the separator character
    1984        2453 :         for (sal_Int32 i = 0; i < aSepStr.getLength(); ++i)
    1985             :         {
    1986        2101 :             if (string::equals(rLocaleDataWrapper.getTimeSep(), aSepStr[i]))
    1987         352 :                 continue;
    1988       12786 :             for ( sal_Int32 j = 0; j < aStr.getLength(); j++ )
    1989             :             {
    1990       11037 :                 if (aStr[j] == aSepStr[i])
    1991           0 :                     aStr[j] = rLocaleDataWrapper.getTimeSep()[0];
    1992             :             }
    1993         352 :         }
    1994             :     }
    1995             : 
    1996         352 :     bool bNegative = false;
    1997         352 :     sal_Int32 nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    1998         352 :     if ( aStr[0] == '-' )
    1999           0 :         bNegative = true;
    2000         352 :     if ( eFormat != TimeFieldFormat::F_SEC_CS )
    2001             :     {
    2002         352 :         if ( nSepPos < 0 )
    2003          16 :             nSepPos = aStr.getLength();
    2004         352 :         if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nHour ) )
    2005           0 :             return false;
    2006             : 
    2007         352 :         nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    2008         352 :         if ( !aStr.isEmpty() && aStr[0] == '-' )
    2009           0 :             bNegative = true;
    2010         352 :         if ( nSepPos >= 0 )
    2011             :         {
    2012          88 :             if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nMinute ) )
    2013           0 :                 return false;
    2014             : 
    2015          88 :             nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    2016          88 :             if ( !aStr.isEmpty() && aStr[0] == '-' )
    2017           0 :                 bNegative = true;
    2018          88 :             if ( nSepPos >= 0 )
    2019             :             {
    2020           0 :                 if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nSecond ) )
    2021           0 :                     return false;
    2022           0 :                 if ( !aStr.isEmpty() && aStr[0] == '-' )
    2023           0 :                     bNegative = true;
    2024           0 :                 nNanoSec = aStr.toString().toInt64();
    2025             :             }
    2026             :             else
    2027          88 :                 nSecond = (short)aStr.toString().toInt32();
    2028             :         }
    2029             :         else
    2030         264 :             nMinute = (short)aStr.toString().toInt32();
    2031             :     }
    2032           0 :     else if ( nSepPos < 0 )
    2033             :     {
    2034           0 :         nSecond = (short)aStr.toString().toInt32();
    2035           0 :         nMinute += nSecond / 60;
    2036           0 :         nSecond %= 60;
    2037           0 :         nHour += nMinute / 60;
    2038           0 :         nMinute %= 60;
    2039             :     }
    2040             :     else
    2041             :     {
    2042           0 :         nSecond = (short)aStr.copy( 0, nSepPos ).toString().toInt32();
    2043           0 :         aStr.remove( 0, nSepPos+1 );
    2044             : 
    2045           0 :         nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    2046           0 :         if ( !aStr.isEmpty() && aStr[0] == '-' )
    2047           0 :             bNegative = true;
    2048           0 :         if ( nSepPos >= 0 )
    2049             :         {
    2050           0 :             nMinute = nSecond;
    2051           0 :             nSecond = (short)aStr.copy( 0, nSepPos ).toString().toInt32();
    2052           0 :             aStr.remove( 0, nSepPos+1 );
    2053             : 
    2054           0 :             nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
    2055           0 :             if ( !aStr.isEmpty() && aStr[0] == '-' )
    2056           0 :                 bNegative = true;
    2057           0 :             if ( nSepPos >= 0 )
    2058             :             {
    2059           0 :                 nHour   = nMinute;
    2060           0 :                 nMinute = nSecond;
    2061           0 :                 nSecond = (short)aStr.copy( 0, nSepPos ).toString().toInt32();
    2062           0 :                 aStr.remove( 0, nSepPos+1 );
    2063             :             }
    2064             :             else
    2065             :             {
    2066           0 :                 nHour += nMinute / 60;
    2067           0 :                 nMinute %= 60;
    2068             :             }
    2069             :         }
    2070             :         else
    2071             :         {
    2072           0 :             nMinute += nSecond / 60;
    2073           0 :             nSecond %= 60;
    2074           0 :             nHour += nMinute / 60;
    2075           0 :             nMinute %= 60;
    2076             :         }
    2077           0 :         nNanoSec = aStr.toString().toInt64();
    2078             :     }
    2079             : 
    2080         352 :     if ( nNanoSec )
    2081             :     {
    2082             :         assert(aStr.getLength() >= 1);
    2083             : 
    2084           0 :         sal_Int32 nLen = 1; // at least one digit, otherwise nNanoSec==0
    2085             : 
    2086           0 :         while ( aStr.getLength() > nLen && aStr[nLen] >= '0' && aStr[nLen] <= '9' )
    2087           0 :             nLen++;
    2088             : 
    2089           0 :         while ( nLen < 9)
    2090             :         {
    2091           0 :             nNanoSec *= 10;
    2092           0 :             ++nLen;
    2093             :         }
    2094           0 :         while ( nLen > 9 )
    2095             :         {
    2096             :             // round if negative?
    2097           0 :             nNanoSec = (nNanoSec + 5) / 10;
    2098           0 :             --nLen;
    2099             :         }
    2100             :     }
    2101             : 
    2102             :     assert(nNanoSec > -1000000000 && nNanoSec < 1000000000);
    2103         352 :     if ( (nMinute > 59) || (nSecond > 59) || (nNanoSec > 1000000000) )
    2104           0 :         return false;
    2105             : 
    2106         352 :     if ( eFormat == TimeFieldFormat::F_NONE )
    2107         255 :         nSecond = nNanoSec = 0;
    2108          97 :     else if ( eFormat == TimeFieldFormat::F_SEC )
    2109          97 :         nNanoSec = 0;
    2110             : 
    2111         352 :     if ( !bDuration )
    2112             :     {
    2113         682 :         if ( bNegative || (nHour < 0) || (nMinute < 0) ||
    2114         682 :              (nSecond < 0) || (nNanoSec < 0) )
    2115           0 :             return false;
    2116             : 
    2117         341 :         OUString aUpperCaseStr = aStr.toString().toAsciiUpperCase();
    2118         682 :         OUString aAM(rLocaleDataWrapper.getTimeAM().toAsciiUpperCase());
    2119         682 :         OUString aPM(rLocaleDataWrapper.getTimePM().toAsciiUpperCase());
    2120         682 :         OUString aAM2("AM");  // aAM is localized
    2121         682 :         OUString aPM2("PM");  // aPM is localized
    2122             : 
    2123         341 :         if ( (nHour < 12) && ( ( aUpperCaseStr.indexOf( aPM ) >= 0 ) || ( aUpperCaseStr.indexOf( aPM2 ) >= 0 ) ) )
    2124           0 :             nHour += 12;
    2125             : 
    2126         341 :         if ( (nHour == 12) && ( ( aUpperCaseStr.indexOf( aAM ) >= 0 ) || ( aUpperCaseStr.indexOf( aAM2 ) >= 0 ) ) )
    2127           0 :             nHour = 0;
    2128             : 
    2129         682 :         aTime = tools::Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
    2130         682 :                       (sal_uInt32)nNanoSec );
    2131             :     }
    2132             :     else
    2133             :     {
    2134             :         assert( !bNegative || (nHour < 0) || (nMinute < 0) ||
    2135             :              (nSecond < 0) || (nNanoSec < 0) );
    2136          22 :         if ( bNegative || (nHour < 0) || (nMinute < 0) ||
    2137          22 :              (nSecond < 0) || (nNanoSec < 0) )
    2138             :         {
    2139             :             // LEM TODO: this looks weird... I think buggy when parsing "05:-02:18"
    2140           0 :             bNegative   = true;
    2141           0 :             nHour       = nHour < 0 ? -nHour : nHour;
    2142           0 :             nMinute     = nMinute < 0 ? -nMinute : nMinute;
    2143           0 :             nSecond     = nSecond < 0 ? -nSecond : nSecond;
    2144           0 :             nNanoSec    = nNanoSec < 0 ? -nNanoSec : nNanoSec;
    2145             :         }
    2146             : 
    2147          22 :         aTime = tools::Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
    2148          11 :                       (sal_uInt32)nNanoSec );
    2149          11 :         if ( bNegative )
    2150           0 :             aTime = -aTime;
    2151             :     }
    2152             : 
    2153         352 :     rTime = aTime;
    2154             : 
    2155         352 :     return true;
    2156             : }
    2157             : 
    2158         162 : bool TimeFormatter::ImplTimeReformat( const OUString& rStr, OUString& rOutStr )
    2159             : {
    2160         162 :     tools::Time aTime( 0, 0, 0 );
    2161         162 :     if ( !ImplTimeGetValue( rStr, aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ) )
    2162          10 :         return true;
    2163             : 
    2164         152 :     tools::Time aTempTime = aTime;
    2165         152 :     if ( aTempTime > GetMax() )
    2166           0 :         aTempTime = GetMax() ;
    2167         152 :     else if ( aTempTime < GetMin() )
    2168          23 :         aTempTime = GetMin();
    2169             : 
    2170         152 :     if ( GetErrorHdl().IsSet() && (aTime != aTempTime) )
    2171             :     {
    2172           0 :         maCorrectedTime = aTempTime;
    2173           0 :         if ( !GetErrorHdl().Call( this ) )
    2174             :         {
    2175           0 :             maCorrectedTime = tools::Time( tools::Time::SYSTEM );
    2176           0 :             return false;
    2177             :         }
    2178             :         else
    2179           0 :             maCorrectedTime = tools::Time( tools::Time::SYSTEM );
    2180             :     }
    2181             : 
    2182         152 :     bool bSecond = false;
    2183         152 :     bool b100Sec = false;
    2184         152 :     if ( meFormat != TimeFieldFormat::F_NONE )
    2185          44 :         bSecond = true;
    2186         152 :     if ( meFormat == TimeFieldFormat::F_100TH_SEC )
    2187           0 :         b100Sec = true;
    2188             : 
    2189         152 :     if ( meFormat == TimeFieldFormat::F_SEC_CS )
    2190             :     {
    2191           0 :         sal_uLong n  = aTempTime.GetHour() * 3600L;
    2192           0 :         n       += aTempTime.GetMin()  * 60L;
    2193           0 :         n       += aTempTime.GetSec();
    2194           0 :         rOutStr  = OUString::number( n );
    2195           0 :         rOutStr += ImplGetLocaleDataWrapper().getTime100SecSep();
    2196           0 :         std::ostringstream ostr;
    2197           0 :         ostr.fill('0');
    2198           0 :         ostr.width(9);
    2199           0 :         ostr << aTempTime.GetNanoSec();
    2200           0 :         rOutStr += OUString::createFromAscii(ostr.str().c_str());
    2201             :     }
    2202         152 :     else if ( mbDuration )
    2203           5 :         rOutStr = ImplGetLocaleDataWrapper().getDuration( aTempTime, bSecond, b100Sec );
    2204             :     else
    2205             :     {
    2206         147 :         rOutStr = ImplGetLocaleDataWrapper().getTime( aTempTime, bSecond, b100Sec );
    2207         147 :         if ( GetTimeFormat() == HOUR_12 )
    2208             :         {
    2209          46 :             if ( aTempTime.GetHour() > 12 )
    2210             :             {
    2211           0 :                 tools::Time aT( aTempTime );
    2212           0 :                 aT.SetHour( aT.GetHour() % 12 );
    2213           0 :                 rOutStr = ImplGetLocaleDataWrapper().getTime( aT, bSecond, b100Sec );
    2214             :             }
    2215             :             // Don't use LocaleDataWrapper, we want AM/PM
    2216          46 :             if ( aTempTime.GetHour() < 12 )
    2217          46 :                 rOutStr += "AM"; // ImplGetLocaleDataWrapper().getTimeAM();
    2218             :             else
    2219           0 :                 rOutStr += "PM"; // ImplGetLocaleDataWrapper().getTimePM();
    2220             :         }
    2221             :     }
    2222             : 
    2223         152 :     return true;
    2224             : }
    2225          50 : bool TimeFormatter::ImplAllowMalformedInput() const
    2226             : {
    2227          50 :     return !IsEnforceValidValue();
    2228             : }
    2229             : 
    2230           6 : void TimeField::ImplTimeSpinArea( bool bUp )
    2231             : {
    2232           6 :     if ( GetField() )
    2233             :     {
    2234           6 :         sal_Int32 nTimeArea = 0;
    2235           6 :         tools::Time aTime( GetTime() );
    2236           6 :         OUString aText( GetText() );
    2237           6 :         Selection aSelection( GetField()->GetSelection() );
    2238             : 
    2239             :         // Area search
    2240           6 :         if ( GetFormat() != TimeFieldFormat::F_SEC_CS )
    2241             :         {
    2242             :             //Which area is the cursor in of HH:MM:SS.TT
    2243          10 :             for ( sal_Int32 i = 1, nPos = 0; i <= 4; i++ )
    2244             :             {
    2245          10 :                 sal_Int32 nPos1 = aText.indexOf( ImplGetLocaleDataWrapper().getTimeSep(), nPos );
    2246          10 :                 sal_Int32 nPos2 = aText.indexOf( ImplGetLocaleDataWrapper().getTime100SecSep(), nPos );
    2247             :                 //which ever comes first, bearing in mind that one might not be there
    2248          10 :                 if (nPos1 >= 0 && nPos2 >= 0)
    2249           0 :                     nPos = nPos1 < nPos2 ? nPos1 : nPos2;
    2250          10 :                 else if (nPos1 >= 0)
    2251           4 :                     nPos = nPos1;
    2252             :                 else
    2253           6 :                     nPos = nPos2;
    2254          10 :                 if ( nPos < 0 || nPos >= aSelection.Max() )
    2255             :                 {
    2256           6 :                     nTimeArea = i;
    2257           6 :                     break;
    2258             :                 }
    2259             :                 else
    2260           4 :                     nPos++;
    2261             :             }
    2262             :         }
    2263             :         else
    2264             :         {
    2265           0 :             sal_Int32 nPos = aText.indexOf( ImplGetLocaleDataWrapper().getTime100SecSep() );
    2266           0 :             if ( nPos < 0 || nPos >= aSelection.Max() )
    2267           0 :                 nTimeArea = 3;
    2268             :             else
    2269           0 :                 nTimeArea = 4;
    2270             :         }
    2271             : 
    2272           6 :         if ( nTimeArea )
    2273             :         {
    2274           6 :             tools::Time aAddTime( 0, 0, 0 );
    2275           6 :             if ( nTimeArea == 1 )
    2276           2 :                 aAddTime = tools::Time( 1, 0 );
    2277           4 :             else if ( nTimeArea == 2 )
    2278           4 :                 aAddTime = tools::Time( 0, 1 );
    2279           0 :             else if ( nTimeArea == 3 )
    2280           0 :                 aAddTime = tools::Time( 0, 0, 1 );
    2281           0 :             else if ( nTimeArea == 4 )
    2282           0 :                 aAddTime = tools::Time( 0, 0, 0, 1 );
    2283             : 
    2284           6 :             if ( !bUp )
    2285           2 :                 aAddTime = -aAddTime;
    2286             : 
    2287           6 :             aTime += aAddTime;
    2288           6 :             if ( !IsDuration() )
    2289             :             {
    2290           6 :                 tools::Time aAbsMaxTime( 23, 59, 59, 999999999 );
    2291           6 :                 if ( aTime > aAbsMaxTime )
    2292           0 :                     aTime = aAbsMaxTime;
    2293           6 :                 tools::Time aAbsMinTime( 0, 0 );
    2294           6 :                 if ( aTime < aAbsMinTime )
    2295           0 :                     aTime = aAbsMinTime;
    2296             :             }
    2297           6 :             ImplNewFieldValue( aTime );
    2298           6 :         }
    2299             : 
    2300             :     }
    2301           6 : }
    2302             : 
    2303          18 : void TimeFormatter::ImplInit()
    2304             : {
    2305          18 :     meFormat        = TimeFieldFormat::F_NONE;
    2306          18 :     mbDuration      = false;
    2307          18 :     mnTimeFormat    = HOUR_24;  // Should become a ExtTimeFieldFormat in next implementation, merge with mbDuration and meFormat
    2308          18 : }
    2309             : 
    2310          18 : TimeFormatter::TimeFormatter() :
    2311             :     maLastTime( 0, 0 ),
    2312             :     maMin( 0, 0 ),
    2313             :     maMax( 23, 59, 59, 999999999 ),
    2314             :     maCorrectedTime( tools::Time::SYSTEM ),
    2315             :     mbEnforceValidValue( true ),
    2316          18 :     maFieldTime( 0, 0 )
    2317             : {
    2318          18 :     ImplInit();
    2319          18 : }
    2320             : 
    2321           0 : TimeFormatter::~TimeFormatter()
    2322             : {
    2323           0 : }
    2324             : 
    2325         149 : void TimeFormatter::ReformatAll()
    2326             : {
    2327         149 :     Reformat();
    2328         149 : }
    2329             : 
    2330          30 : void TimeFormatter::SetMin( const tools::Time& rNewMin )
    2331             : {
    2332          30 :     maMin = rNewMin;
    2333          30 :     if ( !IsEmptyFieldValue() )
    2334          30 :         ReformatAll();
    2335          30 : }
    2336             : 
    2337          30 : void TimeFormatter::SetMax( const tools::Time& rNewMax )
    2338             : {
    2339          30 :     maMax = rNewMax;
    2340          30 :     if ( !IsEmptyFieldValue() )
    2341          30 :         ReformatAll();
    2342          30 : }
    2343             : 
    2344          25 : void TimeFormatter::SetTimeFormat( TimeFormatter::TimeFormat eNewFormat )
    2345             : {
    2346          25 :     mnTimeFormat = sal::static_int_cast<sal_uInt16>(eNewFormat);
    2347          25 : }
    2348             : 
    2349             : 
    2350          26 : void TimeFormatter::SetFormat( TimeFieldFormat eNewFormat )
    2351             : {
    2352          26 :     meFormat = eNewFormat;
    2353          26 :     ReformatAll();
    2354          26 : }
    2355             : 
    2356          26 : void TimeFormatter::SetDuration( bool bNewDuration )
    2357             : {
    2358          26 :     mbDuration = bNewDuration;
    2359          26 :     ReformatAll();
    2360          26 : }
    2361             : 
    2362          16 : void TimeFormatter::SetTime( const tools::Time& rNewTime )
    2363             : {
    2364          16 :     SetUserTime( rNewTime );
    2365          16 :     maFieldTime = maLastTime;
    2366          16 :     SetEmptyFieldValueData( false );
    2367          16 : }
    2368             : 
    2369          10 : void TimeFormatter::ImplNewFieldValue( const tools::Time& rTime )
    2370             : {
    2371          10 :     if ( GetField() )
    2372             :     {
    2373          10 :         Selection aSelection = GetField()->GetSelection();
    2374          10 :         aSelection.Justify();
    2375          10 :         OUString aText = GetField()->GetText();
    2376             : 
    2377             :         // If selected until the end then keep it that way
    2378          10 :         if ( (sal_Int32)aSelection.Max() == aText.getLength() )
    2379             :         {
    2380          10 :             if ( !aSelection.Len() )
    2381          10 :                 aSelection.Min() = SELECTION_MAX;
    2382          10 :             aSelection.Max() = SELECTION_MAX;
    2383             :         }
    2384             : 
    2385          10 :         tools::Time aOldLastTime = maLastTime;
    2386          10 :         ImplSetUserTime( rTime, &aSelection );
    2387          10 :         maLastTime = aOldLastTime;
    2388             : 
    2389             :         // Modify at Edit is only set at KeyInput
    2390          10 :         if ( GetField()->GetText() != aText )
    2391             :         {
    2392           8 :             GetField()->SetModifyFlag();
    2393           8 :             GetField()->Modify();
    2394          10 :         }
    2395             :     }
    2396          10 : }
    2397             : 
    2398          52 : void TimeFormatter::ImplSetUserTime( const tools::Time& rNewTime, Selection* pNewSelection )
    2399             : {
    2400          52 :     tools::Time aNewTime = rNewTime;
    2401          52 :     if ( aNewTime > GetMax() )
    2402           4 :         aNewTime = GetMax();
    2403          48 :     else if ( aNewTime < GetMin() )
    2404           0 :         aNewTime = GetMin();
    2405          52 :     maLastTime = aNewTime;
    2406             : 
    2407          52 :     if ( GetField() )
    2408             :     {
    2409          52 :         OUString aStr;
    2410          52 :         bool bSec    = false;
    2411          52 :         bool b100Sec = false;
    2412          52 :         if ( meFormat != TimeFieldFormat::F_NONE )
    2413          11 :             bSec = true;
    2414          52 :         if ( meFormat == TimeFieldFormat::F_100TH_SEC || meFormat == TimeFieldFormat::F_SEC_CS )
    2415           0 :             b100Sec = true;
    2416          52 :         if ( meFormat == TimeFieldFormat::F_SEC_CS )
    2417             :         {
    2418           0 :             sal_uLong n  = aNewTime.GetHour() * 3600L;
    2419           0 :             n       += aNewTime.GetMin()  * 60L;
    2420           0 :             n       += aNewTime.GetSec();
    2421           0 :             aStr     = OUString::number( n );
    2422           0 :             aStr    += ImplGetLocaleDataWrapper().getTime100SecSep();
    2423           0 :             std::ostringstream ostr;
    2424           0 :             ostr.fill('0');
    2425           0 :             ostr.width(9);
    2426           0 :             ostr << aNewTime.GetNanoSec();
    2427           0 :             aStr += OUString::createFromAscii(ostr.str().c_str());
    2428             :         }
    2429          52 :         else if ( mbDuration )
    2430             :         {
    2431           1 :             aStr = ImplGetLocaleDataWrapper().getDuration( aNewTime, bSec, b100Sec );
    2432             :         }
    2433             :         else
    2434             :         {
    2435          51 :             aStr = ImplGetLocaleDataWrapper().getTime( aNewTime, bSec, b100Sec );
    2436          51 :             if ( GetTimeFormat() == HOUR_12 )
    2437             :             {
    2438          11 :                 if ( aNewTime.GetHour() > 12 )
    2439             :                 {
    2440           0 :                     tools::Time aT( aNewTime );
    2441           0 :                     aT.SetHour( aT.GetHour() % 12 );
    2442           0 :                     aStr = ImplGetLocaleDataWrapper().getTime( aT, bSec, b100Sec );
    2443             :                 }
    2444             :                 // Don't use LocaleDataWrapper, we want AM/PM
    2445          11 :                 if ( aNewTime.GetHour() < 12 )
    2446          11 :                     aStr += "AM"; // ImplGetLocaleDataWrapper().getTimeAM();
    2447             :                 else
    2448           0 :                     aStr += "PM"; // ImplGetLocaleDataWrapper().getTimePM();
    2449             :             }
    2450             :         }
    2451             : 
    2452          52 :         ImplSetText( aStr, pNewSelection );
    2453             :     }
    2454          52 : }
    2455             : 
    2456          42 : void TimeFormatter::SetUserTime( const tools::Time& rNewTime )
    2457             : {
    2458          42 :     ImplSetUserTime( rNewTime );
    2459          42 : }
    2460             : 
    2461          50 : tools::Time TimeFormatter::GetTime() const
    2462             : {
    2463          50 :     tools::Time aTime( 0, 0, 0 );
    2464             : 
    2465          50 :     if ( GetField() )
    2466             :     {
    2467          50 :         bool bAllowMailformed = ImplAllowMalformedInput();
    2468          50 :         if ( ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
    2469             :         {
    2470          48 :             if ( aTime > GetMax() )
    2471           0 :                 aTime = GetMax();
    2472          48 :             else if ( aTime < GetMin() )
    2473           0 :                 aTime = GetMin();
    2474             :         }
    2475             :         else
    2476             :         {
    2477           2 :             if ( bAllowMailformed )
    2478           0 :                 aTime = GetInvalidTime();
    2479             :             else
    2480           2 :                 aTime = maLastTime;
    2481             :         }
    2482             :     }
    2483             : 
    2484          50 :     return aTime;
    2485             : }
    2486             : 
    2487         167 : void TimeFormatter::Reformat()
    2488             : {
    2489         167 :     if ( !GetField() )
    2490           5 :         return;
    2491             : 
    2492         167 :     if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
    2493           5 :         return;
    2494             : 
    2495         162 :     OUString aStr;
    2496         162 :     bool bOK = ImplTimeReformat( GetField()->GetText(), aStr );
    2497         162 :     if ( !bOK )
    2498           0 :         return;
    2499             : 
    2500         162 :     if ( !aStr.isEmpty() )
    2501             :     {
    2502         152 :         ImplSetText( aStr );
    2503         152 :         ImplTimeGetValue( aStr, maLastTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
    2504             :     }
    2505             :     else
    2506          10 :         SetTime( maLastTime );
    2507             : }
    2508             : 
    2509          18 : TimeField::TimeField( vcl::Window* pParent, WinBits nWinStyle ) :
    2510             :     SpinField( pParent, nWinStyle ),
    2511          18 :     maFirst( GetMin() ),
    2512          36 :     maLast( GetMax() )
    2513             : {
    2514          18 :     SetField( this );
    2515          18 :     SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, false, false ) );
    2516          18 :     Reformat();
    2517          18 : }
    2518             : 
    2519           0 : bool TimeField::PreNotify( NotifyEvent& rNEvt )
    2520             : {
    2521           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    2522             :     {
    2523           0 :         if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
    2524           0 :             return true;
    2525             :     }
    2526             : 
    2527           0 :     return SpinField::PreNotify( rNEvt );
    2528             : }
    2529             : 
    2530          19 : bool TimeField::Notify( NotifyEvent& rNEvt )
    2531             : {
    2532          19 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
    2533           0 :         MarkToBeReformatted( false );
    2534          19 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
    2535             :     {
    2536           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
    2537             :         {
    2538           0 :             if ( !ImplAllowMalformedInput() )
    2539           0 :                 Reformat();
    2540             :             else
    2541             :             {
    2542           0 :                 tools::Time aTime( 0, 0, 0 );
    2543           0 :                 if ( ImplTimeGetValue( GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), false ) )
    2544             :                     // even with strict text analysis, our text is a valid time -> do a complete
    2545             :                     // reformat
    2546           0 :                     Reformat();
    2547             :             }
    2548             :         }
    2549             :     }
    2550             : 
    2551          19 :     return SpinField::Notify( rNEvt );
    2552             : }
    2553             : 
    2554         292 : void TimeField::DataChanged( const DataChangedEvent& rDCEvt )
    2555             : {
    2556         292 :     SpinField::DataChanged( rDCEvt );
    2557             : 
    2558         292 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
    2559             :     {
    2560           0 :         if ( IsDefaultLocale() )
    2561           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    2562           0 :         ReformatAll();
    2563             :     }
    2564         292 : }
    2565             : 
    2566          58 : void TimeField::Modify()
    2567             : {
    2568          58 :     MarkToBeReformatted( true );
    2569          58 :     SpinField::Modify();
    2570          58 : }
    2571             : 
    2572           4 : void TimeField::Up()
    2573             : {
    2574           4 :     ImplTimeSpinArea( true );
    2575           4 :     SpinField::Up();
    2576           4 : }
    2577             : 
    2578           2 : void TimeField::Down()
    2579             : {
    2580           2 :     ImplTimeSpinArea( false );
    2581           2 :     SpinField::Down();
    2582           2 : }
    2583             : 
    2584           2 : void TimeField::First()
    2585             : {
    2586           2 :     ImplNewFieldValue( maFirst );
    2587           2 :     SpinField::First();
    2588           2 : }
    2589             : 
    2590           2 : void TimeField::Last()
    2591             : {
    2592           2 :     ImplNewFieldValue( maLast );
    2593           2 :     SpinField::Last();
    2594           2 : }
    2595             : 
    2596          26 : void TimeField::SetExtFormat( ExtTimeFieldFormat eFormat )
    2597             : {
    2598          26 :     switch ( eFormat )
    2599             :     {
    2600             :         case EXTTIMEF_24H_SHORT:
    2601             :         {
    2602          10 :             SetTimeFormat( HOUR_24 );
    2603          10 :             SetDuration( false );
    2604          10 :             SetFormat( TimeFieldFormat::F_NONE );
    2605             :         }
    2606          10 :         break;
    2607             :         case EXTTIMEF_24H_LONG:
    2608             :         {
    2609           6 :             SetTimeFormat( HOUR_24 );
    2610           6 :             SetDuration( false );
    2611           6 :             SetFormat( TimeFieldFormat::F_SEC );
    2612             :         }
    2613           6 :         break;
    2614             :         case EXTTIMEF_12H_SHORT:
    2615             :         {
    2616           6 :             SetTimeFormat( HOUR_12 );
    2617           6 :             SetDuration( false );
    2618           6 :             SetFormat( TimeFieldFormat::F_NONE );
    2619             :         }
    2620           6 :         break;
    2621             :         case EXTTIMEF_12H_LONG:
    2622             :         {
    2623           3 :             SetTimeFormat( HOUR_12 );
    2624           3 :             SetDuration( false );
    2625           3 :             SetFormat( TimeFieldFormat::F_SEC );
    2626             :         }
    2627           3 :         break;
    2628             :         case EXTTIMEF_DURATION_SHORT:
    2629             :         {
    2630           1 :             SetDuration( true );
    2631           1 :             SetFormat( TimeFieldFormat::F_NONE );
    2632             :         }
    2633           1 :         break;
    2634             :         case EXTTIMEF_DURATION_LONG:
    2635             :         {
    2636           0 :             SetDuration( true );
    2637           0 :             SetFormat( TimeFieldFormat::F_SEC );
    2638             :         }
    2639           0 :         break;
    2640             :         default:    OSL_FAIL( "ExtTimeFieldFormat unknown!" );
    2641             :     }
    2642             : 
    2643          26 :     if ( GetField() && !GetField()->GetText().isEmpty() )
    2644          26 :         SetUserTime( GetTime() );
    2645          26 :     ReformatAll();
    2646          26 : }
    2647             : 
    2648           0 : TimeBox::TimeBox( vcl::Window* pParent, WinBits nWinStyle ) :
    2649           0 :     ComboBox( pParent, nWinStyle )
    2650             : {
    2651           0 :     SetField( this );
    2652           0 :     SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, false, false ) );
    2653           0 :     Reformat();
    2654           0 : }
    2655             : 
    2656           0 : bool TimeBox::PreNotify( NotifyEvent& rNEvt )
    2657             : {
    2658           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    2659             :     {
    2660           0 :         if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
    2661           0 :             return true;
    2662             :     }
    2663             : 
    2664           0 :     return ComboBox::PreNotify( rNEvt );
    2665             : }
    2666             : 
    2667           0 : bool TimeBox::Notify( NotifyEvent& rNEvt )
    2668             : {
    2669           0 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
    2670           0 :         MarkToBeReformatted( false );
    2671           0 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
    2672             :     {
    2673           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
    2674           0 :             Reformat();
    2675             :     }
    2676             : 
    2677           0 :     return ComboBox::Notify( rNEvt );
    2678             : }
    2679             : 
    2680           0 : void TimeBox::DataChanged( const DataChangedEvent& rDCEvt )
    2681             : {
    2682           0 :     ComboBox::DataChanged( rDCEvt );
    2683             : 
    2684           0 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
    2685             :     {
    2686           0 :         if ( IsDefaultLocale() )
    2687           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    2688           0 :         ReformatAll();
    2689             :     }
    2690           0 : }
    2691             : 
    2692           0 : void TimeBox::Modify()
    2693             : {
    2694           0 :     MarkToBeReformatted( true );
    2695           0 :     ComboBox::Modify();
    2696           0 : }
    2697             : 
    2698           0 : void TimeBox::ReformatAll()
    2699             : {
    2700           0 :     OUString aStr;
    2701           0 :     SetUpdateMode( false );
    2702           0 :     sal_uInt16 nEntryCount = GetEntryCount();
    2703           0 :     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
    2704             :     {
    2705           0 :         ImplTimeReformat( GetEntry( i ), aStr );
    2706           0 :         RemoveEntryAt(i);
    2707           0 :         InsertEntry( aStr, i );
    2708             :     }
    2709           0 :     TimeFormatter::Reformat();
    2710           0 :     SetUpdateMode( true );
    2711         801 : }
    2712             : 
    2713             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11