LOCALE_IO: replace the call to setlocale by a call to wxLocale to switch to "C" locale.

Previously we call only setlocale( xx, "C" ), but it was not enough on Windows.
Now we call wxLocale("C")
wxLocale calls setlocale, but also make some others initialization in wxWidgets.
It fixes some issues related to comma versus point as fp separator.
Especially wxWidgets warnings are no longer thrown, and a one case of incorrect
conversion is fixed.
However, wxLocale( "C" ) also switches the current translations to English, so
loading files can have a slightly different behavior
This commit is contained in:
jean-pierre charras 2020-02-17 09:14:18 +01:00
parent 3cb326e426
commit 6b78fdf822
3 changed files with 34 additions and 14 deletions

View File

@ -57,6 +57,23 @@ using KIGFX::COLOR4D;
COLOR4D g_GhostColor; COLOR4D g_GhostColor;
// When reading/writing files, we need to swtich to setlocale( LC_NUMERIC, "C" ).
// Works fine to read/write files with floating point numbers.
// We can call setlocale( LC_NUMERIC, "C" ) of wxLocale( "C", "C", "C", false )
// wxWidgets discourage a direct call to setlocale
// However, for us, calling wxLocale( "C", "C", "C", false ) has a unwanted effect:
// The I18N translations are no longer active, because the English dixtionary is selected.
// To read files, this is not a major issues, but the resul can differ
// from using setlocale(xx, "C").
// Previouly, we called setlocale( LC_NUMERIC, "C" )
// The old code will be removed when calling wxLocale( "C", "C", "C", false )
// is fully tested, and all issues fixed
#define USE_WXLOCALE 1 /* 0 to call setlocale, 1 to call wxLocale */
// On Windows, when using setlocale, a wx alert is generated
// in some cases (reading a bitmap for instance)
// So we disable alerts during the time a file is read or written
#if !USE_WXLOCALE
#if defined( _WIN32 ) && defined( DEBUG ) #if defined( _WIN32 ) && defined( DEBUG )
// a wxAssertHandler_t function to filter wxWidgets alert messages when reading/writing a file // a wxAssertHandler_t function to filter wxWidgets alert messages when reading/writing a file
// when switching the locale to LC_NUMERIC, "C" // when switching the locale to LC_NUMERIC, "C"
@ -66,24 +83,20 @@ void KiAssertFilter( const wxString &file, int line,
const wxString &msg) const wxString &msg)
{ {
if( !msg.Contains( "Decimal separator mismatch" ) ) if( !msg.Contains( "Decimal separator mismatch" ) )
wxTheApp->OnAssertFailure( file, line, func, cond, msg ); wxTheApp->OnAssertFailure( file.c_str(), line, func.c_str(), cond.c_str(), msg.c_str() );
} }
#endif #endif
#endif
std::atomic<unsigned int> LOCALE_IO::m_c_count( 0 ); std::atomic<unsigned int> LOCALE_IO::m_c_count( 0 );
LOCALE_IO::LOCALE_IO() : m_wxLocale( nullptr )
// Note on Windows, setlocale( LC_NUMERIC, "C" ) works fine to read/write
// files with floating point numbers, but generates a overzealous wx alert
// in some cases (reading a bitmap for instance)
// So we disable alerts during the time a file is read or written
LOCALE_IO::LOCALE_IO()
{ {
// use thread safe, atomic operation // use thread safe, atomic operation
if( m_c_count++ == 0 ) if( m_c_count++ == 0 )
{ {
#if USE_WXLOCALE
m_wxLocale = new wxLocale( "C", "C", "C", false );
#else
// Store the user locale name, to restore this locale later, in dtor // Store the user locale name, to restore this locale later, in dtor
m_user_locale = setlocale( LC_NUMERIC, nullptr ); m_user_locale = setlocale( LC_NUMERIC, nullptr );
#if defined( _WIN32 ) && defined( DEBUG ) #if defined( _WIN32 ) && defined( DEBUG )
@ -92,6 +105,7 @@ LOCALE_IO::LOCALE_IO()
#endif #endif
// Switch the locale to C locale, to read/write files with fp numbers // Switch the locale to C locale, to read/write files with fp numbers
setlocale( LC_NUMERIC, "C" ); setlocale( LC_NUMERIC, "C" );
#endif
} }
} }
@ -102,10 +116,15 @@ LOCALE_IO::~LOCALE_IO()
if( --m_c_count == 0 ) if( --m_c_count == 0 )
{ {
// revert to the user locale // revert to the user locale
#if USE_WXLOCALE
delete m_wxLocale; // Deleting m_wxLocale restored previous locale
m_wxLocale = nullptr;
#else
setlocale( LC_NUMERIC, m_user_locale.c_str() ); setlocale( LC_NUMERIC, m_user_locale.c_str() );
#if defined( _WIN32 ) && defined( DEBUG ) #if defined( _WIN32 ) && defined( DEBUG )
// Enable wxWidgets alerts // Enable wxWidgets alerts
wxSetDefaultAssertHandler(); wxSetDefaultAssertHandler();
#endif
#endif #endif
} }
} }

View File

@ -4,7 +4,7 @@
* Copyright (C) 2014-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2014-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2007-2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2007-2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -188,6 +188,7 @@ private:
// The locale in use before switching to the "C" locale // The locale in use before switching to the "C" locale
// (the locale can be set by user, and is not always the system locale) // (the locale can be set by user, and is not always the system locale)
std::string m_user_locale; std::string m_user_locale;
wxLocale* m_wxLocale;
}; };
/** /**

View File

@ -477,7 +477,7 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone,
{ {
int gap = zone_clearance; int gap = zone_clearance;
int thermalGap = aZone->GetThermalReliefGap( pad ); int thermalGap = aZone->GetThermalReliefGap( pad );
gap = std::max( gap, thermalGap ); gap = std::max( gap, thermalGap ) + outline_half_thickness;
item_boundingbox = pad->GetBoundingBox(); item_boundingbox = pad->GetBoundingBox();
item_boundingbox.Inflate( gap ); item_boundingbox.Inflate( gap );