xref: /aoo42x/main/vcl/source/control/field.cxx (revision 6ac0dc2e)
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 
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 
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 
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 
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 
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 
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 
310 FormatterBase::~FormatterBase()
311 {
312     delete mpLocaleDataWrapper;
313 }
314 
315 // -----------------------------------------------------------------------
316 
317 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 
326 const LocaleDataWrapper& FormatterBase::GetLocaleDataWrapper() const
327 {
328     return ImplGetLocaleDataWrapper();
329 }
330 
331 // -----------------------------------------------------------------------
332 
333 void FormatterBase::Reformat()
334 {
335 }
336 
337 // -----------------------------------------------------------------------
338 
339 void FormatterBase::ReformatAll()
340 {
341     Reformat();
342 };
343 
344 // -----------------------------------------------------------------------
345 
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 
358 void FormatterBase::SetLocale( const lang::Locale& rLocale )
359 {
360     ImplGetLocaleDataWrapper().setLocale( rLocale );
361     mbDefaultLocale = sal_False;
362     ReformatAll();
363 }
364 
365 // -----------------------------------------------------------------------
366 
367 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 
382 const AllSettings& FormatterBase::GetFieldSettings() const
383 {
384     if ( mpField )
385         return mpField->GetSettings();
386     else
387         return Application::GetSettings();
388 }
389 
390 // -----------------------------------------------------------------------
391 
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 
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 
425 void FormatterBase::SetEmptyFieldValue()
426 {
427     if ( mpField )
428         mpField->SetText( ImplGetSVEmptyStr() );
429     mbEmptyFieldValue = sal_True;
430 }
431 
432 // -----------------------------------------------------------------------
433 
434 sal_Bool FormatterBase::IsEmptyFieldValue() const
435 {
436     return (!mpField || !mpField->GetText().Len());
437 }
438 
439 // -----------------------------------------------------------------------
440 
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 
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 
499 NumericFormatter::NumericFormatter()
500 {
501     ImplInit();
502 }
503 
504 // -----------------------------------------------------------------------
505 
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 
543 NumericFormatter::~NumericFormatter()
544 {
545 }
546 
547 // -----------------------------------------------------------------------
548 
549 void NumericFormatter::SetMin( sal_Int64 nNewMin )
550 {
551     mnMin = nNewMin;
552     if ( !IsEmptyFieldValue() )
553         ReformatAll();
554 }
555 
556 // -----------------------------------------------------------------------
557 
558 void NumericFormatter::SetMax( sal_Int64 nNewMax )
559 {
560     mnMax = nNewMax;
561     if ( !IsEmptyFieldValue() )
562         ReformatAll();
563 }
564 
565 // -----------------------------------------------------------------------
566 
567 void NumericFormatter::SetUseThousandSep( sal_Bool b )
568 {
569     mbThousandSep = b;
570     ReformatAll();
571 }
572 
573 // -----------------------------------------------------------------------
574 
575 void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits )
576 {
577     mnDecimalDigits = nDigits;
578     ReformatAll();
579 }
580 
581 // -----------------------------------------------------------------------
582 
583 void NumericFormatter::SetShowTrailingZeros( sal_Bool bShowTrailingZeros )
584 {
585     if ( mbShowTrailingZeros != bShowTrailingZeros )
586     {
587         mbShowTrailingZeros = bShowTrailingZeros;
588         ReformatAll();
589     }
590 }
591 
592 // -----------------------------------------------------------------------
593 
594 sal_uInt16 NumericFormatter::GetDecimalDigits() const
595 {
596     return mnDecimalDigits;
597 }
598 
599 // -----------------------------------------------------------------------
600 
601 void NumericFormatter::SetValue( sal_Int64 nNewValue )
602 {
603     SetUserValue( nNewValue );
604     mnFieldValue = mnLastValue;
605     SetEmptyFieldValueData( sal_False );
606 }
607 
608 // -----------------------------------------------------------------------
609 
610 XubString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const
611 {
612     return ImplGetLocaleDataWrapper().getNum( nValue, GetDecimalDigits(), IsUseThousandSep(), IsShowTrailingZeros() );
613 }
614 
615 // -----------------------------------------------------------------------
616 
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 
631 void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
632 {
633     ImplSetUserValue( nNewValue );
634 }
635 
636 // -----------------------------------------------------------------------
637 
638 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 
661 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 
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 
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 
690 sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const
691 {
692     return (nValue * ImplPower10( GetDecimalDigits() ) );
693 }
694 
695 // -----------------------------------------------------------------------
696 
697 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 
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 
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 
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 
760 void NumericFormatter::FieldFirst()
761 {
762     ImplNewFieldValue( mnFirst );
763 }
764 
765 // -----------------------------------------------------------------------
766 
767 void NumericFormatter::FieldLast()
768 {
769     ImplNewFieldValue( mnLast );
770 }
771 
772 // -----------------------------------------------------------------------
773 
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 
813 NumericField::NumericField( Window* pParent, WinBits nWinStyle ) :
814     SpinField( pParent, nWinStyle )
815 {
816     SetField( this );
817     Reformat();
818 }
819 
820 // -----------------------------------------------------------------------
821 
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 
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 
857 NumericField::~NumericField()
858 {
859 }
860 
861 // -----------------------------------------------------------------------
862 
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 
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 
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 
910 void NumericField::Modify()
911 {
912     MarkToBeReformatted( sal_True );
913     SpinField::Modify();
914 }
915 
916 // -----------------------------------------------------------------------
917 
918 void NumericField::Up()
919 {
920     FieldUp();
921     SpinField::Up();
922 }
923 
924 // -----------------------------------------------------------------------
925 
926 void NumericField::Down()
927 {
928     FieldDown();
929     SpinField::Down();
930 }
931 
932 // -----------------------------------------------------------------------
933 
934 void NumericField::First()
935 {
936     FieldFirst();
937     SpinField::First();
938 }
939 
940 // -----------------------------------------------------------------------
941 
942 void NumericField::Last()
943 {
944     FieldLast();
945     SpinField::Last();
946 }
947 
948 // -----------------------------------------------------------------------
949 
950 NumericBox::NumericBox( Window* pParent, WinBits nWinStyle ) :
951     ComboBox( pParent, nWinStyle )
952 {
953     SetField( this );
954     Reformat();
955 }
956 
957 // -----------------------------------------------------------------------
958 
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 
976 NumericBox::~NumericBox()
977 {
978 }
979 
980 // -----------------------------------------------------------------------
981 
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 
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 
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 
1029 void NumericBox::Modify()
1030 {
1031     MarkToBeReformatted( sal_True );
1032     ComboBox::Modify();
1033 }
1034 
1035 // -----------------------------------------------------------------------
1036 
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 
1055 void NumericBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos )
1056 {
1057     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
1058 }
1059 
1060 // -----------------------------------------------------------------------
1061 
1062 void NumericBox::RemoveValue( sal_Int64 nValue )
1063 {
1064     ComboBox::RemoveEntry( CreateFieldText( nValue ) );
1065 }
1066 
1067 // -----------------------------------------------------------------------
1068 
1069 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 
1078 sal_uInt16 NumericBox::GetValuePos( sal_Int64 nValue ) const
1079 {
1080     return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
1081 }
1082 
1083 // -----------------------------------------------------------------------
1084 
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 
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 
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 
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 
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 
1208 FieldUnit MetricField::GetDefaultUnit() { return eDefaultUnit; }
1209 void MetricField::SetDefaultUnit( FieldUnit meUnit ) { eDefaultUnit = meUnit; }
1210 
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 
1249 static double nonValueDoubleToValueDouble( double nValue )
1250 {
1251     return rtl::math::isFinite( nValue ) ? nValue : 0.0;
1252 }
1253 
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 
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 
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 
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 
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 
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 
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 
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 
1510 inline void MetricFormatter::ImplInit()
1511 {
1512     mnBaseValue = 0;
1513     meUnit = MetricField::GetDefaultUnit();
1514     mnType = FORMAT_METRIC;
1515 }
1516 
1517 // -----------------------------------------------------------------------
1518 
1519 MetricFormatter::MetricFormatter()
1520 {
1521     ImplInit();
1522 }
1523 
1524 // -----------------------------------------------------------------------
1525 
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 
1545 MetricFormatter::~MetricFormatter()
1546 {
1547 }
1548 
1549 // -----------------------------------------------------------------------
1550 
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 
1565 void MetricFormatter::SetCustomUnitText( const XubString& rStr )
1566 {
1567     maCustomUnitText = rStr;
1568     ReformatAll();
1569 }
1570 
1571 // -----------------------------------------------------------------------
1572 
1573 void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1574 {
1575     SetUserValue( nNewValue, eInUnit );
1576     mnFieldValue = mnLastValue;
1577 }
1578 
1579 // -----------------------------------------------------------------------
1580 
1581 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         aStr += ImplMetricToString( meUnit );
1589 
1590     return aStr;
1591 }
1592 
1593 // -----------------------------------------------------------------------
1594 
1595 void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1596 {
1597     // Umrechnen auf eingestellte Einheiten
1598     nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit );
1599     NumericFormatter::SetUserValue( nNewValue );
1600 }
1601 
1602 // -----------------------------------------------------------------------
1603 
1604 sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const
1605 {
1606     if ( !GetField() )
1607         return 0;
1608 
1609     double nTempValue;
1610     // caution: precision loss in double cast
1611     if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1612         nTempValue = (double)mnLastValue;
1613 
1614     // caution: precision loss in double cast
1615     if ( nTempValue > mnMax )
1616         nTempValue = (double)mnMax;
1617     else if ( nTempValue < mnMin )
1618         nTempValue = (double)mnMin;
1619 
1620     // Umrechnen auf gewuenschte Einheiten
1621     return MetricField::ConvertValue( (sal_Int64)nTempValue, mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit );
1622 }
1623 
1624 // -----------------------------------------------------------------------
1625 
1626 void MetricFormatter::SetValue( sal_Int64 nValue )
1627 {
1628     // Implementation not inline, because it is a virtual Function
1629     SetValue( nValue, FUNIT_NONE );
1630 }
1631 
1632 // -----------------------------------------------------------------------
1633 
1634 sal_Int64 MetricFormatter::GetValue() const
1635 {
1636     // Implementation not inline, because it is a virtual Function
1637     return GetValue( FUNIT_NONE );
1638 }
1639 
1640 // -----------------------------------------------------------------------
1641 
1642 void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )
1643 {
1644     // Umrechnen auf gewuenschte Einheiten
1645     NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin, mnBaseValue, GetDecimalDigits(),
1646                                                          eInUnit, meUnit ) );
1647 }
1648 
1649 // -----------------------------------------------------------------------
1650 
1651 sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const
1652 {
1653     // Umrechnen auf gewuenschte Einheiten
1654     return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue,
1655                                       GetDecimalDigits(), meUnit, eOutUnit );
1656 }
1657 
1658 // -----------------------------------------------------------------------
1659 
1660 void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit )
1661 {
1662     // Umrechnen auf gewuenschte Einheiten
1663     NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax, mnBaseValue, GetDecimalDigits(),
1664                                                          eInUnit, meUnit ) );
1665 }
1666 
1667 // -----------------------------------------------------------------------
1668 
1669 sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const
1670 {
1671     // Umrechnen auf gewuenschte Einheiten
1672     return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue,
1673                                       GetDecimalDigits(), meUnit, eOutUnit );
1674 }
1675 
1676 // -----------------------------------------------------------------------
1677 
1678 void MetricFormatter::SetBaseValue( sal_Int64 nNewBase, FieldUnit eInUnit )
1679 {
1680     mnBaseValue = MetricField::ConvertValue( nNewBase, mnBaseValue, GetDecimalDigits(),
1681                                              eInUnit, meUnit );
1682 }
1683 
1684 // -----------------------------------------------------------------------
1685 
1686 sal_Int64 MetricFormatter::GetBaseValue( FieldUnit eOutUnit ) const
1687 {
1688     // Umrechnen auf gewuenschte Einheiten
1689     return MetricField::ConvertValue( mnBaseValue, mnBaseValue, GetDecimalDigits(),
1690                                       meUnit, eOutUnit );
1691 }
1692 
1693 // -----------------------------------------------------------------------
1694 
1695 void MetricFormatter::Reformat()
1696 {
1697     if ( !GetField() )
1698         return;
1699 
1700     XubString aText = GetField()->GetText();
1701     if ( meUnit == FUNIT_CUSTOM )
1702         maCurUnitText = ImplMetricGetUnitText( aText );
1703 
1704     XubString aStr;
1705     // caution: precision loss in double cast
1706     double nTemp = (double)mnLastValue;
1707     sal_Bool bOK = ImplMetricReformat( aText, nTemp, aStr );
1708     mnLastValue = (sal_Int64)nTemp;
1709 
1710     if ( !bOK )
1711         return;
1712 
1713     if ( aStr.Len() )
1714     {
1715         ImplSetText( aStr );
1716         if ( meUnit == FUNIT_CUSTOM )
1717             CustomConvert();
1718     }
1719     else
1720         SetValue( mnLastValue );
1721     maCurUnitText.Erase();
1722 }
1723 
1724 // -----------------------------------------------------------------------
1725 
1726 sal_Int64 MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit ) const
1727 {
1728     // Umrechnen auf gewuenschte Einheiten
1729     return MetricField::ConvertValue( mnCorrectedValue, mnBaseValue, GetDecimalDigits(),
1730                                       meUnit, eOutUnit );
1731 }
1732 
1733 // -----------------------------------------------------------------------
1734 
1735 MetricField::MetricField( Window* pParent, WinBits nWinStyle ) :
1736     SpinField( pParent, nWinStyle )
1737 {
1738     SetField( this );
1739     Reformat();
1740 }
1741 
1742 // -----------------------------------------------------------------------
1743 
1744 MetricField::MetricField( Window* pParent, const ResId& rResId ) :
1745     SpinField( WINDOW_METRICFIELD )
1746 {
1747     rResId.SetRT( RSC_METRICFIELD );
1748     WinBits nStyle = ImplInitRes( rResId ) ;
1749     SpinField::ImplInit( pParent, nStyle );
1750     SetField( this );
1751     ImplLoadRes( rResId );
1752 
1753     if ( !(nStyle & WB_HIDE ) )
1754         Show();
1755 }
1756 
1757 // -----------------------------------------------------------------------
1758 
1759 void MetricField::ImplLoadRes( const ResId& rResId )
1760 {
1761     SpinField::ImplLoadRes( rResId );
1762     MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1763 
1764     sal_uLong      nMask = ReadLongRes();
1765 
1766     if ( METRICFIELD_FIRST & nMask )
1767         mnFirst = ReadLongRes();
1768 
1769     if ( METRICFIELD_LAST & nMask )
1770         mnLast = ReadLongRes();
1771 
1772     if ( METRICFIELD_SPINSIZE & nMask )
1773         mnSpinSize = ReadLongRes();
1774 
1775     Reformat();
1776 }
1777 
1778 // -----------------------------------------------------------------------
1779 
1780 MetricField::~MetricField()
1781 {
1782 }
1783 
1784 // -----------------------------------------------------------------------
1785 
1786 void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit )
1787 {
1788     // convert
1789     nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(),
1790                                            eInUnit, meUnit );
1791     mnFirst = nNewFirst;
1792 }
1793 
1794 // -----------------------------------------------------------------------
1795 
1796 sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const
1797 {
1798     // convert
1799     return MetricField::ConvertValue( mnFirst, mnBaseValue, GetDecimalDigits(),
1800                                       meUnit, eOutUnit );
1801 }
1802 
1803 // -----------------------------------------------------------------------
1804 
1805 void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit )
1806 {
1807     // Umrechnen
1808     nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(),
1809                                           eInUnit, meUnit );
1810     mnLast = nNewLast;
1811 }
1812 
1813 // -----------------------------------------------------------------------
1814 
1815 sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const
1816 {
1817     // Umrechnen
1818     return MetricField::ConvertValue( mnLast, mnBaseValue, GetDecimalDigits(),
1819                                       meUnit, eOutUnit );
1820 }
1821 
1822 // -----------------------------------------------------------------------
1823 
1824 long MetricField::PreNotify( NotifyEvent& rNEvt )
1825 {
1826     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1827     {
1828         if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1829             return 1;
1830     }
1831 
1832     return SpinField::PreNotify( rNEvt );
1833 }
1834 
1835 // -----------------------------------------------------------------------
1836 
1837 long MetricField::Notify( NotifyEvent& rNEvt )
1838 {
1839     if ( rNEvt.GetType() == EVENT_GETFOCUS )
1840         MarkToBeReformatted( sal_False );
1841     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1842     {
1843         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1844             Reformat();
1845     }
1846 
1847     return SpinField::Notify( rNEvt );
1848 }
1849 
1850 // -----------------------------------------------------------------------
1851 
1852 void MetricField::DataChanged( const DataChangedEvent& rDCEvt )
1853 {
1854     SpinField::DataChanged( rDCEvt );
1855 
1856     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1857     {
1858         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1859         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1860         if ( IsDefaultLocale() )
1861             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1862         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1863         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1864         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1865         ReformatAll();
1866     }
1867 }
1868 
1869 // -----------------------------------------------------------------------
1870 
1871 void MetricField::Modify()
1872 {
1873     MarkToBeReformatted( sal_True );
1874     SpinField::Modify();
1875 }
1876 
1877 // -----------------------------------------------------------------------
1878 
1879 void MetricField::Up()
1880 {
1881     FieldUp();
1882     SpinField::Up();
1883 }
1884 
1885 // -----------------------------------------------------------------------
1886 
1887 void MetricField::Down()
1888 {
1889     FieldDown();
1890     SpinField::Down();
1891 }
1892 
1893 // -----------------------------------------------------------------------
1894 
1895 void MetricField::First()
1896 {
1897     FieldFirst();
1898     SpinField::First();
1899 }
1900 
1901 // -----------------------------------------------------------------------
1902 
1903 void MetricField::Last()
1904 {
1905     FieldLast();
1906     SpinField::Last();
1907 }
1908 
1909 // -----------------------------------------------------------------------
1910 
1911 void MetricField::CustomConvert()
1912 {
1913     maCustomConvertLink.Call( this );
1914 }
1915 
1916 // -----------------------------------------------------------------------
1917 
1918 MetricBox::MetricBox( Window* pParent, WinBits nWinStyle ) :
1919     ComboBox( pParent, nWinStyle )
1920 {
1921     SetField( this );
1922     Reformat();
1923 }
1924 
1925 // -----------------------------------------------------------------------
1926 
1927 MetricBox::MetricBox( Window* pParent, const ResId& rResId ) :
1928     ComboBox( WINDOW_METRICBOX )
1929 {
1930     rResId.SetRT( RSC_METRICBOX );
1931     WinBits nStyle = ImplInitRes( rResId );
1932     ComboBox::ImplInit( pParent, nStyle );
1933     SetField( this );
1934     Reformat();
1935     ComboBox::ImplLoadRes( rResId );
1936     MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1937 
1938     if ( !(nStyle & WB_HIDE ) )
1939         Show();
1940 }
1941 
1942 // -----------------------------------------------------------------------
1943 
1944 MetricBox::~MetricBox()
1945 {
1946 }
1947 
1948 // -----------------------------------------------------------------------
1949 
1950 long MetricBox::PreNotify( NotifyEvent& rNEvt )
1951 {
1952     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2()  )
1953     {
1954         if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1955             return 1;
1956     }
1957 
1958     return ComboBox::PreNotify( rNEvt );
1959 }
1960 
1961 // -----------------------------------------------------------------------
1962 
1963 long MetricBox::Notify( NotifyEvent& rNEvt )
1964 {
1965     if ( rNEvt.GetType() == EVENT_GETFOCUS )
1966         MarkToBeReformatted( sal_False );
1967     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1968     {
1969         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1970             Reformat();
1971     }
1972 
1973     return ComboBox::Notify( rNEvt );
1974 }
1975 
1976 // -----------------------------------------------------------------------
1977 
1978 void MetricBox::DataChanged( const DataChangedEvent& rDCEvt )
1979 {
1980     ComboBox::DataChanged( rDCEvt );
1981 
1982     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1983     {
1984         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1985         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1986         if ( IsDefaultLocale() )
1987             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1988         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1989         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1990         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1991         ReformatAll();
1992     }
1993 }
1994 
1995 // -----------------------------------------------------------------------
1996 
1997 void MetricBox::Modify()
1998 {
1999     MarkToBeReformatted( sal_True );
2000     ComboBox::Modify();
2001 }
2002 
2003 // -----------------------------------------------------------------------
2004 
2005 void MetricBox::ReformatAll()
2006 {
2007     double nValue;
2008     XubString aStr;
2009     SetUpdateMode( sal_False );
2010     sal_uInt16 nEntryCount = GetEntryCount();
2011     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2012     {
2013         ImplMetricReformat( GetEntry( i ), nValue, aStr );
2014         RemoveEntry( i );
2015         InsertEntry( aStr, i );
2016     }
2017     MetricFormatter::Reformat();
2018     SetUpdateMode( sal_True );
2019 }
2020 
2021 // -----------------------------------------------------------------------
2022 
2023 void MetricBox::CustomConvert()
2024 {
2025     maCustomConvertLink.Call( this );
2026 }
2027 
2028 // -----------------------------------------------------------------------
2029 
2030 void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_uInt16 nPos )
2031 {
2032     // Umrechnen auf eingestellte Einheiten
2033     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2034                                         eInUnit, meUnit );
2035     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
2036 }
2037 
2038 // -----------------------------------------------------------------------
2039 
2040 void MetricBox::RemoveValue( sal_Int64 nValue, FieldUnit eInUnit )
2041 {
2042     // Umrechnen auf eingestellte Einheiten
2043     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2044                                         eInUnit, meUnit );
2045     ComboBox::RemoveEntry( CreateFieldText( nValue ) );
2046 }
2047 
2048 // -----------------------------------------------------------------------
2049 
2050 sal_Int64 MetricBox::GetValue( sal_uInt16 nPos, FieldUnit eOutUnit ) const
2051 {
2052     double nValue = 0;
2053     ImplMetricGetValue( ComboBox::GetEntry( nPos ), nValue, mnBaseValue,
2054                         GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit );
2055 
2056     // Umrechnen auf eingestellte Einheiten
2057     sal_Int64 nRetValue = MetricField::ConvertValue( (sal_Int64)nValue, mnBaseValue, GetDecimalDigits(),
2058                                                      meUnit, eOutUnit );
2059 
2060     return nRetValue;
2061 }
2062 
2063 // -----------------------------------------------------------------------
2064 
2065 sal_uInt16 MetricBox::GetValuePos( sal_Int64 nValue, FieldUnit eInUnit ) const
2066 {
2067     // Umrechnen auf eingestellte Einheiten
2068     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2069                                         eInUnit, meUnit );
2070     return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
2071 }
2072 
2073 // -----------------------------------------------------------------------
2074 
2075 sal_Int64 MetricBox::GetValue( FieldUnit eOutUnit ) const
2076 {
2077     // Implementation not inline, because it is a virtual Function
2078     return MetricFormatter::GetValue( eOutUnit );
2079 }
2080 
2081 // -----------------------------------------------------------------------
2082 
2083 sal_Int64 MetricBox::GetValue() const
2084 {
2085     // Implementation not inline, because it is a virtual Function
2086     return GetValue( FUNIT_NONE );
2087 }
2088 
2089 // -----------------------------------------------------------------------
2090 
2091 static sal_Bool ImplCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
2092                                          sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
2093 {
2094     // Es gibt hier kein sinnvolles StrictFormat, also alle
2095     // Zeichen erlauben
2096     return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper );
2097 }
2098 
2099 // -----------------------------------------------------------------------
2100 
2101 inline sal_Bool ImplCurrencyGetValue( const XubString& rStr, double& rValue,
2102                                   sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper )
2103 {
2104     // Zahlenwert holen
2105     return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, sal_True );
2106 }
2107 
2108 // -----------------------------------------------------------------------
2109 
2110 sal_Bool CurrencyFormatter::ImplCurrencyReformat( const XubString& rStr,
2111                                               XubString& rOutStr )
2112 {
2113     double nValue;
2114     if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), sal_True ) )
2115         return sal_True;
2116     else
2117     {
2118         double nTempVal = nValue;
2119         // caution: precision loss in double cast
2120         if ( nTempVal > GetMax() )
2121             nTempVal = (double)GetMax();
2122         else if ( nTempVal < GetMin())
2123             nTempVal = (double)GetMin();
2124 
2125         if ( GetErrorHdl().IsSet() && (nValue != nTempVal) )
2126         {
2127             mnCorrectedValue = (sal_Int64)nTempVal;
2128             if ( !GetErrorHdl().Call( this ) )
2129             {
2130                 mnCorrectedValue = 0;
2131                 return sal_False;
2132             }
2133             else
2134                 mnCorrectedValue = 0;
2135         }
2136 
2137         rOutStr = CreateFieldText( (long)nTempVal );
2138         return sal_True;
2139     }
2140 }
2141 
2142 // -----------------------------------------------------------------------
2143 
2144 inline void CurrencyFormatter::ImplInit()
2145 {
2146     mnType = FORMAT_CURRENCY;
2147 }
2148 
2149 // -----------------------------------------------------------------------
2150 
2151 CurrencyFormatter::CurrencyFormatter()
2152 {
2153     ImplInit();
2154 }
2155 
2156 // -----------------------------------------------------------------------
2157 
2158 CurrencyFormatter::~CurrencyFormatter()
2159 {
2160 }
2161 
2162 // -----------------------------------------------------------------------
2163 
2164 void CurrencyFormatter::SetCurrencySymbol( const String& rStr )
2165 {
2166     maCurrencySymbol= rStr;
2167     ReformatAll();
2168 }
2169 
2170 // -----------------------------------------------------------------------
2171 
2172 String CurrencyFormatter::GetCurrencySymbol() const
2173 {
2174     return maCurrencySymbol.Len() ? maCurrencySymbol : ImplGetLocaleDataWrapper().getCurrSymbol();
2175 }
2176 
2177 // -----------------------------------------------------------------------
2178 
2179 void CurrencyFormatter::SetValue( sal_Int64 nNewValue )
2180 {
2181     SetUserValue( nNewValue );
2182     mnFieldValue = mnLastValue;
2183     SetEmptyFieldValueData( sal_False );
2184 }
2185 
2186 // -----------------------------------------------------------------------
2187 
2188 XubString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const
2189 {
2190     return ImplGetLocaleDataWrapper().getCurr( nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
2191 }
2192 
2193 // -----------------------------------------------------------------------
2194 
2195 sal_Int64 CurrencyFormatter::GetValue() const
2196 {
2197     if ( !GetField() )
2198         return 0;
2199 
2200     double nTempValue;
2201     if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
2202     {
2203         // caution: precision loss in double cast
2204         if ( nTempValue > mnMax )
2205             nTempValue = (double)mnMax;
2206         else if ( nTempValue < mnMin )
2207             nTempValue = (double)mnMin;
2208         return (sal_Int64)nTempValue;
2209     }
2210     else
2211         return mnLastValue;
2212 }
2213 
2214 // -----------------------------------------------------------------------
2215 
2216 void CurrencyFormatter::Reformat()
2217 {
2218     if ( !GetField() )
2219         return;
2220 
2221     XubString aStr;
2222     sal_Bool bOK = ImplCurrencyReformat( GetField()->GetText(), aStr );
2223     if ( !bOK )
2224         return;
2225 
2226     if ( aStr.Len() )
2227     {
2228         ImplSetText( aStr  );
2229         // caution: precision loss in double cast
2230         double nTemp = (double)mnLastValue;
2231         ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2232         mnLastValue = (sal_Int64)nTemp;
2233     }
2234     else
2235         SetValue( mnLastValue );
2236 }
2237 
2238 // -----------------------------------------------------------------------
2239 
2240 CurrencyField::CurrencyField( Window* pParent, WinBits nWinStyle ) :
2241     SpinField( pParent, nWinStyle )
2242 {
2243     SetField( this );
2244     Reformat();
2245 }
2246 
2247 // -----------------------------------------------------------------------
2248 
2249 CurrencyField::CurrencyField( Window* pParent, const ResId& rResId ) :
2250     SpinField( WINDOW_CURRENCYFIELD )
2251 {
2252     rResId.SetRT( RSC_CURRENCYFIELD );
2253     WinBits nStyle = ImplInitRes( rResId );
2254     SpinField::ImplInit( pParent, nStyle);
2255     SetField( this );
2256     ImplLoadRes( rResId );
2257 
2258     if ( !(nStyle & WB_HIDE ) )
2259         Show();
2260 }
2261 
2262 // -----------------------------------------------------------------------
2263 
2264 void CurrencyField::ImplLoadRes( const ResId& rResId )
2265 {
2266     SpinField::ImplLoadRes( rResId );
2267     CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
2268 
2269     sal_uLong      nMask = ReadLongRes();
2270 
2271     if ( CURRENCYFIELD_FIRST & nMask )
2272         mnFirst = ReadLongRes();
2273 
2274     if ( CURRENCYFIELD_LAST & nMask )
2275         mnLast = ReadLongRes();
2276 
2277     if ( CURRENCYFIELD_SPINSIZE & nMask )
2278         mnSpinSize = ReadLongRes();
2279 
2280     Reformat();
2281 }
2282 
2283 // -----------------------------------------------------------------------
2284 
2285 CurrencyField::~CurrencyField()
2286 {
2287 }
2288 
2289 // -----------------------------------------------------------------------
2290 
2291 long CurrencyField::PreNotify( NotifyEvent& rNEvt )
2292 {
2293     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2294     {
2295         if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2296             return 1;
2297     }
2298 
2299     return SpinField::PreNotify( rNEvt );
2300 }
2301 
2302 // -----------------------------------------------------------------------
2303 
2304 long CurrencyField::Notify( NotifyEvent& rNEvt )
2305 {
2306     if ( rNEvt.GetType() == EVENT_GETFOCUS )
2307         MarkToBeReformatted( sal_False );
2308     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2309     {
2310         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
2311             Reformat();
2312     }
2313 
2314     return SpinField::Notify( rNEvt );
2315 }
2316 
2317 // -----------------------------------------------------------------------
2318 
2319 void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt )
2320 {
2321     SpinField::DataChanged( rDCEvt );
2322 
2323     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2324     {
2325         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2326         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2327         if ( IsDefaultLocale() )
2328             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2329         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2330         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2331         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2332         ReformatAll();
2333     }
2334 }
2335 
2336 // -----------------------------------------------------------------------
2337 
2338 void CurrencyField::Modify()
2339 {
2340     MarkToBeReformatted( sal_True );
2341     SpinField::Modify();
2342 }
2343 
2344 // -----------------------------------------------------------------------
2345 
2346 void CurrencyField::Up()
2347 {
2348     FieldUp();
2349     SpinField::Up();
2350 }
2351 
2352 // -----------------------------------------------------------------------
2353 
2354 void CurrencyField::Down()
2355 {
2356     FieldDown();
2357     SpinField::Down();
2358 }
2359 
2360 // -----------------------------------------------------------------------
2361 
2362 void CurrencyField::First()
2363 {
2364     FieldFirst();
2365     SpinField::First();
2366 }
2367 
2368 // -----------------------------------------------------------------------
2369 
2370 void CurrencyField::Last()
2371 {
2372     FieldLast();
2373     SpinField::Last();
2374 }
2375 
2376 // -----------------------------------------------------------------------
2377 
2378 CurrencyBox::CurrencyBox( Window* pParent, WinBits nWinStyle ) :
2379     ComboBox( pParent, nWinStyle )
2380 {
2381     SetField( this );
2382     Reformat();
2383 }
2384 
2385 // -----------------------------------------------------------------------
2386 
2387 CurrencyBox::CurrencyBox( Window* pParent, const ResId& rResId ) :
2388     ComboBox( WINDOW_CURRENCYBOX )
2389 {
2390     rResId.SetRT( RSC_CURRENCYBOX );
2391     WinBits nStyle = ImplInitRes( rResId );
2392     ComboBox::ImplInit( pParent, nStyle );
2393     CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
2394     SetField( this );
2395     ComboBox::ImplLoadRes( rResId );
2396     Reformat();
2397 
2398     if ( !(nStyle & WB_HIDE ) )
2399         Show();
2400 }
2401 
2402 // -----------------------------------------------------------------------
2403 
2404 CurrencyBox::~CurrencyBox()
2405 {
2406 }
2407 
2408 // -----------------------------------------------------------------------
2409 
2410 long CurrencyBox::PreNotify( NotifyEvent& rNEvt )
2411 {
2412     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2413     {
2414         if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2415             return 1;
2416     }
2417 
2418     return ComboBox::PreNotify( rNEvt );
2419 }
2420 
2421 // -----------------------------------------------------------------------
2422 
2423 long CurrencyBox::Notify( NotifyEvent& rNEvt )
2424 {
2425     if ( rNEvt.GetType() == EVENT_GETFOCUS )
2426         MarkToBeReformatted( sal_False );
2427     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2428     {
2429         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
2430             Reformat();
2431     }
2432 
2433     return ComboBox::Notify( rNEvt );
2434 }
2435 
2436 // -----------------------------------------------------------------------
2437 
2438 void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt )
2439 {
2440     ComboBox::DataChanged( rDCEvt );
2441 
2442     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2443     {
2444         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2445         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2446         if ( IsDefaultLocale() )
2447             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2448         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2449         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2450         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2451         ReformatAll();
2452     }
2453 }
2454 
2455 // -----------------------------------------------------------------------
2456 
2457 void CurrencyBox::Modify()
2458 {
2459     MarkToBeReformatted( sal_True );
2460     ComboBox::Modify();
2461 }
2462 
2463 // -----------------------------------------------------------------------
2464 
2465 void CurrencyBox::ReformatAll()
2466 {
2467     XubString aStr;
2468     SetUpdateMode( sal_False );
2469     sal_uInt16 nEntryCount = GetEntryCount();
2470     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2471     {
2472         ImplCurrencyReformat( GetEntry( i ), aStr );
2473         RemoveEntry( i );
2474         InsertEntry( aStr, i );
2475     }
2476     CurrencyFormatter::Reformat();
2477     SetUpdateMode( sal_True );
2478 }
2479 
2480 // -----------------------------------------------------------------------
2481 
2482 void CurrencyBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos )
2483 {
2484     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
2485 }
2486 
2487 // -----------------------------------------------------------------------
2488 
2489 void CurrencyBox::RemoveValue( sal_Int64 nValue )
2490 {
2491     ComboBox::RemoveEntry( CreateFieldText( nValue ) );
2492 }
2493 
2494 // -----------------------------------------------------------------------
2495 
2496 sal_Int64 CurrencyBox::GetValue( sal_uInt16 nPos ) const
2497 {
2498     double nValue = 0;
2499     ImplCurrencyGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2500     return (sal_Int64)nValue;
2501 }
2502 
2503 // -----------------------------------------------------------------------
2504 
2505 sal_uInt16 CurrencyBox::GetValuePos( sal_Int64 nValue ) const
2506 {
2507     return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
2508 }
2509 
2510 // -----------------------------------------------------------------------
2511 
2512 sal_Int64 CurrencyBox::GetValue() const
2513 {
2514     // Implementation not inline, because it is a virtual Function
2515     return CurrencyFormatter::GetValue();
2516 }
2517