Fairly major reorganization of the FilesystemNode and ZIP file handling

code.  This is just a preliminary check-in; ZIP handling is actually
broken ATM.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2600 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2013-02-10 21:47:47 +00:00
parent ecdcf6177d
commit fb56105a85
15 changed files with 626 additions and 352 deletions

View File

@ -0,0 +1,64 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2013 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef FSNODE_FACTORY_HXX
#define FSNODE_FACTORY_HXX
class AbstractFSNode;
#if defined(UNIX) || defined(MAC_OSX)
#include "FSNodePOSIX.hxx"
#elif defined(WIN32)
#include "FSNodeWin32.hxx"
#else
#error Unsupported platform in FSNodeFactory!
#endif
#include "FSNodeZIP.hxx"
/**
This class deals with creating the different FSNode implementations.
I think you can see why this mess was put into a factory class :)
@author Stephen Anthony
*/
class FilesystemNodeFactory
{
public:
enum Type { SYSTEM, ZIP };
public:
static AbstractFSNode* create(const string& path, Type type)
{
switch(type)
{
case SYSTEM:
#if defined(UNIX) || defined(MAC_OSX)
return new FilesystemNodePOSIX(path);
#elif defined(WIN32)
return new FilesystemNodeWin32(path);
#endif
break;
case ZIP:
return new FilesystemNodeZIP(path);
break;
}
return 0;
}
};
#endif

108
src/common/FSNodeZIP.cxx Normal file
View File

