Project JEDI - Issue Tracker
Mantis Bugtracker

Viewing Issue Simple Details Jump to Notes ] View Advanced ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0005060 [JEDI VCL] 00 JVCL Components major always 2009-12-21 17:30 2012-09-10 14:15
Reporter SteffenSchm View Status public  
Assigned To obones
Priority normal Resolution fixed  
Status resolved   Product Version 3.39
Summary 0005060: Wrong Display and Return of Float Values by TJvValidateEdit
Description TJvValidateEdit converts Float to String by using the normal Delphi function StrToFloat. This function uses ThousandSeparator and DecimalSeparator loaded from SysUtils by calling:
GetLocalChar(GetThreadLocale,....)

To convert from String to Float TJvValidateEdit calls JvSafeStrToFloat from the JVCL unit JvJCLUtils. This function loads own Chars for ThousandSeparator and DecimalSeparator by calling:
GetLocalChar(LOCALE_SYSTEM_DEFAULT,....)

Not for all but for some of our computers the ThousandSeparator and DecimalSeparator used for Float to String conversion are different from these used for String to Float conversion.

This causes a lot of trouble and makes the component unusable.
Additional Information
I changed the function JvSafeStrToFloat to use the ThousandSeparator and DecimalSeparator from SysUtils. This solves my problem.
Tags No tags attached.
Attached Files zip file icon JvValidateEdit Bug.zip [^] (8,768 bytes) 2010-07-26 18:08
zip file icon Project2.zip [^] (5,152 bytes) 2010-08-20 16:05
jpg file icon Pic1.JPG [^] (22,533 bytes) 2010-08-20 16:05
jpg file icon Pic2.JPG [^] (23,137 bytes) 2010-08-20 16:06

- Relationships
related to 0005385resolvedobones TJvValidateEdit has a bug in DecimalSeparator handling. 
has duplicate 0005774resolvedobones Values by TJvValidateEdit multiplied by 10^NumberOfDecimals 
related to 0005579resolvedobones TJvValidateEdit: Issues with DisplayFormat of dfFloat with DecimalPlaces on x64 PT 

-  Notes
(0017033)
obones (administrator)
2009-12-28 16:42

Do you happen to change the value of ThousandSeparator and DecimalSeparator while the program is running?
(0017044)
SteffenSchm (reporter)
2009-12-29 12:58

No I did not change any of these values while the program is running
(0017460)
obones (administrator)
2010-06-07 13:54

Could you please provide the zipped sources of a sample application showing this?
(0017542)
jkelley (reporter)
2010-07-26 18:12

I can confirm the bug. My PC is a Windows 7 English (U.S.) installation, so GetLocalChar(LOCALE_SYSTEM_DEFAULT,....) returns English (U.S.) settings. I set my per-user locale to Portuguese (Brazil) while testing an internationalization problem for one of our customers, so the LOCALE_USER_DEFAULT and GetThreadLocale return Portuguese (Brazil) settings. (In response to your earlier question, this change was NOT made while the program was running.)

The result is that, as SteffenSchm reported, TJvValidateEdit sometimes tries to use commas and sometimes tries to use decimals. In my sample project, if I assign a value of 500 to JvValidateEdit1->Value, it's formatted as 500,0000, then the comma is discarded because it doesn't match LOCALE_SYSTEM_DEFAULT, so JvValidateEdit1->Value ends up being 5000000,0000.
(0017612)
SteffenSchm (reporter)
2010-08-20 16:18

Please find enclosed the source code of a asmple application. But the error can not be reproduced at any computer.
At one of my two laptops GetLocalChars returns different results depending on which parameters is used (LOCALE_SYSTEM_DEFAULT, GetThreadLocale or GetSystemDefaultLCID. This is shown on Pic1.jpg. By pressung the Button1 in the sample application the values in all JvValidateEdits are read and rewritten by the following code:
JvValidateEdit1.Value:=JvValidateEdit1.Value;
This results in wrong values shown in Pic2.jpg.
This is exactly the reaction described also by jkelley.

I solved the problem for my project by changing the following lines in the function _JvSafeStrToFloat of the unit JvJCLUtils

  FormatSettings.ThousandSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_STHOUSAND, '.');
  FormatSettings.DecimalSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, '.');

by the following:

  FormatSettings.ThousandSeparator:= ThousandSeparator;
  FormatSettings.DecimalSeparator := DecimalSeparator;

This can also be used to fix the problem generally.
(0017820)
obones (administrator)
2010-10-08 16:23

Changing this has other consequences on codes that use JvSafeStrToFloat.
Wouldn't it be cleaner to have always the same function be called, and preferably the JVCL one?
If yes, could you propose the changes here?
(0018568)
obones (administrator)
2011-06-07 17:25

