Fix an issue in LOCALE_IO class, used to switch to/back locale "C" when reading/writing files: the back to locale was broken, and created issues in countries using the ',' as fp separator, especially when the non default language was used.
It was reported in many bugs.
This commit is contained in:
parent
2bb695b767
commit
90ed0183c8
|
@ -44,6 +44,8 @@
|
|||
#include <wx/utils.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
#include <pgm_base.h>
|
||||
|
||||
|
||||
/**
|
||||
* Global variables definitions.
|
||||
|
@ -58,30 +60,40 @@ EDA_UNITS_T g_UserUnit;
|
|||
EDA_COLOR_T g_GhostColor;
|
||||
|
||||
|
||||
/**
|
||||
* Function to use local notation or C standard notation for floating point numbers
|
||||
* some countries use 1,5 and others (and C) 1.5
|
||||
* so we switch from local to C and C to local when reading or writing files
|
||||
* And other problem is a bug when cross compiling under linux:
|
||||
* a printf print 1,5 and the read functions expects 1.5
|
||||
* (depending on version print = 1.5 and read = 1,5
|
||||
* Very annoying and we detect this and use a stupid but necessary workaround
|
||||
*/
|
||||
bool g_DisableFloatingPointLocalNotation = false;
|
||||
/* Class LOCALE_IO
|
||||
* is a class that can be instantiated within a scope in which you are expecting
|
||||
* exceptions to be thrown. Its constructor sets a "C" locale, to read/print files
|
||||
* with fp numbers.
|
||||
* Its destructor insures that the default locale is restored if an exception
|
||||
* is thrown, or not.
|
||||
*/
|
||||
|
||||
int LOCALE_IO::m_c_count = 0;
|
||||
|
||||
int LOCALE_IO::C_count;
|
||||
|
||||
|
||||
void SetLocaleTo_C_standard()
|
||||
LOCALE_IO::LOCALE_IO()
|
||||
{
|
||||
setlocale( LC_NUMERIC, "C" ); // Switch the locale to standard C
|
||||
wxASSERT_MSG( m_c_count >= 0, wxT( "LOCALE_IO::m_c_count mismanaged." ) );
|
||||
|
||||
// use thread safe, atomic operation
|
||||
if( __sync_fetch_and_add( &m_c_count, 1 ) == 0 )
|
||||
{
|
||||
// Store the user locale name, to restore this locale later, in dtor
|
||||
m_user_locale = setlocale( LC_ALL, 0 );
|
||||
// Switch the locale to C locale, to read/write files with fp numbers
|
||||
setlocale( LC_ALL, "C" );
|
||||
}
|
||||
}
|
||||
|
||||
void SetLocaleTo_Default()
|
||||
LOCALE_IO::~LOCALE_IO()
|
||||
{
|
||||
if( !g_DisableFloatingPointLocalNotation )
|
||||
setlocale( LC_NUMERIC, "" ); // revert to the current locale
|
||||
// use thread safe, atomic operation
|
||||
if( __sync_sub_and_fetch( &m_c_count, 1 ) == 0 )
|
||||
{
|
||||
// revert to the user locale
|
||||
setlocale( LC_ALL, m_user_locale.c_str() );
|
||||
}
|
||||
|
||||
wxASSERT_MSG( m_c_count >= 0, wxT( "LOCALE_IO::m_c_count mismanaged." ) );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -344,6 +344,7 @@ const wxString& PGM_BASE::GetEditorName( bool aCanShowFileChooser )
|
|||
return m_editor_name;
|
||||
}
|
||||
|
||||
|
||||
const wxString PGM_BASE::AskUserForPreferredEditor( const wxString& aDefaultEditor )
|
||||
{
|
||||
// Create a mask representing the executable files in the current platform
|
||||
|
@ -504,9 +505,6 @@ bool PGM_BASE::initPgm()
|
|||
|
||||
loadCommonSettings();
|
||||
|
||||
// Set locale option for separator used in float numbers
|
||||
SetLocaleTo_Default();
|
||||
|
||||
#ifdef __WXMAC__
|
||||
// Always show filters on Open dialog to be able to choose plugin
|
||||
wxSystemOptions::SetOption( wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1 );
|
||||
|
@ -695,20 +693,14 @@ bool PGM_BASE::SetLanguage( bool first_time )
|
|||
double dtst = 0.5;
|
||||
wxString msg;
|
||||
|
||||
extern bool g_DisableFloatingPointLocalNotation; // See common.cpp
|
||||
|
||||
g_DisableFloatingPointLocalNotation = false;
|
||||
|
||||
msg << dtst;
|
||||
double result;
|
||||
msg.ToDouble( &result );
|
||||
|
||||
if( result != dtst ) // string to double encode/decode does not work! Bug detected
|
||||
{
|
||||
if( result != dtst )
|
||||
// string to double encode/decode does not work! Bug detected:
|
||||
// Disable floating point localization:
|
||||
g_DisableFloatingPointLocalNotation = true;
|
||||
SetLocaleTo_C_standard( );
|
||||
}
|
||||
setlocale( LC_ALL, "C" );
|
||||
|
||||
if( !m_locale->IsLoaded( dictionaryName ) )
|
||||
m_locale->AddCatalog( dictionaryName );
|
||||
|
|
|
@ -64,6 +64,7 @@ void DIALOG_PLOT_SCHEMATIC::createPDFFile( bool aPlotAll, bool aPlotFrameRef )
|
|||
wxString msg;
|
||||
wxFileName plotFileName;
|
||||
REPORTER& reporter = m_MessagesBox->Reporter();
|
||||
LOCALE_IO toggle; // Switch the locale to standard C
|
||||
|
||||
// First page handling is different
|
||||
bool first_page = true;
|
||||
|
@ -106,7 +107,6 @@ void DIALOG_PLOT_SCHEMATIC::createPDFFile( bool aPlotAll, bool aPlotFrameRef )
|
|||
}
|
||||
|
||||
// Open the plotter and do the first page
|
||||
SetLocaleTo_C_standard();
|
||||
setupPlotPagePDF( plotter, screen );
|
||||
plotter->StartPlot();
|
||||
first_page = false;
|
||||
|
@ -150,7 +150,6 @@ void DIALOG_PLOT_SCHEMATIC::restoreEnvironment( PDF_PLOTTER* aPlotter,
|
|||
{
|
||||
aPlotter->EndPlot();
|
||||
delete aPlotter;
|
||||
SetLocaleTo_Default();
|
||||
|
||||
// Restore the previous sheet
|
||||
m_parent->SetCurrentSheet( aOldsheetpath );
|
||||
|
|
|
@ -168,7 +168,8 @@ bool DIALOG_PLOT_SCHEMATIC::plotOneSheetPS( const wxString& aFileName,
|
|||
return false;
|
||||
}
|
||||
|
||||
SetLocaleTo_C_standard();
|
||||
LOCALE_IO toggle; // Switch the locale to standard C
|
||||
|
||||
plotter->StartPlot();
|
||||
|
||||
if( aPlotFrameRef )
|
||||
|
@ -185,7 +186,6 @@ bool DIALOG_PLOT_SCHEMATIC::plotOneSheetPS( const wxString& aFileName,
|
|||
|
||||
plotter->EndPlot();
|
||||
delete plotter;
|
||||
SetLocaleTo_Default();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2014-2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2007-2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2008-2015 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
|
@ -176,70 +176,29 @@ extern EDA_UNITS_T g_UserUnit; ///< display units
|
|||
extern EDA_COLOR_T g_GhostColor;
|
||||
|
||||
|
||||
/**
|
||||
* Function SetLocaleTo_C_standard
|
||||
* because KiCad is internationalized, switch internalization to "C" standard
|
||||
* i.e. uses the . (dot) as separator in print/read float numbers
|
||||
* (some countries (France, Germany ..) use , (comma) as separator)
|
||||
* This function must be called before read or write ascii files using float
|
||||
* numbers in data the SetLocaleTo_C_standard function must be called after
|
||||
* reading or writing the file
|
||||
*
|
||||
* This is wrapper to the C setlocale( LC_NUMERIC, "C" ) function,
|
||||
* but could make more easier an optional use of locale in KiCad
|
||||
*/
|
||||
void SetLocaleTo_C_standard();
|
||||
|
||||
/**
|
||||
* Function SetLocaleTo_Default
|
||||
* because KiCad is internationalized, switch internalization to default
|
||||
* to use the default separator in print/read float numbers
|
||||
* (. (dot) but some countries (France, Germany ..) use , (comma) as
|
||||
* separator)
|
||||
* This function must be called after a call to SetLocaleTo_C_standard
|
||||
*
|
||||
* This is wrapper to the C setlocale( LC_NUMERIC, "" ) function,
|
||||
* but could make more easier an optional use of locale in KiCad
|
||||
*/
|
||||
void SetLocaleTo_Default();
|
||||
|
||||
|
||||
/**
|
||||
* Class LOCALE_IO
|
||||
* is a class that can be instantiated within a scope in which you are expecting
|
||||
* exceptions to be thrown. Its constructor calls SetLocaleTo_C_Standard().
|
||||
* exceptions to be thrown. Its constructor set a "C" laguage locale option,
|
||||
* to read/print files with fp numbers.
|
||||
* Its destructor insures that the default locale is restored if an exception
|
||||
* is thrown, or not.
|
||||
*/
|
||||
class LOCALE_IO
|
||||
{
|
||||
public:
|
||||
LOCALE_IO()
|
||||
{
|
||||
wxASSERT_MSG( C_count >= 0, wxT( "LOCALE_IO::C_count mismanaged." ) );
|
||||
|
||||
// use thread safe, atomic operation
|
||||
if( __sync_fetch_and_add( &C_count, 1 ) == 0 )
|
||||
{
|
||||
// printf( "setting C locale.\n" );
|
||||
SetLocaleTo_C_standard();
|
||||
}
|
||||
}
|
||||
|
||||
~LOCALE_IO()
|
||||
{
|
||||
// use thread safe, atomic operation
|
||||
if( __sync_sub_and_fetch( &C_count, 1 ) == 0 )
|
||||
{
|
||||
// printf( "restoring default locale.\n" );
|
||||
SetLocaleTo_Default();
|
||||
}
|
||||
|
||||
wxASSERT_MSG( C_count >= 0, wxT( "LOCALE_IO::C_count mismanaged." ) );
|
||||
}
|
||||
LOCALE_IO();
|
||||
~LOCALE_IO();
|
||||
|
||||
private:
|
||||
static int C_count; // allow for nesting of LOCALE_IO instantiations
|
||||
void setUserLocale( const char* aUserLocale );
|
||||
|
||||
// allow for nesting of LOCALE_IO instantiations
|
||||
static int m_c_count;
|
||||
|
||||
// The locale in use before switching to the "C" locale
|
||||
// (the locale can be set by user, and is not always the system locale)
|
||||
std::string m_user_locale;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ public:
|
|||
* been set.
|
||||
*/
|
||||
VTBL_ENTRY const wxString& GetEditorName( bool aCanShowFileChooser = true );
|
||||
|
||||
|
||||
/**
|
||||
* Shows a dialog that instructs the user to select a new preferred editor.
|
||||
* @param aDefaultEditor Default full path for the default editor this dialog should
|
||||
|
|
|
@ -268,7 +268,8 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& aEvent )
|
|||
DisplayError( this, msg ); return;
|
||||
}
|
||||
|
||||
SetLocaleTo_C_standard(); // No pesky decimal separators in gencad
|
||||
// Switch the locale to standard C (needed to print floating point numbers)
|
||||
LOCALE_IO toggle;
|
||||
|
||||
// Update some board data, to ensure a reliable gencad export
|
||||
GetBoard()->ComputeBoundingBox();
|
||||
|
@ -323,7 +324,6 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& aEvent )
|
|||
CreateRoutesSection( file, pcb );
|
||||
|
||||
fclose( file );
|
||||
SetLocaleTo_Default(); // revert to the current locale
|
||||
|
||||
// Undo the footprints modifications (flipped footprints)
|
||||
for( module = pcb->m_Modules; module; module = module->Next() )
|
||||
|
|
|
@ -538,7 +538,8 @@ bool Export_IDF3( BOARD* aPcb, const wxString& aFullFileName, bool aUseThou,
|
|||
{
|
||||
IDF3_BOARD idfBoard( IDF3::CAD_ELEC );
|
||||
|
||||
SetLocaleTo_C_standard();
|
||||
// Switch the locale to standard C (needed to print floating point numbers)
|
||||
LOCALE_IO toggle;
|
||||
|
||||
bool ok = true;
|
||||
double scale = MM_PER_IU; // we must scale internal units to mm for IDF
|
||||
|
@ -604,7 +605,5 @@ bool Export_IDF3( BOARD* aPcb, const wxString& aFullFileName, bool aUseThou,
|
|||
ok = false;
|
||||
}
|
||||
|
||||
SetLocaleTo_Default();
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -1334,8 +1334,8 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString& aFullFileName, double aMMt
|
|||
output_file.exceptions( std::ofstream::failbit );
|
||||
output_file.open( TO_UTF8( aFullFileName ), std::ios_base::out );
|
||||
|
||||
// Switch the locale to standard C (needed to print floating point numbers like 1.3)
|
||||
SetLocaleTo_C_standard();
|
||||
// Switch the locale to standard C (needed to print floating point numbers)
|
||||
LOCALE_IO toggle;
|
||||
|
||||
// Begin with the usual VRML boilerplate
|
||||
wxString fn = aFullFileName;
|
||||
|
@ -1403,7 +1403,6 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString& aFullFileName, double aMMt
|
|||
// End of work
|
||||
output_file.exceptions( std::ios_base::goodbit );
|
||||
output_file.close();
|
||||
SetLocaleTo_Default(); // revert to the current locale
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue