blob: cfd058ff8123d45ec7c5a94739276ffff0c84c86 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
#include <tools/debug.hxx>
#include <tools/rc.h>
#include <vcl/svapp.hxx>
#include <vcl/sound.hxx>
#include <vcl/event.hxx>
#include <vcl/field.hxx>
#include <vcl/unohelp.hxx>
#include <svdata.hxx>
#include <i18npool/mslangid.hxx>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/i18n/XCharacterClassification.hpp>
#include <com/sun/star/i18n/KCharacterType.hpp>
#include <unotools/localedatawrapper.hxx>
#include <unotools/calendarwrapper.hxx>
#include <unotools/charclass.hxx>
#include <unotools/misccfg.hxx>
using namespace ::com::sun::star;
// =======================================================================
#define EDITMASK_LITERAL 'L'
#define EDITMASK_ALPHA 'a'
#define EDITMASK_UPPERALPHA 'A'
#define EDITMASK_ALPHANUM 'c'
#define EDITMASK_UPPERALPHANUM 'C'
#define EDITMASK_NUM 'N'
#define EDITMASK_NUMSPACE 'n'
#define EDITMASK_ALLCHAR 'x'
#define EDITMASK_UPPERALLCHAR 'X'
uno::Reference< i18n::XCharacterClassification > ImplGetCharClass()
{
static uno::Reference< i18n::XCharacterClassification > xCharClass;
if ( !xCharClass.is() )
xCharClass = vcl::unohelper::CreateCharacterClassification();
return xCharClass;
}
// -----------------------------------------------------------------------
static sal_Unicode* ImplAddString( sal_Unicode* pBuf, const String& rStr )
{
if ( rStr.Len() == 1 )
*pBuf++ = rStr.GetChar(0);
else if ( rStr.Len() == 0 )
;
else
{
memcpy( pBuf, rStr.GetBuffer(), rStr.Len() * sizeof(sal_Unicode) );
pBuf += rStr.Len();
}
return pBuf;
}
// -----------------------------------------------------------------------
static sal_Unicode* ImplAddNum( sal_Unicode* pBuf, sal_uLong nNumber, int nMinLen )
{
// fill temp buffer with digits
sal_Unicode aTempBuf[30];
sal_Unicode* pTempBuf = aTempBuf;
do
{
*pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
pTempBuf++;
nNumber /= 10;
if ( nMinLen )
nMinLen--;
}
while ( nNumber );
// fill with zeros up to the minimal length
while ( nMinLen > 0 )
{
*pBuf = '0';
pBuf++;
nMinLen--;
}
// copy temp buffer to real buffer
do
{
pTempBuf--;
*pBuf = *pTempBuf;
pBuf++;
}
while ( pTempBuf != aTempBuf );
return pBuf;
}
// -----------------------------------------------------------------------
static sal_uInt16 ImplGetNum( const sal_Unicode*& rpBuf, sal_Bool& rbError )
{
if ( !*rpBuf )
{
rbError = sal_True;
return 0;
}
sal_uInt16 nNumber = 0;
while( ( *rpBuf >= '0' ) && ( *rpBuf <= '9' ) )
{
nNumber *= 10;
nNumber += *rpBuf - '0';
rpBuf++;
}
return nNumber;
}
// -----------------------------------------------------------------------
static void ImplSkipDelimiters( const sal_Unicode*& rpBuf )
{
while( ( *rpBuf == ',' ) || ( *rpBuf == '.' ) || ( *rpBuf == ';' ) ||
( *rpBuf == ':' ) || ( *rpBuf == '-' ) || ( *rpBuf == '/' ) )
{
rpBuf++;
}
}
// -----------------------------------------------------------------------
static int ImplIsPatternChar( xub_Unicode cChar, sal_Char cEditMask )
{
sal_Int32 nType = 0;
try
{
String aCharStr( cChar );
nType = ImplGetCharClass()->getStringType( aCharStr, 0, aCharStr.Len(), Application::GetSettings().GetLocale() );
}
catch ( ::com::sun::star::uno::Exception& )
{
DBG_ERRORFILE( "ImplIsPatternChar: Exception caught!" );
return sal_False;
}
if ( (cEditMask == EDITMASK_ALPHA) || (cEditMask == EDITMASK_UPPERALPHA) )
{
if( !CharClass::isLetterType( nType ) )
return sal_False;
}
else if ( cEditMask == EDITMASK_NUM )
{
if( !CharClass::isNumericType( nType ) )
return sal_False;
}
else if ( (cEditMask == EDITMASK_ALPHANUM) || (cEditMask == EDITMASK_UPPERALPHANUM) )
{
if( !CharClass::isLetterNumericType( nType ) )
return sal_False;
}
else if ( (cEditMask == EDITMASK_ALLCHAR) || (cEditMask == EDITMASK_UPPERALLCHAR) )
{
if ( cChar < 32 )
return sal_False;
}
else if ( cEditMask == EDITMASK_NUMSPACE )
{
if ( !CharClass::isNumericType( nType ) && ( cChar != ' ' ) )
return sal_False;
}
else
return sal_False;
return sal_True;
}
// -----------------------------------------------------------------------
static xub_Unicode ImplPatternChar( xub_Unicode cChar, sal_Char cEditMask )
{
if ( ImplIsPatternChar( cChar, cEditMask ) )
{
if ( (cEditMask == EDITMASK_UPPERALPHA) ||
(cEditMask == EDITMASK_UPPERALPHANUM) ||
( cEditMask == EDITMASK_UPPERALLCHAR ) )
{
cChar = ImplGetCharClass()->toUpper( String(cChar),0,1,Application::GetSettings().GetLocale() )[0];
}
return cChar;
}
else
return 0;
}
// -----------------------------------------------------------------------
static int ImplKommaPointCharEqual( xub_Unicode c1, xub_Unicode c2 )
{
if ( c1 == c2 )
return sal_True;
else if ( ((c1 == '.') || (c1 == ',')) &&
((c2 == '.') || (c2 == ',')) )
return sal_True;
else
return sal_False;
}
// -----------------------------------------------------------------------
static XubString ImplPatternReformat( const XubString& rStr,
const ByteString& rEditMask,
const XubString& rLiteralMask,
sal_uInt16 nFormatFlags )
{
if ( !rEditMask.Len() )
return rStr;
XubString aStr = rStr;
XubString aOutStr = rLiteralMask;
xub_Unicode cTempChar;
xub_Unicode cChar;
xub_Unicode cLiteral;
sal_Char cMask;
xub_StrLen nStrIndex = 0;
xub_StrLen i = 0;
xub_StrLen n;
while ( i < rEditMask.Len() )
{
if ( nStrIndex >= aStr.Len() )
break;
cChar = aStr.GetChar(nStrIndex);
cLiteral = rLiteralMask.GetChar(i);
cMask = rEditMask.GetChar(i);
// Aktuelle Position ein Literal
if ( cMask == EDITMASK_LITERAL )
{
// Wenn es das Literal-Zeichen ist, uebernehmen, ansonsten
// ignorieren, da es das naechste gueltige Zeichen vom String
// sein kann
if ( ImplKommaPointCharEqual( cChar, cLiteral ) )
nStrIndex++;
else
{
// Ansonsten testen wir, ob es ein ungueltiges Zeichen ist.
// Dies ist dann der Fall, wenn es nicht in das Muster
// des naechsten nicht Literal-Zeichens passt
n = i+1;
while ( n < rEditMask.Len() )
{
if ( rEditMask.GetChar(n) != EDITMASK_LITERAL )
{
if ( !ImplIsPatternChar( cChar, rEditMask.GetChar(n) ) )
nStrIndex++;
break;
}
n++;
}
}
}
else
{
// Gueltiges Zeichen an der Stelle
cTempChar = ImplPatternChar( cChar, cMask );
if ( cTempChar )
{
// dann Zeichen uebernehmen
aOutStr.SetChar( i, cTempChar );
nStrIndex++;
}
else
{
// Wenn es das Literalzeichen ist, uebernehmen
if ( cLiteral == cChar )
nStrIndex++;
else
{
// Wenn das ungueltige Zeichen das naechste Literalzeichen
// sein kann, dann springen wir bis dahin vor, ansonten
// das Zeichen ignorieren
// Nur machen, wenn leere Literale erlaubt sind
if ( nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS )
{
n = i;
while ( n < rEditMask.Len() )
{
if ( rEditMask.GetChar( n ) == EDITMASK_LITERAL )
{
if ( ImplKommaPointCharEqual( cChar, rLiteralMask.GetChar( n ) ) )
i = n+1;
break;
}
n++;
}
}
nStrIndex++;
continue;
}
}
}
i++;
}
return aOutStr;
}
// -----------------------------------------------------------------------
static void ImplPatternMaxPos( const XubString rStr, const ByteString& rEditMask,
sal_uInt16 nFormatFlags, sal_Bool bSameMask,
sal_uInt16 nCursorPos, sal_uInt16& rPos )
{
// Letzte Position darf nicht groesser als der enthaltene String sein
xub_StrLen nMaxPos = rStr.Len();
// Wenn keine leeren Literale erlaubt sind, auch Leerzeichen
// am Ende ignorieren
if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
{
while ( nMaxPos )
{
if ( (rEditMask.GetChar(nMaxPos-1) != EDITMASK_LITERAL) &&
(rStr.GetChar(nMaxPos-1) != ' ') )
break;
nMaxPos--;
}
// Wenn wir vor einem Literal stehen, dann solange weitersuchen,
// bis erste Stelle nach Literal
xub_StrLen nTempPos = nMaxPos;
while ( nTempPos < rEditMask.Len() )
{
if ( rEditMask.GetChar(nTempPos) != EDITMASK_LITERAL )
{
nMaxPos = nTempPos;
break;
}
nTempPos++;
}
}
if ( rPos > nMaxPos )
rPos = nMaxPos;
// Zeichen sollte nicht nach links wandern
if ( rPos < nCursorPos )
rPos = nCursorPos;
}
// -----------------------------------------------------------------------
static void ImplPatternProcessStrictModify( Edit* pEdit,
const ByteString& rEditMask,
const XubString& rLiteralMask,
sal_uInt16 nFormatFlags, sal_Bool bSameMask )
{
XubString aText = pEdit->GetText();
// Leerzeichen am Anfang entfernen
if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
{
xub_StrLen i = 0;
xub_StrLen nMaxLen = aText.Len();
while ( i < nMaxLen )
{
if ( (rEditMask.GetChar( i ) != EDITMASK_LITERAL) &&
(aText.GetChar( i ) != ' ') )
break;
i++;
}
// Alle Literalzeichen beibehalten
while ( i && (rEditMask.GetChar( i ) == EDITMASK_LITERAL) )
i--;
aText.Erase( 0, i );
}
XubString aNewText = ImplPatternReformat( aText, rEditMask, rLiteralMask, nFormatFlags );
if ( aNewText != aText )
{
// Selection so anpassen, das diese wenn sie vorher am Ende
// stand, immer noch am Ende steht
Selection aSel = pEdit->GetSelection();
sal_uLong nMaxSel = Max( aSel.Min(), aSel.Max() );
if ( nMaxSel >= aText.Len() )
{
xub_StrLen nMaxPos = aNewText.Len();
ImplPatternMaxPos( aNewText, rEditMask, nFormatFlags, bSameMask, (xub_StrLen)nMaxSel, nMaxPos );
if ( aSel.Min() == aSel.Max() )
{
aSel.Min() = nMaxPos;
aSel.Max() = aSel.Min();
}
else if ( aSel.Min() > aSel.Max() )
aSel.Min() = nMaxPos;
else
aSel.Max() = nMaxPos;
}
pEdit->SetText( aNewText, aSel );
}
}
// -----------------------------------------------------------------------
static xub_StrLen ImplPatternLeftPos( const ByteString& rEditMask, xub_StrLen nCursorPos )
{
// Vorheriges Zeichen suchen, was kein Literal ist
xub_StrLen nNewPos = nCursorPos;
xub_StrLen nTempPos = nNewPos;
while ( nTempPos )
{
if ( rEditMask.GetChar(nTempPos-1) != EDITMASK_LITERAL )
{
nNewPos = nTempPos-1;
break;
}
nTempPos--;
}
return nNewPos;
}
// -----------------------------------------------------------------------
static xub_StrLen ImplPatternRightPos( const XubString& rStr, const ByteString& rEditMask,
sal_uInt16 nFormatFlags, sal_Bool bSameMask,
xub_StrLen nCursorPos )
{
// Naechstes Zeichen suchen, was kein Literal ist
xub_StrLen nNewPos = nCursorPos;
xub_StrLen nTempPos = nNewPos;
while ( nTempPos < rEditMask.Len() )
{
if ( rEditMask.GetChar(nTempPos+1) != EDITMASK_LITERAL )
{
nNewPos = nTempPos+1;
break;
}
nTempPos++;
}
ImplPatternMaxPos( rStr, rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
return nNewPos;
}
// -----------------------------------------------------------------------
static sal_Bool ImplPatternProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
const ByteString& rEditMask,
const XubString& rLiteralMask,
sal_Bool bStrictFormat,
sal_uInt16 nFormatFlags,
sal_Bool bSameMask,
sal_Bool& rbInKeyInput )
{
if ( !rEditMask.Len() || !bStrictFormat )
return sal_False;
Selection aOldSel = pEdit->GetSelection();
KeyCode aCode = rKEvt.GetKeyCode();
xub_Unicode cChar = rKEvt.GetCharCode();
sal_uInt16 nKeyCode = aCode.GetCode();
sal_Bool bShift = aCode.IsShift();
xub_StrLen nCursorPos = (xub_StrLen)aOldSel.Max();
xub_StrLen nNewPos;
xub_StrLen nTempPos;
if ( nKeyCode && !aCode.IsMod1() && !aCode.IsMod2() )
{
if ( nKeyCode == KEY_LEFT )
{
Selection aSel( ImplPatternLeftPos( rEditMask, nCursorPos ) );
if ( bShift )
aSel.Min() = aOldSel.Min();
pEdit->SetSelection( aSel );
return sal_True;
}
else if ( nKeyCode == KEY_RIGHT )
{
// Hier nehmen wir Selectionsanfang als minimum, da falls durch
// Focus alles selektiert ist, ist eine kleine Position schon
// erlaubt.
Selection aSel( aOldSel );
aSel.Justify();
nCursorPos = (xub_StrLen)aSel.Min();
aSel.Max() = ImplPatternRightPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos );
if ( bShift )
aSel.Min() = aOldSel.Min();
else
aSel.Min() = aSel.Max();
pEdit->SetSelection( aSel );
return sal_True;
}
else if ( nKeyCode == KEY_HOME )
{
// Home ist Position des ersten nicht literalen Zeichens
nNewPos = 0;
while ( (nNewPos < rEditMask.Len()) &&
(rEditMask.GetChar(nNewPos) == EDITMASK_LITERAL) )
nNewPos++;
// Home sollte nicht nach rechts wandern
if ( nCursorPos < nNewPos )
nNewPos = nCursorPos;
Selection aSel( nNewPos );
if ( bShift )
aSel.Min() = aOldSel.Min();
pEdit->SetSelection( aSel );
return sal_True;
}
else if ( nKeyCode == KEY_END )
{
// End ist die Position des letzten nicht literalen Zeichens
nNewPos = rEditMask.Len();
while ( nNewPos &&
(rEditMask.GetChar(nNewPos-1) == EDITMASK_LITERAL) )
nNewPos--;
// Hier nehmen wir Selectionsanfang als minimum, da falls durch
// Focus alles selektiert ist, ist eine kleine Position schon
// erlaubt.
Selection aSel( aOldSel );
aSel.Justify();
nCursorPos = (xub_StrLen)aSel.Min();
ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
aSel.Max() = nNewPos;
if ( bShift )
aSel.Min() = aOldSel.Min();
else
aSel.Min() = aSel.Max();
pEdit->SetSelection( aSel );
return sal_True;
}
else if ( (nKeyCode == KEY_BACKSPACE) || (nKeyCode == KEY_DELETE) )
{
XubString aStr( pEdit->GetText() );
XubString aOldStr = aStr;
Selection aSel = aOldSel;
aSel.Justify();
nNewPos = (xub_StrLen)aSel.Min();
// Wenn Selection, dann diese Loeschen
if ( aSel.Len() )
{
if ( bSameMask )
aStr.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
else
{
XubString aRep = rLiteralMask.Copy( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
aStr.Replace( (xub_StrLen)aSel.Min(), aRep.Len(), aRep );
}
}
else
{
if ( nKeyCode == KEY_BACKSPACE )
{
nTempPos = nNewPos;
nNewPos = ImplPatternLeftPos( rEditMask, nTempPos );
}
else
nTempPos = ImplPatternRightPos( aStr, rEditMask, nFormatFlags, bSameMask, nNewPos );
if ( nNewPos != nTempPos )
{
if ( bSameMask )
{
if ( rEditMask.GetChar( nNewPos ) != EDITMASK_LITERAL )
aStr.Erase( nNewPos, 1 );
}
else
{
XubString aTempStr = rLiteralMask.Copy( nNewPos, 1 );
aStr.Replace( nNewPos, aTempStr.Len(), aTempStr );
}
}
}
if ( aOldStr != aStr )
{
if ( bSameMask )
aStr = ImplPatternReformat( aStr, rEditMask, rLiteralMask, nFormatFlags );
rbInKeyInput = sal_True;
pEdit->SetText( aStr, Selection( nNewPos ) );
pEdit->SetModifyFlag();
pEdit->Modify();
rbInKeyInput = sal_False;
}
else
pEdit->SetSelection( Selection( nNewPos ) );
return sal_True;
}
else if ( nKeyCode == KEY_INSERT )
{
// InsertModus kann man beim PatternField nur einstellen,
// wenn Maske an jeder Eingabeposition die gleiche
// ist
if ( !bSameMask )
{
Sound::Beep();
return sal_True;
}
}
}
if ( rKEvt.GetKeyCode().IsMod2() || (cChar < 32) || (cChar == 127) )
return sal_False;
Selection aSel = aOldSel;
aSel.Justify();
nNewPos = (xub_StrLen)aSel.Min();
if ( nNewPos < rEditMask.Len() )
{
xub_Unicode cPattChar = ImplPatternChar( cChar, rEditMask.GetChar(nNewPos) );
if ( cPattChar )
cChar = cPattChar;
else
{
// Wenn kein gueltiges Zeichen, dann testen wir, ob der
// Anwender zum naechsten Literal springen wollte. Dies machen
// wir nur, wenn er hinter einem Zeichen steht, damit
// eingebene Literale die automatisch uebersprungenen wurden
// nicht dazu fuehren, das der Anwender dann da steht, wo
// er nicht stehen wollte.
if ( nNewPos &&
(rEditMask.GetChar(nNewPos-1) != EDITMASK_LITERAL) &&
!aSel.Len() )
{
// Naechstes Zeichen suchen, was kein Literal ist
nTempPos = nNewPos;
while ( nTempPos < rEditMask.Len() )
{
if ( rEditMask.GetChar(nTempPos) == EDITMASK_LITERAL )
{
// Gilt nur, wenn ein Literalzeichen vorhanden
if ( (rEditMask.GetChar(nTempPos+1) != EDITMASK_LITERAL ) &&
ImplKommaPointCharEqual( cChar, rLiteralMask.GetChar(nTempPos) ) )
{
nTempPos++;
ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nNewPos, nTempPos );
if ( nTempPos > nNewPos )
{
pEdit->SetSelection( Selection( nTempPos ) );
return sal_True;
}
}
break;
}
nTempPos++;
}
}
cChar = 0;
}
}
else
cChar = 0;
if ( cChar )
{
XubString aStr = pEdit->GetText();
sal_Bool bError = sal_False;
if ( bSameMask && pEdit->IsInsertMode() )
{
// Text um Spacezeichen und Literale am Ende kuerzen, bis zur
// aktuellen Position
xub_StrLen n = aStr.Len();
while ( n && (n > nNewPos) )
{
if ( (aStr.GetChar( n-1 ) != ' ') &&
((n > rEditMask.Len()) || (rEditMask.GetChar(n-1) != EDITMASK_LITERAL)) )
break;
n--;
}
aStr.Erase( n );
if ( aSel.Len() )
aStr.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
if ( aStr.Len() < rEditMask.Len() )
{
// String evtl. noch bis Cursor-Position erweitern
if ( aStr.Len() < nNewPos )
aStr += rLiteralMask.Copy( aStr.Len(), nNewPos-aStr.Len() );
if ( nNewPos < aStr.Len() )
aStr.Insert( cChar, nNewPos );
else if ( nNewPos < rEditMask.Len() )
aStr += cChar;
aStr = ImplPatternReformat( aStr, rEditMask, rLiteralMask, nFormatFlags );
}
else
bError = sal_True;
}
else
{
if ( aSel.Len() )
{
// Selection loeschen
XubString aRep = rLiteralMask.Copy( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
aStr.Replace( (xub_StrLen)aSel.Min(), aRep.Len(), aRep );
}
if ( nNewPos < aStr.Len() )
aStr.SetChar( nNewPos, cChar );
else if ( nNewPos < rEditMask.Len() )
aStr += cChar;
}
if ( bError )
Sound::Beep();
else
{
rbInKeyInput = sal_True;
Selection aNewSel( ImplPatternRightPos( aStr, rEditMask, nFormatFlags, bSameMask, nNewPos ) );
pEdit->SetText( aStr, aNewSel );
pEdit->SetModifyFlag();
pEdit->Modify();
rbInKeyInput = sal_False;
}
}
else
Sound::Beep();
return sal_True;
}
// -----------------------------------------------------------------------
void PatternFormatter::ImplSetMask( const ByteString& rEditMask,
const XubString& rLiteralMask )
{
maEditMask = rEditMask;
maLiteralMask = rLiteralMask;
mbSameMask = sal_True;
if ( maEditMask.Len() != maLiteralMask.Len() )
{
if ( maEditMask.Len() < maLiteralMask.Len() )
maLiteralMask.Erase( maEditMask.Len() );
else
maLiteralMask.Expand( maEditMask.Len(), ' ' );
}
// StrictModus erlaubt nur Input-Mode, wenn als Maske nur
// gleiche Zeichen zugelassen werden und als Vorgabe nur
// Spacezeichen vorgegeben werden, die durch die Maske
// nicht zugelassen sind
xub_StrLen i = 0;
sal_Char c = 0;
while ( i < rEditMask.Len() )
{
sal_Char cTemp = rEditMask.GetChar( i );
if ( cTemp != EDITMASK_LITERAL )
{
if ( (cTemp == EDITMASK_ALLCHAR) ||
(cTemp == EDITMASK_UPPERALLCHAR) ||
(cTemp == EDITMASK_NUMSPACE) )
{
mbSameMask = sal_False;
break;
}
if ( i < rLiteralMask.Len() )
{
if ( rLiteralMask.GetChar( i ) != ' ' )
{
mbSameMask = sal_False;
break;
}
}
if ( !c )
c = cTemp;
if ( cTemp != c )
{
mbSameMask = sal_False;
break;
}
}
i++;
}
}
// -----------------------------------------------------------------------
PatternFormatter::PatternFormatter()
{
mnFormatFlags = 0;
mbSameMask = sal_True;
mbInPattKeyInput = sal_False;
}
// -----------------------------------------------------------------------
void PatternFormatter::ImplLoadRes( const ResId& rResId )
{
ByteString aEditMask;
XubString aLiteralMask;
ResMgr* pMgr = rResId.GetResMgr();
if( pMgr )
{
sal_uLong nMask = pMgr->ReadLong();
if ( PATTERNFORMATTER_STRICTFORMAT & nMask )
SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
if ( PATTERNFORMATTER_EDITMASK & nMask )
aEditMask = ByteString( pMgr->ReadString(), RTL_TEXTENCODING_ASCII_US );
if ( PATTERNFORMATTER_LITTERALMASK & nMask )
aLiteralMask = pMgr->ReadString();
if ( (PATTERNFORMATTER_EDITMASK | PATTERNFORMATTER_LITTERALMASK) & nMask )
ImplSetMask( aEditMask, aLiteralMask );
}
}
// -----------------------------------------------------------------------
PatternFormatter::~PatternFormatter()
{
}
// -----------------------------------------------------------------------
void PatternFormatter::SetMask( const ByteString& rEditMask,
const XubString& rLiteralMask )
{
ImplSetMask( rEditMask, rLiteralMask );
ReformatAll();
}
// -----------------------------------------------------------------------
void PatternFormatter::SetString( const XubString& rStr )
{
maFieldString = rStr;
if ( GetField() )
{
GetField()->SetText( rStr );
MarkToBeReformatted( sal_False );
}
}
// -----------------------------------------------------------------------
XubString PatternFormatter::GetString() const
{
if ( !GetField() )
return ImplGetSVEmptyStr();
else
return ImplPatternReformat( GetField()->GetText(), maEditMask, maLiteralMask, mnFormatFlags );
}
// -----------------------------------------------------------------------
void PatternFormatter::Reformat()
{
if ( GetField() )
{
ImplSetText( ImplPatternReformat( GetField()->GetText(), maEditMask, maLiteralMask, mnFormatFlags ) );
if ( !mbSameMask && IsStrictFormat() && !GetField()->IsReadOnly() )
GetField()->SetInsertMode( sal_False );
}
}
// -----------------------------------------------------------------------
void PatternFormatter::SelectFixedFont()
{
if ( GetField() )
{
Font aFont = OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, Application::GetSettings().GetLanguage(), 0 );
Font aControlFont;
aControlFont.SetName( aFont.GetName() );
aControlFont.SetFamily( aFont.GetFamily() );
aControlFont.SetPitch( aFont.GetPitch() );
GetField()->SetControlFont( aControlFont );
}
}
// -----------------------------------------------------------------------
PatternField::PatternField( Window* pParent, WinBits nWinStyle ) :
SpinField( pParent, nWinStyle )
{
SetField( this );
Reformat();
}
// -----------------------------------------------------------------------
PatternField::PatternField( Window* pParent, const ResId& rResId ) :
SpinField( WINDOW_PATTERNFIELD )
{
rResId.SetRT( RSC_PATTERNFIELD );
WinBits nStyle = ImplInitRes( rResId );
ImplInit( pParent, nStyle );
SetField( this );
SpinField::ImplLoadRes( rResId );
PatternFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
Reformat();
if ( !(nStyle & WB_HIDE ) )
Show();
}
// -----------------------------------------------------------------------
PatternField::~PatternField()
{
}
// -----------------------------------------------------------------------
long PatternField::PreNotify( NotifyEvent& rNEvt )
{
if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
{
if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
IsStrictFormat(), GetFormatFlags(),
ImplIsSameMask(), ImplGetInPattKeyInput() ) )
return 1;
}
return SpinField::PreNotify( rNEvt );
}
// -----------------------------------------------------------------------
long PatternField::Notify( NotifyEvent& rNEvt )
{
if ( rNEvt.GetType() == EVENT_GETFOCUS )
MarkToBeReformatted( sal_False );
else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
{
if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
Reformat();
}
return SpinField::Notify( rNEvt );
}
// -----------------------------------------------------------------------
void PatternField::Modify()
{
if ( !ImplGetInPattKeyInput() )
{
if ( IsStrictFormat() )
ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
else
MarkToBeReformatted( sal_True );
}
SpinField::Modify();
}
// -----------------------------------------------------------------------
PatternBox::PatternBox( Window* pParent, WinBits nWinStyle ) :
ComboBox( pParent, nWinStyle )
{
SetField( this );
Reformat();
}
// -----------------------------------------------------------------------
PatternBox::PatternBox( Window* pParent, const ResId& rResId ) :
ComboBox( WINDOW_PATTERNBOX )
{
rResId.SetRT( RSC_PATTERNBOX );
WinBits nStyle = ImplInitRes( rResId );
ImplInit( pParent, nStyle );
SetField( this );
ComboBox::ImplLoadRes( rResId );
PatternFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
Reformat();
if ( !(nStyle & WB_HIDE ) )
Show();
}
// -----------------------------------------------------------------------
PatternBox::~PatternBox()
{
}
// -----------------------------------------------------------------------
long PatternBox::PreNotify( NotifyEvent& rNEvt )
{
if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
{
if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
IsStrictFormat(), GetFormatFlags(),
ImplIsSameMask(), ImplGetInPattKeyInput() ) )
return 1;
}
return ComboBox::PreNotify( rNEvt );
}
// -----------------------------------------------------------------------
long PatternBox::Notify( NotifyEvent& rNEvt )
{
if ( rNEvt.GetType() == EVENT_GETFOCUS )
MarkToBeReformatted( sal_False );
else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
{
if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
Reformat();
}
return ComboBox::Notify( rNEvt );
}
// -----------------------------------------------------------------------
void PatternBox::Modify()
{
if ( !ImplGetInPattKeyInput() )
{
if ( IsStrictFormat() )
ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
else
MarkToBeReformatted( sal_True );
}
ComboBox::Modify();
}
// -----------------------------------------------------------------------
void PatternBox::ReformatAll()
{
XubString aStr;
SetUpdateMode( sal_False );
sal_uInt16 nEntryCount = GetEntryCount();
for ( sal_uInt16 i=0; i < nEntryCount; i++ )
{
aStr = ImplPatternReformat( GetEntry( i ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
RemoveEntry( i );
InsertEntry( aStr, i );
}
PatternFormatter::Reformat();
SetUpdateMode( sal_True );
}
// -----------------------------------------------------------------------
void PatternBox::InsertString( const XubString& rStr, sal_uInt16 nPos )
{
ComboBox::InsertEntry( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ), nPos );
}
// -----------------------------------------------------------------------
void PatternBox::RemoveString( const XubString& rStr )
{
ComboBox::RemoveEntry( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ) );
}
// -----------------------------------------------------------------------
XubString PatternBox::GetString( sal_uInt16 nPos ) const
{
return ImplPatternReformat( ComboBox::GetEntry( nPos ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
}
// -----------------------------------------------------------------------
sal_uInt16 PatternBox::GetStringPos( const XubString& rStr ) const
{
return ComboBox::GetEntryPos( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ) );
}
// =======================================================================
static ExtDateFieldFormat ImplGetExtFormat( DateFormat eOld )
{
switch( eOld )
{
case DMY: return XTDATEF_SHORT_DDMMYY;
case MDY: return XTDATEF_SHORT_MMDDYY;
default: return XTDATEF_SHORT_YYMMDD;
}
}
// -----------------------------------------------------------------------
static sal_uInt16 ImplCutNumberFromString( XubString& rStr )
{
// Nach Zahl suchen
while ( rStr.Len() && !(rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
rStr.Erase( 0, 1 );
if ( !rStr.Len() )
return 0;
XubString aNumStr;
while ( rStr.Len() && (rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
{
aNumStr.Insert( rStr.GetChar( 0 ) );
rStr.Erase( 0, 1 );
}
return (sal_uInt16)aNumStr.ToInt32();
}
// -----------------------------------------------------------------------
static sal_Bool ImplCutMonthName( XubString& rStr, const XubString& _rLookupMonthName )
{
sal_uInt16 nPos = rStr.Search( _rLookupMonthName );
if ( nPos != STRING_NOTFOUND )
{
rStr.Erase( 0, nPos + _rLookupMonthName.Len() );
return sal_True;
}
return sal_False;
}
// -----------------------------------------------------------------------
static sal_uInt16 ImplCutMonthFromString( XubString& rStr, const CalendarWrapper& rCalendarWrapper )
{
// search for a month' name
for ( sal_uInt16 i=1; i <= 12; i++ )
{
String aMonthName = rCalendarWrapper.getMonths()[i-1].FullName;
// long month name?
if ( ImplCutMonthName( rStr, aMonthName ) )
return i;
// short month name?
String aAbbrevMonthName = rCalendarWrapper.getMonths()[i-1].AbbrevName;
if ( ImplCutMonthName( rStr, aAbbrevMonthName ) )
return i;
}
return ImplCutNumberFromString( rStr );
}
// -----------------------------------------------------------------------
static String ImplGetDateSep( const LocaleDataWrapper& rLocaleDataWrapper, ExtDateFieldFormat eFormat )
{
String aDateSep = rLocaleDataWrapper.getDateSep();
if ( ( eFormat == XTDATEF_SHORT_YYMMDD_DIN5008 ) || ( eFormat == XTDATEF_SHORT_YYYYMMDD_DIN5008 ) )
aDateSep = String( RTL_CONSTASCII_USTRINGPARAM( "-" ) );
return aDateSep;
}
static sal_Bool ImplDateProcessKeyInput( Edit*, const KeyEvent& rKEvt, ExtDateFieldFormat eFormat,
const LocaleDataWrapper& rLocaleDataWrapper )
{
xub_Unicode cChar = rKEvt.GetCharCode();
sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
(nGroup == KEYGROUP_MISC)||
((cChar >= '0') && (cChar <= '9')) ||
(cChar == ImplGetDateSep( rLocaleDataWrapper, eFormat ).GetChar(0) ) )
return sal_False;
else
return sal_True;
}
// -----------------------------------------------------------------------
static sal_Bool ImplDateGetValue( const XubString& rStr, Date& rDate, ExtDateFieldFormat eDateFormat,
const LocaleDataWrapper& rLocaleDataWrapper, const CalendarWrapper& rCalendarWrapper,
const AllSettings& )
{
sal_uInt16 nDay = 0;
sal_uInt16 nMonth = 0;
sal_uInt16 nYear = 0;
sal_Bool bYear = sal_True;
sal_Bool bError = sal_False;
String aStr( rStr );
if ( eDateFormat == XTDATEF_SYSTEM_LONG )
{
DateFormat eFormat = rLocaleDataWrapper.getLongDateFormat();
switch( eFormat )
{
case MDY:
nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
nDay = ImplCutNumberFromString( aStr );
nYear = ImplCutNumberFromString( aStr );
break;
case DMY:
nDay = ImplCutNumberFromString( aStr );
nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
nYear = ImplCutNumberFromString( aStr );
break;
case YMD:
default:
nYear = ImplCutNumberFromString( aStr );
nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
nDay = ImplCutNumberFromString( aStr );
break;
}
}
else
{
// Check if year is present:
String aDateSep = ImplGetDateSep( rLocaleDataWrapper, eDateFormat );
sal_uInt16 nSepPos = aStr.Search( aDateSep );
if ( nSepPos == STRING_NOTFOUND )
return sal_False;
nSepPos = aStr.Search( aDateSep, nSepPos+1 );
if ( ( nSepPos == STRING_NOTFOUND ) || ( nSepPos == (aStr.Len()-1) ) )
{
bYear = sal_False;
nYear = Date().GetYear();
}
const sal_Unicode* pBuf = aStr.GetBuffer();
ImplSkipDelimiters( pBuf );
switch ( eDateFormat )
{
case XTDATEF_SHORT_DDMMYY:
case XTDATEF_SHORT_DDMMYYYY:
{
nDay = ImplGetNum( pBuf, bError );
ImplSkipDelimiters( pBuf );
nMonth = ImplGetNum( pBuf, bError );
ImplSkipDelimiters( pBuf );
if ( bYear )
nYear = ImplGetNum( pBuf, bError );
}
break;
case XTDATEF_SHORT_MMDDYY:
case XTDATEF_SHORT_MMDDYYYY:
{
nMonth = ImplGetNum( pBuf, bError );
ImplSkipDelimiters( pBuf );
nDay = ImplGetNum( pBuf, bError );
ImplSkipDelimiters( pBuf );
if ( bYear )
nYear = ImplGetNum( pBuf, bError );
}
break;
case XTDATEF_SHORT_YYMMDD:
case XTDATEF_SHORT_YYYYMMDD:
case XTDATEF_SHORT_YYMMDD_DIN5008:
case XTDATEF_SHORT_YYYYMMDD_DIN5008:
{
if ( bYear )
nYear = ImplGetNum( pBuf, bError );
ImplSkipDelimiters( pBuf );
nMonth = ImplGetNum( pBuf, bError );
ImplSkipDelimiters( pBuf );
nDay = ImplGetNum( pBuf, bError );
}
break;
default:
{
DBG_ERROR( "DateFormat???" );
}
}
}
if ( bError || !nDay || !nMonth )
return sal_False;
Date aNewDate( nDay, nMonth, nYear );
DateFormatter::ExpandCentury( aNewDate, utl::MiscCfg().GetYear2000() );
if ( aNewDate.IsValid() )
{
rDate = aNewDate;
return sal_True;
}
return sal_False;
}
// -----------------------------------------------------------------------
sal_Bool DateFormatter::ImplDateReformat( const XubString& rStr, XubString& rOutStr, const AllSettings& rSettings )
{
Date aDate( 0, 0, 0 );
if ( !ImplDateGetValue( rStr, aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
return sal_True;
Date aTempDate = aDate;
if ( aTempDate > GetMax() )
aTempDate = GetMax();
else if ( aTempDate < GetMin() )
aTempDate = GetMin();
if ( GetErrorHdl().IsSet() && (aDate != aTempDate) )
{
maCorrectedDate = aTempDate;
if( !GetErrorHdl().Call( this ) )
{
maCorrectedDate = Date();
return sal_False;
}
else
maCorrectedDate = Date();
}
rOutStr = ImplGetDateAsText( aTempDate, rSettings );
return sal_True;
}
// -----------------------------------------------------------------------
XubString DateFormatter::ImplGetDateAsText( const Date& rDate,
const AllSettings& ) const
{
sal_Bool bShowCentury = sal_False;
switch ( GetExtDateFormat() )
{
case XTDATEF_SYSTEM_SHORT_YYYY:
case XTDATEF_SYSTEM_LONG:
case XTDATEF_SHORT_DDMMYYYY:
case XTDATEF_SHORT_MMDDYYYY:
case XTDATEF_SHORT_YYYYMMDD:
case XTDATEF_SHORT_YYYYMMDD_DIN5008:
{
bShowCentury = sal_True;
}
break;
default:
{
bShowCentury = sal_False;
}
}
if ( !bShowCentury )
{
// Check if I have to use force showing the century
sal_uInt16 nTwoDigitYearStart = utl::MiscCfg().GetYear2000();
sal_uInt16 nYear = rDate.GetYear();
// Wenn Jahr nicht im 2stelligen Grenzbereich liegt,
if ( (nYear < nTwoDigitYearStart) || (nYear >= nTwoDigitYearStart+100) )
bShowCentury = sal_True;
}
sal_Unicode aBuf[128];
sal_Unicode* pBuf = aBuf;
String aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), GetExtDateFormat( sal_True ) );
sal_uInt16 nDay = rDate.GetDay();
sal_uInt16 nMonth = rDate.GetMonth();
sal_uInt16 nYear = rDate.GetYear();
sal_uInt16 nYearLen = bShowCentury ? 4 : 2;
if ( !bShowCentury )
nYear %= 100;
switch ( GetExtDateFormat( sal_True ) )
{
case XTDATEF_SYSTEM_LONG:
{
return ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, sal_False, 1, !bShowCentury );
}
case XTDATEF_SHORT_DDMMYY:
case XTDATEF_SHORT_DDMMYYYY:
{
pBuf = ImplAddNum( pBuf, nDay, 2 );
pBuf = ImplAddString( pBuf, aDateSep );
pBuf = ImplAddNum( pBuf, nMonth, 2 );
pBuf = ImplAddString( pBuf, aDateSep );
pBuf = ImplAddNum( pBuf, nYear, nYearLen );
}
break;
case XTDATEF_SHORT_MMDDYY:
case XTDATEF_SHORT_MMDDYYYY:
{
pBuf = ImplAddNum( pBuf, nMonth, 2 );
pBuf = ImplAddString( pBuf, aDateSep );
pBuf = ImplAddNum( pBuf, nDay, 2 );
pBuf = ImplAddString( pBuf, aDateSep );
pBuf = ImplAddNum( pBuf, nYear, nYearLen );
}
break;
case XTDATEF_SHORT_YYMMDD:
case XTDATEF_SHORT_YYYYMMDD:
case XTDATEF_SHORT_YYMMDD_DIN5008:
case XTDATEF_SHORT_YYYYMMDD_DIN5008:
{
pBuf = ImplAddNum( pBuf, nYear, nYearLen );
pBuf = ImplAddString( pBuf, aDateSep );
pBuf = ImplAddNum( pBuf, nMonth, 2 );
pBuf = ImplAddString( pBuf, aDateSep );
pBuf = ImplAddNum( pBuf, nDay, 2 );
}
break;
default:
{
DBG_ERROR( "DateFormat???" );
}
}
return String( aBuf, (xub_StrLen)(sal_uLong)(pBuf-aBuf) );
}
// -----------------------------------------------------------------------
static void ImplDateIncrementDay( Date& rDate, sal_Bool bUp )
{
DateFormatter::ExpandCentury( rDate );
if ( bUp )
{
if ( (rDate.GetDay() != 31) || (rDate.GetMonth() != 12) || (rDate.GetYear() != 9999) )
rDate++;
}
else
{
if ( (rDate.GetDay() != 1 ) || (rDate.GetMonth() != 1) || (rDate.GetYear() != 0) )
rDate--;
}
}
// -----------------------------------------------------------------------
static void ImplDateIncrementMonth( Date& rDate, sal_Bool bUp )
{
DateFormatter::ExpandCentury( rDate );
sal_uInt16 nMonth = rDate.GetMonth();
sal_uInt16 nYear = rDate.GetYear();
if ( bUp )
{
if ( (nMonth == 12) && (nYear < 9999) )
{
rDate.SetMonth( 1 );
rDate.SetYear( nYear + 1 );
}
else
{
if ( nMonth < 12 )
rDate.SetMonth( nMonth + 1 );
}
}
else
{
if ( (nMonth == 1) && (nYear > 0) )
{
rDate.SetMonth( 12 );
rDate.SetYear( nYear - 1 );
}
else
{
if ( nMonth > 1 )
rDate.SetMonth( nMonth - 1 );
}
}
sal_uInt16 nDaysInMonth = rDate.GetDaysInMonth();
if ( rDate.GetDay() > nDaysInMonth )
rDate.SetDay( nDaysInMonth );
}
// -----------------------------------------------------------------------
static void ImplDateIncrementYear( Date& rDate, sal_Bool bUp )
{
DateFormatter::ExpandCentury( rDate );
sal_uInt16 nYear = rDate.GetYear();
if ( bUp )
{
if ( nYear < 9999 )
rDate.SetYear( nYear + 1 );
}
else
{
if ( nYear > 0 )
rDate.SetYear( nYear - 1 );
}
}
// -----------------------------------------------------------------------
sal_Bool DateFormatter::ImplAllowMalformedInput() const
{
return !IsEnforceValidValue();
}
// -----------------------------------------------------------------------
void DateField::ImplDateSpinArea( sal_Bool bUp )
{
// Wenn alles selektiert ist, Tage hochzaehlen
if ( GetField() )
{
Date aDate( GetDate() );
Selection aSelection = GetField()->GetSelection();
aSelection.Justify();
XubString aText( GetText() );
if ( (xub_StrLen)aSelection.Len() == aText.Len() )
ImplDateIncrementDay( aDate, bUp );
else
{
xub_StrLen nDateArea = 0;
ExtDateFieldFormat eFormat = GetExtDateFormat( sal_True );
if ( eFormat == XTDATEF_SYSTEM_LONG )
{
eFormat = ImplGetExtFormat( ImplGetLocaleDataWrapper().getLongDateFormat() );
nDateArea = 1;
}
else
{
// Area suchen
xub_StrLen nPos = 0;
String aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), eFormat );
for ( xub_StrLen i = 1; i <= 3; i++ )
{
nPos = aText.Search( aDateSep, nPos );
if ( nPos >= (sal_uInt16)aSelection.Max() )
{
nDateArea = i;
break;
}
else
nPos++;
}
}
switch( eFormat )
{
case XTDATEF_SHORT_MMDDYY:
case XTDATEF_SHORT_MMDDYYYY:
switch( nDateArea )
{
case 1: ImplDateIncrementMonth( aDate, bUp );
break;
case 2: ImplDateIncrementDay( aDate, bUp );
break;
case 3: ImplDateIncrementYear( aDate, bUp );
break;
}
break;
case XTDATEF_SHORT_DDMMYY:
case XTDATEF_SHORT_DDMMYYYY:
switch( nDateArea )
{
case 1: ImplDateIncrementDay( aDate, bUp );
break;
case 2: ImplDateIncrementMonth( aDate, bUp );
break;
case 3: ImplDateIncrementYear( aDate, bUp );
break;
}
break;
case XTDATEF_SHORT_YYMMDD:
case XTDATEF_SHORT_YYYYMMDD:
case XTDATEF_SHORT_YYMMDD_DIN5008:
case XTDATEF_SHORT_YYYYMMDD_DIN5008:
switch( nDateArea )
{
case 1: ImplDateIncrementYear( aDate, bUp );
break;
case 2: ImplDateIncrementMonth( aDate, bUp );
break;
case 3: ImplDateIncrementDay( aDate, bUp );
break;
}
break;
default:
DBG_ERROR( "invalid conversion" );
break;
}
}
ImplNewFieldValue( aDate );
}
}
// -----------------------------------------------------------------------
void DateFormatter::ImplInit()
{
mbLongFormat = sal_False;
mbShowDateCentury = sal_True;
mpCalendarWrapper = NULL;
mnDateFormat = 0xFFFF;
mnExtDateFormat = XTDATEF_SYSTEM_SHORT;
}
// -----------------------------------------------------------------------
DateFormatter::DateFormatter() :
maFieldDate( 0 ),
maLastDate( 0 ),
maMin( 1, 1, 1900 ),
maMax( 31, 12, 2200 ),
mbEnforceValidValue( sal_True )
{
ImplInit();
}
// -----------------------------------------------------------------------
void DateFormatter::ImplLoadRes( const ResId& rResId )
{
ResMgr* pMgr = rResId.GetResMgr();
if( pMgr )
{
sal_uLong nMask = pMgr->ReadLong();
if ( DATEFORMATTER_MIN & nMask )
{
maMin = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
}
if ( DATEFORMATTER_MAX & nMask )
{
maMax = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
}
if ( DATEFORMATTER_LONGFORMAT & nMask )
mbLongFormat = (sal_Bool)pMgr->ReadShort();
if ( DATEFORMATTER_STRICTFORMAT & nMask )
SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
if ( DATEFORMATTER_VALUE & nMask )
{
maFieldDate = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
if ( maFieldDate > maMax )
maFieldDate = maMax;
if ( maFieldDate < maMin )
maFieldDate = maMin;
maLastDate = maFieldDate;
}
}
}
// -----------------------------------------------------------------------
DateFormatter::~DateFormatter()
{
delete mpCalendarWrapper;
mpCalendarWrapper = NULL;
}
// -----------------------------------------------------------------------
void DateFormatter::SetLocale( const ::com::sun::star::lang::Locale& rLocale )
{
delete mpCalendarWrapper;
mpCalendarWrapper = NULL;
FormatterBase::SetLocale( rLocale );
}
// -----------------------------------------------------------------------
CalendarWrapper& DateFormatter::GetCalendarWrapper() const
{
if ( !mpCalendarWrapper )
{
((DateFormatter*)this)->mpCalendarWrapper = new CalendarWrapper( vcl::unohelper::GetMultiServiceFactory() );
mpCalendarWrapper->loadDefaultCalendar( GetLocale() );
}
return *mpCalendarWrapper;
}
// -----------------------------------------------------------------------
void DateFormatter::SetExtDateFormat( ExtDateFieldFormat eFormat )
{
mnExtDateFormat = eFormat;
ReformatAll();
}
// -----------------------------------------------------------------------
ExtDateFieldFormat DateFormatter::GetExtDateFormat( sal_Bool bResolveSystemFormat ) const
{
ExtDateFieldFormat eDateFormat = (ExtDateFieldFormat)mnExtDateFormat;
if ( bResolveSystemFormat && ( eDateFormat <= XTDATEF_SYSTEM_SHORT_YYYY ) )
{
sal_Bool bShowCentury = (eDateFormat == XTDATEF_SYSTEM_SHORT_YYYY);
switch ( ImplGetLocaleDataWrapper().getDateFormat() )
{
case DMY: eDateFormat = bShowCentury ? XTDATEF_SHORT_DDMMYYYY : XTDATEF_SHORT_DDMMYY;
break;
case MDY: eDateFormat = bShowCentury ? XTDATEF_SHORT_MMDDYYYY : XTDATEF_SHORT_MMDDYY;
break;
default: eDateFormat = bShowCentury ? XTDATEF_SHORT_YYYYMMDD : XTDATEF_SHORT_YYMMDD;
}
}
return eDateFormat;
}
// -----------------------------------------------------------------------
void DateFormatter::ReformatAll()
{
Reformat();
}
// -----------------------------------------------------------------------
void DateFormatter::SetMin( const Date& rNewMin )
{
maMin = rNewMin;
if ( !IsEmptyFieldValue() )
ReformatAll();
}
// -----------------------------------------------------------------------
void DateFormatter::SetMax( const Date& rNewMax )
{
maMax = rNewMax;
if ( !IsEmptyFieldValue() )
ReformatAll();
}
// -----------------------------------------------------------------------
void DateFormatter::SetLongFormat( sal_Bool bLong )
{
mbLongFormat = bLong;
// #91913# Remove LongFormat and DateShowCentury - redundant
if ( bLong )
{
SetExtDateFormat( XTDATEF_SYSTEM_LONG );
}
else
{
if( mnExtDateFormat == XTDATEF_SYSTEM_LONG )
SetExtDateFormat( XTDATEF_SYSTEM_SHORT );
}
ReformatAll();
}
// -----------------------------------------------------------------------
void DateFormatter::SetShowDateCentury( sal_Bool bShowDateCentury )
{
mbShowDateCentury = bShowDateCentury;
// #91913# Remove LongFormat and DateShowCentury - redundant
if ( bShowDateCentury )
{
switch ( GetExtDateFormat() )
{
case XTDATEF_SYSTEM_SHORT:
case XTDATEF_SYSTEM_SHORT_YY:
SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY ); break;
case XTDATEF_SHORT_DDMMYY:
SetExtDateFormat( XTDATEF_SHORT_DDMMYYYY ); break;
case XTDATEF_SHORT_MMDDYY:
SetExtDateFormat( XTDATEF_SHORT_MMDDYYYY ); break;
case XTDATEF_SHORT_YYMMDD:
SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD ); break;
case XTDATEF_SHORT_YYMMDD_DIN5008:
SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD_DIN5008 ); break;
default:
;
}
}
else
{
switch ( GetExtDateFormat() )
{
case XTDATEF_SYSTEM_SHORT:
case XTDATEF_SYSTEM_SHORT_YYYY:
SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YY ); break;
case XTDATEF_SHORT_DDMMYYYY:
SetExtDateFormat( XTDATEF_SHORT_DDMMYY ); break;
case XTDATEF_SHORT_MMDDYYYY:
SetExtDateFormat( XTDATEF_SHORT_MMDDYY ); break;
case XTDATEF_SHORT_YYYYMMDD:
SetExtDateFormat( XTDATEF_SHORT_YYMMDD ); break;
case XTDATEF_SHORT_YYYYMMDD_DIN5008:
SetExtDateFormat( XTDATEF_SHORT_YYMMDD_DIN5008 ); break;
default:
;
}
}
ReformatAll();
}
// -----------------------------------------------------------------------
void DateFormatter::SetDate( const Date& rNewDate )
{
SetUserDate( rNewDate );
maFieldDate = maLastDate;
maLastDate = GetDate();
}
// -----------------------------------------------------------------------
void DateFormatter::SetUserDate( const Date& rNewDate )
{
ImplSetUserDate( rNewDate );
}
// -----------------------------------------------------------------------
void DateFormatter::ImplSetUserDate( const Date& rNewDate, Selection* pNewSelection )
{
Date aNewDate = rNewDate;
if ( aNewDate > maMax )
aNewDate = maMax;
else if ( aNewDate < maMin )
aNewDate = maMin;
maLastDate = aNewDate;
if ( GetField() )
ImplSetText( ImplGetDateAsText( aNewDate, GetFieldSettings() ), pNewSelection );
}
// -----------------------------------------------------------------------
void DateFormatter::ImplNewFieldValue( const Date& rDate )
{
if ( GetField() )
{
Selection aSelection = GetField()->GetSelection();
aSelection.Justify();
XubString aText = GetField()->GetText();
// Wenn bis ans Ende selektiert war, soll das auch so bleiben...
if ( (xub_StrLen)aSelection.Max() == aText.Len() )
{
if ( !aSelection.Len() )
aSelection.Min() = SELECTION_MAX;
aSelection.Max() = SELECTION_MAX;
}
Date aOldLastDate = maLastDate;
ImplSetUserDate( rDate, &aSelection );
maLastDate = aOldLastDate;
// Modify am Edit wird nur bei KeyInput gesetzt...
if ( GetField()->GetText() != aText )
{
GetField()->SetModifyFlag();
GetField()->Modify();
}
}
}
// -----------------------------------------------------------------------
Date DateFormatter::GetDate() const
{
Date aDate( 0, 0, 0 );
if ( GetField() )
{
if ( ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
{
if ( aDate > maMax )
aDate = maMax;
else if ( aDate < maMin )
aDate = maMin;
}
else
{
// !!! TH-18.2.99: Wenn wir Zeit haben sollte einmal
// !!! geklaert werden, warum dieses beim Datum gegenueber
// !!! allen anderen Feldern anders behandelt wird.
// !!! Siehe dazu Bug: 52304
if ( !ImplAllowMalformedInput() )
{
if ( maLastDate.GetDate() )
aDate = maLastDate;
else if ( !IsEmptyFieldValueEnabled() )
aDate = Date();
}
else
aDate = GetInvalidDate();
}
}
return aDate;
}
// -----------------------------------------------------------------------
Date DateFormatter::GetRealDate() const
{
// !!! TH-18.2.99: Wenn wir Zeit haben sollte dieses auch einmal
// !!! fuer die Numeric-Klassen eingebaut werden.
Date aDate( 0, 0, 0 );
if ( GetField() )
{
if ( !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
if ( ImplAllowMalformedInput() )
aDate = GetInvalidDate();
}
return aDate;
}
// -----------------------------------------------------------------------
void DateFormatter::SetEmptyDate()
{
FormatterBase::SetEmptyFieldValue();
}
// -----------------------------------------------------------------------
sal_Bool DateFormatter::IsEmptyDate() const
{
sal_Bool bEmpty = FormatterBase::IsEmptyFieldValue();
if ( GetField() && MustBeReformatted() && IsEmptyFieldValueEnabled() )
{
if ( !GetField()->GetText().Len() )
{
bEmpty = sal_True;
}
else if ( !maLastDate.GetDate() )
{
Date aDate;
bEmpty = !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
}
}
return bEmpty;
}
// -----------------------------------------------------------------------
sal_Bool DateFormatter::IsDateModified() const
{
if ( ImplGetEmptyFieldValue() )
return !IsEmptyDate();
else if ( GetDate() != maFieldDate )
return sal_True;
else
return sal_False;
}
// -----------------------------------------------------------------------
void DateFormatter::Reformat()
{
if ( !GetField() )
return;
if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
return;
XubString aStr;
sal_Bool bOK = ImplDateReformat( GetField()->GetText(), aStr, GetFieldSettings() );
if( !bOK )
return;
if ( aStr.Len() )
{
ImplSetText( aStr );
ImplDateGetValue( aStr, maLastDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
}
else
{
if ( maLastDate.GetDate() )
SetDate( maLastDate );
else if ( !IsEmptyFieldValueEnabled() )
SetDate( Date() );
else
{
ImplSetText( ImplGetSVEmptyStr() );
SetEmptyFieldValueData( sal_True );
}
}
}
// -----------------------------------------------------------------------
void DateFormatter::ExpandCentury( Date& rDate )
{
ExpandCentury( rDate, utl::MiscCfg().GetYear2000() );
}
// -----------------------------------------------------------------------
void DateFormatter::ExpandCentury( Date& rDate, sal_uInt16 nTwoDigitYearStart )
{
sal_uInt16 nDateYear = rDate.GetYear();
if ( nDateYear < 100 )
{
sal_uInt16 nCentury = nTwoDigitYearStart / 100;
if ( nDateYear < (nTwoDigitYearStart % 100) )
nCentury++;
rDate.SetYear( nDateYear + (nCentury*100) );
}
}
// -----------------------------------------------------------------------
DateField::DateField( Window* pParent, WinBits nWinStyle ) :
SpinField( pParent, nWinStyle ),
maFirst( GetMin() ),
maLast( GetMax() )
{
SetField( this );
SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
Reformat();
ResetLastDate();
}
// -----------------------------------------------------------------------
DateField::DateField( Window* pParent, const ResId& rResId ) :
SpinField( WINDOW_DATEFIELD ),
maFirst( GetMin() ),
maLast( GetMax() )
{
rResId.SetRT( RSC_DATEFIELD );
WinBits nStyle = ImplInitRes( rResId );
SpinField::ImplInit( pParent, nStyle );
SetField( this );
SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
ImplLoadRes( rResId );
if ( !(nStyle & WB_HIDE ) )
Show();
ResetLastDate();
}
// -----------------------------------------------------------------------
void DateField::ImplLoadRes( const ResId& rResId )
{
SpinField::ImplLoadRes( rResId );
ResMgr* pMgr = rResId.GetResMgr();
if( pMgr )
{
DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
sal_uLong nMask = ReadLongRes();
if ( DATEFIELD_FIRST & nMask )
{
maFirst = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
}
if ( DATEFIELD_LAST & nMask )
{
maLast = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
}
}
Reformat();
}
// -----------------------------------------------------------------------
DateField::~DateField()
{
}
// -----------------------------------------------------------------------
long DateField::PreNotify( NotifyEvent& rNEvt )
{
if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
!rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
{
if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( sal_True ), ImplGetLocaleDataWrapper() ) )
return 1;
}
return SpinField::PreNotify( rNEvt );
}
// -----------------------------------------------------------------------
long DateField::Notify( NotifyEvent& rNEvt )
{
if ( rNEvt.GetType() == EVENT_GETFOCUS )
MarkToBeReformatted( sal_False );
else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
{
if ( MustBeReformatted() )
{
// !!! TH-18.2.99: Wenn wir Zeit haben sollte einmal
// !!! geklaert werden, warum dieses beim Datum gegenueber
// !!! allen anderen Feldern anders behandelt wird.
// !!! Siehe dazu Bug: 52304
sal_Bool bTextLen = GetText().Len() != 0;
if ( bTextLen || !IsEmptyFieldValueEnabled() )
{
if ( !ImplAllowMalformedInput() )
Reformat();
else
{
Date aDate( 0, 0, 0 );
if ( ImplDateGetValue( GetText(), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
// even with strict text analysis, our text is a valid date -> do a complete
// reformat
Reformat();
}
}
else if ( !bTextLen && IsEmptyFieldValueEnabled() )
{
ResetLastDate();
SetEmptyFieldValueData( sal_True );
}
}
}
return SpinField::Notify( rNEvt );
}
// -----------------------------------------------------------------------
void DateField::DataChanged( const DataChangedEvent& rDCEvt )
{
SpinField::DataChanged( rDCEvt );
if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & (SETTINGS_LOCALE|SETTINGS_MISC)) )
{
if ( IsDefaultLocale() && ( rDCEvt.GetFlags() & SETTINGS_LOCALE ) )
ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
ReformatAll();
}
}
// -----------------------------------------------------------------------
void DateField::Modify()
{
MarkToBeReformatted( sal_True );
SpinField::Modify();
}
// -----------------------------------------------------------------------
void DateField::Up()
{
ImplDateSpinArea( sal_True );
SpinField::Up();
}
// -----------------------------------------------------------------------
void DateField::Down()
{
ImplDateSpinArea( sal_False );
SpinField::Down();
}
// -----------------------------------------------------------------------
void DateField::First()
{
ImplNewFieldValue( maFirst );
SpinField::First();
}
// -----------------------------------------------------------------------
void DateField::Last()
{
ImplNewFieldValue( maLast );
SpinField::Last();
}
// -----------------------------------------------------------------------
DateBox::DateBox( Window* pParent, WinBits nWinStyle ) :
ComboBox( pParent, nWinStyle )
{
SetField( this );
SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
Reformat();
}
// -----------------------------------------------------------------------
DateBox::DateBox( Window* pParent, const ResId& rResId ) :
ComboBox( WINDOW_DATEBOX )
{
rResId.SetRT( RSC_DATEBOX );
WinBits nStyle = ImplInitRes( rResId );
ComboBox::ImplInit( pParent, nStyle );
SetField( this );
SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
ComboBox::ImplLoadRes( rResId );
ResMgr* pMgr = rResId.GetResMgr();
if( pMgr )
DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
Reformat();
if ( !( nStyle & WB_HIDE ) )
Show();
}
// -----------------------------------------------------------------------
DateBox::~DateBox()
{
}
// -----------------------------------------------------------------------
long DateBox::PreNotify( NotifyEvent& rNEvt )
{
if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
!rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
{
if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( sal_True ), ImplGetLocaleDataWrapper() ) )
return 1;
}
return ComboBox::PreNotify( rNEvt );
}
// -----------------------------------------------------------------------
void DateBox::DataChanged( const DataChangedEvent& rDCEvt )
{
ComboBox::DataChanged( rDCEvt );
if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
{
if ( IsDefaultLocale() )
ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
ReformatAll();
}
}
// -----------------------------------------------------------------------
long DateBox::Notify( NotifyEvent& rNEvt )
{
if ( rNEvt.GetType() == EVENT_GETFOCUS )
MarkToBeReformatted( sal_False );
else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
{
if ( MustBeReformatted() )
{
sal_Bool bTextLen = GetText().Len() != 0;
if ( bTextLen || !IsEmptyFieldValueEnabled() )
Reformat();
else if ( !bTextLen && IsEmptyFieldValueEnabled() )
{
ResetLastDate();
SetEmptyFieldValueData( sal_True );
}
}
}
return ComboBox::Notify( rNEvt );
}
// -----------------------------------------------------------------------
void DateBox::Modify()
{
MarkToBeReformatted( sal_True );
ComboBox::Modify();
}
// -----------------------------------------------------------------------
void DateBox::ReformatAll()
{
XubString aStr;
SetUpdateMode( sal_False );
sal_uInt16 nEntryCount = GetEntryCount();
for ( sal_uInt16 i=0; i < nEntryCount; i++ )
{
ImplDateReformat( GetEntry( i ), aStr, GetFieldSettings() );
RemoveEntry( i );
InsertEntry( aStr, i );
}
DateFormatter::Reformat();
SetUpdateMode( sal_True );
}
// -----------------------------------------------------------------------
void DateBox::InsertDate( const Date& rDate, sal_uInt16 nPos )
{
Date aDate = rDate;
if ( aDate > GetMax() )
aDate = GetMax();
else if ( aDate < GetMin() )
aDate = GetMin();
ComboBox::InsertEntry( ImplGetDateAsText( aDate, GetFieldSettings() ), nPos );
}
// -----------------------------------------------------------------------
void DateBox::RemoveDate( const Date& rDate )
{
ComboBox::RemoveEntry( ImplGetDateAsText( rDate, GetFieldSettings() ) );
}
// -----------------------------------------------------------------------
Date DateBox::GetDate( sal_uInt16 nPos ) const
{
Date aDate( 0, 0, 0 );
ImplDateGetValue( ComboBox::GetEntry( nPos ), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetSettings() );
return aDate;
}
// -----------------------------------------------------------------------
sal_uInt16 DateBox::GetDatePos( const Date& rDate ) const
{
XubString aStr;
if ( IsLongFormat() )
aStr = ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, sal_False, 1, !IsShowDateCentury() );
else
aStr = ImplGetLocaleDataWrapper().getDate( rDate );
return ComboBox::GetEntryPos( aStr );
}
// -----------------------------------------------------------------------
static sal_Bool ImplTimeProcessKeyInput( Edit*, const KeyEvent& rKEvt,
sal_Bool bStrictFormat, sal_Bool bDuration,
TimeFieldFormat eFormat,
const LocaleDataWrapper& rLocaleDataWrapper )
{
xub_Unicode cChar = rKEvt.GetCharCode();
if ( !bStrictFormat )
return sal_False;
else
{
sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
(nGroup == KEYGROUP_MISC) ||
((cChar >= '0') && (cChar <= '9')) ||
(cChar == rLocaleDataWrapper.getTimeSep()) ||
( ( rLocaleDataWrapper.getTimeAM().Search( cChar ) != STRING_NOTFOUND ) ) ||
( ( rLocaleDataWrapper.getTimePM().Search( cChar ) != STRING_NOTFOUND ) ) ||
// Accept AM/PM:
(cChar == 'a') || (cChar == 'A') || (cChar == 'm') || (cChar == 'M') || (cChar == 'p') || (cChar == 'P') ||
((eFormat == TIMEF_100TH_SEC) && (cChar == rLocaleDataWrapper.getTime100SecSep())) ||
((eFormat == TIMEF_SEC_CS) && (cChar == rLocaleDataWrapper.getTime100SecSep())) ||
(bDuration && (cChar == '-')) )
return sal_False;
else
return sal_True;
}
}
// -----------------------------------------------------------------------
static sal_Bool ImplIsOnlyDigits( const String& _rStr )
{
const sal_Unicode* _pChr = _rStr.GetBuffer();
for ( xub_StrLen i = 0; i < _rStr.Len(); ++i, ++_pChr )
{
if ( *_pChr < '0' || *_pChr > '9' )
return sal_False;
}
return sal_True;
}
// -----------------------------------------------------------------------
static sal_Bool ImplIsValidTimePortion( sal_Bool _bSkipInvalidCharacters, const String& _rStr )
{
if ( !_bSkipInvalidCharacters )
{
if ( ( _rStr.Len() > 2 ) || ( _rStr.Len() < 1 ) || !ImplIsOnlyDigits( _rStr ) )
return sal_False;
}
return sal_True;
}
// -----------------------------------------------------------------------
static sal_Bool ImplCutTimePortion( String& _rStr, xub_StrLen _nSepPos, sal_Bool _bSkipInvalidCharacters, short* _pPortion )
{
String sPortion = _rStr.Copy( 0, _nSepPos );
_rStr.Erase( 0, _nSepPos + 1 );
if ( !ImplIsValidTimePortion( _bSkipInvalidCharacters, sPortion ) )
return sal_False;
*_pPortion = (short)sPortion.ToInt32();
return sal_True;
}
// -----------------------------------------------------------------------
static sal_Bool ImplTimeGetValue( const XubString& rStr, Time& rTime,
TimeFieldFormat eFormat, sal_Bool bDuration,
const LocaleDataWrapper& rLocaleDataWrapper, sal_Bool _bSkipInvalidCharacters = sal_True )
{
XubString aStr = rStr;
short nHour = 0;
short nMinute = 0;
short nSecond = 0;
short n100Sec = 0;
Time aTime( 0, 0, 0 );
if ( !rStr.Len() )
return sal_False;
// Nach Separatoren suchen
if ( rLocaleDataWrapper.getTimeSep().Len() )
{
XubString aSepStr( RTL_CONSTASCII_USTRINGPARAM( ",.;:/" ) );
if ( !bDuration )
aSepStr.Append( '-' );
// Die obigen Zeichen durch das Separatorzeichen ersetzen
for ( xub_StrLen i = 0; i < aSepStr.Len(); i++ )
{
if ( aSepStr.GetChar( i ) == rLocaleDataWrapper.getTimeSep() )
continue;
for ( xub_StrLen j = 0; j < aStr.Len(); j++ )
{
if ( aStr.GetChar( j ) == aSepStr.GetChar( i ) )
aStr.SetChar( j, rLocaleDataWrapper.getTimeSep().GetChar(0) );
}
}
}
sal_Bool bNegative = sal_False;
xub_StrLen nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
if ( aStr.GetChar( 0 ) == '-' )
bNegative = sal_True;
if ( eFormat != TIMEF_SEC_CS )
{
if ( nSepPos == STRING_NOTFOUND )
nSepPos = aStr.Len();
if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nHour ) )
return sal_False;
nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
if ( aStr.GetChar( 0 ) == '-' )
bNegative = sal_True;
if ( nSepPos != STRING_NOTFOUND )
{
if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nMinute ) )
return sal_False;
nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
if ( aStr.GetChar( 0 ) == '-' )
bNegative = sal_True;
if ( nSepPos != STRING_NOTFOUND )
{
if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nSecond ) )
return sal_False;
if ( aStr.GetChar( 0 ) == '-' )
bNegative = sal_True;
n100Sec = (short)aStr.ToInt32();
}
else
nSecond = (short)aStr.ToInt32();
}
else
nMinute = (short)aStr.ToInt32();
}
else if ( nSepPos == STRING_NOTFOUND )
{
nSecond = (short)aStr.ToInt32();
nMinute += nSecond / 60;
nSecond %= 60;
nHour += nMinute / 60;
nMinute %= 60;
}
else
{
nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
aStr.Erase( 0, nSepPos+1 );
nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
if ( aStr.GetChar( 0 ) == '-' )
bNegative = sal_True;
if ( nSepPos != STRING_NOTFOUND )
{
nMinute = nSecond;
nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
aStr.Erase( 0, nSepPos+1 );
nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
if ( aStr.GetChar( 0 ) == '-' )
bNegative = sal_True;
if ( nSepPos != STRING_NOTFOUND )
{
nHour = nMinute;
nMinute = nSecond;
nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
aStr.Erase( 0, nSepPos+1 );
}
else
{
nHour += nMinute / 60;
nMinute %= 60;
}
}
else
{
nMinute += nSecond / 60;
nSecond %= 60;
nHour += nMinute / 60;
nMinute %= 60;
}
n100Sec = (short)aStr.ToInt32();
if ( n100Sec )
{
xub_StrLen nLen = 1; // mindestens eine Ziffer, weil sonst n100Sec==0
while ( aStr.GetChar(nLen) >= '0' && aStr.GetChar(nLen) <= '9' )
nLen++;
if ( nLen > 2 )
{
while( nLen > 3 )
{
n100Sec = n100Sec / 10;
nLen--;
}
// Rundung bei negativen Zahlen???
n100Sec = (n100Sec + 5) / 10;
}
else
{
while( nLen < 2 )
{
n100Sec = n100Sec * 10;
nLen++;
}
}
}
}
if ( (nMinute > 59) || (nSecond > 59) || (n100Sec > 100) )
return sal_False;
if ( eFormat == TIMEF_NONE )
nSecond = n100Sec = 0;
else if ( eFormat == TIMEF_SEC )
n100Sec = 0;
if ( !bDuration )
{
if ( bNegative || (nHour < 0) || (nMinute < 0) ||
(nSecond < 0) || (n100Sec < 0) )
return sal_False;
aStr.ToUpperAscii();
XubString aAM( rLocaleDataWrapper.getTimeAM() );
XubString aPM( rLocaleDataWrapper.getTimePM() );
aAM.ToUpperAscii();
aPM.ToUpperAscii();
XubString aAM2( RTL_CONSTASCII_USTRINGPARAM( "AM" ) ); // aAM is localized
XubString aPM2( RTL_CONSTASCII_USTRINGPARAM( "PM" ) ); // aPM is localized
if ( (nHour < 12) && ( ( aStr.Search( aPM ) != STRING_NOTFOUND ) || ( aStr.Search( aPM2 ) != STRING_NOTFOUND ) ) )
nHour += 12;
if ( (nHour == 12) && ( ( aStr.Search( aAM ) != STRING_NOTFOUND ) || ( aStr.Search( aAM2 ) != STRING_NOTFOUND ) ) )
nHour = 0;
aTime = Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
(sal_uInt16)n100Sec );
}
else
{
if ( bNegative || (nHour < 0) || (nMinute < 0) ||
(nSecond < 0) || (n100Sec < 0) )
{
bNegative = sal_True;
nHour = nHour < 0 ? -nHour : nHour;
nMinute = nMinute < 0 ? -nMinute : nMinute;
nSecond = nSecond < 0 ? -nSecond : nSecond;
n100Sec = n100Sec < 0 ? -n100Sec : n100Sec;
}
aTime = Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
(sal_uInt16)n100Sec );
if ( bNegative )
aTime = -aTime;
}
rTime = aTime;
return sal_True;
}
// -----------------------------------------------------------------------
sal_Bool TimeFormatter::ImplTimeReformat( const XubString& rStr, XubString& rOutStr )
{
Time aTime( 0, 0, 0 );
if ( !ImplTimeGetValue( rStr, aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ) )
return sal_True;
Time aTempTime = aTime;
if ( aTempTime > GetMax() )
aTempTime = GetMax() ;
else if ( aTempTime < GetMin() )
aTempTime = GetMin();
if ( GetErrorHdl().IsSet() && (aTime != aTempTime) )
{
maCorrectedTime = aTempTime;
if ( !GetErrorHdl().Call( this ) )
{
maCorrectedTime = Time();
return sal_False;
}
else
maCorrectedTime = Time();
}
sal_Bool bSecond = sal_False;
sal_Bool b100Sec = sal_False;
if ( meFormat != TIMEF_NONE )
bSecond = sal_True;
if ( meFormat == TIMEF_100TH_SEC )
b100Sec = sal_True;
if ( meFormat == TIMEF_SEC_CS )
{
sal_uLong n = aTempTime.GetHour() * 3600L;
n += aTempTime.GetMin() * 60L;
n += aTempTime.GetSec();
rOutStr = String::CreateFromInt32( n );
rOutStr += ImplGetLocaleDataWrapper().getTime100SecSep();
if ( aTempTime.Get100Sec() < 10 )
rOutStr += '0';
rOutStr += String::CreateFromInt32( aTempTime.Get100Sec() );
}
else if ( mbDuration )
rOutStr = ImplGetLocaleDataWrapper().getDuration( aTempTime, bSecond, b100Sec );
else
{
rOutStr = ImplGetLocaleDataWrapper().getTime( aTempTime, bSecond, b100Sec );
if ( GetTimeFormat() == HOUR_12 )
{
if ( aTempTime.GetHour() > 12 )
{
Time aT( aTempTime );
aT.SetHour( aT.GetHour() % 12 );
rOutStr = ImplGetLocaleDataWrapper().getTime( aT, bSecond, b100Sec );
}
// Don't use LocaleDataWrapper, we want AM/PM
if ( aTempTime.GetHour() < 12 )
rOutStr += String( RTL_CONSTASCII_USTRINGPARAM( "AM" ) ); // ImplGetLocaleDataWrapper().getTimeAM();
else
rOutStr += String( RTL_CONSTASCII_USTRINGPARAM( "PM" ) ); // ImplGetLocaleDataWrapper().getTimePM();
}
}
return sal_True;
}
// -----------------------------------------------------------------------
sal_Bool TimeFormatter::ImplAllowMalformedInput() const
{
return !IsEnforceValidValue();
}
// -----------------------------------------------------------------------
void TimeField::ImplTimeSpinArea( sal_Bool bUp )
{
if ( GetField() )
{
xub_StrLen nTimeArea = 0;
Time aTime( GetTime() );
XubString aText( GetText() );
Selection aSelection( GetField()->GetSelection() );
// Area suchen
if ( GetFormat() != TIMEF_SEC_CS )
{
for ( xub_StrLen i = 1, nPos = 0; i <= 4; i++ )
{
xub_StrLen nPos1 = aText.Search( ImplGetLocaleDataWrapper().getTimeSep(), nPos );
xub_StrLen nPos2 = aText.Search( ImplGetLocaleDataWrapper().getTime100SecSep(), nPos );
nPos = nPos1 < nPos2 ? nPos1 : nPos2;
if ( nPos >= (xub_StrLen)aSelection.Max() )
{
nTimeArea = i;
break;
}
else
nPos++;
}
}
else
{
xub_StrLen nPos = aText.Search( ImplGetLocaleDataWrapper().getTime100SecSep() );
if ( nPos == STRING_NOTFOUND || nPos >= (xub_StrLen)aSelection.Max() )
nTimeArea = 3;
else
nTimeArea = 4;
}
if ( nTimeArea )
{
Time aAddTime( 0, 0, 0 );
if ( nTimeArea == 1 )
aAddTime = Time( 1, 0 );
else if ( nTimeArea == 2 )
aAddTime = Time( 0, 1 );
else if ( nTimeArea == 3 )
aAddTime = Time( 0, 0, 1 );
else if ( nTimeArea == 4 )
aAddTime = Time( 0, 0, 0, 1 );
if ( !bUp )
aAddTime = -aAddTime;
aTime += aAddTime;
if ( !IsDuration() )
{
Time aAbsMaxTime( 23, 59, 59, 99 );
if ( aTime > aAbsMaxTime )
aTime = aAbsMaxTime;
Time aAbsMinTime( 0, 0 );
if ( aTime < aAbsMinTime )
aTime = aAbsMinTime;
}
ImplNewFieldValue( aTime );
}
}
}
// -----------------------------------------------------------------------
void TimeFormatter::ImplInit()
{
meFormat = TIMEF_NONE;
mbDuration = sal_False;
mnTimeFormat = HOUR_24; // Should become a ExtTimeFieldFormat in next implementation, merge with mbDuration and meFormat
}
// -----------------------------------------------------------------------
TimeFormatter::TimeFormatter() :
maLastTime( 0, 0 ),
maMin( 0, 0 ),
maMax( 23, 59, 59, 99 ),
mbEnforceValidValue( sal_True ),
maFieldTime( 0, 0 )
{
ImplInit();
}
// -----------------------------------------------------------------------
void TimeFormatter::ImplLoadRes( const ResId& rResId )
{
ResMgr* pMgr = rResId.GetResMgr();
if( pMgr )
{
sal_uLong nMask = pMgr->ReadLong();
if ( TIMEFORMATTER_MIN & nMask )
{
SetMin( Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
}
if ( TIMEFORMATTER_MAX & nMask )
{
SetMax( Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
}
if ( TIMEFORMATTER_TIMEFIELDFORMAT & nMask )
meFormat = (TimeFieldFormat)pMgr->ReadLong();
if ( TIMEFORMATTER_DURATION & nMask )
mbDuration = (sal_Bool)pMgr->ReadShort();
if ( TIMEFORMATTER_STRICTFORMAT & nMask )
SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
if ( TIMEFORMATTER_VALUE & nMask )
{
maFieldTime = Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
if ( maFieldTime > GetMax() )
maFieldTime = GetMax();
if ( maFieldTime < GetMin() )
maFieldTime = GetMin();
maLastTime = maFieldTime;
pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
}
}
}
// -----------------------------------------------------------------------
TimeFormatter::~TimeFormatter()
{
}
// -----------------------------------------------------------------------
void TimeFormatter::ReformatAll()
{
Reformat();
}
// -----------------------------------------------------------------------
void TimeFormatter::SetMin( const Time& rNewMin )
{
maMin = rNewMin;
if ( !IsEmptyFieldValue() )
ReformatAll();
}
// -----------------------------------------------------------------------
void TimeFormatter::SetMax( const Time& rNewMax )
{
maMax = rNewMax;
if ( !IsEmptyFieldValue() )
ReformatAll();
}
// -----------------------------------------------------------------------
void TimeFormatter::SetTimeFormat( TimeFormatter::TimeFormat eNewFormat )
{
mnTimeFormat = sal::static_int_cast<sal_uInt16>(eNewFormat);
}
// -----------------------------------------------------------------------
TimeFormatter::TimeFormat TimeFormatter::GetTimeFormat() const
{
return (TimeFormat)mnTimeFormat;
}
// -----------------------------------------------------------------------
void TimeFormatter::SetFormat( TimeFieldFormat eNewFormat )
{
meFormat = eNewFormat;
ReformatAll();
}
// -----------------------------------------------------------------------
void TimeFormatter::SetDuration( sal_Bool bNewDuration )
{
mbDuration = bNewDuration;
ReformatAll();
}
// -----------------------------------------------------------------------
void TimeFormatter::SetTime( const Time& rNewTime )
{
SetUserTime( rNewTime );
maFieldTime = maLastTime;
SetEmptyFieldValueData( sal_False );
}
// -----------------------------------------------------------------------
void TimeFormatter::ImplNewFieldValue( const Time& rTime )
{
if ( GetField() )
{
Selection aSelection = GetField()->GetSelection();
aSelection.Justify();
XubString aText = GetField()->GetText();
// Wenn bis ans Ende selektiert war, soll das auch so bleiben...
if ( (xub_StrLen)aSelection.Max() == aText.Len() )
{
if ( !aSelection.Len() )
aSelection.Min() = SELECTION_MAX;
aSelection.Max() = SELECTION_MAX;
}
Time aOldLastTime = maLastTime;
ImplSetUserTime( rTime, &aSelection );
maLastTime = aOldLastTime;
// Modify am Edit wird nur bei KeyInput gesetzt...
if ( GetField()->GetText() != aText )
{
GetField()->SetModifyFlag();
GetField()->Modify();
}
}
}
// -----------------------------------------------------------------------
void TimeFormatter::ImplSetUserTime( const Time& rNewTime, Selection* pNewSelection )
{
Time aNewTime = rNewTime;
if ( aNewTime > GetMax() )
aNewTime = GetMax();
else if ( aNewTime < GetMin() )
aNewTime = GetMin();
maLastTime = aNewTime;
if ( GetField() )
{
XubString aStr;
sal_Bool bSec = sal_False;
sal_Bool b100Sec = sal_False;
if ( meFormat != TIMEF_NONE )
bSec = sal_True;
if ( meFormat == TIMEF_100TH_SEC || meFormat == TIMEF_SEC_CS )
b100Sec = sal_True;
if ( meFormat == TIMEF_SEC_CS )
{
sal_uLong n = aNewTime.GetHour() * 3600L;
n += aNewTime.GetMin() * 60L;
n += aNewTime.GetSec();
aStr = String::CreateFromInt32( n );
aStr += ImplGetLocaleDataWrapper().getTime100SecSep();
if ( aNewTime.Get100Sec() < 10 )
aStr += '0';
aStr += String::CreateFromInt32( aNewTime.Get100Sec() );
}
else if ( mbDuration )
{
aStr = ImplGetLocaleDataWrapper().getDuration( aNewTime, bSec, b100Sec );
}
else
{
aStr = ImplGetLocaleDataWrapper().getTime( aNewTime, bSec, b100Sec );
if ( GetTimeFormat() == HOUR_12 )
{
if ( aNewTime.GetHour() > 12 )
{
Time aT( aNewTime );
aT.SetHour( aT.GetHour() % 12 );
aStr = ImplGetLocaleDataWrapper().getTime( aT, bSec, b100Sec );
}
// Don't use LocaleDataWrapper, we want AM/PM
if ( aNewTime.GetHour() < 12 )
aStr += String( RTL_CONSTASCII_USTRINGPARAM( "AM" ) ); // ImplGetLocaleDataWrapper().getTimeAM();
else
aStr += String( RTL_CONSTASCII_USTRINGPARAM( "PM" ) ); // ImplGetLocaleDataWrapper().getTimePM();
}
}
ImplSetText( aStr, pNewSelection );
}
}
// -----------------------------------------------------------------------
void TimeFormatter::SetUserTime( const Time& rNewTime )
{
ImplSetUserTime( rNewTime );
}
// -----------------------------------------------------------------------
Time TimeFormatter::GetTime() const
{
Time aTime( 0, 0, 0 );
if ( GetField() )
{
sal_Bool bAllowMailformed = ImplAllowMalformedInput();
if ( ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
{
if ( aTime > GetMax() )
aTime = GetMax();
else if ( aTime < GetMin() )
aTime = GetMin();
}
else
{
if ( bAllowMailformed )
aTime = GetInvalidTime();
else
aTime = maLastTime;
}
}
return aTime;
}
// -----------------------------------------------------------------------
Time TimeFormatter::GetRealTime() const
{
Time aTime( 0, 0, 0 );
if ( GetField() )
{
sal_Bool bAllowMailformed = ImplAllowMalformedInput();
if ( !ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
if ( bAllowMailformed )
aTime = GetInvalidTime();
}
return aTime;
}
// -----------------------------------------------------------------------
sal_Bool TimeFormatter::IsTimeModified() const
{
if ( ImplGetEmptyFieldValue() )
return !IsEmptyTime();
else if ( GetTime() != maFieldTime )
return sal_True;
else
return sal_False;
}
// -----------------------------------------------------------------------
void TimeFormatter::Reformat()
{
if ( !GetField() )
return;
if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
return;
XubString aStr;
sal_Bool bOK = ImplTimeReformat( GetField()->GetText(), aStr );
if ( !bOK )
return;
if ( aStr.Len() )
{
ImplSetText( aStr );
ImplTimeGetValue( aStr, maLastTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
}
else
SetTime( maLastTime );
}
// -----------------------------------------------------------------------
TimeField::TimeField( Window* pParent, WinBits nWinStyle ) :
SpinField( pParent, nWinStyle ),
maFirst( GetMin() ),
maLast( GetMax() )
{
SetField( this );
SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, sal_False, sal_False ) );
Reformat();
}
// -----------------------------------------------------------------------
TimeField::TimeField( Window* pParent, const ResId& rResId ) :
SpinField( WINDOW_TIMEFIELD ),
maFirst( GetMin() ),
maLast( GetMax() )
{
rResId.SetRT( RSC_TIMEFIELD );
WinBits nStyle = ImplInitRes( rResId );
SpinField::ImplInit( pParent, nStyle );
SetField( this );
SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, sal_False, sal_False ) );
ImplLoadRes( rResId );
if ( !(nStyle & WB_HIDE ) )
Show();
}
// -----------------------------------------------------------------------
void TimeField::ImplLoadRes( const ResId& rResId )
{
SpinField::ImplLoadRes( rResId );
ResMgr* pMgr = rResId.GetResMgr();
if( pMgr )
{
TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
sal_uLong nMask = ReadLongRes();
if ( TIMEFIELD_FIRST & nMask )
{
maFirst = Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
}
if ( TIMEFIELD_LAST & nMask )
{
maLast = Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
}
}
Reformat();
}
// -----------------------------------------------------------------------
TimeField::~TimeField()
{
}
// -----------------------------------------------------------------------
long TimeField::PreNotify( NotifyEvent& rNEvt )
{
if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
{
if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
return 1;
}
return SpinField::PreNotify( rNEvt );
}
// -----------------------------------------------------------------------
long TimeField::Notify( NotifyEvent& rNEvt )
{
if ( rNEvt.GetType() == EVENT_GETFOCUS )
MarkToBeReformatted( sal_False );
else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
{
if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
{
if ( !ImplAllowMalformedInput() )
Reformat();
else
{
Time aTime( 0, 0, 0 );
if ( ImplTimeGetValue( GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), sal_False ) )
// even with strict text analysis, our text is a valid time -> do a complete
// reformat
Reformat();
}
}
}
return SpinField::Notify( rNEvt );
}
// -----------------------------------------------------------------------
void TimeField::DataChanged( const DataChangedEvent& rDCEvt )
{
SpinField::DataChanged( rDCEvt );
if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
{
if ( IsDefaultLocale() )
ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
ReformatAll();
}
}
// -----------------------------------------------------------------------
void TimeField::Modify()
{
MarkToBeReformatted( sal_True );
SpinField::Modify();
}
// -----------------------------------------------------------------------
void TimeField::Up()
{
ImplTimeSpinArea( sal_True );
SpinField::Up();
}
// -----------------------------------------------------------------------
void TimeField::Down()
{
ImplTimeSpinArea( sal_False );
SpinField::Down();
}
// -----------------------------------------------------------------------
void TimeField::First()
{
ImplNewFieldValue( maFirst );
SpinField::First();
}
// -----------------------------------------------------------------------
void TimeField::Last()
{
ImplNewFieldValue( maLast );
SpinField::Last();
}
// -----------------------------------------------------------------------
void TimeField::SetExtFormat( ExtTimeFieldFormat eFormat )
{
switch ( eFormat )
{
case EXTTIMEF_24H_SHORT:
{
SetTimeFormat( HOUR_24 );
SetDuration( sal_False );
SetFormat( TIMEF_NONE );
}
break;
case EXTTIMEF_24H_LONG:
{
SetTimeFormat( HOUR_24 );
SetDuration( sal_False );
SetFormat( TIMEF_SEC );
}
break;
case EXTTIMEF_12H_SHORT:
{
SetTimeFormat( HOUR_12 );
SetDuration( sal_False );
SetFormat( TIMEF_NONE );
}
break;
case EXTTIMEF_12H_LONG:
{
SetTimeFormat( HOUR_12 );
SetDuration( sal_False );
SetFormat( TIMEF_SEC );
}
break;
case EXTTIMEF_DURATION_SHORT:
{
SetDuration( sal_True );
SetFormat( TIMEF_NONE );
}
break;
case EXTTIMEF_DURATION_LONG:
{
SetDuration( sal_True );
SetFormat( TIMEF_SEC );
}
break;
default: DBG_ERROR( "ExtTimeFieldFormat unknown!" );
}
if ( GetField() && GetField()->GetText().Len() )
SetUserTime( GetTime() );
ReformatAll();
}
// -----------------------------------------------------------------------
TimeBox::TimeBox( Window* pParent, WinBits nWinStyle ) :
ComboBox( pParent, nWinStyle )
{
SetField( this );
SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, sal_False, sal_False ) );
Reformat();
}
// -----------------------------------------------------------------------
TimeBox::TimeBox( Window* pParent, const ResId& rResId ) :
ComboBox( WINDOW_TIMEBOX )
{
rResId.SetRT( RSC_TIMEBOX );
WinBits nStyle = ImplInitRes( rResId );
ComboBox::ImplInit( pParent, nStyle );
SetField( this );
SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, sal_False, sal_False ) );
ComboBox::ImplLoadRes( rResId );
ResMgr* pMgr = rResId.GetResMgr();
if( pMgr )
TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
Reformat();
if ( !(nStyle & WB_HIDE) )
Show();
}
// -----------------------------------------------------------------------
TimeBox::~TimeBox()
{
}
// -----------------------------------------------------------------------
long TimeBox::PreNotify( NotifyEvent& rNEvt )
{
if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
{
if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
return 1;
}
return ComboBox::PreNotify( rNEvt );
}
// -----------------------------------------------------------------------
long TimeBox::Notify( NotifyEvent& rNEvt )
{
if ( rNEvt.GetType() == EVENT_GETFOCUS )
MarkToBeReformatted( sal_False );
else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
{
if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
Reformat();
}
return ComboBox::Notify( rNEvt );
}
// -----------------------------------------------------------------------
void TimeBox::DataChanged( const DataChangedEvent& rDCEvt )
{
ComboBox::DataChanged( rDCEvt );
if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
{
if ( IsDefaultLocale() )
ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
ReformatAll();
}
}
// -----------------------------------------------------------------------
void TimeBox::Modify()
{
MarkToBeReformatted( sal_True );
ComboBox::Modify();
}
// -----------------------------------------------------------------------
void TimeBox::ReformatAll()
{
XubString aStr;
SetUpdateMode( sal_False );
sal_uInt16 nEntryCount = GetEntryCount();
for ( sal_uInt16 i=0; i < nEntryCount; i++ )
{
ImplTimeReformat( GetEntry( i ), aStr );
RemoveEntry( i );
InsertEntry( aStr, i );
}
TimeFormatter::Reformat();
SetUpdateMode( sal_True );
}
// -----------------------------------------------------------------------
void TimeBox::InsertTime( const Time& rTime, sal_uInt16 nPos )
{
Time aTime = rTime;
if ( aTime > GetMax() )
aTime = GetMax();
else if ( aTime < GetMin() )
aTime = GetMin();
sal_Bool bSec = sal_False;
sal_Bool b100Sec = sal_False;
if ( GetFormat() == TIMEF_SEC )
bSec = sal_True;
if ( GetFormat() == TIMEF_100TH_SEC || GetFormat() == TIMEF_SEC_CS )
bSec = b100Sec = sal_True;
ComboBox::InsertEntry( ImplGetLocaleDataWrapper().getTime( aTime, bSec, b100Sec ), nPos );
}
// -----------------------------------------------------------------------
void TimeBox::RemoveTime( const Time& rTime )
{
sal_Bool bSec = sal_False;
sal_Bool b100Sec = sal_False;
if ( GetFormat() == TIMEF_SEC )
bSec = sal_True;
if ( GetFormat() == TIMEF_100TH_SEC || TIMEF_SEC_CS )
bSec = b100Sec = sal_True;
ComboBox::RemoveEntry( ImplGetLocaleDataWrapper().getTime( rTime, bSec, b100Sec ) );
}
// -----------------------------------------------------------------------
Time TimeBox::GetTime( sal_uInt16 nPos ) const
{
Time aTime( 0, 0, 0 );
ImplTimeGetValue( ComboBox::GetEntry( nPos ), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
return aTime;
}
// -----------------------------------------------------------------------
sal_uInt16 TimeBox::GetTimePos( const Time& rTime ) const
{
sal_Bool bSec = sal_False;
sal_Bool b100Sec = sal_False;
if ( GetFormat() == TIMEF_SEC )
bSec = sal_True;
if ( GetFormat() == TIMEF_100TH_SEC || TIMEF_SEC_CS )
bSec = b100Sec = sal_True;
return ComboBox::GetEntryPos( ImplGetLocaleDataWrapper().getTime( rTime, bSec, b100Sec ) );
}