Fix opening files with spaces on Linux

`wxLaunchDefaultApplication()` fails on files with spaces on Unix
systems due to a programmer error. This is fixed in newer wxWidgets
versions, so let's backport it as a workaround.
This commit is contained in:
Mikolaj Wielgus 2021-11-02 23:53:24 +01:00 committed by Jon Evans
parent 8baea9004f
commit 6d9456ea4d
3 changed files with 35 additions and 25 deletions

View File

@ -37,6 +37,7 @@
#include <core/arraydim.h> #include <core/arraydim.h>
#include <gestfich.h> #include <gestfich.h>
#include <string_utils.h> #include <string_utils.h>
#include <launch_ext.h>
void QuoteString( wxString& string ) void QuoteString( wxString& string )
{ {
@ -164,22 +165,7 @@ bool OpenPDF( const wxString& file )
if( Pgm().UseSystemPdfBrowser() ) if( Pgm().UseSystemPdfBrowser() )
{ {
// wxLaunchDefaultApplication on Unix systems is run as an external process passing if( !LaunchExternal( filename ) )
// the filename to the appropriate application as a command argument.
// depending on wxWidgets version, spaces in the path and/or file name will cause
// argument parsing issues so always quote the filename and path.
// This is applicable to all Unix platforms with wxWidgets version < 3.1.0.
// See https://github.com/wxWidgets/wxWidgets/blob/master/src/unix/utilsx11.cpp#L2654
#ifdef __WXGTK__
#if !wxCHECK_VERSION( 3, 1, 0 )
// Quote in case there are spaces in the path.
// Not needed on 3.1.4, but needed in 3.0 versions
// Moreover, on Linux, 3.1.4 wx version, adding quotes breaks wxLaunchDefaultApplication
QuoteString( filename );
#endif
#endif
if( !wxLaunchDefaultApplication( filename ) )
{ {
msg.Printf( _( "Unable to find a PDF viewer for '%s'." ), filename ); msg.Printf( _( "Unable to find a PDF viewer for '%s'." ), filename );
DisplayError( nullptr, msg ); DisplayError( nullptr, msg );

View File

@ -18,18 +18,42 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <gestfich.h>
#include <launch_ext.h> #include <launch_ext.h>
#include <wx/utils.h>
void LaunchExternal( const wxString& aPath ) bool LaunchExternal( const wxString& aPath )
{ {
#ifdef __WXMAC__ #ifdef __WXMAC__
const wchar_t* args[] = { L"open", aPath.wc_str(), nullptr };
wxExecute( const_cast<wchar_t**>( args ) );
#else
wxString path( aPath );
wxLaunchDefaultApplication( path ); const wchar_t* args[] = { L"open", aPath.wc_str(), nullptr };
return wxExecute( const_cast<wchar_t**>( args ) ) != -1;
#elif defined( __WXGTK__ ) && !wxCHECK_VERSION( 3, 1, 1 )
// On Unix systems `wxLaunchDefaultApplication()` before wxWidgets 3.1.1 mistakenly uses
// `wxExecute(xdg_open + " " + document)`, thereby failing for filenames with spaces. Below is
// a backport of the fixed `wxLaunchDefaultApplication()`, to be used until we switch to a
// newer version of wxWidgets.
wxString PATH, xdg_open;
if( wxGetEnv( "PATH", &PATH ) && wxFindFileInPath( &xdg_open, PATH, "xdg-open" ) )
{
const char* argv[3];
argv[0] = xdg_open.fn_str();
argv[1] = aPath.fn_str();
argv[2] = nullptr;
if( wxExecute( const_cast<char**>( argv ) ) )
return true;
}
return false;
#else
wxString path( aPath );
return wxLaunchDefaultApplication( path );
#endif #endif
} }

View File

@ -27,6 +27,6 @@ class wxString;
* Launches the given file or folder in the host OS * Launches the given file or folder in the host OS
* @param aPath is a path to a file or folder * @param aPath is a path to a file or folder
*/ */
void LaunchExternal( const wxString& aPath ); bool LaunchExternal( const wxString& aPath );
#endif #endif