X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpbd%2Flocale_guard.cc;h=8007ea001b60c7fcd9b7d24f07ad559146d6b400;hb=3dc7728038860bda6eb4b0de1f4a3e14ec9e86cc;hp=aa5a57552188b3a38f74b53367cee3d4a6eb5512;hpb=32e23db6652fbbe54957872a96953b3eed7dad66;p=ardour.git diff --git a/libs/pbd/locale_guard.cc b/libs/pbd/locale_guard.cc index aa5a575521..8007ea001b 100644 --- a/libs/pbd/locale_guard.cc +++ b/libs/pbd/locale_guard.cc @@ -1,5 +1,5 @@ /* - 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 @@ -19,36 +19,57 @@ #include #include +#include #include #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); } -