aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2007-09-18 20:02:04 +0000
committerMax Horn2007-09-18 20:02:04 +0000
commitc3d3aebe87d16d4fc3b7ac8581b99fb97241c9ac (patch)
tree17b2ba9f45743d2cf8f8e5faa6c9511e213f15f3
parent5c08cb1bcf84828cc93114fadbc89dd6f9909d06 (diff)
parent1dc13a641dd82825334e81bb3eb3b4ebd69d2552 (diff)
downloadscummvm-rg350-c3d3aebe87d16d4fc3b7ac8581b99fb97241c9ac.tar.gz
scummvm-rg350-c3d3aebe87d16d4fc3b7ac8581b99fb97241c9ac.tar.bz2
scummvm-rg350-c3d3aebe87d16d4fc3b7ac8581b99fb97241c9ac.zip
Patch #1768757: Merge fsnode-gsoc into trunk (MAJOR change, will break compilation on some ports)
svn-id: r28944
-rw-r--r--backends/fs/abstract-fs-factory.h73
-rw-r--r--backends/fs/abstract-fs.h131
-rw-r--r--backends/fs/amigaos4/amigaos4-fs-factory.cpp40
-rw-r--r--backends/fs/amigaos4/amigaos4-fs-factory.h51
-rw-r--r--backends/fs/amigaos4/amigaos4-fs.cpp166
-rw-r--r--backends/fs/dc/dc-fs.cpp104
-rw-r--r--backends/fs/dc/ronincd-fs-factory.cpp40
-rw-r--r--backends/fs/dc/ronincd-fs-factory.h51
-rw-r--r--backends/fs/ds/ds-fs-factory.cpp53
-rw-r--r--backends/fs/ds/ds-fs-factory.h51
-rw-r--r--backends/fs/ds/ds-fs.cpp234
-rw-r--r--backends/fs/ds/ds-fs.h119
-rw-r--r--backends/fs/fs-factory-maker.cpp87
-rw-r--r--backends/fs/gp32/gp32-fs-factory.cpp40
-rw-r--r--backends/fs/gp32/gp32-fs-factory.h51
-rw-r--r--backends/fs/gp32/gp32-fs.cpp128
-rw-r--r--backends/fs/morphos/abox-fs-factory.cpp40
-rw-r--r--backends/fs/morphos/abox-fs-factory.h51
-rw-r--r--backends/fs/morphos/abox-fs.cpp268
-rw-r--r--backends/fs/palmos/palmos-fs-factory.cpp40
-rw-r--r--backends/fs/palmos/palmos-fs-factory.h51
-rw-r--r--backends/fs/palmos/palmos-fs.cpp139
-rw-r--r--backends/fs/posix/posix-fs-factory.cpp42
-rw-r--r--backends/fs/posix/posix-fs-factory.h51
-rw-r--r--backends/fs/posix/posix-fs.cpp147
-rw-r--r--backends/fs/ps2/ps2-fs-factory.cpp40
-rw-r--r--backends/fs/ps2/ps2-fs-factory.h51
-rw-r--r--backends/fs/ps2/ps2-fs.cpp130
-rw-r--r--backends/fs/psp/psp-fs-factory.cpp40
-rw-r--r--backends/fs/psp/psp-fs-factory.h51
-rw-r--r--backends/fs/psp/psp_fs.cpp110
-rw-r--r--backends/fs/symbian/symbian-fs-factory.cpp42
-rw-r--r--backends/fs/symbian/symbian-fs-factory.h51
-rw-r--r--backends/fs/symbian/symbian-fs.cpp120
-rw-r--r--backends/fs/windows/windows-fs-factory.cpp40
-rw-r--r--backends/fs/windows/windows-fs-factory.h51
-rw-r--r--backends/fs/windows/windows-fs.cpp212
-rw-r--r--backends/plugins/dc/dc-provider.cpp6
-rw-r--r--backends/plugins/posix/posix-provider.cpp6
-rw-r--r--backends/plugins/sdl/sdl-provider.cpp6
-rw-r--r--backends/plugins/win32/win32-provider.cpp6
-rw-r--r--backends/saves/default/default-saves.cpp115
-rw-r--r--backends/saves/default/default-saves.h6
-rw-r--r--base/commandLine.cpp48
-rw-r--r--common/advancedDetector.cpp6
-rw-r--r--common/error.h47
-rw-r--r--common/file.cpp63
-rw-r--r--common/file.h5
-rw-r--r--common/fs.cpp210
-rw-r--r--common/fs.h155
-rw-r--r--common/md5.cpp11
-rw-r--r--common/savefile.h52
-rw-r--r--engines/agi/detection.cpp6
-rw-r--r--engines/agi/loader_v3.cpp6
-rw-r--r--engines/agi/sound.cpp10
-rw-r--r--engines/agos/saveload.cpp23
-rw-r--r--engines/kyra/resource.cpp10
-rw-r--r--engines/lure/detection.cpp2
-rw-r--r--engines/queen/queen.cpp27
-rw-r--r--engines/saga/saveload.cpp24
-rw-r--r--engines/scumm/detection.cpp10
-rw-r--r--engines/scumm/dialogs.cpp12
-rw-r--r--engines/scumm/saveload.cpp22
-rw-r--r--engines/sky/sky.cpp6
-rw-r--r--engines/sword1/sword1.cpp6
-rw-r--r--engines/sword2/sword2.cpp8
-rw-r--r--engines/touche/saveload.cpp2
-rw-r--r--engines/touche/ui.cpp26
-rw-r--r--gui/browser.cpp11
-rw-r--r--gui/launcher.cpp16
-rw-r--r--gui/massadd.cpp6
-rw-r--r--gui/options.cpp18
-rw-r--r--gui/themebrowser.cpp9
73 files changed, 3021 insertions, 1167 deletions
diff --git a/backends/fs/abstract-fs-factory.h b/backends/fs/abstract-fs-factory.h
new file mode 100644
index 0000000000..c826ef2745
--- /dev/null
+++ b/backends/fs/abstract-fs-factory.h
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef ABSTRACT_FILESYSTEM_FACTORY_H
+#define ABSTRACT_FILESYSTEM_FACTORY_H
+
+#include "common/str.h"
+#include "backends/fs/abstract-fs.h"
+
+/**
+ * Creates concrete FilesystemNode objects depending on the current architecture.
+ */
+class AbstractFilesystemFactory {
+public:
+ typedef Common::String String;
+
+ /**
+ * Destructor.
+ */
+ virtual ~AbstractFilesystemFactory() {}
+
+ /**
+ * Returns a node representing the "current directory".
+ * If your system does not support this concept, you can either try to
+ * emulate it or simply return some "sensible" default directory node,
+ * e.g. the same value as getRoot() returns.
+ */
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const = 0;
+
+ /**
+ * Construct a node based on a path; the path is in the same format as it
+ * would be for calls to fopen().
+ *
+ * Furthermore getNodeForPath(oldNode.path()) should create a new node
+ * identical to oldNode. Hence, we can use the "path" value for persistent
+ * storage e.g. in the config file.
+ *
+ * @param path The path string to create a FilesystemNode for.
+ */
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const = 0;
+
+ /**
+ * Returns a special node representing the filesystem root.
+ * The starting point for any file system browsing.
+ *
+ * On Unix, this will be simply the node for / (the root directory).
+ * On Windows, it will be a special node which "contains" all drives (C:, D:, E:).
+ */
+ virtual AbstractFilesystemNode *makeRootFileNode() const = 0;
+};
+
+#endif /*ABSTRACT_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/abstract-fs.h b/backends/fs/abstract-fs.h
index 09b08cfe60..aeae0ac1c2 100644
--- a/backends/fs/abstract-fs.h
+++ b/backends/fs/abstract-fs.h
@@ -27,7 +27,6 @@
#include "common/array.h"
#include "common/str.h"
-
#include "common/fs.h"
class AbstractFilesystemNode;
@@ -47,88 +46,106 @@ protected:
friend class FilesystemNode;
typedef Common::String String;
typedef FilesystemNode::ListMode ListMode;
-
- /**
- * The parent node of this directory.
- * The parent of the root is the root itself.
- */
- virtual AbstractFilesystemNode *parent() const = 0;
-
+
/**
- * The child node with the given name. If no child with this name
+ * Returns the child node with the given name. If no child with this name
* exists, returns 0. When called on a non-directory node, it should
* handle this gracefully by returning 0.
*
+ * Example:
+ * Calling getChild() for a node with path "/foo/bar" using name="file.txt",
+ * would produce a new node with "/foo/bar/file.txt" as path.
+ *
+ * @note This function will append a separator char (\ or /) to the end of the
+ * path if needed.
+ *
* @note Handling calls on non-dir nodes gracefully makes it possible to
* switch to a lazy type detection scheme in the future.
+ *
+ * @param name String containing the name of the child to create a new node.
*/
- virtual AbstractFilesystemNode *child(const String &name) const = 0;
-
+ virtual AbstractFilesystemNode *getChild(const String &name) const = 0;
/**
- * Returns a special node representing the FS root. The starting point for
- * any file system browsing.
- * On Unix, this will be simply the node for / (the root directory).
- * On Windows, it will be a special node which "contains" all drives (C:, D:, E:).
+ * The parent node of this directory.
+ * The parent of the root is the root itself.
*/
- static AbstractFilesystemNode *getRoot();
+ virtual AbstractFilesystemNode *getParent() const = 0;
+public:
/**
- * Returns a node representing the "current directory". If your system does
- * not support this concept, you can either try to emulate it or
- * simply return some "sensible" default directory node, e.g. the same
- * value as getRoot() returns.
+ * Destructor.
*/
- static AbstractFilesystemNode *getCurrentDirectory();
-
+ virtual ~AbstractFilesystemNode() {}
+
+ /*
+ * Indicates whether the object referred by this path exists in the filesystem or not.
+ */
+ virtual bool exists() const = 0;
/**
- * Construct a node based on a path; the path is in the same format as it
- * would be for calls to fopen().
- *
- * Furthermore getNodeForPath(oldNode.path()) should create a new node
- * identical to oldNode. Hence, we can use the "path" value for persistent
- * storage e.g. in the config file.
- *
- * @todo: This is of course a place where non-portable code easily will sneak
- * in, because the format of the path used here is not well-defined.
- * So we really should reconsider this API and try to come up with
- * something which is more portable but still flexible enough for our
- * purposes.
+ * Return a list of child nodes of this directory node. If called on a node
+ * that does not represent a directory, false is returned.
+ *
+ * @param list List to put the contents of the directory in.
+ * @param mode Mode to use while listing the directory.
+ * @param hidden Whether to include hidden files or not in the results.
+ *
+ * @return true if succesful, false otherwise (e.g. when the directory does not exist).
*/
- static AbstractFilesystemNode *getNodeForPath(const String &path);
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const = 0;
+ /**
+ * Returns a human readable path string.
+ *
+ * @note By default, this method returns the value of getName().
+ */
+ virtual String getDisplayName() const { return getName(); }
-public:
- virtual ~AbstractFilesystemNode() {}
-
- virtual String name() const = 0;
+ /**
+ * Returns a string with an architecture dependent path description.
+ */
+ virtual String getName() const = 0;
- // By default, we use the actual file name as 'display name'.
- virtual String displayName() const { return name(); }
-
- virtual bool isValid() const = 0;
-
+ /**
+ * Returns the 'path' of the current node, usable in fopen().
+ */
+ virtual String getPath() const = 0;
+
+ /**
+ * Indicates whether this path refers to a directory or not.
+ */
virtual bool isDirectory() const = 0;
/**
- * Return the 'path' of the current node, usable in fopen(). See also
- * the static getNodeForPath() method.
+ * Indicates whether the object referred by this path can be read from or not.
+ *
+ * If the path refers to a directory, readability implies being able to read
+ * and list the directory entries.
+ *
+ * If the path refers to a file, readability implies being able to read the
+ * contents of the file.
+ *
+ * @return bool true if the object can be read, false otherwise.
*/
- virtual String path() const = 0;
- virtual bool listDir(AbstractFSList &list, ListMode mode) const = 0;
-
+ virtual bool isReadable() const = 0;
+
+ /**
+ * Indicates whether the object referred by this path can be written to or not.
+ *
+ * If the path refers to a directory, writability implies being able to modify
+ * the directory entry (i.e. rename the directory, remove it or write files inside of it).
+ *
+ * If the path refers to a file, writability implies being able to write data
+ * to the file.
+ *
+ * @return bool true if the object can be written to, false otherwise.
+ */
+ virtual bool isWritable() const = 0;
/* TODO:
- bool exists();
-
- bool isDirectory();
bool isFile();
-
- bool isReadable();
- bool isWriteable();
*/
};
-
-#endif
+#endif //BACKENDS_ABSTRACT_FS_H
diff --git a/backends/fs/amigaos4/amigaos4-fs-factory.cpp b/backends/fs/amigaos4/amigaos4-fs-factory.cpp
new file mode 100644
index 0000000000..7307deb4bf
--- /dev/null
+++ b/backends/fs/amigaos4/amigaos4-fs-factory.cpp
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/amigaos4/amigaos4-fs-factory.h"
+#include "backends/fs/amigaos4/amigaos4-fs.cpp"
+
+DECLARE_SINGLETON(AmigaOSFilesystemFactory);
+
+AbstractFilesystemNode *AmigaOSFilesystemFactory::makeRootFileNode() const {
+ return new AmigaOSFilesystemNode();
+}
+
+AbstractFilesystemNode *AmigaOSFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new AmigaOSFilesystemNode();
+}
+
+AbstractFilesystemNode *AmigaOSFilesystemFactory::makeFileNodePath(const String &path) const {
+ return new AmigaOSFilesystemNode(path);
+}
diff --git a/backends/fs/amigaos4/amigaos4-fs-factory.h b/backends/fs/amigaos4/amigaos4-fs-factory.h
new file mode 100644
index 0000000000..01a976bdd7
--- /dev/null
+++ b/backends/fs/amigaos4/amigaos4-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef AMIGAOS_FILESYSTEM_FACTORY_H
+#define AMIGAOS_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates AmigaOSFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class AmigaOSFilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<AmigaOSFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ AmigaOSFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*AMIGAOS_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp
index ffed8bc87c..3eefd6507e 100644
--- a/backends/fs/amigaos4/amigaos4-fs.cpp
+++ b/backends/fs/amigaos4/amigaos4-fs.cpp
@@ -38,58 +38,76 @@
#include <common/stdafx.h>
#include "common/util.h"
-
#include "engines/engine.h"
#include "backends/fs/abstract-fs.h"
#define ENTER() /* debug(6, "Enter") */
#define LEAVE() /* debug(6, "Leave") */
-
const uint32 kExAllBufferSize = 40960; // TODO: is this okay for sure?
+/**
+ * Implementation of the ScummVM file system API.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
+ */
class AmigaOSFilesystemNode : public AbstractFilesystemNode {
- protected:
- BPTR _pFileLock;
- String _sDisplayName;
- bool _bIsDirectory;
- bool _bIsValid;
- String _sPath;
-
- public:
- AmigaOSFilesystemNode();
- AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayName = 0);
- AmigaOSFilesystemNode(const String &p);
-
- // Note: Copy constructor is needed because it duplicates the file lock
- AmigaOSFilesystemNode(const AmigaOSFilesystemNode &node);
-
- virtual ~AmigaOSFilesystemNode();
-
- virtual String displayName() const { return _sDisplayName; };
- virtual String name() const { return _sDisplayName; };
- virtual bool isValid() const { return _bIsValid; };
- virtual bool isDirectory() const { return _bIsDirectory; };
- virtual String path() const { return _sPath; };
-
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- virtual AbstractFSList listVolumes() const;
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *child(const String &n) const;
+protected:
+ BPTR _pFileLock;
+ String _sDisplayName;
+ String _sPath;
+ bool _bIsDirectory;
+ bool _bIsValid;
+
+public:
+ /**
+ * Creates a AmigaOSFilesystemNode with the root node as path.
+ */
+ AmigaOSFilesystemNode();
+
+ /**
+ * Creates a AmigaOSFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ */
+ AmigaOSFilesystemNode(const String &p);
+
+ /**
+ * FIXME: document this constructor.
+ */
+ AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayName = 0);
+
+ /**
+ * Copy constructor.
+ *
+ * @note Needed because it duplicates the file lock
+ */
+ AmigaOSFilesystemNode(const AmigaOSFilesystemNode &node);
+
+ /**
+ * Destructor.
+ */
+ virtual ~AmigaOSFilesystemNode();
+
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _sDisplayName; };
+ virtual String getName() const { return _sDisplayName; };
+ virtual String getPath() const { return _sPath; };
+ virtual bool isDirectory() const { return _bIsDirectory; };
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
+ virtual bool isValid() const { return _bIsValid; };
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
+
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
+
+ /**
+ * Creates a list with all the volumes present in the root node.
+ */
+ virtual AbstractFSList listVolumes() const;
};
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- return AbstractFilesystemNode::getRoot();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot() {
- return new AmigaOSFilesystemNode();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new AmigaOSFilesystemNode(path);
-}
-
AmigaOSFilesystemNode::AmigaOSFilesystemNode() {
ENTER();
_sDisplayName = "Available Disks";
@@ -100,7 +118,6 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode() {
LEAVE();
}
-
AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) {
ENTER();
@@ -150,7 +167,6 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) {
const char c = _sPath.lastChar();
if (c != '/' && c != ':')
_sPath += '/';
-
}
else {
//_bIsDirectory = false;
@@ -170,7 +186,7 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayNam
int bufSize = MAXPATHLEN;
_pFileLock = 0;
- while (1) {
+ while (true) {
char *n = new char[bufSize];
if (IDOS->NameFromLock(pLock, (STRPTR)n, bufSize) != DOSFALSE) {
_sPath = n;
@@ -186,6 +202,7 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayNam
delete [] n;
return;
}
+
bufSize *= 2;
delete [] n;
}
@@ -238,9 +255,35 @@ AmigaOSFilesystemNode::~AmigaOSFilesystemNode() {
LEAVE();
}
-bool AmigaOSFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
+AbstractFilesystemNode *AmigaOSFilesystemNode::getChild(const String &n) const {
+ if (!_bIsDirectory) {
+ debug(6, "Not a directory");
+ return 0;
+ }
+
+ String newPath(_sPath);
+
+ if (_sPath.lastChar() != '/')
+ newPath += '/';
+
+ newPath += n;
+ BPTR lock = IDOS->Lock(newPath.c_str(), SHARED_LOCK);
+
+ if (!lock) {
+ debug(6, "Bad path");
+ return 0;
+ }
+
+ IDOS->UnLock(lock);
+
+ return new AmigaOSFilesystemNode(newPath);
+}
+
+bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
ENTER();
+ //TODO: honor the hidden flag
+
if (!_bIsValid) {
debug(6, "Invalid node");
LEAVE();
@@ -308,10 +351,11 @@ bool AmigaOSFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
}
LEAVE();
+
return true;
}
-AbstractFilesystemNode *AmigaOSFilesystemNode::parent() const {
+AbstractFilesystemNode *AmigaOSFilesystemNode::getParent() const {
ENTER();
if (!_bIsDirectory) {
@@ -337,33 +381,8 @@ AbstractFilesystemNode *AmigaOSFilesystemNode::parent() const {
node = new AmigaOSFilesystemNode();
LEAVE();
- return node;
-}
-
-AbstractFilesystemNode *AmigaOSFilesystemNode::child(const String &n) const {
- if (!_bIsDirectory) {
- debug(6, "Not a directory");
- return 0;
- }
-
- String newPath(_sPath);
-
- if (_sPath.lastChar() != '/')
- newPath += '/';
-
- newPath += n;
-
- BPTR lock = IDOS->Lock(newPath.c_str(), SHARED_LOCK);
-
- if (!lock) {
- debug(6, "Bad path");
- return 0;
- }
-
- IDOS->UnLock(lock);
-
- return new AmigaOSFilesystemNode(newPath);
+ return node;
}
AbstractFSList AmigaOSFilesystemNode::listVolumes() const {
@@ -431,7 +450,8 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const {
IDOS->UnLockDosList(kLockFlags);
LEAVE();
+
return myList;
}
-#endif
+#endif //defined(__amigaos4__)
diff --git a/backends/fs/dc/dc-fs.cpp b/backends/fs/dc/dc-fs.cpp
index 010ca20276..6554544c7f 100644
--- a/backends/fs/dc/dc-fs.cpp
+++ b/backends/fs/dc/dc-fs.cpp
@@ -25,40 +25,62 @@
#if defined(__DC__)
#include "common/stdafx.h"
-
#include "backends/fs/abstract-fs.h"
#include <ronin/cdfs.h>
#include <stdio.h>
#include <unistd.h>
-/*
- * Implementation of the ScummVM file system API based on ronin.
+/**
+ * Implementation of the ScummVM file system API based on Ronin.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
-
class RoninCDFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
+ String _path;
bool _isDirectory;
bool _isValid;
- String _path;
public:
+ /**
+ * Creates a RoninCDFilesystemNode with the root node as path.
+ */
RoninCDFilesystemNode();
+
+ /**
+ * Creates a RoninCDFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ * @param verify true if the isValid and isDirectory flags should be verified during the construction.
+ */
RoninCDFilesystemNode(const String &path, bool verify);
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
- virtual bool isValid() const { return _isValid; }
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
+ virtual bool isValid() const { return _isValid; }
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *child(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
};
-
+/**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * /foo/bar.txt would return /bar.txt
+ * /foo/bar/ would return /bar/
+ *
+ * @param str String containing the path.
+ * @return Pointer to the first char of the last component inside str.
+ */
static const char *lastPathComponent(const Common::String &str) {
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
@@ -70,22 +92,6 @@ static const char *lastPathComponent(const Common::String &str) {
return cur + 1;
}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- // Since there is no way to _set_ the current directory,
- // it will always be /...
-
- return getRoot();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot() {
- return new RoninCDFilesystemNode();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new RoninCDFilesystemNode(path, true);
-}
-
RoninCDFilesystemNode::RoninCDFilesystemNode() {
// The root dir.
_path = "/";
@@ -118,10 +124,25 @@ RoninCDFilesystemNode::RoninCDFilesystemNode(const String &p, bool verify) {
}
}
-bool RoninCDFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
+AbstractFilesystemNode *RoninCDFilesystemNode::getChild(const String &n) const {
+ // FIXME: Pretty lame implementation! We do no error checking to speak
+ // of, do not check if this is a special node, etc.
assert(_isDirectory);
- DIR *dirp = opendir(_path.c_str());
+
+ String newPath(_path);
+ if (_path.lastChar() != '/')
+ newPath += '/';
+ newPath += n;
+
+ return new RoninCDFilesystemNode(newPath, true);
+}
+bool RoninCDFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
+ assert(_isDirectory);
+
+ //TODO: honor the hidden flag
+
+ DIR *dirp = opendir(_path.c_str());
struct dirent *dp;
if (dirp == NULL)
@@ -150,35 +171,22 @@ bool RoninCDFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
if (entry._isDirectory)
entry._path += "/";
+
myList.push_back(new RoninCDFilesystemNode(entry));
}
closedir(dirp);
+
return true;
}
-AbstractFilesystemNode *RoninCDFilesystemNode::parent() const {
+AbstractFilesystemNode *RoninCDFilesystemNode::getParent() const {
if (_path == "/")
return 0;
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
- RoninCDFilesystemNode *p = new RoninCDFilesystemNode(String(start, end - start), false);
-
- return p;
-}
-
-AbstractFilesystemNode *RoninCDFilesystemNode::child(const String &n) const {
- // FIXME: Pretty lame implementation! We do no error checking to speak
- // of, do not check if this is a special node, etc.
- assert(_isDirectory);
- String newPath(_path);
- if (_path.lastChar() != '/')
- newPath += '/';
- newPath += n;
- RoninCDFilesystemNode *p = new RoninCDFilesystemNode(newPath, true);
-
- return p;
+ return new RoninCDFilesystemNode(String(start, end - start), false);
}
#endif // defined(__DC__)
diff --git a/backends/fs/dc/ronincd-fs-factory.cpp b/backends/fs/dc/ronincd-fs-factory.cpp
new file mode 100644
index 0000000000..f72906c2aa
--- /dev/null
+++ b/backends/fs/dc/ronincd-fs-factory.cpp
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/dc/ronincd-fs-factory.h"
+#include "backends/fs/dc/dc-fs.cpp"
+
+DECLARE_SINGLETON(RoninCDFilesystemFactory);
+
+AbstractFilesystemNode *RoninCDFilesystemFactory::makeRootFileNode() const {
+ return new RoninCDFilesystemNode();
+}
+
+AbstractFilesystemNode *RoninCDFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new RoninCDFilesystemNode();
+}
+
+AbstractFilesystemNode *RoninCDFilesystemFactory::makeFileNodePath(const String &path) const {
+ return new RoninCDFilesystemNode(path, true);
+}
diff --git a/backends/fs/dc/ronincd-fs-factory.h b/backends/fs/dc/ronincd-fs-factory.h
new file mode 100644
index 0000000000..d827cc51e3
--- /dev/null
+++ b/backends/fs/dc/ronincd-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef RONINCD_FILESYSTEM_FACTORY_H
+#define RONINCD_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates RoninCDFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class RoninCDFilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<RoninCDFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ RoninCDFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*RONINCD_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/ds/ds-fs-factory.cpp b/backends/fs/ds/ds-fs-factory.cpp
new file mode 100644
index 0000000000..0de284d1eb
--- /dev/null
+++ b/backends/fs/ds/ds-fs-factory.cpp
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/ds/ds-fs-factory.h"
+#include "backends/fs/ds/ds-fs.cpp"
+#include "dsmain.h" //for the isGBAMPAvailable() function
+
+DECLARE_SINGLETON(DSFilesystemFactory);
+
+AbstractFilesystemNode *DSFilesystemFactory::makeRootFileNode() const {
+ if (DS::isGBAMPAvailable()) {
+ return new DS::GBAMPFileSystemNode();
+ } else {
+ return new DS::DSFileSystemNode();
+ }
+}
+
+AbstractFilesystemNode *DSFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ if (DS::isGBAMPAvailable()) {
+ return new DS::GBAMPFileSystemNode();
+ } else {
+ return new DS::DSFileSystemNode();
+ }
+}
+
+AbstractFilesystemNode *DSFilesystemFactory::makeFileNodePath(const String &path) const {
+ if (DS::isGBAMPAvailable()) {
+ return new DS::GBAMPFileSystemNode(path);
+ } else {
+ return new DS::DSFileSystemNode(path);
+ }
+}
diff --git a/backends/fs/ds/ds-fs-factory.h b/backends/fs/ds/ds-fs-factory.h
new file mode 100644
index 0000000000..a6a7bf6532
--- /dev/null
+++ b/backends/fs/ds/ds-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef DS_FILESYSTEM_FACTORY_H
+#define DS_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates DSFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class DSFilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<DSFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ DSFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*DS_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/ds/ds-fs.cpp b/backends/fs/ds/ds-fs.cpp
index abfd0397c6..11d373ea1e 100644
--- a/backends/fs/ds/ds-fs.cpp
+++ b/backends/fs/ds/ds-fs.cpp
@@ -20,24 +20,18 @@
*
*/
-
#include "stdafx.h"
#include "str.h"
-#include "fs.h"
#include "common/util.h"
//#include <NDS/ARM9/console.h> //basic print funcionality
#include "ds-fs.h"
#include "dsmain.h"
#include "gba_nds_fat.h"
-
namespace DS {
-
-
-
//////////////////////////////////////////////////////////////
-// DSFileSystemNode - Flash ROM file system using Zip files
+// DSFileSystemNode - Flash ROM file system using Zip files //
//////////////////////////////////////////////////////////////
ZipFile* DSFileSystemNode::_zipFile = NULL;
@@ -66,7 +60,6 @@ DSFileSystemNode::DSFileSystemNode(const String& path) {
char disp[128];
char* pathStr = (char *) path.c_str();
-
int lastSlash = 3;
for (int r = 0; r < (int) strlen(pathStr) - 1; r++) {
if (path[r] == '\\') {
@@ -81,13 +74,10 @@ DSFileSystemNode::DSFileSystemNode(const String& path) {
// _isValid = true;
// _isDirectory = false;
-
-
if (!strncmp(pathStr, "ds:/", 4)) {
pathStr += 4;
}
-
if (*pathStr == '\0') {
_isValid = true;
_isDirectory = true;
@@ -130,35 +120,10 @@ DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) {
}
DSFileSystemNode::DSFileSystemNode(const DSFileSystemNode* node) {
-
+ //TODO: not implemented?
}
-AbstractFilesystemNode* DSFileSystemNode::parent() const {
-// consolePrintf("parent\n");
- DSFileSystemNode *p;
-
- if (_path != "ds:/") {
- char *path = (char *) _path.c_str();
- int lastSlash = 4;
-
- for (int r = 4; r < (int) strlen((char *) path); r++) {
- if (path[r] == '\\') {
- lastSlash = r;
- }
- }
-
- p = new DSFileSystemNode(String(path, lastSlash));
- ((DSFileSystemNode *) (p))->_isDirectory = true;
- } else {
- p = new DSFileSystemNode();
- }
-
- return p;
-
-}
-
-
-AbstractFilesystemNode *DSFileSystemNode::child(const Common::String& n) const {
+AbstractFilesystemNode *DSFileSystemNode::getChild(const Common::String& n) const {
if (_path.lastChar() == '\\') {
return new DSFileSystemNode(_path + n);
} else {
@@ -168,14 +133,12 @@ AbstractFilesystemNode *DSFileSystemNode::child(const Common::String& n) const {
return NULL;
}
-
-bool DSFileSystemNode::listDir(AbstractFSList &dirList, ListMode mode) const {
+bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool hidden) const {
// consolePrintf("Listdir\n");
-
-
// consolePrintf("Directory\n");
-
+ //TODO: honor the hidden flag
+
char temp[128];
strcpy(temp, _path.c_str());
@@ -190,14 +153,13 @@ bool DSFileSystemNode::listDir(AbstractFSList &dirList, ListMode mode) const {
/* // This is the root dir, so add the RAM folder
DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/ram");
dsfsn->_isDirectory = true;
- dirList->push_back(wrap(dsfsn));*/
+ dirList->push_back(wrap(dsfsn));
+*/
}
} else {
_zipFile->changeDirectory(temp);
}
-
-
if (_zipFile->restartFile()) {
do {
char n[128];
@@ -218,12 +180,32 @@ bool DSFileSystemNode::listDir(AbstractFSList &dirList, ListMode mode) const {
return true;
}
+AbstractFilesystemNode* DSFileSystemNode::getParent() const {
+// consolePrintf("parent\n");
+ DSFileSystemNode *p;
+
+ if (_path != "ds:/") {
+ char *path = (char *) _path.c_str();
+ int lastSlash = 4;
+
+ for (int r = 4; r < (int) strlen((char *) path); r++) {
+ if (path[r] == '\\') {
+ lastSlash = r;
+ }
+ }
+ p = new DSFileSystemNode(String(path, lastSlash));
+ ((DSFileSystemNode *) (p))->_isDirectory = true;
+ } else {
+ p = new DSFileSystemNode();
+ }
+ return p;
+}
-/////////////////////////////////////////////////////////////////////////
-// GBAMPFileSystemNode - File system using GBA Movie Player and CF card
-/////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// GBAMPFileSystemNode - File system using GBA Movie Player and CF card //
+//////////////////////////////////////////////////////////////////////////
GBAMPFileSystemNode::GBAMPFileSystemNode() {
_displayName = "mp:/";
@@ -290,35 +272,10 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) {
GBAMPFileSystemNode::GBAMPFileSystemNode(const GBAMPFileSystemNode* node) {
-
+ //TODO: not implemented?
}
-
-AbstractFilesystemNode* GBAMPFileSystemNode::parent() const {
-// consolePrintf("parent\n");
- GBAMPFileSystemNode *p;
-
- if (_path != "mp:/") {
- char *path = (char *) _path.c_str();
- int lastSlash = 4;
-
- for (int r = 4; r < (int) strlen((char *) path); r++) {
- if (path[r] == '/') {
- lastSlash = r;
- }
- }
-
- p = new GBAMPFileSystemNode(String(path, lastSlash));
- p->_isDirectory = true;
- } else {
- p = new GBAMPFileSystemNode();
- }
-
- return p;
-
-}
-
-AbstractFilesystemNode *GBAMPFileSystemNode::child(const Common::String& n) const {
+AbstractFilesystemNode *GBAMPFileSystemNode::getChild(const Common::String& n) const {
if (_path.lastChar() == '\\') {
return new DSFileSystemNode(_path + n);
} else {
@@ -328,9 +285,11 @@ AbstractFilesystemNode *GBAMPFileSystemNode::child(const Common::String& n) cons
return NULL;
}
-bool GBAMPFileSystemNode::listDir(AbstractFSList& dirList, ListMode mode) const {
+bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bool hidden) const {
// consolePrintf("Listdir\n");
+ //TODO: honor the hidden flag
+
enum { TYPE_NO_MORE = 0, TYPE_FILE = 1, TYPE_DIR = 2 };
char temp[128], fname[128], *path, *pathTemp;
@@ -346,7 +305,6 @@ bool GBAMPFileSystemNode::listDir(AbstractFSList& dirList, ListMode mode) const
pathTemp++;
}
-
// consolePrintf("This dir: %s\n", path);
FAT_chdir(path);
@@ -369,8 +327,6 @@ bool GBAMPFileSystemNode::listDir(AbstractFSList& dirList, ListMode mode) const
// dsfsn->_isDirectory = entryType == DIR;
dirList.push_back((dsfsn));
}
-
-
} else {
// consolePrintf("Skipping %s\n", fname);
}
@@ -385,6 +341,28 @@ bool GBAMPFileSystemNode::listDir(AbstractFSList& dirList, ListMode mode) const
return true;
}
+AbstractFilesystemNode* GBAMPFileSystemNode::getParent() const {
+// consolePrintf("parent\n");
+ GBAMPFileSystemNode *p;
+
+ if (_path != "mp:/") {
+ char *path = (char *) _path.c_str();
+ int lastSlash = 4;
+
+ for (int r = 4; r < (int) strlen((char *) path); r++) {
+ if (path[r] == '/') {
+ lastSlash = r;
+ }
+ }
+
+ p = new GBAMPFileSystemNode(String(path, lastSlash));
+ p->_isDirectory = true;
+ } else {
+ p = new GBAMPFileSystemNode();
+ }
+
+ return p;
+}
// Stdio replacements
#define MAX_FILE_HANDLES 32
@@ -393,9 +371,6 @@ bool inited = false;
DS::fileHandle handle[MAX_FILE_HANDLES];
FILE* std_fopen(const char* name, const char* mode) {
-
-
-
if (!inited) {
for (int r = 0; r < MAX_FILE_HANDLES; r++) {
handle[r].used = false;
@@ -403,9 +378,6 @@ FILE* std_fopen(const char* name, const char* mode) {
inited = true;
currentDir[0] = '\0';
}
-
-
-
char* realName = (char *) name;
@@ -413,7 +385,7 @@ FILE* std_fopen(const char* name, const char* mode) {
if ((name[0] == 'd') && (name[1] == 's') && (name[2] == ':') && (name[3] == '/')) {
realName += 4;
}
-
+
if ((name[0] == 'm') && (name[1] == 'p') && (name[2] == ':') && (name[3] == '/')) {
realName += 4;
}
@@ -421,7 +393,6 @@ FILE* std_fopen(const char* name, const char* mode) {
// consolePrintf("Open file:");
// consolePrintf("'%s', [%s]", realName, mode);
-
if (DS::isGBAMPAvailable()) {
FAT_chdir("/");
@@ -443,10 +414,9 @@ FILE* std_fopen(const char* name, const char* mode) {
return (FILE *) result;
}
-
// Fail to open file for writing. It's in ROM!
-
+
// Allocate a file handle
int r = 0;
while (handle[r].used) r++;
@@ -459,7 +429,6 @@ FILE* std_fopen(const char* name, const char* mode) {
handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false);
}
-
if (handle[r].sramFile) {
handle[r].used = true;
handle[r].pos = 0;
@@ -513,6 +482,7 @@ FILE* std_fopen(const char* name, const char* mode) {
return NULL;
}
}
+
void std_fclose(FILE* handle) {
if (DS::isGBAMPAvailable()) {
@@ -528,14 +498,9 @@ void std_fclose(FILE* handle) {
}
size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
-
// consolePrintf("fread %d,%d %d ", size, numItems, ptr);
-
-
if (DS::isGBAMPAvailable()) {
-
-
int bytes = FAT_fread((void *) ptr, size, numItems, (FAT_FILE *) handle);
if (!std_feof(handle)) {
return numItems;
@@ -560,27 +525,24 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
}
- return item;*/
-
-
+ return item;
+*/
int items = 0;
//for (int r = 0; r < numItems; r++) {
if (!std_feof(handle)) {
-
-
-
/* for (int t = 0; t < size; t++) {
if (feof(handle)) eof = true;
*(((char *) (ptr)) + r * size + t) = getc(handle);
}*/
int left = size * numItems;
int bytesRead = -1;
+
while ((left > 0) && (!FAT_feof((FAT_FILE *) handle))) {
int amount = left > 8192? 8192: left;
// do {
bytesRead = FAT_fread((void *) ptr, 1, amount, (FAT_FILE *) handle);
- /* if (bytesRead == 0) {
+/* if (bytesRead == 0) {
consolePrintf("Pos:%d items:%d num:%d amount:%d read:%d\n", ftell(handle), items, numItems, amount, bytesRead);
left++;
@@ -592,27 +554,24 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
fread(ptr, 1024, 1, handle);
swiWaitForVBlank();
//while (true);
- }*/
- //} while (bytesRead == 0);
+ }
+
+ } while (bytesRead == 0);
+*/
left -= bytesRead;
ptr = ((char *) (ptr)) + bytesRead;
}
items = numItems - (left / size);
-
-
-
-
+
// FAT_fread((void *) ptr, size, 1, ((int) (handle)) - 1);
- // ptr = ((char *) (ptr)) + size;
-
+// ptr = ((char *) (ptr)) + size;
}
- //}
+// }
// consolePrintf("...done %d \n", items)
return items;
-
}
if (handle->sramFile) {
@@ -630,7 +589,6 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
return bytes / size;
}
-
if (handle->pos + size * numItems > handle->size) {
numItems = (handle->size - handle->pos) / size;
if (numItems < 0) numItems = 0;
@@ -639,10 +597,8 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
// consolePrintf("read %d ", size * numItems);
memcpy((void *) ptr, handle->data + handle->pos, size * numItems);
-
handle->pos += size * numItems;
-
return numItems;
}
@@ -657,7 +613,6 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
//consolePrintf("fwrite size=%d\n", size * numItems);
if (DS::isGBAMPAvailable()) {
-
FAT_fwrite(((char *) (ptr)), size, numItems, (FAT_FILE *) handle);
return numItems;
@@ -675,7 +630,6 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
return numItems;
}
-
if (handle->sramFile) {
handle->sramFile->write(ptr, size);
return size;
@@ -704,6 +658,7 @@ bool std_feof(FILE* handle) {
}
void std_fflush(FILE* handle) {
+ //FIXME: not implemented?
// consolePrintf("fflush ");
}
@@ -711,7 +666,6 @@ char* std_fgets(char* str, int size, FILE* file) {
// consolePrintf("fgets file=%d ", file);
if (DS::isGBAMPAvailable()) {
-
char* s = str;
while ((*s++ = std_getc(file)) >= 32) {
// consolePrintf("%d ", *s);
@@ -723,7 +677,6 @@ char* std_fgets(char* str, int size, FILE* file) {
return str;
}
-
if (file->sramFile) {
file->pos--;
int p = -1;
@@ -743,7 +696,6 @@ char* std_fgets(char* str, int size, FILE* file) {
}
long int std_ftell(FILE* handle) {
-
if (DS::isGBAMPAvailable()) {
return FAT_ftell((FAT_FILE *) handle);
}
@@ -758,39 +710,30 @@ int std_fseek(FILE* handle, long int offset, int whence) {
return FAT_fseek((FAT_FILE *) handle, offset, whence);
}
-
switch (whence) {
- case SEEK_CUR: {
+ case SEEK_CUR:
handle->pos += offset;
break;
- }
-
- case SEEK_SET: {
+ case SEEK_SET:
handle->pos = offset;
break;
- }
-
- case SEEK_END: {
+ case SEEK_END:
handle->pos = handle->size + offset;
break;
- }
-
- default: {
+ default:
handle->pos = offset;
break;
- }
-
}
return 0;
}
void std_clearerr(FILE* handle) {
+ //FIXME: not implemented?
// consolePrintf("clearerr ");
}
int std_getc(FILE* handle) {
-
if (DS::isGBAMPAvailable()) {
char c;
FAT_fread(&c, 1, 1, (FAT_FILE *) handle);
@@ -852,24 +795,3 @@ int std_ferror(FILE* handle) {
}
} // namespace DS
-
-// These functions are added to AbstractFileSystemNode and are therefore outside
-// the DS namespace.
-
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
-// consolePrintf("New node");
-
- if (DS::isGBAMPAvailable()) {
- return new DS::GBAMPFileSystemNode();
- } else {
- return new DS::DSFileSystemNode();
- }
-}
-
-AbstractFilesystemNode* AbstractFilesystemNode::getNodeForPath(const String& path) {
- if (DS::isGBAMPAvailable()) {
- return new DS::GBAMPFileSystemNode(path);
- } else {
- return new DS::DSFileSystemNode(path);
- }
-}
diff --git a/backends/fs/ds/ds-fs.h b/backends/fs/ds/ds-fs.h
index ef651b7ea7..ead0acc05e 100644
--- a/backends/fs/ds/ds-fs.h
+++ b/backends/fs/ds/ds-fs.h
@@ -23,8 +23,6 @@
#ifndef _DS_FS_H
#define _DS_FS_H
-
-
//#include <NDS/ARM9/console.h>
#include "fs.h"
#include "zipreader.h"
@@ -32,81 +30,137 @@
#include "scummconsole.h"
#include "gba_nds_fat.h"
#include "backends/fs/abstract-fs.h"
-//#include "backends/fs/fs.h"
namespace DS {
/**
+ * Implementation of the ScummVM file system API.
* This class is used when a Flash cart is in use.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
class DSFileSystemNode : public AbstractFilesystemNode {
protected:
- static ZipFile* _zipFile;
-
typedef class Common::String String;
+ static ZipFile* _zipFile;
+
String _displayName;
+ String _path;
bool _isDirectory;
bool _isValid;
- String _path;
int _refCountVal;
public:
+ /**
+ * Creates a DSFilesystemNode with the root node as path.
+ */
DSFileSystemNode();
+
+ /**
+ * Creates a DSFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ */
DSFileSystemNode(const String &path);
- DSFileSystemNode(const DSFileSystemNode *node);
+
+ /**
+ * Creates a DSFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ * @param path true if path is a directory, false otherwise.
+ */
DSFileSystemNode(const String& path, bool isDir);
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
- virtual bool isValid() const { return _isValid; }
+ /**
+ * Copy constructor.
+ */
+ DSFileSystemNode(const DSFileSystemNode *node);
+
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
+ virtual bool isValid() const { return _isValid; }
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
- virtual bool listDir(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly) const;
- virtual AbstractFilesystemNode *parent() const;
+ /**
+ * Returns a copy of this node.
+ */
virtual AbstractFilesystemNode *clone() const { return new DSFileSystemNode(this); }
- virtual AbstractFilesystemNode *child(const Common::String& name) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String& name) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
+
+ /**
+ * Returns the zip file this node points to.
+ * TODO: check this documentation.
+ */
static ZipFile* getZip() { return _zipFile; }
};
-
-/**
+ /**
+ * Implementation of the ScummVM file system API.
* This class is used when the GBAMP (GBA Movie Player) is used with a CompactFlash card.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
class GBAMPFileSystemNode : public AbstractFilesystemNode {
protected:
typedef class Common::String String;
String _displayName;
+ String _path;
bool _isDirectory;
bool _isValid;
- String _path;
-
int _refCountVal;
public:
+ /**
+ * Creates a GBAMPFilesystemNode with the root node as path.
+ */
GBAMPFileSystemNode();
+
+ /**
+ * Creates a GBAMPFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ */
GBAMPFileSystemNode(const String &path);
+
+ /**
+ * Creates a DSFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ * @param path true if path is a directory, false otherwise.
+ */
GBAMPFileSystemNode(const String &path, bool isDirectory);
+
+ /**
+ * Copy constructor.
+ */
GBAMPFileSystemNode(const GBAMPFileSystemNode *node);
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
-
- virtual bool isValid() const { return _isValid; }
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
- virtual bool listDir(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly) const;
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *clone() const { return new GBAMPFileSystemNode(this); }
- virtual AbstractFilesystemNode *child(const Common::String& name) const;
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
+ virtual bool isValid() const { return _isValid; }
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
+ /**
+ * Returns a copy of this node.
+ */
+ virtual AbstractFilesystemNode *clone() const { return new GBAMPFileSystemNode(this); }
+ virtual AbstractFilesystemNode *getChild(const Common::String& name) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
};
-
-
-
struct fileHandle {
int pos;
bool used;
@@ -116,7 +170,6 @@ struct fileHandle {
DSSaveFile* sramFile;
};
-
#undef stderr
#undef stdout
#undef stdin
@@ -140,6 +193,6 @@ void std_clearerr(FILE* handle);
void std_cwd(char* dir);
void std_fflush(FILE* handle);
-}
+} //namespace DS
-#endif
+#endif //_DS_FS_H
diff --git a/backends/fs/fs-factory-maker.cpp b/backends/fs/fs-factory-maker.cpp
new file mode 100644
index 0000000000..045f30cb28
--- /dev/null
+++ b/backends/fs/fs-factory-maker.cpp
@@ -0,0 +1,87 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/abstract-fs-factory.h"
+
+/*
+ * All the following includes choose, at compile time, which specific backend will be used
+ * during the execution of the ScummVM.
+ *
+ * It has to be done this way because not all the necessary libraries will be available in
+ * all build environments. Additionally, this results in smaller binaries.
+ */
+#if defined(__amigaos4__)
+ #include "backends/fs/amigaos4/amigaos4-fs-factory.cpp"
+#elif defined(__DC__)
+ #include "backends/fs/dc/ronincd-fs-factory.cpp"
+#elif defined(__DS__)
+ #include "backends/fs/ds/ds-fs-factory.cpp"
+#elif defined(__GP32__)
+ #include "backends/fs/gp32/gp32-fs-factory.cpp"
+#elif defined(__MORPHOS__)
+ #include "backends/fs/morphos/abox-fs-factory.cpp"
+#elif defined(PALMOS_MODE)
+ #include "backends/fs/palmos/palmos-fs-factory.cpp"
+#elif defined(__PLAYSTATION2__)
+ #include "backends/fs/ps2/ps2-fs-factory.cpp"
+#elif defined(__PSP__)
+ #include "backends/fs/psp/psp-fs-factory.cpp"
+#elif defined(__SYMBIAN32__)
+ #include "backends/fs/symbian/symbian-fs-factory.cpp"
+#elif defined(UNIX)
+ #include "backends/fs/posix/posix-fs-factory.cpp"
+#elif defined(WIN32)
+ #include "backends/fs/windows/windows-fs-factory.cpp"
+#endif
+
+/**
+ * Creates concrete FilesystemFactory objects depending on the current architecture.
+ *
+ * @return AbstractFilesystemFactory* The specific factory for the current architecture.
+ */
+static AbstractFilesystemFactory *makeFSFactory() {
+ #if defined(__amigaos4__)
+ return &AmigaOSFilesystemFactory::instance();
+ #elif defined(__DC__)
+ return &RoninCDFilesystemFactory::instance();
+ #elif defined(__DS__)
+ return &DSFilesystemFactory::instance();
+ #elif defined(__GP32__)
+ return &GP32FilesystemFactory::instance();
+ #elif defined(__MORPHOS__)
+ return &ABoxFilesystemFactory::instance();
+ #elif defined(PALMOS_MODE)
+ return &PalmOSFilesystemFactory::instance();
+ #elif defined(__PLAYSTATION2__)
+ return &Ps2FilesystemFactory::instance();
+ #elif defined(__PSP__)
+ return &PSPFilesystemFactory::instance();
+ #elif defined(__SYMBIAN32__)
+ return &SymbianFilesystemFactory::instance();
+ #elif defined(UNIX)
+ return &POSIXFilesystemFactory::instance();
+ #elif defined(WIN32)
+ return &WindowsFilesystemFactory::instance();
+ #endif
+}
diff --git a/backends/fs/gp32/gp32-fs-factory.cpp b/backends/fs/gp32/gp32-fs-factory.cpp
new file mode 100644
index 0000000000..62cdaedf45
--- /dev/null
+++ b/backends/fs/gp32/gp32-fs-factory.cpp
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/gp32/gp32-fs-factory.h"
+#include "backends/fs/gp32/gp32-fs.cpp"
+
+DECLARE_SINGLETON(GP32FilesystemFactory);
+
+AbstractFilesystemNode *GP32FilesystemFactory::makeRootFileNode() const {
+ return new GP32FilesystemNode();
+}
+
+AbstractFilesystemNode *GP32FilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new GP32FilesystemNode();
+}
+
+AbstractFilesystemNode *GP32FilesystemFactory::makeFileNodePath(const String &path) const {
+ return new GP32FilesystemNode(path);
+}
diff --git a/backends/fs/gp32/gp32-fs-factory.h b/backends/fs/gp32/gp32-fs-factory.h
new file mode 100644
index 0000000000..0810695152
--- /dev/null
+++ b/backends/fs/gp32/gp32-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef GP32_FILESYSTEM_FACTORY_H
+#define GP32_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates GP32FilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class GP32FilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<GP32FilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ GP32FilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*GP32_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/gp32/gp32-fs.cpp b/backends/fs/gp32/gp32-fs.cpp
index 017fa98349..9b839867bc 100644
--- a/backends/fs/gp32/gp32-fs.cpp
+++ b/backends/fs/gp32/gp32-fs.cpp
@@ -24,38 +24,81 @@
*/
#include "stdafx.h"
-
#include "backends/fs/abstract-fs.h"
+#define MAX_PATH_SIZE 256
+
+/**
+ * Implementation of the ScummVM file system API.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
+ */
class GP32FilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
+ String _path;
bool _isDirectory;
bool _isRoot;
- String _path;
public:
+ /**
+ * Creates a GP32FilesystemNode with the root node as path.
+ */
GP32FilesystemNode();
+
+ /**
+ * Creates a GP32FilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ */
GP32FilesystemNode(const String &path);
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
+ virtual bool isDirectory() const { return _isDirectory; }
// FIXME: isValid should return false if this Node can't be used!
- // client code can rely on the return value.
+ // so client code can rely on the return value.
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isValid() const { return true; }
- virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *child(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
};
-#define MAX_PATH_SIZE 256
-
const char gpRootPath[] = "gp:\\";
//char gpCurrentPath[MAX_PATH_SIZE] = "gp:\\"; // must end with '\'
+/**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * gp:\foo\bar.txt would return "\bar.txt"
+ * gp:\foo\bar\ would return "\bar\"
+ *
+ * @param str Path to obtain the last component from.
+ * @return Pointer to the first char of the last component inside str.
+ */
+static const char *lastPathComponent(const Common::String &str) {
+ const char *start = str.c_str();
+ const char *cur = start + str.size() - 2;
+
+ while (cur >= start && *cur != '\\') {
+ --cur;
+ }
+
+ return cur + 1;
+}
+
+/**
+ * FIXME: document this function.
+ *
+ * @param path
+ * @param convPath
+ */
int gpMakePath(const char *path, char *convPath) {
// copy root or current directory
const char *p;
@@ -106,18 +149,6 @@ int gpMakePath(const char *path, char *convPath) {
return 0;
}
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- return AbstractFilesystemNode::getRoot();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot() {
- return new GP32FilesystemNode();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new GP32FilesystemNode(path);
-}
-
GP32FilesystemNode::GP32FilesystemNode() {
_isDirectory = true;
_isRoot = true;
@@ -132,8 +163,8 @@ GP32FilesystemNode::GP32FilesystemNode(const String &path) {
gpMakePath(path.c_str(), convPath);
_path = convPath;
-
pos = convPath;
+
while (*pos)
if (*pos++ == '\\')
dsplName = pos;
@@ -150,14 +181,27 @@ GP32FilesystemNode::GP32FilesystemNode(const String &path) {
_isDirectory = true;
}
-bool GP32FilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
+AbstractFilesystemNode *GP32FilesystemNode::getChild(const String &n) const {
+ // FIXME: Pretty lame implementation! We do no error checking to speak
+ // of, do not check if this is a special node, etc.
assert(_isDirectory);
+
+ String newPath(_path);
+ if (_path.lastChar() != '\\')
+ newPath += '\\';
+ newPath += n;
+
+ return new GP32FilesystemNode(newPath);
+}
+
+bool GP32FilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
+ assert(_isDirectory);
+
+ //TODO: honor the hidden flag
GPDIRENTRY dirEntry;
GPFILEATTR attr;
-
GP32FilesystemNode entry;
-
uint32 read;
if (mode == FilesystemNode::kListAll)
@@ -168,9 +212,11 @@ bool GP32FilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
int startIdx = 0; // current file
String listDir(_path);
//listDir += "/";
+
while (GpDirEnumList(listDir.c_str(), startIdx++, 1, &dirEntry, &read) == SM_OK) {
if (dirEntry.name[0] == '.')
continue;
+
entry._displayName = dirEntry.name;
entry._path = _path;
entry._path += dirEntry.name;
@@ -194,18 +240,7 @@ bool GP32FilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
return true;
}
-static const char *lastPathComponent(const Common::String &str) {
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '\\') {
- --cur;
- }
-
- return cur + 1;
-}
-
-AbstractFilesystemNode *GP32FilesystemNode::parent() const {
+AbstractFilesystemNode *GP32FilesystemNode::getParent() const {
if(_isRoot)
return 0;
@@ -218,16 +253,3 @@ AbstractFilesystemNode *GP32FilesystemNode::parent() const {
return p;
}
-
-AbstractFilesystemNode *GP32FilesystemNode::child(const String &n) const {
- // FIXME: Pretty lame implementation! We do no error checking to speak
- // of, do not check if this is a special node, etc.
- assert(_isDirectory);
- String newPath(_path);
- if (_path.lastChar() != '\\')
- newPath += '\\';
- newPath += n;
- GP32FilesystemNode *p = new GP32FilesystemNode(newPath);
-
- return p;
-}
diff --git a/backends/fs/morphos/abox-fs-factory.cpp b/backends/fs/morphos/abox-fs-factory.cpp
new file mode 100644
index 0000000000..e182513002
--- /dev/null
+++ b/backends/fs/morphos/abox-fs-factory.cpp
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/morphos/abox-fs-factory.h"
+#include "backends/fs/morphos/abox-fs.cpp"
+
+DECLARE_SINGLETON(ABoxFilesystemFactory);
+
+AbstractFilesystemNode *ABoxFilesystemFactory::makeRootFileNode() const {
+ return new ABoxFilesystemNode();
+}
+
+AbstractFilesystemNode *ABoxFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new ABoxFilesystemNode();
+}
+
+AbstractFilesystemNode *ABoxFilesystemFactory::makeFileNodePath(const String &path) const {
+ return new ABoxFilesystemNode(path);
+}
diff --git a/backends/fs/morphos/abox-fs-factory.h b/backends/fs/morphos/abox-fs-factory.h
new file mode 100644
index 0000000000..19ef2b097f
--- /dev/null
+++ b/backends/fs/morphos/abox-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef ABOX_FILESYSTEM_FACTORY_H
+#define ABOX_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates ABoxFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class ABoxFilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<ABoxFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ ABoxFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*ABOX_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/morphos/abox-fs.cpp b/backends/fs/morphos/abox-fs.cpp
index 8206e83030..ef50a11e4e 100644
--- a/backends/fs/morphos/abox-fs.cpp
+++ b/backends/fs/morphos/abox-fs.cpp
@@ -35,52 +35,66 @@
#include "base/engine.h"
#include "backends/fs/abstract-fs.h"
-/*
+/**
* Implementation of the ScummVM file system API based on the MorphOS A-Box API.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
-
class ABoxFilesystemNode : public AbstractFilesystemNode {
- protected:
- BPTR _lock;
- String _displayName;
- bool _isDirectory;
- bool _isValid;
- String _path;
-
- public:
- ABoxFilesystemNode();
- ABoxFilesystemNode(BPTR lock, CONST_STRPTR display_name = NULL);
- ABoxFilesystemNode(const String &p);
- ABoxFilesystemNode(const ABoxFilesystemNode &node);
-
- ~ABoxFilesystemNode();
-
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; };
- virtual bool isValid() const { return _isValid; }
- virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
-
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- static AbstractFSList listRoot();
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *child(const String &name) const;
+protected:
+ BPTR _lock;
+ String _displayName;
+ String _path;
+ bool _isDirectory;
+ bool _isValid;
+
+public:
+ /**
+ * Creates a ABoxFilesystemNode with the root node as path.
+ */
+ ABoxFilesystemNode();
+
+ /**
+ * Creates a ABoxFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ */
+ ABoxFilesystemNode(const String &p);
+
+ /**
+ * FIXME: document this constructor.
+ */
+ ABoxFilesystemNode(BPTR lock, CONST_STRPTR display_name = NULL);
+
+ /**
+ * Copy constructor.
+ */
+ ABoxFilesystemNode(const ABoxFilesystemNode &node);
+
+ /**
+ * Destructor.
+ */
+ ~ABoxFilesystemNode();
+
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; };
+ virtual String getPath() const { return _path; }
+ virtual bool isDirectory() const { return _isDirectory; }
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
+ virtual bool isValid() const { return _isValid; }
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
+
+ virtual AbstractFilesystemNode *getChild(const String &name) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
+
+ /**
+ * Return the list of child nodes for the root node.
+ */
+ static AbstractFSList getRootChildren();
};
-
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- return AbstractFilesystemNode::getRoot();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new ABoxFilesystemNode(path);
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot()
-{
- return new ABoxFilesystemNode();
-}
-
ABoxFilesystemNode::ABoxFilesystemNode()
{
_displayName = "Mounted Volumes";
@@ -90,57 +104,6 @@ ABoxFilesystemNode::ABoxFilesystemNode()
_lock = NULL;
}
-ABoxFilesystemNode::ABoxFilesystemNode(BPTR lock, CONST_STRPTR display_name)
-{
- int bufsize = 256;
-
- _lock = NULL;
- for (;;)
- {
- char name[bufsize];
- if (NameFromLock(lock, name, bufsize) != DOSFALSE)
- {
- _path = name;
- _displayName = display_name ? display_name : FilePart(name);
- break;
- }
- if (IoErr() != ERROR_LINE_TOO_LONG)
- {
- _isValid = false;
- debug(6, "Error while retrieving path name: %ld", IoErr());
- return;
- }
- bufsize *= 2;
- }
-
- _isDirectory = false;
- _isValid = false;
-
- FileInfoBlock *fib = (FileInfoBlock*) AllocDosObject(DOS_FIB, NULL);
- if (fib == NULL)
- {
- debug(6, "Failed to allocate memory for FileInfoBlock");
- return;
- }
-
- if (Examine(lock, fib) != DOSFALSE)
- {
- _isDirectory = fib->fib_EntryType > 0;
- if (_isDirectory)
- {
- if (fib->fib_EntryType != ST_ROOT)
- _path += "/";
- _lock = DupLock(lock);
- _isValid = (_lock != NULL);
- }
- else
- {
- _isValid = true;
- }
- }
- FreeDosObject(DOS_FIB, fib);
-}
-
ABoxFilesystemNode::ABoxFilesystemNode(const String &p) {
int len = 0, offset = p.size();
@@ -168,7 +131,6 @@ ABoxFilesystemNode::ABoxFilesystemNode(const String &p) {
}
// Check whether the node exists and if it is a directory
-
BPTR pLock = Lock((STRPTR)_path.c_str(), SHARED_LOCK);
if (pLock)
{
@@ -198,6 +160,58 @@ ABoxFilesystemNode::ABoxFilesystemNode(const String &p) {
FreeDosObject(DOS_FIB, fib);
}
+ABoxFilesystemNode::ABoxFilesystemNode(BPTR lock, CONST_STRPTR display_name)
+{
+ int bufsize = 256;
+
+ _lock = NULL;
+ for (;;)
+ {
+ char name[bufsize];
+ if (NameFromLock(lock, name, bufsize) != DOSFALSE)
+ {
+ _path = name;
+ _displayName = display_name ? display_name : FilePart(name);
+ break;
+ }
+ if (IoErr() != ERROR_LINE_TOO_LONG)
+ {
+ _isValid = false;
+ debug(6, "Error while retrieving path name: %ld", IoErr());
+ return;
+ }
+ bufsize *= 2;
+ }
+
+ _isDirectory = false;
+ _isValid = false;
+
+ FileInfoBlock *fib = (FileInfoBlock*) AllocDosObject(DOS_FIB, NULL);
+ if (fib == NULL)
+ {
+ debug(6, "Failed to allocate memory for FileInfoBlock");
+ return;
+ }
+
+ if (Examine(lock, fib) != DOSFALSE)
+ {
+ _isDirectory = fib->fib_EntryType > 0;
+ if (_isDirectory)
+ {
+ if (fib->fib_EntryType != ST_ROOT)
+ _path += "/";
+ _lock = DupLock(lock);
+ _isValid = (_lock != NULL);
+ }
+ else
+ {
+ _isValid = true;
+ }
+ }
+
+ FreeDosObject(DOS_FIB, fib);
+}
+
ABoxFilesystemNode::ABoxFilesystemNode(const ABoxFilesystemNode& node)
{
_displayName = node._displayName;
@@ -216,8 +230,30 @@ ABoxFilesystemNode::~ABoxFilesystemNode()
}
}
-bool ABoxFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
+AbstractFilesystemNode *ABoxFilesystemNode::getChild(const String &name) const {
+ assert(_isDirectory);
+ String newPath(_path);
+
+ if (_path.lastChar() != '/')
+ newPath += '/';
+ newPath += name;
+
+ BPTR lock = Lock(newPath.c_str(), SHARED_LOCK);
+
+ if (!lock)
+ {
+ return 0;
+ }
+
+ UnLock(lock);
+
+ return new ABoxFilesystemNode(newPath);
+}
+
+bool ABoxFilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hidden) const
{
+ //TODO: honor the hidden flag
+
if (!_isValid)
{
debug(6, "listDir() called on invalid node");
@@ -232,7 +268,7 @@ bool ABoxFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
if (_lock == NULL)
{
/* This is the root node */
- myList = listRoot();
+ list = getRootChildren();
return true;
}
@@ -266,7 +302,7 @@ bool ABoxFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
if (entry)
{
if (entry->isValid())
- myList.push_back(entry);
+ list.push_back(entry);
else
delete entry;
}
@@ -284,7 +320,7 @@ bool ABoxFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
return true;
}
-AbstractFilesystemNode *ABoxFilesystemNode::parent() const
+AbstractFilesystemNode *ABoxFilesystemNode::getParent() const
{
AbstractFilesystemNode *node = NULL;
@@ -309,29 +345,9 @@ AbstractFilesystemNode *ABoxFilesystemNode::parent() const
return node;
}
-AbstractFilesystemNode *ABoxFilesystemNode::child(const String &name) const {
- assert(_isDirectory);
- String newPath(_path);
-
- if (_path.lastChar() != '/')
- newPath += '/';
- newPath += name;
-
- BPTR lock = Lock(newPath.c_str(), SHARED_LOCK);
-
- if (!lock)
- {
- return 0;
- }
-
- UnLock(lock);
-
- return new ABoxFilesystemNode(newPath);
-}
-
-AbstractFSList ABoxFilesystemNode::listRoot()
+AbstractFSList ABoxFilesystemNode::getRootChildren()
{
- AbstractFSList myList;
+ AbstractFSList list;
DosList *dosList;
CONST ULONG lockDosListFlags = LDF_READ | LDF_VOLUMES;
char name[256];
@@ -339,15 +355,15 @@ AbstractFSList ABoxFilesystemNode::listRoot()
dosList = LockDosList(lockDosListFlags);
if (dosList == NULL)
{
- return myList;
+ return list;
}
dosList = NextDosEntry(dosList, LDF_VOLUMES);
while (dosList)
{
- if (dosList->dol_Type == DLT_VOLUME && // Should always be true, but ...
- dosList->dol_Name && // Same here
- dosList->dol_Task // Will be NULL if volume is removed from drive but still in use by some program
+ if (dosList->dol_Type == DLT_VOLUME && // Should always be true, but ...
+ dosList->dol_Name && // Same here
+ dosList->dol_Task // Will be NULL if volume is removed from drive but still in use by some program
)
{
ABoxFilesystemNode *entry;
@@ -365,7 +381,7 @@ AbstractFSList ABoxFilesystemNode::listRoot()
if (entry)
{
if (entry->isValid())
- myList.push_back(entry);
+ list.push_back(entry);
else
delete entry;
}
@@ -377,9 +393,7 @@ AbstractFSList ABoxFilesystemNode::listRoot()
UnLockDosList(lockDosListFlags);
- return myList;
+ return list;
}
#endif // defined(__MORPHOS__)
-
-
diff --git a/backends/fs/palmos/palmos-fs-factory.cpp b/backends/fs/palmos/palmos-fs-factory.cpp
new file mode 100644
index 0000000000..9f24bcd596
--- /dev/null
+++ b/backends/fs/palmos/palmos-fs-factory.cpp
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/palmos/palmos-fs-factory.h"
+#include "backends/fs/palmos/palmos-fs.cpp"
+
+DECLARE_SINGLETON(PalmOSFilesystemFactory);
+
+AbstractFilesystemNode *PalmOSFilesystemFactory::makeRootFileNode() const {
+ return new PalmOSFilesystemNode();
+}
+
+AbstractFilesystemNode *PalmOSFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new PalmOSFilesystemNode();
+}
+
+AbstractFilesystemNode *PalmOSFilesystemFactory::makeFileNodePath(const String &path) const {
+ return new PalmOSFilesystemNode(path);
+}
diff --git a/backends/fs/palmos/palmos-fs-factory.h b/backends/fs/palmos/palmos-fs-factory.h
new file mode 100644
index 0000000000..575ad8fbfc
--- /dev/null
+++ b/backends/fs/palmos/palmos-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef PALMOS_FILESYSTEM_FACTORY_H
+#define PALMOS_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates PalmOSFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class PalmOSFilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<PalmOSFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ PalmOSFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*PALMOS_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/palmos/palmos-fs.cpp b/backends/fs/palmos/palmos-fs.cpp
index 2c524bb830..1e954be2f6 100644
--- a/backends/fs/palmos/palmos-fs.cpp
+++ b/backends/fs/palmos/palmos-fs.cpp
@@ -30,36 +30,68 @@
#include "common/stdafx.h"
#include "backends/fs/abstract-fs.h"
-/*
+/**
* Implementation of the ScummVM file system API based on PalmOS VFS API.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
-
class PalmOSFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
+ String _path;
bool _isDirectory;
bool _isValid;
bool _isPseudoRoot;
- String _path;
public:
+ /**
+ * Creates a PalmOSFilesystemNode with the root node as path.
+ */
PalmOSFilesystemNode();
+
+ /**
+ * Creates a POSIXFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ */
PalmOSFilesystemNode(const String &p);
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
- virtual bool isValid() const { return _isValid; }
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
+ virtual bool isValid() const { return _isValid; }
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *child(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
private:
- static void addFile (AbstractFSList &list, ListMode mode, const Char *base, FileInfoType* find_data);
+ /**
+ * 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, FileInfoType* find_data);
};
+/**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * /foo/bar.txt would return /bar.txt
+ * /foo/bar/ would return /bar/
+ *
+ * @param str String containing the path.
+ * @return Pointer to the first char of the last component inside str.
+ */
static const char *lastPathComponent(const Common::String &str) {
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
@@ -95,19 +127,6 @@ void PalmOSFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const ch
list.push_back(new PalmOSFilesystemNode(entry));
}
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- return AbstractFilesystemNode::getRoot();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot() {
- return new PalmOSFilesystemNode();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new PalmOSFilesystemNode(path);
-}
-
-
PalmOSFilesystemNode::PalmOSFilesystemNode() {
_isDirectory = true;
_displayName = "Root";
@@ -122,13 +141,13 @@ PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) {
UInt32 attr;
FileRef handle;
- Err e = VFSFileOpen(gVars->VFS.volRefNum, _path.c_str(), vfsModeRead, &handle);
- if (!e) {
- e = VFSFileGetAttributes(handle, &attr);
+ Err error = VFSFileOpen(gVars->VFS.volRefNum, _path.c_str(), vfsModeRead, &handle);
+ if (!error) {
+ error = VFSFileGetAttributes(handle, &attr);
VFSFileClose(handle);
}
- if (e) {
+ if (error) {
_isValid = false;
_isDirectory = false;
@@ -139,8 +158,33 @@ PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) {
_isPseudoRoot = false;
}
-bool PalmOSFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
- Err e;
+AbstractFilesystemNode *PalmOSFilesystemNode::getChild(const String &n) const {
+ assert(_isDirectory);
+
+ String newPath(_path);
+ if (_path.lastChar() != '/')
+ newPath += '/';
+ newPath += n;
+
+ FileRef handle;
+ UInt32 attr;
+ Err error = VFSFileOpen(gVars->VFS.volRefNum, newPath.c_str(), vfsModeRead, &handle);
+ if (error)
+ return 0;
+
+ error = VFSFileGetAttributes(handle, &attr);
+ VFSFileClose(handle);
+
+ if (error || !(attr & vfsFileAttrDirectory))
+ return 0;
+
+ return new PalmOSFilesystemNode(newPath);
+}
+
+bool PalmOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
+ //TODO: honor the hidden flag
+
+ Err error;
Char nameP[256];
FileInfoType desc;
FileRef handle;
@@ -148,14 +192,14 @@ bool PalmOSFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
desc.nameP = nameP;
desc.nameBufLen = 256;
- e = VFSFileOpen(gVars->VFS.volRefNum, _path.c_str(), vfsModeRead, &handle);
+ error = VFSFileOpen(gVars->VFS.volRefNum, _path.c_str(), vfsModeRead, &handle);
- if (e)
+ if (error)
return false;
while(dirIterator != expIteratorStop) {
- e = VFSDirEntryEnumerate(handle, &dirIterator, &desc);
- if (!e) {
+ error = VFSDirEntryEnumerate(handle, &dirIterator, &desc);
+ if (!error) {
addFile(myList, mode, _path.c_str(), &desc);
}
}
@@ -165,8 +209,7 @@ bool PalmOSFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
return true;
}
-
-AbstractFilesystemNode *PalmOSFilesystemNode::parent() const {
+AbstractFilesystemNode *PalmOSFilesystemNode::getParent() const {
PalmOSFilesystemNode *p = 0;
if (!_isPseudoRoot) {
@@ -180,31 +223,7 @@ AbstractFilesystemNode *PalmOSFilesystemNode::parent() const {
p->_displayName = lastPathComponent(p->_path);
p->_isPseudoRoot =(p->_path == "/");
}
- return p;
-}
-
-
-AbstractFilesystemNode *PalmOSFilesystemNode::child(const String &n) const {
- assert(_isDirectory);
- String newPath(_path);
-
- if (_path.lastChar() != '/')
- newPath += '/';
- newPath += n;
-
- FileRef handle;
- UInt32 attr;
- Err e = VFSFileOpen(gVars->VFS.volRefNum, newPath.c_str(), vfsModeRead, &handle);
- if (e)
- return 0;
- e = VFSFileGetAttributes(handle, &attr);
- VFSFileClose(handle);
-
- if (e || !(attr & vfsFileAttrDirectory))
- return 0;
-
- PalmOSFilesystemNode *p = new PalmOSFilesystemNode(newPath);
return p;
}
diff --git a/backends/fs/posix/posix-fs-factory.cpp b/backends/fs/posix/posix-fs-factory.cpp
new file mode 100644
index 0000000000..13212fb51f
--- /dev/null
+++ b/backends/fs/posix/posix-fs-factory.cpp
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/posix/posix-fs-factory.h"
+#include "backends/fs/posix/posix-fs.cpp"
+
+DECLARE_SINGLETON(POSIXFilesystemFactory);
+
+AbstractFilesystemNode *POSIXFilesystemFactory::makeRootFileNode() const {
+ return new POSIXFilesystemNode();
+}
+
+AbstractFilesystemNode *POSIXFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ char buf[MAXPATHLEN];
+ getcwd(buf, MAXPATHLEN);
+ return new POSIXFilesystemNode(buf, true);
+}
+
+AbstractFilesystemNode *POSIXFilesystemFactory::makeFileNodePath(const String &path) const {
+ return new POSIXFilesystemNode(path, true);
+}
diff --git a/backends/fs/posix/posix-fs-factory.h b/backends/fs/posix/posix-fs-factory.h
new file mode 100644
index 0000000000..a714175548
--- /dev/null
+++ b/backends/fs/posix/posix-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef POSIX_FILESYSTEM_FACTORY_H
+#define POSIX_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates POSIXFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class POSIXFilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<POSIXFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ POSIXFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*POSIX_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp
index ba1668a390..3708acd2a8 100644
--- a/backends/fs/posix/posix-fs.cpp
+++ b/backends/fs/posix/posix-fs.cpp
@@ -25,7 +25,6 @@
#if defined(UNIX)
#include "common/stdafx.h"
-
#include "backends/fs/abstract-fs.h"
#ifdef MACOSX
@@ -37,33 +36,61 @@
#include <stdio.h>
#include <unistd.h>
-/*
+/**
* Implementation of the ScummVM file system API based on POSIX.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
-
class POSIXFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
+ String _path;
bool _isDirectory;
bool _isValid;
- String _path;
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 flags should be verified during the construction.
+ */
POSIXFilesystemNode(const String &path, bool verify);
-
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
- virtual bool isValid() const { return _isValid; }
+
+ virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
-
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *child(const String &n) const;
+ virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
+ virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
+
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
+
+private:
+ /**
+ * Tests and sets the _isValid and _isDirectory flags, using the stat() function.
+ */
+ virtual void setFlags();
};
-
+/**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * /foo/bar.txt would return /bar.txt
+ * /foo/bar/ would return /bar/
+ *
+ * @param str String containing the path.
+ * @return Pointer to the first char of the last component inside str.
+ */
static const char *lastPathComponent(const Common::String &str) {
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
@@ -75,18 +102,11 @@ static const char *lastPathComponent(const Common::String &str) {
return cur + 1;
}
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- char buf[MAXPATHLEN];
- getcwd(buf, MAXPATHLEN);
- return new POSIXFilesystemNode(buf, true);
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot() {
- return new POSIXFilesystemNode();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new POSIXFilesystemNode(path, true);
+void POSIXFilesystemNode::setFlags() {
+ struct stat st;
+
+ _isValid = (0 == stat(_path.c_str(), &st));
+ _isDirectory = _isValid ? S_ISDIR(st.st_mode) : false;
}
POSIXFilesystemNode::POSIXFilesystemNode() {
@@ -123,30 +143,44 @@ POSIXFilesystemNode::POSIXFilesystemNode(const String &p, bool verify) {
_path = p;
_displayName = lastPathComponent(_path);
- _isValid = true;
- _isDirectory = true;
if (verify) {
- struct stat st;
- _isValid = (0 == stat(_path.c_str(), &st));
- _isDirectory = _isValid ? S_ISDIR(st.st_mode) : false;
+ setFlags();
}
}
-bool POSIXFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
+AbstractFilesystemNode *POSIXFilesystemNode::getChild(const String &n) const {
+ // FIXME: Pretty lame implementation! We do no error checking to speak
+ // of, do not check if this is a special node, etc.
assert(_isDirectory);
- DIR *dirp = opendir(_path.c_str());
+
+ String newPath(_path);
+ if (_path.lastChar() != '/')
+ newPath += '/';
+ newPath += n;
+
+ return new POSIXFilesystemNode(newPath, true);
+}
+bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
+ assert(_isDirectory);
+
+ DIR *dirp = opendir(_path.c_str());
struct dirent *dp;
if (dirp == NULL)
return false;
- // ... loop over dir entries using readdir
+ // loop over dir entries using readdir
while ((dp = readdir(dirp)) != NULL) {
- // Skip 'invisible' files
- if (dp->d_name[0] == '.')
+ // Skip 'invisible' files if necessary
+ if (dp->d_name[0] == '.' && !hidden) {
+ continue;
+ }
+ // Skip '.' and '..' to avoid cycles
+ if((dp->d_name[0] == '.' && dp->d_name[1] == 0) || (dp->d_name[0] == '.' && dp->d_name[1] == '.')) {
continue;
+ }
String newPath(_path);
if (newPath.lastChar() != '/')
@@ -156,18 +190,18 @@ bool POSIXFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
POSIXFilesystemNode entry(newPath, false);
#if defined(SYSTEM_NOT_SUPPORTING_D_TYPE)
- // TODO: d_type is not part of POSIX, so it might not be supported
- // on some of our targets. For those systems where it isn't supported,
- // add this #elif case, which tries to use stat() instead.
- struct stat st;
- entry._isValid = (0 == stat(entry._path.c_str(), &st));
- entry._isDirectory = entry._isValid ? S_ISDIR(st.st_mode) : false;
+ /* TODO: d_type is not part of POSIX, so it might not be supported
+ * on some of our targets. For those systems where it isn't supported,
+ * add this #elif case, which tries to use stat() instead.
+ *
+ * The d_type method is used to avoid costly recurrent stat() calls in big
+ * directories.
+ */
+ entry.setFlags();
#else
if (dp->d_type == DT_UNKNOWN) {
// Fall back to stat()
- struct stat st;
- entry._isValid = (0 == stat(entry._path.c_str(), &st));
- entry._isDirectory = entry._isValid ? S_ISDIR(st.st_mode) : false;
+ entry.setFlags();
} else {
entry._isValid = (dp->d_type == DT_DIR) || (dp->d_type == DT_REG) || (dp->d_type == DT_LNK);
if (dp->d_type == DT_LNK) {
@@ -194,35 +228,22 @@ bool POSIXFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
if (entry._isDirectory)
entry._path += "/";
+
myList.push_back(new POSIXFilesystemNode(entry));
}
closedir(dirp);
+
return true;
}
-AbstractFilesystemNode *POSIXFilesystemNode::parent() const {
+AbstractFilesystemNode *POSIXFilesystemNode::getParent() const {
if (_path == "/")
return 0;
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
- POSIXFilesystemNode *p = new POSIXFilesystemNode(String(start, end - start), false);
-
- return p;
-}
-
-AbstractFilesystemNode *POSIXFilesystemNode::child(const String &n) const {
- // FIXME: Pretty lame implementation! We do no error checking to speak
- // of, do not check if this is a special node, etc.
- assert(_isDirectory);
- String newPath(_path);
- if (_path.lastChar() != '/')
- newPath += '/';
- newPath += n;
- POSIXFilesystemNode *p = new POSIXFilesystemNode(newPath, true);
-
- return p;
+ return new POSIXFilesystemNode(String(start, end - start), true);
}
-#endif // defined(UNIX)
+#endif //#if defined(UNIX)
diff --git a/backends/fs/ps2/ps2-fs-factory.cpp b/backends/fs/ps2/ps2-fs-factory.cpp
new file mode 100644
index 0000000000..570fbd008c
--- /dev/null
+++ b/backends/fs/ps2/ps2-fs-factory.cpp
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/ps2/ps2-fs-factory.h"
+#include "backends/fs/ps2/ps2-fs.cpp"
+
+DECLARE_SINGLETON(Ps2FilesystemFactory);
+
+AbstractFilesystemNode *Ps2FilesystemFactory::makeRootFileNode() const {
+ return new Ps2FilesystemNode();
+}
+
+AbstractFilesystemNode *Ps2FilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new Ps2FilesystemNode();
+}
+
+AbstractFilesystemNode *Ps2FilesystemFactory::makeFileNodePath(const String &path) const {
+ return new Ps2FilesystemNode(path);
+}
diff --git a/backends/fs/ps2/ps2-fs-factory.h b/backends/fs/ps2/ps2-fs-factory.h
new file mode 100644
index 0000000000..9798b2b497
--- /dev/null
+++ b/backends/fs/ps2/ps2-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef PS2_FILESYSTEM_FACTORY_H
+#define PS2_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates PS2FilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class Ps2FilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<Ps2FilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ Ps2FilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*PS2_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/ps2/ps2-fs.cpp b/backends/fs/ps2/ps2-fs.cpp
index afe1842e43..727e1a894f 100644
--- a/backends/fs/ps2/ps2-fs.cpp
+++ b/backends/fs/ps2/ps2-fs.cpp
@@ -32,44 +32,52 @@
extern AsyncFio fio;
extern OSystem_PS2 *g_systemPs2;
+/**
+ * Implementation of the ScummVM file system API based on the Ps2SDK.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
+ */
class Ps2FilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
+ String _path;
bool _isDirectory;
bool _isRoot;
- String _path;
public:
- Ps2FilesystemNode(void);
- Ps2FilesystemNode(const Ps2FilesystemNode *node);
+ /**
+ * Creates a PS2FilesystemNode with the root node as path.
+ */
+ Ps2FilesystemNode();
+
+ /**
+ * Creates a PS2FilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ */
Ps2FilesystemNode(const String &path);
+
+ /**
+ * Copy constructor.
+ */
+ Ps2FilesystemNode(const Ps2FilesystemNode *node);
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
- virtual bool isValid() const { return !_isRoot; }
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
+ virtual bool isValid() const { return !_isRoot; }
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
- //virtual FSList listDir(ListMode) const;
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- virtual AbstractFilesystemNode *parent() const;
virtual AbstractFilesystemNode *clone() const { return new Ps2FilesystemNode(this); }
- virtual AbstractFilesystemNode *child(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
};
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- return AbstractFilesystemNode::getRoot();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot(void) {
- return new Ps2FilesystemNode();
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new Ps2FilesystemNode(path);
-}
-
-Ps2FilesystemNode::Ps2FilesystemNode(void) {
+Ps2FilesystemNode::Ps2FilesystemNode() {
_isDirectory = true;
_isRoot = true;
_displayName = "PlayStation 2";
@@ -108,7 +116,43 @@ Ps2FilesystemNode::Ps2FilesystemNode(const Ps2FilesystemNode *node) {
_isRoot = node->_isRoot;
}
-bool Ps2FilesystemNode::listDir(AbstractFSList &list, ListMode mode) const {
+AbstractFilesystemNode *Ps2FilesystemNode::getChild(const String &n) const {
+ if (!_isDirectory)
+ return NULL;
+
+ char listDir[256];
+ sprintf(listDir, "%s/", _path.c_str());
+ int fd = fio.dopen(listDir);
+
+ if (fd >= 0) {
+ iox_dirent_t dirent;
+
+ while (fio.dread(fd, &dirent) > 0) {
+ if (strcmp(n.c_str(), dirent.name) == 0) {
+ Ps2FilesystemNode *dirEntry = new Ps2FilesystemNode();
+
+ dirEntry->_isDirectory = (bool)(dirent.stat.mode & FIO_S_IFDIR);
+ dirEntry->_isRoot = false;
+
+ dirEntry->_path = _path;
+ dirEntry->_path += "/";
+ dirEntry->_path += dirent.name;
+
+ dirEntry->_displayName = dirent.name;
+
+ fio.dclose(fd);
+ return dirEntry;
+ }
+ }
+ fio.dclose(fd);
+ }
+
+ return NULL;
+}
+
+bool Ps2FilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hidden) const {
+ //TODO: honor the hidden flag
+
if (!_isDirectory)
return false;
@@ -135,6 +179,7 @@ bool Ps2FilesystemNode::listDir(AbstractFSList &list, ListMode mode) const {
} else {
char listDir[256];
int fd;
+
if (_path.lastChar() == '/')
fd = fio.dopen(_path.c_str());
else {
@@ -173,7 +218,7 @@ bool Ps2FilesystemNode::listDir(AbstractFSList &list, ListMode mode) const {
}
}
-AbstractFilesystemNode *Ps2FilesystemNode::parent() const {
+AbstractFilesystemNode *Ps2FilesystemNode::getParent() const {
if (_isRoot)
return new Ps2FilesystemNode(this);
@@ -191,36 +236,3 @@ AbstractFilesystemNode *Ps2FilesystemNode::parent() const {
else
return new Ps2FilesystemNode();
}
-
-AbstractFilesystemNode *Ps2FilesystemNode::child(const String &n) const {
- if (!_isDirectory)
- return NULL;
-
- char listDir[256];
- sprintf(listDir, "%s/", _path.c_str());
- int fd = fio.dopen(listDir);
-
- if (fd >= 0) {
- iox_dirent_t dirent;
-
- while (fio.dread(fd, &dirent) > 0) {
- if (strcmp(n.c_str(), dirent.name) == 0) {
- Ps2FilesystemNode *dirEntry = new Ps2FilesystemNode();
-
- dirEntry->_isDirectory = (bool)(dirent.stat.mode & FIO_S_IFDIR);
- dirEntry->_isRoot = false;
-
- dirEntry->_path = _path;
- dirEntry->_path += "/";
- dirEntry->_path += dirent.name;
-
- dirEntry->_displayName = dirent.name;
-
- fio.dclose(fd);
- return dirEntry;
- }
- }
- fio.dclose(fd);
- }
- return NULL;
-}
diff --git a/backends/fs/psp/psp-fs-factory.cpp b/backends/fs/psp/psp-fs-factory.cpp
new file mode 100644
index 0000000000..e1d2b8fb49
--- /dev/null
+++ b/backends/fs/psp/psp-fs-factory.cpp
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/psp/psp-fs-factory.h"
+#include "backends/fs/psp/psp_fs.cpp"
+
+DECLARE_SINGLETON(PSPFilesystemFactory);
+
+AbstractFilesystemNode *PSPFilesystemFactory::makeRootFileNode() const {
+ return new PSPFilesystemNode();
+}
+
+AbstractFilesystemNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new PSPFilesystemNode();
+}
+
+AbstractFilesystemNode *PSPFilesystemFactory::makeFileNodePath(const String &path) const {
+ return new PSPFilesystemNode(path, true);
+}
diff --git a/backends/fs/psp/psp-fs-factory.h b/backends/fs/psp/psp-fs-factory.h
new file mode 100644
index 0000000000..83a59dcc6a
--- /dev/null
+++ b/backends/fs/psp/psp-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef PSP_FILESYSTEM_FACTORY_H
+#define PSP_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates PSPFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class PSPFilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<PSPFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ PSPFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*PSP_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/psp/psp_fs.cpp b/backends/fs/psp/psp_fs.cpp
index 3f25a63f86..019b13e9e6 100644
--- a/backends/fs/psp/psp_fs.cpp
+++ b/backends/fs/psp/psp_fs.cpp
@@ -23,8 +23,8 @@
*/
#ifdef __PSP__
-#include "engines/engine.h"
+#include "engines/engine.h"
#include "backends/fs/abstract-fs.h"
#include <sys/stat.h>
@@ -32,39 +32,65 @@
#define ROOT_PATH "ms0:/"
-
-/*
+/**
* Implementation of the ScummVM file system API based on PSPSDK API.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
-
class PSPFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
+ String _path;
bool _isDirectory;
bool _isValid;
- String _path;
public:
+ /**
+ * Creates a PSPFilesystemNode with the root node as path.
+ */
PSPFilesystemNode();
+
+ /**
+ * Creates a PSPFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ * @param verify true if the isValid and isDirectory flags should be verified during the construction.
+ */
PSPFilesystemNode(const Common::String &p, bool verify);
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
- virtual bool isValid() const { return _isValid; }
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
+ virtual bool isValid() const { return _isValid; }
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *child(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
};
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- return AbstractFilesystemNode::getRoot();
-}
+/**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * /foo/bar.txt would return /bar.txt
+ * /foo/bar/ would return /bar/
+ *
+ * @param str String containing the path.
+ * @return Pointer to the first char of the last component inside str.
+ */
+static const char *lastPathComponent(const Common::String &str) {
+ const char *start = str.c_str();
+ const char *cur = start + str.size() - 2;
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot() {
- return new PSPFilesystemNode();
+ while (cur >= start && *cur != '/') {
+ --cur;
+ }
+
+ return cur + 1;
}
PSPFilesystemNode::PSPFilesystemNode() {
@@ -89,14 +115,24 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
}
}
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new PSPFilesystemNode(path, true);
-}
+AbstractFilesystemNode *PSPFilesystemNode::getChild(const String &n) const {
+ // FIXME: Pretty lame implementation! We do no error checking to speak
+ // of, do not check if this is a special node, etc.
+ assert(_isDirectory);
+
+ String newPath(_path);
+ if (_path.lastChar() != '/')
+ newPath += '/';
+ newPath += n;
+ return new PSPFilesystemNode(newPath, true);
+}
-bool PSPFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
+bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
assert(_isDirectory);
+ //TODO: honor the hidden flag
+
int dfd = sceIoDopen(_path.c_str());
if (dfd > 0) {
SceIoDirent dir;
@@ -133,18 +169,7 @@ bool PSPFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
}
}
-static const char *lastPathComponent(const Common::String &str) {
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
-
- return cur + 1;
-}
-
-AbstractFilesystemNode *PSPFilesystemNode::parent() const {
+AbstractFilesystemNode *PSPFilesystemNode::getParent() const {
assert(_isValid);
if (_path == ROOT_PATH)
@@ -153,22 +178,7 @@ AbstractFilesystemNode *PSPFilesystemNode::parent() const {
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
- PSPFilesystemNode *p = new PSPFilesystemNode(String(start, end - start), false);
-
- return p;
-}
-
-AbstractFilesystemNode *PSPFilesystemNode::child(const String &n) const {
- // FIXME: Pretty lame implementation! We do no error checking to speak
- // of, do not check if this is a special node, etc.
- assert(_isDirectory);
- String newPath(_path);
- if (_path.lastChar() != '/')
- newPath += '/';
- newPath += n;
- PSPFilesystemNode *p = new PSPFilesystemNode(newPath, true);
-
- return p;
+ return new PSPFilesystemNode(String(start, end - start), false);
}
-#endif // PSP
+#endif //#ifdef __PSP__
diff --git a/backends/fs/symbian/symbian-fs-factory.cpp b/backends/fs/symbian/symbian-fs-factory.cpp
new file mode 100644
index 0000000000..195402e0bb
--- /dev/null
+++ b/backends/fs/symbian/symbian-fs-factory.cpp
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/symbian/symbian-fs-factory.h"
+#include "backends/fs/symbian/symbian-fs.cpp"
+
+DECLARE_SINGLETON(SymbianFilesystemFactory);
+
+AbstractFilesystemNode *SymbianFilesystemFactory::makeRootFileNode() const {
+ return new SymbianFilesystemNode(true);
+}
+
+AbstractFilesystemNode *SymbianFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ char path[MAXPATHLEN];
+ getcwd(path, MAXPATHLEN);
+ return new SymbianFilesystemNode(path);
+}
+
+AbstractFilesystemNode *SymbianFilesystemFactory::makeFileNodePath(const String &path) const {
+ return new SymbianFilesystemNode(path);
+}
diff --git a/backends/fs/symbian/symbian-fs-factory.h b/backends/fs/symbian/symbian-fs-factory.h
new file mode 100644
index 0000000000..b30ca89f99
--- /dev/null
+++ b/backends/fs/symbian/symbian-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef SYMBIAN_FILESYSTEM_FACTORY_H
+#define SYMBIAN_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates SymbianFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class SymbianFilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<SymbianFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ SymbianFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*SYMBIAN_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/symbian/symbian-fs.cpp b/backends/fs/symbian/symbian-fs.cpp
index 8a4c2abaf2..60693eefb5 100644
--- a/backends/fs/symbian/symbian-fs.cpp
+++ b/backends/fs/symbian/symbian-fs.cpp
@@ -31,33 +31,58 @@
#include <f32file.h>
#include <bautils.h>
-/*
+/**
* Implementation of the ScummVM file system API based on POSIX.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
-
class SymbianFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
+ String _path;
bool _isDirectory;
bool _isValid;
- String _path;
bool _isPseudoRoot;
public:
+ /**
+ * Creates a SymbianFilesystemNode with the root node as path.
+ *
+ * @param aIsRoot true if the node will be a pseudo root, false otherwise.
+ */
SymbianFilesystemNode(bool aIsRoot);
+
+ /**
+ * Creates a SymbianFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ */
SymbianFilesystemNode(const String &path);
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
- virtual bool isValid() const { return _isValid; }
+
+ virtual bool exists() const { return true; } //FIXME: this is just a stub
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
+ virtual bool isReadable() const { return true; } //FIXME: this is just a stub
+ virtual bool isValid() const { return _isValid; }
+ virtual bool isWritable() const { return true; } //FIXME: this is just a stub
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *child(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
};
-
+/**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * c:\foo\bar.txt would return "\bar.txt"
+ * c:\foo\bar\ would return "\bar\"
+ *
+ * @param str Path to obtain the last component from.
+ * @return Pointer to the first char of the last component inside str.
+ */
static const char *lastPathComponent(const Common::String &str) {
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
@@ -69,6 +94,11 @@ static const char *lastPathComponent(const Common::String &str) {
return cur + 1;
}
+/**
+ * Fixes the path by changing all slashes to backslashes.
+ *
+ * @param path String with the path to be fixed.
+ */
static void fixFilePath(Common::String& path) {
TInt len = path.size();
@@ -79,20 +109,6 @@ static void fixFilePath(Common::String& path) {
}
}
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- char path[MAXPATHLEN];
- getcwd(path, MAXPATHLEN);
- return new SymbianFilesystemNode(path);
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot() {
- return new SymbianFilesystemNode(true);
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new SymbianFilesystemNode(path);
-}
-
SymbianFilesystemNode::SymbianFilesystemNode(bool aIsRoot) {
_path = "";
_isValid = true;
@@ -128,8 +144,29 @@ SymbianFilesystemNode::SymbianFilesystemNode(const String &path) {
}
}
-bool SymbianFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
+AbstractFilesystemNode *SymbianFilesystemNode::getChild(const String &n) const {
assert(_isDirectory);
+ String newPath(_path);
+
+ if (_path.lastChar() != '\\')
+ newPath += '\\';
+ newPath += n;
+
+ TPtrC8 ptr((const unsigned char*) newPath.c_str(), newPath.size());
+ TFileName fname;
+ fname.Copy(ptr);
+ TBool isFolder = EFalse;
+ BaflUtils::IsFolder(CEikonEnv::Static()->FsSession(), fname, isFolder);
+ if(!isFolder)
+ return 0;
+
+ return new SymbianFilesystemNode(newPath);
+}
+
+bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
+ assert(_isDirectory);
+
+ //TODO: honor the hidden flag
if (_isPseudoRoot) {
// Drives enumeration
@@ -199,18 +236,18 @@ bool SymbianFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
}
CleanupStack::PopAndDestroy(dirPtr);
}
-
}
+
return true;
}
-AbstractFilesystemNode *SymbianFilesystemNode::parent() const {
+AbstractFilesystemNode *SymbianFilesystemNode::getParent() const {
SymbianFilesystemNode *p =NULL;
// Root node is its own parent. Still we can't just return this
// as the GUI code will call delete on the old node.
if (!_isPseudoRoot && _path.size() > 3) {
- p=new SymbianFilesystemNode(false);
+ p = new SymbianFilesystemNode(false);
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
@@ -221,29 +258,10 @@ AbstractFilesystemNode *SymbianFilesystemNode::parent() const {
}
else
{
- p=new SymbianFilesystemNode(true);
+ p = new SymbianFilesystemNode(true);
}
+
return p;
}
-AbstractFilesystemNode *SymbianFilesystemNode::child(const String &n) const {
- assert(_isDirectory);
- String newPath(_path);
-
- if (_path.lastChar() != '\\')
- newPath += '\\';
- newPath += n;
-
- TPtrC8 ptr((const unsigned char*) newPath.c_str(), newPath.size());
- TFileName fname;
- fname.Copy(ptr);
- TBool isFolder = EFalse;
- BaflUtils::IsFolder(CEikonEnv::Static()->FsSession(), fname, isFolder);
- if(!isFolder)
- return 0;
-
- SymbianFilesystemNode *p = new SymbianFilesystemNode(newPath);
- return p;
-}
-
-#endif // defined(__SYMBIAN32__)
+#endif //#if defined (__SYMBIAN32__)
diff --git a/backends/fs/windows/windows-fs-factory.cpp b/backends/fs/windows/windows-fs-factory.cpp
new file mode 100644
index 0000000000..4a4ef018fb
--- /dev/null
+++ b/backends/fs/windows/windows-fs-factory.cpp
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/fs/windows/windows-fs-factory.h"
+#include "backends/fs/windows/windows-fs.cpp"
+
+DECLARE_SINGLETON(WindowsFilesystemFactory);
+
+AbstractFilesystemNode *WindowsFilesystemFactory::makeRootFileNode() const {
+ return new WindowsFilesystemNode();
+}
+
+AbstractFilesystemNode *WindowsFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new WindowsFilesystemNode("", true);
+}
+
+AbstractFilesystemNode *WindowsFilesystemFactory::makeFileNodePath(const String &path) const {
+ return new WindowsFilesystemNode(path, false);
+}
diff --git a/backends/fs/windows/windows-fs-factory.h b/backends/fs/windows/windows-fs-factory.h
new file mode 100644
index 0000000000..eb8ade1a8e
--- /dev/null
+++ b/backends/fs/windows/windows-fs-factory.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef WINDOWS_FILESYSTEM_FACTORY_H
+#define WINDOWS_FILESYSTEM_FACTORY_H
+
+#include "common/singleton.h"
+#include "backends/fs/abstract-fs-factory.h"
+
+/**
+ * Creates WindowsFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemFactory.
+ */
+class WindowsFilesystemFactory : public AbstractFilesystemFactory, public Common::Singleton<WindowsFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ WindowsFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*WINDOWS_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/windows/windows-fs.cpp b/backends/fs/windows/windows-fs.cpp
index 0e12c4a96a..995264f110 100644
--- a/backends/fs/windows/windows-fs.cpp
+++ b/backends/fs/windows/windows-fs.cpp
@@ -29,6 +29,7 @@
#endif
#include "common/stdafx.h"
#include "backends/fs/abstract-fs.h"
+#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32_WCE
@@ -36,39 +37,93 @@
#endif
#include <tchar.h>
-/*
+/**
* Implementation of the ScummVM file system API based on Windows API.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
-
class WindowsFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
+ String _path;
bool _isDirectory;
- bool _isValid;
bool _isPseudoRoot;
- String _path;
+ bool _isValid;
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();
- WindowsFilesystemNode(const String &path);
-
- virtual String displayName() const { return _displayName; }
- virtual String name() const { return _displayName; }
- virtual bool isValid() const { return _isValid; }
+
+ /**
+ * 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.
+ * @param currentDir if true, the path parameter will be ignored and the resulting node will point to the current directory.
+ */
+ WindowsFilesystemNode(const String &path, const bool currentDir);
+
+ virtual bool exists() const { return _access(_path.c_str(), F_OK) == 0; }
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
- virtual String path() const { return _path; }
+ virtual bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; }
+ virtual bool isValid() const { return _isValid; }
+ virtual bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; }
- virtual bool listDir(AbstractFSList &list, ListMode mode) const;
- virtual AbstractFilesystemNode *parent() const;
- virtual AbstractFilesystemNode *child(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
private:
- static char *toAscii(TCHAR *x);
- static const TCHAR* toUnicode(const char *x);
- static void addFile (AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data);
+ /**
+ * 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.
+ *
+ * Examples:
+ * c:\foo\bar.txt would return "\bar.txt"
+ * c:\foo\bar\ would return "\bar\"
+ *
+ * @param str Path to obtain the last component from.
+ * @return Pointer to the first char of the last component inside str.
+ */
static const char *lastPathComponent(const Common::String &str) {
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
@@ -80,27 +135,6 @@ static const char *lastPathComponent(const Common::String &str) {
return cur + 1;
}
-char* WindowsFilesystemNode::toAscii(TCHAR *x) {
-
-#ifndef UNICODE
- return (char*)x;
-#else
- static char asciiString[MAX_PATH];
- WideCharToMultiByte(CP_ACP, 0, x, _tcslen(x) + 1, asciiString, sizeof(asciiString), NULL, NULL);
- return asciiString;
-#endif
-}
-
-const TCHAR* WindowsFilesystemNode::toUnicode(const char *x) {
-#ifndef UNICODE
- return (const TCHAR *)x;
-#else
- static TCHAR unicodeString[MAX_PATH];
- MultiByteToWideChar(CP_ACP, 0, x, strlen(x) + 1, unicodeString, sizeof(unicodeString) / sizeof(TCHAR));
- return unicodeString;
-#endif
-}
-
void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data) {
WindowsFilesystemNode entry;
char *asciiName = toAscii(find_data->cFileName);
@@ -128,25 +162,24 @@ void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const c
list.push_back(new WindowsFilesystemNode(entry));
}
-AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
- char path[MAX_PATH];
- GetCurrentDirectory(MAX_PATH, path);
-
- // Add a trailing slash, if necessary.
- if (path[0] != 0) {
- if (path[strlen(path) - 1] != '\\')
- strcat(path, "\\");
- }
-
- return new WindowsFilesystemNode(path);
-}
-
-AbstractFilesystemNode *AbstractFilesystemNode::getRoot() {
- return new WindowsFilesystemNode();
+char* WindowsFilesystemNode::toAscii(TCHAR *str) {
+#ifndef UNICODE
+ return (char*)str;
+#else
+ static char asciiString[MAX_PATH];
+ WideCharToMultiByte(CP_ACP, 0, str, _tcslen(str) + 1, asciiString, sizeof(asciiString), NULL, NULL);
+ return asciiString;
+#endif
}
-AbstractFilesystemNode *AbstractFilesystemNode::getNodeForPath(const String &path) {
- return new WindowsFilesystemNode(path);
+const TCHAR* WindowsFilesystemNode::toUnicode(const char *str) {
+#ifndef UNICODE
+ return (const TCHAR *)str;
+#else
+ static TCHAR unicodeString[MAX_PATH];
+ MultiByteToWideChar(CP_ACP, 0, str, strlen(str) + 1, unicodeString, sizeof(unicodeString) / sizeof(TCHAR));
+ return unicodeString;
+#endif
}
WindowsFilesystemNode::WindowsFilesystemNode() {
@@ -165,28 +198,59 @@ WindowsFilesystemNode::WindowsFilesystemNode() {
#endif
}
-WindowsFilesystemNode::WindowsFilesystemNode(const String &p) {
- assert(p.size() > 0);
+WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool currentDir) {
+ if (currentDir) {
+ char path[MAX_PATH];
+ GetCurrentDirectory(MAX_PATH, path);
- _path = p;
+ // Add a trailing slash, if necessary.
+ if (path[0] != 0) {
+ if (path[strlen(path) - 1] != '\\')
+ strcat(path, "\\");
+ }
+ _path = path;
+ }
+ else {
+ assert(p.size() > 0);
+ _path = p;
+ }
+
_displayName = lastPathComponent(_path);
// Check whether it is a directory, and whether the file actually exists
DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str()));
if (fileAttribs == INVALID_FILE_ATTRIBUTES) {
- _isValid = false;
_isDirectory = false;
+ _isValid = false;
} else {
- _isValid = true;
_isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0);
+ _isValid = true;
}
_isPseudoRoot = false;
}
-bool WindowsFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const {
+AbstractFilesystemNode *WindowsFilesystemNode::getChild(const String &n) const {
+ assert(_isDirectory);
+
+ String newPath(_path);
+ if (_path.lastChar() != '\\')
+ newPath += '\\';
+ newPath += n;
+
+ // Check whether the directory actually exists
+ DWORD fileAttribs = GetFileAttributes(toUnicode(newPath.c_str()));
+ if (fileAttribs == INVALID_FILE_ATTRIBUTES)
+ return 0;
+
+ return new WindowsFilesystemNode(newPath, false);
+}
+
+bool WindowsFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
assert(_isDirectory);
+ //TODO: honor the hidden flag
+
if (_isPseudoRoot) {
#ifndef _WIN32_WCE
// Drives enumeration
@@ -218,9 +282,12 @@ bool WindowsFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
sprintf(searchPath, "%s*", _path.c_str());
handle = FindFirstFile(toUnicode(searchPath), &desc);
+
if (handle == INVALID_HANDLE_VALUE)
return false;
+
addFile(myList, mode, _path.c_str(), &desc);
+
while (FindNextFile(handle, &desc))
addFile(myList, mode, _path.c_str(), &desc);
@@ -230,10 +297,12 @@ bool WindowsFilesystemNode::listDir(AbstractFSList &myList, ListMode mode) const
return true;
}
-AbstractFilesystemNode *WindowsFilesystemNode::parent() const {
+AbstractFilesystemNode *WindowsFilesystemNode::getParent() const {
assert(_isValid || _isPseudoRoot);
+
if (_isPseudoRoot)
return 0;
+
WindowsFilesystemNode *p = new WindowsFilesystemNode();
if (_path.size() > 3) {
const char *start = _path.c_str();
@@ -246,23 +315,8 @@ AbstractFilesystemNode *WindowsFilesystemNode::parent() const {
p->_displayName = lastPathComponent(p->_path);
p->_isPseudoRoot = false;
}
+
return p;
}
-AbstractFilesystemNode *WindowsFilesystemNode::child(const String &n) const {
- assert(_isDirectory);
- String newPath(_path);
- if (_path.lastChar() != '\\')
- newPath += '\\';
- newPath += n;
-
- // Check whether the directory actually exists
- DWORD fileAttribs = GetFileAttributes(toUnicode(newPath.c_str()));
- if (fileAttribs == INVALID_FILE_ATTRIBUTES)
- return 0;
-
- WindowsFilesystemNode *p = new WindowsFilesystemNode(newPath);
- return p;
-}
-
-#endif // WIN32
+#endif //#ifdef WIN32
diff --git a/backends/plugins/dc/dc-provider.cpp b/backends/plugins/dc/dc-provider.cpp
index 166852655b..db0242f7d8 100644
--- a/backends/plugins/dc/dc-provider.cpp
+++ b/backends/plugins/dc/dc-provider.cpp
@@ -114,14 +114,14 @@ PluginList DCPluginProvider::getPlugins() {
// Scan for all plugins in this directory
FilesystemNode dir(PLUGIN_DIRECTORY);
FSList files;
- if (!dir.listDir(files, FilesystemNode::kListFilesOnly)) {
+ if (!dir.getChildren(files, FilesystemNode::kListFilesOnly)) {
error("Couldn't open plugin directory '%s'", PLUGIN_DIRECTORY);
}
for (FSList::const_iterator i = files.begin(); i != files.end(); ++i) {
- Common::String name(i->name());
+ Common::String name(i->getName());
if (name.hasPrefix(PLUGIN_PREFIX) && name.hasSuffix(PLUGIN_SUFFIX)) {
- pl.push_back(new DCPlugin(i->path()));
+ pl.push_back(new DCPlugin(i->getPath()));
}
}
diff --git a/backends/plugins/posix/posix-provider.cpp b/backends/plugins/posix/posix-provider.cpp
index ce319840a4..03ee1c204f 100644
--- a/backends/plugins/posix/posix-provider.cpp
+++ b/backends/plugins/posix/posix-provider.cpp
@@ -107,14 +107,14 @@ PluginList POSIXPluginProvider::getPlugins() {
// Scan for all plugins in this directory
FilesystemNode dir(PLUGIN_DIRECTORY);
FSList files;
- if (!dir.listDir(files, FilesystemNode::kListFilesOnly)) {
+ if (!dir.getChildren(files, FilesystemNode::kListFilesOnly)) {
error("Couldn't open plugin directory '%s'", PLUGIN_DIRECTORY);
}
for (FSList::const_iterator i = files.begin(); i != files.end(); ++i) {
- Common::String name(i->name());
+ Common::String name(i->getName());
if (name.hasPrefix(PLUGIN_PREFIX) && name.hasSuffix(PLUGIN_SUFFIX)) {
- pl.push_back(new POSIXPlugin(i->path()));
+ pl.push_back(new POSIXPlugin(i->getPath()));
}
}
diff --git a/backends/plugins/sdl/sdl-provider.cpp b/backends/plugins/sdl/sdl-provider.cpp
index 0f67c9a691..cb09af20ca 100644
--- a/backends/plugins/sdl/sdl-provider.cpp
+++ b/backends/plugins/sdl/sdl-provider.cpp
@@ -107,14 +107,14 @@ PluginList SDLPluginProvider::getPlugins() {
// Scan for all plugins in this directory
FilesystemNode dir(PLUGIN_DIRECTORY);
FSList files;
- if (!dir.listDir(files, FilesystemNode::kListFilesOnly)) {
+ if (!dir.getChildren(files, FilesystemNode::kListFilesOnly)) {
error("Couldn't open plugin directory '%s'", PLUGIN_DIRECTORY);
}
for (FSList::const_iterator i = files.begin(); i != files.end(); ++i) {
- Common::String name(i->name());
+ Common::String name(i->getName());
if (name.hasPrefix(PLUGIN_PREFIX) && name.hasSuffix(PLUGIN_SUFFIX)) {
- pl.push_back(new SDLPlugin(i->path()));
+ pl.push_back(new SDLPlugin(i->getPath()));
}
}
diff --git a/backends/plugins/win32/win32-provider.cpp b/backends/plugins/win32/win32-provider.cpp
index eeea3b805c..b340c23709 100644
--- a/backends/plugins/win32/win32-provider.cpp
+++ b/backends/plugins/win32/win32-provider.cpp
@@ -110,14 +110,14 @@ PluginList Win32PluginProvider::getPlugins() {
// Scan for all plugins in this directory
FilesystemNode dir(PLUGIN_DIRECTORY);
FSList files;
- if (!dir.listDir(files, FilesystemNode::kListFilesOnly)) {
+ if (!dir.getChildren(files, FilesystemNode::kListFilesOnly)) {
error("Couldn't open plugin directory '%s'", PLUGIN_DIRECTORY);
}
for (FSList::const_iterator i = files.begin(); i != files.end(); ++i) {
- Common::String name(i->name());
+ Common::String name(i->getName());
if (name.hasPrefix(PLUGIN_PREFIX) && name.hasSuffix(PLUGIN_SUFFIX)) {
- pl.push_back(new Win32Plugin(i->path()));
+ pl.push_back(new Win32Plugin(i->getPath()));
}
}
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index 1898a23f2a..f4742f15a0 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -28,6 +28,8 @@
#include "common/stdafx.h"
#include "common/savefile.h"
#include "common/util.h"
+#include "common/fs.h"
+#include "common/file.h"
#include "backends/saves/default/default-saves.h"
#include "backends/saves/compressed/compressed-saves.h"
@@ -86,7 +88,6 @@ public:
}
};
-
static void join_paths(const char *filename, const char *directory,
char *buf, int bufsize) {
buf[bufsize-1] = '\0';
@@ -113,42 +114,103 @@ static void join_paths(const char *filename, const char *directory,
strncat(buf, filename, bufsize-1);
}
+Common::StringList DefaultSaveFileManager::listSavefiles(const char *regex) {
+ FilesystemNode savePath(getSavePath());
+ FSList savefiles;
+ Common::StringList results;
+ Common::String search(regex);
+
+ if (savePath.lookupFile(savefiles, savePath, search, false, true)) {
+ for (FSList::const_iterator file = savefiles.begin(); file != savefiles.end(); file++) {
+ results.push_back(file->getPath());
+ }
+ }
+
+ return results;
+}
+
+Common::InSaveFile *DefaultSaveFileManager::openForLoading(const char *filename) {
+ char buf[256];
+ join_paths(filename, getSavePath(), buf, sizeof(buf));
+
+ StdioSaveFile *sf = new StdioSaveFile(buf, false);
+
+ if (!sf->isOpen()) {
+ delete sf;
+ sf = 0;
+ }
+ return wrapInSaveFile(sf);
+}
+
Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename) {
char buf[256];
// Ensure that the savepath exists and is writeable. If not, generate
// an appropriate error
const char *savePath = getSavePath();
+
#if defined(UNIX) || defined(__SYMBIAN32__)
struct stat sb;
+ clearError();
// Check whether the dir exists
if (stat(savePath, &sb) == -1) {
// The dir does not exist, or stat failed for some other reason.
// If the problem was that the path pointed to nothing, try
- // to create the dir.
- if (errno == ENOENT) {
+ // to create the dir (ENOENT case).
+ switch (errno) {
+ case EACCES:
+ setError(SFM_DIR_ACCESS, Common::String("Search or write permission denied"));
+ break;
+ case ELOOP:
+ setError(SFM_DIR_LOOP, Common::String("Too many symbolic links encountered while traversing the path"));
+ break;
+ case ENAMETOOLONG:
+ setError(SFM_DIR_NAMETOOLONG, Common::String("The path name is too long"));
+ break;
+ case ENOENT:
if (mkdir(savePath, 0755) != 0) {
// mkdir could fail for various reasons: The parent dir doesn't exist,
// or is not writeable, the path could be completly bogus, etc.
warning("mkdir for '%s' failed!", savePath);
perror("mkdir");
- // TODO: Specify an error code here so that callers can
- // determine what exactly went wrong.
+
+ switch (errno) {
+ case EACCES:
+ setError(SFM_DIR_ACCESS, Common::String("Search or write permission denied"));
+ break;
+ case EMLINK:
+ setError(SFM_DIR_LINKMAX, Common::String("The link count of the parent directory would exceed {LINK_MAX}"));
+ break;
+ case ELOOP:
+ setError(SFM_DIR_LOOP, Common::String("Too many symbolic links encountered while traversing the path"));
+ break;
+ case ENAMETOOLONG:
+ setError(SFM_DIR_NAMETOOLONG, Common::String("The path name is too long"));
+ break;
+ case ENOENT:
+ setError(SFM_DIR_NOENT, Common::String("A component of the path path does not exist, or the path is an empty string"));
+ break;
+ case ENOTDIR:
+ setError(SFM_DIR_NOTDIR, Common::String("A component of the path prefix is not a directory"));
+ break;
+ case EROFS:
+ setError(SFM_DIR_ROFS, Common::String("The parent directory resides on a read-only file system"));
+ break;
+ }
+
return 0;
}
- } else {
- // Unknown error, abort.
- // TODO: Specify an error code here so that callers can
- // determine what exactly went wrong.
- return 0;
- }
+ break;
+ case ENOTDIR:
+ setError(SFM_DIR_NOTDIR, Common::String("A component of the path prefix is not a directory"));
+ break;
+ }
} else {
- // So stat() succeeded. But is the path actually pointing to a
- // directory?
+ // So stat() succeeded. But is the path actually pointing to a directory?
if (!S_ISDIR(sb.st_mode)) {
- // TODO: Specify an error code here so that callers can
- // determine what exactly went wrong.
+ setError(SFM_DIR_NOTDIR, Common::String("The given savepath is not a directory"));
+
return 0;
}
}
@@ -163,27 +225,14 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename)
delete sf;
sf = 0;
}
+
return wrapOutSaveFile(sf);
}
-Common::InSaveFile *DefaultSaveFileManager::openForLoading(const char *filename) {
- char buf[256];
- join_paths(filename, getSavePath(), buf, sizeof(buf));
-
- StdioSaveFile *sf = new StdioSaveFile(buf, false);
-
- if (!sf->isOpen()) {
- delete sf;
- sf = 0;
- }
- return wrapInSaveFile(sf);
-}
-
-void DefaultSaveFileManager::listSavefiles(const char * /* prefix */, bool *marks, int num) {
- // TODO: Implement this properly, at least on systems that support
- // opendir/readdir.
- // Even better, replace this with a better design...
- memset(marks, true, num * sizeof(bool));
+bool DefaultSaveFileManager::removeSavefile(const char *filename) {
+ Common::File file;
+ FilesystemNode savePath(filename);
+ return file.remove(savePath);
}
#endif // !defined(DISABLE_DEFAULT_SAVEFILEMANAGER)
diff --git a/backends/saves/default/default-saves.h b/backends/saves/default/default-saves.h
index 3aea1495a4..9346e79700 100644
--- a/backends/saves/default/default-saves.h
+++ b/backends/saves/default/default-saves.h
@@ -28,12 +28,14 @@
#include "common/stdafx.h"
#include "common/savefile.h"
+#include "common/str.h"
class DefaultSaveFileManager : public Common::SaveFileManager {
public:
- virtual Common::OutSaveFile *openForSaving(const char *filename);
+ virtual Common::StringList listSavefiles(const char *regex);
virtual Common::InSaveFile *openForLoading(const char *filename);
- virtual void listSavefiles(const char * /* prefix */, bool *marks, int num);
+ virtual Common::OutSaveFile *openForSaving(const char *filename);
+ virtual bool removeSavefile(const char *filename);
};
#endif
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 985ef8b3cb..20249e758b 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -32,6 +32,7 @@
#include "common/config-manager.h"
#include "common/system.h"
+#include "common/fs.h"
#include "sound/mididrv.h"
#include "sound/mixer.h"
@@ -48,10 +49,6 @@
#define DETECTOR_TESTING_HACK
-#ifdef DETECTOR_TESTING_HACK
-#include "common/fs.h"
-#endif
-
namespace Base {
static const char USAGE_STRING[] =
@@ -313,7 +310,7 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
for (int i = 1; i < argc; ++i) {
s = argv[i];
s2 = (i < argc-1) ? argv[i+1] : 0;
-
+
if (s[0] != '-') {
// The argument doesn't start with a dash, so it's not an option.
// Hence it must be the target name. We currently enforce that
@@ -390,7 +387,12 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
END_OPTION
DO_OPTION('p', "path")
- // TODO: Verify whether the path is valid
+ FilesystemNode path(option);
+ if(!path.exists()) {
+ usage("Non-existent game path '%s'", option);
+ } else if(!path.isReadable()) {
+ usage("Non-readable game path '%s'", option);
+ }
END_OPTION
DO_OPTION('q', "language")
@@ -428,7 +430,12 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
END_OPTION
DO_LONG_OPTION("soundfont")
- // TODO: Verify whether the path is valid
+ FilesystemNode path(option);
+ if(!path.exists()) {
+ usage("Non-existent soundfont path '%s'", option);
+ } else if(!path.isReadable()) {
+ usage("Non-readable soundfont path '%s'", option);
+ }
END_OPTION
DO_LONG_OPTION_BOOL("disable-sdl-parachute")
@@ -453,7 +460,12 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
END_OPTION
DO_LONG_OPTION("savepath")
- // TODO: Verify whether the path is valid
+ FilesystemNode path(option);
+ if(!path.exists()) {
+ usage("Non-existent savegames path '%s'", option);
+ } else if(!path.isWritable()) {
+ usage("Non-writable savegames path '%s'", option);
+ }
END_OPTION
DO_LONG_OPTION_INT("talkspeed")
@@ -466,7 +478,12 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, char **ar
END_OPTION
DO_LONG_OPTION("themepath")
- // TODO: Verify whether the path is valid
+ FilesystemNode path(option);
+ if(!path.exists()) {
+ usage("Non-existent theme path '%s'", option);
+ } else if(!path.isReadable()) {
+ usage("Non-readable theme path '%s'", option);
+ }
END_OPTION
DO_LONG_OPTION("target-md5")
@@ -562,7 +579,7 @@ static void runDetectorTest() {
FilesystemNode dir(path);
FSList files;
- if (!dir.listDir(files, FilesystemNode::kListAll)) {
+ if (!dir.getChildren(files, FilesystemNode::kListAll)) {
printf(" ... invalid path, skipping\n");
continue;
}
@@ -673,13 +690,18 @@ bool processSettings(Common::String &command, Common::StringMap &settings) {
if (!settings.contains("savepath")) {
const char *dir = getenv("SCUMMVM_SAVEPATH");
if (dir && *dir && strlen(dir) < MAXPATHLEN) {
- // TODO: Verify whether the path is valid
- settings["savepath"] = dir;
+ FilesystemNode saveDir(dir);
+ if(!saveDir.exists()) {
+ warning("Non-existent SCUMMVM_SAVEPATH save path. It will be ignored.");
+ } else if(!saveDir.isWritable()) {
+ warning("Non-writable SCUMMVM_SAVEPATH save path. It will be ignored.");
+ } else {
+ settings["savepath"] = dir;
+ }
}
}
#endif
-
// Finally, store the command line settings into the config manager.
for (Common::StringMap::const_iterator x = settings.begin(); x != settings.end(); ++x) {
Common::String key(x->_key);
diff --git a/common/advancedDetector.cpp b/common/advancedDetector.cpp
index a342ed910a..f3e8671025 100644
--- a/common/advancedDetector.cpp
+++ b/common/advancedDetector.cpp
@@ -276,7 +276,7 @@ PluginError detectGameForEngineCreation(
FSList fslist;
FilesystemNode dir(ConfMan.get("path"));
- if (!dir.listDir(fslist, FilesystemNode::kListFilesOnly)) {
+ if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {
return kInvalidPathError;
}
@@ -345,7 +345,7 @@ static ADGameDescList detectGame(const FSList *fslist, const Common::ADParams &p
// Get the information of the existing files
for (FSList::const_iterator file = fslist->begin(); file != fslist->end(); ++file) {
if (file->isDirectory()) continue;
- tstr = file->name();
+ tstr = file->getName();
tstr.toLowercase();
// Strip any trailing dot
@@ -364,7 +364,7 @@ static ADGameDescList detectGame(const FSList *fslist, const Common::ADParams &p
debug(3, "> %s: %s", tstr.c_str(), md5str);
- if (testFile.open(file->path())) {
+ if (testFile.open(file->getPath())) {
filesSize[tstr] = (int32)testFile.size();
testFile.close();
}
diff --git a/common/error.h b/common/error.h
new file mode 100644
index 0000000000..0ac84df5c3
--- /dev/null
+++ b/common/error.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_ERROR_H
+#define COMMON_ERROR_H
+
+/**
+ * This file contains enums with error codes commonly used.
+ */
+
+/**
+ * Errors used in the SaveFileManager class.
+ */
+enum SFMError {
+ SFM_NO_ERROR, //Default state, indicates no error has been recorded
+ SFM_DIR_ACCESS, //stat(), mkdir()::EACCES: Search or write permission denied
+ SFM_DIR_LINKMAX, //mkdir()::EMLINK: The link count of the parent directory would exceed {LINK_MAX}
+ SFM_DIR_LOOP, //stat(), mkdir()::ELOOP: Too many symbolic links encountered while traversing the path
+ SFM_DIR_NAMETOOLONG, //stat(), mkdir()::ENAMETOOLONG: The path name is too long
+ SFM_DIR_NOENT, //stat(), mkdir()::ENOENT: A component of the path path does not exist, or the path is an empty string
+ SFM_DIR_NOTDIR, //stat(), mkdir()::ENOTDIR: A component of the path prefix is not a directory
+ SFM_DIR_ROFS //mkdir()::EROFS: The parent directory resides on a read-only file system
+};
+
+#endif //COMMON_ERROR_H
diff --git a/common/file.cpp b/common/file.cpp
index 2eba1bcb3d..880383d220 100644
--- a/common/file.cpp
+++ b/common/file.cpp
@@ -28,6 +28,7 @@
#include "common/hashmap.h"
#include "common/util.h"
#include "common/hash-str.h"
+#include <errno.h>
#ifdef MACOSX
#include "CoreFoundation/CoreFoundation.h"
@@ -226,7 +227,7 @@ void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, co
return;
FSList fslist;
- if (!dir.listDir(fslist, FilesystemNode::kListAll)) {
+ if (!dir.getChildren(fslist, FilesystemNode::kListAll)) {
// Failed listing the contents of this node, so it is either not a
// directory, or just doesn't exist at all.
return;
@@ -237,7 +238,7 @@ void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, co
// Do not add directories multiple times, unless this time they are added
// with a bigger depth.
- const String &directory(dir.path());
+ const String &directory(dir.getPath());
if (_defaultDirectories->contains(directory) && (*_defaultDirectories)[directory] >= level)
return;
(*_defaultDirectories)[directory] = level;
@@ -247,13 +248,13 @@ void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, co
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (file->isDirectory()) {
- addDefaultDirectoryRecursive(file->path(), level - 1, prefix + file->name() + "/");
+ addDefaultDirectoryRecursive(file->getPath(), level - 1, prefix + file->getName() + "/");
} else {
String lfn(prefix);
- lfn += file->name();
+ lfn += file->getName();
lfn.toLowercase();
if (!_filesMap->contains(lfn)) {
- (*_filesMap)[lfn] = file->path();
+ (*_filesMap)[lfn] = file->getPath();
}
}
}
@@ -364,15 +365,21 @@ bool File::open(const String &filename, AccessMode mode) {
bool File::open(const FilesystemNode &node, AccessMode mode) {
assert(mode == kFileReadMode || mode == kFileWriteMode);
- if (!node.isValid()) {
- warning("File::open: Trying to open an invalid FilesystemNode object");
+ if (!node.exists()) {
+ warning("File::open: Trying to open a FilesystemNode which does not exist");
return false;
} else if (node.isDirectory()) {
warning("File::open: Trying to open a FilesystemNode which is a directory");
return false;
- }
+ } /*else if (!node.isReadable() && mode == kFileReadMode) {
+ warning("File::open: Trying to open an unreadable FilesystemNode object for reading");
+ return false;
+ } else if (!node.isWritable() && mode == kFileWriteMode) {
+ warning("File::open: Trying to open an unwritable FilesystemNode object for writing");
+ return false;
+ }*/
- String filename(node.name());
+ String filename(node.getName());
if (_handle) {
error("File::open: This file object already is opened (%s), won't open '%s'", _name.c_str(), filename.c_str());
@@ -383,7 +390,7 @@ bool File::open(const FilesystemNode &node, AccessMode mode) {
const char *modeStr = (mode == kFileReadMode) ? "rb" : "wb";
- _handle = fopen(node.path().c_str(), modeStr);
+ _handle = fopen(node.getPath().c_str(), modeStr);
if (_handle == NULL) {
if (mode == kFileReadMode)
@@ -402,16 +409,40 @@ bool File::open(const FilesystemNode &node, AccessMode mode) {
return true;
}
+bool File::remove(const String &filename){
+ if (remove(filename.c_str()) != 0) {
+ if(errno == EACCES)
+ ;//TODO: read-only file
+ if(errno == ENOENT)
+ ;//TODO: non-existent file
+
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool File::remove(const FilesystemNode &node){
+ if (remove(node.getPath()) != 0) {
+ if(errno == EACCES)
+ ;//TODO: read-only file
+ if(errno == ENOENT)
+ ;//TODO: non-existent file
+
+ return false;
+ } else {
+ return true;
+ }
+}
+
bool File::exists(const String &filename) {
// First try to find the file it via a FilesystemNode (in case an absolute
// path was passed). But we only use this to filter out directories.
FilesystemNode file(filename);
- // FIXME: can't use isValid() here since at the time of writing
- // FilesystemNode is to be unable to find for example files
- // added in extrapath
- if (file.isDirectory())
- return false;
-
+
+ return (!file.isDirectory() && file.exists());
+
+ //***DEPRECATED COMMENTS BELOW, LEFT FOR DISCUSSION***
// Next, try to locate the file by *opening* it in read mode. This has
// multiple effects:
// 1) It takes _filesMap and _defaultDirectories into consideration -> good
diff --git a/common/file.h b/common/file.h
index 3d816a6104..416ca75ec7 100644
--- a/common/file.h
+++ b/common/file.h
@@ -52,7 +52,7 @@ private:
// code that accidentally copied File objects tended to break in strange
// ways.
File(const File &f);
- File &operator =(const File &f);
+ File &operator =(const File &f);
public:
enum AccessMode {
@@ -86,6 +86,9 @@ public:
virtual void close();
+ virtual bool remove(const String &filename);
+ virtual bool remove(const FilesystemNode &node);
+
/**
* Checks if the object opened a file successfully.
*
diff --git a/common/fs.cpp b/common/fs.cpp
index c33fc42223..3e0959b232 100644
--- a/common/fs.cpp
+++ b/common/fs.cpp
@@ -23,14 +23,45 @@
*/
#include "common/stdafx.h"
-
-#include "backends/fs/abstract-fs.h"
#include "common/util.h"
+#include "backends/fs/abstract-fs.h"
+#include "backends/fs/fs-factory-maker.cpp"
+/*
+ * Simple DOS-style pattern matching function (understands * and ? like used in DOS).
+ * Taken from exult/files/listfiles.cc
+ */
+static bool matchString(const char *str, const char *pat) {
+ const char *p = 0;
+ const char *q = 0;
+
+ for (;;) {
+ switch (*pat) {
+ case '*':
+ p = ++pat;
+ q = str;
+ break;
-FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode) {
- _realNode = realNode;
- _refCount = new int(1);
+ default:
+ if (*pat != *str) {
+ if (p) {
+ pat = p;
+ str = ++q;
+ if(!*str)
+ return !*pat;
+ break;
+ }
+ else
+ return false;
+ }
+ // fallthrough
+ case '?':
+ if(!*str)
+ return !*pat;
+ pat++;
+ str++;
+ }
+ }
}
FilesystemNode::FilesystemNode() {
@@ -38,6 +69,11 @@ FilesystemNode::FilesystemNode() {
_refCount = 0;
}
+FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode) {
+ _realNode = realNode;
+ _refCount = new int(1);
+}
+
FilesystemNode::FilesystemNode(const FilesystemNode &node) {
_realNode = node._realNode;
_refCount = node._refCount;
@@ -46,10 +82,12 @@ FilesystemNode::FilesystemNode(const FilesystemNode &node) {
}
FilesystemNode::FilesystemNode(const Common::String &p) {
+ AbstractFilesystemFactory *factory = makeFSFactory();
+
if (p.empty() || p == ".")
- _realNode = AbstractFilesystemNode::getCurrentDirectory();
+ _realNode = factory->makeCurrentDirectoryFileNode();
else
- _realNode = AbstractFilesystemNode::getNodeForPath(p);
+ _realNode = factory->makeFileNodePath(p);
_refCount = new int(1);
}
@@ -57,18 +95,7 @@ FilesystemNode::~FilesystemNode() {
decRefCount();
}
-void FilesystemNode::decRefCount() {
- if (_refCount) {
- assert(*_refCount > 0);
- --(*_refCount);
- if (*_refCount == 0) {
- delete _refCount;
- delete _realNode;
- }
- }
-}
-
-FilesystemNode &FilesystemNode::operator =(const FilesystemNode &node) {
+FilesystemNode &FilesystemNode::operator= (const FilesystemNode &node) {
if (node._refCount)
++(*node._refCount);
@@ -80,40 +107,50 @@ FilesystemNode &FilesystemNode::operator =(const FilesystemNode &node) {
return *this;
}
-bool FilesystemNode::isValid() const {
- if (_realNode == 0)
+bool FilesystemNode::operator<(const FilesystemNode& node) const
+{
+ if (isDirectory() && !node.isDirectory())
+ return true;
+ if (!isDirectory() && node.isDirectory())
return false;
- return _realNode->isValid();
+
+ return scumm_stricmp(getDisplayName().c_str(), node.getDisplayName().c_str()) < 0;
}
-FilesystemNode FilesystemNode::getParent() const {
- if (_realNode == 0)
- return *this;
-
- AbstractFilesystemNode *node = _realNode->parent();
- if (node == 0) {
- return *this;
- } else {
- return FilesystemNode(node);
+void FilesystemNode::decRefCount() {
+ if (_refCount) {
+ assert(*_refCount > 0);
+ --(*_refCount);
+ if (*_refCount == 0) {
+ delete _refCount;
+ delete _realNode;
+ }
}
}
+bool FilesystemNode::exists() const {
+ if (_realNode == 0)
+ return false;
+
+ return _realNode->exists();
+}
+
FilesystemNode FilesystemNode::getChild(const Common::String &n) const {
if (_realNode == 0)
return *this;
assert(_realNode->isDirectory());
- AbstractFilesystemNode *node = _realNode->child(n);
+ AbstractFilesystemNode *node = _realNode->getChild(n);
return FilesystemNode(node);
}
-bool FilesystemNode::listDir(FSList &fslist, ListMode mode) const {
+bool FilesystemNode::getChildren(FSList &fslist, ListMode mode, bool hidden) const {
if (!_realNode || !_realNode->isDirectory())
return false;
AbstractFSList tmp;
- if (!_realNode->listDir(tmp, mode))
+ if (!_realNode->getChildren(tmp, mode, hidden))
return false;
fslist.clear();
@@ -124,33 +161,108 @@ bool FilesystemNode::listDir(FSList &fslist, ListMode mode) const {
return true;
}
+Common::String FilesystemNode::getDisplayName() const {
+ assert(_realNode);
+ return _realNode->getDisplayName();
+}
+
+Common::String FilesystemNode::getName() const {
+ assert(_realNode);
+ return _realNode->getName();
+}
+
+FilesystemNode FilesystemNode::getParent() const {
+ if (_realNode == 0)
+ return *this;
+
+ AbstractFilesystemNode *node = _realNode->getParent();
+ if (node == 0) {
+ return *this;
+ } else {
+ return FilesystemNode(node);
+ }
+}
+
+Common::String FilesystemNode::getPath() const {
+ assert(_realNode);
+ return _realNode->getPath();
+}
+
bool FilesystemNode::isDirectory() const {
if (_realNode == 0)
return false;
+
return _realNode->isDirectory();
}
-Common::String FilesystemNode::displayName() const {
- assert(_realNode);
- return _realNode->displayName();
+bool FilesystemNode::isReadable() const {
+ if (_realNode == 0)
+ return false;
+
+ return _realNode->isReadable();
}
-Common::String FilesystemNode::name() const {
- assert(_realNode);
- return _realNode->name();
+bool FilesystemNode::isWritable() const {
+ if (_realNode == 0)
+ return false;
+
+ return _realNode->isWritable();
}
-Common::String FilesystemNode::path() const {
- assert(_realNode);
- return _realNode->path();
-}
+bool FilesystemNode::lookupFile(FSList &results, FSList &fslist, Common::String &filename, bool hidden, bool exhaustive) const
+{
+ int matches = 0;
+
+ for (FSList::iterator entry = fslist.begin(); entry != fslist.end(); ++entry) {
+ if (entry->isDirectory()) {
+ matches += lookupFileRec(results, *entry, filename, hidden, exhaustive);
+ }
+ }
+ return ((matches > 0) ? true : false);
+}
-bool FilesystemNode::operator< (const FilesystemNode& node) const
+bool FilesystemNode::lookupFile(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const
{
- if (isDirectory() && !node.isDirectory())
- return true;
- if (!isDirectory() && node.isDirectory())
+ int matches;
+
+ if (!dir.isDirectory())
return false;
- return scumm_stricmp(displayName().c_str(), node.displayName().c_str()) < 0;
+
+ matches = lookupFileRec(results, dir, filename, hidden, exhaustive);
+
+ return ((matches > 0) ? true : false);
+}
+
+int FilesystemNode::lookupFileRec(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const
+{
+ FSList entries;
+ FSList children;
+ int matches = 0;
+ dir.getChildren(entries, FilesystemNode::kListAll, hidden);
+
+ //Breadth search (entries in the same level)
+ for (FSList::iterator entry = entries.begin(); entry != entries.end(); ++entry) {
+ if (entry->isDirectory()) {
+ children.push_back(*entry);
+ } else {
+ //TODO: here we assume all backends implement the lastPathComponent method. It is currently static,
+ // so it might be a good idea to include it inside the backend class. This would enforce its
+ // implementation by all ports.
+ if (matchString(lastPathComponent(entry->getPath()), filename.c_str())) {
+ results.push_back(*entry);
+ matches++;
+
+ if (!exhaustive)
+ break;
+ }
+ }
+ }
+
+ //Depth search (entries in lower levels)
+ for (FSList::iterator child = children.begin(); child != children.end(); ++child) {
+ matches += lookupFileRec(results, *child, filename, hidden, exhaustive);
+ }
+
+ return matches;
}
diff --git a/common/fs.h b/common/fs.h
index 4c275b5b2a..38e5c64a10 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -33,7 +33,6 @@
class FilesystemNode;
class AbstractFilesystemNode;
-
/**
* List of multiple file system nodes. E.g. the contents of a given directory.
* This is subclass instead of just a typedef so that we can use forward
@@ -41,9 +40,8 @@ class AbstractFilesystemNode;
*/
class FSList : public Common::Array<FilesystemNode> {};
-
/**
- * FilesystemNode provides an abstraction for file pathes, allowing for portable
+ * FilesystemNode provides an abstraction for file paths, allowing for portable
* file system browsing. To this ends, multiple or single roots have to be supported
* (compare Unix with a single root, Windows with multiple roots C:, D:, ...).
*
@@ -64,12 +62,13 @@ class FSList : public Common::Array<FilesystemNode> {};
* paths (MacOS 9 doesn't even have the notion of a "current directory").
* And if we ever want to support devices with no FS in the classical sense (Palm...),
* we can build upon this.
+ *
+ * This class acts as a wrapper around the AbstractFilesystemNode class defined in backends/fs.
*/
class FilesystemNode {
private:
- AbstractFilesystemNode *_realNode;
int *_refCount;
-
+ AbstractFilesystemNode *_realNode;
FilesystemNode(AbstractFilesystemNode *realNode);
public:
@@ -83,9 +82,9 @@ public:
};
/**
- * Create a new invalid FilesystemNode. In other words, isValid() for that
- * node returns false, and if you try to get it's path, an assert is
- * triggered.
+ * Create a new pathless FilesystemNode. Since there's no path associated
+ * with this node, path-related operations (i.e. exists(), isDirectory(),
+ * getPath()) will always return false or raise an assertion.
*/
FilesystemNode();
@@ -113,51 +112,44 @@ public:
/**
* Copy operator.
*/
- FilesystemNode &operator =(const FilesystemNode &node);
-
+ FilesystemNode &operator= (const FilesystemNode &node);
+
/**
- * Checks if the FilesystemNode is valid for any usage
+ * Compare the name of this node to the name of another. Directories
+ * go before normal files.
*/
- bool isValid() const;
+ bool operator<(const FilesystemNode& node) const;
/**
- * Get the parent node of this node. If this node has no parent node,
- * then it returns a duplicate of this node.
+ * Indicates whether the object referred by this path exists in the filesystem or not.
+ *
+ * @return bool true if the path exists, false otherwise.
*/
- FilesystemNode getParent() const;
+ virtual bool exists() const;
/**
* Fetch a child node of this node, with the given name. Only valid for
- * directory nodes (an assertion is triggered otherwise). If no no child
- * node with the given name exists, an invalid node is returned.
+ * directory nodes (an assertion is triggered otherwise).
+ * If no child node with the given name exists, an invalid node is returned.
*/
FilesystemNode getChild(const Common::String &name) const;
-
+
/**
* Return a list of child nodes of this directory node. If called on a node
* that does not represent a directory, false is returned.
+ *
* @return true if succesful, false otherwise (e.g. when the directory does not exist).
- * @todo Rename this to listChildren or getChildren.
*/
- virtual bool listDir(FSList &fslist, ListMode mode = kListDirectoriesOnly) const;
-
- /**
- * Is this node pointing to a directory?
- * @todo Currently we assume that a valid node that is not a directory
- * automatically is a file (ignoring things like symlinks). That might
- * actually be OK... but we could still add an isFile method. Or even replace
- * isValid and isDirectory by a getType() method that can return values like
- * kDirNodeType, kFileNodeType, kInvalidNodeType.
- */
- virtual bool isDirectory() const;
+ virtual bool getChildren(FSList &fslist, ListMode mode = kListDirectoriesOnly, bool hidden = false) const;
/**
* Return a human readable string for this node, usable for display (e.g.
* in the GUI code). Do *not* rely on it being usable for anything else,
* like constructing paths!
+ *
* @return the display name
*/
- virtual Common::String displayName() const;
+ virtual Common::String getDisplayName() const;
/**
* Return a string representation of the name of the file. This is can be
@@ -167,7 +159,7 @@ public:
*
* @return the file name
*/
- virtual Common::String name() const;
+ virtual Common::String getName() const;
/**
* Return a string representation of the file which can be passed to fopen(),
@@ -180,18 +172,107 @@ public:
*
* @return the 'path' represented by this filesystem node
*/
- virtual Common::String path() const;
+ virtual Common::String getPath() const;
+
+ /**
+ * Get the parent node of this node. If this node has no parent node,
+ * then it returns a duplicate of this node.
+ */
+ FilesystemNode getParent() const;
/**
- * Compare the name of this node to the name of another. Directories
- * go before normal files.
+ * Indicates whether the path refers to a directory or not.
+ *
+ * @todo Currently we assume that a node that is not a directory
+ * automatically is a file (ignoring things like symlinks or pipes).
+ * That might actually be OK... but we could still add an isFile method.
+ * Or even replace isDirectory by a getType() method that can return values like
+ * kDirNodeType, kFileNodeType, kInvalidNodeType.
+ */
+ virtual bool isDirectory() const;
+
+ /**
+ * Indicates whether the object referred by this path can be read from or not.
+ *
+ * If the path refers to a directory, readability implies being able to read
+ * and list the directory entries.
+ *
+ * If the path refers to a file, readability implies being able to read the
+ * contents of the file.
+ *
+ * @return bool true if the object can be read, false otherwise.
+ */
+ virtual bool isReadable() const;
+
+ /**
+ * Indicates whether the object referred by this path can be written to or not.
+ *
+ * If the path refers to a directory, writability implies being able to modify
+ * the directory entry (i.e. rename the directory, remove it or write files inside of it).
+ *
+ * If the path refers to a file, writability implies being able to write data
+ * to the file.
+ *
+ * @return bool true if the object can be written to, false otherwise.
*/
- bool operator< (const FilesystemNode& node) const;
+ virtual bool isWritable() const;
+
+ /**
+ * Searches recursively for a filename inside the given directories.
+ *
+ * For each directory in the directory list a breadth-first search is performed,
+ * that is, the current directory entries are scanned before going into subdirectories.
+ *
+ * @param results List to put the matches in.
+ * @param fslist List of directories to search within.
+ * @param filename Name of the file to look for.
+ * @param hidden Whether to search hidden files or not.
+ * @param exhaustive Whether to continue searching after one match has been found.
+ *
+ * @return true if matches could be found, false otherwise.
+ */
+ virtual bool lookupFile(FSList &results, FSList &fslist, Common::String &filename, bool hidden, bool exhaustive) const;
+
+ /**
+ * Searches recursively for a filename inside the given directory.
+ *
+ * The search is performed breadth-first, that is, the current directory entries
+ * are scanned before going into subdirectories.
+ *
+ * @param results List to put the matches in.
+ * @param FilesystemNode Directory to search within.
+ * @param filename Name of the file to look for.
+ * @param hidden Whether to search hidden files or not.
+ * @param exhaustive Whether to continue searching after one match has been found.
+ *
+ * @return true if matches could be found, false otherwise.
+ */
+ virtual bool lookupFile(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const;
protected:
+ /**
+ * Decreases the reference count to the FilesystemNode, and if necessary,
+ * deletes the corresponding underlying references.
+ */
void decRefCount();
+
+ /**
+ * Searches recursively for a filename inside the given directory.
+ *
+ * The search is performed breadth-first, that is, the current directory entries
+ * are scanned before going into subdirectories.
+ *
+ * @param results List to put the matches in.
+ * @param FilesystemNode Directory to search within.
+ * @param filename Name of the file to look for.
+ * @param hidden Whether to search hidden files or not.
+ * @param exhaustive Whether to continue searching after one match has been found.
+ *
+ * @return The number of matches found.
+ */
+ int lookupFileRec(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const;
};
//} // End of namespace Common
-#endif
+#endif //COMMON_FS_H
diff --git a/common/md5.cpp b/common/md5.cpp
index a48ecb4948..32acdc5b8c 100644
--- a/common/md5.cpp
+++ b/common/md5.cpp
@@ -246,15 +246,18 @@ void md5_finish(md5_context *ctx, uint8 digest[16]) {
}
bool md5_file(const FilesystemNode &file, uint8 digest[16], uint32 length) {
- if (!file.isValid()) {
- warning("md5_file: using an invalid FilesystemNode");
+ if(!file.exists()) {
+ warning("md5_file: using an inexistent FilesystemNode");
+ return false;
+ } else if (!file.isReadable()) {
+ warning("md5_file: using an unreadable FilesystemNode");
return false;
} else if (file.isDirectory()) {
- warning("md5_file: using a diretory FilesystemNode");
+ warning("md5_file: using a directory FilesystemNode");
return false;
}
- return md5_file(file.path().c_str(), digest, length);
+ return md5_file(file.getPath().c_str(), digest, length);
}
bool md5_file(const char *name, uint8 digest[16], uint32 length) {
diff --git a/common/savefile.h b/common/savefile.h
index e1a54638b5..9fdd76ae15 100644
--- a/common/savefile.h
+++ b/common/savefile.h
@@ -30,6 +30,8 @@
#include "common/noncopyable.h"
#include "common/scummsys.h"
#include "common/stream.h"
+#include "common/str.h"
+#include "common/error.h"
namespace Common {
@@ -75,10 +77,40 @@ public:
* returning the single SaveFileManager instances to be used.
*/
class SaveFileManager : NonCopyable {
-
+
+protected:
+ SFMError _error;
+ String _errorDesc;
+
public:
virtual ~SaveFileManager() {}
-
+
+ /**
+ * Clears the last set error code and string.
+ */
+ virtual void clearError() { _error = SFM_NO_ERROR; _errorDesc = ""; }
+
+ /**
+ * Returns the last ocurred error code. If none ocurred, returns SFM_NO_ERROR.
+ *
+ * @return A SFMError indicating the type of the last error.
+ */
+ virtual SFMError getError() { return _error; }
+
+ /**
+ * Returns the last ocurred error description. If none ocurred, returns 0.
+ *
+ * @return A string describing the last error.
+ */
+ virtual String getErrorDesc() { return _errorDesc; }
+
+ /**
+ * Sets the last ocurred error.
+ * @param error Code identifying the last error.
+ * @param errorDesc String describing the last error.
+ */
+ virtual void setError(SFMError error, String errorDesc) { _error = error; _errorDesc = errorDesc; }
+
/**
* Open the file with name filename in the given directory for saving.
* @param filename the filename
@@ -94,12 +126,18 @@ public:
virtual InSaveFile *openForLoading(const char *filename) = 0;
/**
- * Request a list of available savegames with a given prefix.
- * TODO: Document this better!
- * TODO: Or even replace it with a better API. For example, one that
- * returns a list of strings for all present file names.
+ * Removes the given savefile from the filesystem.
+ * @param filename Filename path pointing to the savefile.
+ * @return true if no error ocurred. false otherwise.
+ */
+ virtual bool removeSavefile(const char *filename) = 0;
+
+ /**
+ * Request a list of available savegames with a given regex.
+ * @param regex Regular expression to match. Wildcards like * or ? are available.
+ * returns a list of strings for all present file names.
*/
- virtual void listSavefiles(const char * /* prefix */, bool *marks, int num) = 0;
+ virtual Common::StringList listSavefiles(const char *regex) = 0;
/**
* Get the path to the save game directory.
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 601b660ad3..afd61ae765 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -1930,7 +1930,7 @@ Common::EncapsulatedADGameDesc fallbackDetector(const FSList *fslist) {
path = ".";
FilesystemNode fsCurrentDir(path);
- fsCurrentDir.listDir(fslistCurrentDir, FilesystemNode::kListFilesOnly);
+ fsCurrentDir.getChildren(fslistCurrentDir, FilesystemNode::kListFilesOnly);
fslist = &fslistCurrentDir;
}
@@ -1947,13 +1947,13 @@ Common::EncapsulatedADGameDesc fallbackDetector(const FSList *fslist) {
// First grab all filenames and at the same time count the number of *.wag files
for (FSList::const_iterator file = fslist->begin(); file != fslist->end(); ++file) {
if (file->isDirectory()) continue;
- Common::String filename = file->name();
+ Common::String filename = file->getName();
filename.toLowercase();
allFiles[filename] = true; // Save the filename in a hash table
if (filename.hasSuffix(".wag")) {
// Save latest found *.wag file's path (Can be used to open the file, the name can't)
- wagFilePath = file->path();
+ wagFilePath = file->getPath();
wagFileCount++; // Count found *.wag files
}
}
diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp
index 65b9e6592b..362d778c66 100644
--- a/engines/agi/loader_v3.cpp
+++ b/engines/agi/loader_v3.cpp
@@ -52,14 +52,14 @@ int AgiLoader_v3::detectGame() {
FSList fslist;
FilesystemNode dir(ConfMan.get("path"));
- if (!dir.listDir(fslist, FilesystemNode::kListFilesOnly)) {
- warning("AgiEngine: invalid game path '%s'", dir.path().c_str());
+ if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {
+ warning("AgiEngine: invalid game path '%s'", dir.getPath().c_str());
return errInvalidAGIFile;
}
for (FSList::const_iterator file = fslist.begin();
file != fslist.end() && !found; ++file) {
- Common::String f = file->name();
+ Common::String f = file->getName();
f.toLowercase();
if (f.hasSuffix("vol.0")) {
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index 99d29bcc6b..b76ab309a5 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -989,7 +989,7 @@ struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction<const Filesyste
fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); }
bool operator()(const FilesystemNode &param) const {
for (Common::StringList::const_iterator iter = _str.begin(); iter != _str.end(); iter++)
- if (param.name().equalsIgnoreCase(*iter))
+ if (param.getName().equalsIgnoreCase(*iter))
return true;
return false;
}
@@ -1014,8 +1014,8 @@ bool SoundMgr::loadInstruments() {
// List files in the game path
FSList fslist;
FilesystemNode dir(ConfMan.get("path"));
- if (!dir.listDir(fslist, FilesystemNode::kListFilesOnly)) {
- warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.path().c_str());
+ if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {
+ warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str());
return false;
}
@@ -1050,12 +1050,12 @@ bool SoundMgr::loadInstruments() {
// Finally fix the instruments' lengths using the wave file data
// (A zero in the wave file data can end the sample prematurely)
// and convert the wave file from 8-bit unsigned to 16-bit signed format.
- Common::MemoryReadStream *uint8Wave = loadWaveFile(waveFsnode->path(), *exeInfo);
+ Common::MemoryReadStream *uint8Wave = loadWaveFile(waveFsnode->getPath(), *exeInfo);
// Seek the wave to its
if (uint8Wave != NULL)
uint8Wave->seek(0);
- bool result = uint8Wave != NULL && loadInstrumentHeaders(exeFsnode->path(), *exeInfo) &&
+ bool result = uint8Wave != NULL && loadInstrumentHeaders(exeFsnode->getPath(), *exeInfo) &&
finalizeInstruments(*uint8Wave) && convertWave(*uint8Wave, g_wave, uint8Wave->size());
delete uint8Wave; // Free the 8-bit unsigned wave file buffer
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index 3715088ee7..f7c2d4846f 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -38,13 +38,29 @@ namespace AGOS {
int AGOSEngine::countSaveGames() {
Common::InSaveFile *f;
+ Common::StringList filenames;
uint i = 1;
+ char slot[3];
+ int slotNum;
bool marks[256];
char *prefix = genSaveName(998);
- prefix[strlen(prefix)-3] = '\0';
- _saveFileMan->listSavefiles(prefix, marks, 256);
-
+ prefix[strlen(prefix)-3] = '*';
+ prefix[strlen(prefix)-2] = '\0';
+ memset(marks, false, 256 * sizeof(bool)); //assume no savegames for this title
+ filenames = _saveFileMan->listSavefiles(prefix);
+
+ for(Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++){
+ //Obtain the last 3 digits of the filename, since they correspond to the save slot
+ slot[0] = file->c_str()[file->size()-3];
+ slot[1] = file->c_str()[file->size()-2];
+ slot[2] = file->c_str()[file->size()-1];
+
+ slotNum = atoi(slot);
+ if(slotNum >= 0 && slotNum < 256)
+ marks[slotNum] = true; //mark this slot as valid
+ }
+
while (i < 256) {
if (marks[i] &&
(f = _saveFileMan->openForLoading(genSaveName(i)))) {
@@ -53,6 +69,7 @@ int AGOSEngine::countSaveGames() {
} else
break;
}
+
return i;
}
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index 3f01463dc6..32c090dc57 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -82,8 +82,8 @@ Resource::Resource(KyraEngine *vm) {
FSList fslist;
FilesystemNode dir(ConfMan.get("path"));
- if (!dir.listDir(fslist, FilesystemNode::kListFilesOnly))
- error("invalid game path '%s'", dir.path().c_str());
+ if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly))
+ error("invalid game path '%s'", dir.getPath().c_str());
if (_vm->game() == GI_KYRA1 && _vm->gameFlags().isTalkie) {
static const char *list[] = {
@@ -96,7 +96,7 @@ Resource::Resource(KyraEngine *vm) {
Common::for_each(_pakfiles.begin(), _pakfiles.end(), Common::bind2nd(Common::mem_fun(&ResourceFile::protect), true));
} else {
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- Common::String filename = file->name();
+ Common::String filename = file->getName();
filename.toUppercase();
// No real PAK file!
@@ -104,8 +104,8 @@ Resource::Resource(KyraEngine *vm) {
continue;
if (filename.hasSuffix("PAK") || filename.hasSuffix("APK")) {
- if (!loadPakFile(file->name()))
- error("couldn't open pakfile '%s'", file->name().c_str());
+ if (!loadPakFile(file->getName()))
+ error("couldn't open pakfile '%s'", file->getName().c_str());
}
}
diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp
index d12244af07..4291b9aedb 100644
--- a/engines/lure/detection.cpp
+++ b/engines/lure/detection.cpp
@@ -97,7 +97,7 @@ GameList Engine_LURE_detectGames(const FSList &fslist) {
continue;
for (g = lure_games; g->gameid; g++) {
- if (scumm_stricmp(file->name().c_str(), g->checkFile) == 0)
+ if (scumm_stricmp(file->getName().c_str(), g->checkFile) == 0)
isFound = true;
}
if (isFound)
diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp
index bbb186d0ae..7ba89b7af9 100644
--- a/engines/queen/queen.cpp
+++ b/engines/queen/queen.cpp
@@ -73,7 +73,7 @@ GameList Engine_QUEEN_detectGames(const FSList &fslist) {
if (file->isDirectory()) {
continue;
}
- if (file->name().equalsIgnoreCase("queen.1") || file->name().equalsIgnoreCase("queen.1c")) {
+ if (file->getName().equalsIgnoreCase("queen.1") || file->getName().equalsIgnoreCase("queen.1c")) {
Common::File dataFile;
if (!dataFile.open(*file)) {
continue;
@@ -317,11 +317,28 @@ void QueenEngine::makeGameStateName(uint16 slot, char *buf) {
}
void QueenEngine::findGameStateDescriptions(char descriptions[100][32]) {
- char filename[20];
- makeGameStateName(0, filename);
- filename[strlen(filename) - 2] = 0;
+ char prefix[20];
+ makeGameStateName(0, prefix);
+ prefix[strlen(prefix) - 2] = '*';
+ prefix[strlen(prefix) - 1] = 0;
bool marks[SAVESTATE_MAX_NUM];
- _saveFileMan->listSavefiles(filename, marks, SAVESTATE_MAX_NUM);
+ char slot[2];
+ int slotNum;
+ Common::StringList filenames;
+
+ memset(marks, false, SAVESTATE_MAX_NUM * sizeof(bool)); //assume no savegames for this title
+ filenames = _saveFileMan->listSavefiles(prefix);
+
+ for(Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++){
+ //Obtain the last 2 digits of the filename, since they correspond to the save slot
+ slot[0] = file->c_str()[file->size()-2];
+ slot[1] = file->c_str()[file->size()-1];
+
+ slotNum = atoi(slot);
+ if(slotNum >= 0 && slotNum < SAVESTATE_MAX_NUM)
+ marks[slotNum] = true; //mark this slot as valid
+ }
+
for (int i = 0; i < SAVESTATE_MAX_NUM; ++i) {
if (marks[i]) {
GameStateHeader header;
diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp
index a697ab25ff..6e731de44e 100644
--- a/engines/saga/saveload.cpp
+++ b/engines/saga/saveload.cpp
@@ -112,14 +112,32 @@ uint SagaEngine::getNewSaveSlotNumber() {
}
void SagaEngine::fillSaveList() {
+ assert(_saveMarks);
+
int i;
Common::InSaveFile *in;
+ Common::StringList filenames;
+ char slot[2];
+ int slotNum;
char *name;
name = calcSaveFileName(MAX_SAVES);
- name[strlen(name) - 2] = 0;
- _saveFileMan->listSavefiles(name, _saveMarks, MAX_SAVES);
-
+ name[strlen(name) - 2] = '*';
+ name[strlen(name) - 1] = 0;
+
+ memset(_saveMarks, false, MAX_SAVES * sizeof(bool)); //assume no savegames for this title
+ filenames = _saveFileMan->listSavefiles(name);
+
+ for(Common::StringList::iterator file = filenames.begin(); file != filenames.end(); file++){
+ //Obtain the last 2 digits of the filename, since they correspond to the save slot
+ slot[0] = file->c_str()[file->size()-2];
+ slot[1] = file->c_str()[file->size()-1];
+
+ slotNum = atoi(slot);
+ if(slotNum >= 0 && slotNum < MAX_SAVES)
+ _saveMarks[slotNum] = true; //mark this slot as valid
+ }
+
_saveFilesMaxCount = 0;
for (i = 0; i < MAX_SAVES; i++) {
if (_saveMarks[i]) {
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 25c0a7318d..90c6e40aa7 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -190,7 +190,7 @@ static bool testGame(const GameSettings *g, const DescMap &fileMD5Map, const Com
// the first match is used.
static bool searchFSNode(const FSList &fslist, const Common::String &name, FilesystemNode &result) {
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (!scumm_stricmp(file->name().c_str(), name.c_str())) {
+ if (!scumm_stricmp(file->getName().c_str(), name.c_str())) {
result = *file;
return true;
}
@@ -216,7 +216,7 @@ static Common::Language detectLanguage(const FSList &fslist, byte id) {
FSList tmpList;
if (searchFSNode(fslist, "RESOURCE", resDir)
&& resDir.isDirectory()
- && resDir.listDir(tmpList, FilesystemNode::kListFilesOnly)
+ && resDir.getChildren(tmpList, FilesystemNode::kListFilesOnly)
&& searchFSNode(tmpList, filename, langFile)) {
tmp.open(langFile);
}
@@ -320,7 +320,7 @@ static void detectGames(const FSList &fslist, Common::List<DetectorResult> &resu
DetectorDesc d;
d.node = *file;
d.md5Entry = 0;
- fileMD5Map[file->name()] = d;
+ fileMD5Map[file->getName()] = d;
}
}
@@ -447,7 +447,7 @@ static bool testGame(const GameSettings *g, const DescMap &fileMD5Map, const Com
Common::File tmp;
if (!tmp.open(d.node)) {
- warning("SCUMM detectGames: failed to open '%s' for read access", d.node.path().c_str());
+ warning("SCUMM detectGames: failed to open '%s' for read access", d.node.getPath().c_str());
return false;
}
@@ -751,7 +751,7 @@ PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) {
// Fetch the list of files in the current directory
FSList fslist;
FilesystemNode dir(ConfMan.get("path"));
- if (!dir.listDir(fslist, FilesystemNode::kListFilesOnly)) {
+ if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {
return kInvalidPathError;
}
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 58fd740b17..1666578c4c 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -421,10 +421,10 @@ void SaveLoadChooser::updateInfos() {
#pragma mark -
Common::StringList generateSavegameList(ScummEngine *scumm, bool saveMode) {
- // Get savegame names
- Common::StringList l;
+ // Get savegame descriptions
+ Common::StringList descriptions;
char name[32];
- uint i = saveMode ? 1 : 0;
+ uint i = saveMode ? 1 : 0; //the autosave is on slot #0
bool avail_saves[81];
scumm->listSavegames(avail_saves, ARRAYSIZE(avail_saves));
@@ -433,10 +433,10 @@ Common::StringList generateSavegameList(ScummEngine *scumm, bool saveMode) {
scumm->getSavegameName(i, name);
else
name[0] = 0;
- l.push_back(name);
+ descriptions.push_back(name);
}
-
- return l;
+
+ return descriptions;
}
MainMenuDialog::MainMenuDialog(ScummEngine *scumm)
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 4e8d670403..0e485e226a 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -384,10 +384,28 @@ void ScummEngine::makeSavegameName(char *out, int slot, bool temporary) {
}
void ScummEngine::listSavegames(bool *marks, int num) {
+ assert(marks);
+
char prefix[256];
+ char slot[2];
+ int slotNum;
+ Common::StringList filenames;
+
makeSavegameName(prefix, 99, false);
- prefix[strlen(prefix)-2] = 0;
- _saveFileMan->listSavefiles(prefix, marks, num);
+ prefix[strlen(prefix)-2] = '*';
+ prefix[strlen(prefix)-1] = 0;
+ memset(marks, false, num * sizeof(bool)); //assume no savegames for this title
+ filenames = _saveFileMan->listSavefiles(prefix);
+
+ for(Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++){
+ //Obtain the last 2 digits of the filename, since they correspond to the save slot
+ slot[0] = file->c_str()[file->size()-2];
+ slot[1] = file->c_str()[file->size()-1];
+
+ slotNum = atoi(slot);
+ if(slotNum >= 0 && slotNum < num)
+ marks[slotNum] = true; //mark this slot as valid
+ }
}
bool ScummEngine::getSavegameName(int slot, char *desc) {
diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp
index 79c1f0cb7d..1ff23dbd07 100644
--- a/engines/sky/sky.cpp
+++ b/engines/sky/sky.cpp
@@ -124,11 +124,11 @@ GameList Engine_SKY_detectGames(const FSList &fslist) {
// Iterate over all files in the given directory
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (!file->isDirectory()) {
- const char *fileName = file->name().c_str();
+ const char *fileName = file->getName().c_str();
if (0 == scumm_stricmp("sky.dsk", fileName)) {
Common::File dataDisk;
- if (dataDisk.open(file->path())) {
+ if (dataDisk.open(file->getPath())) {
hasSkyDsk = true;
dataDiskSize = dataDisk.size();
}
@@ -136,7 +136,7 @@ GameList Engine_SKY_detectGames(const FSList &fslist) {
if (0 == scumm_stricmp("sky.dnr", fileName)) {
Common::File dinner;
- if (dinner.open(file->path())) {
+ if (dinner.open(file->getPath())) {
hasSkyDnr = true;
dinnerTableEntries = dinner.readUint32LE();
}
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 5633a58f0f..b5152f33bc 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -107,15 +107,15 @@ GameDescriptor Engine_SWORD1_findGameID(const char *gameid) {
void Sword1CheckDirectory(const FSList &fslist, bool *filesFound) {
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
if (!file->isDirectory()) {
- const char *fileName = file->name().c_str();
+ const char *fileName = file->getName().c_str();
for (int cnt = 0; cnt < NUM_FILES_TO_CHECK; cnt++)
if (scumm_stricmp(fileName, g_filesToCheck[cnt]) == 0)
filesFound[cnt] = true;
} else {
for (int cnt = 0; cnt < ARRAYSIZE(g_dirNames); cnt++)
- if (scumm_stricmp(file->name().c_str(), g_dirNames[cnt]) == 0) {
+ if (scumm_stricmp(file->getName().c_str(), g_dirNames[cnt]) == 0) {
FSList fslist2;
- if (file->listDir(fslist2, FilesystemNode::kListFilesOnly))
+ if (file->getChildren(fslist2, FilesystemNode::kListFilesOnly))
Sword1CheckDirectory(fslist2, filesFound);
}
}
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index 8bf3467b86..6bbd58ff3c 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -101,7 +101,7 @@ GameList Engine_SWORD2_detectGames(const FSList &fslist) {
// Iterate over all files in the given directory
for (file = fslist.begin(); file != fslist.end(); ++file) {
if (!file->isDirectory()) {
- const char *fileName = file->name().c_str();
+ const char *fileName = file->getName().c_str();
if (0 == scumm_stricmp(g->detectname, fileName)) {
// Match found, add to list of candidates, then abort inner loop.
@@ -118,11 +118,11 @@ GameList Engine_SWORD2_detectGames(const FSList &fslist) {
// present e.g. if the user copied the data straight from CD.
for (file = fslist.begin(); file != fslist.end(); ++file) {
if (file->isDirectory()) {
- const char *fileName = file->name().c_str();
+ const char *fileName = file->getName().c_str();
if (0 == scumm_stricmp("clusters", fileName)) {
FSList recList;
- if (file->listDir(recList, FilesystemNode::kListAll)) {
+ if (file->getChildren(recList, FilesystemNode::kListAll)) {
GameList recGames(Engine_SWORD2_detectGames(recList));
if (!recGames.empty()) {
detectedGames.push_back(recGames);
@@ -144,7 +144,7 @@ PluginError Engine_SWORD2_create(OSystem *syst, Engine **engine) {
FSList fslist;
FilesystemNode dir(ConfMan.get("path"));
- if (!dir.listDir(fslist, FilesystemNode::kListAll)) {
+ if (!dir.getChildren(fslist, FilesystemNode::kListAll)) {
return kInvalidPathError;
}
diff --git a/engines/touche/saveload.cpp b/engines/touche/saveload.cpp
index fb82e68944..5ff749fa68 100644
--- a/engines/touche/saveload.cpp
+++ b/engines/touche/saveload.cpp
@@ -400,7 +400,7 @@ void ToucheEngine::readGameStateDescription(int num, char *description, int len)
void ToucheEngine::generateGameStateFileName(int num, char *dst, int len, bool prefixOnly) const {
if (prefixOnly) {
- snprintf(dst, len, "%s.", _targetName.c_str());
+ snprintf(dst, len, "%s.*", _targetName.c_str());
} else {
snprintf(dst, len, "%s.%d", _targetName.c_str(), num);
}
diff --git a/engines/touche/ui.cpp b/engines/touche/ui.cpp
index 15dc64aaf2..4d7100d4d0 100644
--- a/engines/touche/ui.cpp
+++ b/engines/touche/ui.cpp
@@ -370,9 +370,33 @@ void ToucheEngine::handleOptions(int forceDisplay) {
setupMenu(menuData.mode, &menuData);
curMode = menuData.mode;
if (menuData.mode == kMenuLoadStateMode || menuData.mode == kMenuSaveStateMode) {
+ assert(menuData.saveLoadMarks);
+
char gameStateFileName[16];
generateGameStateFileName(999, gameStateFileName, 15, true);
- _saveFileMan->listSavefiles(gameStateFileName, menuData.saveLoadMarks, 100);
+ char slot[2];
+ int slotNum;
+ Common::StringList filenames;
+
+ memset(menuData.saveLoadMarks, false, 100 * sizeof(bool)); //assume no savegames for this title
+ filenames = _saveFileMan->listSavefiles(gameStateFileName);
+
+ for(Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++){
+ //Obtain the last 1 or 2 digits of the filename, since they correspond to the save slot
+ //This engine can save games either with one or two digits, hence the additional if statement
+ slot[0] = file->c_str()[file->size()-2];
+ slot[1] = file->c_str()[file->size()-1];
+
+ if(!atoi(&slot[0])){
+ slotNum = atoi(&slot[1]);
+ } else {
+ slotNum = atoi(slot);
+ }
+
+ if(slotNum >= 0 && slotNum < 100)
+ menuData.saveLoadMarks[slotNum] = true; //mark this slot as valid
+ }
+
for (int i = 0; i < 100; ++i) {
menuData.saveLoadDescriptionsTable[i][0] = 0;
if (menuData.saveLoadMarks[i]) {
diff --git a/gui/browser.cpp b/gui/browser.cpp
index b0367fa1dc..ebe4aef0c4 100644
--- a/gui/browser.cpp
+++ b/gui/browser.cpp
@@ -28,7 +28,6 @@
#include "gui/ListWidget.h"
#include "common/config-manager.h"
-#include "common/fs.h"
#include "common/system.h"
#include "common/algorithm.h"
@@ -223,15 +222,15 @@ void BrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
void BrowserDialog::updateListing() {
// Update the path display
- _currentPath->setLabel(_node.path());
+ _currentPath->setLabel(_node.getPath());
// We memorize the last visited path.
- ConfMan.set("browser_lastpath", _node.path());
+ ConfMan.set("browser_lastpath", _node.getPath());
// Read in the data from the file system
FilesystemNode::ListMode listMode = _isDirBrowser ? FilesystemNode::kListDirectoriesOnly
: FilesystemNode::kListAll;
- if (!_node.listDir(_nodeContent, listMode)) {
+ if (!_node.getChildren(_nodeContent, listMode)) {
_nodeContent.clear();
} else {
Common::sort(_nodeContent.begin(), _nodeContent.end());
@@ -241,9 +240,9 @@ void BrowserDialog::updateListing() {
Common::StringList list;
for (FSList::iterator i = _nodeContent.begin(); i != _nodeContent.end(); ++i) {
if (!_isDirBrowser && i->isDirectory())
- list.push_back(i->displayName() + "/");
+ list.push_back(i->getDisplayName() + "/");
else
- list.push_back(i->displayName());
+ list.push_back(i->getDisplayName());
}
_fileList->setList(list);
_fileList->scrollTo(0);
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 59404dfd74..2dc3fbba28 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -394,9 +394,9 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
if (browser.runModal() > 0) {
// User made this choice...
FilesystemNode file(browser.getResult());
- _soundFont->setLabel(file.path());
+ _soundFont->setLabel(file.getPath());
- if (!file.path().empty() && (file.path() != "None"))
+ if (!file.getPath().empty() && (file.getPath() != "None"))
_soundFontClearButton->setEnabled(true);
else
_soundFontClearButton->setEnabled(false);
@@ -417,7 +417,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
// done with optional specific gameid to pluginmgr detectgames?
// FSList files = dir.listDir(FilesystemNode::kListFilesOnly);
- _gamePathWidget->setLabel(dir.path());
+ _gamePathWidget->setLabel(dir.getPath());
draw();
}
draw();
@@ -430,7 +430,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
if (browser.runModal() > 0) {
// User made his choice...
FilesystemNode dir(browser.getResult());
- _extraPathWidget->setLabel(dir.path());
+ _extraPathWidget->setLabel(dir.getPath());
draw();
}
draw();
@@ -442,7 +442,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
if (browser.runModal() > 0) {
// User made his choice...
FilesystemNode dir(browser.getResult());
- _savePathWidget->setLabel(dir.path());
+ _savePathWidget->setLabel(dir.getPath());
draw();
}
draw();
@@ -654,9 +654,9 @@ void LauncherDialog::addGame() {
// User made his choice...
FilesystemNode dir(_browser->getResult());
FSList files;
- if (!dir.listDir(files, FilesystemNode::kListAll)) {
+ if (!dir.getChildren(files, FilesystemNode::kListAll)) {
error("browser returned a node that is not a directory: '%s'",
- dir.path().c_str());
+ dir.getPath().c_str());
}
// ...so let's determine a list of candidates, games that
@@ -686,7 +686,7 @@ void LauncherDialog::addGame() {
GameDescriptor result = candidates[idx];
// TODO: Change the detectors to set "path" !
- result["path"] = dir.path();
+ result["path"] = dir.getPath();
Common::String domain = addGameToConf(result);
diff --git a/gui/massadd.cpp b/gui/massadd.cpp
index 802f1cf084..987a92efb5 100644
--- a/gui/massadd.cpp
+++ b/gui/massadd.cpp
@@ -128,9 +128,9 @@ void MassAddDialog::handleTickle() {
FilesystemNode dir = _scanStack.pop();
FSList files;
- if (!dir.listDir(files, FilesystemNode::kListAll)) {
+ if (!dir.getChildren(files, FilesystemNode::kListAll)) {
error("browser returned a node that is not a directory: '%s'",
- dir.path().c_str());
+ dir.getPath().c_str());
}
// Run the detector on the dir
@@ -142,7 +142,7 @@ void MassAddDialog::handleTickle() {
// e.g. ask the user which one to pick (make sure to display the
// path, too).
GameDescriptor result = candidates[0];
- result["path"] = dir.path();
+ result["path"] = dir.getPath();
_games.push_back(result);
}
diff --git a/gui/options.cpp b/gui/options.cpp
index c14677f007..66786eff6c 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -27,6 +27,7 @@
#include "gui/themebrowser.h"
#include "gui/chooser.h"
#include "gui/eval.h"
+#include "gui/message.h"
#include "gui/newgui.h"
#include "gui/options.h"
#include "gui/PopUpWidget.h"
@@ -813,9 +814,14 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
if (browser.runModal() > 0) {
// User made his choice...
FilesystemNode dir(browser.getResult());
- _savePath->setLabel(dir.path());
+ if(dir.isWritable()) {
+ _savePath->setLabel(dir.getPath());
+ } else {
+ MessageDialog error("The chosen directory cannot be written to. Please select another one.");
+ error.runModal();
+ return;
+ }
draw();
- // TODO - we should check if the directory is writeable before accepting it
}
break;
}
@@ -824,7 +830,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
if (browser.runModal() > 0) {
// User made his choice...
FilesystemNode dir(browser.getResult());
- _themePath->setLabel(dir.path());
+ _themePath->setLabel(dir.getPath());
draw();
}
break;
@@ -834,7 +840,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
if (browser.runModal() > 0) {
// User made his choice...
FilesystemNode dir(browser.getResult());
- _extraPath->setLabel(dir.path());
+ _extraPath->setLabel(dir.getPath());
draw();
}
break;
@@ -844,9 +850,9 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
if (browser.runModal() > 0) {
// User made his choice...
FilesystemNode file(browser.getResult());
- _soundFont->setLabel(file.path());
+ _soundFont->setLabel(file.getPath());
- if (!file.path().empty() && (file.path() != "None"))
+ if (!file.getPath().empty() && (file.getPath() != "None"))
_soundFontClearButton->setEnabled(true);
else
_soundFontClearButton->setEnabled(false);
diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp
index 234e0ed2b9..75fe5404c4 100644
--- a/gui/themebrowser.cpp
+++ b/gui/themebrowser.cpp
@@ -27,7 +27,6 @@
#include "gui/ListWidget.h"
#include "gui/widget.h"
#include "gui/theme.h"
-#include "common/fs.h"
#ifdef MACOSX
#include "CoreFoundation/CoreFoundation.h"
@@ -145,16 +144,16 @@ void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) {
FilesystemNode node(dir);
- if (!node.isValid())
+ if (!node.exists() || !node.isReadable())
return;
FSList fslist;
- if (!node.listDir(fslist, FilesystemNode::kListAll))
+ if (!node.getChildren(fslist, FilesystemNode::kListAll))
return;
for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) {
if (i->isDirectory()) {
- addDir(list, i->path(), level-1);
+ addDir(list, i->getPath(), level-1);
} else {
Entry th;
if (isTheme(*i, th)) {
@@ -177,7 +176,7 @@ bool ThemeBrowser::isTheme(const FilesystemNode &node, Entry &out) {
Common::ConfigFile cfg;
Common::String type;
- out.file = node.name();
+ out.file = node.getName();
for (int i = out.file.size()-1; out.file[i] != '.' && i > 0; --i) {
out.file.deleteLastChar();
}