@ -0,0 +1,108 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2013 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#include "bspf.hxx"
#include "FSNodeFactory.hxx"
#include "FSNodeZIP.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNodeZIP::FilesystemNodeZIP()
{
// We need a name, else the node is invalid
_path = _shortPath = _virtualFile = "";
_isValid = _isDirectory = _isFile = _isVirtual = false;
AbstractFSNode* tmp = 0;
_realNode = Common::SharedPtr<AbstractFSNode>(tmp);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNodeZIP::FilesystemNodeZIP(const string& p)
{
// Extract ZIP file and virtual file (if specified)
size_t pos = BSPF_findIgnoreCase(p, ".zip");
if(pos == string::npos)
{
// Not a ZIP file
_path = _shortPath = _virtualFile = "";
_isValid = _isDirectory = _isFile = _isVirtual = false;
cerr << "Not a ZIP file\n";
return;
}
_zipFile = p.substr(0, pos+4);
// A ZIP file is, behind the scenes, still a real file in the filesystem
// Hence, we need to create a real filesystem node for it
AbstractFSNode* tmp = FilesystemNodeFactory::create(_zipFile,
FilesystemNodeFactory::SYSTEM);
_realNode = Common::SharedPtr<AbstractFSNode>(tmp);
_path = _realNode->getPath();
_shortPath = _realNode->getShortPath();
// Is a file component present?
if(pos+5 < p.length())
{
_isVirtual = true;
_virtualFile = p.substr(pos+5);
_path += (BSPF_PATH_SEPARATOR + _virtualFile);
_shortPath += (BSPF_PATH_SEPARATOR + _virtualFile);
}
else
{
_isVirtual = false;
_virtualFile = "";
}
cerr << "FilesystemNodeZIP: " << p << endl
<< "path: " << _path << endl
<< "spath: " << getShortPath() << endl
<< "zipFile: " << _zipFile << endl
<< "virtualFile: " << _virtualFile << endl
<< endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FilesystemNodeZIP::getChildren(AbstractFSList& myList, ListMode mode,
bool hidden) const
{
cerr << "getChildren: " << _path << endl;
// Files within ZIP archives don't contain children
if(_isVirtual)
return false;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FilesystemNodeZIP::isAbsolute() const
{
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFSNode* FilesystemNodeZIP::getParent() const
{
return _realNode ? _realNode->getParent() : 0;
}

80
src/common/FSNodeZIP.hxx Normal file
View File

@ -0,0 +1,80 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2013 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#ifndef FS_NODE_ZIP_HXX
#define FS_NODE_ZIP_HXX
#include "StringList.hxx"
#include "FSNode.hxx"
/*
* Implementation of the Stella file system API based on ZIP archives.
*
* Parts of this class are documented in the base interface class, AbstractFSNode.
*/
class FilesystemNodeZIP : public AbstractFSNode
{
public:
/**
* Creates a FilesystemNodeZIP with the root node as path.
*/
FilesystemNodeZIP();
/**
* Creates a FilesystemNodeZIP for a given path.
*
* @param path String with the path the new node should point to.
* @param verify true if the isValid and isDirectory/isFile flags should
* be verified during the construction.
*/
FilesystemNodeZIP(const string& path);
bool exists() const { return false; }
const string& getName() const { return _virtualFile; }
const string& getPath() const { return _path; }
string getShortPath() const { return _shortPath; }
bool isDirectory() const { return _isDirectory; }
bool isFile() const { return _isFile; }
bool isReadable() const { return false; }
bool isWritable() const { return false; }
bool isAbsolute() const;
//////////////////////////////////////////////////////////
// For now, ZIP files cannot be modified in any way
bool makeDir() { return false; }
bool rename(const string& newfile) { return false; }
//////////////////////////////////////////////////////////
bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const;
AbstractFSNode* getParent() const;
protected:
Common::SharedPtr<AbstractFSNode> _realNode;
string _zipFile, _virtualFile;
string _path, _shortPath;
bool _isDirectory;
bool _isFile;
bool _isValid;
bool _isVirtual;
};
#endif

View File

@ -174,6 +174,12 @@ inline bool BSPF_endsWithIgnoreCase(const string& s1, const string& s2)
false; false;
} }
// Test whether the first string contains the second one (case insensitive)
inline bool BSPF_containsIgnoreCase(const string& s1, const string& s2)
{
return BSPF_findIgnoreCase(s1, s2) != string::npos;
}
static const string EmptyString(""); static const string EmptyString("");
#endif #endif

View File

@ -7,6 +7,7 @@ MODULE_OBJS := \
src/common/FrameBufferGL.o \ src/common/FrameBufferGL.o \
src/common/FBSurfaceGL.o \ src/common/FBSurfaceGL.o \
src/common/FBSurfaceTIA.o \ src/common/FBSurfaceTIA.o \
src/common/FSNodeZIP.o \
src/common/PNGLibrary.o \ src/common/PNGLibrary.o \
src/common/MouseControl.o \ src/common/MouseControl.o \
src/common/RectList.o src/common/RectList.o

View File

@ -22,6 +22,7 @@
#include "bspf.hxx" #include "bspf.hxx"
#include "SharedPtr.hxx" #include "SharedPtr.hxx"
#include "FSNodeFactory.hxx"
#include "FSNode.hxx" #include "FSNode.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -30,7 +31,7 @@ FilesystemNode::FilesystemNode()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode) FilesystemNode::FilesystemNode(AbstractFSNode *realNode)
: _realNode(realNode) : _realNode(realNode)
{ {
} }
@ -38,8 +39,15 @@ FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode::FilesystemNode(const string& p) FilesystemNode::FilesystemNode(const string& p)
{ {
AbstractFilesystemNode* tmp = AbstractFilesystemNode::makeFileNodePath(p); AbstractFSNode* tmp = 0;
_realNode = Common::SharedPtr<AbstractFilesystemNode>(tmp);
// Is this potentially a ZIP archive?
if(BSPF_containsIgnoreCase(p, ".zip"))
tmp = FilesystemNodeFactory::create(p, FilesystemNodeFactory::ZIP);
else
tmp = FilesystemNodeFactory::create(p, FilesystemNodeFactory::SYSTEM);
_realNode = Common::SharedPtr<AbstractFSNode>(tmp);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -85,7 +93,7 @@ FilesystemNode FilesystemNode::getParent() const
if (_realNode == 0) if (_realNode == 0)
return *this; return *this;
AbstractFilesystemNode* node = _realNode->getParent(); AbstractFSNode* node = _realNode->getParent();
if (node == 0) if (node == 0)
return *this; return *this;
else else
@ -95,14 +103,12 @@ FilesystemNode FilesystemNode::getParent() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string& FilesystemNode::getPath() const const string& FilesystemNode::getPath() const
{ {
assert(_realNode);
return _realNode->getPath(); return _realNode->getPath();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string FilesystemNode::getShortPath() const string FilesystemNode::getShortPath() const
{ {
assert(_realNode);
return _realNode->getShortPath(); return _realNode->getShortPath();
} }

View File

@ -51,7 +51,7 @@
#include "SharedPtr.hxx" #include "SharedPtr.hxx"
class FilesystemNode; class FilesystemNode;
class AbstractFilesystemNode; class AbstractFSNode;
/** /**
* List of multiple file system nodes. E.g. the contents of a given directory. * List of multiple file system nodes. E.g. the contents of a given directory.
@ -61,7 +61,7 @@ class AbstractFilesystemNode;
class FSList : public Common::Array<FilesystemNode> { }; class FSList : public Common::Array<FilesystemNode> { };
/** /**
* This class acts as a wrapper around the AbstractFilesystemNode class defined * This class acts as a wrapper around the AbstractFSNode class defined
* in backends/fs. * in backends/fs.
*/ */
class FilesystemNode class FilesystemNode
@ -244,8 +244,8 @@ class FilesystemNode
const string& ext); const string& ext);
private: private:
Common::SharedPtr<AbstractFilesystemNode> _realNode; Common::SharedPtr<AbstractFSNode> _realNode;
FilesystemNode(AbstractFilesystemNode* realNode); FilesystemNode(AbstractFSNode* realNode);
}; };
@ -258,9 +258,9 @@ class FilesystemNode
* the semantics. * the semantics.
*/ */
typedef Common::Array<AbstractFilesystemNode *> AbstractFSList; typedef Common::Array<AbstractFSNode *> AbstractFSList;
class AbstractFilesystemNode class AbstractFSNode
{ {
protected: protected:
friend class FilesystemNode; friend class FilesystemNode;
@ -270,7 +270,7 @@ class AbstractFilesystemNode
/** /**
* Destructor. * Destructor.
*/ */
virtual ~AbstractFilesystemNode() {} virtual ~AbstractFSNode() {}
/* /*
* Indicates whether the object referred by this path exists in the * Indicates whether the object referred by this path exists in the
@ -372,20 +372,11 @@ class AbstractFilesystemNode
*/ */
virtual bool rename(const string& newfile) = 0; virtual bool rename(const string& newfile) = 0;
protected:
/** /**
* The parent node of this directory. * The parent node of this directory.
* The parent of the root is the root itself. * The parent of the root is the root itself.
*/ */
virtual AbstractFilesystemNode* getParent() const = 0; virtual AbstractFSNode* getParent() const = 0;
/**
* Construct a node based on a path; the path is in the same format as it
* would be for calls to fopen().
*
* @param path The path string to create a FilesystemNode for.
*/
static AbstractFilesystemNode* makeFileNodePath(const string& path);
}; };
#endif #endif

View File

@ -1,80 +0,0 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2013 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
////////////////////////////////////////////////////////////////////
// I think you can see why this mess was put into a factory class :)
////////////////////////////////////////////////////////////////////
#include "MediaFactory.hxx"
#include "OSystem.hxx"
#include "Settings.hxx"
#include "FrameBuffer.hxx"
#include "FrameBufferSoft.hxx"
#ifdef DISPLAY_OPENGL
#include "FrameBufferGL.hxx"
#endif
#include "Sound.hxx"
#ifdef SOUND_SUPPORT
#include "SoundSDL.hxx"
#else
#include "SoundNull.hxx"
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer* MediaFactory::createVideo(OSystem* osystem)
{
FrameBuffer* fb = (FrameBuffer*) NULL;
// OpenGL mode *may* fail, so we check for it first
#ifdef DISPLAY_OPENGL
if(osystem->settings().getString("video") == "gl")
{
const string& gl_lib = osystem->settings().getString("gl_lib");
if(FrameBufferGL::loadLibrary(gl_lib))
fb = new FrameBufferGL(osystem);
}
#endif
// If OpenGL failed, or if it wasn't requested, create the appropriate
// software framebuffer
if(!fb)
fb = new FrameBufferSoft(osystem);
// This should never happen
assert(fb != NULL);
return fb;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sound* MediaFactory::createAudio(OSystem* osystem)
{
Sound* sound = (Sound*) NULL;
#ifdef SOUND_SUPPORT
sound = new SoundSDL(osystem);
#else
sound = new SoundNull(osystem);
#endif
return sound;
}

View File

@ -20,23 +20,72 @@
#ifndef MEDIA_FACTORY_HXX #ifndef MEDIA_FACTORY_HXX
#define MEDIA_FACTORY_HXX #define MEDIA_FACTORY_HXX
class FrameBuffer; #include "OSystem.hxx"
class Sound; #include "Settings.hxx"
class OSystem;
#include "FrameBuffer.hxx"
#include "FrameBufferSoft.hxx"
#ifdef DISPLAY_OPENGL
#include "FrameBufferGL.hxx"
#endif
#include "Sound.hxx"
#ifdef SOUND_SUPPORT
#include "SoundSDL.hxx"
#else
#include "SoundNull.hxx"
#endif
/** /**
This class deals with the different framebuffer/sound implementations This class deals with the different framebuffer/sound implementations
for the various ports of Stella, and always returns a valid media object for the various ports of Stella, and always returns a valid media object
based on the specific port and restrictions on that port. based on the specific port and restrictions on that port.
I think you can see why this mess was put into a factory class :)
@author Stephen Anthony @author Stephen Anthony
@version $Id$ @version $Id$
*/ */
class MediaFactory class MediaFactory
{ {
public: public:
static FrameBuffer* createVideo(OSystem* osystem); static FrameBuffer* createVideo(OSystem* osystem)
static Sound* createAudio(OSystem* osystem); {
FrameBuffer* fb = (FrameBuffer*) NULL;
// OpenGL mode *may* fail, so we check for it first
#ifdef DISPLAY_OPENGL
if(osystem->settings().getString("video") == "gl")
{
const string& gl_lib = osystem->settings().getString("gl_lib");
if(FrameBufferGL::loadLibrary(gl_lib))
fb = new FrameBufferGL(osystem);
}
#endif
// If OpenGL failed, or if it wasn't requested, create the appropriate
// software framebuffer
if(!fb)
fb = new FrameBufferSoft(osystem);
// This should never happen
assert(fb != NULL);
return fb;
}
static Sound* createAudio(OSystem* osystem)
{
Sound* sound = (Sound*) NULL;
#ifdef SOUND_SUPPORT
sound = new SoundSDL(osystem);
#else
sound = new SoundNull(osystem);
#endif
return sound;
}
}; };
#endif #endif

View File

@ -67,7 +67,6 @@ MODULE_OBJS := \
src/emucore/TIATables.o \ src/emucore/TIATables.o \
src/emucore/TrackBall.o \ src/emucore/TrackBall.o \
src/emucore/unzip.o \ src/emucore/unzip.o \
src/emucore/MediaFactory.o \
src/emucore/Thumbulator.o src/emucore/Thumbulator.o
MODULE_DIRS += \ MODULE_DIRS += \

View File

@ -373,11 +373,13 @@ void LauncherDialog::loadDirListing()
if(strlen(filename) >= 4 && if(strlen(filename) >= 4 &&
!BSPF_startsWithIgnoreCase(filename, "__MACOSX")) !BSPF_startsWithIgnoreCase(filename, "__MACOSX"))
{ {
#if 0
// Grab 3-character extension // Grab 3-character extension
const char* ext = filename + strlen(filename) - 4; const char* ext = filename + strlen(filename) - 4;
if(BSPF_equalsIgnoreCase(ext, ".a26") || BSPF_equalsIgnoreCase(ext, ".bin") || if(BSPF_equalsIgnoreCase(ext, ".a26") || BSPF_equalsIgnoreCase(ext, ".bin") ||
BSPF_equalsIgnoreCase(ext, ".rom")) BSPF_equalsIgnoreCase(ext, ".rom"))
#endif
{ {
FilesystemNode newFile(FilesystemNode::createAbsolutePath( FilesystemNode newFile(FilesystemNode::createAbsolutePath(
filename, myCurrentNode.getPath(), "")); filename, myCurrentNode.getPath(), ""));

View File

@ -20,79 +20,7 @@
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
//============================================================================ //============================================================================
#include "FSNode.hxx" #include "FSNodePOSIX.hxx"
#ifdef MACOSX
#include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sstream>
#ifndef MAXPATHLEN // No MAXPATHLEN, as happens on Hurd
#define MAXPATHLEN 1024
#endif
/*
* Implementation of the Stella file system API based on POSIX (for Linux and OSX)
*
* Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
class POSIXFilesystemNode : public AbstractFilesystemNode
{
public:
/**
* Creates a POSIXFilesystemNode with the root node as path.
*/
POSIXFilesystemNode();
/**
* Creates a POSIXFilesystemNode for a given path.
*
* @param path String with the path the new node should point to.
* @param verify true if the isValid and isDirectory/isFile flags should
* be verified during the construction.
*/
POSIXFilesystemNode(const string& path, bool verify = true);
bool exists() const { return access(_path.c_str(), F_OK) == 0; }
const string& getName() const { return _displayName; }
const string& getPath() const { return _path; }
string getShortPath() const;
bool isDirectory() const { return _isDirectory; }
bool isFile() const { return _isFile; }
bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
bool isAbsolute() const;
bool makeDir();
bool rename(const string& newfile);
bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const;
AbstractFilesystemNode* getParent() const;
protected:
string _displayName;
string _path;
bool _isDirectory;
bool _isFile;
bool _isValid;
private:
/**
* Tests and sets the _isValid and _isDirectory/_isFile flags,
* using the stat() function.
*/
virtual void setFlags();
};
/** /**
* Returns the last component of a given path. * Returns the last component of a given path.
@ -120,7 +48,7 @@ const char* lastPathComponent(const string& str)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void POSIXFilesystemNode::setFlags() void FilesystemNodePOSIX::setFlags()
{ {
struct stat st; struct stat st;
@ -135,7 +63,7 @@ void POSIXFilesystemNode::setFlags()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
POSIXFilesystemNode::POSIXFilesystemNode() FilesystemNodePOSIX::FilesystemNodePOSIX()
{ {
// The root dir. // The root dir.
_path = "/"; _path = "/";
@ -146,7 +74,7 @@ POSIXFilesystemNode::POSIXFilesystemNode()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
POSIXFilesystemNode::POSIXFilesystemNode(const string& p, bool verify) FilesystemNodePOSIX::FilesystemNodePOSIX(const string& p, bool verify)
{ {
// Default to home directory // Default to home directory
_path = p.length() > 0 ? p : "~"; _path = p.length() > 0 ? p : "~";
@ -177,7 +105,7 @@ POSIXFilesystemNode::POSIXFilesystemNode(const string& p, bool verify)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string POSIXFilesystemNode::getShortPath() const string FilesystemNodePOSIX::getShortPath() const
{ {
// If the path starts with the home directory, replace it with '~' // If the path starts with the home directory, replace it with '~'
const char* home = getenv("HOME"); const char* home = getenv("HOME");
@ -193,7 +121,7 @@ string POSIXFilesystemNode::getShortPath() const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool POSIXFilesystemNode::getChildren(AbstractFSList& myList, ListMode mode, bool FilesystemNodePOSIX::getChildren(AbstractFSList& myList, ListMode mode,
bool hidden) const bool hidden) const
{ {
assert(_isDirectory); assert(_isDirectory);
@ -220,7 +148,7 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList& myList, ListMode mode,
newPath += '/'; newPath += '/';
newPath += dp->d_name; newPath += dp->d_name;
POSIXFilesystemNode entry(newPath, false); FilesystemNodePOSIX entry(newPath, false);
#if defined(SYSTEM_NOT_SUPPORTING_D_TYPE) #if defined(SYSTEM_NOT_SUPPORTING_D_TYPE)
/* TODO: d_type is not part of POSIX, so it might not be supported /* TODO: d_type is not part of POSIX, so it might not be supported
@ -272,7 +200,7 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList& myList, ListMode mode,
if (entry._isDirectory) if (entry._isDirectory)
entry._path += "/"; entry._path += "/";
myList.push_back(new POSIXFilesystemNode(entry)); myList.push_back(new FilesystemNodePOSIX(entry));
} }
closedir(dirp); closedir(dirp);
@ -280,13 +208,13 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList& myList, ListMode mode,
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool POSIXFilesystemNode::isAbsolute() const bool FilesystemNodePOSIX::isAbsolute() const
{ {
return _path.length() > 0 && (_path[0] == '~' || _path[0] == '/'); return _path.length() > 0 && (_path[0] == '~' || _path[0] == '/');
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool POSIXFilesystemNode::makeDir() bool FilesystemNodePOSIX::makeDir()
{ {
if(mkdir(_path.c_str(), 0777) == 0) if(mkdir(_path.c_str(), 0777) == 0)
{ {
@ -309,7 +237,7 @@ bool POSIXFilesystemNode::makeDir()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool POSIXFilesystemNode::rename(const string& newfile) bool FilesystemNodePOSIX::rename(const string& newfile)
{ {
if(std::rename(_path.c_str(), newfile.c_str()) == 0) if(std::rename(_path.c_str(), newfile.c_str()) == 0)
{ {
@ -334,7 +262,7 @@ bool POSIXFilesystemNode::rename(const string& newfile)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode* POSIXFilesystemNode::getParent() const AbstractFSNode* FilesystemNodePOSIX::getParent() const
{ {
if (_path == "/") if (_path == "/")
return 0; return 0;
@ -342,11 +270,5 @@ AbstractFilesystemNode* POSIXFilesystemNode::getParent() const
const char *start = _path.c_str(); const char *start = _path.c_str();
const char *end = lastPathComponent(_path); const char *end = lastPathComponent(_path);
return new POSIXFilesystemNode(string(start, end - start)); return new FilesystemNodePOSIX(string(start, end - start));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode* AbstractFilesystemNode::makeFileNodePath(const string& path)
{
return new POSIXFilesystemNode(path);
} }

100
src/unix/FSNodePOSIX.hxx Normal file
View File

@ -0,0 +1,100 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2013 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#ifndef FS_NODE_POSIX_HXX
#define FS_NODE_POSIX_HXX
#include "FSNode.hxx"
#ifdef MACOSX
#include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sstream>
#ifndef MAXPATHLEN // No MAXPATHLEN, as happens on Hurd
#define MAXPATHLEN 1024
#endif
/*
* Implementation of the Stella file system API based on POSIX (for Linux and OSX)
*
* Parts of this class are documented in the base interface class, AbstractFSNode.
*/
class FilesystemNodePOSIX : public AbstractFSNode
{
public:
/**
* Creates a FilesystemNodePOSIX with the root node as path.
*/
FilesystemNodePOSIX();
/**
* Creates a FilesystemNodePOSIX for a given path.
*
* @param path String with the path the new node should point to.
* @param verify true if the isValid and isDirectory/isFile flags should
* be verified during the construction.
*/
FilesystemNodePOSIX(const string& path, bool verify = true);
bool exists() const { return access(_path.c_str(), F_OK) == 0; }
const string& getName() const { return _displayName; }
const string& getPath() const { return _path; }
string getShortPath() const;
bool isDirectory() const { return _isDirectory; }
bool isFile() const { return _isFile; }
bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
bool isAbsolute() const;
bool makeDir();
bool rename(const string& newfile);
bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const;
AbstractFSNode* getParent() const;
protected:
string _displayName;
string _path;
bool _isDirectory;
bool _isFile;
bool _isValid;
private:
/**
* Tests and sets the _isValid and _isDirectory/_isFile flags,
* using the stat() function.
*/
virtual void setFlags();
};
#endif

View File

@ -20,139 +20,6 @@
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
//============================================================================ //============================================================================
#include <cassert>
#include <shlobj.h>
#ifdef ARRAYSIZE
#undef ARRAYSIZE
#endif
#ifdef _WIN32_WCE
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
#undef GetCurrentDirectory
#endif
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32_WCE
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
#endif
#include <tchar.h>
// F_OK, R_OK and W_OK are not defined under MSVC, so we define them here
// For more information on the modes used by MSVC, check:
// http://msdn2.microsoft.com/en-us/library/1w06ktdy(VS.80).aspx
#ifndef F_OK
#define F_OK 0
#endif
#ifndef R_OK
#define R_OK 4
#endif
#ifndef W_OK
#define W_OK 2
#endif
#include "FSNode.hxx"
#include "HomeFinder.hxx"
static HomeFinder myHomeFinder;
// TODO - fix isFile() functionality so that it actually determines if something
// is a file; for now, it assumes a file if it isn't a directory
/*
* Implementation of the Stella file system API based on Windows API.
*
* Parts of this class are documented in the base interface class,
* AbstractFilesystemNode.
*/
class WindowsFilesystemNode : public AbstractFilesystemNode
{
public:
/**
* Creates a WindowsFilesystemNode with the root node as path.
*
* In regular windows systems, a virtual root path is used "".
* In windows CE, the "\" root is used instead.
*/
WindowsFilesystemNode();
/**
* Creates a WindowsFilesystemNode for a given path.
*
* Examples:
* path=c:\foo\bar.txt, currentDir=false -> c:\foo\bar.txt
* path=c:\foo\bar.txt, currentDir=true -> current directory
* path=NULL, currentDir=true -> current directory
*
* @param path String with the path the new node should point to.
*/
WindowsFilesystemNode(const string& path);
bool exists() const { return _access(_path.c_str(), F_OK) == 0; }
const string& getName() const { return _displayName; }
const string& getPath() const { return _path; }
string getShortPath() const;
bool isDirectory() const { return _isDirectory; }
bool isFile() const { return _isFile; }
bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; }
bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; }
bool isAbsolute() const;
bool makeDir();
bool rename(const string& newfile);
bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const;
AbstractFilesystemNode* getParent() const;
protected:
string _displayName;
string _path;
bool _isDirectory;
bool _isFile;
bool _isPseudoRoot;
bool _isValid;
private:
/**
* Tests and sets the _isValid and _isDirectory/_isFile flags,
* using the GetFileAttributes() function.
*/
virtual void setFlags();
/**
* Adds a single WindowsFilesystemNode to a given list.
* This method is used by getChildren() to populate the directory entries list.
*
* @param list List to put the file entry node in.
* @param mode Mode to use while adding the file entry to the list.
* @param base String with the directory being listed.
* @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find.
*/
static void addFile(AbstractFSList& list, ListMode mode, const char* base, WIN32_FIND_DATA* find_data);
/**
* Converts a Unicode string to Ascii format.
*
* @param str String to convert from Unicode to Ascii.
* @return str in Ascii format.
*/
static char* toAscii(TCHAR *str);
/**
* Converts an Ascii string to Unicode format.
*
* @param str String to convert from Ascii to Unicode.
* @return str in Unicode format.
*/
static const TCHAR* toUnicode(const char* str);
};
/** /**
* Returns the last component of a given path. * Returns the last component of a given path.
* *
@ -179,7 +46,7 @@ const char* lastPathComponent(const string& str)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void WindowsFilesystemNode::setFlags() void FilesystemNodeWin32::setFlags()
{ {
// Get absolute path // Get absolute path
TCHAR buf[4096]; TCHAR buf[4096];
@ -209,10 +76,10 @@ void WindowsFilesystemNode::setFlags()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void WindowsFilesystemNode::addFile(AbstractFSList& list, ListMode mode, void FilesystemNodeWin32::addFile(AbstractFSList& list, ListMode mode,
const char* base, WIN32_FIND_DATA* find_data) const char* base, WIN32_FIND_DATA* find_data)
{ {
WindowsFilesystemNode entry; FilesystemNodeWin32 entry;
char* asciiName = toAscii(find_data->cFileName); char* asciiName = toAscii(find_data->cFileName);
bool isDirectory, isFile; bool isDirectory, isFile;
@ -237,11 +104,11 @@ void WindowsFilesystemNode::addFile(AbstractFSList& list, ListMode mode,
entry._isValid = true; entry._isValid = true;
entry._isPseudoRoot = false; entry._isPseudoRoot = false;
list.push_back(new WindowsFilesystemNode(entry)); list.push_back(new FilesystemNodeWin32(entry));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
char* WindowsFilesystemNode::toAscii(TCHAR* str) char* FilesystemNodeWin32::toAscii(TCHAR* str)
{ {
#ifndef UNICODE #ifndef UNICODE
return (char*)str; return (char*)str;
@ -253,7 +120,7 @@ char* WindowsFilesystemNode::toAscii(TCHAR* str)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const TCHAR* WindowsFilesystemNode::toUnicode(const char* str) const TCHAR* FilesystemNodeWin32::toUnicode(const char* str)
{ {
#ifndef UNICODE #ifndef UNICODE
return (const TCHAR *)str; return (const TCHAR *)str;
@ -265,7 +132,7 @@ const TCHAR* WindowsFilesystemNode::toUnicode(const char* str)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WindowsFilesystemNode::WindowsFilesystemNode() FilesystemNodeWin32::FilesystemNodeWin32()
{ {
// Create a virtual root directory for standard Windows system // Create a virtual root directory for standard Windows system
_isDirectory = true; _isDirectory = true;
@ -276,7 +143,7 @@ WindowsFilesystemNode::WindowsFilesystemNode()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WindowsFilesystemNode::WindowsFilesystemNode(const string& p) FilesystemNodeWin32::FilesystemNodeWin32(const string& p)
{ {
// Default to home directory // Default to home directory
_path = p.length() > 0 ? p : "~"; _path = p.length() > 0 ? p : "~";
@ -289,7 +156,7 @@ WindowsFilesystemNode::WindowsFilesystemNode(const string& p)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string WindowsFilesystemNode::getShortPath() const string FilesystemNodeWin32::getShortPath() const
{ {
// If the path starts with the home directory, replace it with '~' // If the path starts with the home directory, replace it with '~'
const string& home = myHomeFinder.getHomePath(); const string& home = myHomeFinder.getHomePath();
@ -305,7 +172,7 @@ string WindowsFilesystemNode::getShortPath() const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool WindowsFilesystemNode:: bool FilesystemNodeWin32::
getChildren(AbstractFSList& myList, ListMode mode, bool hidden) const getChildren(AbstractFSList& myList, ListMode mode, bool hidden) const
{ {
assert(_isDirectory); assert(_isDirectory);
@ -321,7 +188,7 @@ bool WindowsFilesystemNode::
for (TCHAR *current_drive = drive_buffer; *current_drive; for (TCHAR *current_drive = drive_buffer; *current_drive;
current_drive += _tcslen(current_drive) + 1) current_drive += _tcslen(current_drive) + 1)
{ {
WindowsFilesystemNode entry; FilesystemNodeWin32 entry;
char drive_name[2]; char drive_name[2];
drive_name[0] = toAscii(current_drive)[0]; drive_name[0] = toAscii(current_drive)[0];
@ -332,7 +199,7 @@ bool WindowsFilesystemNode::
entry._isValid = true; entry._isValid = true;
entry._isPseudoRoot = false; entry._isPseudoRoot = false;
entry._path = toAscii(current_drive); entry._path = toAscii(current_drive);
myList.push_back(new WindowsFilesystemNode(entry)); myList.push_back(new FilesystemNodeWin32(entry));
} }
} }
else else
@ -361,13 +228,13 @@ bool WindowsFilesystemNode::
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool WindowsFilesystemNode::isAbsolute() const bool FilesystemNodeWin32::isAbsolute() const
{ {
return _path.length() >= 2 && (_path[0] == '~' || _path[1] == ':'); return _path.length() >= 2 && (_path[0] == '~' || _path[1] == ':');
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool WindowsFilesystemNode::makeDir() bool FilesystemNodeWin32::makeDir()
{ {
if(!_isPseudoRoot && CreateDirectory(_path.c_str(), NULL) != 0) if(!_isPseudoRoot && CreateDirectory(_path.c_str(), NULL) != 0)
{ {
@ -379,7 +246,7 @@ bool WindowsFilesystemNode::makeDir()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool WindowsFilesystemNode::rename(const string& newfile) bool FilesystemNodeWin32::rename(const string& newfile)
{ {
if(!_isPseudoRoot && MoveFile(_path.c_str(), newfile.c_str()) != 0) if(!_isPseudoRoot && MoveFile(_path.c_str(), newfile.c_str()) != 0)
{ {
@ -391,12 +258,12 @@ bool WindowsFilesystemNode::rename(const string& newfile)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode* WindowsFilesystemNode::getParent() const AbstractFSNode* FilesystemNodeWin32::getParent() const
{ {
if (!_isValid || _isPseudoRoot) if (!_isValid || _isPseudoRoot)
return 0; return 0;
WindowsFilesystemNode* p = new WindowsFilesystemNode(); FilesystemNodeWin32* p = new FilesystemNodeWin32();
if (_path.size() > 3) if (_path.size() > 3)
{ {
const char *start = _path.c_str(); const char *start = _path.c_str();
@ -414,7 +281,7 @@ AbstractFilesystemNode* WindowsFilesystemNode::getParent() const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode* AbstractFilesystemNode::makeFileNodePath(const string& path) AbstractFSNode* AbstractFSNode::makeFileNodePath(const string& path)
{ {
return new WindowsFilesystemNode(path); return new FilesystemNodeWin32(path);
} }

159
src/win32/FSNodeWin32.hxx Normal file
View File

@ -0,0 +1,159 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2013 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#ifndef FS_NODE_WIN32_HXX
#define FS_NODE_WIN32_HXX
#include <cassert>
#include <shlobj.h>
#ifdef ARRAYSIZE
#undef ARRAYSIZE
#endif
#ifdef _WIN32_WCE
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
#undef GetCurrentDirectory
#endif
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32_WCE
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
#endif
#include <tchar.h>
// F_OK, R_OK and W_OK are not defined under MSVC, so we define them here
// For more information on the modes used by MSVC, check:
// http://msdn2.microsoft.com/en-us/library/1w06ktdy(VS.80).aspx
#ifndef F_OK
#define F_OK 0
#endif
#ifndef R_OK
#define R_OK 4
#endif
#ifndef W_OK
#define W_OK 2
#endif
#include "FSNode.hxx"
#include "HomeFinder.hxx"
static HomeFinder myHomeFinder;
// TODO - fix isFile() functionality so that it actually determines if something
// is a file; for now, it assumes a file if it isn't a directory
/*
* Implementation of the Stella file system API based on Windows API.
*
* Parts of this class are documented in the base interface class,
* AbstractFSNode.
*/
class FilesystemNodeWin32 : public AbstractFSNode
{
public:
/**
* Creates a FilesystemNodeWin32 with the root node as path.
*
* In regular windows systems, a virtual root path is used "".
* In windows CE, the "\" root is used instead.
*/
FilesystemNodeWin32();
/**
* Creates a FilesystemNodeWin32 for a given path.
*
* Examples:
* path=c:\foo\bar.txt, currentDir=false -> c:\foo\bar.txt
* path=c:\foo\bar.txt, currentDir=true -> current directory
* path=NULL, currentDir=true -> current directory
*
* @param path String with the path the new node should point to.
*/
FilesystemNodeWin32(const string& path);
bool exists() const { return _access(_path.c_str(), F_OK) == 0; }
const string& getName() const { return _displayName; }
const string& getPath() const { return _path; }
string getShortPath() const;
bool isDirectory() const { return _isDirectory; }
bool isFile() const { return _isFile; }
bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; }
bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; }
bool isAbsolute() const;
bool makeDir();
bool rename(const string& newfile);
bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const;
AbstractFSNode* getParent() const;
protected:
string _displayName;
string _path;
bool _isDirectory;
bool _isFile;
bool _isPseudoRoot;
bool _isValid;
private:
/**
* Tests and sets the _isValid and _isDirectory/_isFile flags,
* using the GetFileAttributes() function.
*/
virtual void setFlags();
/**
* Adds a single FilesystemNodeWin32 to a given list.
* This method is used by getChildren() to populate the directory entries list.
*
* @param list List to put the file entry node in.
* @param mode Mode to use while adding the file entry to the list.
* @param base String with the directory being listed.
* @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find.
*/
static void addFile(AbstractFSList& list, ListMode mode, const char* base, WIN32_FIND_DATA* find_data);
/**
* Converts a Unicode string to Ascii format.
*
* @param str String to convert from Unicode to Ascii.
* @return str in Ascii format.
*/
static char* toAscii(TCHAR *str);
/**
* Converts an Ascii string to Unicode format.
*
* @param str String to convert from Ascii to Unicode.
* @return str in Unicode format.
*/
static const TCHAR* toUnicode(const char* str);
};
#endif