[glibmm] Glib::init(): Set the global locale



commit d27f6f0c715b226e6a9dc67cd05b4dc860d2271b
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Wed Dec 14 09:49:55 2016 +0100

    Glib::init(): Set the global locale
    
    * glib/glibmm/init.[cc|h]: Add set/get_init_to_users_preferred_locale().
    Let Glib::init() set the C andC++ global locale to the user's preferred locale,
    or (if Glib::set_init_to_users_preferred_locale(false) has been called) set
    the C++ locale to be equal to the C locale.
    * glib/glibmm/ustring.h: Add to the documentation that Glib::init() sets the
    global locale. Bug 661588

 glib/glibmm/init.cc   |   56 +++++++++++++++++++++++++++++++++++++++++++++++-
 glib/glibmm/init.h    |   47 +++++++++++++++++++++++++++++++++++-----
 glib/glibmm/ustring.h |    4 ++-
 3 files changed, 98 insertions(+), 9 deletions(-)
---
diff --git a/glib/glibmm/init.cc b/glib/glibmm/init.cc
index cc3b84c..f42cdf5 100644
--- a/glib/glibmm/init.cc
+++ b/glib/glibmm/init.cc
@@ -17,15 +17,67 @@
 
 #include <glibmm/init.h>
 #include <glibmm/error.h>
+#include <locale>
+#include <clocale>
+#include <stdexcept>
+
+namespace
+{
+  bool init_to_users_preferred_locale = true;
+
+} // anonymous namespace
 
 namespace Glib
 {
+void set_init_to_users_preferred_locale(bool state)
+{
+  init_to_users_preferred_locale = state;
+}
+
+bool get_init_to_users_preferred_locale()
+{
+  return init_to_users_preferred_locale;
+}
 
-void
-init()
+void init()
 {
+  static bool is_initialized = false;
+
+  if (is_initialized)
+    return;
+
+  if (init_to_users_preferred_locale)
+  {
+    try
+    {
+      // Set the global locale for C++ functions and the locale for C functions
+      // to the user-preferred locale.
+      std::locale::global(std::locale(""));
+    }
+    catch (const std::runtime_error& ex)
+    {
+      g_warning("Can't set the global locale to the user's preferred locale.\n"
+        "   %s\n   The environment variable LANG may be wrong.\n", ex.what());
+    }
+  }
+  else
+  {
+    try
+    {
+      // Make the C++ locale equal to the C locale.
+      std::locale::global(std::locale(std::setlocale(LC_ALL, nullptr)));
+    }
+    catch (const std::runtime_error& ex)
+    {
+      g_warning("Can't make the global C++ locale equal to the C locale.\n"
+        "   %s\n   C locale = %s\n", ex.what(), std::setlocale(LC_ALL, nullptr));
+    }
+  }
+
   // Also calls Glib::wrap_register_init() and Glib::wrap_init().
   Glib::Error::register_init();
+
+  is_initialized = true;
 }
 
 } // namespace Glib
diff --git a/glib/glibmm/init.h b/glib/glibmm/init.h
index 844945a..a736093 100644
--- a/glib/glibmm/init.h
+++ b/glib/glibmm/init.h
@@ -1,9 +1,6 @@
-// -*- c++ -*-
 #ifndef _GLIBMM_INIT_H
 #define _GLIBMM_INIT_H
 
-/* $Id$ */
-
 /* Copyright (C) 2002 The gtkmm Development Team
  *
  * This library is free software; you can redistribute it and/or
@@ -25,12 +22,50 @@ namespace Glib
 {
 
 /** Initialize glibmm.
- * You may call this more than once.
- * You do not need to call this if you are using Glib::MainLoop or Gtk::Main,
- * because they call it for you.
+ *
+ * You may call this more than once. Calls after the first one have no effect.
+ * Sets the global locale as specified by set_init_to_users_preferred_locale().
+ * You do not need to call %Glib::init() if you are using Gtk::Application,
+ * because it calls %Glib::init() for you.
+ *
+ * @see set_init_to_users_preferred_locale()
  */
 void init();
 
+/** Instruct Glib::init() which global locale to set.
+ *
+ * To have the intended effect, this function must be called before init() is called.
+ * Not calling it has the same effect as calling it with @a state = <tt>true</tt>.
+ *
+ * Note the confusing difference between C locale and "C" locale.
+ * The C locale is the locale used by C code, set by std::setlocale(LC_ALL,&nbsp;locale_name).
+ * The "C" locale is the classic locale, set by std::setlocale(LC_ALL,&nbsp;"C")
+ * or std::locale::global(std::locale::classic()). It's the default global locale
+ * in a C or C++ program.
+ *
+ * In a mixed C and C++ program, like a program using glibmm, having the C global
+ * locale differ from std::locale::global() is error prone. Glib::init() tries
+ * to avoid that.
+ *
+ * @param state If <tt>true</tt>, init() will set the C and C++ global locale
+ *              to the user's preferred locale (std::locale::global(std::locale(""))).
+ *              The user's preferred locale is set in the program's environment,
+ *              usually with the LANG environment variable.<br>
+ *              If <tt>false</tt>, init() will set the C++ global locale to the C global locale
+ *              (std::locale::global(std::locale(std::setlocale(LC_ALL,&nbsp;nullptr)))).
+ *
+ * @newin{2,52}
+ */
+void set_init_to_users_preferred_locale(bool state = true);
+
+/** Get the state, set with set_init_to_users_preferred_locale().
+ * @returns The state, set with set_init_to_users_preferred_locale(); <tt>true</tt>
+ *          if set_init_to_users_preferred_locale() has not been called.
+ *
+ * @newin{2,52}
+ */
+bool get_init_to_users_preferred_locale();
+
 } // namespace Glib
 
 #endif /* _GLIBMM_INIT_H */
diff --git a/glib/glibmm/ustring.h b/glib/glibmm/ustring.h
index fe45c1a..ba6289d 100644
--- a/glib/glibmm/ustring.h
+++ b/glib/glibmm/ustring.h
@@ -184,7 +184,9 @@ gunichar get_unichar_from_std_iterator(std::string::const_iterator pos) G_GNUC_P
  * If you're using std::ostringstream to build strings for display in the
  * user interface, you must convert the result back to UTF-8 as shown below:
  * @code
- * std::locale::global(std::locale("")); // set the global locale to the user's preferred locale
+ * std::locale::global(std::locale("")); // Set the global locale to the user's preferred locale.
+ *                                       // Usually unnecessary here, because Glib::init()
+ *                                       // does it for you.
  * std::ostringstream output;
  * output << percentage << " % done";
  * label->set_text(Glib::locale_to_utf8(output.str()));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]