Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <algorithm>
23 :
24 : #include <tools/diagnose_ex.h>
25 : #include <comphelper/processfactory.hxx>
26 : #include <comphelper/string.hxx>
27 : #include <tools/rc.h>
28 : #include <vcl/svapp.hxx>
29 : #include <vcl/event.hxx>
30 : #include <vcl/field.hxx>
31 : #include <vcl/unohelp.hxx>
32 : #include <vcl/settings.hxx>
33 :
34 : #include <svdata.hxx>
35 :
36 : #include <i18nlangtag/mslangid.hxx>
37 :
38 : #include <com/sun/star/lang/Locale.hpp>
39 : #include <com/sun/star/i18n/XCharacterClassification.hpp>
40 : #include <com/sun/star/i18n/KCharacterType.hpp>
41 :
42 : #include <unotools/localedatawrapper.hxx>
43 : #include <unotools/calendarwrapper.hxx>
44 : #include <unotools/charclass.hxx>
45 : #include <unotools/misccfg.hxx>
46 :
47 : using namespace ::com::sun::star;
48 : using namespace ::comphelper;
49 :
50 : #define EDITMASK_LITERAL 'L'
51 : #define EDITMASK_ALPHA 'a'
52 : #define EDITMASK_UPPERALPHA 'A'
53 : #define EDITMASK_ALPHANUM 'c'
54 : #define EDITMASK_UPPERALPHANUM 'C'
55 : #define EDITMASK_NUM 'N'
56 : #define EDITMASK_NUMSPACE 'n'
57 : #define EDITMASK_ALLCHAR 'x'
58 : #define EDITMASK_UPPERALLCHAR 'X'
59 :
60 140 : uno::Reference< i18n::XCharacterClassification > ImplGetCharClass()
61 : {
62 140 : static uno::Reference< i18n::XCharacterClassification > xCharClass;
63 140 : if ( !xCharClass.is() )
64 4 : xCharClass = vcl::unohelper::CreateCharacterClassification();
65 :
66 140 : return xCharClass;
67 : }
68 :
69 624 : static sal_Unicode* ImplAddString( sal_Unicode* pBuf, const OUString& rStr )
70 : {
71 624 : if ( rStr.getLength() == 1 )
72 624 : *pBuf++ = rStr[0];
73 0 : else if ( rStr.isEmpty() )
74 : ;
75 : else
76 : {
77 0 : memcpy( pBuf, rStr.getStr(), rStr.getLength() * sizeof(sal_Unicode) );
78 0 : pBuf += rStr.getLength();
79 : }
80 624 : return pBuf;
81 : }
82 :
83 936 : static sal_Unicode* ImplAddNum( sal_Unicode* pBuf, sal_uLong nNumber, int nMinLen )
84 : {
85 : // fill temp buffer with digits
86 : sal_Unicode aTempBuf[30];
87 936 : sal_Unicode* pTempBuf = aTempBuf;
88 1474 : do
89 : {
90 1474 : *pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
91 1474 : pTempBuf++;
92 1474 : nNumber /= 10;
93 1474 : if ( nMinLen )
94 1474 : nMinLen--;
95 : }
96 : while ( nNumber );
97 :
98 : // fill with zeros up to the minimal length
99 2622 : while ( nMinLen > 0 )
100 : {
101 750 : *pBuf = '0';
102 750 : pBuf++;
103 750 : nMinLen--;
104 : }
105 :
106 : // copy temp buffer to real buffer
107 1474 : do
108 : {
109 1474 : pTempBuf--;
110 1474 : *pBuf = *pTempBuf;
111 1474 : pBuf++;
112 : }
113 : while ( pTempBuf != aTempBuf );
114 :
115 936 : return pBuf;
116 : }
117 :
118 1758 : static sal_uInt16 ImplGetNum( const sal_Unicode*& rpBuf, bool& rbError )
119 : {
120 1758 : if ( !*rpBuf )
121 : {
122 0 : rbError = true;
123 0 : return 0;
124 : }
125 :
126 1758 : sal_uInt16 nNumber = 0;
127 7716 : while( ( *rpBuf >= '0' ) && ( *rpBuf <= '9' ) )
128 : {
129 4200 : nNumber *= 10;
130 4200 : nNumber += *rpBuf - '0';
131 4200 : rpBuf++;
132 : }
133 :
134 1758 : return nNumber;
135 : }
136 :
137 1758 : static void ImplSkipDelimiters( const sal_Unicode*& rpBuf )
138 : {
139 7618 : while( ( *rpBuf == ',' ) || ( *rpBuf == '.' ) || ( *rpBuf == ';' ) ||
140 5860 : ( *rpBuf == ':' ) || ( *rpBuf == '-' ) || ( *rpBuf == '/' ) )
141 : {
142 1172 : rpBuf++;
143 : }
144 1758 : }
145 :
146 140 : static bool ImplIsPatternChar( sal_Unicode cChar, sal_Char cEditMask )
147 : {
148 140 : sal_Int32 nType = 0;
149 :
150 : try
151 : {
152 140 : OUString aCharStr(cChar);
153 280 : nType = ImplGetCharClass()->getStringType( aCharStr, 0, aCharStr.getLength(),
154 280 : Application::GetSettings().GetLanguageTag().getLocale() );
155 : }
156 0 : catch (const ::com::sun::star::uno::Exception&)
157 : {
158 : SAL_WARN( "vcl.control", "ImplIsPatternChar: Exception caught!" );
159 : DBG_UNHANDLED_EXCEPTION();
160 0 : return false;
161 : }
162 :
163 140 : if ( (cEditMask == EDITMASK_ALPHA) || (cEditMask == EDITMASK_UPPERALPHA) )
164 : {
165 0 : if( !CharClass::isLetterType( nType ) )
166 0 : return false;
167 : }
168 140 : else if ( cEditMask == EDITMASK_NUM )
169 : {
170 80 : if( !CharClass::isNumericType( nType ) )
171 80 : return false;
172 : }
173 60 : else if ( (cEditMask == EDITMASK_ALPHANUM) || (cEditMask == EDITMASK_UPPERALPHANUM) )
174 : {
175 96 : if( !CharClass::isLetterNumericType( nType ) )
176 0 : return false;
177 : }
178 12 : else if ( (cEditMask == EDITMASK_ALLCHAR) || (cEditMask == EDITMASK_UPPERALLCHAR) )
179 : {
180 0 : if ( cChar < 32 )
181 0 : return false;
182 : }
183 12 : else if ( cEditMask == EDITMASK_NUMSPACE )
184 : {
185 0 : if ( !CharClass::isNumericType( nType ) && ( cChar != ' ' ) )
186 0 : return false;
187 : }
188 : else
189 12 : return false;
190 :
191 48 : return true;
192 : }
193 :
194 140 : static sal_Unicode ImplPatternChar( sal_Unicode cChar, sal_Char cEditMask )
195 : {
196 140 : if ( ImplIsPatternChar( cChar, cEditMask ) )
197 : {
198 48 : if ( (cEditMask == EDITMASK_UPPERALPHA) ||
199 48 : (cEditMask == EDITMASK_UPPERALPHANUM) ||
200 : ( cEditMask == EDITMASK_UPPERALLCHAR ) )
201 : {
202 0 : cChar = ImplGetCharClass()->toUpper(OUString(cChar), 0, 1,
203 0 : Application::GetSettings().GetLanguageTag().getLocale())[0];
204 : }
205 48 : return cChar;
206 : }
207 : else
208 92 : return 0;
209 : }
210 :
211 0 : static bool ImplCommaPointCharEqual( sal_Unicode c1, sal_Unicode c2 )
212 : {
213 0 : if ( c1 == c2 )
214 0 : return true;
215 0 : else if ( ((c1 == '.') || (c1 == ',')) &&
216 0 : ((c2 == '.') || (c2 == ',')) )
217 0 : return true;
218 : else
219 0 : return false;
220 : }
221 :
222 190 : static OUString ImplPatternReformat( const OUString& rStr,
223 : const OString& rEditMask,
224 : const OUString& rLiteralMask,
225 : sal_uInt16 nFormatFlags )
226 : {
227 190 : if (rEditMask.isEmpty())
228 106 : return rStr;
229 :
230 84 : OUString aStr = rStr;
231 168 : OUStringBuffer aOutStr = OUString(rLiteralMask);
232 : sal_Unicode cTempChar;
233 : sal_Unicode cChar;
234 : sal_Unicode cLiteral;
235 : sal_Char cMask;
236 84 : sal_Int32 nStrIndex = 0;
237 84 : sal_Int32 i = 0;
238 : sal_Int32 n;
239 :
240 308 : while ( i < rEditMask.getLength() )
241 : {
242 202 : if ( nStrIndex >= aStr.getLength() )
243 62 : break;
244 :
245 140 : cChar = aStr[nStrIndex];
246 140 : cLiteral = rLiteralMask[i];
247 140 : cMask = rEditMask[i];
248 :
249 : // current position is a literal
250 140 : if ( cMask == EDITMASK_LITERAL )
251 : {
252 : // if it is a literal copy otherwise ignore because it might be the next valid
253 : // character of the string
254 0 : if ( ImplCommaPointCharEqual( cChar, cLiteral ) )
255 0 : nStrIndex++;
256 : else
257 : {
258 : // Otherwise we check if it is a invalid character. This is the case if it does not
259 : // fit in the pattern of the next non-literal character.
260 0 : n = i+1;
261 0 : while ( n < rEditMask.getLength() )
262 : {
263 0 : if ( rEditMask[n] != EDITMASK_LITERAL )
264 : {
265 0 : if ( !ImplIsPatternChar( cChar, rEditMask[n] ) )
266 0 : nStrIndex++;
267 0 : break;
268 : }
269 :
270 0 : n++;
271 : }
272 : }
273 : }
274 : else
275 : {
276 : // valid character at this position
277 140 : cTempChar = ImplPatternChar( cChar, cMask );
278 140 : if ( cTempChar )
279 : {
280 : // use this character
281 48 : aOutStr[i] = cTempChar;
282 48 : nStrIndex++;
283 : }
284 : else
285 : {
286 : // copy if it is a literal character
287 92 : if ( cLiteral == cChar )
288 74 : nStrIndex++;
289 : else
290 : {
291 : // If the invalid character might be the next literal character then we jump
292 : // ahead to it, otherwise we ignore it. Do only if empty literals are allowed.
293 18 : if ( nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS )
294 : {
295 0 : n = i;
296 0 : while ( n < rEditMask.getLength() )
297 : {
298 0 : if ( rEditMask[n] == EDITMASK_LITERAL )
299 : {
300 0 : if ( ImplCommaPointCharEqual( cChar, rLiteralMask[n] ) )
301 0 : i = n+1;
302 :
303 0 : break;
304 : }
305 :
306 0 : n++;
307 : }
308 : }
309 :
310 18 : nStrIndex++;
311 18 : continue;
312 : }
313 : }
314 : }
315 :
316 122 : i++;
317 : }
318 :
319 168 : return aOutStr.makeStringAndClear();
320 : }
321 :
322 0 : static void ImplPatternMaxPos( const OUString& rStr, const OString& rEditMask,
323 : sal_uInt16 nFormatFlags, bool bSameMask,
324 : sal_Int32 nCursorPos, sal_Int32& rPos )
325 : {
326 :
327 : // last position must not be longer than the contained string
328 0 : sal_Int32 nMaxPos = rStr.getLength();
329 :
330 : // if non empty literals are allowed ignore blanks at the end as well
331 0 : if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
332 : {
333 0 : while ( nMaxPos )
334 : {
335 0 : if ( (rEditMask[nMaxPos-1] != EDITMASK_LITERAL) &&
336 0 : (rStr[nMaxPos-1] != ' ') )
337 0 : break;
338 0 : nMaxPos--;
339 : }
340 :
341 : // if we are in front of a literal, continue search until first character after the literal
342 0 : sal_Int32 nTempPos = nMaxPos;
343 0 : while ( nTempPos < rEditMask.getLength() )
344 : {
345 0 : if ( rEditMask[nTempPos] != EDITMASK_LITERAL )
346 : {
347 0 : nMaxPos = nTempPos;
348 0 : break;
349 : }
350 0 : nTempPos++;
351 : }
352 : }
353 :
354 0 : if ( rPos > nMaxPos )
355 0 : rPos = nMaxPos;
356 :
357 : // character should not move left
358 0 : if ( rPos < nCursorPos )
359 0 : rPos = nCursorPos;
360 0 : }
361 :
362 0 : static void ImplPatternProcessStrictModify( Edit* pEdit,
363 : const OString& rEditMask,
364 : const OUString& rLiteralMask,
365 : sal_uInt16 nFormatFlags, bool bSameMask )
366 : {
367 0 : OUString aText = pEdit->GetText();
368 :
369 : // remove leading blanks
370 0 : if ( bSameMask && !(nFormatFlags & PATTERN_FORMAT_EMPTYLITERALS) )
371 : {
372 0 : sal_Int32 i = 0;
373 0 : sal_Int32 nMaxLen = aText.getLength();
374 0 : while ( i < nMaxLen )
375 : {
376 0 : if ( (rEditMask[i] != EDITMASK_LITERAL) &&
377 0 : (aText[i] != ' ') )
378 0 : break;
379 :
380 0 : i++;
381 : }
382 : // keep all literal characters
383 0 : while ( i && (rEditMask[i] == EDITMASK_LITERAL) )
384 0 : i--;
385 0 : aText = aText.copy( i );
386 : }
387 :
388 0 : OUString aNewText = ImplPatternReformat( aText, rEditMask, rLiteralMask, nFormatFlags );
389 0 : if ( aNewText != aText )
390 : {
391 : // adjust selection such that it remains at the end if it was there before
392 0 : Selection aSel = pEdit->GetSelection();
393 0 : sal_Int64 nMaxSel = std::max( aSel.Min(), aSel.Max() );
394 0 : if ( nMaxSel >= aText.getLength() )
395 : {
396 0 : sal_Int32 nMaxPos = aNewText.getLength();
397 0 : ImplPatternMaxPos( aNewText, rEditMask, nFormatFlags, bSameMask, nMaxSel, nMaxPos );
398 0 : if ( aSel.Min() == aSel.Max() )
399 : {
400 0 : aSel.Min() = nMaxPos;
401 0 : aSel.Max() = aSel.Min();
402 : }
403 0 : else if ( aSel.Min() > aSel.Max() )
404 0 : aSel.Min() = nMaxPos;
405 : else
406 0 : aSel.Max() = nMaxPos;
407 : }
408 0 : pEdit->SetText( aNewText, aSel );
409 0 : }
410 0 : }
411 :
412 0 : static sal_Int32 ImplPatternLeftPos(const OString& rEditMask, sal_Int32 nCursorPos)
413 : {
414 : // search non-literal predecessor
415 0 : sal_Int32 nNewPos = nCursorPos;
416 0 : sal_Int32 nTempPos = nNewPos;
417 0 : while ( nTempPos )
418 : {
419 0 : if ( rEditMask[nTempPos-1] != EDITMASK_LITERAL )
420 : {
421 0 : nNewPos = nTempPos-1;
422 0 : break;
423 : }
424 0 : nTempPos--;
425 : }
426 0 : return nNewPos;
427 : }
428 :
429 0 : static sal_Int32 ImplPatternRightPos( const OUString& rStr, const OString& rEditMask,
430 : sal_uInt16 nFormatFlags, bool bSameMask,
431 : sal_Int32 nCursorPos )
432 : {
433 : // search non-literal successor
434 0 : sal_Int32 nNewPos = nCursorPos;
435 0 : sal_Int32 nTempPos = nNewPos;
436 0 : while ( nTempPos < rEditMask.getLength() )
437 : {
438 0 : if ( rEditMask[nTempPos+1] != EDITMASK_LITERAL )
439 : {
440 0 : nNewPos = nTempPos+1;
441 0 : break;
442 : }
443 0 : nTempPos++;
444 : }
445 0 : ImplPatternMaxPos( rStr, rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
446 0 : return nNewPos;
447 : }
448 :
449 0 : static bool ImplPatternProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
450 : const OString& rEditMask,
451 : const OUString& rLiteralMask,
452 : bool bStrictFormat,
453 : sal_uInt16 nFormatFlags,
454 : bool bSameMask,
455 : bool& rbInKeyInput )
456 : {
457 0 : if ( rEditMask.isEmpty() || !bStrictFormat )
458 0 : return false;
459 :
460 0 : Selection aOldSel = pEdit->GetSelection();
461 0 : vcl::KeyCode aCode = rKEvt.GetKeyCode();
462 0 : sal_Unicode cChar = rKEvt.GetCharCode();
463 0 : sal_uInt16 nKeyCode = aCode.GetCode();
464 0 : bool bShift = aCode.IsShift();
465 0 : sal_Int32 nCursorPos = static_cast<sal_Int32>(aOldSel.Max());
466 : sal_Int32 nNewPos;
467 : sal_Int32 nTempPos;
468 :
469 0 : if ( nKeyCode && !aCode.IsMod1() && !aCode.IsMod2() )
470 : {
471 0 : if ( nKeyCode == KEY_LEFT )
472 : {
473 0 : Selection aSel( ImplPatternLeftPos( rEditMask, nCursorPos ) );
474 0 : if ( bShift )
475 0 : aSel.Min() = aOldSel.Min();
476 0 : pEdit->SetSelection( aSel );
477 0 : return true;
478 : }
479 0 : else if ( nKeyCode == KEY_RIGHT )
480 : {
481 : // Use the start of selection as minimum; even a small position is allowed in case that
482 : // all was selected by the focus
483 0 : Selection aSel( aOldSel );
484 0 : aSel.Justify();
485 0 : nCursorPos = aSel.Min();
486 0 : aSel.Max() = ImplPatternRightPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos );
487 0 : if ( bShift )
488 0 : aSel.Min() = aOldSel.Min();
489 : else
490 0 : aSel.Min() = aSel.Max();
491 0 : pEdit->SetSelection( aSel );
492 0 : return true;
493 : }
494 0 : else if ( nKeyCode == KEY_HOME )
495 : {
496 : // Home is the position of the first non-literal character
497 0 : nNewPos = 0;
498 0 : while ( (nNewPos < rEditMask.getLength()) &&
499 0 : (rEditMask[nNewPos] == EDITMASK_LITERAL) )
500 0 : nNewPos++;
501 :
502 : // Home should not move to the right
503 0 : if ( nCursorPos < nNewPos )
504 0 : nNewPos = nCursorPos;
505 0 : Selection aSel( nNewPos );
506 0 : if ( bShift )
507 0 : aSel.Min() = aOldSel.Min();
508 0 : pEdit->SetSelection( aSel );
509 0 : return true;
510 : }
511 0 : else if ( nKeyCode == KEY_END )
512 : {
513 : // End is position of last non-literal character
514 0 : nNewPos = rEditMask.getLength();
515 0 : while ( nNewPos &&
516 0 : (rEditMask[nNewPos-1] == EDITMASK_LITERAL) )
517 0 : nNewPos--;
518 : // Use the start of selection as minimum; even a small position is allowed in case that
519 : // all was selected by the focus
520 0 : Selection aSel( aOldSel );
521 0 : aSel.Justify();
522 0 : nCursorPos = static_cast<sal_Int32>(aSel.Min());
523 0 : ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nCursorPos, nNewPos );
524 0 : aSel.Max() = nNewPos;
525 0 : if ( bShift )
526 0 : aSel.Min() = aOldSel.Min();
527 : else
528 0 : aSel.Min() = aSel.Max();
529 0 : pEdit->SetSelection( aSel );
530 0 : return true;
531 : }
532 0 : else if ( (nKeyCode == KEY_BACKSPACE) || (nKeyCode == KEY_DELETE) )
533 : {
534 0 : OUString aOldStr( pEdit->GetText() );
535 0 : OUStringBuffer aStr( aOldStr );
536 0 : Selection aSel = aOldSel;
537 :
538 0 : aSel.Justify();
539 0 : nNewPos = static_cast<sal_Int32>(aSel.Min());
540 :
541 : // if selection then delete it
542 0 : if ( aSel.Len() )
543 : {
544 0 : if ( bSameMask )
545 0 : aStr.remove( static_cast<sal_Int32>(aSel.Min()), static_cast<sal_Int32>(aSel.Len()) );
546 : else
547 : {
548 0 : OUString aRep = rLiteralMask.copy( static_cast<sal_Int32>(aSel.Min()), static_cast<sal_Int32>(aSel.Len()) );
549 0 : aStr.remove( aSel.Min(), aRep.getLength() );
550 0 : aStr.insert( aSel.Min(), aRep );
551 : }
552 : }
553 : else
554 : {
555 0 : if ( nKeyCode == KEY_BACKSPACE )
556 : {
557 0 : nTempPos = nNewPos;
558 0 : nNewPos = ImplPatternLeftPos( rEditMask, nTempPos );
559 : }
560 : else
561 0 : nTempPos = ImplPatternRightPos( aStr.toString(), rEditMask, nFormatFlags, bSameMask, nNewPos );
562 :
563 0 : if ( nNewPos != nTempPos )
564 : {
565 0 : if ( bSameMask )
566 : {
567 0 : if ( rEditMask[nNewPos] != EDITMASK_LITERAL )
568 0 : aStr.remove( nNewPos, 1 );
569 : }
570 : else
571 : {
572 0 : aStr[nNewPos] = rLiteralMask[nNewPos];
573 : }
574 : }
575 : }
576 :
577 0 : if ( aOldStr != aStr.toString() )
578 : {
579 0 : if ( bSameMask )
580 0 : aStr = ImplPatternReformat( aStr.toString(), rEditMask, rLiteralMask, nFormatFlags );
581 0 : rbInKeyInput = true;
582 0 : pEdit->SetText( aStr.toString(), Selection( nNewPos ) );
583 0 : pEdit->SetModifyFlag();
584 0 : pEdit->Modify();
585 0 : rbInKeyInput = false;
586 : }
587 : else
588 0 : pEdit->SetSelection( Selection( nNewPos ) );
589 :
590 0 : return true;
591 : }
592 0 : else if ( nKeyCode == KEY_INSERT )
593 : {
594 : // you can only set InsertModus for a PatternField if the
595 : // mask is equal at all input positions
596 0 : if ( !bSameMask )
597 : {
598 0 : return true;
599 : }
600 : }
601 : }
602 :
603 0 : if ( rKEvt.GetKeyCode().IsMod2() || (cChar < 32) || (cChar == 127) )
604 0 : return false;
605 :
606 0 : Selection aSel = aOldSel;
607 0 : aSel.Justify();
608 0 : nNewPos = aSel.Min();
609 :
610 0 : if ( nNewPos < rEditMask.getLength() )
611 : {
612 0 : sal_Unicode cPattChar = ImplPatternChar( cChar, rEditMask[nNewPos] );
613 0 : if ( cPattChar )
614 0 : cChar = cPattChar;
615 : else
616 : {
617 : // If no valid character, check if the user wanted to jump to next literal. We do this
618 : // only if we're after a character, so that literals that were skipped automatically
619 : // do not influence the position anymore.
620 0 : if ( nNewPos &&
621 0 : (rEditMask[nNewPos-1] != EDITMASK_LITERAL) &&
622 0 : !aSel.Len() )
623 : {
624 : // search for next character not being a literal
625 0 : nTempPos = nNewPos;
626 0 : while ( nTempPos < rEditMask.getLength() )
627 : {
628 0 : if ( rEditMask[nTempPos] == EDITMASK_LITERAL )
629 : {
630 : // only valid if no literal present
631 0 : if ( (rEditMask[nTempPos+1] != EDITMASK_LITERAL ) &&
632 0 : ImplCommaPointCharEqual( cChar, rLiteralMask[nTempPos] ) )
633 : {
634 0 : nTempPos++;
635 0 : ImplPatternMaxPos( pEdit->GetText(), rEditMask, nFormatFlags, bSameMask, nNewPos, nTempPos );
636 0 : if ( nTempPos > nNewPos )
637 : {
638 0 : pEdit->SetSelection( Selection( nTempPos ) );
639 0 : return true;
640 : }
641 : }
642 0 : break;
643 : }
644 0 : nTempPos++;
645 : }
646 : }
647 :
648 0 : cChar = 0;
649 : }
650 : }
651 : else
652 0 : cChar = 0;
653 0 : if ( cChar )
654 : {
655 0 : OUStringBuffer aStr = pEdit->GetText();
656 0 : bool bError = false;
657 0 : if ( bSameMask && pEdit->IsInsertMode() )
658 : {
659 : // crop spaces and literals at the end until current position
660 0 : sal_Int32 n = aStr.getLength();
661 0 : while ( n && (n > nNewPos) )
662 : {
663 0 : if ( (aStr[n-1] != ' ') &&
664 0 : ((n > rEditMask.getLength()) || (rEditMask[n-1] != EDITMASK_LITERAL)) )
665 0 : break;
666 :
667 0 : n--;
668 : }
669 0 : aStr.truncate( n );
670 :
671 0 : if ( aSel.Len() )
672 0 : aStr.remove( aSel.Min(), aSel.Len() );
673 :
674 0 : if ( aStr.getLength() < rEditMask.getLength() )
675 : {
676 : // possibly extend string until cursor position
677 0 : if ( aStr.getLength() < nNewPos )
678 0 : aStr.append( rLiteralMask.copy( aStr.getLength(), nNewPos-aStr.getLength() ));
679 0 : if ( nNewPos < aStr.getLength() )
680 0 : aStr.insert( cChar, nNewPos );
681 0 : else if ( nNewPos < rEditMask.getLength() )
682 0 : aStr.append(cChar);
683 0 : aStr = ImplPatternReformat( aStr.toString(), rEditMask, rLiteralMask, nFormatFlags );
684 : }
685 : else
686 0 : bError = true;
687 : }
688 : else
689 : {
690 0 : if ( aSel.Len() )
691 : {
692 : // delete selection
693 0 : OUString aRep = rLiteralMask.copy( aSel.Min(), aSel.Len() );
694 0 : aStr.remove( aSel.Min(), aRep.getLength() );
695 0 : aStr.insert( aSel.Min(), aRep );
696 : }
697 :
698 0 : if ( nNewPos < aStr.getLength() )
699 0 : aStr[nNewPos] = cChar;
700 0 : else if ( nNewPos < rEditMask.getLength() )
701 0 : aStr.append(cChar);
702 : }
703 :
704 0 : if ( !bError )
705 : {
706 0 : rbInKeyInput = true;
707 0 : Selection aNewSel( ImplPatternRightPos( aStr.toString(), rEditMask, nFormatFlags, bSameMask, nNewPos ) );
708 0 : pEdit->SetText( aStr.toString(), aNewSel );
709 0 : pEdit->SetModifyFlag();
710 0 : pEdit->Modify();
711 0 : rbInKeyInput = false;
712 0 : }
713 : }
714 :
715 0 : return true;
716 : }
717 :
718 160 : void PatternFormatter::ImplSetMask(const OString& rEditMask, const OUString& rLiteralMask)
719 : {
720 160 : m_aEditMask = rEditMask;
721 160 : maLiteralMask = rLiteralMask;
722 160 : mbSameMask = true;
723 :
724 160 : if ( m_aEditMask.getLength() != maLiteralMask.getLength() )
725 : {
726 28 : OUStringBuffer aBuf(maLiteralMask);
727 28 : if (m_aEditMask.getLength() < aBuf.getLength())
728 0 : aBuf.remove(m_aEditMask.getLength(), aBuf.getLength() - m_aEditMask.getLength());
729 : else
730 28 : comphelper::string::padToLength(aBuf, m_aEditMask.getLength(), ' ');
731 28 : maLiteralMask = aBuf.makeStringAndClear();
732 : }
733 :
734 : // Strict mode allows only the input mode if only equal characters are allowed as mask and if
735 : // only spaces are specified which are not allowed by the mask
736 160 : sal_Int32 i = 0;
737 160 : sal_Char c = 0;
738 362 : while ( i < rEditMask.getLength() )
739 : {
740 100 : sal_Char cTemp = rEditMask[i];
741 100 : if ( cTemp != EDITMASK_LITERAL )
742 : {
743 100 : if ( (cTemp == EDITMASK_ALLCHAR) ||
744 100 : (cTemp == EDITMASK_UPPERALLCHAR) ||
745 : (cTemp == EDITMASK_NUMSPACE) )
746 : {
747 0 : mbSameMask = false;
748 0 : break;
749 : }
750 100 : if ( i < rLiteralMask.getLength() )
751 : {
752 60 : if ( rLiteralMask[i] != ' ' )
753 : {
754 52 : mbSameMask = false;
755 52 : break;
756 : }
757 : }
758 48 : if ( !c )
759 18 : c = cTemp;
760 48 : if ( cTemp != c )
761 : {
762 6 : mbSameMask = false;
763 6 : break;
764 : }
765 : }
766 42 : i++;
767 : }
768 160 : }
769 :
770 16 : PatternFormatter::PatternFormatter()
771 : {
772 16 : mnFormatFlags = 0;
773 16 : mbSameMask = true;
774 16 : mbInPattKeyInput = false;
775 16 : }
776 :
777 16 : PatternFormatter::~PatternFormatter()
778 : {
779 16 : }
780 :
781 160 : void PatternFormatter::SetMask( const OString& rEditMask,
782 : const OUString& rLiteralMask )
783 : {
784 160 : ImplSetMask( rEditMask, rLiteralMask );
785 160 : ReformatAll();
786 160 : }
787 :
788 160 : void PatternFormatter::SetString( const OUString& rStr )
789 : {
790 160 : maFieldString = rStr;
791 160 : if ( GetField() )
792 : {
793 160 : GetField()->SetText( rStr );
794 160 : MarkToBeReformatted( false );
795 : }
796 160 : }
797 :
798 0 : OUString PatternFormatter::GetString() const
799 : {
800 0 : if ( !GetField() )
801 0 : return OUString();
802 : else
803 0 : return ImplPatternReformat( GetField()->GetText(), m_aEditMask, maLiteralMask, mnFormatFlags );
804 : }
805 :
806 190 : void PatternFormatter::Reformat()
807 : {
808 190 : if ( GetField() )
809 : {
810 190 : ImplSetText( ImplPatternReformat( GetField()->GetText(), m_aEditMask, maLiteralMask, mnFormatFlags ) );
811 190 : if ( !mbSameMask && IsStrictFormat() && !GetField()->IsReadOnly() )
812 0 : GetField()->SetInsertMode( false );
813 : }
814 190 : }
815 :
816 16 : PatternField::PatternField( vcl::Window* pParent, WinBits nWinStyle ) :
817 16 : SpinField( pParent, nWinStyle )
818 : {
819 16 : SetField( this );
820 16 : Reformat();
821 16 : }
822 :
823 32 : PatternField::~PatternField()
824 : {
825 32 : }
826 :
827 0 : bool PatternField::PreNotify( NotifyEvent& rNEvt )
828 : {
829 0 : if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
830 : {
831 0 : if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
832 0 : IsStrictFormat(), GetFormatFlags(),
833 0 : ImplIsSameMask(), ImplGetInPattKeyInput() ) )
834 0 : return true;
835 : }
836 :
837 0 : return SpinField::PreNotify( rNEvt );
838 : }
839 :
840 16 : bool PatternField::Notify( NotifyEvent& rNEvt )
841 : {
842 16 : if ( rNEvt.GetType() == EVENT_GETFOCUS )
843 0 : MarkToBeReformatted( false );
844 16 : else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
845 : {
846 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
847 0 : Reformat();
848 : }
849 :
850 16 : return SpinField::Notify( rNEvt );
851 : }
852 :
853 0 : void PatternField::Modify()
854 : {
855 0 : if ( !ImplGetInPattKeyInput() )
856 : {
857 0 : if ( IsStrictFormat() )
858 0 : ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
859 : else
860 0 : MarkToBeReformatted( true );
861 : }
862 :
863 0 : SpinField::Modify();
864 0 : }
865 :
866 0 : PatternBox::PatternBox( vcl::Window* pParent, WinBits nWinStyle ) :
867 0 : ComboBox( pParent, nWinStyle )
868 : {
869 0 : SetField( this );
870 0 : Reformat();
871 0 : }
872 :
873 0 : PatternBox::~PatternBox()
874 : {
875 0 : }
876 :
877 0 : bool PatternBox::PreNotify( NotifyEvent& rNEvt )
878 : {
879 0 : if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
880 : {
881 0 : if ( ImplPatternProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetEditMask(), GetLiteralMask(),
882 0 : IsStrictFormat(), GetFormatFlags(),
883 0 : ImplIsSameMask(), ImplGetInPattKeyInput() ) )
884 0 : return true;
885 : }
886 :
887 0 : return ComboBox::PreNotify( rNEvt );
888 : }
889 :
890 0 : bool PatternBox::Notify( NotifyEvent& rNEvt )
891 : {
892 0 : if ( rNEvt.GetType() == EVENT_GETFOCUS )
893 0 : MarkToBeReformatted( false );
894 0 : else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
895 : {
896 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
897 0 : Reformat();
898 : }
899 :
900 0 : return ComboBox::Notify( rNEvt );
901 : }
902 :
903 0 : void PatternBox::Modify()
904 : {
905 0 : if ( !ImplGetInPattKeyInput() )
906 : {
907 0 : if ( IsStrictFormat() )
908 0 : ImplPatternProcessStrictModify( GetField(), GetEditMask(), GetLiteralMask(), GetFormatFlags(), ImplIsSameMask() );
909 : else
910 0 : MarkToBeReformatted( true );
911 : }
912 :
913 0 : ComboBox::Modify();
914 0 : }
915 :
916 0 : void PatternBox::ReformatAll()
917 : {
918 0 : OUString aStr;
919 0 : SetUpdateMode( false );
920 0 : sal_uInt16 nEntryCount = GetEntryCount();
921 0 : for ( sal_uInt16 i=0; i < nEntryCount; i++ )
922 : {
923 0 : aStr = ImplPatternReformat( GetEntry( i ), GetEditMask(), GetLiteralMask(), GetFormatFlags() );
924 0 : RemoveEntryAt(i);
925 0 : InsertEntry( aStr, i );
926 : }
927 0 : PatternFormatter::Reformat();
928 0 : SetUpdateMode( true );
929 0 : }
930 :
931 8 : static ExtDateFieldFormat ImplGetExtFormat( DateFormat eOld )
932 : {
933 8 : switch( eOld )
934 : {
935 0 : case DMY: return XTDATEF_SHORT_DDMMYY;
936 8 : case MDY: return XTDATEF_SHORT_MMDDYY;
937 0 : default: return XTDATEF_SHORT_YYMMDD;
938 : }
939 : }
940 :
941 332 : static sal_uInt16 ImplCutNumberFromString( OUString& rStr )
942 : {
943 332 : sal_Int32 i1 = 0;
944 2194 : while (i1 != rStr.getLength() && !(rStr[i1] >= '0' && rStr[i1] <= '9')) {
945 1530 : ++i1;
946 : }
947 332 : sal_Int32 i2 = i1;
948 1348 : while (i2 != rStr.getLength() && rStr[i2] >= '0' && rStr[i2] <= '9') {
949 684 : ++i2;
950 : }
951 332 : sal_Int32 nValue = rStr.copy(i1, i2-i1).toInt32();
952 332 : rStr = rStr.copy(std::min(i2+1, rStr.getLength()));
953 332 : return nValue;
954 : }
955 :
956 1736 : static bool ImplCutMonthName( OUString& rStr, const OUString& _rLookupMonthName )
957 : {
958 1736 : sal_Int32 index = 0;
959 1736 : rStr = rStr.replaceFirst(_rLookupMonthName, OUString(), &index);
960 1736 : return index >= 0;
961 : }
962 :
963 156 : static sal_uInt16 ImplCutMonthFromString( OUString& rStr, const CalendarWrapper& rCalendarWrapper )
964 : {
965 : // search for a month' name
966 956 : for ( sal_uInt16 i=1; i <= 12; i++ )
967 : {
968 936 : OUString aMonthName = rCalendarWrapper.getMonths()[i-1].FullName;
969 : // long month name?
970 936 : if ( ImplCutMonthName( rStr, aMonthName ) )
971 136 : return i;
972 :
973 : // short month name?
974 1600 : OUString aAbbrevMonthName = rCalendarWrapper.getMonths()[i-1].AbbrevName;
975 800 : if ( ImplCutMonthName( rStr, aAbbrevMonthName ) )
976 0 : return i;
977 800 : }
978 :
979 20 : return ImplCutNumberFromString( rStr );
980 : }
981 :
982 974 : static OUString ImplGetDateSep( const LocaleDataWrapper& rLocaleDataWrapper, ExtDateFieldFormat eFormat )
983 : {
984 974 : if ( ( eFormat == XTDATEF_SHORT_YYMMDD_DIN5008 ) || ( eFormat == XTDATEF_SHORT_YYYYMMDD_DIN5008 ) )
985 0 : return OUString("-");
986 : else
987 974 : return rLocaleDataWrapper.getDateSep();
988 : }
989 :
990 0 : static bool ImplDateProcessKeyInput( Edit*, const KeyEvent& rKEvt, ExtDateFieldFormat eFormat,
991 : const LocaleDataWrapper& rLocaleDataWrapper )
992 : {
993 0 : sal_Unicode cChar = rKEvt.GetCharCode();
994 0 : sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
995 0 : if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
996 0 : (nGroup == KEYGROUP_MISC)||
997 0 : ((cChar >= '0') && (cChar <= '9')) ||
998 0 : (cChar == ImplGetDateSep( rLocaleDataWrapper, eFormat )[0]) )
999 0 : return false;
1000 : else
1001 0 : return true;
1002 : }
1003 :
1004 748 : static bool ImplDateGetValue( const OUString& rStr, Date& rDate, ExtDateFieldFormat eDateFormat,
1005 : const LocaleDataWrapper& rLocaleDataWrapper, const CalendarWrapper& rCalendarWrapper,
1006 : const AllSettings& )
1007 : {
1008 748 : sal_uInt16 nDay = 0;
1009 748 : sal_uInt16 nMonth = 0;
1010 748 : sal_uInt16 nYear = 0;
1011 748 : bool bYear = true;
1012 748 : bool bError = false;
1013 748 : OUString aStr( rStr );
1014 :
1015 748 : if ( eDateFormat == XTDATEF_SYSTEM_LONG )
1016 : {
1017 156 : DateFormat eFormat = rLocaleDataWrapper.getLongDateFormat();
1018 156 : switch( eFormat )
1019 : {
1020 : case MDY:
1021 156 : nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
1022 156 : nDay = ImplCutNumberFromString( aStr );
1023 156 : nYear = ImplCutNumberFromString( aStr );
1024 156 : break;
1025 : case DMY:
1026 0 : nDay = ImplCutNumberFromString( aStr );
1027 0 : nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
1028 0 : nYear = ImplCutNumberFromString( aStr );
1029 0 : break;
1030 : case YMD:
1031 : default:
1032 0 : nYear = ImplCutNumberFromString( aStr );
1033 0 : nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
1034 0 : nDay = ImplCutNumberFromString( aStr );
1035 0 : break;
1036 : }
1037 : }
1038 : else
1039 : {
1040 : // Check if year is present:
1041 592 : OUString aDateSep = ImplGetDateSep( rLocaleDataWrapper, eDateFormat );
1042 592 : sal_Int32 nSepPos = aStr.indexOf( aDateSep );
1043 592 : if ( nSepPos < 0 )
1044 6 : return false;
1045 586 : nSepPos = aStr.indexOf( aDateSep, nSepPos+1 );
1046 586 : if ( ( nSepPos < 0 ) || ( nSepPos == (aStr.getLength()-1) ) )
1047 : {
1048 0 : bYear = false;
1049 0 : nYear = Date( Date::SYSTEM ).GetYear();
1050 : }
1051 :
1052 586 : const sal_Unicode* pBuf = aStr.getStr();
1053 586 : ImplSkipDelimiters( pBuf );
1054 :
1055 586 : switch ( eDateFormat )
1056 : {
1057 : case XTDATEF_SHORT_DDMMYY:
1058 : case XTDATEF_SHORT_DDMMYYYY:
1059 : {
1060 42 : nDay = ImplGetNum( pBuf, bError );
1061 42 : ImplSkipDelimiters( pBuf );
1062 42 : nMonth = ImplGetNum( pBuf, bError );
1063 42 : ImplSkipDelimiters( pBuf );
1064 42 : if ( bYear )
1065 42 : nYear = ImplGetNum( pBuf, bError );
1066 : }
1067 42 : break;
1068 : case XTDATEF_SHORT_MMDDYY:
1069 : case XTDATEF_SHORT_MMDDYYYY:
1070 : {
1071 544 : nMonth = ImplGetNum( pBuf, bError );
1072 544 : ImplSkipDelimiters( pBuf );
1073 544 : nDay = ImplGetNum( pBuf, bError );
1074 544 : ImplSkipDelimiters( pBuf );
1075 544 : if ( bYear )
1076 544 : nYear = ImplGetNum( pBuf, bError );
1077 : }
1078 544 : break;
1079 : case XTDATEF_SHORT_YYMMDD:
1080 : case XTDATEF_SHORT_YYYYMMDD:
1081 : case XTDATEF_SHORT_YYMMDD_DIN5008:
1082 : case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1083 : {
1084 0 : if ( bYear )
1085 0 : nYear = ImplGetNum( pBuf, bError );
1086 0 : ImplSkipDelimiters( pBuf );
1087 0 : nMonth = ImplGetNum( pBuf, bError );
1088 0 : ImplSkipDelimiters( pBuf );
1089 0 : nDay = ImplGetNum( pBuf, bError );
1090 : }
1091 0 : break;
1092 :
1093 : default:
1094 : {
1095 : OSL_FAIL( "DateFormat???" );
1096 : }
1097 586 : }
1098 : }
1099 :
1100 742 : if ( bError || !nDay || !nMonth )
1101 272 : return false;
1102 :
1103 470 : Date aNewDate( nDay, nMonth, nYear );
1104 470 : DateFormatter::ExpandCentury( aNewDate, utl::MiscCfg().GetYear2000() );
1105 470 : if ( aNewDate.IsValidDate() )
1106 : {
1107 470 : rDate = aNewDate;
1108 470 : return true;
1109 : }
1110 0 : return false;
1111 : }
1112 :
1113 330 : bool DateFormatter::ImplDateReformat( const OUString& rStr, OUString& rOutStr, const AllSettings& rSettings )
1114 : {
1115 330 : Date aDate( 0, 0, 0 );
1116 330 : if ( !ImplDateGetValue( rStr, aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
1117 146 : return true;
1118 :
1119 184 : Date aTempDate = aDate;
1120 184 : if ( aTempDate > GetMax() )
1121 54 : aTempDate = GetMax();
1122 130 : else if ( aTempDate < GetMin() )
1123 4 : aTempDate = GetMin();
1124 :
1125 184 : if ( GetErrorHdl().IsSet() && (aDate != aTempDate) )
1126 : {
1127 0 : maCorrectedDate = aTempDate;
1128 0 : if( !GetErrorHdl().Call( this ) )
1129 : {
1130 0 : maCorrectedDate = Date( Date::SYSTEM );
1131 0 : return false;
1132 : }
1133 : else
1134 0 : maCorrectedDate = Date( Date::SYSTEM );
1135 : }
1136 :
1137 184 : rOutStr = ImplGetDateAsText( aTempDate, rSettings );
1138 :
1139 184 : return true;
1140 : }
1141 :
1142 382 : OUString DateFormatter::ImplGetDateAsText( const Date& rDate,
1143 : const AllSettings& ) const
1144 : {
1145 382 : bool bShowCentury = false;
1146 382 : switch ( GetExtDateFormat() )
1147 : {
1148 : case XTDATEF_SYSTEM_SHORT_YYYY:
1149 : case XTDATEF_SYSTEM_LONG:
1150 : case XTDATEF_SHORT_DDMMYYYY:
1151 : case XTDATEF_SHORT_MMDDYYYY:
1152 : case XTDATEF_SHORT_YYYYMMDD:
1153 : case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1154 : {
1155 158 : bShowCentury = true;
1156 : }
1157 158 : break;
1158 : default:
1159 : {
1160 224 : bShowCentury = false;
1161 : }
1162 : }
1163 :
1164 382 : if ( !bShowCentury )
1165 : {
1166 : // Check if I have to use force showing the century
1167 224 : sal_uInt16 nTwoDigitYearStart = utl::MiscCfg().GetYear2000();
1168 224 : sal_uInt16 nYear = rDate.GetYear();
1169 :
1170 : // If year is not in double digit range
1171 224 : if ( (nYear < nTwoDigitYearStart) || (nYear >= nTwoDigitYearStart+100) )
1172 88 : bShowCentury = true;
1173 : }
1174 :
1175 : sal_Unicode aBuf[128];
1176 382 : sal_Unicode* pBuf = aBuf;
1177 :
1178 382 : OUString aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), GetExtDateFormat( true ) );
1179 382 : sal_uInt16 nDay = rDate.GetDay();
1180 382 : sal_uInt16 nMonth = rDate.GetMonth();
1181 382 : sal_uInt16 nYear = rDate.GetYear();
1182 382 : sal_uInt16 nYearLen = bShowCentury ? 4 : 2;
1183 :
1184 382 : if ( !bShowCentury )
1185 136 : nYear %= 100;
1186 :
1187 382 : switch ( GetExtDateFormat( true ) )
1188 : {
1189 : case XTDATEF_SYSTEM_LONG:
1190 : {
1191 70 : return ImplGetLocaleDataWrapper().getLongDate( rDate, GetCalendarWrapper(), 1, false, 1, !bShowCentury );
1192 : }
1193 : case XTDATEF_SHORT_DDMMYY:
1194 : case XTDATEF_SHORT_DDMMYYYY:
1195 : {
1196 22 : pBuf = ImplAddNum( pBuf, nDay, 2 );
1197 22 : pBuf = ImplAddString( pBuf, aDateSep );
1198 22 : pBuf = ImplAddNum( pBuf, nMonth, 2 );
1199 22 : pBuf = ImplAddString( pBuf, aDateSep );
1200 22 : pBuf = ImplAddNum( pBuf, nYear, nYearLen );
1201 : }
1202 22 : break;
1203 : case XTDATEF_SHORT_MMDDYY:
1204 : case XTDATEF_SHORT_MMDDYYYY:
1205 : {
1206 290 : pBuf = ImplAddNum( pBuf, nMonth, 2 );
1207 290 : pBuf = ImplAddString( pBuf, aDateSep );
1208 290 : pBuf = ImplAddNum( pBuf, nDay, 2 );
1209 290 : pBuf = ImplAddString( pBuf, aDateSep );
1210 290 : pBuf = ImplAddNum( pBuf, nYear, nYearLen );
1211 : }
1212 290 : break;
1213 : case XTDATEF_SHORT_YYMMDD:
1214 : case XTDATEF_SHORT_YYYYMMDD:
1215 : case XTDATEF_SHORT_YYMMDD_DIN5008:
1216 : case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1217 : {
1218 0 : pBuf = ImplAddNum( pBuf, nYear, nYearLen );
1219 0 : pBuf = ImplAddString( pBuf, aDateSep );
1220 0 : pBuf = ImplAddNum( pBuf, nMonth, 2 );
1221 0 : pBuf = ImplAddString( pBuf, aDateSep );
1222 0 : pBuf = ImplAddNum( pBuf, nDay, 2 );
1223 : }
1224 0 : break;
1225 : default:
1226 : {
1227 : OSL_FAIL( "DateFormat???" );
1228 : }
1229 : }
1230 :
1231 312 : return OUString(aBuf, pBuf-aBuf);
1232 : }
1233 :
1234 4 : static void ImplDateIncrementDay( Date& rDate, bool bUp )
1235 : {
1236 4 : DateFormatter::ExpandCentury( rDate );
1237 :
1238 4 : if ( bUp )
1239 : {
1240 4 : if ( (rDate.GetDay() != 31) || (rDate.GetMonth() != 12) || (rDate.GetYear() != 9999) )
1241 4 : rDate++;
1242 : }
1243 : else
1244 : {
1245 0 : if ( (rDate.GetDay() != 1 ) || (rDate.GetMonth() != 1) || (rDate.GetYear() != 0) )
1246 0 : rDate--;
1247 : }
1248 4 : }
1249 :
1250 8 : static void ImplDateIncrementMonth( Date& rDate, bool bUp )
1251 : {
1252 8 : DateFormatter::ExpandCentury( rDate );
1253 :
1254 8 : sal_uInt16 nMonth = rDate.GetMonth();
1255 8 : sal_uInt16 nYear = rDate.GetYear();
1256 8 : if ( bUp )
1257 : {
1258 4 : if ( (nMonth == 12) && (nYear < 9999) )
1259 : {
1260 0 : rDate.SetMonth( 1 );
1261 0 : rDate.SetYear( nYear + 1 );
1262 : }
1263 : else
1264 : {
1265 4 : if ( nMonth < 12 )
1266 4 : rDate.SetMonth( nMonth + 1 );
1267 : }
1268 : }
1269 : else
1270 : {
1271 4 : if ( (nMonth == 1) && (nYear > 0) )
1272 : {
1273 0 : rDate.SetMonth( 12 );
1274 0 : rDate.SetYear( nYear - 1 );
1275 : }
1276 : else
1277 : {
1278 4 : if ( nMonth > 1 )
1279 4 : rDate.SetMonth( nMonth - 1 );
1280 : }
1281 : }
1282 :
1283 8 : sal_uInt16 nDaysInMonth = Date::GetDaysInMonth( rDate.GetMonth(), rDate.GetYear());
1284 8 : if ( rDate.GetDay() > nDaysInMonth )
1285 0 : rDate.SetDay( nDaysInMonth );
1286 8 : }
1287 :
1288 0 : static void ImplDateIncrementYear( Date& rDate, bool bUp )
1289 : {
1290 0 : DateFormatter::ExpandCentury( rDate );
1291 :
1292 0 : sal_uInt16 nYear = rDate.GetYear();
1293 0 : sal_uInt16 nMonth = rDate.GetMonth();
1294 0 : if ( bUp )
1295 : {
1296 0 : if ( nYear < 9999 )
1297 0 : rDate.SetYear( nYear + 1 );
1298 : }
1299 : else
1300 : {
1301 0 : if ( nYear > 0 )
1302 0 : rDate.SetYear( nYear - 1 );
1303 : }
1304 0 : if (nMonth == 2)
1305 : {
1306 : // Handle February 29 from leap year to non-leap year.
1307 0 : sal_uInt16 nDay = rDate.GetDay();
1308 0 : if (nDay > 28)
1309 : {
1310 : // The check would not be necessary if it was guaranteed that the
1311 : // date was valid before and actually was a leap year,
1312 : // de-/incrementing a leap year with 29 always results in 28.
1313 0 : sal_uInt16 nDaysInMonth = Date::GetDaysInMonth( nMonth, rDate.GetYear());
1314 0 : if (nDay > nDaysInMonth)
1315 0 : rDate.SetDay( nDaysInMonth);
1316 : }
1317 : }
1318 0 : }
1319 :
1320 100 : bool DateFormatter::ImplAllowMalformedInput() const
1321 : {
1322 100 : return !IsEnforceValidValue();
1323 : }
1324 :
1325 12 : void DateField::ImplDateSpinArea( bool bUp )
1326 : {
1327 : // increment days if all is selected
1328 12 : if ( GetField() )
1329 : {
1330 12 : Date aDate( GetDate() );
1331 12 : Selection aSelection = GetField()->GetSelection();
1332 12 : aSelection.Justify();
1333 12 : OUString aText( GetText() );
1334 12 : if ( (sal_Int32)aSelection.Len() == aText.getLength() )
1335 4 : ImplDateIncrementDay( aDate, bUp );
1336 : else
1337 : {
1338 8 : sal_Int8 nDateArea = 0;
1339 :
1340 8 : ExtDateFieldFormat eFormat = GetExtDateFormat( true );
1341 8 : if ( eFormat == XTDATEF_SYSTEM_LONG )
1342 : {
1343 8 : eFormat = ImplGetExtFormat( ImplGetLocaleDataWrapper().getLongDateFormat() );
1344 8 : nDateArea = 1;
1345 : }
1346 : else
1347 : {
1348 : // search area
1349 0 : sal_Int32 nPos = 0;
1350 0 : OUString aDateSep = ImplGetDateSep( ImplGetLocaleDataWrapper(), eFormat );
1351 0 : for ( sal_Int8 i = 1; i <= 3; i++ )
1352 : {
1353 0 : nPos = aText.indexOf( aDateSep, nPos );
1354 0 : if ( nPos >= (sal_Int32)aSelection.Max() )
1355 : {
1356 0 : nDateArea = i;
1357 0 : break;
1358 : }
1359 : else
1360 0 : nPos++;
1361 0 : }
1362 : }
1363 :
1364 8 : switch( eFormat )
1365 : {
1366 : case XTDATEF_SHORT_MMDDYY:
1367 : case XTDATEF_SHORT_MMDDYYYY:
1368 8 : switch( nDateArea )
1369 : {
1370 8 : case 1: ImplDateIncrementMonth( aDate, bUp );
1371 8 : break;
1372 0 : case 2: ImplDateIncrementDay( aDate, bUp );
1373 0 : break;
1374 0 : case 3: ImplDateIncrementYear( aDate, bUp );
1375 0 : break;
1376 : }
1377 8 : break;
1378 : case XTDATEF_SHORT_DDMMYY:
1379 : case XTDATEF_SHORT_DDMMYYYY:
1380 0 : switch( nDateArea )
1381 : {
1382 0 : case 1: ImplDateIncrementDay( aDate, bUp );
1383 0 : break;
1384 0 : case 2: ImplDateIncrementMonth( aDate, bUp );
1385 0 : break;
1386 0 : case 3: ImplDateIncrementYear( aDate, bUp );
1387 0 : break;
1388 : }
1389 0 : break;
1390 : case XTDATEF_SHORT_YYMMDD:
1391 : case XTDATEF_SHORT_YYYYMMDD:
1392 : case XTDATEF_SHORT_YYMMDD_DIN5008:
1393 : case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1394 0 : switch( nDateArea )
1395 : {
1396 0 : case 1: ImplDateIncrementYear( aDate, bUp );
1397 0 : break;
1398 0 : case 2: ImplDateIncrementMonth( aDate, bUp );
1399 0 : break;
1400 0 : case 3: ImplDateIncrementDay( aDate, bUp );
1401 0 : break;
1402 : }
1403 0 : break;
1404 : default:
1405 : OSL_FAIL( "invalid conversion" );
1406 0 : break;
1407 : }
1408 : }
1409 :
1410 12 : ImplNewFieldValue( aDate );
1411 : }
1412 12 : }
1413 :
1414 60 : void DateFormatter::ImplInit()
1415 : {
1416 60 : mbLongFormat = false;
1417 60 : mbShowDateCentury = true;
1418 60 : mpCalendarWrapper = NULL;
1419 60 : mnDateFormat = 0xFFFF;
1420 60 : mnExtDateFormat = XTDATEF_SYSTEM_SHORT;
1421 60 : }
1422 :
1423 60 : DateFormatter::DateFormatter() :
1424 : maFieldDate( 0 ),
1425 : maLastDate( 0 ),
1426 : maMin( 1, 1, 1900 ),
1427 : maMax( 31, 12, 2200 ),
1428 : maCorrectedDate( Date::SYSTEM ),
1429 60 : mbEnforceValidValue( true )
1430 : {
1431 60 : ImplInit();
1432 60 : }
1433 :
1434 0 : void DateFormatter::ImplLoadRes( const ResId& rResId )
1435 : {
1436 0 : ResMgr* pMgr = rResId.GetResMgr();
1437 0 : if( pMgr )
1438 : {
1439 0 : sal_uLong nMask = pMgr->ReadLong();
1440 :
1441 0 : if ( DATEFORMATTER_MIN & nMask )
1442 : {
1443 0 : maMin = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
1444 0 : pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
1445 : }
1446 0 : if ( DATEFORMATTER_MAX & nMask )
1447 : {
1448 0 : maMax = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
1449 0 : pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
1450 : }
1451 0 : if ( DATEFORMATTER_LONGFORMAT & nMask )
1452 0 : mbLongFormat = pMgr->ReadShort() != 0;
1453 :
1454 0 : if ( DATEFORMATTER_STRICTFORMAT & nMask )
1455 0 : SetStrictFormat( pMgr->ReadShort() != 0 );
1456 :
1457 0 : if ( DATEFORMATTER_VALUE & nMask )
1458 : {
1459 0 : maFieldDate = Date( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
1460 0 : pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE*)pMgr->GetClass() ) );
1461 0 : if ( maFieldDate > maMax )
1462 0 : maFieldDate = maMax;
1463 0 : if ( maFieldDate < maMin )
1464 0 : maFieldDate = maMin;
1465 0 : maLastDate = maFieldDate;
1466 : }
1467 : }
1468 0 : }
1469 :
1470 120 : DateFormatter::~DateFormatter()
1471 : {
1472 60 : delete mpCalendarWrapper;
1473 60 : mpCalendarWrapper = NULL;
1474 60 : }
1475 :
1476 0 : void DateFormatter::SetLocale( const ::com::sun::star::lang::Locale& rLocale )
1477 : {
1478 0 : delete mpCalendarWrapper;
1479 0 : mpCalendarWrapper = NULL;
1480 0 : FormatterBase::SetLocale( rLocale );
1481 0 : }
1482 :
1483 818 : CalendarWrapper& DateFormatter::GetCalendarWrapper() const
1484 : {
1485 818 : if ( !mpCalendarWrapper )
1486 : {
1487 60 : ((DateFormatter*)this)->mpCalendarWrapper = new CalendarWrapper( comphelper::getProcessComponentContext() );
1488 60 : mpCalendarWrapper->loadDefaultCalendar( GetLocale() );
1489 : }
1490 :
1491 818 : return *mpCalendarWrapper;
1492 : }
1493 :
1494 90 : void DateFormatter::SetExtDateFormat( ExtDateFieldFormat eFormat )
1495 : {
1496 90 : mnExtDateFormat = eFormat;
1497 90 : ReformatAll();
1498 90 : }
1499 :
1500 1914 : ExtDateFieldFormat DateFormatter::GetExtDateFormat( bool bResolveSystemFormat ) const
1501 : {
1502 1914 : ExtDateFieldFormat eDateFormat = (ExtDateFieldFormat)mnExtDateFormat;
1503 :
1504 1914 : if ( bResolveSystemFormat && ( eDateFormat <= XTDATEF_SYSTEM_SHORT_YYYY ) )
1505 : {
1506 1056 : bool bShowCentury = (eDateFormat == XTDATEF_SYSTEM_SHORT_YYYY);
1507 1056 : switch ( ImplGetLocaleDataWrapper().getDateFormat() )
1508 : {
1509 0 : case DMY: eDateFormat = bShowCentury ? XTDATEF_SHORT_DDMMYYYY : XTDATEF_SHORT_DDMMYY;
1510 0 : break;
1511 1056 : case MDY: eDateFormat = bShowCentury ? XTDATEF_SHORT_MMDDYYYY : XTDATEF_SHORT_MMDDYY;
1512 1056 : break;
1513 0 : default: eDateFormat = bShowCentury ? XTDATEF_SHORT_YYYYMMDD : XTDATEF_SHORT_YYMMDD;
1514 :
1515 : }
1516 : }
1517 :
1518 1914 : return eDateFormat;
1519 : }
1520 :
1521 280 : void DateFormatter::ReformatAll()
1522 : {
1523 280 : Reformat();
1524 280 : }
1525 :
1526 80 : void DateFormatter::SetMin( const Date& rNewMin )
1527 : {
1528 80 : maMin = rNewMin;
1529 80 : if ( !IsEmptyFieldValue() )
1530 72 : ReformatAll();
1531 80 : }
1532 :
1533 80 : void DateFormatter::SetMax( const Date& rNewMax )
1534 : {
1535 80 : maMax = rNewMax;
1536 80 : if ( !IsEmptyFieldValue() )
1537 72 : ReformatAll();
1538 80 : }
1539 :
1540 8 : void DateFormatter::SetLongFormat( bool bLong )
1541 : {
1542 8 : mbLongFormat = bLong;
1543 :
1544 : // #91913# Remove LongFormat and DateShowCentury - redundant
1545 8 : if ( bLong )
1546 : {
1547 8 : SetExtDateFormat( XTDATEF_SYSTEM_LONG );
1548 : }
1549 : else
1550 : {
1551 0 : if( mnExtDateFormat == XTDATEF_SYSTEM_LONG )
1552 0 : SetExtDateFormat( XTDATEF_SYSTEM_SHORT );
1553 : }
1554 :
1555 8 : ReformatAll();
1556 8 : }
1557 :
1558 12 : void DateFormatter::SetShowDateCentury( bool bShowDateCentury )
1559 : {
1560 12 : mbShowDateCentury = bShowDateCentury;
1561 :
1562 : // #91913# Remove LongFormat and DateShowCentury - redundant
1563 12 : if ( bShowDateCentury )
1564 : {
1565 12 : switch ( GetExtDateFormat() )
1566 : {
1567 : case XTDATEF_SYSTEM_SHORT:
1568 : case XTDATEF_SYSTEM_SHORT_YY:
1569 6 : SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY ); break;
1570 : case XTDATEF_SHORT_DDMMYY:
1571 0 : SetExtDateFormat( XTDATEF_SHORT_DDMMYYYY ); break;
1572 : case XTDATEF_SHORT_MMDDYY:
1573 0 : SetExtDateFormat( XTDATEF_SHORT_MMDDYYYY ); break;
1574 : case XTDATEF_SHORT_YYMMDD:
1575 0 : SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD ); break;
1576 : case XTDATEF_SHORT_YYMMDD_DIN5008:
1577 0 : SetExtDateFormat( XTDATEF_SHORT_YYYYMMDD_DIN5008 ); break;
1578 : default:
1579 : ;
1580 : }
1581 : }
1582 : else
1583 : {
1584 0 : switch ( GetExtDateFormat() )
1585 : {
1586 : case XTDATEF_SYSTEM_SHORT:
1587 : case XTDATEF_SYSTEM_SHORT_YYYY:
1588 0 : SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YY ); break;
1589 : case XTDATEF_SHORT_DDMMYYYY:
1590 0 : SetExtDateFormat( XTDATEF_SHORT_DDMMYY ); break;
1591 : case XTDATEF_SHORT_MMDDYYYY:
1592 0 : SetExtDateFormat( XTDATEF_SHORT_MMDDYY ); break;
1593 : case XTDATEF_SHORT_YYYYMMDD:
1594 0 : SetExtDateFormat( XTDATEF_SHORT_YYMMDD ); break;
1595 : case XTDATEF_SHORT_YYYYMMDD_DIN5008:
1596 0 : SetExtDateFormat( XTDATEF_SHORT_YYMMDD_DIN5008 ); break;
1597 : default:
1598 : ;
1599 : }
1600 : }
1601 :
1602 12 : ReformatAll();
1603 12 : }
1604 :
1605 178 : void DateFormatter::SetDate( const Date& rNewDate )
1606 : {
1607 178 : SetUserDate( rNewDate );
1608 178 : maFieldDate = maLastDate;
1609 178 : maLastDate = GetDate();
1610 178 : }
1611 :
1612 178 : void DateFormatter::SetUserDate( const Date& rNewDate )
1613 : {
1614 178 : ImplSetUserDate( rNewDate );
1615 178 : }
1616 :
1617 198 : void DateFormatter::ImplSetUserDate( const Date& rNewDate, Selection* pNewSelection )
1618 : {
1619 198 : Date aNewDate = rNewDate;
1620 198 : if ( aNewDate > maMax )
1621 34 : aNewDate = maMax;
1622 164 : else if ( aNewDate < maMin )
1623 42 : aNewDate = maMin;
1624 198 : maLastDate = aNewDate;
1625 :
1626 198 : if ( GetField() )
1627 198 : ImplSetText( ImplGetDateAsText( aNewDate, GetFieldSettings() ), pNewSelection );
1628 198 : }
1629 :
1630 20 : void DateFormatter::ImplNewFieldValue( const Date& rDate )
1631 : {
1632 20 : if ( GetField() )
1633 : {
1634 20 : Selection aSelection = GetField()->GetSelection();
1635 20 : aSelection.Justify();
1636 20 : OUString aText = GetField()->GetText();
1637 :
1638 : // If selected until the end then keep it that way
1639 20 : if ( (sal_Int32)aSelection.Max() == aText.getLength() )
1640 : {
1641 20 : if ( !aSelection.Len() )
1642 20 : aSelection.Min() = SELECTION_MAX;
1643 20 : aSelection.Max() = SELECTION_MAX;
1644 : }
1645 :
1646 20 : Date aOldLastDate = maLastDate;
1647 20 : ImplSetUserDate( rDate, &aSelection );
1648 20 : maLastDate = aOldLastDate;
1649 :
1650 : // Modify at Edit is only set at KeyInput
1651 20 : if ( GetField()->GetText() != aText )
1652 : {
1653 20 : GetField()->SetModifyFlag();
1654 20 : GetField()->Modify();
1655 20 : }
1656 : }
1657 20 : }
1658 :
1659 234 : Date DateFormatter::GetDate() const
1660 : {
1661 234 : Date aDate( 0, 0, 0 );
1662 :
1663 234 : if ( GetField() )
1664 : {
1665 234 : if ( ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
1666 : {
1667 134 : if ( aDate > maMax )
1668 4 : aDate = maMax;
1669 130 : else if ( aDate < maMin )
1670 0 : aDate = maMin;
1671 : }
1672 : else
1673 : {
1674 : // !!! We should find out why dates are treated differently than other fields (see
1675 : // also bug: 52384)
1676 :
1677 100 : if ( !ImplAllowMalformedInput() )
1678 : {
1679 88 : if ( maLastDate.GetDate() )
1680 88 : aDate = maLastDate;
1681 0 : else if ( !IsEmptyFieldValueEnabled() )
1682 0 : aDate = Date( Date::SYSTEM );
1683 : }
1684 : else
1685 12 : aDate = GetInvalidDate();
1686 : }
1687 : }
1688 :
1689 234 : return aDate;
1690 : }
1691 :
1692 4 : void DateFormatter::SetEmptyDate()
1693 : {
1694 4 : FormatterBase::SetEmptyFieldValue();
1695 4 : }
1696 :
1697 56 : bool DateFormatter::IsEmptyDate() const
1698 : {
1699 56 : bool bEmpty = FormatterBase::IsEmptyFieldValue();
1700 :
1701 56 : if ( GetField() && MustBeReformatted() && IsEmptyFieldValueEnabled() )
1702 : {
1703 48 : if ( GetField()->GetText().isEmpty() )
1704 : {
1705 8 : bEmpty = true;
1706 : }
1707 40 : else if ( !maLastDate.GetDate() )
1708 : {
1709 0 : Date aDate( Date::EMPTY );
1710 0 : bEmpty = !ImplDateGetValue( GetField()->GetText(), aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
1711 : }
1712 : }
1713 56 : return bEmpty;
1714 : }
1715 :
1716 340 : void DateFormatter::Reformat()
1717 : {
1718 340 : if ( !GetField() )
1719 10 : return;
1720 :
1721 340 : if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
1722 10 : return;
1723 :
1724 330 : OUString aStr;
1725 330 : bool bOK = ImplDateReformat( GetField()->GetText(), aStr, GetFieldSettings() );
1726 330 : if( !bOK )
1727 0 : return;
1728 :
1729 330 : if ( !aStr.isEmpty() )
1730 : {
1731 184 : ImplSetText( aStr );
1732 184 : ImplDateGetValue( aStr, maLastDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() );
1733 : }
1734 : else
1735 : {
1736 146 : if ( maLastDate.GetDate() )
1737 78 : SetDate( maLastDate );
1738 68 : else if ( !IsEmptyFieldValueEnabled() )
1739 60 : SetDate( Date( Date::SYSTEM ) );
1740 : else
1741 : {
1742 8 : ImplSetText( OUString() );
1743 8 : SetEmptyFieldValueData( true );
1744 : }
1745 330 : }
1746 : }
1747 :
1748 12 : void DateFormatter::ExpandCentury( Date& rDate )
1749 : {
1750 12 : ExpandCentury( rDate, utl::MiscCfg().GetYear2000() );
1751 12 : }
1752 :
1753 482 : void DateFormatter::ExpandCentury( Date& rDate, sal_uInt16 nTwoDigitYearStart )
1754 : {
1755 482 : sal_uInt16 nDateYear = rDate.GetYear();
1756 482 : if ( nDateYear < 100 )
1757 : {
1758 296 : sal_uInt16 nCentury = nTwoDigitYearStart / 100;
1759 296 : if ( nDateYear < (nTwoDigitYearStart % 100) )
1760 280 : nCentury++;
1761 296 : rDate.SetYear( nDateYear + (nCentury*100) );
1762 : }
1763 482 : }
1764 :
1765 60 : DateField::DateField( vcl::Window* pParent, WinBits nWinStyle ) :
1766 : SpinField( pParent, nWinStyle ),
1767 60 : maFirst( GetMin() ),
1768 120 : maLast( GetMax() )
1769 : {
1770 60 : SetField( this );
1771 60 : SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
1772 60 : Reformat();
1773 60 : ResetLastDate();
1774 60 : }
1775 :
1776 0 : DateField::DateField( vcl::Window* pParent, const ResId& rResId ) :
1777 : SpinField( WINDOW_DATEFIELD ),
1778 0 : maFirst( GetMin() ),
1779 0 : maLast( GetMax() )
1780 : {
1781 0 : rResId.SetRT( RSC_DATEFIELD );
1782 0 : WinBits nStyle = ImplInitRes( rResId );
1783 0 : SpinField::ImplInit( pParent, nStyle );
1784 0 : SetField( this );
1785 0 : SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
1786 0 : ImplLoadRes( rResId );
1787 :
1788 0 : if ( !(nStyle & WB_HIDE ) )
1789 0 : Show();
1790 :
1791 0 : ResetLastDate();
1792 0 : }
1793 :
1794 0 : void DateField::ImplLoadRes( const ResId& rResId )
1795 : {
1796 0 : SpinField::ImplLoadRes( rResId );
1797 :
1798 0 : ResMgr* pMgr = rResId.GetResMgr();
1799 0 : if( pMgr )
1800 : {
1801 0 : DateFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
1802 :
1803 0 : sal_uLong nMask = ReadLongRes();
1804 0 : if ( DATEFIELD_FIRST & nMask )
1805 : {
1806 0 : maFirst = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
1807 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
1808 : }
1809 0 : if ( DATEFIELD_LAST & nMask )
1810 : {
1811 0 : maLast = Date( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
1812 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
1813 : }
1814 : }
1815 :
1816 0 : Reformat();
1817 0 : }
1818 :
1819 60 : DateField::~DateField()
1820 : {
1821 60 : }
1822 :
1823 0 : bool DateField::PreNotify( NotifyEvent& rNEvt )
1824 : {
1825 0 : if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
1826 0 : ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
1827 0 : !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1828 : {
1829 0 : if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( true ), ImplGetLocaleDataWrapper() ) )
1830 0 : return true;
1831 : }
1832 :
1833 0 : return SpinField::PreNotify( rNEvt );
1834 : }
1835 :
1836 62 : bool DateField::Notify( NotifyEvent& rNEvt )
1837 : {
1838 62 : if ( rNEvt.GetType() == EVENT_GETFOCUS )
1839 0 : MarkToBeReformatted( false );
1840 62 : else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1841 : {
1842 0 : if ( MustBeReformatted() )
1843 : {
1844 : // !!! We should find out why dates are treated differently than other fields (see
1845 : // also bug: 52384)
1846 :
1847 0 : bool bTextLen = !GetText().isEmpty();
1848 0 : if ( bTextLen || !IsEmptyFieldValueEnabled() )
1849 : {
1850 0 : if ( !ImplAllowMalformedInput() )
1851 0 : Reformat();
1852 : else
1853 : {
1854 0 : Date aDate( 0, 0, 0 );
1855 0 : if ( ImplDateGetValue( GetText(), aDate, GetExtDateFormat(true), ImplGetLocaleDataWrapper(), GetCalendarWrapper(), GetFieldSettings() ) )
1856 : // even with strict text analysis, our text is a valid date -> do a complete
1857 : // reformat
1858 0 : Reformat();
1859 : }
1860 : }
1861 0 : else if ( !bTextLen && IsEmptyFieldValueEnabled() )
1862 : {
1863 0 : ResetLastDate();
1864 0 : SetEmptyFieldValueData( true );
1865 : }
1866 : }
1867 : }
1868 :
1869 62 : return SpinField::Notify( rNEvt );
1870 : }
1871 :
1872 380 : void DateField::DataChanged( const DataChangedEvent& rDCEvt )
1873 : {
1874 380 : SpinField::DataChanged( rDCEvt );
1875 :
1876 380 : if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & (SETTINGS_LOCALE|SETTINGS_MISC)) )
1877 : {
1878 0 : if ( IsDefaultLocale() && ( rDCEvt.GetFlags() & SETTINGS_LOCALE ) )
1879 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
1880 0 : ReformatAll();
1881 : }
1882 380 : }
1883 :
1884 176 : void DateField::Modify()
1885 : {
1886 176 : MarkToBeReformatted( true );
1887 176 : SpinField::Modify();
1888 176 : }
1889 :
1890 8 : void DateField::Up()
1891 : {
1892 8 : ImplDateSpinArea( true );
1893 8 : SpinField::Up();
1894 8 : }
1895 :
1896 4 : void DateField::Down()
1897 : {
1898 4 : ImplDateSpinArea( false );
1899 4 : SpinField::Down();
1900 4 : }
1901 :
1902 4 : void DateField::First()
1903 : {
1904 4 : ImplNewFieldValue( maFirst );
1905 4 : SpinField::First();
1906 4 : }
1907 :
1908 4 : void DateField::Last()
1909 : {
1910 4 : ImplNewFieldValue( maLast );
1911 4 : SpinField::Last();
1912 4 : }
1913 :
1914 0 : DateBox::DateBox( vcl::Window* pParent, WinBits nWinStyle ) :
1915 0 : ComboBox( pParent, nWinStyle )
1916 : {
1917 0 : SetField( this );
1918 0 : SetText( ImplGetLocaleDataWrapper().getDate( ImplGetFieldDate() ) );
1919 0 : Reformat();
1920 0 : }
1921 :
1922 0 : DateBox::~DateBox()
1923 : {
1924 0 : }
1925 :
1926 0 : bool DateBox::PreNotify( NotifyEvent& rNEvt )
1927 : {
1928 0 : if ( (rNEvt.GetType() == EVENT_KEYINPUT) && IsStrictFormat() &&
1929 0 : ( GetExtDateFormat() != XTDATEF_SYSTEM_LONG ) &&
1930 0 : !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1931 : {
1932 0 : if ( ImplDateProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), GetExtDateFormat( true ), ImplGetLocaleDataWrapper() ) )
1933 0 : return true;
1934 : }
1935 :
1936 0 : return ComboBox::PreNotify( rNEvt );
1937 : }
1938 :
1939 0 : void DateBox::DataChanged( const DataChangedEvent& rDCEvt )
1940 : {
1941 0 : ComboBox::DataChanged( rDCEvt );
1942 :
1943 0 : if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1944 : {
1945 0 : if ( IsDefaultLocale() )
1946 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
1947 0 : ReformatAll();
1948 : }
1949 0 : }
1950 :
1951 0 : bool DateBox::Notify( NotifyEvent& rNEvt )
1952 : {
1953 0 : if ( rNEvt.GetType() == EVENT_GETFOCUS )
1954 0 : MarkToBeReformatted( false );
1955 0 : else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1956 : {
1957 0 : if ( MustBeReformatted() )
1958 : {
1959 0 : bool bTextLen = !GetText().isEmpty();
1960 0 : if ( bTextLen || !IsEmptyFieldValueEnabled() )
1961 0 : Reformat();
1962 0 : else if ( !bTextLen && IsEmptyFieldValueEnabled() )
1963 : {
1964 0 : ResetLastDate();
1965 0 : SetEmptyFieldValueData( true );
1966 : }
1967 : }
1968 : }
1969 :
1970 0 : return ComboBox::Notify( rNEvt );
1971 : }
1972 :
1973 0 : void DateBox::Modify()
1974 : {
1975 0 : MarkToBeReformatted( true );
1976 0 : ComboBox::Modify();
1977 0 : }
1978 :
1979 0 : void DateBox::ReformatAll()
1980 : {
1981 0 : OUString aStr;
1982 0 : SetUpdateMode( false );
1983 0 : sal_uInt16 nEntryCount = GetEntryCount();
1984 0 : for ( sal_uInt16 i=0; i < nEntryCount; i++ )
1985 : {
1986 0 : ImplDateReformat( GetEntry( i ), aStr, GetFieldSettings() );
1987 0 : RemoveEntryAt(i);
1988 0 : InsertEntry( aStr, i );
1989 : }
1990 0 : DateFormatter::Reformat();
1991 0 : SetUpdateMode( true );
1992 0 : }
1993 :
1994 0 : static bool ImplTimeProcessKeyInput( Edit*, const KeyEvent& rKEvt,
1995 : bool bStrictFormat, bool bDuration,
1996 : TimeFieldFormat eFormat,
1997 : const LocaleDataWrapper& rLocaleDataWrapper )
1998 : {
1999 0 : sal_Unicode cChar = rKEvt.GetCharCode();
2000 :
2001 0 : if ( !bStrictFormat )
2002 0 : return false;
2003 : else
2004 : {
2005 0 : sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
2006 0 : if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
2007 0 : (nGroup == KEYGROUP_MISC) ||
2008 0 : ((cChar >= '0') && (cChar <= '9')) ||
2009 0 : string::equals(rLocaleDataWrapper.getTimeSep(), cChar) ||
2010 0 : (rLocaleDataWrapper.getTimeAM().indexOf(cChar) != -1) ||
2011 0 : (rLocaleDataWrapper.getTimePM().indexOf(cChar) != -1) ||
2012 : // Accept AM/PM:
2013 0 : (cChar == 'a') || (cChar == 'A') || (cChar == 'm') || (cChar == 'M') || (cChar == 'p') || (cChar == 'P') ||
2014 0 : ((eFormat == TimeFieldFormat::F_100TH_SEC) && string::equals(rLocaleDataWrapper.getTime100SecSep(), cChar)) ||
2015 0 : ((eFormat == TimeFieldFormat::F_SEC_CS) && string::equals(rLocaleDataWrapper.getTime100SecSep(), cChar)) ||
2016 0 : (bDuration && (cChar == '-')) )
2017 0 : return false;
2018 : else
2019 0 : return true;
2020 : }
2021 : }
2022 :
2023 22 : static bool ImplIsOnlyDigits( const OUStringBuffer& _rStr )
2024 : {
2025 22 : const sal_Unicode* _pChr = _rStr.getStr();
2026 66 : for ( sal_Int32 i = 0; i < _rStr.getLength(); ++i, ++_pChr )
2027 : {
2028 44 : if ( *_pChr < '0' || *_pChr > '9' )
2029 0 : return false;
2030 : }
2031 22 : return true;
2032 : }
2033 :
2034 854 : static bool ImplIsValidTimePortion( bool _bSkipInvalidCharacters, const OUStringBuffer& _rStr )
2035 : {
2036 854 : if ( !_bSkipInvalidCharacters )
2037 : {
2038 22 : if ( ( _rStr.getLength() > 2 ) || _rStr.isEmpty() || !ImplIsOnlyDigits( _rStr ) )
2039 0 : return false;
2040 : }
2041 854 : return true;
2042 : }
2043 :
2044 854 : static bool ImplCutTimePortion( OUStringBuffer& _rStr, sal_Int32 _nSepPos, bool _bSkipInvalidCharacters, short* _pPortion )
2045 : {
2046 854 : OUString sPortion(_rStr.getStr(), _nSepPos );
2047 1708 : _rStr = _nSepPos < _rStr.getLength()
2048 854 : ? _rStr.copy( _nSepPos + 1 ) : OUStringBuffer();
2049 :
2050 854 : if ( !ImplIsValidTimePortion( _bSkipInvalidCharacters, sPortion ) )
2051 0 : return false;
2052 854 : *_pPortion = (short)sPortion.toInt32();
2053 854 : return true;
2054 : }
2055 :
2056 702 : static bool ImplTimeGetValue( const OUString& rStr, tools::Time& rTime,
2057 : TimeFieldFormat eFormat, bool bDuration,
2058 : const LocaleDataWrapper& rLocaleDataWrapper, bool _bSkipInvalidCharacters = true )
2059 : {
2060 702 : OUStringBuffer aStr = rStr;
2061 702 : short nHour = 0;
2062 702 : short nMinute = 0;
2063 702 : short nSecond = 0;
2064 702 : sal_Int64 nNanoSec = 0;
2065 702 : tools::Time aTime( 0, 0, 0 );
2066 :
2067 702 : if ( rStr.isEmpty() )
2068 24 : return false;
2069 :
2070 : // Search for separators
2071 678 : if (!rLocaleDataWrapper.getTimeSep().isEmpty())
2072 : {
2073 678 : OUStringBuffer aSepStr(",.;:/");
2074 678 : if ( !bDuration )
2075 656 : aSepStr.append('-');
2076 :
2077 : // Replace characters above by the separator character
2078 4724 : for (sal_Int32 i = 0; i < aSepStr.getLength(); ++i)
2079 : {
2080 4046 : if (string::equals(rLocaleDataWrapper.getTimeSep(), aSepStr[i]))
2081 678 : continue;
2082 24582 : for ( sal_Int32 j = 0; j < aStr.getLength(); j++ )
2083 : {
2084 21214 : if (aStr[j] == aSepStr[i])
2085 0 : aStr[j] = rLocaleDataWrapper.getTimeSep()[0];
2086 : }
2087 678 : }
2088 : }
2089 :
2090 678 : bool bNegative = false;
2091 678 : sal_Int32 nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
2092 678 : if ( aStr[0] == '-' )
2093 0 : bNegative = true;
2094 678 : if ( eFormat != TimeFieldFormat::F_SEC_CS )
2095 : {
2096 678 : if ( nSepPos < 0 )
2097 30 : nSepPos = aStr.getLength();
2098 678 : if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nHour ) )
2099 0 : return false;
2100 :
2101 678 : nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
2102 678 : if ( !aStr.isEmpty() && aStr[0] == '-' )
2103 0 : bNegative = true;
2104 678 : if ( nSepPos >= 0 )
2105 : {
2106 176 : if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nMinute ) )
2107 0 : return false;
2108 :
2109 176 : nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
2110 176 : if ( !aStr.isEmpty() && aStr[0] == '-' )
2111 0 : bNegative = true;
2112 176 : if ( nSepPos >= 0 )
2113 : {
2114 0 : if ( !ImplCutTimePortion( aStr, nSepPos, _bSkipInvalidCharacters, &nSecond ) )
2115 0 : return false;
2116 0 : if ( !aStr.isEmpty() && aStr[0] == '-' )
2117 0 : bNegative = true;
2118 0 : nNanoSec = aStr.toString().toInt64();
2119 : }
2120 : else
2121 176 : nSecond = (short)aStr.toString().toInt32();
2122 : }
2123 : else
2124 502 : nMinute = (short)aStr.toString().toInt32();
2125 : }
2126 0 : else if ( nSepPos < 0 )
2127 : {
2128 0 : nSecond = (short)aStr.toString().toInt32();
2129 0 : nMinute += nSecond / 60;
2130 0 : nSecond %= 60;
2131 0 : nHour += nMinute / 60;
2132 0 : nMinute %= 60;
2133 : }
2134 : else
2135 : {
2136 0 : nSecond = (short)aStr.copy( 0, nSepPos ).toString().toInt32();
2137 0 : aStr.remove( 0, nSepPos+1 );
2138 :
2139 0 : nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
2140 0 : if ( !aStr.isEmpty() && aStr[0] == '-' )
2141 0 : bNegative = true;
2142 0 : if ( nSepPos >= 0 )
2143 : {
2144 0 : nMinute = nSecond;
2145 0 : nSecond = (short)aStr.copy( 0, nSepPos ).toString().toInt32();
2146 0 : aStr.remove( 0, nSepPos+1 );
2147 :
2148 0 : nSepPos = aStr.indexOf( rLocaleDataWrapper.getTimeSep() );
2149 0 : if ( !aStr.isEmpty() && aStr[0] == '-' )
2150 0 : bNegative = true;
2151 0 : if ( nSepPos >= 0 )
2152 : {
2153 0 : nHour = nMinute;
2154 0 : nMinute = nSecond;
2155 0 : nSecond = (short)aStr.copy( 0, nSepPos ).toString().toInt32();
2156 0 : aStr.remove( 0, nSepPos+1 );
2157 : }
2158 : else
2159 : {
2160 0 : nHour += nMinute / 60;
2161 0 : nMinute %= 60;
2162 : }
2163 : }
2164 : else
2165 : {
2166 0 : nMinute += nSecond / 60;
2167 0 : nSecond %= 60;
2168 0 : nHour += nMinute / 60;
2169 0 : nMinute %= 60;
2170 : }
2171 0 : nNanoSec = aStr.toString().toInt64();
2172 : }
2173 :
2174 678 : if ( nNanoSec )
2175 : {
2176 : assert(aStr.getLength() >= 1);
2177 :
2178 0 : sal_Int32 nLen = 1; // at least one digit, otherwise nNanoSec==0
2179 :
2180 0 : while ( aStr.getLength() > nLen && aStr[nLen] >= '0' && aStr[nLen] <= '9' )
2181 0 : nLen++;
2182 :
2183 0 : while ( nLen < 9)
2184 : {
2185 0 : nNanoSec *= 10;
2186 0 : ++nLen;
2187 : }
2188 0 : while ( nLen > 9 )
2189 : {
2190 : // round if negative?
2191 0 : nNanoSec = (nNanoSec + 5) / 10;
2192 0 : --nLen;
2193 : }
2194 : }
2195 :
2196 : assert(nNanoSec > -1000000000 && nNanoSec < 1000000000);
2197 678 : if ( (nMinute > 59) || (nSecond > 59) || (nNanoSec > 1000000000) )
2198 0 : return false;
2199 :
2200 678 : if ( eFormat == TimeFieldFormat::F_NONE )
2201 484 : nSecond = nNanoSec = 0;
2202 194 : else if ( eFormat == TimeFieldFormat::F_SEC )
2203 194 : nNanoSec = 0;
2204 :
2205 678 : if ( !bDuration )
2206 : {
2207 1312 : if ( bNegative || (nHour < 0) || (nMinute < 0) ||
2208 1312 : (nSecond < 0) || (nNanoSec < 0) )
2209 0 : return false;
2210 :
2211 656 : OUString aUpperCaseStr = aStr.toString().toAsciiUpperCase();
2212 1312 : OUString aAM(rLocaleDataWrapper.getTimeAM().toAsciiUpperCase());
2213 1312 : OUString aPM(rLocaleDataWrapper.getTimePM().toAsciiUpperCase());
2214 1312 : OUString aAM2("AM"); // aAM is localized
2215 1312 : OUString aPM2("PM"); // aPM is localized
2216 :
2217 656 : if ( (nHour < 12) && ( ( aUpperCaseStr.indexOf( aPM ) >= 0 ) || ( aUpperCaseStr.indexOf( aPM2 ) >= 0 ) ) )
2218 0 : nHour += 12;
2219 :
2220 656 : if ( (nHour == 12) && ( ( aUpperCaseStr.indexOf( aAM ) >= 0 ) || ( aUpperCaseStr.indexOf( aAM2 ) >= 0 ) ) )
2221 0 : nHour = 0;
2222 :
2223 1312 : aTime = tools::Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
2224 1312 : (sal_uInt32)nNanoSec );
2225 : }
2226 : else
2227 : {
2228 : assert( !bNegative || (nHour < 0) || (nMinute < 0) ||
2229 : (nSecond < 0) || (nNanoSec < 0) );
2230 44 : if ( bNegative || (nHour < 0) || (nMinute < 0) ||
2231 44 : (nSecond < 0) || (nNanoSec < 0) )
2232 : {
2233 : // LEM TODO: this looks weird... I think buggy when parsing "05:-02:18"
2234 0 : bNegative = true;
2235 0 : nHour = nHour < 0 ? -nHour : nHour;
2236 0 : nMinute = nMinute < 0 ? -nMinute : nMinute;
2237 0 : nSecond = nSecond < 0 ? -nSecond : nSecond;
2238 0 : nNanoSec = nNanoSec < 0 ? -nNanoSec : nNanoSec;
2239 : }
2240 :
2241 44 : aTime = tools::Time( (sal_uInt16)nHour, (sal_uInt16)nMinute, (sal_uInt16)nSecond,
2242 22 : (sal_uInt32)nNanoSec );
2243 22 : if ( bNegative )
2244 0 : aTime = -aTime;
2245 : }
2246 :
2247 678 : rTime = aTime;
2248 :
2249 678 : return true;
2250 : }
2251 :
2252 312 : bool TimeFormatter::ImplTimeReformat( const OUString& rStr, OUString& rOutStr )
2253 : {
2254 312 : tools::Time aTime( 0, 0, 0 );
2255 312 : if ( !ImplTimeGetValue( rStr, aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() ) )
2256 20 : return true;
2257 :
2258 292 : tools::Time aTempTime = aTime;
2259 292 : if ( aTempTime > GetMax() )
2260 0 : aTempTime = GetMax() ;
2261 292 : else if ( aTempTime < GetMin() )
2262 44 : aTempTime = GetMin();
2263 :
2264 292 : if ( GetErrorHdl().IsSet() && (aTime != aTempTime) )
2265 : {
2266 0 : maCorrectedTime = aTempTime;
2267 0 : if ( !GetErrorHdl().Call( this ) )
2268 : {
2269 0 : maCorrectedTime = tools::Time( tools::Time::SYSTEM );
2270 0 : return false;
2271 : }
2272 : else
2273 0 : maCorrectedTime = tools::Time( tools::Time::SYSTEM );
2274 : }
2275 :
2276 292 : bool bSecond = false;
2277 292 : bool b100Sec = false;
2278 292 : if ( meFormat != TimeFieldFormat::F_NONE )
2279 88 : bSecond = true;
2280 292 : if ( meFormat == TimeFieldFormat::F_100TH_SEC )
2281 0 : b100Sec = true;
2282 :
2283 292 : if ( meFormat == TimeFieldFormat::F_SEC_CS )
2284 : {
2285 0 : sal_uLong n = aTempTime.GetHour() * 3600L;
2286 0 : n += aTempTime.GetMin() * 60L;
2287 0 : n += aTempTime.GetSec();
2288 0 : rOutStr = OUString::number( n );
2289 0 : rOutStr += ImplGetLocaleDataWrapper().getTime100SecSep();
2290 0 : std::ostringstream ostr;
2291 0 : ostr.fill('0');
2292 0 : ostr.width(9);
2293 0 : ostr << aTempTime.GetNanoSec();
2294 0 : rOutStr += OUString::createFromAscii(ostr.str().c_str());
2295 : }
2296 292 : else if ( mbDuration )
2297 10 : rOutStr = ImplGetLocaleDataWrapper().getDuration( aTempTime, bSecond, b100Sec );
2298 : else
2299 : {
2300 282 : rOutStr = ImplGetLocaleDataWrapper().getTime( aTempTime, bSecond, b100Sec );
2301 282 : if ( GetTimeFormat() == HOUR_12 )
2302 : {
2303 82 : if ( aTempTime.GetHour() > 12 )
2304 : {
2305 0 : tools::Time aT( aTempTime );
2306 0 : aT.SetHour( aT.GetHour() % 12 );
2307 0 : rOutStr = ImplGetLocaleDataWrapper().getTime( aT, bSecond, b100Sec );
2308 : }
2309 : // Don't use LocaleDataWrapper, we want AM/PM
2310 82 : if ( aTempTime.GetHour() < 12 )
2311 82 : rOutStr += "AM"; // ImplGetLocaleDataWrapper().getTimeAM();
2312 : else
2313 0 : rOutStr += "PM"; // ImplGetLocaleDataWrapper().getTimePM();
2314 : }
2315 : }
2316 :
2317 292 : return true;
2318 : }
2319 98 : bool TimeFormatter::ImplAllowMalformedInput() const
2320 : {
2321 98 : return !IsEnforceValidValue();
2322 : }
2323 :
2324 12 : void TimeField::ImplTimeSpinArea( bool bUp )
2325 : {
2326 12 : if ( GetField() )
2327 : {
2328 12 : sal_Int32 nTimeArea = 0;
2329 12 : tools::Time aTime( GetTime() );
2330 12 : OUString aText( GetText() );
2331 12 : Selection aSelection( GetField()->GetSelection() );
2332 :
2333 : // Area search
2334 12 : if ( GetFormat() != TimeFieldFormat::F_SEC_CS )
2335 : {
2336 : //Which area is the cursor in of HH:MM:SS.TT
2337 20 : for ( sal_Int32 i = 1, nPos = 0; i <= 4; i++ )
2338 : {
2339 20 : sal_Int32 nPos1 = aText.indexOf( ImplGetLocaleDataWrapper().getTimeSep(), nPos );
2340 20 : sal_Int32 nPos2 = aText.indexOf( ImplGetLocaleDataWrapper().getTime100SecSep(), nPos );
2341 : //which ever comes first, bearing in mind that one might not be there
2342 20 : if (nPos1 >= 0 && nPos2 >= 0)
2343 0 : nPos = nPos1 < nPos2 ? nPos1 : nPos2;
2344 20 : else if (nPos1 >= 0)
2345 8 : nPos = nPos1;
2346 : else
2347 12 : nPos = nPos2;
2348 20 : if ( nPos < 0 || nPos >= aSelection.Max() )
2349 : {
2350 12 : nTimeArea = i;
2351 12 : break;
2352 : }
2353 : else
2354 8 : nPos++;
2355 : }
2356 : }
2357 : else
2358 : {
2359 0 : sal_Int32 nPos = aText.indexOf( ImplGetLocaleDataWrapper().getTime100SecSep() );
2360 0 : if ( nPos < 0 || nPos >= aSelection.Max() )
2361 0 : nTimeArea = 3;
2362 : else
2363 0 : nTimeArea = 4;
2364 : }
2365 :
2366 12 : if ( nTimeArea )
2367 : {
2368 12 : tools::Time aAddTime( 0, 0, 0 );
2369 12 : if ( nTimeArea == 1 )
2370 4 : aAddTime = tools::Time( 1, 0 );
2371 8 : else if ( nTimeArea == 2 )
2372 8 : aAddTime = tools::Time( 0, 1 );
2373 0 : else if ( nTimeArea == 3 )
2374 0 : aAddTime = tools::Time( 0, 0, 1 );
2375 0 : else if ( nTimeArea == 4 )
2376 0 : aAddTime = tools::Time( 0, 0, 0, 1 );
2377 :
2378 12 : if ( !bUp )
2379 4 : aAddTime = -aAddTime;
2380 :
2381 12 : aTime += aAddTime;
2382 12 : if ( !IsDuration() )
2383 : {
2384 12 : tools::Time aAbsMaxTime( 23, 59, 59, 999999999 );
2385 12 : if ( aTime > aAbsMaxTime )
2386 0 : aTime = aAbsMaxTime;
2387 12 : tools::Time aAbsMinTime( 0, 0 );
2388 12 : if ( aTime < aAbsMinTime )
2389 0 : aTime = aAbsMinTime;
2390 : }
2391 12 : ImplNewFieldValue( aTime );
2392 12 : }
2393 :
2394 : }
2395 12 : }
2396 :
2397 34 : void TimeFormatter::ImplInit()
2398 : {
2399 34 : meFormat = TimeFieldFormat::F_NONE;
2400 34 : mbDuration = false;
2401 34 : mnTimeFormat = HOUR_24; // Should become a ExtTimeFieldFormat in next implementation, merge with mbDuration and meFormat
2402 34 : }
2403 :
2404 34 : TimeFormatter::TimeFormatter() :
2405 : maLastTime( 0, 0 ),
2406 : maMin( 0, 0 ),
2407 : maMax( 23, 59, 59, 999999999 ),
2408 : maCorrectedTime( tools::Time::SYSTEM ),
2409 : mbEnforceValidValue( true ),
2410 34 : maFieldTime( 0, 0 )
2411 : {
2412 34 : ImplInit();
2413 34 : }
2414 :
2415 0 : void TimeFormatter::ImplLoadRes( const ResId& rResId )
2416 : {
2417 0 : ResMgr* pMgr = rResId.GetResMgr();
2418 0 : if( pMgr )
2419 : {
2420 0 : sal_uLong nMask = pMgr->ReadLong();
2421 :
2422 0 : if ( TIMEFORMATTER_MIN & nMask )
2423 : {
2424 0 : SetMin( tools::Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
2425 0 : pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
2426 : }
2427 :
2428 0 : if ( TIMEFORMATTER_MAX & nMask )
2429 : {
2430 0 : SetMax( tools::Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) ) );
2431 0 : pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
2432 : }
2433 :
2434 0 : if ( TIMEFORMATTER_TIMEFIELDFORMAT & nMask )
2435 0 : meFormat = (TimeFieldFormat)pMgr->ReadLong();
2436 :
2437 0 : if ( TIMEFORMATTER_DURATION & nMask )
2438 0 : mbDuration = pMgr->ReadShort() != 0;
2439 :
2440 0 : if ( TIMEFORMATTER_STRICTFORMAT & nMask )
2441 0 : SetStrictFormat( pMgr->ReadShort() != 0 );
2442 :
2443 0 : if ( TIMEFORMATTER_VALUE & nMask )
2444 : {
2445 0 : maFieldTime = tools::Time( ResId( (RSHEADER_TYPE *)pMgr->GetClass(), *pMgr ) );
2446 0 : if ( maFieldTime > GetMax() )
2447 0 : maFieldTime = GetMax();
2448 0 : if ( maFieldTime < GetMin() )
2449 0 : maFieldTime = GetMin();
2450 0 : maLastTime = maFieldTime;
2451 :
2452 0 : pMgr->Increment( ResMgr::GetObjSize( (RSHEADER_TYPE *)pMgr->GetClass() ) );
2453 : }
2454 : }
2455 0 : }
2456 :
2457 34 : TimeFormatter::~TimeFormatter()
2458 : {
2459 34 : }
2460 :
2461 288 : void TimeFormatter::ReformatAll()
2462 : {
2463 288 : Reformat();
2464 288 : }
2465 :
2466 58 : void TimeFormatter::SetMin( const tools::Time& rNewMin )
2467 : {
2468 58 : maMin = rNewMin;
2469 58 : if ( !IsEmptyFieldValue() )
2470 58 : ReformatAll();
2471 58 : }
2472 :
2473 58 : void TimeFormatter::SetMax( const tools::Time& rNewMax )
2474 : {
2475 58 : maMax = rNewMax;
2476 58 : if ( !IsEmptyFieldValue() )
2477 58 : ReformatAll();
2478 58 : }
2479 :
2480 48 : void TimeFormatter::SetTimeFormat( TimeFormatter::TimeFormat eNewFormat )
2481 : {
2482 48 : mnTimeFormat = sal::static_int_cast<sal_uInt16>(eNewFormat);
2483 48 : }
2484 :
2485 :
2486 50 : void TimeFormatter::SetFormat( TimeFieldFormat eNewFormat )
2487 : {
2488 50 : meFormat = eNewFormat;
2489 50 : ReformatAll();
2490 50 : }
2491 :
2492 50 : void TimeFormatter::SetDuration( bool bNewDuration )
2493 : {
2494 50 : mbDuration = bNewDuration;
2495 50 : ReformatAll();
2496 50 : }
2497 :
2498 30 : void TimeFormatter::SetTime( const tools::Time& rNewTime )
2499 : {
2500 30 : SetUserTime( rNewTime );
2501 30 : maFieldTime = maLastTime;
2502 30 : SetEmptyFieldValueData( false );
2503 30 : }
2504 :
2505 20 : void TimeFormatter::ImplNewFieldValue( const tools::Time& rTime )
2506 : {
2507 20 : if ( GetField() )
2508 : {
2509 20 : Selection aSelection = GetField()->GetSelection();
2510 20 : aSelection.Justify();
2511 20 : OUString aText = GetField()->GetText();
2512 :
2513 : // If selected until the end then keep it that way
2514 20 : if ( (sal_Int32)aSelection.Max() == aText.getLength() )
2515 : {
2516 20 : if ( !aSelection.Len() )
2517 20 : aSelection.Min() = SELECTION_MAX;
2518 20 : aSelection.Max() = SELECTION_MAX;
2519 : }
2520 :
2521 20 : tools::Time aOldLastTime = maLastTime;
2522 20 : ImplSetUserTime( rTime, &aSelection );
2523 20 : maLastTime = aOldLastTime;
2524 :
2525 : // Modify at Edit is only set at KeyInput
2526 20 : if ( GetField()->GetText() != aText )
2527 : {
2528 16 : GetField()->SetModifyFlag();
2529 16 : GetField()->Modify();
2530 20 : }
2531 : }
2532 20 : }
2533 :
2534 100 : void TimeFormatter::ImplSetUserTime( const tools::Time& rNewTime, Selection* pNewSelection )
2535 : {
2536 100 : tools::Time aNewTime = rNewTime;
2537 100 : if ( aNewTime > GetMax() )
2538 8 : aNewTime = GetMax();
2539 92 : else if ( aNewTime < GetMin() )
2540 0 : aNewTime = GetMin();
2541 100 : maLastTime = aNewTime;
2542 :
2543 100 : if ( GetField() )
2544 : {
2545 100 : OUString aStr;
2546 100 : bool bSec = false;
2547 100 : bool b100Sec = false;
2548 100 : if ( meFormat != TimeFieldFormat::F_NONE )
2549 22 : bSec = true;
2550 100 : if ( meFormat == TimeFieldFormat::F_100TH_SEC || meFormat == TimeFieldFormat::F_SEC_CS )
2551 0 : b100Sec = true;
2552 100 : if ( meFormat == TimeFieldFormat::F_SEC_CS )
2553 : {
2554 0 : sal_uLong n = aNewTime.GetHour() * 3600L;
2555 0 : n += aNewTime.GetMin() * 60L;
2556 0 : n += aNewTime.GetSec();
2557 0 : aStr = OUString::number( n );
2558 0 : aStr += ImplGetLocaleDataWrapper().getTime100SecSep();
2559 0 : std::ostringstream ostr;
2560 0 : ostr.fill('0');
2561 0 : ostr.width(9);
2562 0 : ostr << aNewTime.GetNanoSec();
2563 0 : aStr += OUString::createFromAscii(ostr.str().c_str());
2564 : }
2565 100 : else if ( mbDuration )
2566 : {
2567 2 : aStr = ImplGetLocaleDataWrapper().getDuration( aNewTime, bSec, b100Sec );
2568 : }
2569 : else
2570 : {
2571 98 : aStr = ImplGetLocaleDataWrapper().getTime( aNewTime, bSec, b100Sec );
2572 98 : if ( GetTimeFormat() == HOUR_12 )
2573 : {
2574 18 : if ( aNewTime.GetHour() > 12 )
2575 : {
2576 0 : tools::Time aT( aNewTime );
2577 0 : aT.SetHour( aT.GetHour() % 12 );
2578 0 : aStr = ImplGetLocaleDataWrapper().getTime( aT, bSec, b100Sec );
2579 : }
2580 : // Don't use LocaleDataWrapper, we want AM/PM
2581 18 : if ( aNewTime.GetHour() < 12 )
2582 18 : aStr += "AM"; // ImplGetLocaleDataWrapper().getTimeAM();
2583 : else
2584 0 : aStr += "PM"; // ImplGetLocaleDataWrapper().getTimePM();
2585 : }
2586 : }
2587 :
2588 100 : ImplSetText( aStr, pNewSelection );
2589 : }
2590 100 : }
2591 :
2592 80 : void TimeFormatter::SetUserTime( const tools::Time& rNewTime )
2593 : {
2594 80 : ImplSetUserTime( rNewTime );
2595 80 : }
2596 :
2597 98 : tools::Time TimeFormatter::GetTime() const
2598 : {
2599 98 : tools::Time aTime( 0, 0, 0 );
2600 :
2601 98 : if ( GetField() )
2602 : {
2603 98 : bool bAllowMailformed = ImplAllowMalformedInput();
2604 98 : if ( ImplTimeGetValue( GetField()->GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), !bAllowMailformed ) )
2605 : {
2606 94 : if ( aTime > GetMax() )
2607 0 : aTime = GetMax();
2608 94 : else if ( aTime < GetMin() )
2609 0 : aTime = GetMin();
2610 : }
2611 : else
2612 : {
2613 4 : if ( bAllowMailformed )
2614 0 : aTime = GetInvalidTime();
2615 : else
2616 4 : aTime = maLastTime;
2617 : }
2618 : }
2619 :
2620 98 : return aTime;
2621 : }
2622 :
2623 322 : void TimeFormatter::Reformat()
2624 : {
2625 322 : if ( !GetField() )
2626 10 : return;
2627 :
2628 322 : if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
2629 10 : return;
2630 :
2631 312 : OUString aStr;
2632 312 : bool bOK = ImplTimeReformat( GetField()->GetText(), aStr );
2633 312 : if ( !bOK )
2634 0 : return;
2635 :
2636 312 : if ( !aStr.isEmpty() )
2637 : {
2638 292 : ImplSetText( aStr );
2639 292 : ImplTimeGetValue( aStr, maLastTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper() );
2640 : }
2641 : else
2642 20 : SetTime( maLastTime );
2643 : }
2644 :
2645 34 : TimeField::TimeField( vcl::Window* pParent, WinBits nWinStyle ) :
2646 : SpinField( pParent, nWinStyle ),
2647 34 : maFirst( GetMin() ),
2648 68 : maLast( GetMax() )
2649 : {
2650 34 : SetField( this );
2651 34 : SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, false, false ) );
2652 34 : Reformat();
2653 34 : }
2654 :
2655 0 : TimeField::TimeField( vcl::Window* pParent, const ResId& rResId ) :
2656 : SpinField( WINDOW_TIMEFIELD ),
2657 0 : maFirst( GetMin() ),
2658 0 : maLast( GetMax() )
2659 : {
2660 0 : rResId.SetRT( RSC_TIMEFIELD );
2661 0 : WinBits nStyle = ImplInitRes( rResId );
2662 0 : SpinField::ImplInit( pParent, nStyle );
2663 0 : SetField( this );
2664 0 : SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, false, false ) );
2665 0 : ImplLoadRes( rResId );
2666 :
2667 0 : if ( !(nStyle & WB_HIDE ) )
2668 0 : Show();
2669 0 : }
2670 :
2671 0 : void TimeField::ImplLoadRes( const ResId& rResId )
2672 : {
2673 0 : SpinField::ImplLoadRes( rResId );
2674 0 : ResMgr* pMgr = rResId.GetResMgr();
2675 0 : if( pMgr )
2676 : {
2677 0 : TimeFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2678 :
2679 0 : sal_uLong nMask = ReadLongRes();
2680 :
2681 0 : if ( TIMEFIELD_FIRST & nMask )
2682 : {
2683 0 : maFirst = tools::Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2684 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
2685 : }
2686 0 : if ( TIMEFIELD_LAST & nMask )
2687 : {
2688 0 : maLast = tools::Time( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
2689 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
2690 : }
2691 : }
2692 :
2693 0 : Reformat();
2694 0 : }
2695 :
2696 68 : TimeField::~TimeField()
2697 : {
2698 68 : }
2699 :
2700 0 : bool TimeField::PreNotify( NotifyEvent& rNEvt )
2701 : {
2702 0 : if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2703 : {
2704 0 : if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
2705 0 : return true;
2706 : }
2707 :
2708 0 : return SpinField::PreNotify( rNEvt );
2709 : }
2710 :
2711 24 : bool TimeField::Notify( NotifyEvent& rNEvt )
2712 : {
2713 24 : if ( rNEvt.GetType() == EVENT_GETFOCUS )
2714 0 : MarkToBeReformatted( false );
2715 24 : else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2716 : {
2717 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
2718 : {
2719 0 : if ( !ImplAllowMalformedInput() )
2720 0 : Reformat();
2721 : else
2722 : {
2723 0 : tools::Time aTime( 0, 0, 0 );
2724 0 : if ( ImplTimeGetValue( GetText(), aTime, GetFormat(), IsDuration(), ImplGetLocaleDataWrapper(), false ) )
2725 : // even with strict text analysis, our text is a valid time -> do a complete
2726 : // reformat
2727 0 : Reformat();
2728 : }
2729 : }
2730 : }
2731 :
2732 24 : return SpinField::Notify( rNEvt );
2733 : }
2734 :
2735 292 : void TimeField::DataChanged( const DataChangedEvent& rDCEvt )
2736 : {
2737 292 : SpinField::DataChanged( rDCEvt );
2738 :
2739 292 : if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2740 : {
2741 0 : if ( IsDefaultLocale() )
2742 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
2743 0 : ReformatAll();
2744 : }
2745 292 : }
2746 :
2747 112 : void TimeField::Modify()
2748 : {
2749 112 : MarkToBeReformatted( true );
2750 112 : SpinField::Modify();
2751 112 : }
2752 :
2753 8 : void TimeField::Up()
2754 : {
2755 8 : ImplTimeSpinArea( true );
2756 8 : SpinField::Up();
2757 8 : }
2758 :
2759 4 : void TimeField::Down()
2760 : {
2761 4 : ImplTimeSpinArea( false );
2762 4 : SpinField::Down();
2763 4 : }
2764 :
2765 4 : void TimeField::First()
2766 : {
2767 4 : ImplNewFieldValue( maFirst );
2768 4 : SpinField::First();
2769 4 : }
2770 :
2771 4 : void TimeField::Last()
2772 : {
2773 4 : ImplNewFieldValue( maLast );
2774 4 : SpinField::Last();
2775 4 : }
2776 :
2777 50 : void TimeField::SetExtFormat( ExtTimeFieldFormat eFormat )
2778 : {
2779 50 : switch ( eFormat )
2780 : {
2781 : case EXTTIMEF_24H_SHORT:
2782 : {
2783 20 : SetTimeFormat( HOUR_24 );
2784 20 : SetDuration( false );
2785 20 : SetFormat( TimeFieldFormat::F_NONE );
2786 : }
2787 20 : break;
2788 : case EXTTIMEF_24H_LONG:
2789 : {
2790 12 : SetTimeFormat( HOUR_24 );
2791 12 : SetDuration( false );
2792 12 : SetFormat( TimeFieldFormat::F_SEC );
2793 : }
2794 12 : break;
2795 : case EXTTIMEF_12H_SHORT:
2796 : {
2797 10 : SetTimeFormat( HOUR_12 );
2798 10 : SetDuration( false );
2799 10 : SetFormat( TimeFieldFormat::F_NONE );
2800 : }
2801 10 : break;
2802 : case EXTTIMEF_12H_LONG:
2803 : {
2804 6 : SetTimeFormat( HOUR_12 );
2805 6 : SetDuration( false );
2806 6 : SetFormat( TimeFieldFormat::F_SEC );
2807 : }
2808 6 : break;
2809 : case EXTTIMEF_DURATION_SHORT:
2810 : {
2811 2 : SetDuration( true );
2812 2 : SetFormat( TimeFieldFormat::F_NONE );
2813 : }
2814 2 : break;
2815 : case EXTTIMEF_DURATION_LONG:
2816 : {
2817 0 : SetDuration( true );
2818 0 : SetFormat( TimeFieldFormat::F_SEC );
2819 : }
2820 0 : break;
2821 : default: OSL_FAIL( "ExtTimeFieldFormat unknown!" );
2822 : }
2823 :
2824 50 : if ( GetField() && !GetField()->GetText().isEmpty() )
2825 50 : SetUserTime( GetTime() );
2826 50 : ReformatAll();
2827 50 : }
2828 :
2829 0 : TimeBox::TimeBox( vcl::Window* pParent, WinBits nWinStyle ) :
2830 0 : ComboBox( pParent, nWinStyle )
2831 : {
2832 0 : SetField( this );
2833 0 : SetText( ImplGetLocaleDataWrapper().getTime( maFieldTime, false, false ) );
2834 0 : Reformat();
2835 0 : }
2836 :
2837 0 : TimeBox::~TimeBox()
2838 : {
2839 0 : }
2840 :
2841 0 : bool TimeBox::PreNotify( NotifyEvent& rNEvt )
2842 : {
2843 0 : if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2844 : {
2845 0 : if ( ImplTimeProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsDuration(), GetFormat(), ImplGetLocaleDataWrapper() ) )
2846 0 : return true;
2847 : }
2848 :
2849 0 : return ComboBox::PreNotify( rNEvt );
2850 : }
2851 :
2852 0 : bool TimeBox::Notify( NotifyEvent& rNEvt )
2853 : {
2854 0 : if ( rNEvt.GetType() == EVENT_GETFOCUS )
2855 0 : MarkToBeReformatted( false );
2856 0 : else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2857 : {
2858 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
2859 0 : Reformat();
2860 : }
2861 :
2862 0 : return ComboBox::Notify( rNEvt );
2863 : }
2864 :
2865 0 : void TimeBox::DataChanged( const DataChangedEvent& rDCEvt )
2866 : {
2867 0 : ComboBox::DataChanged( rDCEvt );
2868 :
2869 0 : if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2870 : {
2871 0 : if ( IsDefaultLocale() )
2872 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
2873 0 : ReformatAll();
2874 : }
2875 0 : }
2876 :
2877 0 : void TimeBox::Modify()
2878 : {
2879 0 : MarkToBeReformatted( true );
2880 0 : ComboBox::Modify();
2881 0 : }
2882 :
2883 0 : void TimeBox::ReformatAll()
2884 : {
2885 0 : OUString aStr;
2886 0 : SetUpdateMode( false );
2887 0 : sal_uInt16 nEntryCount = GetEntryCount();
2888 0 : for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2889 : {
2890 0 : ImplTimeReformat( GetEntry( i ), aStr );
2891 0 : RemoveEntryAt(i);
2892 0 : InsertEntry( aStr, i );
2893 : }
2894 0 : TimeFormatter::Reformat();
2895 0 : SetUpdateMode( true );
2896 1233 : }
2897 :
2898 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|