Added first pass of filesystem handling. We can now see a listing in the

launcher window, and double-clicking on a listed file will start that ROM.

Some optimizations WRT launcher stuff.  Specifically, it was not necessary
to delete and re-create the launcher dialog all the time.

It's all starting to come together ...


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@415 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2005-05-09 18:58:19 +00:00
parent 16ee1f8e7f
commit 7deea3a6a6
7 changed files with 588 additions and 26 deletions

View File

@ -13,7 +13,7 @@
## See the file "license" for information on usage and redistribution of
## this file, and for a DISCLAIMER OF ALL WARRANTIES.
##
## $Id: makefile,v 1.75 2005-05-06 18:38:59 stephena Exp $
## $Id: makefile,v 1.76 2005-05-09 18:58:17 stephena Exp $
##============================================================================
##============================================================================
@ -126,7 +126,7 @@ linux:
$(MAKE) $(SMP) stella \
EXE_NAME="stella" \
OPTIONS="$(OPTIONS) -DBSPF_UNIX -DUNIX -DHAVE_GETTIMEOFDAY" \
OBJS="$(OBJECTS) SettingsUNIX.o OSystemUNIX.o"
OBJS="$(OBJECTS) SettingsUNIX.o OSystemUNIX.o FSNodePOSIX.o"
linux-gl:
$(MAKE) $(SMP) stella \
@ -134,20 +134,20 @@ linux-gl:
LDFLAGS="$(LDFLAGS) -L/usr/X11R6/lib" \
LDLIBS="$(LDLIBS) -lGL" \
OPTIONS="$(OPTIONS) -DBSPF_UNIX -DUNIX -DHAVE_GETTIMEOFDAY -DDISPLAY_OPENGL" \
OBJS="$(OBJECTS) FrameBufferGL.o SettingsUNIX.o OSystemUNIX.o"
OBJS="$(OBJECTS) FrameBufferGL.o SettingsUNIX.o OSystemUNIX.o FSNodePOSIX.o"
win32:
$(MAKE) $(SMP) stella \
EXE_NAME="stella.exe" \
OPTIONS="$(OPTIONS) -DBSPF_WIN32 -DWIN32" \
OBJS="$(OBJECTS) SettingsWin32.o OSystemWin32.o"
OBJS="$(OBJECTS) SettingsWin32.o OSystemWin32.o FSNodeWin32.o"
win32-gl:
$(MAKE) $(SMP) stella \
EXE_NAME="stella.exe" \
LDLIBS="$(LDLIBS) -lopengl32" \
OPTIONS="$(OPTIONS) -DBSPF_WIN32 -DWIN32 -DDISPLAY_OPENGL -DTEXTURES_ARE_LOST" \
OBJS="$(OBJECTS) FrameBufferGL.o SettingsWin32.o OSystemWin32.o"
OBJS="$(OBJECTS) FrameBufferGL.o SettingsWin32.o FSNodeWin32.o"
###############################################################################
@ -168,7 +168,7 @@ CORE_OBJS = Booster.o Cart.o Cart2K.o Cart3F.o Cart4K.o CartAR.o CartDPC.o \
Event.o Joystick.o Keyboard.o M6532.o MD5.o MediaSrc.o Paddles.o \
Props.o PropsSet.o Random.o SoundNull.o Switches.o Settings.o TIA.o \
Serializer.o Deserializer.o EventHandler.o FrameBuffer.o \
OSystem.o \
OSystem.o FSNode.o \
$(M6502_OBJS) $(GUI_OBJS)
stella: $(CORE_OBJS) $(OBJS)
@ -316,18 +316,27 @@ Settings.o: $(CORE)/Settings.cxx $(CORE)/Settings.hxx
OSystem.o: $(CORE)/OSystem.cxx $(CORE)/OSystem.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(CORE)/OSystem.cxx
FSNode.o: $(CORE)/FSNode.cxx $(CORE)/FSNode.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(CORE)/FSNode.cxx
SettingsUNIX.o: $(SRC)/unix/SettingsUNIX.cxx $(SRC)/unix/SettingsUNIX.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(SRC)/unix/SettingsUNIX.cxx
OSystemUNIX.o: $(SRC)/unix/OSystemUNIX.cxx $(SRC)/unix/OSystemUNIX.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(SRC)/unix/OSystemUNIX.cxx
FSNodePOSIX.o: $(SRC)/unix/FSNodePOSIX.cxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(SRC)/unix/FSNodePOSIX.cxx
SettingsWin32.o: $(SRC)/win32/SettingsWin32.cxx $(SRC)/win32/SettingsWin32.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(SRC)/win32/SettingsWin32.cxx
OSystemWin32.o: $(SRC)/win32/OSystemWin32.cxx $(SRC)/win32/OSystemWin32.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(SRC)/win32/OSystemWin32.cxx
FSNodeWin32.o: $(SRC)/win32/FSNodeWin32.cxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(SRC)/win32/FSNodeWin32.cxx
SoundNull.o: $(COMMON)/SoundNull.cxx $(COMMON)/SoundNull.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(COMMON)/SoundNull.cxx

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: mainSDL.cxx,v 1.37 2005-05-06 18:38:59 stephena Exp $
// $Id: mainSDL.cxx,v 1.38 2005-05-09 18:58:18 stephena Exp $
//============================================================================
#include <fstream>
@ -33,6 +33,7 @@
#include "PropsSet.hxx"
#include "Sound.hxx"
#include "Settings.hxx"
#include "FSNode.hxx"
#include "OSystem.hxx"
#if defined(UNIX)

