diff options
Diffstat (limited to 'vcl/source/control/field2.cxx')
-rw-r--r-- | vcl/source/control/field2.cxx | 3469 |
1 files changed, 3469 insertions, 0 deletions
diff --git a/vcl/source/control/field2.cxx b/vcl/source/control/field2.cxx new file mode 100644 index 000000000000..8ae2ecff41b9 --- /dev/null +++ b/vcl/source/control/field2.cxx @@ -0,0 +1,3469 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" +#include <tools/debug.hxx> + +#ifndef _SV_RC_H +#include <tools/rc.h> +#endif +#include <vcl/svdata.hxx> +#ifndef _SV_EVENT_HXX +#include <vcl/field.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/sound.hxx> +#include <vcl/event.hxx> +#include <vcl/field.hxx> +#include <i18npool/mslangid.hxx> + +#include <vcl/unohelp.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, 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 USHORT ImplGetNum( const sal_Unicode*& rpBuf, BOOL& rbError ) +{ + if ( !*rpBuf ) + { + rbError = TRUE; + return 0; + } + + USHORT 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 FALSE; + } + + if ( (cEditMask == EDITMASK_ALPHA) || (cEditMask == EDITMASK_UPPERALPHA) ) + { + if( !CharClass::isLetterType( nType ) ) + return FALSE; + } + else if ( cEditMask == EDITMASK_NUM ) + { + if( !CharClass::isNumericType( nType ) ) + return FALSE; + } + else if ( (cEditMask == EDITMASK_ALPHANUM) || (cEditMask == EDITMASK_UPPERALPHANUM) ) + { + if( !CharClass::isLetterNumericType( nType ) ) + return FALSE; + } + else if ( (cEditMask == EDITMASK_ALLCHAR) || (cEditMask == EDITMASK_UPPERALLCHAR) ) + { + if ( cChar < 32 ) + return FALSE; + } + else if ( cEditMask == EDITMASK_NUMSPACE ) + { + if ( !CharClass::isNumericType( nType ) && ( cChar != ' ' ) ) + return FALSE; + } + else + return FALSE; + + return 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 TRUE; + else if ( ((c1 == '.') || (c1 == ',')) && + ((c2 == '.') || (c2 == ',')) ) + return TRUE; + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +static XubString ImplPatternReformat( const XubString& rStr, + const ByteString& rEditMask, + const XubString& rLiteralMask, + USHORT 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, + USHORT nFormatFlags, BOOL bSameMask, + USHORT nCursorPos, USHORT& 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, + USHORT nFormatFlags, 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(); + 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, + USHORT nFormatFlags, 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 BOOL ImplPatternProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt, + const ByteString& rEditMask, + const XubString& rLiteralMask, + BOOL bStrictFormat, + USHORT nFormatFlags, + BOOL bSameMask, + BOOL& rbInKeyInput ) +{ + if ( !rEditMask.Len() || !bStrictFormat ) + return FALSE; + + Selection aOldSel = pEdit->GetSelection(); + KeyCode aCode = rKEvt.GetKeyCode(); + xub_Unicode cChar = rKEvt.GetCharCode(); + USHORT nKeyCode = aCode.GetCode(); + 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 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 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 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 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 = TRUE; + pEdit->SetText( aStr, Selection( nNewPos ) ); + pEdit->SetModifyFlag(); + pEdit->Modify(); + rbInKeyInput = FALSE; + } + else + pEdit->SetSelection( Selection( nNewPos ) ); + + return 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 TRUE; + } + } + } + + if ( rKEvt.GetKeyCode().IsMod2() || (cChar < 32) || (cChar == 127) ) + return 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 TRUE; + } + } + break; + } + nTempPos++; + } + } + + cChar = 0; + } + } + else + cChar = 0; + if ( cChar ) + { + XubString aStr = pEdit->GetText(); + BOOL bError = 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 = 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 = TRUE; + Selection aNewSel( ImplPatternRightPos( aStr, rEditMask, nFormatFlags, bSameMask, nNewPos ) ); + pEdit->SetText( aStr, aNewSel ); + pEdit->SetModifyFlag(); + pEdit->Modify(); + rbInKeyInput = FALSE; + } + } + else + Sound::Beep(); + + return TRUE; +} + +// ----------------------------------------------------------------------- + +void PatternFormatter::ImplSetMask( const ByteString& rEditMask, + const XubString& rLiteralMask ) +{ + maEditMask = rEditMask; + maLiteralMask = rLiteralMask; + mbSameMask = 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 = FALSE; + break; + } + if ( i < rLiteralMask.Len() ) + { + if ( rLiteralMask.GetChar( i ) != ' ' ) + { + mbSameMask = FALSE; + break; + } + } + if ( !c ) + c = cTemp; + if ( cTemp != c ) + { + mbSameMask = FALSE; + break; + } + } + i++; + } +} + +// ----------------------------------------------------------------------- + +PatternFormatter::PatternFormatter() +{ + mnFormatFlags = 0; + mbSameMask = TRUE; + mbInPattKeyInput = FALSE; +} + +// ----------------------------------------------------------------------- + +void PatternFormatter::ImplLoadRes( const ResId& rResId ) +{ + ByteString aEditMask; + XubString aLiteralMask; + ResMgr* pMgr = rResId.GetResMgr(); + if( pMgr ) + { + ULONG nMask = pMgr->ReadLong(); + + if ( PATTERNFORMATTER_STRICTFORMAT & nMask ) + SetStrictFormat( (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( 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( 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( 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( 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( 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( TRUE ); + } + + ComboBox::Modify(); +} + +// ----------------------------------------------------------------------- + +void PatternBox::ReformatAll() +{ + XubString aStr; + SetUpdateMode( FALSE ); + USHORT nEntryCount = GetEntryCount(); + for ( USHORT i=0; i < nEntryCount; i++ ) + { + aStr = ImplPatternReformat( GetEntry( i ), GetEditMask(), GetLiteralMask(), GetFormatFlags() ); + RemoveEntry( i ); + InsertEntry( aStr, i ); + } + PatternFormatter::Reformat(); + SetUpdateMode( TRUE ); +} + +// ----------------------------------------------------------------------- + +void PatternBox::InsertString( const XubString& rStr, USHORT 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( USHORT nPos ) const +{ + return ImplPatternReformat( ComboBox::GetEntry( nPos ), GetEditMask(), GetLiteralMask(), GetFormatFlags() ); +} + +// ----------------------------------------------------------------------- + +USHORT 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 USHORT 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 (USHORT)aNumStr.ToInt32(); +} + +// ----------------------------------------------------------------------- + +static BOOL ImplCutMonthName( XubString& rStr, const XubString& _rLookupMonthName ) +{ + USHORT nPos = rStr.Search( _rLookupMonthName ); + if ( nPos != STRING_NOTFOUND ) + { + rStr.Erase( 0, nPos + _rLookupMonthName.Len() ); + return TRUE; + } + return FALSE; +} + +// ----------------------------------------------------------------------- + +static USHORT ImplCutMonthFromString( XubString& rStr, const CalendarWrapper& rCalendarWrapper ) +{ + // search for a month' name + for ( USHORT 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 BOOL ImplDateProcessKeyInput( Edit*, const KeyEvent& rKEvt, ExtDateFieldFormat eFormat, + const LocaleDataWrapper& rLocaleDataWrapper ) +{ + xub_Unicode cChar = rKEvt.GetCharCode(); + USHORT 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 FALSE; + else + return TRUE; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplDateGetValue( const XubString& rStr, Date& rDate, ExtDateFieldFormat eDateFormat, + const LocaleDataWrapper& rLocaleDataWrapper, const CalendarWrapper& rCalendarWrapper, + const AllSettings& ) +{ + USHORT nDay = 0; + USHORT nMonth = 0; + USHORT nYear = 0; + BOOL bYear = TRUE; + BOOL bError = 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 ); + USHORT nSepPos = aStr.Search( aDateSep ); + if ( nSepPos == STRING_NOTFOUND ) + return FALSE; + nSepPos = aStr.Search( aDateSep, nSepPos+1 ); + if ( ( nSepPos == STRING_NOTFOUND ) || ( nSepPos == (aStr.Len()-1) ) ) + { + bYear = 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 FALSE; + + Date aNewDate( nDay, nMonth, nYear ); + DateFormatter::ExpandCentury( aNewDate, utl::MiscCfg().GetYear2000() ); + if ( aNewDate.IsValid() ) + { + rDate = aNewDate; + return TRUE; + } + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL DateFormatter::ImplDateReformat( const XubString& rStr, XubString& rOutStr, const AllSettings& rSettings ) +{ + Date aDate( 0, 0, 0 ); + if ( !ImplDateGetValue( rStr, aDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) ) + return 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 FALSE; + } + else + maCorrectedDate = Date(); + } + + rOutStr = ImplGetDateAsText( aTempDate, rSettings ); + + return TRUE; +} + +// ----------------------------------------------------------------------- + +XubString DateFormatter::ImplGetDateAsText( const Date& rDate, + const AllSettings& ) const +{ + BOOL bShowCentury = 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 = TRUE; + } + break; + default: + { + bShowCentury = FALSE; + } + } + + if ( !bShowCentury ) + { + // Check if I have to use force showing the century + USHORT nTwoDigitYearStart = utl::MiscCfg().GetYear2000(); + USHORT nYear = rDate.GetYear(); + + // Wenn Jahr nicht im 2stelligen Grenzbereich liegt, + if ( (nYear < nTwoDigitYearStart) || (nYear >= nTwoDigitYearStart+100) ) + bShowCentury = TRUE; + } + + sal_Unicode aBuf[128]; + sal_Unicode* pBuf = aBuf; + + String aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), GetExtDateFormat( TRUE ) ); + USHORT nDay = rDate.GetDay(); + USHORT nMonth = rDate.GetMonth(); + USHORT nYear = rDate.GetYear(); + USHORT nYearLen = bShowCentury ? 4 : 2; + + if ( !bShowCentury ) + nYear %= 100; + + switch ( GetExtDateFormat( TRUE ) ) + { + case XTDATEF_SYSTEM_LONG: + { + return ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, 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)(ULONG)(pBuf-aBuf) ); +} + +// ----------------------------------------------------------------------- + +static void ImplDateIncrementDay( Date& rDate, 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, BOOL bUp ) +{ + DateFormatter::ExpandCentury( rDate ); + + USHORT nMonth = rDate.GetMonth(); + USHORT 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 ); + } + } + + USHORT nDaysInMonth = rDate.GetDaysInMonth(); + if ( rDate.GetDay() > nDaysInMonth ) + rDate.SetDay( nDaysInMonth ); +} + +// ----------------------------------------------------------------------- + +static void ImplDateIncrementYear( Date& rDate, BOOL bUp ) +{ + DateFormatter::ExpandCentury( rDate ); + + USHORT nYear = rDate.GetYear(); + if ( bUp ) + { + if ( nYear < 9999 ) + rDate.SetYear( nYear + 1 ); + } + else + { + if ( nYear > 0 ) + rDate.SetYear( nYear - 1 ); + } +} + +// ----------------------------------------------------------------------- +BOOL DateFormatter::ImplAllowMalformedInput() const +{ + return !IsEnforceValidValue(); +} + +// ----------------------------------------------------------------------- + +void DateField::ImplDateSpinArea( 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( 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 >= (USHORT)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 = FALSE; + mbShowDateCentury = TRUE; + mpCalendarWrapper = NULL; + mnDateFormat = 0xFFFF; + mnExtDateFormat = XTDATEF_SYSTEM_SHORT; +} + +// ----------------------------------------------------------------------- + +DateFormatter::DateFormatter() : + maFieldDate( 0 ), + maLastDate( 0 ), + maMin( 1, 1, 1900 ), + maMax( 31, 12, 2200 ), + mbEnforceValidValue( TRUE ) +{ + ImplInit(); +} + +// ----------------------------------------------------------------------- + +void DateFormatter::ImplLoadRes( const ResId& rResId ) +{ + ResMgr* pMgr = rResId.GetResMgr(); + if( pMgr ) + { + 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 = (BOOL)pMgr->ReadShort(); + + if ( DATEFORMATTER_STRICTFORMAT & nMask ) + SetStrictFormat( (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( BOOL bResolveSystemFormat ) const +{ + ExtDateFieldFormat eDateFormat = (ExtDateFieldFormat)mnExtDateFormat; + + if ( bResolveSystemFormat && ( eDateFormat <= XTDATEF_SYSTEM_SHORT_YYYY ) ) + { + 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( 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( 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(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(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) ) + if ( ImplAllowMalformedInput() ) + aDate = GetInvalidDate(); + } + + return aDate; +} + +// ----------------------------------------------------------------------- + +void DateFormatter::SetEmptyDate() +{ + FormatterBase::SetEmptyFieldValue(); +} + +// ----------------------------------------------------------------------- + +BOOL DateFormatter::IsEmptyDate() const +{ + BOOL bEmpty = FormatterBase::IsEmptyFieldValue(); + + if ( GetField() && MustBeReformatted() && IsEmptyFieldValueEnabled() ) + { + if ( !GetField()->GetText().Len() ) + { + bEmpty = TRUE; + } + else if ( !maLastDate.GetDate() ) + { + Date aDate; + bEmpty = !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ); + } + } + return bEmpty; +} + +// ----------------------------------------------------------------------- + +BOOL DateFormatter::IsDateModified() const +{ + if ( ImplGetEmptyFieldValue() ) + return !IsEmptyDate(); + else if ( GetDate() != maFieldDate ) + return TRUE; + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +void DateFormatter::Reformat() +{ + if ( !GetField() ) + return; + + if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() ) + return; + + XubString aStr; + BOOL bOK = ImplDateReformat( GetField()->GetText(), aStr, GetFieldSettings() ); + if( !bOK ) + return; + + if ( aStr.Len() ) + { + ImplSetText( aStr ); + ImplDateGetValue( aStr, maLastDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ); + } + else + { + if ( maLastDate.GetDate() ) + SetDate( maLastDate ); + else if ( !IsEmptyFieldValueEnabled() ) + SetDate( Date() ); + else + { + ImplSetText( ImplGetSVEmptyStr() ); + SetEmptyFieldValueData( TRUE ); + } + } +} + +// ----------------------------------------------------------------------- + +void DateFormatter::ExpandCentury( Date& rDate ) +{ + ExpandCentury( rDate, utl::MiscCfg().GetYear2000() ); +} + +// ----------------------------------------------------------------------- + +void DateFormatter::ExpandCentury( Date& rDate, USHORT nTwoDigitYearStart ) +{ + USHORT nDateYear = rDate.GetYear(); + if ( nDateYear < 100 ) + { + USHORT 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 ) ); + + 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( TRUE ), ImplGetLocaleDataWrapper() ) ) + return 1; + } + + return SpinField::PreNotify( rNEvt ); +} + +// ----------------------------------------------------------------------- + +long DateField::Notify( NotifyEvent& rNEvt ) +{ + if ( rNEvt.GetType() == EVENT_GETFOCUS ) + MarkToBeReformatted( 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 + + BOOL bTextLen = GetText().Len() != 0; + if ( bTextLen || !IsEmptyFieldValueEnabled() ) + { + if ( !ImplAllowMalformedInput() ) + Reformat(); + else + { + Date aDate( 0, 0, 0 ); + if ( ImplDateGetValue( GetText(), aDate, GetExtDateFormat(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( 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( TRUE ); + SpinField::Modify(); +} + +// ----------------------------------------------------------------------- + +void DateField::Up() +{ + ImplDateSpinArea( TRUE ); + SpinField::Up(); +} + +// ----------------------------------------------------------------------- + +void DateField::Down() +{ + ImplDateSpinArea( 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( 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( FALSE ); + else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) + { + if ( MustBeReformatted() ) + { + BOOL bTextLen = GetText().Len() != 0; + if ( bTextLen || !IsEmptyFieldValueEnabled() ) + Reformat(); + else if ( !bTextLen && IsEmptyFieldValueEnabled() ) + { + ResetLastDate(); + SetEmptyFieldValueData( TRUE ); + } + } + } + + return ComboBox::Notify( rNEvt ); +} + +// ----------------------------------------------------------------------- + +void DateBox::Modify() +{ + MarkToBeReformatted( TRUE ); + ComboBox::Modify(); +} + +// ----------------------------------------------------------------------- + +void DateBox::ReformatAll() +{ + XubString aStr; + SetUpdateMode( FALSE ); + USHORT nEntryCount = GetEntryCount(); + for ( USHORT i=0; i < nEntryCount; i++ ) + { + ImplDateReformat( GetEntry( i ), aStr, GetFieldSettings() ); + RemoveEntry( i ); + InsertEntry( aStr, i ); + } + DateFormatter::Reformat(); + SetUpdateMode( TRUE ); +} + +// ----------------------------------------------------------------------- + +void DateBox::InsertDate( const Date& rDate, USHORT 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( USHORT nPos ) const +{ + Date aDate( 0, 0, 0 ); + ImplDateGetValue( ComboBox::GetEntry( nPos ), aDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetSettings() ); + return aDate; +} + +// ----------------------------------------------------------------------- + +USHORT DateBox::GetDatePos( const Date& rDate ) const +{ + XubString aStr; + if ( IsLongFormat() ) + aStr = ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, FALSE, 1, !IsShowDateCentury() ); + else + aStr = ImplGetLocaleDataWrapper().getDate( rDate ); + return ComboBox::GetEntryPos( aStr ); +} + +// ----------------------------------------------------------------------- + +static BOOL ImplTimeProcessKeyInput( Edit*, const KeyEvent& rKEvt, + BOOL bStrictFormat, BOOL bDuration, + TimeFieldFormat eFormat, + const LocaleDataWrapper& rLocaleDataWrapper ) +{ + xub_Unicode cChar = rKEvt.GetCharCode(); + + if ( !bStrictFormat ) + return FALSE; + else + { + USHORT 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 FALSE; + else + return TRUE; + } +} + +// ----------------------------------------------------------------------- + +static 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 FALSE; + } + return TRUE; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplIsValidTimePortion( BOOL _bSkipInvalidCharacters, const String& _rStr ) +{ + if ( !_bSkipInvalidCharacters ) + { + if ( ( _rStr.Len() > 2 ) || ( _rStr.Len() < 1 ) || !ImplIsOnlyDigits( _rStr ) ) + return FALSE; + } + return TRUE; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplCutTimePortion( String& _rStr, xub_StrLen _nSepPos, BOOL _bSkipInvalidCharacters, short* _pPortion ) +{ + String sPortion = _rStr.Copy( 0, _nSepPos ); + _rStr.Erase( 0, _nSepPos + 1 ); + + if ( !ImplIsValidTimePortion( _bSkipInvalidCharacters, sPortion ) ) + return FALSE; + *_pPortion = (short)sPortion.ToInt32(); + return TRUE; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplTimeGetValue( const XubString& rStr, Time& rTime, + TimeFieldFormat eFormat, BOOL bDuration, + const LocaleDataWrapper& rLocaleDataWrapper, BOOL _bSkipInvalidCharacters = 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 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) ); + } + } + } + + BOOL bNegative = FALSE; + xub_StrLen nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() ); + if ( aStr.GetChar( 0 ) == '-' ) + bNegative = TRUE; + if ( eFormat != TIMEF_SEC_CS ) + { + if ( nSepPos == STRING_NOTFOUND ) + nSepPos = aStr.Len(); + if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nHour ) ) + return FALSE; + + nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() ); + if ( aStr.GetChar( 0 ) == '-' ) + bNegative = TRUE; + if ( nSepPos != STRING_NOTFOUND ) + { + if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nMinute ) ) + return FALSE; + + nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() ); + if ( aStr.GetChar( 0 ) == '-' ) + bNegative = TRUE; + if ( nSepPos != STRING_NOTFOUND ) + { + if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nSecond ) ) + return FALSE; + if ( aStr.GetChar( 0 ) == '-' ) + bNegative = 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 = 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 = 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 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 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( (USHORT)nHour, (USHORT)nMinute, (USHORT)nSecond, + (USHORT)n100Sec ); + } + else + { + if ( bNegative || (nHour < 0) || (nMinute < 0) || + (nSecond < 0) || (n100Sec < 0) ) + { + bNegative = TRUE; + nHour = nHour < 0 ? -nHour : nHour; + nMinute = nMinute < 0 ? -nMinute : nMinute; + nSecond = nSecond < 0 ? -nSecond : nSecond; + n100Sec = n100Sec < 0 ? -n100Sec : n100Sec; + } + + aTime = Time( (USHORT)nHour, (USHORT)nMinute, (USHORT)nSecond, + (USHORT)n100Sec ); + if ( bNegative ) + aTime = -aTime; + } + + rTime = aTime; + + return TRUE; +} + +// ----------------------------------------------------------------------- + +BOOL TimeFormatter::ImplTimeReformat( const XubString& rStr, XubString& rOutStr ) +{ + Time aTime( 0, 0, 0 ); + if ( !ImplTimeGetValue( rStr, aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ) ) + return 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 FALSE; + } + else + maCorrectedTime = Time(); + } + + BOOL bSecond = FALSE; + BOOL b100Sec = FALSE; + if ( meFormat != TIMEF_NONE ) + bSecond = TRUE; + if ( meFormat == TIMEF_100TH_SEC ) + b100Sec = TRUE; + + if ( meFormat == TIMEF_SEC_CS ) + { + 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 TRUE; +} + +// ----------------------------------------------------------------------- +BOOL TimeFormatter::ImplAllowMalformedInput() const +{ + return !IsEnforceValidValue(); +} + +// ----------------------------------------------------------------------- + +void TimeField::ImplTimeSpinArea( 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 = 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( TRUE ), + maFieldTime( 0, 0 ) +{ + ImplInit(); +} + +// ----------------------------------------------------------------------- + +void TimeFormatter::ImplLoadRes( const ResId& rResId ) +{ + ResMgr* pMgr = rResId.GetResMgr(); + if( pMgr ) + { + 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 = (BOOL)pMgr->ReadShort(); + + if ( TIMEFORMATTER_STRICTFORMAT & nMask ) + SetStrictFormat( (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<USHORT>(eNewFormat); +} + +// ----------------------------------------------------------------------- + +TimeFormatter::TimeFormat TimeFormatter::GetTimeFormat() const +{ + return (TimeFormat)mnTimeFormat; +} + +// ----------------------------------------------------------------------- + +void TimeFormatter::SetFormat( TimeFieldFormat eNewFormat ) +{ + meFormat = eNewFormat; + ReformatAll(); +} + +// ----------------------------------------------------------------------- + +void TimeFormatter::SetDuration( BOOL bNewDuration ) +{ + mbDuration = bNewDuration; + ReformatAll(); +} + +// ----------------------------------------------------------------------- + +void TimeFormatter::SetTime( const Time& rNewTime ) +{ + SetUserTime( rNewTime ); + maFieldTime = maLastTime; + SetEmptyFieldValueData( 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; + BOOL bSec = FALSE; + BOOL b100Sec = FALSE; + if ( meFormat != TIMEF_NONE ) + bSec = TRUE; + if ( meFormat == TIMEF_100TH_SEC || meFormat == TIMEF_SEC_CS ) + b100Sec = TRUE; + if ( meFormat == TIMEF_SEC_CS ) + { + 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() ) + { + 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() ) + { + BOOL bAllowMailformed = ImplAllowMalformedInput(); + if ( !ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) ) + if ( bAllowMailformed ) + aTime = GetInvalidTime(); + } + + return aTime; +} + +// ----------------------------------------------------------------------- + +BOOL TimeFormatter::IsTimeModified() const +{ + if ( ImplGetEmptyFieldValue() ) + return !IsEmptyTime(); + else if ( GetTime() != maFieldTime ) + return TRUE; + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +void TimeFormatter::Reformat() +{ + if ( !GetField() ) + return; + + if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() ) + return; + + XubString aStr; + 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, FALSE, 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, FALSE, 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 ) ); + + 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( 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(), 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( TRUE ); + SpinField::Modify(); +} + +// ----------------------------------------------------------------------- + +void TimeField::Up() +{ + ImplTimeSpinArea( TRUE ); + SpinField::Up(); +} + +// ----------------------------------------------------------------------- + +void TimeField::Down() +{ + ImplTimeSpinArea( 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( FALSE ); + SetFormat( TIMEF_NONE ); + } + break; + case EXTTIMEF_24H_LONG: + { + SetTimeFormat( HOUR_24 ); + SetDuration( FALSE ); + SetFormat( TIMEF_SEC ); + } + break; + case EXTTIMEF_12H_SHORT: + { + SetTimeFormat( HOUR_12 ); + SetDuration( FALSE ); + SetFormat( TIMEF_NONE ); + } + break; + case EXTTIMEF_12H_LONG: + { + SetTimeFormat( HOUR_12 ); + SetDuration( FALSE ); + SetFormat( TIMEF_SEC ); + } + break; + case EXTTIMEF_DURATION_SHORT: + { + SetDuration( TRUE ); + SetFormat( TIMEF_NONE ); + } + break; + case EXTTIMEF_DURATION_LONG: + { + SetDuration( 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, FALSE, 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, FALSE, 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( 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( TRUE ); + ComboBox::Modify(); +} + +// ----------------------------------------------------------------------- + +void TimeBox::ReformatAll() +{ + XubString aStr; + SetUpdateMode( FALSE ); + USHORT nEntryCount = GetEntryCount(); + for ( USHORT i=0; i < nEntryCount; i++ ) + { + ImplTimeReformat( GetEntry( i ), aStr ); + RemoveEntry( i ); + InsertEntry( aStr, i ); + } + TimeFormatter::Reformat(); + SetUpdateMode( TRUE ); +} + +// ----------------------------------------------------------------------- + +void TimeBox::InsertTime( const Time& rTime, USHORT nPos ) +{ + Time aTime = rTime; + if ( aTime > GetMax() ) + aTime = GetMax(); + else if ( aTime < GetMin() ) + aTime = GetMin(); + + BOOL bSec = FALSE; + BOOL b100Sec = FALSE; + if ( GetFormat() == TIMEF_SEC ) + bSec = TRUE; + if ( GetFormat() == TIMEF_100TH_SEC || GetFormat() == TIMEF_SEC_CS ) + bSec = b100Sec = TRUE; + ComboBox::InsertEntry( ImplGetLocaleDataWrapper().getTime( aTime, bSec, b100Sec ), nPos ); +} + +// ----------------------------------------------------------------------- + +void TimeBox::RemoveTime( const Time& rTime ) +{ + BOOL bSec = FALSE; + BOOL b100Sec = FALSE; + if ( GetFormat() == TIMEF_SEC ) + bSec = TRUE; + if ( GetFormat() == TIMEF_100TH_SEC || TIMEF_SEC_CS ) + bSec = b100Sec = TRUE; + ComboBox::RemoveEntry( ImplGetLocaleDataWrapper().getTime( rTime, bSec, b100Sec ) ); +} + +// ----------------------------------------------------------------------- + +Time TimeBox::GetTime( USHORT nPos ) const +{ + Time aTime( 0, 0, 0 ); + ImplTimeGetValue( ComboBox::GetEntry( nPos ), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ); + return aTime; +} + +// ----------------------------------------------------------------------- + +USHORT TimeBox::GetTimePos( const Time& rTime ) const +{ + BOOL bSec = FALSE; + BOOL b100Sec = FALSE; + if ( GetFormat() == TIMEF_SEC ) + bSec = TRUE; + if ( GetFormat() == TIMEF_100TH_SEC || TIMEF_SEC_CS ) + bSec = b100Sec = TRUE; + return ComboBox::GetEntryPos( ImplGetLocaleDataWrapper().getTime( rTime, bSec, b100Sec ) ); +} |