Rewrite class UTF8 to contain rather than extend std::string storage.

This forces the compiler class specific features rather than borrowing
from the base class's std::string.  In some cases prior to this,
wxString( std::string ) was being called rather than UTF8::operator
wxString() leading to garbled wxStrings.

Added function UTF8::wx_str() which is of great convenience also.

Implicit conversions still work as before, and hopefully more reliably.
This commit is contained in:
Dick Hollenbeck 2017-07-25 14:14:31 -05:00 committed by Wayne Stambaugh
parent 0aedaffed9
commit 19e6bde09a
18 changed files with 170 additions and 97 deletions

View File

@ -286,7 +286,7 @@ MODULE* FP_LIB_TABLE::FootprintLoad( const wxString& aNickname, const wxString&
LIB_ID& fpid = (LIB_ID&) ret->GetFPID(); LIB_ID& fpid = (LIB_ID&) ret->GetFPID();
// Catch any misbehaving plugin, which should be setting internal footprint name properly: // Catch any misbehaving plugin, which should be setting internal footprint name properly:
wxASSERT( aFootprintName == (wxString) fpid.GetLibItemName() ); wxASSERT( aFootprintName == fpid.GetLibItemName().wx_str() );
// and clearing nickname // and clearing nickname
wxASSERT( !fpid.GetLibNickname().size() ); wxASSERT( !fpid.GetLibNickname().size() );

View File

@ -83,7 +83,7 @@ int RevCmp( const char* s1, const char* s2 )
//----<Policy and field test functions>------------------------------------- //----<Policy and field test functions>-------------------------------------
static inline int okLogical( const std::string& aField ) static inline int okLogical( const UTF8& aField )
{ {
// std::string::npos is largest positive number, casting to int makes it -1. // std::string::npos is largest positive number, casting to int makes it -1.
// Returning that means success. // Returning that means success.
@ -91,7 +91,7 @@ static inline int okLogical( const std::string& aField )
} }
static int okRevision( const std::string& aField ) static int okRevision( const UTF8& aField )
{ {
char rev[32]; // C string for speed char rev[32]; // C string for speed
@ -175,7 +175,7 @@ int LIB_ID::Parse( const UTF8& aId )
} }
LIB_ID::LIB_ID( const std::string& aId ) LIB_ID::LIB_ID( const UTF8& aId )
{ {
int offset = Parse( aId ); int offset = Parse( aId );

View File

@ -40,11 +40,17 @@
UTF8::UTF8( const wxString& o ) : UTF8::UTF8( const wxString& o ) :
std::string( (const char*) o.utf8_str() ) m_s( (const char*) o.utf8_str() )
{ {
} }
wxString UTF8::wx_str() const
{
return wxString( c_str(), wxConvUTF8 );
}
UTF8::operator wxString () const UTF8::operator wxString () const
{ {
return wxString( c_str(), wxConvUTF8 ); return wxString( c_str(), wxConvUTF8 );
@ -53,7 +59,7 @@ UTF8::operator wxString () const
UTF8& UTF8::operator=( const wxString& o ) UTF8& UTF8::operator=( const wxString& o )
{ {
std::string::operator=( (const char*) o.utf8_str() ); m_s = (const char*) o.utf8_str();
return *this; return *this;
} }
@ -193,7 +199,7 @@ bool IsUTF8( const char* aString )
UTF8::UTF8( const wchar_t* txt ) : UTF8::UTF8( const wchar_t* txt ) :
// size initial string safely large enough, then shrink to known size later. // size initial string safely large enough, then shrink to known size later.
std::string( wcslen( txt ) * 4, 0 ) m_s( wcslen( txt ) * 4, 0 )
{ {
/* /*
@ -206,9 +212,9 @@ UTF8::UTF8( const wchar_t* txt ) :
*/ */
int sz = wxConvUTF8.WC2MB( (char*) data(), txt, size() ); int sz = wxConvUTF8.WC2MB( (char*) m_s.data(), txt, m_s.size() );
resize( sz ); m_s.resize( sz );
} }

View File

@ -811,7 +811,7 @@ int CVPCB_MAINFRAME::ReadSchematicNetlist( const std::string& aNetlist )
for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ ) for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ )
{ {
if( m_netlist.GetComponent( ii )->GetFPID().GetLibItemName() == std::string( "$noname" ) ) if( m_netlist.GetComponent( ii )->GetFPID().GetLibItemName() == std::string( "$noname" ) )
m_netlist.GetComponent( ii )->SetFPID( LIB_ID( wxEmptyString ) ); m_netlist.GetComponent( ii )->SetFPID( LIB_ID() );
} }
// Sort components by reference: // Sort components by reference:

View File

@ -672,7 +672,7 @@ void PART_LIBS::LoadAllLibraries( PROJECT* aProject, bool aShowProgress )
{ {
// Use a different exception type so catch()er can route to proper use // Use a different exception type so catch()er can route to proper use
// of the HTML_MESSAGE_BOX. // of the HTML_MESSAGE_BOX.
THROW_PARSE_ERROR( wxEmptyString, UTF8( __func__ ), UTF8( libs_not_found ), 0, 0 ); THROW_PARSE_ERROR( wxEmptyString, __func__, TO_UTF8(libs_not_found), 0, 0 );
} }
#if defined(DEBUG) && 1 #if defined(DEBUG) && 1

View File

@ -205,14 +205,14 @@ void DIALOG_SYMBOL_REMAP::remapSymbolsToLibTable( REPORTER& aReporter )
if( !remapSymbolToLibTable( symbol ) ) if( !remapSymbolToLibTable( symbol ) )
{ {
msg.Printf( _( "No symbol '%s' founded in symbol library table." ), msg.Printf( _( "No symbol '%s' founded in symbol library table." ),
FROM_UTF8( symbol->GetLibId().GetLibItemName() ) ); symbol->GetLibId().GetLibItemName().wx_str() );
aReporter.Report( msg, REPORTER::RPT_WARNING ); aReporter.Report( msg, REPORTER::RPT_WARNING );
} }
else else
{ {
msg.Printf( _( "Symbol '%s' mapped to symbol library '%s'." ), msg.Printf( _( "Symbol '%s' mapped to symbol library '%s'." ),
FROM_UTF8( symbol->GetLibId().GetLibItemName() ), symbol->GetLibId().GetLibItemName().wx_str(),
FROM_UTF8( symbol->GetLibId().GetLibNickname() ) ); symbol->GetLibId().GetLibNickname().wx_str() );
aReporter.Report( msg, REPORTER::RPT_ACTION ); aReporter.Report( msg, REPORTER::RPT_ACTION );
} }
} }

View File

@ -106,7 +106,7 @@ bool SCH_EDIT_FRAME::CreateArchiveLibrary( const wxString& aFileName )
catch( ... /* IO_ERROR ioe */ ) catch( ... /* IO_ERROR ioe */ )
{ {
msg.Printf( _( "Failed to add symbol %s to library file '%s'" ), msg.Printf( _( "Failed to add symbol %s to library file '%s'" ),
wxString( component->GetLibId().GetLibItemName() ), aFileName ); component->GetLibId().GetLibItemName().wx_str(), aFileName );
DisplayError( this, msg ); DisplayError( this, msg );
return false; return false;
} }

View File

@ -264,7 +264,7 @@ public:
for( SCH_COMPONENT* each_component : *( aRescuer.GetComponents() ) ) for( SCH_COMPONENT* each_component : *( aRescuer.GetComponents() ) )
{ {
wxString part_name( each_component->GetLibId().GetLibItemName() ); wxString part_name = each_component->GetLibId().GetLibItemName();
if( last_part_name != part_name ) if( last_part_name != part_name )
{ {
@ -373,7 +373,7 @@ public:
for( SCH_COMPONENT* each_component : *( aRescuer.GetComponents() ) ) for( SCH_COMPONENT* each_component : *( aRescuer.GetComponents() ) )
{ {
wxString part_name( each_component->GetLibId().GetLibItemName() ); wxString part_name = each_component->GetLibId().GetLibItemName();
if( old_part_name != part_name ) if( old_part_name != part_name )
{ {

View File

@ -271,7 +271,7 @@ LIB_ALIAS* SYMBOL_LIB_TABLE::LoadSymbol( const wxString& aNickname, const wxStri
LIB_ID& id = (LIB_ID&) ret->GetPart()->GetLibId(); LIB_ID& id = (LIB_ID&) ret->GetPart()->GetLibId();
// Catch any misbehaving plugin, which should be setting internal alias name properly: // Catch any misbehaving plugin, which should be setting internal alias name properly:
wxASSERT( aAliasName == (wxString) id.GetLibItemName() ); wxASSERT( aAliasName == id.GetLibItemName().wx_str() );
// and clearing nickname // and clearing nickname
wxASSERT( !id.GetLibNickname().size() ); wxASSERT( !id.GetLibNickname().size() );

View File

@ -70,7 +70,7 @@ public:
* *
* @param aId is a string to be parsed into the LIB_ID object. * @param aId is a string to be parsed into the LIB_ID object.
*/ */
LIB_ID( const std::string& aId ); LIB_ID( const UTF8& aId );
LIB_ID( const wxString& aId ); LIB_ID( const wxString& aId );

View File

@ -50,13 +50,13 @@ bool IsUTF8( const char* aString );
/** /**
* Class UTF8 * Class UTF8
* is an 8 bit std::string that is assuredly encoded in UTF8, and supplies special * is an 8 bit string that is assuredly encoded in UTF8, and supplies special
* conversion support to and from wxString, and has iteration over unicode characters. * conversion support to and from wxString, to and from std::string, and has
* non-mutating iteration over unicode characters.
* *
* <p>I've been careful to supply only conversion facilities and not try * <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 * and duplicate wxString() with many member functions. There are multiple ways
* to be a std::string. There are multiple ways to create text into a std::string * to create text into a std::string without the need of too many member functions:
* without the need of too many member functions:
* *
* <ul> * <ul>
* <li>richio.h's StrPrintf()</li> * <li>richio.h's StrPrintf()</li>
@ -70,7 +70,7 @@ bool IsUTF8( const char* aString );
* *
* @author Dick Hollenbeck * @author Dick Hollenbeck
*/ */
class UTF8 : public std::string class UTF8
{ {
public: public:
@ -79,7 +79,7 @@ public:
/// This is a constructor for which you could end up with /// This is a constructor for which you could end up with
/// non-UTF8 encoding, but that would be your fault. /// non-UTF8 encoding, but that would be your fault.
UTF8( const char* txt ) : UTF8( const char* txt ) :
std::string( txt ) m_s( txt )
{ {
MAYBE_VERIFY_UTF8( c_str() ); MAYBE_VERIFY_UTF8( c_str() );
} }
@ -89,13 +89,12 @@ public:
UTF8( const wchar_t* txt ); UTF8( const wchar_t* txt );
UTF8( const std::string& o ) : UTF8( const std::string& o ) :
std::string( o ) m_s( o )
{ {
MAYBE_VERIFY_UTF8( c_str() ); MAYBE_VERIFY_UTF8( c_str() );
} }
UTF8() : UTF8()
std::string()
{ {
} }
@ -103,61 +102,97 @@ public:
{ {
} }
// expose some std::string functions publicly, since base class must be private.
const char* c_str() const { return m_s.c_str(); }
bool empty() const { return m_s.empty(); }
std::string::size_type find( char c ) const { return m_s.find( c ); }
std::string::size_type find( char c, size_t& s ) const { return m_s.find( c, s ); }
void clear() { m_s.clear(); }
std::string::size_type length() const { return m_s.length(); }
std::string::size_type size() const { return m_s.size(); }
int compare( const std::string& s ) const { return m_s.compare( s ); }
bool operator==( const UTF8& rhs ) const { return m_s == rhs.m_s; }
bool operator==( const std::string& rhs ) const { return m_s == rhs; }
bool operator==( const char* s ) const { return m_s == s; }
std::string::size_type find_first_of( const std::string& str, std::string::size_type pos = 0 ) const
{
return m_s.find_first_of( str, pos );
}
UTF8& operator+=( const UTF8& str )
{
m_s += str.m_s;
MAYBE_VERIFY_UTF8( c_str() );
return (UTF8&) *this;
}
UTF8& operator+=( char ch )
{
m_s.operator+=( ch );
MAYBE_VERIFY_UTF8( c_str() );
return (UTF8&) *this;
}
UTF8& operator+=( const char* s )
{
m_s.operator+=( s );
MAYBE_VERIFY_UTF8( c_str() );
return (UTF8&) *this;
}
static const std::string::size_type npos = std::string::npos;
UTF8& operator=( const wxString& o ); UTF8& operator=( const wxString& o );
UTF8& operator=( const std::string& o ) UTF8& operator=( const std::string& o )
{ {
std::string::operator=( o ); m_s = o;
MAYBE_VERIFY_UTF8( c_str() ); MAYBE_VERIFY_UTF8( c_str() );
return *this; return *this;
} }
UTF8& operator=( const char* s ) UTF8& operator=( const char* s )
{ {
std::string::operator=( s ); m_s = s;
MAYBE_VERIFY_UTF8( c_str() ); MAYBE_VERIFY_UTF8( c_str() );
return *this; return *this;
} }
UTF8& operator=( char c ) UTF8& operator=( char c )
{ {
std::string::operator=( c ); m_s = c;
MAYBE_VERIFY_UTF8( c_str() ); MAYBE_VERIFY_UTF8( c_str() );
return *this; return *this;
} }
UTF8 substr( size_t pos = 0, size_t len = npos ) const // a substring of a UTF8 is not necessarily a UTF8 if a multibyte character
// was split, so return std::string not UTF8
std::string substr( size_t pos = 0, size_t len = npos ) const
{ {
return std::string::substr( pos, len ); return m_s.substr( pos, len );
} }
operator const std::string& () const { return m_s; }
//operator std::string& () { return m_s; }
//operator std::string () const { return m_s; }
wxString wx_str() const;
operator wxString () const; operator wxString () const;
/// This one is not in std::string, and one wonders why... might be a solid // "Read only" iterating over bytes is done with these, use the uni_iter to iterate
/// enough reason to remove it still. // over UTF8 (multi-byte) characters
operator char* () const std::string::const_iterator begin() const { return m_s.begin(); }
{ std::string::const_iterator end() const { return m_s.end(); }
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 );
#ifndef SWIG #ifndef SWIG
/** /**
* class uni_iter * class uni_iter
* is a non-muting iterator that walks through unicode code points in the UTF8 encoded * is a non-mutating iterator that walks through unicode code points in the UTF8 encoded
* string. The normal ++(), ++(int), ->(), and *() operators are all supported * string. The normal ++(), ++(int), ->(), and *() operators are all supported
* for read only access and some return an unsigned holding the unicode character * for read only access and some return an unsigned holding the unicode character
* appropriate for the respective operator. * appropriate for the respective operator.
@ -168,11 +203,10 @@ public:
const unsigned char* it; const unsigned char* it;
// private constructor. // private constructor
uni_iter( const char* start ) : uni_iter( const char* start ) :
it( (const unsigned char*) start ) it( (const unsigned char*) start )
{ {
// for the human: assert( sizeof(unsigned) >= 4 );
} }
@ -204,7 +238,6 @@ public:
return ret; return ret;
} }
/*
/// return unicode at current position /// return unicode at current position
unsigned operator->() const unsigned operator->() const
{ {
@ -214,7 +247,6 @@ public:
uni_forward( it, &result ); uni_forward( it, &result );
return result; return result;
} }
*/
/// return unicode at current position /// return unicode at current position
unsigned operator*() const unsigned operator*() const
@ -226,6 +258,8 @@ public:
return result; return result;
} }
uni_iter operator-( int aVal ) const { return uni_iter( (char*) it - aVal ); }
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; }
@ -243,7 +277,7 @@ public:
*/ */
uni_iter ubegin() const uni_iter ubegin() const
{ {
return uni_iter( data() ); return uni_iter( m_s.data() );
} }
/** /**
@ -252,9 +286,24 @@ public:
*/ */
uni_iter uend() const uni_iter uend() const
{ {
return uni_iter( data() + size() ); return uni_iter( m_s.data() + m_s.size() );
} }
/**
* 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 );
#endif // SWIG #endif // SWIG
protected:
std::string m_s;
}; };
#endif // UTF8_H_ #endif // UTF8_H_

View File

@ -1165,7 +1165,7 @@ MODULE* EAGLE_PLUGIN::makeModule( wxXmlNode* aPackage, const string& aPkgName )
{ {
std::unique_ptr<MODULE> m( new MODULE( m_board ) ); std::unique_ptr<MODULE> m( new MODULE( m_board ) );
m->SetFPID( LIB_ID( aPkgName ) ); m->SetFPID( LIB_ID( UTF8(aPkgName) ) );
// Get the first package item and iterate // Get the first package item and iterate
wxXmlNode* packageItem = aPackage->GetChildren(); wxXmlNode* packageItem = aPackage->GetChildren();

View File

@ -116,7 +116,7 @@ private:
static int m_fileOpt; static int m_fileOpt;
static int m_fileFormat; static int m_fileFormat;
void initDialog(); void initDialog();
void OnOutputDirectoryBrowseClicked( wxCommandEvent& event ) override; void OnOutputDirectoryBrowseClicked( wxCommandEvent& event ) override;
void OnOKButton( wxCommandEvent& event ) override; void OnOKButton( wxCommandEvent& event ) override;
@ -524,7 +524,7 @@ int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName,
line << csv_sep; line << csv_sep;
line << list[ii].m_Value; line << list[ii].m_Value;
line << csv_sep; line << csv_sep;
line << wxString( list[ii].m_Module->GetFPID().GetLibItemName() ); line << list[ii].m_Module->GetFPID().GetLibItemName().wx_str();
line << csv_sep; line << csv_sep;
line << wxString::Format( "%f%c%f%c%f", line << wxString::Format( "%f%c%f%c%f",

View File

@ -98,9 +98,9 @@ using namespace std;
static const char* PRETTY_DIR = "allow_pretty_writing_to_this_dir"; static const char* PRETTY_DIR = "allow_pretty_writing_to_this_dir";
typedef boost::ptr_map<string, wxZipEntry> MODULE_MAP; typedef boost::ptr_map< wxString, wxZipEntry > MODULE_MAP;
typedef MODULE_MAP::iterator MODULE_ITER; typedef MODULE_MAP::iterator MODULE_ITER;
typedef MODULE_MAP::const_iterator MODULE_CITER; typedef MODULE_MAP::const_iterator MODULE_CITER;
/** /**
@ -160,7 +160,7 @@ void GITHUB_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames,
for( MODULE_ITER it = m_gh_cache->begin(); it!=m_gh_cache->end(); ++it ) for( MODULE_ITER it = m_gh_cache->begin(); it!=m_gh_cache->end(); ++it )
{ {
unique.insert( FROM_UTF8( it->first.c_str() ) ); unique.insert( it->first );
} }
for( MYSET::const_iterator it = unique.begin(); it != unique.end(); ++it ) for( MYSET::const_iterator it = unique.begin(); it != unique.end(); ++it )
@ -205,9 +205,7 @@ MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
} }
} }
UTF8 fp_name = aFootprintName; MODULE_CITER it = m_gh_cache->find( aFootprintName );
MODULE_CITER it = m_gh_cache->find( fp_name );
if( it != m_gh_cache->end() ) // fp_name is present if( it != m_gh_cache->end() ) // fp_name is present
{ {
@ -234,7 +232,7 @@ MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
// any name found in the pretty file; any name in the pretty file // any name found in the pretty file; any name in the pretty file
// must be ignored here. Also, the library nickname is unknown in // must be ignored here. Also, the library nickname is unknown in
// this context so clear it just in case. // this context so clear it just in case.
ret->SetFPID( fp_name ); ret->SetFPID( aFootprintName );
return ret; return ret;
} }
@ -447,6 +445,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
wxZipInputStream zis( mis, wxConvUTF8 ); wxZipInputStream zis( mis, wxConvUTF8 );
wxZipEntry* entry; wxZipEntry* entry;
wxString fp_name;
while( ( entry = zis.GetNextEntry() ) != NULL ) while( ( entry = zis.GetNextEntry() ) != NULL )
{ {
@ -454,9 +453,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
if( fn.GetExt() == kicad_mod ) if( fn.GetExt() == kicad_mod )
{ {
UTF8 fp_name = fn.GetName(); // omit extension & path fp_name = fn.GetName(); // omit extension & path
wxASSERT( IsUTF8( fp_name.c_str() ) );
m_gh_cache->insert( fp_name, entry ); m_gh_cache->insert( fp_name, entry );
} }

View File

@ -133,9 +133,9 @@ bool FP_CACHE_ITEM::IsModified() const
} }
typedef boost::ptr_map< std::string, FP_CACHE_ITEM > MODULE_MAP; typedef boost::ptr_map< wxString, FP_CACHE_ITEM > MODULE_MAP;
typedef MODULE_MAP::iterator MODULE_ITER; typedef MODULE_MAP::iterator MODULE_ITER;
typedef MODULE_MAP::const_iterator MODULE_CITER; typedef MODULE_MAP::const_iterator MODULE_CITER;
class FP_CACHE class FP_CACHE
@ -304,12 +304,13 @@ void FP_CACHE::Load()
m_owner->m_parser->SetLineReader( &reader ); m_owner->m_parser->SetLineReader( &reader );
UTF8 name = fullPath.GetName(); MODULE* footprint = (MODULE*) m_owner->m_parser->Parse();
MODULE* footprint = (MODULE*) m_owner->m_parser->Parse();
// The footprint name is the file name without the extension. // The footprint name is the file name without the extension.
footprint->SetFPID( LIB_ID( fullPath.GetName() ) ); wxString fpName = fullPath.GetName();
m_modules.insert( name, new FP_CACHE_ITEM( footprint, fullPath ) );
footprint->SetFPID( LIB_ID( fpName ) );
m_modules.insert( fpName, new FP_CACHE_ITEM( footprint, fullPath ) );
} }
catch( const IO_ERROR& ioe ) catch( const IO_ERROR& ioe )
{ {
@ -333,9 +334,7 @@ void FP_CACHE::Load()
void FP_CACHE::Remove( const wxString& aFootprintName ) void FP_CACHE::Remove( const wxString& aFootprintName )
{ {
std::string footprintName = TO_UTF8( aFootprintName ); MODULE_CITER it = m_modules.find( aFootprintName );
MODULE_CITER it = m_modules.find( footprintName );
if( it == m_modules.end() ) if( it == m_modules.end() )
{ {
@ -349,7 +348,7 @@ void FP_CACHE::Remove( const wxString& aFootprintName )
// Remove the module from the cache and delete the module file from the library. // Remove the module from the cache and delete the module file from the library.
wxString fullPath = it->second->GetFileName().GetFullPath(); wxString fullPath = it->second->GetFileName().GetFullPath();
m_modules.erase( footprintName ); m_modules.erase( aFootprintName );
wxRemoveFile( fullPath ); wxRemoveFile( fullPath );
} }
@ -400,7 +399,7 @@ bool FP_CACHE::IsModified( const wxString& aLibPath, const wxString& aFootprintN
} }
else else
{ {
MODULE_CITER it = m_modules.find( TO_UTF8( aFootprintName ) ); MODULE_CITER it = m_modules.find( aFootprintName );
if( it == m_modules.end() || it->second->IsModified() ) if( it == m_modules.end() || it->second->IsModified() )
return true; return true;
@ -1848,7 +1847,7 @@ void PCB_IO::FootprintEnumerate( wxArrayString& aFootprintNames,
for( MODULE_CITER it = mods.begin(); it != mods.end(); ++it ) for( MODULE_CITER it = mods.begin(); it != mods.end(); ++it )
{ {
aFootprintNames.Add( FROM_UTF8( it->first.c_str() ) ); aFootprintNames.Add( it->first );
} }
if( !errorMsg.IsEmpty() ) if( !errorMsg.IsEmpty() )
@ -1867,7 +1866,7 @@ MODULE* PCB_IO::FootprintLoad( const wxString& aLibraryPath, const wxString& aFo
const MODULE_MAP& mods = m_cache->GetModules(); const MODULE_MAP& mods = m_cache->GetModules();
MODULE_CITER it = mods.find( TO_UTF8( aFootprintName ) ); MODULE_CITER it = mods.find( aFootprintName );
if( it == mods.end() ) if( it == mods.end() )
{ {
@ -1902,7 +1901,7 @@ void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootpri
THROW_IO_ERROR( msg ); THROW_IO_ERROR( msg );
} }
std::string footprintName = aFootprint->GetFPID().GetLibItemName(); wxString footprintName = aFootprint->GetFPID().GetLibItemName();
MODULE_MAP& mods = m_cache->GetModules(); MODULE_MAP& mods = m_cache->GetModules();

View File

@ -442,7 +442,7 @@ void LEGACY_PLUGIN::loadAllSections( bool doAppend )
ReplaceIllegalFileNameChars( &fpName ); ReplaceIllegalFileNameChars( &fpName );
if( !fpName.empty() ) if( !fpName.empty() )
fpid = LIB_ID( fpName ); fpid = LIB_ID( UTF8( fpName ) );
module->SetFPID( fpid ); module->SetFPID( fpid );
@ -3315,7 +3315,7 @@ void LP_CACHE::LoadModules( LINE_READER* aReader )
ReplaceIllegalFileNameChars( &footprintName ); ReplaceIllegalFileNameChars( &footprintName );
// set the footprint name first thing, so exceptions can use name. // set the footprint name first thing, so exceptions can use name.
module->SetFPID( LIB_ID( footprintName ) ); module->SetFPID( LIB_ID( UTF8( footprintName ) ) );
m_owner->loadMODULE( module.get() ); m_owner->loadMODULE( module.get() );
@ -3370,7 +3370,7 @@ void LP_CACHE::LoadModules( LINE_READER* aReader )
{ {
nameOK = true; nameOK = true;
m->SetFPID( LIB_ID( newName ) ); m->SetFPID( LIB_ID( UTF8( newName ) ) );
std::pair<MODULE_ITER, bool> r = m_modules.insert( newName, m ); std::pair<MODULE_ITER, bool> r = m_modules.insert( newName, m );
wxASSERT_MSG( r.second, wxT( "error doing cache insert using guaranteed unique name" ) ); wxASSERT_MSG( r.second, wxT( "error doing cache insert using guaranteed unique name" ) );

View File

@ -345,7 +345,7 @@ MODULE* MWAVE::CreateMicrowaveInductor( INDUCTOR_PATTERN& inductorPattern,
MODULE* module = aPcbFrame->CreateNewModule( msg ); MODULE* module = aPcbFrame->CreateNewModule( msg );
// here the module is already in the BOARD, CreateNewModule() does that. // here the module is already in the BOARD, CreateNewModule() does that.
module->SetFPID( LIB_ID( std::string( "mw_inductor" ) ) ); module->SetFPID( LIB_ID( wxString( "mw_inductor" ) ) );
module->SetAttributes( MOD_VIRTUAL | MOD_CMS ); module->SetAttributes( MOD_VIRTUAL | MOD_CMS );
module->ClearFlags(); module->ClearFlags();
module->SetPosition( inductorPattern.m_End ); module->SetPosition( inductorPattern.m_End );

View File

@ -1,15 +1,37 @@
#include <string>
#include <utf8.h> #include <utf8.h>
#include <wx/string.h> #include <wx/string.h>
void callee( const wxString& aString )
{
UTF8 arg = aString;
printf( "%s: '%s'\n", __func__, arg.c_str() );
}
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
UTF8 bozo = "ü";
UTF8 bozo = "bozo"; callee( bozo );
wxString s = bozo; wxString s = bozo;
wxString b = bozo;
if( s.IsEmpty() )
{
printf( "string is empty\n" );
}
if( s != bozo.wx_str() )
{
printf( "string miscompare\n" );
}
return 0; return 0;
} }