summaryrefslogtreecommitdiff
path: root/vcl/source/control/field2.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/control/field2.cxx')
-rw-r--r--vcl/source/control/field2.cxx3469
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 ) );
+}