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