diff --git a/3d-viewer/3d_cache/3d_cache.cpp b/3d-viewer/3d_cache/3d_cache.cpp index aecb463dd6..a46a819eaf 100644 --- a/3d-viewer/3d_cache/3d_cache.cpp +++ b/3d-viewer/3d_cache/3d_cache.cpp @@ -51,16 +51,6 @@ #define CACHE_CONFIG_NAME wxT( "cache.cfg" ) -void display(unsigned char* hash) -{ - std::cout << "SHA1: " << std::hex; - for(int i = 0; i < 20; ++i) - { - std::cout << ((hash[i] & 0x000000F0) >> 4) - << (hash[i] & 0x0000000F); - } - std::cout << std::endl; // Das wars -} static const wxString sha1ToWXString( const unsigned char* aSHA1Sum ) { @@ -91,7 +81,6 @@ static const wxString sha1ToWXString( const unsigned char* aSHA1Sum ) } sha1[j] = 0; - std::cerr << "XXX: SHA1: " << sha1 << "\n"; return wxString::FromUTF8Unchecked( sha1 ); } @@ -265,7 +254,7 @@ SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() ) { - // just in case we can't get an MD5 sum (for example, on access issues) + // just in case we can't get an hash digest (for example, on access issues) // or we do not have a configured cache file directory, we create an // entry to prevent further attempts at loading the file S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY; @@ -381,8 +370,6 @@ bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum ) aSHA1Sum[idx] = tmp & 0xff; } - display( aSHA1Sum ); - return true; } @@ -712,3 +699,28 @@ S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName ) return mp; } + + +wxString S3D_CACHE::GetModelHash( const wxString& aModelFileName ) +{ + wxString full3Dpath = m_FNResolver->ResolvePath( aModelFileName ); + + if( full3Dpath.empty() || !wxFileName::FileExists( full3Dpath ) ) + return wxEmptyString; + + // check cache if file is already loaded + std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString >::iterator mi; + mi = m_CacheMap.find( full3Dpath ); + + if( mi != m_CacheMap.end() ) + return mi->second->GetCacheBaseName(); + + // a cache item does not exist; search the Filename->Cachename map + S3D_CACHE_ENTRY* cp = NULL; + checkCache( full3Dpath, &cp ); + + if( NULL != cp ) + return cp->GetCacheBaseName(); + + return wxEmptyString; +} diff --git a/3d-viewer/3d_cache/3d_cache.h b/3d-viewer/3d_cache/3d_cache.h index 9f32e72999..00b21e937e 100644 --- a/3d-viewer/3d_cache/3d_cache.h +++ b/3d-viewer/3d_cache/3d_cache.h @@ -182,15 +182,17 @@ public: */ void ClosePlugins( void ); -/** - * Function GetModel - * attempts to load the scene data for a model and to translate it - * into an S3D_MODEL structure for display by a renderer - * - * @param aModelFileName is the full path to the model to be loaded - * @return is a pointer to the render data or NULL if not available - */ + /** + * Function GetModel + * attempts to load the scene data for a model and to translate it + * into an S3D_MODEL structure for display by a renderer + * + * @param aModelFileName is the full path to the model to be loaded + * @return is a pointer to the render data or NULL if not available + */ S3DMODEL* GetModel( const wxString& aModelFileName ); + + wxString GetModelHash( const wxString& aModelFileName ); }; #endif // CACHE_3D_H diff --git a/3d-viewer/3d_cache/3d_filename_resolver.cpp b/3d-viewer/3d_cache/3d_filename_resolver.cpp index a0a34a9be3..d64a302037 100644 --- a/3d-viewer/3d_cache/3d_filename_resolver.cpp +++ b/3d-viewer/3d_cache/3d_filename_resolver.cpp @@ -25,13 +25,28 @@ #include #include #include +#include #include #include +#include #include "3d_filename_resolver.h" #define S3D_RESOLVER_CONFIG wxT( "3Dresolver.cfg" ) +// flag bits used to track different one-off messages to users +#define ERRFLG_NODIR (1) +#define ERRFLG_RELPATH (2) + + +static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& aResult ); + + +S3D_FILENAME_RESOLVER::S3D_FILENAME_RESOLVER() +{ + m_errflags = 0; +} + bool S3D_FILENAME_RESOLVER::Set3DConfigDir( const wxString& aConfigDir ) { @@ -69,7 +84,13 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh if( m_Paths.empty() ) { - m_Paths.push_back( path ); + S3D_ALIAS al; + al.m_alias = _( "(DEFAULT)" ); + al.m_pathvar = _( "${PROJDIR}" ); + al.m_pathexp = path; + al.m_description = _( "Current project directory" ); + m_Paths.push_back( al ); + m_NameMap.clear(); if( flgChanged ) *flgChanged = true; @@ -77,10 +98,9 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh } else { - if( m_Paths.front().Cmp( path ) ) + if( m_Paths.front().m_pathexp.Cmp( path ) ) { - m_Paths.pop_front(); - m_Paths.push_front( path ); + m_Paths.front().m_pathexp = path; m_NameMap.clear(); if( flgChanged ) @@ -95,7 +115,8 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh #ifdef DEBUG std::cout << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cout << " * [INFO] changed project dir to " << m_Paths.front().ToUTF8() << "\n"; + std::cout << " * [INFO] changed project dir to "; + std::cout << m_Paths.front().m_pathexp.ToUTF8() << "\n"; #endif return true; @@ -107,7 +128,7 @@ wxString S3D_FILENAME_RESOLVER::GetProjectDir( void ) if( m_Paths.empty() ) return wxEmptyString; - return m_Paths.front(); + return m_Paths.front().m_pathexp; } @@ -122,11 +143,27 @@ bool S3D_FILENAME_RESOLVER::createPathList( void ) // default; since CWD is not necessarily what we really want, // the user may change this later with a call to SetProjectDir() - if( !addPath( wxFileName::GetCwd() ) ) - m_Paths.push_back( wxEmptyString ); + S3D_ALIAS lpath; + lpath.m_alias = _( "(DEFAULT)" ); + lpath.m_pathvar = _( "(PROJECT DIR)" ); + lpath.m_pathexp = wxFileName::GetCwd(); + lpath.m_description = _( "Current project directory" ); + m_Paths.push_back( lpath ); - if( wxGetEnv( wxT( "KISYS3DMOD" ), &kmod ) ) - addPath( kmod ); + if( wxGetEnv( wxT( "KISYS3DMOD" ), &kmod ) && !kmod.empty() ) + { + wxFileName tmp( kmod ); + wxString kpath = tmp.GetFullPath(); + + if( tmp.Normalize() && lpath.m_pathexp.Cmp( kpath ) ) + { + lpath.m_alias = wxT( "KISYS3DMOD" ); + lpath.m_pathvar = wxT( "${KISYS3DMOD}" ); + lpath.m_pathexp = kpath; + lpath.m_description = _( "Legacy 3D environment path" ); + addPath( lpath ); + } + } if( !m_ConfigDir.empty() ) readPathList(); @@ -136,12 +173,12 @@ bool S3D_FILENAME_RESOLVER::createPathList( void ) #ifdef DEBUG std::cout << " * [3D model] search paths:\n"; - std::list< wxString >::const_iterator sPL = m_Paths.begin(); - std::list< wxString >::const_iterator ePL = m_Paths.end(); + std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin(); + std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end(); while( sPL != ePL ) { - std::cout << " + '" << (*sPL).ToUTF8() << "'\n"; + std::cout << " + '" << (*sPL).m_pathexp.ToUTF8() << "'\n"; ++sPL; } #endif @@ -150,7 +187,7 @@ bool S3D_FILENAME_RESOLVER::createPathList( void ) } -bool S3D_FILENAME_RESOLVER::UpdatePathList( std::vector< wxString >& aPathList ) +bool S3D_FILENAME_RESOLVER::UpdatePathList( std::vector< S3D_ALIAS >& aPathList ) { while( m_Paths.size() > 1 ) m_Paths.pop_back(); @@ -172,61 +209,125 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName ) if( m_Paths.empty() ) createPathList(); - // first attempt to use the name as specified: - wxString aResolvedName; - wxString fname; + // look up the filename in the internal filename map + std::map< wxString, wxString, S3D::rsort_wxString >::iterator mi; + mi = m_NameMap.find( aFileName ); + + if( mi != m_NameMap.end() ) + return mi->second; + + // first attempt to use the name as specified: + wxString tname = aFileName; + + #ifdef _WIN32 + // translate from KiCad's internal UNIX-like path to MSWin paths + tname.Replace( wxT( "/" ), wxT( "\\" ) ); + #endif + + if( wxFileName::FileExists( tname ) ) + { + wxFileName tmp( tname ); + + if( tmp.Normalize() ) + tname = tmp.GetFullPath(); + + m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) ); + + std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n"; + + return tname; + } + + // at this point aFileName: + // a. is a legacy ${} shortened name + // b. an aliased shortened name + // c. cannot be determined - // normalize paths with "${VARNAME}" to support legacy behavior if( aFileName.StartsWith( wxT( "${" ) ) ) { wxFileName tmp( aFileName ); if( tmp.Normalize() ) - fname = tmp.GetFullPath(); - else - fname = aFileName; + { + tname = tmp.GetFullPath(); + m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) ); + std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n"; + + return tname; + } + + std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n"; + + // XXX - no such path - consider showing the user a pop-up message + return wxEmptyString; } - else + + std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin(); + std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end(); + + // check the path relative to the current dir + do { - fname = aFileName; + wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) ); + wxString fullPath = fpath.GetPathWithSep() + tname; + + if( wxFileName::FileExists( fullPath ) ) + { + wxFileName tmp( fullPath ); + + if( tmp.Normalize() ) + tname = tmp.GetFullPath(); + + m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) ); + + std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n"; + + return tname; + } + } while( 0 ); + + ++sPL; + + wxString alias; // the alias portion of the short filename + wxString relpath; // the path relative to the alias + + if( !SplitAlias( aFileName, alias, relpath ) ) + { + std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n"; + + // XXX - no such path - consider showing the user a pop-up message + return wxEmptyString; } -#ifdef _WIN32 - // translate from KiCad's internal UNIX-like path to MSWin paths - fname.Replace( wxT( "/" ), wxT( "\\" ) ); -#endif - - if( checkRealPath( fname, aResolvedName ) ) - return aResolvedName; - - // look up the filename in the internal filename map - std::map< wxString, wxString, S3D::rsort_wxString >::iterator mi; - mi = m_NameMap.find( fname ); - - if( mi != m_NameMap.end() ) - return mi->second; - - std::list< wxString >::const_iterator sPL = m_Paths.begin(); - std::list< wxString >::const_iterator ePL = m_Paths.end(); - while( sPL != ePL ) { - wxFileName fpath( wxFileName::DirName( *sPL ) ); - wxFileName filename( fname ); - - // we can only attempt a search if the filename is incomplete - if( filename.IsRelative() ) + if( !sPL->m_alias.Cmp( alias ) ) { - wxString fullPath = fpath.GetPathWithSep() + fname; + wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) ); + wxString fullPath = fpath.GetPathWithSep() + relpath; - if( checkRealPath( fullPath, aResolvedName ) ) - return aResolvedName; + if( wxFileName::FileExists( fullPath ) ) + { + wxFileName tmp( fullPath ); + + if( tmp.Normalize() ) + tname = tmp.GetFullPath(); + + m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) ); + + std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n"; + + return tname; + } } ++sPL; } + std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n"; + + // XXX - no such path - consider showing the user a pop-up message wxString errmsg = _( "filename could not be resolved" ); std::cerr << " * [3D Model] " << errmsg.ToUTF8() << " '"; std::cerr << aFileName.ToUTF8() << "'\n"; @@ -235,52 +336,113 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName ) } -bool S3D_FILENAME_RESOLVER::checkRealPath( const wxString& aFileName, - wxString& aResolvedName ) +bool S3D_FILENAME_RESOLVER::addPath( const S3D_ALIAS& aPath ) { - aResolvedName.clear(); - wxFileName fname( aFileName ); - fname.Normalize(); - - if( !fname.FileExists() ) + if( aPath.m_alias.empty() || aPath.m_pathvar.empty() ) return false; - aResolvedName = fname.GetFullPath(); - m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, aResolvedName ) ); - - return true; -} - - -bool S3D_FILENAME_RESOLVER::addPath( const wxString& aPath ) -{ - if( aPath.empty() ) - return false; - - wxFileName path( aPath, wxT( "" ) ); + wxFileName path( aPath.m_pathvar, wxT( "" ) ); path.Normalize(); - if( !path.DirExists() ) - { - wxString errmsg = _( "invalid path" ); - std::cerr << " * [3D Model] " << errmsg.ToUTF8() << " '" << path.GetPath().ToUTF8() << "'\n"; + S3D_ALIAS tpath = aPath; - return false; - } + if( !path.DirExists() ) + tpath.m_pathexp.clear(); + else + tpath.m_pathexp = path.GetFullPath(); wxString pname = path.GetPath(); - std::list< wxString >::const_iterator sPL = m_Paths.begin(); - std::list< wxString >::const_iterator ePL = m_Paths.end(); + std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin(); + std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end(); while( sPL != ePL ) { - if( !pname.Cmp( *sPL ) ) - return true; + if( !sPL->m_pathvar.empty() && !tpath.m_pathvar.empty() + && !tpath.m_pathvar.Cmp( sPL->m_pathvar ) ) + { + wxString msg = _T( "This alias: " ); + msg.append( tpath.m_alias ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "This path: " ) ); + msg.append( tpath.m_pathvar ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "Existing alias: " ) ); + msg.append( sPL->m_alias ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "Existing path: " ) ); + msg.append( sPL->m_pathvar ); + wxMessageBox( msg, _T( "Bad alias (duplicate path)" ) ); + + return false; + } + + if( !sPL->m_pathexp.empty() && !tpath.m_pathexp.empty() ) + { + if( !tpath.m_pathexp.Cmp( sPL->m_pathexp ) ) + { + wxString msg = _T( "This alias: " ); + msg.append( tpath.m_alias ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "Existing alias: " ) ); + msg.append( sPL->m_alias ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "This path: " ) ); + msg.append( tpath.m_pathexp ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "Existing path: " ) ); + msg.append( sPL->m_pathexp ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "This full path: " ) ); + msg.append( tpath.m_pathexp ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "Existing full path: " ) ); + msg.append( sPL->m_pathexp ); + wxMessageBox( msg, _T( "Bad alias (duplicate path)" ) ); + + return false; + } + + if( tpath.m_pathexp.find( sPL->m_pathexp ) != wxString::npos + || sPL->m_pathexp.find( tpath.m_pathexp ) != wxString::npos ) + { + wxString msg = _T( "This alias: " ); + msg.append( tpath.m_alias ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "This path: " ) ); + msg.append( tpath.m_pathexp ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "Existing alias: " ) ); + msg.append( sPL->m_alias ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "Existing path: " ) ); + msg.append( sPL->m_pathexp ); + wxMessageBox( msg, _T( "Bad alias (common path)" ) ); + + return false; + } + } + + if( !tpath.m_alias.Cmp( sPL->m_alias ) ) + { + wxString msg = _T( "Alias: " ); + msg.append( tpath.m_alias ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "This path: " ) ); + msg.append( tpath.m_pathvar ); + msg.append( wxT( "\n" ) ); + msg.append( _T( "Existing path: " ) ); + msg.append( sPL->m_pathvar ); + wxMessageBox( msg, _T( "Bad alias (duplicate name)" ) ); + + return false; + } ++sPL; } - m_Paths.push_back( pname ); + // Note: at this point we may still have duplicated paths + + m_Paths.push_back( tpath ); return true; } @@ -324,7 +486,8 @@ bool S3D_FILENAME_RESOLVER::readPathList( void ) } int lineno = 0; - bool mod = false; // set to true if there are non-existent paths in the file + S3D_ALIAS al; + size_t idx; while( cfgFile.good() ) { @@ -340,42 +503,22 @@ bool S3D_FILENAME_RESOLVER::readPathList( void ) continue; } - std::string::size_type spos = cfgLine.find_first_of( '"', 0 ); + idx = 0; - if( std::string::npos == spos ) - { - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - wxString errmsg = _( "missing opening quote mark in config file" ); - std::cerr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'\n"; - } + if( !getHollerith( cfgLine, idx, al.m_alias ) ) + continue; - cfgLine.erase( 0, spos + 1 ); + if( !getHollerith( cfgLine, idx, al.m_pathvar ) ) + continue; - spos = cfgLine.find_last_of( '"' ); + if( !getHollerith( cfgLine, idx, al.m_description ) ) + continue; - if( std::string::npos == spos ) - { - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - wxString errmsg = _( "missing closing quote mark in config file" ); - std::cerr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'\n"; - } - - cfgLine.erase( spos ); - - if( !addPath( cfgLine ) ) - { - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - wxString errmsg = _( "invalid path in config file" ); - std::cerr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'\n"; - mod = true; - } + addPath( al ); } cfgFile.close(); - if( mod ) - writePathList(); - if( m_Paths.size() != nitems ) return true; @@ -410,16 +553,22 @@ bool S3D_FILENAME_RESOLVER::writePathList( void ) return false; } - std::list< wxString >::const_iterator sPL = m_Paths.begin(); - std::list< wxString >::const_iterator ePL = m_Paths.end(); + std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin(); + std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end(); - // the first entry is the current project dir; we never add a project dir - // to the path list in the configuration file + // the first entry is the current project dir; we never add the implicit + // project dir to the path list in the configuration file ++sPL; + std::string tstr; while( sPL != ePL ) { - cfgFile << "\"" << sPL->ToUTF8() << "\"\n"; + tstr = sPL->m_alias.ToUTF8(); + cfgFile << "\"" << tstr.size() << ":" << tstr << "\","; + tstr = sPL->m_pathvar.ToUTF8(); + cfgFile << "\"" << tstr.size() << ":" << tstr << "\","; + tstr = sPL->m_description.ToUTF8(); + cfgFile << "\"" << tstr.size() << ":" << tstr << "\"\n"; ++sPL; } @@ -440,23 +589,56 @@ wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName ) if( m_Paths.empty() ) createPathList(); - std::list< wxString >::const_iterator sL = m_Paths.begin(); - std::list< wxString >::const_iterator eL = m_Paths.end(); + std::list< S3D_ALIAS >::const_iterator sL = m_Paths.begin(); + std::list< S3D_ALIAS >::const_iterator eL = m_Paths.end(); + size_t idx; + + // test for files within the current project directory + if( !sL->m_pathexp.empty() ) + { + wxFileName fpath( sL->m_pathexp, wxT( "" ) ); + wxString fps = fpath.GetPathWithSep(); + + idx = fname.find( fps ); + + if( std::string::npos != idx && 0 == idx ) + { + fname = fname.substr( fps.size() ); + return fname; + } + } + + ++sL; while( sL != eL ) { - wxFileName fpath( *sL, wxT( "" ) ); - wxString fps = fpath.GetPathWithSep(); + if( sL->m_pathexp.empty() ) + { + ++sL; + continue; + } - if( std::string::npos != fname.find( fps ) ) + wxFileName fpath( sL->m_pathexp, wxT( "" ) ); + wxString fps = fpath.GetPathWithSep(); + wxString tname; + + idx = fname.find( fps ); + + if( std::string::npos != idx && 0 == idx ) { fname = fname.substr( fps.size() ); -#ifdef _WIN32 + #ifdef _WIN32 + // ensure only the '/' separator is used in the internal name fname.Replace( wxT( "\\" ), wxT( "/" ) ); -#endif + #endif - return fname; + tname = ":"; + tname.append( sL->m_alias ); + tname.append( ":" ); + tname.append( fname ); + + return tname; } ++sL; @@ -475,7 +657,114 @@ wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName ) -const std::list< wxString >* S3D_FILENAME_RESOLVER::GetPaths( void ) +const std::list< S3D_ALIAS >* S3D_FILENAME_RESOLVER::GetPaths( void ) { return &m_Paths; } + + +bool S3D_FILENAME_RESOLVER::SplitAlias( const wxString& aFileName, + wxString& anAlias, wxString& aRelPath ) +{ + anAlias.clear(); + aRelPath.clear(); + + if( !aFileName.StartsWith( wxT( ":" ) ) ) + return false; + + size_t tagpos = aFileName.find( wxT( ":" ), 1 ); + + if( wxString::npos == tagpos || 1 == tagpos ) + return false; + + if( tagpos + 1 >= aFileName.length() ) + return false; + + anAlias = aFileName.substr( 1, tagpos - 1 ); + aRelPath = aFileName.substr( tagpos + 1 ); + + return true; +} + + +static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& aResult ) +{ + aResult.clear(); + + if( aIndex < 0 || aIndex >= aString.size() ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + wxString errmsg = _( "bad Hollerith string on line" ); + std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n"; + + return false; + } + + size_t i2 = aString.find( '"', aIndex ); + + if( std::string::npos == i2 ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + wxString errmsg = _( "missing opening quote mark in config file" ); + std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n"; + + return false; + } + + ++i2; + + if( i2 >= aString.size() ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + wxString errmsg = _( "invalid entry (unexpected end of line)" ); + std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n"; + + return false; + } + + std::string tnum; + + while( aString[i2] >= '0' && aString[i2] <= '9' ) + tnum.append( 1, aString[i2++] ); + + if( tnum.empty() || aString[i2++] != ':' ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + wxString errmsg = _( "bad Hollerith string on line" ); + std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n"; + + return false; + } + + std::istringstream istr; + istr.str( tnum ); + size_t nchars; + istr >> nchars; + + if( (i2 + nchars) >= aString.size() ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + wxString errmsg = _( "invalid entry (unexpected end of line)" ); + std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n"; + + return false; + } + + if( nchars > 0 ) + { + aResult = aString.substr( i2, nchars ); + i2 += nchars; + } + + if( aString[i2] != '"' ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + wxString errmsg = _( "missing closing quote mark in config file" ); + std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n"; + + return false; + } + + aIndex = i2 + 1; + return true; +} diff --git a/3d-viewer/3d_cache/3d_filename_resolver.h b/3d-viewer/3d_cache/3d_filename_resolver.h index d88bc7c760..4542c3e517 100644 --- a/3d-viewer/3d_cache/3d_filename_resolver.h +++ b/3d-viewer/3d_cache/3d_filename_resolver.h @@ -39,26 +39,22 @@ #include #include "str_rsort.h" +struct S3D_ALIAS +{ + wxString m_alias; // alias to the base path + wxString m_pathvar; // base path as stored in the config file + wxString m_pathexp; // expanded base path + wxString m_description; // description of the aliased path +}; class S3D_FILENAME_RESOLVER { private: wxString m_ConfigDir; // 3D configuration directory - std::list< wxString > m_Paths; // list of base paths to search from + std::list< S3D_ALIAS > m_Paths; // list of base paths to search from // mapping of (short) file names to resolved names std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap; - - /** - * Function checkRealPath - * checks if a file exists, is a regular file, and retrieves - * the canonical name and extension. - * - * @param aFileName [in] is the file name and path to be checked - * @param aResolvedName [out] is the canonical resolved filename - * @param aFileExtension [out] is the file's extension string - * @return true if the file was found and is a regular file - */ - bool checkRealPath( const wxString& aFileName, wxString& aResolvedName ); + int m_errflags; /** * Function createPathList @@ -75,10 +71,10 @@ private: * Function addPath * checks that a path is valid and adds it to the search list * - * @param aPath is the path to be checked and added + * @param aPath is the alias set to be checked and added * @return true if aPath is valid */ - bool addPath( const wxString& aPath ); + bool addPath( const S3D_ALIAS& aPath ); /** * Function readPathList @@ -99,6 +95,8 @@ private: bool writePathList( void ); public: + S3D_FILENAME_RESOLVER(); + /** * Function Set3DConfigDir * sets the user's configuration directory @@ -127,7 +125,7 @@ public: * clears the current path list and substitutes the given path * list, updating the path configuration file on success. */ - bool UpdatePathList( std::vector< wxString >& aPathList ); + bool UpdatePathList( std::vector< S3D_ALIAS >& aPathList ); /** * Function ResolvePath @@ -159,7 +157,15 @@ public: * * @return pointer to the internal path list */ - const std::list< wxString >* GetPaths( void ); + const std::list< S3D_ALIAS >* GetPaths( void ); + + /** + * Function SplitAlias + * returns true if the given name contains an alias and + * populates the string anAlias with the alias and aRelPath + * with the relative path. + */ + bool SplitAlias( const wxString& aFileName, wxString& anAlias, wxString& aRelPath ); }; #endif // FILENAME_RESOLVER_3D_H diff --git a/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.cpp b/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.cpp index e328c3babe..db57b297e7 100644 --- a/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.cpp +++ b/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.cpp @@ -100,9 +100,9 @@ DLG_CFG_3DPATH::DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResol if( resolver ) { - const std::list< wxString >* pl = resolver->GetPaths(); - std::list< wxString >::const_iterator sL = pl->begin(); - std::list< wxString >::const_iterator eL = pl->end(); + const std::list< S3D_ALIAS >* pl = resolver->GetPaths(); + std::list< S3D_ALIAS >::const_iterator sL = pl->begin(); + std::list< S3D_ALIAS >::const_iterator eL = pl->end(); // always skip the first entry which is the current project dir if( sL != eL ) @@ -113,7 +113,7 @@ DLG_CFG_3DPATH::DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResol while( sL != eL ) { m_paths.push_back( *sL ); - pathList->InsertItem( i, *sL ); + pathList->InsertItem( i, sL->m_alias ); ++i; ++sL; } @@ -130,8 +130,10 @@ DLG_CFG_3DPATH::DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResol bool DLG_CFG_3DPATH::TransferDataFromWindow() { - if( resolver && resolver->UpdatePathList( m_paths ) ) - return true; + // NOTE: This dialog is to be deprecated + + //if( resolver && resolver->UpdatePathList( m_paths ) ) + // return true; return false; } @@ -139,6 +141,9 @@ bool DLG_CFG_3DPATH::TransferDataFromWindow() void DLG_CFG_3DPATH::EditPath( wxCommandEvent& event ) { + // NOTE: This dialog is to be deprecated + + /* long nItem = pathList->GetFirstSelected(); wxString tmpname = m_paths[ nItem ]; @@ -164,6 +169,7 @@ void DLG_CFG_3DPATH::EditPath( wxCommandEvent& event ) } delete dd; + */ return; } @@ -171,6 +177,9 @@ void DLG_CFG_3DPATH::EditPath( wxCommandEvent& event ) void DLG_CFG_3DPATH::AddPath( wxCommandEvent& event ) { + // NOTE: This dialog is to be deprecated + + /* wxDirDialog* dd = new wxDirDialog( this, _( "Add a 3D model directory" ) ); if( wxID_OK == dd->ShowModal() ) @@ -188,6 +197,7 @@ void DLG_CFG_3DPATH::AddPath( wxCommandEvent& event ) } delete dd; + */ return; } @@ -195,6 +205,9 @@ void DLG_CFG_3DPATH::AddPath( wxCommandEvent& event ) void DLG_CFG_3DPATH::DeletePath( wxCommandEvent& event ) { + // NOTE: This dialog is to be deprecated + + /* long nItem = pathList->GetFirstSelected(); if( -1 == nItem ) @@ -216,6 +229,7 @@ void DLG_CFG_3DPATH::DeletePath( wxCommandEvent& event ) deleteButton->Enable( false ); pathList->Select( -1 ); } + */ return; } diff --git a/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.h b/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.h index 218f5ddab1..e47baa4365 100644 --- a/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.h +++ b/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.h @@ -43,7 +43,7 @@ private: wxButton* deleteButton; S3D_FILENAME_RESOLVER* resolver; - std::vector< wxString > m_paths; + std::vector< S3D_ALIAS > m_paths; public: DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver ); diff --git a/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp index 8cdd725e50..7427cc051d 100644 --- a/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp +++ b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp @@ -350,14 +350,14 @@ void PANEL_PREV_3D::updateDirChoiceList( void ) if( NULL == m_FileDlg || NULL == m_ModelManager || NULL == dirChoices ) return; - std::list< wxString > const* md = m_ModelManager->GetResolver()->GetPaths(); - std::list< wxString >::const_iterator sL = md->begin(); - std::list< wxString >::const_iterator eL = md->end(); + std::list< S3D_ALIAS > const* md = m_ModelManager->GetResolver()->GetPaths(); + std::list< S3D_ALIAS >::const_iterator sL = md->begin(); + std::list< S3D_ALIAS >::const_iterator eL = md->end(); std::vector< wxString > cl; while( sL != eL ) { - cl.push_back( *sL ); + cl.push_back( sL->m_pathexp ); ++sL; }