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, see <https://www.gnu.org/licenses/>.
18
*/
19
20
#include <
locale_io.h
>
21
#include <wx/intl.h>
22
#include <clocale>
23
#include <mutex>
24
25
// When reading/writing files, we need to switch to setlocale( LC_NUMERIC, "C" ).
26
// Works fine to read/write files with floating point numbers.
27
// We can call setlocale( LC_NUMERIC, "C" ) or wxLocale( "C", "C", "C", false )
28
// wxWidgets discourage a direct call to setlocale
29
// However, for us, calling wxLocale( "C", "C", "C", false ) has a unwanted effect:
30
// The I18N translations are no longer active, because the English dictionary is selected.
31
// To read files, this is not a major issues, but the result can differ
32
// from using setlocale(xx, "C").
33
// Previously, we used only setlocale( LC_NUMERIC, "C" )
34
//
35
// Known issues are
36
// on MSW
37
// using setlocale( LC_NUMERIC, "C" ) generates an alert message in debug mode,
38
// and this message ("Decimal separator mismatch") must be disabled.
39
// But calling wxLocale( "C", "C", "C", false ) works fine
40
// On unix:
41
// calling wxLocale( "C", "C", "C", false ) breaks env vars containing non ASCII7 chars.
42
// these env vars return a empty string from wxGetEnv() in many cases, and if such a
43
// var must be read after calling wxLocale( "C", "C", "C", false ), it looks like empty
44
//
45
// So use wxLocale on Windows and setlocale on unix
46
47
// On Windows, when using setlocale, a wx alert is generated
48
// in some cases (reading a bitmap for instance)
49
// So we disable alerts during the time a file is read or written
50
51
52
// set USE_WXLOCALE to 0 to use setlocale, 1 to use wxLocale:
53
#if defined( _WIN32 )
54
#define USE_WXLOCALE 1
55
#else
56
#define USE_WXLOCALE 0
57
#endif
58
59
#if !USE_WXLOCALE
60
#if defined( _WIN32 ) && defined( DEBUG )
61
#include <wx/appl.h>
// for wxTheApp
62
63
// a wxAssertHandler_t function to filter wxWidgets alert messages when reading/writing a file
64
// when switching the locale to LC_NUMERIC, "C"
65
// It is used in class LOCALE_IO to hide a useless (in KiCad) wxWidgets alert message
66
void
KiAssertFilter(
const
wxString &file,
int
line,
67
const
wxString &func,
const
wxString &cond,
68
const
wxString &msg)
69
{
70
if
( !msg.Contains(
"Decimal separator mismatch"
) )
71
wxTheApp->OnAssertFailure( file.c_str(), line, func.c_str(), cond.c_str(), msg.c_str() );
72
}
73
#endif
74
#endif
75
76
// Allow for nesting of LOCALE_IO instantiations. SPICE library parsing (and other code) toggles
77
// the locale from worker threads in parallel, so both the nesting count and the global locale
78
// transitions it triggers must be serialized together under one mutex. An atomic count alone is
79
// not enough, since setlocale() and the wxLocale new/delete it guards mutate process-global state
80
// and the heap, which corrupts when two threads transition at the same time.
81
static
std::mutex
locale_mutex
;
82
static
unsigned
int
locale_count
= 0;
83
static
wxLocale*
locale_wxLocale
=
nullptr
;
84
static
std::string
locale_user_locale
;
85
86
LOCALE_IO::LOCALE_IO
()
87
{
88
std::lock_guard<std::mutex> lock(
locale_mutex
);
89
90
if
(
locale_count
++ == 0 )
91
{
92
#if USE_WXLOCALE
93
#define C_LANG "C"
94
locale_wxLocale
=
new
wxLocale( C_LANG, C_LANG, C_LANG,
false
);
95
#else
96
// Store the user locale name, to restore this locale later, in dtor
97
locale_user_locale
= setlocale( LC_NUMERIC,
nullptr
);
98
#if defined( _WIN32 ) && defined( DEBUG )
99
// Disable wxWidgets alerts
100
wxSetAssertHandler( KiAssertFilter );
101
#endif
102
// Switch the locale to C locale, to read/write files with fp numbers
103
setlocale( LC_NUMERIC,
"C"
);
104
#endif
105
}
106
}
107
108
109
LOCALE_IO::~LOCALE_IO
()
110
{
111
std::lock_guard<std::mutex> lock(
locale_mutex
);
112
113
if
( --
locale_count
== 0 )
114
{
115
// revert to the user locale
116
#if USE_WXLOCALE
117
delete
locale_wxLocale
;
// Deleting the wxLocale restored the previous locale
118
locale_wxLocale
=
nullptr
;
119
#else
120
setlocale( LC_NUMERIC,
locale_user_locale
.c_str() );
121
#if defined( _WIN32 ) && defined( DEBUG )
122
// Enable wxWidgets alerts
123
wxSetDefaultAssertHandler();
124
#endif
125
#endif
126
}
127
}
LOCALE_IO::LOCALE_IO
LOCALE_IO()
Definition
locale_io.cpp:86
LOCALE_IO::~LOCALE_IO
~LOCALE_IO()
Definition
locale_io.cpp:109
locale_wxLocale
static wxLocale * locale_wxLocale
Definition
locale_io.cpp:83
locale_count
static unsigned int locale_count
Definition
locale_io.cpp:82
locale_user_locale
static std::string locale_user_locale
Definition
locale_io.cpp:84
locale_mutex
static std::mutex locale_mutex
Definition
locale_io.cpp:81
locale_io.h
src
common
locale_io.cpp
Generated on Fri Jun 26 2026 00:05:32 for KiCad PCB EDA Suite by
1.13.2