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#include <atomic>
28
29// When reading/writing files, we need to switch to setlocale( LC_NUMERIC, "C" ).
30// Works fine to read/write files with floating point numbers.
31// We can call setlocale( LC_NUMERIC, "C" ) or wxLocale( "C", "C", "C", false )
32// wxWidgets discourage a direct call to setlocale
33// However, for us, calling wxLocale( "C", "C", "C", false ) has a unwanted effect:
34// The I18N translations are no longer active, because the English dictionary is selected.
35// To read files, this is not a major issues, but the result can differ
36// from using setlocale(xx, "C").
37// Previously, we used only setlocale( LC_NUMERIC, "C" )
38//
39// Known issues are
40// on MSW
41// using setlocale( LC_NUMERIC, "C" ) generates an alert message in debug mode,
42// and this message ("Decimal separator mismatch") must be disabled.
43// But calling wxLocale( "C", "C", "C", false ) works fine
44// On unix:
45// calling wxLocale( "C", "C", "C", false ) breaks env vars containing non ASCII7 chars.
46// these env vars return a empty string from wxGetEnv() in many cases, and if such a
47// var must be read after calling wxLocale( "C", "C", "C", false ), it looks like empty
48//
49// So use wxLocale on Windows and setlocale on unix
50
51// On Windows, when using setlocale, a wx alert is generated
52// in some cases (reading a bitmap for instance)
53// So we disable alerts during the time a file is read or written
54
55
56// set USE_WXLOCALE to 0 to use setlocale, 1 to use wxLocale:
57#if defined( _WIN32 )
58#define USE_WXLOCALE 1
59#else
60#define USE_WXLOCALE 0
61#endif
62
63#if !USE_WXLOCALE
64#if defined( _WIN32 ) && defined( DEBUG )
65#include <wx/appl.h> // for wxTheApp
66
67// a wxAssertHandler_t function to filter wxWidgets alert messages when reading/writing a file
68// when switching the locale to LC_NUMERIC, "C"
69// It is used in class LOCALE_IO to hide a useless (in KiCad) wxWidgets alert message
70void KiAssertFilter( const wxString &file, int line,
71 const wxString &func, const wxString &cond,
72 const wxString &msg)
73{
74 if( !msg.Contains( "Decimal separator mismatch" ) )
75 wxTheApp->OnAssertFailure( file.c_str(), line, func.c_str(), cond.c_str(), msg.c_str() );
76}
77#endif
78#endif
79
80// allow for nesting of LOCALE_IO instantiations
81static std::atomic<unsigned int> locale_count( 0 );
82
84 m_wxLocale( nullptr )
85{
86 // use thread safe, atomic operation
87 if( locale_count++ == 0 )
88 {
89#if USE_WXLOCALE
90 #define C_LANG "C"
91 m_wxLocale = new wxLocale( C_LANG, C_LANG, C_LANG, false );
92#else
93 // Store the user locale name, to restore this locale later, in dtor
94 m_user_locale = setlocale( LC_NUMERIC, nullptr );
95#if defined( _WIN32 ) && defined( DEBUG )
96 // Disable wxWidgets alerts
97 wxSetAssertHandler( KiAssertFilter );
98#endif
99 // Switch the locale to C locale, to read/write files with fp numbers
100 setlocale( LC_NUMERIC, "C" );
101#endif
102 }
103}
104
105
107{
108 // use thread safe, atomic operation
109 if( --locale_count == 0 )
110 {
111 // revert to the user locale
112#if USE_WXLOCALE
113 delete m_wxLocale; // Deleting m_wxLocale restored previous locale
114 m_wxLocale = nullptr;
115#else
116 setlocale( LC_NUMERIC, m_user_locale.c_str() );
117#if defined( _WIN32 ) && defined( DEBUG )
118 // Enable wxWidgets alerts
119 wxSetDefaultAssertHandler();
120#endif
121#endif
122 }
123}
wxLocale * m_wxLocale
Definition locale_io.h:49
std::string m_user_locale
Definition locale_io.h:50
static std::atomic< unsigned int > locale_count(0)