Any news?
(0018642)
cguser (reporter)
2011-06-07 18:13

As I mentioned on 0005579, I didn't touch on _JvSafeStrToFloat.

Instead, just passing the third argument of JvSafeStrToFloatDef as
{$IFDEF RTL220_UP}FormatSettings.{$ENDIF RTL220_UP}DecimalSeparator
did solve it.

That seems the most correct usage of that function.
(0018894)
ThomasC (reporter)
2011-09-16 14:44

JvJCLUtils.pas, line 7013:
{$IFDEF RTL150_UP}
FormatSettings.ThousandSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_STHOUSAND, '.');
  FormatSettings.DecimalSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, '.');
{$ELSE}
FormatSettings.DecimalSeparator := DecimalSeparator;
{$ENDIF RTL150_UP}

The above code will load the default decimal and thousand separators for the current system. If the user changed these settings the conversion will fail. This prevents JvValidateEdit from working correctly.

Proposed fix: replace "LOCALE_SYSTEM_DEFAULT" with "GetThreadLocale" to load the currently used decimal and thousand separators. I tested a number of scenarios and everything worked fine.
(0018960)
obones (administrator)
2011-09-21 14:46

Have you seen this:

http://stackoverflow.com/questions/1767946/getthreadlocale-returns-different-value-than-getuserdefaultlcid [^]

Seems like GetThreadLocale is not such a good idea after all
(0018965)
ThomasC (reporter)
2011-09-21 16:35

We are able to reproduce the Problem on Windows Vista Business 32 and Windows 7 Business 64. The screenshots below show the dialogs used to change these settings.

Steps:
- Change your format settings to "German (Germany)"
  http://1.bp.blogspot.com/-05cWKX7SVUE/Ti7hPCJfI7I/AAAAAAAAAEg/gBcS-u7l3eQ/s1600/Changing+Time+Format+Windows+7.png [^]
- Change your system locale to "English (USA)"
  (http://www.sisulizer.de/_img/codepage-problems/w7-region-and-language-administrative.jpg) [^]

Your DecimalSeparator will now be "," according to Windows. Entering floating point numbers in TJvValidateEdit will now fail. E.g entering "1,23" will be converted into "123,00". Notice how you can enter "," bot not ".".

The underlying problem seems to be that JvValidateEdit uses different methods of obtaining DecimalSeparator.

(1) TJvCustomValidateEdit.IsValidChar in JvValidateEdit.pas uses "{$IFDEF RTL220_UP}FormatSettings.{$ENDIF RTL220_UP}DecimalSeparator".

(2) Several other methods in this unit use JvSafeStrToFloatDef from JvJCLUtils.pas which calls _JvSafeStrToFloat in JvJCLUtils.pas. Ultimately "GetLocaleChar(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, '.')" is called.

(1) always returned the correct value in our tests. In the above scenario "," is returned which corresponds the chosen format setting "German (Germany)".
(2) seems to return values corresponding to chosen system locale. In the above scenario this is "." for "English (USA)".

Obviously both can't be right at the same time. Windows seems to give precedence to format settings which are per user settings. (2) can be changed to return these user settings rather than the system settings.

Proposed fix: replace "LOCALE_SYSTEM_DEFAULT" with "LOCALE_USER_DEFAULT" in JvJCLUtils.pas (lines 7014 and 7015). This also avoids using "GetThreadLocale" which seems to have problems of its own.
(0018967)
ThomasC (reporter)
2011-09-21 16:39

Sorry, the parenthesis broke the second link. Here is a working link:
http://www.sisulizer.de/_img/codepage-problems/w7-region-and-language-administrative.jpg [^]
(0018971)
obones (administrator)
2011-09-22 11:34

Fair enough, thanks for the pointers
(0019319)
ArnoBrinkman (reporter)
2012-01-19 16:07

Please change in JvJCLUtils the function _JvSafeStrToFloat() the next lines

-----------------------------------------------------------------------
  { Locale Handling logic October 2008 supercedes former StrToFloatUS functionality. }
  {$IFDEF RTL150_UP}
  LocalFormatSettings.ThousandSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_STHOUSAND, '.');
  LocalFormatSettings.DecimalSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, '.');
  {$ELSE}
-----------------------------------------------------------------------

to these lines:

-----------------------------------------------------------------------
  { Locale Handling logic October 2008 supercedes former StrToFloatUS functionality. }
  {$IFDEF RTL150_UP}
  LocalFormatSettings.ThousandSeparator := GetLocaleChar(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, '.');
  LocalFormatSettings.DecimalSeparator := GetLocaleChar(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, '.');
  {$ELSE}
