xref: /aoo42x/main/vcl/source/control/field.cxx (revision 5abfe151)
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     mnCorrectedValue    = 0;
481     mnDecimalDigits     = 2;
482     mnType              = FORMAT_NUMERIC;
483     mbThousandSep       = sal_True;
484     mbShowTrailingZeros = sal_True;
485 
486     // for fields
487     mnSpinSize          = 1;
488     mnFirst             = mnMin;
489     mnLast              = mnMax;
490 
491     SetDecimalDigits( 0 );
492 }
493 
494 // -----------------------------------------------------------------------
495 
496 NumericFormatter::NumericFormatter()
497 {
498     ImplInit();
499 }
500 
501 // -----------------------------------------------------------------------
502 
503 void NumericFormatter::ImplLoadRes( const ResId& rResId )
504 {
505     ResMgr*     pMgr = rResId.GetResMgr();
506 
507     if( pMgr )
508     {
509         sal_uLong nMask = pMgr->ReadLong();
510 
511         if ( NUMERICFORMATTER_MIN & nMask )
512             mnMin = pMgr->ReadLong();
513 
514         if ( NUMERICFORMATTER_MAX & nMask )
515             mnMax = pMgr->ReadLong();
516 
517         if ( NUMERICFORMATTER_STRICTFORMAT & nMask )
518             SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
519 
520         if ( NUMERICFORMATTER_DECIMALDIGITS & nMask )
521             SetDecimalDigits( pMgr->ReadShort() );
522 
523         if ( NUMERICFORMATTER_VALUE & nMask )
524         {
525             mnFieldValue = pMgr->ReadLong();
526             if ( mnFieldValue > mnMax )
527                 mnFieldValue = mnMax;
528             else if ( mnFieldValue < mnMin )
529                 mnFieldValue = mnMin;
530             mnLastValue = mnFieldValue;
531         }
532 
533         if ( NUMERICFORMATTER_NOTHOUSANDSEP & nMask )
534             SetUseThousandSep( !(sal_Bool)pMgr->ReadShort() );
535     }
536 }
537 
538 // -----------------------------------------------------------------------
539 
540 NumericFormatter::~NumericFormatter()
541 {
542 }
543 
544 // -----------------------------------------------------------------------
545 
546 void NumericFormatter::SetMin( sal_Int64 nNewMin )
547 {
548     mnMin = nNewMin;
549     if ( !IsEmptyFieldValue() )
550         ReformatAll();
551 }
552 
553 // -----------------------------------------------------------------------
554 
555 void NumericFormatter::SetMax( sal_Int64 nNewMax )
556 {
557     mnMax = nNewMax;
558     if ( !IsEmptyFieldValue() )
559         ReformatAll();
560 }
561 
562 // -----------------------------------------------------------------------
563 
564 void NumericFormatter::SetUseThousandSep( sal_Bool b )
565 {
566     mbThousandSep = b;
567     ReformatAll();
568 }
569 
570 // -----------------------------------------------------------------------
571 
572 void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits )
573 {
574     mnDecimalDigits = nDigits;
575     ReformatAll();
576 }
577 
578 // -----------------------------------------------------------------------
579 
580 void NumericFormatter::SetShowTrailingZeros( sal_Bool bShowTrailingZeros )
581 {
582     if ( mbShowTrailingZeros != bShowTrailingZeros )
583     {
584         mbShowTrailingZeros = bShowTrailingZeros;
585         ReformatAll();
586     }
587 }
588 
589 // -----------------------------------------------------------------------
590 
591 sal_uInt16 NumericFormatter::GetDecimalDigits() const
592 {
593     return mnDecimalDigits;
594 }
595 
596 // -----------------------------------------------------------------------
597 
598 void NumericFormatter::SetValue( sal_Int64 nNewValue )
599 {
600     SetUserValue( nNewValue );
601     mnFieldValue = mnLastValue;
602     SetEmptyFieldValueData( sal_False );
603 }
604 
605 // -----------------------------------------------------------------------
606 
607 XubString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const
608 {
609     return ImplGetLocaleDataWrapper().getNum( nValue, GetDecimalDigits(), IsUseThousandSep(), IsShowTrailingZeros() );
610 }
611 
612 // -----------------------------------------------------------------------
613 
614 void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection* pNewSelection )
615 {
616     if ( nNewValue > mnMax )
617         nNewValue = mnMax;
618     else if ( nNewValue < mnMin )
619         nNewValue = mnMin;
620     mnLastValue = nNewValue;
621 
622     if ( GetField() )
623         ImplSetText( CreateFieldText( nNewValue ), pNewSelection );
624 }
625 
626 // -----------------------------------------------------------------------
627 
628 void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
629 {
630     ImplSetUserValue( nNewValue );
631 }
632 
633 // -----------------------------------------------------------------------
634 
635 sal_Int64 NumericFormatter::GetValue() const
636 {
637     if ( !GetField() )
638         return 0;
639 
640     double nTempValue;
641 
642     if ( ImplNumericGetValue( GetField()->GetText(), nTempValue,
643                               GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
644     {
645         // caution: precision loss in double cast
646         if ( nTempValue > mnMax )
647             nTempValue = (double)mnMax;
648         else if ( nTempValue < mnMin )
649             nTempValue = (double)mnMin;
650         return (sal_Int64)nTempValue;
651     }
652     else
653         return mnLastValue;
654 }
655 
656 // -----------------------------------------------------------------------
657 
658 sal_Bool NumericFormatter::IsValueModified() const
659 {
660     if ( ImplGetEmptyFieldValue() )
661         return !IsEmptyFieldValue();
662     else if ( GetValue() != mnFieldValue )
663         return sal_True;
664     else
665         return sal_False;
666 }
667 
668 // -----------------------------------------------------------------------
669 
670 Fraction NumericFormatter::ConvertToFraction( sal_Int64 nValue )
671 {
672     // caution: precision loss in double cast (and in fraction anyhow)
673     return Fraction( (double)nValue/(double)ImplPower10( GetDecimalDigits() ) );
674 }
675 
676 // -----------------------------------------------------------------------
677 
678 sal_Int64 NumericFormatter::ConvertToLong( const Fraction& rValue )
679 {
680     Fraction aFract = rValue;
681     aFract *= Fraction( (long)ImplPower10( GetDecimalDigits() ), 1 );
682     return (sal_Int64)(double)aFract;
683 }
684 
685 // -----------------------------------------------------------------------
686 
687 sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const
688 {
689     return (nValue * ImplPower10( GetDecimalDigits() ) );
690 }
691 
692 // -----------------------------------------------------------------------
693 
694 sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const
695 {
696     sal_Int64 nFactor = ImplPower10( GetDecimalDigits() );
697 
698     if((nValue < ( SAL_MIN_INT64 + nFactor )) ||
699        (nValue > ( SAL_MAX_INT64 - nFactor )))
700 	return ( nValue / nFactor );
701     if( nValue < 0 )
702 	return ((nValue-(nFactor/2)) / nFactor );
703     else
704 	return ((nValue+(nFactor/2)) / nFactor );
705 }
706 
707 // -----------------------------------------------------------------------
708 
709 void NumericFormatter::Reformat()
710 {
711     if ( !GetField() )
712         return;
713 
714     if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
715         return;
716 
717     XubString aStr;
718     // caution: precision loss in double cast
719     double nTemp = (double)mnLastValue;
720     sal_Bool bOK = ImplNumericReformat( GetField()->GetText(), nTemp, aStr );
721     mnLastValue = (sal_Int64)nTemp;
722     if ( !bOK )
723         return;
724 
725     if ( aStr.Len() )
726         ImplSetText( aStr );
727     else
728         SetValue( mnLastValue );
729 }
730 
731 // -----------------------------------------------------------------------
732 
733 void NumericFormatter::FieldUp()
734 {
735     sal_Int64 nValue = GetValue();
736     nValue += mnSpinSize;
737     if ( nValue > mnMax )
738         nValue = mnMax;
739 
740     ImplNewFieldValue( nValue );
741 }
742 
743 // -----------------------------------------------------------------------
744 
745 void NumericFormatter::FieldDown()
746 {
747     sal_Int64 nValue = GetValue();
748     nValue -= mnSpinSize;
749     if ( nValue < mnMin )
750         nValue = mnMin;
751 
752     ImplNewFieldValue( nValue );
753 }
754 
755 // -----------------------------------------------------------------------
756 
757 void NumericFormatter::FieldFirst()
758 {
759     ImplNewFieldValue( mnFirst );
760 }
761 
762 // -----------------------------------------------------------------------
763 
764 void NumericFormatter::FieldLast()
765 {
766     ImplNewFieldValue( mnLast );
767 }
768 
769 // -----------------------------------------------------------------------
770 
771 void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue )
772 {
773     if ( GetField() )
774     {
775         // !!! TH-18.2.99: Wenn wir Zeit haben sollte mal geklaert werden,
776         // !!! warum nicht bei ImplSetUserValue() geprueft wird, ob
777         // !!! sich der Wert aendert. Denn auch hier muesste dieses
778         // !!! gemacht werden, da ansonsten der Modify-Aufruf
779         // !!! nicht gemacht werden duerfte. Jedenfalls sollten die
780         // !!! Wege von ImplNewFieldValue, ImplSetUserValue und
781         // !!! ImplSetText ueberprueft und klarer gestalltet (mit Kommentar)
782         // !!! werden, damit wir mal wissen, was dort ablaeuft!!!
783 
784         Selection aSelection = GetField()->GetSelection();
785         aSelection.Justify();
786         XubString aText = GetField()->GetText();
787         // Wenn bis ans Ende selektiert war, soll das auch so bleiben...
788         if ( (xub_StrLen)aSelection.Max() == aText.Len() )
789         {
790             if ( !aSelection.Len() )
791                 aSelection.Min() = SELECTION_MAX;
792             aSelection.Max() = SELECTION_MAX;
793         }
794 
795         sal_Int64 nOldLastValue  = mnLastValue;
796         ImplSetUserValue( nNewValue, &aSelection );
797         mnLastValue = nOldLastValue;
798 
799         // Modify am Edit wird nur bei KeyInput gesetzt...
800         if ( GetField()->GetText() != aText )
801         {
802             GetField()->SetModifyFlag();
803             GetField()->Modify();
804         }
805     }
806 }
807 
808 // -----------------------------------------------------------------------
809 
810 NumericField::NumericField( Window* pParent, WinBits nWinStyle ) :
811     SpinField( pParent, nWinStyle )
812 {
813     SetField( this );
814     Reformat();
815 }
816 
817 // -----------------------------------------------------------------------
818 
819 NumericField::NumericField( Window* pParent, const ResId& rResId ) :
820     SpinField( WINDOW_NUMERICFIELD )
821 {
822     rResId.SetRT( RSC_NUMERICFIELD );
823     WinBits nStyle = ImplInitRes( rResId ) ;
824     SpinField::ImplInit( pParent, nStyle );
825     SetField( this );
826     ImplLoadRes( rResId );
827     Reformat();
828 
829     if ( !(nStyle & WB_HIDE ) )
830         Show();
831 }
832 
833 // -----------------------------------------------------------------------
834 
835 void NumericField::ImplLoadRes( const ResId& rResId )
836 {
837     SpinField::ImplLoadRes( rResId );
838     NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
839 
840     sal_uLong      nMask = ReadLongRes();
841 
842     if ( NUMERICFIELD_FIRST & nMask )
843         mnFirst = ReadLongRes();
844 
845     if ( NUMERICFIELD_LAST & nMask )
846         mnLast = ReadLongRes();
847 
848     if ( NUMERICFIELD_SPINSIZE & nMask )
849         mnSpinSize = ReadLongRes();
850 }
851 
852 // -----------------------------------------------------------------------
853 
854 NumericField::~NumericField()
855 {
856 }
857 
858 // -----------------------------------------------------------------------
859 
860 long NumericField::PreNotify( NotifyEvent& rNEvt )
861 {
862         if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
863     {
864         if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
865             return 1;
866     }
867 
868     return SpinField::PreNotify( rNEvt );
869 }
870 
871 // -----------------------------------------------------------------------
872 
873 long NumericField::Notify( NotifyEvent& rNEvt )
874 {
875     if ( rNEvt.GetType() == EVENT_GETFOCUS )
876         MarkToBeReformatted( sal_False );
877     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
878     {
879         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
880             Reformat();
881     }
882 
883     return SpinField::Notify( rNEvt );
884 }
885 
886 // -----------------------------------------------------------------------
887 
888 void NumericField::DataChanged( const DataChangedEvent& rDCEvt )
889 {
890     SpinField::DataChanged( rDCEvt );
891 
892     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
893     {
894         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
895         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
896         if ( IsDefaultLocale() )
897             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
898         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
899         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
900         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
901         ReformatAll();
902     }
903 }
904 
905 // -----------------------------------------------------------------------
906 
907 void NumericField::Modify()
908 {
909     MarkToBeReformatted( sal_True );
910     SpinField::Modify();
911 }
912 
913 // -----------------------------------------------------------------------
914 
915 void NumericField::Up()
916 {
917     FieldUp();
918     SpinField::Up();
919 }
920 
921 // -----------------------------------------------------------------------
922 
923 void NumericField::Down()
924 {
925     FieldDown();
926     SpinField::Down();
927 }
928 
929 // -----------------------------------------------------------------------
930 
931 void NumericField::First()
932 {
933     FieldFirst();
934     SpinField::First();
935 }
936 
937 // -----------------------------------------------------------------------
938 
939 void NumericField::Last()
940 {
941     FieldLast();
942     SpinField::Last();
943 }
944 
945 // -----------------------------------------------------------------------
946 
947 NumericBox::NumericBox( Window* pParent, WinBits nWinStyle ) :
948     ComboBox( pParent, nWinStyle )
949 {
950     SetField( this );
951     Reformat();
952 }
953 
954 // -----------------------------------------------------------------------
955 
956 NumericBox::NumericBox( Window* pParent, const ResId& rResId ) :
957     ComboBox( WINDOW_NUMERICBOX )
958 {
959     rResId.SetRT( RSC_NUMERICBOX );
960     WinBits nStyle = ImplInitRes( rResId );
961     ComboBox::ImplInit( pParent, nStyle );
962     SetField( this );
963     ComboBox::ImplLoadRes( rResId );
964     NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
965     Reformat();
966 
967     if ( !(nStyle & WB_HIDE ) )
968         Show();
969 }
970 
971 // -----------------------------------------------------------------------
972 
973 NumericBox::~NumericBox()
974 {
975 }
976 
977 // -----------------------------------------------------------------------
978 
979 long NumericBox::PreNotify( NotifyEvent& rNEvt )
980 {
981     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
982     {
983         if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
984             return 1;
985     }
986 
987     return ComboBox::PreNotify( rNEvt );
988 }
989 
990 // -----------------------------------------------------------------------
991 
992 long NumericBox::Notify( NotifyEvent& rNEvt )
993 {
994     if ( rNEvt.GetType() == EVENT_GETFOCUS )
995         MarkToBeReformatted( sal_False );
996     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
997     {
998         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
999             Reformat();
1000     }
1001 
1002     return ComboBox::Notify( rNEvt );
1003 }
1004 
1005 // -----------------------------------------------------------------------
1006 
1007 void NumericBox::DataChanged( const DataChangedEvent& rDCEvt )
1008 {
1009     ComboBox::DataChanged( rDCEvt );
1010 
1011     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1012     {
1013         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1014         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1015         if ( IsDefaultLocale() )
1016             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1017         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1018         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1019         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1020         ReformatAll();
1021     }
1022 }
1023 
1024 // -----------------------------------------------------------------------
1025 
1026 void NumericBox::Modify()
1027 {
1028     MarkToBeReformatted( sal_True );
1029     ComboBox::Modify();
1030 }
1031 
1032 // -----------------------------------------------------------------------
1033 
1034 void NumericBox::ReformatAll()
1035 {
1036     double nValue;
1037     XubString aStr;
1038     SetUpdateMode( sal_False );
1039     sal_uInt16 nEntryCount = GetEntryCount();
1040     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
1041     {
1042         ImplNumericReformat( GetEntry( i ), nValue, aStr );
1043         RemoveEntry( i );
1044         InsertEntry( aStr, i );
1045     }
1046     NumericFormatter::Reformat();
1047     SetUpdateMode( sal_True );
1048 }
1049 
1050 // -----------------------------------------------------------------------
1051 
1052 void NumericBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos )
1053 {
1054     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
1055 }
1056 
1057 // -----------------------------------------------------------------------
1058 
1059 void NumericBox::RemoveValue( sal_Int64 nValue )
1060 {
1061     ComboBox::RemoveEntry( CreateFieldText( nValue ) );
1062 }
1063 
1064 // -----------------------------------------------------------------------
1065 
1066 sal_Int64 NumericBox::GetValue( sal_uInt16 nPos ) const
1067 {
1068     double nValue = 0;
1069     ImplNumericGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
1070     return (sal_Int64)nValue;
1071 }
1072 
1073 // -----------------------------------------------------------------------
1074 
1075 sal_uInt16 NumericBox::GetValuePos( sal_Int64 nValue ) const
1076 {
1077     return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
1078 }
1079 
1080 // -----------------------------------------------------------------------
1081 
1082 static sal_Bool ImplMetricProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
1083                                        sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
1084 {
1085     // Es gibt hier kein sinnvolles StrictFormat, also alle
1086     // Zeichen erlauben
1087     return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper );
1088 }
1089 
1090 // -----------------------------------------------------------------------
1091 
1092 static XubString ImplMetricGetUnitText( const XubString& rStr )
1093 {
1094     // Einheitentext holen
1095     XubString aStr;
1096     for ( short i = rStr.Len()-1; i >= 0; i-- )
1097     {
1098         xub_Unicode c = rStr.GetChar( i );
1099         if ( unicode::isAlpha( c ) ||
1100              (c == '\'') || (c == '\"') || (c == '%' ) )
1101             aStr.Insert( c, 0 );
1102         else
1103         {
1104             if ( aStr.Len() )
1105                 break;
1106         }
1107     }
1108     return aStr;
1109 
1110 /*
1111     // MT: #90545# Preparation for translated strings...
1112     String aMetricText;
1113     for ( sal_uInt16 n = rStr.Len(); n; )
1114     {
1115         sal_Unicode c = rStr.GetChar( --n );
1116         sal_Int32 nType = xCharClass->getStringType( rStr, n, 1, rLocale );
1117 
1118         if ( CharClass::isLetterType( nType ) )
1119         {
1120             aMetricText.Insert( c, 0 );
1121         }
1122         else
1123         {
1124             if ( aMetricText.Len() )
1125                 break;
1126         }
1127     }
1128 */
1129 }
1130 
1131 // -----------------------------------------------------------------------
1132 
1133 // #104355# support localized mesaurements
1134 
1135 static const String& ImplMetricToString( FieldUnit rUnit )
1136 {
1137     FieldUnitStringList* pList = ImplGetFieldUnits();
1138     if( pList )
1139     {
1140         // return unit's default string (ie, the first one )
1141         for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it )
1142         {
1143             if ( it->second == rUnit )
1144                 return it->first;
1145         }
1146     }
1147 
1148     return String::EmptyString();
1149 }
1150 
1151 static FieldUnit ImplStringToMetric( const String &rMetricString )
1152 {
1153     FieldUnitStringList* pList = ImplGetCleanedFieldUnits();
1154     if( pList )
1155     {
1156         // return FieldUnit
1157         String aStr( rMetricString );
1158         aStr.ToLowerAscii();
1159         aStr.EraseAllChars( sal_Unicode( ' ' ) );
1160         for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it )
1161         {
1162             if ( it->first.Equals( aStr ) )
1163                 return it->second;
1164         }
1165     }
1166 
1167     return FUNIT_NONE;
1168 }
1169 
1170 // -----------------------------------------------------------------------
1171 
1172 static FieldUnit ImplMetricGetUnit( const XubString& rStr )
1173 {
1174     XubString aStr = ImplMetricGetUnitText( rStr );
1175     return ImplStringToMetric( aStr );
1176 }
1177 
1178 #define K *1000L
1179 #define M *1000000L
1180 #define X *5280L
1181 
1182 static const sal_Int64 aImplFactor[FUNIT_MILE+1][FUNIT_MILE+1] =
1183 { /*
1184 mm/100    mm    cm       m     km  twip point  pica  inch    foot     mile */
1185 {    1,  100,  1 K,  100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X },
1186 {    1,    1,   10,    1 K,   1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X },
1187 {    1,    1,    1,    100, 100 K,  254,  254,  254,  254, 254*12, 254*12 X },
1188 {    1,    1,    1,      1,   1 K,  254,  254,  254,  254, 254*12, 254*12 X },
1189 {    1,    1,    1,      1,     1,    0,  254,  254,  254, 254*12, 254*12 X },
1190 { 1440,144 K,144 K,14400 K,     0,    1,   20,  240, 1440,1440*12,1440*12 X },
1191 {   72, 7200, 7200,  720 K, 720 M,    1,    1,   12,   72,  72*12,  72*12 X },
1192 {    6,  600,  600,   60 K,  60 M,    1,    1,    1,    6,   6*12,   6*12 X },
1193 {    1,  100,  100,   10 K,  10 M,    1,    1,    1,    1,     12,     12 X },
1194 {    1,  100,  100,   10 K,  10 M,    1,    1,    1,    1,      1,      1 X },
1195 {    1,  100,  100,   10 K,  10 M,    1,    1,    1,    1,      1,        1 }
1196 };
1197 
1198 #undef X
1199 #undef M
1200 #undef K
1201 // twip in km 254/14400 M
1202 
1203 static FieldUnit eDefaultUnit = FUNIT_NONE;
1204 
1205 FieldUnit MetricField::GetDefaultUnit() { return eDefaultUnit; }
1206 void MetricField::SetDefaultUnit( FieldUnit meUnit ) { eDefaultUnit = meUnit; }
1207 
1208 static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, long& nDecDigits )
1209 {
1210     switch( meUnit )
1211     {
1212         case MAP_100TH_MM :
1213             nDecDigits -= 2;
1214             return FUNIT_MM;
1215         case MAP_10TH_MM :
1216             nDecDigits -= 1;
1217             return FUNIT_MM;
1218         case MAP_MM :
1219             return FUNIT_MM;
1220         case MAP_CM :
1221             return FUNIT_CM;
1222         case MAP_1000TH_INCH :
1223             nDecDigits -= 3;
1224             return FUNIT_INCH;
1225         case MAP_100TH_INCH :
1226             nDecDigits -= 2;
1227             return FUNIT_INCH;
1228         case MAP_10TH_INCH :
1229             nDecDigits -= 1;
1230             return FUNIT_INCH;
1231         case MAP_INCH :
1232             return FUNIT_INCH;
1233         case MAP_POINT :
1234             return FUNIT_POINT;
1235         case MAP_TWIP :
1236             return FUNIT_TWIP;
1237         default:
1238             DBG_ERROR( "default eInUnit" );
1239             break;
1240     }
1241     return FUNIT_NONE;
1242 }
1243 
1244 // -----------------------------------------------------------------------
1245 
1246 static double nonValueDoubleToValueDouble( double nValue )
1247 {
1248     return rtl::math::isFinite( nValue ) ? nValue : 0.0;
1249 }
1250 
1251 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1252                                      FieldUnit eInUnit, FieldUnit eOutUnit )
1253 {
1254     double nDouble = nonValueDoubleToValueDouble( ConvertDoubleValue(
1255                 (double)nValue, mnBaseValue, nDecDigits, eInUnit, eOutUnit ) );
1256     sal_Int64 nLong ;
1257 
1258     // caution: precision loss in double cast
1259     if ( nDouble <= (double)SAL_MIN_INT64 )
1260 	nLong = SAL_MIN_INT64;
1261     else if ( nDouble >= (double)SAL_MAX_INT64 )
1262 	nLong = SAL_MAX_INT64;
1263     else
1264 	nLong = static_cast<sal_Int64>( nDouble );
1265     return ( nLong );
1266 }
1267 
1268 // -----------------------------------------------------------------------
1269 
1270 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1271                                      MapUnit eInUnit, FieldUnit eOutUnit )
1272 {
1273     return static_cast<sal_Int64>(
1274         nonValueDoubleToValueDouble(
1275             ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) );
1276 }
1277 
1278 // -----------------------------------------------------------------------
1279 
1280 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1281                                      FieldUnit eInUnit, MapUnit eOutUnit )
1282 {
1283     return static_cast<sal_Int64>(
1284         // #150733# cast double to sal_Int64 can throw a
1285         // EXCEPTION_FLT_INVALID_OPERATION on Windows
1286         nonValueDoubleToValueDouble(
1287             ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) );
1288 }
1289 
1290 // -----------------------------------------------------------------------
1291 
1292 double MetricField::ConvertDoubleValue( double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1293                                         FieldUnit eInUnit, FieldUnit eOutUnit )
1294 {
1295     if ( eInUnit != eOutUnit )
1296     {
1297         sal_Int64 nMult = 1, nDiv = 1;
1298 
1299         if ( eInUnit == FUNIT_PERCENT )
1300         {
1301             if ( (mnBaseValue <= 0) || (nValue <= 0) )
1302                 return nValue;
1303             nDiv = 100;
1304             for ( sal_uInt16 i=0; i < nDecDigits; i++ )
1305                 nDiv *= 10;
1306 
1307             nMult = mnBaseValue;
1308         }
1309         else if ( eOutUnit == FUNIT_PERCENT ||
1310                   eOutUnit == FUNIT_CUSTOM ||
1311                   eOutUnit == FUNIT_NONE ||
1312                   eInUnit  == FUNIT_CUSTOM ||
1313                   eInUnit  == FUNIT_NONE )
1314              return nValue;
1315         else
1316         {
1317             if ( eOutUnit == FUNIT_100TH_MM )
1318                 eOutUnit = FUNIT_NONE;
1319             if ( eInUnit == FUNIT_100TH_MM )
1320                 eInUnit = FUNIT_NONE;
1321 
1322             nDiv  = aImplFactor[eInUnit][eOutUnit];
1323             nMult = aImplFactor[eOutUnit][eInUnit];
1324 
1325             DBG_ASSERT( nMult > 0, "illegal *" );
1326             DBG_ASSERT( nDiv  > 0, "illegal /" );
1327         }
1328 
1329         if ( nMult != 1 && nMult > 0 )
1330             nValue *= nMult;
1331         if ( nDiv != 1 && nDiv > 0 )
1332         {
1333             nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2);
1334             nValue /= nDiv;
1335         }
1336     }
1337 
1338     return nValue;
1339 }
1340 
1341 // -----------------------------------------------------------------------
1342 
1343 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1344                                         MapUnit eInUnit, FieldUnit eOutUnit )
1345 {
1346     if ( eOutUnit == FUNIT_PERCENT ||
1347          eOutUnit == FUNIT_CUSTOM ||
1348          eOutUnit == FUNIT_NONE ||
1349          eInUnit == MAP_PIXEL ||
1350          eInUnit == MAP_SYSFONT ||
1351          eInUnit == MAP_APPFONT ||
1352          eInUnit == MAP_RELATIVE )
1353     {
1354         DBG_ERROR( "invalid parameters" );
1355         return nValue;
1356     }
1357 
1358     long nDecDigits = nDigits;
1359     FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1360 
1361     if ( nDecDigits < 0 )
1362     {
1363         while ( nDecDigits )
1364         {
1365             nValue += 5;
1366             nValue /= 10;
1367             nDecDigits++;
1368         }
1369     }
1370     else
1371     {
1372         while ( nDecDigits )
1373         {
1374             nValue *= 10;
1375             nDecDigits--;
1376         }
1377     }
1378 
1379     if ( eFieldUnit != eOutUnit )
1380     {
1381         sal_Int64 nDiv  = aImplFactor[eFieldUnit][eOutUnit];
1382         sal_Int64 nMult = aImplFactor[eOutUnit][eFieldUnit];
1383 
1384         DBG_ASSERT( nMult > 0, "illegal *" );
1385         DBG_ASSERT( nDiv  > 0, "illegal /" );
1386 
1387         if ( nMult != 1 && nMult > 0)
1388             nValue *= nMult;
1389         if ( nDiv != 1 && nDiv > 0 )
1390         {
1391             nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1392             nValue /= nDiv;
1393         }
1394     }
1395     return nValue;
1396 }
1397 
1398 // -----------------------------------------------------------------------
1399 
1400 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1401                                         FieldUnit eInUnit, MapUnit eOutUnit )
1402 {
1403     if ( eInUnit == FUNIT_PERCENT ||
1404          eInUnit == FUNIT_CUSTOM ||
1405          eInUnit == FUNIT_NONE ||
1406          eOutUnit == MAP_PIXEL ||
1407          eOutUnit == MAP_SYSFONT ||
1408          eOutUnit == MAP_APPFONT ||
1409          eOutUnit == MAP_RELATIVE )
1410     {
1411         DBG_ERROR( "invalid parameters" );
1412         return nValue;
1413     }
1414 
1415     long nDecDigits = nDigits;
1416     FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits );
1417 
1418     if ( nDecDigits < 0 )
1419     {
1420         while ( nDecDigits )
1421         {
1422             nValue *= 10;
1423             nDecDigits++;
1424         }
1425     }
1426     else
1427     {
1428         while ( nDecDigits )
1429         {
1430             nValue += 5;
1431             nValue /= 10;
1432             nDecDigits--;
1433         }
1434     }
1435 
1436     if ( eFieldUnit != eInUnit )
1437     {
1438         sal_Int64 nDiv  = aImplFactor[eInUnit][eFieldUnit];
1439         sal_Int64 nMult = aImplFactor[eFieldUnit][eInUnit];
1440 
1441         DBG_ASSERT( nMult > 0, "illegal *" );
1442         DBG_ASSERT( nDiv  > 0, "illegal /" );
1443 
1444         if( nMult != 1 && nMult > 0 )
1445             nValue *= nMult;
1446         if( nDiv != 1 && nDiv > 0 )
1447         {
1448             nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1449             nValue /= nDiv;
1450         }
1451     }
1452     return nValue;
1453 }
1454 
1455 // -----------------------------------------------------------------------
1456 
1457 static sal_Bool ImplMetricGetValue( const XubString& rStr, double& rValue, sal_Int64 nBaseValue,
1458                                 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit )
1459 {
1460     // Zahlenwert holen
1461     if ( !ImplNumericGetValue( rStr, rValue, nDecDigits, rLocaleDataWrapper ) )
1462         return sal_False;
1463 
1464     // Einheit rausfinden
1465     FieldUnit eEntryUnit = ImplMetricGetUnit( rStr );
1466 
1467     // Einheiten umrechnen
1468     rValue = MetricField::ConvertDoubleValue( rValue, nBaseValue, nDecDigits, eEntryUnit, eUnit );
1469 
1470     return sal_True;
1471 }
1472 
1473 // -----------------------------------------------------------------------
1474 
1475 sal_Bool MetricFormatter::ImplMetricReformat( const XubString& rStr, double& rValue, XubString& rOutStr )
1476 {
1477     if ( !ImplMetricGetValue( rStr, rValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1478         return sal_True;
1479     else
1480     {
1481         double nTempVal = rValue;
1482         // caution: precision loss in double cast
1483         if ( nTempVal > GetMax() )
1484             nTempVal = (double)GetMax();
1485         else if ( nTempVal < GetMin())
1486             nTempVal = (double)GetMin();
1487 
1488         if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
1489         {
1490             mnCorrectedValue = (sal_Int64)nTempVal;
1491             if ( !GetErrorHdl().Call( this ) )
1492             {
1493                 mnCorrectedValue = 0;
1494                 return sal_False;
1495             }
1496             else
1497                 mnCorrectedValue = 0;
1498         }
1499 
1500         rOutStr = CreateFieldText( (sal_Int64)nTempVal );
1501         return sal_True;
1502     }
1503 }
1504 
1505 // -----------------------------------------------------------------------
1506 
1507 inline void MetricFormatter::ImplInit()
1508 {
1509     mnBaseValue = 0;
1510     meUnit = MetricField::GetDefaultUnit();
1511     mnType = FORMAT_METRIC;
1512 }
1513 
1514 // -----------------------------------------------------------------------
1515 
1516 MetricFormatter::MetricFormatter()
1517 {
1518     ImplInit();
1519 }
1520 
1521 // -----------------------------------------------------------------------
1522 
1523 void MetricFormatter::ImplLoadRes( const ResId& rResId )
1524 {
1525     NumericFormatter::ImplLoadRes( rResId );
1526 
1527     ResMgr*     pMgr = rResId.GetResMgr();
1528     if( pMgr )
1529     {
1530         sal_uLong       nMask = pMgr->ReadLong();
1531 
1532         if ( METRICFORMATTER_UNIT & nMask )
1533             meUnit = (FieldUnit)pMgr->ReadLong();
1534 
1535         if ( METRICFORMATTER_CUSTOMUNITTEXT & nMask )
1536             maCustomUnitText = pMgr->ReadString();
1537     }
1538 }
1539 
1540 // -----------------------------------------------------------------------
1541 
1542 MetricFormatter::~MetricFormatter()
1543 {
1544 }
1545 
1546 // -----------------------------------------------------------------------
1547 
1548 void MetricFormatter::SetUnit( FieldUnit eNewUnit )
1549 {
1550     if ( eNewUnit == FUNIT_100TH_MM )
1551     {
1552         SetDecimalDigits( GetDecimalDigits() + 2 );
1553         meUnit = FUNIT_MM;
1554     }
1555     else
1556         meUnit = eNewUnit;
1557     ReformatAll();
1558 }
1559 
1560 // -----------------------------------------------------------------------
1561 
1562 void MetricFormatter::SetCustomUnitText( const XubString& rStr )
1563 {
1564     maCustomUnitText = rStr;
1565     ReformatAll();
1566 }
1567 
1568 // -----------------------------------------------------------------------
1569 
1570 void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1571 {
1572     SetUserValue( nNewValue, eInUnit );
1573     mnFieldValue = mnLastValue;
1574 }
1575 
1576 // -----------------------------------------------------------------------
1577 
1578 XubString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const
1579 {
1580     XubString aStr = NumericFormatter::CreateFieldText( nValue );
1581 
1582     if( meUnit == FUNIT_CUSTOM )
1583         aStr += maCustomUnitText;
1584     else
1585         aStr += ImplMetricToString( meUnit );
1586 
1587     return aStr;
1588 }
1589 
1590 // -----------------------------------------------------------------------
1591 
1592 void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1593 {
1594     // Umrechnen auf eingestellte Einheiten
1595     nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit );
1596     NumericFormatter::SetUserValue( nNewValue );
1597 }
1598 
1599 // -----------------------------------------------------------------------
1600 
1601 sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const
1602 {
1603     if ( !GetField() )
1604         return 0;
1605 
1606     double nTempValue;
1607     // caution: precision loss in double cast
1608     if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1609         nTempValue = (double)mnLastValue;
1610 
1611     // caution: precision loss in double cast
1612     if ( nTempValue > mnMax )
1613         nTempValue = (double)mnMax;
1614     else if ( nTempValue < mnMin )
1615         nTempValue = (double)mnMin;
1616 
1617     // Umrechnen auf gewuenschte Einheiten
1618     return MetricField::ConvertValue( (sal_Int64)nTempValue, mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit );
1619 }
1620 
1621 // -----------------------------------------------------------------------
1622 
1623 void MetricFormatter::SetValue( sal_Int64 nValue )
1624 {
1625     // Implementation not inline, because it is a virtual Function
1626     SetValue( nValue, FUNIT_NONE );
1627 }
1628 
1629 // -----------------------------------------------------------------------
1630 
1631 sal_Int64 MetricFormatter::GetValue() const
1632 {
1633     // Implementation not inline, because it is a virtual Function
1634     return GetValue( FUNIT_NONE );
1635 }
1636 
1637 // -----------------------------------------------------------------------
1638 
1639 void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )
1640 {
1641     // Umrechnen auf gewuenschte Einheiten
1642     NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin, mnBaseValue, GetDecimalDigits(),
1643                                                          eInUnit, meUnit ) );
1644 }
1645 
1646 // -----------------------------------------------------------------------
1647 
1648 sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const
1649 {
1650     // Umrechnen auf gewuenschte Einheiten
1651     return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue,
1652                                       GetDecimalDigits(), meUnit, eOutUnit );
1653 }
1654 
1655 // -----------------------------------------------------------------------
1656 
1657 void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit )
1658 {
1659     // Umrechnen auf gewuenschte Einheiten
1660     NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax, mnBaseValue, GetDecimalDigits(),
1661                                                          eInUnit, meUnit ) );
1662 }
1663 
1664 // -----------------------------------------------------------------------
1665 
1666 sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const
1667 {
1668     // Umrechnen auf gewuenschte Einheiten
1669     return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue,
1670                                       GetDecimalDigits(), meUnit, eOutUnit );
1671 }
1672 
1673 // -----------------------------------------------------------------------
1674 
1675 void MetricFormatter::SetBaseValue( sal_Int64 nNewBase, FieldUnit eInUnit )
1676 {
1677     mnBaseValue = MetricField::ConvertValue( nNewBase, mnBaseValue, GetDecimalDigits(),
1678                                              eInUnit, meUnit );
1679 }
1680 
1681 // -----------------------------------------------------------------------
1682 
1683 sal_Int64 MetricFormatter::GetBaseValue( FieldUnit eOutUnit ) const
1684 {
1685     // Umrechnen auf gewuenschte Einheiten
1686     return MetricField::ConvertValue( mnBaseValue, mnBaseValue, GetDecimalDigits(),
1687                                       meUnit, eOutUnit );
1688 }
1689 
1690 // -----------------------------------------------------------------------
1691 
1692 void MetricFormatter::Reformat()
1693 {
1694     if ( !GetField() )
1695         return;
1696 
1697     XubString aText = GetField()->GetText();
1698     if ( meUnit == FUNIT_CUSTOM )
1699         maCurUnitText = ImplMetricGetUnitText( aText );
1700 
1701     XubString aStr;
1702     // caution: precision loss in double cast
1703     double nTemp = (double)mnLastValue;
1704     sal_Bool bOK = ImplMetricReformat( aText, nTemp, aStr );
1705     mnLastValue = (sal_Int64)nTemp;
1706 
1707     if ( !bOK )
1708         return;
1709 
1710     if ( aStr.Len() )
1711     {
1712         ImplSetText( aStr );
1713         if ( meUnit == FUNIT_CUSTOM )
1714             CustomConvert();
1715     }
1716     else
1717         SetValue( mnLastValue );
1718     maCurUnitText.Erase();
1719 }
1720 
1721 // -----------------------------------------------------------------------
1722 
1723 sal_Int64 MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit ) const
1724 {
1725     // Umrechnen auf gewuenschte Einheiten
1726     return MetricField::ConvertValue( mnCorrectedValue, mnBaseValue, GetDecimalDigits(),
1727                                       meUnit, eOutUnit );
1728 }
1729 
1730 // -----------------------------------------------------------------------
1731 
1732 MetricField::MetricField( Window* pParent, WinBits nWinStyle ) :
1733     SpinField( pParent, nWinStyle )
1734 {
1735     SetField( this );
1736     Reformat();
1737 }
1738 
1739 // -----------------------------------------------------------------------
1740 
1741 MetricField::MetricField( Window* pParent, const ResId& rResId ) :
1742     SpinField( WINDOW_METRICFIELD )
1743 {
1744     rResId.SetRT( RSC_METRICFIELD );
1745     WinBits nStyle = ImplInitRes( rResId ) ;
1746     SpinField::ImplInit( pParent, nStyle );
1747     SetField( this );
1748     ImplLoadRes( rResId );
1749 
1750     if ( !(nStyle & WB_HIDE ) )
1751         Show();
1752 }
1753 
1754 // -----------------------------------------------------------------------
1755 
1756 void MetricField::ImplLoadRes( const ResId& rResId )
1757 {
1758     SpinField::ImplLoadRes( rResId );
1759     MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1760 
1761     sal_uLong      nMask = ReadLongRes();
1762 
1763     if ( METRICFIELD_FIRST & nMask )
1764         mnFirst = ReadLongRes();
1765 
1766     if ( METRICFIELD_LAST & nMask )
1767         mnLast = ReadLongRes();
1768 
1769     if ( METRICFIELD_SPINSIZE & nMask )
1770         mnSpinSize = ReadLongRes();
1771 
1772     Reformat();
1773 }
1774 
1775 // -----------------------------------------------------------------------
1776 
1777 MetricField::~MetricField()
1778 {
1779 }
1780 
1781 // -----------------------------------------------------------------------
1782 
1783 void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit )
1784 {
1785     // convert
1786     nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(),
1787                                            eInUnit, meUnit );
1788     mnFirst = nNewFirst;
1789 }
1790 
1791 // -----------------------------------------------------------------------
1792 
1793 sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const
1794 {
1795     // convert
1796     return MetricField::ConvertValue( mnFirst, mnBaseValue, GetDecimalDigits(),
1797                                       meUnit, eOutUnit );
1798 }
1799 
1800 // -----------------------------------------------------------------------
1801 
1802 void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit )
1803 {
1804     // Umrechnen
1805     nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(),
1806                                           eInUnit, meUnit );
1807     mnLast = nNewLast;
1808 }
1809 
1810 // -----------------------------------------------------------------------
1811 
1812 sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const
1813 {
1814     // Umrechnen
1815     return MetricField::ConvertValue( mnLast, mnBaseValue, GetDecimalDigits(),
1816                                       meUnit, eOutUnit );
1817 }
1818 
1819 // -----------------------------------------------------------------------
1820 
1821 long MetricField::PreNotify( NotifyEvent& rNEvt )
1822 {
1823     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1824     {
1825         if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1826             return 1;
1827     }
1828 
1829     return SpinField::PreNotify( rNEvt );
1830 }
1831 
1832 // -----------------------------------------------------------------------
1833 
1834 long MetricField::Notify( NotifyEvent& rNEvt )
1835 {
1836     if ( rNEvt.GetType() == EVENT_GETFOCUS )
1837         MarkToBeReformatted( sal_False );
1838     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1839     {
1840         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1841             Reformat();
1842     }
1843 
1844     return SpinField::Notify( rNEvt );
1845 }
1846 
1847 // -----------------------------------------------------------------------
1848 
1849 void MetricField::DataChanged( const DataChangedEvent& rDCEvt )
1850 {
1851     SpinField::DataChanged( rDCEvt );
1852 
1853     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1854     {
1855         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1856         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1857         if ( IsDefaultLocale() )
1858             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1859         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1860         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1861         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1862         ReformatAll();
1863     }
1864 }
1865 
1866 // -----------------------------------------------------------------------
1867 
1868 void MetricField::Modify()
1869 {
1870     MarkToBeReformatted( sal_True );
1871     SpinField::Modify();
1872 }
1873 
1874 // -----------------------------------------------------------------------
1875 
1876 void MetricField::Up()
1877 {
1878     FieldUp();
1879     SpinField::Up();
1880 }
1881 
1882 // -----------------------------------------------------------------------
1883 
1884 void MetricField::Down()
1885 {
1886     FieldDown();
1887     SpinField::Down();
1888 }
1889 
1890 // -----------------------------------------------------------------------
1891 
1892 void MetricField::First()
1893 {
1894     FieldFirst();
1895     SpinField::First();
1896 }
1897 
1898 // -----------------------------------------------------------------------
1899 
1900 void MetricField::Last()
1901 {
1902     FieldLast();
1903     SpinField::Last();
1904 }
1905 
1906 // -----------------------------------------------------------------------
1907 
1908 void MetricField::CustomConvert()
1909 {
1910     maCustomConvertLink.Call( this );
1911 }
1912 
1913 // -----------------------------------------------------------------------
1914 
1915 MetricBox::MetricBox( Window* pParent, WinBits nWinStyle ) :
1916     ComboBox( pParent, nWinStyle )
1917 {
1918     SetField( this );
1919     Reformat();
1920 }
1921 
1922 // -----------------------------------------------------------------------
1923 
1924 MetricBox::MetricBox( Window* pParent, const ResId& rResId ) :
1925     ComboBox( WINDOW_METRICBOX )
1926 {
1927     rResId.SetRT( RSC_METRICBOX );
1928     WinBits nStyle = ImplInitRes( rResId );
1929     ComboBox::ImplInit( pParent, nStyle );
1930     SetField( this );
1931     Reformat();
1932     ComboBox::ImplLoadRes( rResId );
1933     MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1934 
1935     if ( !(nStyle & WB_HIDE ) )
1936         Show();
1937 }
1938 
1939 // -----------------------------------------------------------------------
1940 
1941 MetricBox::~MetricBox()
1942 {
1943 }
1944 
1945 // -----------------------------------------------------------------------
1946 
1947 long MetricBox::PreNotify( NotifyEvent& rNEvt )
1948 {
1949     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2()  )
1950     {
1951         if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1952             return 1;
1953     }
1954 
1955     return ComboBox::PreNotify( rNEvt );
1956 }
1957 
1958 // -----------------------------------------------------------------------
1959 
1960 long MetricBox::Notify( NotifyEvent& rNEvt )
1961 {
1962     if ( rNEvt.GetType() == EVENT_GETFOCUS )
1963         MarkToBeReformatted( sal_False );
1964     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1965     {
1966         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1967             Reformat();
1968     }
1969 
1970     return ComboBox::Notify( rNEvt );
1971 }
1972 
1973 // -----------------------------------------------------------------------
1974 
1975 void MetricBox::DataChanged( const DataChangedEvent& rDCEvt )
1976 {
1977     ComboBox::DataChanged( rDCEvt );
1978 
1979     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1980     {
1981         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1982         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1983         if ( IsDefaultLocale() )
1984             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1985         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1986         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1987         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1988         ReformatAll();
1989     }
1990 }
1991 
1992 // -----------------------------------------------------------------------
1993 
1994 void MetricBox::Modify()
1995 {
1996     MarkToBeReformatted( sal_True );
1997     ComboBox::Modify();
1998 }
1999 
2000 // -----------------------------------------------------------------------
2001 
2002 void MetricBox::ReformatAll()
2003 {
2004     double nValue;
2005     XubString aStr;
2006     SetUpdateMode( sal_False );
2007     sal_uInt16 nEntryCount = GetEntryCount();
2008     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2009     {
2010         ImplMetricReformat( GetEntry( i ), nValue, aStr );
2011         RemoveEntry( i );
2012         InsertEntry( aStr, i );
2013     }
2014     MetricFormatter::Reformat();
2015     SetUpdateMode( sal_True );
2016 }
2017 
2018 // -----------------------------------------------------------------------
2019 
2020 void MetricBox::CustomConvert()
2021 {
2022     maCustomConvertLink.Call( this );
2023 }
2024 
2025 // -----------------------------------------------------------------------
2026 
2027 void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_uInt16 nPos )
2028 {
2029     // Umrechnen auf eingestellte Einheiten
2030     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2031                                         eInUnit, meUnit );
2032     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
2033 }
2034 
2035 // -----------------------------------------------------------------------
2036 
2037 void MetricBox::RemoveValue( sal_Int64 nValue, FieldUnit eInUnit )
2038 {
2039     // Umrechnen auf eingestellte Einheiten
2040     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2041                                         eInUnit, meUnit );
2042     ComboBox::RemoveEntry( CreateFieldText( nValue ) );
2043 }
2044 
2045 // -----------------------------------------------------------------------
2046 
2047 sal_Int64 MetricBox::GetValue( sal_uInt16 nPos, FieldUnit eOutUnit ) const
2048 {
2049     double nValue = 0;
2050     ImplMetricGetValue( ComboBox::GetEntry( nPos ), nValue, mnBaseValue,
2051                         GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit );
2052 
2053     // Umrechnen auf eingestellte Einheiten
2054     sal_Int64 nRetValue = MetricField::ConvertValue( (sal_Int64)nValue, mnBaseValue, GetDecimalDigits(),
2055                                                      meUnit, eOutUnit );
2056 
2057     return nRetValue;
2058 }
2059 
2060 // -----------------------------------------------------------------------
2061 
2062 sal_uInt16 MetricBox::GetValuePos( sal_Int64 nValue, FieldUnit eInUnit ) const
2063 {
2064     // Umrechnen auf eingestellte Einheiten
2065     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2066                                         eInUnit, meUnit );
2067     return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
2068 }
2069 
2070 // -----------------------------------------------------------------------
2071 
2072 sal_Int64 MetricBox::GetValue( FieldUnit eOutUnit ) const
2073 {
2074     // Implementation not inline, because it is a virtual Function
2075     return MetricFormatter::GetValue( eOutUnit );
2076 }
2077 
2078 // -----------------------------------------------------------------------
2079 
2080 sal_Int64 MetricBox::GetValue() const
2081 {
2082     // Implementation not inline, because it is a virtual Function
2083     return GetValue( FUNIT_NONE );
2084 }
2085 
2086 // -----------------------------------------------------------------------
2087 
2088 static sal_Bool ImplCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
2089                                          sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
2090 {
2091     // Es gibt hier kein sinnvolles StrictFormat, also alle
2092     // Zeichen erlauben
2093     return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper );
2094 }
2095 
2096 // -----------------------------------------------------------------------
2097 
2098 inline sal_Bool ImplCurrencyGetValue( const XubString& rStr, double& rValue,
2099                                   sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper )
2100 {
2101     // Zahlenwert holen
2102     return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, sal_True );
2103 }
2104 
2105 // -----------------------------------------------------------------------
2106 
2107 sal_Bool CurrencyFormatter::ImplCurrencyReformat( const XubString& rStr,
2108                                               XubString& rOutStr )
2109 {
2110     double nValue;
2111     if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), sal_True ) )
2112         return sal_True;
2113     else
2114     {
2115         double nTempVal = nValue;
2116         // caution: precision loss in double cast
2117         if ( nTempVal > GetMax() )
2118             nTempVal = (double)GetMax();
2119         else if ( nTempVal < GetMin())
2120             nTempVal = (double)GetMin();
2121 
2122         if ( GetErrorHdl().IsSet() && (nValue != nTempVal) )
2123         {
2124             mnCorrectedValue = (sal_Int64)nTempVal;
2125             if ( !GetErrorHdl().Call( this ) )
2126             {
2127                 mnCorrectedValue = 0;
2128                 return sal_False;
2129             }
2130             else
2131                 mnCorrectedValue = 0;
2132         }
2133 
2134         rOutStr = CreateFieldText( (long)nTempVal );
2135         return sal_True;
2136     }
2137 }
2138 
2139 // -----------------------------------------------------------------------
2140 
2141 inline void CurrencyFormatter::ImplInit()
2142 {
2143     mnType = FORMAT_CURRENCY;
2144 }
2145 
2146 // -----------------------------------------------------------------------
2147 
2148 CurrencyFormatter::CurrencyFormatter()
2149 {
2150     ImplInit();
2151 }
2152 
2153 // -----------------------------------------------------------------------
2154 
2155 CurrencyFormatter::~CurrencyFormatter()
2156 {
2157 }
2158 
2159 // -----------------------------------------------------------------------
2160 
2161 void CurrencyFormatter::SetCurrencySymbol( const String& rStr )
2162 {
2163     maCurrencySymbol= rStr;
2164     ReformatAll();
2165 }
2166 
2167 // -----------------------------------------------------------------------
2168 
2169 String CurrencyFormatter::GetCurrencySymbol() const
2170 {
2171     return maCurrencySymbol.Len() ? maCurrencySymbol : ImplGetLocaleDataWrapper().getCurrSymbol();
2172 }
2173 
2174 // -----------------------------------------------------------------------
2175 
2176 void CurrencyFormatter::SetValue( sal_Int64 nNewValue )
2177 {
2178     SetUserValue( nNewValue );
2179     mnFieldValue = mnLastValue;
2180     SetEmptyFieldValueData( sal_False );
2181 }
2182 
2183 // -----------------------------------------------------------------------
2184 
2185 XubString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const
2186 {
2187     return ImplGetLocaleDataWrapper().getCurr( nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
2188 }
2189 
2190 // -----------------------------------------------------------------------
2191 
2192 sal_Int64 CurrencyFormatter::GetValue() const
2193 {
2194     if ( !GetField() )
2195         return 0;
2196 
2197     double nTempValue;
2198     if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
2199     {
2200         // caution: precision loss in double cast
2201         if ( nTempValue > mnMax )
2202             nTempValue = (double)mnMax;
2203         else if ( nTempValue < mnMin )
2204             nTempValue = (double)mnMin;
2205         return (sal_Int64)nTempValue;
2206     }
2207     else
2208         return mnLastValue;
2209 }
2210 
2211 // -----------------------------------------------------------------------
2212 
2213 void CurrencyFormatter::Reformat()
2214 {
2215     if ( !GetField() )
2216         return;
2217 
2218     XubString aStr;
2219     sal_Bool bOK = ImplCurrencyReformat( GetField()->GetText(), aStr );
2220     if ( !bOK )
2221         return;
2222 
2223     if ( aStr.Len() )
2224     {
2225         ImplSetText( aStr  );
2226         // caution: precision loss in double cast
2227         double nTemp = (double)mnLastValue;
2228         ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2229         mnLastValue = (sal_Int64)nTemp;
2230     }
2231     else
2232         SetValue( mnLastValue );
2233 }
2234 
2235 // -----------------------------------------------------------------------
2236 
2237 CurrencyField::CurrencyField( Window* pParent, WinBits nWinStyle ) :
2238     SpinField( pParent, nWinStyle )
2239 {
2240     SetField( this );
2241     Reformat();
2242 }
2243 
2244 // -----------------------------------------------------------------------
2245 
2246 CurrencyField::CurrencyField( Window* pParent, const ResId& rResId ) :
2247     SpinField( WINDOW_CURRENCYFIELD )
2248 {
2249     rResId.SetRT( RSC_CURRENCYFIELD );
2250     WinBits nStyle = ImplInitRes( rResId );
2251     SpinField::ImplInit( pParent, nStyle);
2252     SetField( this );
2253     ImplLoadRes( rResId );
2254 
2255     if ( !(nStyle & WB_HIDE ) )
2256         Show();
2257 }
2258 
2259 // -----------------------------------------------------------------------
2260 
2261 void CurrencyField::ImplLoadRes( const ResId& rResId )
2262 {
2263     SpinField::ImplLoadRes( rResId );
2264     CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
2265 
2266     sal_uLong      nMask = ReadLongRes();
2267 
2268     if ( CURRENCYFIELD_FIRST & nMask )
2269         mnFirst = ReadLongRes();
2270 
2271     if ( CURRENCYFIELD_LAST & nMask )
2272         mnLast = ReadLongRes();
2273 
2274     if ( CURRENCYFIELD_SPINSIZE & nMask )
2275         mnSpinSize = ReadLongRes();
2276 
2277     Reformat();
2278 }
2279 
2280 // -----------------------------------------------------------------------
2281 
2282 CurrencyField::~CurrencyField()
2283 {
2284 }
2285 
2286 // -----------------------------------------------------------------------
2287 
2288 long CurrencyField::PreNotify( NotifyEvent& rNEvt )
2289 {
2290     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2291     {
2292         if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2293             return 1;
2294     }
2295 
2296     return SpinField::PreNotify( rNEvt );
2297 }
2298 
2299 // -----------------------------------------------------------------------
2300 
2301 long CurrencyField::Notify( NotifyEvent& rNEvt )
2302 {
2303     if ( rNEvt.GetType() == EVENT_GETFOCUS )
2304         MarkToBeReformatted( sal_False );
2305     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2306     {
2307         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
2308             Reformat();
2309     }
2310 
2311     return SpinField::Notify( rNEvt );
2312 }
2313 
2314 // -----------------------------------------------------------------------
2315 
2316 void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt )
2317 {
2318     SpinField::DataChanged( rDCEvt );
2319 
2320     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2321     {
2322         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2323         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2324         if ( IsDefaultLocale() )
2325             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2326         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2327         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2328         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2329         ReformatAll();
2330     }
2331 }
2332 
2333 // -----------------------------------------------------------------------
2334 
2335 void CurrencyField::Modify()
2336 {
2337     MarkToBeReformatted( sal_True );
2338     SpinField::Modify();
2339 }
2340 
2341 // -----------------------------------------------------------------------
2342 
2343 void CurrencyField::Up()
2344 {
2345     FieldUp();
2346     SpinField::Up();
2347 }
2348 
2349 // -----------------------------------------------------------------------
2350 
2351 void CurrencyField::Down()
2352 {
2353     FieldDown();
2354     SpinField::Down();
2355 }
2356 
2357 // -----------------------------------------------------------------------
2358 
2359 void CurrencyField::First()
2360 {
2361     FieldFirst();
2362     SpinField::First();
2363 }
2364 
2365 // -----------------------------------------------------------------------
2366 
2367 void CurrencyField::Last()
2368 {
2369     FieldLast();
2370     SpinField::Last();
2371 }
2372 
2373 // -----------------------------------------------------------------------
2374 
2375 CurrencyBox::CurrencyBox( Window* pParent, WinBits nWinStyle ) :
2376     ComboBox( pParent, nWinStyle )
2377 {
2378     SetField( this );
2379     Reformat();
2380 }
2381 
2382 // -----------------------------------------------------------------------
2383 
2384 CurrencyBox::CurrencyBox( Window* pParent, const ResId& rResId ) :
2385     ComboBox( WINDOW_CURRENCYBOX )
2386 {
2387     rResId.SetRT( RSC_CURRENCYBOX );
2388     WinBits nStyle = ImplInitRes( rResId );
2389     ComboBox::ImplInit( pParent, nStyle );
2390     CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
2391     SetField( this );
2392     ComboBox::ImplLoadRes( rResId );
2393     Reformat();
2394 
2395     if ( !(nStyle & WB_HIDE ) )
2396         Show();
2397 }
2398 
2399 // -----------------------------------------------------------------------
2400 
2401 CurrencyBox::~CurrencyBox()
2402 {
2403 }
2404 
2405 // -----------------------------------------------------------------------
2406 
2407 long CurrencyBox::PreNotify( NotifyEvent& rNEvt )
2408 {
2409     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2410     {
2411         if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2412             return 1;
2413     }
2414 
2415     return ComboBox::PreNotify( rNEvt );
2416 }
2417 
2418 // -----------------------------------------------------------------------
2419 
2420 long CurrencyBox::Notify( NotifyEvent& rNEvt )
2421 {
2422     if ( rNEvt.GetType() == EVENT_GETFOCUS )
2423         MarkToBeReformatted( sal_False );
2424     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2425     {
2426         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
2427             Reformat();
2428     }
2429 
2430     return ComboBox::Notify( rNEvt );
2431 }
2432 
2433 // -----------------------------------------------------------------------
2434 
2435 void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt )
2436 {
2437     ComboBox::DataChanged( rDCEvt );
2438 
2439     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2440     {
2441         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2442         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2443         if ( IsDefaultLocale() )
2444             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2445         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2446         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2447         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2448         ReformatAll();
2449     }
2450 }
2451 
2452 // -----------------------------------------------------------------------
2453 
2454 void CurrencyBox::Modify()
2455 {
2456     MarkToBeReformatted( sal_True );
2457     ComboBox::Modify();
2458 }
2459 
2460 // -----------------------------------------------------------------------
2461 
2462 void CurrencyBox::ReformatAll()
2463 {
2464     XubString aStr;
2465     SetUpdateMode( sal_False );
2466     sal_uInt16 nEntryCount = GetEntryCount();
2467     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2468     {
2469         ImplCurrencyReformat( GetEntry( i ), aStr );
2470         RemoveEntry( i );
2471         InsertEntry( aStr, i );
2472     }
2473     CurrencyFormatter::Reformat();
2474     SetUpdateMode( sal_True );
2475 }
2476 
2477 // -----------------------------------------------------------------------
2478 
2479 void CurrencyBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos )
2480 {
2481     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
2482 }
2483 
2484 // -----------------------------------------------------------------------
2485 
2486 void CurrencyBox::RemoveValue( sal_Int64 nValue )
2487 {
2488     ComboBox::RemoveEntry( CreateFieldText( nValue ) );
2489 }
2490 
2491 // -----------------------------------------------------------------------
2492 
2493 sal_Int64 CurrencyBox::GetValue( sal_uInt16 nPos ) const
2494 {
2495     double nValue = 0;
2496     ImplCurrencyGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2497     return (sal_Int64)nValue;
2498 }
2499 
2500 // -----------------------------------------------------------------------
2501 
2502 sal_uInt16 CurrencyBox::GetValuePos( sal_Int64 nValue ) const
2503 {
2504     return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
2505 }
2506 
2507 // -----------------------------------------------------------------------
2508 
2509 sal_Int64 CurrencyBox::GetValue() const
2510 {
2511     // Implementation not inline, because it is a virtual Function
2512     return CurrencyFormatter::GetValue();
2513 }
2514