/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2008 Wayne Stambaugh * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.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 */ /** * @file gestfich.cpp * @brief Functions for file management */ #include #include #include #include #include #include #include #include #include #include "wx/tokenzr.h" #include void QuoteString( wxString& string ) { if( !string.StartsWith( wxT( "\"" ) ) ) { string.Prepend ( wxT( "\"" ) ); string.Append ( wxT( "\"" ) ); } } wxString FindKicadFile( const wxString& shortname ) { // Test the presence of the file in the directory shortname of // the KiCad binary path. #ifndef __WXMAC__ wxString fullFileName = Pgm().GetExecutablePath() + shortname; #else wxString fullFileName = Pgm().GetExecutablePath() + wxT( "Contents/MacOS/" ) + shortname; #endif if( wxFileExists( fullFileName ) ) return fullFileName; // Test the presence of the file in the directory shortname // defined by the environment variable KiCad. if( Pgm().IsKicadEnvVariableDefined() ) { fullFileName = Pgm().GetKicadEnvVariable() + shortname; if( wxFileExists( fullFileName ) ) return fullFileName; } #if defined( __WINDOWS__ ) // kicad can be installed highly portably on Windows, anywhere and concurrently // either the "kicad file" is immediately adjacent to the exe or it's not a valid install return shortname; #else // Path list for KiCad binary files const static wxChar* possibilities[] = { #if defined( __WXMAC__ ) // all internal paths are relative to main bundle kicad.app wxT( "Contents/Applications/pcbnew.app/Contents/MacOS/" ), wxT( "Contents/Applications/eeschema.app/Contents/MacOS/" ), wxT( "Contents/Applications/gerbview.app/Contents/MacOS/" ), wxT( "Contents/Applications/bitmap2component.app/Contents/MacOS/" ), wxT( "Contents/Applications/pcb_calculator.app/Contents/MacOS/" ), wxT( "Contents/Applications/pl_editor.app/Contents/MacOS/" ), #else wxT( "/usr/bin/" ), wxT( "/usr/local/bin/" ), wxT( "/usr/local/kicad/bin/" ), #endif }; // find binary file from possibilities list: for( unsigned i=0; i params; #ifdef __UNIX__ wxString param; bool inSingleQuotes = false; bool inDoubleQuotes = false; auto pushParam = [&]() { if( !param.IsEmpty() ) { params.push_back( param ); param.clear(); } }; for( wxUniChar ch : aEditorName ) { if( inSingleQuotes ) { if( ch == '\'' ) { pushParam(); inSingleQuotes = false; continue; } else { param += ch; } } else if( inDoubleQuotes ) { if( ch == '"' ) { pushParam(); inDoubleQuotes = false; } else { param += ch; } } else if( ch == '\'' ) { pushParam(); inSingleQuotes = true; } else if( ch == '"' ) { pushParam(); inDoubleQuotes = true; } else if( ch == ' ' ) { pushParam(); } else { param += ch; } } pushParam(); fullEditorName = FindKicadFile( params[0] ); params.erase( params.begin() ); #else fullEditorName = FindKicadFile( aEditorName ); #endif if( wxFileExists( fullEditorName ) ) { int i = 0; std::vector args; args.emplace_back( fullEditorName.wc_str() ); if( !params.empty() ) { for( const wxString& p : params ) args.emplace_back( p.wc_str() ); } if( !aFileName.IsEmpty() ) args.emplace_back( aFileName.wc_str() ); args.emplace_back( nullptr ); return wxExecute( const_cast( args.data() ), wxEXEC_ASYNC, aCallback ); } wxString msg; msg.Printf( _( "Command '%s' could not be found." ), fullEditorName ); DisplayError( nullptr, msg, 20 ); return -1; } bool OpenPDF( const wxString& file ) { wxString msg; wxString filename = file; Pgm().ReadPdfBrowserInfos(); if( Pgm().UseSystemPdfBrowser() ) { if( !LaunchExternal( filename ) ) { msg.Printf( _( "Unable to find a PDF viewer for '%s'." ), filename ); DisplayError( nullptr, msg ); return false; } } else { const wchar_t* args[3]; args[0] = Pgm().GetPdfBrowserName().wc_str(); args[1] = filename.wc_str(); args[2] = nullptr; if( wxExecute( const_cast( args ) ) == -1 ) { msg.Printf( _( "Problem while running the PDF viewer '%s'." ), args[0] ); DisplayError( nullptr, msg ); return false; } } return true; } void OpenFile( const wxString& file ) { wxFileName fileName( file ); wxFileType* filetype = wxTheMimeTypesManager->GetFileTypeFromExtension( fileName.GetExt() ); if( !filetype ) return; wxString command; wxFileType::MessageParameters params( file ); filetype->GetOpenCommand( &command, params ); delete filetype; if( !command.IsEmpty() ) wxExecute( command ); } void KiCopyFile( const wxString& aSrcPath, const wxString& aDestPath, wxString& aErrors ) { if( !wxCopyFile( aSrcPath, aDestPath ) ) { wxString msg; if( !aErrors.IsEmpty() ) aErrors += "\n"; msg.Printf( _( "Cannot copy file '%s'." ), aDestPath ); aErrors += msg; } } wxString QuoteFullPath( wxFileName& fn, wxPathFormat format ) { return wxT( "\"" ) + fn.GetFullPath( format ) + wxT( "\"" ); } bool RmDirRecursive( const wxString& aFileName, wxString* aErrors ) { namespace fs = std::filesystem; std::string rmDir = aFileName.ToStdString(); if( rmDir.length() < 3 ) { if( aErrors ) *aErrors = _( "Invalid directory name, cannot remove root" ); return false; } if( !fs::exists( rmDir ) ) { if( aErrors ) *aErrors = wxString::Format( _( "Directory '%s' does not exist" ), aFileName ); return false; } fs::path path( rmDir ); if( !fs::is_directory( path ) ) { if( aErrors ) *aErrors = wxString::Format( _( "'%s' is not a directory" ), aFileName ); return false; } try { fs::remove_all( path ); } catch( const fs::filesystem_error& e ) { if( aErrors ) *aErrors = wxString::Format( _( "Error removing directory '%s': %s" ), aFileName, e.what() ); return false; } return true; }