From 4f88b9d8117c1951132cb49862185845d492bd00 Mon Sep 17 00:00:00 2001 From: rambetter Date: Sun, 14 Nov 2010 01:40:25 +0000 Subject: [PATCH] In Radiant main() method, add putenv("LC_NUMERIC=C"). sscanf() and *printf() calls are all over the code, which are locale-sensitive. gtk_init() sets all locales. So if you're in Germany, your printf()'s will output e.g. "10,5" for ten and a half. Reading floating points with sscanf() is also totally broken in locales such as Germany. So, we can't really get rid of all the *scanf()'s and the *printf()'s. Instead, set LC_NUMERIC to "C". git-svn-id: https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/trunk@334 8a3a26a2-13c4-0310-b231-cf6edde360e5 --- radiant/main.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/radiant/main.cpp b/radiant/main.cpp index 02369ac8..0f7b434d 100644 --- a/radiant/main.cpp +++ b/radiant/main.cpp @@ -427,6 +427,52 @@ int main( int argc, char* argv[] ) { char *libgl, *ptr; int i, j, k; + /* + Rambetter on Sat Nov 13, 2010: + + The following line fixes parsing and writing of floating point numbers in locales such as + Italy, Germany, and others outside of en_US. In particular, in such problem locales, users + are not able to use certain map entities such as "light" because the definitions of these entities + in the entity definition files contain floating point values written in the standard "C" format + (containing a dot instead of, for example, a comma). The call sscanf() is all over the code, + including parsing entity definition files and reading Radiant preferences. sscanf() is sensitive + to locale (in particular when reading floating point numbers). + + The line below is the minimalistic way to address only this particular problem - the parsing + and writing of floating point values. There may be other yet-undiscovered bugs related to + locale still lingering in the code. When such bugs are discovered, they should be addressed by + setting more than just "LC_NUMERIC=C" (for example LC_CTYPE for regular expression matching) + or by fixing the problem in the actual code instead of fiddling with LC_* variables. + + Another way to fix the floating point format problem is to locate all calls such as *scanf() + and *printf() in the code and replace them with other functions. However, we're also using + external libraries such as libxml and [maybe?] they use locale to parse their numeric values. + I'm just saying, it may get ugly if we try to fix the problem without setting LC_NUMERIC. + + Usage of sscanf() throughout the code looks like so: + sscanf(str, "%f %f %f", &val1, &val2, &val3); + Code like this exists in many files, here are 4 examples: + tools/quake3/q3map2/light.c + tools/quake3/q3map2/model.c + radiant/preferences.cpp + plugins/entity/miscmodel.cpp + + Also affected are printf() calls when using formats that contain "%f". + + I did some research and putenv() seems to be the best choice for being cross-platform. It + used to be a function in Windows (now deprecated): + http://msdn.microsoft.com/en-us/library/ms235321(VS.80).aspx + And of course it's defined in UNIX. + + One more thing. the gtk_init() call below modifies all of the locale settings. In fact if it + weren't for gtk_init(), we wouldn't have to set LC_NUMERIC (parsing of floating points with + a dot works just fine before the gtk_init() call on a sample Linux system). If we were to + just setlocale() here, it would get clobbered by gtk_init(). So instead of using setlocale() + _after_ gtk_init(), I chose to fix this problem via environment variable. I think it's cleaner + that way. + */ + putenv("LC_NUMERIC=C"); + #ifdef _WIN32 libgl = "opengl32.dll"; #endif -- 2.39.2