-----------------------------------------------------------------------


This fucking bug caused us a headache and lot of time, because in our application the values were multiplied by 10^x (where x = number of decimals) everywhere the TJvValidateEdit is used. You can image which dramatic effects this has :(

Mainly on Terminal Systems we see this, because the DecimalSeparator in LOCALE_SYSTEM_DEFAULT is totally different from the LOCALE_USER_DEFAULT one.
(0019320)
cguser (reporter)
2012-01-19 16:32

Arno,

I've come with a different fix that didn't touched JvJCLUtils, just check case 0005579.
(0019321)
ArnoBrinkman (reporter)
2012-01-19 17:29

@cguser,

I see your fix more as a workaround, i think the JvSafeStrToFloat() should behave correctly for the users regional settings.
Probably this function is also used by other components/functions and will fail therefor also.
(0019322)
cguser (reporter)
2012-01-19 17:43

Arno,

Likely so. I do not have the details fresh on my memory anymore, so I won't comment on the technical details. It does puzzle me, however, that for such a serious (and visible) issue, no clean solution has been applied after this long.

I still need to mind to manually patch this each and every time Jedi components are updated. Every now and then, some coleague gets bitten by this.
(0019323)
ArnoBrinkman (reporter)
2012-01-19 18:26

I see indeed this issue is hurting many people already since 2009/2010.
We upgraded recently to latest version, because we slowly start migrating everything to Delphi XE2. While we were using a very old version we were not bitten by it earlier.

HOW CAN IT BE THIS BUG IS STILL ALIVE??

Please, somebody with commit rights fix this.
(0019324)
SteffenSchm (reporter)
2012-01-19 18:35

I started this topic in 2009 and solved the problem for my application by the fix descriped 2010-08-10.

I am not a advanced programmer and do not understand in common why the jvl needs to read the chars for Decimal and ThousandSeparator again. Why not using the constants already defined by Delphi?
(0019528)
obones (administrator)
2012-02-24 11:56

This is now fixed in SVN

- Issue History
Date Modified Username Field Change
2009-12-21 17:30 SteffenSchm New Issue
2009-12-28 16:42 obones Note Added: 0017033
2009-12-28 16:42 obones Status new => feedback
2009-12-29 12:58 SteffenSchm Note Added: 0017044
2010-01-05 07:57 SteffenSchm Issue Monitored: SteffenSchm
2010-01-05 07:58 SteffenSchm Issue End Monitor: SteffenSchm
2010-06-07 13:54 obones Note Added: 0017460
2010-07-26 18:08 jkelley File Added: JvValidateEdit Bug.zip
2010-07-26 18:12 jkelley Note Added: 0017542
2010-08-20 16:05 SteffenSchm File Added: Project2.zip
2010-08-20 16:05 SteffenSchm File Added: Pic1.JPG
2010-08-20 16:06 SteffenSchm File Added: Pic2.JPG
2010-08-20 16:18 SteffenSchm Note Added: 0017612
2010-10-08 16:23 obones Note Added: 0017820
2011-06-07 17:25 obones Note Added: 0018568
2011-06-07 18:01 obones Relationship added related to 0005579
2011-06-07 18:01 obones Relationship added related to 0005385
2011-06-07 18:13 cguser Note Added: 0018642
2011-09-16 14:44 ThomasC Note Added: 0018894
2011-09-16 14:47 ThomasC Issue Monitored: ThomasC
2011-09-21 14:46 obones Note Added: 0018960
2011-09-21 16:35 ThomasC Note Added: 0018965
2011-09-21 16:39 ThomasC Note Added: 0018967
2011-09-22 11:34 obones Note Added: 0018971
2011-09-22 11:34 obones Status feedback => acknowledged
2012-01-19 16:07 ArnoBrinkman Note Added: 0019319
2012-01-19 16:32 cguser Note Added: 0019320
2012-01-19 17:29 ArnoBrinkman Note Added: 0019321
2012-01-19 17:43 cguser Note Added: 0019322
2012-01-19 18:26 ArnoBrinkman Note Added: 0019323
2012-01-19 18:35 SteffenSchm Note Added: 0019324
2012-02-24 11:56 obones Note Added: 0019528
2012-02-24 11:56 obones Status acknowledged => resolved
2012-02-24 11:56 obones Fixed in Version => Daily / SVN
2012-02-24 11:56 obones Resolution open => fixed
2012-02-24 11:56 obones Assigned To => obones
2012-02-24 17:37 obones Relationship added related to 0005774
2012-02-24 17:37 obones Relationship replaced has duplicate 0005774
2012-09-10 14:15 obones Fixed in Version Daily / SVN => 3.46


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker