xref: /trunk/main/vcl/source/control/field2.cxx (revision 9f62ea84)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 #include <tools/debug.hxx>
27 
28 #include <tools/rc.h>
29 
30 #include <vcl/svapp.hxx>
31 #include <vcl/sound.hxx>
32 #include <vcl/event.hxx>
33 #include <vcl/field.hxx>
34 #include <vcl/unohelp.hxx>
35 
36 #include <svdata.hxx>
37 
38 #include <i18npool/mslangid.hxx>
39 
40 #include <com/sun/star/lang/Locale.hpp>
41 #include <com/sun/star/i18n/XCharacterClassification.hpp>
42 #include <com/sun/star/i18n/KCharacterType.hpp>
43 
44 
45 #include <unotools/localedatawrapper.hxx>
46 #include <unotools/calendarwrapper.hxx>
47 #include <unotools/charclass.hxx>
48 #include <unotools/misccfg.hxx>
49 
50 using namespace ::com::sun::star;
51 
52 // =======================================================================
53 
54 #define EDITMASK_LITERAL       'L'
55 #define EDITMASK_ALPHA         'a'
56 #define EDITMASK_UPPERALPHA    'A'
57 #define EDITMASK_ALPHANUM      'c'
58 #define EDITMASK_UPPERALPHANUM 'C'
59 #define EDITMASK_NUM           'N'
60 #define EDITMASK_NUMSPACE      'n'
61 #define EDITMASK_ALLCHAR       'x'
62 #define EDITMASK_UPPERALLCHAR  'X'
63 
ImplGetCharClass()64 uno::Reference< i18n::XCharacterClassification > ImplGetCharClass()
65 {
66     static uno::Reference< i18n::XCharacterClassification > xCharClass;
67     if ( !xCharClass.is() )
68         xCharClass = vcl::unohelper::CreateCharacterClassification();
69 
70     return xCharClass;
71 }
72 
73 // -----------------------------------------------------------------------
74 
ImplAddString(sal_Unicode * pBuf,const String & rStr)75 static sal_Unicode* ImplAddString( sal_Unicode* pBuf, const String& rStr )
76 {
77 	if ( rStr.Len() == 1 )
78 		*pBuf++ = rStr.GetChar(0);
79 	else if ( rStr.Len() == 0 )
80 		;
81 	else
82 	{
83 		memcpy( pBuf, rStr.GetBuffer(), rStr.Len() * sizeof(sal_Unicode) );
84 		pBuf += rStr.Len();
85 	}
86 	return pBuf;
87 }
88 
89 // -----------------------------------------------------------------------
90 
ImplAddNum(sal_Unicode * pBuf,sal_uLong nNumber,int nMinLen)91 static sal_Unicode* ImplAddNum( sal_Unicode* pBuf, sal_uLong nNumber, int nMinLen )
92 {
93 	// fill temp buffer with digits
94     sal_Unicode aTempBuf[30];
95     sal_Unicode* pTempBuf = aTempBuf;
96     do
97     {
98         *pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
99         pTempBuf++;
100         nNumber /= 10;
101         if ( nMinLen )
102             nMinLen--;
103     }
104     while ( nNumber );
105 
106     // fill with zeros up to the minimal length
107     while ( nMinLen > 0 )
108     {
109         *pBuf = '0';
110         pBuf++;
111         nMinLen--;
112     }
113 
114     // copy temp buffer to real buffer
115     do
116     {
117         pTempBuf--;
118         *pBuf = *pTempBuf;
119         pBuf++;
120     }
121     while ( pTempBuf != aTempBuf );
122 
123     return pBuf;
124 }
125 
126 // -----------------------------------------------------------------------
127 
ImplGetNum(const sal_Unicode * & rpBuf,sal_Bool & rbError)128 static sal_uInt16 ImplGetNum( const sal_Unicode*& rpBuf, sal_Bool& rbError )
129 {
130     if ( !*rpBuf )
131     {
132         rbError = sal_True;
133         return 0;
134     }
135 
136     sal_uInt16 nNumber = 0;
137     while( ( *rpBuf >= '0' ) && ( *rpBuf <= '9' ) )
138     {
139         nNumber *= 10;
140         nNumber += *rpBuf - '0';
141         rpBuf++;
142     }
143 
144     return nNumber;
145 }
146 
147 // -----------------------------------------------------------------------
148 
ImplSkipDelimiters(const sal_Unicode * & rpBuf)149 static void ImplSkipDelimiters( const sal_Unicode*& rpBuf )
150 {
151     while( ( *rpBuf == ',' ) || ( *rpBuf == '.' ) || ( *rpBuf == ';' ) ||
152            ( *rpBuf == ':' ) || ( *rpBuf == '-' ) || ( *rpBuf == '/' ) )
153     {
154         rpBuf++;
155     }
156 }
157 
158 // -----------------------------------------------------------------------
159 
ImplIsPatternChar(xub_Unicode cChar,sal_Char cEditMask)160 static int ImplIsPatternChar( xub_Unicode cChar, sal_Char cEditMask )
161 {
162     sal_Int32 nType = 0;
163 
164     try
165 	{
166         String aCharStr( cChar );
167         nType = ImplGetCharClass()->getStringType( aCharStr, 0, aCharStr.Len(), Application::GetSettings().GetLocale() );
168     }
169     catch ( ::com::sun::star::uno::Exception& )
170     {
171 		DBG_ERRORFILE( "ImplIsPatternChar: Exception caught!" );
172 		return sal_False;
173 	}
174 
175     if ( (cEditMask == EDITMASK_ALPHA) || (cEditMask == EDITMASK_UPPERALPHA) )
176     {
177         if( !CharClass::isLetterType( nType ) )
178             return sal_False;
179     }
180     else if ( cEditMask == EDITMASK_NUM )
181     {
182         if( !CharClass::isNumericType( nType ) )
183             return sal_False;
184     }
185     else if ( (cEditMask == EDITMASK_ALPHANUM) || (cEditMask == EDITMASK_UPPERALPHANUM) )
186     {
187         if( !CharClass::isLetterNumericType( nType ) )
188             return sal_False;
189     }
190     else if ( (cEditMask == EDITMASK_ALLCHAR) || (cEditMask == EDITMASK_UPPERALLCHAR) )
191     {
192         if ( cChar < 32 )
193             return sal_False;
194     }
195     else if ( cEditMask == EDITMASK_NUMSPACE )
196     {
197         if ( !CharClass::isNumericType( nType ) && ( cChar != ' ' ) )
198             return sal_False;
199     }
200     else
201         return sal_False;
202 
203     return sal_True;
204 }
205 
206 // -----------------------------------------------------------------------
207 
ImplPatternChar(xub_Unicode cChar,sal_Char cEditMask)208 static xub_Unicode ImplPatternChar( xub_Unicode cChar, sal_Char cEditMask )
209 {
210     if ( ImplIsPatternChar( cChar, cEditMask ) )
211     {
212         if ( (cEditMask == EDITMASK_UPPERALPHA) ||
213              (cEditMask == EDITMASK_UPPERALPHANUM) ||
214              ( cEditMask == EDITMASK_UPPERALLCHAR ) )
215         {
216             cChar = ImplGetCharClass()->toUpper( String(cChar),0,1,Application::GetSettings().GetLocale() )[0];
217         }
218         return cChar;
219     }
220     else
221         return 0;
222 }
223 
224 // -----------------------------------------------------------------------
225 
ImplKommaPointCharEqual(xub_Unicode c1,xub_Unicode c2)226 static int ImplKommaPointCharEqual( xub_Unicode c1, xub_Unicode c2 )
227 {
228     if ( c1 == c2 )
229         return sal_True;
230     else if ( ((c1 == '.') || (c1 == ',')) &&
231               ((c2 == '.') || (c2 == ',')) )
232         return sal_True;
233     else
234         return sal_False;
235 }
236 
237 // -----------------------------------------------------------------------
238 
ImplPatternReformat(const XubString & rStr,const ByteString & rEditMask,const XubString & rLiteralMask,sal_uInt16 nFormatFlags)239 static XubString ImplPatternReformat( const XubString& rStr,
240                                       const ByteString& rEditMask,
241                                       const XubString& rLiteralMask,
242                                       sal_uInt16 nFormatFlags )
243 {
244     if ( !rEditMask.Len() )
245         return rStr;
246 
247     XubString   aStr    = rStr;
248     XubString   aOutStr = rLiteralMask;
249     xub_Unicode cTempChar;
250     xub_Unicode cChar;
251     xub_Unicode cLiteral;
252     sal_Char    cMask;
253     xub_StrLen  nStrIndex = 0;
254     xub_StrLen  i = 0;
255     xub_StrLen  n;
256 
257     while ( i < rEditMask.Len() )
258     {
259         if ( nStrIndex >= aStr.Len() )
260             break;
261 
262         cChar = aStr.GetChar(nStrIndex);
263         cLiteral = rLiteralMask.GetChar(i);
264         cMask = rEditMask.GetChar(i);
265 
266         // Aktuelle Position ein Literal
267         if ( cMask == EDITMASK_LITERAL )
268         {
269             // Wenn es das Literal-Zeichen ist, uebernehmen, ansonsten
270             // ignorieren, da es das naechste gueltige Zeichen vom String
271             // sein kann
272             if ( ImplKommaPointCharEqual( cChar, cLiteral ) )
273                 nStrIndex++;
274             else
275             {
276                 // Ansonsten testen wir, ob es ein ungueltiges Zeichen ist.
277                 // Dies ist dann der Fall, wenn es nicht in das Muster
278                 // des naechsten nicht Literal-Zeichens passt
279                 n = i+1;
280                 while ( n < rEditMask.Len() )
281                 {
282                     if ( rEditMask.GetChar(n) != EDITMASK_LITERAL )
283                     {
284                         if ( !ImplIsPatternChar( cChar, rEditMask.GetChar(n) ) )
285                             nStrIndex++;
286                         break;
287                     }
288 
289                     n++;
290                 }
291             }
292         }
293         else
294         {
295             // Gueltiges Zeichen an der Stelle
296             cTempChar = ImplPatternChar( cChar, cMask );
297             if ( cTempChar )
298             {
299                 // dann Zeichen uebernehmen
300                 aOutStr.SetChar( i, cTempChar );
301                 nStrIndex++;
302             }
303             else
304             {
305                 // Wenn es das Literalzeichen ist, uebernehmen
306                 if ( cLiteral == cChar )
307                     nStrIndex++;
308                 else
309                 {
310                     // Wenn das ungueltige Zeichen das naechste Literalzeichen
311                     // sein kann, dann springen wir bis dahin vor, ansonten
312                     // das Zeichen ignorieren
313                     // Nur machen, wenn leere Literale erlaubt sind
314                     if ( nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS )
315                     {
316                         n = i;
317                         while ( n < rEditMask.Len() )
318                         {
319                             if ( rEditMask.GetChar( n ) == EDITMASK_LITERAL )
320                             {
321                                 if ( ImplKommaPointCharEqual( cChar, rLiteralMask.GetChar( n ) ) )
322                                     i = n+1;
323 
324                                 break;
325                             }
326 
327                             n++;
328                         }
329                     }
330 
331                     nStrIndex++;
332                     continue;
333                 }
334             }
335         }
336 
337         i++;
338     }
339 
340     return aOutStr;
341 }
342 
343 // -----------------------------------------------------------------------
344 
ImplPatternMaxPos(const XubString rStr,const ByteString & rEditMask,sal_uInt16 nFormatFlags,sal_Bool bSameMask,sal_uInt16 nCursorPos,sal_uInt16 & rPos)345 static void ImplPatternMaxPos( const XubString rStr, const ByteString& rEditMask,
346                                sal_uInt16 nFormatFlags, sal_Bool bSameMask,
347                                sal_uInt16 nCursorPos, sal_uInt16& rPos )
348 {
349 
350     // Letzte Position darf nicht groesser als der enthaltene String sein
351     xub_StrLen nMaxPos = rStr.Len();
352 
353     // Wenn keine leeren Literale erlaubt sind, auch Leerzeichen
354     // am Ende ignorieren
355     if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
356     {
357         while ( nMaxPos )
358         {
359             if ( (rEditMask.GetChar(nMaxPos-1) != EDITMASK_LITERAL) &&
360                  (rStr.GetChar(nMaxPos-1) != ' ') )
361                 break;
362             nMaxPos--;
363         }
364 
365         // Wenn wir vor einem Literal stehen, dann solange weitersuchen,
366         // bis erste Stelle nach Literal
367         xub_StrLen nTempPos = nMaxPos;
368         while ( nTempPos < rEditMask.Len() )
369         {
370             if ( rEditMask.GetChar(nTempPos) != EDITMASK_LITERAL )
371             {
372                 nMaxPos = nTempPos;
373                 break;
374             }
375             nTempPos++;
376         }
377     }
378 
379     if ( rPos > nMaxPos )
380         rPos = nMaxPos;
381     // Zeichen sollte nicht nach links wandern
382     if ( rPos < nCursorPos )
383         rPos = nCursorPos;
384 }
385 
386 // -----------------------------------------------------------------------
387 
ImplPatternProcessStrictModify(Edit * pEdit,const ByteString & rEditMask,const XubString & rLiteralMask,sal_uInt16 nFormatFlags,sal_Bool bSameMask)388 static void ImplPatternProcessStrictModify( Edit* pEdit,
389                                             const ByteString& rEditMask,
390                                             const XubString& rLiteralMask,
391                                             sal_uInt16 nFormatFlags, sal_Bool bSameMask )
392 {
393     XubString aText = pEdit->GetText();
394 
395     // Leerzeichen am Anfang entfernen
396     if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
397     {
398         xub_StrLen i = 0;
399         xub_StrLen nMaxLen = aText.Len();
400         while ( i < nMaxLen )
401         {
402             if ( (rEditMask.GetChar( i ) != EDITMASK_LITERAL) &&
403                  (aText.GetChar( i ) != ' ') )
404                 break;
405 
406             i++;
407         }
408         // Alle Literalzeichen beibehalten
409         while ( i && (rEditMask.GetChar( i ) == EDITMASK_LITERAL) )
410             i--;
411         aText.Erase( 0, i );
412     }
413 
414     XubString aNewText = ImplPatternReformat( aText, rEditMask, rLiteralMask, nFormatFlags );
415     if ( aNewText != aText )
416     {
417         // Selection so anpassen, das diese wenn sie vorher am Ende
418         // stand, immer noch am Ende steht
419         Selection aSel = pEdit->GetSelection();
420         sal_uLong nMaxSel = Max( aSel.Min(), aSel.Max() );
421         if ( nMaxSel >= aText.Len() )
422         {
423             xub_StrLen nMaxPos = aNewText.Len();
424             ImplPatternMaxPos( aNewText, rEditMask, nFormatFlags, bSameMask, (xub_StrLen)nMaxSel, nMaxPos );
425             if ( aSel.Min() == aSel.Max() )
426             {
427                 aSel.Min() = nMaxPos;
428                 aSel.Max() = aSel.Min();
429             }
430             else if ( aSel.Min() > aSel.Max() )
431                 aSel.Min() = nMaxPos;
432             else
433                 aSel.Max() = nMaxPos;
434         }
435         pEdit->SetText( aNewText, aSel );
436     }
437 }
438 
439 // -----------------------------------------------------------------------
440 
ImplPatternLeftPos(const ByteString & rEditMask,xub_StrLen nCursorPos)441 static xub_StrLen ImplPatternLeftPos( const ByteString& rEditMask, xub_StrLen nCursorPos )
442 {
443     // Vorheriges Zeichen suchen, was kein Literal ist
444     xub_StrLen nNewPos = nCursorPos;
445     xub_StrLen nTempPos = nNewPos;
446     while ( nTempPos )
447     {
448         if ( rEditMask.GetChar(nTempPos-1) != EDITMASK_LITERAL )
449         {
450             nNewPos = nTempPos-1;
451             break;
452         }
453         nTempPos--;
454     }
455     return nNewPos;
456 }
457 
458 // -----------------------------------------------------------------------
459 
ImplPatternRightPos(const XubString & rStr,const ByteString & rEditMask,sal_uInt16 nFormatFlags,sal_Bool bSameMask,xub_StrLen nCursorPos)460 static xub_StrLen ImplPatternRightPos( const XubString& rStr, const ByteString& rEditMask,
461                                        sal_uInt16 nFormatFlags, sal_Bool bSameMask,
462                                        xub_StrLen nCursorPos )
463 {
464     // Naechstes Zeichen suchen, was kein Literal ist
465     xub_StrLen nNewPos = nCursorPos;
466     xub_StrLen nTempPos = nNewPos;
467     while ( nTempPos < rEditMask.Len() )
468     {
469         if ( rEditMask.GetChar(nTempPos+1) != EDITMASK_LITERAL )
470         {
471             nNewPos = nTempPos+1;
472             break;
473         }
474         nTempPos++;
475     }
476     ImplPatternMaxPos( rStr, rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
477     return nNewPos;
478 }
479 
480 // -----------------------------------------------------------------------
481 
ImplPatternProcessKeyInput(Edit * pEdit,const KeyEvent & rKEvt,const ByteString & rEditMask,const XubString & rLiteralMask,sal_Bool bStrictFormat,sal_uInt16 nFormatFlags,sal_Bool bSameMask,sal_Bool & rbInKeyInput)482 static sal_Bool ImplPatternProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
483                                         const ByteString& rEditMask,
484                                         const XubString& rLiteralMask,
485                                         sal_Bool bStrictFormat,
486                                         sal_uInt16 nFormatFlags,
487                                         sal_Bool bSameMask,
488                                         sal_Bool& rbInKeyInput )
489 {
490     if ( !rEditMask.Len() || !bStrictFormat )
491         return sal_False;
492 
493     Selection   aOldSel     = pEdit->GetSelection();
494     KeyCode     aCode       = rKEvt.GetKeyCode();
495     xub_Unicode cChar       = rKEvt.GetCharCode();
496     sal_uInt16      nKeyCode    = aCode.GetCode();
497     sal_Bool        bShift      = aCode.IsShift();
498     xub_StrLen  nCursorPos  = (xub_StrLen)aOldSel.Max();
499     xub_StrLen  nNewPos;
500     xub_StrLen  nTempPos;
501 
502     if ( nKeyCode && !aCode.IsMod1() && !aCode.IsMod2() )
503     {
504         if ( nKeyCode == KEY_LEFT )
505         {
506             Selection aSel( ImplPatternLeftPos( rEditMask, nCursorPos ) );
507             if ( bShift )
508                 aSel.Min() = aOldSel.Min();
509             pEdit->SetSelection( aSel );
510             return sal_True;
511         }
512         else if ( nKeyCode == KEY_RIGHT )
513         {
514             // Hier nehmen wir Selectionsanfang als minimum, da falls durch
515             // Focus alles selektiert ist, ist eine kleine Position schon
516             // erlaubt.
517             Selection aSel( aOldSel );
518             aSel.Justify();
519             nCursorPos = (xub_StrLen)aSel.Min();
520             aSel.Max() = ImplPatternRightPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos );
521             if ( bShift )
522                 aSel.Min() = aOldSel.Min();
523             else
524                 aSel.Min() = aSel.Max();
525             pEdit->SetSelection( aSel );
526             return sal_True;
527         }
528         else if ( nKeyCode == KEY_HOME )
529         {
530             // Home ist Position des ersten nicht literalen Zeichens
531             nNewPos = 0;
532             while ( (nNewPos < rEditMask.Len()) &&
533                     (rEditMask.GetChar(nNewPos) == EDITMASK_LITERAL) )
534                 nNewPos++;
535             // Home sollte nicht nach rechts wandern
536             if ( nCursorPos < nNewPos )
537                 nNewPos = nCursorPos;
538             Selection aSel( nNewPos );
539             if ( bShift )
540                 aSel.Min() = aOldSel.Min();
541             pEdit->SetSelection( aSel );
542             return sal_True;
543         }
544         else if ( nKeyCode == KEY_END )
545         {
546             // End ist die Position des letzten nicht literalen Zeichens
547             nNewPos = rEditMask.Len();
548             while ( nNewPos &&
549                     (rEditMask.GetChar(nNewPos-1) == EDITMASK_LITERAL) )
550                 nNewPos--;
551             // Hier nehmen wir Selectionsanfang als minimum, da falls durch
552             // Focus alles selektiert ist, ist eine kleine Position schon
553             // erlaubt.
554             Selection aSel( aOldSel );
555             aSel.Justify();
556             nCursorPos = (xub_StrLen)aSel.Min();
557             ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
558             aSel.Max() = nNewPos;
559             if ( bShift )
560                 aSel.Min() = aOldSel.Min();
561             else
562                 aSel.Min() = aSel.Max();
563             pEdit->SetSelection( aSel );
564             return sal_True;
565         }
566         else if ( (nKeyCode == KEY_BACKSPACE) || (nKeyCode == KEY_DELETE) )
567         {
568             XubString   aStr( pEdit->GetText() );
569             XubString   aOldStr = aStr;
570             Selection   aSel = aOldSel;
571 
572             aSel.Justify();
573             nNewPos = (xub_StrLen)aSel.Min();
574 
575             // Wenn Selection, dann diese Loeschen
576             if ( aSel.Len() )
577             {
578                 if ( bSameMask )
579                     aStr.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
580                 else
581                 {
582                     XubString aRep = rLiteralMask.Copy( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
583                     aStr.Replace( (xub_StrLen)aSel.Min(), aRep.Len(), aRep );
584                 }
585             }
586             else
587             {
588                 if ( nKeyCode == KEY_BACKSPACE )
589                 {
590                     nTempPos = nNewPos;
591                     nNewPos = ImplPatternLeftPos( rEditMask, nTempPos );
592                 }
593                 else
594                     nTempPos = ImplPatternRightPos( aStr, rEditMask, nFormatFlags, bSameMask, nNewPos );
595 
596                 if ( nNewPos != nTempPos )
597                 {
598                     if ( bSameMask )
599                     {
600                         if ( rEditMask.GetChar( nNewPos ) != EDITMASK_LITERAL )
601                             aStr.Erase( nNewPos, 1 );
602                     }
603                     else
604                     {
605                         XubString aTempStr = rLiteralMask.Copy( nNewPos, 1 );
606                         aStr.Replace( nNewPos, aTempStr.Len(), aTempStr );
607                     }
608                 }
609             }
610 
611             if ( aOldStr != aStr )
612             {
613                 if ( bSameMask )
614                     aStr = ImplPatternReformat( aStr, rEditMask, rLiteralMask, nFormatFlags );
615                 rbInKeyInput = sal_True;
616                 pEdit->SetText( aStr, Selection( nNewPos ) );
617                 pEdit->SetModifyFlag();
618                 pEdit->Modify();
619                 rbInKeyInput = sal_False;
620             }
621             else
622                 pEdit->SetSelection( Selection( nNewPos ) );
623 
624             return sal_True;
625         }
626         else if ( nKeyCode == KEY_INSERT )
627         {
628             // InsertModus kann man beim PatternField nur einstellen,
629             // wenn Maske an jeder Eingabeposition die gleiche
630             // ist
631             if ( !bSameMask )
632             {
633                 Sound::Beep();
634                 return sal_True;
635             }
636         }
637     }
638 
639     if ( rKEvt.GetKeyCode().IsMod2() || (cChar < 32) || (cChar == 127) )
640         return sal_False;
641 
642     Selection aSel = aOldSel;
643     aSel.Justify();
644     nNewPos = (xub_StrLen)aSel.Min();
645 
646     if ( nNewPos < rEditMask.Len() )
647     {
648         xub_Unicode cPattChar = ImplPatternChar( cChar, rEditMask.GetChar(nNewPos) );
649         if ( cPattChar )
650             cChar = cPattChar;
651         else
652         {
653             // Wenn kein gueltiges Zeichen, dann testen wir, ob der
654             // Anwender zum naechsten Literal springen wollte. Dies machen
655             // wir nur, wenn er hinter einem Zeichen steht, damit
656             // eingebene Literale die automatisch uebersprungenen wurden
657             // nicht dazu fuehren, das der Anwender dann da steht, wo
658             // er nicht stehen wollte.
659             if ( nNewPos &&
660                  (rEditMask.GetChar(nNewPos-1) != EDITMASK_LITERAL) &&
661                  !aSel.Len() )
662             {
663                 // Naechstes Zeichen suchen, was kein Literal ist
664                 nTempPos = nNewPos;
665                 while ( nTempPos < rEditMask.Len() )
666                 {
667                     if ( rEditMask.GetChar(nTempPos) == EDITMASK_LITERAL )
668                     {
669                         // Gilt nur, wenn ein Literalzeichen vorhanden
670                         if ( (rEditMask.GetChar(nTempPos+1) != EDITMASK_LITERAL ) &&
671                              ImplKommaPointCharEqual( cChar, rLiteralMask.GetChar(nTempPos) ) )
672                         {
673                             nTempPos++;
674                             ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nNewPos, nTempPos );
675                             if ( nTempPos > nNewPos )
676                             {
677                                 pEdit->SetSelection( Selection( nTempPos ) );
678                                 return sal_True;
679                             }
680                         }
681                         break;
682                     }
683                     nTempPos++;
684                 }
685             }
686 
687             cChar = 0;
688         }
689     }
690     else
691         cChar = 0;
692     if ( cChar )
693     {
694         XubString   aStr = pEdit->GetText();
695         sal_Bool        bError = sal_False;
696         if ( bSameMask && pEdit->IsInsertMode() )
697         {
698             // Text um Spacezeichen und Literale am Ende kuerzen, bis zur
699             // aktuellen Position
700             xub_StrLen n = aStr.Len();
701             while ( n && (n > nNewPos) )
702             {
703                 if ( (aStr.GetChar( n-1 ) != ' ') &&
704                      ((n > rEditMask.Len()) || (rEditMask.GetChar(n-1) != EDITMASK_LITERAL)) )
705                     break;
706 
707                 n--;
708             }
709             aStr.Erase( n );
710 
711             if ( aSel.Len() )
712                 aStr.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
713 
714             if ( aStr.Len() < rEditMask.Len() )
715             {
716                 // String evtl. noch bis Cursor-Position erweitern
717                 if ( aStr.Len() < nNewPos )
718                     aStr += rLiteralMask.Copy( aStr.Len(), nNewPos-aStr.Len() );
719                 if ( nNewPos < aStr.Len() )
720                     aStr.Insert( cChar, nNewPos );
721                 else if ( nNewPos < rEditMask.Len() )
722                     aStr += cChar;
723                 aStr = ImplPatternReformat( aStr, rEditMask, rLiteralMask, nFormatFlags );
724             }
725             else
726                 bError = sal_True;
727         }
728         else
729         {
730             if ( aSel.Len() )
731             {
732                 // Selection loeschen
733                 XubString aRep = rLiteralMask.Copy( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
734                 aStr.Replace( (xub_StrLen)aSel.Min(), aRep.Len(), aRep );
735             }
736 
737             if ( nNewPos < aStr.Len() )
738                 aStr.SetChar( nNewPos, cChar );
739             else if ( nNewPos < rEditMask.Len() )
740                 aStr += cChar;
741         }
742 
743         if ( bError )
744             Sound::Beep();
745         else
746         {
747             rbInKeyInput = sal_True;
748             Selection aNewSel( ImplPatternRightPos( aStr, rEditMask, nFormatFlags, bSameMask, nNewPos ) );
749             pEdit->SetText( aStr, aNewSel );
750             pEdit->SetModifyFlag();
751             pEdit->Modify();
752             rbInKeyInput = sal_False;
753         }
754     }
755     else
756         Sound::Beep();
757 
758     return sal_True;
759 }
760 
761 // -----------------------------------------------------------------------
762 
ImplSetMask(const ByteString & rEditMask,const XubString & rLiteralMask)763 void PatternFormatter::ImplSetMask( const ByteString& rEditMask,
764                                     const XubString& rLiteralMask )
765 {
766     maEditMask      = rEditMask;
767     maLiteralMask   = rLiteralMask;
768     mbSameMask      = sal_True;
769 
770     if ( maEditMask.Len() != maLiteralMask.Len() )
771     {
772         if ( maEditMask.Len() < maLiteralMask.Len() )
773             maLiteralMask.Erase( maEditMask.Len() );
774         else
775             maLiteralMask.Expand( maEditMask.Len(), ' ' );
776     }
777 
778     // StrictModus erlaubt nur Input-Mode, wenn als Maske nur
779     // gleiche Zeichen zugelassen werden und als Vorgabe nur
780     // Spacezeichen vorgegeben werden, die durch die Maske
781     // nicht zugelassen sind
782     xub_StrLen  i = 0;
783     sal_Char    c = 0;
784     while ( i < rEditMask.Len() )
785     {
786         sal_Char cTemp = rEditMask.GetChar( i );
787         if ( cTemp != EDITMASK_LITERAL )
788         {
789             if ( (cTemp == EDITMASK_ALLCHAR) ||
790                  (cTemp == EDITMASK_UPPERALLCHAR) ||
791                  (cTemp == EDITMASK_NUMSPACE) )
792             {
793                 mbSameMask = sal_False;
794                 break;
795             }
796             if ( i < rLiteralMask.Len() )
797             {
798                 if ( rLiteralMask.GetChar( i ) != ' ' )
799                 {
800                     mbSameMask = sal_False;
801                     break;
802                 }
803             }
804             if ( !c )
805                 c = cTemp;
806             if ( cTemp != c )
807             {
808                 mbSameMask = sal_False;
809                 break;
810             }
811         }
812         i++;
813     }
814 }
815 
816 // -----------------------------------------------------------------------
817 
PatternFormatter()818 PatternFormatter::PatternFormatter()
819 {
820     mnFormatFlags       = 0;
821     mbSameMask          = sal_True;
822     mbInPattKeyInput    = sal_False;
823 }
824 
825 // -----------------------------------------------------------------------
826 
ImplLoadRes(const ResId & rResId)827 void PatternFormatter::ImplLoadRes( const ResId& rResId )
828 {
829     ByteString  aEditMask;
830     XubString   aLiteralMask;
831     ResMgr*     pMgr = rResId.GetResMgr();
832     if( pMgr )
833     {
834         sal_uLong       nMask = pMgr->ReadLong();
835 
836         if ( PATTERNFORMATTER_STRICTFORMAT & nMask )
837             SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
838 
839         if ( PATTERNFORMATTER_EDITMASK & nMask )
840             aEditMask = ByteString( pMgr->ReadString(), RTL_TEXTENCODING_ASCII_US );
841 
842         if ( PATTERNFORMATTER_LITTERALMASK & nMask )
843             aLiteralMask = pMgr->ReadString();
844 
845         if ( (PATTERNFORMATTER_EDITMASK | PATTERNFORMATTER_LITTERALMASK) & nMask )
846             ImplSetMask( aEditMask, aLiteralMask );
847     }
848 }
849 
850 // -----------------------------------------------------------------------
851 
~PatternFormatter()852 PatternFormatter::~PatternFormatter()
853 {
854 }
855 
856 // -----------------------------------------------------------------------
857 
SetMask(const ByteString & rEditMask,const XubString & rLiteralMask)858 void PatternFormatter::SetMask( const ByteString& rEditMask,
859                                 const XubString& rLiteralMask )
860 {
861     ImplSetMask( rEditMask, rLiteralMask );
862     ReformatAll();
863 }
864 
865 // -----------------------------------------------------------------------
866 
SetString(const XubString & rStr)867 void PatternFormatter::SetString( const XubString& rStr )
868 {
869     maFieldString = rStr;
870     if ( GetField() )
871     {
872         GetField()->SetText( rStr );
873         MarkToBeReformatted( sal_False );
874     }
875 }
876 
877 // -----------------------------------------------------------------------
878 
GetString() const879 XubString PatternFormatter::GetString() const
880 {
881     if ( !GetField() )
882         return ImplGetSVEmptyStr();
883     else
884         return ImplPatternReformat( GetField()->GetText(), maEditMask, maLiteralMask, mnFormatFlags );
885 }
886 
887 // -----------------------------------------------------------------------
888 
Reformat()889 void PatternFormatter::Reformat()
890 {
891     if ( GetField() )
892     {
893         ImplSetText( ImplPatternReformat( GetField()->GetText(), maEditMask, maLiteralMask, mnFormatFlags ) );
894         if ( !mbSameMask && IsStrictFormat() && !GetField()->IsReadOnly() )
895             GetField()->SetInsertMode( sal_False );
896     }
897 }
898 
899 // -----------------------------------------------------------------------
900 
SelectFixedFont()901 void PatternFormatter::SelectFixedFont()
902 {
903     if ( GetField() )
904     {
905         Font aFont = OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, Application::GetSettings().GetLanguage(), 0 );
906         Font aControlFont;
907         aControlFont.SetName( aFont.GetName() );
908         aControlFont.SetFamily( aFont.GetFamily() );
909         aControlFont.SetPitch( aFont.GetPitch() );
910         GetField()->SetControlFont( aControlFont );
911     }
912 }
913 
914 // -----------------------------------------------------------------------
915 
PatternField(Window * pParent,WinBits nWinStyle)916 PatternField::PatternField( Window* pParent, WinBits nWinStyle ) :
917     SpinField( pParent, nWinStyle )
918 {
919     SetField( this );
920     Reformat();
921 }
922 
923 // -----------------------------------------------------------------------
924 
PatternField(Window * pParent,const ResId & rResId)925 PatternField::PatternField( Window* pParent, const ResId& rResId ) :
926     SpinField( WINDOW_PATTERNFIELD )
927 {
928     rResId.SetRT( RSC_PATTERNFIELD );
929     WinBits nStyle = ImplInitRes( rResId );
930     ImplInit( pParent, nStyle );
931     SetField( this );
932     SpinField::ImplLoadRes( rResId );
933     PatternFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
934     Reformat();
935 
936     if ( !(nStyle & WB_HIDE ) )
937         Show();
938 }
939 
940 // -----------------------------------------------------------------------
941 
~PatternField()942 PatternField::~PatternField()
943 {
944 }
945 
946 // -----------------------------------------------------------------------
947 
PreNotify(NotifyEvent & rNEvt)948 long PatternField::PreNotify( NotifyEvent& rNEvt )
949 {
950     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
951     {
952         if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
953                                          IsStrictFormat(), GetFormatFlags(),
954                                          ImplIsSameMask(), ImplGetInPattKeyInput() ) )
955             return 1;
956     }
957 
958     return SpinField::PreNotify( rNEvt );
959 }
960 
961 // -----------------------------------------------------------------------
962 
Notify(NotifyEvent & rNEvt)963 long PatternField::Notify( NotifyEvent& rNEvt )
964 {
965     if ( rNEvt.GetType() == EVENT_GETFOCUS )
966         MarkToBeReformatted( sal_False );
967     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
968     {
969         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
970             Reformat();
971     }
972 
973     return SpinField::Notify( rNEvt );
974 }
975 
976 // -----------------------------------------------------------------------
977 
Modify()978 void PatternField::Modify()
979 {
980     if ( !ImplGetInPattKeyInput() )
981     {
982         if ( IsStrictFormat() )
983             ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
984         else
985             MarkToBeReformatted( sal_True );
986     }
987 
988     SpinField::Modify();
989 }
990 
991 // -----------------------------------------------------------------------
992 
PatternBox(Window * pParent,WinBits nWinStyle)993 PatternBox::PatternBox( Window* pParent, WinBits nWinStyle ) :
994     ComboBox( pParent, nWinStyle )
995 {
996     SetField( this );
997     Reformat();
998 }
999 
1000 // -----------------------------------------------------------------------
1001 
PatternBox(Window * pParent,const ResId & rResId)1002 PatternBox::PatternBox( Window* pParent, const ResId& rResId ) :
1003     ComboBox( WINDOW_PATTERNBOX )
1004 {
1005     rResId.SetRT( RSC_PATTERNBOX );
1006     WinBits nStyle = ImplInitRes( rResId );
1007     ImplInit( pParent, nStyle );
1008 
1009     SetField( this );
1010     ComboBox::ImplLoadRes( rResId );
1011     PatternFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1012     Reformat();
1013 
1014     if ( !(nStyle & WB_HIDE ) )
1015         Show();
1016 }
1017 
1018 // -----------------------------------------------------------------------
1019 
~PatternBox()1020 PatternBox::~PatternBox()
1021 {
1022 }
1023 
1024 // -----------------------------------------------------------------------
1025 
PreNotify(NotifyEvent & rNEvt)1026 long PatternBox::PreNotify( NotifyEvent& rNEvt )
1027 {
1028     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1029     {
1030         if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
1031                                          IsStrictFormat(), GetFormatFlags(),
1032                                          ImplIsSameMask(), ImplGetInPattKeyInput() ) )
1033             return 1;
1034     }
1035 
1036     return ComboBox::PreNotify( rNEvt );
1037 }
1038 
1039 // -----------------------------------------------------------------------
1040 
Notify(NotifyEvent & rNEvt)1041 long PatternBox::Notify( NotifyEvent& rNEvt )
1042 {
1043     if ( rNEvt.GetType() == EVENT_GETFOCUS )
1044         MarkToBeReformatted( sal_False );
1045     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1046     {
1047         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1048             Reformat();
1049     }
1050 
1051     return ComboBox::Notify( rNEvt );
1052 }
1053 
1054 // -----------------------------------------------------------------------
1055 
Modify()1056 void PatternBox::Modify()
1057 {
1058     if ( !ImplGetInPattKeyInput() )
1059     {
1060         if ( IsStrictFormat() )
1061             ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
1062         else
1063             MarkToBeReformatted( sal_True );
1064     }
1065 
1066     ComboBox::Modify();
1067 }
1068 
1069 // -----------------------------------------------------------------------
1070 
ReformatAll()1071 void PatternBox::ReformatAll()
1072 {
1073     XubString aStr;
1074     SetUpdateMode( sal_False );
1075     sal_uInt16 nEntryCount = GetEntryCount();
1076     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
1077     {
1078         aStr = ImplPatternReformat( GetEntry( i ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
1079         RemoveEntry( i );
1080         InsertEntry( aStr, i );
1081     }
1082     PatternFormatter::Reformat();
1083     SetUpdateMode( sal_True );
1084 }
1085 
1086 // -----------------------------------------------------------------------
1087 
InsertString(const XubString & rStr,sal_uInt16 nPos)1088 void PatternBox::InsertString( const XubString& rStr, sal_uInt16 nPos )
1089 {
1090     ComboBox::InsertEntry( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ), nPos );
1091 }
1092 
1093 // -----------------------------------------------------------------------
1094 
RemoveString(const XubString & rStr)1095 void PatternBox::RemoveString( const XubString& rStr )
1096 {
1097     ComboBox::RemoveEntry( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ) );
1098 }
1099 
1100 // -----------------------------------------------------------------------
1101 
GetString(sal_uInt16 nPos) const1102 XubString PatternBox::GetString( sal_uInt16 nPos ) const
1103 {
1104     return ImplPatternReformat( ComboBox::GetEntry( nPos ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
1105 }
1106 
1107 // -----------------------------------------------------------------------
1108 
GetStringPos(const XubString & rStr) const1109 sal_uInt16 PatternBox::GetStringPos( const XubString& rStr ) const
1110 {
1111     return ComboBox::GetEntryPos( ImplPatternReformat( rStr, GetEditMask(), GetLiteralMask(), GetFormatFlags() ) );
1112 }
1113 
1114 // =======================================================================
1115 
ImplGetExtFormat(DateFormat eOld)1116 static ExtDateFieldFormat ImplGetExtFormat( DateFormat eOld )
1117 {
1118     switch( eOld )
1119     {
1120         case DMY:   return XTDATEF_SHORT_DDMMYY;
1121         case MDY:   return XTDATEF_SHORT_MMDDYY;
1122         default:    return XTDATEF_SHORT_YYMMDD;
1123     }
1124 }
1125 
1126 // -----------------------------------------------------------------------
1127 
ImplCutNumberFromString(XubString & rStr)1128 static sal_uInt16 ImplCutNumberFromString( XubString& rStr )
1129 {
1130     // Nach Zahl suchen
1131     while ( rStr.Len() && !(rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
1132         rStr.Erase( 0, 1 );
1133     if ( !rStr.Len() )
1134         return 0;
1135     XubString aNumStr;
1136     while ( rStr.Len() && (rStr.GetChar( 0 ) >= '0' && rStr.GetChar( 0 ) <= '9') )
1137     {
1138         aNumStr.Insert( rStr.GetChar( 0 ) );
1139         rStr.Erase( 0, 1 );
1140     }
1141     return (sal_uInt16)aNumStr.ToInt32();
1142 }
1143 
1144 // -----------------------------------------------------------------------
1145 
ImplCutMonthName(XubString & rStr,const XubString & _rLookupMonthName)1146 static sal_Bool ImplCutMonthName( XubString& rStr, const XubString& _rLookupMonthName )
1147 {
1148     sal_uInt16 nPos = rStr.Search( _rLookupMonthName );
1149     if ( nPos != STRING_NOTFOUND )
1150     {
1151         rStr.Erase( 0, nPos + _rLookupMonthName.Len() );
1152         return sal_True;
1153     }
1154     return sal_False;
1155 }
1156 
1157 // -----------------------------------------------------------------------
1158 
ImplCutMonthFromString(XubString & rStr,const CalendarWrapper & rCalendarWrapper)1159 static sal_uInt16 ImplCutMonthFromString( XubString& rStr, const CalendarWrapper& rCalendarWrapper )
1160 {
1161     // search for a month' name
1162     for ( sal_uInt16 i=1; i <= 12; i++ )
1163     {
1164         String aMonthName = rCalendarWrapper.getMonths()[i-1].FullName;
1165         // long month name?
1166         if ( ImplCutMonthName( rStr, aMonthName ) )
1167             return i;
1168 
1169         // short month name?
1170         String aAbbrevMonthName = rCalendarWrapper.getMonths()[i-1].AbbrevName;
1171         if ( ImplCutMonthName( rStr, aAbbrevMonthName ) )
1172             return i;
1173     }
1174 
1175     return ImplCutNumberFromString( rStr );
1176 }
1177 
1178 // -----------------------------------------------------------------------
1179 
ImplGetDateSep(const LocaleDataWrapper & rLocaleDataWrapper,ExtDateFieldFormat eFormat)1180 static String ImplGetDateSep( const LocaleDataWrapper& rLocaleDataWrapper, ExtDateFieldFormat eFormat )
1181 {
1182     String aDateSep = rLocaleDataWrapper.getDateSep();
1183 
1184     if ( ( eFormat == XTDATEF_SHORT_YYMMDD_DIN5008 ) || ( eFormat == XTDATEF_SHORT_YYYYMMDD_DIN5008 ) )
1185         aDateSep = String( RTL_CONSTASCII_USTRINGPARAM( "-" ) );
1186 
1187     return aDateSep;
1188 }
1189 
ImplDateProcessKeyInput(Edit *,const KeyEvent & rKEvt,ExtDateFieldFormat eFormat,const LocaleDataWrapper & rLocaleDataWrapper)1190 static sal_Bool ImplDateProcessKeyInput( Edit*, const KeyEvent& rKEvt, ExtDateFieldFormat eFormat,
1191                                      const LocaleDataWrapper& rLocaleDataWrapper  )
1192 {
1193     xub_Unicode cChar = rKEvt.GetCharCode();
1194     sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
1195     if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
1196          (nGroup == KEYGROUP_MISC)||
1197          ((cChar >= '0') && (cChar <= '9')) ||
1198          (cChar == ImplGetDateSep( rLocaleDataWrapper, eFormat ).GetChar(0) ) )
1199         return sal_False;
1200     else
1201         return sal_True;
1202 }
1203 
1204 // -----------------------------------------------------------------------
1205 
ImplDateGetValue(const XubString & rStr,Date & rDate,ExtDateFieldFormat eDateFormat,const LocaleDataWrapper & rLocaleDataWrapper,const CalendarWrapper & rCalendarWrapper,const AllSettings &)1206 static sal_Bool ImplDateGetValue( const XubString& rStr, Date& rDate, ExtDateFieldFormat eDateFormat,
1207                               const LocaleDataWrapper& rLocaleDataWrapper, const CalendarWrapper& rCalendarWrapper,
1208                               const AllSettings& )
1209 {
1210     sal_uInt16 nDay = 0;
1211     sal_uInt16 nMonth = 0;
1212     sal_uInt16 nYear = 0;
1213     sal_Bool bYear = sal_True;
1214     sal_Bool bError = sal_False;
1215     String aStr( rStr );
1216 
1217     if ( eDateFormat == XTDATEF_SYSTEM_LONG )
1218     {
1219         DateFormat eFormat = rLocaleDataWrapper.getLongDateFormat();
1220         switch( eFormat )
1221         {
1222             case MDY:
1223                 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
1224                 nDay = ImplCutNumberFromString( aStr );
1225                 nYear  = ImplCutNumberFromString( aStr );
1226                 break;
1227             case DMY:
1228                 nDay = ImplCutNumberFromString( aStr );
1229                 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
1230                 nYear  = ImplCutNumberFromString( aStr );
1231                 break;
1232             case YMD:
1233             default:
1234                 nYear = ImplCutNumberFromString( aStr );
1235                 nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
1236                 nDay  = ImplCutNumberFromString( aStr );
1237                 break;
1238         }
1239     }
1240     else
1241     {
1242         // Check if year is present:
1243         String aDateSep = ImplGetDateSep( rLocaleDataWrapper, eDateFormat );
1244         sal_uInt16 nSepPos = aStr.Search( aDateSep );
1245         if ( nSepPos == STRING_NOTFOUND )
1246             return sal_False;
1247         nSepPos = aStr.Search( aDateSep, nSepPos+1 );
1248         if ( ( nSepPos == STRING_NOTFOUND ) || ( nSepPos == (aStr.Len()-1) ) )
1249         {
1250             bYear = sal_False;
1251             nYear = Date().GetYear();
1252         }
1253 
1254         const sal_Unicode* pBuf = aStr.GetBuffer();
1255         ImplSkipDelimiters( pBuf );
1256 
1257         switch ( eDateFormat )
1258         {
1259             case XTDATEF_SHORT_DDMMYY:
1260             case XTDATEF_SHORT_DDMMYYYY:
1261             {
1262                 nDay = ImplGetNum( pBuf, bError );
1263                 ImplSkipDelimiters( pBuf );
1264                 nMonth = ImplGetNum( pBuf, bError );
1265                 ImplSkipDelimiters( pBuf );
1266                 if ( bYear )
1267                     nYear = ImplGetNum( pBuf, bError );
1268             }
1269             break;
1270             case XTDATEF_SHORT_MMDDYY:
1271             case XTDATEF_SHORT_MMDDYYYY:
1272             {
1273                 nMonth = ImplGetNum( pBuf, bError );
1274                 ImplSkipDelimiters( pBuf );
1275                 nDay = ImplGetNum( pBuf, bError );
1276                 ImplSkipDelimiters( pBuf );
1277                 if ( bYear )
1278                     nYear = ImplGetNum( pBuf, bError );
1279             }
1280             break;
1281             case XTDATEF_SHORT_YYMMDD:
1282             case XTDATEF_SHORT_YYYYMMDD:
1283             case XTDATEF_SHORT_YYMMDD_DIN5008:
1284             case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1285             {
1286                 if ( bYear )
1287                     nYear = ImplGetNum( pBuf, bError );
1288                 ImplSkipDelimiters( pBuf );
1289                 nMonth = ImplGetNum( pBuf, bError );
1290                 ImplSkipDelimiters( pBuf );
1291                 nDay = ImplGetNum( pBuf, bError );
1292             }
1293             break;
1294 
1295             default:
1296             {
1297                 DBG_ERROR( "DateFormat???" );
1298             }
1299         }
1300     }
1301 
1302     if ( bError || !nDay || !nMonth )
1303         return sal_False;
1304 
1305     Date aNewDate( nDay, nMonth, nYear );
1306 	DateFormatter::ExpandCentury( aNewDate, utl::MiscCfg().GetYear2000() );
1307     if ( aNewDate.IsValid() )
1308     {
1309         rDate = aNewDate;
1310         return sal_True;
1311     }
1312     return sal_False;
1313 }
1314 
1315 // -----------------------------------------------------------------------
1316 
ImplDateReformat(const XubString & rStr,XubString & rOutStr,const AllSettings & rSettings)1317 sal_Bool DateFormatter::ImplDateReformat( const XubString& rStr, XubString& rOutStr, const AllSettings& rSettings )
1318 {
1319     Date aDate( 0, 0, 0 );
1320     if ( !ImplDateGetValue( rStr, aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
1321         return sal_True;
1322 
1323     Date aTempDate = aDate;
1324     if ( aTempDate > GetMax() )
1325         aTempDate = GetMax();
1326     else if ( aTempDate < GetMin() )
1327         aTempDate = GetMin();
1328 
1329     if ( GetErrorHdl().IsSet() && (aDate != aTempDate) )
1330     {
1331         maCorrectedDate = aTempDate;
1332         if( !GetErrorHdl().Call( this ) )
1333         {
1334             maCorrectedDate = Date();
1335             return sal_False;
1336         }
1337         else
1338             maCorrectedDate = Date();
1339     }
1340 
1341     rOutStr = ImplGetDateAsText( aTempDate, rSettings );
1342 
1343     return sal_True;
1344 }
1345 
1346 // -----------------------------------------------------------------------
1347 
ImplGetDateAsText(const Date & rDate,const AllSettings &) const1348 XubString DateFormatter::ImplGetDateAsText( const Date& rDate,
1349                                             const AllSettings& ) const
1350 {
1351     sal_Bool bShowCentury = sal_False;
1352     switch ( GetExtDateFormat() )
1353     {
1354         case XTDATEF_SYSTEM_SHORT_YYYY:
1355         case XTDATEF_SYSTEM_LONG:
1356         case XTDATEF_SHORT_DDMMYYYY:
1357         case XTDATEF_SHORT_MMDDYYYY:
1358         case XTDATEF_SHORT_YYYYMMDD:
1359         case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1360         {
1361             bShowCentury = sal_True;
1362         }
1363         break;
1364         default:
1365         {
1366             bShowCentury = sal_False;
1367         }
1368     }
1369 
1370     if ( !bShowCentury )
1371     {
1372         // Check if I have to use force showing the century
1373         sal_uInt16 nTwoDigitYearStart = utl::MiscCfg().GetYear2000();
1374         sal_uInt16 nYear = rDate.GetYear();
1375 
1376         // Wenn Jahr nicht im 2stelligen Grenzbereich liegt,
1377         if ( (nYear < nTwoDigitYearStart) || (nYear >= nTwoDigitYearStart+100) )
1378             bShowCentury = sal_True;
1379     }
1380 
1381     sal_Unicode aBuf[128];
1382     sal_Unicode* pBuf = aBuf;
1383 
1384     String aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), GetExtDateFormat( sal_True ) );
1385     sal_uInt16 nDay = rDate.GetDay();
1386     sal_uInt16 nMonth = rDate.GetMonth();
1387     sal_uInt16 nYear = rDate.GetYear();
1388     sal_uInt16 nYearLen = bShowCentury ? 4 : 2;
1389 
1390     if ( !bShowCentury )
1391         nYear %= 100;
1392 
1393     switch ( GetExtDateFormat( sal_True ) )
1394     {
1395         case XTDATEF_SYSTEM_LONG:
1396         {
1397             return ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, sal_False, 1, !bShowCentury );
1398         }
1399         case XTDATEF_SHORT_DDMMYY:
1400         case XTDATEF_SHORT_DDMMYYYY:
1401         {
1402             pBuf = ImplAddNum( pBuf, nDay, 2 );
1403             pBuf = ImplAddString( pBuf, aDateSep );
1404             pBuf = ImplAddNum( pBuf, nMonth, 2 );
1405             pBuf = ImplAddString( pBuf, aDateSep );
1406             pBuf = ImplAddNum( pBuf, nYear, nYearLen );
1407         }
1408         break;
1409         case XTDATEF_SHORT_MMDDYY:
1410         case XTDATEF_SHORT_MMDDYYYY:
1411         {
1412             pBuf = ImplAddNum( pBuf, nMonth, 2 );
1413             pBuf = ImplAddString( pBuf, aDateSep );
1414             pBuf = ImplAddNum( pBuf, nDay, 2 );
1415             pBuf = ImplAddString( pBuf, aDateSep );
1416             pBuf = ImplAddNum( pBuf, nYear, nYearLen );
1417         }
1418         break;
1419         case XTDATEF_SHORT_YYMMDD:
1420         case XTDATEF_SHORT_YYYYMMDD:
1421         case XTDATEF_SHORT_YYMMDD_DIN5008:
1422         case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1423         {
1424             pBuf = ImplAddNum( pBuf, nYear, nYearLen );
1425             pBuf = ImplAddString( pBuf, aDateSep );
1426             pBuf = ImplAddNum( pBuf, nMonth, 2 );
1427             pBuf = ImplAddString( pBuf, aDateSep );
1428             pBuf = ImplAddNum( pBuf, nDay, 2 );
1429         }
1430         break;
1431         default:
1432         {
1433             DBG_ERROR( "DateFormat???" );
1434         }
1435     }
1436 
1437     return String( aBuf, (xub_StrLen)(sal_uLong)(pBuf-aBuf) );
1438 }
1439 
1440 // -----------------------------------------------------------------------
1441 
ImplDateIncrementDay(Date & rDate,sal_Bool bUp)1442 static void ImplDateIncrementDay( Date& rDate, sal_Bool bUp )
1443 {
1444     DateFormatter::ExpandCentury( rDate );
1445 
1446     if ( bUp )
1447     {
1448         if ( (rDate.GetDay() != 31) || (rDate.GetMonth() != 12) || (rDate.GetYear() != 9999) )
1449             rDate++;
1450     }
1451     else
1452     {
1453         if ( (rDate.GetDay() != 1 ) || (rDate.GetMonth() != 1) || (rDate.GetYear() != 0) )
1454             rDate--;
1455     }
1456 }
1457 
1458 // -----------------------------------------------------------------------
1459 
ImplDateIncrementMonth(Date & rDate,sal_Bool bUp)1460 static void ImplDateIncrementMonth( Date& rDate, sal_Bool bUp )
1461 {
1462     DateFormatter::ExpandCentury( rDate );
1463 
1464     sal_uInt16 nMonth = rDate.GetMonth();
1465     sal_uInt16 nYear = rDate.GetYear();
1466     if ( bUp )
1467     {
1468         if ( (nMonth == 12) && (nYear < 9999) )
1469         {
1470             rDate.SetMonth( 1 );
1471             rDate.SetYear( nYear + 1 );
1472         }
1473         else
1474         {
1475             if ( nMonth < 12 )
1476                 rDate.SetMonth( nMonth + 1 );
1477         }
1478     }
1479     else
1480     {
1481         if ( (nMonth == 1) && (nYear > 0) )
1482         {
1483             rDate.SetMonth( 12 );
1484             rDate.SetYear( nYear - 1 );
1485         }
1486         else
1487         {
1488             if ( nMonth > 1 )
1489                 rDate.SetMonth( nMonth - 1 );
1490         }
1491     }
1492 
1493     sal_uInt16 nDaysInMonth = rDate.GetDaysInMonth();
1494     if ( rDate.GetDay() > nDaysInMonth )
1495         rDate.SetDay( nDaysInMonth );
1496 }
1497 
1498 // -----------------------------------------------------------------------
1499 
ImplDateIncrementYear(Date & rDate,sal_Bool bUp)1500 static void ImplDateIncrementYear( Date& rDate, sal_Bool bUp )
1501 {
1502     DateFormatter::ExpandCentury( rDate );
1503 
1504     sal_uInt16 nYear = rDate.GetYear();
1505     if ( bUp )
1506     {
1507         if ( nYear < 9999 )
1508             rDate.SetYear( nYear + 1 );
1509     }
1510     else
1511     {
1512         if ( nYear > 0 )
1513             rDate.SetYear( nYear - 1 );
1514     }
1515 }
1516 
1517 // -----------------------------------------------------------------------
ImplAllowMalformedInput() const1518 sal_Bool DateFormatter::ImplAllowMalformedInput() const
1519 {
1520     return !IsEnforceValidValue();
1521 }
1522 
1523 // -----------------------------------------------------------------------
1524 
ImplDateSpinArea(sal_Bool bUp)1525 void DateField::ImplDateSpinArea( sal_Bool bUp )
1526 {
1527     // Wenn alles selektiert ist, Tage hochzaehlen
1528     if ( GetField() )
1529     {
1530         Date aDate( GetDate() );
1531         Selection aSelection = GetField()->GetSelection();
1532         aSelection.Justify();
1533         XubString aText( GetText() );
1534         if ( (xub_StrLen)aSelection.Len() == aText.Len() )
1535             ImplDateIncrementDay( aDate, bUp );
1536         else
1537         {
1538             xub_StrLen nDateArea = 0;
1539 
1540             ExtDateFieldFormat eFormat = GetExtDateFormat( sal_True );
1541             if ( eFormat == XTDATEF_SYSTEM_LONG )
1542             {
1543                 eFormat = ImplGetExtFormat( ImplGetLocaleDataWrapper().getLongDateFormat() );
1544                 nDateArea = 1;
1545             }
1546             else
1547             {
1548                 // Area suchen
1549                 xub_StrLen nPos = 0;
1550                 String aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), eFormat );
1551                 for ( xub_StrLen i = 1; i <= 3; i++ )
1552                 {
1553                     nPos = aText.Search( aDateSep, nPos );
1554                     if ( nPos >= (sal_uInt16)aSelection.Max() )
1555                     {
1556                         nDateArea = i;
1557                         break;
1558                     }
1559                     else
1560                         nPos++;
1561                 }
1562             }
1563 
1564 
1565             switch( eFormat )
1566             {
1567                 case XTDATEF_SHORT_MMDDYY:
1568                 case XTDATEF_SHORT_MMDDYYYY:
1569                 switch( nDateArea )
1570                 {
1571                     case 1: ImplDateIncrementMonth( aDate, bUp );
1572                             break;
1573                     case 2: ImplDateIncrementDay( aDate, bUp );
1574                             break;
1575                     case 3: ImplDateIncrementYear( aDate, bUp );
1576                             break;
1577                 }
1578                 break;
1579                 case XTDATEF_SHORT_DDMMYY:
1580                 case XTDATEF_SHORT_DDMMYYYY:
1581                 switch( nDateArea )
1582                 {
1583                     case 1: ImplDateIncrementDay( aDate, bUp );
1584                             break;
1585                     case 2: ImplDateIncrementMonth( aDate, bUp );
1586                             break;
1587                     case 3: ImplDateIncrementYear( aDate, bUp );
1588                             break;
1589                 }
1590                 break;
1591                 case XTDATEF_SHORT_YYMMDD:
1592                 case XTDATEF_SHORT_YYYYMMDD:
1593                 case XTDATEF_SHORT_YYMMDD_DIN5008:
1594                 case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1595                 switch( nDateArea )
1596                 {
1597                     case 1: ImplDateIncrementYear( aDate, bUp );
1598                             break;
1599                     case 2: ImplDateIncrementMonth( aDate, bUp );
1600                             break;
1601                     case 3: ImplDateIncrementDay( aDate, bUp );
1602                             break;
1603                 }
1604                 break;
1605                 default:
1606                     DBG_ERROR( "invalid conversion" );
1607                     break;
1608             }
1609         }
1610 
1611         ImplNewFieldValue( aDate );
1612     }
1613 }
1614 
1615 // -----------------------------------------------------------------------
1616 
ImplInit()1617 void DateFormatter::ImplInit()
1618 {
1619     mbLongFormat        = sal_False;
1620     mbShowDateCentury   = sal_True;
1621     mpCalendarWrapper   = NULL;
1622     mnDateFormat        = 0xFFFF;
1623     mnExtDateFormat     = XTDATEF_SYSTEM_SHORT;
1624 }
1625 
1626 // -----------------------------------------------------------------------
1627 
DateFormatter()1628 DateFormatter::DateFormatter() :
1629     maFieldDate( 0 ),
1630     maLastDate( 0 ),
1631     maMin( 1, 1, 1900 ),
1632     maMax( 31, 12, 2200 ),
1633     mbEnforceValidValue( sal_True )
1634 {
1635     ImplInit();
1636 }
1637 
1638 // -----------------------------------------------------------------------
1639 
ImplLoadRes(const ResId & rResId)1640 void DateFormatter::ImplLoadRes( const ResId& rResId )
1641 {
1642     ResMgr*     pMgr = rResId.GetResMgr();
1643     if( pMgr )
1644     {
1645         sal_uLong       nMask = pMgr->ReadLong();
1646 
1647         if ( DATEFORMATTER_MIN & nMask )
1648         {
1649             maMin = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
1650             pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
1651         }
1652         if ( DATEFORMATTER_MAX & nMask )
1653         {
1654             maMax = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
1655             pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
1656         }
1657         if ( DATEFORMATTER_LONGFORMAT & nMask )
1658             mbLongFormat = (sal_Bool)pMgr->ReadShort();
1659 
1660         if ( DATEFORMATTER_STRICTFORMAT & nMask )
1661             SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
1662 
1663         if ( DATEFORMATTER_VALUE & nMask )
1664         {
1665             maFieldDate = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
1666             pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
1667             if ( maFieldDate > maMax )
1668                 maFieldDate = maMax;
1669             if ( maFieldDate < maMin )
1670                 maFieldDate = maMin;
1671             maLastDate = maFieldDate;
1672         }
1673     }
1674 }
1675 
1676 // -----------------------------------------------------------------------
1677 
~DateFormatter()1678 DateFormatter::~DateFormatter()
1679 {
1680     delete mpCalendarWrapper;
1681     mpCalendarWrapper = NULL;
1682 }
1683 
1684 // -----------------------------------------------------------------------
1685 
SetLocale(const::com::sun::star::lang::Locale & rLocale)1686 void DateFormatter::SetLocale( const ::com::sun::star::lang::Locale& rLocale )
1687 {
1688     delete mpCalendarWrapper;
1689     mpCalendarWrapper = NULL;
1690     FormatterBase::SetLocale( rLocale );
1691 }
1692 
1693 
1694 // -----------------------------------------------------------------------
1695 
GetCalendarWrapper() const1696 CalendarWrapper& DateFormatter::GetCalendarWrapper() const
1697 {
1698     if ( !mpCalendarWrapper )
1699     {
1700         ((DateFormatter*)this)->mpCalendarWrapper = new CalendarWrapper( vcl::unohelper::GetMultiServiceFactory() );
1701         mpCalendarWrapper->loadDefaultCalendar( GetLocale() );
1702     }
1703 
1704     return *mpCalendarWrapper;
1705 }
1706 
1707 // -----------------------------------------------------------------------
1708 
SetExtDateFormat(ExtDateFieldFormat eFormat)1709 void DateFormatter::SetExtDateFormat( ExtDateFieldFormat eFormat )
1710 {
1711     mnExtDateFormat = eFormat;
1712     ReformatAll();
1713 }
1714 
1715 // -----------------------------------------------------------------------
1716 
GetExtDateFormat(sal_Bool bResolveSystemFormat) const1717 ExtDateFieldFormat DateFormatter::GetExtDateFormat( sal_Bool bResolveSystemFormat ) const
1718 {
1719     ExtDateFieldFormat eDateFormat = (ExtDateFieldFormat)mnExtDateFormat;
1720 
1721     if ( bResolveSystemFormat && ( eDateFormat <= XTDATEF_SYSTEM_SHORT_YYYY ) )
1722     {
1723         sal_Bool bShowCentury = (eDateFormat == XTDATEF_SYSTEM_SHORT_YYYY);
1724         switch ( ImplGetLocaleDataWrapper().getDateFormat() )
1725         {
1726             case DMY:   eDateFormat = bShowCentury ? XTDATEF_SHORT_DDMMYYYY : XTDATEF_SHORT_DDMMYY;
1727                         break;
1728             case MDY:   eDateFormat = bShowCentury ? XTDATEF_SHORT_MMDDYYYY : XTDATEF_SHORT_MMDDYY;
1729                         break;
1730             default:    eDateFormat = bShowCentury ? XTDATEF_SHORT_YYYYMMDD : XTDATEF_SHORT_YYMMDD;
1731 
1732         }
1733     }
1734 
1735     return eDateFormat;
1736 }
1737 
1738 // -----------------------------------------------------------------------
1739 
ReformatAll()1740 void DateFormatter::ReformatAll()
1741 {
1742     Reformat();
1743 }
1744 
1745 // -----------------------------------------------------------------------
1746 
SetMin(const Date & rNewMin)1747 void DateFormatter::SetMin( const Date& rNewMin )
1748 {
1749     maMin = rNewMin;
1750     if ( !IsEmptyFieldValue() )
1751         ReformatAll();
1752 }
1753 
1754 // -----------------------------------------------------------------------
1755 
SetMax(const Date & rNewMax)1756 void DateFormatter::SetMax( const Date& rNewMax )
1757 {
1758     maMax = rNewMax;
1759     if ( !IsEmptyFieldValue() )
1760         ReformatAll();
1761 }
1762 
1763 // -----------------------------------------------------------------------
1764 
SetLongFormat(sal_Bool bLong)1765 void DateFormatter::SetLongFormat( sal_Bool bLong )
1766 {
1767     mbLongFormat = bLong;
1768 
1769     // #91913# Remove LongFormat and DateShowCentury - redundant
1770     if ( bLong )
1771     {
1772         SetExtDateFormat( XTDATEF_SYSTEM_LONG );
1773     }
1774     else
1775     {
1776         if( mnExtDateFormat == XTDATEF_SYSTEM_LONG )
1777             SetExtDateFormat( XTDATEF_SYSTEM_SHORT );
1778     }
1779 
1780     ReformatAll();
1781 }
1782 
1783 // -----------------------------------------------------------------------
1784 
SetShowDateCentury(sal_Bool bShowDateCentury)1785 void DateFormatter::SetShowDateCentury( sal_Bool bShowDateCentury )
1786 {
1787     mbShowDateCentury = bShowDateCentury;
1788 
1789     // #91913# Remove LongFormat and DateShowCentury - redundant
1790     if ( bShowDateCentury )
1791     {
1792         switch ( GetExtDateFormat() )
1793         {
1794             case XTDATEF_SYSTEM_SHORT:
1795             case XTDATEF_SYSTEM_SHORT_YY:
1796                 SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );  break;
1797             case XTDATEF_SHORT_DDMMYY:
1798                 SetExtDateFormat( XTDATEF_SHORT_DDMMYYYY );     break;
1799             case XTDATEF_SHORT_MMDDYY:
1800                 SetExtDateFormat( XTDATEF_SHORT_MMDDYYYY );     break;
1801             case XTDATEF_SHORT_YYMMDD:
1802                 SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD );     break;
1803             case XTDATEF_SHORT_YYMMDD_DIN5008:
1804                 SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD_DIN5008 ); break;
1805             default:
1806                 ;
1807         }
1808     }
1809     else
1810     {
1811         switch ( GetExtDateFormat() )
1812         {
1813             case XTDATEF_SYSTEM_SHORT:
1814             case XTDATEF_SYSTEM_SHORT_YYYY:
1815                 SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YY );    break;
1816             case XTDATEF_SHORT_DDMMYYYY:
1817                 SetExtDateFormat( XTDATEF_SHORT_DDMMYY );       break;
1818             case XTDATEF_SHORT_MMDDYYYY:
1819                 SetExtDateFormat( XTDATEF_SHORT_MMDDYY );       break;
1820             case XTDATEF_SHORT_YYYYMMDD:
1821                 SetExtDateFormat( XTDATEF_SHORT_YYMMDD );       break;
1822             case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1823                 SetExtDateFormat( XTDATEF_SHORT_YYMMDD_DIN5008 );  break;
1824             default:
1825                 ;
1826         }
1827     }
1828 
1829     ReformatAll();
1830 }
1831 
1832 // -----------------------------------------------------------------------
1833 
SetDate(const Date & rNewDate)1834 void DateFormatter::SetDate( const Date& rNewDate )
1835 {
1836     SetUserDate( rNewDate );
1837     maFieldDate = maLastDate;
1838     maLastDate = GetDate();
1839 }
1840 
1841 // -----------------------------------------------------------------------
1842 
SetUserDate(const Date & rNewDate)1843 void DateFormatter::SetUserDate( const Date& rNewDate )
1844 {
1845     ImplSetUserDate( rNewDate );
1846 }
1847 
1848 // -----------------------------------------------------------------------
1849 
ImplSetUserDate(const Date & rNewDate,Selection * pNewSelection)1850 void DateFormatter::ImplSetUserDate( const Date& rNewDate, Selection* pNewSelection )
1851 {
1852     Date aNewDate = rNewDate;
1853     if ( aNewDate > maMax )
1854         aNewDate = maMax;
1855     else if ( aNewDate < maMin )
1856         aNewDate = maMin;
1857     maLastDate = aNewDate;
1858 
1859     if ( GetField() )
1860         ImplSetText( ImplGetDateAsText( aNewDate, GetFieldSettings() ), pNewSelection );
1861 }
1862 
1863 // -----------------------------------------------------------------------
1864 
ImplNewFieldValue(const Date & rDate)1865 void DateFormatter::ImplNewFieldValue( const Date& rDate )
1866 {
1867     if ( GetField() )
1868     {
1869         Selection aSelection = GetField()->GetSelection();
1870         aSelection.Justify();
1871         XubString aText = GetField()->GetText();
1872         // Wenn bis ans Ende selektiert war, soll das auch so bleiben...
1873         if ( (xub_StrLen)aSelection.Max() == aText.Len() )
1874         {
1875             if ( !aSelection.Len() )
1876                 aSelection.Min() = SELECTION_MAX;
1877             aSelection.Max() = SELECTION_MAX;
1878         }
1879 
1880         Date aOldLastDate  = maLastDate;
1881         ImplSetUserDate( rDate, &aSelection );
1882         maLastDate = aOldLastDate;
1883 
1884         // Modify am Edit wird nur bei KeyInput gesetzt...
1885         if ( GetField()->GetText() != aText )
1886         {
1887             GetField()->SetModifyFlag();
1888             GetField()->Modify();
1889         }
1890     }
1891 }
1892 
1893 // -----------------------------------------------------------------------
1894 
GetDate() const1895 Date DateFormatter::GetDate() const
1896 {
1897     Date aDate( 0, 0, 0 );
1898 
1899     if ( GetField() )
1900     {
1901         if ( ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
1902         {
1903             if ( aDate > maMax )
1904                 aDate = maMax;
1905             else if ( aDate < maMin )
1906                 aDate = maMin;
1907         }
1908         else
1909         {
1910             // !!! TH-18.2.99: Wenn wir Zeit haben sollte einmal
1911             // !!! geklaert werden, warum dieses beim Datum gegenueber
1912             // !!! allen anderen Feldern anders behandelt wird.
1913             // !!! Siehe dazu Bug: 52304
1914 
1915             if ( !ImplAllowMalformedInput() )
1916             {
1917                 if ( maLastDate.GetDate() )
1918                     aDate = maLastDate;
1919                 else if ( !IsEmptyFieldValueEnabled() )
1920                     aDate = Date();
1921             }
1922             else
1923                 aDate = GetInvalidDate();
1924         }
1925     }
1926 
1927     return aDate;
1928 }
1929 
1930 // -----------------------------------------------------------------------
1931 
GetRealDate() const1932 Date DateFormatter::GetRealDate() const
1933 {
1934     // !!! TH-18.2.99: Wenn wir Zeit haben sollte dieses auch einmal
1935     // !!! fuer die Numeric-Klassen eingebaut werden.
1936 
1937     Date aDate( 0, 0, 0 );
1938 
1939     if ( GetField() )
1940     {
1941         if ( !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
1942             if ( ImplAllowMalformedInput() )
1943                 aDate = GetInvalidDate();
1944     }
1945 
1946     return aDate;
1947 }
1948 
1949 // -----------------------------------------------------------------------
1950 
SetEmptyDate()1951 void DateFormatter::SetEmptyDate()
1952 {
1953     FormatterBase::SetEmptyFieldValue();
1954 }
1955 
1956 // -----------------------------------------------------------------------
1957 
IsEmptyDate() const1958 sal_Bool DateFormatter::IsEmptyDate() const
1959 {
1960     sal_Bool bEmpty = FormatterBase::IsEmptyFieldValue();
1961 
1962     if ( GetField() && MustBeReformatted() && IsEmptyFieldValueEnabled() )
1963     {
1964         if ( !GetField()->GetText().Len() )
1965         {
1966             bEmpty = sal_True;
1967         }
1968         else if ( !maLastDate.GetDate() )
1969         {
1970             Date aDate;
1971             bEmpty = !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
1972         }
1973     }
1974     return bEmpty;
1975 }
1976 
1977 // -----------------------------------------------------------------------
1978 
IsDateModified() const1979 sal_Bool DateFormatter::IsDateModified() const
1980 {
1981     if ( ImplGetEmptyFieldValue() )
1982         return !IsEmptyDate();
1983     else if ( GetDate() != maFieldDate )
1984         return sal_True;
1985     else
1986         return sal_False;
1987 }
1988 
1989 // -----------------------------------------------------------------------
1990 
Reformat()1991 void DateFormatter::Reformat()
1992 {
1993     if ( !GetField() )
1994         return;
1995 
1996     if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
1997         return;
1998 
1999     XubString aStr;
2000     sal_Bool bOK = ImplDateReformat( GetField()->GetText(), aStr, GetFieldSettings() );
2001     if( !bOK )
2002         return;
2003 
2004     if ( aStr.Len() )
2005     {
2006         ImplSetText( aStr );
2007         ImplDateGetValue( aStr, maLastDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
2008     }
2009     else
2010     {
2011         if ( maLastDate.GetDate() )
2012             SetDate( maLastDate );
2013         else if ( !IsEmptyFieldValueEnabled() )
2014             SetDate( Date() );
2015         else
2016         {
2017             ImplSetText( ImplGetSVEmptyStr() );
2018             SetEmptyFieldValueData( sal_True );
2019         }
2020     }
2021 }
2022 
2023 // -----------------------------------------------------------------------
2024 
ExpandCentury(Date & rDate)2025 void DateFormatter::ExpandCentury( Date& rDate )
2026 {
2027     ExpandCentury( rDate, utl::MiscCfg().GetYear2000() );
2028 }
2029 
2030 // -----------------------------------------------------------------------
2031 
ExpandCentury(Date & rDate,sal_uInt16 nTwoDigitYearStart)2032 void DateFormatter::ExpandCentury( Date& rDate, sal_uInt16 nTwoDigitYearStart )
2033 {
2034     sal_uInt16 nDateYear = rDate.GetYear();
2035     if ( nDateYear < 100 )
2036     {
2037         sal_uInt16 nCentury = nTwoDigitYearStart / 100;
2038         if ( nDateYear < (nTwoDigitYearStart % 100) )
2039             nCentury++;
2040         rDate.SetYear( nDateYear + (nCentury*100) );
2041     }
2042 }
2043 
2044 // -----------------------------------------------------------------------
2045 
DateField(Window * pParent,WinBits nWinStyle)2046 DateField::DateField( Window* pParent, WinBits nWinStyle ) :
2047     SpinField( pParent, nWinStyle ),
2048     maFirst( GetMin() ),
2049     maLast( GetMax() )
2050 {
2051     SetField( this );
2052     SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
2053     Reformat();
2054     ResetLastDate();
2055 }
2056 
2057 // -----------------------------------------------------------------------
2058 
DateField(Window * pParent,const ResId & rResId)2059 DateField::DateField( Window* pParent, const ResId& rResId ) :
2060     SpinField( WINDOW_DATEFIELD ),
2061     maFirst( GetMin() ),
2062     maLast( GetMax() )
2063 {
2064     rResId.SetRT( RSC_DATEFIELD );
2065     WinBits nStyle = ImplInitRes( rResId );
2066     SpinField::ImplInit( pParent, nStyle );
2067     SetField( this );
2068     SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
2069     ImplLoadRes( rResId );
2070 
2071     if ( !(nStyle & WB_HIDE ) )
2072         Show();
2073 
2074     ResetLastDate();
2075 }
2076 
2077 // -----------------------------------------------------------------------
2078 
ImplLoadRes(const ResId & rResId)2079 void DateField::ImplLoadRes( const ResId& rResId )
2080 {
2081     SpinField::ImplLoadRes( rResId );
2082 
2083     ResMgr* pMgr = rResId.GetResMgr();
2084     if( pMgr )
2085     {
2086         DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2087 
2088         sal_uLong  nMask = ReadLongRes();
2089         if ( DATEFIELD_FIRST & nMask )
2090         {
2091             maFirst = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2092             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
2093         }
2094         if ( DATEFIELD_LAST & nMask )
2095         {
2096             maLast = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2097             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
2098         }
2099     }
2100 
2101     Reformat();
2102 }
2103 
2104 // -----------------------------------------------------------------------
2105 
~DateField()2106 DateField::~DateField()
2107 {
2108 }
2109 
2110 // -----------------------------------------------------------------------
2111 
PreNotify(NotifyEvent & rNEvt)2112 long DateField::PreNotify( NotifyEvent& rNEvt )
2113 {
2114     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
2115          ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
2116          !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2117     {
2118         if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( sal_True ), ImplGetLocaleDataWrapper() ) )
2119             return 1;
2120     }
2121 
2122     return SpinField::PreNotify( rNEvt );
2123 }
2124 
2125 // -----------------------------------------------------------------------
2126 
Notify(NotifyEvent & rNEvt)2127 long DateField::Notify( NotifyEvent& rNEvt )
2128 {
2129     if ( rNEvt.GetType() == EVENT_GETFOCUS )
2130         MarkToBeReformatted( sal_False );
2131     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2132     {
2133         if ( MustBeReformatted() )
2134         {
2135             // !!! TH-18.2.99: Wenn wir Zeit haben sollte einmal
2136             // !!! geklaert werden, warum dieses beim Datum gegenueber
2137             // !!! allen anderen Feldern anders behandelt wird.
2138             // !!! Siehe dazu Bug: 52304
2139 
2140             sal_Bool bTextLen = GetText().Len() != 0;
2141             if ( bTextLen || !IsEmptyFieldValueEnabled() )
2142             {
2143                 if ( !ImplAllowMalformedInput() )
2144                     Reformat();
2145                 else
2146                 {
2147                     Date aDate( 0, 0, 0 );
2148                     if ( ImplDateGetValue( GetText(), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
2149                         // even with strict text analysis, our text is a valid date -> do a complete
2150                         // reformat
2151                         Reformat();
2152                 }
2153             }
2154             else if ( !bTextLen && IsEmptyFieldValueEnabled() )
2155             {
2156                 ResetLastDate();
2157                 SetEmptyFieldValueData( sal_True );
2158             }
2159         }
2160     }
2161 
2162     return SpinField::Notify( rNEvt );
2163 }
2164 
2165 // -----------------------------------------------------------------------
2166 
DataChanged(const DataChangedEvent & rDCEvt)2167 void DateField::DataChanged( const DataChangedEvent& rDCEvt )
2168 {
2169     SpinField::DataChanged( rDCEvt );
2170 
2171     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & (SETTINGS_LOCALE|SETTINGS_MISC)) )
2172     {
2173         if ( IsDefaultLocale() && ( rDCEvt.GetFlags() & SETTINGS_LOCALE ) )
2174             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2175         ReformatAll();
2176     }
2177 }
2178 
2179 // -----------------------------------------------------------------------
2180 
Modify()2181 void DateField::Modify()
2182 {
2183     MarkToBeReformatted( sal_True );
2184     SpinField::Modify();
2185 }
2186 
2187 // -----------------------------------------------------------------------
2188 
Up()2189 void DateField::Up()
2190 {
2191     ImplDateSpinArea( sal_True );
2192     SpinField::Up();
2193 }
2194 
2195 // -----------------------------------------------------------------------
2196 
Down()2197 void DateField::Down()
2198 {
2199     ImplDateSpinArea( sal_False );
2200     SpinField::Down();
2201 }
2202 
2203 // -----------------------------------------------------------------------
2204 
First()2205 void DateField::First()
2206 {
2207     ImplNewFieldValue( maFirst );
2208     SpinField::First();
2209 }
2210 
2211 // -----------------------------------------------------------------------
2212 
Last()2213 void DateField::Last()
2214 {
2215     ImplNewFieldValue( maLast );
2216     SpinField::Last();
2217 }
2218 
2219 // -----------------------------------------------------------------------
2220 
DateBox(Window * pParent,WinBits nWinStyle)2221 DateBox::DateBox( Window* pParent, WinBits nWinStyle ) :
2222     ComboBox( pParent, nWinStyle )
2223 {
2224     SetField( this );
2225     SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
2226     Reformat();
2227 }
2228 
2229 // -----------------------------------------------------------------------
2230 
DateBox(Window * pParent,const ResId & rResId)2231 DateBox::DateBox( Window* pParent, const ResId& rResId ) :
2232     ComboBox( WINDOW_DATEBOX )
2233 {
2234     rResId.SetRT( RSC_DATEBOX );
2235     WinBits nStyle = ImplInitRes( rResId );
2236     ComboBox::ImplInit( pParent, nStyle );
2237     SetField( this );
2238     SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
2239     ComboBox::ImplLoadRes( rResId );
2240     ResMgr* pMgr = rResId.GetResMgr();
2241     if( pMgr )
2242         DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2243     Reformat();
2244 
2245     if ( !( nStyle & WB_HIDE ) )
2246         Show();
2247 }
2248 
2249 // -----------------------------------------------------------------------
2250 
~DateBox()2251 DateBox::~DateBox()
2252 {
2253 }
2254 
2255 // -----------------------------------------------------------------------
2256 
PreNotify(NotifyEvent & rNEvt)2257 long DateBox::PreNotify( NotifyEvent& rNEvt )
2258 {
2259     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
2260          ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
2261          !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2262     {
2263         if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( sal_True ), ImplGetLocaleDataWrapper() ) )
2264             return 1;
2265     }
2266 
2267     return ComboBox::PreNotify( rNEvt );
2268 }
2269 
2270 // -----------------------------------------------------------------------
2271 
DataChanged(const DataChangedEvent & rDCEvt)2272 void DateBox::DataChanged( const DataChangedEvent& rDCEvt )
2273 {
2274     ComboBox::DataChanged( rDCEvt );
2275 
2276     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2277     {
2278         if ( IsDefaultLocale() )
2279             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2280         ReformatAll();
2281     }
2282 }
2283 
2284 // -----------------------------------------------------------------------
2285 
Notify(NotifyEvent & rNEvt)2286 long DateBox::Notify( NotifyEvent& rNEvt )
2287 {
2288     if ( rNEvt.GetType() == EVENT_GETFOCUS )
2289         MarkToBeReformatted( sal_False );
2290     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2291     {
2292         if ( MustBeReformatted() )
2293         {
2294             sal_Bool bTextLen = GetText().Len() != 0;
2295             if ( bTextLen || !IsEmptyFieldValueEnabled() )
2296                 Reformat();
2297             else if ( !bTextLen && IsEmptyFieldValueEnabled() )
2298             {
2299                 ResetLastDate();
2300                 SetEmptyFieldValueData( sal_True );
2301             }
2302         }
2303     }
2304 
2305     return ComboBox::Notify( rNEvt );
2306 }
2307 
2308 // -----------------------------------------------------------------------
2309 
Modify()2310 void DateBox::Modify()
2311 {
2312     MarkToBeReformatted( sal_True );
2313     ComboBox::Modify();
2314 }
2315 
2316 // -----------------------------------------------------------------------
2317 
ReformatAll()2318 void DateBox::ReformatAll()
2319 {
2320     XubString aStr;
2321     SetUpdateMode( sal_False );
2322     sal_uInt16 nEntryCount = GetEntryCount();
2323     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2324     {
2325         ImplDateReformat( GetEntry( i ), aStr, GetFieldSettings() );
2326         RemoveEntry( i );
2327         InsertEntry( aStr, i );
2328     }
2329     DateFormatter::Reformat();
2330     SetUpdateMode( sal_True );
2331 }
2332 
2333 // -----------------------------------------------------------------------
2334 
InsertDate(const Date & rDate,sal_uInt16 nPos)2335 void DateBox::InsertDate( const Date& rDate, sal_uInt16 nPos )
2336 {
2337     Date aDate = rDate;
2338     if ( aDate > GetMax() )
2339         aDate = GetMax();
2340     else if ( aDate < GetMin() )
2341         aDate = GetMin();
2342 
2343     ComboBox::InsertEntry( ImplGetDateAsText( aDate, GetFieldSettings() ), nPos );
2344 }
2345 
2346 // -----------------------------------------------------------------------
2347 
RemoveDate(const Date & rDate)2348 void DateBox::RemoveDate( const Date& rDate )
2349 {
2350     ComboBox::RemoveEntry( ImplGetDateAsText( rDate, GetFieldSettings() ) );
2351 }
2352 
2353 // -----------------------------------------------------------------------
2354 
GetDate(sal_uInt16 nPos) const2355 Date DateBox::GetDate( sal_uInt16 nPos ) const
2356 {
2357     Date aDate( 0, 0, 0 );
2358     ImplDateGetValue( ComboBox::GetEntry( nPos ), aDate, GetExtDateFormat(sal_True), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetSettings() );
2359     return aDate;
2360 }
2361 
2362 // -----------------------------------------------------------------------
2363 
GetDatePos(const Date & rDate) const2364 sal_uInt16 DateBox::GetDatePos( const Date& rDate ) const
2365 {
2366     XubString aStr;
2367     if ( IsLongFormat() )
2368         aStr = ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, sal_False, 1, !IsShowDateCentury() );
2369     else
2370         aStr = ImplGetLocaleDataWrapper().getDate( rDate );
2371     return ComboBox::GetEntryPos( aStr );
2372 }
2373 
2374 // -----------------------------------------------------------------------
2375 
ImplTimeProcessKeyInput(Edit *,const KeyEvent & rKEvt,sal_Bool bStrictFormat,sal_Bool bDuration,TimeFieldFormat eFormat,const LocaleDataWrapper & rLocaleDataWrapper)2376 static sal_Bool ImplTimeProcessKeyInput( Edit*, const KeyEvent& rKEvt,
2377                                      sal_Bool bStrictFormat, sal_Bool bDuration,
2378                                      TimeFieldFormat eFormat,
2379                                      const LocaleDataWrapper& rLocaleDataWrapper  )
2380 {
2381     xub_Unicode cChar = rKEvt.GetCharCode();
2382 
2383     if ( !bStrictFormat )
2384         return sal_False;
2385     else
2386     {
2387         sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
2388         if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
2389              (nGroup == KEYGROUP_MISC)   ||
2390              ((cChar >= '0') && (cChar <= '9')) ||
2391              (cChar == rLocaleDataWrapper.getTimeSep()) ||
2392              ( ( rLocaleDataWrapper.getTimeAM().Search( cChar ) != STRING_NOTFOUND ) ) ||
2393              ( ( rLocaleDataWrapper.getTimePM().Search( cChar ) != STRING_NOTFOUND ) ) ||
2394              // Accept AM/PM:
2395              (cChar == 'a') || (cChar == 'A') || (cChar == 'm') || (cChar == 'M') || (cChar == 'p') || (cChar == 'P') ||
2396              ((eFormat == TIMEF_100TH_SEC) && (cChar == rLocaleDataWrapper.getTime100SecSep())) ||
2397              ((eFormat == TIMEF_SEC_CS) && (cChar == rLocaleDataWrapper.getTime100SecSep())) ||
2398              (bDuration && (cChar == '-')) )
2399             return sal_False;
2400         else
2401             return sal_True;
2402     }
2403 }
2404 
2405 // -----------------------------------------------------------------------
2406 
ImplIsOnlyDigits(const String & _rStr)2407 static sal_Bool ImplIsOnlyDigits( const String& _rStr )
2408 {
2409     const sal_Unicode* _pChr = _rStr.GetBuffer();
2410     for ( xub_StrLen i = 0; i < _rStr.Len(); ++i, ++_pChr )
2411     {
2412         if ( *_pChr < '0' || *_pChr > '9' )
2413             return sal_False;
2414     }
2415     return sal_True;
2416 }
2417 
2418 // -----------------------------------------------------------------------
2419 
ImplIsValidTimePortion(sal_Bool _bSkipInvalidCharacters,const String & _rStr)2420 static sal_Bool ImplIsValidTimePortion( sal_Bool _bSkipInvalidCharacters, const String& _rStr )
2421 {
2422     if ( !_bSkipInvalidCharacters )
2423     {
2424         if ( ( _rStr.Len() > 2 ) || ( _rStr.Len() < 1 ) || !ImplIsOnlyDigits( _rStr ) )
2425             return sal_False;
2426     }
2427     return sal_True;
2428 }
2429 
2430 // -----------------------------------------------------------------------
2431 
ImplCutTimePortion(String & _rStr,xub_StrLen _nSepPos,sal_Bool _bSkipInvalidCharacters,short * _pPortion)2432 static sal_Bool ImplCutTimePortion( String& _rStr, xub_StrLen _nSepPos, sal_Bool _bSkipInvalidCharacters, short* _pPortion )
2433 {
2434     String sPortion = _rStr.Copy( 0, _nSepPos );
2435     _rStr.Erase( 0, _nSepPos + 1 );
2436 
2437     if ( !ImplIsValidTimePortion( _bSkipInvalidCharacters, sPortion ) )
2438         return sal_False;
2439     *_pPortion = (short)sPortion.ToInt32();
2440     return sal_True;
2441 }
2442 
2443 // -----------------------------------------------------------------------
2444 
ImplTimeGetValue(const XubString & rStr,Time & rTime,TimeFieldFormat eFormat,sal_Bool bDuration,const LocaleDataWrapper & rLocaleDataWrapper,sal_Bool _bSkipInvalidCharacters=sal_True)2445 static sal_Bool ImplTimeGetValue( const XubString& rStr, Time& rTime,
2446                               TimeFieldFormat eFormat, sal_Bool bDuration,
2447                               const LocaleDataWrapper& rLocaleDataWrapper, sal_Bool _bSkipInvalidCharacters = sal_True )
2448 {
2449     XubString   aStr    = rStr;
2450     short       nHour   = 0;
2451     short       nMinute = 0;
2452     short       nSecond = 0;
2453     short       n100Sec = 0;
2454     Time        aTime( 0, 0, 0 );
2455 
2456     if ( !rStr.Len() )
2457         return sal_False;
2458 
2459     // Nach Separatoren suchen
2460     if ( rLocaleDataWrapper.getTimeSep().Len() )
2461     {
2462         XubString aSepStr( RTL_CONSTASCII_USTRINGPARAM( ",.;:/" ) );
2463         if ( !bDuration )
2464             aSepStr.Append( '-' );
2465 
2466         // Die obigen Zeichen durch das Separatorzeichen ersetzen
2467         for ( xub_StrLen i = 0; i < aSepStr.Len(); i++ )
2468         {
2469             if ( aSepStr.GetChar( i ) == rLocaleDataWrapper.getTimeSep() )
2470                 continue;
2471             for ( xub_StrLen j = 0; j < aStr.Len(); j++ )
2472             {
2473                 if ( aStr.GetChar( j ) == aSepStr.GetChar( i ) )
2474                     aStr.SetChar( j, rLocaleDataWrapper.getTimeSep().GetChar(0) );
2475             }
2476         }
2477     }
2478 
2479     sal_Bool bNegative = sal_False;
2480     xub_StrLen nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2481     if ( aStr.GetChar( 0 ) == '-' )
2482         bNegative = sal_True;
2483     if ( eFormat != TIMEF_SEC_CS )
2484     {
2485         if ( nSepPos == STRING_NOTFOUND )
2486             nSepPos = aStr.Len();
2487         if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nHour ) )
2488             return sal_False;
2489 
2490         nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2491         if ( aStr.GetChar( 0 ) == '-' )
2492             bNegative = sal_True;
2493         if ( nSepPos != STRING_NOTFOUND )
2494         {
2495             if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nMinute ) )
2496                 return sal_False;
2497 
2498             nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2499             if ( aStr.GetChar( 0 ) == '-' )
2500                 bNegative = sal_True;
2501             if ( nSepPos != STRING_NOTFOUND )
2502             {
2503                 if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nSecond ) )
2504                     return sal_False;
2505                 if ( aStr.GetChar( 0 ) == '-' )
2506                     bNegative = sal_True;
2507                 n100Sec = (short)aStr.ToInt32();
2508             }
2509             else
2510                 nSecond = (short)aStr.ToInt32();
2511         }
2512         else
2513             nMinute = (short)aStr.ToInt32();
2514     }
2515     else if ( nSepPos == STRING_NOTFOUND )
2516     {
2517         nSecond = (short)aStr.ToInt32();
2518         nMinute += nSecond / 60;
2519         nSecond %= 60;
2520         nHour += nMinute / 60;
2521         nMinute %= 60;
2522     }
2523     else
2524     {
2525         nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
2526         aStr.Erase( 0, nSepPos+1 );
2527 
2528         nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2529         if ( aStr.GetChar( 0 ) == '-' )
2530             bNegative = sal_True;
2531         if ( nSepPos != STRING_NOTFOUND )
2532         {
2533             nMinute = nSecond;
2534             nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
2535             aStr.Erase( 0, nSepPos+1 );
2536 
2537             nSepPos = aStr.Search( rLocaleDataWrapper.getTimeSep() );
2538             if ( aStr.GetChar( 0 ) == '-' )
2539                 bNegative = sal_True;
2540             if ( nSepPos != STRING_NOTFOUND )
2541             {
2542                 nHour   = nMinute;
2543                 nMinute = nSecond;
2544                 nSecond = (short)aStr.Copy( 0, nSepPos ).ToInt32();
2545                 aStr.Erase( 0, nSepPos+1 );
2546             }
2547             else
2548             {
2549                 nHour += nMinute / 60;
2550                 nMinute %= 60;
2551             }
2552         }
2553         else
2554         {
2555             nMinute += nSecond / 60;
2556             nSecond %= 60;
2557             nHour += nMinute / 60;
2558             nMinute %= 60;
2559         }
2560         n100Sec = (short)aStr.ToInt32();
2561 
2562         if ( n100Sec )
2563         {
2564             xub_StrLen nLen = 1; // mindestens eine Ziffer, weil sonst n100Sec==0
2565 
2566             while ( aStr.GetChar(nLen) >= '0' && aStr.GetChar(nLen) <= '9' )
2567                 nLen++;
2568 
2569             if ( nLen > 2 )
2570             {
2571                 while( nLen > 3 )
2572                 {
2573                     n100Sec = n100Sec / 10;
2574                     nLen--;
2575                 }
2576                 // Rundung bei negativen Zahlen???
2577                 n100Sec = (n100Sec + 5) / 10;
2578             }
2579             else
2580             {
2581                 while( nLen < 2 )
2582                 {
2583                     n100Sec = n100Sec * 10;
2584                     nLen++;
2585                 }
2586             }
2587         }
2588     }
2589 
2590     if ( (nMinute > 59) || (nSecond > 59) || (n100Sec > 100) )
2591         return sal_False;
2592 
2593     if ( eFormat == TIMEF_NONE )
2594         nSecond = n100Sec = 0;
2595     else if ( eFormat == TIMEF_SEC )
2596         n100Sec = 0;
2597 
2598     if ( !bDuration )
2599     {
2600         if ( bNegative || (nHour < 0) || (nMinute < 0) ||
2601              (nSecond < 0) || (n100Sec < 0) )
2602             return sal_False;
2603 
2604         aStr.ToUpperAscii();
2605         XubString aAM( rLocaleDataWrapper.getTimeAM() );
2606         XubString aPM( rLocaleDataWrapper.getTimePM() );
2607         aAM.ToUpperAscii();
2608         aPM.ToUpperAscii();
2609         XubString aAM2( RTL_CONSTASCII_USTRINGPARAM( "AM" ) );  // aAM is localized
2610         XubString aPM2( RTL_CONSTASCII_USTRINGPARAM( "PM" ) );  // aPM is localized
2611 
2612         if ( (nHour < 12) && ( ( aStr.Search( aPM ) != STRING_NOTFOUND ) || ( aStr.Search( aPM2 ) != STRING_NOTFOUND ) ) )
2613             nHour += 12;
2614 
2615         if ( (nHour == 12) && ( ( aStr.Search( aAM ) != STRING_NOTFOUND ) || ( aStr.Search( aAM2 ) != STRING_NOTFOUND ) ) )
2616             nHour = 0;
2617 
2618         aTime = Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
2619                       (sal_uInt16)n100Sec );
2620     }
2621     else
2622     {
2623         if ( bNegative || (nHour < 0) || (nMinute < 0) ||
2624              (nSecond < 0) || (n100Sec < 0) )
2625         {
2626             bNegative   = sal_True;
2627             nHour       = nHour < 0 ? -nHour : nHour;
2628             nMinute     = nMinute < 0 ? -nMinute : nMinute;
2629             nSecond     = nSecond < 0 ? -nSecond : nSecond;
2630             n100Sec     = n100Sec < 0 ? -n100Sec : n100Sec;
2631         }
2632 
2633         aTime = Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
2634                       (sal_uInt16)n100Sec );
2635         if ( bNegative )
2636             aTime = -aTime;
2637     }
2638 
2639     rTime = aTime;
2640 
2641     return sal_True;
2642 }
2643 
2644 // -----------------------------------------------------------------------
2645 
ImplTimeReformat(const XubString & rStr,XubString & rOutStr)2646 sal_Bool TimeFormatter::ImplTimeReformat( const XubString& rStr, XubString& rOutStr )
2647 {
2648     Time aTime( 0, 0, 0 );
2649     if ( !ImplTimeGetValue( rStr, aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ) )
2650         return sal_True;
2651 
2652     Time aTempTime = aTime;
2653     if ( aTempTime > GetMax() )
2654         aTempTime = GetMax() ;
2655     else if ( aTempTime < GetMin() )
2656         aTempTime = GetMin();
2657 
2658     if ( GetErrorHdl().IsSet() && (aTime != aTempTime) )
2659     {
2660         maCorrectedTime = aTempTime;
2661         if ( !GetErrorHdl().Call( this ) )
2662         {
2663             maCorrectedTime = Time();
2664             return sal_False;
2665         }
2666         else
2667             maCorrectedTime = Time();
2668     }
2669 
2670     sal_Bool bSecond = sal_False;
2671     sal_Bool b100Sec = sal_False;
2672     if ( meFormat != TIMEF_NONE )
2673         bSecond = sal_True;
2674     if ( meFormat == TIMEF_100TH_SEC )
2675         b100Sec = sal_True;
2676 
2677     if ( meFormat == TIMEF_SEC_CS )
2678     {
2679         sal_uLong n  = aTempTime.GetHour() * 3600L;
2680         n       += aTempTime.GetMin()  * 60L;
2681         n       += aTempTime.GetSec();
2682         rOutStr  = String::CreateFromInt32( n );
2683         rOutStr += ImplGetLocaleDataWrapper().getTime100SecSep();
2684         if ( aTempTime.Get100Sec() < 10 )
2685             rOutStr += '0';
2686         rOutStr += String::CreateFromInt32( aTempTime.Get100Sec() );
2687     }
2688     else if ( mbDuration )
2689         rOutStr = ImplGetLocaleDataWrapper().getDuration( aTempTime, bSecond, b100Sec );
2690     else
2691     {
2692         rOutStr = ImplGetLocaleDataWrapper().getTime( aTempTime, bSecond, b100Sec );
2693         if ( GetTimeFormat() == HOUR_12 )
2694         {
2695             if ( aTempTime.GetHour() > 12 )
2696             {
2697                 Time aT( aTempTime );
2698                 aT.SetHour( aT.GetHour() % 12 );
2699                 rOutStr = ImplGetLocaleDataWrapper().getTime( aT, bSecond, b100Sec );
2700             }
2701             // Don't use LocaleDataWrapper, we want AM/PM
2702             if ( aTempTime.GetHour() < 12 )
2703                 rOutStr += String( RTL_CONSTASCII_USTRINGPARAM( "AM" ) ); // ImplGetLocaleDataWrapper().getTimeAM();
2704             else
2705                 rOutStr += String( RTL_CONSTASCII_USTRINGPARAM( "PM" ) ); // ImplGetLocaleDataWrapper().getTimePM();
2706         }
2707     }
2708 
2709     return sal_True;
2710 }
2711 
2712 // -----------------------------------------------------------------------
ImplAllowMalformedInput() const2713 sal_Bool TimeFormatter::ImplAllowMalformedInput() const
2714 {
2715     return !IsEnforceValidValue();
2716 }
2717 
2718 // -----------------------------------------------------------------------
2719 
ImplTimeSpinArea(sal_Bool bUp)2720 void TimeField::ImplTimeSpinArea( sal_Bool bUp )
2721 {
2722     if ( GetField() )
2723     {
2724         xub_StrLen nTimeArea = 0;
2725         Time aTime( GetTime() );
2726         XubString aText( GetText() );
2727         Selection aSelection( GetField()->GetSelection() );
2728 
2729         // Area suchen
2730         if ( GetFormat() != TIMEF_SEC_CS )
2731         {
2732             for ( xub_StrLen i = 1, nPos = 0; i <= 4; i++ )
2733             {
2734                 xub_StrLen nPos1 = aText.Search( ImplGetLocaleDataWrapper().getTimeSep(), nPos );
2735                 xub_StrLen nPos2 = aText.Search( ImplGetLocaleDataWrapper().getTime100SecSep(), nPos );
2736                 nPos = nPos1 < nPos2 ? nPos1 : nPos2;
2737                 if ( nPos >= (xub_StrLen)aSelection.Max() )
2738                 {
2739                     nTimeArea = i;
2740                     break;
2741                 }
2742                 else
2743                     nPos++;
2744             }
2745         }
2746         else
2747         {
2748             xub_StrLen nPos = aText.Search( ImplGetLocaleDataWrapper().getTime100SecSep() );
2749             if ( nPos == STRING_NOTFOUND || nPos >= (xub_StrLen)aSelection.Max() )
2750                 nTimeArea = 3;
2751             else
2752                 nTimeArea = 4;
2753         }
2754 
2755         if ( nTimeArea )
2756         {
2757             Time aAddTime( 0, 0, 0 );
2758             if ( nTimeArea == 1 )
2759                 aAddTime = Time( 1, 0 );
2760             else if ( nTimeArea == 2 )
2761                 aAddTime = Time( 0, 1 );
2762             else if ( nTimeArea == 3 )
2763                 aAddTime = Time( 0, 0, 1 );
2764             else if ( nTimeArea == 4 )
2765                 aAddTime = Time( 0, 0, 0, 1 );
2766 
2767             if ( !bUp )
2768                 aAddTime = -aAddTime;
2769 
2770             aTime += aAddTime;
2771             if ( !IsDuration() )
2772             {
2773                 Time aAbsMaxTime( 23, 59, 59, 99 );
2774                 if ( aTime > aAbsMaxTime )
2775                     aTime = aAbsMaxTime;
2776                 Time aAbsMinTime( 0, 0 );
2777                 if ( aTime < aAbsMinTime )
2778                     aTime = aAbsMinTime;
2779             }
2780             ImplNewFieldValue( aTime );
2781         }
2782 
2783     }
2784 }
2785 
2786 // -----------------------------------------------------------------------
2787 
ImplInit()2788 void TimeFormatter::ImplInit()
2789 {
2790     meFormat        = TIMEF_NONE;
2791     mbDuration      = sal_False;
2792     mnTimeFormat    = HOUR_24;  // Should become a ExtTimeFieldFormat in next implementation, merge with mbDuration and meFormat
2793 }
2794 
2795 // -----------------------------------------------------------------------
2796 
TimeFormatter()2797 TimeFormatter::TimeFormatter() :
2798     maLastTime( 0, 0 ),
2799     maMin( 0, 0 ),
2800     maMax( 23, 59, 59, 99 ),
2801     mbEnforceValidValue( sal_True ),
2802     maFieldTime( 0, 0 )
2803 {
2804     ImplInit();
2805 }
2806 
2807 // -----------------------------------------------------------------------
2808 
ImplLoadRes(const ResId & rResId)2809 void TimeFormatter::ImplLoadRes( const ResId& rResId )
2810 {
2811     ResMgr* pMgr = rResId.GetResMgr();
2812     if( pMgr )
2813     {
2814         sal_uLong   nMask = pMgr->ReadLong();
2815 
2816         if ( TIMEFORMATTER_MIN & nMask )
2817         {
2818             SetMin( Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
2819             pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
2820         }
2821 
2822         if ( TIMEFORMATTER_MAX & nMask )
2823         {
2824             SetMax( Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
2825             pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
2826         }
2827 
2828         if ( TIMEFORMATTER_TIMEFIELDFORMAT & nMask )
2829             meFormat = (TimeFieldFormat)pMgr->ReadLong();
2830 
2831         if ( TIMEFORMATTER_DURATION & nMask )
2832             mbDuration = (sal_Bool)pMgr->ReadShort();
2833 
2834         if ( TIMEFORMATTER_STRICTFORMAT & nMask )
2835             SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
2836 
2837         if ( TIMEFORMATTER_VALUE & nMask )
2838         {
2839             maFieldTime = Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
2840             if ( maFieldTime > GetMax() )
2841                 maFieldTime = GetMax();
2842             if ( maFieldTime < GetMin() )
2843                 maFieldTime = GetMin();
2844             maLastTime = maFieldTime;
2845 
2846             pMgr->Increment( pMgr->GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
2847         }
2848     }
2849 }
2850 
2851 // -----------------------------------------------------------------------
2852 
~TimeFormatter()2853 TimeFormatter::~TimeFormatter()
2854 {
2855 }
2856 
2857 // -----------------------------------------------------------------------
2858 
ReformatAll()2859 void TimeFormatter::ReformatAll()
2860 {
2861     Reformat();
2862 }
2863 
2864 // -----------------------------------------------------------------------
2865 
SetMin(const Time & rNewMin)2866 void TimeFormatter::SetMin( const Time& rNewMin )
2867 {
2868     maMin = rNewMin;
2869     if ( !IsEmptyFieldValue() )
2870         ReformatAll();
2871 }
2872 
2873 // -----------------------------------------------------------------------
2874 
SetMax(const Time & rNewMax)2875 void TimeFormatter::SetMax( const Time& rNewMax )
2876 {
2877     maMax = rNewMax;
2878     if ( !IsEmptyFieldValue() )
2879         ReformatAll();
2880 }
2881 
2882 // -----------------------------------------------------------------------
2883 
SetTimeFormat(TimeFormatter::TimeFormat eNewFormat)2884 void TimeFormatter::SetTimeFormat( TimeFormatter::TimeFormat eNewFormat )
2885 {
2886     mnTimeFormat = sal::static_int_cast<sal_uInt16>(eNewFormat);
2887 }
2888 
2889 // -----------------------------------------------------------------------
2890 
GetTimeFormat() const2891 TimeFormatter::TimeFormat TimeFormatter::GetTimeFormat() const
2892 {
2893     return (TimeFormat)mnTimeFormat;
2894 }
2895 
2896 // -----------------------------------------------------------------------
2897 
SetFormat(TimeFieldFormat eNewFormat)2898 void TimeFormatter::SetFormat( TimeFieldFormat eNewFormat )
2899 {
2900     meFormat = eNewFormat;
2901     ReformatAll();
2902 }
2903 
2904 // -----------------------------------------------------------------------
2905 
SetDuration(sal_Bool bNewDuration)2906 void TimeFormatter::SetDuration( sal_Bool bNewDuration )
2907 {
2908     mbDuration = bNewDuration;
2909     ReformatAll();
2910 }
2911 
2912 // -----------------------------------------------------------------------
2913 
SetTime(const Time & rNewTime)2914 void TimeFormatter::SetTime( const Time& rNewTime )
2915 {
2916     SetUserTime( rNewTime );
2917     maFieldTime = maLastTime;
2918     SetEmptyFieldValueData( sal_False );
2919 }
2920 
2921 // -----------------------------------------------------------------------
2922 
ImplNewFieldValue(const Time & rTime)2923 void TimeFormatter::ImplNewFieldValue( const Time& rTime )
2924 {
2925     if ( GetField() )
2926     {
2927         Selection aSelection = GetField()->GetSelection();
2928         aSelection.Justify();
2929         XubString aText = GetField()->GetText();
2930         // Wenn bis ans Ende selektiert war, soll das auch so bleiben...
2931         if ( (xub_StrLen)aSelection.Max() == aText.Len() )
2932         {
2933             if ( !aSelection.Len() )
2934                 aSelection.Min() = SELECTION_MAX;
2935             aSelection.Max() = SELECTION_MAX;
2936         }
2937 
2938         Time aOldLastTime = maLastTime;
2939         ImplSetUserTime( rTime, &aSelection );
2940         maLastTime = aOldLastTime;
2941 
2942         // Modify am Edit wird nur bei KeyInput gesetzt...
2943         if ( GetField()->GetText() != aText )
2944         {
2945             GetField()->SetModifyFlag();
2946             GetField()->Modify();
2947         }
2948     }
2949 }
2950 
2951 // -----------------------------------------------------------------------
2952 
ImplSetUserTime(const Time & rNewTime,Selection * pNewSelection)2953 void TimeFormatter::ImplSetUserTime( const Time& rNewTime, Selection* pNewSelection )
2954 {
2955     Time aNewTime = rNewTime;
2956     if ( aNewTime > GetMax() )
2957         aNewTime = GetMax();
2958     else if ( aNewTime < GetMin() )
2959         aNewTime = GetMin();
2960     maLastTime = aNewTime;
2961 
2962     if ( GetField() )
2963     {
2964         XubString aStr;
2965         sal_Bool bSec    = sal_False;
2966         sal_Bool b100Sec = sal_False;
2967         if ( meFormat != TIMEF_NONE )
2968             bSec = sal_True;
2969         if ( meFormat == TIMEF_100TH_SEC || meFormat == TIMEF_SEC_CS )
2970             b100Sec = sal_True;
2971         if ( meFormat == TIMEF_SEC_CS )
2972         {
2973             sal_uLong n  = aNewTime.GetHour() * 3600L;
2974             n       += aNewTime.GetMin()  * 60L;
2975             n       += aNewTime.GetSec();
2976             aStr     = String::CreateFromInt32( n );
2977             aStr    += ImplGetLocaleDataWrapper().getTime100SecSep();
2978             if ( aNewTime.Get100Sec() < 10 )
2979                 aStr += '0';
2980             aStr += String::CreateFromInt32( aNewTime.Get100Sec() );
2981         }
2982         else if ( mbDuration )
2983         {
2984             aStr = ImplGetLocaleDataWrapper().getDuration( aNewTime, bSec, b100Sec );
2985         }
2986         else
2987         {
2988             aStr = ImplGetLocaleDataWrapper().getTime( aNewTime, bSec, b100Sec );
2989             if ( GetTimeFormat() == HOUR_12 )
2990             {
2991                 if ( aNewTime.GetHour() > 12 )
2992                 {
2993                     Time aT( aNewTime );
2994                     aT.SetHour( aT.GetHour() % 12 );
2995                     aStr = ImplGetLocaleDataWrapper().getTime( aT, bSec, b100Sec );
2996                 }
2997                 // Don't use LocaleDataWrapper, we want AM/PM
2998                 if ( aNewTime.GetHour() < 12 )
2999                     aStr += String( RTL_CONSTASCII_USTRINGPARAM( "AM" ) ); // ImplGetLocaleDataWrapper().getTimeAM();
3000                 else
3001                     aStr += String( RTL_CONSTASCII_USTRINGPARAM( "PM" ) ); // ImplGetLocaleDataWrapper().getTimePM();
3002             }
3003         }
3004 
3005         ImplSetText( aStr, pNewSelection );
3006     }
3007 }
3008 
3009 // -----------------------------------------------------------------------
3010 
SetUserTime(const Time & rNewTime)3011 void TimeFormatter::SetUserTime( const Time& rNewTime )
3012 {
3013     ImplSetUserTime( rNewTime );
3014 }
3015 
3016 // -----------------------------------------------------------------------
3017 
GetTime() const3018 Time TimeFormatter::GetTime() const
3019 {
3020     Time aTime( 0, 0, 0 );
3021 
3022     if ( GetField() )
3023     {
3024         sal_Bool bAllowMailformed = ImplAllowMalformedInput();
3025         if ( ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
3026         {
3027             if ( aTime > GetMax() )
3028                 aTime = GetMax();
3029             else if ( aTime < GetMin() )
3030                 aTime = GetMin();
3031         }
3032         else
3033         {
3034             if ( bAllowMailformed )
3035                 aTime = GetInvalidTime();
3036             else
3037                 aTime = maLastTime;
3038         }
3039     }
3040 
3041     return aTime;
3042 }
3043 
3044 // -----------------------------------------------------------------------
3045 
GetRealTime() const3046 Time TimeFormatter::GetRealTime() const
3047 {
3048     Time aTime( 0, 0, 0 );
3049 
3050     if ( GetField() )
3051     {
3052         sal_Bool bAllowMailformed = ImplAllowMalformedInput();
3053         if ( !ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
3054             if ( bAllowMailformed )
3055                 aTime = GetInvalidTime();
3056     }
3057 
3058     return aTime;
3059 }
3060 
3061 // -----------------------------------------------------------------------
3062 
IsTimeModified() const3063 sal_Bool TimeFormatter::IsTimeModified() const
3064 {
3065     if ( ImplGetEmptyFieldValue() )
3066         return !IsEmptyTime();
3067     else if ( GetTime() != maFieldTime )
3068         return sal_True;
3069     else
3070         return sal_False;
3071 }
3072 
3073 // -----------------------------------------------------------------------
3074 
Reformat()3075 void TimeFormatter::Reformat()
3076 {
3077     if ( !GetField() )
3078         return;
3079 
3080     if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
3081         return;
3082 
3083     XubString aStr;
3084     sal_Bool bOK = ImplTimeReformat( GetField()->GetText(), aStr );
3085     if ( !bOK )
3086         return;
3087 
3088     if ( aStr.Len() )
3089     {
3090         ImplSetText( aStr );
3091         ImplTimeGetValue( aStr, maLastTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
3092     }
3093     else
3094         SetTime( maLastTime );
3095 }
3096 
3097 // -----------------------------------------------------------------------
3098 
TimeField(Window * pParent,WinBits nWinStyle)3099 TimeField::TimeField( Window* pParent, WinBits nWinStyle ) :
3100     SpinField( pParent, nWinStyle ),
3101     maFirst( GetMin() ),
3102     maLast( GetMax() )
3103 {
3104     SetField( this );
3105     SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, sal_False, sal_False ) );
3106     Reformat();
3107 }
3108 
3109 // -----------------------------------------------------------------------
3110 
TimeField(Window * pParent,const ResId & rResId)3111 TimeField::TimeField( Window* pParent, const ResId& rResId ) :
3112     SpinField( WINDOW_TIMEFIELD ),
3113     maFirst( GetMin() ),
3114     maLast( GetMax() )
3115 {
3116     rResId.SetRT( RSC_TIMEFIELD );
3117     WinBits nStyle = ImplInitRes( rResId );
3118     SpinField::ImplInit( pParent, nStyle );
3119     SetField( this );
3120     SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, sal_False, sal_False ) );
3121     ImplLoadRes( rResId );
3122 
3123     if ( !(nStyle & WB_HIDE ) )
3124         Show();
3125 }
3126 
3127 // -----------------------------------------------------------------------
3128 
ImplLoadRes(const ResId & rResId)3129 void TimeField::ImplLoadRes( const ResId& rResId )
3130 {
3131     SpinField::ImplLoadRes( rResId );
3132     ResMgr* pMgr = rResId.GetResMgr();
3133     if( pMgr )
3134     {
3135         TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
3136 
3137         sal_uLong      nMask = ReadLongRes();
3138 
3139         if ( TIMEFIELD_FIRST & nMask )
3140         {
3141             maFirst = Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
3142             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
3143         }
3144         if ( TIMEFIELD_LAST & nMask )
3145         {
3146             maLast = Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
3147             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
3148         }
3149     }
3150 
3151     Reformat();
3152 }
3153 
3154 // -----------------------------------------------------------------------
3155 
~TimeField()3156 TimeField::~TimeField()
3157 {
3158 }
3159 
3160 // -----------------------------------------------------------------------
3161 
PreNotify(NotifyEvent & rNEvt)3162 long TimeField::PreNotify( NotifyEvent& rNEvt )
3163 {
3164     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
3165     {
3166         if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
3167             return 1;
3168     }
3169 
3170     return SpinField::PreNotify( rNEvt );
3171 }
3172 
3173 // -----------------------------------------------------------------------
3174 
Notify(NotifyEvent & rNEvt)3175 long TimeField::Notify( NotifyEvent& rNEvt )
3176 {
3177     if ( rNEvt.GetType() == EVENT_GETFOCUS )
3178         MarkToBeReformatted( sal_False );
3179     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
3180     {
3181         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
3182         {
3183             if ( !ImplAllowMalformedInput() )
3184                 Reformat();
3185             else
3186             {
3187                 Time aTime( 0, 0, 0 );
3188                 if ( ImplTimeGetValue( GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), sal_False ) )
3189                     // even with strict text analysis, our text is a valid time -> do a complete
3190                     // reformat
3191                     Reformat();
3192             }
3193         }
3194     }
3195 
3196     return SpinField::Notify( rNEvt );
3197 }
3198 
3199 // -----------------------------------------------------------------------
3200 
DataChanged(const DataChangedEvent & rDCEvt)3201 void TimeField::DataChanged( const DataChangedEvent& rDCEvt )
3202 {
3203     SpinField::DataChanged( rDCEvt );
3204 
3205     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
3206     {
3207         if ( IsDefaultLocale() )
3208             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
3209         ReformatAll();
3210     }
3211 }
3212 
3213 // -----------------------------------------------------------------------
3214 
Modify()3215 void TimeField::Modify()
3216 {
3217     MarkToBeReformatted( sal_True );
3218     SpinField::Modify();
3219 }
3220 
3221 // -----------------------------------------------------------------------
3222 
Up()3223 void TimeField::Up()
3224 {
3225     ImplTimeSpinArea( sal_True );
3226     SpinField::Up();
3227 }
3228 
3229 // -----------------------------------------------------------------------
3230 
Down()3231 void TimeField::Down()
3232 {
3233     ImplTimeSpinArea( sal_False );
3234     SpinField::Down();
3235 }
3236 
3237 // -----------------------------------------------------------------------
3238 
First()3239 void TimeField::First()
3240 {
3241     ImplNewFieldValue( maFirst );
3242     SpinField::First();
3243 }
3244 
3245 // -----------------------------------------------------------------------
3246 
Last()3247 void TimeField::Last()
3248 {
3249     ImplNewFieldValue( maLast );
3250     SpinField::Last();
3251 }
3252 
3253 // -----------------------------------------------------------------------
3254 
SetExtFormat(ExtTimeFieldFormat eFormat)3255 void TimeField::SetExtFormat( ExtTimeFieldFormat eFormat )
3256 {
3257     switch ( eFormat )
3258     {
3259         case EXTTIMEF_24H_SHORT:
3260         {
3261             SetTimeFormat( HOUR_24 );
3262             SetDuration( sal_False );
3263             SetFormat( TIMEF_NONE );
3264         }
3265         break;
3266         case EXTTIMEF_24H_LONG:
3267         {
3268             SetTimeFormat( HOUR_24 );
3269             SetDuration( sal_False );
3270             SetFormat( TIMEF_SEC );
3271         }
3272         break;
3273         case EXTTIMEF_12H_SHORT:
3274         {
3275             SetTimeFormat( HOUR_12 );
3276             SetDuration( sal_False );
3277             SetFormat( TIMEF_NONE );
3278         }
3279         break;
3280         case EXTTIMEF_12H_LONG:
3281         {
3282             SetTimeFormat( HOUR_12 );
3283             SetDuration( sal_False );
3284             SetFormat( TIMEF_SEC );
3285         }
3286         break;
3287         case EXTTIMEF_DURATION_SHORT:
3288         {
3289             SetDuration( sal_True );
3290             SetFormat( TIMEF_NONE );
3291         }
3292         break;
3293         case EXTTIMEF_DURATION_LONG:
3294         {
3295             SetDuration( sal_True );
3296             SetFormat( TIMEF_SEC );
3297         }
3298         break;
3299         default:    DBG_ERROR( "ExtTimeFieldFormat unknown!" );
3300     }
3301 
3302     if ( GetField() && GetField()->GetText().Len() )
3303         SetUserTime( GetTime() );
3304     ReformatAll();
3305 }
3306 
3307 // -----------------------------------------------------------------------
3308 
TimeBox(Window * pParent,WinBits nWinStyle)3309 TimeBox::TimeBox( Window* pParent, WinBits nWinStyle ) :
3310     ComboBox( pParent, nWinStyle )
3311 {
3312     SetField( this );
3313     SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, sal_False, sal_False ) );
3314     Reformat();
3315 }
3316 
3317 // -----------------------------------------------------------------------
3318 
TimeBox(Window * pParent,const ResId & rResId)3319 TimeBox::TimeBox( Window* pParent, const ResId& rResId ) :
3320     ComboBox( WINDOW_TIMEBOX )
3321 {
3322     rResId.SetRT( RSC_TIMEBOX );
3323     WinBits nStyle = ImplInitRes( rResId );
3324     ComboBox::ImplInit( pParent, nStyle );
3325     SetField( this );
3326     SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, sal_False, sal_False ) );
3327     ComboBox::ImplLoadRes( rResId );
3328     ResMgr* pMgr = rResId.GetResMgr();
3329     if( pMgr )
3330         TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
3331     Reformat();
3332 
3333     if ( !(nStyle & WB_HIDE) )
3334         Show();
3335 }
3336 
3337 // -----------------------------------------------------------------------
3338 
~TimeBox()3339 TimeBox::~TimeBox()
3340 {
3341 }
3342 
3343 // -----------------------------------------------------------------------
3344 
PreNotify(NotifyEvent & rNEvt)3345 long TimeBox::PreNotify( NotifyEvent& rNEvt )
3346 {
3347     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
3348     {
3349         if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
3350             return 1;
3351     }
3352 
3353     return ComboBox::PreNotify( rNEvt );
3354 }
3355 
3356 // -----------------------------------------------------------------------
3357 
Notify(NotifyEvent & rNEvt)3358 long TimeBox::Notify( NotifyEvent& rNEvt )
3359 {
3360     if ( rNEvt.GetType() == EVENT_GETFOCUS )
3361         MarkToBeReformatted( sal_False );
3362     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
3363     {
3364         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
3365             Reformat();
3366     }
3367 
3368     return ComboBox::Notify( rNEvt );
3369 }
3370 
3371 // -----------------------------------------------------------------------
3372 
DataChanged(const DataChangedEvent & rDCEvt)3373 void TimeBox::DataChanged( const DataChangedEvent& rDCEvt )
3374 {
3375     ComboBox::DataChanged( rDCEvt );
3376 
3377     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
3378     {
3379         if ( IsDefaultLocale() )
3380             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
3381         ReformatAll();
3382     }
3383 }
3384 
3385 // -----------------------------------------------------------------------
3386 
Modify()3387 void TimeBox::Modify()
3388 {
3389     MarkToBeReformatted( sal_True );
3390     ComboBox::Modify();
3391 }
3392 
3393 // -----------------------------------------------------------------------
3394 
ReformatAll()3395 void TimeBox::ReformatAll()
3396 {
3397     XubString aStr;
3398     SetUpdateMode( sal_False );
3399     sal_uInt16 nEntryCount = GetEntryCount();
3400     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
3401     {
3402         ImplTimeReformat( GetEntry( i ), aStr );
3403         RemoveEntry( i );
3404         InsertEntry( aStr, i );
3405     }
3406     TimeFormatter::Reformat();
3407     SetUpdateMode( sal_True );
3408 }
3409 
3410 // -----------------------------------------------------------------------
3411 
InsertTime(const Time & rTime,sal_uInt16 nPos)3412 void TimeBox::InsertTime( const Time& rTime, sal_uInt16 nPos )
3413 {
3414     Time aTime = rTime;
3415     if ( aTime > GetMax() )
3416         aTime = GetMax();
3417     else if ( aTime < GetMin() )
3418         aTime = GetMin();
3419 
3420     sal_Bool bSec    = sal_False;
3421     sal_Bool b100Sec = sal_False;
3422     if ( GetFormat() == TIMEF_SEC )
3423         bSec = sal_True;
3424     if ( GetFormat() == TIMEF_100TH_SEC || GetFormat() == TIMEF_SEC_CS )
3425         bSec = b100Sec = sal_True;
3426     ComboBox::InsertEntry( ImplGetLocaleDataWrapper().getTime( aTime, bSec, b100Sec ), nPos );
3427 }
3428 
3429 // -----------------------------------------------------------------------
3430 
RemoveTime(const Time & rTime)3431 void TimeBox::RemoveTime( const Time& rTime )
3432 {
3433     sal_Bool bSec    = sal_False;
3434     sal_Bool b100Sec = sal_False;
3435     if ( GetFormat() == TIMEF_SEC )
3436         bSec = sal_True;
3437     if ( GetFormat() == TIMEF_100TH_SEC || TIMEF_SEC_CS )
3438         bSec = b100Sec = sal_True;
3439     ComboBox::RemoveEntry( ImplGetLocaleDataWrapper().getTime( rTime, bSec, b100Sec ) );
3440 }
3441 
3442 // -----------------------------------------------------------------------
3443 
GetTime(sal_uInt16 nPos) const3444 Time TimeBox::GetTime( sal_uInt16 nPos ) const
3445 {
3446     Time aTime( 0, 0, 0 );
3447     ImplTimeGetValue( ComboBox::GetEntry( nPos ), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
3448     return aTime;
3449 }
3450 
3451 // -----------------------------------------------------------------------
3452 
GetTimePos(const Time & rTime) const3453 sal_uInt16 TimeBox::GetTimePos( const Time& rTime ) const
3454 {
3455     sal_Bool bSec    = sal_False;
3456     sal_Bool b100Sec = sal_False;
3457     if ( GetFormat() == TIMEF_SEC )
3458         bSec = sal_True;
3459     if ( GetFormat() == TIMEF_100TH_SEC || TIMEF_SEC_CS )
3460         bSec = b100Sec = sal_True;
3461     return ComboBox::GetEntryPos( ImplGetLocaleDataWrapper().getTime( rTime, bSec, b100Sec ) );
3462 }
3463