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