I may as well forget trying to release for tomorrow; it's just not going

to happen.

Fixes to Filesystem handling, particularly for Win32.  The '~' symbol
is now recognized as 'My Documents' in Windows.

The '~' directory is now the default used if the one specified is
incorrect.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1629 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-01-16 14:57:53 +00:00
parent 4981ce2158
commit 8d3c4fa642
9 changed files with 113 additions and 133 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FSNode.cxx,v 1.14 2009-01-11 19:10:40 stephena Exp $ // $Id: FSNode.cxx,v 1.15 2009-01-16 14:57:52 stephena Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -37,9 +37,11 @@ FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNode::FilesystemNode(const string& p) FilesystemNode::FilesystemNode(const string& p)
{ {
AbstractFilesystemNode *tmp = 0; AbstractFilesystemNode* tmp = 0;
if (p.empty() || p == ".") if (p.empty() || p == ".")
tmp = AbstractFilesystemNode::makeCurrentDirectoryFileNode(); tmp = AbstractFilesystemNode::makeCurrentDirectoryFileNode();
else if (p == "~")
tmp = AbstractFilesystemNode::makeHomeDirectoryFileNode();
else else
tmp = AbstractFilesystemNode::makeFileNodePath(p); tmp = AbstractFilesystemNode::makeFileNodePath(p);

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FSNode.hxx,v 1.17 2009-01-11 19:10:40 stephena Exp $ // $Id: FSNode.hxx,v 1.18 2009-01-16 14:57:52 stephena Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -354,6 +354,15 @@ class AbstractFilesystemNode
*/ */
static AbstractFilesystemNode* makeCurrentDirectoryFileNode(); static AbstractFilesystemNode* makeCurrentDirectoryFileNode();
/**
* Returns a node representing the "home directory".
*
* On Unix, this will be the value of $HOME.
* On Windows, it will be the 'My Documents' folder.
* Otherwise, it should just return the same value as getRoot().
*/
static AbstractFilesystemNode* makeHomeDirectoryFileNode();
/** /**
* Construct a node based on a path; the path is in the same format as it * Construct a node based on a path; the path is in the same format as it
* would be for calls to fopen(). * would be for calls to fopen().

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: BrowserDialog.cxx,v 1.36 2009-01-11 19:10:40 stephena Exp $ // $Id: BrowserDialog.cxx,v 1.37 2009-01-16 14:57:52 stephena Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -134,11 +134,10 @@ void BrowserDialog::show(const string& title, const string& startpath,
_mode = mode; _mode = mode;
// If no node has been set, or the last used one is now invalid, // If no node has been set, or the last used one is now invalid,
// go back to the root/default dir. // go back to the users home dir.
_node = FilesystemNode(startpath); _node = FilesystemNode(startpath);
if(!_node.exists()) if(!_node.exists())
_node = FilesystemNode(); _node = FilesystemNode("~");
// Generally, we always want a directory listing // Generally, we always want a directory listing
if(!_node.isDirectory() && _node.hasParent()) if(!_node.isDirectory() && _node.hasParent())
@ -217,7 +216,7 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
int item = _fileList->getSelected(); int item = _fileList->getSelected();
if(item >= 0) if(item >= 0)
{ {
_node = FilesystemNode(_nodeList->path(item)); _node = FilesystemNode(_nodeList->path(item));
updateListing(); updateListing();
} }
break; break;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: LauncherDialog.cxx,v 1.101 2009-01-14 20:31:07 stephena Exp $ // $Id: LauncherDialog.cxx,v 1.102 2009-01-16 14:57:52 stephena Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -223,6 +223,8 @@ void LauncherDialog::loadConfig()
{ {
myPrevDirButton->setEnabled(false); myPrevDirButton->setEnabled(false);
myCurrentNode = FilesystemNode(instance().settings().getString("romdir")); myCurrentNode = FilesystemNode(instance().settings().getString("romdir"));
if(!(myCurrentNode.exists() && myCurrentNode.isDirectory()))
myCurrentNode = FilesystemNode("~");
updateListing(); updateListing();
} }
@ -448,7 +450,8 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
#endif #endif
} }
else else
instance().frameBuffer().showMessage("Error creating console (screen too small)", kMiddleCenter); instance().frameBuffer().showMessage(
"Error creating console (screen too small)", kMiddleCenter);
} }
else else
instance().frameBuffer().showMessage("Not a valid ROM file", kMiddleCenter); instance().frameBuffer().showMessage("Not a valid ROM file", kMiddleCenter);
@ -477,6 +480,8 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
case kRomDirChosenCmd: case kRomDirChosenCmd:
myCurrentNode = FilesystemNode(instance().settings().getString("romdir")); myCurrentNode = FilesystemNode(instance().settings().getString("romdir"));
if(!(myCurrentNode.exists() && myCurrentNode.isDirectory()))
myCurrentNode = FilesystemNode("~");
updateListing(); updateListing();
break; break;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FSNodePOSIX.cxx,v 1.19 2009-01-11 22:05:37 stephena Exp $ // $Id: FSNodePOSIX.cxx,v 1.20 2009-01-16 14:57:53 stephena Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -29,6 +29,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <dirent.h> #include <dirent.h>
#include <cassert>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <unistd.h> #include <unistd.h>
@ -256,6 +257,12 @@ AbstractFilesystemNode* AbstractFilesystemNode::makeCurrentDirectoryFileNode()
return new POSIXFilesystemNode(path, true); return new POSIXFilesystemNode(path, true);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode* AbstractFilesystemNode::makeHomeDirectoryFileNode()
{
return new POSIXFilesystemNode("~/", true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode* AbstractFilesystemNode::makeFileNodePath(const string& path) AbstractFilesystemNode* AbstractFilesystemNode::makeFileNodePath(const string& path)
{ {

View File

@ -13,18 +13,14 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: OSystemUNIX.cxx,v 1.30 2009-01-01 18:13:39 stephena Exp $ // $Id: OSystemUNIX.cxx,v 1.31 2009-01-16 14:57:53 stephena Exp $
//============================================================================ //============================================================================
#include <cstdlib> #include <cstdlib>
#include <sstream>
#include <fstream>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "bspf.hxx" #include "bspf.hxx"
#include "FSNode.hxx"
#include "OSystem.hxx" #include "OSystem.hxx"
#include "OSystemUNIX.hxx" #include "OSystemUNIX.hxx"
@ -47,7 +43,8 @@
OSystemUNIX::OSystemUNIX() OSystemUNIX::OSystemUNIX()
: OSystem() : OSystem()
{ {
const string& basedir = string(getenv("HOME")) + "/.stella"; FilesystemNode home("~");
const string& basedir = home.getPath() + "/.stella";
setBaseDir(basedir); setBaseDir(basedir);
setConfigFile(basedir + "/stellarc"); setConfigFile(basedir + "/stellarc");
} }

View File

@ -13,12 +13,15 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FSNodeWin32.cxx,v 1.16 2009-01-11 21:31:21 stephena Exp $ // $Id: FSNodeWin32.cxx,v 1.17 2009-01-16 14:57:53 stephena Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
//============================================================================ //============================================================================
#include <cassert>
#include <shlobj.h>
#ifdef ARRAYSIZE #ifdef ARRAYSIZE
#undef ARRAYSIZE #undef ARRAYSIZE
#endif #endif
@ -56,6 +59,56 @@
#include "FSNode.hxx" #include "FSNode.hxx"
/*
* Used to determine the location of the 'My Documents' folder.
*
* Win98 and earlier don't have SHGetFolderPath in shell32.dll.
* Microsoft recommend that we load shfolder.dll at run time and
* access the function through that.
*
* shfolder.dll is loaded dynamically in the constructor, and unloaded in
* the destructor
*
* The class makes SHGetFolderPath available through its function operator.
* It will work on all versions of Windows >= Win95.
*
* This code was borrowed from the Lyx project.
*/
class MyDocumentsFinder
{
public:
GetFolderPathWin32::GetFolderPathWin32()
: myFolderModule(0), myFolderPathFunc(0)
{
myFolderModule = LoadLibrary("shfolder.dll");
if(myFolderModule)
{
myFolderPathFunc = reinterpret_cast<function_pointer>
(::GetProcAddress(myFolderModule, "SHGetFolderPathA"));
}
}
~GetFolderPathWin32() { if(myFolderModule) FreeLibrary(myFolderModule); }
/** Wrapper for SHGetFolderPathA, returning the 'My Documents' folder
(or an empty string if the folder couldn't be determined. */
string getPath() const
{
if(!myFolderPathFunc) return "";
char folder_path[MAX_PATH];
HRESULT const result = (myFolderPathFunc)
(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, folder_path);
return (result == 0) ? folder_path : "";
}
private:
typedef HRESULT (__stdcall * function_pointer)(HWND, int, HANDLE, DWORD, LPCSTR);
HMODULE myFolderModule;
function_pointer myFolderPathFunc;
};
/* /*
* Implementation of the Stella file system API based on Windows API. * Implementation of the Stella file system API based on Windows API.
* *
@ -103,6 +156,8 @@ class WindowsFilesystemNode : public AbstractFilesystemNode
bool _isPseudoRoot; bool _isPseudoRoot;
bool _isValid; bool _isValid;
static MyDocumentsFinder myDocsFinder;
private: private:
/** /**
* Adds a single WindowsFilesystemNode to a given list. * Adds a single WindowsFilesystemNode to a given list.
@ -232,6 +287,14 @@ WindowsFilesystemNode::WindowsFilesystemNode()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WindowsFilesystemNode::WindowsFilesystemNode(const string& p, const bool currentDir) WindowsFilesystemNode::WindowsFilesystemNode(const string& p, const bool currentDir)
{ {
// If '~' is requested, use the 'My Documents' directory, otherwise default
// to the current directory
if (p == "~")
{
_path = myDocsFinder.getPath();
if(_path == "") currentDir = true;
}
if (currentDir) if (currentDir)
{ {
char path[MAX_PATH]; char path[MAX_PATH];
@ -360,6 +423,12 @@ AbstractFilesystemNode* AbstractFilesystemNode::makeCurrentDirectoryFileNode()
return new WindowsFilesystemNode("", true); return new WindowsFilesystemNode("", true);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode* AbstractFilesystemNode::makeHomeDirectoryFileNode()
{
return new WindowsFilesystemNode("~", false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AbstractFilesystemNode* AbstractFilesystemNode::makeFileNodePath(const string& path) AbstractFilesystemNode* AbstractFilesystemNode::makeFileNodePath(const string& path)
{ {

View File

@ -13,14 +13,9 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: OSystemWin32.cxx,v 1.27 2009-01-11 21:31:21 stephena Exp $ // $Id: OSystemWin32.cxx,v 1.28 2009-01-16 14:57:53 stephena Exp $
//============================================================================ //============================================================================
#include <sstream>
#include <fstream>
#include <windows.h>
#include <shlobj.h>
#include "bspf.hxx" #include "bspf.hxx"
#include "FSNode.hxx" #include "FSNode.hxx"
#include "OSystem.hxx" #include "OSystem.hxx"
@ -45,27 +40,8 @@ OSystemWin32::OSystemWin32()
FilesystemNode node("disable_profiles.txt"); FilesystemNode node("disable_profiles.txt");
if(!node.exists()) if(!node.exists())
{ {
/* FilesystemNode home("~");
Use 'My Documents' folder for the Stella folder, which can be in many basedir = home.getPath() + "\\Stella";
different places depending on the version of Windows, as follows:
98: C:\My Documents
XP: C:\Document and Settings\USERNAME\My Documents\
Vista: C:\Users\USERNAME\Documents\
This function is guaranteed to return a valid 'My Documents'
folder (as much as Windows *can* make that guarantee)
*/
try
{
GetFolderPathWin32 win32FolderPath;
string path = win32FolderPath(GetFolderPathWin32::PERSONAL) + "\\Stella";
basedir = path;
}
catch(char* msg)
{
cerr << msg << endl;
}
} }
setBaseDir(basedir); setBaseDir(basedir);
@ -82,50 +58,3 @@ uInt32 OSystemWin32::getTicks() const
{ {
return (uInt32) SDL_GetTicks() * 1000; return (uInt32) SDL_GetTicks() * 1000;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GetFolderPathWin32::GetFolderPathWin32()
: myFolderModule(0),
myFolderPathFunc(0)
{
myFolderModule = LoadLibrary("shfolder.dll");
if(!myFolderModule)
throw "ERROR: GetFolderPathWin32() failed; cannot determine \'My Documents\' folder";
myFolderPathFunc = reinterpret_cast<function_pointer>
(::GetProcAddress(myFolderModule, "SHGetFolderPathA"));
if(myFolderPathFunc == 0)
throw "ERROR: GetFolderPathWin32() failed; cannot determine \'My Documents\' folder";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GetFolderPathWin32::~GetFolderPathWin32()
{
if(myFolderModule)
FreeLibrary(myFolderModule);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Given a folder ID, returns the folder name.
string const GetFolderPathWin32::operator()(kFolderId _id) const
{
char folder_path[MAX_PATH];
int id = 0;
switch(_id)
{
case PERSONAL:
id = CSIDL_PERSONAL;
break;
case APPDATA:
id = CSIDL_APPDATA;
break;
default:
return "";
}
HRESULT const result =
(myFolderPathFunc)(NULL, id | CSIDL_FLAG_CREATE, NULL, 0, folder_path);
return (result == 0) ? folder_path : "";
}

View File

@ -13,21 +13,20 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: OSystemWin32.hxx,v 1.15 2009-01-01 18:13:39 stephena Exp $ // $Id: OSystemWin32.hxx,v 1.16 2009-01-16 14:57:53 stephena Exp $
//============================================================================ //============================================================================
#ifndef OSYSTEM_WIN32_HXX #ifndef OSYSTEM_WIN32_HXX
#define OSYSTEM_WIN32_HXX #define OSYSTEM_WIN32_HXX
#include <windows.h> #include "OSystem.hxx"
#include "bspf.hxx" #include "bspf.hxx"
/** /**
This class defines Windows system specific settings. This class defines Windows system specific settings.
@author Stephen Anthony @author Stephen Anthony
@version $Id: OSystemWin32.hxx,v 1.15 2009-01-01 18:13:39 stephena Exp $ @version $Id: OSystemWin32.hxx,v 1.16 2009-01-16 14:57:53 stephena Exp $
*/ */
class OSystemWin32 : public OSystem class OSystemWin32 : public OSystem
{ {
@ -51,40 +50,4 @@ class OSystemWin32 : public OSystem
virtual uInt32 getTicks() const; virtual uInt32 getTicks() const;
}; };
/**
Win98 and earlier don't have SHGetFolderPath in shell32.dll.
Microsoft recommend that we load shfolder.dll at run time and
access the function through that.
shfolder.dll is loaded dynamically in the constructor. If loading
fails or if the .dll is found not to contain SHGetFolderPathA then
the program exits immediately. Otherwise, the .dll is unloaded in
the destructor
The class makes SHGetFolderPath available through its function operator.
It will work on all versions of Windows >= Win95.
This code was borrowed from the Lyx project.
*/
class GetFolderPathWin32
{
public:
enum kFolderId {
PERSONAL, // CSIDL_PERSONAL
APPDATA // CSIDL_APPDATA
};
GetFolderPathWin32();
~GetFolderPathWin32();
/** Wrapper for SHGetFolderPathA, returning the path asscociated with id. */
string const operator()(kFolderId id) const;
private:
typedef HRESULT (__stdcall * function_pointer)(HWND, int, HANDLE, DWORD, LPCSTR);
HMODULE myFolderModule;
function_pointer myFolderPathFunc;
};
#endif #endif