}
+namespace {
+
+// Trivial wrapper around gettext()
+docstring const getText(string const & m)
+{
+ // FIXME: gettext sometimes "forgets" the ucs4_codeset we set
+ // in init(), which leads to severe message corruption (#7371)
+ // We set it again here unconditionally. A real fix must be found!
+ LASSERT(bind_textdomain_codeset(PACKAGE, ucs4_codeset), /**/);
+
+ char const * m_c = m.c_str();
+ char const * trans_c = gettext(m_c);
+ docstring trans;
+ if (!trans_c) {
+ LYXERR(Debug::LOCALE, "Undefined result from gettext for `" << m << "'.");
+ trans = from_ascii(m);
+ } else if (trans_c == m_c) {
+ //LYXERR(Debug::LOCALE, "Same as entered returned");
+ trans = from_ascii(m);
+ } else {
+ //LYXERR(Debug::LOCALE, "We got a translation");
+ // m is actually not a char const * but ucs4 data
+ trans = reinterpret_cast<char_type const *>(trans_c);
+ }
+
+ cleanTranslation(trans);
+
+ return trans;
+}
+
+}
+
docstring const Messages::get(string const & m) const
{
return it->second;
// The string was not found, use gettext to generate it
- static string oldLC_ALL;
- static string oldLANGUAGE;
+ docstring trans;
if (!lang_.empty()) {
- oldLC_ALL = getEnv("LC_ALL");
// This GNU extension overrides any language locale
// wrt gettext.
LYXERR(Debug::LOCALE, "Setting LANGUAGE to " << lang_);
- oldLANGUAGE = getEnv("LANGUAGE");
- if (!setEnv("LANGUAGE", lang_))
- LYXERR(Debug::LOCALE, "\t... failed!");
+ EnvChanger language_chg("LANGUAGE", lang_);
// However, setting LANGUAGE does nothing when the
// locale is "C". Therefore we set the locale to
// something that is believed to exist on most
// load German documents even without having de_DE
// installed.
LYXERR(Debug::LOCALE, "Setting LC_ALL to en_US");
- if (!setEnv("LC_ALL", "en_US"))
- LYXERR(Debug::LOCALE, "\t... failed!");
+ EnvChanger lc_all_chg("LC_ALL", "en_US");
#ifdef HAVE_LC_MESSAGES
setlocale(LC_MESSAGES, "");
#endif
- }
-
- // FIXME: gettext sometimes "forgets" the ucs4_codeset we set
- // in init(), which leads to severe message corruption (#7371)
- // We set it again here unconditionally. A real fix must be found!
- LASSERT(bind_textdomain_codeset(PACKAGE, ucs4_codeset), /**/);
-
- char const * m_c = m.c_str();
- char const * trans_c = gettext(m_c);
- docstring trans;
- if (!trans_c) {
- LYXERR(Debug::LOCALE, "Undefined result from gettext for `" << m << "'.");
- trans = from_ascii(m);
- } else if (trans_c == m_c) {
- //LYXERR(Debug::LOCALE, "Same as entered returned");
- trans = from_ascii(m);
- } else {
- //LYXERR(Debug::LOCALE, "We got a translation");
- // m is actually not a char const * but ucs4 data
- trans = reinterpret_cast<char_type const *>(trans_c);
- }
-
- cleanTranslation(trans);
+ trans = getText(m);
+ } else
+ trans = getText(m);
+
- // Reset environment variables as they were.
- if (!lang_.empty()) {
- // Reset everything as it was.
- LYXERR(Debug::LOCALE, "restoring LANGUAGE from "
- << getEnv("LANGUAGE")
- << " to " << oldLANGUAGE);
- if (!setEnv("LANGUAGE", oldLANGUAGE))
- LYXERR(Debug::LOCALE, "\t... failed!");
- LYXERR(Debug::LOCALE, "restoring LC_ALL from " << getEnv("LC_ALL")
- << " to " << oldLC_ALL);
- if (!setEnv("LC_ALL", oldLC_ALL))
- LYXERR(Debug::LOCALE, "\t... failed!");
#ifdef HAVE_LC_MESSAGES
- setlocale(LC_MESSAGES, "");
+ setlocale(LC_MESSAGES, "");
#endif
- }
+ // store translation in cache
pair<TranslationCache::iterator, bool> result =
cache_.insert(make_pair(m, trans));
namespace lyx {
namespace support {
-string const getEnv(string const & envname)
+
+bool hasEnv(string const & name)
+{
+ return getenv(name.c_str());
+}
+
+
+string const getEnv(string const & name)
{
// f.ex. what about error checking?
- char const * const ch = getenv(envname.c_str());
+ char const * const ch = getenv(name.c_str());
return ch ? to_utf8(from_local8bit(ch)) : string();
}
setEnvPath(name, env_var);
}
+
+bool unsetEnv(string const & name)
+{
+#if defined(HAVE_UNSETENV)
+ // FIXME: does it leak?
+ return unsetenv(name.c_str()) == 0;
+#elif defined(HAVE_PUTENV)
+ // This is OK with MSVC and MinGW at least.
+ return putenv((name + "=").c_str()) == 0;
+#else
+#error No environment-unsetting function has been defined.
+#endif
+}
+
+
} // namespace support
} // namespace lyx
namespace lyx {
namespace support {
+/// @returns true if the environment variable @c name exists.
+bool hasEnv(std::string const & name);
+
/// @returns the contents of the environment variable @c name encoded in utf8.
-std::string const getEnv(std::string const & envname);
+std::string const getEnv(std::string const & name);
/** @returns the contents of the environment variable @c name,
* split into path elements using the OS-dependent separator token
*/
void prependEnvPath(std::string const & name, std::string const & prefix);
+/** Remove the variable @c name from the environment.
+ * @returns true if the variable was unset successfully.
+ */
+bool unsetEnv(std::string const & name);
+
+
+/** Utility class to change temporarily an environment variable. The
+ * variable is reset to its original state when the dummy EnvChanger
+ * variable is deleted.
+ */
+class EnvChanger {
+public:
+ ///
+ EnvChanger(std::string const & name, std::string const & value)
+ : name_(name), set_(hasEnv(name)), value_(getEnv(name))
+ {
+ setEnv(name, value);
+ }
+ ///
+ ~EnvChanger()
+ {
+ if (set_)
+ setEnv(name_, value_);
+ else
+ unsetEnv(name_);
+ }
+
+private:
+ /// the name of the variable
+ std::string name_;
+ /// was the variable set?
+ bool set_;
+ ///
+ std::string value_;
+};
+
} // namespace support
} // namespace lyx