diff --git a/stella/src/win32/FSNodeWin32.cxx b/stella/src/win32/FSNodeWin32.cxx new file mode 100644 index 000000000..eddc32426 --- /dev/null +++ b/stella/src/win32/FSNodeWin32.cxx @@ -0,0 +1,230 @@ +//============================================================================ +// +// 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: FSNodeWin32.cxx,v 1.1 2005-05-19 13:52:55 stephena Exp $ +// +// Based on code from ScummVM - Scumm Interpreter +// Copyright (C) 2002-2004 The ScummVM project +//============================================================================ + +//#include "stdafx.h" +#include +#include +#include +#include + +#include "FSNode.hxx" + +/* + * Implementation of the Stella file system API based on Windows API. + */ + +class WindowsFilesystemNode : public AbstractFilesystemNode +{ + public: + WindowsFilesystemNode(); + WindowsFilesystemNode(const string &path); + WindowsFilesystemNode(const WindowsFilesystemNode* 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) const; + virtual AbstractFilesystemNode* parent() const; + + protected: + string _displayName; + bool _isDirectory; + bool _isValid; + bool _isPseudoRoot; + string _path; + + private: + static char* toAscii(TCHAR* x); + static TCHAR* toUnicode(char* x); + static void addFile (FSList& list, ListMode mode, + const char* base, WIN32_FIND_DATA* find_data); +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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 +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TCHAR* WindowsFilesystemNode::toUnicode(char* x) +{ +#ifndef UNICODE + return (TCHAR*)x; +#else + static TCHAR unicodeString[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, x, strlen(x) + 1, unicodeString, sizeof(unicodeString)); + return unicodeString; +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void WindowsFilesystemNode::addFile(FSList& list, ListMode mode, + const char* base, WIN32_FIND_DATA* find_data) +{ + WindowsFilesystemNode entry; + char* asciiName = toAscii(find_data->cFileName); + bool isDirectory; + + // Skip local directory (.) and parent (..) + if (!strcmp(asciiName, ".") || !strcmp(asciiName, "..")) + return; + + isDirectory = (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? true : false); + + if ((!isDirectory && mode == kListDirectoriesOnly) || + (isDirectory && mode == kListFilesOnly)) + return; + + entry._isDirectory = isDirectory; + entry._displayName = asciiName; + entry._path = base; + entry._path += asciiName; + if (entry._isDirectory) + entry._path += "\\"; + entry._isValid = true; + entry._isPseudoRoot = false; + + list.push_back(wrap(new WindowsFilesystemNode(&entry))); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +AbstractFilesystemNode *FilesystemNode::getRoot() +{ + return new WindowsFilesystemNode(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +WindowsFilesystemNode::WindowsFilesystemNode() +{ + _isDirectory = true; + + // Create a virtual root directory for standard Windows system + _isValid = false; + _path = ""; + _isPseudoRoot = true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +WindowsFilesystemNode::WindowsFilesystemNode(const WindowsFilesystemNode* node) +{ + _displayName = node->_displayName; + _isDirectory = node->_isDirectory; + _isValid = node->_isValid; + _isPseudoRoot = node->_isPseudoRoot; + _path = node->_path; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +FSList WindowsFilesystemNode::listDir(ListMode mode) const +{ + assert(_isDirectory); + + FSList myList; + + if (_isPseudoRoot) + { + // Drives enumeration + TCHAR drive_buffer[100]; + GetLogicalDriveStrings(sizeof(drive_buffer) / sizeof(TCHAR), drive_buffer); + + for (TCHAR *current_drive = drive_buffer; *current_drive; + current_drive += _tcslen(current_drive) + 1) + { + WindowsFilesystemNode entry; + char drive_name[2]; + + drive_name[0] = toAscii(current_drive)[0]; + drive_name[1] = '\0'; + entry._displayName = drive_name; + entry._isDirectory = true; + entry._isValid = true; + entry._isPseudoRoot = false; + entry._path = toAscii(current_drive); + myList.push_back(wrap(new WindowsFilesystemNode(&entry))); + } + } + else + { + // Files enumeration + WIN32_FIND_DATA desc; + HANDLE handle; + char searchPath[MAX_PATH + 10]; + + sprintf(searchPath, "%s*", _path.c_str()); + + handle = FindFirstFile(toUnicode(searchPath), &desc); + if (handle == INVALID_HANDLE_VALUE) + return myList; + + addFile(myList, mode, _path.c_str(), &desc); + while (FindNextFile(handle, &desc)) + addFile(myList, mode, _path.c_str(), &desc); + + FindClose(handle); + } + + return myList; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const char* lastPathComponent(const string& str) +{ + const char* start = str.c_str(); + const char* cur = start + str.size() - 2; + + while (cur > start && *cur != '\\') + --cur; + + return cur + 1; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +AbstractFilesystemNode* WindowsFilesystemNode::parent() const +{ + assert(_isValid || _isPseudoRoot); + if (_isPseudoRoot) + return 0; + + WindowsFilesystemNode* p = new WindowsFilesystemNode(); + if (_path.size() > 3) + { + const char *start = _path.c_str(); + const char *end = lastPathComponent(_path); + + p = new WindowsFilesystemNode(); + p->_path = String(start, end - start); + p->_isValid = true; + p->_isDirectory = true; + p->_displayName = lastPathComponent(p->_path); + p->_isPseudoRoot = false; + } + + return p; +}