Commit ce32ffa3 authored by Olivier Teulière's avatar Olivier Teulière

* skins2/src/theme_loader.cpp: .vlt files can now contain directories

   and subdirectories. When loading a skin, the "theme.xml" file will be
   searched recursively, and the first one to be found is used.

 * skins2/*: Do not 'cd' anymore to the temporary directory where the
   .vlt is extracted (instead, we transform the relative paths specified
   in the XML file into absolute paths).
parent a44edfa9
...@@ -28,8 +28,10 @@ ...@@ -28,8 +28,10 @@
#define SKINS_DTD_VERSION "2.0" #define SKINS_DTD_VERSION "2.0"
SkinParser::SkinParser( intf_thread_t *pIntf, const string &rFileName ): SkinParser::SkinParser( intf_thread_t *pIntf, const string &rFileName,
XMLParser( pIntf, rFileName ), m_xOffset( 0 ), m_yOffset( 0 ) const string &rPath ):
XMLParser( pIntf, rFileName ), m_xOffset( 0 ), m_yOffset( 0 ),
m_path( rPath )
{ {
} }
...@@ -46,14 +48,16 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr ) ...@@ -46,14 +48,16 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
else if( rName == "Bitmap" ) else if( rName == "Bitmap" )
{ {
const BuilderData::Bitmap bitmap( attr["id"] , attr["file"], const BuilderData::Bitmap bitmap( attr["id"] ,
ConvertFileName( attr["file"] ),
ConvertColor( attr["alphacolor"] ) ); ConvertColor( attr["alphacolor"] ) );
m_data.m_listBitmap.push_back( bitmap ); m_data.m_listBitmap.push_back( bitmap );
} }
else if( rName == "BitmapFont" ) else if( rName == "BitmapFont" )
{ {
const BuilderData::BitmapFont font( attr["id"] , attr["file"], const BuilderData::BitmapFont font( attr["id"],
ConvertFileName( attr["file"] ),
attr["type"] ); attr["type"] );
m_data.m_listBitmapFont.push_back( font ); m_data.m_listBitmapFont.push_back( font );
} }
...@@ -84,7 +88,8 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr ) ...@@ -84,7 +88,8 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
else if( rName == "Font" ) else if( rName == "Font" )
{ {
const BuilderData::Font fontData( attr["id"], attr["file"], const BuilderData::Font fontData( attr["id"],
ConvertFileName( attr["file"] ),
atoi( attr["size"] ) ); atoi( attr["size"] ) );
m_data.m_listFont.push_back( fontData ); m_data.m_listFont.push_back( fontData );
} }
...@@ -259,6 +264,11 @@ int SkinParser::ConvertColor( const char *transcolor ) const ...@@ -259,6 +264,11 @@ int SkinParser::ConvertColor( const char *transcolor ) const
return ( iRed << 16 | iGreen << 8 | iBlue ); return ( iRed << 16 | iGreen << 8 | iBlue );
} }
string SkinParser::ConvertFileName( const char *fileName ) const
{
return m_path + string( fileName );
}
const string SkinParser::generateId() const const string SkinParser::generateId() const
{ {
static int i = 1; static int i = 1;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* skin_parser.hpp * skin_parser.hpp
***************************************************************************** *****************************************************************************
* Copyright (C) 2004 VideoLAN * Copyright (C) 2004 VideoLAN
* $Id: skin_parser.hpp,v 1.2 2004/03/01 18:33:31 asmax Exp $ * $Id$
* *
* Authors: Cyril Deguet <asmax@via.ecp.fr> * Authors: Cyril Deguet <asmax@via.ecp.fr>
* *
...@@ -33,7 +33,8 @@ ...@@ -33,7 +33,8 @@
class SkinParser: public XMLParser class SkinParser: public XMLParser
{ {
public: public:
SkinParser( intf_thread_t *pIntf, const string &rFileName ); SkinParser( intf_thread_t *pIntf, const string &rFileName,
const string &rPath );
virtual ~SkinParser() {} virtual ~SkinParser() {}
const BuilderData &getData() const { return m_data; } const BuilderData &getData() const { return m_data; }
...@@ -52,14 +53,18 @@ class SkinParser: public XMLParser ...@@ -52,14 +53,18 @@ class SkinParser: public XMLParser
int m_curLayer; int m_curLayer;
/// Set of used id /// Set of used id
set<string> m_idSet; set<string> m_idSet;
/// Path of the XML file being parsed
const string m_path;
/// Callbacks /// Callbacks
virtual void handleBeginElement( const string &rName, AttrList_t &attr ); virtual void handleBeginElement( const string &rName,
AttrList_t &attr );
virtual void handleEndElement( const string &rName ); virtual void handleEndElement( const string &rName );
/// Helper functions /// Helper functions
bool ConvertBoolean( const char *value ) const; bool ConvertBoolean( const char *value ) const;
int ConvertColor( const char *transcolor ) const; int ConvertColor( const char *transcolor ) const;
string ConvertFileName( const char *fileName ) const;
/// Generate a new id /// Generate a new id
const string generateId() const; const string generateId() const;
......
...@@ -29,13 +29,20 @@ ...@@ -29,13 +29,20 @@
#include "../src/os_factory.hpp" #include "../src/os_factory.hpp"
#include "../src/window_manager.hpp" #include "../src/window_manager.hpp"
#include <fcntl.h> #ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#if !defined( WIN32 ) #if !defined( WIN32 )
# include <unistd.h> # include <unistd.h>
#else #else
# include <direct.h> # include <direct.h>
#endif #endif
#if (!defined( WIN32 ) || defined(__MINGW32__))
/* Mingw has its own version of dirent */
# include <dirent.h>
#endif
#if defined( HAVE_ZLIB_H ) #if defined( HAVE_ZLIB_H )
# include <zlib.h> # include <zlib.h>
...@@ -134,9 +141,9 @@ bool ThemeLoader::extract( const string &fileName ) ...@@ -134,9 +141,9 @@ bool ThemeLoader::extract( const string &fileName )
if( ! extractTarGz( fileName, tempPath ) ) if( ! extractTarGz( fileName, tempPath ) )
return false; return false;
// Parse the extracted XML file // Find the XML file and parse it
const string &sep = OSFactory::instance( getIntf() )->getDirSeparator(); string xmlFile;
if( ! parse( tempPath + sep + string( DEFAULT_XML_FILE ) ) ) if( ! findThemeFile( tempPath, xmlFile ) || ! parse( xmlFile ) )
{ {
msg_Err( getIntf(), "%s doesn't contain a " DEFAULT_XML_FILE " file", msg_Err( getIntf(), "%s doesn't contain a " DEFAULT_XML_FILE " file",
fileName.c_str() ); fileName.c_str() );
...@@ -162,28 +169,24 @@ bool ThemeLoader::parse( const string &xmlFile ) ...@@ -162,28 +169,24 @@ bool ThemeLoader::parse( const string &xmlFile )
// File loaded // File loaded
msg_Dbg( getIntf(), "Using skin file: %s", xmlFile.c_str() ); msg_Dbg( getIntf(), "Using skin file: %s", xmlFile.c_str() );
// Save current working directory // Extract the path of the XML file
char *cwd = new char[PATH_MAX]; string path;
getcwd( cwd, PATH_MAX );
// Change current working directory to xml file
const string &sep = OSFactory::instance( getIntf() )->getDirSeparator(); const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();
unsigned int p = xmlFile.rfind( sep, xmlFile.size() ); unsigned int p = xmlFile.rfind( sep, xmlFile.size() );
if( p != string::npos ) if( p != string::npos )
{ {
string path = xmlFile.substr( 0, p ); path = xmlFile.substr( 0, p + 1 );
chdir( path.c_str() ); }
else
{
path = "";
} }
// Start the parser // Start the parser
SkinParser parser( getIntf(), xmlFile ); SkinParser parser( getIntf(), xmlFile, path );
bool ret = parser.parse(); if( ! parser.parse() )
if( !ret )
{ {
msg_Err( getIntf(), "Failed to parse %s", xmlFile.c_str() ); msg_Err( getIntf(), "Failed to parse %s", xmlFile.c_str() );
// Set old working directory to current
chdir( cwd );
delete[] cwd;
return false; return false;
} }
...@@ -191,13 +194,72 @@ bool ThemeLoader::parse( const string &xmlFile ) ...@@ -191,13 +194,72 @@ bool ThemeLoader::parse( const string &xmlFile )
Builder builder( getIntf(), parser.getData() ); Builder builder( getIntf(), parser.getData() );
getIntf()->p_sys->p_theme = builder.build(); getIntf()->p_sys->p_theme = builder.build();
// Set old working directory to current. return true;
// We need to do that _after_ calling Builder:build(), otherwise the }
// opening of the files will fail
chdir( cwd );
delete[] cwd; bool ThemeLoader::findThemeFile( const string &rootDir, string &themeFilePath )
{
// Path separator
const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();
DIR *pCurrDir;
struct dirent *pDirContent;
// Open the dir
pCurrDir = opendir( rootDir.c_str() );
if( pCurrDir == NULL )
{
// An error occurred
msg_Dbg( getIntf(), "Cannot open directory %s", rootDir.c_str() );
return false;
}
// Get the first directory entry
pDirContent = readdir( pCurrDir );
// While we still have entries in the directory
while( pDirContent != NULL )
{
string newURI = rootDir + sep + pDirContent->d_name;
// Skip . and ..
if( string( pDirContent->d_name ) != "." &&
string( pDirContent->d_name ) != ".." )
{
#if defined( S_ISDIR )
struct stat stat_data;
stat( newURI.c_str(), &stat_data );
if( S_ISDIR(stat_data.st_mode) )
#elif defined( DT_DIR )
if( pDirContent->d_type == DT_DIR )
#else
if( 0 )
#endif
{
// Can we find the theme file in this subdirectory?
if( findThemeFile( newURI, themeFilePath ) )
{
return true;
}
}
else
{
// Found the theme file?
if( string( DEFAULT_XML_FILE ) ==
string( pDirContent->d_name ) )
{
themeFilePath = newURI;
return true; return true;
}
}
}
pDirContent = readdir( pCurrDir );
}
return false;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* theme_loader.hpp * theme_loader.hpp
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: theme_loader.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $ * $Id$
* *
* Authors: Cyril Deguet <asmax@via.ecp.fr> * Authors: Cyril Deguet <asmax@via.ecp.fr>
* Olivier Teulière <ipkiss@via.ecp.fr> * Olivier Teulière <ipkiss@via.ecp.fr>
...@@ -39,11 +39,24 @@ class ThemeLoader: public SkinObject ...@@ -39,11 +39,24 @@ class ThemeLoader: public SkinObject
private: private:
#if defined( HAVE_ZLIB_H ) #if defined( HAVE_ZLIB_H )
bool extractTarGz( const string &tarFile, const string &rootDir ); /// Extract files from an archive (currently only handles tar.gz)
bool extract( const string &fileName ); bool extract( const string &fileName );
/// Extract files from a tar.gz archive
bool extractTarGz( const string &tarFile, const string &rootDir );
/// Clean up the temporary files created by the extraction
void deleteTempFiles( const string &path ); void deleteTempFiles( const string &path );
#endif #endif
/// Parse the XML file given as a parameter and build the skin
bool parse( const string &xmlFile ); bool parse( const string &xmlFile );
/// Recursively look for the XML file from rootDir.
/// The first corresponding file found will be chosen and themeFilePath
/// will be updated accordingly.
/// The method returns true if a theme file was found, false otherwise
bool findThemeFile( const string &rootDir, string &themeFilePath );
}; };
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment