xref: /AOO41X/main/vcl/source/control/field.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #ifndef _BIGINT_HXX
32 #define _TOOLS_BIGINT
33 #include "tools/bigint.hxx"
34 #endif
35 
36 #include "tools/debug.hxx"
37 
38 #include "tools/rc.h"
39 #include "tools/resary.hxx"
40 
41 #include "vcl/field.hxx"
42 #include "vcl/event.hxx"
43 #include "vcl/svapp.hxx"
44 #include "vcl/unohelp.hxx"
45 
46 #include "svids.hrc"
47 #include "svdata.hxx"
48 
49 #include "i18nutil/unicode.hxx"
50 
51 #include "rtl/math.hxx"
52 
53 
54 #include <unotools/localedatawrapper.hxx>
55 
56 using namespace ::com::sun::star;
57 
58 // -----------------------------------------------------------------------
59 
60 #define FORMAT_NUMERIC       1
61 #define FORMAT_METRIC        2
62 #define FORMAT_CURRENCY      3
63 
64 // -----------------------------------------------------------------------
65 
66 static sal_Int64 ImplPower10( sal_uInt16 n )
67 {
68     sal_uInt16 i;
69     sal_Int64   nValue = 1;
70 
71     for ( i=0; i < n; i++ )
72         nValue *= 10;
73 
74     return nValue;
75 }
76 
77 // -----------------------------------------------------------------------
78 
79 static sal_Bool ImplNumericProcessKeyInput( Edit*, const KeyEvent& rKEvt,
80                                         sal_Bool bStrictFormat, sal_Bool bThousandSep,
81                                         const LocaleDataWrapper& rLocaleDataWrappper )
82 {
83     if ( !bStrictFormat )
84         return sal_False;
85     else
86     {
87         xub_Unicode cChar = rKEvt.GetCharCode();
88         sal_uInt16      nGroup = rKEvt.GetKeyCode().GetGroup();
89 
90         if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
91              (nGroup == KEYGROUP_MISC) ||
92              ((cChar >= '0') && (cChar <= '9')) ||
93              (cChar == rLocaleDataWrappper.getNumDecimalSep() ) ||
94              (bThousandSep && (cChar == rLocaleDataWrappper.getNumThousandSep())) ||
95              (cChar == '-') )
96             return sal_False;
97         else
98             return sal_True;
99     }
100 }
101 
102 // -----------------------------------------------------------------------
103 
104 static sal_Bool ImplNumericGetValue( const XubString& rStr, double& rValue,
105                                  sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrappper,
106                                  sal_Bool bCurrency = sal_False )
107 {
108     XubString   aStr = rStr;
109     XubString   aStr1;
110     XubString   aStr2;
111     sal_Bool        bNegative = sal_False;
112     xub_StrLen  nDecPos;
113     xub_StrLen  i;
114 
115     // Reaktion auf leeren String
116     if ( !rStr.Len() )
117         return sal_False;
118 
119     // Fuehrende und nachfolgende Leerzeichen entfernen
120     aStr.EraseLeadingAndTrailingChars( ' ' );
121 
122     // Position des Dezimalpunktes suchen
123     nDecPos = aStr.Search( rLocaleDataWrappper.getNumDecimalSep() );
124     if ( nDecPos != STRING_NOTFOUND )
125     {
126         aStr1 = aStr.Copy( 0, nDecPos );
127         aStr2 = aStr.Copy( nDecPos+1 );
128     }
129     else
130         aStr1 = aStr;
131 
132     // Negativ ?
133     if ( bCurrency )
134     {
135         if ( (aStr.GetChar( 0 ) == '(') && (aStr.GetChar( aStr.Len()-1 ) == ')') )
136             bNegative = sal_True;
137         if ( !bNegative )
138         {
139             for ( i=0; i < aStr.Len(); i++ )
140             {
141                 if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
142                     break;
143                 else if ( aStr.GetChar( i ) == '-' )
144                 {
145                     bNegative = sal_True;
146                     break;
147                 }
148             }
149         }
150         if ( !bNegative && bCurrency && aStr.Len() )
151         {
152             sal_uInt16 nFormat = rLocaleDataWrappper.getCurrNegativeFormat();
153             if ( (nFormat == 3) || (nFormat == 6)  ||
154                  (nFormat == 7) || (nFormat == 10) )
155             {
156                 for ( i = (xub_StrLen)(aStr.Len()-1); i > 0; i++ )
157                 {
158                     if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
159                         break;
160                     else if ( aStr.GetChar( i ) == '-' )
161                     {
162                         bNegative = sal_True;
163                         break;
164                     }
165                 }
166             }
167         }
168     }
169     else
170     {
171         if ( aStr1.GetChar( 0 ) == '-' )
172             bNegative = sal_True;
173     }
174 
175     // Alle unerwuenschten Zeichen rauswerfen
176     for ( i=0; i < aStr1.Len(); )
177     {
178         if ( (aStr1.GetChar( i ) >= '0') && (aStr1.GetChar( i ) <= '9') )
179             i++;
180         else
181             aStr1.Erase( i, 1 );
182     }
183     for ( i=0; i < aStr2.Len(); )
184     {
185         if ( (aStr2.GetChar( i ) >= '0') && (aStr2.GetChar( i ) <= '9') )
186             i++;
187         else
188             aStr2.Erase( i, 1 );
189     }
190 
191     if ( !aStr1.Len() && !aStr2.Len() )
192         return sal_False;
193 
194     if ( !aStr1.Len() )
195         aStr1.Insert( '0' );
196     if ( bNegative )
197         aStr1.Insert( '-', 0 );
198 
199     // Nachkommateil zurechtstutzen und dabei runden
200     sal_Bool bRound = sal_False;
201     if ( aStr2.Len() > nDecDigits )
202     {
203         if ( aStr2.GetChar( nDecDigits ) >= '5' )
204             bRound = sal_True;
205         aStr2.Erase( nDecDigits );
206     }
207     if ( aStr2.Len() < nDecDigits )
208         aStr2.Expand( nDecDigits, '0' );
209 
210     aStr  = aStr1;
211     aStr += aStr2;
212 
213     // Bereichsueberpruefung
214     double nValue = aStr.ToDouble();
215     if ( bRound )
216     {
217         if ( !bNegative )
218             nValue++;
219         else
220             nValue--;
221     }
222 
223     rValue = nValue;
224 
225     return sal_True;
226 }
227 
228 static void ImplUpdateSeparatorString( String& io_rText,
229                                        const String& rOldDecSep, const String& rNewDecSep,
230                                        const String& rOldThSep, const String& rNewThSep )
231 {
232     rtl::OUStringBuffer aBuf( io_rText.Len() );
233     xub_StrLen nIndexDec = 0, nIndexTh = 0, nIndex = 0;
234 
235     const sal_Unicode* pBuffer = io_rText.GetBuffer();
236     while( nIndex != STRING_NOTFOUND )
237     {
238         nIndexDec = io_rText.Search( rOldDecSep, nIndex );
239         nIndexTh = io_rText.Search( rOldThSep, nIndex );
240         if(   (nIndexTh != STRING_NOTFOUND && nIndexDec != STRING_NOTFOUND && nIndexTh < nIndexDec )
241            || (nIndexTh != STRING_NOTFOUND && nIndexDec == STRING_NOTFOUND)
242            )
243         {
244             aBuf.append( pBuffer + nIndex, nIndexTh - nIndex );
245             aBuf.append( rNewThSep );
246             nIndex = nIndexTh + rOldThSep.Len();
247         }
248         else if( nIndexDec != STRING_NOTFOUND )
249         {
250             aBuf.append( pBuffer + nIndex, nIndexDec - nIndex );
251             aBuf.append( rNewDecSep );
252             nIndex = nIndexDec + rOldDecSep.Len();
253         }
254         else
255         {
256             aBuf.append( pBuffer + nIndex );
257             nIndex = STRING_NOTFOUND;
258         }
259     }
260 
261     io_rText = aBuf.makeStringAndClear();
262 }
263 
264 static void ImplUpdateSeparators( const String& rOldDecSep, const String& rNewDecSep,
265                                   const String& rOldThSep, const String& rNewThSep,
266                                   Edit* pEdit )
267 {
268     bool bChangeDec = (rOldDecSep != rNewDecSep);
269     bool bChangeTh = (rOldThSep != rNewThSep );
270 
271     if( bChangeDec || bChangeTh )
272     {
273         sal_Bool bUpdateMode = pEdit->IsUpdateMode();
274         pEdit->SetUpdateMode( sal_False );
275         String aText = pEdit->GetText();
276         ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
277         pEdit->SetText( aText );
278 
279         ComboBox* pCombo = dynamic_cast<ComboBox*>(pEdit);
280         if( pCombo )
281         {
282             // update box entries
283             sal_uInt16 nEntryCount = pCombo->GetEntryCount();
284             for ( sal_uInt16 i=0; i < nEntryCount; i++ )
285             {
286                 aText = pCombo->GetEntry( i );
287                 void* pEntryData = pCombo->GetEntryData( i );
288                 ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
289                 pCombo->RemoveEntry( i );
290                 pCombo->InsertEntry( aText, i );
291                 pCombo->SetEntryData( i, pEntryData );
292             }
293         }
294         if( bUpdateMode )
295             pEdit->SetUpdateMode( bUpdateMode );
296     }
297 }
298 
299 // -----------------------------------------------------------------------
300 
301 FormatterBase::FormatterBase( Edit* pField )
302 {
303     mpField                     = pField;
304     mpLocaleDataWrapper         = NULL;
305     mbReformat                  = sal_False;
306     mbStrictFormat              = sal_False;
307     mbEmptyFieldValue           = sal_False;
308     mbEmptyFieldValueEnabled    = sal_False;
309     mbDefaultLocale             = sal_True;
310 }
311 
312 // -----------------------------------------------------------------------
313 
314 FormatterBase::~FormatterBase()
315 {
316     delete mpLocaleDataWrapper;
317 }
318 
319 // -----------------------------------------------------------------------
320 
321 LocaleDataWrapper& FormatterBase::ImplGetLocaleDataWrapper() const
322 {
323     if ( !mpLocaleDataWrapper )
324     {
325         ((FormatterBase*)this)->mpLocaleDataWrapper = new LocaleDataWrapper( vcl::unohelper::GetMultiServiceFactory(), GetLocale() );
326     }
327     return *mpLocaleDataWrapper;
328 }
329 
330 const LocaleDataWrapper& FormatterBase::GetLocaleDataWrapper() const
331 {
332     return ImplGetLocaleDataWrapper();
333 }
334 
335 // -----------------------------------------------------------------------
336 
337 void FormatterBase::Reformat()
338 {
339 }
340 
341 // -----------------------------------------------------------------------
342 
343 void FormatterBase::ReformatAll()
344 {
345     Reformat();
346 };
347 
348 // -----------------------------------------------------------------------
349 
350 void FormatterBase::SetStrictFormat( sal_Bool bStrict )
351 {
352     if ( bStrict != mbStrictFormat )
353     {
354         mbStrictFormat = bStrict;
355         if ( mbStrictFormat )
356             ReformatAll();
357     }
358 }
359 
360 // -----------------------------------------------------------------------
361 
362 void FormatterBase::SetLocale( const lang::Locale& rLocale )
363 {
364     ImplGetLocaleDataWrapper().setLocale( rLocale );
365     mbDefaultLocale = sal_False;
366     ReformatAll();
367 }
368 
369 // -----------------------------------------------------------------------
370 
371 const lang::Locale& FormatterBase::GetLocale() const
372 {
373     if ( !mpLocaleDataWrapper || mbDefaultLocale )
374     {
375         if ( mpField )
376             return mpField->GetSettings().GetLocale();
377         else
378             return Application::GetSettings().GetLocale();
379     }
380 
381     return mpLocaleDataWrapper->getLocale();
382 }
383 
384 // -----------------------------------------------------------------------
385 
386 const AllSettings& FormatterBase::GetFieldSettings() const
387 {
388     if ( mpField )
389         return mpField->GetSettings();
390     else
391         return Application::GetSettings();
392 }
393 
394 // -----------------------------------------------------------------------
395 
396 void FormatterBase::SetFieldText( const XubString& rText, sal_Bool bKeepSelection )
397 {
398     if ( mpField )
399     {
400         Selection aNewSelection( 0xFFFF, 0xFFFF );
401         if ( bKeepSelection )
402             aNewSelection = mpField->GetSelection();
403 
404         ImplSetText( rText, &aNewSelection );
405     }
406 }
407 
408 // -----------------------------------------------------------------------
409 
410 void FormatterBase::ImplSetText( const XubString& rText, Selection* pNewSelection )
411 {
412     if ( mpField )
413     {
414         if ( pNewSelection )
415             mpField->SetText( rText, *pNewSelection );
416         else
417         {
418             Selection aSel = mpField->GetSelection();
419             aSel.Min() = aSel.Max();
420             mpField->SetText( rText, aSel );
421         }
422 
423         MarkToBeReformatted( sal_False );
424     }
425 }
426 
427 // -----------------------------------------------------------------------
428 
429 void FormatterBase::SetEmptyFieldValue()
430 {
431     if ( mpField )
432         mpField->SetText( ImplGetSVEmptyStr() );
433     mbEmptyFieldValue = sal_True;
434 }
435 
436 // -----------------------------------------------------------------------
437 
438 sal_Bool FormatterBase::IsEmptyFieldValue() const
439 {
440     return (!mpField || !mpField->GetText().Len());
441 }
442 
443 // -----------------------------------------------------------------------
444 
445 sal_Bool NumericFormatter::ImplNumericReformat( const XubString& rStr, double& rValue,
446                                             XubString& rOutStr )
447 {
448     if ( !ImplNumericGetValue( rStr, rValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
449         return sal_True;
450     else
451     {
452         double nTempVal = rValue;
453         // caution: precision loss in double cast
454         if ( nTempVal > mnMax )
455             nTempVal = (double)mnMax;
456         else if ( nTempVal < mnMin )
457             nTempVal = (double)mnMin;
458 
459         if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
460         {
461             mnCorrectedValue = (sal_Int64)nTempVal;
462             if ( !GetErrorHdl().Call( this ) )
463             {
464                 mnCorrectedValue = 0;
465                 return sal_False;
466             }
467             else
468                 mnCorrectedValue = 0;
469         }
470 
471         rOutStr = CreateFieldText( (sal_Int64)nTempVal );
472         return sal_True;
473     }
474 }
475 
476 // -----------------------------------------------------------------------
477 
478 void NumericFormatter::ImplInit()
479 {
480     mnFieldValue        = 0;
481     mnLastValue         = 0;
482     mnMin               = 0;
483     mnMax               = 0x7FFFFFFFFFFFFFFFLL;
484     mnCorrectedValue    = 0;
485     mnDecimalDigits     = 2;
486     mnType              = FORMAT_NUMERIC;
487     mbThousandSep       = sal_True;
488     mbShowTrailingZeros = sal_True;
489 
490     // for fields
491     mnSpinSize          = 1;
492     mnFirst             = mnMin;
493     mnLast              = mnMax;
494 
495     SetDecimalDigits( 0 );
496 }
497 
498 // -----------------------------------------------------------------------
499 
500 NumericFormatter::NumericFormatter()
501 {
502     ImplInit();
503 }
504 
505 // -----------------------------------------------------------------------
506 
507 void NumericFormatter::ImplLoadRes( const ResId& rResId )
508 {
509     ResMgr*     pMgr = rResId.GetResMgr();
510 
511     if( pMgr )
512     {
513         sal_uLong nMask = pMgr->ReadLong();
514 
515         if ( NUMERICFORMATTER_MIN & nMask )
516             mnMin = pMgr->ReadLong();
517 
518         if ( NUMERICFORMATTER_MAX & nMask )
519             mnMax = pMgr->ReadLong();
520 
521         if ( NUMERICFORMATTER_STRICTFORMAT & nMask )
522             SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
523 
524         if ( NUMERICFORMATTER_DECIMALDIGITS & nMask )
525             SetDecimalDigits( pMgr->ReadShort() );
526 
527         if ( NUMERICFORMATTER_VALUE & nMask )
528         {
529             mnFieldValue = pMgr->ReadLong();
530             if ( mnFieldValue > mnMax )
531                 mnFieldValue = mnMax;
532             else if ( mnFieldValue < mnMin )
533                 mnFieldValue = mnMin;
534             mnLastValue = mnFieldValue;
535         }
536 
537         if ( NUMERICFORMATTER_NOTHOUSANDSEP & nMask )
538             SetUseThousandSep( !(sal_Bool)pMgr->ReadShort() );
539     }
540 }
541 
542 // -----------------------------------------------------------------------
543 
544 NumericFormatter::~NumericFormatter()
545 {
546 }
547 
548 // -----------------------------------------------------------------------
549 
550 void NumericFormatter::SetMin( sal_Int64 nNewMin )
551 {
552     mnMin = nNewMin;
553     if ( !IsEmptyFieldValue() )
554         ReformatAll();
555 }
556 
557 // -----------------------------------------------------------------------
558 
559 void NumericFormatter::SetMax( sal_Int64 nNewMax )
560 {
561     mnMax = nNewMax;
562     if ( !IsEmptyFieldValue() )
563         ReformatAll();
564 }
565 
566 // -----------------------------------------------------------------------
567 
568 void NumericFormatter::SetUseThousandSep( sal_Bool b )
569 {
570     mbThousandSep = b;
571     ReformatAll();
572 }
573 
574 // -----------------------------------------------------------------------
575 
576 void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits )
577 {
578     mnDecimalDigits = nDigits;
579     ReformatAll();
580 }
581 
582 // -----------------------------------------------------------------------
583 
584 void NumericFormatter::SetShowTrailingZeros( sal_Bool bShowTrailingZeros )
585 {
586     if ( mbShowTrailingZeros != bShowTrailingZeros )
587     {
588         mbShowTrailingZeros = bShowTrailingZeros;
589         ReformatAll();
590     }
591 }
592 
593 // -----------------------------------------------------------------------
594 
595 sal_uInt16 NumericFormatter::GetDecimalDigits() const
596 {
597     return mnDecimalDigits;
598 }
599 
600 // -----------------------------------------------------------------------
601 
602 void NumericFormatter::SetValue( sal_Int64 nNewValue )
603 {
604     SetUserValue( nNewValue );
605     mnFieldValue = mnLastValue;
606     SetEmptyFieldValueData( sal_False );
607 }
608 
609 // -----------------------------------------------------------------------
610 
611 XubString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const
612 {
613     return ImplGetLocaleDataWrapper().getNum( nValue, GetDecimalDigits(), IsUseThousandSep(), IsShowTrailingZeros() );
614 }
615 
616 // -----------------------------------------------------------------------
617 
618 void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection* pNewSelection )
619 {
620     if ( nNewValue > mnMax )
621         nNewValue = mnMax;
622     else if ( nNewValue < mnMin )
623         nNewValue = mnMin;
624     mnLastValue = nNewValue;
625 
626     if ( GetField() )
627         ImplSetText( CreateFieldText( nNewValue ), pNewSelection );
628 }
629 
630 // -----------------------------------------------------------------------
631 
632 void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
633 {
634     ImplSetUserValue( nNewValue );
635 }
636 
637 // -----------------------------------------------------------------------
638 
639 sal_Int64 NumericFormatter::GetValue() const
640 {
641     if ( !GetField() )
642         return 0;
643 
644     double nTempValue;
645 
646     if ( ImplNumericGetValue( GetField()->GetText(), nTempValue,
647                               GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
648     {
649         // caution: precision loss in double cast
650         if ( nTempValue > mnMax )
651             nTempValue = (double)mnMax;
652         else if ( nTempValue < mnMin )
653             nTempValue = (double)mnMin;
654         return (sal_Int64)nTempValue;
655     }
656     else
657         return mnLastValue;
658 }
659 
660 // -----------------------------------------------------------------------
661 
662 sal_Bool NumericFormatter::IsValueModified() const
663 {
664     if ( ImplGetEmptyFieldValue() )
665         return !IsEmptyFieldValue();
666     else if ( GetValue() != mnFieldValue )
667         return sal_True;
668     else
669         return sal_False;
670 }
671 
672 // -----------------------------------------------------------------------
673 
674 Fraction NumericFormatter::ConvertToFraction( sal_Int64 nValue )
675 {
676     // caution: precision loss in double cast (and in fraction anyhow)
677     return Fraction( (double)nValue/(double)ImplPower10( GetDecimalDigits() ) );
678 }
679 
680 // -----------------------------------------------------------------------
681 
682 sal_Int64 NumericFormatter::ConvertToLong( const Fraction& rValue )
683 {
684     Fraction aFract = rValue;
685     aFract *= Fraction( (long)ImplPower10( GetDecimalDigits() ), 1 );
686     return (sal_Int64)(double)aFract;
687 }
688 
689 // -----------------------------------------------------------------------
690 
691 sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const
692 {
693     return (nValue * ImplPower10( GetDecimalDigits() ) );
694 }
695 
696 // -----------------------------------------------------------------------
697 
698 sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const
699 {
700     sal_Int64 nFactor = ImplPower10( GetDecimalDigits() );
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     // caution: precision loss in double cast
1255     return static_cast<sal_Int64>(
1256         // #150733# cast double to sal_Int64 can throw a
1257         // EXCEPTION_FLT_INVALID_OPERATION on Windows
1258         nonValueDoubleToValueDouble(
1259             ConvertDoubleValue( (double)nValue, mnBaseValue, nDecDigits,
1260                                 eInUnit, eOutUnit ) ) );
1261 }
1262 
1263 // -----------------------------------------------------------------------
1264 
1265 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1266                                      MapUnit eInUnit, FieldUnit eOutUnit )
1267 {
1268     return static_cast<sal_Int64>(
1269         // #150733# cast double to sal_Int64 can throw a
1270         // EXCEPTION_FLT_INVALID_OPERATION on Windows
1271         nonValueDoubleToValueDouble(
1272             ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) );
1273 }
1274 
1275 // -----------------------------------------------------------------------
1276 
1277 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1278                                      FieldUnit eInUnit, MapUnit eOutUnit )
1279 {
1280     return static_cast<sal_Int64>(
1281         // #150733# cast double to sal_Int64 can throw a
1282         // EXCEPTION_FLT_INVALID_OPERATION on Windows
1283         nonValueDoubleToValueDouble(
1284             ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) );
1285 }
1286 
1287 // -----------------------------------------------------------------------
1288 
1289 double MetricField::ConvertDoubleValue( double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1290                                         FieldUnit eInUnit, FieldUnit eOutUnit )
1291 {
1292     if ( eInUnit != eOutUnit )
1293     {
1294         sal_Int64 nMult = 1, nDiv = 1;
1295 
1296         if ( eInUnit == FUNIT_PERCENT )
1297         {
1298             if ( (mnBaseValue <= 0) || (nValue <= 0) )
1299                 return nValue;
1300             nDiv = 100;
1301             for ( sal_uInt16 i=0; i < nDecDigits; i++ )
1302                 nDiv *= 10;
1303 
1304             nMult = mnBaseValue;
1305         }
1306         else if ( eOutUnit == FUNIT_PERCENT ||
1307                   eOutUnit == FUNIT_CUSTOM ||
1308                   eOutUnit == FUNIT_NONE ||
1309                   eInUnit  == FUNIT_CUSTOM ||
1310                   eInUnit  == FUNIT_NONE )
1311              return nValue;
1312         else
1313         {
1314             if ( eOutUnit == FUNIT_100TH_MM )
1315                 eOutUnit = FUNIT_NONE;
1316             if ( eInUnit == FUNIT_100TH_MM )
1317                 eInUnit = FUNIT_NONE;
1318 
1319             nDiv  = aImplFactor[eInUnit][eOutUnit];
1320             nMult = aImplFactor[eOutUnit][eInUnit];
1321 
1322             DBG_ASSERT( nMult > 0, "illegal *" );
1323             DBG_ASSERT( nDiv  > 0, "illegal /" );
1324         }
1325 
1326         if ( nMult != 1 && nMult > 0 )
1327             nValue *= nMult;
1328         if ( nDiv != 1 && nDiv > 0 )
1329         {
1330             nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2);
1331             nValue /= nDiv;
1332         }
1333     }
1334 
1335     return nValue;
1336 }
1337 
1338 // -----------------------------------------------------------------------
1339 
1340 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1341                                         MapUnit eInUnit, FieldUnit eOutUnit )
1342 {
1343     if ( eOutUnit == FUNIT_PERCENT ||
1344          eOutUnit == FUNIT_CUSTOM ||
1345          eOutUnit == FUNIT_NONE ||
1346          eInUnit == MAP_PIXEL ||
1347          eInUnit == MAP_SYSFONT ||
1348          eInUnit == MAP_APPFONT ||
1349          eInUnit == MAP_RELATIVE )
1350     {
1351         DBG_ERROR( "invalid parameters" );
1352         return nValue;
1353     }
1354 
1355     long nDecDigits = nDigits;
1356     FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1357 
1358     if ( nDecDigits < 0 )
1359     {
1360         while ( nDecDigits )
1361         {
1362             nValue += 5;
1363             nValue /= 10;
1364             nDecDigits++;
1365         }
1366     }
1367     else
1368     {
1369         while ( nDecDigits )
1370         {
1371             nValue *= 10;
1372             nDecDigits--;
1373         }
1374     }
1375 
1376     if ( eFieldUnit != eOutUnit )
1377     {
1378         sal_Int64 nDiv  = aImplFactor[eFieldUnit][eOutUnit];
1379         sal_Int64 nMult = aImplFactor[eOutUnit][eFieldUnit];
1380 
1381         DBG_ASSERT( nMult > 0, "illegal *" );
1382         DBG_ASSERT( nDiv  > 0, "illegal /" );
1383 
1384         if ( nMult != 1 && nMult > 0)
1385             nValue *= nMult;
1386         if ( nDiv != 1 && nDiv > 0 )
1387         {
1388             nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1389             nValue /= nDiv;
1390         }
1391     }
1392     return nValue;
1393 }
1394 
1395 // -----------------------------------------------------------------------
1396 
1397 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1398                                         FieldUnit eInUnit, MapUnit eOutUnit )
1399 {
1400     if ( eInUnit == FUNIT_PERCENT ||
1401          eInUnit == FUNIT_CUSTOM ||
1402          eInUnit == FUNIT_NONE ||
1403          eOutUnit == MAP_PIXEL ||
1404          eOutUnit == MAP_SYSFONT ||
1405          eOutUnit == MAP_APPFONT ||
1406          eOutUnit == MAP_RELATIVE )
1407     {
1408         DBG_ERROR( "invalid parameters" );
1409         return nValue;
1410     }
1411 
1412     long nDecDigits = nDigits;
1413     FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits );
1414 
1415     if ( nDecDigits < 0 )
1416     {
1417         while ( nDecDigits )
1418         {
1419             nValue *= 10;
1420             nDecDigits++;
1421         }
1422     }
1423     else
1424     {
1425         while ( nDecDigits )
1426         {
1427             nValue += 5;
1428             nValue /= 10;
1429             nDecDigits--;
1430         }
1431     }
1432 
1433     if ( eFieldUnit != eInUnit )
1434     {
1435         sal_Int64 nDiv  = aImplFactor[eInUnit][eFieldUnit];
1436         sal_Int64 nMult = aImplFactor[eFieldUnit][eInUnit];
1437 
1438         DBG_ASSERT( nMult > 0, "illegal *" );
1439         DBG_ASSERT( nDiv  > 0, "illegal /" );
1440 
1441         if( nMult != 1 && nMult > 0 )
1442             nValue *= nMult;
1443         if( nDiv != 1 && nDiv > 0 )
1444         {
1445             nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1446             nValue /= nDiv;
1447         }
1448     }
1449     return nValue;
1450 }
1451 
1452 // -----------------------------------------------------------------------
1453 
1454 static sal_Bool ImplMetricGetValue( const XubString& rStr, double& rValue, sal_Int64 nBaseValue,
1455                                 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit )
1456 {
1457     // Zahlenwert holen
1458     if ( !ImplNumericGetValue( rStr, rValue, nDecDigits, rLocaleDataWrapper ) )
1459         return sal_False;
1460 
1461     // Einheit rausfinden
1462     FieldUnit eEntryUnit = ImplMetricGetUnit( rStr );
1463 
1464     // Einheiten umrechnen
1465     rValue = MetricField::ConvertDoubleValue( rValue, nBaseValue, nDecDigits, eEntryUnit, eUnit );
1466 
1467     return sal_True;
1468 }
1469 
1470 // -----------------------------------------------------------------------
1471 
1472 sal_Bool MetricFormatter::ImplMetricReformat( const XubString& rStr, double& rValue, XubString& rOutStr )
1473 {
1474     if ( !ImplMetricGetValue( rStr, rValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1475         return sal_True;
1476     else
1477     {
1478         double nTempVal = rValue;
1479         // caution: precision loss in double cast
1480         if ( nTempVal > GetMax() )
1481             nTempVal = (double)GetMax();
1482         else if ( nTempVal < GetMin())
1483             nTempVal = (double)GetMin();
1484 
1485         if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
1486         {
1487             mnCorrectedValue = (sal_Int64)nTempVal;
1488             if ( !GetErrorHdl().Call( this ) )
1489             {
1490                 mnCorrectedValue = 0;
1491                 return sal_False;
1492             }
1493             else
1494                 mnCorrectedValue = 0;
1495         }
1496 
1497         rOutStr = CreateFieldText( (sal_Int64)nTempVal );
1498         return sal_True;
1499     }
1500 }
1501 
1502 // -----------------------------------------------------------------------
1503 
1504 inline void MetricFormatter::ImplInit()
1505 {
1506     mnBaseValue = 0;
1507     meUnit = MetricField::GetDefaultUnit();
1508     mnType = FORMAT_METRIC;
1509 }
1510 
1511 // -----------------------------------------------------------------------
1512 
1513 MetricFormatter::MetricFormatter()
1514 {
1515     ImplInit();
1516 }
1517 
1518 // -----------------------------------------------------------------------
1519 
1520 void MetricFormatter::ImplLoadRes( const ResId& rResId )
1521 {
1522     NumericFormatter::ImplLoadRes( rResId );
1523 
1524     ResMgr*     pMgr = rResId.GetResMgr();
1525     if( pMgr )
1526     {
1527         sal_uLong       nMask = pMgr->ReadLong();
1528 
1529         if ( METRICFORMATTER_UNIT & nMask )
1530             meUnit = (FieldUnit)pMgr->ReadLong();
1531 
1532         if ( METRICFORMATTER_CUSTOMUNITTEXT & nMask )
1533             maCustomUnitText = pMgr->ReadString();
1534     }
1535 }
1536 
1537 // -----------------------------------------------------------------------
1538 
1539 MetricFormatter::~MetricFormatter()
1540 {
1541 }
1542 
1543 // -----------------------------------------------------------------------
1544 
1545 void MetricFormatter::SetUnit( FieldUnit eNewUnit )
1546 {
1547     if ( eNewUnit == FUNIT_100TH_MM )
1548     {
1549         SetDecimalDigits( GetDecimalDigits() + 2 );
1550         meUnit = FUNIT_MM;
1551     }
1552     else
1553         meUnit = eNewUnit;
1554     ReformatAll();
1555 }
1556 
1557 // -----------------------------------------------------------------------
1558 
1559 void MetricFormatter::SetCustomUnitText( const XubString& rStr )
1560 {
1561     maCustomUnitText = rStr;
1562     ReformatAll();
1563 }
1564 
1565 // -----------------------------------------------------------------------
1566 
1567 void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1568 {
1569     SetUserValue( nNewValue, eInUnit );
1570     mnFieldValue = mnLastValue;
1571 }
1572 
1573 // -----------------------------------------------------------------------
1574 
1575 XubString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const
1576 {
1577     XubString aStr = NumericFormatter::CreateFieldText( nValue );
1578 
1579     if( meUnit == FUNIT_CUSTOM )
1580         aStr += maCustomUnitText;
1581     else
1582         aStr += ImplMetricToString( meUnit );
1583 
1584     return aStr;
1585 }
1586 
1587 // -----------------------------------------------------------------------
1588 
1589 void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1590 {
1591     // Umrechnen auf eingestellte Einheiten
1592     nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit );
1593     NumericFormatter::SetUserValue( nNewValue );
1594 }
1595 
1596 // -----------------------------------------------------------------------
1597 
1598 sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const
1599 {
1600     if ( !GetField() )
1601         return 0;
1602 
1603     double nTempValue;
1604     // caution: precision loss in double cast
1605     if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1606         nTempValue = (double)mnLastValue;
1607 
1608     // caution: precision loss in double cast
1609     if ( nTempValue > mnMax )
1610         nTempValue = (double)mnMax;
1611     else if ( nTempValue < mnMin )
1612         nTempValue = (double)mnMin;
1613 
1614     // Umrechnen auf gewuenschte Einheiten
1615     return MetricField::ConvertValue( (sal_Int64)nTempValue, mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit );
1616 }
1617 
1618 // -----------------------------------------------------------------------
1619 
1620 void MetricFormatter::SetValue( sal_Int64 nValue )
1621 {
1622     // Implementation not inline, because it is a virtual Function
1623     SetValue( nValue, FUNIT_NONE );
1624 }
1625 
1626 // -----------------------------------------------------------------------
1627 
1628 sal_Int64 MetricFormatter::GetValue() const
1629 {
1630     // Implementation not inline, because it is a virtual Function
1631     return GetValue( FUNIT_NONE );
1632 }
1633 
1634 // -----------------------------------------------------------------------
1635 
1636 void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )
1637 {
1638     // Umrechnen auf gewuenschte Einheiten
1639     NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin, mnBaseValue, GetDecimalDigits(),
1640                                                          eInUnit, meUnit ) );
1641 }
1642 
1643 // -----------------------------------------------------------------------
1644 
1645 sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const
1646 {
1647     // Umrechnen auf gewuenschte Einheiten
1648     return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue,
1649                                       GetDecimalDigits(), meUnit, eOutUnit );
1650 }
1651 
1652 // -----------------------------------------------------------------------
1653 
1654 void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit )
1655 {
1656     // Umrechnen auf gewuenschte Einheiten
1657     NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax, mnBaseValue, GetDecimalDigits(),
1658                                                          eInUnit, meUnit ) );
1659 }
1660 
1661 // -----------------------------------------------------------------------
1662 
1663 sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const
1664 {
1665     // Umrechnen auf gewuenschte Einheiten
1666     return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue,
1667                                       GetDecimalDigits(), meUnit, eOutUnit );
1668 }
1669 
1670 // -----------------------------------------------------------------------
1671 
1672 void MetricFormatter::SetBaseValue( sal_Int64 nNewBase, FieldUnit eInUnit )
1673 {
1674     mnBaseValue = MetricField::ConvertValue( nNewBase, mnBaseValue, GetDecimalDigits(),
1675                                              eInUnit, meUnit );
1676 }
1677 
1678 // -----------------------------------------------------------------------
1679 
1680 sal_Int64 MetricFormatter::GetBaseValue( FieldUnit eOutUnit ) const
1681 {
1682     // Umrechnen auf gewuenschte Einheiten
1683     return MetricField::ConvertValue( mnBaseValue, mnBaseValue, GetDecimalDigits(),
1684                                       meUnit, eOutUnit );
1685 }
1686 
1687 // -----------------------------------------------------------------------
1688 
1689 void MetricFormatter::Reformat()
1690 {
1691     if ( !GetField() )
1692         return;
1693 
1694     XubString aText = GetField()->GetText();
1695     if ( meUnit == FUNIT_CUSTOM )
1696         maCurUnitText = ImplMetricGetUnitText( aText );
1697 
1698     XubString aStr;
1699     // caution: precision loss in double cast
1700     double nTemp = (double)mnLastValue;
1701     sal_Bool bOK = ImplMetricReformat( aText, nTemp, aStr );
1702     mnLastValue = (sal_Int64)nTemp;
1703 
1704     if ( !bOK )
1705         return;
1706 
1707     if ( aStr.Len() )
1708     {
1709         ImplSetText( aStr );
1710         if ( meUnit == FUNIT_CUSTOM )
1711             CustomConvert();
1712     }
1713     else
1714         SetValue( mnLastValue );
1715     maCurUnitText.Erase();
1716 }
1717 
1718 // -----------------------------------------------------------------------
1719 
1720 sal_Int64 MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit ) const
1721 {
1722     // Umrechnen auf gewuenschte Einheiten
1723     return MetricField::ConvertValue( mnCorrectedValue, mnBaseValue, GetDecimalDigits(),
1724                                       meUnit, eOutUnit );
1725 }
1726 
1727 // -----------------------------------------------------------------------
1728 
1729 MetricField::MetricField( Window* pParent, WinBits nWinStyle ) :
1730     SpinField( pParent, nWinStyle )
1731 {
1732     SetField( this );
1733     Reformat();
1734 }
1735 
1736 // -----------------------------------------------------------------------
1737 
1738 MetricField::MetricField( Window* pParent, const ResId& rResId ) :
1739     SpinField( WINDOW_METRICFIELD )
1740 {
1741     rResId.SetRT( RSC_METRICFIELD );
1742     WinBits nStyle = ImplInitRes( rResId ) ;
1743     SpinField::ImplInit( pParent, nStyle );
1744     SetField( this );
1745     ImplLoadRes( rResId );
1746 
1747     if ( !(nStyle & WB_HIDE ) )
1748         Show();
1749 }
1750 
1751 // -----------------------------------------------------------------------
1752 
1753 void MetricField::ImplLoadRes( const ResId& rResId )
1754 {
1755     SpinField::ImplLoadRes( rResId );
1756     MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1757 
1758     sal_uLong      nMask = ReadLongRes();
1759 
1760     if ( METRICFIELD_FIRST & nMask )
1761         mnFirst = ReadLongRes();
1762 
1763     if ( METRICFIELD_LAST & nMask )
1764         mnLast = ReadLongRes();
1765 
1766     if ( METRICFIELD_SPINSIZE & nMask )
1767         mnSpinSize = ReadLongRes();
1768 
1769     Reformat();
1770 }
1771 
1772 // -----------------------------------------------------------------------
1773 
1774 MetricField::~MetricField()
1775 {
1776 }
1777 
1778 // -----------------------------------------------------------------------
1779 
1780 void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit )
1781 {
1782     // convert
1783     nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(),
1784                                            eInUnit, meUnit );
1785     mnFirst = nNewFirst;
1786 }
1787 
1788 // -----------------------------------------------------------------------
1789 
1790 sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const
1791 {
1792     // convert
1793     return MetricField::ConvertValue( mnFirst, mnBaseValue, GetDecimalDigits(),
1794                                       meUnit, eOutUnit );
1795 }
1796 
1797 // -----------------------------------------------------------------------
1798 
1799 void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit )
1800 {
1801     // Umrechnen
1802     nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(),
1803                                           eInUnit, meUnit );
1804     mnLast = nNewLast;
1805 }
1806 
1807 // -----------------------------------------------------------------------
1808 
1809 sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const
1810 {
1811     // Umrechnen
1812     return MetricField::ConvertValue( mnLast, mnBaseValue, GetDecimalDigits(),
1813                                       meUnit, eOutUnit );
1814 }
1815 
1816 // -----------------------------------------------------------------------
1817 
1818 long MetricField::PreNotify( NotifyEvent& rNEvt )
1819 {
1820     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1821     {
1822         if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1823             return 1;
1824     }
1825 
1826     return SpinField::PreNotify( rNEvt );
1827 }
1828 
1829 // -----------------------------------------------------------------------
1830 
1831 long MetricField::Notify( NotifyEvent& rNEvt )
1832 {
1833     if ( rNEvt.GetType() == EVENT_GETFOCUS )
1834         MarkToBeReformatted( sal_False );
1835     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1836     {
1837         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1838             Reformat();
1839     }
1840 
1841     return SpinField::Notify( rNEvt );
1842 }
1843 
1844 // -----------------------------------------------------------------------
1845 
1846 void MetricField::DataChanged( const DataChangedEvent& rDCEvt )
1847 {
1848     SpinField::DataChanged( rDCEvt );
1849 
1850     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1851     {
1852         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1853         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1854         if ( IsDefaultLocale() )
1855             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1856         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1857         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1858         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1859         ReformatAll();
1860     }
1861 }
1862 
1863 // -----------------------------------------------------------------------
1864 
1865 void MetricField::Modify()
1866 {
1867     MarkToBeReformatted( sal_True );
1868     SpinField::Modify();
1869 }
1870 
1871 // -----------------------------------------------------------------------
1872 
1873 void MetricField::Up()
1874 {
1875     FieldUp();
1876     SpinField::Up();
1877 }
1878 
1879 // -----------------------------------------------------------------------
1880 
1881 void MetricField::Down()
1882 {
1883     FieldDown();
1884     SpinField::Down();
1885 }
1886 
1887 // -----------------------------------------------------------------------
1888 
1889 void MetricField::First()
1890 {
1891     FieldFirst();
1892     SpinField::First();
1893 }
1894 
1895 // -----------------------------------------------------------------------
1896 
1897 void MetricField::Last()
1898 {
1899     FieldLast();
1900     SpinField::Last();
1901 }
1902 
1903 // -----------------------------------------------------------------------
1904 
1905 void MetricField::CustomConvert()
1906 {
1907     maCustomConvertLink.Call( this );
1908 }
1909 
1910 // -----------------------------------------------------------------------
1911 
1912 MetricBox::MetricBox( Window* pParent, WinBits nWinStyle ) :
1913     ComboBox( pParent, nWinStyle )
1914 {
1915     SetField( this );
1916     Reformat();
1917 }
1918 
1919 // -----------------------------------------------------------------------
1920 
1921 MetricBox::MetricBox( Window* pParent, const ResId& rResId ) :
1922     ComboBox( WINDOW_METRICBOX )
1923 {
1924     rResId.SetRT( RSC_METRICBOX );
1925     WinBits nStyle = ImplInitRes( rResId );
1926     ComboBox::ImplInit( pParent, nStyle );
1927     SetField( this );
1928     Reformat();
1929     ComboBox::ImplLoadRes( rResId );
1930     MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
1931 
1932     if ( !(nStyle & WB_HIDE ) )
1933         Show();
1934 }
1935 
1936 // -----------------------------------------------------------------------
1937 
1938 MetricBox::~MetricBox()
1939 {
1940 }
1941 
1942 // -----------------------------------------------------------------------
1943 
1944 long MetricBox::PreNotify( NotifyEvent& rNEvt )
1945 {
1946     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2()  )
1947     {
1948         if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1949             return 1;
1950     }
1951 
1952     return ComboBox::PreNotify( rNEvt );
1953 }
1954 
1955 // -----------------------------------------------------------------------
1956 
1957 long MetricBox::Notify( NotifyEvent& rNEvt )
1958 {
1959     if ( rNEvt.GetType() == EVENT_GETFOCUS )
1960         MarkToBeReformatted( sal_False );
1961     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
1962     {
1963         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
1964             Reformat();
1965     }
1966 
1967     return ComboBox::Notify( rNEvt );
1968 }
1969 
1970 // -----------------------------------------------------------------------
1971 
1972 void MetricBox::DataChanged( const DataChangedEvent& rDCEvt )
1973 {
1974     ComboBox::DataChanged( rDCEvt );
1975 
1976     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
1977     {
1978         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1979         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1980         if ( IsDefaultLocale() )
1981             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
1982         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1983         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1984         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1985         ReformatAll();
1986     }
1987 }
1988 
1989 // -----------------------------------------------------------------------
1990 
1991 void MetricBox::Modify()
1992 {
1993     MarkToBeReformatted( sal_True );
1994     ComboBox::Modify();
1995 }
1996 
1997 // -----------------------------------------------------------------------
1998 
1999 void MetricBox::ReformatAll()
2000 {
2001     double nValue;
2002     XubString aStr;
2003     SetUpdateMode( sal_False );
2004     sal_uInt16 nEntryCount = GetEntryCount();
2005     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2006     {
2007         ImplMetricReformat( GetEntry( i ), nValue, aStr );
2008         RemoveEntry( i );
2009         InsertEntry( aStr, i );
2010     }
2011     MetricFormatter::Reformat();
2012     SetUpdateMode( sal_True );
2013 }
2014 
2015 // -----------------------------------------------------------------------
2016 
2017 void MetricBox::CustomConvert()
2018 {
2019     maCustomConvertLink.Call( this );
2020 }
2021 
2022 // -----------------------------------------------------------------------
2023 
2024 void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_uInt16 nPos )
2025 {
2026     // Umrechnen auf eingestellte Einheiten
2027     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2028                                         eInUnit, meUnit );
2029     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
2030 }
2031 
2032 // -----------------------------------------------------------------------
2033 
2034 void MetricBox::RemoveValue( sal_Int64 nValue, FieldUnit eInUnit )
2035 {
2036     // Umrechnen auf eingestellte Einheiten
2037     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2038                                         eInUnit, meUnit );
2039     ComboBox::RemoveEntry( CreateFieldText( nValue ) );
2040 }
2041 
2042 // -----------------------------------------------------------------------
2043 
2044 sal_Int64 MetricBox::GetValue( sal_uInt16 nPos, FieldUnit eOutUnit ) const
2045 {
2046     double nValue = 0;
2047     ImplMetricGetValue( ComboBox::GetEntry( nPos ), nValue, mnBaseValue,
2048                         GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit );
2049 
2050     // Umrechnen auf eingestellte Einheiten
2051     sal_Int64 nRetValue = MetricField::ConvertValue( (sal_Int64)nValue, mnBaseValue, GetDecimalDigits(),
2052                                                      meUnit, eOutUnit );
2053 
2054     return nRetValue;
2055 }
2056 
2057 // -----------------------------------------------------------------------
2058 
2059 sal_uInt16 MetricBox::GetValuePos( sal_Int64 nValue, FieldUnit eInUnit ) const
2060 {
2061     // Umrechnen auf eingestellte Einheiten
2062     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
2063                                         eInUnit, meUnit );
2064     return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
2065 }
2066 
2067 // -----------------------------------------------------------------------
2068 
2069 sal_Int64 MetricBox::GetValue( FieldUnit eOutUnit ) const
2070 {
2071     // Implementation not inline, because it is a virtual Function
2072     return MetricFormatter::GetValue( eOutUnit );
2073 }
2074 
2075 // -----------------------------------------------------------------------
2076 
2077 sal_Int64 MetricBox::GetValue() const
2078 {
2079     // Implementation not inline, because it is a virtual Function
2080     return GetValue( FUNIT_NONE );
2081 }
2082 
2083 // -----------------------------------------------------------------------
2084 
2085 static sal_Bool ImplCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
2086                                          sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
2087 {
2088     // Es gibt hier kein sinnvolles StrictFormat, also alle
2089     // Zeichen erlauben
2090     return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper );
2091 }
2092 
2093 // -----------------------------------------------------------------------
2094 
2095 inline sal_Bool ImplCurrencyGetValue( const XubString& rStr, double& rValue,
2096                                   sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper )
2097 {
2098     // Zahlenwert holen
2099     return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, sal_True );
2100 }
2101 
2102 // -----------------------------------------------------------------------
2103 
2104 sal_Bool CurrencyFormatter::ImplCurrencyReformat( const XubString& rStr,
2105                                               XubString& rOutStr )
2106 {
2107     double nValue;
2108     if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), sal_True ) )
2109         return sal_True;
2110     else
2111     {
2112         double nTempVal = nValue;
2113         // caution: precision loss in double cast
2114         if ( nTempVal > GetMax() )
2115             nTempVal = (double)GetMax();
2116         else if ( nTempVal < GetMin())
2117             nTempVal = (double)GetMin();
2118 
2119         if ( GetErrorHdl().IsSet() && (nValue != nTempVal) )
2120         {
2121             mnCorrectedValue = (sal_Int64)nTempVal;
2122             if ( !GetErrorHdl().Call( this ) )
2123             {
2124                 mnCorrectedValue = 0;
2125                 return sal_False;
2126             }
2127             else
2128                 mnCorrectedValue = 0;
2129         }
2130 
2131         rOutStr = CreateFieldText( (long)nTempVal );
2132         return sal_True;
2133     }
2134 }
2135 
2136 // -----------------------------------------------------------------------
2137 
2138 inline void CurrencyFormatter::ImplInit()
2139 {
2140     mnType = FORMAT_CURRENCY;
2141 }
2142 
2143 // -----------------------------------------------------------------------
2144 
2145 CurrencyFormatter::CurrencyFormatter()
2146 {
2147     ImplInit();
2148 }
2149 
2150 // -----------------------------------------------------------------------
2151 
2152 CurrencyFormatter::~CurrencyFormatter()
2153 {
2154 }
2155 
2156 // -----------------------------------------------------------------------
2157 
2158 void CurrencyFormatter::SetCurrencySymbol( const String& rStr )
2159 {
2160     maCurrencySymbol= rStr;
2161     ReformatAll();
2162 }
2163 
2164 // -----------------------------------------------------------------------
2165 
2166 String CurrencyFormatter::GetCurrencySymbol() const
2167 {
2168     return maCurrencySymbol.Len() ? maCurrencySymbol : ImplGetLocaleDataWrapper().getCurrSymbol();
2169 }
2170 
2171 // -----------------------------------------------------------------------
2172 
2173 void CurrencyFormatter::SetValue( sal_Int64 nNewValue )
2174 {
2175     SetUserValue( nNewValue );
2176     mnFieldValue = mnLastValue;
2177     SetEmptyFieldValueData( sal_False );
2178 }
2179 
2180 // -----------------------------------------------------------------------
2181 
2182 XubString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const
2183 {
2184     return ImplGetLocaleDataWrapper().getCurr( nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
2185 }
2186 
2187 // -----------------------------------------------------------------------
2188 
2189 sal_Int64 CurrencyFormatter::GetValue() const
2190 {
2191     if ( !GetField() )
2192         return 0;
2193 
2194     double nTempValue;
2195     if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
2196     {
2197         // caution: precision loss in double cast
2198         if ( nTempValue > mnMax )
2199             nTempValue = (double)mnMax;
2200         else if ( nTempValue < mnMin )
2201             nTempValue = (double)mnMin;
2202         return (sal_Int64)nTempValue;
2203     }
2204     else
2205         return mnLastValue;
2206 }
2207 
2208 // -----------------------------------------------------------------------
2209 
2210 void CurrencyFormatter::Reformat()
2211 {
2212     if ( !GetField() )
2213         return;
2214 
2215     XubString aStr;
2216     sal_Bool bOK = ImplCurrencyReformat( GetField()->GetText(), aStr );
2217     if ( !bOK )
2218         return;
2219 
2220     if ( aStr.Len() )
2221     {
2222         ImplSetText( aStr  );
2223         // caution: precision loss in double cast
2224         double nTemp = (double)mnLastValue;
2225         ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2226         mnLastValue = (sal_Int64)nTemp;
2227     }
2228     else
2229         SetValue( mnLastValue );
2230 }
2231 
2232 // -----------------------------------------------------------------------
2233 
2234 CurrencyField::CurrencyField( Window* pParent, WinBits nWinStyle ) :
2235     SpinField( pParent, nWinStyle )
2236 {
2237     SetField( this );
2238     Reformat();
2239 }
2240 
2241 // -----------------------------------------------------------------------
2242 
2243 CurrencyField::CurrencyField( Window* pParent, const ResId& rResId ) :
2244     SpinField( WINDOW_CURRENCYFIELD )
2245 {
2246     rResId.SetRT( RSC_CURRENCYFIELD );
2247     WinBits nStyle = ImplInitRes( rResId );
2248     SpinField::ImplInit( pParent, nStyle);
2249     SetField( this );
2250     ImplLoadRes( rResId );
2251 
2252     if ( !(nStyle & WB_HIDE ) )
2253         Show();
2254 }
2255 
2256 // -----------------------------------------------------------------------
2257 
2258 void CurrencyField::ImplLoadRes( const ResId& rResId )
2259 {
2260     SpinField::ImplLoadRes( rResId );
2261     CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
2262 
2263     sal_uLong      nMask = ReadLongRes();
2264 
2265     if ( CURRENCYFIELD_FIRST & nMask )
2266         mnFirst = ReadLongRes();
2267 
2268     if ( CURRENCYFIELD_LAST & nMask )
2269         mnLast = ReadLongRes();
2270 
2271     if ( CURRENCYFIELD_SPINSIZE & nMask )
2272         mnSpinSize = ReadLongRes();
2273 
2274     Reformat();
2275 }
2276 
2277 // -----------------------------------------------------------------------
2278 
2279 CurrencyField::~CurrencyField()
2280 {
2281 }
2282 
2283 // -----------------------------------------------------------------------
2284 
2285 long CurrencyField::PreNotify( NotifyEvent& rNEvt )
2286 {
2287     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2288     {
2289         if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2290             return 1;
2291     }
2292 
2293     return SpinField::PreNotify( rNEvt );
2294 }
2295 
2296 // -----------------------------------------------------------------------
2297 
2298 long CurrencyField::Notify( NotifyEvent& rNEvt )
2299 {
2300     if ( rNEvt.GetType() == EVENT_GETFOCUS )
2301         MarkToBeReformatted( sal_False );
2302     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2303     {
2304         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
2305             Reformat();
2306     }
2307 
2308     return SpinField::Notify( rNEvt );
2309 }
2310 
2311 // -----------------------------------------------------------------------
2312 
2313 void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt )
2314 {
2315     SpinField::DataChanged( rDCEvt );
2316 
2317     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2318     {
2319         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2320         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2321         if ( IsDefaultLocale() )
2322             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2323         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2324         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2325         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2326         ReformatAll();
2327     }
2328 }
2329 
2330 // -----------------------------------------------------------------------
2331 
2332 void CurrencyField::Modify()
2333 {
2334     MarkToBeReformatted( sal_True );
2335     SpinField::Modify();
2336 }
2337 
2338 // -----------------------------------------------------------------------
2339 
2340 void CurrencyField::Up()
2341 {
2342     FieldUp();
2343     SpinField::Up();
2344 }
2345 
2346 // -----------------------------------------------------------------------
2347 
2348 void CurrencyField::Down()
2349 {
2350     FieldDown();
2351     SpinField::Down();
2352 }
2353 
2354 // -----------------------------------------------------------------------
2355 
2356 void CurrencyField::First()
2357 {
2358     FieldFirst();
2359     SpinField::First();
2360 }
2361 
2362 // -----------------------------------------------------------------------
2363 
2364 void CurrencyField::Last()
2365 {
2366     FieldLast();
2367     SpinField::Last();
2368 }
2369 
2370 // -----------------------------------------------------------------------
2371 
2372 CurrencyBox::CurrencyBox( Window* pParent, WinBits nWinStyle ) :
2373     ComboBox( pParent, nWinStyle )
2374 {
2375     SetField( this );
2376     Reformat();
2377 }
2378 
2379 // -----------------------------------------------------------------------
2380 
2381 CurrencyBox::CurrencyBox( Window* pParent, const ResId& rResId ) :
2382     ComboBox( WINDOW_CURRENCYBOX )
2383 {
2384     rResId.SetRT( RSC_CURRENCYBOX );
2385     WinBits nStyle = ImplInitRes( rResId );
2386     ComboBox::ImplInit( pParent, nStyle );
2387     CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
2388     SetField( this );
2389     ComboBox::ImplLoadRes( rResId );
2390     Reformat();
2391 
2392     if ( !(nStyle & WB_HIDE ) )
2393         Show();
2394 }
2395 
2396 // -----------------------------------------------------------------------
2397 
2398 CurrencyBox::~CurrencyBox()
2399 {
2400 }
2401 
2402 // -----------------------------------------------------------------------
2403 
2404 long CurrencyBox::PreNotify( NotifyEvent& rNEvt )
2405 {
2406     if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2407     {
2408         if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2409             return 1;
2410     }
2411 
2412     return ComboBox::PreNotify( rNEvt );
2413 }
2414 
2415 // -----------------------------------------------------------------------
2416 
2417 long CurrencyBox::Notify( NotifyEvent& rNEvt )
2418 {
2419     if ( rNEvt.GetType() == EVENT_GETFOCUS )
2420         MarkToBeReformatted( sal_False );
2421     else if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
2422     {
2423         if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) )
2424             Reformat();
2425     }
2426 
2427     return ComboBox::Notify( rNEvt );
2428 }
2429 
2430 // -----------------------------------------------------------------------
2431 
2432 void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt )
2433 {
2434     ComboBox::DataChanged( rDCEvt );
2435 
2436     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) )
2437     {
2438         String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2439         String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2440         if ( IsDefaultLocale() )
2441             ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() );
2442         String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2443         String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2444         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2445         ReformatAll();
2446     }
2447 }
2448 
2449 // -----------------------------------------------------------------------
2450 
2451 void CurrencyBox::Modify()
2452 {
2453     MarkToBeReformatted( sal_True );
2454     ComboBox::Modify();
2455 }
2456 
2457 // -----------------------------------------------------------------------
2458 
2459 void CurrencyBox::ReformatAll()
2460 {
2461     XubString aStr;
2462     SetUpdateMode( sal_False );
2463     sal_uInt16 nEntryCount = GetEntryCount();
2464     for ( sal_uInt16 i=0; i < nEntryCount; i++ )
2465     {
2466         ImplCurrencyReformat( GetEntry( i ), aStr );
2467         RemoveEntry( i );
2468         InsertEntry( aStr, i );
2469     }
2470     CurrencyFormatter::Reformat();
2471     SetUpdateMode( sal_True );
2472 }
2473 
2474 // -----------------------------------------------------------------------
2475 
2476 void CurrencyBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos )
2477 {
2478     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
2479 }
2480 
2481 // -----------------------------------------------------------------------
2482 
2483 void CurrencyBox::RemoveValue( sal_Int64 nValue )
2484 {
2485     ComboBox::RemoveEntry( CreateFieldText( nValue ) );
2486 }
2487 
2488 // -----------------------------------------------------------------------
2489 
2490 sal_Int64 CurrencyBox::GetValue( sal_uInt16 nPos ) const
2491 {
2492     double nValue = 0;
2493     ImplCurrencyGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2494     return (sal_Int64)nValue;
2495 }
2496 
2497 // -----------------------------------------------------------------------
2498 
2499 sal_uInt16 CurrencyBox::GetValuePos( sal_Int64 nValue ) const
2500 {
2501     return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
2502 }
2503 
2504 // -----------------------------------------------------------------------
2505 
2506 sal_Int64 CurrencyBox::GetValue() const
2507 {
2508     // Implementation not inline, because it is a virtual Function
2509     return CurrencyFormatter::GetValue();
2510 }
2511