1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 #ifndef _BIGINT_HXX
28 #define _TOOLS_BIGINT
29 #include "tools/bigint.hxx"
30 #endif
31
32 #include "tools/debug.hxx"
33
34 #include "tools/rc.h"
35 #include "tools/resary.hxx"
36
37 #include "vcl/field.hxx"
38 #include "vcl/event.hxx"
39 #include "vcl/svapp.hxx"
40 #include "vcl/unohelp.hxx"
41
42 #include "svids.hrc"
43 #include "svdata.hxx"
44
45 #include "i18nutil/unicode.hxx"
46
47 #include "rtl/math.hxx"
48
49
50 #include <unotools/localedatawrapper.hxx>
51
52 using namespace ::com::sun::star;
53
54 // -----------------------------------------------------------------------
55
56 #define FORMAT_NUMERIC 1
57 #define FORMAT_METRIC 2
58 #define FORMAT_CURRENCY 3
59
60 // -----------------------------------------------------------------------
61
ImplPower10(sal_uInt16 n)62 static sal_Int64 ImplPower10( sal_uInt16 n )
63 {
64 sal_uInt16 i;
65 sal_Int64 nValue = 1;
66
67 for ( i=0; i < n; i++ )
68 nValue *= 10;
69
70 return nValue;
71 }
72
73 // -----------------------------------------------------------------------
74
ImplNumericProcessKeyInput(Edit *,const KeyEvent & rKEvt,sal_Bool bStrictFormat,sal_Bool bThousandSep,const LocaleDataWrapper & rLocaleDataWrappper)75 static sal_Bool ImplNumericProcessKeyInput( Edit*, const KeyEvent& rKEvt,
76 sal_Bool bStrictFormat, sal_Bool bThousandSep,
77 const LocaleDataWrapper& rLocaleDataWrappper )
78 {
79 if ( !bStrictFormat )
80 return sal_False;
81 else
82 {
83 xub_Unicode cChar = rKEvt.GetCharCode();
84 sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
85
86 if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
87 (nGroup == KEYGROUP_MISC) ||
88 ((cChar >= '0') && (cChar <= '9')) ||
89 (cChar == rLocaleDataWrappper.getNumDecimalSep() ) ||
90 (bThousandSep && (cChar == rLocaleDataWrappper.getNumThousandSep())) ||
91 (cChar == '-') )
92 return sal_False;
93 else
94 return sal_True;
95 }
96 }
97
98 // -----------------------------------------------------------------------
99
ImplNumericGetValue(const XubString & rStr,double & rValue,sal_uInt16 nDecDigits,const LocaleDataWrapper & rLocaleDataWrappper,sal_Bool bCurrency=sal_False)100 static sal_Bool ImplNumericGetValue( const XubString& rStr, double& rValue,
101 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrappper,
102 sal_Bool bCurrency = sal_False )
103 {
104 XubString aStr = rStr;
105 XubString aStr1;
106 XubString aStr2;
107 sal_Bool bNegative = sal_False;
108 xub_StrLen nDecPos;
109 xub_StrLen i;
110
111 // Reaktion auf leeren String
112 if ( !rStr.Len() )
113 return sal_False;
114
115 // Fuehrende und nachfolgende Leerzeichen entfernen
116 aStr.EraseLeadingAndTrailingChars( ' ' );
117
118 // Position des Dezimalpunktes suchen
119 nDecPos = aStr.Search( rLocaleDataWrappper.getNumDecimalSep() );
120 if ( nDecPos != STRING_NOTFOUND )
121 {
122 aStr1 = aStr.Copy( 0, nDecPos );
123 aStr2 = aStr.Copy( nDecPos+1 );
124 }
125 else
126 aStr1 = aStr;
127
128 // Negativ ?
129 if ( bCurrency )
130 {
131 if ( (aStr.GetChar( 0 ) == '(') && (aStr.GetChar( aStr.Len()-1 ) == ')') )
132 bNegative = sal_True;
133 if ( !bNegative )
134 {
135 for ( i=0; i < aStr.Len(); i++ )
136 {
137 if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
138 break;
139 else if ( aStr.GetChar( i ) == '-' )
140 {
141 bNegative = sal_True;
142 break;
143 }
144 }
145 }
146 if ( !bNegative && bCurrency && aStr.Len() )
147 {
148 sal_uInt16 nFormat = rLocaleDataWrappper.getCurrNegativeFormat();
149 if ( (nFormat == 3) || (nFormat == 6) ||
150 (nFormat == 7) || (nFormat == 10) )
151 {
152 for ( i = (xub_StrLen)(aStr.Len()-1); i > 0; i++ )
153 {
154 if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
155 break;
156 else if ( aStr.GetChar( i ) == '-' )
157 {
158 bNegative = sal_True;
159 break;
160 }
161 }
162 }
163 }
164 }
165 else
166 {
167 if ( aStr1.GetChar( 0 ) == '-' )
168 bNegative = sal_True;
169 }
170
171 // Alle unerwuenschten Zeichen rauswerfen
172 for ( i=0; i < aStr1.Len(); )
173 {
174 if ( (aStr1.GetChar( i ) >= '0') && (aStr1.GetChar( i ) <= '9') )
175 i++;
176 else
177 aStr1.Erase( i, 1 );
178 }
179 for ( i=0; i < aStr2.Len(); )
180 {
181 if ( (aStr2.GetChar( i ) >= '0') && (aStr2.GetChar( i ) <= '9') )
182 i++;
183 else
184 aStr2.Erase( i, 1 );
185 }
186
187 if ( !aStr1.Len() && !aStr2.Len() )
188 return sal_False;
189
190 if ( !aStr1.Len() )
191 aStr1.Insert( '0' );
192 if ( bNegative )
193 aStr1.Insert( '-', 0 );
194
195 // Nachkommateil zurechtstutzen und dabei runden
196 sal_Bool bRound = sal_False;
197 if ( aStr2.Len() > nDecDigits )
198 {
199 if ( aStr2.GetChar( nDecDigits ) >= '5' )
200 bRound = sal_True;
201 aStr2.Erase( nDecDigits );
202 }
203 if ( aStr2.Len() < nDecDigits )
204 aStr2.Expand( nDecDigits, '0' );
205
206 aStr = aStr1;
207 aStr += aStr2;
208
209 // Bereichsueberpruefung
210 double nValue = aStr.ToDouble();
211 if ( bRound )
212 {
213 if ( !bNegative )
214 nValue++;
215 else
216 nValue--;
217 }
218
219 rValue = nValue;
220
221 return sal_True;
222 }
223
ImplUpdateSeparatorString(String & io_rText,const String & rOldDecSep,const String & rNewDecSep,const String & rOldThSep,const String & rNewThSep)224 static void ImplUpdateSeparatorString( String& io_rText,
225 const String& rOldDecSep, const String& rNewDecSep,
226 const String& rOldThSep, const String& rNewThSep )
227 {
228 rtl::OUStringBuffer aBuf( io_rText.Len() );
229 xub_StrLen nIndexDec = 0, nIndexTh = 0, nIndex = 0;
230
231 const sal_Unicode* pBuffer = io_rText.GetBuffer();
232 while( nIndex != STRING_NOTFOUND )
233 {
234 nIndexDec = io_rText.Search( rOldDecSep, nIndex );
235 nIndexTh = io_rText.Search( rOldThSep, nIndex );
236 if( (nIndexTh != STRING_NOTFOUND && nIndexDec != STRING_NOTFOUND && nIndexTh < nIndexDec )
237 || (nIndexTh != STRING_NOTFOUND && nIndexDec == STRING_NOTFOUND)
238 )
239 {
240 aBuf.append( pBuffer + nIndex, nIndexTh - nIndex );
241 aBuf.append( rNewThSep );
242 nIndex = nIndexTh + rOldThSep.Len();
243 }
244 else if( nIndexDec != STRING_NOTFOUND )
245 {
246 aBuf.append( pBuffer + nIndex, nIndexDec - nIndex );
247 aBuf.append( rNewDecSep );
248 nIndex = nIndexDec + rOldDecSep.Len();
249 }
250 else
251 {
252 aBuf.append( pBuffer + nIndex );
253 nIndex = STRING_NOTFOUND;
254 }
255 }
256
257 io_rText = aBuf.makeStringAndClear();
258 }
259
ImplUpdateSeparators(const String & rOldDecSep,const String & rNewDecSep,const String & rOldThSep,const String & rNewThSep,Edit * pEdit)260 static void ImplUpdateSeparators( const String& rOldDecSep, const String& rNewDecSep,
261 const String& rOldThSep, const String& rNewThSep,
262 Edit* pEdit )
263 {
264 bool bChangeDec = (rOldDecSep != rNewDecSep);
265 bool bChangeTh = (rOldThSep != rNewThSep );
266
267 if( bChangeDec || bChangeTh )
268 {
269 sal_Bool bUpdateMode = pEdit->IsUpdateMode();
270 pEdit->SetUpdateMode( sal_False );
271 String aText = pEdit->GetText();
272 ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
273 pEdit->SetText( aText );
274
275 ComboBox* pCombo = dynamic_cast<ComboBox*>(pEdit);
276 if( pCombo )
277 {
278 // update box entries
279 sal_uInt16 nEntryCount = pCombo->GetEntryCount();
280 for ( sal_uInt16 i=0; i < nEntryCount; i++ )
281 {
282 aText = pCombo->GetEntry( i );
283 void* pEntryData = pCombo->GetEntryData( i );
284 ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
285 pCombo->RemoveEntry( i );
286 pCombo->InsertEntry( aText, i );
287 pCombo->SetEntryData( i, pEntryData );
288 }
289 }
290 if( bUpdateMode )
291 pEdit->SetUpdateMode( bUpdateMode );
292 }
293 }
294
295 // -----------------------------------------------------------------------
296
FormatterBase(Edit * pField)297 FormatterBase::FormatterBase( Edit* pField )
298 {
299 mpField = pField;
300 mpLocaleDataWrapper = NULL;
301 mbReformat = sal_False;
302 mbStrictFormat = sal_False;
303 mbEmptyFieldValue = sal_False;
304 mbEmptyFieldValueEnabled = sal_False;
305 mbDefaultLocale = sal_True;
306 }
307
308 // -----------------------------------------------------------------------
309
~FormatterBase()310 FormatterBase::~FormatterBase()
311 {
312 delete mpLocaleDataWrapper;
313 }
314
315 // -----------------------------------------------------------------------
316
ImplGetLocaleDataWrapper() const317 LocaleDataWrapper& FormatterBase::ImplGetLocaleDataWrapper() const
318 {
319 if ( !mpLocaleDataWrapper )
320 {
321 ((FormatterBase*)this)->mpLocaleDataWrapper = new LocaleDataWrapper( vcl::unohelper::GetMultiServiceFactory(), GetLocale() );
322 }
323 return *mpLocaleDataWrapper;
324 }
325
GetLocaleDataWrapper() const326 const LocaleDataWrapper& FormatterBase::GetLocaleDataWrapper() const
327 {
328 return ImplGetLocaleDataWrapper();
329 }
330
331 // -----------------------------------------------------------------------
332
Reformat()333 void FormatterBase::Reformat()
334 {
335 }
336
337 // -----------------------------------------------------------------------
338
ReformatAll()339 void FormatterBase::ReformatAll()
340 {
341 Reformat();
342 };
343
344 // -----------------------------------------------------------------------
345
SetStrictFormat(sal_Bool bStrict)346 void FormatterBase::SetStrictFormat( sal_Bool bStrict )
347 {
348 if ( bStrict != mbStrictFormat )
349 {
350 mbStrictFormat = bStrict;
351 if ( mbStrictFormat )
352 ReformatAll();
353 }
354 }
355
356 // -----------------------------------------------------------------------
357
SetLocale(const lang::Locale & rLocale)358 void FormatterBase::SetLocale( const lang::Locale& rLocale )
359 {
360 ImplGetLocaleDataWrapper().setLocale( rLocale );
361 mbDefaultLocale = sal_False;
362 ReformatAll();
363 }
364
365 // -----------------------------------------------------------------------
366
GetLocale() const367 const lang::Locale& FormatterBase::GetLocale() const
368 {
369 if ( !mpLocaleDataWrapper || mbDefaultLocale )
370 {
371 if ( mpField )
372 return mpField->GetSettings().GetLocale();
373 else
374 return Application::GetSettings().GetLocale();
375 }
376
377 return mpLocaleDataWrapper->getLocale();
378 }
379
380 // -----------------------------------------------------------------------
381
GetFieldSettings() const382 const AllSettings& FormatterBase::GetFieldSettings() const
383 {
384 if ( mpField )
385 return mpField->GetSettings();
386 else
387 return Application::GetSettings();
388 }
389
390 // -----------------------------------------------------------------------
391
SetFieldText(const XubString & rText,sal_Bool bKeepSelection)392 void FormatterBase::SetFieldText( const XubString& rText, sal_Bool bKeepSelection )
393 {
394 if ( mpField )
395 {
396 Selection aNewSelection( 0xFFFF, 0xFFFF );
397 if ( bKeepSelection )
398 aNewSelection = mpField->GetSelection();
399
400 ImplSetText( rText, &aNewSelection );
401 }
402 }
403
404 // -----------------------------------------------------------------------
405
ImplSetText(const XubString & rText,Selection * pNewSelection)406 void FormatterBase::ImplSetText( const XubString& rText, Selection* pNewSelection )
407 {
408 if ( mpField )
409 {
410 if ( pNewSelection )
411 mpField->SetText( rText, *pNewSelection );
412 else
413 {
414 Selection aSel = mpField->GetSelection();
415 aSel.Min() = aSel.Max();
416 mpField->SetText( rText, aSel );
417 }
418
419 MarkToBeReformatted( sal_False );
420 }
421 }
422
423 // -----------------------------------------------------------------------
424
SetEmptyFieldValue()425 void FormatterBase::SetEmptyFieldValue()
426 {
427 if ( mpField )
428 mpField->SetText( ImplGetSVEmptyStr() );
429 mbEmptyFieldValue = sal_True;
430 }
431
432 // -----------------------------------------------------------------------
433
IsEmptyFieldValue() const434 sal_Bool FormatterBase::IsEmptyFieldValue() const
435 {
436 return (!mpField || !mpField->GetText().Len());
437 }
438
439 // -----------------------------------------------------------------------
440
ImplNumericReformat(const XubString & rStr,double & rValue,XubString & rOutStr)441 sal_Bool NumericFormatter::ImplNumericReformat( const XubString& rStr, double& rValue,
442 XubString& rOutStr )
443 {
444 if ( !ImplNumericGetValue( rStr, rValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
445 return sal_True;
446 else
447 {
448 double nTempVal = rValue;
449 // caution: precision loss in double cast
450 if ( nTempVal > mnMax )
451 nTempVal = (double)mnMax;
452 else if ( nTempVal < mnMin )
453 nTempVal = (double)mnMin;
454
455 if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
456 {
457 mnCorrectedValue = (sal_Int64)nTempVal;
458 if ( !GetErrorHdl().Call( this ) )
459 {
460 mnCorrectedValue = 0;
461 return sal_False;
462 }
463 else
464 mnCorrectedValue = 0;
465 }
466
467 rOutStr = CreateFieldText( (sal_Int64)nTempVal );
468 return sal_True;
469 }
470 }
471
472 // -----------------------------------------------------------------------
473
ImplInit()474 void NumericFormatter::ImplInit()
475 {
476 mnFieldValue = 0;
477 mnLastValue = 0;
478 mnMin = 0;
479 mnMax = 0x7FFFFFFFFFFFFFFFLL;
480 #ifdef OS2 // see i120312 for details.
481 mnMax = 0x00000000FFFFFFFFLL;
482 #endif
483 mnCorrectedValue = 0;
484 mnDecimalDigits = 2;
485 mnType = FORMAT_NUMERIC;
486 mbThousandSep = sal_True;
487 mbShowTrailingZeros = sal_True;
488
489 // for fields
490 mnSpinSize = 1;
491 mnFirst = mnMin;
492 mnLast = mnMax;
493
494 SetDecimalDigits( 0 );
495 }
496
497 // -----------------------------------------------------------------------
498
NumericFormatter()499 NumericFormatter::NumericFormatter()
500 {
501 ImplInit();
502 }
503
504 // -----------------------------------------------------------------------
505
ImplLoadRes(const ResId & rResId)506 void NumericFormatter::ImplLoadRes( const ResId& rResId )
507 {
508 ResMgr* pMgr = rResId.GetResMgr();
509
510 if( pMgr )
511 {
512 sal_uLong nMask = pMgr->ReadLong();
513
514 if ( NUMERICFORMATTER_MIN & nMask )
515 mnMin = pMgr->ReadLong();
516
517 if ( NUMERICFORMATTER_MAX & nMask )
518 mnMax = pMgr->ReadLong();
519
520 if ( NUMERICFORMATTER_STRICTFORMAT & nMask )
521 SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
522
523 if ( NUMERICFORMATTER_DECIMALDIGITS & nMask )
524 SetDecimalDigits( pMgr->ReadShort() );
525
526 if ( NUMERICFORMATTER_VALUE & nMask )
527 {
528 mnFieldValue = pMgr->ReadLong();
529 if ( mnFieldValue > mnMax )
530 mnFieldValue = mnMax;
531 else if ( mnFieldValue < mnMin )
532 mnFieldValue = mnMin;
533 mnLastValue = mnFieldValue;
534 }
535
536 if ( NUMERICFORMATTER_NOTHOUSANDSEP & nMask )
537 SetUseThousandSep( !(sal_Bool)pMgr->ReadShort() );
538 }
539 }
540
541 // -----------------------------------------------------------------------
542
~NumericFormatter()543 NumericFormatter::~NumericFormatter()
544 {
545 }
546
547 // -----------------------------------------------------------------------
548
SetMin(sal_Int64 nNewMin)549 void NumericFormatter::SetMin( sal_Int64 nNewMin )
550 {
551 mnMin = nNewMin;
552 if ( !IsEmptyFieldValue() )
553 ReformatAll();
554 }
555
556 // -----------------------------------------------------------------------
557
SetMax(sal_Int64 nNewMax)558 void NumericFormatter::SetMax( sal_Int64 nNewMax )
559 {
560 mnMax = nNewMax;
561 if ( !IsEmptyFieldValue() )
562 ReformatAll();
563 }
564
565 // -----------------------------------------------------------------------
566
SetUseThousandSep(sal_Bool b)567 void NumericFormatter::SetUseThousandSep( sal_Bool b )
568 {
569 mbThousandSep = b;
570 ReformatAll();
571 }
572
573 // -----------------------------------------------------------------------
574
SetDecimalDigits(sal_uInt16 nDigits)575 void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits )
576 {
577 mnDecimalDigits = nDigits;
578 ReformatAll();
579 }
580
581 // -----------------------------------------------------------------------
582
SetShowTrailingZeros(sal_Bool bShowTrailingZeros)583 void NumericFormatter::SetShowTrailingZeros( sal_Bool bShowTrailingZeros )
584 {
585 if ( mbShowTrailingZeros != bShowTrailingZeros )
586 {
587 mbShowTrailingZeros = bShowTrailingZeros;
588 ReformatAll();
589 }
590 }
591
592 // -----------------------------------------------------------------------
593
GetDecimalDigits() const594 sal_uInt16 NumericFormatter::GetDecimalDigits() const
595 {
596 return mnDecimalDigits;
597 }
598
599 // -----------------------------------------------------------------------
600
SetValue(sal_Int64 nNewValue)601 void NumericFormatter::SetValue( sal_Int64 nNewValue )
602 {
603 SetUserValue( nNewValue );
604 mnFieldValue = mnLastValue;
605 SetEmptyFieldValueData( sal_False );
606 }
607
608 // -----------------------------------------------------------------------
609
CreateFieldText(sal_Int64 nValue) const610 XubString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const
611 {
612 return ImplGetLocaleDataWrapper().getNum( nValue, GetDecimalDigits(), IsUseThousandSep(), IsShowTrailingZeros() );
613 }
614
615 // -----------------------------------------------------------------------
616
ImplSetUserValue(sal_Int64 nNewValue,Selection * pNewSelection)617 void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection* pNewSelection )
618 {
619 if ( nNewValue > mnMax )
620 nNewValue = mnMax;
621 else if ( nNewValue < mnMin )
622 nNewValue = mnMin;
623 mnLastValue = nNewValue;
624
625 if ( GetField() )
626 ImplSetText( CreateFieldText( nNewValue ), pNewSelection );
627 }
628
629 // -----------------------------------------------------------------------
630
SetUserValue(sal_Int64 nNewValue)631 void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
632 {
633 ImplSetUserValue( nNewValue );
634 }
635
636 // -----------------------------------------------------------------------
637
GetValue() const638 sal_Int64 NumericFormatter::GetValue() const
639 {
640 if ( !GetField() )
641 return 0;
642
643 double nTempValue;
644
645 if ( ImplNumericGetValue( GetField()->GetText(), nTempValue,
646 GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
647 {
648 // caution: precision loss in double cast
649 if ( nTempValue > mnMax )
650 nTempValue = (double)mnMax;
651 else if ( nTempValue < mnMin )
652 nTempValue = (double)mnMin;
653 return (sal_Int64)nTempValue;
654 }
655 else
656 return mnLastValue;
657 }
658
659 // -----------------------------------------------------------------------
660
IsValueModified() const661 sal_Bool NumericFormatter::IsValueModified() const
662 {
663 if ( ImplGetEmptyFieldValue() )
664 return !IsEmptyFieldValue();
665 else if ( GetValue() != mnFieldValue )
666 return sal_True;
667 else
668 return sal_False;
669 }
670
671 // -----------------------------------------------------------------------
672
ConvertToFraction(sal_Int64 nValue)673 Fraction NumericFormatter::ConvertToFraction( sal_Int64 nValue )
674 {
675 // caution: precision loss in double cast (and in fraction anyhow)
676 return Fraction( (double)nValue/(double)ImplPower10( GetDecimalDigits() ) );
677 }
678
679 // -----------------------------------------------------------------------
680
ConvertToLong(const Fraction & rValue)681 sal_Int64 NumericFormatter::ConvertToLong( const Fraction& rValue )
682 {
683 Fraction aFract = rValue;
684 aFract *= Fraction( (long)ImplPower10( GetDecimalDigits() ), 1 );
685 return (sal_Int64)(double)aFract;
686 }
687
688 // -----------------------------------------------------------------------
689
Normalize(sal_Int64 nValue) const690 sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const
691 {
692 return (nValue * ImplPower10( GetDecimalDigits() ) );
693 }
694
695 // -----------------------------------------------------------------------
696
Denormalize(sal_Int64 nValue) const697 sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const
698 {
699 sal_Int64 nFactor = ImplPower10( GetDecimalDigits() );
700
701 if((nValue < ( SAL_MIN_INT64 + nFactor )) ||
702 (nValue > ( SAL_MAX_INT64 - nFactor )))
703 return ( nValue / nFactor );
704 if( nValue < 0 )
705 return ((nValue-(nFactor/2)) / nFactor );
706 else
707 return ((nValue+(nFactor/2)) / nFactor );
708 }
709
710 // -----------------------------------------------------------------------
711
Reformat()712 void NumericFormatter::Reformat()
713 {
714 if ( !GetField() )
715 return;
716
717 if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
718 return;
719
720 XubString aStr;
721 // caution: precision loss in double cast
722 double nTemp = (double)mnLastValue;
723 sal_Bool bOK = ImplNumericReformat( GetField()->GetText(), nTemp, aStr );
724 mnLastValue = (sal_Int64)nTemp;
725 if ( !bOK )
726 return;
727
728 if ( aStr.Len() )
729 ImplSetText( aStr );
730 else
731 SetValue( mnLastValue );
732 }
733
734 // -----------------------------------------------------------------------
735
FieldUp()736 void NumericFormatter::FieldUp()
737 {
738 sal_Int64 nValue = GetValue();
739 nValue += mnSpinSize;
740 if ( nValue > mnMax )
741 nValue = mnMax;
742
743 ImplNewFieldValue( nValue );
744 }
745
746 // -----------------------------------------------------------------------
747
FieldDown()748 void NumericFormatter::FieldDown()
749 {
750 sal_Int64 nValue = GetValue();
751 nValue -= mnSpinSize;
752 if ( nValue < mnMin )
753 nValue = mnMin;
754
755 ImplNewFieldValue( nValue );
756 }
757
758 // -----------------------------------------------------------------------
759
FieldFirst()760 void NumericFormatter::FieldFirst()
761 {
762 ImplNewFieldValue( mnFirst );
763 }
764
765 // -----------------------------------------------------------------------
766
FieldLast()767 void NumericFormatter::FieldLast()
768 {
769 ImplNewFieldValue( mnLast );
770 }
771
772 // -----------------------------------------------------------------------
773
ImplNewFieldValue(sal_Int64 nNewValue)774 void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue )
775 {
776 if ( GetField() )
777 {
778 // !!! TH-18.2.99: Wenn wir Zeit haben sollte mal geklaert werden,
779 // !!! warum nicht bei ImplSetUserValue() geprueft wird, ob
780 // !!! sich der Wert aendert. Denn auch hier muesste dieses
781 // !!! gemacht werden, da ansonsten der Modify-Aufruf
782 // !!! nicht gemacht werden duerfte. Jedenfalls sollten die
783 // !!! Wege von ImplNewFieldValue, ImplSetUserValue und
784 // !!! ImplSetText ueberprueft und klarer gestalltet (mit Kommentar)
785 // !!! werden, damit wir mal wissen, was dort ablaeuft!!!
786
787 Selection aSelection = GetField()->GetSelection();
788 aSelection.Justify();
789 XubString aText = GetField()->GetText();
790 // Wenn bis ans Ende selektiert war, soll das auch so bleiben...
791 if ( (xub_StrLen)aSelection.Max() == aText.Len() )
792 {
793 if ( !aSelection.Len() )
794 aSelection.Min() = SELECTION_MAX;
795 aSelection.Max() = SELECTION_MAX;
796 }
797
798 sal_Int64 nOldLastValue = mnLastValue;
799 ImplSetUserValue( nNewValue, &aSelection );
800 mnLastValue = nOldLastValue;
801
802 // Modify am Edit wird nur bei KeyInput gesetzt...
803 if ( GetField()->GetText() != aText )
804 {
805 GetField()->SetModifyFlag();
806 GetField()->Modify();
807 }
808 }
809 }
810
811 // -----------------------------------------------------------------------
812
NumericField(Window * pParent,WinBits nWinStyle)813 NumericField::NumericField( Window* pParent, WinBits nWinStyle ) :
814 SpinField( pParent, nWinStyle )
815 {
816 SetField( this );
817 Reformat();
818 }
819
820 // -----------------------------------------------------------------------
821
NumericField(Window * pParent,const ResId & rResId)822 NumericField::NumericField( Window* pParent, const ResId& rResId ) :
823 SpinField( WINDOW_NUMERICFIELD )
824 {
825 rResId.SetRT( RSC_NUMERICFIELD );
826 WinBits nStyle = ImplInitRes( rResId ) ;
827 SpinField::ImplInit( pParent, nStyle );
828 SetField( this );
829 ImplLoadRes( rResId );
830 Reformat();
831
832 if ( !(nStyle & WB_HIDE ) )
833 Show();
834 }
835
836 // -----------------------------------------------------------------------
837
ImplLoadRes(const ResId & rResId)838 void NumericField::ImplLoadRes( const ResId& rResId )
839 {
840 SpinField::ImplLoadRes( rResId );
841 NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
842
843 sal_uLong nMask = ReadLongRes();
844
845 if ( NUMERICFIELD_FIRST & nMask )
846 mnFirst = ReadLongRes();
847
848 if ( NUMERICFIELD_LAST & nMask )
849 mnLast = ReadLongRes();
850
851 if ( NUMERICFIELD_SPINSIZE & nMask )
852 mnSpinSize = ReadLongRes();
853 }
854
855 // -----------------------------------------------------------------------
856
~NumericField()857 NumericField::~NumericField()
858 {
859 }
860
861 // -----------------------------------------------------------------------
862
PreNotify(NotifyEvent & rNEvt)863 long NumericField::PreNotify( NotifyEvent& rNEvt )
864 {
865 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
866 {
867 if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
868 return 1;
869 }
870
871 return SpinField::PreNotify( rNEvt );
872 }
873
874 // -----------------------------------------------------------------------
875
Notify(NotifyEvent & rNEvt)876 long NumericField::Notify( NotifyEvent& rNEvt )
877 {
878 if ( rNEvt.GetType() == EVENT_GETFOCUS )
879 MarkToBeReformatted( sal_False );
880 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
881 {
882 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
883 Reformat();
884 }
885
886 return SpinField::Notify( rNEvt );
887 }
888
889 // -----------------------------------------------------------------------
890
DataChanged(const DataChangedEvent & rDCEvt)891 void NumericField::DataChanged( const DataChangedEvent& rDCEvt )
892 {
893 SpinField::DataChanged( rDCEvt );
894
895 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
896 {
897 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
898 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
899 if ( IsDefaultLocale() )
900 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
901 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
902 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
903 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
904 ReformatAll();
905 }
906 }
907
908 // -----------------------------------------------------------------------
909
Modify()910 void NumericField::Modify()
911 {
912 MarkToBeReformatted( sal_True );
913 SpinField::Modify();
914 }
915
916 // -----------------------------------------------------------------------
917
Up()918 void NumericField::Up()
919 {
920 FieldUp();
921 SpinField::Up();
922 }
923
924 // -----------------------------------------------------------------------
925
Down()926 void NumericField::Down()
927 {
928 FieldDown();
929 SpinField::Down();
930 }
931
932 // -----------------------------------------------------------------------
933
First()934 void NumericField::First()
935 {
936 FieldFirst();
937 SpinField::First();
938 }
939
940 // -----------------------------------------------------------------------
941
Last()942 void NumericField::Last()
943 {
944 FieldLast();
945 SpinField::Last();
946 }
947
948 // -----------------------------------------------------------------------
949
NumericBox(Window * pParent,WinBits nWinStyle)950 NumericBox::NumericBox( Window* pParent, WinBits nWinStyle ) :
951 ComboBox( pParent, nWinStyle )
952 {
953 SetField( this );
954 Reformat();
955 }
956
957 // -----------------------------------------------------------------------
958
NumericBox(Window * pParent,const ResId & rResId)959 NumericBox::NumericBox( Window* pParent, const ResId& rResId ) :
960 ComboBox( WINDOW_NUMERICBOX )
961 {
962 rResId.SetRT( RSC_NUMERICBOX );
963 WinBits nStyle = ImplInitRes( rResId );
964 ComboBox::ImplInit( pParent, nStyle );
965 SetField( this );
966 ComboBox::ImplLoadRes( rResId );
967 NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
968 Reformat();
969
970 if ( !(nStyle & WB_HIDE ) )
971 Show();
972 }
973
974 // -----------------------------------------------------------------------
975
~NumericBox()976 NumericBox::~NumericBox()
977 {
978 }
979
980 // -----------------------------------------------------------------------
981
PreNotify(NotifyEvent & rNEvt)982 long NumericBox::PreNotify( NotifyEvent& rNEvt )
983 {
984 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
985 {
986 if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
987 return 1;
988 }
989
990 return ComboBox::PreNotify( rNEvt );
991 }
992
993 // -----------------------------------------------------------------------
994
Notify(NotifyEvent & rNEvt)995 long NumericBox::Notify( NotifyEvent& rNEvt )
996 {
997 if ( rNEvt.GetType() == EVENT_GETFOCUS )
998 MarkToBeReformatted( sal_False );
999 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1000 {
1001 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1002 Reformat();
1003 }
1004
1005 return ComboBox::Notify( rNEvt );
1006 }
1007
1008 // -----------------------------------------------------------------------
1009
DataChanged(const DataChangedEvent & rDCEvt)1010 void NumericBox::DataChanged( const DataChangedEvent& rDCEvt )
1011 {
1012 ComboBox::DataChanged( rDCEvt );
1013
1014 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1015 {
1016 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1017 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1018 if ( IsDefaultLocale() )
1019 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1020 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1021 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1022 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1023 ReformatAll();
1024 }
1025 }
1026
1027 // -----------------------------------------------------------------------
1028
Modify()1029 void NumericBox::Modify()
1030 {
1031 MarkToBeReformatted( sal_True );
1032 ComboBox::Modify();
1033 }
1034
1035 // -----------------------------------------------------------------------
1036
ReformatAll()1037 void NumericBox::ReformatAll()
1038 {
1039 double nValue;
1040 XubString aStr;
1041 SetUpdateMode( sal_False );
1042 sal_uInt16 nEntryCount = GetEntryCount();
1043 for ( sal_uInt16 i=0; i < nEntryCount; i++ )
1044 {
1045 ImplNumericReformat( GetEntry( i ), nValue, aStr );
1046 RemoveEntry( i );
1047 InsertEntry( aStr, i );
1048 }
1049 NumericFormatter::Reformat();
1050 SetUpdateMode( sal_True );
1051 }
1052
1053 // -----------------------------------------------------------------------
1054
InsertValue(sal_Int64 nValue,sal_uInt16 nPos)1055 void NumericBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos )
1056 {
1057 ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
1058 }
1059
1060 // -----------------------------------------------------------------------
1061
RemoveValue(sal_Int64 nValue)1062 void NumericBox::RemoveValue( sal_Int64 nValue )
1063 {
1064 ComboBox::RemoveEntry( CreateFieldText( nValue ) );
1065 }
1066
1067 // -----------------------------------------------------------------------
1068
GetValue(sal_uInt16 nPos) const1069 sal_Int64 NumericBox::GetValue( sal_uInt16 nPos ) const
1070 {
1071 double nValue = 0;
1072 ImplNumericGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
1073 return (sal_Int64)nValue;
1074 }
1075
1076 // -----------------------------------------------------------------------
1077
GetValuePos(sal_Int64 nValue) const1078 sal_uInt16 NumericBox::GetValuePos( sal_Int64 nValue ) const
1079 {
1080 return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
1081 }
1082
1083 // -----------------------------------------------------------------------
1084
ImplMetricProcessKeyInput(Edit * pEdit,const KeyEvent & rKEvt,sal_Bool,sal_Bool bUseThousandSep,const LocaleDataWrapper & rWrapper)1085 static sal_Bool ImplMetricProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
1086 sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
1087 {
1088 // Es gibt hier kein sinnvolles StrictFormat, also alle
1089 // Zeichen erlauben
1090 return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper );
1091 }
1092
1093 // -----------------------------------------------------------------------
1094
ImplMetricGetUnitText(const XubString & rStr)1095 static XubString ImplMetricGetUnitText( const XubString& rStr )
1096 {
1097 // Einheitentext holen
1098 XubString aStr;
1099 for ( short i = rStr.Len()-1; i >= 0; i-- )
1100 {
1101 xub_Unicode c = rStr.GetChar( i );
1102 if ( unicode::isAlpha( c ) ||
1103 (c == '\'') || (c == '\"') || (c == '%' ) )
1104 aStr.Insert( c, 0 );
1105 else
1106 {
1107 if ( aStr.Len() )
1108 break;
1109 }
1110 }
1111 return aStr;
1112
1113 /*
1114 // MT: #90545# Preparation for translated strings...
1115 String aMetricText;
1116 for ( sal_uInt16 n = rStr.Len(); n; )
1117 {
1118 sal_Unicode c = rStr.GetChar( --n );
1119 sal_Int32 nType = xCharClass->getStringType( rStr, n, 1, rLocale );
1120
1121 if ( CharClass::isLetterType( nType ) )
1122 {
1123 aMetricText.Insert( c, 0 );
1124 }
1125 else
1126 {
1127 if ( aMetricText.Len() )
1128 break;
1129 }
1130 }
1131 */
1132 }
1133
1134 // -----------------------------------------------------------------------
1135
1136 // #104355# support localized mesaurements
1137
ImplMetricToString(FieldUnit rUnit)1138 static const String& ImplMetricToString( FieldUnit rUnit )
1139 {
1140 FieldUnitStringList* pList = ImplGetFieldUnits();
1141 if( pList )
1142 {
1143 // return unit's default string (ie, the first one )
1144 for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it )
1145 {
1146 if ( it->second == rUnit )
1147 return it->first;
1148 }
1149 }
1150
1151 return String::EmptyString();
1152 }
1153
ImplStringToMetric(const String & rMetricString)1154 static FieldUnit ImplStringToMetric( const String &rMetricString )
1155 {
1156 FieldUnitStringList* pList = ImplGetCleanedFieldUnits();
1157 if( pList )
1158 {
1159 // return FieldUnit
1160 String aStr( rMetricString );
1161 aStr.ToLowerAscii();
1162 aStr.EraseAllChars( sal_Unicode( ' ' ) );
1163 for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it )
1164 {
1165 if ( it->first.Equals( aStr ) )
1166 return it->second;
1167 }
1168 }
1169
1170 return FUNIT_NONE;
1171 }
1172
1173 // -----------------------------------------------------------------------
1174
ImplMetricGetUnit(const XubString & rStr)1175 static FieldUnit ImplMetricGetUnit( const XubString& rStr )
1176 {
1177 XubString aStr = ImplMetricGetUnitText( rStr );
1178 return ImplStringToMetric( aStr );
1179 }
1180
1181 #define K *1000L
1182 #define M *1000000L
1183 #define X *5280L
1184
1185 static const sal_Int64 aImplFactor[FUNIT_MILE+1][FUNIT_MILE+1] =
1186 { /*
1187 mm/100 mm cm m km twip point pica inch foot mile */
1188 { 1, 100, 1 K, 100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X },
1189 { 1, 1, 10, 1 K, 1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X },
1190 { 1, 1, 1, 100, 100 K, 254, 254, 254, 254, 254*12, 254*12 X },
1191 { 1, 1, 1, 1, 1 K, 254, 254, 254, 254, 254*12, 254*12 X },
1192 { 1, 1, 1, 1, 1, 0, 254, 254, 254, 254*12, 254*12 X },
1193 { 1440,144 K,144 K,14400 K, 0, 1, 20, 240, 1440,1440*12,1440*12 X },
1194 { 72, 7200, 7200, 720 K, 720 M, 1, 1, 12, 72, 72*12, 72*12 X },
1195 { 6, 600, 600, 60 K, 60 M, 1, 1, 1, 6, 6*12, 6*12 X },
1196 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 12, 12 X },
1197 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 X },
1198 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 }
1199 };
1200
1201 #undef X
1202 #undef M
1203 #undef K
1204 // twip in km 254/14400 M
1205
1206 static FieldUnit eDefaultUnit = FUNIT_NONE;
1207
GetDefaultUnit()1208 FieldUnit MetricField::GetDefaultUnit() { return eDefaultUnit; }
SetDefaultUnit(FieldUnit meUnit)1209 void MetricField::SetDefaultUnit( FieldUnit meUnit ) { eDefaultUnit = meUnit; }
1210
ImplMap2FieldUnit(MapUnit meUnit,long & nDecDigits)1211 static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, long& nDecDigits )
1212 {
1213 switch( meUnit )
1214 {
1215 case MAP_100TH_MM :
1216 nDecDigits -= 2;
1217 return FUNIT_MM;
1218 case MAP_10TH_MM :
1219 nDecDigits -= 1;
1220 return FUNIT_MM;
1221 case MAP_MM :
1222 return FUNIT_MM;
1223 case MAP_CM :
1224 return FUNIT_CM;
1225 case MAP_1000TH_INCH :
1226 nDecDigits -= 3;
1227 return FUNIT_INCH;
1228 case MAP_100TH_INCH :
1229 nDecDigits -= 2;
1230 return FUNIT_INCH;
1231 case MAP_10TH_INCH :
1232 nDecDigits -= 1;
1233 return FUNIT_INCH;
1234 case MAP_INCH :
1235 return FUNIT_INCH;
1236 case MAP_POINT :
1237 return FUNIT_POINT;
1238 case MAP_TWIP :
1239 return FUNIT_TWIP;
1240 default:
1241 DBG_ERROR( "default eInUnit" );
1242 break;
1243 }
1244 return FUNIT_NONE;
1245 }
1246
1247 // -----------------------------------------------------------------------
1248
nonValueDoubleToValueDouble(double nValue)1249 static double nonValueDoubleToValueDouble( double nValue )
1250 {
1251 return rtl::math::isFinite( nValue ) ? nValue : 0.0;
1252 }
1253
ConvertValue(sal_Int64 nValue,sal_Int64 mnBaseValue,sal_uInt16 nDecDigits,FieldUnit eInUnit,FieldUnit eOutUnit)1254 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1255 FieldUnit eInUnit, FieldUnit eOutUnit )
1256 {
1257 double nDouble = nonValueDoubleToValueDouble( ConvertDoubleValue(
1258 (double)nValue, mnBaseValue, nDecDigits, eInUnit, eOutUnit ) );
1259 sal_Int64 nLong ;
1260
1261 // caution: precision loss in double cast
1262 if ( nDouble <= (double)SAL_MIN_INT64 )
1263 nLong = SAL_MIN_INT64;
1264 else if ( nDouble >= (double)SAL_MAX_INT64 )
1265 nLong = SAL_MAX_INT64;
1266 else
1267 nLong = static_cast<sal_Int64>( nDouble );
1268 return ( nLong );
1269 }
1270
1271 // -----------------------------------------------------------------------
1272
ConvertValue(sal_Int64 nValue,sal_uInt16 nDigits,MapUnit eInUnit,FieldUnit eOutUnit)1273 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1274 MapUnit eInUnit, FieldUnit eOutUnit )
1275 {
1276 return static_cast<sal_Int64>(
1277 nonValueDoubleToValueDouble(
1278 ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) );
1279 }
1280
1281 // -----------------------------------------------------------------------
1282
ConvertValue(sal_Int64 nValue,sal_uInt16 nDigits,FieldUnit eInUnit,MapUnit eOutUnit)1283 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1284 FieldUnit eInUnit, MapUnit eOutUnit )
1285 {
1286 return static_cast<sal_Int64>(
1287 // #150733# cast double to sal_Int64 can throw a
1288 // EXCEPTION_FLT_INVALID_OPERATION on Windows
1289 nonValueDoubleToValueDouble(
1290 ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) );
1291 }
1292
1293 // -----------------------------------------------------------------------
1294
ConvertDoubleValue(double nValue,sal_Int64 mnBaseValue,sal_uInt16 nDecDigits,FieldUnit eInUnit,FieldUnit eOutUnit)1295 double MetricField::ConvertDoubleValue( double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1296 FieldUnit eInUnit, FieldUnit eOutUnit )
1297 {
1298 if ( eInUnit != eOutUnit )
1299 {
1300 sal_Int64 nMult = 1, nDiv = 1;
1301
1302 if ( eInUnit == FUNIT_PERCENT )
1303 {
1304 if ( (mnBaseValue <= 0) || (nValue <= 0) )
1305 return nValue;
1306 nDiv = 100;
1307 for ( sal_uInt16 i=0; i < nDecDigits; i++ )
1308 nDiv *= 10;
1309
1310 nMult = mnBaseValue;
1311 }
1312 else if ( eOutUnit == FUNIT_PERCENT ||
1313 eOutUnit == FUNIT_CUSTOM ||
1314 eOutUnit == FUNIT_NONE ||
1315 eInUnit == FUNIT_CUSTOM ||
1316 eInUnit == FUNIT_NONE )
1317 return nValue;
1318 else
1319 {
1320 if ( eOutUnit == FUNIT_100TH_MM )
1321 eOutUnit = FUNIT_NONE;
1322 if ( eInUnit == FUNIT_100TH_MM )
1323 eInUnit = FUNIT_NONE;
1324
1325 nDiv = aImplFactor[eInUnit][eOutUnit];
1326 nMult = aImplFactor[eOutUnit][eInUnit];
1327
1328 DBG_ASSERT( nMult > 0, "illegal *" );
1329 DBG_ASSERT( nDiv > 0, "illegal /" );
1330 }
1331
1332 if ( nMult != 1 && nMult > 0 )
1333 nValue *= nMult;
1334 if ( nDiv != 1 && nDiv > 0 )
1335 {
1336 nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2);
1337 nValue /= nDiv;
1338 }
1339 }
1340
1341 return nValue;
1342 }
1343
1344 // -----------------------------------------------------------------------
1345
ConvertDoubleValue(double nValue,sal_uInt16 nDigits,MapUnit eInUnit,FieldUnit eOutUnit)1346 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1347 MapUnit eInUnit, FieldUnit eOutUnit )
1348 {
1349 if ( eOutUnit == FUNIT_PERCENT ||
1350 eOutUnit == FUNIT_CUSTOM ||
1351 eOutUnit == FUNIT_NONE ||
1352 eInUnit == MAP_PIXEL ||
1353 eInUnit == MAP_SYSFONT ||
1354 eInUnit == MAP_APPFONT ||
1355 eInUnit == MAP_RELATIVE )
1356 {
1357 DBG_ERROR( "invalid parameters" );
1358 return nValue;
1359 }
1360
1361 long nDecDigits = nDigits;
1362 FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1363
1364 if ( nDecDigits < 0 )
1365 {
1366 while ( nDecDigits )
1367 {
1368 nValue += 5;
1369 nValue /= 10;
1370 nDecDigits++;
1371 }
1372 }
1373 else
1374 {
1375 while ( nDecDigits )
1376 {
1377 nValue *= 10;
1378 nDecDigits--;
1379 }
1380 }
1381
1382 if ( eFieldUnit != eOutUnit )
1383 {
1384 sal_Int64 nDiv = aImplFactor[eFieldUnit][eOutUnit];
1385 sal_Int64 nMult = aImplFactor[eOutUnit][eFieldUnit];
1386
1387 DBG_ASSERT( nMult > 0, "illegal *" );
1388 DBG_ASSERT( nDiv > 0, "illegal /" );
1389
1390 if ( nMult != 1 && nMult > 0)
1391 nValue *= nMult;
1392 if ( nDiv != 1 && nDiv > 0 )
1393 {
1394 nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1395 nValue /= nDiv;
1396 }
1397 }
1398 return nValue;
1399 }
1400
1401 // -----------------------------------------------------------------------
1402
ConvertDoubleValue(double nValue,sal_uInt16 nDigits,FieldUnit eInUnit,MapUnit eOutUnit)1403 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1404 FieldUnit eInUnit, MapUnit eOutUnit )
1405 {
1406 if ( eInUnit == FUNIT_PERCENT ||
1407 eInUnit == FUNIT_CUSTOM ||
1408 eInUnit == FUNIT_NONE ||
1409 eOutUnit == MAP_PIXEL ||
1410 eOutUnit == MAP_SYSFONT ||
1411 eOutUnit == MAP_APPFONT ||
1412 eOutUnit == MAP_RELATIVE )
1413 {
1414 DBG_ERROR( "invalid parameters" );
1415 return nValue;
1416 }
1417
1418 long nDecDigits = nDigits;
1419 FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits );
1420
1421 if ( nDecDigits < 0 )
1422 {
1423 while ( nDecDigits )
1424 {
1425 nValue *= 10;
1426 nDecDigits++;
1427 }
1428 }
1429 else
1430 {
1431 while ( nDecDigits )
1432 {
1433 nValue += 5;
1434 nValue /= 10;
1435 nDecDigits--;
1436 }
1437 }
1438
1439 if ( eFieldUnit != eInUnit )
1440 {
1441 sal_Int64 nDiv = aImplFactor[eInUnit][eFieldUnit];
1442 sal_Int64 nMult = aImplFactor[eFieldUnit][eInUnit];
1443
1444 DBG_ASSERT( nMult > 0, "illegal *" );
1445 DBG_ASSERT( nDiv > 0, "illegal /" );
1446
1447 if( nMult != 1 && nMult > 0 )
1448 nValue *= nMult;
1449 if( nDiv != 1 && nDiv > 0 )
1450 {
1451 nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1452 nValue /= nDiv;
1453 }
1454 }
1455 return nValue;
1456 }
1457
1458 // -----------------------------------------------------------------------
1459
ImplMetricGetValue(const XubString & rStr,double & rValue,sal_Int64 nBaseValue,sal_uInt16 nDecDigits,const LocaleDataWrapper & rLocaleDataWrapper,FieldUnit eUnit)1460 static sal_Bool ImplMetricGetValue( const XubString& rStr, double& rValue, sal_Int64 nBaseValue,
1461 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit )
1462 {
1463 // Zahlenwert holen
1464 if ( !ImplNumericGetValue( rStr, rValue, nDecDigits, rLocaleDataWrapper ) )
1465 return sal_False;
1466
1467 // Einheit rausfinden
1468 FieldUnit eEntryUnit = ImplMetricGetUnit( rStr );
1469
1470 // Einheiten umrechnen
1471 rValue = MetricField::ConvertDoubleValue( rValue, nBaseValue, nDecDigits, eEntryUnit, eUnit );
1472
1473 return sal_True;
1474 }
1475
1476 // -----------------------------------------------------------------------
1477
ImplMetricReformat(const XubString & rStr,double & rValue,XubString & rOutStr)1478 sal_Bool MetricFormatter::ImplMetricReformat( const XubString& rStr, double& rValue, XubString& rOutStr )
1479 {
1480 if ( !ImplMetricGetValue( rStr, rValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1481 return sal_True;
1482 else
1483 {
1484 double nTempVal = rValue;
1485 // caution: precision loss in double cast
1486 if ( nTempVal > GetMax() )
1487 nTempVal = (double)GetMax();
1488 else if ( nTempVal < GetMin())
1489 nTempVal = (double)GetMin();
1490
1491 if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
1492 {
1493 mnCorrectedValue = (sal_Int64)nTempVal;
1494 if ( !GetErrorHdl().Call( this ) )
1495 {
1496 mnCorrectedValue = 0;
1497 return sal_False;
1498 }
1499 else
1500 mnCorrectedValue = 0;
1501 }
1502
1503 rOutStr = CreateFieldText( (sal_Int64)nTempVal );
1504 return sal_True;
1505 }
1506 }
1507
1508 // -----------------------------------------------------------------------
1509
ImplInit()1510 inline void MetricFormatter::ImplInit()
1511 {
1512 mnBaseValue = 0;
1513 meUnit = MetricField::GetDefaultUnit();
1514 mnType = FORMAT_METRIC;
1515 }
1516
1517 // -----------------------------------------------------------------------
1518
MetricFormatter()1519 MetricFormatter::MetricFormatter()
1520 {
1521 ImplInit();
1522 }
1523
1524 // -----------------------------------------------------------------------
1525
ImplLoadRes(const ResId & rResId)1526 void MetricFormatter::ImplLoadRes( const ResId& rResId )
1527 {
1528 NumericFormatter::ImplLoadRes( rResId );
1529
1530 ResMgr* pMgr = rResId.GetResMgr();
1531 if( pMgr )
1532 {
1533 sal_uLong nMask = pMgr->ReadLong();
1534
1535 if ( METRICFORMATTER_UNIT & nMask )
1536 meUnit = (FieldUnit)pMgr->ReadLong();
1537
1538 if ( METRICFORMATTER_CUSTOMUNITTEXT & nMask )
1539 maCustomUnitText = pMgr->ReadString();
1540 }
1541 }
1542
1543 // -----------------------------------------------------------------------
1544
~MetricFormatter()1545 MetricFormatter::~MetricFormatter()
1546 {
1547 }
1548
1549 // -----------------------------------------------------------------------
1550
SetUnit(FieldUnit eNewUnit)1551 void MetricFormatter::SetUnit( FieldUnit eNewUnit )
1552 {
1553 if ( eNewUnit == FUNIT_100TH_MM )
1554 {
1555 SetDecimalDigits( GetDecimalDigits() + 2 );
1556 meUnit = FUNIT_MM;
1557 }
1558 else
1559 meUnit = eNewUnit;
1560 ReformatAll();
1561 }
1562
1563 // -----------------------------------------------------------------------
1564
SetCustomUnitText(const XubString & rStr)1565 void MetricFormatter::SetCustomUnitText( const XubString& rStr )
1566 {
1567 maCustomUnitText = rStr;
1568 ReformatAll();
1569 }
1570
1571 // -----------------------------------------------------------------------
1572
SetValue(sal_Int64 nNewValue,FieldUnit eInUnit)1573 void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1574 {
1575 SetUserValue( nNewValue, eInUnit );
1576 mnFieldValue = mnLastValue;
1577 }
1578
1579 // -----------------------------------------------------------------------
1580
CreateFieldText(sal_Int64 nValue) const1581 XubString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const
1582 {
1583 XubString aStr = NumericFormatter::CreateFieldText( nValue );
1584
1585 if( meUnit == FUNIT_CUSTOM )
1586 aStr += maCustomUnitText;
1587 else
1588 {
1589 if ( meUnit != FUNIT_NONE )
1590 aStr += xub_Unicode( ' ' );
1591 aStr += ImplMetricToString( meUnit );
1592 }
1593 return aStr;
1594 }
1595
1596 // -----------------------------------------------------------------------
1597
SetUserValue(sal_Int64 nNewValue,FieldUnit eInUnit)1598 void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1599 {
1600 // Umrechnen auf eingestellte Einheiten
1601 nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit );
1602 NumericFormatter::SetUserValue( nNewValue );
1603 }
1604
1605 // -----------------------------------------------------------------------
1606
GetValue(FieldUnit eOutUnit) const1607 sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const
1608 {
1609 if ( !GetField() )
1610 return 0;
1611
1612 double nTempValue;
1613 // caution: precision loss in double cast
1614 if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1615 nTempValue = (double)mnLastValue;
1616
1617 // caution: precision loss in double cast
1618 if ( nTempValue > mnMax )
1619 nTempValue = (double)mnMax;
1620 else if ( nTempValue < mnMin )
1621 nTempValue = (double)mnMin;
1622
1623 // Umrechnen auf gewuenschte Einheiten
1624 return MetricField::ConvertValue( (sal_Int64)nTempValue, mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit );
1625 }
1626
1627 // -----------------------------------------------------------------------
1628
SetValue(sal_Int64 nValue)1629 void MetricFormatter::SetValue( sal_Int64 nValue )
1630 {
1631 // Implementation not inline, because it is a virtual Function
1632 SetValue( nValue, FUNIT_NONE );
1633 }
1634
1635 // -----------------------------------------------------------------------
1636
GetValue() const1637 sal_Int64 MetricFormatter::GetValue() const
1638 {
1639 // Implementation not inline, because it is a virtual Function
1640 return GetValue( FUNIT_NONE );
1641 }
1642
1643 // -----------------------------------------------------------------------
1644
SetMin(sal_Int64 nNewMin,FieldUnit eInUnit)1645 void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )
1646 {
1647 // Umrechnen auf gewuenschte Einheiten
1648 NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin, mnBaseValue, GetDecimalDigits(),
1649 eInUnit, meUnit ) );
1650 }
1651
1652 // -----------------------------------------------------------------------
1653
GetMin(FieldUnit eOutUnit) const1654 sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const
1655 {
1656 // Umrechnen auf gewuenschte Einheiten
1657 return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue,
1658 GetDecimalDigits(), meUnit, eOutUnit );
1659 }
1660
1661 // -----------------------------------------------------------------------
1662
SetMax(sal_Int64 nNewMax,FieldUnit eInUnit)1663 void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit )
1664 {
1665 // Umrechnen auf gewuenschte Einheiten
1666 NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax, mnBaseValue, GetDecimalDigits(),
1667 eInUnit, meUnit ) );
1668 }
1669
1670 // -----------------------------------------------------------------------
1671
GetMax(FieldUnit eOutUnit) const1672 sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const
1673 {
1674 // Umrechnen auf gewuenschte Einheiten
1675 return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue,
1676 GetDecimalDigits(), meUnit, eOutUnit );
1677 }
1678
1679 // -----------------------------------------------------------------------
1680
SetBaseValue(sal_Int64 nNewBase,FieldUnit eInUnit)1681 void MetricFormatter::SetBaseValue( sal_Int64 nNewBase, FieldUnit eInUnit )
1682 {
1683 mnBaseValue = MetricField::ConvertValue( nNewBase, mnBaseValue, GetDecimalDigits(),
1684 eInUnit, meUnit );
1685 }
1686
1687 // -----------------------------------------------------------------------
1688
GetBaseValue(FieldUnit eOutUnit) const1689 sal_Int64 MetricFormatter::GetBaseValue( FieldUnit eOutUnit ) const
1690 {
1691 // Umrechnen auf gewuenschte Einheiten
1692 return MetricField::ConvertValue( mnBaseValue, mnBaseValue, GetDecimalDigits(),
1693 meUnit, eOutUnit );
1694 }
1695
1696 // -----------------------------------------------------------------------
1697
Reformat()1698 void MetricFormatter::Reformat()
1699 {
1700 if ( !GetField() )
1701 return;
1702
1703 XubString aText = GetField()->GetText();
1704 if ( meUnit == FUNIT_CUSTOM )
1705 maCurUnitText = ImplMetricGetUnitText( aText );
1706
1707 XubString aStr;
1708 // caution: precision loss in double cast
1709 double nTemp = (double)mnLastValue;
1710 sal_Bool bOK = ImplMetricReformat( aText, nTemp, aStr );
1711 mnLastValue = (sal_Int64)nTemp;
1712
1713 if ( !bOK )
1714 return;
1715
1716 if ( aStr.Len() )
1717 {
1718 ImplSetText( aStr );
1719 if ( meUnit == FUNIT_CUSTOM )
1720 CustomConvert();
1721 }
1722 else
1723 SetValue( mnLastValue );
1724 maCurUnitText.Erase();
1725 }
1726
1727 // -----------------------------------------------------------------------
1728
GetCorrectedValue(FieldUnit eOutUnit) const1729 sal_Int64 MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit ) const
1730 {
1731 // Umrechnen auf gewuenschte Einheiten
1732 return MetricField::ConvertValue( mnCorrectedValue, mnBaseValue, GetDecimalDigits(),
1733 meUnit, eOutUnit );
1734 }
1735
1736 // -----------------------------------------------------------------------
1737
MetricField(Window * pParent,WinBits nWinStyle)1738 MetricField::MetricField( Window* pParent, WinBits nWinStyle ) :
1739 SpinField( pParent, nWinStyle )
1740 {
1741 SetField( this );
1742 Reformat();
1743 }
1744
1745 // -----------------------------------------------------------------------
1746
MetricField(Window * pParent,const ResId & rResId)1747 MetricField::MetricField( Window* pParent, const ResId& rResId ) :
1748 SpinField( WINDOW_METRICFIELD )
1749 {
1750 rResId.SetRT( RSC_METRICFIELD );
1751 WinBits nStyle = ImplInitRes( rResId ) ;
1752 SpinField::ImplInit( pParent, nStyle );
1753 SetField( this );
1754 ImplLoadRes( rResId );
1755
1756 if ( !(nStyle & WB_HIDE ) )
1757 Show();
1758 }
1759
1760 // -----------------------------------------------------------------------
1761
ImplLoadRes(const ResId & rResId)1762 void MetricField::ImplLoadRes( const ResId& rResId )
1763 {
1764 SpinField::ImplLoadRes( rResId );
1765 MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1766
1767 sal_uLong nMask = ReadLongRes();
1768
1769 if ( METRICFIELD_FIRST & nMask )
1770 mnFirst = ReadLongRes();
1771
1772 if ( METRICFIELD_LAST & nMask )
1773 mnLast = ReadLongRes();
1774
1775 if ( METRICFIELD_SPINSIZE & nMask )
1776 mnSpinSize = ReadLongRes();
1777
1778 Reformat();
1779 }
1780
1781 // -----------------------------------------------------------------------
1782
~MetricField()1783 MetricField::~MetricField()
1784 {
1785 }
1786
1787 // -----------------------------------------------------------------------
1788
SetFirst(sal_Int64 nNewFirst,FieldUnit eInUnit)1789 void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit )
1790 {
1791 // convert
1792 nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(),
1793 eInUnit, meUnit );
1794 mnFirst = nNewFirst;
1795 }
1796
1797 // -----------------------------------------------------------------------
1798
GetFirst(FieldUnit eOutUnit) const1799 sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const
1800 {
1801 // convert
1802 return MetricField::ConvertValue( mnFirst, mnBaseValue, GetDecimalDigits(),
1803 meUnit, eOutUnit );
1804 }
1805
1806 // -----------------------------------------------------------------------
1807
SetLast(sal_Int64 nNewLast,FieldUnit eInUnit)1808 void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit )
1809 {
1810 // Umrechnen
1811 nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(),
1812 eInUnit, meUnit );
1813 mnLast = nNewLast;
1814 }
1815
1816 // -----------------------------------------------------------------------
1817
GetLast(FieldUnit eOutUnit) const1818 sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const
1819 {
1820 // Umrechnen
1821 return MetricField::ConvertValue( mnLast, mnBaseValue, GetDecimalDigits(),
1822 meUnit, eOutUnit );
1823 }
1824
1825 // -----------------------------------------------------------------------
1826
PreNotify(NotifyEvent & rNEvt)1827 long MetricField::PreNotify( NotifyEvent& rNEvt )
1828 {
1829 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1830 {
1831 if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1832 return 1;
1833 }
1834
1835 return SpinField::PreNotify( rNEvt );
1836 }
1837
1838 // -----------------------------------------------------------------------
1839
Notify(NotifyEvent & rNEvt)1840 long MetricField::Notify( NotifyEvent& rNEvt )
1841 {
1842 if ( rNEvt.GetType() == EVENT_GETFOCUS )
1843 MarkToBeReformatted( sal_False );
1844 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1845 {
1846 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1847 Reformat();
1848 }
1849
1850 return SpinField::Notify( rNEvt );
1851 }
1852
1853 // -----------------------------------------------------------------------
1854
DataChanged(const DataChangedEvent & rDCEvt)1855 void MetricField::DataChanged( const DataChangedEvent& rDCEvt )
1856 {
1857 SpinField::DataChanged( rDCEvt );
1858
1859 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1860 {
1861 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1862 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1863 if ( IsDefaultLocale() )
1864 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1865 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1866 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1867 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1868 ReformatAll();
1869 }
1870 }
1871
1872 // -----------------------------------------------------------------------
1873
Modify()1874 void MetricField::Modify()
1875 {
1876 MarkToBeReformatted( sal_True );
1877 SpinField::Modify();
1878 }
1879
1880 // -----------------------------------------------------------------------
1881
Up()1882 void MetricField::Up()
1883 {
1884 FieldUp();
1885 SpinField::Up();
1886 }
1887
1888 // -----------------------------------------------------------------------
1889
Down()1890 void MetricField::Down()
1891 {
1892 FieldDown();
1893 SpinField::Down();
1894 }
1895
1896 // -----------------------------------------------------------------------
1897
First()1898 void MetricField::First()
1899 {
1900 FieldFirst();
1901 SpinField::First();
1902 }
1903
1904 // -----------------------------------------------------------------------
1905
Last()1906 void MetricField::Last()
1907 {
1908 FieldLast();
1909 SpinField::Last();
1910 }
1911
1912 // -----------------------------------------------------------------------
1913
CustomConvert()1914 void MetricField::CustomConvert()
1915 {
1916 maCustomConvertLink.Call( this );
1917 }
1918
1919 // -----------------------------------------------------------------------
1920
MetricBox(Window * pParent,WinBits nWinStyle)1921 MetricBox::MetricBox( Window* pParent, WinBits nWinStyle ) :
1922 ComboBox( pParent, nWinStyle )
1923 {
1924 SetField( this );
1925 Reformat();
1926 }
1927
1928 // -----------------------------------------------------------------------
1929
MetricBox(Window * pParent,const ResId & rResId)1930 MetricBox::MetricBox( Window* pParent, const ResId& rResId ) :
1931 ComboBox( WINDOW_METRICBOX )
1932 {
1933 rResId.SetRT( RSC_METRICBOX );
1934 WinBits nStyle = ImplInitRes( rResId );
1935 ComboBox::ImplInit( pParent, nStyle );
1936 SetField( this );
1937 Reformat();
1938 ComboBox::ImplLoadRes( rResId );
1939 MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1940
1941 if ( !(nStyle & WB_HIDE ) )
1942 Show();
1943 }
1944
1945 // -----------------------------------------------------------------------
1946
~MetricBox()1947 MetricBox::~MetricBox()
1948 {
1949 }
1950
1951 // -----------------------------------------------------------------------
1952
PreNotify(NotifyEvent & rNEvt)1953 long MetricBox::PreNotify( NotifyEvent& rNEvt )
1954 {
1955 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1956 {
1957 if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1958 return 1;
1959 }
1960
1961 return ComboBox::PreNotify( rNEvt );
1962 }
1963
1964 // -----------------------------------------------------------------------
1965
Notify(NotifyEvent & rNEvt)1966 long MetricBox::Notify( NotifyEvent& rNEvt )
1967 {
1968 if ( rNEvt.GetType() == EVENT_GETFOCUS )
1969 MarkToBeReformatted( sal_False );
1970 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1971 {
1972 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1973 Reformat();
1974 }
1975
1976 return ComboBox::Notify( rNEvt );
1977 }
1978
1979 // -----------------------------------------------------------------------
1980
DataChanged(const DataChangedEvent & rDCEvt)1981 void MetricBox::DataChanged( const DataChangedEvent& rDCEvt )
1982 {
1983 ComboBox::DataChanged( rDCEvt );
1984
1985 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1986 {
1987 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1988 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1989 if ( IsDefaultLocale() )
1990 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1991 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1992 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1993 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1994 ReformatAll();
1995 }
1996 }
1997
1998 // -----------------------------------------------------------------------
1999
Modify()2000 void MetricBox::Modify()
2001 {
2002 MarkToBeReformatted( sal_True );
2003 ComboBox::Modify();
2004 }
2005
2006 // -----------------------------------------------------------------------
2007
ReformatAll()2008 void MetricBox::ReformatAll()
2009 {
2010 double nValue;
2011 XubString aStr;
2012 SetUpdateMode( sal_False );
2013 sal_uInt16 nEntryCount = GetEntryCount();
2014 for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2015 {
2016 ImplMetricReformat( GetEntry( i ), nValue, aStr );
2017 RemoveEntry( i );
2018 InsertEntry( aStr, i );
2019 }
2020 MetricFormatter::Reformat();
2021 SetUpdateMode( sal_True );
2022 }
2023
2024 // -----------------------------------------------------------------------
2025
CustomConvert()2026 void MetricBox::CustomConvert()
2027 {
2028 maCustomConvertLink.Call( this );
2029 }
2030
2031 // -----------------------------------------------------------------------
2032
InsertValue(sal_Int64 nValue,FieldUnit eInUnit,sal_uInt16 nPos)2033 void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_uInt16 nPos )
2034 {
2035 // Umrechnen auf eingestellte Einheiten
2036 nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2037 eInUnit, meUnit );
2038 ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
2039 }
2040
2041 // -----------------------------------------------------------------------
2042
RemoveValue(sal_Int64 nValue,FieldUnit eInUnit)2043 void MetricBox::RemoveValue( sal_Int64 nValue, FieldUnit eInUnit )
2044 {
2045 // Umrechnen auf eingestellte Einheiten
2046 nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2047 eInUnit, meUnit );
2048 ComboBox::RemoveEntry( CreateFieldText( nValue ) );
2049 }
2050
2051 // -----------------------------------------------------------------------
2052
GetValue(sal_uInt16 nPos,FieldUnit eOutUnit) const2053 sal_Int64 MetricBox::GetValue( sal_uInt16 nPos, FieldUnit eOutUnit ) const
2054 {
2055 double nValue = 0;
2056 ImplMetricGetValue( ComboBox::GetEntry( nPos ), nValue, mnBaseValue,
2057 GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit );
2058
2059 // Umrechnen auf eingestellte Einheiten
2060 sal_Int64 nRetValue = MetricField::ConvertValue( (sal_Int64)nValue, mnBaseValue, GetDecimalDigits(),
2061 meUnit, eOutUnit );
2062
2063 return nRetValue;
2064 }
2065
2066 // -----------------------------------------------------------------------
2067
GetValuePos(sal_Int64 nValue,FieldUnit eInUnit) const2068 sal_uInt16 MetricBox::GetValuePos( sal_Int64 nValue, FieldUnit eInUnit ) const
2069 {
2070 // Umrechnen auf eingestellte Einheiten
2071 nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2072 eInUnit, meUnit );
2073 return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
2074 }
2075
2076 // -----------------------------------------------------------------------
2077
GetValue(FieldUnit eOutUnit) const2078 sal_Int64 MetricBox::GetValue( FieldUnit eOutUnit ) const
2079 {
2080 // Implementation not inline, because it is a virtual Function
2081 return MetricFormatter::GetValue( eOutUnit );
2082 }
2083
2084 // -----------------------------------------------------------------------
2085
GetValue() const2086 sal_Int64 MetricBox::GetValue() const
2087 {
2088 // Implementation not inline, because it is a virtual Function
2089 return GetValue( FUNIT_NONE );
2090 }
2091
2092 // -----------------------------------------------------------------------
2093
ImplCurrencyProcessKeyInput(Edit * pEdit,const KeyEvent & rKEvt,sal_Bool,sal_Bool bUseThousandSep,const LocaleDataWrapper & rWrapper)2094 static sal_Bool ImplCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
2095 sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
2096 {
2097 // Es gibt hier kein sinnvolles StrictFormat, also alle
2098 // Zeichen erlauben
2099 return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper );
2100 }
2101
2102 // -----------------------------------------------------------------------
2103
ImplCurrencyGetValue(const XubString & rStr,double & rValue,sal_uInt16 nDecDigits,const LocaleDataWrapper & rWrapper)2104 inline sal_Bool ImplCurrencyGetValue( const XubString& rStr, double& rValue,
2105 sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper )
2106 {
2107 // Zahlenwert holen
2108 return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, sal_True );
2109 }
2110
2111 // -----------------------------------------------------------------------
2112
ImplCurrencyReformat(const XubString & rStr,XubString & rOutStr)2113 sal_Bool CurrencyFormatter::ImplCurrencyReformat( const XubString& rStr,
2114 XubString& rOutStr )
2115 {
2116 double nValue;
2117 if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), sal_True ) )
2118 return sal_True;
2119 else
2120 {
2121 double nTempVal = nValue;
2122 // caution: precision loss in double cast
2123 if ( nTempVal > GetMax() )
2124 nTempVal = (double)GetMax();
2125 else if ( nTempVal < GetMin())
2126 nTempVal = (double)GetMin();
2127
2128 if ( GetErrorHdl().IsSet() && (nValue != nTempVal) )
2129 {
2130 mnCorrectedValue = (sal_Int64)nTempVal;
2131 if ( !GetErrorHdl().Call( this ) )
2132 {
2133 mnCorrectedValue = 0;
2134 return sal_False;
2135 }
2136 else
2137 mnCorrectedValue = 0;
2138 }
2139
2140 rOutStr = CreateFieldText( (long)nTempVal );
2141 return sal_True;
2142 }
2143 }
2144
2145 // -----------------------------------------------------------------------
2146
ImplInit()2147 inline void CurrencyFormatter::ImplInit()
2148 {
2149 mnType = FORMAT_CURRENCY;
2150 }
2151
2152 // -----------------------------------------------------------------------
2153
CurrencyFormatter()2154 CurrencyFormatter::CurrencyFormatter()
2155 {
2156 ImplInit();
2157 }
2158
2159 // -----------------------------------------------------------------------
2160
~CurrencyFormatter()2161 CurrencyFormatter::~CurrencyFormatter()
2162 {
2163 }
2164
2165 // -----------------------------------------------------------------------
2166
SetCurrencySymbol(const String & rStr)2167 void CurrencyFormatter::SetCurrencySymbol( const String& rStr )
2168 {
2169 maCurrencySymbol= rStr;
2170 ReformatAll();
2171 }
2172
2173 // -----------------------------------------------------------------------
2174
GetCurrencySymbol() const2175 String CurrencyFormatter::GetCurrencySymbol() const
2176 {
2177 return maCurrencySymbol.Len() ? maCurrencySymbol : ImplGetLocaleDataWrapper().getCurrSymbol();
2178 }
2179
2180 // -----------------------------------------------------------------------
2181
SetValue(sal_Int64 nNewValue)2182 void CurrencyFormatter::SetValue( sal_Int64 nNewValue )
2183 {
2184 SetUserValue( nNewValue );
2185 mnFieldValue = mnLastValue;
2186 SetEmptyFieldValueData( sal_False );
2187 }
2188
2189 // -----------------------------------------------------------------------
2190
CreateFieldText(sal_Int64 nValue) const2191 XubString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const
2192 {
2193 return ImplGetLocaleDataWrapper().getCurr( nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
2194 }
2195
2196 // -----------------------------------------------------------------------
2197
GetValue() const2198 sal_Int64 CurrencyFormatter::GetValue() const
2199 {
2200 if ( !GetField() )
2201 return 0;
2202
2203 double nTempValue;
2204 if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
2205 {
2206 // caution: precision loss in double cast
2207 if ( nTempValue > mnMax )
2208 nTempValue = (double)mnMax;
2209 else if ( nTempValue < mnMin )
2210 nTempValue = (double)mnMin;
2211 return (sal_Int64)nTempValue;
2212 }
2213 else
2214 return mnLastValue;
2215 }
2216
2217 // -----------------------------------------------------------------------
2218
Reformat()2219 void CurrencyFormatter::Reformat()
2220 {
2221 if ( !GetField() )
2222 return;
2223
2224 XubString aStr;
2225 sal_Bool bOK = ImplCurrencyReformat( GetField()->GetText(), aStr );
2226 if ( !bOK )
2227 return;
2228
2229 if ( aStr.Len() )
2230 {
2231 ImplSetText( aStr );
2232 // caution: precision loss in double cast
2233 double nTemp = (double)mnLastValue;
2234 ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2235 mnLastValue = (sal_Int64)nTemp;
2236 }
2237 else
2238 SetValue( mnLastValue );
2239 }
2240
2241 // -----------------------------------------------------------------------
2242
CurrencyField(Window * pParent,WinBits nWinStyle)2243 CurrencyField::CurrencyField( Window* pParent, WinBits nWinStyle ) :
2244 SpinField( pParent, nWinStyle )
2245 {
2246 SetField( this );
2247 Reformat();
2248 }
2249
2250 // -----------------------------------------------------------------------
2251
CurrencyField(Window * pParent,const ResId & rResId)2252 CurrencyField::CurrencyField( Window* pParent, const ResId& rResId ) :
2253 SpinField( WINDOW_CURRENCYFIELD )
2254 {
2255 rResId.SetRT( RSC_CURRENCYFIELD );
2256 WinBits nStyle = ImplInitRes( rResId );
2257 SpinField::ImplInit( pParent, nStyle);
2258 SetField( this );
2259 ImplLoadRes( rResId );
2260
2261 if ( !(nStyle & WB_HIDE ) )
2262 Show();
2263 }
2264
2265 // -----------------------------------------------------------------------
2266
ImplLoadRes(const ResId & rResId)2267 void CurrencyField::ImplLoadRes( const ResId& rResId )
2268 {
2269 SpinField::ImplLoadRes( rResId );
2270 CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
2271
2272 sal_uLong nMask = ReadLongRes();
2273
2274 if ( CURRENCYFIELD_FIRST & nMask )
2275 mnFirst = ReadLongRes();
2276
2277 if ( CURRENCYFIELD_LAST & nMask )
2278 mnLast = ReadLongRes();
2279
2280 if ( CURRENCYFIELD_SPINSIZE & nMask )
2281 mnSpinSize = ReadLongRes();
2282
2283 Reformat();
2284 }
2285
2286 // -----------------------------------------------------------------------
2287
~CurrencyField()2288 CurrencyField::~CurrencyField()
2289 {
2290 }
2291
2292 // -----------------------------------------------------------------------
2293
PreNotify(NotifyEvent & rNEvt)2294 long CurrencyField::PreNotify( NotifyEvent& rNEvt )
2295 {
2296 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2297 {
2298 if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2299 return 1;
2300 }
2301
2302 return SpinField::PreNotify( rNEvt );
2303 }
2304
2305 // -----------------------------------------------------------------------
2306
Notify(NotifyEvent & rNEvt)2307 long CurrencyField::Notify( NotifyEvent& rNEvt )
2308 {
2309 if ( rNEvt.GetType() == EVENT_GETFOCUS )
2310 MarkToBeReformatted( sal_False );
2311 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2312 {
2313 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
2314 Reformat();
2315 }
2316
2317 return SpinField::Notify( rNEvt );
2318 }
2319
2320 // -----------------------------------------------------------------------
2321
DataChanged(const DataChangedEvent & rDCEvt)2322 void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt )
2323 {
2324 SpinField::DataChanged( rDCEvt );
2325
2326 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2327 {
2328 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2329 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2330 if ( IsDefaultLocale() )
2331 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2332 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2333 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2334 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2335 ReformatAll();
2336 }
2337 }
2338
2339 // -----------------------------------------------------------------------
2340
Modify()2341 void CurrencyField::Modify()
2342 {
2343 MarkToBeReformatted( sal_True );
2344 SpinField::Modify();
2345 }
2346
2347 // -----------------------------------------------------------------------
2348
Up()2349 void CurrencyField::Up()
2350 {
2351 FieldUp();
2352 SpinField::Up();
2353 }
2354
2355 // -----------------------------------------------------------------------
2356
Down()2357 void CurrencyField::Down()
2358 {
2359 FieldDown();
2360 SpinField::Down();
2361 }
2362
2363 // -----------------------------------------------------------------------
2364
First()2365 void CurrencyField::First()
2366 {
2367 FieldFirst();
2368 SpinField::First();
2369 }
2370
2371 // -----------------------------------------------------------------------
2372
Last()2373 void CurrencyField::Last()
2374 {
2375 FieldLast();
2376 SpinField::Last();
2377 }
2378
2379 // -----------------------------------------------------------------------
2380
CurrencyBox(Window * pParent,WinBits nWinStyle)2381 CurrencyBox::CurrencyBox( Window* pParent, WinBits nWinStyle ) :
2382 ComboBox( pParent, nWinStyle )
2383 {
2384 SetField( this );
2385 Reformat();
2386 }
2387
2388 // -----------------------------------------------------------------------
2389
CurrencyBox(Window * pParent,const ResId & rResId)2390 CurrencyBox::CurrencyBox( Window* pParent, const ResId& rResId ) :
2391 ComboBox( WINDOW_CURRENCYBOX )
2392 {
2393 rResId.SetRT( RSC_CURRENCYBOX );
2394 WinBits nStyle = ImplInitRes( rResId );
2395 ComboBox::ImplInit( pParent, nStyle );
2396 CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
2397 SetField( this );
2398 ComboBox::ImplLoadRes( rResId );
2399 Reformat();
2400
2401 if ( !(nStyle & WB_HIDE ) )
2402 Show();
2403 }
2404
2405 // -----------------------------------------------------------------------
2406
~CurrencyBox()2407 CurrencyBox::~CurrencyBox()
2408 {
2409 }
2410
2411 // -----------------------------------------------------------------------
2412
PreNotify(NotifyEvent & rNEvt)2413 long CurrencyBox::PreNotify( NotifyEvent& rNEvt )
2414 {
2415 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2416 {
2417 if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2418 return 1;
2419 }
2420
2421 return ComboBox::PreNotify( rNEvt );
2422 }
2423
2424 // -----------------------------------------------------------------------
2425
Notify(NotifyEvent & rNEvt)2426 long CurrencyBox::Notify( NotifyEvent& rNEvt )
2427 {
2428 if ( rNEvt.GetType() == EVENT_GETFOCUS )
2429 MarkToBeReformatted( sal_False );
2430 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2431 {
2432 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
2433 Reformat();
2434 }
2435
2436 return ComboBox::Notify( rNEvt );
2437 }
2438
2439 // -----------------------------------------------------------------------
2440
DataChanged(const DataChangedEvent & rDCEvt)2441 void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt )
2442 {
2443 ComboBox::DataChanged( rDCEvt );
2444
2445 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2446 {
2447 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2448 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2449 if ( IsDefaultLocale() )
2450 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2451 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2452 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2453 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2454 ReformatAll();
2455 }
2456 }
2457
2458 // -----------------------------------------------------------------------
2459
Modify()2460 void CurrencyBox::Modify()
2461 {
2462 MarkToBeReformatted( sal_True );
2463 ComboBox::Modify();
2464 }
2465
2466 // -----------------------------------------------------------------------
2467
ReformatAll()2468 void CurrencyBox::ReformatAll()
2469 {
2470 XubString aStr;
2471 SetUpdateMode( sal_False );
2472 sal_uInt16 nEntryCount = GetEntryCount();
2473 for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2474 {
2475 ImplCurrencyReformat( GetEntry( i ), aStr );
2476 RemoveEntry( i );
2477 InsertEntry( aStr, i );
2478 }
2479 CurrencyFormatter::Reformat();
2480 SetUpdateMode( sal_True );
2481 }
2482
2483 // -----------------------------------------------------------------------
2484
InsertValue(sal_Int64 nValue,sal_uInt16 nPos)2485 void CurrencyBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos )
2486 {
2487 ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
2488 }
2489
2490 // -----------------------------------------------------------------------
2491
RemoveValue(sal_Int64 nValue)2492 void CurrencyBox::RemoveValue( sal_Int64 nValue )
2493 {
2494 ComboBox::RemoveEntry( CreateFieldText( nValue ) );
2495 }
2496
2497 // -----------------------------------------------------------------------
2498
GetValue(sal_uInt16 nPos) const2499 sal_Int64 CurrencyBox::GetValue( sal_uInt16 nPos ) const
2500 {
2501 double nValue = 0;
2502 ImplCurrencyGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2503 return (sal_Int64)nValue;
2504 }
2505
2506 // -----------------------------------------------------------------------
2507
GetValuePos(sal_Int64 nValue) const2508 sal_uInt16 CurrencyBox::GetValuePos( sal_Int64 nValue ) const
2509 {
2510 return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
2511 }
2512
2513 // -----------------------------------------------------------------------
2514
GetValue() const2515 sal_Int64 CurrencyBox::GetValue() const
2516 {
2517 // Implementation not inline, because it is a virtual Function
2518 return CurrencyFormatter::GetValue();
2519 }
2520