KiCad PCB EDA Suite
Loading...
Searching...
No Matches
locale_io.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <locale_io.h>
25#include <wx/intl.h>
26#include <clocale>
27
28// When reading/writing files, we need to switch to setlocale( LC_NUMERIC, "C" ).
29// Works fine to read/write files with floating point numbers.
30// We can call setlocale( LC_NUMERIC, "C" ) or wxLocale( "C", "C", "C", false )
31// wxWidgets discourage a direct call to setlocale
32// However, for us, calling wxLocale( "C", "C", "C", false ) has a unwanted effect:
33// The I18N translations are no longer active, because the English dictionary is selected.
34// To read files, this is not a major issues, but the result can differ
35// from using setlocale(xx, "C").
36// Previously, we used only setlocale( LC_NUMERIC, "C" )
37//
38// Known issues are
39// on MSW
40// using setlocale( LC_NUMERIC, "C" ) generates an alert message in debug mode,
41// and this message ("Decimal separator mismatch") must be disabled.
42// But calling wxLocale( "C", "C", "C", false ) works fine
43// On unix:
44// calling wxLocale( "C", "C", "C", false ) breaks env vars containing non ASCII7 chars.
45// these env vars return a empty string from wxGetEnv() in many cases, and if such a
46// var must be read after calling wxLocale( "C", "C", "C", false ), it looks like empty
47//
48// So use wxLocale on Windows and setlocale on unix
49
50// On Windows, when using setlocale, a wx alert is generated
51// in some cases (reading a bitmap for instance)
52// So we disable alerts during the time a file is read or written
53#if !USE_WXLOCALE
54#if defined( _WIN32 ) && defined( DEBUG )
55
56// a wxAssertHandler_t function to filter wxWidgets alert messages when reading/writing a file
57// when switching the locale to LC_NUMERIC, "C"
58// It is used in class LOCALE_IO to hide a useless (in KiCad) wxWidgets alert message
59void KiAssertFilter( const wxString &file, int line,
60 const wxString &func, const wxString &cond,
61 const wxString &msg)
62{
63 if( !msg.Contains( "Decimal separator mismatch" ) )
64 wxTheApp->OnAssertFailure( file.c_str(), line, func.c_str(), cond.c_str(), msg.c_str() );
65}
66#endif
67#endif
68
69// allow for nesting of LOCALE_IO instantiations
70static std::atomic<unsigned int> locale_count( 0 );
71
73#if USE_WXLOCALE
74 : m_wxLocale( nullptr )
75#endif
76{
77 // use thread safe, atomic operation
78 if( locale_count++ == 0 )
79 {
80#if USE_WXLOCALE
81 #define C_LANG "C"
82 m_wxLocale = new wxLocale( C_LANG, C_LANG, C_LANG, false );
83#else
84 // Store the user locale name, to restore this locale later, in dtor
85 m_user_locale = setlocale( LC_NUMERIC, nullptr );
86#if defined( _WIN32 ) && defined( DEBUG )
87 // Disable wxWidgets alerts
88 wxSetAssertHandler( KiAssertFilter );
89#endif
90 // Switch the locale to C locale, to read/write files with fp numbers
91 setlocale( LC_NUMERIC, "C" );
92#endif
93 }
94}
95
96
98{
99 // use thread safe, atomic operation
100 if( --locale_count == 0 )
101 {
102 // revert to the user locale
103#if USE_WXLOCALE
104 delete m_wxLocale; // Deleting m_wxLocale restored previous locale
105 m_wxLocale = nullptr;
106#else
107 setlocale( LC_NUMERIC, m_user_locale.c_str() );
108#if defined( _WIN32 ) && defined( DEBUG )
109 // Enable wxWidgets alerts
110 wxSetDefaultAssertHandler();
111#endif
112#endif
113 }
114}
std::string m_user_locale
Definition: locale_io.h:60
static std::atomic< unsigned int > locale_count(0)