/*
- Copyright (C) 2012 Paul Davis
+ Copyright (C) 2012 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include <locale.h>
#include "pbd/locale_guard.h"
+#include "pbd/error.h"
using namespace PBD;
-// try to avoid calling setlocale() recursively. this is not thread-safe.
-std::string PBD::LocaleGuard::current;
+/* The initial C++ locale is "C" regardless of the user's preferred locale.
+ * The C locale from setlocale() matches the user's preferred locale
+ *
+ * Setting the C++ locale will change the C locale, but not the other way 'round.
+ * and some plugin may change either behind our back.
+ */
-LocaleGuard::LocaleGuard (const char* str)
- : old(0)
+LocaleGuard::LocaleGuard ()
+ : old_c (0)
{
- if (current != str) {
- old = strdup (setlocale (LC_NUMERIC, NULL));
- if (strcmp (old, str)) {
- if (setlocale (LC_NUMERIC, str)) {
- current = str;
- }
- }
+ char* actual = setlocale (LC_NUMERIC, NULL);
+ if (strcmp ("C", actual)) {
+ /* purpose of LocaleGuard is to make sure we're using "C" for
+ the numeric locale during its lifetime, so make it so.
+ */
+ old_c = strdup (actual);
+ /* this changes both C++ and C locale */
+ std::locale::global (std::locale (std::locale::classic(), "C", std::locale::numeric));
+ }
+ if (old_cpp != std::locale::classic ()) {
+ PBD::error << "LocaleGuard: initial C++ locale is not 'C'. Expect non-portable session files.\n";
}
}
LocaleGuard::~LocaleGuard ()
{
- if (old) {
- if (setlocale (LC_NUMERIC, old)) {
- current = old;
- }
+ char* actual = setlocale (LC_NUMERIC, NULL);
+ std::locale current;
- free (old);
+ if (current != old_cpp) {
+ /* the C++ locale should always be "C", that's the default
+ * at application start, and ardour never changes it to
+ * anything but "C".
+ *
+ * if it's not: some plugin meddled with it.
+ */
+ if (old_cpp != std::locale::classic ()) {
+ PBD::error << "LocaleGuard: someone (a plugin) changed the C++ locale, expect non-portable session files.\n";
+ }
+ std::locale::global (old_cpp);
+ }
+ if (old_c && strcmp (old_c, actual)) {
+ setlocale (LC_NUMERIC, old_c);
}
+ free (old_c);
}
-