View File

@ -0,0 +1,114 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FSNode.cxx,v 1.1 2005-05-09 18:58:18 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#include "bspf.hxx"
#include "GuiUtils.hxx"
#include "FSNode.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FSList::sort()
{
// Simple selection sort
for (Int32 i = 0; i < _size-1; i++)
{
Int32 min = i;
for (Int32 j = i+1; j < _size; j++)
if (_data[j] < _data[min])
min = j;
if (min != i)
SWAP(_data[min], _data[i]);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode AbstractFilesystemNode::wrap(AbstractFilesystemNode *node)
{
FilesystemNode wrapper;
wrapper._realNode = node;
return wrapper;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode::FilesystemNode()
{
_realNode = getRoot();
_refCount = new int(1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode::FilesystemNode(const FilesystemNode &node)
: AbstractFilesystemNode()
{
_realNode = node._realNode;
_refCount = node._refCount;
++(*_refCount);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#ifdef MACOSX
FilesystemNode::FilesystemNode(const string& p)
{
_realNode = getNodeForPath(p);
_refCount = new int(1);
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode::~FilesystemNode()
{
decRefCount();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FilesystemNode::decRefCount()
{
--(*_refCount);
if (*_refCount <= 0)
{
delete _refCount;
delete _realNode;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode &FilesystemNode::operator =(const FilesystemNode &node)
{
++(*node._refCount);
decRefCount();
_realNode = node._realNode;
_refCount = node._refCount;
return *this;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode FilesystemNode::getParent() const
{
AbstractFilesystemNode *node = _realNode->parent();
if(node == 0)
return *this;
else
return AbstractFilesystemNode::wrap(node);
}

View File

@ -0,0 +1,209 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FSNode.hxx,v 1.1 2005-05-09 18:58:18 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#ifndef FS_NODE_HXX
#define FS_NODE_HXX
/*
* The API described in this header is meant to allow for file system browsing in a
* portable fashions. To this ends, multiple or single roots have to be supported
* (compare Unix with a single root, Windows with multiple roots C:, D:, ...).
*
* To this end, we abstract away from paths; implementations can be based on
* paths (and it's left to them whether / or \ or : is the path separator :-);
* but it is also possible to use inodes or vrefs (MacOS 9) or anything else.
*
* NOTE: Backends still have to provide a way to extract a path from a FSIntern
*
* You may ask now: "isn't this cheating? Why do we go through all this when we use
* a path in the end anyway?!?".
* Well, for once as long as we don't provide our own file open/read/write API, we
* still have to use fopen(). Since all our targets already support fopen(), it should
* be possible to get a fopen() compatible string for any file system node.
*
* Secondly, with this abstraction layer, we still avoid a lot of complications based on
* differences in FS roots, different path separators, or even systems with no real
* 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.
*/
/*
* TODO - Instead of starting with getRoot(), we should rather add a getDefaultDir()
* call that on Unix might return the current dir or the users home dir...
* i.e. the root dir is usually not the best starting point for browsing.
*/
#include "Array.hxx"
class FilesystemNode;
/**
* List of multiple file system nodes. E.g. the contents of a given directory.
*/
class FSList : public Array<FilesystemNode>
{
public:
void sort();
};
/**
* File system node.
*/
class AbstractFilesystemNode
{
public:
/**
Flag to tell listDir() which kind of files to list.
*/
typedef enum {
kListFilesOnly = 1,
kListDirectoriesOnly = 2,
kListAll = 3
} ListMode;
virtual ~AbstractFilesystemNode() {}
/**
Return display name, used by e.g. the GUI to present the file in the file browser.
@return the display name
*/
virtual string displayName() const = 0;
/**
Is this node valid (i.e. referring to an actual FS object)?
*/
virtual bool isValid() const = 0;
/**
Is this node a directory or not?
*/
virtual bool isDirectory() const = 0;
/**
A path representation suitable for use with fopen()
*/
virtual string path() const = 0;
/**
List the content of this directory node.
If this node is not a directory, throw an exception or call error().
*/
virtual FSList listDir(ListMode mode = kListDirectoriesOnly) const = 0;
/**
Compare the name of this node to the name of another.
*/
virtual bool operator< (const AbstractFilesystemNode& node) const
{
string first = displayName();
string second = node.displayName();
transform(first.begin(), first.end(), first.begin(), (int(*)(int)) tolower);
transform(second.begin(), second.end(), second.begin(), (int(*)(int)) tolower);
return first < second;
}
/* TODO:
bool exists();
bool isDirectory();
bool isFile();
bool isReadable();
bool isWriteable();
*/
protected:
friend class FilesystemNode;
/**
The parent node of this directory.
The parent of the root is the root itself.
*/
virtual AbstractFilesystemNode *parent() const = 0;
/**
* This method is a rather ugly hack which is used internally by the
* actual node implementions to wrap up raw nodes inside FilesystemNode
* objects. We probably want to get rid of this eventually and replace it
* with a cleaner / more elegant solution, but for now it works.
* @note This takes over ownership of node. Do not delete it yourself,
* else you'll get ugly crashes. You've been warned!
*/
static FilesystemNode wrap(AbstractFilesystemNode *node);
};
class FilesystemNode : public AbstractFilesystemNode
{
friend class AbstractFilesystemNode;
public:
FilesystemNode();
FilesystemNode(const FilesystemNode& node);
#ifdef MACOSX
FilesystemNode(const string& path);
#endif
~FilesystemNode();
FilesystemNode &operator =(const FilesystemNode &node);
FilesystemNode getParent() const;
virtual string displayName() const { return _realNode->displayName(); }
virtual bool isValid() const { return _realNode->isValid(); }
virtual bool isDirectory() const { return _realNode->isDirectory(); }
virtual string path() const { return _realNode->path(); }
virtual FSList listDir(ListMode mode = kListDirectoriesOnly) const
{ return _realNode->listDir(mode); }
protected:
void decRefCount();
virtual AbstractFilesystemNode* parent() const { return 0; }
private:
AbstractFilesystemNode *_realNode;
int *_refCount;
/**
* 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:).
*/
static AbstractFilesystemNode* getRoot();
#ifdef MACOSX
/*
* Construct a node based on a path; the path is in the same format as it
* would be for calls to fopen().
*
* I.e. getNodeForPath(oldNode.path()) should create a new node identical to oldNode.
*/
static AbstractFilesystemNode* getNodeForPath(const string& path);
#endif
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Launcher.cxx,v 1.2 2005-05-06 22:50:15 stephena Exp $
// $Id: Launcher.cxx,v 1.3 2005-05-09 18:58:19 stephena Exp $
//============================================================================
#include "OSystem.hxx"
@ -36,8 +36,10 @@ Launcher::~Launcher()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Launcher::initialize()
{
delete myBaseDialog;
myBaseDialog = new LauncherDialog(myOSystem, 0, 0, kLauncherWidth, kLauncherHeight);
// We only create one instance of this dialog, since each time we do so,
// the ROM listing is read from disk. This can be very expensive.
if(myBaseDialog == NULL)
myBaseDialog = new LauncherDialog(myOSystem, 0, 0, kLauncherWidth, kLauncherHeight);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -13,13 +13,14 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: LauncherDialog.cxx,v 1.3 2005-05-08 17:38:23 stephena Exp $
// $Id: LauncherDialog.cxx,v 1.4 2005-05-09 18:58:19 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#include "OSystem.hxx"
#include "FSNode.hxx"
#include "Widget.hxx"
#include "ListWidget.hxx"
#include "Dialog.hxx"
@ -78,9 +79,6 @@ LauncherDialog::LauncherDialog(OSystem* osystem, uInt16 x, uInt16 y,
myList->setEditable(false);
myList->setNumberingMode(kListNumberingOff);
// Populate the list
updateListing();
// Restore last selection
/*
string last = ConfMan.get(String("lastselectedgame"), ConfigManager::kApplicationDomain);
@ -114,6 +112,10 @@ LauncherDialog::~LauncherDialog()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherDialog::loadConfig()
{
// Assume that if the list is empty, this is the first time that loadConfig()
// has been called (and we should reload the list).
if(myList->getList().isEmpty())
updateListing();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -135,10 +137,35 @@ void LauncherDialog::close()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherDialog::updateListing()
{
// FIXME - add bulk of KStella code here wrt loading from stella.cache
cerr << "LauncherDialog::updateListing()\n";
// Figure out if the ROM dir has changed since we last accessed it.
// If so, we do a full reload from disk (takes quite some time).
// Otherwise, we can use the cache file (which is much faster).
// FIXME - actually implement the following code
/*
Common::StringList l;
if(... ROM_DIR_CHANGED ...)
loadListFromDisk();
else if( ... CACHE_FILE_EXISTS)
loadListFromCache();
else // we have no other choice
loadListFromDisk();
*/
StringList l;
FilesystemNode t;
FilesystemNode dir(t);//"/local/emulators/atari/roms"); // FIXME
FSList files = dir.listDir(FilesystemNode::kListAll);
files.sort();
for (int idx = 0; idx < (int)files.size(); idx++)
l.push_back(files[idx].displayName());
/*
// ...so let's determine a list of candidates, games that
// could be contained in the specified directory.
DetectedGameList candidates(PluginManager::instance().detectGames(files));
// Retrieve a list of all games defined in the config file
_domains.clear();
@ -166,10 +193,9 @@ cerr << "LauncherDialog::updateListing()\n";
_domains.insert_at(pos, iter->_key);
}
}
_list->setList(l);
updateButtons();
*/
myList->setList(l);
updateButtons();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -292,19 +318,21 @@ void LauncherDialog::addGame()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherDialog::handleCommand(CommandSender* sender, uInt32 cmd, uInt32 data)
{
Int32 item = myList->getSelected();
switch (cmd)
{
case kStartCmd:
case kListItemActivatedCmd:
case kListItemDoubleClickedCmd:
cerr << "Game selected: " << item << endl;
// FIXME - start a new console based on the filename selected
// this is only here for testing
instance()->createConsole("frostbite.a26");
close();
{
if(myList->getSelected() >= 0)
{
string item = myList->getSelectedString();
cerr << "Game selected: " << item << endl;
instance()->createConsole(item);
close();
}
break;
}
case kLocationCmd:
cerr << "kLocationCmd from LauncherDialog\n";

View File

@ -0,0 +1,199 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FSNodePOSIX.cxx,v 1.1 2005-05-09 18:58:19 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#include "FSNode.hxx"
#ifdef MACOSX
#include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <unistd.h>
/*
* Implementation of the Stella file system API based on POSIX (for Linux and OSX)
*/
class POSIXFilesystemNode : public AbstractFilesystemNode
{
public:
POSIXFilesystemNode();
POSIXFilesystemNode(const string& path);
POSIXFilesystemNode(const POSIXFilesystemNode* node);
virtual string displayName() const { return _displayName; }
virtual bool isValid() const { return _isValid; }
virtual bool isDirectory() const { return _isDirectory; }
virtual string path() const { return _path; }
virtual FSList listDir(ListMode mode = kListDirectoriesOnly) const;
virtual AbstractFilesystemNode* parent() const;
protected:
string _displayName;
bool _isDirectory;
bool _isValid;
string _path;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const char* lastPathComponent(const string& str)
{
// FIXME - use native C++ string code
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur > start && *cur != '/')
--cur;
return cur+1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode* FilesystemNode::getRoot()
{
return new POSIXFilesystemNode();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#ifdef MACOSX
AbstractFilesystemNode* FilesystemNode::getNodeForPath(const string& path)
{
return new POSIXFilesystemNode(path);
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
POSIXFilesystemNode::POSIXFilesystemNode()
{
char buf[MAXPATHLEN];
getcwd(buf, MAXPATHLEN);
_path = buf;
_displayName = lastPathComponent(_path);
_path += '/';
_isValid = true;
_isDirectory = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
POSIXFilesystemNode::POSIXFilesystemNode(const string& p)
{
Int32 len = 0, offset = p.size();
struct stat st;
assert(offset > 0);
_path = p;
// Extract last component from path
const char *str = p.c_str();
while (offset > 0 && str[offset-1] == '/')
offset--;
while (offset > 0 && str[offset-1] != '/')
{
len++;
offset--;
}
_displayName = string(str + offset, len);
// Check whether it is a directory, and whether the file actually exists
_isValid = (0 == stat(_path.c_str(), &st));
_isDirectory = S_ISDIR(st.st_mode);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
POSIXFilesystemNode::POSIXFilesystemNode(const POSIXFilesystemNode* node)
{
_displayName = node->_displayName;
_isValid = node->_isValid;
_isDirectory = node->_isDirectory;
_path = node->_path;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FSList POSIXFilesystemNode::listDir(ListMode mode) const
{
assert(_isDirectory);
DIR *dirp = opendir(_path.c_str());
struct stat st;
struct dirent *dp;
FSList myList;
if (dirp == NULL)
return myList;
// ... loop over dir entries using readdir
while ((dp = readdir(dirp)) != NULL)
{
// Skip 'invisible' files
if (dp->d_name[0] == '.')
continue;
POSIXFilesystemNode entry;
entry._displayName = dp->d_name;
entry._path = _path;
if (entry._path.length() > 0 && entry._path[entry._path.length()-1] != '/')
entry._path += '/';
entry._path += dp->d_name;
if (stat(entry._path.c_str(), &st))
continue;
entry._isDirectory = S_ISDIR(st.st_mode);
// Honor the chosen mode
if ((mode == kListFilesOnly && entry._isDirectory) ||
(mode == kListDirectoriesOnly && !entry._isDirectory))
continue;
if (entry._isDirectory)
entry._path += "/";
myList.push_back(wrap(new POSIXFilesystemNode(&entry)));
}
closedir(dirp);
return myList;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode *POSIXFilesystemNode::parent() const
{
if (_path == "/")
return 0;
POSIXFilesystemNode* p = new POSIXFilesystemNode();
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
p->_path = string(start, end - start);
p->_displayName = lastPathComponent(p->_path);
p->_isValid = true;
p->_isDirectory = true;
return p;
}