On 9/23/20 9:42 PM Ian MacArthur wrote:
> All,
>
> In an off-list discussion elsewhere, a potential issue was flagged with Fl_Preferences interacting oddly with locale settings, specifically with the handling of the decimal separator.
> In this case a FI locale was used but ISTR that uses the same decimal separator as, say, DE uses, so I imagine that several of the fltk regulars would have seen this (like, maybe, Matt who wrote Fl_preferences, for example...)
>
> Anyway, I’ll post parts of the original below for the details, though I recall that we had some discussion about locale settings recently but can’t recall the outcome.
Maybe regarding localized error messages? See below.
> I wondered if we have seen this before and what the thinking is on non-C-locale settings etc...?
Hmm, I just did a small test with test/preferences and I *believe* it
works as /expected/. The questions is: what are the expectations...
(again, see more below).
>> I'm pretty sure one of my fldigi users (
http://www.w1hkj.com/files/fldigi/) has found a bug in Fl_Preferences.
>>
>> Fl_Preferences::get, fails if the system locale does not use a period as the decimal separator character. The problem was discovered by a user in the FI_fi locale.
>>
>> Symptom:
>>
>> method set correctly writes the double value with the locale decimal separator
>> method get fails.
I tried this with de_DE locale in test/preferences that includes two
float values. The unmodified program works as if it uses the C locale
(and in fact it does). Hence all float values are written with '.' as
decimal separator and read back correctly.
Then I modified test/preferences.cxx (I edited the .cxx file for
simplicity) to include:
#include <locale.h>
and as the first line in main():
setlocale(LC_ALL, ""); // enable multilanguage behavior
With these modifications it works correctly writing float values with
decimal separator ',' and reads them back correctly.
This is what I expected.
>> My code does not execute a setenv(LC_NUMERIC,..., but relies on that environment variable set in the user's system (Fedora F32). I'm not sure why the set works and the get does not.
I don't know either. To know that we'd need to see more code.
The point is, however, that the locale environment variables are only
used if setlocale(LC_*, ""); is called, i.e. with an empty string as the
second argument (see `man setlocale`). The man page says among other things:
>>>
On startup of the main program, the portable "C" locale is selected as
default. A program may be made portable to all locales by calling:
setlocale(LC_ALL, "");
after program initialization, ...
<<<
So it's maybe a misunderstanding of the original error reporter how the
locale stuff works. It took me some time to find that out myself when we
tried to return localized error messages recently but I'm still not an
expert.
So I'd suggest the error reporter (author of fldigi?) to add the
setlocale(LC_ALL, ""); call right at the beginning of main() and see how
that works. A good and simple test is test/preferences(.fl/.cxx) which
can be simplified for a local test if required.
Calling setenv(LC_*,...) inside the program would be wrong anyway unless
setlocale(...) would be called *after* that. The right thing to do would
be to call setlocale(LC_NUMERIC, ...) *if* the program needed to use a
specific locale and *not* the user's locale (after the initialization
with `setlocale(LC_ALL, "");`.
So *if* the author of the program decided to use the user's locale
settings for everything except the numeric locale (and to use "C" for
the latter) to always use the decimal separator "." in preferences they
could use (see fluid/fluid.c in 1.4):
setlocale(LC_ALL, ""); // enable multilanguage errors in file
chooser
setlocale(LC_NUMERIC, "C"); // make sure numeric values are written
correctly
Note that fluid writes and reads the fluid/fltk version number as a
numeric (float) value to/from the .fl file which is why we need to set
LC_NUMERIC to "C".
As I said, I'm not an expert, but I believe I got the basics of how it
works and how we should expect it to work.