]> git.rm.cloudns.org Git - xonotic/netradiant.git/commitdiff
In Radiant main() method, add putenv("LC_NUMERIC=C").
authorrambetter <rambetter>
Sun, 14 Nov 2010 01:40:25 +0000 (01:40 +0000)
committerrambetter <rambetter>
Sun, 14 Nov 2010 01:40:25 +0000 (01:40 +0000)
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: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@334 8a3a26a2-13c4-0310-b231-cf6edde360e5

radiant/main.cpp

index 02369ac84a7e9dd5c51ae725fbd0b5f90f917a4f..0f7b434d879d2f038968cfd60085394a67f63414 100644 (file)
@@ -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