Blast quite a bit of LOCALE_IO into the sun

After forcing the locale-specific read/writes out of our IO, we can
remove the global LOCALE_IO calls in many places.

Still to do: exporters, pcm, specctra, settings, drawing sheets,
plotters
This commit is contained in:
Seth Hillbrand 2025-07-14 15:30:42 -07:00
parent 55da0e46af
commit 6cd076eed4
32 changed files with 77 additions and 279 deletions

View File

@ -37,7 +37,6 @@
#include <utility> #include <utility>
#include <wx/tokenzr.h> #include <wx/tokenzr.h>
#include <kiface_base.h> #include <kiface_base.h>
#include <locale_io.h>
DESIGN_BLOCK_INFO* DESIGN_BLOCK_LIST::GetDesignBlockInfo( const wxString& aLibNickname, DESIGN_BLOCK_INFO* DESIGN_BLOCK_LIST::GetDesignBlockInfo( const wxString& aLibNickname,
const wxString& aDesignBlockName ) const wxString& aDesignBlockName )

View File

@ -42,7 +42,6 @@ class DESIGN_BLOCK_LIST_IMPL;
class PROGRESS_REPORTER; class PROGRESS_REPORTER;
class wxTopLevelWindow; class wxTopLevelWindow;
class KIWAY; class KIWAY;
class LOCALE_IO;
class wxTextFile; class wxTextFile;
@ -114,7 +113,7 @@ protected:
} }
/// lazily load stuff not filled in by constructor. This may throw IO_ERRORS. /// lazily load stuff not filled in by constructor. This may throw IO_ERRORS.
virtual void load( const LOCALE_IO* locale = nullptr ) {}; virtual void load() {};
protected: protected:
DESIGN_BLOCK_LIST* m_owner; ///< provides access to DESIGN_BLOCK_LIB_TABLE DESIGN_BLOCK_LIST* m_owner; ///< provides access to DESIGN_BLOCK_LIB_TABLE

View File

