]> git.sesse.net Git - vlc/commitdiff
* skins2/src/theme_loader.cpp: .vlt files can now contain directories
authorOlivier Teulière <ipkiss@videolan.org>
Tue, 6 Apr 2004 19:56:57 +0000 (19:56 +0000)
committerOlivier Teulière <ipkiss@videolan.org>
Tue, 6 Apr 2004 19:56:57 +0000 (19:56 +0000)
   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).

modules/gui/skins2/parser/skin_parser.cpp
modules/gui/skins2/parser/skin_parser.hpp
modules/gui/skins2/src/theme_loader.cpp
modules/gui/skins2/src/theme_loader.hpp

index d9d3661b9ae932e74930821d15716b4b4609416e..c76e365f302e85cee856379013b4110e85a333b1 100644 (file)
 #define SKINS_DTD_VERSION "2.0"
 
 
-SkinParser::SkinParser( intf_thread_t *pIntf, const string &rFileName ):
-    XMLParser( pIntf, rFileName ), m_xOffset( 0 ), m_yOffset( 0 )
+SkinParser::SkinParser( intf_thread_t *pIntf, const string &rFileName,
+                        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 )
 
     else if( rName == "Bitmap" )
     {
-        const BuilderData::Bitmap bitmap( attr["id"] , attr["file"],
+        const BuilderData::Bitmap bitmap( attr["id"] ,
+                ConvertFileName( attr["file"] ),
                 ConvertColor( attr["alphacolor"] ) );
         m_data.m_listBitmap.push_back( bitmap );
     }
 
     else if( rName == "BitmapFont" )
     {
-        const BuilderData::BitmapFont font( attr["id"] , attr["file"],
+        const BuilderData::BitmapFont font( attr["id"],
+                ConvertFileName( attr["file"] ),
                 attr["type"] );
         m_data.m_listBitmapFont.push_back( font );
     }
@@ -84,7 +88,8 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
 
     else if( rName == "Font" )
     {
-        const BuilderData::Font fontData( attr["id"], attr["file"],
+        const BuilderData::Font fontData( attr["id"],
+                ConvertFileName( attr["file"] ),
                 atoi( attr["size"] ) );
         m_data.m_listFont.push_back( fontData );
     }
@@ -259,6 +264,11 @@ int SkinParser::ConvertColor( const char *transcolor ) const
     return ( iRed << 16 | iGreen << 8 | iBlue );
 }
 
+string SkinParser::ConvertFileName( const char *fileName ) const
+{
+    return m_path + string( fileName );
+}
+
 const string SkinParser::generateId() const
 {
     static int i = 1;
index a1f4fc5922197a74d02eebdcd8777d761497aac1..20d93c3eb4978437fa59b4fc177741cccba9db02 100644 (file)
@@ -2,7 +2,7 @@
  * skin_parser.hpp
  *****************************************************************************
  * 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>
  *
@@ -33,7 +33,8 @@
 class SkinParser: public XMLParser
 {
     public:
-        SkinParser( intf_thread_t *pIntf, const string &rFileName );
+        SkinParser( intf_thread_t *pIntf, const string &rFileName,
+                    const string &rPath );
         virtual ~SkinParser() {}
 
         const BuilderData &getData() const { return m_data; }
@@ -52,14 +53,18 @@ class SkinParser: public XMLParser
         int m_curLayer;
         /// Set of used id
         set<string> m_idSet;
+        /// Path of the XML file being parsed
+        const string m_path;
 
         /// 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 );
 
         /// Helper functions
         bool ConvertBoolean( const char *value ) const;
         int ConvertColor( const char *transcolor ) const;
+        string ConvertFileName( const char *fileName ) const;
 
         /// Generate a new id
         const string generateId() const;
index f3acd4b1fad3b37b5d43e2dd5d0899d16b68a4c1..7a4c4ca29ebfe8a41925fea0a37bfa4fbd3cec23 100755 (executable)
 #include "../src/os_factory.hpp"
 #include "../src/window_manager.hpp"
 
-#include <fcntl.h>
+#ifdef HAVE_FCNTL_H
+#   include <fcntl.h>
+#endif
 #if !defined( WIN32 )
 #   include <unistd.h>
 #else
 #   include <direct.h>
 #endif
 
+#if (!defined( WIN32 ) || defined(__MINGW32__))
+/* Mingw has its own version of dirent */
+#   include <dirent.h>
+#endif
+
 
 #if defined( HAVE_ZLIB_H )
 #   include <zlib.h>
@@ -134,9 +141,9 @@ bool ThemeLoader::extract( const string &fileName )
     if( ! extractTarGz( fileName, tempPath ) )
         return false;
 
-    // Parse the extracted XML file
-    const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();
-    if( ! parse( tempPath + sep + string( DEFAULT_XML_FILE ) ) )
+    // Find the XML file and parse it
+    string xmlFile;
+    if( ! findThemeFile( tempPath, xmlFile ) || ! parse( xmlFile ) )
     {
         msg_Err( getIntf(), "%s doesn't contain a " DEFAULT_XML_FILE " file",
                  fileName.c_str() );
@@ -162,28 +169,24 @@ bool ThemeLoader::parse( const string &xmlFile )
     // File loaded
     msg_Dbg( getIntf(), "Using skin file: %s", xmlFile.c_str() );
 
-    // Save current working directory
-    char *cwd = new char[PATH_MAX];
-    getcwd( cwd, PATH_MAX );
-
-    // Change current working directory to xml file
+    // Extract the path of the XML file
+    string path;
     const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();
     unsigned int p = xmlFile.rfind( sep, xmlFile.size() );
     if( p != string::npos )
     {
-        string path = xmlFile.substr( 0, p );
-        chdir( path.c_str() );
+        path = xmlFile.substr( 0, p + 1 );
+    }
+    else
+    {
+        path = "";
     }
 
     // Start the parser
-    SkinParser parser( getIntf(), xmlFile );
-    bool ret = parser.parse();
-    if( !ret )
+    SkinParser parser( getIntf(), xmlFile, path );
+    if( ! parser.parse() )
     {
         msg_Err( getIntf(), "Failed to parse %s", xmlFile.c_str() );
-        // Set old working directory to current
-        chdir( cwd );
-        delete[] cwd;
         return false;
     }
 
@@ -191,16 +194,75 @@ bool ThemeLoader::parse( const string &xmlFile )
     Builder builder( getIntf(), parser.getData() );
     getIntf()->p_sys->p_theme = builder.build();
 
-    // Set old working directory to current.
-    // We need to do that _after_ calling Builder:build(), otherwise the
-    // opening of the files will fail
-    chdir( cwd );
-    delete[] cwd;
-
     return true;
 }
 
 
+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;
+                }
+            }
+        }
+
+        pDirContent = readdir( pCurrDir );
+    }
+
+    return false;
+}
+
+
 #if !defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
 
 #ifdef WIN32
index 73dedf8ee54b65e0361d87ce3f30dd3af1915af6..939cbe65a514c3d3b9243ca34eb19222e1da0d93 100755 (executable)
@@ -2,7 +2,7 @@
  * theme_loader.hpp
  *****************************************************************************
  * 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>
  *          Olivier Teulière <ipkiss@via.ecp.fr>
@@ -39,11 +39,24 @@ class ThemeLoader: public SkinObject
 
     private:
 #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 );
+
+        /// 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 );
 #endif
+
+        /// Parse the XML file given as a parameter and build the skin
         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