update dev300-m58
[ooovba.git] / vcl / source / control / field2.cxx
blobb69a1b910128ac5fda61616402bad74566548cbe
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: field2.cxx,v $
10 * $Revision: 1.27 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/debug.hxx>
35 #ifndef _SV_RC_H
36 #include <tools/rc.h>
37 #endif
38 #include <vcl/svdata.hxx>
39 #ifndef _SV_EVENT_HXX
40 #include <vcl/field.hxx>
41 #endif
42 #include <vcl/svapp.hxx>
43 #include <vcl/sound.hxx>
44 #include <vcl/event.hxx>
45 #include <vcl/field.hxx>
46 #include <i18npool/mslangid.hxx>
48 #include <vcl/unohelp.hxx>
50 #include <com/sun/star/lang/Locale.hpp>
51 #include <com/sun/star/i18n/XCharacterClassification.hpp>
52 #include <com/sun/star/i18n/KCharacterType.hpp>
55 #include <unotools/localedatawrapper.hxx>
56 #include <unotools/calendarwrapper.hxx>
57 #include <unotools/charclass.hxx>
59 using namespace ::com::sun::star;
61 // =======================================================================
63 #define EDITMASK_LITERAL 'L'
64 #define EDITMASK_ALPHA 'a'
65 #define EDITMASK_UPPERALPHA 'A'
66 #define EDITMASK_ALPHANUM 'c'
67 #define EDITMASK_UPPERALPHANUM 'C'
68 #define EDITMASK_NUM 'N'
69 #define EDITMASK_NUMSPACE 'n'
70 #define EDITMASK_ALLCHAR 'x'
71 #define EDITMASK_UPPERALLCHAR 'X'
73 uno::Reference< i18n::XCharacterClassification > ImplGetCharClass()
75 static uno::Reference< i18n::XCharacterClassification > xCharClass;
76 if ( !xCharClass.is() )
77 xCharClass = vcl::unohelper::CreateCharacterClassification();
79 return xCharClass;
82 // -----------------------------------------------------------------------
84 static sal_Unicode* ImplAddString( sal_Unicode* pBuf, const String& rStr )
86 if ( rStr.Len() == 1 )
87 *pBuf++ = rStr.GetChar(0);
88 else if ( rStr.Len() == 0 )
90 else
92 memcpy( pBuf, rStr.GetBuffer(), rStr.Len() * sizeof(sal_Unicode) );
93 pBuf += rStr.Len();
95 return pBuf;
98 // -----------------------------------------------------------------------
100 static sal_Unicode* ImplAddNum( sal_Unicode* pBuf, ULONG nNumber, int nMinLen )
102 // fill temp buffer with digits
103 sal_Unicode aTempBuf[30];
104 sal_Unicode* pTempBuf = aTempBuf;
107 *pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
108 pTempBuf++;
109 nNumber /= 10;
110 if ( nMinLen )
111 nMinLen--;
113 while ( nNumber );
115 // fill with zeros up to the minimal length
116 while ( nMinLen > 0 )
118 *pBuf = '0';
119 pBuf++;
120 nMinLen--;
123 // copy temp buffer to real buffer
126 pTempBuf--;
127 *pBuf = *pTempBuf;
128 pBuf++;
130 while ( pTempBuf != aTempBuf );
132 return pBuf;
135 // -----------------------------------------------------------------------
137 static USHORT ImplGetNum( const sal_Unicode*& rpBuf, BOOL& rbError )
139 if ( !*rpBuf )
141 rbError = TRUE;
142 return 0;
145 USHORT nNumber = 0;
146 while( ( *rpBuf >= '0' ) && ( *rpBuf <= '9' ) )
148 nNumber *= 10;
149 nNumber += *rpBuf - '0';
150 rpBuf++;
153 return nNumber;
156 // -----------------------------------------------------------------------
158 static void ImplSkipDelimiters( const sal_Unicode*& rpBuf )
160 while( ( *rpBuf == ',' ) || ( *rpBuf == '.' ) || ( *rpBuf == ';' ) ||
161 ( *rpBuf == ':' ) || ( *rpBuf == '-' ) || ( *rpBuf == '/' ) )
163 rpBuf++;
167 // -----------------------------------------------------------------------
169 static int ImplIsPatternChar( xub_Unicode cChar, sal_Char cEditMask )
171 sal_Int32 nType = 0;
175 String aCharStr( cChar );
176 nType = ImplGetCharClass()->getStringType( aCharStr, 0, aCharStr.Len(), Application::GetSettings().GetLocale() );
178 catch ( ::com::sun::star::uno::Exception& )
180 DBG_ERRORFILE( "ImplIsPatternChar: Exception caught!" );
181 return FALSE;
184 if ( (cEditMask == EDITMASK_ALPHA) || (cEditMask == EDITMASK_UPPERALPHA) )
186 if( !CharClass::isLetterType( nType ) )
187 return FALSE;
189 else if ( cEditMask == EDITMASK_NUM )
191 if( !CharClass::isNumericType( nType ) )
192 return FALSE;
194 else if ( (cEditMask == EDITMASK_ALPHANUM) || (cEditMask == EDITMASK_UPPERALPHANUM) )
196 if( !CharClass::isLetterNumericType( nType ) )
197 return FALSE;
199 else if ( (cEditMask == EDITMASK_ALLCHAR) || (cEditMask == EDITMASK_UPPERALLCHAR) )
201 if ( cChar < 32 )
202 return FALSE;
204 else if ( cEditMask == EDITMASK_NUMSPACE )
206 if ( !CharClass::isNumericType( nType ) && ( cChar != ' ' ) )
207 return FALSE;
209 else
210 return FALSE;
212 return TRUE;
215 // -----------------------------------------------------------------------
217 static xub_Unicode ImplPatternChar( xub_Unicode cChar, sal_Char cEditMask )
219 if ( ImplIsPatternChar( cChar, cEditMask ) )
221 if ( (cEditMask == EDITMASK_UPPERALPHA) ||
222 (cEditMask == EDITMASK_UPPERALPHANUM) ||
223 ( cEditMask == EDITMASK_UPPERALLCHAR ) )
225 cChar = ImplGetCharClass()->toUpper( String(cChar),0,1,Application::GetSettings().GetLocale() )[0];
227 return cChar;
229 else
230 return 0;
233 // -----------------------------------------------------------------------
235 static int ImplKommaPointCharEqual( xub_Unicode c1, xub_Unicode c2 )
237 if ( c1 == c2 )
238 return TRUE;
239 else if ( ((c1 == '.') || (c1 == ',')) &&
240 ((c2 == '.') || (c2 == ',')) )
241 return TRUE;
242 else
243 return FALSE;
246 // -----------------------------------------------------------------------
248 static XubString ImplPatternReformat( const XubString& rStr,
249 const ByteString& rEditMask,
250 const XubString& rLiteralMask,
251 USHORT nFormatFlags )
253 if ( !rEditMask.Len() )
254 return rStr;
256 XubString aStr = rStr;
257 XubString aOutStr = rLiteralMask;
258 xub_Unicode cTempChar;
259 xub_Unicode cChar;
260 xub_Unicode cLiteral;
261 sal_Char cMask;
262 xub_StrLen nStrIndex = 0;
263 xub_StrLen i = 0;
264 xub_StrLen n;
266 while ( i < rEditMask.Len() )
268 if ( nStrIndex >= aStr.Len() )
269 break;
271 cChar = aStr.GetChar(nStrIndex);
272 cLiteral = rLiteralMask.GetChar(i);
273 cMask = rEditMask.GetChar(i);
275 // Aktuelle Position ein Literal
276 if ( cMask == EDITMASK_LITERAL )
278 // Wenn es das Literal-Zeichen ist, uebernehmen, ansonsten
279 // ignorieren, da es das naechste gueltige Zeichen vom String
280 // sein kann
281 if ( ImplKommaPointCharEqual( cChar, cLiteral ) )
282 nStrIndex++;
283 else
285 // Ansonsten testen wir, ob es ein ungueltiges Zeichen ist.
286 // Dies ist dann der Fall, wenn es nicht in das Muster
287 // des naechsten nicht Literal-Zeichens passt
288 n = i+1;
289 while ( n < rEditMask.Len() )
291 if ( rEditMask.GetChar(n) != EDITMASK_LITERAL )
293 if ( !ImplIsPatternChar( cChar, rEditMask.GetChar(n) ) )
294 nStrIndex++;
295 break;
298 n++;
302 else
304 // Gueltiges Zeichen an der Stelle
305 cTempChar = ImplPatternChar( cChar, cMask );
306 if ( cTempChar )
308 // dann Zeichen uebernehmen
309 aOutStr.SetChar( i, cTempChar );
310 nStrIndex++;
312 else
314 // Wenn es das Literalzeichen ist, uebernehmen
315 if ( cLiteral == cChar )
316 nStrIndex++;
317 else
319 // Wenn das ungueltige Zeichen das naechste Literalzeichen
320 // sein kann, dann springen wir bis dahin vor, ansonten
321 // das Zeichen ignorieren
322 // Nur machen, wenn leere Literale erlaubt sind
323 if ( nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS )
325 n = i;
326 while ( n < rEditMask.Len() )
328 if ( rEditMask.GetChar( n ) == EDITMASK_LITERAL )
330 if ( ImplKommaPointCharEqual( cChar, rLiteralMask.GetChar( n ) ) )
331 i = n+1;
333 break;
336 n++;
340 nStrIndex++;
341 continue;
346 i++;
349 return aOutStr;
352 // -----------------------------------------------------------------------
354 static void ImplPatternMaxPos( const XubString rStr, const ByteString& rEditMask,
355 USHORT nFormatFlags, BOOL bSameMask,
356 USHORT nCursorPos, USHORT& rPos )
359 // Letzte Position darf nicht groesser als der enthaltene String sein
360 xub_StrLen nMaxPos = rStr.Len();
362 // Wenn keine leeren Literale erlaubt sind, auch Leerzeichen
363 // am Ende ignorieren
364 if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
366 while ( nMaxPos )
368 if ( (rEditMask.GetChar(nMaxPos-1) != EDITMASK_LITERAL) &&
369 (rStr.GetChar(nMaxPos-1) != ' ') )
370 break;
371 nMaxPos--;
374 // Wenn wir vor einem Literal stehen, dann solange weitersuchen,
375 // bis erste Stelle nach Literal
376 xub_StrLen nTempPos = nMaxPos;
377 while ( nTempPos < rEditMask.Len() )
379 if ( rEditMask.GetChar(nTempPos) != EDITMASK_LITERAL )
381 nMaxPos = nTempPos;
382 break;
384 nTempPos++;
388 if ( rPos > nMaxPos )
389 rPos = nMaxPos;
390 // Zeichen sollte nicht nach links wandern
391 if ( rPos < nCursorPos )
392 rPos = nCursorPos;
395 // -----------------------------------------------------------------------
397 static void ImplPatternProcessStrictModify( Edit* pEdit,
398 const ByteString& rEditMask,
399 const XubString& rLiteralMask,
400 USHORT nFormatFlags, BOOL bSameMask )
402 XubString aText = pEdit->GetText();
404 // Leerzeichen am Anfang entfernen
405 if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
407 xub_StrLen i = 0;
408 xub_StrLen nMaxLen = aText.Len();
409 while ( i < nMaxLen )
411 if ( (rEditMask.GetChar( i ) != EDITMASK_LITERAL) &&
412 (aText.GetChar( i ) != ' ') )
413 break;
415 i++;
417 // Alle Literalzeichen beibehalten
418 while ( i && (rEditMask.GetChar( i ) == EDITMASK_LITERAL) )
419 i--;
420 aText.Erase( 0, i );
423 XubString aNewText = ImplPatternReformat( aText, rEditMask, rLiteralMask, nFormatFlags );
424 if ( aNewText != aText )
426 // Selection so anpassen, das diese wenn sie vorher am Ende
427 // stand, immer noch am Ende steht
428 Selection aSel = pEdit->GetSelection();
429 ULONG nMaxSel = Max( aSel.Min(), aSel.Max() );
430 if ( nMaxSel >= aText.Len() )
432 xub_StrLen nMaxPos = aNewText.Len();
433 ImplPatternMaxPos( aNewText, rEditMask, nFormatFlags, bSameMask, (xub_StrLen)nMaxSel, nMaxPos );
434 if ( aSel.Min() == aSel.Max() )
436 aSel.Min() = nMaxPos;
437 aSel.Max() = aSel.Min();
439 else if ( aSel.Min() > aSel.Max() )
440 aSel.Min() = nMaxPos;
441 else
442 aSel.Max() = nMaxPos;
444 pEdit->SetText( aNewText, aSel );
448 // -----------------------------------------------------------------------
450 static xub_StrLen ImplPatternLeftPos( const ByteString& rEditMask, xub_StrLen nCursorPos )
452 // Vorheriges Zeichen suchen, was kein Literal ist
453 xub_StrLen nNewPos = nCursorPos;
454 xub_StrLen nTempPos = nNewPos;
455 while ( nTempPos )
457 if ( rEditMask.GetChar(nTempPos-1) != EDITMASK_LITERAL )
459 nNewPos = nTempPos-1;
460 break;
462 nTempPos--;
464 return nNewPos;
467 // -----------------------------------------------------------------------
469 static xub_StrLen ImplPatternRightPos( const XubString& rStr, const ByteString& rEditMask,
470 USHORT nFormatFlags, BOOL bSameMask,
471 xub_StrLen nCursorPos )
473 // Naechstes Zeichen suchen, was kein Literal ist
474 xub_StrLen nNewPos = nCursorPos;
475 xub_StrLen nTempPos = nNewPos;
476 while ( nTempPos < rEditMask.Len() )
478 if ( rEditMask.GetChar(nTempPos+1) != EDITMASK_LITERAL )
480 nNewPos = nTempPos+1;
481 break;
483 nTempPos++;
485 ImplPatternMaxPos( rStr, rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
486 return nNewPos;
489 // -----------------------------------------------------------------------
491 static BOOL ImplPatternProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
492 const ByteString& rEditMask,
493 const XubString& rLiteralMask,
494 BOOL bStrictFormat,
495 USHORT nFormatFlags,
496 BOOL bSameMask,
497 BOOL& rbInKeyInput )
499 if ( !rEditMask.Len() || !bStrictFormat )
500 return FALSE;
502 Selection aOldSel = pEdit->GetSelection();
503 KeyCode aCode = rKEvt.GetKeyCode();
504 xub_Unicode cChar = rKEvt.GetCharCode();
505 USHORT nKeyCode = aCode.GetCode();
506 BOOL bShift = aCode.IsShift();
507 xub_StrLen nCursorPos = (xub_StrLen)aOldSel.Max();
508 xub_StrLen nNewPos;
509 xub_StrLen nTempPos;
511 if ( nKeyCode && !aCode.IsMod1() && !aCode.IsMod2() )
513 if ( nKeyCode == KEY_LEFT )
515 Selection aSel( ImplPatternLeftPos( rEditMask, nCursorPos ) );
516 if ( bShift )
517 aSel.Min() = aOldSel.Min();
518 pEdit->SetSelection( aSel );
519 return TRUE;
521 else if ( nKeyCode == KEY_RIGHT )
523 // Hier nehmen wir Selectionsanfang als minimum, da falls durch
524 // Focus alles selektiert ist, ist eine kleine Position schon
525 // erlaubt.
526 Selection aSel( aOldSel );
527 aSel.Justify();
528 nCursorPos = (xub_StrLen)aSel.Min();
529 aSel.Max() = ImplPatternRightPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos );
530 if ( bShift )
531 aSel.Min() = aOldSel.Min();
532 else
533 aSel.Min() = aSel.Max();
534 pEdit->SetSelection( aSel );
535 return TRUE;
537 else if ( nKeyCode == KEY_HOME )
539 // Home ist Position des ersten nicht literalen Zeichens
540 nNewPos = 0;
541 while ( (nNewPos < rEditMask.Len()) &&
542 (rEditMask.GetChar(nNewPos) == EDITMASK_LITERAL) )
543 nNewPos++;
544 // Home sollte nicht nach rechts wandern
545 if ( nCursorPos < nNewPos )
546 nNewPos = nCursorPos;
547 Selection aSel( nNewPos );
548 if ( bShift )
549 aSel.Min() = aOldSel.Min();
550 pEdit->SetSelection( aSel );
551 return TRUE;
553 else if ( nKeyCode == KEY_END )
555 // End ist die Position des letzten nicht literalen Zeichens
556 nNewPos = rEditMask.Len();
557 while ( nNewPos &&
558 (rEditMask.GetChar(nNewPos-1) == EDITMASK_LITERAL) )
559 nNewPos--;
560 // Hier nehmen wir Selectionsanfang als minimum, da falls durch
561 // Focus alles selektiert ist, ist eine kleine Position schon
562 // erlaubt.
563 Selection aSel( aOldSel );
564 aSel.Justify();
565 nCursorPos = (xub_StrLen)aSel.Min();
566 ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
567 aSel.Max() = nNewPos;
568 if ( bShift )
569 aSel.Min() = aOldSel.Min();
570 else
571 aSel.Min() = aSel.Max();
572 pEdit->SetSelection( aSel );
573 return TRUE;
575 else if ( (nKeyCode == KEY_BACKSPACE) || (nKeyCode == KEY_DELETE) )
577 XubString aStr( pEdit->GetText() );
578 XubString aOldStr = aStr;
579 Selection aSel = aOldSel;
581 aSel.Justify();
582 nNewPos = (xub_StrLen)aSel.Min();
584 // Wenn Selection, dann diese Loeschen
585 if ( aSel.Len() )
587 if ( bSameMask )
588 aStr.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
589 else
591 XubString aRep = rLiteralMask.Copy( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
592 aStr.Replace( (xub_StrLen)aSel.Min(), aRep.Len(), aRep );
595 else
597 if ( nKeyCode == KEY_BACKSPACE )
599 nTempPos = nNewPos;
600 nNewPos = ImplPatternLeftPos( rEditMask, nTempPos );
602 else
603 nTempPos = ImplPatternRightPos( aStr, rEditMask, nFormatFlags, bSameMask, nNewPos );
605 if ( nNewPos != nTempPos )
607 if ( bSameMask )
609 if ( rEditMask.GetChar( nNewPos ) != EDITMASK_LITERAL )
610 aStr.Erase( nNewPos, 1 );
612 else
614 XubString aTempStr = rLiteralMask.Copy( nNewPos, 1 );
615 aStr.Replace( nNewPos, aTempStr.Len(), aTempStr );
620 if ( aOldStr != aStr )
622 if ( bSameMask )
623 aStr = ImplPatternReformat( aStr, rEditMask, rLiteralMask, nFormatFlags );
624 rbInKeyInput = TRUE;
625 pEdit->SetText( aStr, Selection( nNewPos ) );
626 pEdit->SetModifyFlag();
627 pEdit->Modify();
628 rbInKeyInput = FALSE;
630 else
631 pEdit->SetSelection( Selection( nNewPos ) );
633 return TRUE;
635 else if ( nKeyCode == KEY_INSERT )
637 // InsertModus kann man beim PatternField nur einstellen,
638 // wenn Maske an jeder Eingabeposition die gleiche
639 // ist
640 if ( !bSameMask )
642 Sound::Beep();
643 return TRUE;
648 if ( rKEvt.GetKeyCode().IsMod2() || (cChar < 32) || (cChar == 127) )
649 return FALSE;
651 Selection aSel = aOldSel;
652 aSel.Justify();
653 nNewPos = (xub_StrLen)aSel.Min();
655 if ( nNewPos < rEditMask.Len() )
657 xub_Unicode cPattChar = ImplPatternChar( cChar, rEditMask.GetChar(nNewPos) );
658 if ( cPattChar )
659 cChar = cPattChar;
660 else
662 // Wenn kein gueltiges Zeichen, dann testen wir, ob der
663 // Anwender zum naechsten Literal springen wollte. Dies machen
664 // wir nur, wenn er hinter einem Zeichen steht, damit
665 // eingebene Literale die automatisch uebersprungenen wurden
666 // nicht dazu fuehren, das der Anwender dann da steht, wo
667 // er nicht stehen wollte.
668 if ( nNewPos &&
669 (rEditMask.GetChar(nNewPos-1) != EDITMASK_LITERAL) &&
670 !aSel.Len() )
672 // Naechstes Zeichen suchen, was kein Literal ist
673 nTempPos = nNewPos;
674 while ( nTempPos < rEditMask.Len() )
676 if ( rEditMask.GetChar(nTempPos) == EDITMASK_LITERAL )
678 // Gilt nur, wenn ein Literalzeichen vorhanden
679 if ( (rEditMask.GetChar(nTempPos+1) != EDITMASK_LITERAL ) &&
680 ImplKommaPointCharEqual( cChar, rLiteralMask.GetChar(nTempPos) ) )
682 nTempPos++;
683 ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nNewPos, nTempPos );
684 if ( nTempPos > nNewPos )
686 pEdit->SetSelection( Selection( nTempPos ) );
687 return TRUE;
690 break;
692 nTempPos++;
696 cChar = 0;
699 else
700 cChar = 0;
701 if ( cChar )
703 XubString aStr = pEdit->GetText();
704 BOOL bError = FALSE;
705 if ( bSameMask && pEdit->IsInsertMode() )
707 // Text um Spacezeichen und Literale am Ende kuerzen, bis zur
708 // aktuellen Position
709 xub_StrLen n = aStr.Len();
710 while ( n && (n > nNewPos) )
712 if ( (aStr.GetChar( n-1 ) != ' ') &&
713 ((n > rEditMask.Len()) || (rEditMask.GetChar(n-1) != EDITMASK_LITERAL)) )
714 break;
716 n--;
718 aStr.Erase( n );
720 if ( aSel.Len() )
721 aStr.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
723 if ( aStr.Len() < rEditMask.Len() )
725 // String evtl. noch bis Cursor-Position erweitern
726 if ( aStr.Len() < nNewPos )
727 aStr += rLiteralMask.Copy( aStr.Len(), nNewPos-aStr.Len() );
728 if ( nNewPos < aStr.Len() )
729 aStr.Insert( cChar, nNewPos );
730 else if ( nNewPos < rEditMask.Len() )
731 aStr += cChar;
732 aStr = ImplPatternReformat( aStr, rEditMask, rLiteralMask, nFormatFlags );
734 else
735 bError = TRUE;
737 else
739 if ( aSel.Len() )
741 // Selection loeschen
742 XubString aRep = rLiteralMask.Copy( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
743 aStr.Replace( (xub_StrLen)aSel.Min(), aRep.Len(), aRep );
746 if ( nNewPos < aStr.Len() )
747 aStr.SetChar( nNewPos, cChar );
748 else if ( nNewPos < rEditMask.Len() )
749 aStr += cChar;
752 if ( bError )
753 Sound::Beep();
754 else
756 rbInKeyInput = TRUE;
757 Selection aNewSel( ImplPatternRightPos( aStr, rEditMask, nFormatFlags, bSameMask, nNewPos ) );
758 pEdit->SetText( aStr, aNewSel );
759 pEdit->SetModifyFlag();
760 pEdit->Modify();
761 rbInKeyInput = FALSE;
764 else
765 Sound::Beep();
767 return TRUE;
770 // -----------------------------------------------------------------------
772 void PatternFormatter::ImplSetMask( const ByteString& rEditMask,
773 const XubString& rLiteralMask )
775 maEditMask = rEditMask;
776 maLiteralMask = rLiteralMask;
777 mbSameMask = TRUE;
779 if ( maEditMask.Len() != maLiteralMask.Len() )
781 if ( maEditMask.Len() < maLiteralMask.Len() )
782 maLiteralMask.Erase( maEditMask.Len() );
783 else
784 maLiteralMask.Expand( maEditMask.Len(), ' ' );
787 // StrictModus erlaubt nur Input-Mode, wenn als Maske nur
788 // gleiche Zeichen zugelassen werden und als Vorgabe nur
789 // Spacezeichen vorgegeben werden, die durch die Maske
790 // nicht zugelassen sind
791 xub_StrLen i = 0;
792 sal_Char c = 0;
793 while ( i < rEditMask.Len() )
795 sal_Char cTemp = rEditMask.GetChar( i );
796 if ( cTemp != EDITMASK_LITERAL )
798 if ( (cTemp == EDITMASK_ALLCHAR) ||
799 (cTemp == EDITMASK_UPPERALLCHAR) ||
800 (cTemp == EDITMASK_NUMSPACE) )
802 mbSameMask = FALSE;
803 break;
805 if ( i < rLiteralMask.Len() )
807 if ( rLiteralMask.GetChar( i ) != ' ' )
809 mbSameMask = FALSE;
810 break;
813 if ( !c )
814 c = cTemp;
815 if ( cTemp != c )
817 mbSameMask = FALSE;
818 break;
821 i++;
825 // -----------------------------------------------------------------------
827 PatternFormatter::PatternFormatter()
829 mnFormatFlags = 0;
830 mbSameMask = TRUE;
831 mbInPattKeyInput = FALSE;
834 // -----------------------------------------------------------------------
836 void PatternFormatter::ImplLoadRes( const ResId& rResId )
838 ByteString aEditMask;
839 XubString aLiteralMask;
840 ResMgr* pMgr = rResId.GetResMgr();
841 if( pMgr )
843 ULONG nMask = pMgr->ReadLong();
845 if ( PATTERNFORMATTER_STRICTFORMAT & nMask )
846 SetStrictFormat( (BOOL)pMgr->ReadShort() );
848 if ( PATTERNFORMATTER_EDITMASK & nMask )
849 aEditMask = ByteString( pMgr->ReadString(), RTL_TEXTENCODING_ASCII_US );
851 if ( PATTERNFORMATTER_LITTERALMASK & nMask )
852 aLiteralMask = pMgr->ReadString();
854 if ( (PATTERNFORMATTER_EDITMASK | PATTERNFORMATTER_LITTERALMASK) & nMask )
855 ImplSetMask( aEditMask, aLiteralMask );
859 // -----------------------------------------------------------------------
861 PatternFormatter::~PatternFormatter()
865 // -----------------------------------------------------------------------
867 void PatternFormatter::SetMask( const ByteString& rEditMask,
868 const XubString& rLiteralMask )
870 ImplSetMask( rEditMask, rLiteralMask );
871 ReformatAll();
874 // -----------------------------------------------------------------------
876 void PatternFormatter::SetString( const XubString& rStr )
878 maFieldString = rStr;
879 if ( GetField() )
881 GetField()->SetText( rStr );
882 MarkToBeReformatted( FALSE );
886 // -----------------------------------------------------------------------
888 XubString PatternFormatter::GetString() const
890 if ( !GetField() )
891 return ImplGetSVEmptyStr();
892 else
893 return ImplPatternReformat( GetField()->GetText(), maEditMask, maLiteralMask, mnFormatFlags );
896 // -----------------------------------------------------------------------
898 void PatternFormatter::Reformat()
900 if ( GetField() )
902 ImplSetText( ImplPatternReformat( GetField()->GetText(), maEditMask, maLiteralMask, mnFormatFlags ) );
903 if ( !mbSameMask && IsStrictFormat() && !GetField()->IsReadOnly() )
904 GetField()->SetInsertMode( FALSE );
908 // -----------------------------------------------------------------------
910 void PatternFormatter::SelectFixedFont()
912 if ( GetField() )
914 Font aFont = OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, Application::GetSettings().GetLanguage(), 0 );
915 Font aControlFont;
916 aControlFont.SetName( aFont.GetName() );
917 aControlFont.SetFamily( aFont.GetFamily() );
918 aControlFont.SetPitch( aFont.GetPitch() );
919 GetField()->SetControlFont( aControlFont );
923 \f// -----------------------------------------------------------------------
925 PatternField::PatternField( Window* pParent, WinBits nWinStyle ) :
926 SpinField( pParent, nWinStyle )
928 SetField( this );
929 Reformat();
932 // -----------------------------------------------------------------------
934 PatternField::PatternField( Window* pParent, const ResId& rResId ) :
935 SpinField( WINDOW_PATTERNFIELD )
937 rResId.SetRT( RSC_PATTERNFIELD );
938 WinBits nStyle = ImplInitRes( rResId );
939 ImplInit( pParent, nStyle );
940 SetField( this );
941 SpinField::ImplLoadRes( rResId );
942 PatternFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
943 Reformat();
945 if ( !(nStyle & WB_HIDE ) )
946 Show();
949 // -----------------------------------------------------------------------
951 PatternField::~PatternField()
955 // -----------------------------------------------------------------------
957 long PatternField::PreNotify( NotifyEvent& rNEvt )
959 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
961 if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
962 IsStrictFormat(), GetFormatFlags(),
963 ImplIsSameMask(), ImplGetInPattKeyInput() ) )
964 return 1;
967 return SpinField::PreNotify( rNEvt );
970 // -----------------------------------------------------------------------
972 long PatternField::Notify( NotifyEvent& rNEvt )
974 if ( rNEvt.GetType() == EVENT_GETFOCUS )
975 MarkToBeReformatted( FALSE );
976 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
978 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
979 Reformat();
982 return SpinField::Notify( rNEvt );
985 // -----------------------------------------------------------------------
987 void PatternField::Modify()
989 if ( !ImplGetInPattKeyInput() )
991 if ( IsStrictFormat() )
992 ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
993 else
994 MarkToBeReformatted( TRUE );
997 SpinField::Modify();
1000 // -----------------------------------------------------------------------
1002 PatternBox::PatternBox( Window* pParent, WinBits nWinStyle ) :
1003 ComboBox( pParent, nWinStyle )
1005 SetField( this );
1006 Reformat();
1009 // -----------------------------------------------------------------------
1011 PatternBox::PatternBox( Window* pParent, const ResId& rResId ) :
1012 ComboBox( WINDOW_PATTERNBOX )
1014 rResId.SetRT( RSC_PATTERNBOX );
1015 WinBits nStyle = ImplInitRes( rResId );
1016 ImplInit( pParent, nStyle );
1018 SetField( this );
1019 ComboBox::ImplLoadRes( rResId );
1020 PatternFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1021 Reformat();
1023 if ( !(nStyle & WB_HIDE ) )
1024 Show();
1027 // -----------------------------------------------------------------------
1029 PatternBox::~PatternBox()
1033 // -----------------------------------------------------------------------
1035 long PatternBox::PreNotify( NotifyEvent& rNEvt )
1037 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1039 if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
1040 IsStrictFormat(), GetFormatFlags(),
1041 ImplIsSameMask(), ImplGetInPattKeyInput() ) )
1042 return 1;
1045 return ComboBox::PreNotify( rNEvt );
1048 // -----------------------------------------------------------------------
1050 long PatternBox::Notify( NotifyEvent& rNEvt )
1052 if ( rNEvt.GetType() == EVENT_GETFOCUS )
1053 MarkToBeReformatted( FALSE );
1054 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1056 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1057 Reformat();
1060 return ComboBox::Notify( rNEvt );
1063 // -----------------------------------------------------------------------
1065 void PatternBox::Modify()
1067 if ( !ImplGetInPattKeyInput() )
1069 if ( IsStrictFormat() )
1070 ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
1071 else
1072 MarkToBeReformatted( TRUE );
1075 ComboBox::Modify();
1078 // -----------------------------------------------------------------------
1080 void PatternBox::ReformatAll()
1082 XubString aStr;
1083 SetUpdateMode( FALSE );
1084 USHORT nEntryCount = GetEntryCount();
1085 for ( USHORT i=0; i < nEntryCount; i++ )
1087 aStr = ImplPatternReformat( GetEntry( i ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
1088 RemoveEntry( i );
1089 InsertEntry( aStr, i );
1091 PatternFormatter::Reformat();
1092 SetUpdateMode( TRUE );
1095 // -----------------------------------------------------------------------
1097 void PatternBox::InsertString( const XubString& rStr, USHORT nPos )
1099 ComboBox::InsertEntry( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ), nPos );
1102 // -----------------------------------------------------------------------
1104 void PatternBox::RemoveString( const XubString& rStr )
1106 ComboBox::RemoveEntry( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ) );
1109 // -----------------------------------------------------------------------
1111 XubString PatternBox::GetString( USHORT nPos ) const
1113 return ImplPatternReformat( ComboBox::GetEntry( nPos ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
1116 // -----------------------------------------------------------------------
1118 USHORT PatternBox::GetStringPos( const XubString& rStr ) const
1120 return ComboBox::GetEntryPos( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ) );
1123 // =======================================================================
1125 static ExtDateFieldFormat ImplGetExtFormat( DateFormat eOld )
1127 switch( eOld )
1129 case DMY: return XTDATEF_SHORT_DDMMYY;
1130 case MDY: return XTDATEF_SHORT_MMDDYY;
1131 default: return XTDATEF_SHORT_YYMMDD;
1135 // -----------------------------------------------------------------------
1137 static USHORT ImplCutNumberFromString( XubString& rStr )
1139 // Nach Zahl suchen
1140 while ( rStr.Len() && !(rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
1141 rStr.Erase( 0, 1 );
1142 if ( !rStr.Len() )
1143 return 0;
1144 XubString aNumStr;
1145 while ( rStr.Len() && (rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
1147 aNumStr.Insert( rStr.GetChar( 0 ) );
1148 rStr.Erase( 0, 1 );
1150 return (USHORT)aNumStr.ToInt32();
1153 // -----------------------------------------------------------------------
1155 static BOOL ImplCutMonthName( XubString& rStr, const XubString& _rLookupMonthName )
1157 USHORT nPos = rStr.Search( _rLookupMonthName );
1158 if ( nPos != STRING_NOTFOUND )
1160 rStr.Erase( 0, nPos + _rLookupMonthName.Len() );
1161 return TRUE;
1163 return FALSE;
1166 // -----------------------------------------------------------------------
1168 static USHORT ImplCutMonthFromString( XubString& rStr, const CalendarWrapper& rCalendarWrapper )
1170 // search for a month' name
1171 for ( USHORT i=1; i <= 12; i++ )
1173 String aMonthName = rCalendarWrapper.getMonths()[i-1].FullName;
1174 // long month name?
1175 if ( ImplCutMonthName( rStr, aMonthName ) )
1176 return i;
1178 // short month name?
1179 String aAbbrevMonthName = rCalendarWrapper.getMonths()[i-1].AbbrevName;
1180 if ( ImplCutMonthName( rStr, aAbbrevMonthName ) )
1181 return i;
1184 return ImplCutNumberFromString( rStr );
1187 // -----------------------------------------------------------------------
1189 static String ImplGetDateSep( const LocaleDataWrapper& rLocaleDataWrapper, ExtDateFieldFormat eFormat )
1191 String aDateSep = rLocaleDataWrapper.getDateSep();
1193 if ( ( eFormat == XTDATEF_SHORT_YYMMDD_DIN5008 ) || ( eFormat == XTDATEF_SHORT_YYYYMMDD_DIN5008 ) )
1194 aDateSep = String( RTL_CONSTASCII_USTRINGPARAM( "-" ) );
1196 return aDateSep;
1199 static BOOL ImplDateProcessKeyInput( Edit*, const KeyEvent& rKEvt, ExtDateFieldFormat eFormat,
1200 const LocaleDataWrapper& rLocaleDataWrapper )
1202 xub_Unicode cChar = rKEvt.GetCharCode();
1203 USHORT nGroup = rKEvt.GetKeyCode().GetGroup();
1204 if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
1205 (nGroup == KEYGROUP_MISC)||
1206 ((cChar >= '0') && (cChar <= '9')) ||
1207 (cChar == ImplGetDateSep( rLocaleDataWrapper, eFormat ).GetChar(0) ) )
1208 return FALSE;
1209 else
1210 return TRUE;
1213 // -----------------------------------------------------------------------
1215 static BOOL ImplDateGetValue( const XubString& rStr, Date& rDate, ExtDateFieldFormat eDateFormat,
1216 const LocaleDataWrapper& rLocaleDataWrapper, const CalendarWrapper& rCalendarWrapper,
1217 const AllSettings& rSettings )
1219 USHORT nDay = 0;
1220 USHORT nMonth = 0;
1221 USHORT nYear = 0;
1222 BOOL bYear = TRUE;
1223 BOOL bError = FALSE;
1224 String aStr( rStr );
1226 if ( eDateFormat == XTDATEF_SYSTEM_LONG )
1228 DateFormat eFormat = rLocaleDataWrapper.getLongDateFormat();
1229 switch( eFormat )
1231 case MDY:
1232 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
1233 nDay = ImplCutNumberFromString( aStr );
1234 nYear = ImplCutNumberFromString( aStr );
1235 break;
1236 case DMY:
1237 nDay = ImplCutNumberFromString( aStr );
1238 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
1239 nYear = ImplCutNumberFromString( aStr );
1240 break;
1241 case YMD:
1242 default:
1243 nYear = ImplCutNumberFromString( aStr );
1244 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
1245 nDay = ImplCutNumberFromString( aStr );
1246 break;
1249 else
1251 // Check if year is present:
1252 String aDateSep = ImplGetDateSep( rLocaleDataWrapper, eDateFormat );
1253 USHORT nSepPos = aStr.Search( aDateSep );
1254 if ( nSepPos == STRING_NOTFOUND )
1255 return FALSE;
1256 nSepPos = aStr.Search( aDateSep, nSepPos+1 );
1257 if ( ( nSepPos == STRING_NOTFOUND ) || ( nSepPos == (aStr.Len()-1) ) )
1259 bYear = FALSE;
1260 nYear = Date().GetYear();
1263 const sal_Unicode* pBuf = aStr.GetBuffer();
1264 ImplSkipDelimiters( pBuf );
1266 switch ( eDateFormat )
1268 case XTDATEF_SHORT_DDMMYY:
1269 case XTDATEF_SHORT_DDMMYYYY:
1271 nDay = ImplGetNum( pBuf, bError );
1272 ImplSkipDelimiters( pBuf );
1273 nMonth = ImplGetNum( pBuf, bError );
1274 ImplSkipDelimiters( pBuf );
1275 if ( bYear )
1276 nYear = ImplGetNum( pBuf, bError );
1278 break;
1279 case XTDATEF_SHORT_MMDDYY:
1280 case XTDATEF_SHORT_MMDDYYYY:
1282 nMonth = ImplGetNum( pBuf, bError );
1283 ImplSkipDelimiters( pBuf );
1284 nDay = ImplGetNum( pBuf, bError );
1285 ImplSkipDelimiters( pBuf );
1286 if ( bYear )
1287 nYear = ImplGetNum( pBuf, bError );
1289 break;
1290 case XTDATEF_SHORT_YYMMDD:
1291 case XTDATEF_SHORT_YYYYMMDD:
1292 case XTDATEF_SHORT_YYMMDD_DIN5008:
1293 case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1295 if ( bYear )
1296 nYear = ImplGetNum( pBuf, bError );
1297 ImplSkipDelimiters( pBuf );
1298 nMonth = ImplGetNum( pBuf, bError );
1299 ImplSkipDelimiters( pBuf );
1300 nDay = ImplGetNum( pBuf, bError );
1302 break;
1304 default:
1306 DBG_ERROR( "DateFormat???" );
1311 if ( bError || !nDay || !nMonth )
1312 return FALSE;
1314 Date aNewDate( nDay, nMonth, nYear );
1315 DateFormatter::ExpandCentury( aNewDate, rSettings.GetMiscSettings().GetTwoDigitYearStart() );
1316 if ( aNewDate.IsValid() )
1318 rDate = aNewDate;
1319 return TRUE;
1321 return FALSE;
1324 // -----------------------------------------------------------------------
1326 BOOL DateFormatter::ImplDateReformat( const XubString& rStr, XubString& rOutStr, const AllSettings& rSettings )
1328 Date aDate( 0, 0, 0 );
1329 if ( !ImplDateGetValue( rStr, aDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
1330 return TRUE;
1332 Date aTempDate = aDate;
1333 if ( aTempDate > GetMax() )
1334 aTempDate = GetMax();
1335 else if ( aTempDate < GetMin() )
1336 aTempDate = GetMin();
1338 if ( GetErrorHdl().IsSet() && (aDate != aTempDate) )
1340 maCorrectedDate = aTempDate;
1341 if( !GetErrorHdl().Call( this ) )
1343 maCorrectedDate = Date();
1344 return FALSE;
1346 else
1347 maCorrectedDate = Date();
1350 rOutStr = ImplGetDateAsText( aTempDate, rSettings );
1352 return TRUE;
1355 // -----------------------------------------------------------------------
1357 XubString DateFormatter::ImplGetDateAsText( const Date& rDate,
1358 const AllSettings& rSettings ) const
1360 BOOL bShowCentury = FALSE;
1361 switch ( GetExtDateFormat() )
1363 case XTDATEF_SYSTEM_SHORT_YYYY:
1364 case XTDATEF_SYSTEM_LONG:
1365 case XTDATEF_SHORT_DDMMYYYY:
1366 case XTDATEF_SHORT_MMDDYYYY:
1367 case XTDATEF_SHORT_YYYYMMDD:
1368 case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1370 bShowCentury = TRUE;
1372 break;
1373 default:
1375 bShowCentury = FALSE;
1379 if ( !bShowCentury )
1381 // Check if I have to use force showing the century
1382 USHORT nTwoDigitYearStart = rSettings.GetMiscSettings().GetTwoDigitYearStart();
1383 USHORT nYear = rDate.GetYear();
1385 // Wenn Jahr nicht im 2stelligen Grenzbereich liegt,
1386 if ( (nYear < nTwoDigitYearStart) || (nYear >= nTwoDigitYearStart+100) )
1387 bShowCentury = TRUE;
1390 sal_Unicode aBuf[128];
1391 sal_Unicode* pBuf = aBuf;
1393 String aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), GetExtDateFormat( TRUE ) );
1394 USHORT nDay = rDate.GetDay();
1395 USHORT nMonth = rDate.GetMonth();
1396 USHORT nYear = rDate.GetYear();
1397 USHORT nYearLen = bShowCentury ? 4 : 2;
1399 if ( !bShowCentury )
1400 nYear %= 100;
1402 switch ( GetExtDateFormat( TRUE ) )
1404 case XTDATEF_SYSTEM_LONG:
1406 return ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, FALSE, 1, !bShowCentury );
1408 case XTDATEF_SHORT_DDMMYY:
1409 case XTDATEF_SHORT_DDMMYYYY:
1411 pBuf = ImplAddNum( pBuf, nDay, 2 );
1412 pBuf = ImplAddString( pBuf, aDateSep );
1413 pBuf = ImplAddNum( pBuf, nMonth, 2 );
1414 pBuf = ImplAddString( pBuf, aDateSep );
1415 pBuf = ImplAddNum( pBuf, nYear, nYearLen );
1417 break;
1418 case XTDATEF_SHORT_MMDDYY:
1419 case XTDATEF_SHORT_MMDDYYYY:
1421 pBuf = ImplAddNum( pBuf, nMonth, 2 );
1422 pBuf = ImplAddString( pBuf, aDateSep );
1423 pBuf = ImplAddNum( pBuf, nDay, 2 );
1424 pBuf = ImplAddString( pBuf, aDateSep );
1425 pBuf = ImplAddNum( pBuf, nYear, nYearLen );
1427 break;
1428 case XTDATEF_SHORT_YYMMDD:
1429 case XTDATEF_SHORT_YYYYMMDD:
1430 case XTDATEF_SHORT_YYMMDD_DIN5008:
1431 case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1433 pBuf = ImplAddNum( pBuf, nYear, nYearLen );
1434 pBuf = ImplAddString( pBuf, aDateSep );
1435 pBuf = ImplAddNum( pBuf, nMonth, 2 );
1436 pBuf = ImplAddString( pBuf, aDateSep );
1437 pBuf = ImplAddNum( pBuf, nDay, 2 );
1439 break;
1440 default:
1442 DBG_ERROR( "DateFormat???" );
1446 return String( aBuf, (xub_StrLen)(ULONG)(pBuf-aBuf) );
1449 // -----------------------------------------------------------------------
1451 static void ImplDateIncrementDay( Date& rDate, BOOL bUp )
1453 DateFormatter::ExpandCentury( rDate );
1455 if ( bUp )
1457 if ( (rDate.GetDay() != 31) || (rDate.GetMonth() != 12) || (rDate.GetYear() != 9999) )
1458 rDate++;
1460 else
1462 if ( (rDate.GetDay() != 1 ) || (rDate.GetMonth() != 1) || (rDate.GetYear() != 0) )
1463 rDate--;
1467 // -----------------------------------------------------------------------
1469 static void ImplDateIncrementMonth( Date& rDate, BOOL bUp )
1471 DateFormatter::ExpandCentury( rDate );
1473 USHORT nMonth = rDate.GetMonth();
1474 USHORT nYear = rDate.GetYear();
1475 if ( bUp )
1477 if ( (nMonth == 12) && (nYear < 9999) )
1479 rDate.SetMonth( 1 );
1480 rDate.SetYear( nYear + 1 );
1482 else
1484 if ( nMonth < 12 )
1485 rDate.SetMonth( nMonth + 1 );
1488 else
1490 if ( (nMonth == 1) && (nYear > 0) )
1492 rDate.SetMonth( 12 );
1493 rDate.SetYear( nYear - 1 );
1495 else
1497 if ( nMonth > 1 )
1498 rDate.SetMonth( nMonth - 1 );
1502 USHORT nDaysInMonth = rDate.GetDaysInMonth();
1503 if ( rDate.GetDay() > nDaysInMonth )
1504 rDate.SetDay( nDaysInMonth );
1507 // -----------------------------------------------------------------------
1509 static void ImplDateIncrementYear( Date& rDate, BOOL bUp )
1511 DateFormatter::ExpandCentury( rDate );
1513 USHORT nYear = rDate.GetYear();
1514 if ( bUp )
1516 if ( nYear < 9999 )
1517 rDate.SetYear( nYear + 1 );
1519 else
1521 if ( nYear > 0 )
1522 rDate.SetYear( nYear - 1 );
1526 // -----------------------------------------------------------------------
1527 BOOL DateFormatter::ImplAllowMalformedInput() const
1529 return !IsEnforceValidValue();
1532 // -----------------------------------------------------------------------
1534 void DateField::ImplDateSpinArea( BOOL bUp )
1536 // Wenn alles selektiert ist, Tage hochzaehlen
1537 if ( GetField() )
1539 Date aDate( GetDate() );
1540 Selection aSelection = GetField()->GetSelection();
1541 aSelection.Justify();
1542 XubString aText( GetText() );
1543 if ( (xub_StrLen)aSelection.Len() == aText.Len() )
1544 ImplDateIncrementDay( aDate, bUp );
1545 else
1547 xub_StrLen nDateArea = 0;
1549 ExtDateFieldFormat eFormat = GetExtDateFormat( TRUE );
1550 if ( eFormat == XTDATEF_SYSTEM_LONG )
1552 eFormat = ImplGetExtFormat( ImplGetLocaleDataWrapper().getLongDateFormat() );
1553 nDateArea = 1;
1555 else
1557 // Area suchen
1558 xub_StrLen nPos = 0;
1559 String aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), eFormat );
1560 for ( xub_StrLen i = 1; i <= 3; i++ )
1562 nPos = aText.Search( aDateSep, nPos );
1563 if ( nPos >= (USHORT)aSelection.Max() )
1565 nDateArea = i;
1566 break;
1568 else
1569 nPos++;
1574 switch( eFormat )
1576 case XTDATEF_SHORT_MMDDYY:
1577 case XTDATEF_SHORT_MMDDYYYY:
1578 switch( nDateArea )
1580 case 1: ImplDateIncrementMonth( aDate, bUp );
1581 break;
1582 case 2: ImplDateIncrementDay( aDate, bUp );
1583 break;
1584 case 3: ImplDateIncrementYear( aDate, bUp );
1585 break;
1587 break;
1588 case XTDATEF_SHORT_DDMMYY:
1589 case XTDATEF_SHORT_DDMMYYYY:
1590 switch( nDateArea )
1592 case 1: ImplDateIncrementDay( aDate, bUp );
1593 break;
1594 case 2: ImplDateIncrementMonth( aDate, bUp );
1595 break;
1596 case 3: ImplDateIncrementYear( aDate, bUp );
1597 break;
1599 break;
1600 case XTDATEF_SHORT_YYMMDD:
1601 case XTDATEF_SHORT_YYYYMMDD:
1602 case XTDATEF_SHORT_YYMMDD_DIN5008:
1603 case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1604 switch( nDateArea )
1606 case 1: ImplDateIncrementYear( aDate, bUp );
1607 break;
1608 case 2: ImplDateIncrementMonth( aDate, bUp );
1609 break;
1610 case 3: ImplDateIncrementDay( aDate, bUp );
1611 break;
1613 break;
1614 default:
1615 DBG_ERROR( "invalid conversion" );
1616 break;
1620 ImplNewFieldValue( aDate );
1624 // -----------------------------------------------------------------------
1626 void DateFormatter::ImplInit()
1628 mbLongFormat = FALSE;
1629 mbShowDateCentury = TRUE;
1630 mpCalendarWrapper = NULL;
1631 mnDateFormat = 0xFFFF;
1632 mnExtDateFormat = XTDATEF_SYSTEM_SHORT;
1635 // -----------------------------------------------------------------------
1637 DateFormatter::DateFormatter() :
1638 maFieldDate( 0 ),
1639 maLastDate( 0 ),
1640 maMin( 1, 1, 1900 ),
1641 maMax( 31, 12, 2200 ),
1642 mbEnforceValidValue( TRUE )
1644 ImplInit();
1647 // -----------------------------------------------------------------------
1649 void DateFormatter::ImplLoadRes( const ResId& rResId )
1651 ResMgr* pMgr = rResId.GetResMgr();
1652 if( pMgr )
1654 ULONG nMask = pMgr->ReadLong();
1656 if ( DATEFORMATTER_MIN & nMask )
1658 maMin = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
1659 pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
1661 if ( DATEFORMATTER_MAX & nMask )
1663 maMax = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
1664 pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
1666 if ( DATEFORMATTER_LONGFORMAT & nMask )
1667 mbLongFormat = (BOOL)pMgr->ReadShort();
1669 if ( DATEFORMATTER_STRICTFORMAT & nMask )
1670 SetStrictFormat( (BOOL)pMgr->ReadShort() );
1672 if ( DATEFORMATTER_VALUE & nMask )
1674 maFieldDate = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
1675 pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
1676 if ( maFieldDate > maMax )
1677 maFieldDate = maMax;
1678 if ( maFieldDate < maMin )
1679 maFieldDate = maMin;
1680 maLastDate = maFieldDate;
1685 // -----------------------------------------------------------------------
1687 DateFormatter::~DateFormatter()
1689 delete mpCalendarWrapper;
1690 mpCalendarWrapper = NULL;
1693 // -----------------------------------------------------------------------
1695 void DateFormatter::SetLocale( const ::com::sun::star::lang::Locale& rLocale )
1697 delete mpCalendarWrapper;
1698 mpCalendarWrapper = NULL;
1699 FormatterBase::SetLocale( rLocale );
1703 // -----------------------------------------------------------------------
1705 CalendarWrapper& DateFormatter::GetCalendarWrapper() const
1707 if ( !mpCalendarWrapper )
1709 ((DateFormatter*)this)->mpCalendarWrapper = new CalendarWrapper( vcl::unohelper::GetMultiServiceFactory() );
1710 mpCalendarWrapper->loadDefaultCalendar( GetLocale() );
1713 return *mpCalendarWrapper;
1716 // -----------------------------------------------------------------------
1718 void DateFormatter::SetExtDateFormat( ExtDateFieldFormat eFormat )
1720 mnExtDateFormat = eFormat;
1721 ReformatAll();
1724 // -----------------------------------------------------------------------
1726 ExtDateFieldFormat DateFormatter::GetExtDateFormat( BOOL bResolveSystemFormat ) const
1728 ExtDateFieldFormat eDateFormat = (ExtDateFieldFormat)mnExtDateFormat;
1730 if ( bResolveSystemFormat && ( eDateFormat <= XTDATEF_SYSTEM_SHORT_YYYY ) )
1732 BOOL bShowCentury = (eDateFormat == XTDATEF_SYSTEM_SHORT_YYYY);
1733 switch ( ImplGetLocaleDataWrapper().getDateFormat() )
1735 case DMY: eDateFormat = bShowCentury ? XTDATEF_SHORT_DDMMYYYY : XTDATEF_SHORT_DDMMYY;
1736 break;
1737 case MDY: eDateFormat = bShowCentury ? XTDATEF_SHORT_MMDDYYYY : XTDATEF_SHORT_MMDDYY;
1738 break;
1739 default: eDateFormat = bShowCentury ? XTDATEF_SHORT_YYYYMMDD : XTDATEF_SHORT_YYMMDD;
1744 return eDateFormat;
1747 // -----------------------------------------------------------------------
1749 void DateFormatter::ReformatAll()
1751 Reformat();
1754 // -----------------------------------------------------------------------
1756 void DateFormatter::SetMin( const Date& rNewMin )
1758 maMin = rNewMin;
1759 if ( !IsEmptyFieldValue() )
1760 ReformatAll();
1763 // -----------------------------------------------------------------------
1765 void DateFormatter::SetMax( const Date& rNewMax )
1767 maMax = rNewMax;
1768 if ( !IsEmptyFieldValue() )
1769 ReformatAll();
1772 // -----------------------------------------------------------------------
1774 void DateFormatter::SetLongFormat( BOOL bLong )
1776 mbLongFormat = bLong;
1778 // #91913# Remove LongFormat and DateShowCentury - redundant
1779 if ( bLong )
1781 SetExtDateFormat( XTDATEF_SYSTEM_LONG );
1783 else
1785 if( mnExtDateFormat == XTDATEF_SYSTEM_LONG )
1786 SetExtDateFormat( XTDATEF_SYSTEM_SHORT );
1789 ReformatAll();
1792 // -----------------------------------------------------------------------
1794 void DateFormatter::SetShowDateCentury( BOOL bShowDateCentury )
1796 mbShowDateCentury = bShowDateCentury;
1798 // #91913# Remove LongFormat and DateShowCentury - redundant
1799 if ( bShowDateCentury )
1801 switch ( GetExtDateFormat() )
1803 case XTDATEF_SYSTEM_SHORT:
1804 case XTDATEF_SYSTEM_SHORT_YY:
1805 SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY ); break;
1806 case XTDATEF_SHORT_DDMMYY:
1807 SetExtDateFormat( XTDATEF_SHORT_DDMMYYYY ); break;
1808 case XTDATEF_SHORT_MMDDYY:
1809 SetExtDateFormat( XTDATEF_SHORT_MMDDYYYY ); break;
1810 case XTDATEF_SHORT_YYMMDD:
1811 SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD ); break;
1812 case XTDATEF_SHORT_YYMMDD_DIN5008:
1813 SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD_DIN5008 ); break;
1814 default:
1818 else
1820 switch ( GetExtDateFormat() )
1822 case XTDATEF_SYSTEM_SHORT:
1823 case XTDATEF_SYSTEM_SHORT_YYYY:
1824 SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YY ); break;
1825 case XTDATEF_SHORT_DDMMYYYY:
1826 SetExtDateFormat( XTDATEF_SHORT_DDMMYY ); break;
1827 case XTDATEF_SHORT_MMDDYYYY:
1828 SetExtDateFormat( XTDATEF_SHORT_MMDDYY ); break;
1829 case XTDATEF_SHORT_YYYYMMDD:
1830 SetExtDateFormat( XTDATEF_SHORT_YYMMDD ); break;
1831 case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1832 SetExtDateFormat( XTDATEF_SHORT_YYMMDD_DIN5008 ); break;
1833 default:
1838 ReformatAll();
1841 // -----------------------------------------------------------------------
1843 void DateFormatter::SetDate( const Date& rNewDate )
1845 SetUserDate( rNewDate );
1846 maFieldDate = maLastDate;
1847 maLastDate = GetDate();
1850 // -----------------------------------------------------------------------
1852 void DateFormatter::SetUserDate( const Date& rNewDate )
1854 ImplSetUserDate( rNewDate );
1857 // -----------------------------------------------------------------------
1859 void DateFormatter::ImplSetUserDate( const Date& rNewDate, Selection* pNewSelection )
1861 Date aNewDate = rNewDate;
1862 if ( aNewDate > maMax )
1863 aNewDate = maMax;
1864 else if ( aNewDate < maMin )
1865 aNewDate = maMin;
1866 maLastDate = aNewDate;
1868 if ( GetField() )
1869 ImplSetText( ImplGetDateAsText( aNewDate, GetFieldSettings() ), pNewSelection );
1872 // -----------------------------------------------------------------------
1874 void DateFormatter::ImplNewFieldValue( const Date& rDate )
1876 if ( GetField() )
1878 Selection aSelection = GetField()->GetSelection();
1879 aSelection.Justify();
1880 XubString aText = GetField()->GetText();
1881 // Wenn bis ans Ende selektiert war, soll das auch so bleiben...
1882 if ( (xub_StrLen)aSelection.Max() == aText.Len() )
1884 if ( !aSelection.Len() )
1885 aSelection.Min() = SELECTION_MAX;
1886 aSelection.Max() = SELECTION_MAX;
1889 Date aOldLastDate = maLastDate;
1890 ImplSetUserDate( rDate, &aSelection );
1891 maLastDate = aOldLastDate;
1893 // Modify am Edit wird nur bei KeyInput gesetzt...
1894 if ( GetField()->GetText() != aText )
1896 GetField()->SetModifyFlag();
1897 GetField()->Modify();
1902 // -----------------------------------------------------------------------
1904 Date DateFormatter::GetDate() const
1906 Date aDate( 0, 0, 0 );
1908 if ( GetField() )
1910 if ( ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
1912 if ( aDate > maMax )
1913 aDate = maMax;
1914 else if ( aDate < maMin )
1915 aDate = maMin;
1917 else
1919 // !!! TH-18.2.99: Wenn wir Zeit haben sollte einmal
1920 // !!! geklaert werden, warum dieses beim Datum gegenueber
1921 // !!! allen anderen Feldern anders behandelt wird.
1922 // !!! Siehe dazu Bug: 52304
1924 if ( !ImplAllowMalformedInput() )
1926 if ( maLastDate.GetDate() )
1927 aDate = maLastDate;
1928 else if ( !IsEmptyFieldValueEnabled() )
1929 aDate = Date();
1931 else
1932 aDate = GetInvalidDate();
1936 return aDate;
1939 // -----------------------------------------------------------------------
1941 Date DateFormatter::GetRealDate() const
1943 // !!! TH-18.2.99: Wenn wir Zeit haben sollte dieses auch einmal
1944 // !!! fuer die Numeric-Klassen eingebaut werden.
1946 Date aDate( 0, 0, 0 );
1948 if ( GetField() )
1950 if ( !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
1951 if ( ImplAllowMalformedInput() )
1952 aDate = GetInvalidDate();
1955 return aDate;
1958 // -----------------------------------------------------------------------
1960 void DateFormatter::SetEmptyDate()
1962 FormatterBase::SetEmptyFieldValue();
1965 // -----------------------------------------------------------------------
1967 BOOL DateFormatter::IsEmptyDate() const
1969 BOOL bEmpty = FormatterBase::IsEmptyFieldValue();
1971 if ( GetField() && MustBeReformatted() && IsEmptyFieldValueEnabled() )
1973 if ( !GetField()->GetText().Len() )
1975 bEmpty = TRUE;
1977 else if ( !maLastDate.GetDate() )
1979 Date aDate;
1980 bEmpty = !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
1983 return bEmpty;
1986 // -----------------------------------------------------------------------
1988 BOOL DateFormatter::IsDateModified() const
1990 if ( ImplGetEmptyFieldValue() )
1991 return !IsEmptyDate();
1992 else if ( GetDate() != maFieldDate )
1993 return TRUE;
1994 else
1995 return FALSE;
1998 // -----------------------------------------------------------------------
2000 void DateFormatter::Reformat()
2002 if ( !GetField() )
2003 return;
2005 if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
2006 return;
2008 XubString aStr;
2009 BOOL bOK = ImplDateReformat( GetField()->GetText(), aStr, GetFieldSettings() );
2010 if( !bOK )
2011 return;
2013 if ( aStr.Len() )
2015 ImplSetText( aStr );
2016 ImplDateGetValue( aStr, maLastDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
2018 else
2020 if ( maLastDate.GetDate() )
2021 SetDate( maLastDate );
2022 else if ( !IsEmptyFieldValueEnabled() )
2023 SetDate( Date() );
2024 else
2026 ImplSetText( ImplGetSVEmptyStr() );
2027 SetEmptyFieldValueData( TRUE );
2032 // -----------------------------------------------------------------------
2034 void DateFormatter::ExpandCentury( Date& rDate )
2036 ExpandCentury( rDate, Application::GetSettings().GetMiscSettings().GetTwoDigitYearStart() );
2039 // -----------------------------------------------------------------------
2041 void DateFormatter::ExpandCentury( Date& rDate, USHORT nTwoDigitYearStart )
2043 USHORT nDateYear = rDate.GetYear();
2044 if ( nDateYear < 100 )
2046 USHORT nCentury = nTwoDigitYearStart / 100;
2047 if ( nDateYear < (nTwoDigitYearStart % 100) )
2048 nCentury++;
2049 rDate.SetYear( nDateYear + (nCentury*100) );
2053 // -----------------------------------------------------------------------
2055 DateField::DateField( Window* pParent, WinBits nWinStyle ) :
2056 SpinField( pParent, nWinStyle ),
2057 maFirst( GetMin() ),
2058 maLast( GetMax() )
2060 SetField( this );
2061 SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
2062 Reformat();
2063 ResetLastDate();
2066 // -----------------------------------------------------------------------
2068 DateField::DateField( Window* pParent, const ResId& rResId ) :
2069 SpinField( WINDOW_DATEFIELD ),
2070 maFirst( GetMin() ),
2071 maLast( GetMax() )
2073 rResId.SetRT( RSC_DATEFIELD );
2074 WinBits nStyle = ImplInitRes( rResId );
2075 SpinField::ImplInit( pParent, nStyle );
2076 SetField( this );
2077 SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
2078 ImplLoadRes( rResId );
2080 if ( !(nStyle & WB_HIDE ) )
2081 Show();
2083 ResetLastDate();
2086 // -----------------------------------------------------------------------
2088 void DateField::ImplLoadRes( const ResId& rResId )
2090 SpinField::ImplLoadRes( rResId );
2092 ResMgr* pMgr = rResId.GetResMgr();
2093 if( pMgr )
2095 DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2097 ULONG nMask = ReadLongRes();
2098 if ( DATEFIELD_FIRST & nMask )
2100 maFirst = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2101 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
2103 if ( DATEFIELD_LAST & nMask )
2105 maLast = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2106 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
2110 Reformat();
2113 // -----------------------------------------------------------------------
2115 DateField::~DateField()
2119 // -----------------------------------------------------------------------
2121 long DateField::PreNotify( NotifyEvent& rNEvt )
2123 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
2124 ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
2125 !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2127 if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( TRUE ), ImplGetLocaleDataWrapper() ) )
2128 return 1;
2131 return SpinField::PreNotify( rNEvt );
2134 // -----------------------------------------------------------------------
2136 long DateField::Notify( NotifyEvent& rNEvt )
2138 if ( rNEvt.GetType() == EVENT_GETFOCUS )
2139 MarkToBeReformatted( FALSE );
2140 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2142 if ( MustBeReformatted() )
2144 // !!! TH-18.2.99: Wenn wir Zeit haben sollte einmal
2145 // !!! geklaert werden, warum dieses beim Datum gegenueber
2146 // !!! allen anderen Feldern anders behandelt wird.
2147 // !!! Siehe dazu Bug: 52304
2149 BOOL bTextLen = GetText().Len() != 0;
2150 if ( bTextLen || !IsEmptyFieldValueEnabled() )
2152 if ( !ImplAllowMalformedInput() )
2153 Reformat();
2154 else
2156 Date aDate( 0, 0, 0 );
2157 if ( ImplDateGetValue( GetText(), aDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
2158 // even with strict text analysis, our text is a valid date -> do a complete
2159 // reformat
2160 Reformat();
2163 else if ( !bTextLen && IsEmptyFieldValueEnabled() )
2165 ResetLastDate();
2166 SetEmptyFieldValueData( TRUE );
2171 return SpinField::Notify( rNEvt );
2174 // -----------------------------------------------------------------------
2176 void DateField::DataChanged( const DataChangedEvent& rDCEvt )
2178 SpinField::DataChanged( rDCEvt );
2180 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & (SETTINGS_LOCALE|SETTINGS_MISC)) )
2182 if ( IsDefaultLocale() && ( rDCEvt.GetFlags() & SETTINGS_LOCALE ) )
2183 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2184 ReformatAll();
2188 // -----------------------------------------------------------------------
2190 void DateField::Modify()
2192 MarkToBeReformatted( TRUE );
2193 SpinField::Modify();
2196 // -----------------------------------------------------------------------
2198 void DateField::Up()
2200 ImplDateSpinArea( TRUE );
2201 SpinField::Up();
2204 // -----------------------------------------------------------------------
2206 void DateField::Down()
2208 ImplDateSpinArea( FALSE );
2209 SpinField::Down();
2212 // -----------------------------------------------------------------------
2214 void DateField::First()
2216 ImplNewFieldValue( maFirst );
2217 SpinField::First();
2220 // -----------------------------------------------------------------------
2222 void DateField::Last()
2224 ImplNewFieldValue( maLast );
2225 SpinField::Last();
2228 // -----------------------------------------------------------------------
2230 DateBox::DateBox( Window* pParent, WinBits nWinStyle ) :
2231 ComboBox( pParent, nWinStyle )
2233 SetField( this );
2234 SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
2235 Reformat();
2238 // -----------------------------------------------------------------------
2240 DateBox::DateBox( Window* pParent, const ResId& rResId ) :
2241 ComboBox( WINDOW_DATEBOX )
2243 rResId.SetRT( RSC_DATEBOX );
2244 WinBits nStyle = ImplInitRes( rResId );
2245 ComboBox::ImplInit( pParent, nStyle );
2246 SetField( this );
2247 SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
2248 ComboBox::ImplLoadRes( rResId );
2249 ResMgr* pMgr = rResId.GetResMgr();
2250 if( pMgr )
2251 DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2252 Reformat();
2254 if ( !( nStyle & WB_HIDE ) )
2255 Show();
2258 // -----------------------------------------------------------------------
2260 DateBox::~DateBox()
2264 // -----------------------------------------------------------------------
2266 long DateBox::PreNotify( NotifyEvent& rNEvt )
2268 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
2269 ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
2270 !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2272 if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( TRUE ), ImplGetLocaleDataWrapper() ) )
2273 return 1;
2276 return ComboBox::PreNotify( rNEvt );
2279 // -----------------------------------------------------------------------
2281 void DateBox::DataChanged( const DataChangedEvent& rDCEvt )
2283 ComboBox::DataChanged( rDCEvt );
2285 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2287 if ( IsDefaultLocale() )
2288 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2289 ReformatAll();
2293 // -----------------------------------------------------------------------
2295 long DateBox::Notify( NotifyEvent& rNEvt )
2297 if ( rNEvt.GetType() == EVENT_GETFOCUS )
2298 MarkToBeReformatted( FALSE );
2299 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2301 if ( MustBeReformatted() )
2303 BOOL bTextLen = GetText().Len() != 0;
2304 if ( bTextLen || !IsEmptyFieldValueEnabled() )
2305 Reformat();
2306 else if ( !bTextLen && IsEmptyFieldValueEnabled() )
2308 ResetLastDate();
2309 SetEmptyFieldValueData( TRUE );
2314 return ComboBox::Notify( rNEvt );
2317 // -----------------------------------------------------------------------
2319 void DateBox::Modify()
2321 MarkToBeReformatted( TRUE );
2322 ComboBox::Modify();
2325 // -----------------------------------------------------------------------
2327 void DateBox::ReformatAll()
2329 XubString aStr;
2330 SetUpdateMode( FALSE );
2331 USHORT nEntryCount = GetEntryCount();
2332 for ( USHORT i=0; i < nEntryCount; i++ )
2334 ImplDateReformat( GetEntry( i ), aStr, GetFieldSettings() );
2335 RemoveEntry( i );
2336 InsertEntry( aStr, i );
2338 DateFormatter::Reformat();
2339 SetUpdateMode( TRUE );
2342 // -----------------------------------------------------------------------
2344 void DateBox::InsertDate( const Date& rDate, USHORT nPos )
2346 Date aDate = rDate;
2347 if ( aDate > GetMax() )
2348 aDate = GetMax();
2349 else if ( aDate < GetMin() )
2350 aDate = GetMin();
2352 ComboBox::InsertEntry( ImplGetDateAsText( aDate, GetFieldSettings() ), nPos );
2355 // -----------------------------------------------------------------------
2357 void DateBox::RemoveDate( const Date& rDate )
2359 ComboBox::RemoveEntry( ImplGetDateAsText( rDate, GetFieldSettings() ) );
2362 // -----------------------------------------------------------------------
2364 Date DateBox::GetDate( USHORT nPos ) const
2366 Date aDate( 0, 0, 0 );
2367 ImplDateGetValue( ComboBox::GetEntry( nPos ), aDate, GetExtDateFormat(TRUE), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetSettings() );
2368 return aDate;
2371 // -----------------------------------------------------------------------
2373 USHORT DateBox::GetDatePos( const Date& rDate ) const
2375 XubString aStr;
2376 if ( IsLongFormat() )
2377 aStr = ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, FALSE, 1, !IsShowDateCentury() );
2378 else
2379 aStr = ImplGetLocaleDataWrapper().getDate( rDate );
2380 return ComboBox::GetEntryPos( aStr );
2383 // -----------------------------------------------------------------------
2385 static BOOL ImplTimeProcessKeyInput( Edit*, const KeyEvent& rKEvt,
2386 BOOL bStrictFormat, BOOL bDuration,
2387 TimeFieldFormat eFormat,
2388 const LocaleDataWrapper& rLocaleDataWrapper )
2390 xub_Unicode cChar = rKEvt.GetCharCode();
2392 if ( !bStrictFormat )
2393 return FALSE;
2394 else
2396 USHORT nGroup = rKEvt.GetKeyCode().GetGroup();
2397 if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
2398 (nGroup == KEYGROUP_MISC) ||
2399 ((cChar >= '0') && (cChar <= '9')) ||
2400 (cChar == rLocaleDataWrapper.getTimeSep()) ||
2401 ( ( rLocaleDataWrapper.getTimeAM().Search( cChar ) != STRING_NOTFOUND ) ) ||
2402 ( ( rLocaleDataWrapper.getTimePM().Search( cChar ) != STRING_NOTFOUND ) ) ||
2403 // Accept AM/PM:
2404 (cChar == 'a') || (cChar == 'A') || (cChar == 'm') || (cChar == 'M') || (cChar == 'p') || (cChar == 'P') ||
2405 ((eFormat == TIMEF_100TH_SEC) && (cChar == rLocaleDataWrapper.getTime100SecSep())) ||
2406 ((eFormat == TIMEF_SEC_CS) && (cChar == rLocaleDataWrapper.getTime100SecSep())) ||
2407 (bDuration && (cChar == '-')) )
2408 return FALSE;
2409 else
2410 return TRUE;
2414 // -----------------------------------------------------------------------
2416 static BOOL ImplIsOnlyDigits( const String& _rStr )
2418 const sal_Unicode* _pChr = _rStr.GetBuffer();
2419 for ( xub_StrLen i = 0; i < _rStr.Len(); ++i, ++_pChr )
2421 if ( *_pChr < '0' || *_pChr > '9' )
2422 return FALSE;
2424 return TRUE;
2427 // -----------------------------------------------------------------------
2429 static BOOL ImplIsValidTimePortion( BOOL _bSkipInvalidCharacters, const String& _rStr )
2431 if ( !_bSkipInvalidCharacters )
2433 if ( ( _rStr.Len() > 2 ) || ( _rStr.Len() < 1 ) || !ImplIsOnlyDigits( _rStr ) )
2434 return FALSE;
2436 return TRUE;
2439 // -----------------------------------------------------------------------
2441 static BOOL ImplCutTimePortion( String& _rStr, xub_StrLen _nSepPos, BOOL _bSkipInvalidCharacters, short* _pPortion )
2443 String sPortion = _rStr.Copy( 0, _nSepPos );
2444 _rStr.Erase( 0, _nSepPos + 1 );
2446 if ( !ImplIsValidTimePortion( _bSkipInvalidCharacters, sPortion ) )
2447 return FALSE;
2448 *_pPortion = (short)sPortion.ToInt32();
2449 return TRUE;
2452 // -----------------------------------------------------------------------
2454 static BOOL ImplTimeGetValue( const XubString& rStr, Time& rTime,
2455 TimeFieldFormat eFormat, BOOL bDuration,
2456 const LocaleDataWrapper& rLocaleDataWrapper, BOOL _bSkipInvalidCharacters = TRUE )
2458 XubString aStr = rStr;
2459 short nHour = 0;
2460 short nMinute = 0;
2461 short nSecond = 0;
2462 short n100Sec = 0;
2463 Time aTime( 0, 0, 0 );
2465 if ( !rStr.Len() )
2466 return FALSE;
2468 // Nach Separatoren suchen
2469 if ( rLocaleDataWrapper.getTimeSep().Len() )
2471 XubString aSepStr( RTL_CONSTASCII_USTRINGPARAM( ",.;:/" ) );
2472 if ( !bDuration )
2473 aSepStr.Append( '-' );
2475 // Die obigen Zeichen durch das Separatorzeichen ersetzen
2476 for ( xub_StrLen i = 0; i < aSepStr.Len(); i++ )
2478 if ( aSepStr.GetChar( i ) == rLocaleDataWrapper.getTimeSep() )
2479 continue;
2480 for ( xub_StrLen j = 0; j < aStr.Len(); j++ )
2482 if ( aStr.GetChar( j ) == aSepStr.GetChar( i ) )
2483 aStr.SetChar( j, rLocaleDataWrapper.getTimeSep().GetChar(0) );
2488 BOOL bNegative = FALSE;
2489 xub_StrLen nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2490 if ( aStr.GetChar( 0 ) == '-' )
2491 bNegative = TRUE;
2492 if ( eFormat != TIMEF_SEC_CS )
2494 if ( nSepPos == STRING_NOTFOUND )
2495 nSepPos = aStr.Len();
2496 if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nHour ) )
2497 return FALSE;
2499 nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2500 if ( aStr.GetChar( 0 ) == '-' )
2501 bNegative = TRUE;
2502 if ( nSepPos != STRING_NOTFOUND )
2504 if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nMinute ) )
2505 return FALSE;
2507 nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2508 if ( aStr.GetChar( 0 ) == '-' )
2509 bNegative = TRUE;
2510 if ( nSepPos != STRING_NOTFOUND )
2512 if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nSecond ) )
2513 return FALSE;
2514 if ( aStr.GetChar( 0 ) == '-' )
2515 bNegative = TRUE;
2516 n100Sec = (short)aStr.ToInt32();
2518 else
2519 nSecond = (short)aStr.ToInt32();
2521 else
2522 nMinute = (short)aStr.ToInt32();
2524 else if ( nSepPos == STRING_NOTFOUND )
2526 nSecond = (short)aStr.ToInt32();
2527 nMinute += nSecond / 60;
2528 nSecond %= 60;
2529 nHour += nMinute / 60;
2530 nMinute %= 60;
2532 else
2534 nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
2535 aStr.Erase( 0, nSepPos+1 );
2537 nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2538 if ( aStr.GetChar( 0 ) == '-' )
2539 bNegative = TRUE;
2540 if ( nSepPos != STRING_NOTFOUND )
2542 nMinute = nSecond;
2543 nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
2544 aStr.Erase( 0, nSepPos+1 );
2546 nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2547 if ( aStr.GetChar( 0 ) == '-' )
2548 bNegative = TRUE;
2549 if ( nSepPos != STRING_NOTFOUND )
2551 nHour = nMinute;
2552 nMinute = nSecond;
2553 nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
2554 aStr.Erase( 0, nSepPos+1 );
2556 else
2558 nHour += nMinute / 60;
2559 nMinute %= 60;
2562 else
2564 nMinute += nSecond / 60;
2565 nSecond %= 60;
2566 nHour += nMinute / 60;
2567 nMinute %= 60;
2569 n100Sec = (short)aStr.ToInt32();
2571 if ( n100Sec )
2573 xub_StrLen nLen = 1; // mindestens eine Ziffer, weil sonst n100Sec==0
2575 while ( aStr.GetChar(nLen) >= '0' && aStr.GetChar(nLen) <= '9' )
2576 nLen++;
2578 if ( nLen > 2 )
2580 while( nLen > 3 )
2582 n100Sec = n100Sec / 10;
2583 nLen--;
2585 // Rundung bei negativen Zahlen???
2586 n100Sec = (n100Sec + 5) / 10;
2588 else
2590 while( nLen < 2 )
2592 n100Sec = n100Sec * 10;
2593 nLen++;
2599 if ( (nMinute > 59) || (nSecond > 59) || (n100Sec > 100) )
2600 return FALSE;
2602 if ( eFormat == TIMEF_NONE )
2603 nSecond = n100Sec = 0;
2604 else if ( eFormat == TIMEF_SEC )
2605 n100Sec = 0;
2607 if ( !bDuration )
2609 if ( bNegative || (nHour < 0) || (nMinute < 0) ||
2610 (nSecond < 0) || (n100Sec < 0) )
2611 return FALSE;
2613 aStr.ToUpperAscii();
2614 XubString aAM( rLocaleDataWrapper.getTimeAM() );
2615 XubString aPM( rLocaleDataWrapper.getTimePM() );
2616 aAM.ToUpperAscii();
2617 aPM.ToUpperAscii();
2618 XubString aAM2( RTL_CONSTASCII_USTRINGPARAM( "AM" ) ); // aAM is localized
2619 XubString aPM2( RTL_CONSTASCII_USTRINGPARAM( "PM" ) ); // aPM is localized
2621 if ( (nHour < 12) && ( ( aStr.Search( aPM ) != STRING_NOTFOUND ) || ( aStr.Search( aPM2 ) != STRING_NOTFOUND ) ) )
2622 nHour += 12;
2624 if ( (nHour == 12) && ( ( aStr.Search( aAM ) != STRING_NOTFOUND ) || ( aStr.Search( aAM2 ) != STRING_NOTFOUND ) ) )
2625 nHour = 0;
2627 aTime = Time( (USHORT)nHour, (USHORT)nMinute, (USHORT)nSecond,
2628 (USHORT)n100Sec );
2630 else
2632 if ( bNegative || (nHour < 0) || (nMinute < 0) ||
2633 (nSecond < 0) || (n100Sec < 0) )
2635 bNegative = TRUE;
2636 nHour = nHour < 0 ? -nHour : nHour;
2637 nMinute = nMinute < 0 ? -nMinute : nMinute;
2638 nSecond = nSecond < 0 ? -nSecond : nSecond;
2639 n100Sec = n100Sec < 0 ? -n100Sec : n100Sec;
2642 aTime = Time( (USHORT)nHour, (USHORT)nMinute, (USHORT)nSecond,
2643 (USHORT)n100Sec );
2644 if ( bNegative )
2645 aTime = -aTime;
2648 rTime = aTime;
2650 return TRUE;
2653 // -----------------------------------------------------------------------
2655 BOOL TimeFormatter::ImplTimeReformat( const XubString& rStr, XubString& rOutStr )
2657 Time aTime( 0, 0, 0 );
2658 if ( !ImplTimeGetValue( rStr, aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ) )
2659 return TRUE;
2661 Time aTempTime = aTime;
2662 if ( aTempTime > GetMax() )
2663 aTempTime = GetMax() ;
2664 else if ( aTempTime < GetMin() )
2665 aTempTime = GetMin();
2667 if ( GetErrorHdl().IsSet() && (aTime != aTempTime) )
2669 maCorrectedTime = aTempTime;
2670 if ( !GetErrorHdl().Call( this ) )
2672 maCorrectedTime = Time();
2673 return FALSE;
2675 else
2676 maCorrectedTime = Time();
2679 BOOL bSecond = FALSE;
2680 BOOL b100Sec = FALSE;
2681 if ( meFormat != TIMEF_NONE )
2682 bSecond = TRUE;
2683 if ( meFormat == TIMEF_100TH_SEC )
2684 b100Sec = TRUE;
2686 if ( meFormat == TIMEF_SEC_CS )
2688 ULONG n = aTempTime.GetHour() * 3600L;
2689 n += aTempTime.GetMin() * 60L;
2690 n += aTempTime.GetSec();
2691 rOutStr = String::CreateFromInt32( n );
2692 rOutStr += ImplGetLocaleDataWrapper().getTime100SecSep();
2693 if ( aTempTime.Get100Sec() < 10 )
2694 rOutStr += '0';
2695 rOutStr += String::CreateFromInt32( aTempTime.Get100Sec() );
2697 else if ( mbDuration )
2698 rOutStr = ImplGetLocaleDataWrapper().getDuration( aTempTime, bSecond, b100Sec );
2699 else
2701 rOutStr = ImplGetLocaleDataWrapper().getTime( aTempTime, bSecond, b100Sec );
2702 if ( GetTimeFormat() == HOUR_12 )
2704 if ( aTempTime.GetHour() > 12 )
2706 Time aT( aTempTime );
2707 aT.SetHour( aT.GetHour() % 12 );
2708 rOutStr = ImplGetLocaleDataWrapper().getTime( aT, bSecond, b100Sec );
2710 // Don't use LocaleDataWrapper, we want AM/PM
2711 if ( aTempTime.GetHour() < 12 )
2712 rOutStr += String( RTL_CONSTASCII_USTRINGPARAM( "AM" ) ); // ImplGetLocaleDataWrapper().getTimeAM();
2713 else
2714 rOutStr += String( RTL_CONSTASCII_USTRINGPARAM( "PM" ) ); // ImplGetLocaleDataWrapper().getTimePM();
2718 return TRUE;
2721 // -----------------------------------------------------------------------
2722 BOOL TimeFormatter::ImplAllowMalformedInput() const
2724 return !IsEnforceValidValue();
2727 // -----------------------------------------------------------------------
2729 void TimeField::ImplTimeSpinArea( BOOL bUp )
2731 if ( GetField() )
2733 xub_StrLen nTimeArea = 0;
2734 Time aTime( GetTime() );
2735 XubString aText( GetText() );
2736 Selection aSelection( GetField()->GetSelection() );
2738 // Area suchen
2739 if ( GetFormat() != TIMEF_SEC_CS )
2741 for ( xub_StrLen i = 1, nPos = 0; i <= 4; i++ )
2743 xub_StrLen nPos1 = aText.Search( ImplGetLocaleDataWrapper().getTimeSep(), nPos );
2744 xub_StrLen nPos2 = aText.Search( ImplGetLocaleDataWrapper().getTime100SecSep(), nPos );
2745 nPos = nPos1 < nPos2 ? nPos1 : nPos2;
2746 if ( nPos >= (xub_StrLen)aSelection.Max() )
2748 nTimeArea = i;
2749 break;
2751 else
2752 nPos++;
2755 else
2757 xub_StrLen nPos = aText.Search( ImplGetLocaleDataWrapper().getTime100SecSep() );
2758 if ( nPos == STRING_NOTFOUND || nPos >= (xub_StrLen)aSelection.Max() )
2759 nTimeArea = 3;
2760 else
2761 nTimeArea = 4;
2764 if ( nTimeArea )
2766 Time aAddTime( 0, 0, 0 );
2767 if ( nTimeArea == 1 )
2768 aAddTime = Time( 1, 0 );
2769 else if ( nTimeArea == 2 )
2770 aAddTime = Time( 0, 1 );
2771 else if ( nTimeArea == 3 )
2772 aAddTime = Time( 0, 0, 1 );
2773 else if ( nTimeArea == 4 )
2774 aAddTime = Time( 0, 0, 0, 1 );
2776 if ( !bUp )
2777 aAddTime = -aAddTime;
2779 aTime += aAddTime;
2780 if ( !IsDuration() )
2782 Time aAbsMaxTime( 23, 59, 59, 99 );
2783 if ( aTime > aAbsMaxTime )
2784 aTime = aAbsMaxTime;
2785 Time aAbsMinTime( 0, 0 );
2786 if ( aTime < aAbsMinTime )
2787 aTime = aAbsMinTime;
2789 ImplNewFieldValue( aTime );
2795 // -----------------------------------------------------------------------
2797 void TimeFormatter::ImplInit()
2799 meFormat = TIMEF_NONE;
2800 mbDuration = FALSE;
2801 mnTimeFormat = HOUR_24; // Should become a ExtTimeFieldFormat in next implementation, merge with mbDuration and meFormat
2804 // -----------------------------------------------------------------------
2806 TimeFormatter::TimeFormatter() :
2807 maLastTime( 0, 0 ),
2808 maMin( 0, 0 ),
2809 maMax( 23, 59, 59, 99 ),
2810 mbEnforceValidValue( TRUE ),
2811 maFieldTime( 0, 0 )
2813 ImplInit();
2816 // -----------------------------------------------------------------------
2818 void TimeFormatter::ImplLoadRes( const ResId& rResId )
2820 ResMgr* pMgr = rResId.GetResMgr();
2821 if( pMgr )
2823 ULONG nMask = pMgr->ReadLong();
2825 if ( TIMEFORMATTER_MIN & nMask )
2827 SetMin( Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
2828 pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
2831 if ( TIMEFORMATTER_MAX & nMask )
2833 SetMax( Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
2834 pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
2837 if ( TIMEFORMATTER_TIMEFIELDFORMAT & nMask )
2838 meFormat = (TimeFieldFormat)pMgr->ReadLong();
2840 if ( TIMEFORMATTER_DURATION & nMask )
2841 mbDuration = (BOOL)pMgr->ReadShort();
2843 if ( TIMEFORMATTER_STRICTFORMAT & nMask )
2844 SetStrictFormat( (BOOL)pMgr->ReadShort() );
2846 if ( TIMEFORMATTER_VALUE & nMask )
2848 maFieldTime = Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
2849 if ( maFieldTime > GetMax() )
2850 maFieldTime = GetMax();
2851 if ( maFieldTime < GetMin() )
2852 maFieldTime = GetMin();
2853 maLastTime = maFieldTime;
2855 pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
2860 // -----------------------------------------------------------------------
2862 TimeFormatter::~TimeFormatter()
2866 // -----------------------------------------------------------------------
2868 void TimeFormatter::ReformatAll()
2870 Reformat();
2873 // -----------------------------------------------------------------------
2875 void TimeFormatter::SetMin( const Time& rNewMin )
2877 maMin = rNewMin;
2878 if ( !IsEmptyFieldValue() )
2879 ReformatAll();
2882 // -----------------------------------------------------------------------
2884 void TimeFormatter::SetMax( const Time& rNewMax )
2886 maMax = rNewMax;
2887 if ( !IsEmptyFieldValue() )
2888 ReformatAll();
2891 // -----------------------------------------------------------------------
2893 void TimeFormatter::SetTimeFormat( TimeFormatter::TimeFormat eNewFormat )
2895 mnTimeFormat = sal::static_int_cast<USHORT>(eNewFormat);
2898 // -----------------------------------------------------------------------
2900 TimeFormatter::TimeFormat TimeFormatter::GetTimeFormat() const
2902 return (TimeFormat)mnTimeFormat;
2905 // -----------------------------------------------------------------------
2907 void TimeFormatter::SetFormat( TimeFieldFormat eNewFormat )
2909 meFormat = eNewFormat;
2910 ReformatAll();
2913 // -----------------------------------------------------------------------
2915 void TimeFormatter::SetDuration( BOOL bNewDuration )
2917 mbDuration = bNewDuration;
2918 ReformatAll();
2921 // -----------------------------------------------------------------------
2923 void TimeFormatter::SetTime( const Time& rNewTime )
2925 SetUserTime( rNewTime );
2926 maFieldTime = maLastTime;
2927 SetEmptyFieldValueData( FALSE );
2930 // -----------------------------------------------------------------------
2932 void TimeFormatter::ImplNewFieldValue( const Time& rTime )
2934 if ( GetField() )
2936 Selection aSelection = GetField()->GetSelection();
2937 aSelection.Justify();
2938 XubString aText = GetField()->GetText();
2939 // Wenn bis ans Ende selektiert war, soll das auch so bleiben...
2940 if ( (xub_StrLen)aSelection.Max() == aText.Len() )
2942 if ( !aSelection.Len() )
2943 aSelection.Min() = SELECTION_MAX;
2944 aSelection.Max() = SELECTION_MAX;
2947 Time aOldLastTime = maLastTime;
2948 ImplSetUserTime( rTime, &aSelection );
2949 maLastTime = aOldLastTime;
2951 // Modify am Edit wird nur bei KeyInput gesetzt...
2952 if ( GetField()->GetText() != aText )
2954 GetField()->SetModifyFlag();
2955 GetField()->Modify();
2960 // -----------------------------------------------------------------------
2962 void TimeFormatter::ImplSetUserTime( const Time& rNewTime, Selection* pNewSelection )
2964 Time aNewTime = rNewTime;
2965 if ( aNewTime > GetMax() )
2966 aNewTime = GetMax();
2967 else if ( aNewTime < GetMin() )
2968 aNewTime = GetMin();
2969 maLastTime = aNewTime;
2971 if ( GetField() )
2973 XubString aStr;
2974 BOOL bSec = FALSE;
2975 BOOL b100Sec = FALSE;
2976 if ( meFormat != TIMEF_NONE )
2977 bSec = TRUE;
2978 if ( meFormat == TIMEF_100TH_SEC || meFormat == TIMEF_SEC_CS )
2979 b100Sec = TRUE;
2980 if ( meFormat == TIMEF_SEC_CS )
2982 ULONG n = aNewTime.GetHour() * 3600L;
2983 n += aNewTime.GetMin() * 60L;
2984 n += aNewTime.GetSec();
2985 aStr = String::CreateFromInt32( n );
2986 aStr += ImplGetLocaleDataWrapper().getTime100SecSep();
2987 if ( aNewTime.Get100Sec() < 10 )
2988 aStr += '0';
2989 aStr += String::CreateFromInt32( aNewTime.Get100Sec() );
2991 else if ( mbDuration )
2993 aStr = ImplGetLocaleDataWrapper().getDuration( aNewTime, bSec, b100Sec );
2995 else
2997 aStr = ImplGetLocaleDataWrapper().getTime( aNewTime, bSec, b100Sec );
2998 if ( GetTimeFormat() == HOUR_12 )
3000 if ( aNewTime.GetHour() > 12 )
3002 Time aT( aNewTime );
3003 aT.SetHour( aT.GetHour() % 12 );
3004 aStr = ImplGetLocaleDataWrapper().getTime( aT, bSec, b100Sec );
3006 // Don't use LocaleDataWrapper, we want AM/PM
3007 if ( aNewTime.GetHour() < 12 )
3008 aStr += String( RTL_CONSTASCII_USTRINGPARAM( "AM" ) ); // ImplGetLocaleDataWrapper().getTimeAM();
3009 else
3010 aStr += String( RTL_CONSTASCII_USTRINGPARAM( "PM" ) ); // ImplGetLocaleDataWrapper().getTimePM();
3014 ImplSetText( aStr, pNewSelection );
3018 // -----------------------------------------------------------------------
3020 void TimeFormatter::SetUserTime( const Time& rNewTime )
3022 ImplSetUserTime( rNewTime );
3025 // -----------------------------------------------------------------------
3027 Time TimeFormatter::GetTime() const
3029 Time aTime( 0, 0, 0 );
3031 if ( GetField() )
3033 BOOL bAllowMailformed = ImplAllowMalformedInput();
3034 if ( ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
3036 if ( aTime > GetMax() )
3037 aTime = GetMax();
3038 else if ( aTime < GetMin() )
3039 aTime = GetMin();
3041 else
3043 if ( bAllowMailformed )
3044 aTime = GetInvalidTime();
3045 else
3046 aTime = maLastTime;
3050 return aTime;
3053 // -----------------------------------------------------------------------
3055 Time TimeFormatter::GetRealTime() const
3057 Time aTime( 0, 0, 0 );
3059 if ( GetField() )
3061 BOOL bAllowMailformed = ImplAllowMalformedInput();
3062 if ( !ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
3063 if ( bAllowMailformed )
3064 aTime = GetInvalidTime();
3067 return aTime;
3070 // -----------------------------------------------------------------------
3072 BOOL TimeFormatter::IsTimeModified() const
3074 if ( ImplGetEmptyFieldValue() )
3075 return !IsEmptyTime();
3076 else if ( GetTime() != maFieldTime )
3077 return TRUE;
3078 else
3079 return FALSE;
3082 // -----------------------------------------------------------------------
3084 void TimeFormatter::Reformat()
3086 if ( !GetField() )
3087 return;
3089 if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
3090 return;
3092 XubString aStr;
3093 BOOL bOK = ImplTimeReformat( GetField()->GetText(), aStr );
3094 if ( !bOK )
3095 return;
3097 if ( aStr.Len() )
3099 ImplSetText( aStr );
3100 ImplTimeGetValue( aStr, maLastTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
3102 else
3103 SetTime( maLastTime );
3106 // -----------------------------------------------------------------------
3108 TimeField::TimeField( Window* pParent, WinBits nWinStyle ) :
3109 SpinField( pParent, nWinStyle ),
3110 maFirst( GetMin() ),
3111 maLast( GetMax() )
3113 SetField( this );
3114 SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, FALSE, FALSE ) );
3115 Reformat();
3118 // -----------------------------------------------------------------------
3120 TimeField::TimeField( Window* pParent, const ResId& rResId ) :
3121 SpinField( WINDOW_TIMEFIELD ),
3122 maFirst( GetMin() ),
3123 maLast( GetMax() )
3125 rResId.SetRT( RSC_TIMEFIELD );
3126 WinBits nStyle = ImplInitRes( rResId );
3127 SpinField::ImplInit( pParent, nStyle );
3128 SetField( this );
3129 SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, FALSE, FALSE ) );
3130 ImplLoadRes( rResId );
3132 if ( !(nStyle & WB_HIDE ) )
3133 Show();
3136 // -----------------------------------------------------------------------
3138 void TimeField::ImplLoadRes( const ResId& rResId )
3140 SpinField::ImplLoadRes( rResId );
3141 ResMgr* pMgr = rResId.GetResMgr();
3142 if( pMgr )
3144 TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
3146 ULONG nMask = ReadLongRes();
3148 if ( TIMEFIELD_FIRST & nMask )
3150 maFirst = Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
3151 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
3153 if ( TIMEFIELD_LAST & nMask )
3155 maLast = Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
3156 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
3160 Reformat();
3163 // -----------------------------------------------------------------------
3165 TimeField::~TimeField()
3169 // -----------------------------------------------------------------------
3171 long TimeField::PreNotify( NotifyEvent& rNEvt )
3173 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
3175 if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
3176 return 1;
3179 return SpinField::PreNotify( rNEvt );
3182 // -----------------------------------------------------------------------
3184 long TimeField::Notify( NotifyEvent& rNEvt )
3186 if ( rNEvt.GetType() == EVENT_GETFOCUS )
3187 MarkToBeReformatted( FALSE );
3188 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
3190 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
3192 if ( !ImplAllowMalformedInput() )
3193 Reformat();
3194 else
3196 Time aTime( 0, 0, 0 );
3197 if ( ImplTimeGetValue( GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), FALSE ) )
3198 // even with strict text analysis, our text is a valid time -> do a complete
3199 // reformat
3200 Reformat();
3205 return SpinField::Notify( rNEvt );
3208 // -----------------------------------------------------------------------
3210 void TimeField::DataChanged( const DataChangedEvent& rDCEvt )
3212 SpinField::DataChanged( rDCEvt );
3214 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
3216 if ( IsDefaultLocale() )
3217 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
3218 ReformatAll();
3222 // -----------------------------------------------------------------------
3224 void TimeField::Modify()
3226 MarkToBeReformatted( TRUE );
3227 SpinField::Modify();
3230 // -----------------------------------------------------------------------
3232 void TimeField::Up()
3234 ImplTimeSpinArea( TRUE );
3235 SpinField::Up();
3238 // -----------------------------------------------------------------------
3240 void TimeField::Down()
3242 ImplTimeSpinArea( FALSE );
3243 SpinField::Down();
3246 // -----------------------------------------------------------------------
3248 void TimeField::First()
3250 ImplNewFieldValue( maFirst );
3251 SpinField::First();
3254 // -----------------------------------------------------------------------
3256 void TimeField::Last()
3258 ImplNewFieldValue( maLast );
3259 SpinField::Last();
3262 // -----------------------------------------------------------------------
3264 void TimeField::SetExtFormat( ExtTimeFieldFormat eFormat )
3266 switch ( eFormat )
3268 case EXTTIMEF_24H_SHORT:
3270 SetTimeFormat( HOUR_24 );
3271 SetDuration( FALSE );
3272 SetFormat( TIMEF_NONE );
3274 break;
3275 case EXTTIMEF_24H_LONG:
3277 SetTimeFormat( HOUR_24 );
3278 SetDuration( FALSE );
3279 SetFormat( TIMEF_SEC );
3281 break;
3282 case EXTTIMEF_12H_SHORT:
3284 SetTimeFormat( HOUR_12 );
3285 SetDuration( FALSE );
3286 SetFormat( TIMEF_NONE );
3288 break;
3289 case EXTTIMEF_12H_LONG:
3291 SetTimeFormat( HOUR_12 );
3292 SetDuration( FALSE );
3293 SetFormat( TIMEF_SEC );
3295 break;
3296 case EXTTIMEF_DURATION_SHORT:
3298 SetDuration( TRUE );
3299 SetFormat( TIMEF_NONE );
3301 break;
3302 case EXTTIMEF_DURATION_LONG:
3304 SetDuration( TRUE );
3305 SetFormat( TIMEF_SEC );
3307 break;
3308 default: DBG_ERROR( "ExtTimeFieldFormat unknown!" );
3311 if ( GetField() && GetField()->GetText().Len() )
3312 SetUserTime( GetTime() );
3313 ReformatAll();
3316 // -----------------------------------------------------------------------
3318 TimeBox::TimeBox( Window* pParent, WinBits nWinStyle ) :
3319 ComboBox( pParent, nWinStyle )
3321 SetField( this );
3322 SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, FALSE, FALSE ) );
3323 Reformat();
3326 // -----------------------------------------------------------------------
3328 TimeBox::TimeBox( Window* pParent, const ResId& rResId ) :
3329 ComboBox( WINDOW_TIMEBOX )
3331 rResId.SetRT( RSC_TIMEBOX );
3332 WinBits nStyle = ImplInitRes( rResId );
3333 ComboBox::ImplInit( pParent, nStyle );
3334 SetField( this );
3335 SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, FALSE, FALSE ) );
3336 ComboBox::ImplLoadRes( rResId );
3337 ResMgr* pMgr = rResId.GetResMgr();
3338 if( pMgr )
3339 TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
3340 Reformat();
3342 if ( !(nStyle & WB_HIDE) )
3343 Show();
3346 // -----------------------------------------------------------------------
3348 TimeBox::~TimeBox()
3352 // -----------------------------------------------------------------------
3354 long TimeBox::PreNotify( NotifyEvent& rNEvt )
3356 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
3358 if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
3359 return 1;
3362 return ComboBox::PreNotify( rNEvt );
3365 // -----------------------------------------------------------------------
3367 long TimeBox::Notify( NotifyEvent& rNEvt )
3369 if ( rNEvt.GetType() == EVENT_GETFOCUS )
3370 MarkToBeReformatted( FALSE );
3371 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
3373 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
3374 Reformat();
3377 return ComboBox::Notify( rNEvt );
3380 // -----------------------------------------------------------------------
3382 void TimeBox::DataChanged( const DataChangedEvent& rDCEvt )
3384 ComboBox::DataChanged( rDCEvt );
3386 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
3388 if ( IsDefaultLocale() )
3389 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
3390 ReformatAll();
3394 // -----------------------------------------------------------------------
3396 void TimeBox::Modify()
3398 MarkToBeReformatted( TRUE );
3399 ComboBox::Modify();
3402 // -----------------------------------------------------------------------
3404 void TimeBox::ReformatAll()
3406 XubString aStr;
3407 SetUpdateMode( FALSE );
3408 USHORT nEntryCount = GetEntryCount();
3409 for ( USHORT i=0; i < nEntryCount; i++ )
3411 ImplTimeReformat( GetEntry( i ), aStr );
3412 RemoveEntry( i );
3413 InsertEntry( aStr, i );
3415 TimeFormatter::Reformat();
3416 SetUpdateMode( TRUE );
3419 // -----------------------------------------------------------------------
3421 void TimeBox::InsertTime( const Time& rTime, USHORT nPos )
3423 Time aTime = rTime;
3424 if ( aTime > GetMax() )
3425 aTime = GetMax();
3426 else if ( aTime < GetMin() )
3427 aTime = GetMin();
3429 BOOL bSec = FALSE;
3430 BOOL b100Sec = FALSE;
3431 if ( GetFormat() == TIMEF_SEC )
3432 bSec = TRUE;
3433 if ( GetFormat() == TIMEF_100TH_SEC || GetFormat() == TIMEF_SEC_CS )
3434 bSec = b100Sec = TRUE;
3435 ComboBox::InsertEntry( ImplGetLocaleDataWrapper().getTime( aTime, bSec, b100Sec ), nPos );
3438 // -----------------------------------------------------------------------
3440 void TimeBox::RemoveTime( const Time& rTime )
3442 BOOL bSec = FALSE;
3443 BOOL b100Sec = FALSE;
3444 if ( GetFormat() == TIMEF_SEC )
3445 bSec = TRUE;
3446 if ( GetFormat() == TIMEF_100TH_SEC || TIMEF_SEC_CS )
3447 bSec = b100Sec = TRUE;
3448 ComboBox::RemoveEntry( ImplGetLocaleDataWrapper().getTime( rTime, bSec, b100Sec ) );
3451 // -----------------------------------------------------------------------
3453 Time TimeBox::GetTime( USHORT nPos ) const
3455 Time aTime( 0, 0, 0 );
3456 ImplTimeGetValue( ComboBox::GetEntry( nPos ), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
3457 return aTime;
3460 // -----------------------------------------------------------------------
3462 USHORT TimeBox::GetTimePos( const Time& rTime ) const
3464 BOOL bSec = FALSE;
3465 BOOL b100Sec = FALSE;
3466 if ( GetFormat() == TIMEF_SEC )
3467 bSec = TRUE;
3468 if ( GetFormat() == TIMEF_100TH_SEC || TIMEF_SEC_CS )
3469 bSec = b100Sec = TRUE;
3470 return ComboBox::GetEntryPos( ImplGetLocaleDataWrapper().getTime( rTime, bSec, b100Sec ) );