@ -23,7 +23,6 @@
#include <design_block.h> #include <design_block.h>
#include <design_block_lib_table.h> #include <design_block_lib_table.h>
#include <kiway.h> #include <kiway.h>
#include <locale_io.h>
#include <progress_reporter.h> #include <progress_reporter.h>
#include <string_utils.h> #include <string_utils.h>
#include <thread_pool.h> #include <thread_pool.h>
@ -35,14 +34,13 @@
#include <wx/wfstream.h> #include <wx/wfstream.h>
void DESIGN_BLOCK_INFO_IMPL::load( const LOCALE_IO* locale ) void DESIGN_BLOCK_INFO_IMPL::load()
{ {
DESIGN_BLOCK_LIB_TABLE* dbtable = m_owner->GetTable(); DESIGN_BLOCK_LIB_TABLE* dbtable = m_owner->GetTable();
wxASSERT( dbtable ); wxASSERT( dbtable );
std::unique_ptr<const DESIGN_BLOCK> design_block( dbtable->GetEnumeratedDesignBlock( m_nickname, m_dbname, std::unique_ptr<const DESIGN_BLOCK> design_block( dbtable->GetEnumeratedDesignBlock( m_nickname, m_dbname ) );
locale ) );
if( design_block ) if( design_block )
{ {
@ -148,14 +146,7 @@ bool DESIGN_BLOCK_LIST_IMPL::ReadDesignBlockFiles( DESIGN_BLOCK_LIB_TABLE* aTabl
void DESIGN_BLOCK_LIST_IMPL::loadDesignBlocks() void DESIGN_BLOCK_LIST_IMPL::loadDesignBlocks()
{ {
LOCALE_IO toggle_locale; // Parse the design_blocks in parallel.
// Parse the design_blocks in parallel. WARNING! This requires changing the locale, which is
// GLOBAL. It is only thread safe to construct the LOCALE_IO before the threads are created,
// destroy it after they finish, and block the main (GUI) thread while they work. Any deviation
// from this will cause nasal demons.
//
// TODO: blast LOCALE_IO into the sun
SYNC_QUEUE<std::unique_ptr<DESIGN_BLOCK_INFO>> queue_parsed; SYNC_QUEUE<std::unique_ptr<DESIGN_BLOCK_INFO>> queue_parsed;
@ -164,7 +155,7 @@ void DESIGN_BLOCK_LIST_IMPL::loadDesignBlocks()
std::vector<std::future<size_t>> returns( num_elements ); std::vector<std::future<size_t>> returns( num_elements );
auto db_thread = auto db_thread =
[ this, &queue_parsed, &toggle_locale ]() -> size_t [ this, &queue_parsed ]() -> size_t
{ {
wxString nickname; wxString nickname;
@ -176,7 +167,7 @@ void DESIGN_BLOCK_LIST_IMPL::loadDesignBlocks()
CatchErrors( CatchErrors(
[&]() [&]()
{ {
m_lib_table->DesignBlockEnumerate( dbnames, nickname, false, &toggle_locale ); m_lib_table->DesignBlockEnumerate( dbnames, nickname, false );
} ); } );
for( wxString dbname : dbnames ) for( wxString dbname : dbnames )
@ -184,7 +175,7 @@ void DESIGN_BLOCK_LIST_IMPL::loadDesignBlocks()
CatchErrors( CatchErrors(
[&]() [&]()
{ {
auto* dbinfo = new DESIGN_BLOCK_INFO_IMPL( this, nickname, dbname, &toggle_locale ); auto* dbinfo = new DESIGN_BLOCK_INFO_IMPL( this, nickname, dbname );
queue_parsed.move_push( std::unique_ptr<DESIGN_BLOCK_INFO>( dbinfo ) ); queue_parsed.move_push( std::unique_ptr<DESIGN_BLOCK_INFO>( dbinfo ) );
} ); } );

View File

@ -30,13 +30,11 @@
#include <design_block_info.h> #include <design_block_info.h>
#include <core/sync_queue.h> #include <core/sync_queue.h>
class LOCALE_IO;
class KICOMMON_API DESIGN_BLOCK_INFO_IMPL : public DESIGN_BLOCK_INFO class KICOMMON_API DESIGN_BLOCK_INFO_IMPL : public DESIGN_BLOCK_INFO
{ {
public: public:
DESIGN_BLOCK_INFO_IMPL( DESIGN_BLOCK_LIST* aOwner, const wxString& aNickname, DESIGN_BLOCK_INFO_IMPL( DESIGN_BLOCK_LIST* aOwner, const wxString& aNickname,
const wxString& aDesignBlockName, const LOCALE_IO* aLocale ) const wxString& aDesignBlockName )
{ {
m_nickname = aNickname; m_nickname = aNickname;
m_dbname = aDesignBlockName; m_dbname = aDesignBlockName;
@ -44,7 +42,7 @@ public:
m_owner = aOwner; m_owner = aOwner;
m_loaded = false; m_loaded = false;
load( aLocale ); load();
} }
// A constructor for cached items // A constructor for cached items
@ -73,7 +71,7 @@ public:
} }
protected: protected:
virtual void load( const LOCALE_IO* aLocale = nullptr ) override; virtual void load() override;
}; };

View File

@ -39,7 +39,6 @@
#include <wx/dir.h> #include <wx/dir.h>
#include <wx/hash.h> #include <wx/hash.h>
#include <locale_io.h>
#define OPT_SEP '|' ///< options separator character #define OPT_SEP '|' ///< options separator character
@ -334,23 +333,13 @@ long long DESIGN_BLOCK_LIB_TABLE::GenerateTimestamp( const wxString* aNickname )
void DESIGN_BLOCK_LIB_TABLE::DesignBlockEnumerate( wxArrayString& aDesignBlockNames, const wxString& aNickname, void DESIGN_BLOCK_LIB_TABLE::DesignBlockEnumerate( wxArrayString& aDesignBlockNames, const wxString& aNickname,
bool aBestEfforts, const LOCALE_IO* aLocale ) bool aBestEfforts )
{ {
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin ); wxASSERT( row->plugin );
if( !aLocale ) row->plugin->DesignBlockEnumerate( aDesignBlockNames, row->GetFullURI( true ), aBestEfforts,
{ row->GetProperties() );
LOCALE_IO toggle_locale;
row->plugin->DesignBlockEnumerate( aDesignBlockNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
}
else
{
row->plugin->DesignBlockEnumerate( aDesignBlockNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
}
} }
@ -401,34 +390,19 @@ static void setLibNickname( DESIGN_BLOCK* aModule, const wxString& aNickname,
const DESIGN_BLOCK* const DESIGN_BLOCK*
DESIGN_BLOCK_LIB_TABLE::GetEnumeratedDesignBlock( const wxString& aNickname, DESIGN_BLOCK_LIB_TABLE::GetEnumeratedDesignBlock( const wxString& aNickname,
const wxString& aDesignBlockName, const wxString& aDesignBlockName )
const LOCALE_IO* aLocale )
{ {
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin ); wxASSERT( row->plugin );
if( !aLocale ) return row->plugin->GetEnumeratedDesignBlock( row->GetFullURI( true ), aDesignBlockName,
{ row->GetProperties() );
LOCALE_IO toggle_locale;
return row->plugin->GetEnumeratedDesignBlock( row->GetFullURI( true ), aDesignBlockName,
row->GetProperties() );
}
else
{
return row->plugin->GetEnumeratedDesignBlock( row->GetFullURI( true ), aDesignBlockName,
row->GetProperties() );
}
} }
bool DESIGN_BLOCK_LIB_TABLE::DesignBlockExists( const wxString& aNickname, bool DESIGN_BLOCK_LIB_TABLE::DesignBlockExists( const wxString& aNickname,
const wxString& aDesignBlockName ) const wxString& aDesignBlockName )
{ {
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
try try
{ {
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
@ -448,10 +422,6 @@ DESIGN_BLOCK* DESIGN_BLOCK_LIB_TABLE::DesignBlockLoad( const wxString& aNickname
const wxString& aDesignBlockName, const wxString& aDesignBlockName,
bool aKeepUUID ) bool aKeepUUID )
{ {
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin ); wxASSERT( row->plugin );
@ -468,10 +438,6 @@ DESIGN_BLOCK_LIB_TABLE::SAVE_T
DESIGN_BLOCK_LIB_TABLE::DesignBlockSave( const wxString& aNickname, DESIGN_BLOCK_LIB_TABLE::DesignBlockSave( const wxString& aNickname,
const DESIGN_BLOCK* aDesignBlock, bool aOverwrite ) const DESIGN_BLOCK* aDesignBlock, bool aOverwrite )
{ {
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const DESIGN_BLOCK_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin ); wxASSERT( row->plugin );

View File

@ -39,7 +39,6 @@
#include <utility> #include <utility>
#include <wx/tokenzr.h> #include <wx/tokenzr.h>
#include <kiface_base.h> #include <kiface_base.h>
#include <locale_io.h>
FOOTPRINT_INFO* FOOTPRINT_LIST::GetFootprintInfo( const wxString& aLibNickname, FOOTPRINT_INFO* FOOTPRINT_LIST::GetFootprintInfo( const wxString& aLibNickname,
const wxString& aFootprintName ) const wxString& aFootprintName )

View File

@ -40,7 +40,6 @@
#include <wx/dir.h> #include <wx/dir.h>
#include <wx/hash.h> #include <wx/hash.h>
#include <locale_io.h>
#define OPT_SEP '|' ///< options separator character #define OPT_SEP '|' ///< options separator character
@ -313,23 +312,13 @@ long long FP_LIB_TABLE::GenerateTimestamp( const wxString* aNickname )
void FP_LIB_TABLE::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aNickname, void FP_LIB_TABLE::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aNickname,
bool aBestEfforts, const LOCALE_IO* aLocale ) bool aBestEfforts )
{ {
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin ); wxASSERT( row->plugin );
if( !aLocale ) row->plugin->FootprintEnumerate( aFootprintNames, row->GetFullURI( true ), aBestEfforts,
{ row->GetProperties() );
LOCALE_IO toggle_locale;
row->plugin->FootprintEnumerate( aFootprintNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
}
else
{
row->plugin->FootprintEnumerate( aFootprintNames, row->GetFullURI( true ), aBestEfforts,
row->GetProperties() );
}
} }
@ -379,33 +368,18 @@ static void setLibNickname( FOOTPRINT* aModule, const wxString& aNickname,
const FOOTPRINT* FP_LIB_TABLE::GetEnumeratedFootprint( const wxString& aNickname, const FOOTPRINT* FP_LIB_TABLE::GetEnumeratedFootprint( const wxString& aNickname,
const wxString& aFootprintName, const wxString& aFootprintName )
const LOCALE_IO* aLocale )
{ {
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin ); wxASSERT( row->plugin );
if( !aLocale ) return row->plugin->GetEnumeratedFootprint( row->GetFullURI( true ), aFootprintName,
{ row->GetProperties() );
LOCALE_IO toggle_locale;
return row->plugin->GetEnumeratedFootprint( row->GetFullURI( true ), aFootprintName,
row->GetProperties() );
}
else
{
return row->plugin->GetEnumeratedFootprint( row->GetFullURI( true ), aFootprintName,
row->GetProperties() );
}
} }
bool FP_LIB_TABLE::FootprintExists( const wxString& aNickname, const wxString& aFootprintName ) bool FP_LIB_TABLE::FootprintExists( const wxString& aNickname, const wxString& aFootprintName )
{ {
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
try try
{ {
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
@ -424,10 +398,6 @@ bool FP_LIB_TABLE::FootprintExists( const wxString& aNickname, const wxString& a
FOOTPRINT* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname, FOOTPRINT* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname,
const wxString& aFootprintName, bool aKeepUUID ) const wxString& aFootprintName, bool aKeepUUID )
{ {
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin ); wxASSERT( row->plugin );
@ -443,10 +413,6 @@ FOOTPRINT* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname,
FP_LIB_TABLE::SAVE_T FP_LIB_TABLE::FootprintSave( const wxString& aNickname, FP_LIB_TABLE::SAVE_T FP_LIB_TABLE::FootprintSave( const wxString& aNickname,
const FOOTPRINT* aFootprint, bool aOverwrite ) const FOOTPRINT* aFootprint, bool aOverwrite )
{ {
// NOT THREAD-SAFE! LOCALE_IO is global!
LOCALE_IO toggle_locale;
const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true ); const FP_LIB_TABLE_ROW* row = FindRow( aNickname, true );
wxASSERT( row->plugin ); wxASSERT( row->plugin );

View File

@ -24,8 +24,6 @@
#include <sch_io/eagle/sch_io_eagle.h> #include <sch_io/eagle/sch_io_eagle.h>
#include <locale_io.h>
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <wx/filename.h> #include <wx/filename.h>
@ -351,7 +349,6 @@ SCH_SHEET* SCH_IO_EAGLE::LoadSchematicFile( const wxString& aFileName, SCHEMATIC
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
wxASSERT( !aFileName || aSchematic != nullptr ); wxASSERT( !aFileName || aSchematic != nullptr );
LOCALE_IO toggle; // toggles on, then off, the C locale.
// Show the font substitution warnings // Show the font substitution warnings
fontconfig::FONTCONFIG::SetReporter( &WXLOG_REPORTER::GetInstance() ); fontconfig::FONTCONFIG::SetReporter( &WXLOG_REPORTER::GetInstance() );
@ -559,8 +556,6 @@ void SCH_IO_EAGLE::ensureLoadedLibrary( const wxString& aLibraryPath )
return; return;
} }
LOCALE_IO toggle; // toggles on, then off, the C locale.
if( m_progressReporter ) if( m_progressReporter )
{ {
m_progressReporter->Report( wxString::Format( _( "Loading %s..." ), aLibraryPath ) ); m_progressReporter->Report( wxString::Format( _( "Loading %s..." ), aLibraryPath ) );

View File

@ -37,7 +37,6 @@
#include <fmt/format.h> #include <fmt/format.h>
#include <kiway.h> #include <kiway.h>
#include <string_utils.h> #include <string_utils.h>
#include <locale_io.h>
#include <richio.h> #include <richio.h>
#include <trace_helpers.h> #include <trace_helpers.h>
#include <trigo.h> #include <trigo.h>
@ -130,9 +129,7 @@ SCH_SHEET* SCH_IO_KICAD_LEGACY::LoadSchematicFile( const wxString& aFileName, SC
{ {
wxASSERT( !aFileName || aSchematic != nullptr ); wxASSERT( !aFileName || aSchematic != nullptr );
LOCALE_IO toggle; // toggles on, then off, the C locale.
SCH_SHEET* sheet; SCH_SHEET* sheet;
wxFileName fn = aFileName; wxFileName fn = aFileName;
// Unfortunately child sheet file names the legacy schematic file format are not fully // Unfortunately child sheet file names the legacy schematic file format are not fully
@ -1502,8 +1499,6 @@ void SCH_IO_KICAD_LEGACY::SaveSchematicFile( const wxString& aFileName, SCH_SHEE
wxCHECK_RET( aSheet != nullptr, "NULL SCH_SHEET object." ); wxCHECK_RET( aSheet != nullptr, "NULL SCH_SHEET object." );
wxCHECK_RET( !aFileName.IsEmpty(), "No schematic file name defined." ); wxCHECK_RET( !aFileName.IsEmpty(), "No schematic file name defined." );
LOCALE_IO toggle; // toggles on, then off, the C locale, to write floating point values.
init( aSchematic, aProperties ); init( aSchematic, aProperties );
wxFileName fn = aFileName; wxFileName fn = aFileName;
@ -1804,7 +1799,7 @@ void SCH_IO_KICAD_LEGACY::saveBitmap( const SCH_BITMAP& aBitmap )
m_out->Print( 0, "Pos %-4d %-4d\n", m_out->Print( 0, "Pos %-4d %-4d\n",
schIUScale.IUToMils( aBitmap.GetPosition().x ), schIUScale.IUToMils( aBitmap.GetPosition().x ),
schIUScale.IUToMils( aBitmap.GetPosition().y ) ); schIUScale.IUToMils( aBitmap.GetPosition().y ) );
m_out->Print( "%s", fmt::format("Scale {:g}\n atof", refImage.GetImageScale()).c_str() ); m_out->Print( "%s", fmt::format("Scale {:g}\n", refImage.GetImageScale()).c_str() );
m_out->Print( 0, "Data\n" ); m_out->Print( 0, "Data\n" );
wxMemoryOutputStream stream; wxMemoryOutputStream stream;
@ -2123,8 +2118,6 @@ void SCH_IO_KICAD_LEGACY::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
const wxString& aLibraryPath, const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
bool powerSymbolsOnly = ( aProperties && bool powerSymbolsOnly = ( aProperties &&
aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() ); aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
@ -2144,8 +2137,6 @@ void SCH_IO_KICAD_LEGACY::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolL
const wxString& aLibraryPath, const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
bool powerSymbolsOnly = ( aProperties && bool powerSymbolsOnly = ( aProperties &&
aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() ); aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
@ -2165,8 +2156,6 @@ LIB_SYMBOL* SCH_IO_KICAD_LEGACY::LoadSymbol( const wxString& aLibraryPath,
const wxString& aSymbolName, const wxString& aSymbolName,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
cacheLib( aLibraryPath, aProperties ); cacheLib( aLibraryPath, aProperties );
LIB_SYMBOL_MAP::const_iterator it = m_cache->m_symbols.find( aSymbolName ); LIB_SYMBOL_MAP::const_iterator it = m_cache->m_symbols.find( aSymbolName );
@ -2181,8 +2170,6 @@ LIB_SYMBOL* SCH_IO_KICAD_LEGACY::LoadSymbol( const wxString& aLibraryPath,
void SCH_IO_KICAD_LEGACY::SaveSymbol( const wxString& aLibraryPath, const LIB_SYMBOL* aSymbol, void SCH_IO_KICAD_LEGACY::SaveSymbol( const wxString& aLibraryPath, const LIB_SYMBOL* aSymbol,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
cacheLib( aLibraryPath, aProperties ); cacheLib( aLibraryPath, aProperties );
m_cache->AddSymbol( aSymbol ); m_cache->AddSymbol( aSymbol );
@ -2195,8 +2182,6 @@ void SCH_IO_KICAD_LEGACY::SaveSymbol( const wxString& aLibraryPath, const LIB_SY
void SCH_IO_KICAD_LEGACY::DeleteSymbol( const wxString& aLibraryPath, const wxString& aSymbolName, void SCH_IO_KICAD_LEGACY::DeleteSymbol( const wxString& aLibraryPath, const wxString& aSymbolName,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
cacheLib( aLibraryPath, aProperties ); cacheLib( aLibraryPath, aProperties );
m_cache->DeleteSymbol( aSymbolName ); m_cache->DeleteSymbol( aSymbolName );
@ -2215,8 +2200,6 @@ void SCH_IO_KICAD_LEGACY::CreateLibrary( const wxString& aLibraryPath,
aLibraryPath.GetData() ) ); aLibraryPath.GetData() ) );
} }
LOCALE_IO toggle;
delete m_cache; delete m_cache;
m_cache = new SCH_IO_KICAD_LEGACY_LIB_CACHE( aLibraryPath ); m_cache = new SCH_IO_KICAD_LEGACY_LIB_CACHE( aLibraryPath );
m_cache->SetModified(); m_cache->SetModified();

View File

@ -33,7 +33,6 @@
#include <sch_selection.h> #include <sch_selection.h>
#include <font/fontconfig.h> #include <font/fontconfig.h>
#include <io/kicad/kicad_io_utils.h> #include <io/kicad/kicad_io_utils.h>
#include <locale_io.h>
#include <progress_reporter.h> #include <progress_reporter.h>
#include <schematic.h> #include <schematic.h>
#include <schematic_lexer.h> #include <schematic_lexer.h>
@ -101,7 +100,6 @@ SCH_SHEET* SCH_IO_KICAD_SEXPR::LoadSchematicFile( const wxString& aFileName, SCH
{ {
wxASSERT( !aFileName || aSchematic != nullptr ); wxASSERT( !aFileName || aSchematic != nullptr );
LOCALE_IO toggle; // toggles on, then off, the C locale.
SCH_SHEET* sheet; SCH_SHEET* sheet;
wxFileName fn = aFileName; wxFileName fn = aFileName;
@ -324,7 +322,6 @@ void SCH_IO_KICAD_SEXPR::LoadContent( LINE_READER& aReader, SCH_SHEET* aSheet, i
{ {
wxCHECK( aSheet, /* void */ ); wxCHECK( aSheet, /* void */ );
LOCALE_IO toggle;
SCH_IO_KICAD_SEXPR_PARSER parser( &aReader ); SCH_IO_KICAD_SEXPR_PARSER parser( &aReader );
parser.ParseSchematic( aSheet, true, aFileVersion ); parser.ParseSchematic( aSheet, true, aFileVersion );
@ -338,8 +335,6 @@ void SCH_IO_KICAD_SEXPR::SaveSchematicFile( const wxString& aFileName, SCH_SHEET
wxCHECK_RET( aSheet != nullptr, "NULL SCH_SHEET object." ); wxCHECK_RET( aSheet != nullptr, "NULL SCH_SHEET object." );
wxCHECK_RET( !aFileName.IsEmpty(), "No schematic file name defined." ); wxCHECK_RET( !aFileName.IsEmpty(), "No schematic file name defined." );
LOCALE_IO toggle; // toggles on, then off, the C locale, to write floating point values.
wxString sanityResult = aSheet->GetScreen()->GroupsSanityCheck(); wxString sanityResult = aSheet->GetScreen()->GroupsSanityCheck();
if( sanityResult != wxEmptyString && m_queryUserCallback ) if( sanityResult != wxEmptyString && m_queryUserCallback )
@ -520,7 +515,6 @@ void SCH_IO_KICAD_SEXPR::Format( SCH_SELECTION* aSelection, SCH_SHEET_PATH* aSel
{ {
wxCHECK( aSelection && aSelectionPath && aFormatter, /* void */ ); wxCHECK( aSelection && aSelectionPath && aFormatter, /* void */ );
LOCALE_IO toggle;
SCH_SHEET_LIST sheets = aSchematic.Hierarchy(); SCH_SHEET_LIST sheets = aSchematic.Hierarchy();
m_schematic = &aSchematic; m_schematic = &aSchematic;
@ -1583,8 +1577,6 @@ void SCH_IO_KICAD_SEXPR::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
const wxString& aLibraryPath, const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
bool powerSymbolsOnly = ( aProperties && bool powerSymbolsOnly = ( aProperties &&
aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() ); aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
@ -1604,8 +1596,6 @@ void SCH_IO_KICAD_SEXPR::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolLi
const wxString& aLibraryPath, const wxString& aLibraryPath,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
bool powerSymbolsOnly = ( aProperties && bool powerSymbolsOnly = ( aProperties &&
aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() ); aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
@ -1625,8 +1615,6 @@ LIB_SYMBOL* SCH_IO_KICAD_SEXPR::LoadSymbol( const wxString& aLibraryPath,
const wxString& aSymbolName, const wxString& aSymbolName,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
cacheLib( aLibraryPath, aProperties ); cacheLib( aLibraryPath, aProperties );
LIB_SYMBOL_MAP::const_iterator it = m_cache->m_symbols.find( aSymbolName ); LIB_SYMBOL_MAP::const_iterator it = m_cache->m_symbols.find( aSymbolName );
@ -1652,8 +1640,6 @@ LIB_SYMBOL* SCH_IO_KICAD_SEXPR::LoadSymbol( const wxString& aLibraryPath,
void SCH_IO_KICAD_SEXPR::SaveSymbol( const wxString& aLibraryPath, const LIB_SYMBOL* aSymbol, void SCH_IO_KICAD_SEXPR::SaveSymbol( const wxString& aLibraryPath, const LIB_SYMBOL* aSymbol,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
cacheLib( aLibraryPath, aProperties ); cacheLib( aLibraryPath, aProperties );
m_cache->AddSymbol( aSymbol ); m_cache->AddSymbol( aSymbol );
@ -1666,8 +1652,6 @@ void SCH_IO_KICAD_SEXPR::SaveSymbol( const wxString& aLibraryPath, const LIB_SYM
void SCH_IO_KICAD_SEXPR::DeleteSymbol( const wxString& aLibraryPath, const wxString& aSymbolName, void SCH_IO_KICAD_SEXPR::DeleteSymbol( const wxString& aLibraryPath, const wxString& aSymbolName,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
cacheLib( aLibraryPath, aProperties ); cacheLib( aLibraryPath, aProperties );
m_cache->DeleteSymbol( aSymbolName ); m_cache->DeleteSymbol( aSymbolName );
@ -1686,8 +1670,6 @@ void SCH_IO_KICAD_SEXPR::CreateLibrary( const wxString& aLibraryPath,
aLibraryPath.GetData() ) ); aLibraryPath.GetData() ) );
} }
LOCALE_IO toggle;
delete m_cache; delete m_cache;
m_cache = new SCH_IO_KICAD_SEXPR_LIB_CACHE( aLibraryPath ); m_cache = new SCH_IO_KICAD_SEXPR_LIB_CACHE( aLibraryPath );
m_cache->SetModified(); m_cache->SetModified();
@ -1802,7 +1784,6 @@ std::vector<LIB_SYMBOL*> SCH_IO_KICAD_SEXPR::ParseLibSymbols( std::string& aSymb
std::string aSource, std::string aSource,
int aFileVersion ) int aFileVersion )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
LIB_SYMBOL* newSymbol = nullptr; LIB_SYMBOL* newSymbol = nullptr;
LIB_SYMBOL_MAP map; LIB_SYMBOL_MAP map;
@ -1829,7 +1810,6 @@ std::vector<LIB_SYMBOL*> SCH_IO_KICAD_SEXPR::ParseLibSymbols( std::string& aSymb
void SCH_IO_KICAD_SEXPR::FormatLibSymbol( LIB_SYMBOL* symbol, OUTPUTFORMATTER & formatter ) void SCH_IO_KICAD_SEXPR::FormatLibSymbol( LIB_SYMBOL* symbol, OUTPUTFORMATTER & formatter )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( symbol, formatter ); SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( symbol, formatter );
} }

View File

@ -28,7 +28,6 @@
#include <sch_shape.h> #include <sch_shape.h>
#include <lib_symbol.h> #include <lib_symbol.h>
#include <sch_textbox.h> #include <sch_textbox.h>
#include <locale_io.h>
#include <macros.h> #include <macros.h>
#include <richio.h> #include <richio.h>
#include "sch_io_kicad_sexpr_lib_cache.h" #include "sch_io_kicad_sexpr_lib_cache.h"
@ -63,10 +62,6 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::Load()
wxString::Format( "Cannot use relative file paths in sexpr plugin to " wxString::Format( "Cannot use relative file paths in sexpr plugin to "
"open library '%s'.", m_libFileName.GetFullPath() ) ); "open library '%s'.", m_libFileName.GetFullPath() ) );
// The current locale must use period as the decimal point.
// Yes, we did this earlier, but it's sadly not thread-safe.
LOCALE_IO toggle;
wxLogTrace( traceSchLegacyPlugin, "Loading sexpr symbol library file '%s'", wxLogTrace( traceSchLegacyPlugin, "Loading sexpr symbol library file '%s'",
m_libFileName.GetFullPath() ); m_libFileName.GetFullPath() );
@ -89,8 +84,6 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::Save( const std::optional<bool>& aOpt )
if( !m_isModified ) if( !m_isModified )
return; return;
LOCALE_IO toggle; // toggles on, then off, the C locale.
// Write through symlinks, don't replace them. // Write through symlinks, don't replace them.
wxFileName fn = GetRealFile(); wxFileName fn = GetRealFile();
@ -139,11 +132,6 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMAT
{ {
wxCHECK_RET( aSymbol, "Invalid LIB_SYMBOL pointer." ); wxCHECK_RET( aSymbol, "Invalid LIB_SYMBOL pointer." );
// The current locale must use period as the decimal point.
wxCHECK2( wxLocale::GetInfo( wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER ) == ".",
LOCALE_IO toggle );
// If we've requested to embed the fonts in the symbol, do so. // If we've requested to embed the fonts in the symbol, do so.
// Otherwise, clear the embedded fonts from the symbol. Embedded // Otherwise, clear the embedded fonts from the symbol. Embedded
// fonts will be used if available // fonts will be used if available

View File

@ -74,7 +74,6 @@
#include <macros.h> #include <macros.h>
#include <richio.h> #include <richio.h>
#include <string_utils.h> #include <string_utils.h>
#include <locale_io.h>
#include <X2_gerber_attributes.h> #include <X2_gerber_attributes.h>
#include <view/view.h> #include <view/view.h>
#include <gerbview_settings.h> #include <gerbview_settings.h>
@ -481,8 +480,6 @@ bool EXCELLON_IMAGE::LoadFile( const wxString & aFullFileName, EXCELLON_DEFAULTS
wxString msg; wxString msg;
m_FileName = aFullFileName; m_FileName = aFullFileName;
LOCALE_IO toggleIo;
// FILE_LINE_READER will close the file. // FILE_LINE_READER will close the file.
FILE_LINE_READER excellonReader( m_Current_File, m_FileName ); FILE_LINE_READER excellonReader( m_Current_File, m_FileName );

View File

@ -28,7 +28,6 @@
#include <confirm.h> #include <confirm.h>
#include <string_utils.h> #include <string_utils.h>
#include <locale_io.h>
#include <lset.h> #include <lset.h>
#include <macros.h> #include <macros.h>
#include <trigo.h> #include <trigo.h>
@ -57,8 +56,6 @@ GBR_TO_PCB_EXPORTER::~GBR_TO_PCB_EXPORTER()
bool GBR_TO_PCB_EXPORTER::ExportPcb( const int* aLayerLookUpTable, int aCopperLayers ) bool GBR_TO_PCB_EXPORTER::ExportPcb( const int* aLayerLookUpTable, int aCopperLayers )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
m_fp = wxFopen( m_pcb_file_name, wxT( "wt" ) ); m_fp = wxFopen( m_pcb_file_name, wxT( "wt" ) );
if( m_fp == nullptr ) if( m_fp == nullptr )

View File

@ -32,7 +32,6 @@
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <gerbview.h> #include <gerbview.h>
#include <richio.h> #include <richio.h>
#include <locale_io.h>
#include <string_utils.h> #include <string_utils.h>
#include <gerber_file_image.h> #include <gerber_file_image.h>
#include <gerber_file_image_list.h> #include <gerber_file_image_list.h>
@ -111,8 +110,6 @@ bool GERBER_JOBFILE_READER::ReadGerberJobFile()
if( jobFile == nullptr ) if( jobFile == nullptr )
return false; return false;
LOCALE_IO toggleIo;
FILE_LINE_READER jobfileReader( jobFile, m_filename.GetFullPath() ); // Will close jobFile FILE_LINE_READER jobfileReader( jobFile, m_filename.GetFullPath() ); // Will close jobFile
wxString data; wxString data;

View File

@ -24,7 +24,6 @@
#include "ki_exception.h" #include "ki_exception.h"
#include <string_utils.h> #include <string_utils.h>
#include <locale_io.h>
#include <gerbview.h> #include <gerbview.h>
#include <gerbview_frame.h> #include <gerbview_frame.h>
#include <gerber_file_image.h> #include <gerber_file_image.h>
@ -245,8 +244,6 @@ bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
m_FileName = aFullFileName; m_FileName = aFullFileName;
LOCALE_IO toggleIo;
wxString msg; wxString msg;
while( true ) while( true )

View File

@ -114,7 +114,9 @@ VECTOR2I GERBER_FILE_IMAGE::ReadXYCoord( char*& aText, bool aExcellonMode )
line.push_back( *( aText++ ) ); line.push_back( *( aText++ ) );
} }
double val = strtod( line.data(), nullptr ); double val;
wxString text( line.data() );
text.ToCDouble( &val );
if( is_float ) if( is_float )
{ {
@ -202,7 +204,10 @@ VECTOR2I GERBER_FILE_IMAGE::ReadIJCoord( char*& aText )
line.push_back( *( aText++ ) ); line.push_back( *( aText++ ) );
} }
double val = strtod( line.data(), nullptr ); double val;
wxString text( line.data() );
text.Trim( true ).Trim( false );
text.ToCDouble( &val );
if( is_float ) if( is_float )
{ {
@ -314,7 +319,21 @@ double ReadDouble( char*& text, bool aSkipSeparator = true )
} }
else else
{ {
ret = strtod( text, &text ); wxString line( text );
auto endpos = line.find_first_not_of( "0123456789.-+eE" );
line.Trim( false );
line.ToCDouble( &ret );
if( endpos != wxString::npos )
{
// Advance the text pointer to the end of the number
text += endpos;
}
else
{
// If no non-number characters found, advance to the end of the string
text += line.length();
}
} }
if( *text == ',' || isspace( *text ) ) if( *text == ',' || isspace( *text ) )

View File

@ -158,13 +158,11 @@ public:
* \a aNickname. * \a aNickname.
* @param aNickname is a locator for the "library", it is a "name" in LIB_TABLE_ROW. * @param aNickname is a locator for the "library", it is a "name" in LIB_TABLE_ROW.
* @param aBestEfforts if true, don't throw on errors. * @param aBestEfforts if true, don't throw on errors.
* @param aLocale a previously set-up locale. Currently required for multi-threading, as LOCALE_IO
* uses global storage.
* *
* @throw IO_ERROR if the library cannot be found, or design block cannot be loaded. * @throw IO_ERROR if the library cannot be found, or design block cannot be loaded.
*/ */
void DesignBlockEnumerate( wxArrayString& aDesignBlockNames, const wxString& aNickname, void DesignBlockEnumerate( wxArrayString& aDesignBlockNames, const wxString& aNickname,
bool aBestEfforts, const LOCALE_IO* aLocale = nullptr ); bool aBestEfforts );
/** /**
* Generate a hashed timestamp representing the last-mod-times of the library indicated * Generate a hashed timestamp representing the last-mod-times of the library indicated
@ -202,8 +200,7 @@ public:
* *
* The return value is const to allow it to return a reference to a cached item. * The return value is const to allow it to return a reference to a cached item.
*/ */
const DESIGN_BLOCK* GetEnumeratedDesignBlock( const wxString& aNickname, const wxString& aDesignBlockName, const DESIGN_BLOCK* GetEnumeratedDesignBlock( const wxString& aNickname, const wxString& aDesignBlockName );
const LOCALE_IO* aLocale = nullptr );
/** /**
* The set of return values from DesignBlockSave() below. * The set of return values from DesignBlockSave() below.
*/ */

View File

@ -46,7 +46,6 @@ class FOOTPRINT_LIST_IMPL;
class PROGRESS_REPORTER; class PROGRESS_REPORTER;
class wxTopLevelWindow; class wxTopLevelWindow;
class KIWAY; class KIWAY;
class LOCALE_IO;
class wxTextFile; class wxTextFile;
@ -135,7 +134,7 @@ protected:
} }
/// lazily load stuff not filled in by constructor. This may throw IO_ERRORS. /// lazily load stuff not filled in by constructor. This may throw IO_ERRORS.
virtual void load( const LOCALE_IO* aLocale = nullptr ) { }; virtual void load() { };
FOOTPRINT_LIST* m_owner; ///< provides access to FP_LIB_TABLE FOOTPRINT_LIST* m_owner; ///< provides access to FP_LIB_TABLE

View File

@ -32,7 +32,6 @@
class FOOTPRINT; class FOOTPRINT;
class FP_LIB_TABLE_GRID; class FP_LIB_TABLE_GRID;
class PCB_IO; class PCB_IO;
class LOCALE_IO;
/** /**
@ -144,13 +143,11 @@ public:
* @param aFootprintNames is the list to fill with the footprint names found in \a aNickname * @param aFootprintNames is the list to fill with the footprint names found in \a aNickname
* @param aNickname is a locator for the "library", it is a "name" in LIB_TABLE_ROW. * @param aNickname is a locator for the "library", it is a "name" in LIB_TABLE_ROW.
* @param aBestEfforts if true, don't throw on errors. * @param aBestEfforts if true, don't throw on errors.
* @param aLocale a previously set-up locale. Currently required for multi-threading, as LOCALE_IO
* uses global storage.
* *
* @throw IO_ERROR if the library cannot be found, or footprint cannot be loaded. * @throw IO_ERROR if the library cannot be found, or footprint cannot be loaded.
*/ */
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aNickname, void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aNickname,
bool aBestEfforts, const LOCALE_IO* aLocale = nullptr ); bool aBestEfforts );
/** /**
* Generate a hashed timestamp representing the last-mod-times of the library indicated * Generate a hashed timestamp representing the last-mod-times of the library indicated
@ -183,14 +180,10 @@ public:
* A version of #FootprintLoad() for use after #FootprintEnumerate() for more efficient * A version of #FootprintLoad() for use after #FootprintEnumerate() for more efficient
* cache management. * cache management.
* *
* @param aLocale a previously set-up locale. Currently required for multi-threading, as LOCALE_IO
* uses global storage.
*
* The return value is const to allow it to return a reference to a cached item. * The return value is const to allow it to return a reference to a cached item.
*/ */
const FOOTPRINT* GetEnumeratedFootprint( const wxString& aNickname, const FOOTPRINT* GetEnumeratedFootprint( const wxString& aNickname,
const wxString& aFootprintName, const wxString& aFootprintName );
const LOCALE_IO* aLocale = nullptr );
/** /**
* The set of return values from FootprintSave() below. * The set of return values from FootprintSave() below.
*/ */

View File

@ -22,6 +22,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <fmt/format.h>
#include <wx/app.h> #include <wx/app.h>
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
@ -30,7 +32,6 @@
#include <class_regulator_data.h> #include <class_regulator_data.h>
#include <datafile_read_write.h> #include <datafile_read_write.h>
#include <string_utils.h> #include <string_utils.h>
#include <locale_io.h>
#include <macros.h> #include <macros.h>
#include <pcb_calculator_datafile_lexer.h> #include <pcb_calculator_datafile_lexer.h>
#include <pcb_calculator_frame.h> #include <pcb_calculator_frame.h>
@ -53,8 +54,6 @@ bool PANEL_REGULATOR::ReadDataFile()
if( file == nullptr ) if( file == nullptr )
return false; return false;
// Switch the locale to standard C (needed to read/write floating point numbers)
LOCALE_IO toggle;
m_RegulatorList.Clear(); m_RegulatorList.Clear();
PCB_CALCULATOR_DATAFILE* datafile = new PCB_CALCULATOR_DATAFILE( &m_RegulatorList ); PCB_CALCULATOR_DATAFILE* datafile = new PCB_CALCULATOR_DATAFILE( &m_RegulatorList );
@ -92,9 +91,6 @@ bool PANEL_REGULATOR::ReadDataFile()
bool PANEL_REGULATOR::WriteDataFile() bool PANEL_REGULATOR::WriteDataFile()
{ {
// Switch the locale to standard C (needed to read/write floating point numbers)
LOCALE_IO toggle;
auto datafile = std::make_unique<PCB_CALCULATOR_DATAFILE>( &m_RegulatorList ); auto datafile = std::make_unique<PCB_CALCULATOR_DATAFILE>( &m_RegulatorList );
try try
@ -155,19 +151,19 @@ void PCB_CALCULATOR_DATAFILE::Format( OUTPUTFORMATTER* aFormatter,
aFormatter->Print( aNestLevel, "(%s %s\n", getTokenName( T_regulator ), aFormatter->Print( aNestLevel, "(%s %s\n", getTokenName( T_regulator ),
aFormatter->Quotew( item->m_Name ).c_str() ); aFormatter->Quotew( item->m_Name ).c_str() );
aFormatter->Print( aNestLevel + 1, "(%s %g)\n", getTokenName( T_reg_vref_min ), aFormatter->Print( aNestLevel + 1, "%s", fmt::format( "({} {:g})\n", getTokenName( T_reg_vref_min ),
item->m_VrefMin ); item->m_VrefMin ).c_str() );
aFormatter->Print( aNestLevel + 1, "(%s %g)\n", getTokenName( T_reg_vref_typ ), aFormatter->Print( aNestLevel + 1, "%s", fmt::format( "({} {:g})\n", getTokenName( T_reg_vref_typ ),
item->m_VrefTyp ); item->m_VrefTyp ).c_str() );
aFormatter->Print( aNestLevel + 1, "(%s %g)\n", getTokenName( T_reg_vref_max ), aFormatter->Print( aNestLevel + 1, "%s", fmt::format( "({} {:g})\n", getTokenName( T_reg_vref_max ),
item->m_VrefMax ); item->m_VrefMax ).c_str() );
if( item->m_Type == 1 ) if( item->m_Type == 1 )
{ {
aFormatter->Print( aNestLevel + 1, "(%s %g)\n", getTokenName( T_reg_iadj_typ ), aFormatter->Print( aNestLevel + 1, "%s", fmt::format( "({} {:g})\n", getTokenName( T_reg_iadj_typ ),
item->m_IadjTyp ); item->m_IadjTyp ).c_str() );
aFormatter->Print( aNestLevel + 1, "(%s %g)\n", getTokenName( T_reg_iadj_max ), aFormatter->Print( aNestLevel + 1, "%s", fmt::format( "({} {:g})\n", getTokenName( T_reg_iadj_max ),
item->m_IadjMax ); item->m_IadjMax ).c_str() );
} }
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_reg_type ), aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_reg_type ),
@ -233,7 +229,10 @@ void PCB_CALCULATOR_DATAFILE_PARSER::ParseRegulatorDescr( PCB_CALCULATOR_DATAFIL
if( token != T_NUMBER ) if( token != T_NUMBER )
Expecting( T_NUMBER ); Expecting( T_NUMBER );
sscanf( CurText(), "%lf", &val ); wxString text = CurText();
text.Trim( true ).Trim( false );
text.ToCDouble( &val );
NeedRIGHT(); NeedRIGHT();
return val; return val;
}; };

View File

@ -27,7 +27,6 @@
#include <footprint_info.h> #include <footprint_info.h>
#include <fp_lib_table.h> #include <fp_lib_table.h>
#include <kiway.h> #include <kiway.h>
#include <locale_io.h>
#include <lib_id.h> #include <lib_id.h>
#include <progress_reporter.h> #include <progress_reporter.h>
#include <string_utils.h> #include <string_utils.h>
@ -41,13 +40,13 @@
#include <wx/wfstream.h> #include <wx/wfstream.h>
void FOOTPRINT_INFO_IMPL::load( const LOCALE_IO* aLocale ) void FOOTPRINT_INFO_IMPL::load()
{ {
FP_LIB_TABLE* fptable = m_owner->GetTable(); FP_LIB_TABLE* fptable = m_owner->GetTable();
wxASSERT( fptable ); wxASSERT( fptable );
const FOOTPRINT* footprint = fptable->GetEnumeratedFootprint( m_nickname, m_fpname, aLocale ); const FOOTPRINT* footprint = fptable->GetEnumeratedFootprint( m_nickname, m_fpname );
if( footprint == nullptr ) // Should happen only with malformed/broken libraries if( footprint == nullptr ) // Should happen only with malformed/broken libraries
{ {
@ -165,14 +164,7 @@ bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxStri
void FOOTPRINT_LIST_IMPL::loadFootprints() void FOOTPRINT_LIST_IMPL::loadFootprints()
{ {
LOCALE_IO toggle_locale; // Parse the footprints in parallel.
// Parse the footprints in parallel. WARNING! This requires changing the locale, which is
// GLOBAL. It is only thread safe to construct the LOCALE_IO before the threads are created,
// destroy it after they finish, and block the main (GUI) thread while they work. Any deviation
// from this will cause nasal demons.
//
// TODO: blast LOCALE_IO into the sun
SYNC_QUEUE<std::unique_ptr<FOOTPRINT_INFO>> queue_parsed; SYNC_QUEUE<std::unique_ptr<FOOTPRINT_INFO>> queue_parsed;
thread_pool& tp = GetKiCadThreadPool(); thread_pool& tp = GetKiCadThreadPool();
@ -180,7 +172,7 @@ void FOOTPRINT_LIST_IMPL::loadFootprints()
std::vector<std::future<size_t>> returns( num_elements ); std::vector<std::future<size_t>> returns( num_elements );
auto fp_thread = auto fp_thread =
[ this, &queue_parsed, &toggle_locale ]() -> size_t [ this, &queue_parsed ]() -> size_t
{ {
wxString nickname; wxString nickname;
@ -192,7 +184,7 @@ void FOOTPRINT_LIST_IMPL::loadFootprints()
CatchErrors( CatchErrors(
[&]() [&]()
{ {
m_lib_table->FootprintEnumerate( fpnames, nickname, false, &toggle_locale ); m_lib_table->FootprintEnumerate( fpnames, nickname, false );
} ); } );
for( wxString fpname : fpnames ) for( wxString fpname : fpnames )
@ -200,7 +192,7 @@ void FOOTPRINT_LIST_IMPL::loadFootprints()
CatchErrors( CatchErrors(
[&]() [&]()
{ {
auto* fpinfo = new FOOTPRINT_INFO_IMPL( this, nickname, fpname, &toggle_locale ); auto* fpinfo = new FOOTPRINT_INFO_IMPL( this, nickname, fpname );
queue_parsed.move_push( std::unique_ptr<FOOTPRINT_INFO>( fpinfo ) ); queue_parsed.move_push( std::unique_ptr<FOOTPRINT_INFO>( fpinfo ) );
} ); } );

View File

@ -34,8 +34,7 @@ class LOCALE_IO;
class FOOTPRINT_INFO_IMPL : public FOOTPRINT_INFO class FOOTPRINT_INFO_IMPL : public FOOTPRINT_INFO
{ {
public: public:
FOOTPRINT_INFO_IMPL( FOOTPRINT_LIST* aOwner, const wxString& aNickname, const wxString& aFootprintName, FOOTPRINT_INFO_IMPL( FOOTPRINT_LIST* aOwner, const wxString& aNickname, const wxString& aFootprintName )
const LOCALE_IO* aLocale )
{ {
m_nickname = aNickname; m_nickname = aNickname;
m_fpname = aFootprintName; m_fpname = aFootprintName;
@ -45,7 +44,7 @@ public:
m_owner = aOwner; m_owner = aOwner;
m_loaded = false; m_loaded = false;
load( aLocale ); load();
} }
// A constructor for cached items // A constructor for cached items
@ -77,7 +76,7 @@ public:
} }
protected: protected:
virtual void load( const LOCALE_IO* aLocale ) override; virtual void load() override;
}; };

View File

@ -599,7 +599,7 @@ void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxStr
DisplayInfoMessage( this, _( "No footprints to export!" ) ); DisplayInfoMessage( this, _( "No footprints to export!" ) );
return; return;
} }
auto resetReference = auto resetReference =
[]( FOOTPRINT* aFootprint ) []( FOOTPRINT* aFootprint )
{ {
@ -1265,7 +1265,7 @@ FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( wxString aFootprintName, const wx
// Try to infer the footprint attributes from an existing footprint in the library // Try to infer the footprint attributes from an existing footprint in the library
try try
{ {
tbl->FootprintEnumerate( fpnames, aLibName, true, nullptr ); tbl->FootprintEnumerate( fpnames, aLibName, true );
if( !fpnames.empty() ) if( !fpnames.empty() )
footprintAttrs = tbl->FootprintLoad( aLibName, fpnames.Last() )->GetAttributes(); footprintAttrs = tbl->FootprintLoad( aLibName, fpnames.Last() )->GetAttributes();

View File

@ -64,7 +64,6 @@ Load() TODO's
#include <font/fontconfig.h> #include <font/fontconfig.h>
#include <geometry/geometry_utils.h> #include <geometry/geometry_utils.h>
#include <string_utils.h> #include <string_utils.h>
#include <locale_io.h>
#include <trigo.h> #include <trigo.h>
#include <progress_reporter.h> #include <progress_reporter.h>
#include <project.h> #include <project.h>
@ -324,7 +323,6 @@ VECTOR2I inline PCB_IO_EAGLE::kicad_fontsize( const ECOORD& d, int aTextThicknes
BOARD* PCB_IO_EAGLE::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe, BOARD* PCB_IO_EAGLE::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const std::map<std::string, UTF8>* aProperties, PROJECT* aProject ) const std::map<std::string, UTF8>* aProperties, PROJECT* aProject )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
wxXmlNode* doc; wxXmlNode* doc;
fontconfig::FONTCONFIG::SetReporter( &WXLOG_REPORTER::GetInstance() ); fontconfig::FONTCONFIG::SetReporter( &WXLOG_REPORTER::GetInstance() );
@ -3198,7 +3196,6 @@ void PCB_IO_EAGLE::cacheLib( const wxString& aLibPath )
if( aLibPath != m_lib_path || m_timestamp != timestamp ) if( aLibPath != m_lib_path || m_timestamp != timestamp )
{ {
wxXmlNode* doc; wxXmlNode* doc;
LOCALE_IO toggle; // toggles on, then off, the C locale.
deleteTemplates(); deleteTemplates();

View File

@ -35,7 +35,6 @@
#include <font/fontconfig.h> #include <font/fontconfig.h>
#include <footprint.h> #include <footprint.h>
#include <pad.h> #include <pad.h>
#include <locale_io.h>
#include <macros.h> #include <macros.h>
#include <pcb_text.h> #include <pcb_text.h>
#include <pcb_shape.h> #include <pcb_shape.h>
@ -934,8 +933,6 @@ FOOTPRINT* PCB_IO_GEDA::FootprintLoad( const wxString& aLibraryPath,
void PCB_IO_GEDA::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName, void PCB_IO_GEDA::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties ); init( aProperties );
validateCache( aLibraryPath ); validateCache( aLibraryPath );
@ -1036,8 +1033,6 @@ long long PCB_IO_GEDA::GetLibraryTimestamp( const wxString& aLibraryPath ) const
bool PCB_IO_GEDA::IsLibraryWritable( const wxString& aLibraryPath ) bool PCB_IO_GEDA::IsLibraryWritable( const wxString& aLibraryPath )
{ {
LOCALE_IO toggle;
init( nullptr ); init( nullptr );
validateCache( aLibraryPath ); validateCache( aLibraryPath );

View File

@ -71,7 +71,6 @@
#include <boost/ptr_container/ptr_map.hpp> #include <boost/ptr_container/ptr_map.hpp>
#include <string_utils.h> #include <string_utils.h>
#include <locale_io.h>
#include <macros.h> #include <macros.h>
#include <filter_reader.h> #include <filter_reader.h>
#include <zones.h> #include <zones.h>
@ -469,8 +468,6 @@ bool PCB_IO_KICAD_LEGACY::CanReadFootprint( const wxString& aFileName ) const
BOARD* PCB_IO_KICAD_LEGACY::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe, BOARD* PCB_IO_KICAD_LEGACY::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const std::map<std::string, UTF8>* aProperties, PROJECT* aProject ) const std::map<std::string, UTF8>* aProperties, PROJECT* aProject )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties ); init( aProperties );
std::unique_ptr<BOARD> boardDeleter; std::unique_ptr<BOARD> boardDeleter;
@ -3318,8 +3315,6 @@ bool PCB_IO_KICAD_LEGACY::DeleteLibrary( const wxString& aLibraryPath,
bool PCB_IO_KICAD_LEGACY::IsLibraryWritable( const wxString& aLibraryPath ) bool PCB_IO_KICAD_LEGACY::IsLibraryWritable( const wxString& aLibraryPath )
{ {
LOCALE_IO toggle;
init( nullptr ); init( nullptr );
cacheLib( aLibraryPath ); cacheLib( aLibraryPath );

View File

@ -39,7 +39,6 @@
#include <io/kicad/kicad_io_utils.h> #include <io/kicad/kicad_io_utils.h>
#include <kiface_base.h> #include <kiface_base.h>
#include <layer_range.h> #include <layer_range.h>
#include <locale_io.h>
#include <macros.h> #include <macros.h>
#include <pad.h> #include <pad.h>
#include <pcb_dimension.h> #include <pcb_dimension.h>
@ -309,8 +308,6 @@ bool PCB_IO_KICAD_SEXPR::CanReadBoard( const wxString& aFileName ) const
void PCB_IO_KICAD_SEXPR::SaveBoard( const wxString& aFileName, BOARD* aBoard, void PCB_IO_KICAD_SEXPR::SaveBoard( const wxString& aFileName, BOARD* aBoard,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
wxString sanityResult = aBoard->GroupsSanityCheck(); wxString sanityResult = aBoard->GroupsSanityCheck();
if( sanityResult != wxEmptyString && m_queryUserCallback ) if( sanityResult != wxEmptyString && m_queryUserCallback )
@ -379,8 +376,6 @@ BOARD_ITEM* PCB_IO_KICAD_SEXPR::Parse( const wxString& aClipboardSourceInput )
void PCB_IO_KICAD_SEXPR::Format( const BOARD_ITEM* aItem ) const void PCB_IO_KICAD_SEXPR::Format( const BOARD_ITEM* aItem ) const
{ {
LOCALE_IO toggle; // public API function, perform anything convenient for caller
switch( aItem->Type() ) switch( aItem->Type() )
{ {
case PCB_T: case PCB_T:
@ -3107,8 +3102,6 @@ void PCB_IO_KICAD_SEXPR::FootprintDelete( const wxString& aLibraryPath,
const wxString& aFootprintName, const wxString& aFootprintName,
const std::map<std::string, UTF8>* aProperties ) const std::map<std::string, UTF8>* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties ); init( aProperties );
validateCache( aLibraryPath ); validateCache( aLibraryPath );
@ -3139,8 +3132,6 @@ void PCB_IO_KICAD_SEXPR::CreateLibrary( const wxString& aLibraryPath,
aLibraryPath.GetData() ) ); aLibraryPath.GetData() ) );
} }
LOCALE_IO toggle;
init( aProperties ); init( aProperties );
delete m_cache; delete m_cache;
@ -3229,8 +3220,6 @@ bool PCB_IO_KICAD_SEXPR::DeleteLibrary( const wxString& aLibraryPath,
bool PCB_IO_KICAD_SEXPR::IsLibraryWritable( const wxString& aLibraryPath ) bool PCB_IO_KICAD_SEXPR::IsLibraryWritable( const wxString& aLibraryPath )
{ {
LOCALE_IO toggle;
init( nullptr ); init( nullptr );
validateCache( aLibraryPath ); validateCache( aLibraryPath );

View File

@ -61,7 +61,6 @@
#include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h> #include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>
#include <pcb_plot_params_parser.h> #include <pcb_plot_params_parser.h>
#include <pcb_plot_params.h> #include <pcb_plot_params.h>
#include <locale_io.h>
#include <zones.h> #include <zones.h>
#include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h> #include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h>
#include <convert_basic_shapes_to_polygon.h> // for RECT_CHAMFER_POSITIONS definition #include <convert_basic_shapes_to_polygon.h> // for RECT_CHAMFER_POSITIONS definition
@ -809,8 +808,6 @@ FP_3DMODEL* PCB_IO_KICAD_SEXPR_PARSER::parse3DModel()
bool PCB_IO_KICAD_SEXPR_PARSER::IsValidBoardHeader() bool PCB_IO_KICAD_SEXPR_PARSER::IsValidBoardHeader()
{ {
LOCALE_IO toggle;
m_groupInfos.clear(); m_groupInfos.clear();
// See Parse() - FOOTPRINTS can be prefixed with an initial block of single line comments, // See Parse() - FOOTPRINTS can be prefixed with an initial block of single line comments,
@ -831,7 +828,6 @@ BOARD_ITEM* PCB_IO_KICAD_SEXPR_PARSER::Parse()
{ {
T token; T token;
BOARD_ITEM* item; BOARD_ITEM* item;
LOCALE_IO toggle;
m_groupInfos.clear(); m_groupInfos.clear();

View File

@ -27,7 +27,6 @@
#include <build_version.h> #include <build_version.h>
#include <macros.h> #include <macros.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <locale_io.h>
#include <board.h> #include <board.h>
#include <board_design_settings.h> #include <board_design_settings.h>
#include <footprint.h> #include <footprint.h>

View File

@ -33,7 +33,6 @@
#include <io/io_utils.h> #include <io/io_utils.h>
#include <board.h> #include <board.h>
#include <locale_io.h>
#include <cerrno> #include <cerrno>
#include <wx/string.h> #include <wx/string.h>
@ -77,8 +76,6 @@ BOARD* PCB_IO_PCAD::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
PCAD_PCB pcb( m_board ); PCAD_PCB pcb( m_board );
LOCALE_IO toggle; // toggles on, then off, the C locale.
LoadInputFile( aFileName, &xmlDoc ); LoadInputFile( aFileName, &xmlDoc );
pcb.ParseBoard( nullptr, &xmlDoc, wxT( "PCB" ) ); pcb.ParseBoard( nullptr, &xmlDoc, wxT( "PCB" ) );
pcb.AddToBoard(); pcb.AddToBoard();

View File

@ -28,7 +28,6 @@
#include <config.h> #include <config.h>
#include <kiway_player.h> #include <kiway_player.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <locale_io.h>
#include <pcb_io/pcb_io_mgr.h> #include <pcb_io/pcb_io_mgr.h>
#include <pcb_io/eagle/pcb_io_eagle.h> #include <pcb_io/eagle/pcb_io_eagle.h>
@ -196,7 +195,6 @@ bool PCB_IO_MGR::ConvertLibrary( std::map<std::string, UTF8>* aOldFileProps, con
if( oldFileType == PCB_IO_MGR::FILE_TYPE_NONE ) if( oldFileType == PCB_IO_MGR::FILE_TYPE_NONE )
return false; return false;
LOCALE_IO toggle_locale;
IO_RELEASER<PCB_IO> oldFilePI( PCB_IO_MGR::PluginFind( oldFileType ) ); IO_RELEASER<PCB_IO> oldFilePI( PCB_IO_MGR::PluginFind( oldFileType ) );
IO_RELEASER<PCB_IO> kicadPI( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) ); IO_RELEASER<PCB_IO> kicadPI( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
wxArrayString fpNames; wxArrayString fpNames;

View File

@ -56,7 +56,6 @@
#include <specctra.h> #include <specctra.h>
#include <project/project_local_settings.h> #include <project/project_local_settings.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <locale_io.h>
#include <wx/app.h> #include <wx/app.h>
#include <wx/crt.h> #include <wx/crt.h>
#include <wx/image.h> #include <wx/image.h>
@ -127,10 +126,6 @@ SETTINGS_MANAGER* GetSettingsManager()
PROJECT* GetDefaultProject() PROJECT* GetDefaultProject()
{ {
// For some reasons, LoadProject() needs a C locale, so ensure we have the right locale
// This is mainly when running QA Python tests
LOCALE_IO dummy;
PROJECT* project = GetSettingsManager()->GetProject( "" ); PROJECT* project = GetSettingsManager()->GetProject( "" );
if( !project ) if( !project )
@ -160,11 +155,6 @@ BOARD* LoadBoard( const wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, boo
// By default only the BMP handler is available. // By default only the BMP handler is available.
wxInitAllImageHandlers(); wxInitAllImageHandlers();
// Ensure the "C" locale is temporary set, before reading any file
// It also avoid wxWidget alerts about locale issues, later, when using Python 3
LOCALE_IO dummy;
PROJECT* project = GetSettingsManager()->GetProject( projectPath ); PROJECT* project = GetSettingsManager()->GetProject( projectPath );
if( !project ) if( !project )
@ -281,10 +271,6 @@ BOARD* NewBoard( wxString& aFileName )
wxString projectPath = proFn.GetFullPath(); wxString projectPath = proFn.GetFullPath();
// Ensure the "C" locale is temporary set, before reading any file
// It also avoids wxWidgets alerts about locale issues, later, when using Python 3
LOCALE_IO dummy;
GetSettingsManager()->LoadProject( projectPath, false ); GetSettingsManager()->LoadProject( projectPath, false );
PROJECT* project = GetSettingsManager()->GetProject( projectPath ); PROJECT* project = GetSettingsManager()->GetProject( projectPath );
@ -319,10 +305,6 @@ bool SaveBoard( wxString& aFileName, BOARD* aBoard, PCB_IO_MGR::PCB_FILE_T aForm
aBoard->BuildConnectivity(); aBoard->BuildConnectivity();
aBoard->SynchronizeNetsAndNetClasses( false ); aBoard->SynchronizeNetsAndNetClasses( false );
// Ensure the "C" locale is temporary set, before saving any file
// It also avoid wxWidget alerts about locale issues, later, when using Python 3
LOCALE_IO dummy;
try try
{ {
PCB_IO_MGR::Save( aFormat, aFileName, aBoard, nullptr ); PCB_IO_MGR::Save( aFormat, aFileName, aBoard, nullptr );