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 (C) 1992-2021 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// a wxAssertHandler_t function to filter wxWidgets alert messages when reading/writing a file
56// when switching the locale to LC_NUMERIC, "C"
57// It is used in class LOCALE_IO to hide a useless (in kicad) wxWidgets alert message
58void KiAssertFilter( const wxString &file, int line,
59 const wxString &func, const wxString &cond,
60 const wxString &msg)
61{
62 if( !msg.Contains( "Decimal separator mismatch" ) )
63 wxTheApp->OnAssertFailure( file.c_str(), line, func.c_str(), cond.c_str(), msg.c_str() );
64}
65#endif
66#endif
67
68// allow for nesting of LOCALE_IO instantiations
69static std::atomic<unsigned int> locale_count( 0 );
70
72#if USE_WXLOCALE
73 : m_wxLocale( nullptr )
74#endif
75{
76 // use thread safe, atomic operation
77 if( locale_count++ == 0 )
78 {
79#if USE_WXLOCALE
80 #define C_LANG "C"
81 m_wxLocale = new wxLocale( C_LANG, C_LANG, C_LANG, false );
82#else
83 // Store the user locale name, to restore this locale later, in dtor
84 m_user_locale = setlocale( LC_NUMERIC, nullptr );
85#if defined( _WIN32 ) && defined( DEBUG )
86 // Disable wxWidgets alerts
87 wxSetAssertHandler( KiAssertFilter );
88#endif
89 // Switch the locale to C locale, to read/write files with fp numbers
90 setlocale( LC_NUMERIC, "C" );
91#endif
92 }
93}
94
95
97{
98 // use thread safe, atomic operation
99 if( --locale_count == 0 )
100 {
101 // revert to the user locale
102#if USE_WXLOCALE
103 delete m_wxLocale; // Deleting m_wxLocale restored previous locale
104 m_wxLocale = nullptr;
105#else
106 setlocale( LC_NUMERIC, m_user_locale.c_str() );
107#if defined( _WIN32 ) && defined( DEBUG )
108 // Enable wxWidgets alerts
109 wxSetDefaultAssertHandler();
110#endif
111#endif
112 }
113}
std::string m_user_locale
Definition: locale_io.h:60
static std::atomic< unsigned int > locale_count(0)