*) Change FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE*, const wxString*)
To use multiple working threads. This entailed adding KiCad typedefs: *) Add typedefs for MUTEX and MUTLOCK which mask the actual choices for the project. *) Add FOOTPRINT_LIST::DisplayErrors( wxWindow* ) which is a single strategy for showing aggregated load errors. Although what's there is only scaffolding and needs a volunteer who knows HTML pretty well. *) Ensure all callers of ReadFootprintFiles() use the new DisplayErrors() function. *) Push utf8.cpp and utf8.h into common library for open use.
This commit is contained in:
parent
7717aa9279
commit
dba4fccec9
|
@ -141,6 +141,7 @@ set(COMMON_SRCS
|
||||||
selcolor.cpp
|
selcolor.cpp
|
||||||
string.cpp
|
string.cpp
|
||||||
trigo.cpp
|
trigo.cpp
|
||||||
|
utf8.cpp
|
||||||
wildcards_and_files_ext.cpp
|
wildcards_and_files_ext.cpp
|
||||||
worksheet.cpp
|
worksheet.cpp
|
||||||
wxwineda.cpp
|
wxwineda.cpp
|
||||||
|
|
|
@ -102,10 +102,10 @@ void DisplayInfoMessage( wxWindow* parent, const wxString& text, int displaytime
|
||||||
void DisplayHtmlInfoMessage( wxWindow* parent, const wxString& title,
|
void DisplayHtmlInfoMessage( wxWindow* parent, const wxString& title,
|
||||||
const wxString& text, const wxSize& size )
|
const wxString& text, const wxSize& size )
|
||||||
{
|
{
|
||||||
HTML_MESSAGE_BOX *dlg = new HTML_MESSAGE_BOX(parent,title, wxDefaultPosition, size );
|
HTML_MESSAGE_BOX dlg( parent, title, wxDefaultPosition, size );
|
||||||
dlg->AddHTML_Text( text );
|
|
||||||
dlg->ShowModal();
|
dlg.AddHTML_Text( text );
|
||||||
dlg->Destroy();
|
dlg.ShowModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version Oct 8 2012)
|
// C++ code generated with wxFormBuilder (version Nov 5 2013)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||||
|
@ -21,7 +21,7 @@ DIALOG_DISPLAY_HTML_TEXT_BASE::DIALOG_DISPLAY_HTML_TEXT_BASE( wxWindow* parent,
|
||||||
|
|
||||||
m_buttonClose = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
|
m_buttonClose = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
|
||||||
m_buttonClose->SetDefault();
|
m_buttonClose->SetDefault();
|
||||||
bMainSizer->Add( m_buttonClose, 0, wxALIGN_RIGHT|wxRIGHT|wxLEFT, 5 );
|
bMainSizer->Add( m_buttonClose, 0, wxALIGN_RIGHT|wxALL, 10 );
|
||||||
|
|
||||||
|
|
||||||
this->SetSizer( bMainSizer );
|
this->SetSizer( bMainSizer );
|
||||||
|
|
|
@ -20,8 +20,10 @@
|
||||||
<property name="path">.</property>
|
<property name="path">.</property>
|
||||||
<property name="precompiled_header"></property>
|
<property name="precompiled_header"></property>
|
||||||
<property name="relative_path">1</property>
|
<property name="relative_path">1</property>
|
||||||
|
<property name="skip_lua_events">1</property>
|
||||||
<property name="skip_php_events">1</property>
|
<property name="skip_php_events">1</property>
|
||||||
<property name="skip_python_events">1</property>
|
<property name="skip_python_events">1</property>
|
||||||
|
<property name="ui_table">UI</property>
|
||||||
<property name="use_enum">0</property>
|
<property name="use_enum">0</property>
|
||||||
<property name="use_microsoft_bom">0</property>
|
<property name="use_microsoft_bom">0</property>
|
||||||
<object class="Dialog" expanded="1">
|
<object class="Dialog" expanded="1">
|
||||||
|
@ -42,7 +44,7 @@
|
||||||
<property name="minimum_size">400,120</property>
|
<property name="minimum_size">400,120</property>
|
||||||
<property name="name">DIALOG_DISPLAY_HTML_TEXT_BASE</property>
|
<property name="name">DIALOG_DISPLAY_HTML_TEXT_BASE</property>
|
||||||
<property name="pos"></property>
|
<property name="pos"></property>
|
||||||
<property name="size">431,120</property>
|
<property name="size">465,202</property>
|
||||||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
|
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
|
||||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||||
<property name="title"></property>
|
<property name="title"></property>
|
||||||
|
@ -176,8 +178,8 @@
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="1">
|
<object class="sizeritem" expanded="1">
|
||||||
<property name="border">5</property>
|
<property name="border">10</property>
|
||||||
<property name="flag">wxALIGN_RIGHT|wxRIGHT|wxLEFT</property>
|
<property name="flag">wxALIGN_RIGHT|wxALL</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxButton" expanded="1">
|
<object class="wxButton" expanded="1">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version Oct 8 2012)
|
// C++ code generated with wxFormBuilder (version Nov 5 2013)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||||
|
@ -45,7 +45,7 @@ class DIALOG_DISPLAY_HTML_TEXT_BASE : public DIALOG_SHIM
|
||||||
public:
|
public:
|
||||||
wxHtmlWindow* m_htmlWindow;
|
wxHtmlWindow* m_htmlWindow;
|
||||||
|
|
||||||
DIALOG_DISPLAY_HTML_TEXT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 431,120 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
DIALOG_DISPLAY_HTML_TEXT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 465,202 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||||
~DIALOG_DISPLAY_HTML_TEXT_BASE();
|
~DIALOG_DISPLAY_HTML_TEXT_BASE();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,10 +27,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define USE_WORKER_THREADS 1 // 1:yes, 0:no. use worker thread to load libraries
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions to read footprint libraries and fill m_footprints by available footprints names
|
* Functions to read footprint libraries and fill m_footprints by available footprints names
|
||||||
* and their documentation (comments and keywords)
|
* and their documentation (comments and keywords)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
|
@ -40,9 +44,47 @@
|
||||||
#include <io_mgr.h>
|
#include <io_mgr.h>
|
||||||
#include <fp_lib_table.h>
|
#include <fp_lib_table.h>
|
||||||
#include <fpid.h>
|
#include <fpid.h>
|
||||||
|
|
||||||
#include <class_module.h>
|
#include <class_module.h>
|
||||||
|
|
||||||
|
#if defined(USE_FP_LIB_TABLE)
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
wxString ToHTML( const IO_ERROR** aList, int aCount )
|
||||||
|
{
|
||||||
|
wxString msg = wxT( "<table>" );
|
||||||
|
|
||||||
|
msg += "
|
||||||
|
|
||||||
|
for( int i=0; i<aCount; ++i )
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
wxArrayString* sl = wxStringSplit( aList, wxChar( '\n' ) );
|
||||||
|
|
||||||
|
|
||||||
|
delete sl;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString msg = wxT( "<ul>" );
|
||||||
|
|
||||||
|
for ( unsigned ii = 0; ii < strings_list->GetCount(); ii++ )
|
||||||
|
{
|
||||||
|
msg += wxT( "<li>" );
|
||||||
|
msg += strings_list->Item( ii ) + wxT( "</li>" );
|
||||||
|
}
|
||||||
|
|
||||||
|
msg += wxT( "</ul>" );
|
||||||
|
|
||||||
|
m_htmlWindow->AppendToPage( msg );
|
||||||
|
|
||||||
|
delete strings_list;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#if !defined( USE_FP_LIB_TABLE )
|
#if !defined( USE_FP_LIB_TABLE )
|
||||||
|
|
||||||
bool FOOTPRINT_LIST::ReadFootprintFiles( wxArrayString& aFootprintLibNames )
|
bool FOOTPRINT_LIST::ReadFootprintFiles( wxArrayString& aFootprintLibNames )
|
||||||
|
@ -50,9 +92,9 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( wxArrayString& aFootprintLibNames )
|
||||||
bool retv = true;
|
bool retv = true;
|
||||||
|
|
||||||
// Clear data before reading files
|
// Clear data before reading files
|
||||||
m_filesNotFound.Empty();
|
m_error_count = 0;
|
||||||
m_filesInvalid.Empty();
|
m_errors.clear();
|
||||||
m_List.clear();
|
m_list.clear();
|
||||||
|
|
||||||
// try
|
// try
|
||||||
{
|
{
|
||||||
|
@ -80,13 +122,6 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( wxArrayString& aFootprintLibNames )
|
||||||
wxLogDebug( wxT( "Path <%s> -> <%s>." ), GetChars( aFootprintLibNames[ii] ),
|
wxLogDebug( wxT( "Path <%s> -> <%s>." ), GetChars( aFootprintLibNames[ii] ),
|
||||||
GetChars( filename.GetFullPath() ) );
|
GetChars( filename.GetFullPath() ) );
|
||||||
|
|
||||||
if( !filename.IsOk() || !filename.FileExists() )
|
|
||||||
{
|
|
||||||
m_filesNotFound << aFootprintLibNames[ii] << wxT( "\n" );
|
|
||||||
retv = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
wxArrayString fpnames = pi->FootprintEnumerate( filename.GetFullPath() );
|
wxArrayString fpnames = pi->FootprintEnumerate( filename.GetFullPath() );
|
||||||
|
@ -111,37 +146,133 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( wxArrayString& aFootprintLibNames )
|
||||||
AddItem( fpinfo );
|
AddItem( fpinfo );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( IO_ERROR ioe )
|
catch( const PARSE_ERROR& pe )
|
||||||
{
|
{
|
||||||
m_filesInvalid << ioe.errorText << wxT( "\n" );
|
m_errors.push_back( new PARSE_ERROR( pe ) );
|
||||||
|
retv = false;
|
||||||
|
}
|
||||||
|
catch( const IO_ERROR& ioe )
|
||||||
|
{
|
||||||
|
m_errors.push_back( new IO_ERROR( ioe ) );
|
||||||
retv = false;
|
retv = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* caller should catch this, UI seems not wanted here.
|
/* caller should catch this, UI seems not wanted here.
|
||||||
catch( IO_ERROR ioe )
|
catch( const IO_ERROR& ioe )
|
||||||
{
|
{
|
||||||
DisplayError( NULL, ioe.errorText );
|
DisplayError( NULL, ioe.errorText );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
m_List.sort();
|
m_list.sort();
|
||||||
|
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else // yes USE_FP_LIB_TABLE, by all means:
|
||||||
|
|
||||||
|
|
||||||
|
#if USE_WORKER_THREADS //---------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define USE_WORKER_THREADS 1 // 1:yes, 0:no. use worker threads to load libraries
|
||||||
|
|
||||||
|
#define JOBZ 6 // no. libraries per worker thread. It takes about
|
||||||
|
// a second to load a GITHUB library, so assigning
|
||||||
|
// this no. libraries to each thread should give a little
|
||||||
|
// over this no. seconds total time if the original delay
|
||||||
|
// were caused by latencies alone.
|
||||||
|
// (If https://github.com does not mind.)
|
||||||
|
|
||||||
|
#define NTOLERABLE_ERRORS 4 // max errors before aborting, although threads
|
||||||
|
// in progress will still pile on for a bit. e.g. if 9 threads
|
||||||
|
// expect 9 greater than this.
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ )
|
||||||
|
{
|
||||||
|
//DBG(printf( "%s: first:'%s' count:%d\n", __func__, (char*) TO_UTF8( *aNicknameList ), aJobZ );)
|
||||||
|
|
||||||
|
for( int i=0; i<aJobZ; ++i )
|
||||||
|
{
|
||||||
|
if( m_error_count >= NTOLERABLE_ERRORS )
|
||||||
|
break;
|
||||||
|
|
||||||
|
const wxString& nickname = aNicknameList[i];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wxArrayString fpnames = m_lib_table->FootprintEnumerate( nickname );
|
||||||
|
|
||||||
|
for( unsigned ni=0; ni<fpnames.GetCount(); ++ni )
|
||||||
|
{
|
||||||
|
std::auto_ptr<MODULE> m( m_lib_table->FootprintLoad( nickname, fpnames[ni] ) );
|
||||||
|
|
||||||
|
FOOTPRINT_INFO* fpinfo = new FOOTPRINT_INFO();
|
||||||
|
|
||||||
|
fpinfo->SetNickname( nickname );
|
||||||
|
|
||||||
|
fpinfo->m_Module = fpnames[ni];
|
||||||
|
fpinfo->m_padCount = m->GetPadCount( MODULE::DO_NOT_INCLUDE_NPTH );
|
||||||
|
fpinfo->m_KeyWord = m->GetKeywords();
|
||||||
|
fpinfo->m_Doc = m->GetDescription();
|
||||||
|
|
||||||
|
AddItem( fpinfo );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( const PARSE_ERROR& pe )
|
||||||
|
{
|
||||||
|
// push_back is not thread safe, use the lock the MUTEX.
|
||||||
|
MUTLOCK lock( m_errors_lock );
|
||||||
|
|
||||||
|
++m_error_count; // modify only under lock
|
||||||
|
m_errors.push_back( new IO_ERROR( pe ) );
|
||||||
|
}
|
||||||
|
catch( const IO_ERROR& ioe )
|
||||||
|
{
|
||||||
|
MUTLOCK lock( m_errors_lock );
|
||||||
|
|
||||||
|
++m_error_count;
|
||||||
|
m_errors.push_back( new IO_ERROR( ioe ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catch anything unexpected and map it into the expected.
|
||||||
|
// Likely even more important since this function runs on GUI-less
|
||||||
|
// worker threads.
|
||||||
|
catch( const std::exception& se )
|
||||||
|
{
|
||||||
|
// this is a round about way to do this, but who knows what THROW_IO_ERROR()
|
||||||
|
// may be tricked out to do someday, keep it in the game.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( se.what() );
|
||||||
|
}
|
||||||
|
catch( const IO_ERROR& ioe )
|
||||||
|
{
|
||||||
|
MUTLOCK lock( m_errors_lock );
|
||||||
|
|
||||||
|
++m_error_count;
|
||||||
|
m_errors.push_back( new IO_ERROR( ioe ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_WORKER_THREADS ---------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname )
|
bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname )
|
||||||
{
|
{
|
||||||
bool retv = true;
|
bool retv = true;
|
||||||
|
|
||||||
|
m_lib_table = aTable;
|
||||||
|
|
||||||
// Clear data before reading files
|
// Clear data before reading files
|
||||||
m_filesNotFound.Empty();
|
m_error_count = 0;
|
||||||
m_filesInvalid.Empty();
|
m_errors.clear();
|
||||||
m_List.clear();
|
m_list.clear();
|
||||||
|
|
||||||
std::vector< wxString > nicknames;
|
std::vector< wxString > nicknames;
|
||||||
|
|
||||||
|
@ -149,8 +280,68 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a
|
||||||
// do all of them
|
// do all of them
|
||||||
nicknames = aTable->GetLogicalLibs();
|
nicknames = aTable->GetLogicalLibs();
|
||||||
else
|
else
|
||||||
|
// single footprint
|
||||||
nicknames.push_back( *aNickname );
|
nicknames.push_back( *aNickname );
|
||||||
|
|
||||||
|
#if USE_WORKER_THREADS
|
||||||
|
|
||||||
|
// Something which will not invoke a thread copy constructor, one of many ways obviously:
|
||||||
|
typedef boost::ptr_vector< boost::thread > MYTHREADS;
|
||||||
|
|
||||||
|
MYTHREADS threads;
|
||||||
|
|
||||||
|
// Give each thread JOBZ nicknames to process. The last portion of, or if the entire
|
||||||
|
// size() is small, I'll do myself.
|
||||||
|
for( unsigned i=0; i<nicknames.size(); )
|
||||||
|
{
|
||||||
|
if( m_error_count >= NTOLERABLE_ERRORS )
|
||||||
|
{
|
||||||
|
// abort the remaining nicknames.
|
||||||
|
retv = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jobz = JOBZ;
|
||||||
|
|
||||||
|
if( i + jobz >= nicknames.size() )
|
||||||
|
{
|
||||||
|
jobz = nicknames.size() - i;
|
||||||
|
|
||||||
|
// Only a little bit to do, I'll do it myself, on current thread.
|
||||||
|
// This is the path for a single footprint also.
|
||||||
|
loader_job( &nicknames[i], jobz );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Delegate the job to a worker thread created here.
|
||||||
|
threads.push_back( new boost::thread( &FOOTPRINT_LIST::loader_job,
|
||||||
|
this, &nicknames[i], jobz ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
i += jobz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all the worder threads to complete, it does not matter in what order
|
||||||
|
// we wait for them as long as a full sweep is made. Think of the great race,
|
||||||
|
// everyone must finish.
|
||||||
|
for( unsigned i=0; i<threads.size(); ++i )
|
||||||
|
{
|
||||||
|
threads[i].join();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_list.sort();
|
||||||
|
|
||||||
|
// The result of this function can be a blend of successes and failures, whose
|
||||||
|
// mix is given by the Count()s of the two lists. The return value indicates whether
|
||||||
|
// an abort occurred, even true does not necessarily mean full success, although
|
||||||
|
// false definitely means failure.
|
||||||
|
|
||||||
|
return retv;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
bool retv = true;
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < nicknames.size(); ii++ )
|
for( unsigned ii = 0; ii < nicknames.size(); ii++ )
|
||||||
{
|
{
|
||||||
const wxString& nickname = nicknames[ii];
|
const wxString& nickname = nicknames[ii];
|
||||||
|
@ -178,23 +369,44 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a
|
||||||
AddItem( fpinfo );
|
AddItem( fpinfo );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( IO_ERROR ioe )
|
catch( const PARSE_ERROR& pe )
|
||||||
{
|
{
|
||||||
m_filesInvalid << ioe.errorText << wxT( "\n" );
|
m_errors.push_back( new IO_ERROR( pe ) );
|
||||||
|
retv = false;
|
||||||
|
}
|
||||||
|
catch( const IO_ERROR& ioe )
|
||||||
|
{
|
||||||
|
m_errors.push_back( new IO_ERROR( ioe ) );
|
||||||
retv = false;
|
retv = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_List.sort();
|
m_list.sort();
|
||||||
|
|
||||||
return retv;
|
return retv;
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_FP_LIB_TABLE
|
#endif // USE_FP_LIB_TABLE
|
||||||
|
|
||||||
FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aFootprintName )
|
|
||||||
|
void FOOTPRINT_LIST::AddItem( FOOTPRINT_INFO* aItem )
|
||||||
{
|
{
|
||||||
BOOST_FOREACH( FOOTPRINT_INFO& footprint, m_List )
|
#if defined( USE_FP_LIB_TABLE )
|
||||||
|
|
||||||
|
// m_list is not thread safe, and this function is called from
|
||||||
|
// worker threads, lock m_list.
|
||||||
|
MUTLOCK lock( m_list_lock );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_list.push_back( aItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aFootprintName )
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( const FOOTPRINT_INFO& footprint, m_list )
|
||||||
{
|
{
|
||||||
#if defined( USE_FP_LIB_TABLE )
|
#if defined( USE_FP_LIB_TABLE )
|
||||||
FPID fpid;
|
FPID fpid;
|
||||||
|
@ -243,3 +455,45 @@ bool FOOTPRINT_INFO::InLibrary( const wxString& aLibrary ) const
|
||||||
return filename.GetFullPath() == m_lib_path;
|
return filename.GetFullPath() == m_lib_path;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include <confirm.h> // until scaffolding goes.
|
||||||
|
|
||||||
|
void FOOTPRINT_LIST::DisplayErrors( wxTopLevelWindow* aWindow )
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
// scaffolding until a better one is written, hopefully below.
|
||||||
|
|
||||||
|
DBG(printf( "m_error_count:%d\n", m_error_count );)
|
||||||
|
|
||||||
|
wxString msg = _( "Errors were encountered loading footprints" );
|
||||||
|
|
||||||
|
msg += wxT( '\n' );
|
||||||
|
|
||||||
|
for( unsigned i = 0; i<m_errors.size(); ++i )
|
||||||
|
{
|
||||||
|
msg += m_errors[i].errorText;
|
||||||
|
msg += wxT( '\n' );
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayError( aWindow, msg );
|
||||||
|
|
||||||
|
#else // real evolving deal:
|
||||||
|
|
||||||
|
// @todo: go to a more HTML !<table>! ? centric output, possibly with
|
||||||
|
// recommendations for remedy of errors. Add numeric error codes
|
||||||
|
// to PARSE_ERROR, and switch on them for remedies, etc. Full
|
||||||
|
// access is provided to everything in every exception!
|
||||||
|
|
||||||
|
HTML_MESSAGE_BOX dlg( aWindow, _( "Load Error" ) );
|
||||||
|
|
||||||
|
dlg.MessageSet( _( "Errors were encountered loading footprints" ) );
|
||||||
|
|
||||||
|
wxString msg = my html wizardry.
|
||||||
|
|
||||||
|
dlg.AddHTML_Text( msg );
|
||||||
|
|
||||||
|
dlg.ShowModal();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -637,6 +637,26 @@ const FP_LIB_TABLE::ROW* FP_LIB_TABLE::FindRow( const wxString& aNickname )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// wxGetenv( wchar_t* ) is not re-entrant on linux.
|
||||||
|
// Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
|
||||||
|
// needed by bool ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname = NULL );
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
#include <ki_mutex.h>
|
||||||
|
|
||||||
|
const wxString FP_LIB_TABLE::ExpandSubstitutions( const wxString& aString )
|
||||||
|
{
|
||||||
|
static MUTEX getenv_mutex;
|
||||||
|
|
||||||
|
MUTLOCK lock( getenv_mutex );
|
||||||
|
|
||||||
|
// We reserve the right to do this another way, by providing our own member
|
||||||
|
// function.
|
||||||
|
return wxExpandEnvVars( aString );
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
const wxString FP_LIB_TABLE::ExpandSubstitutions( const wxString& aString )
|
const wxString FP_LIB_TABLE::ExpandSubstitutions( const wxString& aString )
|
||||||
{
|
{
|
||||||
// We reserve the right to do this another way, by providing our own member
|
// We reserve the right to do this another way, by providing our own member
|
||||||
|
@ -644,6 +664,7 @@ const wxString FP_LIB_TABLE::ExpandSubstitutions( const wxString& aString )
|
||||||
return wxExpandEnvVars( aString );
|
return wxExpandEnvVars( aString );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
bool FP_LIB_TABLE::IsEmpty( bool aIncludeFallback )
|
bool FP_LIB_TABLE::IsEmpty( bool aIncludeFallback )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,83 +1,78 @@
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <html_messagebox.h>
|
#include <html_messagebox.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
HTML_MESSAGE_BOX::HTML_MESSAGE_BOX( wxWindow* parent, const wxString & aTitle,
|
|
||||||
wxPoint aPos, wxSize aSize)
|
HTML_MESSAGE_BOX::HTML_MESSAGE_BOX( wxWindow* parent, const wxString& aTitle,
|
||||||
: DIALOG_DISPLAY_HTML_TEXT_BASE( parent, wxID_ANY, aTitle, aPos, aSize )
|
wxPoint aPos, wxSize aSize) :
|
||||||
|
DIALOG_DISPLAY_HTML_TEXT_BASE( parent, wxID_ANY, aTitle, aPos, aSize )
|
||||||
{
|
{
|
||||||
ListClear();
|
ListClear();
|
||||||
Center();
|
Center();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HTML_MESSAGE_BOX::OnCloseButtonClick( wxCommandEvent& event )
|
void HTML_MESSAGE_BOX::OnCloseButtonClick( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
EndModal(0);
|
EndModal( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HTML_MESSAGE_BOX::ListClear(void)
|
void HTML_MESSAGE_BOX::ListClear()
|
||||||
{
|
{
|
||||||
m_htmlWindow->SetPage(wxEmptyString);
|
m_htmlWindow->SetPage( wxEmptyString );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Function ListSet
|
|
||||||
* Add a list of items.
|
|
||||||
* @param aList = a string containing items. Items are separated by '\n'
|
|
||||||
*/
|
|
||||||
void HTML_MESSAGE_BOX::ListSet(const wxString &aList)
|
|
||||||
{
|
|
||||||
wxArrayString* wxStringSplit( wxString txt, wxChar splitter );
|
|
||||||
|
|
||||||
wxArrayString* strings_list = wxStringSplit( aList, wxChar('\n') );
|
void HTML_MESSAGE_BOX::ListSet( const wxString& aList )
|
||||||
wxString msg = wxT("<ul>");
|
{
|
||||||
for ( unsigned ii = 0; ii < strings_list->GetCount(); ii ++ )
|
// wxArrayString* wxStringSplit( wxString txt, wxChar splitter );
|
||||||
|
|
||||||
|
wxArrayString* strings_list = wxStringSplit( aList, wxChar( '\n' ) );
|
||||||
|
|
||||||
|
wxString msg = wxT( "<ul>" );
|
||||||
|
|
||||||
|
for ( unsigned ii = 0; ii < strings_list->GetCount(); ii++ )
|
||||||
{
|
{
|
||||||
msg += wxT("<li>");
|
msg += wxT( "<li>" );
|
||||||
msg += strings_list->Item(ii) + wxT("</li>");
|
msg += strings_list->Item( ii ) + wxT( "</li>" );
|
||||||
}
|
}
|
||||||
msg += wxT("</ul>");
|
|
||||||
|
msg += wxT( "</ul>" );
|
||||||
|
|
||||||
m_htmlWindow->AppendToPage( msg );
|
m_htmlWindow->AppendToPage( msg );
|
||||||
|
|
||||||
delete strings_list;
|
delete strings_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Function ListSet
|
void HTML_MESSAGE_BOX::ListSet( const wxArrayString& aList )
|
||||||
* Add a list of items.
|
|
||||||
* @param aList = a wxArrayString containing items
|
|
||||||
*/
|
|
||||||
void HTML_MESSAGE_BOX::ListSet(const wxArrayString &aList)
|
|
||||||
{
|
{
|
||||||
wxString msg = wxT("<ul>");
|
wxString msg = wxT( "<ul>" );
|
||||||
for ( unsigned ii = 0; ii < aList.GetCount(); ii ++ )
|
|
||||||
|
for( unsigned ii = 0; ii < aList.GetCount(); ii++ )
|
||||||
{
|
{
|
||||||
msg += wxT("<li>");
|
msg += wxT( "<li>" );
|
||||||
msg += aList.Item(ii) + wxT("</li>");
|
msg += aList.Item( ii ) + wxT( "</li>" );
|
||||||
}
|
}
|
||||||
msg += wxT("</ul>");
|
|
||||||
|
msg += wxT( "</ul>" );
|
||||||
|
|
||||||
m_htmlWindow->AppendToPage( msg );
|
m_htmlWindow->AppendToPage( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Function MessageSet
|
void HTML_MESSAGE_BOX::MessageSet( const wxString& message )
|
||||||
* Add a message (in bold) to message list.
|
|
||||||
* @param message = the message
|
|
||||||
*/
|
|
||||||
void HTML_MESSAGE_BOX::MessageSet(const wxString &message)
|
|
||||||
{
|
{
|
||||||
wxString message_value;
|
wxString message_value = wxString::Format(
|
||||||
message_value.Printf(wxT("<b>%s</b><br>"), GetChars( message ) );
|
wxT( "<b>%s</b><br>" ), GetChars( message ) );
|
||||||
|
|
||||||
m_htmlWindow->AppendToPage( message_value );
|
m_htmlWindow->AppendToPage( message_value );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Function AddHTML_Text
|
void HTML_MESSAGE_BOX::AddHTML_Text( const wxString& message )
|
||||||
* Add a text to message list.
|
|
||||||
* @param message = the text to add
|
|
||||||
*/
|
|
||||||
void HTML_MESSAGE_BOX::AddHTML_Text(const wxString &message)
|
|
||||||
{
|
{
|
||||||
m_htmlWindow->AppendToPage( message );
|
m_htmlWindow->AppendToPage( message );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,259 +1,39 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
|
* Copyright (C) 2013 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <utf8.h>
|
||||||
|
|
||||||
|
/* THROW_IO_ERROR needs this, but it will soon be including this file, so until some
|
||||||
|
factoring of THROW_IO_ERROR into a separate header, defer and use the asserts.
|
||||||
|
#include <richio.h>
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string>
|
|
||||||
#include <wx/string.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class UTF8
|
|
||||||
* is an 8 bit std::string that is assuredly encoded in UTF8, and supplies special
|
|
||||||
* conversion support to and from wxString, and has iteration over unicode characters.
|
|
||||||
*
|
|
||||||
* <p>I've been careful to supply only conversion facilities and not try
|
|
||||||
* and duplicate wxString() with many member functions. In the end it is
|
|
||||||
* to be a std::string. There are multiple ways to create text into a std::string
|
|
||||||
* without the need of too many member functions:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>richio.h's StrPrintf()</li>
|
|
||||||
* <li>std::ostringstream.</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <p>Because this class used no virtuals, it should be possible to cast any
|
|
||||||
* std::string into a UTF8 using this kind of cast: (UTF8 &) without construction
|
|
||||||
* or copying being the effect of the cast. Be sure the source std::string holds
|
|
||||||
* UTF8 encoded text before you do that.
|
|
||||||
*
|
|
||||||
* @author Dick Hollenbeck
|
|
||||||
*/
|
|
||||||
class UTF8 : public std::string
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
UTF8( const wxString& o );
|
|
||||||
|
|
||||||
/// This is the only constructor for which you could end up with
|
|
||||||
/// non-UTF8 encoding, but that would be your fault.
|
|
||||||
UTF8( const char* txt ) :
|
|
||||||
std::string( txt )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// For use with _() function on wx 2.8:
|
|
||||||
UTF8( const wchar_t* txt );
|
|
||||||
|
|
||||||
explicit UTF8( const std::string& o ) :
|
|
||||||
std::string( o )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
UTF8() :
|
|
||||||
std::string()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
UTF8& operator=( const wxString& o );
|
|
||||||
|
|
||||||
UTF8& operator=( const std::string& o )
|
|
||||||
{
|
|
||||||
std::string::operator=( o );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator wxString () const;
|
|
||||||
|
|
||||||
/// This one is not in std::string, and one wonders why... might be a solid
|
|
||||||
/// enough reason to remove it still.
|
|
||||||
operator char* () const
|
|
||||||
{
|
|
||||||
return (char*) c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function uni_forward
|
|
||||||
* advances over a single UTF8 encoded multibyte character, capturing the
|
|
||||||
* unicode character as it goes, and returning the number of bytes consumed.
|
|
||||||
*
|
|
||||||
* @param aSequence is the UTF8 byte sequence, must be aligned on start of character.
|
|
||||||
* @param aResult is where to put the unicode character, and may be NULL if no interest.
|
|
||||||
* @return int - the count of bytes consumed.
|
|
||||||
*/
|
|
||||||
static int uni_forward( const unsigned char* aSequence, unsigned* aResult = NULL );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* class uni_iter
|
|
||||||
* is a non-muting iterator that walks through unicode code points in the UTF8 encoded
|
|
||||||
* string. The normal ++(), ++(int), ->(), and *() operators are all supported
|
|
||||||
* for read only access and they return an unsigned holding the unicode character
|
|
||||||
* appropriate for the respective operator.
|
|
||||||
*/
|
|
||||||
class uni_iter
|
|
||||||
{
|
|
||||||
friend class UTF8;
|
|
||||||
|
|
||||||
const unsigned char* it;
|
|
||||||
|
|
||||||
// private constructor.
|
|
||||||
uni_iter( const char* start ) :
|
|
||||||
it( (const unsigned char*) start )
|
|
||||||
{
|
|
||||||
// for the human: assert( sizeof(unsigned) >= 4 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
uni_iter( const uni_iter& o )
|
|
||||||
{
|
|
||||||
it = o.it;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// pre-increment and return uni_iter at new position
|
|
||||||
const uni_iter& operator++()
|
|
||||||
{
|
|
||||||
it += uni_forward( it );
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// post-increment and return uni_iter at initial position
|
|
||||||
uni_iter operator++( int )
|
|
||||||
{
|
|
||||||
uni_iter ret = *this;
|
|
||||||
|
|
||||||
it += uni_forward( it );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
/// return unicode at current position
|
|
||||||
unsigned operator->() const
|
|
||||||
{
|
|
||||||
unsigned result;
|
|
||||||
|
|
||||||
// grab the result, do not advance
|
|
||||||
uni_forward( it, &result );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// return unicode at current position
|
|
||||||
unsigned operator*() const
|
|
||||||
{
|
|
||||||
unsigned result;
|
|
||||||
|
|
||||||
// grab the result, do not advance
|
|
||||||
uni_forward( it, &result );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==( const uni_iter& other ) const { return it == other.it; }
|
|
||||||
bool operator!=( const uni_iter& other ) const { return it != other.it; }
|
|
||||||
|
|
||||||
/// Since the ++ operators advance more than one byte, this is your best
|
|
||||||
/// loop termination test, < end(), not == end().
|
|
||||||
bool operator< ( const uni_iter& other ) const { return it < other.it; }
|
|
||||||
bool operator<=( const uni_iter& other ) const { return it <= other.it; }
|
|
||||||
bool operator> ( const uni_iter& other ) const { return it > other.it; }
|
|
||||||
bool operator>=( const uni_iter& other ) const { return it >= other.it; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function ubegin
|
|
||||||
* returns a @a uni_iter initialized to the start of "this" UTF8 byte sequence.
|
|
||||||
*/
|
|
||||||
uni_iter ubegin() const
|
|
||||||
{
|
|
||||||
return uni_iter( data() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function uend
|
|
||||||
* returns a @a uni_iter initialized to the end of "this" UTF8 byte sequence.
|
|
||||||
*/
|
|
||||||
uni_iter uend() const
|
|
||||||
{
|
|
||||||
return uni_iter( data() + size() );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
wxString wxFunctionTaking_wxString( const wxString& wx )
|
|
||||||
{
|
|
||||||
printf( "%s:'%s'\n", __func__, (char*) UTF8( wx ) );
|
|
||||||
printf( "%s:'%s'\n", __func__, (const char*) UTF8( wx ) );
|
|
||||||
printf( "%s:'%s'\n", __func__, UTF8( wx ).c_str() );
|
|
||||||
|
|
||||||
return wx;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
std::string str = "input";
|
|
||||||
|
|
||||||
UTF8 u0 = L"wide string";
|
|
||||||
UTF8 u1 = "initial";
|
|
||||||
wxString wx = wxT( "input2" );
|
|
||||||
|
|
||||||
printf( "u0:'%s'\n", u0.c_str() );
|
|
||||||
printf( "u1:'%s'\n", u1.c_str() );
|
|
||||||
|
|
||||||
u1 = str;
|
|
||||||
|
|
||||||
wxString wx2 = u1;
|
|
||||||
|
|
||||||
// force a std::string into a UTF8, then into a wxString, then copy construct:
|
|
||||||
wxString wx3 = (UTF8&) u1;
|
|
||||||
|
|
||||||
UTF8 u2 = wx2;
|
|
||||||
|
|
||||||
u2 += 'X';
|
|
||||||
|
|
||||||
printf( "u2:'%s'\n", u2.c_str() );
|
|
||||||
|
|
||||||
// key accomplishments here:
|
|
||||||
// 1) passing a UTF8 to a function which normally takes a wxString.
|
|
||||||
// 2) return a wxString back into a UTF8.
|
|
||||||
UTF8 result = wxFunctionTaking_wxString( u2 );
|
|
||||||
|
|
||||||
printf( "result:'%s'\n", result.c_str() );
|
|
||||||
|
|
||||||
// test the unicode iterator:
|
|
||||||
for( UTF8::uni_iter it = u2.ubegin(); it < u2.uend(); )
|
|
||||||
{
|
|
||||||
// test post-increment:
|
|
||||||
printf( " _%c_", *it++ );
|
|
||||||
|
|
||||||
// after UTF8::uni_forward() is implemented, %c is no longer useable.
|
|
||||||
// printf( " _%02x_", *it++ );
|
|
||||||
}
|
|
||||||
|
|
||||||
printf( "\n" );
|
|
||||||
|
|
||||||
UTF8::uni_iter it = u2.ubegin();
|
|
||||||
|
|
||||||
UTF8::uni_iter it2 = it++;
|
|
||||||
|
|
||||||
printf( "post_inc:'%c' should be 'i'\n", *it2 );
|
|
||||||
|
|
||||||
it2 = ++it;
|
|
||||||
|
|
||||||
printf( "pre_inc:'%c' should be 'p'\n", *it2 );
|
|
||||||
|
|
||||||
printf( "u[1]:'%c' should be 'n'\n", u2[1] );
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
These are not inlined so that code space is saved by encapsulating the
|
||||||
These to go into a library *.cpp, they are not inlined so that significant
|
creation of intermediate objects and referencing wxConvUTF8.
|
||||||
code space is saved by encapsulating the creation of intermediate objects
|
|
||||||
and referencing wxConvUTF8.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -405,3 +185,76 @@ UTF8::UTF8( const wchar_t* txt ) :
|
||||||
resize( sz );
|
resize( sz );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 // some unit tests:
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
wxString wxFunctionTaking_wxString( const wxString& wx )
|
||||||
|
{
|
||||||
|
printf( "%s:'%s'\n", __func__, (char*) UTF8( wx ) );
|
||||||
|
printf( "%s:'%s'\n", __func__, (const char*) UTF8( wx ) );
|
||||||
|
printf( "%s:'%s'\n", __func__, UTF8( wx ).c_str() );
|
||||||
|
|
||||||
|
return wx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::string str = "input";
|
||||||
|
|
||||||
|
UTF8 u0 = L"wide string";
|
||||||
|
UTF8 u1 = "initial";
|
||||||
|
wxString wx = wxT( "input2" );
|
||||||
|
|
||||||
|
printf( "u0:'%s'\n", u0.c_str() );
|
||||||
|
printf( "u1:'%s'\n", u1.c_str() );
|
||||||
|
|
||||||
|
u1 = str;
|
||||||
|
|
||||||
|
wxString wx2 = u1;
|
||||||
|
|
||||||
|
// force a std::string into a UTF8, then into a wxString, then copy construct:
|
||||||
|
wxString wx3 = (UTF8&) u1;
|
||||||
|
|
||||||
|
UTF8 u2 = wx2;
|
||||||
|
|
||||||
|
u2 += 'X';
|
||||||
|
|
||||||
|
printf( "u2:'%s'\n", u2.c_str() );
|
||||||
|
|
||||||
|
// key accomplishments here:
|
||||||
|
// 1) passing a UTF8 to a function which normally takes a wxString.
|
||||||
|
// 2) return a wxString back into a UTF8.
|
||||||
|
UTF8 result = wxFunctionTaking_wxString( u2 );
|
||||||
|
|
||||||
|
printf( "result:'%s'\n", result.c_str() );
|
||||||
|
|
||||||
|
// test the unicode iterator:
|
||||||
|
for( UTF8::uni_iter it = u2.ubegin(); it < u2.uend(); )
|
||||||
|
{
|
||||||
|
// test post-increment:
|
||||||
|
printf( " _%c_", *it++ );
|
||||||
|
|
||||||
|
// after UTF8::uni_forward() is implemented, %c is no longer useable.
|
||||||
|
// printf( " _%02x_", *it++ );
|
||||||
|
}
|
||||||
|
|
||||||
|
printf( "\n" );
|
||||||
|
|
||||||
|
UTF8::uni_iter it = u2.ubegin();
|
||||||
|
|
||||||
|
UTF8::uni_iter it2 = it++;
|
||||||
|
|
||||||
|
printf( "post_inc:'%c' should be 'i'\n", *it2 );
|
||||||
|
|
||||||
|
it2 = ++it;
|
||||||
|
|
||||||
|
printf( "pre_inc:'%c' should be 'p'\n", *it2 );
|
||||||
|
|
||||||
|
printf( "u[1]:'%c' should be 'n'\n", u2[1] );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -176,7 +176,7 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
|
||||||
|
|
||||||
/* filter alias so one can use multiple aliases (for polar and nonpolar caps for
|
/* filter alias so one can use multiple aliases (for polar and nonpolar caps for
|
||||||
* example) */
|
* example) */
|
||||||
FOOTPRINT_INFO *module = m_footprints.GetModuleInfo( alias.m_FootprintName );
|
const FOOTPRINT_INFO *module = m_footprints.GetModuleInfo( alias.m_FootprintName );
|
||||||
|
|
||||||
if( module )
|
if( module )
|
||||||
{
|
{
|
||||||
|
@ -210,7 +210,7 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
/* we do not need to analyse wildcards: single footprint do not contain them */
|
/* we do not need to analyse wildcards: single footprint do not contain them */
|
||||||
/* and if there are wildcards it just will not match any */
|
/* and if there are wildcards it just will not match any */
|
||||||
FOOTPRINT_INFO *module = m_footprints.GetModuleInfo( component->GetFootprintFilters()[0] );
|
const FOOTPRINT_INFO* module = m_footprints.GetModuleInfo( component->GetFootprintFilters()[0] );
|
||||||
|
|
||||||
if( module )
|
if( module )
|
||||||
{
|
{
|
||||||
|
|
|
@ -558,9 +558,9 @@ void DISPLAY_FOOTPRINTS_FRAME::InitDisplay()
|
||||||
msg.Printf( _( "Footprint: %s" ), GetChars( footprintName ) );
|
msg.Printf( _( "Footprint: %s" ), GetChars( footprintName ) );
|
||||||
|
|
||||||
SetTitle( msg );
|
SetTitle( msg );
|
||||||
FOOTPRINT_INFO* module_info = parentframe->m_footprints.GetModuleInfo( footprintName );
|
const FOOTPRINT_INFO* module_info = parentframe->m_footprints.GetModuleInfo( footprintName );
|
||||||
|
|
||||||
const wxChar *libname;
|
const wxChar* libname;
|
||||||
|
|
||||||
if( module_info )
|
if( module_info )
|
||||||
libname = GetChars( module_info->GetNickname() );
|
libname = GetChars( module_info->GetNickname() );
|
||||||
|
|
|
@ -704,7 +704,8 @@ void CVPCB_MAINFRAME::DisplayStatus()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxString footprintName = m_FootprintList->GetSelectedFootprint();
|
wxString footprintName = m_FootprintList->GetSelectedFootprint();
|
||||||
FOOTPRINT_INFO* module = m_footprints.GetModuleInfo( footprintName );
|
|
||||||
|
const FOOTPRINT_INFO* module = m_footprints.GetModuleInfo( footprintName );
|
||||||
|
|
||||||
if( module ) // can be NULL if no netlist loaded
|
if( module ) // can be NULL if no netlist loaded
|
||||||
{
|
{
|
||||||
|
@ -716,7 +717,6 @@ void CVPCB_MAINFRAME::DisplayStatus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
msg.Empty();
|
msg.Empty();
|
||||||
|
|
||||||
if( m_FootprintList )
|
if( m_FootprintList )
|
||||||
|
@ -769,26 +769,9 @@ bool CVPCB_MAINFRAME::LoadFootprintFiles()
|
||||||
m_footprints.ReadFootprintFiles( m_footprintLibTable );
|
m_footprints.ReadFootprintFiles( m_footprintLibTable );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Display error messages, if any.
|
if( m_footprints.GetErrorCount() )
|
||||||
if( !m_footprints.m_filesNotFound.IsEmpty() || !m_footprints.m_filesInvalid.IsEmpty() )
|
|
||||||
{
|
{
|
||||||
HTML_MESSAGE_BOX dialog( this, _( "Load Error" ) );
|
m_footprints.DisplayErrors( this );
|
||||||
|
|
||||||
if( !m_footprints.m_filesNotFound.IsEmpty() )
|
|
||||||
{
|
|
||||||
wxString message = _( "Some files could not be found!" );
|
|
||||||
dialog.MessageSet( message );
|
|
||||||
dialog.ListSet( m_footprints.m_filesNotFound );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display if there are invalid files.
|
|
||||||
if( !m_footprints.m_filesInvalid.IsEmpty() )
|
|
||||||
{
|
|
||||||
dialog.MessageSet( _( "Some files are invalid!" ) );
|
|
||||||
dialog.ListSet( m_footprints.m_filesInvalid );
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog.ShowModal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -33,10 +33,15 @@
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
#if defined( USE_FP_LIB_TABLE )
|
||||||
|
#include <ki_mutex.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <kicad_string.h>
|
#include <kicad_string.h>
|
||||||
|
|
||||||
|
|
||||||
class FP_LIB_TABLE;
|
class FP_LIB_TABLE;
|
||||||
|
class wxTopLevelWindow;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,64 +111,103 @@ inline bool operator<( const FOOTPRINT_INFO& item1, const FOOTPRINT_INFO& item2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FOOTPRINT_LIST
|
||||||
|
* holds a list of FOOTPRINT_INFO objects, along with a list of IO_ERRORs or
|
||||||
|
* PARSE_ERRORs that were thrown acquiring the FOOTPRINT_INFOs.
|
||||||
|
*/
|
||||||
class FOOTPRINT_LIST
|
class FOOTPRINT_LIST
|
||||||
{
|
{
|
||||||
public:
|
FP_LIB_TABLE* m_lib_table; ///< no ownership
|
||||||
boost::ptr_vector< FOOTPRINT_INFO > m_List;
|
volatile int m_error_count; ///< thread safe to read.
|
||||||
wxString m_filesNotFound;
|
|
||||||
wxString m_filesInvalid;
|
|
||||||
|
typedef boost::ptr_vector< FOOTPRINT_INFO > FPILIST;
|
||||||
|
typedef boost::ptr_vector< IO_ERROR > ERRLIST;
|
||||||
|
|
||||||
|
FPILIST m_list;
|
||||||
|
ERRLIST m_errors; ///< some can be PARSE_ERRORs also
|
||||||
|
|
||||||
|
#if defined( USE_FP_LIB_TABLE )
|
||||||
|
MUTEX m_errors_lock;
|
||||||
|
MUTEX m_list_lock;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function loader_job
|
||||||
|
* loads footprints from @a aNicknameList and calls AddItem() on to help fill
|
||||||
|
* m_list.
|
||||||
|
*
|
||||||
|
* @param aNicknameList is a wxString[] holding libraries to load all footprints from.
|
||||||
|
* @param aJobZ is the size of the job, i.e. the count of nicknames.
|
||||||
|
*/
|
||||||
|
void loader_job( const wxString* aNicknameList, int aJobZ );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
FOOTPRINT_LIST() :
|
||||||
|
m_lib_table( 0 ),
|
||||||
|
m_error_count( 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetCount
|
* Function GetCount
|
||||||
* @return the number of items stored in list
|
* @return the number of items stored in list
|
||||||
*/
|
*/
|
||||||
unsigned GetCount() const { return m_List.size(); }
|
unsigned GetCount() const { return m_list.size(); }
|
||||||
|
|
||||||
|
/// Was forced to add this by modview_frame.cpp
|
||||||
|
const FPILIST& GetList() const { return m_list; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetModuleInfo
|
* Function GetModuleInfo
|
||||||
* @return the item stored in list if found
|
* @param aFootprintName = the footprint name inside the FOOTPRINT_INFO of interest.
|
||||||
* @param aFootprintName = the name of item
|
* @return const FOOTPRINT_INF* - the item stored in list if found
|
||||||
*/
|
*/
|
||||||
FOOTPRINT_INFO* GetModuleInfo( const wxString & aFootprintName );
|
const FOOTPRINT_INFO* GetModuleInfo( const wxString& aFootprintName );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetItem
|
* Function GetItem
|
||||||
* @return the aIdx item in list
|
|
||||||
* @param aIdx = index of the given item
|
* @param aIdx = index of the given item
|
||||||
|
* @return the aIdx item in list
|
||||||
*/
|
*/
|
||||||
FOOTPRINT_INFO & GetItem( unsigned aIdx )
|
const FOOTPRINT_INFO& GetItem( unsigned aIdx ) const { return m_list[aIdx]; }
|
||||||
{
|
|
||||||
return m_List[aIdx];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function AddItem
|
* Function AddItem
|
||||||
* add aItem in list
|
* add aItem in list
|
||||||
* @param aItem = item to add
|
* @param aItem = item to add
|
||||||
*/
|
*/
|
||||||
void AddItem( FOOTPRINT_INFO* aItem )
|
void AddItem( FOOTPRINT_INFO* aItem );
|
||||||
{
|
|
||||||
m_List.push_back( aItem );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
unsigned GetErrorCount() const { return m_errors.size(); }
|
||||||
|
|
||||||
|
const IO_ERROR* GetError( unsigned aIdx ) const { return &m_errors[aIdx]; }
|
||||||
|
|
||||||
|
#if !defined( USE_FP_LIB_TABLE )
|
||||||
/**
|
/**
|
||||||
* Function ReadFootprintFiles
|
* Function ReadFootprintFiles
|
||||||
*
|
*
|
||||||
* @param aFootprintsLibNames = an array string giving the list of libraries to load
|
* @param aFootprintsLibNames = an array string giving the list of libraries to load
|
||||||
*/
|
*/
|
||||||
bool ReadFootprintFiles( wxArrayString& aFootprintsLibNames );
|
bool ReadFootprintFiles( wxArrayString& aFootprintsLibNames );
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function ReadFootprintFiles
|
* Function ReadFootprintFiles
|
||||||
* reads all the footprints provided by the combination of aTable and aNickname.
|
* reads all the footprints provided by the combination of aTable and aNickname.
|
||||||
|
*
|
||||||
* @param aTable defines all the libraries.
|
* @param aTable defines all the libraries.
|
||||||
* @param aNickname is the library to read from, or if NULL means read all
|
* @param aNickname is the library to read from, or if NULL means read all
|
||||||
* footprints from all known libraries.
|
* footprints from all known libraries in aTable.
|
||||||
|
* @return bool - true if it ran to completion, else false if it aborted after
|
||||||
|
* some number of errors. If true, it does not mean there were no errors, check
|
||||||
|
* GetErrorCount() for that, should be zero to indicate success.
|
||||||
*/
|
*/
|
||||||
bool ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname = NULL );
|
bool ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname = NULL );
|
||||||
|
|
||||||
|
void DisplayErrors( wxTopLevelWindow* aCaller = NULL );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FOOTPRINT_INFO_H_
|
#endif // FOOTPRINT_INFO_H_
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef _html_messagebox_
|
#ifndef _html_messagebox_
|
||||||
#define _html_messagebox_
|
#define _html_messagebox_
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
Subclass of DIALOG_DISPLAY_HTML_TEXT_BASE, which is generated by wxFormBuilder.
|
Subclass of DIALOG_DISPLAY_HTML_TEXT_BASE, which is generated by wxFormBuilder.
|
||||||
|
@ -8,7 +9,10 @@ Subclass of DIALOG_DISPLAY_HTML_TEXT_BASE, which is generated by wxFormBuilder.
|
||||||
|
|
||||||
#include <../common/dialogs/dialog_display_info_HTML_base.h>
|
#include <../common/dialogs/dialog_display_info_HTML_base.h>
|
||||||
|
|
||||||
/** Implementing HTML_MESSAGE_BOX */
|
|
||||||
|
/**
|
||||||
|
* Class HTML_MESSAGE_BOX
|
||||||
|
*/
|
||||||
class HTML_MESSAGE_BOX : public DIALOG_DISPLAY_HTML_TEXT_BASE
|
class HTML_MESSAGE_BOX : public DIALOG_DISPLAY_HTML_TEXT_BASE
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -16,8 +20,10 @@ protected:
|
||||||
void OnCloseButtonClick( wxCommandEvent& event );
|
void OnCloseButtonClick( wxCommandEvent& event );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Constructor */
|
/**
|
||||||
HTML_MESSAGE_BOX( wxWindow* parent, const wxString & aTitle,
|
* Constructor
|
||||||
|
*/
|
||||||
|
HTML_MESSAGE_BOX( wxWindow* parent, const wxString& aTitle,
|
||||||
wxPoint aPos = wxDefaultPosition,
|
wxPoint aPos = wxDefaultPosition,
|
||||||
wxSize aSize = wxSize( 450,250 ) );
|
wxSize aSize = wxSize( 450,250 ) );
|
||||||
|
|
||||||
|
@ -26,28 +32,30 @@ public:
|
||||||
* Add a list of items.
|
* Add a list of items.
|
||||||
* @param aList = a string containing items. Items are separated by '\n'
|
* @param aList = a string containing items. Items are separated by '\n'
|
||||||
*/
|
*/
|
||||||
void ListSet(const wxString &aList);
|
void ListSet( const wxString& aList );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function ListSet
|
* Function ListSet
|
||||||
* Add a list of items.
|
* Add a list of items.
|
||||||
* @param aList = a wxArrayString containing items.
|
* @param aList = a wxArrayString containing items.
|
||||||
*/
|
*/
|
||||||
void ListSet(const wxArrayString &aList);
|
void ListSet( const wxArrayString& aList );
|
||||||
|
|
||||||
void ListClear();
|
void ListClear();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function MessageSet
|
* Function MessageSet
|
||||||
* Add a message (in bold) to message list.
|
* adds a message (in bold) to message list.
|
||||||
* @param message = the message
|
* @param message = the message
|
||||||
*/
|
*/
|
||||||
void MessageSet(const wxString &message);
|
void MessageSet( const wxString& message );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function AddHTML_Text
|
* Function AddHTML_Text
|
||||||
* Add a html text (without any change) to message list.
|
* adds html text (without any change) to message list.
|
||||||
* @param message = the text to add
|
* @param message = the text to add
|
||||||
*/
|
*/
|
||||||
void AddHTML_Text(const wxString &message);
|
void AddHTML_Text( const wxString& message );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _html_messagebox_
|
#endif // _html_messagebox_
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
#ifndef KI_MUTEX_H_
|
||||||
|
#define KI_MUTEX_H_
|
||||||
|
|
||||||
|
|
||||||
|
/// Establish KiCad MUTEX choices here in this file:
|
||||||
|
/// typedef MUTEX and typedef MUTLOCK.
|
||||||
|
///
|
||||||
|
/// Using an unnamed resource is easier, providing a textual name for a
|
||||||
|
/// constructor is cumbersome, so we make choice on that criteria mostly:
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
// This is a fine choice between the two, but requires linking to ${Boost_LIBRARIES}
|
||||||
|
// which currently only happens when GITHUB_PLUGIN goes into pcbnew or _pcbnew.
|
||||||
|
// cvpcb is left out. Changing the 4 CMakeLists.txts fixes all this easily.
|
||||||
|
|
||||||
|
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||||
|
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||||
|
|
||||||
|
typedef boost::interprocess::interprocess_mutex MUTEX;
|
||||||
|
typedef boost::interprocess::scoped_lock<MUTEX> MUTLOCK;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <wx/thread.h>
|
||||||
|
|
||||||
|
typedef wxMutex MUTEX;
|
||||||
|
typedef wxMutexLocker MUTLOCK;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // KI_MUTEX_H_
|
|
@ -93,7 +93,7 @@ std::string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct IO_ERROR
|
* Struct IO_ERROR
|
||||||
* is a class used to hold an error message and may be used to throw exceptions
|
* is a class used to hold an error message and may be used when throwing exceptions
|
||||||
* containing meaningful error messages.
|
* containing meaningful error messages.
|
||||||
* @author Dick Hollenbeck
|
* @author Dick Hollenbeck
|
||||||
*/
|
*/
|
||||||
|
@ -148,7 +148,9 @@ struct IO_ERROR // : std::exception
|
||||||
|
|
||||||
IO_ERROR() {}
|
IO_ERROR() {}
|
||||||
|
|
||||||
~IO_ERROR() throw ( /*none*/ ){}
|
// Destructor is virtual because PARSE_ERROR is derived from it and
|
||||||
|
// boost::ptr_vector lists consisting of both will need a virtual destructor.
|
||||||
|
virtual ~IO_ERROR() throw ( /*none*/ ){}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
#ifndef UTF8_H_
|
||||||
|
#define UTF8_H_
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
|
* Copyright (C) 2013 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UTF8
|
||||||
|
* is an 8 bit std::string that is assuredly encoded in UTF8, and supplies special
|
||||||
|
* conversion support to and from wxString, and has iteration over unicode characters.
|
||||||
|
*
|
||||||
|
* <p>I've been careful to supply only conversion facilities and not try
|
||||||
|
* and duplicate wxString() with many member functions. In the end it is
|
||||||
|
* to be a std::string. There are multiple ways to create text into a std::string
|
||||||
|
* without the need of too many member functions:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>richio.h's StrPrintf()</li>
|
||||||
|
* <li>std::ostringstream.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>Because this class used no virtuals, it should be possible to cast any
|
||||||
|
* std::string into a UTF8 using this kind of cast: (UTF8 &) without construction
|
||||||
|
* or copying being the effect of the cast. Be sure the source std::string holds
|
||||||
|
* UTF8 encoded text before you do that.
|
||||||
|
*
|
||||||
|
* @author Dick Hollenbeck
|
||||||
|
*/
|
||||||
|
class UTF8 : public std::string
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
UTF8( const wxString& o );
|
||||||
|
|
||||||
|
/// This is the only constructor for which you could end up with
|
||||||
|
/// non-UTF8 encoding, but that would be your fault.
|
||||||
|
UTF8( const char* txt ) :
|
||||||
|
std::string( txt )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For use with _() function on wx 2.8:
|
||||||
|
UTF8( const wchar_t* txt );
|
||||||
|
|
||||||
|
explicit UTF8( const std::string& o ) :
|
||||||
|
std::string( o )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UTF8() :
|
||||||
|
std::string()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UTF8& operator=( const wxString& o );
|
||||||
|
|
||||||
|
UTF8& operator=( const std::string& o )
|
||||||
|
{
|
||||||
|
std::string::operator=( o );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator wxString () const;
|
||||||
|
|
||||||
|
/// This one is not in std::string, and one wonders why... might be a solid
|
||||||
|
/// enough reason to remove it still.
|
||||||
|
operator char* () const
|
||||||
|
{
|
||||||
|
return (char*) c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function uni_forward
|
||||||
|
* advances over a single UTF8 encoded multibyte character, capturing the
|
||||||
|
* unicode character as it goes, and returning the number of bytes consumed.
|
||||||
|
*
|
||||||
|
* @param aSequence is the UTF8 byte sequence, must be aligned on start of character.
|
||||||
|
* @param aResult is where to put the unicode character, and may be NULL if no interest.
|
||||||
|
* @return int - the count of bytes consumed.
|
||||||
|
*/
|
||||||
|
static int uni_forward( const unsigned char* aSequence, unsigned* aResult = NULL );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class uni_iter
|
||||||
|
* is a non-muting iterator that walks through unicode code points in the UTF8 encoded
|
||||||
|
* string. The normal ++(), ++(int), ->(), and *() operators are all supported
|
||||||
|
* for read only access and they return an unsigned holding the unicode character
|
||||||
|
* appropriate for the respective operator.
|
||||||
|
*/
|
||||||
|
class uni_iter
|
||||||
|
{
|
||||||
|
friend class UTF8;
|
||||||
|
|
||||||
|
const unsigned char* it;
|
||||||
|
|
||||||
|
// private constructor.
|
||||||
|
uni_iter( const char* start ) :
|
||||||
|
it( (const unsigned char*) start )
|
||||||
|
{
|
||||||
|
// for the human: assert( sizeof(unsigned) >= 4 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
uni_iter( const uni_iter& o )
|
||||||
|
{
|
||||||
|
it = o.it;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// pre-increment and return uni_iter at new position
|
||||||
|
const uni_iter& operator++()
|
||||||
|
{
|
||||||
|
it += uni_forward( it );
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// post-increment and return uni_iter at initial position
|
||||||
|
uni_iter operator++( int )
|
||||||
|
{
|
||||||
|
uni_iter ret = *this;
|
||||||
|
|
||||||
|
it += uni_forward( it );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
/// return unicode at current position
|
||||||
|
unsigned operator->() const
|
||||||
|
{
|
||||||
|
unsigned result;
|
||||||
|
|
||||||
|
// grab the result, do not advance
|
||||||
|
uni_forward( it, &result );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// return unicode at current position
|
||||||
|
unsigned operator*() const
|
||||||
|
{
|
||||||
|
unsigned result;
|
||||||
|
|
||||||
|
// grab the result, do not advance
|
||||||
|
uni_forward( it, &result );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==( const uni_iter& other ) const { return it == other.it; }
|
||||||
|
bool operator!=( const uni_iter& other ) const { return it != other.it; }
|
||||||
|
|
||||||
|
/// Since the ++ operators advance more than one byte, this is your best
|
||||||
|
/// loop termination test, < end(), not == end().
|
||||||
|
bool operator< ( const uni_iter& other ) const { return it < other.it; }
|
||||||
|
bool operator<=( const uni_iter& other ) const { return it <= other.it; }
|
||||||
|
bool operator> ( const uni_iter& other ) const { return it > other.it; }
|
||||||
|
bool operator>=( const uni_iter& other ) const { return it >= other.it; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ubegin
|
||||||
|
* returns a @a uni_iter initialized to the start of "this" UTF8 byte sequence.
|
||||||
|
*/
|
||||||
|
uni_iter ubegin() const
|
||||||
|
{
|
||||||
|
return uni_iter( data() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function uend
|
||||||
|
* returns a @a uni_iter initialized to the end of "this" UTF8 byte sequence.
|
||||||
|
*/
|
||||||
|
uni_iter uend() const
|
||||||
|
{
|
||||||
|
return uni_iter( data() + size() );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // UTF8_H__
|
|
@ -38,10 +38,10 @@ double UNIT_SELECTOR_LEN::GetUnitScale()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UNIT_SELECTOR_FREQUENCY::UNIT_SELECTOR_FREQUENCY(wxWindow *parent, wxWindowID id,
|
UNIT_SELECTOR_FREQUENCY::UNIT_SELECTOR_FREQUENCY( wxWindow *parent, wxWindowID id,
|
||||||
const wxPoint& pos, const wxSize& size,
|
const wxPoint& pos, const wxSize& size,
|
||||||
const wxArrayString& choices, long style )
|
const wxArrayString& choices, long style ):
|
||||||
: UNIT_SELECTOR( parent, id, pos, size, choices, style )
|
UNIT_SELECTOR( parent, id, pos, size, choices, style )
|
||||||
{
|
{
|
||||||
Append( _("GHz") );
|
Append( _("GHz") );
|
||||||
Append( _("MHz") );
|
Append( _("MHz") );
|
||||||
|
@ -58,19 +58,19 @@ double UNIT_SELECTOR_FREQUENCY::GetUnitScale()
|
||||||
{
|
{
|
||||||
switch( GetCurrentSelection() )
|
switch( GetCurrentSelection() )
|
||||||
{
|
{
|
||||||
case 0: return UNIT_GHZ; break;
|
case 0: return UNIT_GHZ;
|
||||||
case 1: return UNIT_MHZ; break;
|
case 1: return UNIT_MHZ;
|
||||||
case 2: return UNIT_KHZ; break;
|
case 2: return UNIT_KHZ;
|
||||||
case 3: return 1.0; break;
|
case 3: return 1.0;
|
||||||
}
|
}
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UNIT_SELECTOR_ANGLE::UNIT_SELECTOR_ANGLE(wxWindow *parent, wxWindowID id,
|
UNIT_SELECTOR_ANGLE::UNIT_SELECTOR_ANGLE( wxWindow *parent, wxWindowID id,
|
||||||
const wxPoint& pos, const wxSize& size,
|
const wxPoint& pos, const wxSize& size,
|
||||||
const wxArrayString& choices, long style )
|
const wxArrayString& choices, long style ) :
|
||||||
: UNIT_SELECTOR( parent, id, pos, size, choices, style )
|
UNIT_SELECTOR( parent, id, pos, size, choices, style )
|
||||||
{
|
{
|
||||||
Append( _("Radian") );
|
Append( _("Radian") );
|
||||||
Append( _("Degree") );
|
Append( _("Degree") );
|
||||||
|
|
|
@ -537,18 +537,11 @@ wxString PCB_BASE_FRAME::SelectFootprint( EDA_DRAW_FRAME* aWindow,
|
||||||
|
|
||||||
wxASSERT( aTable != NULL );
|
wxASSERT( aTable != NULL );
|
||||||
|
|
||||||
if( !MList.ReadFootprintFiles( aTable, !aLibraryName ? NULL : &aLibraryName ) )
|
MList.ReadFootprintFiles( aTable, !aLibraryName ? NULL : &aLibraryName );
|
||||||
|
|
||||||
|
if( MList.GetErrorCount() )
|
||||||
{
|
{
|
||||||
msg.Format( _( "Error occurred attempting to load footprint library '%s':\n\n" ),
|
MList.DisplayErrors( this );
|
||||||
GetChars( aLibraryName ) );
|
|
||||||
|
|
||||||
if( !MList.m_filesNotFound.IsEmpty() )
|
|
||||||
msg += _( "Files not found:\n\n" ) + MList.m_filesNotFound;
|
|
||||||
|
|
||||||
if( !MList.m_filesInvalid.IsEmpty() )
|
|
||||||
msg += _("\n\nFile load errors:\n\n" ) + MList.m_filesInvalid;
|
|
||||||
|
|
||||||
DisplayError( this, msg );
|
|
||||||
return wxEmptyString;
|
return wxEmptyString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,7 +580,7 @@ wxString PCB_BASE_FRAME::SelectFootprint( EDA_DRAW_FRAME* aWindow,
|
||||||
{
|
{
|
||||||
for( unsigned ii = 0; ii < MList.GetCount(); ii++ )
|
for( unsigned ii = 0; ii < MList.GetCount(); ii++ )
|
||||||
{
|
{
|
||||||
wxString& candidate = MList.GetItem( ii ).m_Module;
|
const wxString& candidate = MList.GetItem( ii ).m_Module;
|
||||||
|
|
||||||
if( WildCompareString( aMask, candidate, false ) )
|
if( WildCompareString( aMask, candidate, false ) )
|
||||||
{
|
{
|
||||||
|
@ -648,18 +641,18 @@ wxString PCB_BASE_FRAME::SelectFootprint( EDA_DRAW_FRAME* aWindow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void DisplayCmpDoc( wxString& Name )
|
static void DisplayCmpDoc( wxString& aName )
|
||||||
{
|
{
|
||||||
FOOTPRINT_INFO* module_info = MList.GetModuleInfo( Name );
|
const FOOTPRINT_INFO* module_info = MList.GetModuleInfo( aName );
|
||||||
|
|
||||||
if( !module_info )
|
if( !module_info )
|
||||||
{
|
{
|
||||||
Name.Empty();
|
aName.Empty();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Name = _( "Description: " ) + module_info->m_Doc;
|
aName = _( "Description: " ) + module_info->m_Doc;
|
||||||
Name += _( "\nKey words: " ) + module_info->m_KeyWord;
|
aName += _( "\nKey words: " ) + module_info->m_KeyWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -385,43 +385,29 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool libLoaded = false;
|
|
||||||
FOOTPRINT_LIST fp_info_list;
|
FOOTPRINT_LIST fp_info_list;
|
||||||
wxArrayString libsList;
|
wxArrayString libsList;
|
||||||
|
|
||||||
#if !defined( USE_FP_LIB_TABLE )
|
#if !defined( USE_FP_LIB_TABLE )
|
||||||
|
|
||||||
libsList.Add( m_libraryName );
|
libsList.Add( m_libraryName );
|
||||||
libLoaded = fp_info_list.ReadFootprintFiles( libsList );
|
fp_info_list.ReadFootprintFiles( libsList );
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
libLoaded = fp_info_list.ReadFootprintFiles( m_footprintLibTable, &m_libraryName );
|
fp_info_list.ReadFootprintFiles( m_footprintLibTable, &m_libraryName );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( !libLoaded )
|
if( fp_info_list.GetErrorCount() )
|
||||||
{
|
{
|
||||||
m_footprintName = wxEmptyString;
|
fp_info_list.DisplayErrors( this );
|
||||||
m_libraryName = wxEmptyString;
|
|
||||||
|
|
||||||
wxString msg;
|
|
||||||
msg.Format( _( "Error occurred attempting to load footprint library <%s>:\n\n" ),
|
|
||||||
GetChars( m_libraryName ) );
|
|
||||||
|
|
||||||
if( !fp_info_list.m_filesNotFound.IsEmpty() )
|
|
||||||
msg += _( "Files not found:\n\n" ) + fp_info_list.m_filesNotFound;
|
|
||||||
|
|
||||||
if( !fp_info_list.m_filesInvalid.IsEmpty() )
|
|
||||||
msg += _( "\n\nFile load errors:\n\n" ) + fp_info_list.m_filesInvalid;
|
|
||||||
|
|
||||||
DisplayError( this, msg );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxArrayString fpList;
|
wxArrayString fpList;
|
||||||
|
|
||||||
BOOST_FOREACH( FOOTPRINT_INFO& footprint, fp_info_list.m_List )
|
BOOST_FOREACH( const FOOTPRINT_INFO& footprint, fp_info_list.GetList() )
|
||||||
{
|
{
|
||||||
fpList.Add( footprint.m_Module );
|
fpList.Add( footprint.m_Module );
|
||||||
}
|
}
|
||||||
|
@ -538,23 +524,23 @@ void FOOTPRINT_VIEWER_FRAME::ExportSelectedFootprint( wxCommandEvent& event )
|
||||||
|
|
||||||
void FOOTPRINT_VIEWER_FRAME::LoadSettings( )
|
void FOOTPRINT_VIEWER_FRAME::LoadSettings( )
|
||||||
{
|
{
|
||||||
wxConfig* cfg ;
|
|
||||||
|
|
||||||
EDA_DRAW_FRAME::LoadSettings();
|
EDA_DRAW_FRAME::LoadSettings();
|
||||||
|
|
||||||
wxConfigPathChanger cpc( wxGetApp().GetSettings(), m_configPath );
|
wxConfigPathChanger cpc( wxGetApp().GetSettings(), m_configPath );
|
||||||
cfg = wxGetApp().GetSettings();
|
|
||||||
|
// wxConfig* cfg =
|
||||||
|
wxGetApp().GetSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FOOTPRINT_VIEWER_FRAME::SaveSettings()
|
void FOOTPRINT_VIEWER_FRAME::SaveSettings()
|
||||||
{
|
{
|
||||||
wxConfig* cfg;
|
|
||||||
|
|
||||||
EDA_DRAW_FRAME::SaveSettings();
|
EDA_DRAW_FRAME::SaveSettings();
|
||||||
|
|
||||||
wxConfigPathChanger cpc( wxGetApp().GetSettings(), m_configPath );
|
wxConfigPathChanger cpc( wxGetApp().GetSettings(), m_configPath );
|
||||||
cfg = wxGetApp().GetSettings();
|
|
||||||
|
// wxConfig* cfg =
|
||||||
|
wxGetApp().GetSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue