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